bxs-tools-ui 1.1.1 → 1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bxs-tools-ui",
3
- "version": "1.1.1",
3
+ "version": "1.2.0-0",
4
4
  "description": "微易前端业务组件",
5
5
  "main": "lib/index.js",
6
6
  "files": [
@@ -1,12 +1,27 @@
1
+ export const IS_PRODUCT_ENV = location.hostname.search(/winbaoxian\.com/) !== -1;
2
+
1
3
  export const PURPOSE_OPTIONS = [
2
4
  { val: '高中教育金', desc: '高中教育金' },
3
5
  { val: '大学教育金', desc: '大学教育金' },
4
6
  { val: '婚嫁金', desc: '婚嫁金' },
5
7
  { val: '子女教育金', desc: '子女教育金' },
6
8
  { val: '养老金', desc: '养老金' },
7
- { val: '', desc: '自己填写' }
9
+ { val: '', desc: '自定义' }
8
10
  ];
9
11
 
10
12
  export const AAT_FORM_RULES = {
11
13
  baof: [{ type: 'number', required: true, message: '请输入金额' }]
12
14
  };
15
+
16
+ export const NONEED_PROD_KEYS = ['hadChoice', 'hide', 'totalBaof', 'insShowArr', 'autoImport', 'adjustBaoeData'];
17
+
18
+ export const NONEED_INS_KEYS = [
19
+ 'isFollowing',
20
+ 'pPeriodDesc',
21
+ 'baoeDesc',
22
+ 'baofDesc',
23
+ 'iDurationDesc',
24
+ 'isCheckbox',
25
+ 'groupKey',
26
+ 'groupName'
27
+ ];
@@ -1,3 +1,26 @@
1
+ export function initAddAndTakeData(data) {
2
+ if (!data) {
3
+ return data;
4
+ }
5
+ for (const k in data) {
6
+ if (!data[k]) {
7
+ continue;
8
+ }
9
+ if (k === 'bonus') {
10
+ data[k].title = '分红';
11
+ }
12
+ if (k === 'rate') {
13
+ data[k].title = '账户利率';
14
+ if (data[k].opts) {
15
+ data[k].opts.forEach(o => {
16
+ o.description = getBonusDesc(o);
17
+ });
18
+ }
19
+ }
20
+ }
21
+ return data;
22
+ }
23
+
1
24
  export function getBonusDesc(option) {
2
25
  let desc = `${option.description}(${(option.value * 100).toFixed(2)}%)`;
3
26
  if (option.description.search(/\$/) !== -1) {
@@ -14,11 +37,11 @@ export function getBeginYearOpts(values, options = {}) {
14
37
  const maxLength = data.reduce((a, b) => Math.max(a, b.values.length), 0);
15
38
  let yearOptions = [];
16
39
  for (let i = 0; i < maxLength; i++) {
17
- const year = i + 1;
40
+ const year = i + startPolicyNo;
18
41
  if (year >= values.beginYear) {
19
42
  yearOptions.push({
20
43
  val: year,
21
- desc: `第${i + startPolicyNo}年,${age + year + startIndex}岁`
44
+ desc: `第${year}年,${age + startIndex + i + 1}岁`
22
45
  });
23
46
  }
24
47
  }
@@ -53,7 +76,7 @@ export function rebuildAccountData(values, accountData) {
53
76
 
54
77
  for (let k = values.beginYear; k <= values.endYear; k++) {
55
78
  const currentYear = adjustYears.find(year => year[0] === k);
56
- const purpose = values.customPurpose || values.purpose;
79
+ const purpose = values.purpose || values.customPurpose;
57
80
  if (currentYear) {
58
81
  currentYear[2] = values.baof;
59
82
  currentYear[3] = purpose;
@@ -78,14 +101,13 @@ export function rebuildAccountData(values, accountData) {
78
101
  return accountData;
79
102
  }
80
103
 
81
- export function getEnsureCanTakeAmount(values, initialData) {
82
- if (!values || !initialData) {
104
+ export function getEnsureCanTakeAmount(initialData, options = {}) {
105
+ if (!initialData || !options) {
83
106
  return 0;
84
107
  }
85
- const { beginYear, endYear } = values;
86
- const { data } = initialData;
87
- const rate = initialData.rate.opts[0].value + 1;
88
- const accountValue = data.find(ele => ele.key === 'account_value');
108
+ const { beginYear, endYear } = options;
109
+ const rate = options.rate + 1;
110
+ const accountValue = initialData.find(ele => ele.key === 'account_value');
89
111
  let ensureAmount = 0;
90
112
  if (beginYear && endYear && rate && accountValue && accountValue.values) {
91
113
  for (let k = beginYear; k <= endYear; k++) {
@@ -95,8 +117,8 @@ export function getEnsureCanTakeAmount(values, initialData) {
95
117
  }
96
118
 
97
119
  let numMaxlength = 0;
98
- if (data) {
99
- data.map(d => {
120
+ if (initialData) {
121
+ initialData.map(d => {
100
122
  if (d.key === 'account_value' && d.values && d.values.length) {
101
123
  numMaxlength = d.values.length;
102
124
  }
@@ -17,103 +17,119 @@
17
17
  border-radius: 6px;
18
18
 
19
19
  & .bxt-aat-bonus {
20
- & .bxt-aat-bonus-tips {
21
- font-size: 13px;
22
- }
20
+ margin-top: 12px;
21
+ font-size: 13px;
23
22
 
24
- & .bxt-aat-bonus-type {
25
- display: flex;
26
- padding: 15px 0;
27
-
28
- & li {
29
- flex: 1;
30
- margin-right: 10px;
31
- padding: 0 5px 0 10px;
32
- border: 1px solid var(--color-line-split);
33
- border-radius: 6px;
23
+ & li {
24
+ margin-right: 10px;
25
+ padding: 0 5px 0 10px;
26
+ border-radius: 6px;
34
27
 
35
- &:last-child {
36
- margin-right: 0;
37
- }
28
+ &:last-child {
29
+ margin-right: 0;
30
+ }
38
31
 
39
- & .bxt-item-select {
40
- & .bx-input {
41
- padding: 0;
32
+ & .bxt-aat-bonus-title {
33
+ margin-bottom: 12px;
34
+ color: #999;
35
+ }
42
36
 
43
- & .bx-input-body {
44
- padding: 7px 0;
37
+ & .bxt-aat-bonus-desc {
38
+ display: inline-block;
39
+ margin: 0 9px 15px 0;
40
+ padding: 3px 6px;
41
+ border-radius: 50px;
42
+ background: rgba(0, 0, 0, 0.04);
43
+ }
45
44
 
46
- & .bx-input-control {
47
- text-align: left;
48
- }
49
- }
50
- }
51
- }
45
+ & .bxt-aat-bonus-desc.active {
46
+ font-size: 13px;
47
+ color: #0a64fe;
48
+ background: #e6effe;
52
49
  }
53
50
  }
54
51
  }
55
52
 
56
53
  & .bxt-aat-table-content {
57
54
  width: 100%;
55
+ font-size: 0;
58
56
  color: var(--color-text-primary);
59
- text-align: center;
57
+ white-space: nowrap;
60
58
 
61
- & thead {
62
- font-size: 12px;
59
+ & .bxt-aat-table-content-left,
60
+ & .bxt-aat-table-content-right {
61
+ display: inline-block;
62
+ width: 25%;
63
+ font-size: 13px;
64
+ vertical-align: top;
65
+ text-align: left;
66
+
67
+ & .bxt-aat-table-content-record {
68
+ display: flex;
69
+ white-space: nowrap;
63
70
 
64
- & tr {
65
- & th {
71
+ & .bxt-aat-table-content-cell {
72
+ display: inline-block;
73
+ flex: 1;
74
+ min-width: 30%;
66
75
  padding: 12px 2px;
67
- margin-bottom: 5px;
68
- background: var(--color-bg-minor);
76
+ text-align: center;
77
+ overflow: hidden;
78
+ }
79
+ }
69
80
 
70
- &:nth-child(1),
71
- &:nth-child(2) {
72
- max-width: 24px;
73
- }
81
+ & .bxt-aat-table-content-record:nth-child(2n) {
82
+ & .bxt-aat-table-content-cell {
83
+ background: rgba(0, 0, 0, 0.02);
84
+ }
85
+ }
86
+
87
+ & .bxt-aat-table-content-record:nth-child(1) {
88
+ & .bxt-aat-table-content-cell {
89
+ padding: 6px 2px;
90
+ height: 33px;
91
+ line-height: 33px;
92
+ background: rgba(229, 229, 229, 1);
74
93
  }
75
94
  }
76
95
  }
77
96
 
78
- & tbody {
79
- font-size: 14px;
80
- color: var(--color-text-minor);
97
+ & .bxt-aat-table-content-left {
98
+ overflow: hidden;
81
99
 
82
- & tr {
83
- & td {
84
- position: relative;
85
- padding: 5px 2px;
100
+ & .bxt-aat-table-content-record {
101
+ & .bxt-aat-table-content-cell {
102
+ width: 50%;
103
+ }
104
+ }
105
+ }
86
106
 
87
- & span {
88
- display: block;
89
- padding: 7px 4px;
90
- }
107
+ & .bxt-aat-table-content-right {
108
+ width: 75%;
109
+ overflow: auto;
91
110
 
92
- & .icon-close_circle_surface {
93
- @apply --vertical-center;
111
+ & .bxt-aat-table-content-record {
112
+ & .bxt-aat-table-content-cell {
113
+ white-space: normal;
114
+ }
94
115
 
95
- right: 6px;
96
- color: var(--color-text-assist);
97
- font-size: 15px;
98
- }
116
+ & .bxt-aat-table-content-cell__zero {
117
+ color: #999;
118
+ }
99
119
 
100
- &:nth-child(1),
101
- &:nth-child(2) {
102
- width: 34px;
103
- }
120
+ & .bxt-aat-table-content-cell__purpose {
121
+ display: inline-block;
122
+ padding: 1px 3px;
123
+ color: rgba(10, 100, 254, 1);
124
+ background: rgba(10, 100, 254, 0.1);
125
+ transform: scale(0.8334);
126
+ transform-origin: left center;
127
+ }
128
+ }
104
129
 
105
- &.bxt-aat-table-cell-amount {
106
- & span {
107
- border: 1px solid var(--color-line-split);
108
- border-radius: 6px;
109
- color: var(--color-text-assist);
110
-
111
- &.value-unequal-zero {
112
- padding-right: 15px;
113
- color: var(--color-text-primary);
114
- }
115
- }
116
- }
130
+ & .bxt-aat-table-content-record:nth-child(1) {
131
+ & .bxt-aat-table-content-cell {
132
+ line-height: normal;
117
133
  }
118
134
  }
119
135
  }
@@ -121,26 +137,126 @@
121
137
  }
122
138
 
123
139
  & .bxt-aat-form {
140
+ font-size: 13px;
124
141
  background: white;
125
142
  border-radius: 6px;
126
143
 
127
144
  & .bxt-aat-form-items {
128
- margin-top: 9px;
145
+ padding: 15px 0;
129
146
 
130
147
  & .bx-form-item {
148
+ & .bxt-aat-form-item-title {
149
+ margin-bottom: 12px;
150
+ font-size: 13px;
151
+ color: #999;
152
+ }
153
+
131
154
  & .bx-input {
132
- & .bx-input-control {
133
- text-align: right;
155
+ width: 150px;
156
+ border: 1px solid #999;
157
+ border-radius: 50px;
158
+
159
+ & .bx-input-body {
160
+ padding: 4px 10px 4px 0;
161
+
162
+ & .bx-input-control {
163
+ height: 18px;
164
+ line-height: 18px;
165
+ }
134
166
  }
135
167
  }
136
168
  }
137
169
 
170
+ & .bx-form-item:not(:first-child) {
171
+ margin-top: 21px;
172
+ }
173
+
174
+ & .bx-form-item::after {
175
+ visibility: hidden;
176
+ }
177
+
178
+ & .bxt-aat-form-purpose {
179
+ & .bxt-aat-form-purpose-options {
180
+ font-size: 13px;
181
+
182
+ & .bxt-aat-form-purpose-option {
183
+ display: inline-block;
184
+ min-width: 50px;
185
+ margin: 0 6px 15px 0;
186
+ padding: 3px 6px;
187
+ text-align: center;
188
+ background: rgba(0, 0, 0, 0.04);
189
+ border-radius: 50px;
190
+ }
191
+
192
+ & .bxt-aat-form-purpose-option.active {
193
+ font-weight: bold;
194
+ color: rgba(10, 100, 254, 1);
195
+ background: rgba(230, 239, 254, 1);
196
+ }
197
+
198
+ & .bx-input {
199
+ display: inline-block;
200
+ width: 130px;
201
+ font-size: 13px;
202
+
203
+ & .bx-input-control {
204
+ height: 18px;
205
+ line-height: 18px;
206
+ }
207
+ }
208
+ }
209
+ }
210
+
211
+ & .bxt-aat-form-item-content {
212
+ display: flex;
213
+ font-size: 13px;
214
+
215
+ & .bxt-aat-form-item-select {
216
+ position: relative;
217
+ flex: 1;
218
+
219
+ & .bxt-aat-form-item-select__button {
220
+ display: inline-block;
221
+ width: 100%;
222
+ padding: 5px 12px 5px 6px;
223
+ border: 1px solid #999;
224
+ border-radius: 50px;
225
+ box-sizing: border-box;
226
+ text-align: center;
227
+
228
+ & .icon-arrows_right {
229
+ position: absolute;
230
+ top: 50%;
231
+ right: 9px;
232
+ transform: translateY(-50%);
233
+ font-size: 12px;
234
+ }
235
+ }
236
+ }
237
+
238
+ & .bxt-aat-form-item-symbol {
239
+ position: relative;
240
+ flex: 0 0 44px;
241
+ }
242
+
243
+ & .bxt-aat-form-item-symbol::after {
244
+ position: absolute;
245
+ top: 50%;
246
+ left: 50%;
247
+ transform: translate(-50%, -50%);
248
+ width: 50%;
249
+ height: 1px;
250
+ border-bottom: 1px solid #999;
251
+ content: ' ';
252
+ }
253
+ }
254
+
138
255
  & .bxt-aat-form-baof-tips {
139
- margin-bottom: 15px;
256
+ margin: 6px 0;
140
257
  line-height: 145%;
141
258
  color: var(--color-text-patch);
142
259
  font-size: 12px;
143
- text-align: right;
144
260
 
145
261
  & span {
146
262
  color: var(--color-primary);
@@ -1,96 +1,64 @@
1
1
  <template>
2
2
  <div
3
- v-if="initAddAndTakeData && initAddAndTakeData.data && initAddAndTakeData.data.length"
3
+ v-if="initAddAndTakeData && initAddAndTakeData.length"
4
4
  :class="{
5
5
  'bxt-add-and-take': true,
6
6
  'bxt-add-and-take--footer': footer
7
7
  }"
8
8
  >
9
9
  <div v-if="subName === 'Table'" class="bxt-aat-table">
10
- <div v-if="['addAndTake', 'add', 'take'].includes(type)" class="bxt-aat-bonus">
11
- <p class="bxt-aat-bonus-tips">
12
- 因合规需求,低档收益下账户金额足够才能设置领取:
13
- </p>
14
- <ul class="bxt-aat-bonus-type">
15
- <template v-for="field in ['bonus', 'rate']">
16
- <li :key="field" v-if="initAddAndTakeData[field] && initAddAndTakeData[field].opts">
17
- <SelectItem
18
- v-model.number="initAddAndTakeData[field].opts[0].value"
19
- :options="
20
- initAddAndTakeData[field].opts.map(o => ({
21
- val: o.value,
22
- desc: field === 'bonus' ? o.description : getBonusDesc(o)
23
- }))
24
- "
25
- disabled="true"
26
- right-icon="arrow-right"
27
- />
28
- </li>
29
- </template>
30
- </ul>
31
- </div>
32
- <table class="bxt-aat-table-content">
33
- <thead>
34
- <tr>
35
- <th>年度</th>
36
- <th>年龄</th>
37
- <th v-if="['addAndTake', 'add'].includes(type)">当年追加</th>
38
- <th v-if="['addAndTake', 'take', 'reduceBaof'].includes(type)">
39
- {{ type === 'reduceBaof' ? '领取金额' : '当年领取' }}
40
- </th>
41
- <th>{{ type === 'reduceBaof' ? '现金价值' : '账户价值' }}</th>
42
- </tr>
43
- </thead>
44
- <tbody>
45
- <tr v-for="tr in addAndTakeTable" :key="JSON.stringify(tr)">
46
- <td>
47
- <span>{{ tr[0] + initAddAndTakeData.startPolicyNo - 1 }}</span>
48
- </td>
49
- <td>
50
- <span>{{ tr[1] }}</span>
51
- </td>
52
- <td
53
- v-if="['addAndTake', 'add'].includes(type)"
54
- class="bxt-aat-table-cell-amount"
55
- @click="onClickToForm('add', tr)"
56
- >
57
- <span :class="{ 'value-unequal-zero': tr[2] !== 0 }">{{ tr[2] }}</span>
58
- <i
59
- v-if="tr[2] !== 0"
60
- class="iconfont icon-close_circle_surface"
61
- @click.stop="
62
- updateData({
63
- type: 'add',
64
- beginYear: tr[0],
65
- endYear: tr[0]
66
- })
67
- "
68
- />
69
- </td>
70
- <td
71
- v-if="['addAndTake', 'take', 'reduceBaof'].includes(type)"
72
- class="bxt-aat-table-cell-amount"
73
- @click="onClickToForm('take', tr)"
10
+ <ul v-if="['addAndTake', 'add', 'take'].includes(type)" class="bxt-aat-bonus">
11
+ <template v-for="key in ['bonus', 'rate']">
12
+ <li :key="key" v-if="initInterestData[key] && initInterestData[key].opts">
13
+ <header class="bxt-aat-bonus-title">
14
+ {{ initInterestData[key].title }}
15
+ </header>
16
+ <div class="bxt-aat-bonus-descs">
17
+ <span
18
+ v-for="o in initInterestData[key].opts"
19
+ :key="o.value"
20
+ :class="{
21
+ 'bxt-aat-bonus-desc': true,
22
+ active: interestFormData[key] === o.value
23
+ }"
24
+ @click="onClickBonusOptions(key, o)"
25
+ >
26
+ {{ o.description }}
27
+ </span>
28
+ </div>
29
+ </li>
30
+ </template>
31
+ </ul>
32
+ <div class="bxt-aat-table-content">
33
+ <div class="bxt-aat-table-content-left">
34
+ <div v-for="record in addAndTakeTable" :key="JSON.stringify(record)" class="bxt-aat-table-content-record">
35
+ <div v-for="key in ['year', 'age']" :key="key" class="bxt-aat-table-content-cell">
36
+ <span> {{ record[key] }} </span>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ <div class="bxt-aat-table-content-right">
41
+ <div v-for="record in addAndTakeTable" :key="JSON.stringify(record)" class="bxt-aat-table-content-record">
42
+ <div
43
+ v-for="key in Object.keys(record).filter(k => !['year', 'age', 'purpose'].includes(k))"
44
+ :key="key"
45
+ class="bxt-aat-table-content-cell"
46
+ @click="onClickToForm(key, record)"
74
47
  >
75
- <span :class="{ 'value-unequal-zero': tr[3] !== 0 }">{{ tr[3] }}</span>
76
- <i
77
- v-if="tr[3] !== 0"
78
- class="iconfont icon-close_circle_surface"
79
- @click.stop="
80
- updateData({
81
- type: 'take',
82
- beginYear: tr[0],
83
- endYear: tr[0]
84
- })
85
- "
86
- />
87
- </td>
88
- <td>
89
- <span>{{ Math.round(tr[4]) }}</span>
90
- </td>
91
- </tr>
92
- </tbody>
93
- </table>
48
+ <span
49
+ :class="{
50
+ 'bxt-aat-table-content-cell__zero': !record[key]
51
+ }"
52
+ >
53
+ {{ record[key] }}
54
+ </span>
55
+ <span v-if="key === 'take' && record.purpose" class="bxt-aat-table-content-cell__purpose">
56
+ {{ record.purpose }}
57
+ </span>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </div>
94
62
  </div>
95
63
  <div v-if="subName === 'Form'" class="bxt-aat-form">
96
64
  <bxs-form
@@ -100,71 +68,72 @@
100
68
  :rules="AAT_FORM_RULES"
101
69
  :is-content-vertical-alignment="false"
102
70
  >
103
- <bxs-form-item label="开始时间">
104
- <SelectItem
105
- v-model.number="formData.beginYear"
106
- placeholder="请选择开始时间"
107
- :ele-data="{
108
- label: '请选择开始时间'
109
- }"
110
- :options="beginYearOptions"
111
- right-icon="arrow-right"
112
- />
113
- </bxs-form-item>
114
- <bxs-form-item label="结束时间">
115
- <SelectItem
116
- v-model.number="formData.endYear"
117
- placeholder="请选择结束时间"
118
- :ele-data="{
119
- label: '请选择结束时间'
120
- }"
121
- :options="beginYearOptions.filter(o => o.val >= formData.beginYear)"
122
- right-icon="arrow-right"
123
- />
71
+ <bxs-form-item>
72
+ <header class="bxt-aat-form-item-title">
73
+ 批量{{ ['take'].includes(formData.type) ? '领取' : '追加' }}起止时间
74
+ </header>
75
+ <div class="bxt-aat-form-item-content">
76
+ <div class="bxt-aat-form-item-select">
77
+ <span class="bxt-aat-form-item-select__button" @click="onClickOpenPicker('beginYear')">
78
+ {{ formData.beginYear | filterOption(beginYearOptions) }}
79
+ <i class="iconfont icon-arrows_right"></i>
80
+ </span>
81
+ </div>
82
+ <div class="bxt-aat-form-item-symbol"></div>
83
+ <div class="bxt-aat-form-item-select">
84
+ <span class="bxt-aat-form-item-select__button" @click="onClickOpenPicker('endYear')">
85
+ {{ formData.endYear | filterOption(beginYearOptions) }}
86
+ <i class="iconfont icon-arrows_right"></i>
87
+ </span>
88
+ </div>
89
+ </div>
124
90
  </bxs-form-item>
125
- <bxs-form-item prop="baof" :label="formData.type === 'add' ? '追加金额' : '领取金额'" labelPosition="top">
126
- <bxs-input
127
- id="AatBaof"
128
- :placeholder="`请输入${formData.type === 'add' ? '追加金额' : '领取金额'}`"
129
- v-model.number="formData.baof"
130
- :maxlength="9"
131
- :right-icon="{
132
- prefix: 'icon',
133
- name: 'edit2 iconfont'
134
- }"
135
- autocomplete="off"
136
- @click-icon="onClickEditIcon('AatBaof')"
137
- />
138
- <p v-if="accountDataKey === 'accountData' && formData.type === 'take'" class="bxt-aat-form-baof-tips">
91
+ <bxs-form-item prop="baof">
92
+ <header class="bxt-aat-form-item-title">
93
+ {{ formData.type === 'add' ? '追加金额' : '领取金额' }}
94
+ </header>
95
+ <bxs-input placeholder="请输入金额" v-model.number="formData.baof" :maxlength="9" autocomplete="off" />
96
+ <p v-if="!['reduceBaof'].includes(type) && ['take'].includes(formData.type)" class="bxt-aat-form-baof-tips">
139
97
  根据低档收益,最大领取金额约
140
98
  <span>{{ ensureCanTakeAmount }}</span> 元<br />仅供参考,实际领取以保单账户价值为准
141
99
  </p>
142
100
  </bxs-form-item>
143
- <bxs-form-item v-if="formData.type === 'take'" label="用途" labelPosition="top">
144
- <SelectItem
145
- v-model="formData.purpose"
146
- placeholder="自己填写"
147
- :ele-data="{
148
- label: '请选择用途'
149
- }"
150
- :options="PURPOSE_OPTIONS"
151
- right-icon="arrow-right"
152
- @change="formData.customPurpose = ''"
153
- />
154
- <bxs-input
155
- key="customPurpose"
156
- v-if="!formData.purpose"
157
- id="AatPurpose"
158
- placeholder="请输入用途"
159
- v-model="formData.customPurpose"
160
- :maxlength="50"
161
- :right-icon="{
162
- prefix: 'icon',
163
- name: 'edit2 iconfont'
164
- }"
165
- autocomplete="off"
166
- @click-icon="onClickEditIcon('AatPurpose')"
167
- />
101
+ <bxs-form-item v-if="['take'].includes(formData.type)" class="bxt-aat-form-purpose">
102
+ <header class="bxt-aat-form-item-title">
103
+ 用途
104
+ </header>
105
+ <div class="bxt-aat-form-purpose-options">
106
+ <span
107
+ v-for="o in PURPOSE_OPTIONS"
108
+ :key="o.desc"
109
+ class="bxt-aat-form-purpose-option"
110
+ :class="{
111
+ active: formData.purpose === o.val
112
+ }"
113
+ @click="
114
+ formData.purpose = o.val;
115
+ isShowCustomPurpose = formData.purpose === '';
116
+ "
117
+ >
118
+ {{ o.desc }}
119
+ </span>
120
+ <template v-if="formData.purpose === ''">
121
+ <bxs-input
122
+ placeholder="请输入,5个字以内"
123
+ v-model="formData.customPurpose"
124
+ :maxlength="50"
125
+ autocomplete="off"
126
+ @focus="isShowCustomPurpose = true"
127
+ />
128
+ <span
129
+ v-if="isShowCustomPurpose"
130
+ class="bxt-aat-form-purpose-option active"
131
+ @click="isShowCustomPurpose = false"
132
+ >
133
+ 确定
134
+ </span>
135
+ </template>
136
+ </div>
168
137
  </bxs-form-item>
169
138
  </bxs-form>
170
139
  </div>
@@ -173,73 +142,90 @@
173
142
  </div>
174
143
  <footer v-if="footer" class="bxt-aat-footer">
175
144
  <div class="bxt-aat-footer-wrapper">
176
- <span v-if="subName === 'Form'" @click="goToTable">返回</span>
177
- <span v-if="subName === 'Table' && isShowDeleteAllBtn" class="delete" @click="deleteAllData">
178
- 删除所有记录
179
- </span>
180
- <span
181
- v-if="subName === 'Form' && formData.isShowDelete"
182
- class="delete"
183
- @click="
184
- updateData({
185
- ...formData,
186
- baof: null
187
- })
188
- "
189
- >
190
- 删除{{ formData.beginYear }}-{{ formData.endYear }}年记录
145
+ <span v-if="isShowDeleteAllBtn" class="delete" @click="deleteAllData">
146
+ 清空记录
191
147
  </span>
148
+ <template v-if="subName === 'Form'">
149
+ <span @click="goToTable">返回</span>
150
+ <span
151
+ v-if="formData.isShowDelete"
152
+ class="delete"
153
+ @click="
154
+ updateData({
155
+ ...formData,
156
+ baof: null
157
+ })
158
+ "
159
+ >
160
+ 删除{{ formData.beginYear }}-{{ formData.endYear }}年记录
161
+ </span>
162
+ </template>
192
163
  <span @click="subName === 'Table' ? tableConfirm() : formConfirm()">确定</span>
193
164
  </div>
194
165
  </footer>
195
166
  </div>
196
167
  </template>
197
168
  <script lang="ts">
198
- import QS from 'qs';
199
- import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
200
169
  import cloneDeep from 'lodash/cloneDeep';
201
- import { Toast } from 'bxs-ui-vue';
170
+ import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
171
+ import { Toast, Picker } from 'bxs-ui-vue';
202
172
  import 'bxs-ui-vue/lib/index.css';
203
173
  import { convertPersonData, convertProductData } from 'packages/bxs-utils/planbook/index';
204
- import { AAT_FORM_RULES, PURPOSE_OPTIONS } from './constant.js';
205
- import { getBonusDesc, getBeginYearOpts, getEnsureCanTakeAmount, rebuildAccountData } from './handler.js';
174
+ import { IS_PRODUCT_ENV, AAT_FORM_RULES, PURPOSE_OPTIONS, NONEED_PROD_KEYS, NONEED_INS_KEYS } from './constant.js';
175
+ import { initAddAndTakeData, getBeginYearOpts, getEnsureCanTakeAmount, rebuildAccountData } from './handler.js';
206
176
  import SelectItem from 'packages/components/form-item/select-item.vue';
207
177
 
208
178
  Vue.use(Toast);
179
+ Vue.use(Picker);
209
180
 
210
181
  @Component({
211
182
  components: {
212
183
  SelectItem
184
+ },
185
+ filters: {
186
+ filterOption(value, list) {
187
+ const option = list.find(o => o.val === value);
188
+ return option ? option.desc : '';
189
+ }
213
190
  }
214
191
  })
215
192
  export default class AddAndTake extends Vue {
216
193
  @Prop({
217
194
  type: String,
218
195
  default: () => 'addAndTake',
219
- validator: value => {
196
+ validator: (value: string) => {
220
197
  return ['addAndTake', 'add', 'take', 'reduceBaof'].includes(value);
221
198
  }
222
199
  })
223
200
  type: any;
201
+
224
202
  @Prop({
225
203
  type: Object,
226
- default: () => ({}),
227
- required: true
204
+ default: () => ({})
228
205
  })
229
206
  inputData: any;
207
+
208
+ @Prop({
209
+ type: String,
210
+ default: () => ''
211
+ })
212
+ resultUuid: any;
213
+
230
214
  @Prop({
231
215
  type: Object,
232
216
  default: () => ({})
233
217
  })
234
218
  params: any;
219
+
235
220
  @Prop({
236
221
  type: String,
237
222
  default: () => 'Table',
238
- validator: value => {
223
+ validator: (value: string) => {
239
224
  return ['Table', 'Form'].includes(value);
240
225
  }
241
226
  })
242
227
  submoduleName: any;
228
+
243
229
  @Prop({
244
230
  type: Boolean,
245
231
  default: true
@@ -262,61 +248,59 @@ export default class AddAndTake extends Vue {
262
248
  return this.productData && this.productData.mulInsOrderList.find(ins => ins.key === this.params.insuranceKey);
263
249
  }
264
250
  get addAndTakeTable() {
265
- const { insurerInfo, initAddAndTakeData, accountData } = this;
266
- if (!(initAddAndTakeData && initAddAndTakeData.data)) {
251
+ const { insurerInfo, initInterestData, initAddAndTakeData } = this;
252
+ if (!initInterestData || !initAddAndTakeData) {
267
253
  return [];
268
254
  }
269
- let cashValues;
270
- if (this.type === 'reduceBaof') {
271
- cashValues = initAddAndTakeData.data.find(e => ['cash_value', 'main_cash_value'].includes(e.key));
272
- } else {
273
- cashValues = initAddAndTakeData.data.find(e => ['account_value'].includes(e.key));
274
- }
275
- const accountValues = cashValues && cashValues.values;
276
- if (!(accountValues && accountValues.length)) {
277
- return [];
278
- }
279
- const tableData: any = [];
280
- accountValues.map((val: any, i: number) => {
281
- const year = i + 1;
282
- let addBaof = 0;
283
- let takeBaof = 0;
284
- let purpose = '';
285
- accountData.addAndTakeData.map(ad => {
286
- if (!(ad.adjustData && ad.adjustData.length)) {
287
- return;
255
+
256
+ const tableHeaderData: any = {
257
+ year: '年度',
258
+ age: '年龄'
259
+ };
260
+ initAddAndTakeData.forEach((d, i) => {
261
+ // 为解决接口返回的数组中key相同的问题
262
+ if (!['add', 'take'].includes(d.key)) {
263
+ d.key = `${d.key}_${i}`;
264
+ }
265
+ tableHeaderData[d.key] = d.name;
266
+ });
267
+
268
+ const { startPolicyNo, startIndex, reduceIndex } = initInterestData;
269
+ const maxlength = initAddAndTakeData.reduce((a, b) => Math.max(a, b.values.length || 0), 0);
270
+ let tableData: any = [];
271
+ for (let i = 0; i < maxlength; i++) {
272
+ const record: any = {
273
+ year: i + startPolicyNo, // 年度
274
+ age: insurerInfo.age + startIndex + i + 1 // 年龄
275
+ };
276
+ initAddAndTakeData.map(item => {
277
+ if (item.values) {
278
+ record[item.key] = item.values[i] || 0;
279
+ }
280
+ if (item.details) {
281
+ record.purpose = item.details[i] || '';
288
282
  }
289
- ad.adjustData.map(j => {
290
- if (year < j[0] || year > j[1]) {
291
- return;
292
- }
293
- purpose = j[3] || '';
294
- if (ad.key === 'add') {
295
- addBaof = j[2];
296
- return;
297
- }
298
- takeBaof = j[2];
299
- });
300
283
  });
301
- tableData.push([
302
- i + 1, // 年度
303
- insurerInfo.age + initAddAndTakeData.startIndex + year, // 年龄
304
- addBaof, // 追加金额
305
- takeBaof, // 领取金额
306
- val, // 账户价值
307
- purpose
308
- ]);
309
- });
310
- if (initAddAndTakeData.reduceIndex) {
311
- return tableData.filter(e => e[0] > initAddAndTakeData.reduceIndex);
284
+ tableData.push(record);
285
+ }
286
+
287
+ if (reduceIndex) {
288
+ tableData = tableData.filter(e => e.year > reduceIndex);
312
289
  }
290
+ tableData.unshift(tableHeaderData);
313
291
  return tableData;
314
292
  }
293
+
315
294
  get ensureCanTakeAmount() {
316
- return getEnsureCanTakeAmount(this.formData, this.initAddAndTakeData);
295
+ return getEnsureCanTakeAmount(this.initAddAndTakeData, {
296
+ beginYear: this.formData.beginYear,
297
+ endYear: this.formData.endYear,
298
+ rate: this.interestFormData.rate
299
+ });
317
300
  }
318
301
  get isShowDeleteAllBtn() {
319
302
  return (
303
+ this.subName === 'Table' &&
320
304
  this.accountData.addAndTakeData &&
321
305
  this.accountData.addAndTakeData.some(aat => aat.adjustData && aat.adjustData.length)
322
306
  );
@@ -327,139 +311,248 @@ export default class AddAndTake extends Vue {
327
311
  this.$emit('update:submoduleName', val);
328
312
  }
329
313
 
330
- IS_PRODUCT_ENV = location.hostname.search(/winbaoxian\.com/) !== -1;
331
- AAT_FORM_RULES = AAT_FORM_RULES;
332
- PURPOSE_OPTIONS = PURPOSE_OPTIONS;
333
314
  subName = 'Table';
334
- initAddAndTakeData: any = null;
335
- bonusType = 'low';
336
- accountDataKey = 'accountData';
337
315
  accountData: any = null;
316
+ initInterestData: any = null;
317
+ initAddAndTakeData: any = null;
338
318
  formData: any = {};
339
- getBonusDesc = getBonusDesc;
319
+ interestFormData: any = {};
340
320
  beginYearOptions: any = [];
321
+ isShowCustomPurpose = true;
322
+
323
+ AAT_FORM_RULES = AAT_FORM_RULES;
324
+ PURPOSE_OPTIONS = PURPOSE_OPTIONS;
341
325
 
342
326
  created() {
343
327
  if (this.submoduleName) {
344
328
  this.subName = this.submoduleName;
345
329
  }
346
- this.accountDataKey = ['reduceBaof'].includes(this.type) ? 'reduceBaofData' : 'accountData';
347
- this.accountData = this.insuranceData[this.accountDataKey];
348
- if (!this.accountData) {
349
- this.$toast('缺少配置信息');
350
- return;
330
+ if (this.insuranceData) {
331
+ this.accountData = this.insuranceData[['reduceBaof'].includes(this.type) ? 'reduceBaofData' : 'accountData'];
332
+ if (!this.accountData) {
333
+ this.$toast('缺少配置信息');
334
+ return;
335
+ }
351
336
  }
352
- this.getAddAndTakeData();
337
+ this.getInitInterestData();
353
338
  }
354
339
 
340
+ getInitInterestData() {
341
+ const { resultUuid, params, personData, productData } = this;
342
+ const apis = {
343
+ interest: '/interest/init',
344
+ interestPublic: '/public/interest/init'
345
+ };
346
+ const api = apis['interest' + (params.publicPbUuid ? 'Public' : '')];
347
+ const url = `https://app.winbaoxian.${IS_PRODUCT_ENV ? 'com' : 'cn'}/planBook${api}`;
348
+ const reqParams: any = {
349
+ uuid: resultUuid,
350
+ pbData: '',
351
+ productId: params.productKey
352
+ };
353
+ if (!resultUuid) {
354
+ const cloneProductData = convertProductData(cloneDeep(productData));
355
+ NONEED_PROD_KEYS.forEach(ele => {
356
+ delete cloneProductData[ele];
357
+ });
358
+ cloneProductData.mulInsOrderList?.forEach(ins => {
359
+ NONEED_INS_KEYS.forEach(ele => {
360
+ delete ins[ele];
361
+ });
362
+ });
363
+ reqParams.pbData = JSON.stringify({
364
+ insuranceTypeId: params.planbookId * 1,
365
+ publicPbUuid: params.publicPbUuid,
366
+ personData: {
367
+ personOrderList: convertPersonData(
368
+ personData,
369
+ personData.personOrderList.map(p => p.key)
370
+ )
371
+ },
372
+ productGroupList: [
373
+ {
374
+ key: params.groupKey,
375
+ prodOrderList: [cloneProductData]
376
+ }
377
+ ]
378
+ });
379
+ }
380
+ return fetch(url, {
381
+ method: 'POST',
382
+ credentials: 'include',
383
+ headers: {
384
+ Accept: 'application/json, text/plain, */*',
385
+ 'Content-Type': 'application/json;'
386
+ },
387
+ body: JSON.stringify(reqParams)
388
+ })
389
+ .then(response => response.json())
390
+ .then(({ success, data, info }: any) => {
391
+ if (!success || !data) {
392
+ this.$toast(info);
393
+ return Promise.reject();
394
+ }
395
+ this.initInterestData = initAddAndTakeData(data);
396
+ this.initInterestFormData();
397
+ this.getAddAndTakeData();
398
+ return Promise.resolve(data);
399
+ });
400
+ }
355
401
  getAddAndTakeData(values = null) {
356
- const {
357
- params,
358
- type,
359
- IS_PRODUCT_ENV,
360
- personData,
361
- productData,
362
- insuranceData,
363
- bonusType,
364
- accountDataKey,
365
- accountData
366
- } = this;
367
- const cloneProductData = convertProductData(cloneDeep(productData));
402
+ const { resultUuid, params, type, personData, productData, insuranceData, interestFormData, accountData } = this;
368
403
  const caclAccountData = rebuildAccountData(values, cloneDeep(accountData));
369
404
 
370
- const deleteProdKeys = ['hadChoice', 'hide', 'totalBaof', 'insShowArr', 'autoImport', 'adjustBaoeData'];
371
- deleteProdKeys.forEach(ele => {
372
- delete cloneProductData[ele];
373
- });
374
- cloneProductData.mulInsOrderList?.forEach(ins => {
375
- const deleteInsKeys = [
376
- 'isFollowing',
377
- 'pPeriodDesc',
378
- 'baoeDesc',
379
- 'baofDesc',
380
- 'iDurationDesc',
381
- 'isCheckbox',
382
- 'groupKey',
383
- 'groupName'
384
- ];
385
- deleteInsKeys.forEach(ele => {
386
- delete ins[ele];
387
- });
388
- if (ins.key === insuranceData.key) {
389
- if (values) {
390
- ins[accountDataKey] = caclAccountData;
391
- }
405
+ const apis = {
406
+ addAndTake: '/interest/addAndTake/detail',
407
+ draw: '/interest/draw/detail',
408
+ addAndTakePublic: `/public/addAndTake/${insuranceData.key}/${interestFormData.bonus}`,
409
+ drawPublic: `/public/drawInsurance/${interestFormData.bonus}`
410
+ };
411
+ const api = apis[(type === 'reduceBaof' ? 'draw' : 'addAndTake') + (params.publicPbUuid ? 'Public' : '')];
412
+ const url = `https://app.winbaoxian.${IS_PRODUCT_ENV ? 'com' : 'cn'}/planBook${api}`;
413
+ const reqParams: any = {
414
+ uuid: resultUuid,
415
+ pbData: '',
416
+ productId: params.productKey,
417
+ insuranceId: params.insuranceKey,
418
+ bonus: {
419
+ value: interestFormData.bonus
420
+ },
421
+ rate: {
422
+ value: interestFormData.rate
392
423
  }
393
- });
394
-
395
- const path =
396
- type === 'reduceBaof' ? `/drawInsurance/${bonusType}` : `/addAndTake/${insuranceData.key}/${bonusType}`;
397
- const url = `https://app.winbaoxian.${IS_PRODUCT_ENV ? 'com' : 'cn'}/planBook/${
398
- params.publicPbUuid ? 'public' : 'V2'
399
- }${path}`;
424
+ };
425
+ if (type === 'reduceBaof') {
426
+ reqParams.drawData = JSON.stringify(caclAccountData);
427
+ } else {
428
+ reqParams.addAndTakeData = JSON.stringify(caclAccountData);
429
+ }
430
+ if (!resultUuid) {
431
+ const cloneProductData = convertProductData(cloneDeep(productData));
432
+ NONEED_PROD_KEYS.forEach(ele => {
433
+ delete cloneProductData[ele];
434
+ });
435
+ cloneProductData.mulInsOrderList?.forEach(ins => {
436
+ NONEED_INS_KEYS.forEach(ele => {
437
+ delete ins[ele];
438
+ });
439
+ });
440
+ reqParams.pbData = JSON.stringify({
441
+ insuranceTypeId: params.planbookId * 1,
442
+ publicPbUuid: params.publicPbUuid,
443
+ personData: {
444
+ personOrderList: convertPersonData(
445
+ personData,
446
+ personData.personOrderList.map(p => p.key)
447
+ )
448
+ },
449
+ productGroupList: [
450
+ {
451
+ key: params.groupKey,
452
+ prodOrderList: [cloneProductData]
453
+ }
454
+ ]
455
+ });
456
+ }
400
457
  return fetch(url, {
401
458
  method: 'POST',
402
459
  credentials: 'include',
403
460
  headers: {
404
461
  Accept: 'application/json, text/plain, */*',
405
- 'Content-Type': 'application/x-www-form-urlencoded'
462
+ 'Content-Type': 'application/json;'
406
463
  },
407
- body: QS.stringify({
408
- jd: JSON.stringify({
409
- insuranceTypeId: params.planbookId * 1,
410
- publicPbUuid: params.publicPbUuid,
411
- personData: {
412
- personOrderList: convertPersonData(
413
- personData,
414
- personData.personOrderList.map(p => p.key)
415
- )
416
- },
417
- productGroupList: [
418
- {
419
- key: params.groupKey,
420
- prodOrderList: [cloneProductData]
421
- }
422
- ]
423
- })
424
- })
464
+ body: JSON.stringify(reqParams)
425
465
  })
426
466
  .then(response => response.json())
427
467
  .then(({ success, data, info }: any) => {
428
- if (!success || !data || data === -1) {
468
+ if (!success || !data) {
429
469
  this.$toast(info);
430
470
  return Promise.reject();
431
471
  }
432
472
  this.accountData = caclAccountData;
473
+ data.forEach(d => {
474
+ d.values = d.values && d.values.map(v => (v ? Number(v.toFixed(2)) : v));
475
+ });
433
476
  this.initAddAndTakeData = data;
434
477
  return Promise.resolve(data);
435
478
  });
436
479
  }
437
- onClickEditIcon(id) {
438
- const inputDom: any = document.querySelector(`#${id}`);
439
- inputDom.focus();
480
+ initInterestFormData() {
481
+ const { initInterestData, params } = this;
482
+ const formData = {
483
+ bonus: '',
484
+ rate: null
485
+ };
486
+ if (initInterestData) {
487
+ if (initInterestData.bonus) {
488
+ formData.bonus = initInterestData.bonus.value;
489
+ }
490
+ if (initInterestData.rate) {
491
+ formData.rate = initInterestData.rate.value;
492
+ }
493
+ }
494
+ if (params.bonus) {
495
+ formData.bonus = params.bonus;
496
+ }
497
+ if (params.rate) {
498
+ formData.rate = params.rate;
499
+ }
500
+ this.interestFormData = formData;
501
+ return formData;
502
+ }
503
+
504
+ onClickBonusOptions(key, item) {
505
+ this.interestFormData[key] = item.value;
506
+ this.getAddAndTakeData();
440
507
  }
441
- onClickToForm(operation, item) {
442
- const { insurerInfo, initAddAndTakeData, accountData } = this;
508
+ onClickToForm(key, item) {
509
+ if (!['add', 'take'].includes(key)) {
510
+ return;
511
+ }
512
+ const { insurerInfo, initInterestData, initAddAndTakeData, accountData } = this;
443
513
  const tempItem = accountData.addAndTakeData && accountData.addAndTakeData.find(a => a.key === this.formData.type);
444
- const purposeOption = PURPOSE_OPTIONS.find(o => o.val === item[5]);
514
+ const purposeOption = PURPOSE_OPTIONS.find(o => o.val === item.purpose);
445
515
  this.formData = {
446
- type: operation,
447
- beginYear: item[0],
448
- endYear: item[0],
449
- baof: item[operation === 'add' ? 2 : 3] || null,
516
+ type: key,
517
+ beginYear: item.year,
518
+ endYear: item.year,
519
+ baof: item[key] || null,
450
520
  purpose: purposeOption ? purposeOption.val : '',
451
- customPurpose: item[5],
452
- isShowDelete: !!item[operation === 'add' ? 2 : 3]
521
+ customPurpose: item.purpose,
522
+ isShowDelete: !!item[key]
453
523
  };
524
+
525
+ const { startPolicyNo, startIndex } = initInterestData;
454
526
  this.beginYearOptions = getBeginYearOpts(this.formData, {
455
- data: initAddAndTakeData.data,
456
- startPolicyNo: initAddAndTakeData.startPolicyNo,
457
- startIndex: initAddAndTakeData.startIndex,
527
+ data: initAddAndTakeData,
528
+ startPolicyNo,
529
+ startIndex,
458
530
  age: insurerInfo.age,
459
531
  adjustData: tempItem && tempItem.adjustData
460
532
  });
461
533
  this.subName = 'Form';
462
534
  }
535
+ onClickOpenPicker(key) {
536
+ let self: any = this;
537
+ const { formData, beginYearOptions } = self;
538
+ const options = key === 'beginYear' ? beginYearOptions : beginYearOptions.filter(o => o.val >= formData.beginYear);
539
+ const defaultValue = options.find(o => o.val == formData[key]);
540
+
541
+ return self.$picker({
542
+ title: `请选择${key === 'beginYear' ? '开始' : '结束'}时间`,
543
+ valueKey: 'desc',
544
+ defaultValue: [defaultValue ? defaultValue.desc : null],
545
+ pickerData: options,
546
+ callback(backInfo) {
547
+ if (backInfo.type === 'confirm') {
548
+ formData[key] = backInfo.value.val;
549
+ if (key === 'beginYear' && formData.beginYear > formData.endYear) {
550
+ formData.endYear = formData.beginYear;
551
+ }
552
+ }
553
+ }
554
+ });
555
+ }
463
556
  deleteAllData() {
464
557
  this.accountData.addAndTakeData.forEach(aat => {
465
558
  aat.adjustData = [];
@@ -475,7 +568,14 @@ export default class AddAndTake extends Vue {
475
568
  this.subName = 'Table';
476
569
  }
477
570
  tableConfirm() {
478
- return this.$emit('confirm', this.accountData, this);
571
+ return this.$emit(
572
+ 'confirm',
573
+ {
574
+ accountData: this.accountData,
575
+ interestData: this.interestFormData
576
+ },
577
+ this
578
+ );
479
579
  }
480
580
  formConfirm() {
481
581
  const refForm: any = this.$refs.Form;
@@ -492,7 +592,10 @@ export default class AddAndTake extends Vue {
492
592
  return Promise.reject();
493
593
  }
494
594
  this.tableConfirm();
495
- return Promise.resolve(this.accountData);
595
+ return Promise.resolve({
596
+ accountData: this.accountData,
597
+ interestData: this.interestFormData
598
+ });
496
599
  }
497
600
  }
498
601
  </script>
@@ -383,13 +383,15 @@ export default class BxtProductTable extends Vue {
383
383
  }
384
384
  addAndTakeConfirm(data) {
385
385
  const { productData, popupConf } = this;
386
+ const { accountData, interestData } = data;
386
387
  productData.mulInsOrderList.forEach(ins => {
387
388
  if (ins.key !== popupConf.data.insuranceKey) {
388
389
  return;
389
390
  }
390
- ins.accountData = data;
391
+ ins.accountData = accountData;
391
392
  });
392
- console.log(data);
393
+ console.log(accountData);
394
+ console.log(interestData);
393
395
  this.popupConf = this.initPopupConf();
394
396
  }
395
397
  openAdjustBaoePopup(ins, options: any = {}) {