18
18
/>
19
19
</el-form-item >
20
20
<el-form-item label =" 商品分类" prop =" categoryId" >
21
- <el-tree-select
21
+ <el-cascader
22
22
v-model =" queryParams.categoryId"
23
- :data =" categoryList"
23
+ :options =" categoryList"
24
24
:props =" defaultProps"
25
- check-strictly
26
25
class =" w-1/1"
27
- node-key = " id "
26
+ clearable
28
27
placeholder =" 请选择商品分类"
29
- @change = " nodeClick "
28
+ filterable
30
29
/>
31
30
</el-form-item >
32
31
<el-form-item label =" 创建时间" prop =" createTime" >
78
77
/>
79
78
</el-tabs >
80
79
<el-table v-loading =" loading" :data =" list" >
81
- <el-table-column type =" expand" width = " 30 " >
80
+ <el-table-column type =" expand" >
82
81
<template #default =" { row } " >
83
82
<el-form class =" spu-table-expand" label-position =" left" >
84
83
<el-row >
85
84
<el-col :span =" 24" >
86
85
<el-row >
87
86
<el-col :span =" 8" >
88
87
<el-form-item label =" 商品分类:" >
89
- <span >{{ categoryString (row.categoryId) }}</span >
88
+ <span >{{ formatCategoryName (row.categoryId) }}</span >
90
89
</el-form-item >
91
90
</el-col >
92
91
<el-col :span =" 8" >
93
92
<el-form-item label =" 市场价:" >
94
- <span >{{ floatToFixed2 (row.marketPrice) }}元 </span >
93
+ <span >{{ fenToYuan (row.marketPrice) }}</span >
95
94
</el-form-item >
96
95
</el-col >
97
96
<el-col :span =" 8" >
98
97
<el-form-item label =" 成本价:" >
99
- <span >{{ floatToFixed2 (row.costPrice) }}元 </span >
98
+ <span >{{ fenToYuan (row.costPrice) }}</span >
100
99
</el-form-item >
101
100
</el-col >
102
101
</el-row >
106
105
<el-col :span =" 24" >
107
106
<el-row >
108
107
<el-col :span =" 8" >
109
- <el-form-item label =" 收藏:" >
110
- <!-- TODO 没有这个属性,暂时写死 5 个 -->
111
- <span >5</span >
108
+ <el-form-item label =" 浏览量:" >
109
+ <span >{{ row.browseCount }}</span >
112
110
</el-form-item >
113
111
</el-col >
114
112
<el-col :span =" 8" >
122
120
</el-form >
123
121
</template >
124
122
</el-table-column >
125
- <el-table-column key = " id " align =" center" label =" 商品编号" prop =" id" />
123
+ <el-table-column align =" center" label =" 商品编号" min-width = " 60 " prop =" id" />
126
124
<el-table-column label =" 商品图" min-width =" 80" >
127
125
<template #default =" { row } " >
128
126
<el-image :src =" row.picUrl" class =" h-30px w-30px" @click =" imagePreview(row.picUrl)" />
129
127
</template >
130
128
</el-table-column >
131
129
<el-table-column :show-overflow-tooltip =" true" label =" 商品名称" min-width =" 300" prop =" name" />
132
130
<el-table-column align =" center" label =" 商品售价" min-width =" 90" prop =" price" >
133
- <template #default =" { row } " > {{ floatToFixed2 (row.price) }}元</template >
131
+ <template #default =" { row } " > {{ fenToYuan (row.price) }}元</template >
134
132
</el-table-column >
135
133
<el-table-column align =" center" label =" 销量" min-width =" 90" prop =" salesCount" />
136
134
<el-table-column align =" center" label =" 库存" min-width =" 90" prop =" stock" />
152
150
active-text =" 上架"
153
151
inactive-text =" 下架"
154
152
inline-prompt
155
- @change =" changeStatus (row)"
153
+ @change =" handleStatusChange (row)"
156
154
/>
157
155
</template >
158
156
<template v-else >
191
189
v-hasPermi =" ['product:spu:update']"
192
190
link
193
191
type =" primary"
194
- @click =" changeStatus (row, ProductSpuStatusEnum.DISABLE.status)"
192
+ @click =" handleStatus02Change (row, ProductSpuStatusEnum.DISABLE.status)"
195
193
>
196
194
恢复到仓库
197
195
</el-button >
201
199
v-hasPermi =" ['product:spu:update']"
202
200
link
203
201
type =" primary"
204
- @click =" changeStatus (row, ProductSpuStatusEnum.RECYCLE.status)"
202
+ @click =" handleStatus02Change (row, ProductSpuStatusEnum.RECYCLE.status)"
205
203
>
206
204
加入回收站
207
205
</el-button >
220
218
</template >
221
219
<script lang="ts" setup>
222
220
import { TabsPaneContext } from ' element-plus'
223
- import { cloneDeep } from ' lodash-es'
224
221
import { createImageViewer } from ' @/components/ImageViewer'
225
222
import { dateFormatter } from ' @/utils/formatTime'
226
- import { checkSelectedNode , defaultProps , handleTree , treeToString } from ' @/utils/tree'
223
+ import { defaultProps , handleTree , treeToString } from ' @/utils/tree'
227
224
import { ProductSpuStatusEnum } from ' @/utils/constants'
228
- import { floatToFixed2 } from ' @/utils'
225
+ import { fenToYuan } from ' @/utils'
229
226
import download from ' @/utils/download'
230
227
import * as ProductSpuApi from ' @/api/mall/product/spu'
231
228
import * as ProductCategoryApi from ' @/api/mall/product/category'
@@ -254,7 +251,7 @@ const tabsData = ref([
254
251
},
255
252
{
256
253
count: 0 ,
257
- name: ' 已经售空商品 ' ,
254
+ name: ' 已售罄商品 ' ,
258
255
type: 2
259
256
},
260
257
{
@@ -303,43 +300,37 @@ const getList = async () => {
303
300
}
304
301
}
305
302
306
- /**
307
- * 更改 SPU 状态
308
- *
309
- * @param row
310
- * @param status 更改前的值
311
- */
312
- const changeStatus = async (row , status ? : number ) => {
313
- const deepCopyValue = cloneDeep (unref (row ))
314
- if (typeof status !== ' undefined' ) deepCopyValue .status = status
303
+ /** 添加到仓库 / 回收站的状态 */
304
+ const handleStatus02Change = async (row , newStatus : number ) => {
305
+ try {
306
+ // 二次确认
307
+ const text = newStatus === ProductSpuStatusEnum .RECYCLE .status ? ' 加入到回收站' : ' 恢复到仓库'
308
+ await message .confirm (` 确认要"${row .name }"${text }吗? ` )
309
+ // 发起修改
310
+ await ProductSpuApi .updateStatus ({ id: row .id , status: newStatus })
311
+ message .success (text + ' 成功' )
312
+ // 刷新 tabs 数据
313
+ await getTabsCount ()
314
+ // 刷新列表
315
+ await getList ()
316
+ } catch {}
317
+ }
318
+
319
+ /** 更新上架/下架状态 */
320
+ const handleStatusChange = async (row ) => {
315
321
try {
316
- let text = ' '
317
- switch (deepCopyValue .status ) {
318
- case ProductSpuStatusEnum .DISABLE .status :
319
- text = ProductSpuStatusEnum .DISABLE .name
320
- break
321
- case ProductSpuStatusEnum .ENABLE .status :
322
- text = ProductSpuStatusEnum .ENABLE .name
323
- break
324
- case ProductSpuStatusEnum .RECYCLE .status :
325
- text = ` 加入${ProductSpuStatusEnum .RECYCLE .name } `
326
- break
327
- }
328
- await message .confirm (
329
- deepCopyValue .status === - 1
330
- ? ` 确认要将[${row .name }]${text }吗? `
331
- : row .status === - 1 // 再判断一次原对象是否等于-1,例: 把回收站中的商品恢复到仓库中,事件触发时原对象status为-1 深拷贝对象status被赋值为0
332
- ? ` 确认要将[${row .name }]恢复到仓库吗? `
333
- : ` 确认要${text }[${row .name }]吗? `
334
- )
335
- await ProductSpuApi .updateStatus ({ id: deepCopyValue .id , status: deepCopyValue .status })
336
- message .success (' 更新状态成功' )
322
+ // 二次确认
323
+ const text = row .status ? ' 上架' : ' 下架'
324
+ await message .confirm (` 确认要${text }"${row .name }"吗? ` )
325
+ // 发起修改
326
+ await ProductSpuApi .updateStatus ({ id: row .id , status: row .status })
327
+ message .success (text + ' 成功' )
337
328
// 刷新 tabs 数据
338
329
await getTabsCount ()
339
330
// 刷新列表
340
331
await getList ()
341
332
} catch {
342
- // 取消更改状态时回显数据
333
+ // 异常时,需要重置回之前的值
343
334
row .status =
344
335
row .status === ProductSpuStatusEnum .DISABLE .status
345
336
? ProductSpuStatusEnum .ENABLE .status
@@ -380,26 +371,20 @@ const resetQuery = () => {
380
371
handleQuery ()
381
372
}
382
373
383
- /**
384
- * 新增或修改
385
- *
386
- * @param id 商品 SPU 编号
387
- */
374
+ /** 新增或修改 */
388
375
const openForm = (id ? : number ) => {
389
376
// 修改
390
377
if (typeof id === ' number' ) {
391
- push ({ name: ' ProductSpuEdit' , params: { spuId: id } })
378
+ push ({ name: ' ProductSpuEdit' , params: { id } })
392
379
return
393
380
}
394
381
// 新增
395
382
push ({ name: ' ProductSpuAdd' })
396
383
}
397
384
398
- /**
399
- * 查看商品详情
400
- */
385
+ /** 查看商品详情 */
401
386
const openDetail = (id : number ) => {
402
- push ({ name: ' ProductSpuDetail' , params: { spuId: id } })
387
+ push ({ name: ' ProductSpuDetail' , params: { id } })
403
388
}
404
389
405
390
/** 导出按钮操作 */
@@ -417,6 +402,12 @@ const handleExport = async () => {
417
402
}
418
403
}
419
404
405
+ const categoryList = ref () // 分类树
406
+ /** 获取分类的节点的完整结构 */
407
+ const formatCategoryName = (categoryId ) => {
408
+ return treeToString (categoryList .value , categoryId )
409
+ }
410
+
420
411
// 监听路由变化更新列表,解决商品保存后,列表不刷新的问题。
421
412
watch (
422
413
() => currentRoute .value ,
@@ -425,25 +416,6 @@ watch(
425
416
}
426
417
)
427
418
428
- const categoryList = ref () // 分类树
429
- /**
430
- * 获取分类的节点的完整结构
431
- * @param categoryId 分类id
432
- */
433
- const categoryString = (categoryId ) => {
434
- return treeToString (categoryList .value , categoryId )
435
- }
436
-
437
- /**
438
- * 校验所选是否为二级及以下节点
439
- */
440
- const nodeClick = () => {
441
- if (! checkSelectedNode (categoryList .value , queryParams .value .categoryId )) {
442
- queryParams .value .categoryId = null
443
- message .warning (' 必须选择二级及以下节点!!' )
444
- }
445
- }
446
-
447
419
/** 初始化 **/
448
420
onMounted (async () => {
449
421
await getTabsCount ()
0 commit comments