bxs-tools-ui 3.3.3 → 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 +197 -8192
- package/es/index.css +1 -1
- package/es/index.js +8788 -43737
- 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 +3006 -10612
- 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 +196 -8192
- package/lib/index.css +1 -1
- package/lib/index.js +8717 -43671
- 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 -10414
- package/lib/share-sheet/index.js +72 -8044
- package/lib/utils/index.js +1252 -9337
- package/package.json +5 -3
- package/packages/adjust-baoe/index.vue +2 -9
- 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/planbook-input/components/product-table.vue +3 -13
- package/packages/planbook-input/helper.js +4 -26
- 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 +2 -1
- 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 -532
- package/packages/product-info/readme.md +7 -1
- package/packages/share-sheet/constant.js +1 -2
- 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,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
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# handler.js
|
|
2
|
+
|
|
3
|
+
`product-info` 辅助函数。组合险 UI 状态**不写入**产品数据 / 试算 jd。
|
|
4
|
+
|
|
5
|
+
## 组合险
|
|
6
|
+
|
|
7
|
+
| 函数 | 说明 |
|
|
8
|
+
|------|------|
|
|
9
|
+
| `isTitleEnabled` | title 可选(`!isDisabled`) |
|
|
10
|
+
| `isTitleLockedChecked` | title 已选中且不可改(`value===true` 且 `isDisabled===true`) |
|
|
11
|
+
| `buildGroupUiState` | 按 `groupKey` 首次出现建 `Map`;有锁定勾选则 `active=true`、`locked=true`、`selectedIds` 取第一个(组开关不可关、其他子险不可点);否则非 checkbox 强制单选,派生 `active` / `selectedIds`(剔除已 disabled) |
|
|
12
|
+
| `buildDisplayBlocks` | 普通险在前,组合险在后 |
|
|
13
|
+
| `enforceSingleSelect` | 非 checkbox:多选中时只留第一个 |
|
|
14
|
+
| `applySelectedIds` / `setAllTitles` / `getCheckedIds` | 读写子险 `title` |
|
|
15
|
+
| `snapshotGroupTitleEnabledMap` / `getGroupSubsBecameUnselectable` | 对比承保处理后,哪些**原先已选中**的组合子险变为不可选(未选中的不 Toast) |
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
Map<groupKey, { active: boolean, locked: boolean, selectedIds: Array<id>, groupName?: string }>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 其它
|
|
22
|
+
|
|
23
|
+
| 函数 | 说明 |
|
|
24
|
+
|------|------|
|
|
25
|
+
| `fetchRecommendValues` | 组装试算参数、请求推荐保额/保费并按 min/max 过滤;读写共用传入的 `cache` |
|
|
26
|
+
| `createInsuranceInputResultEle` | 仅对**选中**险种写入 `inputResult`;未选中清掉元素,值回写 `ins.inputResult` |
|
|
@@ -38,6 +38,39 @@
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
& .bxt-product-group {
|
|
42
|
+
margin-bottom: 9px;
|
|
43
|
+
padding-top: 9px;
|
|
44
|
+
background: white;
|
|
45
|
+
border-radius: 6px;
|
|
46
|
+
|
|
47
|
+
& .bxt-product-group-header {
|
|
48
|
+
margin-bottom: 0;
|
|
49
|
+
border-bottom-left-radius: 0;
|
|
50
|
+
border-bottom-right-radius: 0;
|
|
51
|
+
padding: 0 15px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
& .bxt-product-group-sub {
|
|
55
|
+
margin-bottom: 0;
|
|
56
|
+
border-radius: 0;
|
|
57
|
+
|
|
58
|
+
&:last-child {
|
|
59
|
+
margin-bottom: 0;
|
|
60
|
+
border-bottom-left-radius: 6px;
|
|
61
|
+
border-bottom-right-radius: 6px;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
& .bxt-product-insurance-type-group .bxt-item-title::before {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
&:last-child {
|
|
70
|
+
margin-bottom: 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
41
74
|
& .bxt-product-info-form {
|
|
42
75
|
background: white;
|
|
43
76
|
margin-bottom: 9px;
|