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.
Files changed (56) hide show
  1. package/es/add-and-take/index.js +1 -7969
  2. package/es/adjust-baoe/index.js +197 -8192
  3. package/es/index.css +1 -1
  4. package/es/index.js +8788 -43737
  5. package/es/insure-calculate/index.css +1 -1
  6. package/es/insure-calculate/index.js +1046 -36665
  7. package/es/person-info/index.css +1 -1
  8. package/es/person-info/index.js +83 -8042
  9. package/es/product-info/index.css +1 -1
  10. package/es/product-info/index.js +3006 -10612
  11. package/es/share-sheet/index.js +69 -8040
  12. package/es/utils/index.js +1250 -9334
  13. package/lib/add-and-take/index.js +4 -7973
  14. package/lib/adjust-baoe/index.js +196 -8192
  15. package/lib/index.css +1 -1
  16. package/lib/index.js +8717 -43671
  17. package/lib/insure-calculate/index.css +1 -1
  18. package/lib/insure-calculate/index.js +1034 -36662
  19. package/lib/person-info/index.css +1 -1
  20. package/lib/person-info/index.js +86 -8046
  21. package/lib/product-info/index.css +1 -1
  22. package/lib/product-info/index.js +2807 -10414
  23. package/lib/share-sheet/index.js +72 -8044
  24. package/lib/utils/index.js +1252 -9337
  25. package/package.json +5 -3
  26. package/packages/adjust-baoe/index.vue +2 -9
  27. package/packages/bxs-utils/planbook/common.ts +5 -0
  28. package/packages/bxs-utils/planbook/insurance.ts +19 -0
  29. package/packages/bxs-utils/planbook/person.ts +3 -2
  30. package/packages/bxs-utils/planbook/product.ts +57 -164
  31. package/packages/bxs-utils/readme.md +3 -1
  32. package/packages/index.ts +1 -1
  33. package/packages/insure-calculate/demo/index.vue +1 -1
  34. package/packages/insure-calculate/index.vue +18 -17
  35. package/packages/planbook-input/components/product-table.vue +3 -13
  36. package/packages/planbook-input/helper.js +4 -26
  37. package/packages/product-info/components/product-insurance-form.md +46 -0
  38. package/packages/product-info/components/product-insurance-form.vue +360 -0
  39. package/packages/product-info/demo/index.vue +2 -1
  40. package/packages/product-info/handler.js +307 -0
  41. package/packages/product-info/handler.md +26 -0
  42. package/packages/product-info/index.less +33 -0
  43. package/packages/product-info/index.vue +306 -532
  44. package/packages/product-info/readme.md +7 -1
  45. package/packages/share-sheet/constant.js +1 -2
  46. package/src/api/trade.js +31 -0
  47. package/src/components/common/common-group-title.less +54 -0
  48. package/src/components/common/common-group-title.md +34 -0
  49. package/src/components/common/common-group-title.vue +72 -0
  50. package/src/components/common/common-title.less +4 -0
  51. package/src/components/common/common-title.vue +8 -2
  52. package/src/components/profession-list/README.md +114 -0
  53. package/src/components/profession-list/constant.js +4 -0
  54. package/src/components/profession-list/handler.js +155 -0
  55. package/src/components/profession-list/index.less +182 -0
  56. 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;