hl-core 0.0.10-beta.2 → 0.0.10-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/api/base.api.ts +221 -195
  2. package/components/Complex/TextBlock.vue +2 -0
  3. package/components/Dialog/Dialog.vue +7 -1
  4. package/components/Dialog/FamilyDialog.vue +2 -0
  5. package/components/Form/DigitalDocument.vue +52 -0
  6. package/components/Form/DynamicForm.vue +1 -0
  7. package/components/Form/FormData.vue +1 -0
  8. package/components/Form/ManagerAttachment.vue +2 -4
  9. package/components/Input/DynamicInput.vue +2 -0
  10. package/components/Input/FormInput.vue +2 -0
  11. package/components/Input/OtpInput.vue +25 -0
  12. package/components/Input/PanelInput.vue +1 -0
  13. package/components/Input/RoundedInput.vue +2 -0
  14. package/components/Input/RoundedSelect.vue +4 -0
  15. package/components/Input/SwitchInput.vue +2 -0
  16. package/components/Input/TextInput.vue +2 -0
  17. package/components/Layout/Drawer.vue +2 -0
  18. package/components/Pages/Anketa.vue +165 -166
  19. package/components/Pages/Auth.vue +2 -0
  20. package/components/Pages/ContragentForm.vue +1 -0
  21. package/components/Pages/Documents.vue +237 -6
  22. package/components/Pages/MemberForm.vue +204 -56
  23. package/components/Pages/ProductConditions.vue +153 -74
  24. package/components/Panel/PanelHandler.vue +231 -105
  25. package/components/Transitions/Animation.vue +2 -0
  26. package/components/Utilities/Chip.vue +2 -0
  27. package/components/Utilities/JsonViewer.vue +1 -2
  28. package/composables/classes.ts +102 -41
  29. package/composables/fields.ts +6 -4
  30. package/composables/index.ts +220 -7
  31. package/composables/styles.ts +8 -24
  32. package/configs/pwa.ts +1 -7
  33. package/locales/ru.json +11 -4
  34. package/nuxt.config.ts +10 -13
  35. package/package.json +13 -12
  36. package/plugins/head.ts +1 -1
  37. package/store/data.store.ts +235 -357
  38. package/store/member.store.ts +3 -2
  39. package/tsconfig.json +3 -0
  40. package/types/enum.ts +17 -2
  41. package/types/form.ts +71 -75
  42. package/types/index.ts +889 -877
@@ -17,7 +17,7 @@
17
17
  <base-form-input v-model="formStore.contractDate" :label="$dataStore.t('form.date')" :readonly="true" append-inner-icon="mdi mdi-calendar-blank-outline" />
18
18
  <base-file-input :readonly="isDisabled" @input.prevent="onFileChange($event)" />
19
19
  </base-content-block>
20
- <base-content-block v-for="document of formStore.signedDocumentList" :key="document.id" :class="[$styles.textSimple]">
20
+ <base-content-block v-for="document of documentListFiltered" :key="document.id" :class="[$styles.textSimple]">
21
21
  <h5 class="text-center font-medium mb-4">
22
22
  {{ document.fileTypeName }}
23
23
  </h5>
@@ -31,6 +31,40 @@
31
31
  </div>
32
32
  </base-content-block>
33
33
  </section>
34
+ <section v-if="hasDigitalDocuments">
35
+ <base-digital-document
36
+ v-if="$route.params.taskId !== '0'"
37
+ :member="policyholderForm"
38
+ :title="$dataStore.t('policyholderForm')"
39
+ :disabled="isDigitalDocDisabled"
40
+ @openDigitalDocPanel="openDigitalDocPanel($event, 'Страхователя')"
41
+ @openPanel="openPanel"
42
+ />
43
+ <div v-if="insuredFiltered.length !== 0">
44
+ <base-digital-document
45
+ v-for="(member, index) in insuredFiltered"
46
+ :key="index"
47
+ :member="member"
48
+ :number="index + 1"
49
+ :title="$dataStore.t('insuredForm')"
50
+ :disabled="isDigitalDocDisabled"
51
+ @openDigitalDocPanel="openDigitalDocPanel($event, 'Застрахованного')"
52
+ @openPanel="openPanel"
53
+ />
54
+ </div>
55
+ <div v-if="beneficiaryFiltered.length !== 0">
56
+ <base-digital-document
57
+ v-for="(member, index) in beneficiaryFiltered"
58
+ :key="index"
59
+ :member="member"
60
+ :number="index + 1"
61
+ :title="$dataStore.t('beneficiaryForm')"
62
+ :disabled="isDigitalDocDisabled"
63
+ @openDigitalDocPanel="openDigitalDocPanel($event, 'Выгодоприобретателя')"
64
+ @openPanel="openPanel"
65
+ />
66
+ </div>
67
+ </section>
34
68
  <div v-if="noDocuments" class="h-[calc(90vh-70px)] flex flex-col items-center justify-center gap-6">
35
69
  <svg xmlns="http://www.w3.org/2000/svg" width="125" height="131" viewBox="0 0 125 131" fill="none" class="cursor-help">
36
70
  <path
@@ -97,7 +131,7 @@
97
131
  </div>
98
132
  </base-content-block>
99
133
  </section>
100
- <Teleport v-if="$dataStore.panelAction === null" to="#right-panel-actions">
134
+ <Teleport v-if="isPanelOpen" to="#right-panel-actions">
101
135
  <base-fade-transition>
102
136
  <div :class="[$styles.flexColNav]">
103
137
  <base-btn :disabled="documentLoading" :loading="documentLoading" text="Открыть" @click="getFile('view')" />
@@ -108,6 +142,46 @@
108
142
  </div>
109
143
  </base-fade-transition>
110
144
  </Teleport>
145
+ <Teleport v-if="isDigitalDocOpen" to="#right-panel-actions">
146
+ <div :class="[$styles.flexColNav]">
147
+ <base-form-section class="!mt-0">
148
+ <v-expansion-panels :flat="true">
149
+ <v-expansion-panel class="digital-doc-info !rounded-[8px]">
150
+ <v-expansion-panel-title class="!text-[12px]"> Как получить цифровой документ: </v-expansion-panel-title>
151
+ <v-expansion-panel-text class="text-[12px] text-[#464f60]">
152
+ 1. Выберите тип документа.<br /><br />
153
+ 2. Через приложение eGov mobile и другие приложения: <br />
154
+ • Откройте раздел "Цифровые документы". <br />
155
+ • Выберите нужный документ и откройте доступ. <br />
156
+ • Введите 6-значный код в поле «Код подтверждения». <br />
157
+ • Нажмите "Получить документ".<br /><br />
158
+ 3. Через SMS: <br />
159
+ • Нажмите "Отправить код". <br />
160
+ • Введите полученный SMS-код. <br />
161
+ • Нажмите "Получить документ".<br />
162
+ </v-expansion-panel-text>
163
+ </v-expansion-panel>
164
+ </v-expansion-panels>
165
+ </base-form-section>
166
+ <div class="p-4 d-flex flex-col gap-0.5" :class="[$styles.blueBgLight, $styles.rounded]">
167
+ <base-rounded-select v-model="documentType" class="document-type-select" :items="documentItems" :label="$dataStore.t('form.documentType')" hide-details />
168
+ <div class="digital-document-otp flex flex-col">
169
+ <base-otp-input
170
+ v-model="otpCode"
171
+ @keyup.enter.prevent="otpCode.length === useMask().otpSixDigit.length && getCode()"
172
+ @input="otpCode.length === useMask().otpSixDigit.length && getDigitalDocument()"
173
+ />
174
+ <base-animation>
175
+ <span v-if="!documentLoading" class="text-center cursor-pointer" :class="[$styles.mutedText]" @click="getCode"
176
+ >Не получили код? <span class="underline underline-offset-2">Отправить код заново</span></span
177
+ >
178
+ </base-animation>
179
+ </div>
180
+ </div>
181
+ <base-btn :disabled="documentLoading" :loading="documentLoading" :btn="$styles.greenLightBtn" text="Отправить SMS-код" @click="getCode" />
182
+ <base-btn :disabled="documentLoading" :loading="documentLoading" text="Получить документ" @click="getDigitalDocument" />
183
+ </div>
184
+ </Teleport>
111
185
  <base-dialog
112
186
  v-model="deletionDialog"
113
187
  :title="$dataStore.t('dialog.confirmDelete')"
@@ -122,18 +196,39 @@
122
196
 
123
197
  <script lang="ts">
124
198
  import { DocumentItem } from '../../composables/classes';
199
+ import type { IDocument } from '../../composables/classes';
125
200
  import { uuid } from 'vue-uuid';
201
+ import type { Base, FileActions } from '../../types';
126
202
 
127
203
  export default defineComponent({
128
204
  setup() {
205
+ type DigitalDocNames = 'Удостоверение личности' | 'Паспорт';
206
+ type DigitalDocTypes = 'IdentityCard' | 'Passport';
207
+
208
+ const route = useRoute();
129
209
  const dataStore = useDataStore();
130
210
  const formStore = useFormStore();
131
211
  const currentDocument = ref<DocumentItem>(new DocumentItem());
132
212
  const documentLoading = ref<boolean>(false);
133
213
  const deletionDialog = ref<boolean>(false);
214
+ const isPanelOpen = ref<boolean>(false);
215
+ const isDigitalDocOpen = ref<boolean>(false);
134
216
  const isDisabled = computed(() => !dataStore.isTask());
135
217
  const contractDict = computed(() => dataStore.dicFileTypeList.find(i => i.nameRu === 'Договор страхования' || i.nameRu === 'Договор'));
136
218
  const processCode = formStore.applicationData.processCode;
219
+
220
+ const hasDigitalDocuments = computed(() => dataStore.isEfoParent && !dataStore.isGns && !dataStore.isLifeBusiness && !!formStore.applicationData);
221
+ const isDigitalDocDisabled = computed(
222
+ () => !dataStore.isTask() || route.params.taskId === '0' || !dataStore.isInitiator() || !dataStore.isProcessEditable(formStore.applicationData.statusCode),
223
+ );
224
+ const documentType = ref<DigitalDocNames | null>(null);
225
+ const otpCode = ref<string>('');
226
+ const currentIin = ref<string>('');
227
+ const deleteFilesId = ['1', '2', '46'];
228
+ const documentItems: Array<{ title: DigitalDocNames; value: DigitalDocTypes }> = [
229
+ { title: 'Удостоверение личности', value: 'IdentityCard' },
230
+ { title: 'Паспорт', value: 'Passport' },
231
+ ];
137
232
  const signedContract = reactive<{
138
233
  processInstanceId: string | number;
139
234
  fileTypeId: string | number | null;
@@ -176,7 +271,7 @@ export default defineComponent({
176
271
  (formStore.applicationData.statusCode === 'Completed' || formStore.applicationData.statusCode === 'PreparationDossierForm' || dataStore.isActuary()),
177
272
  );
178
273
  const noDocuments = computed(() => {
179
- if (dataStore.isPension) return !showContract.value;
274
+ if (dataStore.isPension && (!formStore.signedDocumentList || !formStore.signedDocumentList.length)) return !showContract.value;
180
275
  return !formStore.signedDocumentList || !formStore.signedDocumentList.length;
181
276
  });
182
277
  const isUnderwriterDocuments = computed(
@@ -189,16 +284,24 @@ export default defineComponent({
189
284
  const canDeleteFiles = computed(() => {
190
285
  const baseCondition = dataStore.isTask() && dataStore.isInitiator() && dataStore.isProcessEditable(formStore.applicationData.statusCode);
191
286
  if (dataStore.isBaiterek || dataStore.isBolashak || dataStore.isLiferenta || dataStore.isKazyna || dataStore.isAmulet || dataStore.isGons) {
192
- return baseCondition && (currentDocument.value ? currentDocument.value.fileTypeCode === '46' : false);
287
+ return baseCondition && (currentDocument.value ? deleteFilesId.includes(String(currentDocument.value.fileTypeCode)) : false);
193
288
  }
194
289
  if (dataStore.isPension) return baseCondition;
195
290
  return false;
196
291
  });
197
292
 
293
+ const policyholderForm = computed(() => formStore.policyholderForm as Base.Document.Digital);
294
+ const insuredFiltered = computed(() => formStore.insuredForm.filter(i => i.iin !== formStore.policyholderForm.iin) as Base.Document.Digital[]);
295
+ const beneficiaryFiltered = computed(() => formStore.beneficiaryForm.filter(i => i.iin !== formStore.policyholderForm.iin) as Base.Document.Digital[]);
296
+ const documentListFiltered = computed(() => formStore.signedDocumentList.filter(i => !['1', '2'].includes(String(i.fileTypeCode))));
297
+
198
298
  const openPanel = async (document: DocumentItem) => {
199
299
  dataStore.rightPanel.title = document.fileTypeName!;
200
300
  currentDocument.value = document;
201
301
  dataStore.rightPanel.open = true;
302
+ isDigitalDocOpen.value = false;
303
+ isPanelOpen.value = true;
304
+ dataStore.panelAction = null;
202
305
  };
203
306
 
204
307
  const onFileChange = async (event: InputEvent) => {
@@ -263,6 +366,17 @@ export default defineComponent({
263
366
  }
264
367
  };
265
368
 
369
+ const openDigitalDocPanel = async (iin: string, title: string) => {
370
+ isPanelOpen.value = false;
371
+ isDigitalDocOpen.value = true;
372
+ dataStore.panelAction = null;
373
+ dataStore.rightPanel.open = true;
374
+ dataStore.rightPanel.title = `Получить ЦД ${title}`;
375
+ documentType.value = null;
376
+ otpCode.value = '';
377
+ currentIin.value = iin;
378
+ };
379
+
266
380
  watch(
267
381
  () => document_list.value,
268
382
  () => {
@@ -293,18 +407,93 @@ export default defineComponent({
293
407
  const data = {
294
408
  id: currentDocument.value.id,
295
409
  processInstanceId: currentDocument.value.processInstanceId,
410
+ iin: currentDocument.value.iin ?? '',
296
411
  };
297
412
  await dataStore.deleteFile(data);
298
413
  deletionDialog.value = false;
299
414
  dataStore.rightPanel.open = false;
300
415
  dataStore.panelAction = null;
301
416
  await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
417
+ if (hasDigitalDocuments.value && (currentDocument.value.fileTypeCode === '1' || currentDocument.value.fileTypeCode === '2')) {
418
+ getDigitalDocs();
419
+ }
420
+ }
421
+ };
422
+
423
+ const getCode = async () => {
424
+ if (!documentType.value) {
425
+ dataStore.showToaster('error', 'Выберите тип документа', 3000);
426
+ return;
427
+ }
428
+ documentLoading.value = true;
429
+ const response = await dataStore.onlineAccess(currentIin.value, String(documentType.value));
430
+ if (response) {
431
+ dataStore.showToaster('success', dataStore.t('toaster.successOtp'), 3000);
432
+ }
433
+ documentLoading.value = false;
434
+ };
435
+
436
+ const getDigitalDocument = async () => {
437
+ if (!otpCode.value) {
438
+ dataStore.showToaster('error', 'Введите код подтверждения', 3000);
439
+ return;
440
+ }
441
+ documentLoading.value = true;
442
+ const response = await dataStore.digitalDocuments(currentIin.value, String(formStore.applicationData.processInstanceId), otpCode.value);
443
+ if (response) {
444
+ await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
445
+ getDigitalDocs();
446
+ isDigitalDocOpen.value = false;
447
+ dataStore.panelAction = null;
448
+ dataStore.rightPanel.open = false;
449
+ documentType.value = null;
450
+ otpCode.value = '';
451
+ }
452
+ documentLoading.value = false;
453
+ };
454
+
455
+ const findCommonDocs = (members: Base.Document.Digital[]) => {
456
+ let commonDocs: IDocument[] = [];
457
+ for (let member of members) {
458
+ const matchingDoc = formStore.signedDocumentList.find(doc => doc.iin === String(member.iin).replaceAll('-', '') && (doc.fileTypeCode === '1' || doc.fileTypeCode === '2'));
459
+ if (matchingDoc) commonDocs.push(matchingDoc);
460
+ }
461
+ return commonDocs;
462
+ };
463
+
464
+ const setDigitalDocuments = (members: Base.Document.Digital[]) => {
465
+ const commonDocs = findCommonDocs(members);
466
+ if (commonDocs.length !== 0) {
467
+ for (let member of members) {
468
+ const matchingDoc = commonDocs.find(doc => doc.iin === String(member.iin).replaceAll('-', ''));
469
+ if (matchingDoc) member.digitalDocument = matchingDoc;
470
+ }
471
+ }
472
+ };
473
+
474
+ const clearDigitalDocuments = (members: Base.Document.Digital[]) => {
475
+ for (let member of members) member.digitalDocument = null;
476
+ };
477
+
478
+ const getDigitalDocs = () => {
479
+ if (route.params.taskId !== '0') {
480
+ clearDigitalDocuments([formStore.policyholderForm as Base.Document.Digital]);
481
+ setDigitalDocuments([formStore.policyholderForm as Base.Document.Digital]);
482
+ if (insuredFiltered.value.length !== 0) {
483
+ clearDigitalDocuments(insuredFiltered.value);
484
+ setDigitalDocuments(insuredFiltered.value);
485
+ }
486
+ if (beneficiaryFiltered.value.length !== 0) {
487
+ clearDigitalDocuments(beneficiaryFiltered.value);
488
+ setDigitalDocuments(beneficiaryFiltered.value);
489
+ }
302
490
  }
303
491
  };
304
492
 
305
493
  const onInit = async () => {
306
494
  await dataStore.getDicFileTypeList();
307
495
  await dataStore.getSignedDocList(formStore.applicationData.processInstanceId);
496
+ if (hasDigitalDocuments.value) getDigitalDocs();
308
497
  };
309
498
 
310
499
  onInit();
@@ -315,12 +504,17 @@ export default defineComponent({
315
504
 
316
505
  return {
317
506
  // State
507
+ otpCode,
318
508
  formStore,
319
- documentLoading,
509
+ processCode,
510
+ isPanelOpen,
320
511
  DocumentItem,
512
+ documentType,
513
+ documentItems,
321
514
  signedContract,
322
515
  deletionDialog,
323
- processCode,
516
+ documentLoading,
517
+ isDigitalDocOpen,
324
518
  underDocumentsList,
325
519
 
326
520
  // Computed
@@ -328,17 +522,54 @@ export default defineComponent({
328
522
  showContract,
329
523
  noDocuments,
330
524
  canDeleteFiles,
525
+ insuredFiltered,
526
+ policyholderForm,
527
+ beneficiaryFiltered,
528
+ hasDigitalDocuments,
529
+ documentListFiltered,
530
+ isDigitalDocDisabled,
331
531
  isUnderwriterDocuments,
332
532
 
333
533
  // Functions
534
+ getCode,
334
535
  getFile,
335
536
  openPanel,
336
537
  deleteFile,
538
+ getDigitalDocument,
337
539
  onFileChange,
338
540
  onUnderFiles,
541
+ openDigitalDocPanel,
339
542
  uploadUnderFiles,
340
543
  onClearUnderFiles,
341
544
  };
342
545
  },
343
546
  });
344
547
  </script>
548
+
549
+ <style>
550
+ .document-type-select .v-field {
551
+ border: none !important;
552
+ border-radius: 4px;
553
+ height: 56px;
554
+ }
555
+ .digital-document-otp .base-otp-input .v-otp-input__content {
556
+ gap: 8px;
557
+ padding-right: 0px !important;
558
+ padding-left: 0px !important;
559
+ }
560
+ .digital-doc-info .v-expansion-panel-text__wrapper {
561
+ padding: 8px 14px !important;
562
+ }
563
+ .digital-doc-info .v-expansion-panel-title {
564
+ max-height: 40px !important;
565
+ min-height: 39px !important;
566
+ padding: 0px 14px !important;
567
+ color: #464f60 !important;
568
+ }
569
+ .document-type-select .v-field-label--floating {
570
+ top: 5px !important;
571
+ }
572
+ .document-type-select .v-field__input {
573
+ padding-top: 21px;
574
+ }
575
+ </style>