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
4870231b
authored
Sep 05, 2024
by
卢越
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【代码优化】代码格式化
parent
40fe63a3
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
376 additions
and
345 deletions
+376
-345
src/api/mall/promotion/combination/combinationActivity.ts
+31
-31
src/components/DiyEditor/components/mobile/PromotionCombination/config.ts
+84
-84
src/components/DiyEditor/components/mobile/PromotionCombination/index.vue
+82
-79
src/components/DiyEditor/components/mobile/PromotionCombination/property.vue
+46
-46
src/components/DiyEditor/index.vue
+5
-1
src/views/mall/promotion/combination/components/CombinationShowcase.vue
+50
-39
src/views/mall/promotion/combination/components/CombinationTableSelect.vue
+78
-65
No files found.
src/api/mall/promotion/combination/combinationActivity.ts
View file @
4870231b
import
request
from
'@/config/axios'
import
request
from
'@/config/axios'
import
{
Sku
,
Spu
}
from
'@/api/mall/product/spu'
import
{
Sku
,
Spu
}
from
'@/api/mall/product/spu'
export
interface
CombinationActivityVO
{
export
interface
CombinationActivityVO
{
id
?:
number
id
?:
number
name
?:
string
name
?:
string
spuId
?:
number
spuId
?:
number
totalLimitCount
?:
number
totalLimitCount
?:
number
singleLimitCount
?:
number
singleLimitCount
?:
number
startTime
?:
Date
startTime
?:
Date
endTime
?:
Date
endTime
?:
Date
userSize
?:
number
userSize
?:
number
totalCount
?:
number
totalCount
?:
number
successCount
?:
number
successCount
?:
number
orderUserCount
?:
number
orderUserCount
?:
number
virtualGroup
?:
number
virtualGroup
?:
number
status
?:
number
status
?:
number
limitDuration
?:
number
limitDuration
?:
number
products
:
CombinationProductVO
[]
products
:
CombinationProductVO
[]
spuName
?:
string
spuName
?:
string
picUrl
?:
string
picUrl
?:
string
marketPrice
?:
number
marketPrice
?:
number
}
}
// 拼团活动所需属性
// 拼团活动所需属性
export
interface
CombinationProductVO
{
export
interface
CombinationProductVO
{
spuId
:
number
spuId
:
number
skuId
:
number
skuId
:
number
combinationPrice
:
number
// 拼团价格
combinationPrice
:
number
// 拼团价格
}
}
// 扩展 Sku 配置
// 扩展 Sku 配置
export
type
SkuExtension
=
Sku
&
{
export
type
SkuExtension
=
Sku
&
{
productConfig
:
CombinationProductVO
productConfig
:
CombinationProductVO
}
}
export
interface
SpuExtension
extends
Spu
{
export
interface
SpuExtension
extends
Spu
{
skus
:
SkuExtension
[]
// 重写类型
skus
:
SkuExtension
[]
// 重写类型
}
}
// 查询拼团活动列表
// 查询拼团活动列表
export
const
getCombinationActivityPage
=
async
(
params
)
=>
{
export
const
getCombinationActivityPage
=
async
(
params
)
=>
{
return
await
request
.
get
({
url
:
'/promotion/combination-activity/page'
,
params
})
return
await
request
.
get
({
url
:
'/promotion/combination-activity/page'
,
params
})
}
}
// 查询拼团活动详情
// 查询拼团活动详情
export
const
getCombinationActivity
=
async
(
id
:
number
)
=>
{
export
const
getCombinationActivity
=
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
'/promotion/combination-activity/get?id='
+
id
})
return
await
request
.
get
({
url
:
'/promotion/combination-activity/get?id='
+
id
})
}
}
// 查询拼团活动详情列表
// 查询拼团活动详情列表
export
const
getCombinationActivityDetailList
=
(
ids
:
number
[])
=>
{
export
const
getCombinationActivityDetailList
=
(
ids
:
number
[])
=>
{
return
request
.
get
({
url
:
`/promotion/combination-activity/detail-list?ids=
${
ids
}
`
})
return
request
.
get
({
url
:
`/promotion/combination-activity/detail-list?ids=
${
ids
}
`
})
}
}
// 新增拼团活动
// 新增拼团活动
export
const
createCombinationActivity
=
async
(
data
:
CombinationActivityVO
)
=>
{
export
const
createCombinationActivity
=
async
(
data
:
CombinationActivityVO
)
=>
{
return
await
request
.
post
({
url
:
'/promotion/combination-activity/create'
,
data
})
return
await
request
.
post
({
url
:
'/promotion/combination-activity/create'
,
data
})
}
}
// 修改拼团活动
// 修改拼团活动
export
const
updateCombinationActivity
=
async
(
data
:
CombinationActivityVO
)
=>
{
export
const
updateCombinationActivity
=
async
(
data
:
CombinationActivityVO
)
=>
{
return
await
request
.
put
({
url
:
'/promotion/combination-activity/update'
,
data
})
return
await
request
.
put
({
url
:
'/promotion/combination-activity/update'
,
data
})
}
}
// 关闭拼团活动
// 关闭拼团活动
export
const
closeCombinationActivity
=
async
(
id
:
number
)
=>
{
export
const
closeCombinationActivity
=
async
(
id
:
number
)
=>
{
return
await
request
.
put
({
url
:
'/promotion/combination-activity/close?id='
+
id
})
return
await
request
.
put
({
url
:
'/promotion/combination-activity/close?id='
+
id
})
}
}
// 删除拼团活动
// 删除拼团活动
export
const
deleteCombinationActivity
=
async
(
id
:
number
)
=>
{
export
const
deleteCombinationActivity
=
async
(
id
:
number
)
=>
{
return
await
request
.
delete
({
url
:
'/promotion/combination-activity/delete?id='
+
id
})
return
await
request
.
delete
({
url
:
'/promotion/combination-activity/delete?id='
+
id
})
}
}
src/components/DiyEditor/components/mobile/PromotionCombination/config.ts
View file @
4870231b
import
{
ComponentStyle
,
DiyComponent
}
from
'@/components/DiyEditor/util'
import
{
ComponentStyle
,
DiyComponent
}
from
'@/components/DiyEditor/util'
/** 拼团属性 */
/** 拼团属性 */
export
interface
PromotionCombinationProperty
{
export
interface
PromotionCombinationProperty
{
// 布局类型:单列 | 三列
// 布局类型:单列 | 三列
layoutType
:
'oneColBigImg'
|
'oneColSmallImg'
|
'twoCol'
;
layoutType
:
'oneColBigImg'
|
'oneColSmallImg'
|
'twoCol'
// 商品字段
// 商品字段
fields
:
{
fields
:
{
// 商品名称
// 商品名称
name
:
PromotionCombinationFieldProperty
name
:
PromotionCombinationFieldProperty
// 商品简介
// 商品简介
introduction
:
PromotionCombinationFieldProperty
introduction
:
PromotionCombinationFieldProperty
// 商品价格
// 商品价格
price
:
PromotionCombinationFieldProperty
price
:
PromotionCombinationFieldProperty
// 市场价
// 市场价
marketPrice
:
PromotionCombinationFieldProperty
marketPrice
:
PromotionCombinationFieldProperty
// 商品销量
// 商品销量
salesCount
:
PromotionCombinationFieldProperty
salesCount
:
PromotionCombinationFieldProperty
// 商品库存
// 商品库存
stock
:
PromotionCombinationFieldProperty
stock
:
PromotionCombinationFieldProperty
}
}
// 角标
// 角标
badge
:
{
badge
:
{
// 是否显示
// 是否显示
show
:
boolean
show
:
boolean
// 角标图片
// 角标图片
imgUrl
:
string
imgUrl
:
string
}
}
// 按钮
// 按钮
btnBuy
:
{
btnBuy
:
{
// 类型:文字 | 图片
// 类型:文字 | 图片
type
:
'text'
|
'img'
type
:
'text'
|
'img'
// 文字
// 文字
text
:
string
text
:
string
// 文字按钮:背景渐变起始颜色
// 文字按钮:背景渐变起始颜色
bgBeginColor
:
string
bgBeginColor
:
string
// 文字按钮:背景渐变结束颜色
// 文字按钮:背景渐变结束颜色
bgEndColor
:
string
bgEndColor
:
string
// 图片按钮:图片地址
// 图片按钮:图片地址
imgUrl
:
string
imgUrl
:
string
}
}
// 上圆角
// 上圆角
borderRadiusTop
:
number
borderRadiusTop
:
number
// 下圆角
// 下圆角
borderRadiusBottom
:
number
borderRadiusBottom
:
number
// 间距
// 间距
space
:
number
space
:
number
// 拼团活动编号
// 拼团活动编号
activityIds
:
number
[]
activityIds
:
number
[]
// 组件样式
// 组件样式
style
:
ComponentStyle
style
:
ComponentStyle
}
}
// 商品字段
// 商品字段
export
interface
PromotionCombinationFieldProperty
{
export
interface
PromotionCombinationFieldProperty
{
// 是否显示
// 是否显示
show
:
boolean
show
:
boolean
// 颜色
// 颜色
color
:
string
color
:
string
}
}
// 定义组件
// 定义组件
export
const
component
=
{
export
const
component
=
{
id
:
'PromotionCombination'
,
id
:
'PromotionCombination'
,
name
:
'拼团'
,
name
:
'拼团'
,
icon
:
'mdi:account-group'
,
icon
:
'mdi:account-group'
,
property
:
{
property
:
{
layoutType
:
'oneColBigImg'
,
layoutType
:
'oneColBigImg'
,
fields
:
{
fields
:
{
name
:
{
show
:
true
,
color
:
'#000'
},
name
:
{
show
:
true
,
color
:
'#000'
},
introduction
:
{
show
:
true
,
color
:
'#999'
},
introduction
:
{
show
:
true
,
color
:
'#999'
},
price
:
{
show
:
true
,
color
:
'#ff3000'
},
price
:
{
show
:
true
,
color
:
'#ff3000'
},
marketPrice
:
{
show
:
true
,
color
:
'#c4c4c4'
},
marketPrice
:
{
show
:
true
,
color
:
'#c4c4c4'
},
salesCount
:
{
show
:
true
,
color
:
'#c4c4c4'
},
salesCount
:
{
show
:
true
,
color
:
'#c4c4c4'
},
stock
:
{
show
:
false
,
color
:
'#c4c4c4'
}
stock
:
{
show
:
false
,
color
:
'#c4c4c4'
}
},
},
badge
:
{
show
:
false
,
imgUrl
:
''
},
badge
:
{
show
:
false
,
imgUrl
:
''
},
btnBuy
:
{
btnBuy
:
{
type
:
'text'
,
type
:
'text'
,
text
:
'去拼团'
,
text
:
'去拼团'
,
bgBeginColor
:
'#FF6000'
,
bgBeginColor
:
'#FF6000'
,
bgEndColor
:
'#FE832A'
,
bgEndColor
:
'#FE832A'
,
imgUrl
:
''
imgUrl
:
''
},
},
borderRadiusTop
:
8
,
borderRadiusTop
:
8
,
borderRadiusBottom
:
8
,
borderRadiusBottom
:
8
,
space
:
8
,
space
:
8
,
style
:
{
style
:
{
bgType
:
'color'
,
bgType
:
'color'
,
bgColor
:
''
,
bgColor
:
''
,
marginLeft
:
8
,
marginLeft
:
8
,
marginRight
:
8
,
marginRight
:
8
,
marginBottom
:
8
marginBottom
:
8
}
as
ComponentStyle
}
as
ComponentStyle
}
}
}
as
DiyComponent
<
PromotionCombinationProperty
>
}
as
DiyComponent
<
PromotionCombinationProperty
>
src/components/DiyEditor/components/mobile/PromotionCombination/index.vue
View file @
4870231b
<
template
>
<
template
>
<div
:class=
"`box-content min-h-30px w-full flex flex-row flex-wrap`"
ref=
"containerRef"
>
<div
:class=
"`box-content min-h-30px w-full flex flex-row flex-wrap`"
ref=
"containerRef"
>
<div
<div
class=
"relative box-content flex flex-row flex-wrap overflow-hidden bg-white"
class=
"relative box-content flex flex-row flex-wrap overflow-hidden bg-white"
:style=
"
{
:style=
"
{
...calculateSpace(index),
...calculateSpace(index),
...calculateWidth(),
...calculateWidth(),
borderTopLeftRadius: `${property.borderRadiusTop}px`,
borderTopLeftRadius: `${property.borderRadiusTop}px`,
...
@@ -10,16 +10,16 @@
...
@@ -10,16 +10,16 @@
borderBottomLeftRadius: `${property.borderRadiusBottom}px`,
borderBottomLeftRadius: `${property.borderRadiusBottom}px`,
borderBottomRightRadius: `${property.borderRadiusBottom}px`
borderBottomRightRadius: `${property.borderRadiusBottom}px`
}"
}"
v-for="(spu, index) in spuList"
v-for="(spu, index) in spuList"
:key="index"
:key="index"
>
>
<!-- 角标 -->
<!-- 角标 -->
<div
v-if=
"property.badge.show"
class=
"absolute left-0 top-0 z-1 items-center justify-center"
>
<div
v-if=
"property.badge.show"
class=
"absolute left-0 top-0 z-1 items-center justify-center"
>
<el-image
fit=
"cover"
:src=
"property.badge.imgUrl"
class=
"h-26px w-38px"
/>
<el-image
fit=
"cover"
:src=
"property.badge.imgUrl"
class=
"h-26px w-38px"
/>
</div>
</div>
<!-- 商品封面图 -->
<!-- 商品封面图 -->
<div
<div
:class=
"[
:class=
"[
'h-140px',
'h-140px',
{
{
'w-full': property.layoutType !== 'oneColSmallImg',
'w-full': property.layoutType !== 'oneColSmallImg',
...
@@ -27,10 +27,10 @@
...
@@ -27,10 +27,10 @@
}
}
]"
]"
>
>
<el-image
fit=
"cover"
class=
"h-full w-full"
:src=
"spu.picUrl"
/>
<el-image
fit=
"cover"
class=
"h-full w-full"
:src=
"spu.picUrl"
/>
</div>
</div>
<div
<div
:class=
"[
:class=
"[
' flex flex-col gap-8px p-8px box-border',
' flex flex-col gap-8px p-8px box-border',
{
{
'w-full': property.layoutType !== 'oneColSmallImg',
'w-full': property.layoutType !== 'oneColSmallImg',
...
@@ -40,48 +40,48 @@
...
@@ -40,48 +40,48 @@
>
>
<!-- 商品名称 -->
<!-- 商品名称 -->
<div
<div
v-if=
"property.fields.name.show"
v-if=
"property.fields.name.show"
:class=
"[
:class=
"[
'text-14px ',
'text-14px ',
{
{
truncate: property.layoutType !== 'oneColSmallImg',
truncate: property.layoutType !== 'oneColSmallImg',
'overflow-ellipsis line-clamp-2': property.layoutType === 'oneColSmallImg'
'overflow-ellipsis line-clamp-2': property.layoutType === 'oneColSmallImg'
}
}
]"
]"
:style="{ color: property.fields.name.color }"
:style="{ color: property.fields.name.color }"
>
>
{{
spu
.
name
}}
{{
spu
.
name
}}
</div>
</div>
<!-- 商品简介 -->
<!-- 商品简介 -->
<div
<div
v-if=
"property.fields.introduction.show"
v-if=
"property.fields.introduction.show"
class=
"truncate text-12px"
class=
"truncate text-12px"
:style=
"
{ color: property.fields.introduction.color }"
:style=
"
{ color: property.fields.introduction.color }"
>
>
{{
spu
.
introduction
}}
{{
spu
.
introduction
}}
</div>
</div>
<div>
<div>
<!-- 价格 -->
<!-- 价格 -->
<span
<span
v-if=
"property.fields.price.show"
v-if=
"property.fields.price.show"
class=
"text-16px"
class=
"text-16px"
:style=
"
{ color: property.fields.price.color }"
:style=
"
{ color: property.fields.price.color }"
>
>
¥
{{
fenToYuan
(
spu
.
price
||
Infinity
)
}}
¥
{{
fenToYuan
(
spu
.
price
||
Infinity
)
}}
</span>
</span>
<!-- 市场价 -->
<!-- 市场价 -->
<span
<span
v-if=
"property.fields.marketPrice.show && spu.marketPrice"
v-if=
"property.fields.marketPrice.show && spu.marketPrice"
class=
"ml-4px text-10px line-through"
class=
"ml-4px text-10px line-through"
:style=
"
{ color: property.fields.marketPrice.color }"
:style=
"
{ color: property.fields.marketPrice.color }"
>¥
{{
fenToYuan
(
spu
.
marketPrice
)
}}
</span
>¥
{{
fenToYuan
(
spu
.
marketPrice
)
}}
</span
>
>
</div>
</div>
<div
class=
"text-12px"
>
<div
class=
"text-12px"
>
<!-- 销量 -->
<!-- 销量 -->
<span
<span
v-if=
"property.fields.salesCount.show"
v-if=
"property.fields.salesCount.show"
:style=
"
{ color: property.fields.salesCount.color }"
:style=
"
{ color: property.fields.salesCount.color }"
>
>
已售
{{
(
spu
.
salesCount
||
0
)
+
(
spu
.
virtualSalesCount
||
0
)
}}
件
已售
{{
(
spu
.
salesCount
||
0
)
+
(
spu
.
virtualSalesCount
||
0
)
}}
件
</span>
</span>
...
@@ -95,9 +95,9 @@
...
@@ -95,9 +95,9 @@
<div
class=
"absolute bottom-8px right-8px"
>
<div
class=
"absolute bottom-8px right-8px"
>
<!-- 文字按钮 -->
<!-- 文字按钮 -->
<span
<span
v-if=
"property.btnBuy.type === 'text'"
v-if=
"property.btnBuy.type === 'text'"
class=
"rounded-full p-x-12px p-y-4px text-12px text-white"
class=
"rounded-full p-x-12px p-y-4px text-12px text-white"
:style=
"
{
:style=
"
{
background: `linear-gradient(to right, ${property.btnBuy.bgBeginColor}, ${property.btnBuy.bgEndColor}`
background: `linear-gradient(to right, ${property.btnBuy.bgBeginColor}, ${property.btnBuy.bgEndColor}`
}"
}"
>
>
...
@@ -105,77 +105,80 @@
...
@@ -105,77 +105,80 @@
</span>
</span>
<!-- 图片按钮 -->
<!-- 图片按钮 -->
<el-image
<el-image
v-else
v-else
class=
"h-28px w-28px rounded-full"
class=
"h-28px w-28px rounded-full"
fit=
"cover"
fit=
"cover"
:src=
"property.btnBuy.imgUrl"
:src=
"property.btnBuy.imgUrl"
/>
/>
</div>
</div>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
PromotionCombinationProperty
}
from
'./config'
import
{
PromotionCombinationProperty
}
from
'./config'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
ProductSpuApi
from
'@/api/mall/product/spu'
import
*
as
CombinationActivityApi
from
'@/api/mall/promotion/combination/combinationActivity'
import
*
as
CombinationActivityApi
from
'@/api/mall/promotion/combination/combinationActivity'
import
{
fenToYuan
}
from
"@/utils"
;
import
{
fenToYuan
}
from
'@/utils'
/** 拼团卡片 */
/** 拼团卡片 */
defineOptions
({
name
:
'PromotionCombination'
})
defineOptions
({
name
:
'PromotionCombination'
})
// 定义属性
// 定义属性
const
props
=
defineProps
<
{
property
:
PromotionCombinationProperty
}
>
()
;
const
props
=
defineProps
<
{
property
:
PromotionCombinationProperty
}
>
()
// 商品列表
// 商品列表
const
spuList
=
ref
<
ProductSpuApi
.
Spu
[]
>
([])
;
const
spuList
=
ref
<
ProductSpuApi
.
Spu
[]
>
([])
const
spuIdList
=
ref
<
number
[]
>
([])
;
const
spuIdList
=
ref
<
number
[]
>
([])
const
combinationActivityList
=
ref
<
CombinationActivityApi
.
CombinationActivityVO
[]
>
([])
;
const
combinationActivityList
=
ref
<
CombinationActivityApi
.
CombinationActivityVO
[]
>
([])
watch
(
watch
(
()
=>
props
.
property
.
activityIds
,
()
=>
props
.
property
.
activityIds
,
async
()
=>
{
async
()
=>
{
try
{
try
{
// 新添加的拼团组件,是没有活动ID的
// 新添加的拼团组件,是没有活动ID的
const
activityIds
=
props
.
property
.
activityIds
;
const
activityIds
=
props
.
property
.
activityIds
// 检查活动ID的有效性
// 检查活动ID的有效性
if
(
Array
.
isArray
(
activityIds
)
&&
activityIds
.
length
>
0
&&
activityIds
.
every
(
item
=>
item
!=
null
))
{
if
(
// 获取拼团活动详情列表
Array
.
isArray
(
activityIds
)
&&
combinationActivityList
.
value
=
await
CombinationActivityApi
.
getCombinationActivityDetailList
(
activityIds
);
activityIds
.
length
>
0
&&
activityIds
.
every
((
item
)
=>
item
!=
null
)
)
{
// 获取拼团活动详情列表
combinationActivityList
.
value
=
await
CombinationActivityApi
.
getCombinationActivityDetailList
(
activityIds
)
// 清空之前的数据,防止有重复
// 清空之前的数据,防止有重复
spuIdList
.
value
=
[];
spuIdList
.
value
=
[]
spuList
.
value
=
[];
spuList
.
value
=
[]
// 生成有效的 spuId 列表
// 生成有效的 spuId 列表
spuIdList
.
value
=
combinationActivityList
.
value
spuIdList
.
value
=
combinationActivityList
.
value
.
map
(
activity
=>
activity
.
spuId
)
.
map
((
activity
)
=>
activity
.
spuId
)
.
filter
((
spuId
):
spuId
is
number
=>
typeof
spuId
===
'number'
);
.
filter
((
spuId
):
spuId
is
number
=>
typeof
spuId
===
'number'
)
// 如果存在有效的 spuId,调用 API 获取详细信息
// 如果存在有效的 spuId,调用 API 获取详细信息
if
(
spuIdList
.
value
.
length
>
0
)
{
if
(
spuIdList
.
value
.
length
>
0
)
{
spuList
.
value
=
await
ProductSpuApi
.
getSpuDetailList
(
spuIdList
.
value
);
spuList
.
value
=
await
ProductSpuApi
.
getSpuDetailList
(
spuIdList
.
value
)
}
else
{
}
else
{
console
.
warn
(
'没有用于获取详细信息的有效 spuId。'
);
console
.
warn
(
'没有用于获取详细信息的有效 spuId。'
)
}
// 更新 SPU 的最低价格
combinationActivityList
.
value
.
forEach
(
activity
=>
{
activity
.
products
.
forEach
(
product
=>
{
const
spu
=
spuList
.
value
.
find
(
spu
=>
spu
.
id
===
product
.
spuId
);
if
(
spu
)
{
spu
.
price
=
Math
.
min
(
product
.
combinationPrice
||
Infinity
,
spu
.
price
||
Infinity
);
}
});
});
}
}
}
catch
(
error
)
{
// 更新 SPU 的最低价格
console
.
error
(
'获取拼团活动细节或 SPU 细节时出错:'
,
error
);
combinationActivityList
.
value
.
forEach
((
activity
)
=>
{
activity
.
products
.
forEach
((
product
)
=>
{
const
spu
=
spuList
.
value
.
find
((
spu
)
=>
spu
.
id
===
product
.
spuId
)
if
(
spu
)
{
spu
.
price
=
Math
.
min
(
product
.
combinationPrice
||
Infinity
,
spu
.
price
||
Infinity
)
}
})
})
}
}
},
}
catch
(
error
)
{
{
console
.
error
(
'获取拼团活动细节或 SPU 细节时出错:'
,
error
)
immediate
:
true
,
deep
:
true
}
}
);
},
{
immediate
:
true
,
deep
:
true
}
)
/**
/**
* 计算商品的间距
* 计算商品的间距
...
@@ -189,7 +192,7 @@ const calculateSpace = (index: number) => {
...
@@ -189,7 +192,7 @@ const calculateSpace = (index: number) => {
// 第一行没有上边距
// 第一行没有上边距
const
marginTop
=
index
<
columns
?
'0'
:
props
.
property
.
space
+
'px'
const
marginTop
=
index
<
columns
?
'0'
:
props
.
property
.
space
+
'px'
return
{
marginLeft
,
marginTop
}
return
{
marginLeft
,
marginTop
}
}
}
// 容器
// 容器
...
@@ -201,7 +204,7 @@ const calculateWidth = () => {
...
@@ -201,7 +204,7 @@ const calculateWidth = () => {
if
(
props
.
property
.
layoutType
===
'twoCol'
)
{
if
(
props
.
property
.
layoutType
===
'twoCol'
)
{
width
=
`
${(
containerRef
.
value
.
offsetWidth
-
props
.
property
.
space
)
/
2
}
px`
width
=
`
${(
containerRef
.
value
.
offsetWidth
-
props
.
property
.
space
)
/
2
}
px`
}
}
return
{
width
}
return
{
width
}
}
}
</
script
>
</
script
>
...
...
src/components/DiyEditor/components/mobile/PromotionCombination/property.vue
View file @
4870231b
...
@@ -2,24 +2,24 @@
...
@@ -2,24 +2,24 @@
<ComponentContainerProperty
v-model=
"formData.style"
>
<ComponentContainerProperty
v-model=
"formData.style"
>
<el-form
label-width=
"80px"
:model=
"formData"
>
<el-form
label-width=
"80px"
:model=
"formData"
>
<el-card
header=
"拼团活动"
class=
"property-group"
shadow=
"never"
>
<el-card
header=
"拼团活动"
class=
"property-group"
shadow=
"never"
>
<CombinationShowcase
v-model=
"formData.activityIds"
/>
<CombinationShowcase
v-model=
"formData.activityIds"
/>
</el-card>
</el-card>
<el-card
header=
"商品样式"
class=
"property-group"
shadow=
"never"
>
<el-card
header=
"商品样式"
class=
"property-group"
shadow=
"never"
>
<el-form-item
label=
"布局"
prop=
"type"
>
<el-form-item
label=
"布局"
prop=
"type"
>
<el-radio-group
v-model=
"formData.layoutType"
>
<el-radio-group
v-model=
"formData.layoutType"
>
<el-tooltip
class=
"item"
content=
"单列大图"
placement=
"bottom"
>
<el-tooltip
class=
"item"
content=
"单列大图"
placement=
"bottom"
>
<el-radio-button
value=
"oneColBigImg"
>
<el-radio-button
value=
"oneColBigImg"
>
<Icon
icon=
"fluent:text-column-one-24-filled"
/>
<Icon
icon=
"fluent:text-column-one-24-filled"
/>
</el-radio-button>
</el-radio-button>
</el-tooltip>
</el-tooltip>
<el-tooltip
class=
"item"
content=
"单列小图"
placement=
"bottom"
>
<el-tooltip
class=
"item"
content=
"单列小图"
placement=
"bottom"
>
<el-radio-button
value=
"oneColSmallImg"
>
<el-radio-button
value=
"oneColSmallImg"
>
<Icon
icon=
"fluent:text-column-two-left-24-filled"
/>
<Icon
icon=
"fluent:text-column-two-left-24-filled"
/>
</el-radio-button>
</el-radio-button>
</el-tooltip>
</el-tooltip>
<el-tooltip
class=
"item"
content=
"双列"
placement=
"bottom"
>
<el-tooltip
class=
"item"
content=
"双列"
placement=
"bottom"
>
<el-radio-button
value=
"twoCol"
>
<el-radio-button
value=
"twoCol"
>
<Icon
icon=
"fluent:text-column-two-24-filled"
/>
<Icon
icon=
"fluent:text-column-two-24-filled"
/>
</el-radio-button>
</el-radio-button>
</el-tooltip>
</el-tooltip>
<!--
<el-tooltip
class=
"item"
content=
"三列"
placement=
"bottom"
>
<!--
<el-tooltip
class=
"item"
content=
"三列"
placement=
"bottom"
>
...
@@ -31,44 +31,44 @@
...
@@ -31,44 +31,44 @@
</el-form-item>
</el-form-item>
<el-form-item
label=
"商品名称"
prop=
"fields.name.show"
>
<el-form-item
label=
"商品名称"
prop=
"fields.name.show"
>
<div
class=
"flex gap-8px"
>
<div
class=
"flex gap-8px"
>
<ColorInput
v-model=
"formData.fields.name.color"
/>
<ColorInput
v-model=
"formData.fields.name.color"
/>
<el-checkbox
v-model=
"formData.fields.name.show"
/>
<el-checkbox
v-model=
"formData.fields.name.show"
/>
</div>
</div>
</el-form-item>
</el-form-item>
<el-form-item
label=
"商品简介"
prop=
"fields.introduction.show"
>
<el-form-item
label=
"商品简介"
prop=
"fields.introduction.show"
>
<div
class=
"flex gap-8px"
>
<div
class=
"flex gap-8px"
>
<ColorInput
v-model=
"formData.fields.introduction.color"
/>
<ColorInput
v-model=
"formData.fields.introduction.color"
/>
<el-checkbox
v-model=
"formData.fields.introduction.show"
/>
<el-checkbox
v-model=
"formData.fields.introduction.show"
/>
</div>
</div>
</el-form-item>
</el-form-item>
<el-form-item
label=
"商品价格"
prop=
"fields.price.show"
>
<el-form-item
label=
"商品价格"
prop=
"fields.price.show"
>
<div
class=
"flex gap-8px"
>
<div
class=
"flex gap-8px"
>
<ColorInput
v-model=
"formData.fields.price.color"
/>
<ColorInput
v-model=
"formData.fields.price.color"
/>
<el-checkbox
v-model=
"formData.fields.price.show"
/>
<el-checkbox
v-model=
"formData.fields.price.show"
/>
</div>
</div>
</el-form-item>
</el-form-item>
<el-form-item
label=
"市场价"
prop=
"fields.marketPrice.show"
>
<el-form-item
label=
"市场价"
prop=
"fields.marketPrice.show"
>
<div
class=
"flex gap-8px"
>
<div
class=
"flex gap-8px"
>
<ColorInput
v-model=
"formData.fields.marketPrice.color"
/>
<ColorInput
v-model=
"formData.fields.marketPrice.color"
/>
<el-checkbox
v-model=
"formData.fields.marketPrice.show"
/>
<el-checkbox
v-model=
"formData.fields.marketPrice.show"
/>
</div>
</div>
</el-form-item>
</el-form-item>
<el-form-item
label=
"商品销量"
prop=
"fields.salesCount.show"
>
<el-form-item
label=
"商品销量"
prop=
"fields.salesCount.show"
>
<div
class=
"flex gap-8px"
>
<div
class=
"flex gap-8px"
>
<ColorInput
v-model=
"formData.fields.salesCount.color"
/>
<ColorInput
v-model=
"formData.fields.salesCount.color"
/>
<el-checkbox
v-model=
"formData.fields.salesCount.show"
/>
<el-checkbox
v-model=
"formData.fields.salesCount.show"
/>
</div>
</div>
</el-form-item>
</el-form-item>
<el-form-item
label=
"商品库存"
prop=
"fields.stock.show"
>
<el-form-item
label=
"商品库存"
prop=
"fields.stock.show"
>
<div
class=
"flex gap-8px"
>
<div
class=
"flex gap-8px"
>
<ColorInput
v-model=
"formData.fields.stock.color"
/>
<ColorInput
v-model=
"formData.fields.stock.color"
/>
<el-checkbox
v-model=
"formData.fields.stock.show"
/>
<el-checkbox
v-model=
"formData.fields.stock.show"
/>
</div>
</div>
</el-form-item>
</el-form-item>
</el-card>
</el-card>
<el-card
header=
"角标"
class=
"property-group"
shadow=
"never"
>
<el-card
header=
"角标"
class=
"property-group"
shadow=
"never"
>
<el-form-item
label=
"角标"
prop=
"badge.show"
>
<el-form-item
label=
"角标"
prop=
"badge.show"
>
<el-switch
v-model=
"formData.badge.show"
/>
<el-switch
v-model=
"formData.badge.show"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"角标"
prop=
"badge.imgUrl"
v-if=
"formData.badge.show"
>
<el-form-item
label=
"角标"
prop=
"badge.imgUrl"
v-if=
"formData.badge.show"
>
<UploadImg
v-model=
"formData.badge.imgUrl"
height=
"44px"
width=
"72px"
>
<UploadImg
v-model=
"formData.badge.imgUrl"
height=
"44px"
width=
"72px"
>
...
@@ -85,13 +85,13 @@
...
@@ -85,13 +85,13 @@
</el-form-item>
</el-form-item>
<
template
v-if=
"formData.btnBuy.type === 'text'"
>
<
template
v-if=
"formData.btnBuy.type === 'text'"
>
<el-form-item
label=
"按钮文字"
prop=
"btnBuy.text"
>
<el-form-item
label=
"按钮文字"
prop=
"btnBuy.text"
>
<el-input
v-model=
"formData.btnBuy.text"
/>
<el-input
v-model=
"formData.btnBuy.text"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"左侧背景"
prop=
"btnBuy.bgBeginColor"
>
<el-form-item
label=
"左侧背景"
prop=
"btnBuy.bgBeginColor"
>
<ColorInput
v-model=
"formData.btnBuy.bgBeginColor"
/>
<ColorInput
v-model=
"formData.btnBuy.bgBeginColor"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"右侧背景"
prop=
"btnBuy.bgEndColor"
>
<el-form-item
label=
"右侧背景"
prop=
"btnBuy.bgEndColor"
>
<ColorInput
v-model=
"formData.btnBuy.bgEndColor"
/>
<ColorInput
v-model=
"formData.btnBuy.bgEndColor"
/>
</el-form-item>
</el-form-item>
</
template
>
</
template
>
<
template
v-else
>
<
template
v-else
>
...
@@ -105,32 +105,32 @@
...
@@ -105,32 +105,32 @@
<el-card
header=
"商品样式"
class=
"property-group"
shadow=
"never"
>
<el-card
header=
"商品样式"
class=
"property-group"
shadow=
"never"
>
<el-form-item
label=
"上圆角"
prop=
"borderRadiusTop"
>
<el-form-item
label=
"上圆角"
prop=
"borderRadiusTop"
>
<el-slider
<el-slider
v-model=
"formData.borderRadiusTop"
v-model=
"formData.borderRadiusTop"
:max=
"100"
:max=
"100"
:min=
"0"
:min=
"0"
show-input
show-input
input-size=
"small"
input-size=
"small"
:show-input-controls=
"false"
:show-input-controls=
"false"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"下圆角"
prop=
"borderRadiusBottom"
>
<el-form-item
label=
"下圆角"
prop=
"borderRadiusBottom"
>
<el-slider
<el-slider
v-model=
"formData.borderRadiusBottom"
v-model=
"formData.borderRadiusBottom"
:max=
"100"
:max=
"100"
:min=
"0"
:min=
"0"
show-input
show-input
input-size=
"small"
input-size=
"small"
:show-input-controls=
"false"
:show-input-controls=
"false"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"间隔"
prop=
"space"
>
<el-form-item
label=
"间隔"
prop=
"space"
>
<el-slider
<el-slider
v-model=
"formData.space"
v-model=
"formData.space"
:max=
"100"
:max=
"100"
:min=
"0"
:min=
"0"
show-input
show-input
input-size=
"small"
input-size=
"small"
:show-input-controls=
"false"
:show-input-controls=
"false"
/>
/>
</el-form-item>
</el-form-item>
</el-card>
</el-card>
...
@@ -139,26 +139,26 @@
...
@@ -139,26 +139,26 @@
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
PromotionCombinationProperty
}
from
'./config'
import
{
PromotionCombinationProperty
}
from
'./config'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
{
usePropertyForm
}
from
'@/components/DiyEditor/util'
import
*
as
CombinationActivityApi
from
'@/api/mall/promotion/combination/combinationActivity'
import
*
as
CombinationActivityApi
from
'@/api/mall/promotion/combination/combinationActivity'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
import
CombinationShowcase
from
"@/views/mall/promotion/combination/components/CombinationShowcase.vue"
;
import
CombinationShowcase
from
'@/views/mall/promotion/combination/components/CombinationShowcase.vue'
// 拼团属性面板
// 拼团属性面板
defineOptions
({
name
:
'PromotionCombinationProperty'
})
defineOptions
({
name
:
'PromotionCombinationProperty'
})
const
props
=
defineProps
<
{
modelValue
:
PromotionCombinationProperty
}
>
()
const
props
=
defineProps
<
{
modelValue
:
PromotionCombinationProperty
}
>
()
const
emit
=
defineEmits
([
'update:modelValue'
])
const
emit
=
defineEmits
([
'update:modelValue'
])
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
const
{
formData
}
=
usePropertyForm
(
props
.
modelValue
,
emit
)
// 活动列表
// 活动列表
const
activityList
=
ref
<
CombinationActivityApi
.
CombinationActivityVO
[]
>
([])
const
activityList
=
ref
<
CombinationActivityApi
.
CombinationActivityVO
[]
>
([])
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
const
{
list
}
=
await
CombinationActivityApi
.
getCombinationActivityPage
({
const
{
list
}
=
await
CombinationActivityApi
.
getCombinationActivityPage
({
status
:
CommonStatusEnum
.
ENABLE
status
:
CommonStatusEnum
.
ENABLE
})
})
activityList
.
value
=
list
activityList
.
value
=
list
console
.
log
(
"formDa"
,
props
);
console
.
log
(
'formDa'
,
props
)
})
})
</
script
>
</
script
>
...
...
src/components/DiyEditor/index.vue
View file @
4870231b
...
@@ -153,7 +153,11 @@
...
@@ -153,7 +153,11 @@
>
>
<!--这里的 key 使用时间戳是为了保证每次点击组件都进行刷新-->
<!--这里的 key 使用时间戳是为了保证每次点击组件都进行刷新-->
<component
<component
:key=
"selectedComponent?.uid || selectedComponent?.id + new Date().getTime() || new Date().getTime().toString()"
:key=
"
selectedComponent?.uid ||
selectedComponent?.id + new Date().getTime() ||
new Date().getTime().toString()
"
:is=
"selectedComponent?.id + 'Property'"
:is=
"selectedComponent?.id + 'Property'"
v-model=
"selectedComponent.property"
v-model=
"selectedComponent.property"
/>
/>
...
...
src/views/mall/promotion/combination/components/CombinationShowcase.vue
View file @
4870231b
<
template
>
<
template
>
<div
class=
"flex flex-wrap items-center gap-8px"
>
<div
class=
"flex flex-wrap items-center gap-8px"
>
<div
<div
v-for=
"(combinationActivity, index) in Activitys"
v-for=
"(combinationActivity, index) in Activitys"
:key=
"combinationActivity.id"
:key=
"combinationActivity.id"
class=
"select-box spu-pic"
>
class=
"select-box spu-pic"
>
<el-tooltip
:content=
"combinationActivity.name"
>
<el-tooltip
:content=
"combinationActivity.name"
>
<div
class=
"relative h-full w-full"
>
<div
class=
"relative h-full w-full"
>
<el-image
:src=
"combinationActivity.picUrl"
class=
"h-full w-full"
/>
<el-image
:src=
"combinationActivity.picUrl"
class=
"h-full w-full"
/>
<Icon
<Icon
v-show=
"!disabled"
v-show=
"!disabled"
class=
"del-icon"
class=
"del-icon"
icon=
"ep:circle-close-filled"
icon=
"ep:circle-close-filled"
@
click=
"handleRemoveActivity(index)"
@
click=
"handleRemoveActivity(index)"
/>
/>
</div>
</div>
</el-tooltip>
</el-tooltip>
</div>
</div>
<el-tooltip
content=
"选择活动"
v-if=
"canAdd"
>
<el-tooltip
content=
"选择活动"
v-if=
"canAdd"
>
<div
class=
"select-box"
@
click=
"openCombinationActivityTableSelect"
>
<div
class=
"select-box"
@
click=
"openCombinationActivityTableSelect"
>
<Icon
icon=
"ep:plus"
/>
<Icon
icon=
"ep:plus"
/>
</div>
</div>
</el-tooltip>
</el-tooltip>
</div>
</div>
<!-- 拼团活动选择对话框(表格形式) -->
<!-- 拼团活动选择对话框(表格形式) -->
<CombinationTableSelect
ref=
"combinationActivityTableSelectRef"
:multiple=
"limit != 1"
<CombinationTableSelect
@
change=
"handleActivitySelected"
/>
ref=
"combinationActivityTableSelectRef"
:multiple=
"limit != 1"
@
change=
"handleActivitySelected"
/>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
*
as
CombinationActivityApi
from
'@/api/mall/promotion/combination/combinationActivity'
import
*
as
CombinationActivityApi
from
'@/api/mall/promotion/combination/combinationActivity'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
oneOfType
}
from
'vue-types'
import
{
oneOfType
}
from
'vue-types'
import
{
isArray
}
from
'@/utils/is'
import
{
isArray
}
from
'@/utils/is'
import
CombinationTableSelect
from
"@/views/mall/promotion/combination/components/CombinationTableSelect.vue"
;
import
CombinationTableSelect
from
'@/views/mall/promotion/combination/components/CombinationTableSelect.vue'
// 活动橱窗,一般用于装修时使用
// 活动橱窗,一般用于装修时使用
// 提供功能:展示活动列表、添加活动、删除活动
// 提供功能:展示活动列表、添加活动、删除活动
defineOptions
({
name
:
'CombinationShowcase'
})
defineOptions
({
name
:
'CombinationShowcase'
})
const
props
=
defineProps
({
const
props
=
defineProps
({
modelValue
:
oneOfType
<
number
|
Array
<
number
>>
([
Number
,
Array
]).
isRequired
,
modelValue
:
oneOfType
<
number
|
Array
<
number
>>
([
Number
,
Array
]).
isRequired
,
...
@@ -58,26 +62,29 @@ const canAdd = computed(() => {
...
@@ -58,26 +62,29 @@ const canAdd = computed(() => {
const
Activitys
=
ref
<
CombinationActivityApi
.
CombinationActivityVO
[]
>
([])
const
Activitys
=
ref
<
CombinationActivityApi
.
CombinationActivityVO
[]
>
([])
watch
(
watch
(
()
=>
props
.
modelValue
,
()
=>
props
.
modelValue
,
async
()
=>
{
async
()
=>
{
const
ids
=
isArray
(
props
.
modelValue
)
const
ids
=
isArray
(
props
.
modelValue
)
?
// 情况一:多选
?
// 情况一:多选
props
.
modelValue
props
.
modelValue
:
// 情况二:单选
:
// 情况二:单选
props
.
modelValue
props
.
modelValue
?
[
props
.
modelValue
]
?
[
props
.
modelValue
]
:
[]
:
[]
// 不需要返显
// 不需要返显
if
(
ids
.
length
===
0
)
{
if
(
ids
.
length
===
0
)
{
Activitys
.
value
=
[]
Activitys
.
value
=
[]
return
return
}
}
// 只有活动发生变化之后,才会查询活动
// 只有活动发生变化之后,才会查询活动
if
(
Activitys
.
value
.
length
===
0
||
Activitys
.
value
.
some
((
combinationActivity
)
=>
!
ids
.
includes
(
combinationActivity
.
id
!
)))
{
if
(
Activitys
.
value
=
await
CombinationActivityApi
.
getCombinationActivityDetailList
(
ids
)
Activitys
.
value
.
length
===
0
||
}
Activitys
.
value
.
some
((
combinationActivity
)
=>
!
ids
.
includes
(
combinationActivity
.
id
!
))
},
)
{
{
immediate
:
true
}
Activitys
.
value
=
await
CombinationActivityApi
.
getCombinationActivityDetailList
(
ids
)
}
},
{
immediate
:
true
}
)
)
/** 活动表格选择对话框 */
/** 活动表格选择对话框 */
...
@@ -91,7 +98,11 @@ const openCombinationActivityTableSelect = () => {
...
@@ -91,7 +98,11 @@ const openCombinationActivityTableSelect = () => {
* 选择活动后触发
* 选择活动后触发
* @param activityVOs 选中的活动列表
* @param activityVOs 选中的活动列表
*/
*/
const
handleActivitySelected
=
(
activityVOs
:
CombinationActivityApi
.
CombinationActivityVO
|
CombinationActivityApi
.
CombinationActivityVO
[])
=>
{
const
handleActivitySelected
=
(
activityVOs
:
|
CombinationActivityApi
.
CombinationActivityVO
|
CombinationActivityApi
.
CombinationActivityVO
[]
)
=>
{
Activitys
.
value
=
isArray
(
activityVOs
)
?
activityVOs
:
[
activityVOs
]
Activitys
.
value
=
isArray
(
activityVOs
)
?
activityVOs
:
[
activityVOs
]
emitActivityChange
()
emitActivityChange
()
}
}
...
@@ -112,8 +123,8 @@ const emitActivityChange = () => {
...
@@ -112,8 +123,8 @@ const emitActivityChange = () => {
emit
(
'change'
,
combinationActivity
)
emit
(
'change'
,
combinationActivity
)
}
else
{
}
else
{
emit
(
emit
(
'update:modelValue'
,
'update:modelValue'
,
Activitys
.
value
.
map
((
combinationActivity
)
=>
combinationActivity
.
id
)
Activitys
.
value
.
map
((
combinationActivity
)
=>
combinationActivity
.
id
)
)
)
emit
(
'change'
,
Activitys
.
value
)
emit
(
'change'
,
Activitys
.
value
)
}
}
...
...
src/views/mall/promotion/combination/components/CombinationTableSelect.vue
View file @
4870231b
...
@@ -3,43 +3,43 @@
...
@@ -3,43 +3,43 @@
<ContentWrap>
<ContentWrap>
<!-- 搜索工作栏 -->
<!-- 搜索工作栏 -->
<el-form
<el-form
ref=
"queryFormRef"
ref=
"queryFormRef"
:inline=
"true"
:inline=
"true"
:model=
"queryParams"
:model=
"queryParams"
class=
"-mb-15px"
class=
"-mb-15px"
label-width=
"68px"
label-width=
"68px"
>
>
<el-form-item
label=
"活动名称"
prop=
"name"
>
<el-form-item
label=
"活动名称"
prop=
"name"
>
<el-input
<el-input
v-model=
"queryParams.name"
v-model=
"queryParams.name"
placeholder=
"请输入活动名称"
placeholder=
"请输入活动名称"
clearable
clearable
@
keyup
.
enter=
"handleQuery"
@
keyup
.
enter=
"handleQuery"
class=
"!w-240px"
class=
"!w-240px"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"活动状态"
prop=
"status"
>
<el-form-item
label=
"活动状态"
prop=
"status"
>
<el-select
<el-select
v-model=
"queryParams.status"
v-model=
"queryParams.status"
placeholder=
"请选择活动状态"
placeholder=
"请选择活动状态"
clearable
clearable
class=
"!w-240px"
class=
"!w-240px"
>
>
<el-option
<el-option
v-for=
"dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
v-for=
"dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key=
"dict.value"
:key=
"dict.value"
:label=
"dict.label"
:label=
"dict.label"
:value=
"dict.value"
:value=
"dict.value"
/>
/>
</el-select>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
>
<el-button
@
click=
"handleQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
搜索
</el-button>
</el-button>
<el-button
@
click=
"resetQuery"
>
<el-button
@
click=
"resetQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
重置
</el-button>
</el-button>
</el-form-item>
</el-form-item>
...
@@ -49,29 +49,33 @@
...
@@ -49,29 +49,33 @@
<el-table-column
width=
"55"
v-if=
"multiple"
>
<el-table-column
width=
"55"
v-if=
"multiple"
>
<template
#
header
>
<template
#
header
>
<el-checkbox
<el-checkbox
v-model=
"isCheckAll"
v-model=
"isCheckAll"
:indeterminate=
"isIndeterminate"
:indeterminate=
"isIndeterminate"
@
change=
"handleCheckAll"
@
change=
"handleCheckAll"
/>
/>
</
template
>
</
template
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-checkbox
<el-checkbox
v-model=
"checkedStatus[row.id]"
v-model=
"checkedStatus[row.id]"
@
change=
"(checked: boolean) => handleCheckOne(checked, row, true)"
@
change=
"(checked: boolean) => handleCheckOne(checked, row, true)"
/>
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<!-- 2. 单选模式 -->
<!-- 2. 单选模式 -->
<el-table-column
label=
"#"
width=
"55"
v-else
>
<el-table-column
label=
"#"
width=
"55"
v-else
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-radio
:value=
"row.id"
v-model=
"selectedActivityId"
@
change=
"handleSingleSelected(row)"
>
<el-radio
:value=
"row.id"
v-model=
"selectedActivityId"
@
change=
"handleSingleSelected(row)"
>
<!-- 空格不能省略,是为了让单选框不显示label,如果不指定label不会有选中的效果 -->
<!-- 空格不能省略,是为了让单选框不显示label,如果不指定label不会有选中的效果 -->
</el-radio>
</el-radio>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"活动编号"
prop=
"id"
min-width=
"80"
/>
<el-table-column
label=
"活动编号"
prop=
"id"
min-width=
"80"
/>
<el-table-column
label=
"活动名称"
prop=
"name"
min-width=
"140"
/>
<el-table-column
label=
"活动名称"
prop=
"name"
min-width=
"140"
/>
<el-table-column
label=
"活动时间"
min-width=
"210"
>
<el-table-column
label=
"活动时间"
min-width=
"210"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
{{
formatDate
(
scope
.
row
.
startTime
,
'YYYY-MM-DD'
)
}}
{{
formatDate
(
scope
.
row
.
startTime
,
'YYYY-MM-DD'
)
}}
...
@@ -81,47 +85,47 @@
...
@@ -81,47 +85,47 @@
<el-table-column
label=
"商品图片"
prop=
"spuName"
min-width=
"80"
>
<el-table-column
label=
"商品图片"
prop=
"spuName"
min-width=
"80"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<el-image
<el-image
:src=
"scope.row.picUrl"
:src=
"scope.row.picUrl"
class=
"h-40px w-40px"
class=
"h-40px w-40px"
:preview-src-list=
"[scope.row.picUrl]"
:preview-src-list=
"[scope.row.picUrl]"
preview-teleported
preview-teleported
/>
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"商品标题"
prop=
"spuName"
min-width=
"300"
/>
<el-table-column
label=
"商品标题"
prop=
"spuName"
min-width=
"300"
/>
<el-table-column
<el-table-column
label=
"原价"
label=
"原价"
prop=
"marketPrice"
prop=
"marketPrice"
min-width=
"100"
min-width=
"100"
:formatter=
"fenToYuanFormat"
:formatter=
"fenToYuanFormat"
/>
/>
<el-table-column
label=
"拼团价"
prop=
"seckillPrice"
min-width=
"100"
>
<el-table-column
label=
"拼团价"
prop=
"seckillPrice"
min-width=
"100"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
{{
formatCombinationPrice
(
scope
.
row
.
products
)
}}
{{
formatCombinationPrice
(
scope
.
row
.
products
)
}}
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"开团组数"
prop=
"groupCount"
min-width=
"100"
/>
<el-table-column
label=
"开团组数"
prop=
"groupCount"
min-width=
"100"
/>
<el-table-column
label=
"成团组数"
prop=
"groupSuccessCount"
min-width=
"100"
/>
<el-table-column
label=
"成团组数"
prop=
"groupSuccessCount"
min-width=
"100"
/>
<el-table-column
label=
"购买次数"
prop=
"recordCount"
min-width=
"100"
/>
<el-table-column
label=
"购买次数"
prop=
"recordCount"
min-width=
"100"
/>
<el-table-column
label=
"活动状态"
align=
"center"
prop=
"status"
min-width=
"100"
>
<el-table-column
label=
"活动状态"
align=
"center"
prop=
"status"
min-width=
"100"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.COMMON_STATUS"
:value=
"scope.row.status"
/>
<dict-tag
:type=
"DICT_TYPE.COMMON_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
<el-table-column
label=
"创建时间"
label=
"创建时间"
align=
"center"
align=
"center"
prop=
"createTime"
prop=
"createTime"
:formatter=
"dateFormatter"
:formatter=
"dateFormatter"
width=
"180px"
width=
"180px"
/>
/>
</el-table>
</el-table>
<!-- 分页 -->
<!-- 分页 -->
<Pagination
<Pagination
v-model:limit=
"queryParams.pageSize"
v-model:limit=
"queryParams.pageSize"
v-model:page=
"queryParams.pageNo"
v-model:page=
"queryParams.pageNo"
:total=
"total"
:total=
"total"
@
pagination=
"getList"
@
pagination=
"getList"
/>
/>
</ContentWrap>
</ContentWrap>
<
template
#
footer
v-if=
"multiple"
>
<
template
#
footer
v-if=
"multiple"
>
...
@@ -132,16 +136,16 @@
...
@@ -132,16 +136,16 @@
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
handleTree
}
from
'@/utils/tree'
import
{
handleTree
}
from
'@/utils/tree'
import
*
as
ProductCategoryApi
from
'@/api/mall/product/category'
import
*
as
ProductCategoryApi
from
'@/api/mall/product/category'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
CHANGE_EVENT
}
from
'element-plus'
import
{
CHANGE_EVENT
}
from
'element-plus'
import
*
as
CombinationActivityApi
from
"@/api/mall/promotion/combination/combinationActivity"
;
import
*
as
CombinationActivityApi
from
'@/api/mall/promotion/combination/combinationActivity'
import
{
fenToYuanFormat
}
from
"@/utils/formatter"
;
import
{
fenToYuanFormat
}
from
'@/utils/formatter'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
"@/utils/dict"
;
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
,
formatDate
}
from
"@/utils/formatTime"
;
import
{
dateFormatter
,
formatDate
}
from
'@/utils/formatTime'
import
{
fenToYuan
}
from
"@/utils"
;
import
{
fenToYuan
}
from
'@/utils'
type
CombinationActivityVO
=
Required
<
CombinationActivityApi
.
CombinationActivityVO
>
type
CombinationActivityVO
=
Required
<
CombinationActivityApi
.
CombinationActivityVO
>
...
@@ -156,7 +160,7 @@ type CombinationActivityVO = Required<CombinationActivityApi.CombinationActivity
...
@@ -156,7 +160,7 @@ type CombinationActivityVO = Required<CombinationActivityApi.CombinationActivity
* 2.3 点击右下角的确定按钮时,结束选择,关闭对话框
* 2.3 点击右下角的确定按钮时,结束选择,关闭对话框
* 2.4 再次打开时,保持选中状态
* 2.4 再次打开时,保持选中状态
*/
*/
defineOptions
({
name
:
'CombinationTableSelect'
})
defineOptions
({
name
:
'CombinationTableSelect'
})
defineProps
({
defineProps
({
// 多选模式
// 多选模式
...
@@ -190,14 +194,16 @@ const open = (CombinationList?: CombinationActivityVO[]) => {
...
@@ -190,14 +194,16 @@ const open = (CombinationList?: CombinationActivityVO[]) => {
// 处理已选中
// 处理已选中
if
(
CombinationList
&&
CombinationList
.
length
>
0
)
{
if
(
CombinationList
&&
CombinationList
.
length
>
0
)
{
checkedActivitys
.
value
=
[...
CombinationList
]
checkedActivitys
.
value
=
[...
CombinationList
]
checkedStatus
.
value
=
Object
.
fromEntries
(
CombinationList
.
map
((
activityVO
)
=>
[
activityVO
.
id
,
true
]))
checkedStatus
.
value
=
Object
.
fromEntries
(
CombinationList
.
map
((
activityVO
)
=>
[
activityVO
.
id
,
true
])
)
}
}
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
resetQuery
()
resetQuery
()
}
}
// 提供 open 方法,用于打开弹窗
// 提供 open 方法,用于打开弹窗
defineExpose
({
open
})
defineExpose
({
open
})
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
...
@@ -208,7 +214,8 @@ const getList = async () => {
...
@@ -208,7 +214,8 @@ const getList = async () => {
total
.
value
=
data
.
total
total
.
value
=
data
.
total
// checkbox绑定undefined会有问题,需要给一个bool值
// checkbox绑定undefined会有问题,需要给一个bool值
list
.
value
.
forEach
(
list
.
value
.
forEach
(
(
activityVO
)
=>
(
checkedStatus
.
value
[
activityVO
.
id
]
=
checkedStatus
.
value
[
activityVO
.
id
]
||
false
)
(
activityVO
)
=>
(
checkedStatus
.
value
[
activityVO
.
id
]
=
checkedStatus
.
value
[
activityVO
.
id
]
||
false
)
)
)
// 计算全选框状态
// 计算全选框状态
calculateIsCheckAll
()
calculateIsCheckAll
()
...
@@ -289,7 +296,11 @@ const handleCheckAll = (checked: boolean) => {
...
@@ -289,7 +296,11 @@ const handleCheckAll = (checked: boolean) => {
* @param combinationActivity 活动
* @param combinationActivity 活动
* @param isCalcCheckAll 是否计算全选
* @param isCalcCheckAll 是否计算全选
*/
*/
const
handleCheckOne
=
(
checked
:
boolean
,
combinationActivity
:
CombinationActivityVO
,
isCalcCheckAll
:
boolean
)
=>
{
const
handleCheckOne
=
(
checked
:
boolean
,
combinationActivity
:
CombinationActivityVO
,
isCalcCheckAll
:
boolean
)
=>
{
if
(
checked
)
{
if
(
checked
)
{
checkedActivitys
.
value
.
push
(
combinationActivity
)
checkedActivitys
.
value
.
push
(
combinationActivity
)
checkedStatus
.
value
[
combinationActivity
.
id
]
=
true
checkedStatus
.
value
[
combinationActivity
.
id
]
=
true
...
@@ -309,13 +320,15 @@ const handleCheckOne = (checked: boolean, combinationActivity: CombinationActivi
...
@@ -309,13 +320,15 @@ const handleCheckOne = (checked: boolean, combinationActivity: CombinationActivi
}
}
// 查找活动在已选中活动列表中的索引
// 查找活动在已选中活动列表中的索引
const
findCheckedIndex
=
(
activityVO
:
CombinationActivityVO
)
=>
checkedActivitys
.
value
.
findIndex
((
item
)
=>
item
.
id
===
activityVO
.
id
)
const
findCheckedIndex
=
(
activityVO
:
CombinationActivityVO
)
=>
checkedActivitys
.
value
.
findIndex
((
item
)
=>
item
.
id
===
activityVO
.
id
)
// 计算全选框状态
// 计算全选框状态
const
calculateIsCheckAll
=
()
=>
{
const
calculateIsCheckAll
=
()
=>
{
isCheckAll
.
value
=
list
.
value
.
every
((
activityVO
)
=>
checkedStatus
.
value
[
activityVO
.
id
])
isCheckAll
.
value
=
list
.
value
.
every
((
activityVO
)
=>
checkedStatus
.
value
[
activityVO
.
id
])
// 计算中间状态:不是全部选中 && 任意一个选中
// 计算中间状态:不是全部选中 && 任意一个选中
isIndeterminate
.
value
=
!
isCheckAll
.
value
&&
list
.
value
.
some
((
activityVO
)
=>
checkedStatus
.
value
[
activityVO
.
id
])
isIndeterminate
.
value
=
!
isCheckAll
.
value
&&
list
.
value
.
some
((
activityVO
)
=>
checkedStatus
.
value
[
activityVO
.
id
])
}
}
// 分类列表
// 分类列表
...
...
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