bxs-tools-ui 3.1.2 → 3.2.0-0

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.
@@ -129,7 +129,8 @@
129
129
  allowCustomResult: true,
130
130
  planbookId: params.planbookId
131
131
  }"
132
- @change="cgProduct"
132
+ @reCalculate="reCalculateProductData"
133
+ @change="(product, options, inst) => $emit('change', product, options, inst)"
133
134
  />
134
135
  </CommonPopup>
135
136
  <CommonPopup
@@ -197,6 +198,7 @@ import { Component, Prop, Watch } from 'vue-property-decorator';
197
198
  import { get as _get, cloneDeep } from 'lodash';
198
199
  import { initAddAndTakePopupConfig } from 'packages/add-and-take/handler.ts';
199
200
  import { ADD_AND_TAKE_TITLE_MAP } from 'packages/add-and-take/constant.ts';
201
+ import { calculateProductData } from '../helper.js';
200
202
  import { convertInputDataToResultData } from './handler';
201
203
 
202
204
  import CommonPopup from '@src/components/common/common-popup.vue';
@@ -285,7 +287,11 @@ export default class BxtProductTable extends Vue {
285
287
  isCkConfirm = false;
286
288
  backupProductData: any = null;
287
289
  addAndTakeTitleMap = ADD_AND_TAKE_TITLE_MAP;
288
-
290
+ reCalculateProductData(inputData, params, resolve, reject) {
291
+ return calculateProductData(inputData, params)
292
+ .then(resolve)
293
+ .catch(reject);
294
+ }
289
295
  isShowDeleteBtn() {
290
296
  let index = this.groupData && this.groupData.prodOrderList && this.groupData.prodOrderList.findIndex(p => p.key === this.params.productKey);
291
297
  return this.productData.hadChoice && !this.productData.required && index >= this.groupData.defNum;
@@ -298,13 +304,6 @@ export default class BxtProductTable extends Vue {
298
304
  }
299
305
  }
300
306
  }
301
- cgProduct(product, options, inst) {
302
- if (options.type === 'change' && options.errorMsg) {
303
- this.$nextTick(() => {
304
- this.$toast(options.errorMsg);
305
- });
306
- }
307
- }
308
307
  deleteProduct() {
309
308
  this.productData.hadChoice = false;
310
309
  this.productData.totalBaof = null;
@@ -1,5 +1,6 @@
1
1
  import { Toast } from 'vant';
2
2
  import QS from 'qs';
3
+ import { get as _get, cloneDeep } from 'lodash';
3
4
  import { PLANBOOK_API_HOSTNAME } from '@src/js/variables.js';
4
5
  import {
5
6
  initPersonData,
@@ -10,7 +11,7 @@ import {
10
11
  convertProductData,
11
12
  verifyProductRules,
12
13
  convertEleOrderListToObj,
13
- deepCopy
14
+ getExpressionParamMap
14
15
  } from 'packages/bxs-utils/index';
15
16
  import { createMd5Token } from '@src/js/md5Token.js';
16
17
 
@@ -37,6 +38,7 @@ export async function initPageData(data) {
37
38
  }
38
39
  return data;
39
40
  }
41
+
40
42
  export function setPageDataBaseOnResult(data) {
41
43
  if (!data) {
42
44
  return data;
@@ -269,7 +271,6 @@ export function receiveProductData(inputData, rProductData, options = {}) {
269
271
  const hasSomeCheckedIns = rProductData.mulInsOrderList.some(ins => ins.title);
270
272
  productData.hadChoice = hasSomeCheckedIns;
271
273
  productData.totalBaof = hasSomeCheckedIns ? rProductData.totalBaof : null;
272
- // ??
273
274
  productData.companyName = rProductData.companyName;
274
275
 
275
276
  let insShowArr = null;
@@ -406,7 +407,7 @@ export function getProductFromInputData(inputData, options = {}) {
406
407
  }
407
408
 
408
409
  export function initRecipientData(personData) {
409
- let eleOrderList = deepCopy(personData.eleOrderList);
410
+ let eleOrderList = cloneDeep(personData.eleOrderList);
410
411
  eleOrderList = eleOrderList.filter(ele => !['name', 'sex'].includes(ele.key));
411
412
  eleOrderList.forEach(ele => {
412
413
  if (ele.key === 'title') {
@@ -478,12 +479,12 @@ export async function calculateProductData(inputData, options = {}) {
478
479
  })
479
480
  .then(response => response.json())
480
481
  .then(res => {
481
- const { success, data } = res;
482
+ const { success, code, info, data } = res;
482
483
  if (success && data) {
483
- const promises = [];
484
+ const productList = [];
484
485
  data.productGroupList.forEach(g => {
485
486
  g.prodOrderList.forEach(p => {
486
- promises.push(
487
+ productList.push(
487
488
  receiveProductData(inputData, p, {
488
489
  publicPbUuid,
489
490
  groupKey,
@@ -492,13 +493,135 @@ export async function calculateProductData(inputData, options = {}) {
492
493
  );
493
494
  });
494
495
  });
495
- return Promise.all(promises);
496
+
497
+ // 计算结果校验
498
+ if (Array.isArray(inputData.productGroupList)) {
499
+ let errorMessage = '';
500
+ const allProductList = inputData.productGroupList.map(g => g.prodOrderList).flat();
501
+ const productData = allProductList.find(p => p && p.key === productKey);
502
+ const mulInsOrderList = _get(productData, 'mulInsOrderList') || [];
503
+ const hasCalcResultExp = mulInsOrderList.some(ins => ins.calcResultExp);
504
+ if (hasCalcResultExp) {
505
+ mulInsOrderList
506
+ .filter(ins => ins.calcResultExp)
507
+ .forEach(ins => {
508
+ if (!errorMessage) {
509
+ const paramMap = getExpressionParamMap(inputData.personData, productData, ins, options);
510
+ if (paramMap) {
511
+ const exp = ins.calcResultExp.replace(/(%)(\d+)(\.*\w*)(%)/g, 'paramMap.i$2$3').replace(/(%)(\w*\.*\w*)(%)/g, 'paramMap.$2');
512
+ errorMessage = eval(exp);
513
+ console.log('计算结果校验公式: ', ins.calcResultExp);
514
+ console.log('计算结果校验结果: ', errorMessage);
515
+ }
516
+ }
517
+ });
518
+ }
519
+ if (errorMessage) {
520
+ return Promise.reject(new Error(errorMessage));
521
+ }
522
+ }
523
+
524
+ return Promise.resolve(productList);
496
525
  }
497
- return Promise.reject();
498
- })
499
- .catch(error => {
500
- console.log(error);
526
+ return Promise.reject(new Error(info || `计算失败:${code || ''}`));
501
527
  });
502
528
  }
503
529
  return Promise.reject();
504
530
  }
531
+
532
+ export async function doubleCalcProductData(inputData, verifyData, options = {}) {
533
+ const { planbookId, publicPbUuid, groupKey, productKey, isIgnoreError } = options;
534
+ const personData = inputData && inputData.personData;
535
+ const productGroupList = inputData && inputData.productGroupList ? inputData.productGroupList : [];
536
+ const productGroup = productGroupList.find(g => g.key === groupKey);
537
+ const prodOrderList = productGroup && productGroup.prodOrderList ? productGroup.prodOrderList : [];
538
+ const productData = prodOrderList.find(p => p.key === productKey);
539
+ const mulInsOrderList = productData && productData.mulInsOrderList ? productData.mulInsOrderList : [];
540
+ const productVerifyData = verifyData && verifyData[productKey];
541
+ const hasRevalidateFlag = mulInsOrderList.some(ins => ins.revalidateFlag);
542
+ if (productData) {
543
+ await productDataHandler(productData, productVerifyData, personData, {
544
+ planbookId
545
+ });
546
+ await calculateProductData(inputData, {
547
+ planbookId,
548
+ publicPbUuid,
549
+ groupKey,
550
+ productKey,
551
+ isIgnoreError
552
+ });
553
+ if (hasRevalidateFlag) {
554
+ await productDataHandler(productData, productVerifyData, personData, {
555
+ planbookId
556
+ });
557
+ await calculateProductData(inputData, {
558
+ planbookId,
559
+ publicPbUuid,
560
+ groupKey,
561
+ productKey,
562
+ isIgnoreError
563
+ });
564
+ }
565
+ }
566
+ }
567
+
568
+ export function setupUnderwriteRuleToInputData(data) {
569
+ const inputData = cloneDeep(data);
570
+ if (inputData) {
571
+ const productGroupList = _get(inputData, 'productGroupList') || [];
572
+ const productList = productGroupList
573
+ .map(g => g.prodOrderList)
574
+ .filter(Boolean)
575
+ .flat();
576
+ const insuranceList = productList
577
+ .map(p => p.mulInsOrderList)
578
+ .filter(Boolean)
579
+ .flat();
580
+ const insuranceIds = insuranceList
581
+ .map(ins => ins.key)
582
+ .filter(k => !['common'].includes(k))
583
+ .filter(Boolean);
584
+
585
+ return fetch(`${PLANBOOK_API_HOSTNAME}/planBook/interest/underwrite/effective-rules`, {
586
+ method: 'POST',
587
+ credentials: 'include',
588
+ headers: {
589
+ Accept: 'application/json, text/plain, */*',
590
+ 'Content-Type': 'application/json;'
591
+ },
592
+ body: JSON.stringify(insuranceIds)
593
+ })
594
+ .then(response => response.json())
595
+ .then(({ success, data }) => {
596
+ if (success && Array.isArray(data)) {
597
+ insuranceList.forEach(ins => {
598
+ const ruleData = data.find(rule => rule.insruanceId === ins.key);
599
+ if (ruleData) {
600
+ const insExpKeys = ['customVariableExp', 'calcResultExp', 'revalidateFlag'];
601
+ insExpKeys
602
+ .filter(k => k in ruleData)
603
+ .forEach(key => {
604
+ ins[key] = ruleData[key];
605
+ });
606
+ if (Array.isArray(ins.eleOrderList) && Array.isArray(ruleData.eleRules)) {
607
+ ins.eleOrderList.forEach(ele => {
608
+ const eleRule = ruleData.eleRules.find(rule => rule.elementKey === ele.key);
609
+ const eleExpkeys = ['defaultValueExp', 'maxExp', 'minExp', 'multiExp', 'underwriteExp'];
610
+ if (eleRule) {
611
+ eleExpkeys
612
+ .filter(k => k in eleRule)
613
+ .forEach(key => {
614
+ ele[key] = eleRule[key];
615
+ });
616
+ }
617
+ });
618
+ }
619
+ }
620
+ });
621
+ return inputData;
622
+ }
623
+ });
624
+ }
625
+
626
+ return inputData;
627
+ }
@@ -34,6 +34,7 @@
34
34
  productKey: p.key,
35
35
  interestProductList: planbookData && planbookData.interestProductList
36
36
  }"
37
+ @change="changeProduct"
37
38
  @confirm="confirmProduct"
38
39
  @changePerson="changePersonInfo"
39
40
  />
@@ -52,7 +53,14 @@ import { get as _get } from 'lodash';
52
53
  import { PLANBOOK_API_HOSTNAME, PBF_HOSTNAME } from '@src/js/variables.js';
53
54
  import { calcTotalBaof } from 'packages/bxs-utils/index';
54
55
  import { getPlanbookData } from './api';
55
- import { initPageData, setPageDataBaseOnResult, calculateProductData, createPlanbookDataToMake } from './helper.js';
56
+ import {
57
+ initPageData,
58
+ setPageDataBaseOnResult,
59
+ calculateProductData,
60
+ doubleCalcProductData,
61
+ createPlanbookDataToMake,
62
+ setupUnderwriteRuleToInputData
63
+ } from './helper.js';
56
64
  import { createMd5Token } from '@src/js/md5Token.js';
57
65
  import PersonInfo from '../person-info/index.vue';
58
66
  import ProductTable from './components/product-table.vue';
@@ -74,6 +82,9 @@ export default class BxtPlanbookInput extends Vue {
74
82
  get inputData(): IPbInput | null {
75
83
  return _get(this, 'planbookData.initData.inputData');
76
84
  }
85
+ get verifyData(): IPbInput | null {
86
+ return _get(this, 'planbookData.verifyData');
87
+ }
77
88
  async created() {
78
89
  this.getPlanbookData();
79
90
  }
@@ -91,6 +102,10 @@ export default class BxtPlanbookInput extends Vue {
91
102
  // publicPbUuid: '5d6499946bbb47bb8f6a286e9d4eee77'
92
103
  })
93
104
  .then(async (data: any) => {
105
+ if (data.initData && data.initData.inputData) {
106
+ const _inputData = await setupUnderwriteRuleToInputData(data.initData.inputData).catch(() => null);
107
+ data.initData.inputData = _inputData || data.initData.inputData;
108
+ }
94
109
  await initPageData(data);
95
110
  setPageDataBaseOnResult(data);
96
111
  document.title = `DEMO:${data.title}`;
@@ -103,26 +118,31 @@ export default class BxtPlanbookInput extends Vue {
103
118
  });
104
119
  }
105
120
  autoImportData() {
106
- const { URL_PARAM, inputData } = this;
121
+ const { URL_PARAM, verifyData, inputData } = this;
107
122
  const { planbookId, publicPbUuid } = URL_PARAM;
108
123
  if (inputData) {
109
124
  inputData.productGroupList
110
125
  .filter((g: IPbProductGroup) => g.prodOrderList)
111
126
  .forEach((g: IPbProductGroup) => {
112
127
  g.prodOrderList.forEach((p: IPbProduct) => {
113
- calculateProductData(inputData, {
114
- planbookId,
128
+ doubleCalcProductData(inputData, verifyData, {
129
+ planbookId: Number(planbookId),
115
130
  publicPbUuid,
116
131
  groupKey: g.key,
117
132
  productKey: p.key,
118
133
  isIgnoreError: true
134
+ }).catch(err => {
135
+ if (err && err.message) {
136
+ Toast(err.message);
137
+ }
138
+ console.error(err);
119
139
  });
120
140
  });
121
141
  });
122
142
  }
123
143
  }
124
144
  changePersonInfo(person: IPbPerson, ele: any = {}) {
125
- const { URL_PARAM, inputData } = this;
145
+ const { URL_PARAM, verifyData, inputData } = this;
126
146
  const { planbookId, publicPbUuid } = URL_PARAM;
127
147
  if (inputData) {
128
148
  inputData.productGroupList
@@ -131,17 +151,24 @@ export default class BxtPlanbookInput extends Vue {
131
151
  g.prodOrderList
132
152
  .filter((p: IPbProduct) => p.hadChoice)
133
153
  .forEach((p: IPbProduct) => {
134
- calculateProductData(inputData, {
135
- planbookId,
154
+ doubleCalcProductData(inputData, verifyData, {
155
+ planbookId: Number(planbookId),
136
156
  publicPbUuid,
137
157
  groupKey: g.key,
138
158
  productKey: p.key,
139
159
  isIgnoreError: true
160
+ }).catch(err => {
161
+ Toast(err.message);
140
162
  });
141
163
  });
142
164
  });
143
165
  }
144
166
  }
167
+ changeProduct(product, options, inst) {
168
+ if (options.type === 'change' && options.errorMsg) {
169
+ Toast(options.errorMsg);
170
+ }
171
+ }
145
172
  confirmProduct(options: any, inst: any) {
146
173
  const self = this;
147
174
  const { URL_PARAM, inputData } = self;
@@ -151,7 +178,7 @@ export default class BxtPlanbookInput extends Vue {
151
178
  .validate()
152
179
  .then(() => {
153
180
  return calculateProductData(inputData, {
154
- planbookId,
181
+ planbookId: Number(planbookId),
155
182
  publicPbUuid,
156
183
  groupKey,
157
184
  productKey
@@ -160,7 +187,10 @@ export default class BxtPlanbookInput extends Vue {
160
187
  });
161
188
  })
162
189
  .catch(err => {
163
- Toast(err && err[0] && err[0].message ? err[0].message : err);
190
+ const errorMessage = _get(err, '[0].message') || _get(err, 'message') || err;
191
+ if (typeof errorMessage === 'string' && errorMessage.trim()) {
192
+ Toast(errorMessage);
193
+ }
164
194
  console.log(err);
165
195
  });
166
196
  }
@@ -331,22 +331,56 @@ export default class BxtProductInfo extends Vue {
331
331
  inputDom.focus();
332
332
  }
333
333
  async changeProduct(productData, options) {
334
- if (options.type === 'change') {
334
+ const { $listeners, inputData, verifyData, personData, groupKey, productKey, params } = this;
335
+ const { type, insData, eleData } = options;
336
+ const planbookId = _get(params, 'planbookId');
337
+ const publicPbUuid = _get(params, 'publicPbUuid');
338
+ const productVerifyData = _get(verifyData, `[${productKey}]`);
339
+
340
+ if (type === 'change') {
335
341
  clearAddAndTakeAndAdjustBaoeData(productData);
336
342
  }
337
- await productDataHandler(productData, _get(this, `verifyData[${productData.key}]`), this.personData, {
338
- planbookId: _get(this, 'params.planbookId')
343
+ await productDataHandler(productData, productVerifyData, personData, {
344
+ planbookId
339
345
  });
340
- if (options.type === 'change') {
341
- this.createInsuranceInputResultEle(options.insData, options.eleData);
346
+ if (type === 'change') {
347
+ this.createInsuranceInputResultEle(insData, eleData);
342
348
  } else {
343
349
  this.createInsuranceInputResultEle();
344
350
  }
345
- return verifyProductRules({
346
- personData: this.personData,
351
+
352
+ let errorMsg: any = verifyProductRules({
353
+ personData,
347
354
  productData,
348
- ...options
355
+ insData,
356
+ eleData
349
357
  });
358
+ if (!errorMsg) {
359
+ const hasRevalidateFlag = (_get(productData, 'mulInsOrderList') || []).some(ins => ins.revalidateFlag);
360
+ if (hasRevalidateFlag && $listeners.reCalculate) {
361
+ await new Promise<any>((resolve, reject) => {
362
+ this.$emit(
363
+ 'reCalculate',
364
+ inputData,
365
+ {
366
+ planbookId,
367
+ publicPbUuid,
368
+ groupKey,
369
+ productKey,
370
+ isIgnoreError: true
371
+ },
372
+ resolve,
373
+ reject
374
+ );
375
+ }).catch(err => {
376
+ errorMsg = _get(err, '[0].message') || _get(err, 'message');
377
+ });
378
+ await productDataHandler(productData, productVerifyData, personData, {
379
+ planbookId
380
+ });
381
+ }
382
+ }
383
+ return errorMsg;
350
384
  }
351
385
  isInsuranceChecked(ins) {
352
386
  let titleEle = ins.eleOrderList.find(e => e.key === 'title');
@@ -122,7 +122,7 @@
122
122
  & .bxt-share {
123
123
  & .bxt-share-wrapper {
124
124
  display: flex;
125
- justify-content: center;
125
+ justify-content: flex-start;
126
126
  padding: 20px 15px;
127
127
  overflow: auto;
128
128
 
@@ -170,8 +170,6 @@
170
170
  }
171
171
 
172
172
  & .bxt-share-wrapper.more {
173
- justify-content: flex-start;
174
-
175
173
  & figure {
176
174
  flex: 0 0 23%;
177
175
  }
@@ -36,7 +36,7 @@
36
36
  </section>
37
37
  <slot name="header"></slot>
38
38
  <section v-if="shareOptions.length" class="bxt-share bxt-bottom-border">
39
- <div class="bxt-share-wrapper" :class="[shareOptions.length > 4 || actionTypeLength > 1 ? 'more' : '']">
39
+ <div class="bxt-share-wrapper" :class="[shareOptions.length > 4 ? 'more' : '']">
40
40
  <figure v-for="o in shareOptions" :key="o.action" @click="onClickShare(o)">
41
41
  <div class="bxt-empty-image">
42
42
  <img v-if="o.actionIcon" :src="o.actionIcon" alt="icon" />
@@ -46,7 +46,7 @@
46
46
  </div>
47
47
  </section>
48
48
  <section v-if="actionOptions.length" class="bxt-share bxt-bottom-border">
49
- <div class="bxt-share-wrapper" :class="[actionOptions.length > 4 || actionTypeLength > 1 ? 'more' : '']">
49
+ <div class="bxt-share-wrapper" :class="[actionOptions.length > 4 ? 'more' : '']">
50
50
  <figure v-for="o in actionOptions" :key="o.action" @click="onClickAction(o)">
51
51
  <div class="bxt-empty-image">
52
52
  <img v-if="o.actionIcon" :src="o.actionIcon" alt="icon" />
@@ -132,9 +132,6 @@ export default {
132
132
  });
133
133
  }
134
134
  return options;
135
- },
136
- actionTypeLength() {
137
- return [this.shareOptions, this.actionOptions].filter(e => e.length).length;
138
135
  }
139
136
  },
140
137
  created() {