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
3d47d674
authored
Jun 22, 2023
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:添加秒杀活动管理
parent
f3622d42
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
848 additions
and
9 deletions
+848
-9
src/api/mall/promotion/seckill/seckillActivity.ts
+50
-0
src/api/mall/promotion/seckill/seckillConfig.ts
+5
-0
src/views/mall/product/spu/components/SkuList.vue
+15
-1
src/views/mall/product/spu/index.vue
+2
-8
src/views/mall/promotion/seckill/activity/SeckillActivityForm.vue
+136
-0
src/views/mall/promotion/seckill/activity/components/SpuAndSkuSelectForm.vue
+290
-0
src/views/mall/promotion/seckill/activity/components/index.ts
+3
-0
src/views/mall/promotion/seckill/activity/index.vue
+86
-0
src/views/mall/promotion/seckill/activity/seckillActivity.data.ts
+261
-0
No files found.
src/api/mall/promotion/seckill/seckillActivity.ts
0 → 100644
View file @
3d47d674
import
request
from
'@/config/axios'
export
interface
SeckillActivityVO
{
id
:
number
spuId
:
number
name
:
string
status
:
number
remark
:
string
startTime
:
Date
endTime
:
Date
sort
:
number
configIds
:
string
orderCount
:
number
userCount
:
number
totalPrice
:
number
totalLimitCount
:
number
singleLimitCount
:
number
stock
:
number
totalStock
:
number
}
// 查询秒杀活动列表
export
const
getSeckillActivityPage
=
async
(
params
)
=>
{
return
await
request
.
get
({
url
:
'/promotion/seckill-activity/page'
,
params
})
}
// 查询秒杀活动详情
export
const
getSeckillActivity
=
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
'/promotion/seckill-activity/get?id='
+
id
})
}
// 新增秒杀活动
export
const
createSeckillActivity
=
async
(
data
:
SeckillActivityVO
)
=>
{
return
await
request
.
post
({
url
:
'/promotion/seckill-activity/create'
,
data
})
}
// 修改秒杀活动
export
const
updateSeckillActivity
=
async
(
data
:
SeckillActivityVO
)
=>
{
return
await
request
.
put
({
url
:
'/promotion/seckill-activity/update'
,
data
})
}
// 删除秒杀活动
export
const
deleteSeckillActivity
=
async
(
id
:
number
)
=>
{
return
await
request
.
delete
({
url
:
'/promotion/seckill-activity/delete?id='
+
id
})
}
// 导出秒杀活动 Excel
export
const
exportSeckillActivityApi
=
async
(
params
)
=>
{
return
await
request
.
download
({
url
:
'/promotion/seckill-activity/export-excel'
,
params
})
}
src/api/mall/promotion/seckill/seckillConfig.ts
View file @
3d47d674
...
@@ -19,6 +19,11 @@ export const getSeckillConfig = async (id: number) => {
...
@@ -19,6 +19,11 @@ export const getSeckillConfig = async (id: number) => {
return
await
request
.
get
({
url
:
'/promotion/seckill-config/get?id='
+
id
})
return
await
request
.
get
({
url
:
'/promotion/seckill-config/get?id='
+
id
})
}
}
// 获得所有开启状态的秒杀时段精简列表
export
const
getListAllSimple
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/promotion/seckill-config/list-all-simple'
})
}
// 新增秒杀时段配置
// 新增秒杀时段配置
export
const
createSeckillConfig
=
async
(
data
:
SeckillConfigVO
)
=>
{
export
const
createSeckillConfig
=
async
(
data
:
SeckillConfigVO
)
=>
{
return
await
request
.
post
({
url
:
'/promotion/seckill-config/create'
,
data
})
return
await
request
.
post
({
url
:
'/promotion/seckill-config/create'
,
data
})
...
...
src/views/mall/product/spu/components/SkuList.vue
View file @
3d47d674
...
@@ -118,7 +118,9 @@
...
@@ -118,7 +118,9 @@
max-height=
"500"
max-height=
"500"
size=
"small"
size=
"small"
style=
"width: 99%"
style=
"width: 99%"
@
selection-change=
"handleSelectionChange"
>
>
<el-table-column
v-if=
"isComponent"
type=
"selection"
width=
"45"
/>
<el-table-column
align=
"center"
label=
"图片"
min-width=
"80"
>
<el-table-column
align=
"center"
label=
"图片"
min-width=
"80"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-image
:src=
"row.picUrl"
class=
"w-60px h-60px"
@
click=
"imagePreview(row.picUrl)"
/>
<el-image
:src=
"row.picUrl"
class=
"w-60px h-60px"
@
click=
"imagePreview(row.picUrl)"
/>
...
@@ -207,7 +209,8 @@ const props = defineProps({
...
@@ -207,7 +209,8 @@ const props = defineProps({
default
:
()
=>
[]
default
:
()
=>
[]
},
},
isBatch
:
propTypes
.
bool
.
def
(
false
),
// 是否作为批量操作组件
isBatch
:
propTypes
.
bool
.
def
(
false
),
// 是否作为批量操作组件
isDetail
:
propTypes
.
bool
.
def
(
false
)
// 是否作为 sku 详情组件
isDetail
:
propTypes
.
bool
.
def
(
false
),
// 是否作为 sku 详情组件
isComponent
:
propTypes
.
bool
.
def
(
false
)
// 是否作为 sku 选择组件
})
})
const
formData
:
Ref
<
Spu
|
undefined
>
=
ref
<
Spu
>
()
// 表单数据
const
formData
:
Ref
<
Spu
|
undefined
>
=
ref
<
Spu
>
()
// 表单数据
const
skuList
=
ref
<
Sku
[]
>
([
const
skuList
=
ref
<
Sku
[]
>
([
...
@@ -263,6 +266,17 @@ const validateSku = (): boolean => {
...
@@ -263,6 +266,17 @@ const validateSku = (): boolean => {
return
validate
return
validate
}
}
const
emit
=
defineEmits
<
{
(
e
:
'selectionChange'
,
value
:
Sku
[]):
void
}
>
()
/**
* 选择时触发
* @param Sku 传递过来的选中的 sku 是一个数组
*/
const
handleSelectionChange
=
(
val
:
Sku
[])
=>
{
emit
(
'selectionChange'
,
val
)
}
/**
/**
* 将传进来的值赋值给 skuList
* 将传进来的值赋值给 skuList
*/
*/
...
...
src/views/mall/product/spu/index.vue
View file @
3d47d674
...
@@ -17,7 +17,6 @@
...
@@ -17,7 +17,6 @@
@
keyup
.
enter=
"handleQuery"
@
keyup
.
enter=
"handleQuery"
/>
/>
</el-form-item>
</el-form-item>
<!-- TODO 分类只能选择二级分类目前还没做,还是先以联调通顺为主 fixL: 已完善 -->
<el-form-item
label=
"商品分类"
prop=
"categoryId"
>
<el-form-item
label=
"商品分类"
prop=
"categoryId"
>
<el-tree-select
<el-tree-select
v-model=
"queryParams.categoryId"
v-model=
"queryParams.categoryId"
...
@@ -79,12 +78,6 @@
...
@@ -79,12 +78,6 @@
/>
/>
</el-tabs>
</el-tabs>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<!-- TODO puhui:这几个属性哈,一行三个 fix
商品分类:服装鞋包/箱包
商品市场价格:100.00
成本价:0.00
收藏:5
虚拟销量:999 -->
<el-table-column
type=
"expand"
width=
"30"
>
<el-table-column
type=
"expand"
width=
"30"
>
<template
#
default=
"
{ row }">
<template
#
default=
"
{ row }">
<el-form
class=
"demo-table-expand"
label-position=
"left"
>
<el-form
class=
"demo-table-expand"
label-position=
"left"
>
...
@@ -290,7 +283,8 @@ const queryParams = ref({
...
@@ -290,7 +283,8 @@ const queryParams = ref({
pageSize
:
10
,
pageSize
:
10
,
tabType
:
0
,
tabType
:
0
,
name
:
''
,
name
:
''
,
categoryId
:
null
categoryId
:
null
,
createTime
:
[]
})
// 查询参数
})
// 查询参数
const
queryFormRef
=
ref
()
// 搜索的表单Ref
const
queryFormRef
=
ref
()
// 搜索的表单Ref
...
...
src/views/mall/promotion/seckill/activity/SeckillActivityForm.vue
0 → 100644
View file @
3d47d674
<
template
>
<Dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"65%"
>
<Form
ref=
"formRef"
v-loading=
"formLoading"
:isCol=
"true"
:rules=
"rules"
:schema=
"allSchemas.formSchema"
>
<!-- 先选择 -->
<template
#
spuId
>
<el-button
@
click=
"spuAndSkuSelectForm.open('秒杀商品选择')"
>
选择商品
</el-button>
<el-table
:data=
"spuList"
>
<el-table-column
key=
"id"
align=
"center"
label=
"商品编号"
prop=
"id"
/>
<el-table-column
label=
"商品图"
min-width=
"80"
>
<template
#
default=
"
{ row }">
<el-image
:src=
"row.picUrl"
class=
"w-30px h-30px"
@
click=
"imagePreview(row.picUrl)"
/>
</
template
>
</el-table-column>
<el-table-column
:show-overflow-tooltip=
"true"
label=
"商品名称"
min-width=
"300"
prop=
"name"
/>
<el-table-column
align=
"center"
label=
"商品售价"
min-width=
"90"
prop=
"price"
>
<
template
#
default=
"{ row }"
>
{{
formatToFraction
(
row
.
price
)
}}
</
template
>
</el-table-column>
<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=
"70"
prop=
"sort"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"创建时间"
prop=
"createTime"
width=
"180"
/>
</el-table>
</template>
</Form>
<
template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
<SpuAndSkuSelectForm
ref=
"spuAndSkuSelectForm"
@
confirm=
"selectSpu"
/>
</template>
<
script
lang=
"ts"
name=
"PromotionSeckillActivityForm"
setup
>
import
{
SpuAndSkuSelectForm
}
from
'./components'
import
{
allSchemas
,
rules
}
from
'./seckillActivity.data'
import
{
Spu
}
from
'@/api/mall/product/spu'
import
*
as
SeckillActivityApi
from
'@/api/mall/promotion/seckill/seckillActivity'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
formatToFraction
}
from
'@/utils'
import
{
createImageViewer
}
from
'@/components/ImageViewer'
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
dialogTitle
=
ref
(
''
)
// 弹窗的标题
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
formType
=
ref
(
''
)
// 表单的类型:create - 新增;update - 修改
const
formRef
=
ref
()
// 表单 Ref
const
spuAndSkuSelectForm
=
ref
()
// 商品和属性选择 Ref
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
dialogVisible
.
value
=
true
dialogTitle
.
value
=
t
(
'action.'
+
type
)
formType
.
value
=
type
// 修改时,设置数据
if
(
id
)
{
formLoading
.
value
=
true
try
{
const
data
=
await
SeckillActivityApi
.
getSeckillActivity
(
id
)
formRef
.
value
.
setValues
(
data
)
}
finally
{
formLoading
.
value
=
false
}
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
const
spuList
=
ref
<
Spu
[]
>
([])
// 选择的 spu
const
selectSpu
=
(
val
:
Spu
)
=>
{
formRef
.
value
.
setValues
({
spuId
:
val
.
id
})
spuList
.
value
=
[
val
]
}
/** 商品图预览 */
const
imagePreview
=
(
imgUrl
:
string
)
=>
{
createImageViewer
({
zIndex
:
99999999
,
urlList
:
[
imgUrl
]
})
}
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
()
=>
{
// 校验表单
if
(
!
formRef
)
return
const
valid
=
await
formRef
.
value
.
getElFormRef
().
validate
()
if
(
!
valid
)
return
// 提交请求
formLoading
.
value
=
true
try
{
const
data
=
formRef
.
value
.
formModel
as
SeckillActivityApi
.
SeckillActivityVO
if
(
formType
.
value
===
'create'
)
{
await
SeckillActivityApi
.
createSeckillActivity
(
data
)
message
.
success
(
t
(
'common.createSuccess'
))
}
else
{
await
SeckillActivityApi
.
updateSeckillActivity
(
data
)
message
.
success
(
t
(
'common.updateSuccess'
))
}
dialogVisible
.
value
=
false
// 发送操作成功的事件
emit
(
'success'
)
}
finally
{
formLoading
.
value
=
false
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.demo-table-expand
{
padding-left
:
42px
;
:deep(.el-form-item__label)
{
width
:
82px
;
font-weight
:
bold
;
color
:
#99a9bf
;
}
}
</
style
>
src/views/mall/promotion/seckill/activity/components/SpuAndSkuSelectForm.vue
0 → 100644
View file @
3d47d674
<
template
>
<Dialog
v-model=
"dialogVisible"
:appendToBody=
"true"
:title=
"dialogTitle"
width=
"70%"
>
<ContentWrap>
<el-row
:gutter=
"20"
class=
"mb-10px"
>
<el-col
:span=
"6"
>
<el-input
v-model=
"queryParams.name"
class=
"!w-240px"
clearable
placeholder=
"请输入商品名称"
@
keyup
.
enter=
"handleQuery"
/>
</el-col>
<el-col
:span=
"6"
>
<el-tree-select
v-model=
"queryParams.categoryId"
:data=
"categoryList"
:props=
"defaultProps"
check-strictly
class=
"w-1/1"
node-key=
"id"
placeholder=
"请选择商品分类"
@
change=
"nodeClick"
/>
</el-col>
<el-col
:span=
"6"
>
<el-date-picker
v-model=
"queryParams.createTime"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class=
"!w-240px"
end-placeholder=
"结束日期"
start-placeholder=
"开始日期"
type=
"daterange"
value-format=
"YYYY-MM-DD HH:mm:ss"
/>
</el-col>
<el-col
:span=
"6"
>
<el-button
@
click=
"handleQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
</el-button>
</el-col>
</el-row>
<el-table
ref=
"spuListRef"
v-loading=
"loading"
:data=
"list"
:expand-row-keys=
"expandRowKeys"
row-key=
"id"
@
expandChange=
"getPropertyList"
@
selection-change=
"selectSpu"
>
<el-table-column
v-if=
"isSelectSku"
type=
"expand"
width=
"30"
>
<template
#
default
>
<SkuList
v-if=
"isExpand"
:isComponent=
"true"
:isDetail=
"true"
:prop-form-data=
"spuData"
:property-list=
"propertyList"
@
selection-change=
"selectSku"
/>
</
template
>
</el-table-column>
<el-table-column
type=
"selection"
width=
"55"
/>
<el-table-column
key=
"id"
align=
"center"
label=
"商品编号"
prop=
"id"
/>
<el-table-column
label=
"商品图"
min-width=
"80"
>
<
template
#
default=
"{ row }"
>
<el-image
:src=
"row.picUrl"
class=
"w-30px h-30px"
@
click=
"imagePreview(row.picUrl)"
/>
</
template
>
</el-table-column>
<el-table-column
:show-overflow-tooltip=
"true"
label=
"商品名称"
min-width=
"300"
prop=
"name"
/>
<el-table-column
align=
"center"
label=
"商品售价"
min-width=
"90"
prop=
"price"
>
<
template
#
default=
"{ row }"
>
{{
formatToFraction
(
row
.
price
)
}}
</
template
>
</el-table-column>
<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=
"70"
prop=
"sort"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"创建时间"
prop=
"createTime"
width=
"180"
/>
</el-table>
<!-- 分页 -->
<Pagination
v-model:limit=
"queryParams.pageSize"
v-model:page=
"queryParams.pageNo"
:total=
"total"
@
pagination=
"getList"
/>
</ContentWrap>
<
template
#
footer
>
<el-button
type=
"primary"
@
click=
"confirm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
name=
"SeckillActivitySpuAndSkuSelect"
setup
>
import
{
SkuList
}
from
'@/views/mall/product/spu/components'
import
{
ElTable
}
from
'element-plus'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
createImageViewer
}
from
'@/components/ImageViewer'
import
{
formatToFraction
}
from
'@/utils'
import
{
checkSelectedNode
,
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
*
as
ProductCategoryApi
from
'@/api/mall/product/category'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
{
propTypes
}
from
'@/utils/propTypes'
const
props
=
defineProps
({
// 默认不需要(不需要的情况下只返回 spu,需要的情况下返回 选中的 spu 和 sku 列表)
// 其它活动需要选择商品和商品属性导入此组件即可,需添加组件属性 :isSelectSku='true'
isSelectSku
:
propTypes
.
bool
.
def
(
false
)
// 是否需要选择 sku 属性
})
const
message
=
useMessage
()
// 消息弹窗
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
<
any
[]
>
([])
// 列表的数据
const
loading
=
ref
(
false
)
// 列表的加载中
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
dialogTitle
=
ref
(
''
)
// 弹窗的标题
const
queryParams
=
ref
({
pageNo
:
1
,
pageSize
:
10
,
tabType
:
0
,
// 默认获取上架的商品
name
:
''
,
categoryId
:
null
,
createTime
:
[]
})
// 查询参数
const
propertyList
=
ref
([])
// 商品属性列表
const
spuListRef
=
ref
<
InstanceType
<
typeof
ElTable
>>
()
const
spuData
=
ref
<
ProductSpuApi
.
Spu
|
{}
>
()
// 商品详情
const
isExpand
=
ref
(
false
)
// 控制 SKU 列表显示
const
expandRowKeys
=
ref
<
number
[]
>
()
// 控制展开行需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。
// 计算商品属性
const
getPropertyList
=
async
(
row
:
ProductSpuApi
.
Spu
,
expandedRows
:
ProductSpuApi
.
Spu
[])
=>
{
spuData
.
value
=
{}
propertyList
.
value
=
[]
isExpand
.
value
=
false
// 如果展开个数为 0
if
(
expandedRows
.
length
===
0
)
{
expandRowKeys
.
value
=
[]
return
}
// 获取 SPU 详情
const
res
=
(
await
ProductSpuApi
.
getSpu
(
row
.
id
as
number
))
as
ProductSpuApi
.
Spu
// 只有是多规格才处理
if
(
res
.
specType
)
{
// 直接拿返回的 skus 属性逆向生成出 propertyList
const
properties
=
[]
res
.
skus
?.
forEach
((
sku
)
=>
{
sku
.
properties
?.
forEach
(({
propertyId
,
propertyName
,
valueId
,
valueName
})
=>
{
// 添加属性
if
(
!
properties
?.
some
((
item
)
=>
item
.
id
===
propertyId
))
{
properties
.
push
({
id
:
propertyId
,
name
:
propertyName
,
values
:
[]
})
}
// 添加属性值
const
index
=
properties
?.
findIndex
((
item
)
=>
item
.
id
===
propertyId
)
if
(
!
properties
[
index
].
values
?.
some
((
value
)
=>
value
.
id
===
valueId
))
{
properties
[
index
].
values
?.
push
({
id
:
valueId
,
name
:
valueName
})
}
})
})
propertyList
.
value
=
properties
}
spuData
.
value
=
res
isExpand
.
value
=
true
expandRowKeys
.
value
=
[
row
.
id
!
]
}
//============ 商品选择相关 ============
const
selectedSpu
=
ref
<
ProductSpuApi
.
Spu
>
()
// 选中的商品 spu 只能选择一个
const
selectedSku
=
ref
<
ProductSpuApi
.
Sku
[]
>
()
// 选中的商品 sku
const
selectSku
=
(
val
:
ProductSpuApi
.
Sku
[])
=>
{
selectedSku
.
value
=
val
}
const
selectSpu
=
(
val
:
ProductSpuApi
.
Spu
[])
=>
{
// 只选择一个
selectedSpu
.
value
=
val
[
0
]
// 如果大于1个
if
(
val
.
length
>
1
)
{
// 清空选择
spuListRef
.
value
.
clearSelection
()
// 变更为最后一次选择的
spuListRef
.
value
.
toggleRowSelection
(
val
.
pop
(),
true
)
}
}
// 确认选择时的触发事件
const
emits
=
defineEmits
<
{
(
e
:
'confirm'
,
value
:
ProductSpuApi
.
Spu
,
value1
?:
ProductSpuApi
.
Sku
[]):
void
}
>
()
/**
* 确认选择返回选中的 spu 和 sku (如果需要选择sku的话)
*/
const
confirm
=
()
=>
{
if
(
typeof
selectedSpu
.
value
===
'undefined'
)
{
message
.
warning
(
'没有选择任何商品'
)
return
}
if
(
(
props
.
isSelectSku
&&
typeof
selectedSku
.
value
===
'undefined'
)
||
selectedSku
.
value
?.
length
===
0
)
{
message
.
warning
(
'没有选择任何商品属性'
)
return
}
props
.
isSelectSku
?
emits
(
'confirm'
,
selectedSpu
.
value
!
,
selectedSku
.
value
!
)
:
emits
(
'confirm'
,
selectedSpu
.
value
!
)
// 关闭弹窗
dialogVisible
.
value
=
false
}
/** 打开弹窗 TODO 没做国际化 */
const
open
=
(
title
:
string
)
=>
{
dialogTitle
.
value
=
title
dialogVisible
.
value
=
true
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ProductSpuApi
.
getSpuPage
(
queryParams
.
value
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
getList
()
}
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryParams
.
value
=
{
pageNo
:
1
,
pageSize
:
10
,
tabType
:
0
,
// 默认获取上架的商品
name
:
''
,
categoryId
:
null
,
createTime
:
[]
}
getList
()
}
/** 商品图预览 */
const
imagePreview
=
(
imgUrl
:
string
)
=>
{
createImageViewer
({
zIndex
:
99999999
,
urlList
:
[
imgUrl
]
})
}
const
categoryList
=
ref
()
// 分类树
/**
* 校验所选是否为二级及以下节点
*/
const
nodeClick
=
()
=>
{
if
(
!
checkSelectedNode
(
categoryList
.
value
,
queryParams
.
value
.
categoryId
))
{
queryParams
.
value
.
categoryId
=
null
message
.
warning
(
'必须选择二级及以下节点!!'
)
}
}
/** 初始化 **/
onMounted
(
async
()
=>
{
await
getList
()
// 获得分类树
const
data
=
await
ProductCategoryApi
.
getCategoryList
({})
categoryList
.
value
=
handleTree
(
data
,
'id'
,
'parentId'
)
})
</
script
>
src/views/mall/promotion/seckill/activity/components/index.ts
0 → 100644
View file @
3d47d674
import
SpuAndSkuSelectForm
from
'./SpuAndSkuSelectForm.vue'
export
{
SpuAndSkuSelectForm
}
src/views/mall/promotion/seckill/activity/index.vue
0 → 100644
View file @
3d47d674
<
template
>
<!-- 搜索工作栏 -->
<ContentWrap>
<Search
:schema=
"allSchemas.searchSchema"
@
reset=
"setSearchParams"
@
search=
"setSearchParams"
>
<!-- 新增等操作按钮 -->
<template
#
actionMore
>
<el-button
v-hasPermi=
"['promotion:seckill-activity:create']"
plain
type=
"primary"
@
click=
"openForm('create')"
>
<Icon
class=
"mr-5px"
icon=
"ep:plus"
/>
新增
</el-button>
</
template
>
</Search>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<Table
v-model:currentPage=
"tableObject.currentPage"
v-model:pageSize=
"tableObject.pageSize"
:columns=
"allSchemas.tableColumns"
:data=
"tableObject.tableList"
:loading=
"tableObject.loading"
:pagination=
"{
total: tableObject.total
}"
>
<
template
#
action=
"{ row }"
>
<el-button
v-hasPermi=
"['promotion:seckill-activity:update']"
link
type=
"primary"
@
click=
"openForm('update', row.id)"
>
编辑
</el-button>
<el-button
v-hasPermi=
"['promotion:seckill-activity:delete']"
link
type=
"danger"
@
click=
"handleDelete(row.id)"
>
删除
</el-button>
</
template
>
</Table>
</ContentWrap>
<!-- 表单弹窗:添加/修改 -->
<SeckillActivityForm
ref=
"formRef"
@
success=
"getList"
/>
</template>
<
script
lang=
"ts"
name=
"PromotionSeckillActivity"
setup
>
import
{
allSchemas
}
from
'./seckillActivity.data'
import
*
as
SeckillActivityApi
from
'@/api/mall/promotion/seckill/seckillActivity'
import
SeckillActivityForm
from
'./SeckillActivityForm.vue'
// tableObject:表格的属性对象,可获得分页大小、条数等属性
// tableMethods:表格的操作对象,可进行获得分页、删除记录等操作
// 详细可见:https://doc.iocoder.cn/vue3/crud-schema/
const
{
tableObject
,
tableMethods
}
=
useTable
({
getListApi
:
SeckillActivityApi
.
getSeckillActivityPage
,
// 分页接口
delListApi
:
SeckillActivityApi
.
deleteSeckillActivity
// 删除接口
})
// 获得表格的各种操作
const
{
getList
,
setSearchParams
}
=
tableMethods
/** 添加/修改操作 */
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
}
/** 删除按钮操作 */
const
handleDelete
=
(
id
:
number
)
=>
{
tableMethods
.
delList
(
id
,
false
)
}
/** 初始化 **/
onMounted
(()
=>
{
getList
()
})
</
script
>
src/views/mall/promotion/seckill/activity/seckillActivity.data.ts
0 → 100644
View file @
3d47d674
import
type
{
CrudSchema
}
from
'@/hooks/web/useCrudSchemas'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
getListAllSimple
}
from
'@/api/mall/promotion/seckill/seckillConfig'
// 表单校验
export
const
rules
=
reactive
({
spuId
:
[
required
],
name
:
[
required
],
startTime
:
[
required
],
endTime
:
[
required
],
sort
:
[
required
],
configIds
:
[
required
],
totalLimitCount
:
[
required
],
singleLimitCount
:
[
required
],
totalStock
:
[
required
]
})
// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/
const
crudSchemas
=
reactive
<
CrudSchema
[]
>
([
{
label
:
'秒杀活动名称'
,
field
:
'name'
,
isSearch
:
true
,
form
:
{
colProps
:
{
span
:
24
}
},
table
:
{
width
:
120
}
},
{
label
:
'活动开始时间'
,
field
:
'startTime'
,
formatter
:
dateFormatter
,
isSearch
:
true
,
search
:
{
component
:
'DatePicker'
,
componentProps
:
{
valueFormat
:
'YYYY-MM-DD HH:mm:ss'
,
type
:
'daterange'
,
defaultTime
:
[
new
Date
(
'1 00:00:00'
),
new
Date
(
'1 23:59:59'
)]
}
},
form
:
{
component
:
'DatePicker'
,
componentProps
:
{
type
:
'date'
,
valueFormat
:
'x'
}
},
table
:
{
width
:
300
}
},
{
label
:
'活动结束时间'
,
field
:
'endTime'
,
formatter
:
dateFormatter
,
isSearch
:
true
,
search
:
{
component
:
'DatePicker'
,
componentProps
:
{
valueFormat
:
'YYYY-MM-DD HH:mm:ss'
,
type
:
'daterange'
,
defaultTime
:
[
new
Date
(
'1 00:00:00'
),
new
Date
(
'1 23:59:59'
)]
}
},
form
:
{
component
:
'DatePicker'
,
componentProps
:
{
type
:
'date'
,
valueFormat
:
'x'
}
},
table
:
{
width
:
300
}
},
{
label
:
'秒杀时段'
,
field
:
'configIds'
,
form
:
{
component
:
'Select'
,
componentProps
:
{
multiple
:
true
,
optionsAlias
:
{
labelField
:
'name'
,
valueField
:
'id'
}
},
api
:
getListAllSimple
},
table
:
{
width
:
300
}
},
{
label
:
'新增订单数'
,
field
:
'orderCount'
,
isForm
:
false
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'付款人数'
,
field
:
'userCount'
,
isForm
:
false
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'订单实付金额'
,
field
:
'totalPrice'
,
isForm
:
false
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'总限购数量'
,
field
:
'totalLimitCount'
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'单次限够数量'
,
field
:
'singleLimitCount'
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'秒杀库存'
,
field
:
'stock'
,
isForm
:
false
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'秒杀总库存'
,
field
:
'totalStock'
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'秒杀活动商品'
,
field
:
'spuId'
,
form
:
{
colProps
:
{
span
:
24
}
},
table
:
{
width
:
200
}
},
{
label
:
'创建时间'
,
field
:
'createTime'
,
formatter
:
dateFormatter
,
search
:
{
component
:
'DatePicker'
,
componentProps
:
{
valueFormat
:
'YYYY-MM-DD HH:mm:ss'
,
type
:
'daterange'
,
defaultTime
:
[
new
Date
(
'1 00:00:00'
),
new
Date
(
'1 23:59:59'
)]
}
},
isForm
:
false
,
table
:
{
width
:
300
}
},
{
label
:
'排序'
,
field
:
'sort'
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
300
}
},
{
label
:
'状态'
,
field
:
'status'
,
dictType
:
DICT_TYPE
.
COMMON_STATUS
,
dictClass
:
'number'
,
isForm
:
false
,
isSearch
:
true
,
form
:
{
component
:
'Radio'
},
table
:
{
width
:
80
}
},
{
label
:
'备注'
,
field
:
'remark'
,
form
:
{
component
:
'Input'
,
componentProps
:
{
type
:
'textarea'
,
rows
:
4
},
colProps
:
{
span
:
24
}
},
table
:
{
width
:
300
}
},
{
label
:
'操作'
,
field
:
'action'
,
isForm
:
false
,
table
:
{
width
:
120
,
fixed
:
'right'
}
}
])
export
const
{
allSchemas
}
=
useCrudSchemas
(
crudSchemas
)
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