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