1/* 2 * Copyright (c) 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 { BusinessError } from '@ohos.base'; 17import { staffItem } from './staff'; 18import Constants from '../constant'; 19import { AccountTipsConfig } from '../AccountTipsConfig'; 20import { HiLog } from '../HiLog'; 21 22interface Staff { 23 authAccount: string; 24 textContent: string; 25} 26 27const TAG = 'AddStaff'; 28 29@Extend(Text) 30function inputMessageText() { 31 .fontSize($r('sys.float.ohos_id_text_size_body3')) 32 .lineHeight(Constants.PP_TEXT_LINE_HEIGHT2) 33 .fontColor($r('sys.color.ohos_id_color_handup')) 34 .fontWeight(FontWeight.Medium) 35 .margin({ top: Constants.ENCRYPTION_ADD_STAFF_BORDER_MARGIN_TOP }) 36 .textAlign(TextAlign.Start) 37} 38 39@Component 40struct AddStaff { 41 @State succ: number = 0; 42 @State fail: number = 0; 43 @Link isAccountCheckSuccess: boolean; 44 @State staffArrayLength: boolean = false; 45 @State @Watch('onErrorStyleChange') isInputInvalid: boolean = false; 46 @State isNetworkInvalid: boolean = false; 47 @State textContent: string = ''; 48 @Link @Watch('onDataChange') staffArray: Staff[]; 49 @State focusFlag: boolean = false; 50 @Prop isDisable: boolean = false; 51 @State isInitDataStatus: boolean = false; 52 @State errInput: string[] = []; 53 @State inputArray: string[] = []; 54 @State isInputInvalidFlag: boolean = false; 55 private controller: RichEditorController = new RichEditorController(); 56 private options: RichEditorOptions = { controller: this.controller }; 57 58 @Builder 59 StaffItemBuilder(authAccount: string, textContent: string, index: number) { 60 Column() { 61 staffItem({ 62 authAccount: authAccount, 63 textContent: textContent, 64 isActive: true, 65 changeIndex: Number(index) 66 }); 67 } 68 .alignItems(HorizontalAlign.Start); 69 } 70 71 removeItem(i: number) { 72 this.staffArray.splice(i, 1) 73 this.staffArrayLength = false; 74 } 75 76 private async onSubmitMock(inputId: string, startOffset: number[], endOffset: number[]) { 77 if (!inputId) { 78 return; 79 } 80 if (this.staffArray.length >= Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX) { 81 this.staffArrayLength = true; 82 this.deleteBuildSpan(startOffset, endOffset); 83 return; 84 } 85 this.isAccountCheckSuccess = false; 86 let regex: RegExp = new RegExp('(\r|\n)*', 'g'); 87 let inputString = inputId.replace(regex, ''); 88 this.inputArray = inputString.split(';'); 89 this.errInput = []; 90 if (this.inputArray.length > Constants.RICH_EDITOR_FIRST) { 91 this.deleteBuildSpan(startOffset, endOffset); 92 } 93 for (let i = 0; i < this.inputArray.length; i++) { 94 if (!this.inputArray[i]) { 95 continue; 96 } 97 if (this.staffArray.length >= Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX) { 98 this.errInput = []; 99 break; 100 } 101 await this.createStaffByDomain(i, startOffset, endOffset); 102 } 103 this.isAccountCheckSuccess = true; 104 if (this.staffArray.length < Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX) { 105 this.controller.addTextSpan(this.errInput.join(';')); 106 if (this.errInput.length && this.isInputInvalidFlag) { 107 this.isInputInvalid = true; 108 } 109 } 110 } 111 112 private createStaffByDomain(i: number, startOffset: number[], endOffset: number[]) { 113 return new Promise<void>(async (resolve, reject) => { 114 try { 115 let result = await AccountTipsConfig.getAccountInfo(this.inputArray[i]); 116 let o1: Staff = { 117 authAccount: result.accountName, 118 textContent: result[this.textContent] as string 119 }; 120 this.staffArray.push(o1); 121 if (this.inputArray.length === Constants.RICH_EDITOR_FIRST) { 122 this.deleteBuildSpan(startOffset, endOffset); 123 } 124 this.succ = AppStorage.get('hiAccountVerifySucc') as number + 1; 125 AppStorage.setOrCreate('hiAccountVerifySucc', this.succ); 126 this.addBuildSpan(i, result[this.textContent]); 127 } catch (error) { 128 HiLog.info(TAG, `getAccountInfo fail: ${JSON.stringify(error)}`); 129 this.showErrInput(i, error, startOffset, endOffset); 130 } 131 resolve(); 132 }); 133 } 134 135 private deleteBuildSpan(startOffset: number[], endOffset: number[]) { 136 for (let i: number = startOffset.length - 1; i >= 0; i--) { 137 this.controller.deleteSpans({ start: startOffset[i], end: endOffset[i] }); 138 } 139 } 140 141 private addBuildSpan(i: number, textContent: string) { 142 let index: number = this.controller.getCaretOffset(); 143 let staffBuilder: CustomBuilder = () => { 144 this.StaffItemBuilder(this.inputArray[i], textContent, index); 145 }; 146 this.controller.addBuilderSpan(staffBuilder); 147 } 148 149 private showErrInput(i: number, error: BusinessError, startOffset: number[], endOffset: number[]) { 150 if (this.inputArray.length === Constants.RICH_EDITOR_FIRST) { 151 this.deleteBuildSpan(startOffset, endOffset); 152 } 153 this.errInput.push(this.inputArray[i]); 154 this.fail = AppStorage.get('hiAccountVerifyFail') as number + 1; 155 AppStorage.setOrCreate('hiAccountVerifyFail', this.fail); 156 if ([ 157 Constants.ERR_JS_INVALID_PARAMETER, 158 Constants.ERR_JS_ACCOUNT_NOT_FOUND 159 ].includes(error.code)) { 160 this.isInputInvalidFlag = true; 161 } else { 162 this.isNetworkInvalid = true; 163 } 164 } 165 166 private onDataChange() { 167 !this.isInitDataStatus && this.staffArray && this.staffArray.forEach((item: Staff, index: number) => { 168 let staffItemBuilder: CustomBuilder = () => { 169 this.StaffItemBuilder(item.authAccount, item.textContent, index); 170 }; 171 this.controller.addBuilderSpan(staffItemBuilder); 172 }); 173 } 174 175 private onErrorStyleChange() { 176 this.controller.updateSpanStyle({ 177 textStyle: { 178 fontSize: $r('sys.float.ohos_id_text_size_body1'), 179 fontColor: this.isInputInvalid ? 180 $r('sys.color.ohos_id_color_handup') : $r('sys.color.ohos_id_color_text_primary') 181 } 182 }); 183 } 184 185 async aboutToAppear() { 186 await AccountTipsConfig.getConfigTips(); 187 this.textContent = AccountTipsConfig.showContentKey; 188 if (this.staffArray.length) { 189 setTimeout(() => { 190 this.onDataChange(); 191 }, Constants.ENCRYPTION_SET_TIMEOUT_TIME); 192 } 193 } 194 195 build() { 196 Column() { 197 Flex({ 198 direction: FlexDirection.Row, 199 wrap: FlexWrap.Wrap, 200 }) { 201 RichEditor(this.options) 202 .placeholder(!this.staffArray.length ? ($r('app.string.enter_a_complete_work_ID')) : '', 203 { 204 font: { size: $r('sys.float.ohos_id_text_size_body1') }, 205 fontColor: $r('sys.color.ohos_id_color_text_hint') 206 }) 207 .flexGrow(Constants.ENCRYPTION_ADD_STAFF_FLEX_GROW) 208 .backgroundColor($r('sys.color.ohos_id_color_dialog_bg')) 209 .borderRadius(Constants.PP_ROW_RADIUS) 210 .align(Alignment.Center) 211 .padding({ 212 top: Constants.PP_BUTTON_PAD, 213 bottom: Constants.PP_BUTTON_PAD, 214 left: Constants.PP_BUTTON_PAD, 215 right: Constants.PP_BUTTON_PAD 216 }) 217 .width(Constants.FOOTER_ROW_WIDTH) 218 .constraintSize({ 219 minHeight: Constants.RICH_EDITOR_MIN_HEIGHT 220 }) 221 .aboutToIMEInput((value: RichEditorInsertValue) => { 222 this.isInitDataStatus = true; 223 if (this.isInputInvalid || this.isNetworkInvalid) { 224 this.isInputInvalid = false; 225 this.isNetworkInvalid = false; 226 } 227 if (value.insertValue === Constants.ENTER_KEY_VALUE) { 228 let richEditorSpans: (RichEditorTextSpanResult | RichEditorImageSpanResult)[] = 229 this.controller.getSpans(); 230 let inputId: string = ''; 231 let startOffset: number[] = []; 232 let endOffset: number[] = []; 233 for (let index: number = 0; index < richEditorSpans.length; index++) { 234 let buildSpan: RichEditorTextSpanResult = richEditorSpans[index] as RichEditorTextSpanResult; 235 if (buildSpan.textStyle) { 236 inputId += buildSpan.value; 237 startOffset.push(buildSpan.spanPosition.spanRange[0]); 238 endOffset.push(buildSpan.spanPosition.spanRange[1]); 239 } 240 } 241 if (this.isAccountCheckSuccess) { 242 this.onSubmitMock(inputId, startOffset, endOffset); 243 }; 244 return false; 245 } 246 return true; 247 }) 248 .aboutToDelete((value: RichEditorDeleteValue) => { 249 if (!value.richEditorDeleteSpans.length) { 250 return false; 251 }; 252 this.isInitDataStatus = true; 253 if (this.isInputInvalid || this.isNetworkInvalid) { 254 this.isInputInvalid = false; 255 this.isNetworkInvalid = false; 256 } 257 258 let richEditorSpansAll: (RichEditorTextSpanResult | RichEditorImageSpanResult)[] = 259 this.controller.getSpans(); 260 261 let richEditorDeleteSpans: (RichEditorTextSpanResult | RichEditorImageSpanResult)[] = 262 value.richEditorDeleteSpans; 263 let len = richEditorDeleteSpans[richEditorDeleteSpans.length - 1].spanPosition.spanIndex; 264 let textNum: number = 0; 265 for (let i = 0; i <= len; i++) { 266 let buildSpan: RichEditorTextSpanResult = richEditorSpansAll[i] as RichEditorTextSpanResult; 267 if (buildSpan?.textStyle) { 268 textNum++; 269 } 270 } 271 for (let index: number = richEditorDeleteSpans.length - 1; index >= 0; index--) { 272 let buildSpan: RichEditorImageSpanResult = richEditorDeleteSpans[index] as RichEditorImageSpanResult; 273 if (buildSpan.imageStyle) { 274 let spanIndex: number = buildSpan.spanPosition.spanIndex; 275 spanIndex -= textNum; 276 this.removeItem(spanIndex); 277 } else { 278 textNum--; 279 } 280 } 281 return true; 282 }) 283 } 284 .onFocus(() => { 285 this.focusFlag = !this.focusFlag; 286 }) 287 .onBlur(() => { 288 this.focusFlag = !this.focusFlag; 289 }) 290 291 Divider() 292 .strokeWidth(this.focusFlag ? 293 px2vp(Constants.ENCRYPTION_ADD_STAFF_BORDER2) : px2vp(Constants.ENCRYPTION_ADD_STAFF_BORDER)) 294 .color((this.isInputInvalid || this.staffArrayLength || this.isNetworkInvalid) 295 ? $r('sys.color.ohos_id_color_handup') : 296 this.focusFlag ? $r('sys.color.ohos_id_color_primary') : $r('sys.color.ohos_id_color_list_separator')) 297 .opacity(this.focusFlag ? Constants.FOOTER_OPACITY_SEPC : Constants.FOOTER_OPACITY_ONE); 298 299 Flex({ direction: FlexDirection.Row }) { 300 if (this.isInputInvalid && !this.isNetworkInvalid) { 301 Text($r('app.string.incorrect_work_ID')) 302 .inputMessageText() 303 } 304 if (this.isNetworkInvalid) { 305 Text($r('app.string.network_invalid')) 306 .inputMessageText() 307 } 308 Blank() 309 if (this.staffArray.length >= 310 Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX * Constants.ENCRYPTION_ADD_STAFF_LENGTH) { 311 Text(`${this.staffArray.length}/${Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX}`) 312 .fontSize($r('sys.float.ohos_id_text_size_body3')) 313 .lineHeight(Constants.PP_TEXT_LINE_HEIGHT2) 314 .fontColor(this.staffArrayLength 315 ? $r('sys.color.ohos_id_color_handup') : $r('sys.color.ohos_id_color_text_secondary')) 316 .fontWeight(FontWeight.Medium) 317 .margin({ top: Constants.ENCRYPTION_ADD_STAFF_BORDER_MARGIN_TOP }) 318 .textAlign(TextAlign.End) 319 } 320 } 321 } 322 .opacity(this.isDisable ? Constants.DU_LINE_WIDTH : Constants.FOOTER_OPACITY_ONE) 323 .enabled(this.isDisable ? false : true) 324 } 325} 326 327export { AddStaff }; 328