bxs-tools-ui 3.3.2 → 3.4.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.
- package/es/add-and-take/index.js +1 -7969
- package/es/adjust-baoe/index.js +196 -8195
- package/es/index.css +1 -1
- package/es/index.js +8788 -43744
- package/es/insure-calculate/index.css +1 -1
- package/es/insure-calculate/index.js +1046 -36665
- package/es/person-info/index.css +1 -1
- package/es/person-info/index.js +83 -8042
- package/es/product-info/index.css +1 -1
- package/es/product-info/index.js +3005 -10614
- package/es/share-sheet/index.js +69 -8040
- package/es/utils/index.js +1250 -9334
- package/lib/add-and-take/index.js +4 -7973
- package/lib/adjust-baoe/index.js +195 -8195
- package/lib/index.css +1 -1
- package/lib/index.js +8717 -43678
- package/lib/insure-calculate/index.css +1 -1
- package/lib/insure-calculate/index.js +1034 -36662
- package/lib/person-info/index.css +1 -1
- package/lib/person-info/index.js +86 -8046
- package/lib/product-info/index.css +1 -1
- package/lib/product-info/index.js +2807 -10417
- package/lib/share-sheet/index.js +72 -8044
- package/lib/utils/index.js +1252 -9337
- package/package.json +5 -3
- package/packages/add-and-take/demo/index.vue +3 -6
- package/packages/adjust-baoe/index.vue +21 -34
- package/packages/adjust-baoe/readme.md +0 -1
- package/packages/bxs-utils/planbook/common.ts +5 -0
- package/packages/bxs-utils/planbook/insurance.ts +19 -0
- package/packages/bxs-utils/planbook/person.ts +3 -2
- package/packages/bxs-utils/planbook/product.ts +57 -164
- package/packages/bxs-utils/readme.md +3 -1
- package/packages/index.ts +1 -1
- package/packages/insure-calculate/demo/index.vue +1 -1
- package/packages/insure-calculate/index.vue +18 -17
- package/packages/person-info/demo/index.vue +2 -4
- package/packages/planbook-input/components/product-table.vue +3 -14
- package/packages/planbook-input/helper.js +16 -53
- package/packages/planbook-input/index.vue +20 -28
- package/packages/planbook-input/readme.md +3 -3
- package/packages/product-info/components/product-insurance-form.md +46 -0
- package/packages/product-info/components/product-insurance-form.vue +360 -0
- package/packages/product-info/demo/index.vue +4 -5
- package/packages/product-info/handler.js +307 -0
- package/packages/product-info/handler.md +26 -0
- package/packages/product-info/index.less +33 -0
- package/packages/product-info/index.vue +306 -534
- package/packages/product-info/readme.md +7 -2
- package/packages/share-sheet/constant.js +1 -2
- package/src/api/adjust-baoe.js +2 -2
- package/src/api/planbook.js +4 -20
- package/src/api/trade.js +31 -0
- package/src/components/common/common-group-title.less +54 -0
- package/src/components/common/common-group-title.md +34 -0
- package/src/components/common/common-group-title.vue +72 -0
- package/src/components/common/common-title.less +4 -0
- package/src/components/common/common-title.vue +8 -2
- package/src/components/profession-list/README.md +114 -0
- package/src/components/profession-list/constant.js +4 -0
- package/src/components/profession-list/handler.js +155 -0
- package/src/components/profession-list/index.less +182 -0
- package/src/components/profession-list/index.vue +443 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<van-form ref="insuranceForm" :class="formClassList" :show-error="false" @submit.native.prevent="closeKeyBoard()">
|
|
3
|
+
<template v-for="ele in ins.eleOrderList">
|
|
4
|
+
<van-field v-if="['cmCommonTitle'].includes(ele.componentName)" :key="ele.key" :name="ele.key" :rules="getElementRules(ele)">
|
|
5
|
+
<template #input>
|
|
6
|
+
<CommonTitle
|
|
7
|
+
v-model="ele.value"
|
|
8
|
+
:key="`${productKey}_${ins.key}_${ele.key}`"
|
|
9
|
+
:name="ele.key"
|
|
10
|
+
:code="ins.code"
|
|
11
|
+
:huomian-tag="getInsuranceTitleHmTag(ins)"
|
|
12
|
+
:status-tag="getInsuranceSaleStatusTag(ins)"
|
|
13
|
+
:huomian-tips="showHuomianTips && getHuomianTips(ins, ele)"
|
|
14
|
+
:label="ele.labelName"
|
|
15
|
+
:style="{
|
|
16
|
+
fontSize: '17px',
|
|
17
|
+
fontWeight: 'bold'
|
|
18
|
+
}"
|
|
19
|
+
:disabled="getElementDisabled(ele)"
|
|
20
|
+
:always-show-checkbox="isGroupSub"
|
|
21
|
+
:data-stat-id="`product_insurance_${ele.key}`"
|
|
22
|
+
@change="onTitleChange(ele)"
|
|
23
|
+
@openCrmPerson="$emit('openCrmPerson')"
|
|
24
|
+
/>
|
|
25
|
+
</template>
|
|
26
|
+
</van-field>
|
|
27
|
+
|
|
28
|
+
<template v-if="isInsuranceChecked && !ele.isHide && ele.componentName !== 'cmCommonTitle'">
|
|
29
|
+
<van-field
|
|
30
|
+
v-if="['cmCommonInput'].includes(ele.componentName)"
|
|
31
|
+
v-model.number="ele.value"
|
|
32
|
+
:ref="ins.key + ele.key + 'item'"
|
|
33
|
+
:key="ins.key + ele.key"
|
|
34
|
+
:id="`id_${ins.key}_${ele.key}`"
|
|
35
|
+
:type="ele.inputType || 'tel'"
|
|
36
|
+
:class="{
|
|
37
|
+
'van-field-unit': activeInputKey === ins.key + ele.key && numberUnitStr
|
|
38
|
+
}"
|
|
39
|
+
:prop="ele.key"
|
|
40
|
+
:label="ele.labelName"
|
|
41
|
+
:placeholder="ele.placeholder"
|
|
42
|
+
:disabled="getElementDisabled(ele)"
|
|
43
|
+
:readonly="getElementDisabled(ele)"
|
|
44
|
+
:maxlength="ele.maxlength || 9"
|
|
45
|
+
:rules="getElementRules(ele)"
|
|
46
|
+
autocomplete="off"
|
|
47
|
+
input-align="right"
|
|
48
|
+
error-message-align="right"
|
|
49
|
+
clearable
|
|
50
|
+
:inputmode="ele.inputType || 'text'"
|
|
51
|
+
@focus="
|
|
52
|
+
activeInputKey = ins.key + ele.key
|
|
53
|
+
numberUnitStr = getAmountUnit(ele)
|
|
54
|
+
"
|
|
55
|
+
@blur="activeInputKey = ''"
|
|
56
|
+
@input="numberUnitStr = getAmountUnit(ele)"
|
|
57
|
+
@change="emitChange(ele)"
|
|
58
|
+
@clear="emitChange(ele)"
|
|
59
|
+
>
|
|
60
|
+
<template v-if="!ele.isDisabled" #right-icon>
|
|
61
|
+
<i class="icon iconfont icon-edit" style="font-size: 20px;" @click="onClickIcon(`id_${ins.key}_${ele.key}`)" />
|
|
62
|
+
</template>
|
|
63
|
+
</van-field>
|
|
64
|
+
<div v-if="activeInputKey === ins.key + ele.key && numberUnitStr" :key="ins.key + ele.key + 'unit'" class="bxt-ins-unit-tips">
|
|
65
|
+
<em />
|
|
66
|
+
<span>
|
|
67
|
+
{{ numberUnitStr }}
|
|
68
|
+
</span>
|
|
69
|
+
</div>
|
|
70
|
+
<div v-if="getRecommendValues(ele)" :key="ins.key + ele.key + 'recommend'" class="bxt-ins-recommend-values">
|
|
71
|
+
<span v-for="v in getRecommendValues(ele)" :key="v" @click="onClickRecommendValue(v, ele)">
|
|
72
|
+
{{ v }}
|
|
73
|
+
</span>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<CommonRadio
|
|
77
|
+
v-if="['cmCommonRadioBtn'].includes(ele.componentName)"
|
|
78
|
+
v-model="ele.value"
|
|
79
|
+
class="bxt-ins-form-radio-btn"
|
|
80
|
+
:key="ins.key + ele.key"
|
|
81
|
+
:name="ele.key"
|
|
82
|
+
:label="ele.labelName"
|
|
83
|
+
:disabled="getElementDisabled(ele)"
|
|
84
|
+
:readonly="getElementDisabled(ele)"
|
|
85
|
+
:rules="getElementRules(ele)"
|
|
86
|
+
:options="ele.opts.filter(o => !o.isHide && !o.isDisabled && !o.isInvalid)"
|
|
87
|
+
input-align="right"
|
|
88
|
+
border
|
|
89
|
+
:data-stat-id="`product_insurance_${ele.key}`"
|
|
90
|
+
@input="emitChange(ele)"
|
|
91
|
+
/>
|
|
92
|
+
|
|
93
|
+
<van-field
|
|
94
|
+
v-if="['cmCommonRadio'].includes(ele.componentName)"
|
|
95
|
+
class="bxt-ins-form-radio"
|
|
96
|
+
:key="ins.key + ele.key"
|
|
97
|
+
:name="ele.key"
|
|
98
|
+
:label="ele.labelName"
|
|
99
|
+
:rules="getElementRules(ele)"
|
|
100
|
+
>
|
|
101
|
+
<template #input>
|
|
102
|
+
<van-radio-group v-model="ele.value" :disabled="getElementDisabled(ele)" @change="emitChange(ele)">
|
|
103
|
+
<van-radio
|
|
104
|
+
v-for="opt in ele.opts"
|
|
105
|
+
:id="`${productKey}_${ins.key}_${ele.key}_${opt.val}`"
|
|
106
|
+
:key="opt.val"
|
|
107
|
+
:name="typeof ele.value === 'number' && !isNaN(Number(opt.val)) ? opt.val * 1 : opt.val"
|
|
108
|
+
:disabled="opt.val != ele.value && opt.isDisabled"
|
|
109
|
+
:label-disabled="opt.val != ele.value && opt.isDisabled"
|
|
110
|
+
>
|
|
111
|
+
<template #icon="props">
|
|
112
|
+
<van-icon v-if="props.checked" class-prefix="iconfont icon" name="multiple_choice" size="20px" />
|
|
113
|
+
<van-icon v-else class-prefix="iconfont icon" name="choose_none_line" size="20px" />
|
|
114
|
+
</template>
|
|
115
|
+
<div class="bxt-ins-form-radio-content">
|
|
116
|
+
<span v-if="opt.code" class="bxt-ins-form-radio--code">{{ opt.code }}</span>
|
|
117
|
+
<span
|
|
118
|
+
class="bxt-ins-form-radio--tx"
|
|
119
|
+
:class="[genInsuranceHmTag(opt) || getInsuranceSaleStatusTagByKey(opt.val) ? 'bxt-ins-form-radio--width' : '']"
|
|
120
|
+
>
|
|
121
|
+
{{ opt.desc }}
|
|
122
|
+
</span>
|
|
123
|
+
<span v-if="getInsuranceSaleStatusTagByKey(opt.val)" class="bxt-ins-form-radio--sale-tag">
|
|
124
|
+
{{ getInsuranceSaleStatusTagByKey(opt.val) }}
|
|
125
|
+
</span>
|
|
126
|
+
<span v-if="genInsuranceHmTag(opt)" class="bxt-ins-form-radio--tag">
|
|
127
|
+
{{ genInsuranceHmTag(opt) }}
|
|
128
|
+
</span>
|
|
129
|
+
</div>
|
|
130
|
+
</van-radio>
|
|
131
|
+
</van-radio-group>
|
|
132
|
+
</template>
|
|
133
|
+
</van-field>
|
|
134
|
+
|
|
135
|
+
<CommonSelect
|
|
136
|
+
v-if="['cmCommonSelect'].includes(ele.componentName)"
|
|
137
|
+
v-model="ele.value"
|
|
138
|
+
:key="ele.componentName + ins.key + ele.key"
|
|
139
|
+
:name="ele.key"
|
|
140
|
+
:label="ele.labelName"
|
|
141
|
+
:placeholder="ele.placeholder"
|
|
142
|
+
:disabled="getElementDisabled(ele)"
|
|
143
|
+
:readonly="getElementDisabled(ele)"
|
|
144
|
+
:rules="getElementRules(ele)"
|
|
145
|
+
:options="ele.opts.filter(o => !o.isHide && !o.isDisabled && !o.isInvalid)"
|
|
146
|
+
:right-icon="getElementDisabled(ele) ? '' : 'arrow'"
|
|
147
|
+
input-align="right"
|
|
148
|
+
border
|
|
149
|
+
:data-stat-id="`product_insurance_${ele.key}`"
|
|
150
|
+
@change="emitChange(ele)"
|
|
151
|
+
/>
|
|
152
|
+
|
|
153
|
+
<div :key="`${ins.key}${ele.key}_note`" v-if="ele.note" class="bxt-form-item-label-note">
|
|
154
|
+
{{ ele.note }}
|
|
155
|
+
</div>
|
|
156
|
+
</template>
|
|
157
|
+
</template>
|
|
158
|
+
</van-form>
|
|
159
|
+
</template>
|
|
160
|
+
<script lang="ts">
|
|
161
|
+
import Vue from 'vue'
|
|
162
|
+
import { Component, Prop } from 'vue-property-decorator'
|
|
163
|
+
import { get as _get } from 'lodash'
|
|
164
|
+
import { convertEleOrderListToObj } from 'packages/bxs-utils/index'
|
|
165
|
+
import CommonTitle from '../../../src/components/common/common-title.vue'
|
|
166
|
+
import CommonRadio from '../../../src/components/common/common-radio.vue'
|
|
167
|
+
import CommonSelect from '../../../src/components/common/common-select.vue'
|
|
168
|
+
|
|
169
|
+
@Component({
|
|
170
|
+
name: 'ProductInsuranceForm',
|
|
171
|
+
components: {
|
|
172
|
+
CommonTitle,
|
|
173
|
+
CommonRadio,
|
|
174
|
+
CommonSelect
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
export default class ProductInsuranceForm extends Vue {
|
|
178
|
+
activeInputKey = ''
|
|
179
|
+
numberUnitStr = ''
|
|
180
|
+
|
|
181
|
+
@Prop({ required: true })
|
|
182
|
+
ins!: any
|
|
183
|
+
|
|
184
|
+
/** 险种表单场景:normal 普通险 | groupSub 组合子险 */
|
|
185
|
+
@Prop({ default: 'normal' })
|
|
186
|
+
insMode!: string
|
|
187
|
+
|
|
188
|
+
@Prop({ default: null })
|
|
189
|
+
productKey!: number | string
|
|
190
|
+
|
|
191
|
+
@Prop({ default: () => [] })
|
|
192
|
+
mulInsOrderList!: any[]
|
|
193
|
+
|
|
194
|
+
@Prop({ default: () => ({}) })
|
|
195
|
+
personData!: any
|
|
196
|
+
|
|
197
|
+
@Prop({ default: () => ({}) })
|
|
198
|
+
recommendValues!: any
|
|
199
|
+
|
|
200
|
+
@Prop({ default: () => ({}) })
|
|
201
|
+
insuranceSaleStatus!: any
|
|
202
|
+
|
|
203
|
+
@Prop({ default: false })
|
|
204
|
+
showHuomianTips!: boolean
|
|
205
|
+
|
|
206
|
+
@Prop({ default: false })
|
|
207
|
+
isFollow!: boolean
|
|
208
|
+
|
|
209
|
+
/** 组合险 locked:其他子险 title 不可点 */
|
|
210
|
+
@Prop({ default: false })
|
|
211
|
+
lockTitleClick!: boolean
|
|
212
|
+
|
|
213
|
+
get isGroupSub() {
|
|
214
|
+
return this.insMode === 'groupSub'
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
get formClassList() {
|
|
218
|
+
return [
|
|
219
|
+
'bxt-product-info-form',
|
|
220
|
+
`bxt-product-insurance-id-${this.ins.key}`,
|
|
221
|
+
this.isGroupSub ? 'bxt-product-group-sub' : '',
|
|
222
|
+
this.isGroupSub ? 'bxt-product-insurance-type-group' : '',
|
|
223
|
+
this.isFollow ? 'bxt-product-info-form-follow' : ''
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
get isInsuranceChecked() {
|
|
228
|
+
const titleEle = (this.ins.eleOrderList || []).find(e => e.key === 'title')
|
|
229
|
+
return this.ins.key === 'common' || (!!titleEle && titleEle.value)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
validate() {
|
|
233
|
+
const form: any = this.$refs.insuranceForm
|
|
234
|
+
return form && form.validate ? form.validate() : Promise.resolve()
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
emitChange(ele) {
|
|
238
|
+
this.$emit('change', { insData: this.ins, eleData: ele })
|
|
239
|
+
}
|
|
240
|
+
onTitleChange(ele) {
|
|
241
|
+
if (this.isGroupSub) {
|
|
242
|
+
this.$emit('title-change', { insData: this.ins, eleData: ele })
|
|
243
|
+
} else {
|
|
244
|
+
this.emitChange(ele)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
onClickIcon(id) {
|
|
248
|
+
const inputDom: any = document.querySelector(`#${id}`)
|
|
249
|
+
if (inputDom) {
|
|
250
|
+
inputDom.focus()
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
closeKeyBoard() {
|
|
254
|
+
const activeElement: any = document.activeElement
|
|
255
|
+
if (!activeElement) {
|
|
256
|
+
return false
|
|
257
|
+
}
|
|
258
|
+
activeElement.blur()
|
|
259
|
+
return false
|
|
260
|
+
}
|
|
261
|
+
getElementRules(ele) {
|
|
262
|
+
let _rules = ele.rules || []
|
|
263
|
+
if (ele.isIgnoreValidate) {
|
|
264
|
+
_rules = []
|
|
265
|
+
}
|
|
266
|
+
return _rules
|
|
267
|
+
}
|
|
268
|
+
getElementDisabled(ele) {
|
|
269
|
+
if (ele.key === 'title' && this.lockTitleClick) {
|
|
270
|
+
return true
|
|
271
|
+
}
|
|
272
|
+
const opts = (ele.opts || []).filter(o => !o.isHide && !o.isDisabled && !o.isInvalid)
|
|
273
|
+
return ele.isDisabled || (opts.length === 1 && _get(opts, '[0].val') === ele.value)
|
|
274
|
+
}
|
|
275
|
+
genInsuranceHmTag(opt) {
|
|
276
|
+
const refInsurance = (this.mulInsOrderList || []).find(ins => ins.key === opt.val)
|
|
277
|
+
if (!refInsurance || !refInsurance.huomian) {
|
|
278
|
+
return ''
|
|
279
|
+
}
|
|
280
|
+
if (refInsurance.huomian === 'beiHuomian') {
|
|
281
|
+
return '被保人'
|
|
282
|
+
}
|
|
283
|
+
return '投保人'
|
|
284
|
+
}
|
|
285
|
+
getInsuranceTitleHmTag(insurance) {
|
|
286
|
+
if (!insurance.huomian) {
|
|
287
|
+
return ''
|
|
288
|
+
}
|
|
289
|
+
if (insurance.huomian === 'beiHuomian') {
|
|
290
|
+
return '被保人'
|
|
291
|
+
}
|
|
292
|
+
return '投保人'
|
|
293
|
+
}
|
|
294
|
+
getInsuranceSaleStatusTagByKey(key: string | number) {
|
|
295
|
+
const map = this.insuranceSaleStatus
|
|
296
|
+
if (!map || typeof map !== 'object' || key === undefined || key === null) {
|
|
297
|
+
return ''
|
|
298
|
+
}
|
|
299
|
+
const status = map[key] ?? map[String(key)]
|
|
300
|
+
if (status === undefined || status === null) {
|
|
301
|
+
return ''
|
|
302
|
+
}
|
|
303
|
+
return Number(status) === 2 ? '停' : ''
|
|
304
|
+
}
|
|
305
|
+
getInsuranceSaleStatusTag(insurance) {
|
|
306
|
+
return this.getInsuranceSaleStatusTagByKey(insurance.key)
|
|
307
|
+
}
|
|
308
|
+
getHuomianTips(insurance, element) {
|
|
309
|
+
const personOrderList = _get(this.personData, 'personOrderList') || []
|
|
310
|
+
const applicationInfo = personOrderList.find(p => p.key === 'applicantInfo')
|
|
311
|
+
const applicationTitle = _get(applicationInfo, 'eleOrderList', []).find(e => e.key === 'title')
|
|
312
|
+
const applicationSame = _get(applicationInfo, 'eleOrderList', []).find(e => e.key === 'applicantAndInsuredSame')
|
|
313
|
+
if (!(['touHuomian', 'shuangHuomian'].includes(insurance.huomian) && element.isDisabled)) {
|
|
314
|
+
return ''
|
|
315
|
+
}
|
|
316
|
+
if (!_get(applicationTitle, 'value')) {
|
|
317
|
+
return '<em>设置</em>投保人信息后选择'
|
|
318
|
+
}
|
|
319
|
+
if (_get(applicationSame, 'value') && !insurance.allowSamePerson) {
|
|
320
|
+
return '投被保人为同一人,<em>修改</em>投保人信息后选择'
|
|
321
|
+
}
|
|
322
|
+
return '当前投保人不能加该险种,<em>修改</em>投保人信息后选择'
|
|
323
|
+
}
|
|
324
|
+
getAmountUnit(ele) {
|
|
325
|
+
let digits = isNaN(ele.value * 1) ? 0 : Math.floor(Math.log10(ele.value) + 1)
|
|
326
|
+
switch (digits) {
|
|
327
|
+
case 5:
|
|
328
|
+
return '万'
|
|
329
|
+
case 6:
|
|
330
|
+
return '十万'
|
|
331
|
+
case 7:
|
|
332
|
+
return '百万'
|
|
333
|
+
case 8:
|
|
334
|
+
return '千万'
|
|
335
|
+
case 9:
|
|
336
|
+
return '亿'
|
|
337
|
+
default:
|
|
338
|
+
return ''
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
getRecommendValues(ele) {
|
|
342
|
+
if (!['baoe', 'baof'].includes(ele.key) || ele.isDisabled) {
|
|
343
|
+
return null
|
|
344
|
+
}
|
|
345
|
+
const insurance = convertEleOrderListToObj(this.ins)
|
|
346
|
+
return this.recommendValues && this.recommendValues[insurance.key]
|
|
347
|
+
}
|
|
348
|
+
onClickRecommendValue(value, ele) {
|
|
349
|
+
ele.value = value
|
|
350
|
+
this.emitChange(ele)
|
|
351
|
+
this.$nextTick(() => {
|
|
352
|
+
const ref: any = this.$refs[this.ins.key + ele.key + 'item']
|
|
353
|
+
const ref0 = Array.isArray(ref) ? ref[0] : ref
|
|
354
|
+
if (ref0 && ref0.validate) {
|
|
355
|
+
ref0.validate()
|
|
356
|
+
}
|
|
357
|
+
})
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
</script>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
<script lang="ts">
|
|
7
7
|
import Vue from 'vue'
|
|
8
8
|
import { Component } from 'vue-property-decorator'
|
|
9
|
+
import { Toast } from 'vant'
|
|
9
10
|
import QS from 'qs'
|
|
10
11
|
import { getPlanbookData } from '../../../src/api/planbook.js'
|
|
11
12
|
import { get as _get } from 'lodash'
|
|
@@ -24,9 +25,6 @@ export default class ProductInfoDemo extends Vue {
|
|
|
24
25
|
groupKey = null
|
|
25
26
|
productKey = null
|
|
26
27
|
created() {
|
|
27
|
-
if (!this.URL_PARAM.publicPbUuid) {
|
|
28
|
-
this.URL_PARAM.publicPbUuid = '5d6499946bbb47bb8f6a286e9d4eee77'
|
|
29
|
-
}
|
|
30
28
|
document.body.style.backgroundColor = '#f2f2f2'
|
|
31
29
|
this.getPlanbookData()
|
|
32
30
|
}
|
|
@@ -35,7 +33,8 @@ export default class ProductInfoDemo extends Vue {
|
|
|
35
33
|
}
|
|
36
34
|
getPlanbookData() {
|
|
37
35
|
getPlanbookData({
|
|
38
|
-
|
|
36
|
+
insuranceTypeId: this.URL_PARAM.planbookId || 13767,
|
|
37
|
+
resultUuid: this.URL_PARAM.uuid
|
|
39
38
|
})
|
|
40
39
|
.then(async (data: any) => {
|
|
41
40
|
await initPageData(data)
|
|
@@ -58,7 +57,7 @@ export default class ProductInfoDemo extends Vue {
|
|
|
58
57
|
}
|
|
59
58
|
cgProduct(product, obj, inst) {
|
|
60
59
|
if (obj.type === 'change') {
|
|
61
|
-
|
|
60
|
+
Toast(`${_get(obj, 'insData.eleOrderList[0].labelName')} -> ${_get(obj, 'eleData.labelName')}: ${_get(obj, 'eleData.value')}`)
|
|
62
61
|
}
|
|
63
62
|
}
|
|
64
63
|
}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* product-info 辅助
|
|
3
|
+
* - 组合险 UI 状态(不进产品数据 / 试算)
|
|
4
|
+
* - 推荐保额保费、自定义结果元素
|
|
5
|
+
*/
|
|
6
|
+
import { get as _get } from 'lodash'
|
|
7
|
+
import { initElementValidateRules } from 'packages/bxs-utils/index'
|
|
8
|
+
import { createdProductDataToCalc } from 'packages/planbook-input/helper.js'
|
|
9
|
+
import { getPlanbookRecommendData } from '../../src/api/planbook.js'
|
|
10
|
+
|
|
11
|
+
export function getTitleEle(ins) {
|
|
12
|
+
return (ins.eleOrderList || []).find(e => e.key === 'title')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isTitleChecked(ins) {
|
|
16
|
+
const t = getTitleEle(ins)
|
|
17
|
+
return !!(t && t.value)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function isTitleEnabled(ins) {
|
|
21
|
+
const t = getTitleEle(ins)
|
|
22
|
+
return !!(t && !t.isDisabled)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** title 已选中且不可改(锁定勾选) */
|
|
26
|
+
export function isTitleLockedChecked(ins) {
|
|
27
|
+
const t = getTitleEle(ins)
|
|
28
|
+
return !!(t && t.value === true && t.isDisabled === true)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function getCheckedIds(siblings) {
|
|
32
|
+
return siblings.filter(isTitleChecked).map(s => s.key)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isCheckboxGroup(siblings) {
|
|
36
|
+
return siblings.some(s => !!s.isCheckbox)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** 非 checkbox:多个选中时只保留第一个 */
|
|
40
|
+
export function enforceSingleSelect(siblings) {
|
|
41
|
+
if (isCheckboxGroup(siblings)) {
|
|
42
|
+
return
|
|
43
|
+
}
|
|
44
|
+
const checked = siblings.filter(isTitleChecked)
|
|
45
|
+
if (checked.length <= 1) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
const keepKey = checked[0].key
|
|
49
|
+
checked.forEach(s => {
|
|
50
|
+
if (s.key !== keepKey) {
|
|
51
|
+
const t = getTitleEle(s)
|
|
52
|
+
if (t) {
|
|
53
|
+
t.value = false
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function setAllTitles(siblings, value) {
|
|
60
|
+
siblings.forEach(s => {
|
|
61
|
+
const t = getTitleEle(s)
|
|
62
|
+
if (t) {
|
|
63
|
+
t.value = value
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** 快照:组合子险 title 是否可选、是否选中 */
|
|
69
|
+
export function snapshotGroupTitleEnabledMap(list) {
|
|
70
|
+
const map = {}
|
|
71
|
+
const insuranceList = list || []
|
|
72
|
+
insuranceList.forEach(ins => {
|
|
73
|
+
if (!ins.groupKey) {
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
const t = getTitleEle(ins)
|
|
77
|
+
if (t) {
|
|
78
|
+
map[ins.key] = {
|
|
79
|
+
enabled: !t.isDisabled,
|
|
80
|
+
checked: !!t.value
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
})
|
|
84
|
+
return map
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 找出「原先选中 → 现在不可选」的组合子险名称(用于 Toast)
|
|
89
|
+
* 未选中的子险变为不可选时不提示
|
|
90
|
+
*/
|
|
91
|
+
export function getGroupSubsBecameUnselectable(list, prevSnapshotMap) {
|
|
92
|
+
const names = []
|
|
93
|
+
const insuranceList = list || []
|
|
94
|
+
insuranceList.forEach(ins => {
|
|
95
|
+
const prev = prevSnapshotMap && prevSnapshotMap[ins.key]
|
|
96
|
+
const wasChecked = !!(prev && prev.checked)
|
|
97
|
+
if (!ins.groupKey || !wasChecked) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
const t = getTitleEle(ins)
|
|
101
|
+
if (t && t.isDisabled && !t.value) {
|
|
102
|
+
names.push(t.labelName || ins.name || String(ins.key))
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
return names
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** 按 id 列表写 title;disabled 的不会勾上 */
|
|
109
|
+
export function applySelectedIds(siblings, selectedIds) {
|
|
110
|
+
const idSet = new Set((selectedIds || []).map(String))
|
|
111
|
+
siblings.forEach(s => {
|
|
112
|
+
const t = getTitleEle(s)
|
|
113
|
+
if (!t) {
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
t.value = idSet.has(String(s.key)) && !t.isDisabled
|
|
117
|
+
})
|
|
118
|
+
return getCheckedIds(siblings)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 按 mulInsOrderList 首次出现顺序构建 groupUiState Map
|
|
123
|
+
* - 若有 title.value===true 且 isDisabled===true:active=true,locked=true,selectedIds 取第一个该险种 id
|
|
124
|
+
* locked:组开关开启且不可关,其他子险 title 不可点
|
|
125
|
+
* - 否则 selectedIds:优先用当前 title 选中;否则回退 prev,并剔除已 disabled 的 id
|
|
126
|
+
*/
|
|
127
|
+
export function buildGroupUiState(list, prevMap, options = {}) {
|
|
128
|
+
const { isInit } = options
|
|
129
|
+
const next = new Map()
|
|
130
|
+
const insuranceList = (list || []).filter(ins => ins.groupKey)
|
|
131
|
+
insuranceList.forEach(ins => {
|
|
132
|
+
const gk = String(ins.groupKey)
|
|
133
|
+
if (next.has(gk)) {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
const siblings = insuranceList.filter(i => String(i.groupKey) === gk)
|
|
137
|
+
const lockedChecked = siblings.find(isTitleLockedChecked)
|
|
138
|
+
if (lockedChecked) {
|
|
139
|
+
next.set(gk, {
|
|
140
|
+
active: true,
|
|
141
|
+
locked: true,
|
|
142
|
+
selectedIds: [lockedChecked.key],
|
|
143
|
+
groupName: ins.groupName
|
|
144
|
+
})
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
enforceSingleSelect(siblings)
|
|
148
|
+
|
|
149
|
+
const enabled = siblings.filter(isTitleEnabled)
|
|
150
|
+
const enabledKeySet = new Set(enabled.map(s => String(s.key)))
|
|
151
|
+
const pickEnabledIds = ids => (ids || []).filter(id => enabledKeySet.has(String(id)))
|
|
152
|
+
|
|
153
|
+
const selectedFromTitle = pickEnabledIds(getCheckedIds(siblings))
|
|
154
|
+
const prev = prevMap && prevMap.get(gk)
|
|
155
|
+
const allDisabled = enabled.length === 0
|
|
156
|
+
|
|
157
|
+
let active = false
|
|
158
|
+
if (allDisabled) {
|
|
159
|
+
active = false
|
|
160
|
+
} else if (isInit || !prev) {
|
|
161
|
+
active = selectedFromTitle.length > 0
|
|
162
|
+
} else {
|
|
163
|
+
active = prev.active || selectedFromTitle.length > 0
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const selectedIds = selectedFromTitle.length > 0 ? selectedFromTitle : pickEnabledIds(prev && Array.isArray(prev.selectedIds) ? prev.selectedIds : [])
|
|
167
|
+
|
|
168
|
+
next.set(gk, {
|
|
169
|
+
active,
|
|
170
|
+
locked: false,
|
|
171
|
+
selectedIds,
|
|
172
|
+
groupName: ins.groupName
|
|
173
|
+
})
|
|
174
|
+
})
|
|
175
|
+
return next
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** 普通险在前,组合险在后(组序 = groupKey 首次出现) */
|
|
179
|
+
export function buildDisplayBlocks(list, groupUiState, normalizeIns) {
|
|
180
|
+
const normals = []
|
|
181
|
+
const groups = []
|
|
182
|
+
const visited = new Set()
|
|
183
|
+
const insuranceList = list || []
|
|
184
|
+
insuranceList.forEach(ins => {
|
|
185
|
+
if (!ins.groupKey) {
|
|
186
|
+
normalizeIns && normalizeIns(ins)
|
|
187
|
+
normals.push({ type: 'normal', ins })
|
|
188
|
+
return
|
|
189
|
+
}
|
|
190
|
+
const gk = String(ins.groupKey)
|
|
191
|
+
if (visited.has(gk)) {
|
|
192
|
+
return
|
|
193
|
+
}
|
|
194
|
+
visited.add(gk)
|
|
195
|
+
const insList = insuranceList.filter(i => String(i.groupKey) === gk)
|
|
196
|
+
insList.forEach(i => normalizeIns && normalizeIns(i))
|
|
197
|
+
const state = groupUiState && groupUiState.get(gk)
|
|
198
|
+
groups.push({
|
|
199
|
+
type: 'group',
|
|
200
|
+
groupKey: gk,
|
|
201
|
+
groupName: (state && state.groupName) || ins.groupName || '',
|
|
202
|
+
insList
|
|
203
|
+
})
|
|
204
|
+
})
|
|
205
|
+
return normals.concat(groups)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 拉取并过滤推荐保额/保费(读写共用传入的 cache 对象)
|
|
210
|
+
* @returns {Promise<{ recommendValues: object, cacheKey: string, fromCache?: boolean } | null>}
|
|
211
|
+
*/
|
|
212
|
+
export async function fetchRecommendValues({ inputData, groupKey, productKey, productData, cache }) {
|
|
213
|
+
const requestDataToCalc = await createdProductDataToCalc(inputData, { groupKey, productKey }).catch(() => null)
|
|
214
|
+
if (!_get(requestDataToCalc, 'jd')) {
|
|
215
|
+
return null
|
|
216
|
+
}
|
|
217
|
+
const inputDataToCalc = JSON.parse(requestDataToCalc.jd)
|
|
218
|
+
const calcList = _get(inputDataToCalc, 'productGroupList[0].prodOrderList[0].mulInsOrderList') || []
|
|
219
|
+
const reqParams = calcList.map(ins => ({
|
|
220
|
+
insuranceId: ins.key,
|
|
221
|
+
period: ins.pPeriod,
|
|
222
|
+
calMethod: ins.calMethod || ins.feeType || ins.feeBaseType
|
|
223
|
+
}))
|
|
224
|
+
const cacheKey = JSON.stringify(reqParams)
|
|
225
|
+
if (cache && cache[cacheKey]) {
|
|
226
|
+
return { recommendValues: cache[cacheKey], fromCache: true, cacheKey }
|
|
227
|
+
}
|
|
228
|
+
const data = await getPlanbookRecommendData(reqParams)
|
|
229
|
+
const recommendValues = (data || []).reduce((obj, ele) => Object.assign(obj, { [ele.insuranceId]: ele.valueList }), {})
|
|
230
|
+
const mulInsOrderList = _get(productData, 'mulInsOrderList') || []
|
|
231
|
+
mulInsOrderList
|
|
232
|
+
.filter(ins => ins.eleOrderList && recommendValues[ins.key])
|
|
233
|
+
.forEach(ins => {
|
|
234
|
+
const calMethod = ins.calMethod || ins.feeType || ins.feeBaseType
|
|
235
|
+
const key = calMethod === 'baof2baoe' ? 'baof' : 'baoe'
|
|
236
|
+
const ele = ins.eleOrderList.find(e => e.key === key)
|
|
237
|
+
if (!ele) {
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
if (ele.min && !isNaN(Number(ele.min))) {
|
|
241
|
+
recommendValues[ins.key] = (recommendValues[ins.key] || []).filter(v => v >= ele.min)
|
|
242
|
+
}
|
|
243
|
+
if (ele.max && !isNaN(Number(ele.max))) {
|
|
244
|
+
recommendValues[ins.key] = (recommendValues[ins.key] || []).filter(v => v <= ele.max)
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
if (cache) {
|
|
248
|
+
cache[cacheKey] = recommendValues
|
|
249
|
+
}
|
|
250
|
+
return { recommendValues, cacheKey, fromCache: false }
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* 为选中险种写入/更新自定义保费 inputResult;未选中则清掉元素(值回写到 ins.inputResult)
|
|
255
|
+
*/
|
|
256
|
+
export function createInsuranceInputResultEle(productData, options = {}) {
|
|
257
|
+
const { allowCustomResult, insData, eleData } = options
|
|
258
|
+
const list = _get(productData, 'mulInsOrderList')
|
|
259
|
+
if (allowCustomResult && list) {
|
|
260
|
+
list.forEach(ins => {
|
|
261
|
+
const isCommon = ins.key === 'common'
|
|
262
|
+
const checked = isTitleChecked(ins)
|
|
263
|
+
const isCurrentIns = !!(insData && eleData && insData.key === ins.key)
|
|
264
|
+
const shouldSkipUpdate = isCurrentIns && eleData.key !== 'calMethod'
|
|
265
|
+
const shouldClear = !isCommon && !checked
|
|
266
|
+
const shouldWrite = !isCommon && checked && !shouldSkipUpdate
|
|
267
|
+
const eleOrderList = _get(ins, 'eleOrderList') || []
|
|
268
|
+
const existingInputResult = eleOrderList.find(e => e.key === 'inputResult')
|
|
269
|
+
const existingInputResultValue = existingInputResult ? existingInputResult.value : null
|
|
270
|
+
|
|
271
|
+
if (shouldClear) {
|
|
272
|
+
if (existingInputResult) {
|
|
273
|
+
ins.inputResult = existingInputResultValue
|
|
274
|
+
}
|
|
275
|
+
ins.eleOrderList = eleOrderList.filter(e => e.key !== 'inputResult')
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (shouldWrite) {
|
|
279
|
+
const calMethod = eleOrderList.find(e => e.key === 'calMethod')
|
|
280
|
+
const baof = eleOrderList.find(e => e.key === 'baof') || eleOrderList.find(e => e.key === 'payModePremium')
|
|
281
|
+
const labelName = calMethod ? (calMethod.value === 'baof2baoe' ? '保额' : '保费') : baof ? '保额' : '保费'
|
|
282
|
+
let value = existingInputResult ? ins.inputResult : ins.inputResult === undefined ? null : ins.inputResult
|
|
283
|
+
if (isCurrentIns && eleData.key === 'inputResult') {
|
|
284
|
+
value = eleData.value
|
|
285
|
+
}
|
|
286
|
+
const inputResult = {
|
|
287
|
+
componentName: 'cmCommonInput',
|
|
288
|
+
placeholder: `按照保单填写${labelName}`,
|
|
289
|
+
isHide: !productData.inputResultSwitch,
|
|
290
|
+
key: 'inputResult',
|
|
291
|
+
labelName: `自定义${labelName}`,
|
|
292
|
+
inputType: 'text',
|
|
293
|
+
required: false,
|
|
294
|
+
regExp: '/^\\d{1,}(\\.\\d{1,2})?$/',
|
|
295
|
+
regExpMessage: '请输入1-2位小数的值',
|
|
296
|
+
value
|
|
297
|
+
}
|
|
298
|
+
inputResult.rules = initElementValidateRules(inputResult)
|
|
299
|
+
delete ins.inputResult
|
|
300
|
+
ins.eleOrderList = eleOrderList.filter(e => e.key !== 'inputResult')
|
|
301
|
+
if (productData.inputResultSwitch) {
|
|
302
|
+
ins.eleOrderList.push(inputResult)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
}
|