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
36c0bce1
authored
Jul 05, 2023
by
puhui999
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: mall SeckillActivity
parent
b98149f1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
140 additions
and
97 deletions
+140
-97
src/api/mall/promotion/seckill/seckillActivity.ts
+1
-2
src/views/mall/product/spu/components/SkuList.vue
+1
-0
src/views/mall/promotion/components/SpuAndSkuList.vue
+2
-17
src/views/mall/promotion/components/SpuSelect.vue
+52
-26
src/views/mall/promotion/seckill/activity/SeckillActivityForm.vue
+71
-36
src/views/mall/promotion/seckill/activity/seckillActivity.data.ts
+13
-16
No files found.
src/api/mall/promotion/seckill/seckillActivity.ts
View file @
36c0bce1
...
@@ -23,14 +23,13 @@ export interface SeckillActivityVO {
...
@@ -23,14 +23,13 @@ export interface SeckillActivityVO {
// 秒杀活动所需属性
// 秒杀活动所需属性
export
interface
SeckillProductVO
{
export
interface
SeckillProductVO
{
spuId
:
number
skuId
:
number
skuId
:
number
seckillPrice
:
number
seckillPrice
:
number
stock
:
number
stock
:
number
}
}
// 扩展 Sku 配置
// 扩展 Sku 配置
type
SkuExtension
=
Sku
&
{
export
type
SkuExtension
=
Sku
&
{
productConfig
:
SeckillProductVO
productConfig
:
SeckillProductVO
}
}
...
...
src/views/mall/product/spu/components/SkuList.vue
View file @
36c0bce1
...
@@ -194,6 +194,7 @@
...
@@ -194,6 +194,7 @@
<!-- 情况三:作为活动组件 -->
<!-- 情况三:作为活动组件 -->
<el-table
<el-table
v-if=
"isActivityComponent"
v-if=
"isActivityComponent"
ref=
"activitySkuListRef"
:data=
"formData!.skus"
:data=
"formData!.skus"
border
border
max-height=
"500"
max-height=
"500"
...
...
src/views/mall/promotion/components/SpuAndSkuList.vue
View file @
36c0bce1
...
@@ -10,22 +10,7 @@
...
@@ -10,22 +10,7 @@
:rule-config=
"ruleConfig"
:rule-config=
"ruleConfig"
>
>
<template
#
extension
>
<template
#
extension
>
<el-table-column
align=
"center"
label=
"秒杀库存"
min-width=
"168"
>
<slot></slot>
<template
#
default=
"
{ row: sku }">
<el-input-number
v-model=
"sku.productConfig.stock"
:min=
"0"
class=
"w-100%"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"秒杀价格(元)"
min-width=
"168"
>
<
template
#
default=
"{ row: sku }"
>
<el-input-number
v-model=
"sku.productConfig.seckillPrice"
:min=
"0"
:precision=
"2"
:step=
"0.1"
class=
"w-100%"
/>
</
template
>
</el-table-column>
</
template
>
</
template
>
</SkuList>
</SkuList>
</template>
</template>
...
@@ -56,7 +41,7 @@ import { SpuProperty } from '@/views/mall/promotion/components/index'
...
@@ -56,7 +41,7 @@ import { SpuProperty } from '@/views/mall/promotion/components/index'
defineOptions
({
name
:
'PromotionSpuAndSkuList'
})
defineOptions
({
name
:
'PromotionSpuAndSkuList'
})
const
props
=
defineProps
<
{
const
props
=
defineProps
<
{
spuList
:
T
[]
spuList
:
T
[]
// TODO 为了方便兼容后续可能有需要展示多个 spu 的情况暂时保持,如果后续都是只操作一个 spu 的话则可更改为接受一个 spu 或保持
ruleConfig
:
RuleConfig
[]
ruleConfig
:
RuleConfig
[]
spuPropertyListP
:
SpuProperty
<
T
>
[]
spuPropertyListP
:
SpuProperty
<
T
>
[]
}
>
()
}
>
()
...
...
src/views/mall/promotion/components/SpuSelect.vue
View file @
36c0bce1
...
@@ -145,17 +145,61 @@ const queryParams = ref({
...
@@ -145,17 +145,61 @@ const queryParams = ref({
})
// 查询参数
})
// 查询参数
const
propertyList
=
ref
<
Properties
[]
>
([])
// 商品属性列表
const
propertyList
=
ref
<
Properties
[]
>
([])
// 商品属性列表
const
spuListRef
=
ref
<
InstanceType
<
typeof
ElTable
>>
()
const
spuListRef
=
ref
<
InstanceType
<
typeof
ElTable
>>
()
const
spuData
=
ref
<
ProductSpuApi
.
Spu
|
{}
>
()
// 商品详情
const
spuData
=
ref
<
ProductSpuApi
.
Spu
>
()
// 商品详情
const
isExpand
=
ref
(
false
)
// 控制 SKU 列表显示
const
isExpand
=
ref
(
false
)
// 控制 SKU 列表显示
const
expandRowKeys
=
ref
<
number
[]
>
()
// 控制展开行需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。
const
expandRowKeys
=
ref
<
number
[]
>
()
// 控制展开行需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。
//============ 商品选择相关 ============
const
selectedSpuId
=
ref
<
number
>
(
0
)
// 选中的商品 spuId
const
selectedSkuIds
=
ref
<
number
[]
>
([])
// 选中的商品 skuIds
const
selectSku
=
(
val
:
ProductSpuApi
.
Sku
[])
=>
{
if
(
selectedSpuId
.
value
===
0
)
{
return
}
selectedSkuIds
.
value
=
val
.
map
((
sku
)
=>
sku
.
id
!
)
}
const
selectSpu
=
(
val
:
ProductSpuApi
.
Spu
[])
=>
{
if
(
val
.
length
===
0
)
{
selectedSpuId
.
value
=
0
return
}
// 只选择一个
selectedSpuId
.
value
=
val
.
map
((
spu
)
=>
spu
.
id
!
)[
0
]
// 切换选择 spu 如果有选择的 sku 则清空,确保选择的 sku 是对应的 spu 下面的
if
(
selectedSkuIds
.
value
.
length
>
0
)
{
selectedSkuIds
.
value
=
[]
}
// 如果大于1个
if
(
val
.
length
>
1
)
{
// 清空选择
spuListRef
.
value
.
clearSelection
()
// 变更为最后一次选择的
spuListRef
.
value
.
toggleRowSelection
(
val
.
pop
(),
true
)
return
}
expandChange
(
val
[
0
],
val
)
}
// 计算商品属性
// 计算商品属性
const
expandChange
=
async
(
row
:
ProductSpuApi
.
Spu
,
expandedRows
:
ProductSpuApi
.
Spu
[])
=>
{
const
expandChange
=
async
(
row
:
ProductSpuApi
.
Spu
,
expandedRows
?:
ProductSpuApi
.
Spu
[])
=>
{
// 判断需要展开的 spuId === 选择的 spuId。如果选择了 A 就展开 A 的 skuList。如果选择了 A 手动展开 B 则阻断
// 目的防止误选 sku
if
(
selectedSpuId
.
value
!==
0
)
{
if
(
row
.
id
!==
selectedSpuId
.
value
)
{
message
.
warning
(
'你已选择商品请先取消'
)
expandRowKeys
.
value
=
[
selectedSpuId
.
value
]
return
}
// 如果以展开 skuList 则选择此对应的 spu 不需要重新获取渲染 skuList
if
(
isExpand
.
value
&&
spuData
.
value
?.
id
===
row
.
id
)
{
return
}
}
spuData
.
value
=
{}
spuData
.
value
=
{}
propertyList
.
value
=
[]
propertyList
.
value
=
[]
isExpand
.
value
=
false
isExpand
.
value
=
false
// 如果展开个数为 0
if
(
expandedRows
?.
length
===
0
)
{
if
(
expandedRows
.
length
===
0
)
{
// 如果展开个数为 0
expandRowKeys
.
value
=
[]
expandRowKeys
.
value
=
[]
return
return
}
}
...
@@ -167,33 +211,15 @@ const expandChange = async (row: ProductSpuApi.Spu, expandedRows: ProductSpuApi.
...
@@ -167,33 +211,15 @@ const expandChange = async (row: ProductSpuApi.Spu, expandedRows: ProductSpuApi.
expandRowKeys
.
value
=
[
row
.
id
!
]
expandRowKeys
.
value
=
[
row
.
id
!
]
}
}
//============ 商品选择相关 ============
const
selectedSpuIds
=
ref
<
number
[]
>
([])
// 选中的商品 spuIds
const
selectedSkuIds
=
ref
<
number
[]
>
([])
// 选中的商品 skuIds
const
selectSku
=
(
val
:
ProductSpuApi
.
Sku
[])
=>
{
selectedSkuIds
.
value
=
val
.
map
((
sku
)
=>
sku
.
id
!
)
}
const
selectSpu
=
(
val
:
ProductSpuApi
.
Spu
[])
=>
{
selectedSpuIds
.
value
=
val
.
map
((
spu
)
=>
spu
.
id
!
)
// // 只选择一个
// selectedSpu.value = val[0]
// // 如果大于1个
// if (val.length > 1) {
// // 清空选择
// spuListRef.value.clearSelection()
// // 变更为最后一次选择的
// spuListRef.value.toggleRowSelection(val.pop(), true)
// }
}
// 确认选择时的触发事件
// 确认选择时的触发事件
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
(
e
:
'confirm'
,
spuId
s
:
number
[]
,
skuIds
?:
number
[]):
void
(
e
:
'confirm'
,
spuId
:
number
,
skuIds
?:
number
[]):
void
}
>
()
}
>
()
/**
/**
* 确认选择返回选中的 spu 和 sku (如果需要选择sku的话)
* 确认选择返回选中的 spu 和 sku (如果需要选择sku的话)
*/
*/
const
confirm
=
()
=>
{
const
confirm
=
()
=>
{
if
(
selectedSpuId
s
.
value
.
length
===
0
)
{
if
(
selectedSpuId
.
value
===
0
)
{
message
.
warning
(
'没有选择任何商品'
)
message
.
warning
(
'没有选择任何商品'
)
return
return
}
}
...
@@ -203,8 +229,8 @@ const confirm = () => {
...
@@ -203,8 +229,8 @@ const confirm = () => {
}
}
// 返回各自 id 列表
// 返回各自 id 列表
props
.
isSelectSku
props
.
isSelectSku
?
emits
(
'confirm'
,
selectedSpuId
s
.
value
,
selectedSkuIds
.
value
)
?
emits
(
'confirm'
,
selectedSpuId
.
value
,
selectedSkuIds
.
value
)
:
emits
(
'confirm'
,
selectedSpuId
s
.
value
)
:
emits
(
'confirm'
,
selectedSpuId
.
value
)
// 关闭弹窗
// 关闭弹窗
dialogVisible
.
value
=
false
dialogVisible
.
value
=
false
}
}
...
...
src/views/mall/promotion/seckill/activity/SeckillActivityForm.vue
View file @
36c0bce1
...
@@ -8,14 +8,31 @@
...
@@ -8,14 +8,31 @@
:schema=
"allSchemas.formSchema"
:schema=
"allSchemas.formSchema"
>
>
<!-- 先选择 -->
<!-- 先选择 -->
<template
#
spuId
s
>
<template
#
spuId
>
<el-button
@
click=
"spuSelectRef.open()"
>
选择商品
</el-button>
<el-button
@
click=
"spuSelectRef.open()"
>
选择商品
</el-button>
<SpuAndSkuList
<SpuAndSkuList
ref=
"spuAndSkuListRef"
ref=
"spuAndSkuListRef"
:rule-config=
"ruleConfig"
:rule-config=
"ruleConfig"
:spu-list=
"spuList"
:spu-list=
"spuList"
:spu-property-list-p=
"spuPropertyList"
:spu-property-list-p=
"spuPropertyList"
/>
>
<el-table-column
align=
"center"
label=
"秒杀库存"
min-width=
"168"
>
<template
#
default=
"
{ row: sku }">
<el-input-number
v-model=
"sku.productConfig.stock"
:min=
"0"
class=
"w-100%"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"秒杀价格(元)"
min-width=
"168"
>
<
template
#
default=
"{ row: sku }"
>
<el-input-number
v-model=
"sku.productConfig.seckillPrice"
:min=
"0"
:precision=
"2"
:step=
"0.1"
class=
"w-100%"
/>
</
template
>
</el-table-column>
</SpuAndSkuList>
</template>
</template>
</Form>
</Form>
<
template
#
footer
>
<
template
#
footer
>
...
@@ -23,15 +40,17 @@
...
@@ -23,15 +40,17 @@
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</
template
>
</Dialog>
</Dialog>
<SpuSelect
ref=
"spuSelectRef"
@
confirm=
"selectSpu"
/>
<SpuSelect
ref=
"spuSelectRef"
:isSelectSku=
"true"
@
confirm=
"selectSpu"
/>
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
SpuAndSkuList
,
SpuProperty
,
SpuSelect
}
from
'../../components'
import
{
SpuAndSkuList
,
SpuProperty
,
SpuSelect
}
from
'../../components'
import
{
allSchemas
,
rules
}
from
'./seckillActivity.data'
import
{
allSchemas
,
rules
}
from
'./seckillActivity.data'
import
*
as
SeckillActivityApi
from
'@/api/mall/promotion/seckill/seckillActivity'
import
*
as
SeckillActivityApi
from
'@/api/mall/promotion/seckill/seckillActivity'
import
{
SeckillProductVO
}
from
'@/api/mall/promotion/seckill/seckillActivity'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
{
getPropertyList
,
RuleConfig
}
from
'@/views/mall/product/spu/components'
import
{
getPropertyList
,
RuleConfig
}
from
'@/views/mall/product/spu/components'
import
{
convertToInteger
}
from
'@/utils'
defineOptions
({
name
:
'PromotionSeckillActivityForm'
})
defineOptions
({
name
:
'PromotionSeckillActivityForm'
})
...
@@ -43,6 +62,9 @@ const dialogTitle = ref('') // 弹窗的标题
...
@@ -43,6 +62,9 @@ const dialogTitle = ref('') // 弹窗的标题
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
formLoading
=
ref
(
false
)
// 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const
formType
=
ref
(
''
)
// 表单的类型:create - 新增;update - 修改
const
formType
=
ref
(
''
)
// 表单的类型:create - 新增;update - 修改
const
formRef
=
ref
()
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
// ================= 商品选择相关 =================
const
spuSelectRef
=
ref
()
// 商品和属性选择 Ref
const
spuSelectRef
=
ref
()
// 商品和属性选择 Ref
const
spuAndSkuListRef
=
ref
()
// sku 秒杀配置组件Ref
const
spuAndSkuListRef
=
ref
()
// sku 秒杀配置组件Ref
const
ruleConfig
:
RuleConfig
[]
=
[
const
ruleConfig
:
RuleConfig
[]
=
[
...
@@ -57,6 +79,46 @@ const ruleConfig: RuleConfig[] = [
...
@@ -57,6 +79,46 @@ const ruleConfig: RuleConfig[] = [
message
:
'商品秒杀价格必须大于 0.01 !!!'
message
:
'商品秒杀价格必须大于 0.01 !!!'
}
}
]
]
const
spuList
=
ref
<
SeckillActivityApi
.
SpuExtension
[]
>
([])
// 选择的 spu
const
spuPropertyList
=
ref
<
SpuProperty
<
SeckillActivityApi
.
SpuExtension
>
[]
>
([])
const
selectSpu
=
(
spuId
:
number
,
skuIds
:
number
[])
=>
{
formRef
.
value
.
setValues
({
spuId
})
getSpuDetails
(
spuId
,
skuIds
)
}
/**
* 获取 SPU 详情
* @param spuIds
*/
const
getSpuDetails
=
async
(
spuId
:
number
,
skuIds
:
number
[])
=>
{
const
spuProperties
:
SpuProperty
<
SeckillActivityApi
.
SpuExtension
>
[]
=
[]
const
res
=
(
await
ProductSpuApi
.
getSpuDetailList
([
spuId
]))
as
SeckillActivityApi
.
SpuExtension
[]
if
(
res
.
length
==
0
)
{
return
}
spuList
.
value
=
[]
// 因为只能选择一个
const
spu
=
res
[
0
]
const
selectSkus
=
spu
?.
skus
?.
filter
((
sku
)
=>
skuIds
.
includes
(
sku
.
id
!
))
selectSkus
?.
forEach
((
sku
)
=>
{
const
config
:
SeckillActivityApi
.
SeckillProductVO
=
{
skuId
:
sku
.
id
!
,
stock
:
0
,
seckillPrice
:
0
}
sku
.
productConfig
=
config
})
spu
.
skus
=
selectSkus
as
SeckillActivityApi
.
SkuExtension
[]
spuProperties
.
push
({
spuId
:
spu
.
id
!
,
spuDetail
:
spu
,
propertyList
:
getPropertyList
(
spu
)
})
spuList
.
value
.
push
(...
res
)
spuPropertyList
.
value
=
spuProperties
}
// ================= end =================
/** 打开弹窗 */
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
...
@@ -76,38 +138,6 @@ const open = async (type: string, id?: number) => {
...
@@ -76,38 +138,6 @@ const open = async (type: string, id?: number) => {
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
const
spuList
=
ref
<
SeckillActivityApi
.
SpuExtension
[]
>
([])
// 选择的 spu
const
spuPropertyList
=
ref
<
SpuProperty
<
SeckillActivityApi
.
SpuExtension
>
[]
>
([])
const
selectSpu
=
(
spuIds
:
number
[])
=>
{
formRef
.
value
.
setValues
({
spuIds
})
getSpuDetails
(
spuIds
)
}
/**
* 获取 SPU 详情
* TODO 获取 SPU 详情,放到各自活动表单来做,让 SpuAndSkuList 职责单一点
* @param spuIds
*/
const
getSpuDetails
=
async
(
spuIds
:
number
[])
=>
{
const
spuProperties
:
SpuProperty
<
SeckillActivityApi
.
SpuExtension
>
[]
=
[]
const
res
=
(
await
ProductSpuApi
.
getSpuDetailList
(
spuIds
))
as
SeckillActivityApi
.
SpuExtension
[]
spuList
.
value
=
[]
res
?.
forEach
((
spu
)
=>
{
// 初始化每个 sku 秒杀配置
spu
.
skus
?.
forEach
((
sku
)
=>
{
const
config
:
SeckillActivityApi
.
SeckillProductVO
=
{
spuId
:
spu
.
id
!
,
skuId
:
sku
.
id
!
,
stock
:
0
,
seckillPrice
:
0
}
sku
.
productConfig
=
config
})
spuProperties
.
push
({
spuId
:
spu
.
id
!
,
spuDetail
:
spu
,
propertyList
:
getPropertyList
(
spu
)
})
})
spuList
.
value
.
push
(...
res
)
spuPropertyList
.
value
=
spuProperties
}
/** 重置表单 */
/** 重置表单 */
const
resetForm
=
async
()
=>
{
const
resetForm
=
async
()
=>
{
spuList
.
value
=
[]
spuList
.
value
=
[]
...
@@ -126,7 +156,12 @@ const submitForm = async () => {
...
@@ -126,7 +156,12 @@ const submitForm = async () => {
formLoading
.
value
=
true
formLoading
.
value
=
true
try
{
try
{
const
data
=
formRef
.
value
.
formModel
as
SeckillActivityApi
.
SeckillActivityVO
const
data
=
formRef
.
value
.
formModel
as
SeckillActivityApi
.
SeckillActivityVO
data
.
spuIds
=
spuList
.
value
.
map
((
spu
)
=>
spu
.
id
!
)
const
products
=
spuAndSkuListRef
.
value
.
getSkuConfigs
(
'productConfig'
)
products
.
forEach
((
item
:
SeckillProductVO
)
=>
{
// 秒杀价格元转分
item
.
seckillPrice
=
convertToInteger
(
item
.
seckillPrice
)
})
// 获取秒杀商品配置
data
.
products
=
spuAndSkuListRef
.
value
.
getSkuConfigs
(
'productConfig'
)
data
.
products
=
spuAndSkuListRef
.
value
.
getSkuConfigs
(
'productConfig'
)
if
(
formType
.
value
===
'create'
)
{
if
(
formType
.
value
===
'create'
)
{
await
SeckillActivityApi
.
createSeckillActivity
(
data
)
await
SeckillActivityApi
.
createSeckillActivity
(
data
)
...
...
src/views/mall/promotion/seckill/activity/seckillActivity.data.ts
View file @
36c0bce1
...
@@ -153,6 +153,17 @@ const crudSchemas = reactive<CrudSchema[]>([
...
@@ -153,6 +153,17 @@ const crudSchemas = reactive<CrudSchema[]>([
}
}
},
},
{
{
label
:
'排序'
,
field
:
'sort'
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
80
}
},
{
label
:
'秒杀库存'
,
label
:
'秒杀库存'
,
field
:
'stock'
,
field
:
'stock'
,
isForm
:
false
,
isForm
:
false
,
...
@@ -167,17 +178,14 @@ const crudSchemas = reactive<CrudSchema[]>([
...
@@ -167,17 +178,14 @@ const crudSchemas = reactive<CrudSchema[]>([
{
{
label
:
'秒杀总库存'
,
label
:
'秒杀总库存'
,
field
:
'totalStock'
,
field
:
'totalStock'
,
form
:
{
isForm
:
false
,
component
:
'InputNumber'
,
value
:
0
},
table
:
{
table
:
{
width
:
120
width
:
120
}
}
},
},
{
{
label
:
'秒杀活动商品'
,
label
:
'秒杀活动商品'
,
field
:
'spuId
s
'
,
field
:
'spuId'
,
isTable
:
false
,
isTable
:
false
,
isSearch
:
false
,
isSearch
:
false
,
form
:
{
form
:
{
...
@@ -207,17 +215,6 @@ const crudSchemas = reactive<CrudSchema[]>([
...
@@ -207,17 +215,6 @@ const crudSchemas = reactive<CrudSchema[]>([
}
}
},
},
{
{
label
:
'排序'
,
field
:
'sort'
,
form
:
{
component
:
'InputNumber'
,
value
:
0
},
table
:
{
width
:
80
}
},
{
label
:
'状态'
,
label
:
'状态'
,
field
:
'status'
,
field
:
'status'
,
dictType
:
DICT_TYPE
.
COMMON_STATUS
,
dictType
:
DICT_TYPE
.
COMMON_STATUS
,
...
...
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