• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 '../../common/constant';
19import { AccountTipsConfig } from '../AccountTipsConfig';
20import { HiLog } from '../../common/HiLog';
21import CommonUtil from '../../common/CommonUtil';
22import AccountManager from '../../manager/AccountManager';
23import DomainAccountResponse from '../../bean/response/DomainAccountResponse';
24import AppStorageConstant from '../../common/AppStorageConstant';
25import { common } from '@kit.AbilityKit';
26import DomainAccountInfo from '../../bean/data/DomainAccountInfo';
27import EncryptProtectionShowCodeEnum from '../../common/enum/EncryptProtectionShowCodeEnum';
28import EncryptProtectionHelper from '../helper/EncryptProtectionHelper';
29
30interface Staff {
31  authAccount: string;
32  textContent: string;
33}
34
35const TAG = 'AddStaff';
36
37@Extend(Text)
38function inputMessageText() {
39  .fontSize($r('sys.float.ohos_id_text_size_body3'))
40  .lineHeight(Constants.PP_TEXT_LINE_HEIGHT2)
41  .fontColor($r('sys.color.ohos_id_color_handup'))
42  .fontWeight(FontWeight.Medium)
43  .margin({ top: Constants.ENCRYPTION_ADD_STAFF_BORDER_MARGIN_TOP })
44  .textAlign(TextAlign.Start)
45}
46
47@Component
48struct AddStaff {
49  @State succ: number = 0;
50  @State fail: number = 0;
51  @Link isAccountCheckSuccess: boolean;
52  @State staffArrayLength: boolean = false;
53  @State textContent: string = '';
54  @Link @Watch('onDataChange') staffArray: Staff[];
55  @State focusFlag: boolean = false;
56  @Prop isDisable: boolean = false;
57  @State isInitDataStatus: boolean = false;
58  @State errInput: string[] = [];
59  @State inputArray: string[] = [];
60  private controller: RichEditorController = new RichEditorController();
61  private options: RichEditorOptions = { controller: this.controller };
62
63  private shardingCount: number = 0;
64  @State @Watch('onErrorStyleChange') showFlag: boolean = false;
65  @State showCode: number = EncryptProtectionShowCodeEnum.INIT_SUCCESS;
66
67  @Builder
68  StaffItemBuilder(authAccount: string, textContent: string, index: number) {
69    Column() {
70      staffItem({
71        authAccount: authAccount,
72        textContent: textContent,
73        isActive: true,
74        changeIndex: Number(index)
75      });
76    }
77    .alignItems(HorizontalAlign.Start);
78  }
79
80  removeItem(i: number) {
81    this.staffArray.splice(i, 1)
82    this.staffArrayLength = false;
83  }
84
85  private async onSubmitMock(inputId: string, startOffset: number[], endOffset: number[]) {
86    if (!inputId) {
87      return;
88    }
89    if (this.staffArray.length >= Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX) {
90      this.staffArrayLength = true;
91      this.deleteBuildSpan(startOffset, endOffset);
92      return;
93    }
94    this.isAccountCheckSuccess = false;
95    let regex: RegExp = new RegExp('(\r|\n)*', 'g');
96    let inputString = inputId.replace(regex, '');
97    this.inputArray = inputString.split(';');
98    this.errInput = [];
99    if (this.inputArray.length > Constants.RICH_EDITOR_FIRST) {
100      this.deleteBuildSpan(startOffset, endOffset);
101    }
102
103    await this.dealAccount(startOffset, endOffset);
104
105    this.isAccountCheckSuccess = true;
106    if (this.staffArray.length < Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX) {
107      this.controller.addTextSpan(this.errInput.join(';'));
108      if (this.showCode !== EncryptProtectionShowCodeEnum.INIT_SUCCESS) {
109        this.showFlag = true;
110      }
111    }
112  }
113
114  private async dealAccount(startOffset: number[], endOffset: number[]) {
115    HiLog.info(TAG, 'dealAccount start');
116    this.inputArray.filter(item =>{
117      return !CommonUtil.isEmptyStr(item);
118    });
119    this.shardingCount = this.inputArray.length / Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX;
120    let startLine: number = 0;
121    for (let i = 0; i < this.shardingCount; i++) {
122      if (this.staffArray.length >= Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX) {
123        this.errInput = [];
124        break;
125      }
126      let searchArray: string[] = this.inputArray.slice(startLine, (i + 1) * Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX);
127      let accountResponse: DomainAccountResponse | undefined =
128        await AccountManager.getDomainAccountByAccountNames(searchArray);
129      this.dealAccountResponse(searchArray, accountResponse, startOffset, endOffset);
130
131      startLine = (i + 1) * Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX;
132    }
133    HiLog.info(TAG, 'dealAccount end');
134  }
135
136  private dealAccountResponse(searchArray: string[], accountResponse: DomainAccountResponse | undefined,
137    startOffset: number[], endOffset: number[]) {
138    let businessCode = this.getBusinessCode(accountResponse);
139    if (businessCode !== Constants.INTERFACE_SUCCESS) {
140      this.batchDealError(searchArray, startOffset, endOffset);
141      this.showCode = EncryptProtectionHelper.convertErrorCodeToShowCode(businessCode);
142      return;
143    }
144    let dataArray: Array<DomainAccountInfo> | undefined = accountResponse?.getData();
145    searchArray.forEach(accountName =>{
146      let matchAccount = dataArray?.find(
147        data => data.accountName.toLocaleUpperCase() === accountName.toLocaleUpperCase());
148      if (matchAccount) {
149        this.addStaff(matchAccount);
150        if (this.inputArray.length === Constants.RICH_EDITOR_FIRST) {
151          this.deleteBuildSpan(startOffset, endOffset);
152        }
153        this.succ = CommonUtil.increaseByAppStorageKey(AppStorageConstant.ACCOUNT_VERIFY_SUCCESS_COUNT, 1);
154        this.addBuildSpan(accountName, matchAccount[this.textContent]);
155      } else {
156        // case: not found
157        this.showErrInput(accountName, startOffset, endOffset);
158        this.showCode = EncryptProtectionShowCodeEnum.INPUT_ERROR;
159      }
160    })
161  }
162
163  private getBusinessCode(accountResponse: DomainAccountResponse | undefined): number {
164    if (accountResponse === undefined || accountResponse.getErrorCode() === Constants.ERR_CODE_NETWORK_ERROR) {
165      // case: ipc error
166      return Constants.ERR_JS_NETWORK_INVALID;
167    }
168    if (accountResponse.getErrorCode() !== Constants.INTERFACE_SUCCESS) {
169      // case: ipc success, but return error code
170      return accountResponse.getErrorCode();
171    }
172    if (CommonUtil.isEmptyArray(accountResponse.getData())) {
173      // case: ipc success, but no data
174      return Constants.ERR_JS_ACCOUNT_NOT_FOUND;
175    }
176    return Constants.INTERFACE_SUCCESS;
177  }
178
179  private addStaff(matchAccount: DomainAccountInfo): void {
180    let staff: Staff = {
181      authAccount: matchAccount.accountName.toLocaleLowerCase(),
182      textContent: matchAccount[this.textContent] as string
183    };
184    if (this.staffArray.length >= Constants.TIPS_STAFF_MAX_WIDTH) {
185      return;
186    }
187    this.staffArray.push(staff);
188  }
189
190  private batchDealError(accountNameArray: string[], startOffset: number[], endOffset: number[]) {
191    accountNameArray.forEach(accountName =>{
192      this.showErrInput(accountName, startOffset, endOffset);
193    })
194  }
195
196  private deleteBuildSpan(startOffset: number[], endOffset: number[]) {
197    for (let i: number = startOffset.length - 1; i >= 0; i--) {
198      this.controller.deleteSpans({ start: startOffset[i], end: endOffset[i] });
199    }
200  }
201
202  private addBuildSpan(staffName: string, textContent: string) {
203    let index: number = this.controller.getCaretOffset();
204    let staffBuilder: CustomBuilder = () => {
205      this.StaffItemBuilder(staffName, textContent, index);
206    };
207    this.controller.addBuilderSpan(staffBuilder);
208  }
209
210  private showErrInput(staffName: string, startOffset: number[], endOffset: number[]) {
211    if (this.inputArray.length === Constants.RICH_EDITOR_FIRST) {
212      this.deleteBuildSpan(startOffset, endOffset);
213    }
214    this.errInput.push(staffName);
215    this.fail = CommonUtil.increaseByAppStorageKey(AppStorageConstant.ACCOUNT_VERIFY_FAIL_COUNT, 1);
216  }
217
218  private onDataChange() {
219    !this.isInitDataStatus && this.staffArray && this.staffArray.forEach((item: Staff, index: number) => {
220      let staffItemBuilder: CustomBuilder = () => {
221        this.StaffItemBuilder(item.authAccount, item.textContent, index);
222      };
223      this.controller.addBuilderSpan(staffItemBuilder);
224    });
225  }
226
227  private onErrorStyleChange() {
228    this.controller.updateSpanStyle({
229      textStyle: {
230        fontSize: $r('sys.float.ohos_id_text_size_body1'),
231        fontColor: this.showFlag ?
232        $r('sys.color.ohos_id_color_handup') : $r('sys.color.ohos_id_color_text_primary')
233      }
234    });
235  }
236
237  private initShowCode() {
238    this.isInitDataStatus = true;
239    this.showCode = EncryptProtectionShowCodeEnum.INIT_SUCCESS;
240    this.showFlag = false;
241  }
242
243  private dealError(inputId: string, startOffset: number[], endOffset: number[]) {
244    this.errInput = [];
245    this.deleteBuildSpan(startOffset, endOffset);
246    this.showErrInput(inputId, startOffset, endOffset);
247    this.controller.addTextSpan(this.errInput.join(';'));
248    this.showCode = EncryptProtectionShowCodeEnum.DEFAULT_ERROR;
249    this.showFlag = true;
250  }
251
252  async aboutToAppear() {
253    AccountManager.connectAbility(getContext(this) as common.UIAbilityContext);
254    await AccountTipsConfig.getConfigTips();
255    this.textContent = AccountTipsConfig.showContentKey;
256    if (this.staffArray.length) {
257      setTimeout(() => {
258        this.onDataChange();
259      }, Constants.ENCRYPTION_SET_TIMEOUT_TIME);
260    }
261  }
262
263  build() {
264    Column() {
265      Flex({
266        direction: FlexDirection.Row,
267        wrap: FlexWrap.Wrap,
268      }) {
269        RichEditor(this.options)
270          .onReady(() => {
271            this.controller.setTypingStyle({
272              fontSize: $r('sys.float.ohos_id_text_size_body1')
273            })
274          })
275          .placeholder(!this.staffArray.length ? ($r('app.string.enter_a_complete_work_ID')) : '',
276            {
277              font: { size: $r('sys.float.ohos_id_text_size_body1') },
278              fontColor: $r('sys.color.ohos_id_color_text_hint')
279            })
280          .flexGrow(Constants.ENCRYPTION_ADD_STAFF_FLEX_GROW)
281          .backgroundColor($r('sys.color.ohos_id_color_dialog_bg'))
282          .borderRadius(Constants.PP_ROW_RADIUS)
283          .align(Alignment.Center)
284          .padding({
285            top: Constants.PP_BUTTON_PAD,
286            bottom: Constants.PP_BUTTON_PAD,
287            left: Constants.PP_BUTTON_PAD,
288            right: Constants.PP_BUTTON_PAD
289          })
290          .width(Constants.FOOTER_ROW_WIDTH)
291          .constraintSize({
292            minHeight: Constants.RICH_EDITOR_MIN_HEIGHT
293          })
294          .aboutToIMEInput((value: RichEditorInsertValue) => {
295            this.isInitDataStatus = true;
296            this.initShowCode();
297            if (value.insertValue === Constants.ENTER_KEY_VALUE) {
298              let richEditorSpans: (RichEditorTextSpanResult | RichEditorImageSpanResult)[] =
299              this.controller.getSpans();
300              let inputId: string = '';
301              let startOffset: number[] = [];
302              let endOffset: number[] = [];
303              for (let index: number = 0; index < richEditorSpans.length; index++) {
304                let buildSpan: RichEditorTextSpanResult = richEditorSpans[index] as RichEditorTextSpanResult;
305                if (buildSpan.textStyle) {
306                  inputId += buildSpan.value;
307                  startOffset.push(buildSpan.spanPosition.spanRange[0]);
308                  endOffset.push(buildSpan.spanPosition.spanRange[1]);
309                  if (inputId.length > EncryptProtectionHelper.INPUT_MAX_LENGTH) {
310                    this.dealError(inputId, startOffset, endOffset);
311                    return true;
312                  }
313                }
314              }
315              if (this.isAccountCheckSuccess) {
316                this.onSubmitMock(inputId, startOffset, endOffset);
317              }
318              return false;
319            }
320            return true;
321          })
322          .aboutToDelete((value: RichEditorDeleteValue) => {
323            if (!value.richEditorDeleteSpans.length) {
324              return false;
325            };
326            this.initShowCode();
327            let richEditorSpansAll: (RichEditorTextSpanResult | RichEditorImageSpanResult)[] =
328              this.controller.getSpans();
329            let richEditorDeleteSpans: (RichEditorTextSpanResult | RichEditorImageSpanResult)[] =
330            value.richEditorDeleteSpans;
331            let len = richEditorDeleteSpans[richEditorDeleteSpans.length - 1].spanPosition.spanIndex;
332            let textNum: number = 0;
333            for (let i = 0; i <= len; i++) {
334              let buildSpan: RichEditorTextSpanResult = richEditorSpansAll[i] as RichEditorTextSpanResult;
335              if (buildSpan?.textStyle) {
336                textNum++;
337              }
338            }
339            for (let index: number = richEditorDeleteSpans.length - 1; index >= 0; index--) {
340              let buildSpan: RichEditorImageSpanResult = richEditorDeleteSpans[index] as RichEditorImageSpanResult;
341              if (buildSpan.imageStyle) {
342                let spanIndex: number = buildSpan.spanPosition.spanIndex;
343                spanIndex -= textNum;
344                this.removeItem(spanIndex);
345              } else {
346                textNum--;
347              }
348            }
349            return true;
350          })
351      }
352      .onFocus(() => {
353        this.focusFlag = !this.focusFlag;
354      })
355      .onBlur(() => {
356        this.focusFlag = !this.focusFlag;
357      })
358
359      Divider()
360        .strokeWidth(this.focusFlag ?
361        px2vp(Constants.ENCRYPTION_ADD_STAFF_BORDER2) : px2vp(Constants.ENCRYPTION_ADD_STAFF_BORDER))
362        .color((EncryptProtectionHelper.isShowErr(this.showCode, this.staffArrayLength))
363          ? $r('sys.color.ohos_id_color_handup') :
364          this.focusFlag ? $r('sys.color.ohos_id_color_primary') : $r('sys.color.ohos_id_color_list_separator'))
365        .opacity(this.focusFlag ? Constants.FOOTER_OPACITY_SEPC : Constants.FOOTER_OPACITY_ONE);
366
367      Flex({ direction: FlexDirection.Row }) {
368        if (EncryptProtectionHelper.getShowErr(this.showCode)) {
369          Text(EncryptProtectionHelper.getShowErr(this.showCode))
370            .inputMessageText()
371        }
372        Blank()
373        if (this.staffArray.length >=
374          Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX * Constants.ENCRYPTION_ADD_STAFF_LENGTH) {
375          Text(`${this.staffArray.length}/${Constants.ENCRYPTION_ADD_STAFF_LENGTH_MAX}`)
376            .fontSize($r('sys.float.ohos_id_text_size_body3'))
377            .lineHeight(Constants.PP_TEXT_LINE_HEIGHT2)
378            .fontColor(this.staffArrayLength
379              ? $r('sys.color.ohos_id_color_handup') : $r('sys.color.ohos_id_color_text_secondary'))
380            .fontWeight(FontWeight.Medium)
381            .margin({ top: Constants.ENCRYPTION_ADD_STAFF_BORDER_MARGIN_TOP })
382            .textAlign(TextAlign.End)
383        }
384      }
385    }
386    .opacity(this.isDisable ? Constants.DU_LINE_WIDTH : Constants.FOOTER_OPACITY_ONE)
387    .enabled(this.isDisable ? false : true)
388  }
389}
390
391export { AddStaff };
392