21
21
<el-table border style =" width : 100% " :data =" formData.templateCharge" >
22
22
<el-table-column align =" center" label =" 区域" >
23
23
<template #default =" { row } " >
24
- <!-- @芋艿 TODO 数据多,性能有问题 , 如何解决 -->
24
+ <!-- 区域数据太多,用赖加载方式,要不然性能有问题 -->
25
25
<el-tree-select
26
26
v-model =" row.areaId"
27
- :data =" areaList"
27
+ lazy
28
+ :load =" loadChargeArea"
28
29
:props =" defaultProps"
29
30
node-key =" id"
30
31
check-strictly
31
32
show-checkbox
32
33
check-on-click-node
33
34
:render-after-expand =" false"
35
+ :cache-data =" areaCache"
34
36
/>
35
37
</template >
36
38
</el-table-column >
39
41
<el-input-number v-model =" row.startCount" :min =" 1" />
40
42
</template >
41
43
</el-table-column >
42
- <!-- TODO 元转换 分 -->
43
44
<el-table-column label =" 运费(元)" prop =" startPrice" >
44
45
<template #default =" { row } " >
45
46
<el-input-number v-model =" row.startPrice" :min =" 1" />
73
74
<el-table border style =" width : 100% " :data =" formData.templateFree" >
74
75
<el-table-column label =" 区域" >
75
76
<template #default =" { row } " >
76
- <!-- @芋艿 TODO 数据多,性能有问题 , 如何解决 -->
77
+ <!-- 区域数据太多,用赖加载方式,要不然性能有问题 -->
77
78
<el-tree-select
78
79
v-model =" row.areaId"
79
- :data =" areaList"
80
+ lazy
81
+ :load =" loadFreeArea"
80
82
:props =" defaultProps"
81
83
node-key =" id"
82
84
check-strictly
83
85
show-checkbox
84
86
check-on-click-node
85
87
:render-after-expand =" false"
88
+ :cache-data =" areaCache"
86
89
/>
87
90
</template >
88
91
</el-table-column >
121
124
<script setup lang="ts">
122
125
import * as DeliveryExpressTemplateApi from ' @/api/mall/trade/delivery/expressTemplate'
123
126
import { defaultProps } from ' @/utils/tree'
124
- import { getAreaTree } from ' @/api/system/area'
127
+ import { yuanToFen , fenToYuan } from ' @/utils'
128
+ import { getChildrenArea , getAreaListByIds } from ' @/api/system/area'
129
+ import { cloneDeep } from ' lodash-es'
125
130
const { t } = useI18n () // 国际化
126
131
const message = useMessage () // 消息弹窗
127
132
@@ -137,6 +142,7 @@ const formData = ref({
137
142
templateCharge: [],
138
143
templateFree: []
139
144
})
145
+ const columnTitleMap = new Map ()
140
146
const columnTitle = ref ({
141
147
startCountTitle: ' 首件' ,
142
148
extraCountTitle: ' 续件' ,
@@ -148,7 +154,8 @@ const formRules = reactive({
148
154
sort: [{ required: true , message: ' 分类排序不能为空' , trigger: ' blur' }]
149
155
})
150
156
const formRef = ref () // 表单 Ref
151
- const areaList = ref ([]) // 区域数据
157
+ const areaCache = ref ([]) // 由于区域节点懒加载,已选区域节点需要缓存展示
158
+ // let areaTree: any[]
152
159
/** 打开弹窗 */
153
160
const open = async (type : string , id ? : number ) => {
154
161
dialogVisible .value = true
@@ -160,6 +167,26 @@ const open = async (type: string, id?: number) => {
160
167
if (id ) {
161
168
formLoading .value = true
162
169
formData .value = await DeliveryExpressTemplateApi .getDeliveryExpressTemplate (id )
170
+ columnTitle .value = columnTitleMap .get (formData .value .chargeMode )
171
+ // 已选的区域节点
172
+ const areaIds = []
173
+ formData .value .templateCharge .forEach ((item ) => {
174
+ // 不等于全国的节点
175
+ if (item .areaId !== 1 ) {
176
+ areaIds .push (item .areaId )
177
+ }
178
+ // 前端价格以元展示
179
+ item .startPrice = fenToYuan (item .startPrice )
180
+ item .extraPrice = fenToYuan (item .extraPrice )
181
+ })
182
+ formData .value .templateFree .forEach ((item ) => {
183
+ if (item .areaId !== 1 && ! areaIds .includes (item .areaId )) {
184
+ areaIds .push (item .areaId )
185
+ }
186
+ item .freePrice = fenToYuan (item .freePrice )
187
+ })
188
+ // 区域节点,懒加载方式。 已选节点需要缓存展示
189
+ areaCache .value = await getAreaListByIds (areaIds )
163
190
}
164
191
} finally {
165
192
formLoading .value = false
@@ -178,6 +205,14 @@ const submitForm = async () => {
178
205
formLoading .value = true
179
206
try {
180
207
const data = formData .value as DeliveryExpressTemplateApi .DeliveryExpressTemplateVO
208
+ data .templateCharge .forEach ((item ) => {
209
+ // 前端价格以元展示,提交到后端。用分计算
210
+ item .startPrice = yuanToFen (item .startPrice )
211
+ item .extraPrice = yuanToFen (item .extraPrice )
212
+ })
213
+ data .templateFree .forEach ((item ) => {
214
+ item .freePrice = yuanToFen (item .freePrice )
215
+ })
181
216
if (formType .value === ' create' ) {
182
217
await DeliveryExpressTemplateApi .createDeliveryExpressTemplate (data )
183
218
message .success (t (' common.createSuccess' ))
@@ -210,46 +245,102 @@ const resetForm = () => {
210
245
templateFree: [],
211
246
sort: 0
212
247
}
213
- columnTitle .value = {
248
+ columnTitle .value = columnTitleMap .get (1 )
249
+ formRef .value ?.resetFields ()
250
+ }
251
+ /** 配送计费方法改变 */
252
+ const changeChargeMode = (chargeMode : number ) => {
253
+ columnTitle .value = columnTitleMap .get (chargeMode )
254
+ }
255
+ const defaultArea = [{ id: 1 , name: ' 全国' , disabled: false }]
256
+
257
+ /** 初始化数据 */
258
+ const initData = async () => {
259
+ // TODO 从服务端全量加载数据, 后面看懒加载是不是可以从前端获取数据。 目前从后端获取数据
260
+ // formLoading.value = true
261
+ // try {
262
+ // const data = await getAreaTree()
263
+ // areaTree = data
264
+ // console.log('areaTree', areaTree)
265
+ // } finally {
266
+ // formLoading.value = false
267
+ // }
268
+ // 表头标题和计费方式的映射
269
+ columnTitleMap .set (1 , {
214
270
startCountTitle: ' 首件' ,
215
271
extraCountTitle: ' 续件' ,
216
272
freeCountTitle: ' 包邮件数'
217
- }
218
- formRef .value ?.resetFields ()
273
+ })
274
+ columnTitleMap .set (2 , {
275
+ startCountTitle: ' 首件重量(kg)' ,
276
+ extraCountTitle: ' 续件重量(kg)' ,
277
+ freeCountTitle: ' 包邮重量(kg)'
278
+ })
279
+ columnTitleMap .set (3 , {
280
+ startCountTitle: ' 首件体积(m³)' ,
281
+ extraCountTitle: ' 续件体积(m³)' ,
282
+ freeCountTitle: ' 包邮体积(m³)'
283
+ })
219
284
}
220
- /** 配送计费方法改变 */
221
- const changeChargeMode = (chargeMod : number ) => {
222
- if (chargeMod === 1 ) {
223
- columnTitle .value = {
224
- startCountTitle: ' 首件' ,
225
- extraCountTitle: ' 续件' ,
226
- freeCountTitle: ' 包邮件数'
227
- }
228
- }
229
- if (chargeMod === 2 ) {
230
- columnTitle .value = {
231
- startCountTitle: ' 首件重量(kg)' ,
232
- extraCountTitle: ' 续件重量(kg)' ,
233
- freeCountTitle: ' 包邮重量(kg)'
285
+
286
+ /** 懒加载运费区域树 */
287
+ const loadChargeArea = async (node , resolve ) => {
288
+ const areaIds = []
289
+ formData .value .templateCharge .forEach ((item ) => {
290
+ if (item .areaId ) {
291
+ areaIds .push (item .areaId )
234
292
}
235
- }
236
- if (chargeMod === 3 ) {
237
- columnTitle .value = {
238
- startCountTitle: ' 首件体积(m³)' ,
239
- extraCountTitle: ' 续件体积(m³)' ,
240
- freeCountTitle: ' 包邮体积(m³)'
293
+ })
294
+ if (node .isLeaf ) return resolve ([])
295
+ const length = node .data .length
296
+ if (length === 0 ) {
297
+ const data = cloneDeep (defaultArea )
298
+ const item = data [0 ]
299
+ if (areaIds .includes (item .id )) {
300
+ item .disabled = true
241
301
}
302
+ resolve (data )
303
+ } else {
304
+ const id = node .data .id
305
+ const data = await getChildrenArea (id )
306
+ data .forEach ((item ) => {
307
+ if (areaIds .includes (item .id )) {
308
+ item .disabled = true
309
+ }
310
+ })
311
+ resolve (data )
242
312
}
243
313
}
244
314
245
- /** 初始化区域数据 */
246
- const initAreaData = async () => {
247
- formLoading .value = true
248
- try {
249
- const data = await getAreaTree (1 )
250
- areaList .value = data
251
- } finally {
252
- formLoading .value = false
315
+ /** 懒加载包邮区域树 */
316
+ const loadFreeArea = async (node , resolve ) => {
317
+ if (node .isLeaf ) return resolve ([])
318
+ // 已经选择的区域id
319
+ const areaIds = []
320
+ formData .value .templateFree .forEach ((item ) => {
321
+ if (item .areaId ) {
322
+ areaIds .push (item .areaId )
323
+ }
324
+ })
325
+ const length = node .data .length
326
+ if (length === 0 ) {
327
+ // 为空,从全国开始选择。全国 id == 1
328
+ const data = cloneDeep (defaultArea )
329
+ const item = data [0 ]
330
+ if (areaIds .includes (item .id )) {
331
+ item .disabled = true
332
+ }
333
+ resolve (data )
334
+ } else {
335
+ const id = node .data .id
336
+ const data = await getChildrenArea (id )
337
+ // 已选区域需要禁止再次选择
338
+ data .forEach ((item ) => {
339
+ if (areaIds .includes (item .id )) {
340
+ item .disabled = true
341
+ }
342
+ })
343
+ resolve (data )
253
344
}
254
345
}
255
346
/** 添加计费区域 */
@@ -285,6 +376,6 @@ const deleteFreeArea = (index) => {
285
376
286
377
/** 初始化 **/
287
378
onMounted (() => {
288
- initAreaData ()
379
+ initData ()
289
380
})
290
381
</script >
0 commit comments