Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
3a9668d6
authored
Oct 01, 2023
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
product:优化商品列表的样式、实现代码
parent
654094b4
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
68 additions
and
96 deletions
+68
-96
src/router/modules/remaining.ts
+7
-9
src/utils/index.ts
+3
-2
src/utils/tree.ts
+4
-3
src/views/mall/product/spu/form/index.vue
+1
-1
src/views/mall/product/spu/index.vue
+53
-81
No files found.
src/router/modules/remaining.ts
View file @
3a9668d6
...
@@ -331,9 +331,8 @@ const remainingRouter: AppRouteRecordRaw[] = [
...
@@ -331,9 +331,8 @@ const remainingRouter: AppRouteRecordRaw[] = [
]
]
},
},
{
{
path
:
'/
product'
,
path
:
'/
mall/product'
,
// 商品中心
component
:
Layout
,
component
:
Layout
,
name
:
'Product'
,
meta
:
{
meta
:
{
hidden
:
true
hidden
:
true
},
},
...
@@ -348,11 +347,11 @@ const remainingRouter: AppRouteRecordRaw[] = [
...
@@ -348,11 +347,11 @@ const remainingRouter: AppRouteRecordRaw[] = [
canTo
:
true
,
canTo
:
true
,
icon
:
'ep:edit'
,
icon
:
'ep:edit'
,
title
:
'添加商品'
,
title
:
'添加商品'
,
activeMenu
:
'/
product/product-
spu'
activeMenu
:
'/
mall/product/
spu'
}
}
},
},
{
{
path
:
'spu/edit/:
spuI
d(\\d+)'
,
path
:
'spu/edit/:
i
d(\\d+)'
,
component
:
()
=>
import
(
'@/views/mall/product/spu/form/index.vue'
),
component
:
()
=>
import
(
'@/views/mall/product/spu/form/index.vue'
),
name
:
'ProductSpuEdit'
,
name
:
'ProductSpuEdit'
,
meta
:
{
meta
:
{
...
@@ -361,11 +360,11 @@ const remainingRouter: AppRouteRecordRaw[] = [
...
@@ -361,11 +360,11 @@ const remainingRouter: AppRouteRecordRaw[] = [
canTo
:
true
,
canTo
:
true
,
icon
:
'ep:edit'
,
icon
:
'ep:edit'
,
title
:
'编辑商品'
,
title
:
'编辑商品'
,
activeMenu
:
'/
product/product-
spu'
activeMenu
:
'/
mall/product/
spu'
}
}
},
},
{
{
path
:
'spu/detail/:
spuI
d(\\d+)'
,
path
:
'spu/detail/:
i
d(\\d+)'
,
component
:
()
=>
import
(
'@/views/mall/product/spu/form/index.vue'
),
component
:
()
=>
import
(
'@/views/mall/product/spu/form/index.vue'
),
name
:
'ProductSpuDetail'
,
name
:
'ProductSpuDetail'
,
meta
:
{
meta
:
{
...
@@ -374,7 +373,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
...
@@ -374,7 +373,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
canTo
:
true
,
canTo
:
true
,
icon
:
'ep:view'
,
icon
:
'ep:view'
,
title
:
'商品详情'
,
title
:
'商品详情'
,
activeMenu
:
'/
product/product-
spu'
activeMenu
:
'/
mall/product/
spu'
}
}
},
},
{
{
...
@@ -393,9 +392,8 @@ const remainingRouter: AppRouteRecordRaw[] = [
...
@@ -393,9 +392,8 @@ const remainingRouter: AppRouteRecordRaw[] = [
]
]
},
},
{
{
path
:
'/trade'
,
path
:
'/trade'
,
// 交易中心
component
:
Layout
,
component
:
Layout
,
name
:
'Order'
,
meta
:
{
meta
:
{
hidden
:
true
hidden
:
true
},
},
...
...
src/utils/index.ts
View file @
3a9668d6
...
@@ -230,6 +230,7 @@ export const yuanToFen = (amount: string | number): number => {
...
@@ -230,6 +230,7 @@ export const yuanToFen = (amount: string | number): number => {
/**
/**
* 分转元
* 分转元
*/
*/
export
const
fenToYuan
=
(
amount
:
string
|
number
):
number
=>
{
export
const
fenToYuan
=
(
price
:
string
|
number
):
number
=>
{
return
Number
((
Number
(
amount
)
/
100
).
toFixed
(
2
))
price
=
Number
(
price
)
return
(
price
/
100.0
).
toFixed
(
2
)
}
}
src/utils/tree.ts
View file @
3a9668d6
...
@@ -13,7 +13,8 @@ export const defaultProps = {
...
@@ -13,7 +13,8 @@ export const defaultProps = {
children
:
'children'
,
children
:
'children'
,
label
:
'name'
,
label
:
'name'
,
value
:
'id'
,
value
:
'id'
,
isLeaf
:
'leaf'
isLeaf
:
'leaf'
,
emitPath
:
false
// 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值
}
}
const
getConfig
=
(
config
:
Partial
<
TreeHelperConfig
>
)
=>
Object
.
assign
({},
DEFAULT_CONFIG
,
config
)
const
getConfig
=
(
config
:
Partial
<
TreeHelperConfig
>
)
=>
Object
.
assign
({},
DEFAULT_CONFIG
,
config
)
...
@@ -377,10 +378,10 @@ export const treeToString = (tree: any[], nodeId) => {
...
@@ -377,10 +378,10 @@ export const treeToString = (tree: any[], nodeId) => {
function
performAThoroughValidation
(
arr
)
{
function
performAThoroughValidation
(
arr
)
{
for
(
const
item
of
arr
)
{
for
(
const
item
of
arr
)
{
if
(
item
.
id
===
nodeId
)
{
if
(
item
.
id
===
nodeId
)
{
str
+=
`
/
${
item
.
name
}
`
str
+=
`
/
${
item
.
name
}
`
return
true
return
true
}
else
if
(
typeof
item
.
children
!==
'undefined'
&&
item
.
children
.
length
!==
0
)
{
}
else
if
(
typeof
item
.
children
!==
'undefined'
&&
item
.
children
.
length
!==
0
)
{
str
+=
`
/
${
item
.
name
}
`
str
+=
`
/
${
item
.
name
}
`
if
(
performAThoroughValidation
(
item
.
children
))
{
if
(
performAThoroughValidation
(
item
.
children
))
{
return
true
return
true
}
}
...
...
src/views/mall/product/spu/form/index.vue
View file @
3a9668d6
...
@@ -102,7 +102,7 @@ const getDetail = async () => {
...
@@ -102,7 +102,7 @@ const getDetail = async () => {
if
(
'ProductSpuDetail'
===
name
)
{
if
(
'ProductSpuDetail'
===
name
)
{
isDetail
.
value
=
true
isDetail
.
value
=
true
}
}
const
id
=
params
.
spuI
d
as
unknown
as
number
const
id
=
params
.
i
d
as
unknown
as
number
if
(
id
)
{
if
(
id
)
{
formLoading
.
value
=
true
formLoading
.
value
=
true
try
{
try
{
...
...
src/views/mall/product/spu/index.vue
View file @
3a9668d6
...
@@ -18,15 +18,14 @@
...
@@ -18,15 +18,14 @@
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"商品分类"
prop=
"categoryId"
>
<el-form-item
label=
"商品分类"
prop=
"categoryId"
>
<el-
tree-select
<el-
cascader
v-model=
"queryParams.categoryId"
v-model=
"queryParams.categoryId"
:
data
=
"categoryList"
:
options
=
"categoryList"
:props=
"defaultProps"
:props=
"defaultProps"
check-strictly
class=
"w-1/1"
class=
"w-1/1"
node-key=
"id"
clearable
placeholder=
"请选择商品分类"
placeholder=
"请选择商品分类"
@
change=
"nodeClick"
filterable
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"创建时间"
prop=
"createTime"
>
<el-form-item
label=
"创建时间"
prop=
"createTime"
>
...
@@ -78,7 +77,7 @@
...
@@ -78,7 +77,7 @@
/>
/>
</el-tabs>
</el-tabs>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
type=
"expand"
width=
"30"
>
<el-table-column
type=
"expand"
>
<template
#
default=
"
{ row }">
<template
#
default=
"
{ row }">
<el-form
class=
"spu-table-expand"
label-position=
"left"
>
<el-form
class=
"spu-table-expand"
label-position=
"left"
>
<el-row>
<el-row>
...
@@ -86,17 +85,17 @@
...
@@ -86,17 +85,17 @@
<el-row>
<el-row>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"商品分类:"
>
<el-form-item
label=
"商品分类:"
>
<span>
{{
categoryString
(
row
.
categoryId
)
}}
</span>
<span>
{{
formatCategoryName
(
row
.
categoryId
)
}}
</span>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"市场价:"
>
<el-form-item
label=
"市场价:"
>
<span>
{{
f
loatToFixed2
(
row
.
marketPrice
)
}}
元
</span>
<span>
{{
f
enToYuan
(
row
.
marketPrice
)
}}
</span>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"成本价:"
>
<el-form-item
label=
"成本价:"
>
<span>
{{
f
loatToFixed2
(
row
.
costPrice
)
}}
元
</span>
<span>
{{
f
enToYuan
(
row
.
costPrice
)
}}
</span>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
@@ -106,9 +105,8 @@
...
@@ -106,9 +105,8 @@
<el-col
:span=
"24"
>
<el-col
:span=
"24"
>
<el-row>
<el-row>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"收藏:"
>
<el-form-item
label=
"浏览量:"
>
<!-- TODO 没有这个属性,暂时写死 5 个 -->
<span>
{{
row
.
browseCount
}}
</span>
<span>
5
</span>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
...
@@ -122,7 +120,7 @@
...
@@ -122,7 +120,7 @@
</el-form>
</el-form>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
key=
"id"
align=
"center"
label=
"商品编号
"
prop=
"id"
/>
<el-table-column
align=
"center"
label=
"商品编号"
min-width=
"60
"
prop=
"id"
/>
<el-table-column
label=
"商品图"
min-width=
"80"
>
<el-table-column
label=
"商品图"
min-width=
"80"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-image
:src=
"row.picUrl"
class=
"h-30px w-30px"
@
click=
"imagePreview(row.picUrl)"
/>
<el-image
:src=
"row.picUrl"
class=
"h-30px w-30px"
@
click=
"imagePreview(row.picUrl)"
/>
...
@@ -130,7 +128,7 @@
...
@@ -130,7 +128,7 @@
</el-table-column>
</el-table-column>
<el-table-column
:show-overflow-tooltip=
"true"
label=
"商品名称"
min-width=
"300"
prop=
"name"
/>
<el-table-column
:show-overflow-tooltip=
"true"
label=
"商品名称"
min-width=
"300"
prop=
"name"
/>
<el-table-column
align=
"center"
label=
"商品售价"
min-width=
"90"
prop=
"price"
>
<el-table-column
align=
"center"
label=
"商品售价"
min-width=
"90"
prop=
"price"
>
<
template
#
default=
"{ row }"
>
{{
f
loatToFixed2
(
row
.
price
)
}}
元
</
template
>
<
template
#
default=
"{ row }"
>
{{
f
enToYuan
(
row
.
price
)
}}
元
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
align=
"center"
label=
"销量"
min-width=
"90"
prop=
"salesCount"
/>
<el-table-column
align=
"center"
label=
"销量"
min-width=
"90"
prop=
"salesCount"
/>
<el-table-column
align=
"center"
label=
"库存"
min-width=
"90"
prop=
"stock"
/>
<el-table-column
align=
"center"
label=
"库存"
min-width=
"90"
prop=
"stock"
/>
...
@@ -152,7 +150,7 @@
...
@@ -152,7 +150,7 @@
active-text=
"上架"
active-text=
"上架"
inactive-text=
"下架"
inactive-text=
"下架"
inline-prompt
inline-prompt
@
change=
"
changeStatus
(row)"
@
change=
"
handleStatusChange
(row)"
/>
/>
</
template
>
</
template
>
<
template
v-else
>
<
template
v-else
>
...
@@ -191,7 +189,7 @@
...
@@ -191,7 +189,7 @@
v-hasPermi=
"['product:spu:update']"
v-hasPermi=
"['product:spu:update']"
link
link
type=
"primary"
type=
"primary"
@
click=
"
changeStatus
(row, ProductSpuStatusEnum.DISABLE.status)"
@
click=
"
handleStatus02Change
(row, ProductSpuStatusEnum.DISABLE.status)"
>
>
恢复到仓库
恢复到仓库
</el-button>
</el-button>
...
@@ -201,7 +199,7 @@
...
@@ -201,7 +199,7 @@
v-hasPermi=
"['product:spu:update']"
v-hasPermi=
"['product:spu:update']"
link
link
type=
"primary"
type=
"primary"
@
click=
"
changeStatus
(row, ProductSpuStatusEnum.RECYCLE.status)"
@
click=
"
handleStatus02Change
(row, ProductSpuStatusEnum.RECYCLE.status)"
>
>
加入回收站
加入回收站
</el-button>
</el-button>
...
@@ -220,12 +218,11 @@
...
@@ -220,12 +218,11 @@
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
TabsPaneContext
}
from
'element-plus'
import
{
TabsPaneContext
}
from
'element-plus'
import
{
cloneDeep
}
from
'lodash-es'
import
{
createImageViewer
}
from
'@/components/ImageViewer'
import
{
createImageViewer
}
from
'@/components/ImageViewer'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
checkSelectedNode
,
defaultProps
,
handleTree
,
treeToString
}
from
'@/utils/tree'
import
{
defaultProps
,
handleTree
,
treeToString
}
from
'@/utils/tree'
import
{
ProductSpuStatusEnum
}
from
'@/utils/constants'
import
{
ProductSpuStatusEnum
}
from
'@/utils/constants'
import
{
f
loatToFixed2
}
from
'@/utils'
import
{
f
enToYuan
}
from
'@/utils'
import
download
from
'@/utils/download'
import
download
from
'@/utils/download'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
ProductCategoryApi
from
'@/api/mall/product/category'
import
*
as
ProductCategoryApi
from
'@/api/mall/product/category'
...
@@ -254,7 +251,7 @@ const tabsData = ref([
...
@@ -254,7 +251,7 @@ const tabsData = ref([
},
},
{
{
count
:
0
,
count
:
0
,
name
:
'已
经售空
商品'
,
name
:
'已
售罄
商品'
,
type
:
2
type
:
2
},
},
{
{
...
@@ -303,43 +300,37 @@ const getList = async () => {
...
@@ -303,43 +300,37 @@ const getList = async () => {
}
}
}
}
/**
/** 添加到仓库 / 回收站的状态 */
* 更改 SPU 状态
const
handleStatus02Change
=
async
(
row
,
newStatus
:
number
)
=>
{
*
* @param row
* @param status 更改前的值
*/
const
changeStatus
=
async
(
row
,
status
?:
number
)
=>
{
const
deepCopyValue
=
cloneDeep
(
unref
(
row
))
if
(
typeof
status
!==
'undefined'
)
deepCopyValue
.
status
=
status
try
{
try
{
let
text
=
''
// 二次确认
switch
(
deepCopyValue
.
status
)
{
const
text
=
newStatus
===
ProductSpuStatusEnum
.
RECYCLE
.
status
?
'加入到回收站'
:
'恢复到仓库'
case
ProductSpuStatusEnum
.
DISABLE
.
status
:
await
message
.
confirm
(
`确认要"
${
row
.
name
}
"
${
text
}
吗?`
)
text
=
ProductSpuStatusEnum
.
DISABLE
.
name
// 发起修改
break
await
ProductSpuApi
.
updateStatus
({
id
:
row
.
id
,
status
:
newStatus
})
case
ProductSpuStatusEnum
.
ENABLE
.
status
:
message
.
success
(
text
+
'成功'
)
text
=
ProductSpuStatusEnum
.
ENABLE
.
name
// 刷新 tabs 数据
break
await
getTabsCount
()
case
ProductSpuStatusEnum
.
RECYCLE
.
status
:
// 刷新列表
text
=
`加入
${
ProductSpuStatusEnum
.
RECYCLE
.
name
}
`
await
getList
()
break
}
catch
{}
}
}
await
message
.
confirm
(
deepCopyValue
.
status
===
-
1
/** 更新上架/下架状态 */
?
`确认要将[
${
row
.
name
}
]
${
text
}
吗?`
const
handleStatusChange
=
async
(
row
)
=>
{
:
row
.
status
===
-
1
// 再判断一次原对象是否等于-1,例: 把回收站中的商品恢复到仓库中,事件触发时原对象status为-1 深拷贝对象status被赋值为0
try
{
?
`确认要将[
${
row
.
name
}
]恢复到仓库吗?`
// 二次确认
:
`确认要
${
text
}
[
${
row
.
name
}
]吗?`
const
text
=
row
.
status
?
'上架'
:
'下架'
)
await
message
.
confirm
(
`确认要
${
text
}
"
${
row
.
name
}
"吗?`
)
await
ProductSpuApi
.
updateStatus
({
id
:
deepCopyValue
.
id
,
status
:
deepCopyValue
.
status
})
// 发起修改
message
.
success
(
'更新状态成功'
)
await
ProductSpuApi
.
updateStatus
({
id
:
row
.
id
,
status
:
row
.
status
})
message
.
success
(
text
+
'成功'
)
// 刷新 tabs 数据
// 刷新 tabs 数据
await
getTabsCount
()
await
getTabsCount
()
// 刷新列表
// 刷新列表
await
getList
()
await
getList
()
}
catch
{
}
catch
{
//
取消更改状态时回显数据
//
异常时,需要重置回之前的值
row
.
status
=
row
.
status
=
row
.
status
===
ProductSpuStatusEnum
.
DISABLE
.
status
row
.
status
===
ProductSpuStatusEnum
.
DISABLE
.
status
?
ProductSpuStatusEnum
.
ENABLE
.
status
?
ProductSpuStatusEnum
.
ENABLE
.
status
...
@@ -380,26 +371,20 @@ const resetQuery = () => {
...
@@ -380,26 +371,20 @@ const resetQuery = () => {
handleQuery
()
handleQuery
()
}
}
/**
/** 新增或修改 */
* 新增或修改
*
* @param id 商品 SPU 编号
*/
const
openForm
=
(
id
?:
number
)
=>
{
const
openForm
=
(
id
?:
number
)
=>
{
// 修改
// 修改
if
(
typeof
id
===
'number'
)
{
if
(
typeof
id
===
'number'
)
{
push
({
name
:
'ProductSpuEdit'
,
params
:
{
spuId
:
id
}
})
push
({
name
:
'ProductSpuEdit'
,
params
:
{
id
}
})
return
return
}
}
// 新增
// 新增
push
({
name
:
'ProductSpuAdd'
})
push
({
name
:
'ProductSpuAdd'
})
}
}
/**
/** 查看商品详情 */
* 查看商品详情
*/
const
openDetail
=
(
id
:
number
)
=>
{
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'ProductSpuDetail'
,
params
:
{
spuId
:
id
}
})
push
({
name
:
'ProductSpuDetail'
,
params
:
{
id
}
})
}
}
/** 导出按钮操作 */
/** 导出按钮操作 */
...
@@ -417,6 +402,12 @@ const handleExport = async () => {
...
@@ -417,6 +402,12 @@ const handleExport = async () => {
}
}
}
}
const
categoryList
=
ref
()
// 分类树
/** 获取分类的节点的完整结构 */
const
formatCategoryName
=
(
categoryId
)
=>
{
return
treeToString
(
categoryList
.
value
,
categoryId
)
}
// 监听路由变化更新列表,解决商品保存后,列表不刷新的问题。
// 监听路由变化更新列表,解决商品保存后,列表不刷新的问题。
watch
(
watch
(
()
=>
currentRoute
.
value
,
()
=>
currentRoute
.
value
,
...
@@ -425,25 +416,6 @@ watch(
...
@@ -425,25 +416,6 @@ watch(
}
}
)
)
const
categoryList
=
ref
()
// 分类树
/**
* 获取分类的节点的完整结构
* @param categoryId 分类id
*/
const
categoryString
=
(
categoryId
)
=>
{
return
treeToString
(
categoryList
.
value
,
categoryId
)
}
/**
* 校验所选是否为二级及以下节点
*/
const
nodeClick
=
()
=>
{
if
(
!
checkSelectedNode
(
categoryList
.
value
,
queryParams
.
value
.
categoryId
))
{
queryParams
.
value
.
categoryId
=
null
message
.
warning
(
'必须选择二级及以下节点!!'
)
}
}
/** 初始化 **/
/** 初始化 **/
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
getTabsCount
()
await
getTabsCount
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment