• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import {
17  ErrorMessage,
18  MediaSizeHelper,
19  MediaTypeCode,
20  MediaTypes,
21  PreviewAttribute,
22  PrinterCapsOptions,
23  PrintJob,
24  PrintJobOptions,
25  PrintUtil,
26  startPrintJob
27} from '@ohos/common';
28import WifiP2pHelper from '../Common/Adapter/WifiP2pHelper';
29import FileModel from '../Model/FileModel';
30import SelectionModel from '../Model/SelectionModel';
31import { WLANConfirmDialog, PrintingSelectDialog, alarmDialog, connectConfirmDialog } from './component/CusDialogComp';
32import {
33  PrinterSelection,
34  MediaSizeSelection,
35  DirectionSelection,
36  MediaTypeSelection,
37  QualitySelection,
38  DuplexSelection
39} from './component/SelectComponent';
40import { MediaSize, MediaSizeUtil } from '@ohos/common';
41import { StringUtil } from '@ohos/common';
42import { PreviewComponent } from './component/PreviewComponent';
43import { ErrorCode, PrintPageSize, PrinterRange, PrintMargin, PrinterCapability, PrinterInfo } from '@ohos/common';
44import PrintAdapter from '../Common/Adapter/PrintAdapter';
45import { GlobalThisHelper, GlobalThisStorageKey} from '@ohos/common';
46import FileUtil from '../Common/Utils/FileUtil';
47import CheckEmptyUtils from '@ohos/common';
48import { CopyUtil } from '@ohos/common';
49import {
50  Constants,
51  AppCommonEvent,
52  AppStorageKeyName,
53  PrintRangeType,
54  PrintQuality,
55  Duplex,
56  PageDirection,
57  ColorCode,
58  MediaType,
59  MouseState
60} from '@ohos/common';
61import { Log } from '@ohos/common';
62import { uuidGenerator } from '@ohos/common';
63import { BISHENG_PRINTER } from '@ohos/common';
64import emitter from '@ohos.events.emitter';
65import { print } from '@kit.BasicServicesKit';
66import promptAction from '@ohos.promptAction';
67import common from '@ohos.app.ability.common';
68import {CancelButton} from './component/BaseComponent';
69import image from '@ohos.multimedia.image';
70import { AboutPageComponent } from './component/AboutPageComponent';
71import router from '@ohos.router';
72import Want from '@ohos.app.ability.Want';
73import { BusinessError } from '@ohos.base';
74import UIExtensionContentSession from '@ohos.app.ability.UIExtensionContentSession';
75
76const TAG = 'PrintPage';
77
78let storage = LocalStorage.getShared();
79@Entry(storage)
80@Component
81struct Index {
82  @Provide('ImageCount') imageCount: number = Constants.NUMBER_1;//预览显示的页数
83  @Provide('CurrentIndex') currentIndex: number = Constants.NUMBER_1;
84  @Provide('Printer') @Watch('onPrinterChange') printer: PrinterInfo | undefined = undefined; //打印机
85  @Provide('ShowPageNum') showPageNum: number = Constants.NUMBER_1
86  @Provide('PrinterList') printerList: Array<PrinterInfo> = [];
87  @Provide('PrintJob') printJob: PrintJob | undefined = undefined;
88  @Provide('UsedPrinterId') usedPrinterId: string | undefined = undefined;
89  @Provide('PrintAdapter') adapter: PrintAdapter | undefined = undefined;
90  @Provide('ConnectCountDown') connectCount: number = Constants.CONNECT_COUNT;
91  @Provide('ConnectCountDownTimer') ConnectTimer: number | undefined = undefined;
92  @Provide('CanPrint') canPrint: boolean = false;
93  @Provide('WLANFlag') wlanFlag: boolean = false;
94  @Provide('IsNeedListenWlan') isNeedListenWlan: boolean = false;
95  @Provide('ConnectingPrinterId') connectingPrinterId: string = Constants.DEFAULT_CONNECTING_PRINTER_ID;
96  @Provide('PrinterSelectArray') printerSelectArray: Array<SelectionModel> = [];
97  @Provide('CurrentPrinter') currentPrinterSelection: SelectionModel = SelectionModel.NO_Printer;
98  @Provide('MediaSizeSelectArray') mediaSizeSelectArray: Array<SelectionModel> = [];
99  @Provide('CurrentMediaSize') @Watch('updateMediaSize') currentMediaSize: SelectionModel = SelectionModel.MediaSize_ISO_A4;
100  @Provide('DirectionSelectArray') directionSelectArray: Array<SelectionModel> = [];
101  @Provide('CurrentDirection') @Watch('updateDirection') currentDirection: SelectionModel = SelectionModel.Direction_AUTO;
102  @Provide('MediaTypeSelectArray') mediaTypeSelectArray: Array<SelectionModel> = [];
103  @Provide('CurrentMediaType') @Watch('updateMediaType') currentMediaType: SelectionModel = SelectionModel.MediaType_NORMAL;
104  @Provide('QualitySelectArray') qualitySelectArray: Array<SelectionModel> = [];
105  @Provide('CurrentQuality') currentQuality: SelectionModel = SelectionModel.PrintQuality_STANDARD;
106  @Provide('DuplexSelectArray') duplexSelectArray: Array<SelectionModel> = [];
107  @Provide('CurrentDuplex') currentDuplex: SelectionModel = SelectionModel.DuplexMode_SINGLE;
108  @Provide('PrintRange') printRange: Array<number> = []; //打印范围
109  @Provide('NeedDuplex') @Watch('needDuplexChange')needDuplex: boolean = true;
110  @Provide('IsBorderless') isBorderless: boolean = false //是否无边距
111  @Provide('IsPreviewFailed') isPreviewFailed: boolean = false //是否需要显示预览失败图示
112  private abilityContext: common.UIExtensionContext | undefined = undefined;
113  @State @Watch('updateImageSources')imageSources: Array<FileModel> = new Array();
114  @State startPage: number = Constants.NUMBER_1 //打印范围起始页
115  @State startPageStr: string = Constants.STRING_ONE //打印范围起始页
116  @State endPage: number = Constants.NUMBER_1 //打印范围终止页
117  @State endPageStr: string = Constants.STRING_ONE //打印范围终止页
118  @State printCount: number = Constants.NUMBER_1 //份数
119  @State printCountStr: string = Constants.STRING_ONE //份数
120  @State isColored: boolean = false //是否彩印
121  @State isColorEnabled: boolean = true //是否支持彩印
122  @State isDuplexEnabled: boolean = true //是否支持双面
123  @State isPhotoEnabled: boolean = true //是否支持相片纸
124  @State isPlusPressed: boolean = false //是否按下份数+
125  @State plusMouseState: number = MouseState.NONE //份数+
126  @State minusMouseState: number = MouseState.NONE //份数-
127  @State isMinusPressed: boolean = false //是否按下份数-
128  @State mediaSizeList: Array<MediaSize> = []; //所有纸张尺寸
129  @State printRangeType: number = PrintRangeType.ALL; //打印范围类型 0:全部页面 1:范围打印
130  @State colorMode: number = ColorCode.MONOCHROME;
131  @State mediaSize: MediaSize = MediaSizeHelper.ISO_A4; //纸张尺寸
132  @State pageDirection: number = Constants.NUMBER_0; //纸张方向
133  @State printerRange: PrinterRange | undefined = undefined; //打印框架需要的参数,实际不起效
134  @State printerPageSize: PrintPageSize | undefined = undefined; //纸张尺寸
135  @State alarmText: string | undefined = undefined;
136  @State lastPrinterExist: boolean = false;
137  @State isConnected: boolean = false;
138  @State printerCap: print.PrinterCapability | undefined = undefined;
139  @State printButtonFlag: boolean = true;
140  @State cusRangeBorderColor: Resource = $r('app.color.border_line');
141  @State errorMessage: Resource | undefined = undefined;
142  @State isCusRangeError: boolean = false;
143  @State isCusRangeMax: boolean = false;
144  @State cusRangeArr: Array<number> = [];
145  @State cusRangeText: string | undefined = undefined;
146  @State isRangeRadioEnable: boolean = false;
147  @State isCustomRadioEnable: boolean = false;
148  @State isAbovePageLimit: boolean = false;//是否超过页数限制
149  @State printParamCompHeight: number = 0;//参数区组件高度
150  @Provide('PreviewCompHeight') previewCompHeight: number = 0;//预览区组件高度
151  @Provide('IsGlobalDisable') isGlobalDisable: boolean = false;
152  @Provide('PrinterSelectFlag') @Watch('openPrinterSelectDialog') printerSelectFlag: boolean = false;
153  @Provide('OpenWLANFlag') @Watch('openWLANDialog') openWlanFlag: boolean = true;
154  @Provide('ConnectFlag') @Watch('connectAlarm') connectFlag: boolean = true;
155  @StorageLink('JobQueue') jobQueue: Array<PrintJob> = new Array();
156  private usedPrinterFileName: string = 'lastUsedPrinter'
157  private firstFileName: string = Constants.STRING_NONE;
158  private totalPage: number = Constants.NUMBER_1//总页数
159  private allPages: Array<number> = [];
160  private jobName: string = Constants.STRING_NONE
161  private jobNum: number = Constants.NUMBER_1
162  private jobDes: string = Constants.STRING_NONE
163  private jobId: string = Constants.STRING_NONE
164  private jobFileList: Array<string> = []
165  private supportedMediaTypes: Array<number> = []
166  private scroller: Scroller = new Scroller()
167  private firstStartPageEdit: boolean = true
168  private firstEndPageEdit: boolean = true
169  private editCusRangeFlag: boolean = true//自定义输入框自动置空时为false,不触发编辑
170  private rangeInputLimit: number = Constants.NUMBER_3 //范围输入框位数限制
171  private firstPrinterDiscoveredFlag: boolean = false;
172  private changeRangeTypeFlag: boolean = true;//范围框radio选中是否让startPage输入框获焦
173  private fileNum: number = Constants.NUMBER_0;
174  private session?: UIExtensionContentSession = undefined;
175  WLANConfirmDialogCtl: CustomDialogController = new CustomDialogController({
176    builder: WLANConfirmDialog(),
177    alignment: DialogAlignment.Center,
178    autoCancel: false,
179    customStyle: true,
180  })
181  PrintingSelectDialogCtl: CustomDialogController = new CustomDialogController({
182    builder: PrintingSelectDialog(),
183    alignment: DialogAlignment.Center,
184    autoCancel: false,
185    customStyle: true,
186  })
187  alarmDialogCtl: CustomDialogController = new CustomDialogController({
188    builder: alarmDialog({ alarmText: this.alarmText }),
189    alignment: DialogAlignment.Center,
190    autoCancel: false,
191    customStyle: true,
192  })
193  connectConfirmDialogCtl: CustomDialogController = new CustomDialogController({
194    builder: connectConfirmDialog(),
195    alignment: DialogAlignment.Center,
196    autoCancel: false,
197    customStyle: true,
198  })
199
200  build() {
201    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
202      // 预览组件
203      PreviewComponent({
204        pageDirection: $pageDirection,
205        colorMode: $colorMode,
206        mediaSize: $mediaSize,
207        imageSources: $imageSources
208      })
209        .height('40%')
210        .onAreaChange((oldValue: Area, newValue: Area) => {
211          Log.info(`Ace: on area change, oldValue is ${JSON.stringify(oldValue)} value is ${JSON.stringify(newValue)}`)
212          this.previewCompHeight = newValue.height as number;
213          this.printParamCompHeight = this.previewCompHeight*1.5
214        })
215      Column() {
216        Scroll(this.scroller) {
217          Column() {
218            PrinterSelection()
219            Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
220              Text($r('app.string.index_add_copies'))
221                .fontSize($r('app.float.font_size_body2'))
222                .width($r('app.float.text_label_width'))
223                .textAlign(TextAlign.End)
224                .key('Index_Text_copies')
225                .focusable(true)
226                .onFocus(()=>{
227                  if (this.printRangeType === PrintRangeType.CUSTOM) {
228                    this.checkCustomRangeTextInput(false)
229                  }
230                })
231              TextInput({ text: this.printCountStr })
232                .type(InputType.Number)
233                .maxLength(Constants.NUMBER_2)
234                .fontSize($r('app.float.font_size_body2'))
235                .border({
236                  width: $r('app.float.border_width'),
237                  radius: $r('app.float.radius_s'),
238                  color: $r('app.color.border_line')
239                })
240                .backgroundColor(Color.White)
241                .width($r('app.float.print_copies_textInput_width'))
242                .height($r('app.float.params_comp_height'))
243                .margin({
244                  left: $r('app.float.print_copies_textInput_left_margin'),
245                  right: $r('app.float.print_copies_textInput_right_margin')
246                })
247                .key('Index_TextInput_copies')
248                .onChange((value: string) => {
249                  Log.info(TAG, 'copies onChange value:' + value)
250                  this.printCount = Number.parseInt(value)
251                  this.printCountStr = value//规避前置0输入
252                  this.printCountStr = this.printCount.toString()
253                  Log.info(TAG, 'copies onChange printCount:' + this.printCount)
254                  if (Number.isNaN(this.printCount)) {
255                    this.printCount = Constants.NUMBER_1
256                    this.printCountStr = Constants.STRING_NONE
257                  }
258                  if (this.printCount < Constants.NUMBER_1) {
259                    this.printCount = Constants.NUMBER_1
260                  }
261                  if (this.printCount > Constants.NUMBER_99||this.printCount >= Number.MAX_VALUE) {
262                    this.printCount = Constants.NUMBER_99
263                  }
264                })
265                .onSubmit(() => {
266                  this.printCountStr = Constants.STRING_NONE
267                  this.printCountStr = this.printCount.toString()
268                })
269                .onBlur(() => {
270                  this.printCountStr = ''
271                  this.printCountStr = this.printCount.toString()
272                  Log.info(TAG,'copies onBlur printCountStr: ',this.printCountStr)
273                })
274                .onTouch((e:TouchEvent)=>{
275                  e.stopPropagation()
276                })
277                .onMouse((e:MouseEvent)=>{
278                  e.stopPropagation()
279                })
280              Column() {
281                Image(this.getPlusImage(this.plusMouseState,this.printCount < Constants.NUMBER_99))
282                  .width($r('app.float.print_copies_image_width'))
283                  .height($r('app.float.print_copies_image_height'))
284                  .enabled(this.printCount < Constants.NUMBER_99)
285                  .key('Index_Image_plus_copies')
286                  .onClick(() => {
287                    if (this.printCount < Constants.NUMBER_99) {
288                      this.printCount++
289                      this.printCountStr = this.printCount.toString()
290                    }
291                  })
292                  .onTouch((event: TouchEvent) => {
293                    if (event.type === TouchType.Down) {
294                      this.plusMouseState = MouseState.PRESS
295                    }
296                    if (event.type === TouchType.Up) {
297                      this.plusMouseState = MouseState.NONE
298                    }
299                  })
300                  .onHover((isHover: boolean) => {
301                    if (isHover) {
302                      this.plusMouseState = MouseState.HOVER
303                    } else {
304                      this.plusMouseState = MouseState.NONE
305                    }
306                  })
307                Image(this.getMinusImage(this.minusMouseState,this.printCount > Constants.NUMBER_1))
308                  .width($r('app.float.print_copies_image_width'))
309                  .height($r('app.float.print_copies_image_height'))
310                  .enabled(this.printCount > Constants.NUMBER_1)
311                  .key('Index_Image_minus_copies')
312                  .onClick(() => {
313                    if (this.printCount > Constants.NUMBER_1) {
314                      this.printCount--
315                      this.printCountStr = this.printCount.toString()
316                    }
317                  })
318                  .onTouch((event: TouchEvent) => {
319                    if (event.type === TouchType.Down) {
320                      this.minusMouseState = MouseState.PRESS
321                    }
322                    if (event.type === TouchType.Up) {
323                      this.minusMouseState = MouseState.NONE
324                    }
325                  })
326                  .onHover((isHover: boolean) => {
327                    if (isHover) {
328                      this.minusMouseState = MouseState.HOVER
329                    } else {
330                      this.minusMouseState = MouseState.NONE
331                    }
332                  })
333              }
334              .width($r('app.float.print_copies_image_width'))
335              .height($r('app.float.params_comp_height'))
336
337              Text($r('app.string.ColorMode'))
338                .key('Index_Text_color')
339                .fontSize($r('app.float.font_size_body2'))
340                .height($r('app.float.params_comp_height'))
341                .margin({
342                  left: $r('app.float.text_colorMode_left_margin'),
343                  right: $r('app.float.text_colorMode_right_margin')
344                })
345                .textAlign(TextAlign.Start)
346                .visibility(this.isColorEnabled ? Visibility.Visible : Visibility.None)
347              Toggle({ type: ToggleType.Switch, isOn: !this.isColored })
348                .key('Index_Toggle_color')
349                .width($r('app.float.toggle_colorMode_width'))
350                .margin({ right: $r('app.float.toggle_colorMode_right_margin') })
351                .alignSelf(ItemAlign.Center)
352                .visibility(this.isColorEnabled ? Visibility.Visible : Visibility.None)
353                .onChange((isOn: boolean) => {
354                  this.isColored = !isOn
355                  Log.info(TAG, 'ColorMode onChange: ' + this.isColored)
356                  if (this.isColored) {
357                    this.colorMode = ColorCode.COLOR
358                  } else {
359                    this.colorMode = ColorCode.MONOCHROME
360                  }
361                })
362            }
363            .height($r('app.float.params_row_height'))
364            .width($r('app.float.params_row_width'))
365
366            Column() {
367              Row() {
368                Text($r('app.string.index_page_range'))
369                  .fontSize($r('app.float.font_size_body2'))
370                  .width($r('app.float.text_label_width'))
371                  .textAlign(TextAlign.End)
372                  .key('Index_Text_pageRange')
373                Radio({ value: 'Radio1', group: 'radioGroup' })
374                  .checked(this.printRangeType === PrintRangeType.ALL)
375                  .key('Index_Radio_allPages_pageRange')
376                  .width($r('app.float.image_comp_width'))
377                  .margin({
378                    left: $r('app.float.Radio_pageRange_left_margin'),
379                    right: $r('app.float.Radio_pageRange_right_margin')
380                  })
381                  .onChange((value: boolean) => {
382                    Log.info(TAG,'Radio_range_pageRange all')
383                    if (value) {
384                      if (this.printRangeType === PrintRangeType.CUSTOM) {
385                        this.checkCustomRangeTextInput(true);
386                        this.printRangeType = PrintRangeType.ALL
387                        focusControl.requestFocus('Index_Text_copies')
388                      }
389                      this.printRangeType = PrintRangeType.ALL;
390                      this.updatePrintRange()
391                    }
392                  })
393                Text($r('app.string.index_all_pages'))
394                  .fontSize($r('app.float.font_size_body2'))
395                  .key('Index_Text_allPages_pageRange')
396              }
397              .height($r('app.float.params_row_height'))
398              .width($r('app.float.params_row_width'))
399
400              Row() {
401                Radio({ value: 'Radio2', group: 'radioGroup' })
402                  .checked(this.printRangeType === PrintRangeType.RANGE)
403                  .key('Index_Radio_range_pageRange')
404                  .width($r('app.float.image_comp_width'))
405                  .margin({
406                    left: $r('app.float.Radio_pageRange2_left_margin'),
407                    right: $r('app.float.Radio_pageRange2_right_margin')
408                  })
409                  .onChange((value: boolean) => {
410                    if (value) {
411                      if (this.changeRangeTypeFlag) {
412                        focusControl.requestFocus('Index_TextInput_from_pageRange')
413                      }
414                      this.checkCustomRangeTextInput(true)
415                      Log.info(TAG, 'Radio_range_pageRange onChange: '+ this.endPage)
416                      this.printRangeType = PrintRangeType.RANGE;
417                      this.editCusRangeFlag = false;this.cusRangeText = Constants.NUMBER_1+Constants.HYPHEN+Constants.MAX_PAGES.toString()
418                      this.isRangeRadioEnable = true
419                      this.updatePrintRange()
420                    }else{
421                      Log.info(TAG,'this.isRangeRadioEnable = false')
422                      this.isRangeRadioEnable = false
423                      this.setStartPageStr()
424                      this.setEndPageStr()
425                    }
426                  })
427                  .onTouch((e:TouchEvent)=>{
428                    e.stopPropagation()
429                  })
430                  .onMouse((e:MouseEvent)=>{
431                    e.stopPropagation()
432                  })
433                Text($r('app.string.index_from'))
434                  .maxLines(Constants.NUMBER_2)
435                  .textOverflow({ overflow: TextOverflow.Ellipsis})
436                  .textAlign(TextAlign.Start)
437                  .fontSize($r('app.float.font_size_body2'))
438                  .key('Index_Text_from_pageRange')
439                TextInput({ text: this.startPageStr })
440                  .key('Index_TextInput_from_pageRange')
441                  .width($r('app.float.textInput_pageRange_width'))
442                  .height($r('app.float.params_comp_height'))
443                  .type(InputType.Number)
444                  .maxLength(this.rangeInputLimit)
445                  .fontSize($r('app.float.font_size_body2'))
446                  .fontColor(this.isRangeRadioEnable?Color.Black:Color.Gray)
447                  .border({
448                    width: $r('app.float.border_width'),
449                    radius: $r('app.float.radius_s'),
450                    color: $r('app.color.border_line')
451                  })
452                  .margin({
453                    left: $r('app.float.textInput_pageRange_left_margin'),
454                    right: $r('app.float.textInput_pageRange_right_margin')
455                  })
456                  .backgroundColor(Color.White)
457                  .onChange((value: string) => {
458                    this.startPage = Number.parseInt(value)
459                    this.startPageStr = value//规避前置0输入
460                    this.startPageStr = this.startPage.toString()
461                    Log.info(TAG, 'from change; value = ' + this.startPage + ' endpage = ' + this.endPage)
462                    if (this.startPage < Constants.NUMBER_1) {
463                      this.startPage = Constants.NUMBER_1
464                    } else if (this.startPage > this.endPage) {
465                      this.startPage = this.endPage
466                      Log.info(TAG, 'from change; startPage = ' + this.startPage)
467                    }
468                    if (Number.isNaN(this.startPage)) {
469                      this.startPage = Constants.NUMBER_1
470                      this.startPageStr = Constants.STRING_NONE
471                    }
472                    if (!this.firstStartPageEdit) {
473                      this.printRangeType = PrintRangeType.RANGE;
474                      this.firstStartPageEdit = false
475                    }
476                    this.updatePrintRange();
477                  })
478                  .onSubmit(() => {
479                    Log.info(TAG,'startPageStr  onSubmit: ',this.startPage.toString())
480                    this.setStartPageStr()
481                  })
482                  .onBlur(() => {
483                    Log.info(TAG,'startPageStr  onBlur: ',this.startPage.toString())
484                    this.setStartPageStr()
485                  })
486                  .onFocus(()=>{
487                    this.printRangeType = PrintRangeType.RANGE;
488                  })
489                  .onTouch((e:TouchEvent)=>{
490                    e.stopPropagation()
491                  })
492                  .onMouse((e:MouseEvent)=>{
493                    e.stopPropagation()
494                  })
495
496                Text($r('app.string.index_to'))
497                  .maxLines(Constants.NUMBER_2)
498                  .textOverflow({ overflow: TextOverflow.Ellipsis})
499                  .textAlign(TextAlign.Start)
500                  .fontSize($r('app.float.font_size_body2'))
501                  .key('Index_Text_to_pageRange')
502                TextInput({ text: this.endPageStr })
503                  .width($r('app.float.textInput_pageRange_width'))
504                  .height($r('app.float.params_comp_height'))
505                  .key('Index_TextInput_to_pageRange')
506                  .type(InputType.Number)
507                  .maxLength(this.rangeInputLimit)
508                  .fontSize($r('app.float.font_size_body2'))
509                  .backgroundColor(Color.White)
510                  .fontColor(this.isRangeRadioEnable?Color.Black:Color.Gray)
511                  .margin({
512                    left: $r('app.float.textInput_pageRange_left_margin'),
513                    right: $r('app.float.textInput_pageRange_right_margin')
514                  })
515                  .border({
516                    width: $r('app.float.border_width'),
517                    radius: $r('app.float.radius_s'),
518                    color: $r('app.color.border_line')
519                  })
520                  .onChange((value: string) => {
521                    this.endPage = Number.parseInt(value)
522                    this.endPageStr = value//规避前置0输入
523                    this.endPageStr = this.endPage.toString()
524                    if (this.endPage > this.totalPage) {
525                      this.endPage = this.totalPage
526                    } else if (this.endPage < this.startPage) {
527                      this.endPage = this.startPage
528                    }
529                    if (Number.isNaN(this.endPage)) {
530                      this.endPage = this.startPage
531                      this.endPageStr = Constants.STRING_NONE
532                    }
533                    if(!this.firstEndPageEdit){
534                      this.printRangeType = PrintRangeType.RANGE;
535                      this.firstEndPageEdit = false
536                    }
537                    this.updatePrintRange();
538                  })
539                  .onSubmit(() => {
540                    Log.info(TAG,'endPageStr  onSubmit: ',this.endPage.toString())
541                    this.setEndPageStr();
542                  })
543                  .onBlur(() => {
544                    this.changeRangeTypeFlag = true;
545                    Log.info(TAG,'endPageStr  onBlur: ',this.endPage.toString())
546                    this.setEndPageStr();
547                  })
548                  .onFocus(()=>{
549                    this.changeRangeTypeFlag = false;
550                    this.printRangeType = PrintRangeType.RANGE;
551                    this.updatePrintRange()
552                  })
553                  .onTouch((e:TouchEvent)=>{
554                    e.stopPropagation()
555                  })
556                  .onMouse((e:MouseEvent)=>{
557                    e.stopPropagation()
558                  })
559              }.height($r('app.float.params_row_height')).width($r('app.float.params_row_width'))
560              Row() {
561                Radio({ value: 'Radio3', group: 'radioGroup' })
562                  .checked(this.printRangeType === PrintRangeType.CUSTOM)
563                  .key('Index_Radio_custom_pageRange')
564                  .width(24)
565                  .margin({
566                    left: 98,
567                    right: 8
568                  })
569                  .onChange((value: boolean) => {
570                    if (value) {
571                      focusControl.requestFocus('Index_TextInput_custom_pageRange')
572                      this.printRangeType = PrintRangeType.CUSTOM;
573                      Log.info(TAG,'isCustomRadioEnable = true')
574                      this.isCustomRadioEnable = true
575                      this.updatePrintRange()
576                    }else{
577                      Log.info(TAG,'isCustomRadioEnable = false')
578                      this.isCustomRadioEnable = false
579                    }
580                  })
581                  .onTouch((e:TouchEvent)=>{
582                    e.stopPropagation()
583                  })
584                  .onMouse((e:MouseEvent)=>{
585                    e.stopPropagation()
586                  })
587                Text($r('app.string.index_page_custom'))
588                  .fontSize(14)
589                  .key('Index_Text_custom_pageRange')
590              }.height(48).width(432)
591              TextInput({placeholder:$r('app.string.index_page_custom_example'),text: this.cusRangeText }).key('Index_TextInput_custom_pageRange')
592                .width(326).height(32).border({ width: 1, radius: 8, color: this.cusRangeBorderColor })
593                .margin({
594                  bottom: 8,
595                  left: 98,
596                  right: 8
597                })
598                .backgroundColor(Color.White)
599                .placeholderFont({size:14})
600                .fontColor(this.isCustomRadioEnable?Color.Black:Color.Gray)
601                .fontSize(14)
602                .maxLength(50)
603                .onChange((value:string)=>{
604                  if (this.editCusRangeFlag) {
605                    this.printRangeType = PrintRangeType.CUSTOM;
606                  }else{
607                    this.editCusRangeFlag = true
608                  }
609                  this.checkCustomRange(value);
610                  this.updatePrintRange();
611                  this.cusRangeText = value;
612                })
613                .onBlur(() => {
614                  Log.info(TAG,'cusRangeTextInput onBlur')
615                })
616                .onFocus(()=>{
617                  this.printRangeType = PrintRangeType.CUSTOM;
618                })
619                .onTouch((e:TouchEvent)=>{
620                  e.stopPropagation()
621                })
622                .onMouse((e:MouseEvent)=>{
623                  e.stopPropagation()
624                })
625              Text(this.errorMessage).key('Index_Text_custom_errorMessage')
626                .fontSize($r('app.float.font_size_body3')).fontColor('#E84026').fontWeight(FontWeight.Medium)
627                .margin({
628                  top: 8,
629                  left: 98,
630                  right: 20,
631                  bottom: 8
632                })
633                .visibility((this.isCusRangeError || this.isCusRangeMax)?Visibility.Visible:Visibility.None)
634            }
635            .alignItems(HorizontalAlign.Start)
636
637            MediaSizeSelection()
638            DirectionSelection()
639            MediaTypeSelection().visibility(!this.isPhotoEnabled ? Visibility.None : Visibility.Visible)
640            Row() {
641              Blank()
642              Row(){
643                Checkbox()
644                  .select(this.isBorderless)
645                  .width($r('app.float.image_comp_width'))
646                  .height($r('app.float.image_comp_height'))
647                  .enabled(SelectionModel.getSelectionValue<number>(this.currentMediaType.name) === MediaType.PHOTO)
648                  .key('Index_Checkbox_borderless')
649                  .onChange((value: boolean) => {
650                    if (value) {
651                      this.showToast($r('app.string.borderless_enable_toast'))
652                    }
653                    this.isBorderless = value
654                  })
655              }
656              .onClick(() => {
657                if (SelectionModel.getSelectionValue<number>(this.currentMediaType.name) !== MediaType.PHOTO) {
658                  this.showToast($r('app.string.borderless_type_toast'))
659                }
660              })
661              Text($r('app.string.index_borderless'))
662                .fontSize($r('app.float.font_size_body2'))
663                .width($r('app.float.text_borderless_width'))
664                .opacity(SelectionModel.getSelectionValue<number>(this.currentMediaType.name) === MediaType.PHOTO ? Constants.NUMBER_1 : $r('app.float.disable_opacity'))
665                .key('Index_Text_borderless')
666            }
667            .visibility(!this.isPhotoEnabled? Visibility.None : Visibility.Visible)
668            .height($r('app.float.params_row_height'))
669            .width($r('app.float.params_row_width'))
670
671            QualitySelection()
672            DuplexSelection().visibility(this.isDuplexEnabled ? Visibility.Visible : Visibility.None)
673          }
674          .alignItems(HorizontalAlign.Start)
675          .justifyContent(FlexAlign.Start)
676          .margin({ top: $r('app.float.print_setting_padding_top')
677          , bottom: $r('app.float.print_setting_padding_bottom')
678          })
679
680        }
681        // .height($r('app.float.print_setting_height'))
682        .height(this.printParamCompHeight-73)
683        .width($r('app.float.print_setting_width'))
684        .margin({left:24,right:24})
685        .scrollable(ScrollDirection.Vertical)  // 滚动方向纵向
686        .scrollBar(BarState.Off)
687        .edgeEffect(EdgeEffect.None)
688        .align(Alignment.Top)
689        .enabled(!this.isGlobalDisable)
690        .opacity(this.isGlobalDisable?0.4:1)
691
692        Column().height(12)
693        Divider()
694          .width($r('app.float.print_setting_width'))
695          .strokeWidth(Constants.NUMBER_1)
696          .color($r('app.color.black'))
697          .opacity($r('app.float.divider_opacity'))
698          .key('Index_Divider')
699        Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End, alignItems: ItemAlign.Center }) {
700          AboutPageComponent().margin({left:24,right:152})
701          CancelButton({
702            cancelLabel: $r('app.string.Cancel'),
703            cancelWidth: $r('app.float.button_index_width'),
704            cancelHeight: $r('app.float.button_index_height'),
705            cancelClick: () => {
706              this.session?.terminateSelf().then(() => {
707                console.info('===>terminateSelfCallBack===>: ');
708              });
709            }
710          })
711            .key('Index_Button_cancel')
712            .margin({ right: $r('app.float.button_index_cancel_margin_right') })
713
714          Button($r('app.string.Index_doPrint'))
715            .key('Index_Button_doPrint')
716            .width($r('app.float.button_index_width'))
717            .height($r('app.float.button_index_height'))
718            .margin({ right: $r('app.float.button_index_doPrint_margin_right') })
719            .enabled(this.canPrint && this.printButtonFlag && !this.isCusRangeError && !this.isGlobalDisable)
720            .fontColor($r('app.color.white'))
721            .onClick(() => {
722              this.getJobDescription()
723              this.startPrint()
724            })
725        }
726        .margin({
727          top: $r('app.float.print_setting_margin_top'),
728          bottom: $r('app.float.print_setting_margin_bottom')
729        })
730      }.width($r('app.float.print_setting_width'))
731    }
732    .padding({ top: 32, bottom: 32 })
733    .backgroundColor($r('sys.color.ohos_id_color_panel_bg'))
734    .onTouch((event:TouchEvent)=>{
735      if (event.type === TouchType.Down) {
736        Log.info(TAG,'requestFocus')
737        focusControl.requestFocus('Index_Text_copies')
738      }
739    })
740  }
741
742  public getPlusImage(mouseState: number,isEnabled :boolean): Resource {
743    if (!isEnabled){
744      return $r('app.media.ic_plus_disabled');
745    }
746    switch (mouseState) {
747      case MouseState.PRESS:
748        return $r('app.media.ic_plusPress');
749      case MouseState.HOVER:
750        return $r('app.media.ic_plusHover');
751      default:
752        return $r('app.media.ic_plus');
753    }
754  }
755
756  public getMinusImage(mouseState: number,isEnabled :boolean): Resource {
757    if (!isEnabled){
758      return $r('app.media.ic_minus_disabled');
759    }
760    switch (mouseState) {
761      case MouseState.PRESS:
762        return $r('app.media.ic_minusPress');
763      case MouseState.HOVER:
764        return $r('app.media.ic_minusHover');
765      default:
766        return $r('app.media.ic_minus');
767    }
768  }
769
770  aboutToAppear() {
771    Log.info(TAG, 'aboutToAppear')
772    this.getWant()
773    this.loadImageSources();
774    this.setSelect();
775    this.initParams();
776    this.bindService();
777    this.recordLastUsedPrinter();
778    this.preDiscovery();
779    this.checkWlan();
780    this.subscribe();
781  }
782
783  aboutToDisappear() {
784    this.unsubscribe()
785    this.abilityContext = undefined
786    clearInterval(this.ConnectTimer)
787    this.releaseResource();
788  }
789
790  releaseResource() {
791    Log.info(TAG, 'start release resource');
792    if (CheckEmptyUtils.isEmptyArr<FileModel>(this.imageSources)) {
793      return;
794    }
795    for (let imageModel of this.imageSources) {
796      imageModel.imageSource.release();
797    }
798  }
799
800  showToast(message: Resource) {
801    try {
802      promptAction.showToast({
803        message: message,
804        duration: Constants.TOAST_INTERVAL,
805        bottom: Constants.TOAST_BOTTOM
806      });
807    } catch (error) {
808      Log.error(TAG, `showToast args error code is ${error.code}, message is ${error.message}`);
809    }
810    ;
811  }
812
813  private getWant() {
814    this.abilityContext = GlobalThisHelper.getValue<common.UIExtensionContext>(GlobalThisStorageKey.KEY_MAIN_ABILITY_CONTEXT)
815    if (CheckEmptyUtils.isEmpty<LocalStorage>(storage)) {
816      storage = router.getParams() as LocalStorage;
817    }
818    this.jobId = storage.get<string>(Constants.WANT_JOB_ID_KEY)!;
819    this.jobFileList = storage.get<Array<string>>(Constants.WANT_FILE_LIST_KEY)!;
820    this.session = storage.get<UIExtensionContentSession>(Constants.SESSION);
821    Log.debug(TAG, 'aboutToAppear jobId: ' + JSON.stringify(this.jobId) + ', fileList: ' + JSON.stringify(this.jobFileList));
822  }
823
824  private subscribe() {
825
826    let innerEventState: emitter.InnerEvent = { eventId: AppCommonEvent.PRINTER_STATE_CHANGE_EVENT }
827    emitter.on(innerEventState, (eventData) => {
828      let printers = AppStorage.get<Array<PrinterInfo>>(AppStorageKeyName.PRINTER_QUEUE_NAME)
829
830      if (this.printer === undefined || printers === undefined) {
831        Log.error(TAG, 'emitter callback this printer is null or printers is null, return');
832        return
833      }
834      Log.info(TAG, 'emitter PRINTER_STATE_CHANGE_EVENT callback this.printer: '
835      + StringUtil.encodeCommonString(this.printer.printerName));
836      for (let index = 0; index < printers.length; index++) {
837        if (printers[index].printerId === this.printer.printerId) {
838          this.checkPrinterConnection(printers[index].printerState)
839        }
840      }
841    })
842
843    let innerEventCap: emitter.InnerEvent = { eventId: AppCommonEvent.PRINTER_UPDATE_CAPABILITY_EVENT }
844    emitter.on(innerEventCap, (eventData) => {
845      let printers = AppStorage.get<Array<PrinterInfo>>(AppStorageKeyName.PRINTER_QUEUE_NAME);
846      if (this.printer === undefined || this.printer === null) {
847        Log.error(TAG, 'printer is undefined');
848        return;
849      }
850      Log.error(TAG, 'emitter PRINTER_UPDATE_CAPABILITY_EVENT callback this.printer: ' + StringUtil.encodeCommonString(this.printer.printerName));
851      if (printers === undefined) {
852        Log.error(TAG, 'emitter callback printers is null, return');
853        return
854      }
855      for (let index = 0; index < printers.length; index++) {
856        if (printers[index].printerId === this.printer.printerId) {
857          clearInterval(this.ConnectTimer)
858          this.connectConfirmDialogCtl.close()
859          this.printer.capability = printers[index].capability
860          this.printer.options = printers[index].options
861          this.printer.description = printers[index].description
862          Log.info(TAG, 'this.printer.capability update: ', JSON.stringify(this.printer.capability))
863          this.updateSupportParam(printers[index])
864        }
865      }
866    })
867
868    let inactiveWlanEvent: emitter.InnerEvent = { eventId: AppCommonEvent.WLAN_INACTIVE_EVENT }
869    emitter.on(inactiveWlanEvent, (eventData) => {
870      Log.info(TAG, 'WLAN_INACTIVE_EVENT')
871      this.isNeedListenWlan = true
872      let isPrinterSelectDialogOpen = GlobalThisHelper.getValue<boolean>(GlobalThisStorageKey.KEY_PRINTER_SELECT_DIALOG_OPEN);
873      Log.info(TAG, 'isPrinterSelectDialogOpen: ' + isPrinterSelectDialogOpen)
874      if (isPrinterSelectDialogOpen) {
875        this.PrintingSelectDialogCtl.close()
876        GlobalThisHelper.createValue<boolean>(false, GlobalThisStorageKey.KEY_PRINTER_SELECT_DIALOG_OPEN, true);
877        this.WLANConfirmDialogCtl.open()
878      }
879    })
880
881    let activeWlanEvent: emitter.InnerEvent = { eventId: AppCommonEvent.WLAN_ACTIVE_EVENT }
882    emitter.on(activeWlanEvent, (eventData) => {
883      Log.info(TAG, 'WLAN_ACTIVE_EVENT')
884      if (this.isNeedListenWlan) {
885        this.isNeedListenWlan = false
886        this.adapter?.getPrinterDiscCtl()?.startDiscovery(Constants.STRING_NONE, [])
887      }
888
889    })
890
891    let innerEventPrinter: emitter.InnerEvent = { eventId: AppCommonEvent.ADD_PRINTER_EVENT }
892    emitter.on(innerEventPrinter, (eventData) => {
893      if (!this.firstPrinterDiscoveredFlag){
894        this.firstPrinterDiscoveredFlag = true;
895      }
896      if(this.isGlobalDisable){
897        Log.info(TAG, 'last printer no need connecting');
898        emitter.off(AppCommonEvent.ADD_PRINTER_EVENT);
899        return;
900      }
901      if (CheckEmptyUtils.isEmpty(eventData) || CheckEmptyUtils.isEmpty(eventData.data)) {
902        Log.error(TAG, 'add_printer info is empty.');
903        return;
904      }
905      let printerJSON: string = eventData!.data!.printer
906      let printer: PrinterInfo = JSON.parse(printerJSON)
907      Log.info(TAG, 'ADD_PRINTER_EVENT')
908      if (printer.printerId === this.usedPrinterId) {
909        Log.info(TAG, 'last printer is connecting');
910        this.printer = printer;
911        this.adapter?.getPrinterDiscCtl()?.connectPrinter(printer)
912        emitter.off(AppCommonEvent.ADD_PRINTER_EVENT)
913      }
914
915    })
916
917
918    print.on('extInfoChange', (extensionId: string, info: string) => {
919      let extInfo: ErrorMessage = JSON.parse(info)
920      Log.info(TAG, 'extInfoChange: ', info)
921      if (CheckEmptyUtils.isEmpty(this.printer)){
922        Log.info(TAG, 'invalid printer!')
923        return;
924      }
925      switch (extInfo.code){
926        case ErrorCode.IPP_CONNECT_ERROR:
927          this.connectionFailed();
928          break;
929        case ErrorCode.GET_CAPS_ERROR:
930          this.adapter?.getPrinterDiscCtl()?.queryPrinterCapability(this.printer!.printerId);
931          break;
932        case ErrorCode.CONNECTION_POP:
933          if (this.printer!.printerId !== this.usedPrinterId){
934            this.connectFlag = !this.connectFlag
935          }
936        default:
937          break;
938      }
939    })
940  }
941
942  private unsubscribe() {
943    emitter.off(AppCommonEvent.PRINTER_STATE_CHANGE_EVENT)
944    emitter.off(AppCommonEvent.PRINTER_UPDATE_CAPABILITY_EVENT)
945    emitter.off(AppCommonEvent.WLAN_INACTIVE_EVENT)
946
947    print.off('extInfoChange')
948  }
949
950  preDiscovery() {
951    this.adapter?.getPrinterDiscCtl()?.startDiscovery(Constants.STRING_NONE, [])
952  }
953
954  checkWlan(){
955    if (!WifiP2pHelper.checkWifiActive()) {
956      Log.info(TAG,'checkWlan: inactive')
957      this.isNeedListenWlan = true;
958    }
959  }
960
961  bindService() {
962    this.adapter = PrintAdapter.getInstance();
963  }
964
965  setSelectDefault(disconnectFlag: boolean) {
966    if (this.printer === undefined || disconnectFlag) {
967      Log.info(TAG, 'setSelectDefault')
968      this.currentPrinterSelection = SelectionModel.NO_Printer
969      this.printerSelectArray = []
970      this.printerSelectArray.push(SelectionModel.Add_Printer)
971    }
972  }
973
974  initParams() {
975    this.printButtonFlag = true
976    this.printerPageSize = MediaSizeUtil.mediaSizeToPageSize(SelectionModel.getSelectionValue<MediaSize>(SelectionModel.MediaSize_ISO_A4.name))
977  }
978
979  setSelect() {
980    SelectionModel.initSelectionMap();
981    this.setSelectDefault(false);
982    this.setMediaSizesSelect();
983    this.setDirectionSelect();
984    this.setMediaTypeSelect();
985    this.setPrintQualitySelect();
986    this.setDuplexSelect();
987  }
988
989  updatePrintRange() {
990    Log.info(TAG, 'updatePrintRange'+ this.startPage+' '+this.endPage)
991    this.printRange = []
992    switch (this.printRangeType) {
993      case PrintRangeType.ALL:
994        for (let num = 1; num <= this.totalPage; ) {
995          this.printRange.push(num)
996          num++
997        }
998        break;
999      case PrintRangeType.RANGE:
1000        for (let num = this.startPage; num <= this.endPage; ) {
1001          this.printRange.push(num)
1002          num++
1003        }
1004        break;
1005      case PrintRangeType.CUSTOM:
1006        this.printRange = CopyUtil.deepClone(this.cusRangeArr)
1007        Log.info(TAG,'updatePrintRange CUSTOM  this.printRange ',JSON.stringify(this.printRange))
1008        break;
1009      default:
1010        break;
1011    }
1012
1013    if (this.printRange.length === 0){
1014      if (this.allPages != undefined) {
1015        this.printRange = CopyUtil.deepClone(this.allPages)
1016      }else{
1017        for (let num = 1; num <= this.totalPage; ) {
1018          this.printRange.push(num)
1019          num++
1020        }
1021      }
1022    }
1023    this.imageCount = this.printRange.length
1024    this.needDuplex = this.imageCount>1?true:false
1025  }
1026
1027  updateMediaSize() {
1028    if (CheckEmptyUtils.isEmpty(this.currentMediaSize)) {
1029      return
1030    }
1031    if (!CheckEmptyUtils.isEmpty(SelectionModel.getSelectionValue<MediaSize>(this.currentMediaSize.name))) {
1032      this.mediaSize = SelectionModel.getSelectionValue<MediaSize>(this.currentMediaSize.name)!;
1033      Log.info(TAG, 'updateMediaSize:MediaSize = ' + JSON.stringify(this.mediaSize))
1034      this.printerPageSize = MediaSizeUtil.mediaSizeToPageSize(this.mediaSize)
1035    }
1036    Log.info(TAG, 'afterUpdateMediaSize: ' + this.printerPageSize?.name)
1037  }
1038
1039  updateMediaType() {
1040    if (this.printer !== undefined) {
1041      let isBSH = this.isBiSheng(this.printer.printerName)
1042      if (isBSH) {
1043        this.mediaSizeList = MediaSizeUtil.getDefaultMediaSizeByMediaType(SelectionModel.getSelectionValue<number>(this.currentMediaType.name)!);
1044      }
1045      this.setMediaSizesSelect()
1046    }
1047    this.setPrintQualitySelect()
1048    if (this.currentMediaType.name === SelectionModel.MediaType_NORMAL.name) {
1049      Log.info(TAG,'this.isBorderless = false')
1050      this.isBorderless = false
1051    }
1052  }
1053
1054  updateDirection() {
1055    this.pageDirection = SelectionModel.getSelectionValue<number>(this.currentMediaType.name)!;
1056  }
1057
1058  /**
1059   * 更新打印机能力支持的参数
1060   *
1061   * @param cap
1062   */
1063  updateSupportParam(printer: PrinterInfo) {
1064    Log.info(TAG, 'updateSupportParam printer: ' + StringUtil.encodeCommonString(this.printer?.printerName));
1065    let cap = printer.capability
1066    if (CheckEmptyUtils.isEmpty(cap)) {
1067      return
1068    }
1069
1070    if (cap!.colorMode === ColorCode.MONOCHROME) {
1071      this.colorMode = ColorCode.MONOCHROME
1072      this.isColored = false
1073      this.isColorEnabled = false
1074    }else{
1075      this.isColorEnabled = true
1076    }
1077
1078    if (cap!.duplexMode === Duplex.SINGLE) {
1079      this.isDuplexEnabled = false;
1080      this.currentDuplex = SelectionModel.DuplexMode_SINGLE;
1081    } else {
1082      this.isDuplexEnabled = true;
1083    }
1084    let isBSH = this.isBiSheng(printer.printerName)
1085    if (isBSH) {
1086      this.mediaSizeList = MediaSizeUtil.getDefaultMediaSizeByMediaType(SelectionModel.getSelectionValue<number>(this.currentMediaType.name)!);
1087    } else {
1088      this.mediaSizeList = new Array<MediaSize>()
1089      for (let index = 0; index < cap!.pageSize.length; index++) {
1090        this.mediaSizeList.push(MediaSizeUtil.pageSizeToMediaSize(cap!.pageSize[index]))
1091      }
1092    }
1093    Log.debug(TAG,'printer.options:',printer.options)
1094    let options: PrinterCapsOptions = JSON.parse(printer.options!);
1095    if(!CheckEmptyUtils.isEmpty(options?.supportedMediaTypes)){
1096      this.supportedMediaTypes = options?.supportedMediaTypes
1097    }
1098    Log.debug(TAG,'supportedMediaTypes:',JSON.stringify(this.supportedMediaTypes))
1099    this.setMediaTypeSelect()
1100    this.setMediaSizesSelect()
1101    this.canPrint = true
1102  }
1103
1104  updateImageSources(){
1105    Log.info(TAG,'updateImageSources length = '+this.imageSources.length)
1106    this.allPages = []
1107    for (let num = 1; num <= this.imageSources.length; ) {
1108      this.allPages.push(num)
1109      num++
1110    }
1111  }
1112
1113  isBiSheng(printerName: string): boolean {
1114    Log.info(TAG, 'isBiSheng:', StringUtil.encodeCommonString(printerName));
1115    return printerName.includes(BISHENG_PRINTER);
1116  }
1117
1118  setMediaSizesSelect() {
1119    if (CheckEmptyUtils.isEmptyArr(this.mediaSizeList)) {
1120      MediaSizeUtil.initMediaSizeArray(this.mediaSizeList);
1121    }
1122    Log.info(TAG, 'setMediaSizesSelect mediaSizeList.length:' + this.mediaSizeList.length);
1123    this.mediaSizeSelectArray = new Array<SelectionModel>()
1124    let isNeedResetMediaSize = true
1125    this.mediaSizeList.forEach(mediaSize => {
1126      if (this.currentMediaSize.res === mediaSize.label) {
1127        isNeedResetMediaSize = false
1128      }
1129      let mediaSizeSelection = SelectionModel.getSelectionModelByLabel(mediaSize.label)!
1130      if(!CheckEmptyUtils.isEmpty(mediaSizeSelection)){
1131        this.mediaSizeSelectArray.push(mediaSizeSelection)
1132      }
1133    });
1134    Log.info(TAG, 'this.mediaSizeSelectArray.length: ' + this.mediaSizeSelectArray.length)
1135    if(isNeedResetMediaSize){
1136      this.currentMediaSize = SelectionModel.MediaSize_ISO_A4;
1137    }
1138  }
1139
1140  setDirectionSelect() {
1141    this.directionSelectArray = new Array<SelectionModel>()
1142    this.directionSelectArray.push(SelectionModel.Direction_AUTO, SelectionModel.Direction_LANDSCAPE, SelectionModel.Direction_VERTICAL)
1143  }
1144
1145  setMediaTypeSelect() {
1146    this.mediaTypeSelectArray = new Array<SelectionModel>()
1147    if(this.supportedMediaTypes.length === Constants.NUMBER_1){
1148      this.isPhotoEnabled = false
1149      this.mediaTypeSelectArray.push(SelectionModel.MediaType_NORMAL)
1150      if (this.currentMediaType.name == SelectionModel.MediaType_PHOTO.name) {
1151        this.currentMediaType = SelectionModel.MediaType_NORMAL
1152      }
1153    } else {
1154      this.isPhotoEnabled = true
1155      this.mediaTypeSelectArray.push(SelectionModel.MediaType_NORMAL, SelectionModel.MediaType_PHOTO)
1156    }
1157  }
1158
1159  setPrintQualitySelect() {
1160    this.qualitySelectArray = new Array<SelectionModel>()
1161    if (SelectionModel.getSelectionValue<number>(this.currentMediaType.name) === MediaType.NORMAL) {
1162      this.qualitySelectArray.push(SelectionModel.PrintQuality_BEST, SelectionModel.PrintQuality_STANDARD, SelectionModel.PrintQuality_ECONOMY);
1163    } else {
1164      this.qualitySelectArray.push(SelectionModel.PrintQuality_BEST, SelectionModel.PrintQuality_STANDARD);
1165      if (this.currentQuality = SelectionModel.PrintQuality_ECONOMY) {
1166        this.currentQuality = SelectionModel.PrintQuality_STANDARD
1167      }
1168    }
1169  }
1170
1171  setDuplexSelect() {
1172    this.duplexSelectArray = new Array<SelectionModel>()
1173    this.duplexSelectArray.push(SelectionModel.DuplexMode_SINGLE, SelectionModel.DuplexMode_LONG, SelectionModel.DuplexMode_SHORT)
1174  }
1175
1176  isPrintRangeAll(): boolean {
1177    Log.info(TAG,'startPage,endPage,totalPage'+this.startPage+' '+this.endPage+' '+this.totalPage )
1178    if (this.startPage === 1 && (this.endPage === this.totalPage || this.totalPage === Constants.NUMBER_0)) {
1179      return true;
1180    } else {
1181      return false;
1182    }
1183  }
1184
1185  /**
1186   * 加载第三方应用传过来的图片信息
1187   *
1188   * @param name
1189   */
1190  async loadImageSources() {
1191    Log.info(TAG, 'loadImageSources start')
1192    if (this.jobFileList && this.jobFileList.length !== 0) {
1193      this.fileNum = this.jobFileList.length;
1194      this.imageSources = await FileUtil.initImageData(this.checkMaxPages(this.jobFileList));
1195    } else {
1196      await print.queryPrintJobById(this.jobId).then(async (printJob) => {
1197        if (!CheckEmptyUtils.isEmpty(printJob) && !CheckEmptyUtils.isEmptyArr(printJob.fdList)) {
1198          this.fileNum = printJob.fdList.length;
1199          Log.debug(TAG, 'queryPrintJobById printJob: ', JSON.stringify(printJob));
1200          this.imageSources = await FileUtil.initFdImageData(printJob.fdList);
1201        }
1202      })
1203    }
1204    Log.debug(TAG, "loadImageSources imageSources: ", JSON.stringify(this.imageSources))
1205    this.totalPage = this.imageSources.length === 0 ? 1 : this.imageSources.length
1206    this.imageCount = this.totalPage
1207    this.rangeInputLimit = this.totalPage.toString().length
1208    let errorCount: number = GlobalThisHelper.getValue<number>(GlobalThisStorageKey.KEY_IMAGE_ERROR_COUNT)
1209    let errorName: string = GlobalThisHelper.getValue<string>(GlobalThisStorageKey.KEY_IMAGE_ERROR_NAME)
1210    if (this.imageSources.length !== 0){
1211      if (errorCount === 1) {
1212        Log.info(TAG, "loadImageSources this.showToast ")
1213        setTimeout(() => {//延迟弹窗,否则会概率弹窗失败
1214          this.showToast($r('app.string.toast_preview_failed',errorName))
1215        }, Constants.SHOW_TOAST_TIMEOUT);
1216      } else if (errorCount > 1) {
1217        setTimeout(() => {//延迟弹窗,否则会概率弹窗失败
1218          this.showToast($r('app.string.toast_preview_failed_plurals',errorName,errorCount))
1219        }, Constants.SHOW_TOAST_TIMEOUT);
1220      }
1221    }else{
1222      this.isPreviewFailed = true;
1223    }
1224    this.endPage = this.totalPage
1225    if (this.imageSources.length > Constants.MAX_PAGES) {//需要弹预览失败toast时不用弹100张限制的toast
1226      this.isAbovePageLimit = true;
1227      this.endPage = Constants.MAX_PAGES;
1228    }
1229    this.isGlobalDisable = this.imageSources.length === 0 ? true : false
1230    this.endPageStr = this.endPage.toString()
1231    this.updatePrintRange()
1232
1233
1234  }
1235
1236  /**
1237   * 记录上一次使用过的打印机
1238   */
1239  async recordLastUsedPrinter() {
1240    let printerString = FileUtil.readStringFromFile(this.usedPrinterFileName, this.abilityContext)
1241    if (CheckEmptyUtils.checkStrIsEmpty(printerString)) {
1242      Log.error(TAG, 'lasted used printer is null');
1243      return;
1244    }
1245    let printer: PrinterInfo = JSON.parse(printerString);
1246    this.usedPrinterId = printer.printerId
1247    Log.info(TAG, 'load last printer: ' + StringUtil.encodeCommonString(printer.printerName));
1248  }
1249
1250  /**
1251   * 保存成功连接并执行过打印的打印机
1252   *
1253   * @param printer 打印机信息
1254   */
1255  saveLastedUsedPrinter(printer: PrinterInfo | undefined) {
1256    Log.info(TAG, 'saveLastedUsedPrinter printer: ' + StringUtil.encodeCommonString(printer?.printerName));
1257    if (CheckEmptyUtils.isEmpty(printer)) {
1258      Log.error(TAG, 'printer is null')
1259      return;
1260    }
1261    let printerString = JSON.stringify(printer!)
1262    if (CheckEmptyUtils.checkStrIsEmpty(printerString)) {
1263      Log.error(TAG, 'printer string is null')
1264      return;
1265    }
1266    FileUtil.writeStringToFile(printerString, this.usedPrinterFileName, this.abilityContext);
1267    Log.info(TAG, 'printer save success')
1268  }
1269
1270  openPrinterSelectDialog() {
1271    Log.info(TAG,'openPrinterSelectDialog printerSelectFlag : '+this.printerSelectFlag)
1272    if (this.printerSelectFlag) {
1273      this.printerSelectFlag = false
1274      this.PrintingSelectDialogCtl.close();
1275      this.PrintingSelectDialogCtl.open();
1276    }
1277  }
1278
1279  openWLANDialog() {
1280    this.WLANConfirmDialogCtl.open()
1281  }
1282
1283  connectAlarm() {
1284    clearInterval(this.ConnectTimer)
1285    this.connectConfirmDialogCtl.open()
1286    this.connectCount = Constants.CONNECT_COUNT
1287    this.ConnectTimer = setInterval(() => {
1288      this.connectCountDown()
1289    }, Constants.COUNTDOWN_INTERVAL);
1290  }
1291
1292  connectCountDown() {
1293    this.connectCount--
1294    if (this.connectCount === Constants.COUNTDOWN_ALARM_TO_FAIL) {
1295      this.connectConfirmDialogCtl.close()
1296    } else if (this.connectCount === Constants.NUMBER_0 && !this.isConnected) {
1297      this.connectionFailed()
1298    }
1299  }
1300
1301  onPrinterChange() {
1302    if (this.printer !== undefined) {
1303      this.currentPrinterSelection = new SelectionModel(this.printer.printerName, this.printer.printerName);
1304      SelectionModel.createSelectionValue<PrinterInfo>(this.printer,this.printer.printerName);
1305      Log.info(TAG, 'onPrinterChange printerName: ' + StringUtil.encodeCommonString(this.currentPrinterSelection.name));
1306    }
1307  }
1308
1309
1310  /**
1311   * 打印机状态发生变化时进行处理
1312   *
1313   * @param printerState 打印机状态
1314   */
1315  checkPrinterConnection(printerState: print.PrinterState) {
1316    Log.error(TAG, 'checkPrinterConnection printerState: ' + JSON.stringify(printerState));
1317    if (CheckEmptyUtils.isEmpty(this.printer)) {
1318      Log.error(TAG, 'checkPrinterConnection, invalid printer.');
1319      return;
1320    }
1321    switch (printerState) {
1322      case print.PrinterState.PRINTER_CONNECTED:
1323        this.isConnected = true
1324        this.connectingPrinterId = this.printer!.printerId;
1325        clearInterval(this.ConnectTimer)
1326        this.connectConfirmDialogCtl.close();
1327        break;
1328      case print.PrinterState.PRINTER_DISCONNECTED:
1329        this.connectionFailed()
1330        break;
1331      default:
1332        break;
1333    }
1334
1335  }
1336  /**
1337   * 将渲染的图片保存
1338   */
1339  async saveImage(jobFiles: string[]): Promise<number[]> {
1340    Log.info(TAG, 'enter saveImage')
1341    let fileList = new Array<number>();
1342    if (this.mediaSize === undefined) {
1343      Log.error(TAG, 'this.mediaSize is undefined')
1344      return fileList;
1345    }
1346    let size = this.mediaSize.get300PixelMediaSize();
1347    let imageSourceIndexList = new Array<number>();
1348    let finalPrintRange = this.checkPrintRange();
1349    for (let index = 0; index < finalPrintRange.length; index++) {
1350      imageSourceIndexList.push(finalPrintRange[index] - 1);
1351    }
1352    Log.info(TAG, 'imageSourceIndexList: ', JSON.stringify(imageSourceIndexList))
1353    let len = imageSourceIndexList.length;
1354    for (let index = 0; index < len; index++) {
1355      Log.info(TAG,'imageModel START ,this.imageSources '+JSON.stringify(this.imageSources))
1356      let imageModel = this.imageSources[imageSourceIndexList[index]];
1357      Log.info(TAG,'imageModel: '+JSON.stringify(imageModel))
1358      let offCanvas: OffscreenCanvasRenderingContext2D | undefined = undefined;
1359      let scale: number;
1360      let offCanvasWidth: number;
1361      let offCanvasHeight: number;
1362      let orientation: PageDirection = PageDirection.AUTO;
1363      if (this.pageDirection === PageDirection.VERTICAL || (this.pageDirection === PageDirection.AUTO && imageModel.height >= imageModel.width)) {
1364        //竖向 或者 自适应且图片竖向
1365        Log.debug('VERTICAL');
1366        offCanvasWidth = px2fp(size.width);
1367        offCanvasHeight = px2fp(size.height);
1368        orientation = PageDirection.VERTICAL
1369      } else if (this.pageDirection === PageDirection.LANDSCAPE || (this.pageDirection === PageDirection.AUTO && imageModel.height <= imageModel.width)) {
1370        //横向 自适应且图片横向
1371        Log.debug('LANDSCAPE');
1372        offCanvasWidth = px2fp(size.height);
1373        offCanvasHeight = px2fp(size.width);
1374        orientation = PageDirection.LANDSCAPE
1375      } else {
1376        offCanvasWidth = px2fp(size.width);
1377        offCanvasHeight = px2fp(size.height);
1378        Log.error('set offCanvas size error');
1379      }
1380      offCanvas = new OffscreenCanvasRenderingContext2D(offCanvasWidth, offCanvasHeight, new RenderingContextSettings(true));
1381      if (offCanvas === undefined) {
1382        Log.error(TAG, 'offCanvas is undefined');
1383        continue;
1384      }
1385      offCanvas.imageSmoothingEnabled = false;
1386      offCanvas.fillStyle = '#fff'
1387      offCanvas.fillRect(Constants.NUMBER_0, Constants.NUMBER_0, offCanvasWidth, offCanvasHeight);
1388      scale = this.isBorderless ? Math.max(offCanvasWidth / px2fp(imageModel.width), offCanvasHeight / px2fp(imageModel.height)) :
1389      Math.min(offCanvasWidth / px2fp(imageModel.width), offCanvasHeight / px2fp(imageModel.height));
1390      let xPosition = (offCanvasWidth - px2fp(imageModel.width * scale)) / Constants.NUMBER_2;
1391      let yPosition = (offCanvasHeight - px2fp(imageModel.height * scale)) / Constants.NUMBER_2;
1392
1393      //将处理好的offCanvas图片写到本地文件
1394      if (CheckEmptyUtils.isEmpty(imageModel.imageSource)) {
1395        Log.error(TAG, 'imageSource is error');
1396        continue;
1397      }
1398      Log.info(TAG, 'begin createPixelMap');
1399      let imageSource: image.ImageSource | undefined = undefined;
1400      let pixelMap: image.PixelMap | undefined = undefined;
1401      let canvasPixelMap: image.PixelMap | undefined = undefined;
1402      try {
1403        imageSource = image.createImageSource(imageModel.fd);
1404        if (CheckEmptyUtils.isEmpty(imageSource)) {
1405          Log.error(TAG, 'imageSource is error')
1406          continue;
1407        };
1408        const editResult: boolean = orientation === PageDirection.LANDSCAPE ? true : false;
1409        pixelMap = await imageSource!.createPixelMap({editable: editResult});
1410        if (CheckEmptyUtils.isEmpty(pixelMap)) {
1411          Log.error(TAG, 'pixelMap is error')
1412          continue;
1413        };
1414        imageModel.imageSource!.release();
1415        Log.info(TAG, 'end createPixelMap');
1416        offCanvas.drawImage(pixelMap, xPosition, yPosition, px2fp(imageModel.width * scale), px2fp(imageModel.height * scale)) //5184 3456 //1200 2133
1417        canvasPixelMap = offCanvas.getPixelMap(Constants.NUMBER_0, Constants.NUMBER_0, offCanvasWidth, offCanvasHeight);
1418
1419        //保存图片
1420        Log.info(TAG, 'begin createDataShareUri');
1421        if (CheckEmptyUtils.checkStrIsEmpty(this.firstFileName)) {
1422          this.firstFileName = imageModel.name;
1423          Log.info(TAG, 'init firstFileName:' + this.firstFileName)
1424        }
1425        let fileName = uuidGenerator() + Constants.JPEG_SUFFIX;
1426        FileUtil.createJobsDir(this.abilityContext?.filesDir)
1427        let uri = this.abilityContext?.filesDir + Constants.FILE_SEPARATOR + Constants.TEMP_JOB_FOLDER + Constants.FILE_SEPARATOR + fileName
1428        await FileUtil.saveImageToJpeg(canvasPixelMap, uri, orientation);
1429        Log.debug(TAG, 'end saveImageToJpeg');
1430        jobFiles.push(uri);
1431      } catch (error) {
1432        Log.error(TAG, 'error happened: ' + JSON.stringify(error))
1433      } finally {
1434        //释放资源
1435        if (pixelMap !== undefined) {
1436          pixelMap.release();
1437        }
1438        if (canvasPixelMap !== undefined) {
1439          canvasPixelMap.release();
1440        }
1441        if (imageSource !== undefined) {
1442          imageSource.release();
1443        }
1444      }
1445    }
1446    Log.info(TAG, 'exit saveImage');
1447    fileList = FileUtil.getFdList(jobFiles);
1448    this.jobNum = fileList.length
1449    this.jobName = this.getJobName(this.jobNum)
1450
1451    return fileList;
1452  }
1453
1454  /**
1455   * 开始打印
1456   *
1457   */
1458  startPrint() {
1459    Log.info(TAG, 'startPrint')
1460    this.isGlobalDisable = true
1461    this.saveLastedUsedPrinter(this.printer)
1462    if (this.printRangeType === PrintRangeType.CUSTOM) {
1463      this.checkCustomRangeTextInput(false)
1464    }
1465
1466    let jobFiles = new Array<string>()
1467    this.saveImage(jobFiles).then((fileList) => {
1468      let ops: PrintJobOptions = {
1469        jobName: this.jobName,
1470        jobNum: this.jobNum * this.printCount,
1471        jobDescription: this.jobDes,
1472        mediaType: this.getMediaType(SelectionModel.getSelectionValue<number>(this.currentMediaType.name)!),
1473        documentCategory: SelectionModel.getSelectionValue<number>(this.currentMediaType.name) === MediaType.PHOTO ? Constants.NUMBER_1 : Constants.NUMBER_0,
1474        printQuality: SelectionModel.getSelectionValue<number>(this.currentQuality.name)!.toString(),
1475        printerName: this.removeSpaces(this.printer?.printerName),
1476        printerUri: this.getPrinterUri(),
1477        documentFormat: 'image/jpeg',
1478        files: jobFiles
1479      }
1480      let options = JSON.stringify(ops);
1481      this.printJob = new PrintJob(jobFiles,fileList,this.jobId, this.printer!.printerId, print.PrintJobState.PRINT_JOB_PREPARE, print.PrintJobSubState.PRINT_JOB_COMPLETED_SUCCESS,
1482        this.printCount,this.printerRange!,true,this.printerPageSize!,true,this.colorMode,SelectionModel.getSelectionValue<number>(this.currentDuplex.name)!,new PrintMargin(Constants.NUMBER_0, Constants.NUMBER_0, Constants.NUMBER_0, Constants.NUMBER_0),
1483      new PreviewAttribute(this.printerRange!, Constants.NUMBER_1), options);
1484
1485      startPrintJob(this.printJob).then((result) => {
1486        if (result) {
1487          this.startJobAbility();
1488        } else { // 任务下发失败
1489          this.showToast($r('app.string.error_task_send_msg'));
1490        }
1491      });
1492    });
1493  }
1494
1495  startJobAbility(){
1496    let jobAbilityWant: Want = {
1497      bundleName: Constants.BUNDLE_NAME,
1498      abilityName: Constants.JOB_MANAGER_ABILITY_NAME,
1499      parameters: {
1500        jobId: this.jobId
1501      },
1502    }
1503
1504    this.abilityContext?.startAbility(jobAbilityWant).then(() => {
1505      Log.info(TAG,'startJobManagerAbility')
1506      this.canPrint = false;
1507      this.session?.terminateSelf().then(() => {
1508        console.info('===>terminateSelfCallBack===>: ');
1509      });
1510    }).catch((err: BusinessError) => {
1511      Log.error(TAG, 'fail to startAbility, err =' + JSON.stringify(err));
1512    })
1513  }
1514
1515  removeSpaces(name: string | undefined) {
1516    if (CheckEmptyUtils.checkStrIsEmpty(name)) {
1517      return "";
1518    }
1519    let regex: RegExp = new RegExp('\\s+', 'g');
1520    return name!.replace(regex, '_');
1521  }
1522
1523  getMediaType(selectType: number): string {
1524    if (MediaTypes.sCodeToStringMap.has(selectType)) {
1525      return MediaTypes.sCodeToStringMap.get(selectType)!;
1526    }
1527    return MediaTypes.sCodeToStringMap.get(MediaTypeCode.MEDIA_PLAIN)!;
1528  }
1529
1530  getPrinterUri(): string {
1531    if (CheckEmptyUtils.isEmpty(this.printer)) {
1532      return '';
1533    }
1534    let options = this.printer!.options;
1535    let optionObject: PrinterCapsOptions = JSON.parse(options!);
1536    if (CheckEmptyUtils.checkStrIsEmpty(optionObject.printerUri)) {
1537      return '';
1538    }
1539    return optionObject.printerUri;
1540  }
1541
1542  connectionFailed() {
1543    if (CheckEmptyUtils.isEmpty(this.printer)) {
1544      Log.error(TAG, 'connectionFailed, invalid printer!');
1545      return;
1546    }
1547    clearInterval(this.ConnectTimer)
1548    this.alarmText = StringUtil.getString('alarm_dialog_connect_failed')
1549    this.alarmDialogCtl.open()
1550    this.printer!.printerId = Constants.STRING_NEGATIVE_ONE
1551    this.connectingPrinterId = Constants.DEFAULT_CONNECTING_PRINTER_ID
1552    Log.info(TAG, 'connectCountDown setPrinterId:' + this.printer!.printerId)
1553    this.setSelectDefault(true)
1554  }
1555
1556  getJobName(fileCount: number): string {
1557    Log.info(TAG, 'getJobName: COUNT' + fileCount)
1558    let jobName: string = this.firstFileName
1559    if (fileCount > 1) {
1560      let nameExt = StringUtil.getString('print_job_name_plurals',fileCount)
1561      jobName = jobName + nameExt
1562    }
1563    Log.debug(TAG,'jobName: ',jobName)
1564    return jobName
1565  }
1566
1567  getJobDescription() {
1568
1569    let color = Constants.STRING_NONE
1570    switch (this.colorMode) {
1571      case ColorCode.COLOR:
1572        color = StringUtil.getString('ColorMode_COLOR') + StringUtil.getString('pauseMark')
1573        break;
1574      case ColorCode.MONOCHROME:
1575        color = StringUtil.getString('ColorMode_MONOCHROME') + StringUtil.getString('pauseMark')
1576        break;
1577    }
1578    let mediaType = Constants.STRING_NONE
1579    switch (SelectionModel.getSelectionValue<number>(this.currentMediaType.name)) {
1580      case MediaType.NORMAL:
1581        mediaType = StringUtil.getString('MediaType_NORMAL') + StringUtil.getString('pauseMark')
1582        break;
1583      case MediaType.PHOTO:
1584        mediaType = StringUtil.getString('MediaType_PHOTO') + StringUtil.getString('pauseMark')
1585        break;
1586    }
1587    let borderless = Constants.STRING_NONE
1588    if (this.isBorderless) {
1589      borderless = StringUtil.getString('pauseMark') + StringUtil.getString('JobDes_BorderLess')
1590    }
1591    let quality = Constants.STRING_NONE
1592    switch (SelectionModel.getSelectionValue<number>(this.currentQuality.name)) {
1593      case PrintQuality.ECONOMY:
1594        quality = StringUtil.getString('PrintQuality_ECONOMY') + StringUtil.getString('pauseMark')
1595        break;
1596      case PrintQuality.STANDARD:
1597        quality = StringUtil.getString('PrintQuality_STANDARD') + StringUtil.getString('pauseMark')
1598        break;
1599      case PrintQuality.BEST:
1600        quality = StringUtil.getString('PrintQuality_BEST') + StringUtil.getString('pauseMark')
1601        break;
1602    }
1603    let direction = Constants.STRING_NONE
1604    switch (SelectionModel.getSelectionValue<number>(this.currentDirection.name)) {
1605      case PageDirection.AUTO:
1606        direction = StringUtil.getString('PageDirection_AUTO') + StringUtil.getString('pauseMark')
1607        break;
1608      case PageDirection.LANDSCAPE:
1609        direction = StringUtil.getString('PageDirection_LANDSCAPE') + StringUtil.getString('pauseMark')
1610        break;
1611      case PageDirection.VERTICAL:
1612        direction = StringUtil.getString('PageDirection_VERTICAL') + StringUtil.getString('pauseMark')
1613        break;
1614    }
1615    let duplex = Constants.STRING_NONE
1616
1617    let size = this.currentMediaSize.res
1618    let sizeStr =size.toString().split(' ')[0]
1619    this.jobDes = `${color}${quality}${direction}${mediaType}${sizeStr}${borderless}`
1620  }
1621
1622  checkCustomRange(value:string){
1623    this.cusRangeArr = []
1624    this.isCusRangeError = false
1625    this.isCusRangeMax = false
1626    this.cusRangeBorderColor = $r('app.color.border_line')
1627
1628    if (value === Constants.STRING_NONE) {
1629      return
1630    }
1631
1632    let prePageArray = new Array<string>();
1633    let pageArray = new Array<string>();
1634    prePageArray = value.split(Constants.EU_COMMA)
1635    prePageArray.forEach((prePage:string)=>{
1636      pageArray.push(...prePage.split(Constants.CN_COMMA));
1637    })
1638
1639    for (let index = 0; index < pageArray.length; index++){
1640      let range =pageArray[index].split(Constants.HYPHEN)
1641      if (range.length === Constants.NUMBER_2) {
1642        let startNum =  this.checkNum(range[0])
1643        let endNum =  this.checkNum(range[1])
1644        if (!(startNum && endNum)){
1645          this.cusRangeArr = []
1646          return
1647        }
1648        if (startNum>endNum) {
1649          this.setInvalidRange()
1650          this.cusRangeArr = []
1651          return
1652        }else{
1653          for (let index:number = startNum; index <= endNum; index++) {
1654            this.cusRangeArr.push(index);
1655          }
1656        }
1657        continue;
1658      }
1659
1660      let num = this.checkNum(pageArray[index])
1661
1662      if (num){
1663        this.cusRangeArr.push(num);
1664      }else{
1665        this.cusRangeArr = []
1666        return
1667      }
1668
1669    }
1670    const set = new Set(this.cusRangeArr)
1671    this.cusRangeArr =  Array.from(set)
1672    let length = value.length
1673    if (length >= Constants.MAX_CUSTOM_PRINT_RANGE_LENGTH) {
1674      this.errorMessage = $r('app.string.cus_range_error_words_limit')
1675      this.cusRangeBorderColor = $r('app.color.border_line_error')
1676      this.isCusRangeMax = true
1677      return
1678    }
1679    Log.info(TAG,'checkCustomRange this.cusRangeArr = ',JSON.stringify(this.cusRangeArr))
1680  }
1681
1682  checkNum(numStr:string):number | undefined{
1683    if (numStr.includes('.')||numStr.startsWith('0')){
1684      this.setInvalidRange()
1685      return
1686    }
1687    let num = Number(numStr)
1688    if (Number.isNaN(num)||num < 1){
1689      this.setInvalidRange()
1690      return undefined
1691    }else if (num > this.totalPage) {
1692      this.errorMessage = $r('app.string.cus_range_error_max_image_count',this.totalPage.toString())
1693      this.cusRangeBorderColor = $r('app.color.border_line_error')
1694      this.isCusRangeError = true
1695      return undefined
1696    }
1697    return num
1698  }
1699
1700  setInvalidRange(){
1701    this.errorMessage = $r('app.string.cus_range_error_invalid_range')
1702    this.cusRangeBorderColor = $r('app.color.border_line_error')
1703    this.isCusRangeError = true
1704  }
1705
1706  needDuplexChange(){
1707    Log.info(TAG,'needDuplexChange ')
1708    if(!this.needDuplex && !(this.currentDuplex === SelectionModel.DuplexMode_SINGLE)){
1709      this.currentDuplex = SelectionModel.DuplexMode_SINGLE
1710    }
1711  }
1712
1713  setStartPageStr(){
1714    this.startPageStr = ''
1715    this.startPageStr = this.startPage.toString();
1716  }
1717  setEndPageStr(){
1718    this.endPageStr = ''
1719    this.endPageStr = this.endPage.toString();
1720  }
1721  /**
1722   * 检查传入图片数量,大于100时不与加载
1723   *
1724   */
1725  checkMaxPages(fileList: Array<string>):  Array<string>{
1726    let returnList:  Array<string>;
1727    if (fileList.length > Constants.MAX_PAGES) {
1728      returnList = fileList.slice(0,Constants.MAX_PAGES);
1729      setTimeout(() => {//延迟弹窗,否则会概率弹窗失败
1730        this.showToast($r('app.string.toast_max_copies'));
1731      }, Constants.SHOW_TOAST_TIMEOUT);
1732    } else {
1733      returnList = fileList
1734    }
1735    return returnList
1736  }
1737
1738  checkCustomRangeTextInput(isChangeRangeType: boolean){
1739    if (!isChangeRangeType && this.printRangeType === PrintRangeType.ALL){
1740      return;
1741    }
1742    if (isChangeRangeType) {
1743      this.editCusRangeFlag = false
1744      this.cusRangeText = ''
1745      this.cusRangeArr = []
1746      this.isCusRangeError = false
1747      this.isCusRangeMax = false
1748      this.cusRangeBorderColor = $r('app.color.border_line')
1749    } else {
1750      if (CheckEmptyUtils.isEmpty(this.cusRangeText)) {
1751        if (this.totalPage > Constants.NUMBER_1) {
1752          if (this.isAbovePageLimit) {
1753            this.cusRangeText = Constants.NUMBER_1+Constants.HYPHEN+Constants.MAX_PAGES.toString()
1754          }else{
1755            this.cusRangeText = Constants.NUMBER_1+Constants.HYPHEN+this.totalPage.toString()
1756          }
1757        }else{
1758          this.cusRangeText = Constants.STRING_ONE
1759        }
1760      }
1761    }
1762
1763    if (this.cusRangeArr.length === 0 ) {
1764      this.printRangeType = PrintRangeType.ALL;
1765      this.updatePrintRange()
1766    }
1767  }
1768
1769  checkPrintRange(): Array<number>{
1770    let returnList = new Array<number>();
1771    if (this.printRange.length>100) {
1772      returnList = PrintUtil.getDefaultArray(100);
1773    }else{
1774      returnList = CopyUtil.deepClone(this.printRange);
1775    }
1776    if (this.printerRange === undefined) {//下发打印参数需要
1777      this.printerRange = {
1778        startPage: this.startPage,
1779        endPage: this.endPage,
1780        pages: returnList.slice()
1781      };
1782    }else{
1783      this.printerRange.startPage = this.startPage;
1784      this.printerRange.endPage = this.endPage;
1785      this.printerRange.pages = returnList.slice();
1786    }
1787    return returnList;
1788  }
1789}
1790
1791