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
Unverified
Commit
f2f39c3a
authored
Aug 23, 2024
by
芋道源码
Committed by
Gitee
Aug 23, 2024
Browse files
Options
Browse Files
Download
Plain Diff
!525 【新增】MALL: 满减送活动赠送优惠券(100%)
Merge pull request !525 from puhui999/dev-crm
parents
a02712ca
d81ca6e8
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
159 additions
and
71 deletions
+159
-71
src/api/mall/promotion/coupon/couponTemplate.ts
+1
-1
src/components/UploadFile/src/UploadFile.vue
+21
-4
src/utils/is.ts
+2
-2
src/views/mall/promotion/coupon/components/CouponSelect.vue
+3
-2
src/views/mall/promotion/rewardActivity/RewardForm.vue
+8
-7
src/views/mall/promotion/rewardActivity/components/RewardRule.vue
+24
-13
src/views/mall/promotion/rewardActivity/components/RewardRuleCouponShowcase.vue
+100
-42
No files found.
src/api/mall/promotion/coupon/couponTemplate.ts
View file @
f2f39c3a
...
...
@@ -74,7 +74,7 @@ export function getCouponTemplatePage(params: PageParam) {
}
// 获得优惠劵模板分页
export
function
getCouponTemplateList
(
ids
:
number
[])
{
export
function
getCouponTemplateList
(
ids
:
number
[])
:
Promise
<
CouponTemplateVO
[]
>
{
return
request
.
get
({
url
:
`/promotion/coupon-template/list?ids=
${
ids
}
`
})
...
...
src/components/UploadFile/src/UploadFile.vue
View file @
f2f39c3a
<
template
>
<div
class=
"upload-file"
>
<div
v-if=
"!disabled"
class=
"upload-file"
>
<el-upload
ref=
"uploadRef"
v-model:file-list=
"fileList"
...
...
@@ -20,11 +20,11 @@
class=
"upload-file-uploader"
name=
"file"
>
<el-button
v-if=
"!disabled"
type=
"primary"
>
<el-button
type=
"primary"
>
<Icon
icon=
"ep:upload-filled"
/>
选取文件
</el-button>
<template
v-if=
"isShowTip
&& !disabled
"
#
tip
>
<template
v-if=
"isShowTip"
#
tip
>
<div
style=
"font-size: 8px"
>
大小不超过
<b
style=
"color: #f56c6c"
>
{{
fileSize
}}
MB
</b>
</div>
...
...
@@ -32,7 +32,7 @@
格式为
<b
style=
"color: #f56c6c"
>
{{
fileType
.
join
(
'/'
)
}}
</b>
的文件
</div>
</
template
>
<!-- TODO @puhui999:1)表单展示的时候,位置会偏掉,已发微信
;2)disable 的时候,应该把【删除】按钮也隐藏掉?
-->
<!-- TODO @puhui999:1)表单展示的时候,位置会偏掉,已发微信-->
<
template
#
file=
"row"
>
<div
class=
"flex items-center"
>
<span>
{{
row
.
file
.
name
}}
</span>
...
...
@@ -54,6 +54,18 @@
</
template
>
</el-upload>
</div>
<!-- 上传操作禁用时 -->
<div
v-if=
"disabled"
class=
"upload-file"
>
<div
v-for=
"(file, index) in fileList"
:key=
"index"
class=
"flex items-center file-list-item"
>
<span>
{{ file.name }}
</span>
<div
class=
"ml-10px"
>
<el-link
:href=
"file.url"
:underline=
"false"
download
target=
"_blank"
type=
"primary"
>
下载
</el-link>
</div>
</div>
</div>
</template>
<
script
lang=
"ts"
setup
>
import
{
propTypes
}
from
'@/utils/propTypes'
...
...
@@ -211,4 +223,9 @@ const emitUpdateModelValue = () => {
:deep
(
.ele-upload-list__item-content-action
.el-link
)
{
margin-right
:
10px
;
}
.file-list-item
{
border
:
1px
dashed
var
(
--el-border-color-darker
);
border-radius
:
8px
;
}
</
style
>
src/utils/is.ts
View file @
f2f39c3a
...
...
@@ -18,8 +18,8 @@ export const isObject = (val: any): val is Record<any, any> => {
return
val
!==
null
&&
is
(
val
,
'Object'
)
}
export
const
isEmpty
=
<
T
=
unknown
>
(
val
:
T
):
val
is
T
=>
{
if
(
val
===
null
)
{
export
const
isEmpty
=
(
val
:
any
):
boolean
=>
{
if
(
val
===
null
||
val
===
undefined
||
typeof
val
===
'undefined'
)
{
return
true
}
if
(
isArray
(
val
)
||
isString
(
val
))
{
...
...
src/views/mall/promotion/coupon/components/CouponSelect.vue
View file @
f2f39c3a
...
...
@@ -176,6 +176,7 @@ const queryParams = reactive({
createTime
:
[]
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
selectedCouponList
=
ref
<
CouponTemplateApi
.
CouponTemplateVO
[]
>
([])
// 选择的数据
/** 查询列表 */
const
getList
=
async
()
=>
{
...
...
@@ -214,11 +215,11 @@ const handleSelectionChange = (val: CouponTemplateApi.CouponTemplateVO[]) => {
emit
(
'update:multipleSelection'
,
val
)
return
}
emit
(
'change'
,
val
)
selectedCouponList
.
value
=
val
}
const
submitForm
=
()
=>
{
dialogVisible
.
value
=
false
emit
(
'change'
,
selectedCouponList
.
value
)
}
// TODO @puhui999:提前 todo,先不用改;未来单独成组件,其它模块可以服用;例如说,满减送,可以选择优惠劵;
</
script
>
src/views/mall/promotion/rewardActivity/RewardForm.vue
View file @
f2f39c3a
<
template
>
<Dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"6
0
%"
>
<Dialog
v-model=
"dialogVisible"
:title=
"dialogTitle"
width=
"6
5
%"
>
<el-form
ref=
"formRef"
v-loading=
"formLoading"
...
...
@@ -31,7 +31,7 @@
</el-radio-group>
</el-form-item>
<el-form-item
label=
"优惠设置"
>
<RewardRule
v-model=
"formData"
/>
<RewardRule
ref=
"rewardRuleRef"
v-model=
"formData"
/>
</el-form-item>
<el-form-item
label=
"活动范围"
prop=
"productScope"
>
<el-radio-group
v-model=
"formData.productScope"
>
...
...
@@ -97,7 +97,8 @@ const formRules = reactive({
productSpuIds
:
[{
required
:
true
,
message
:
'商品不能为空'
,
trigger
:
'blur'
}],
productCategoryIds
:
[{
required
:
true
,
message
:
'商品分类不能为空'
,
trigger
:
'blur'
}]
})
const
formRef
=
ref
([])
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
const
rewardRuleRef
=
ref
<
InstanceType
<
typeof
RewardRule
>>
()
// 活动规则 Ref
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
...
...
@@ -126,14 +127,14 @@ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成
const
submitForm
=
async
()
=>
{
// 校验表单
if
(
!
formRef
)
return
// TODO puhui999: 规则校验
// const valid = await formRef.value.validate()
// if (!valid) return
// TODO puhui999: 处理下数据兼容接口
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
// 提交请求
formLoading
.
value
=
true
try
{
// 设置活动规则优惠券
rewardRuleRef
.
value
?.
setRuleCoupon
()
const
data
=
formData
.
value
// 设置商品范围
setProductScopeValues
(
data
)
...
...
src/views/mall/promotion/rewardActivity/components/RewardRule.vue
View file @
f2f39c3a
...
...
@@ -2,13 +2,11 @@
<!-- 满减送活动规则组件 -->
<el-row>
<template
v-if=
"formData.rules"
>
<div
v-for=
"(rule, index) in formData.rules"
:key=
"index"
>
<el-col
:span=
"24"
>
<span
class=
"font-bold"
>
活动层级
{{
index
+
1
}}
</span>
<el-button
v-if=
"index !== 0"
link
type=
"danger"
@
click=
"deleteRule(index)"
>
删除
</el-button>
</el-col>
<el-col
v-for=
"(rule, index) in formData.rules"
:key=
"index"
:span=
"24"
>
<span
class=
"font-bold"
>
活动层级
{{
index
+
1
}}
</span>
<el-button
v-if=
"index !== 0"
link
type=
"danger"
@
click=
"deleteRule(index)"
>
删除
</el-button>
<el-form
ref=
"formRef"
:model=
"rule"
>
<el-form-item
label=
"优惠门槛:"
label-width=
"100px"
prop=
"limit"
>
满
...
...
@@ -65,8 +63,6 @@
积分
</el-form-item>
</el-col>
<!-- 优惠券待处理 也可以参考优惠劵的SpuShowcase-->
<!-- TODO 待实现!-->
<el-col
:span=
"24"
>
<span>
送优惠券:
</span>
<el-switch
...
...
@@ -75,13 +71,17 @@
inactive-text=
"否"
inline-prompt
/>
<RewardRuleCouponShowcase
v-if=
"rule.giveCoupon"
/>
<RewardRuleCouponShowcase
v-if=
"rule.giveCoupon"
ref=
"rewardRuleCouponShowcaseRef"
v-model=
"rule!"
/>
</el-col>
</el-form-item>
</el-form>
</
div
>
</
el-col
>
</
template
>
<el-col
:span=
"24"
>
<el-col
:span=
"24"
class=
"mt-10px"
>
<el-button
type=
"primary"
@
click=
"addRule"
>
添加优惠规则
</el-button>
</el-col>
</el-row>
...
...
@@ -92,6 +92,7 @@ import RewardRuleCouponShowcase from './RewardRuleCouponShowcase.vue'
import
{
RewardActivityVO
}
from
'@/api/mall/promotion/reward/rewardActivity'
import
{
PromotionConditionTypeEnum
}
from
'@/utils/constants'
import
{
useVModel
}
from
'@vueuse/core'
import
{
isEmpty
}
from
'@/utils/is'
const
props
=
defineProps
<
{
modelValue
:
RewardActivityVO
...
...
@@ -103,6 +104,7 @@ const emits = defineEmits<{
}
>
()
const
formData
=
useVModel
(
props
,
'modelValue'
,
emits
)
// 活动数据
const
rewardRuleCouponShowcaseRef
=
ref
<
InstanceType
<
typeof
RewardRuleCouponShowcase
>
[]
>
()
// 活动规则优惠券 Ref
/** 删除优惠规则 */
const
deleteRule
=
(
ruleIndex
:
number
)
=>
{
...
...
@@ -123,7 +125,16 @@ const addRule = () => {
})
}
// TODO puhui999: 规则校验完善
/** 设置规则优惠券-提交时 */
const
setRuleCoupon
=
()
=>
{
if
(
isEmpty
(
rewardRuleCouponShowcaseRef
.
value
))
{
return
}
rewardRuleCouponShowcaseRef
.
value
?.
forEach
((
item
)
=>
item
.
setGiveCouponList
())
}
defineExpose
({
setRuleCoupon
})
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
src/views/mall/promotion/rewardActivity/components/RewardRuleCouponShowcase.vue
View file @
f2f39c3a
<
template
>
<ContentWrap>
<el-button
@
click=
"selectCoupon"
>
添加优惠卷
</el-button>
<el-table
:data=
"list"
>
<el-table-column
label=
"优惠券名称"
prop=
"name"
/>
<el-table-column
label=
"类型"
prop=
"productScope"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.PROMOTION_PRODUCT_SCOPE"
:value=
"scope.row.productScope"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"优惠"
prop=
"discount"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.PROMOTION_DISCOUNT_TYPE"
:value=
"scope.row.discountType"
/>
{{
discountFormat
(
scope
.
row
)
}}
</
template
>
</el-table-column>
<el-table-column
:formatter=
"validityTypeFormat"
align=
"center"
label=
"使用时间"
prop=
"validityType"
/>
<el-table-column
:formatter=
"remainedCountFormat"
align=
"center"
label=
"剩余数量"
prop=
"totalCount"
/>
<el-table-column
align=
"center"
fixed=
"right"
label=
"状态"
prop=
"status"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.COMMON_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
</el-table>
</ContentWrap>
<el-button
class=
"ml-10px"
type=
"text"
@
click=
"selectCoupon"
>
添加优惠卷
</el-button>
<div
v-for=
"(item, index) in list"
:key=
"item.id"
class=
"coupon-list-item p-x-10px mb-10px flex justify-between"
>
<div
class=
"coupon-list-item-left flex items-center flex-wrap"
>
<div
class=
"mr-10px"
>
优惠券名称:
{{
item
.
name
}}
</div>
<div
class=
"mr-10px"
>
范围:
<dict-tag
:type=
"DICT_TYPE.PROMOTION_PRODUCT_SCOPE"
:value=
"item.productScope"
/>
</div>
<div
class=
"flex items-center"
>
优惠:
<dict-tag
:type=
"DICT_TYPE.PROMOTION_DISCOUNT_TYPE"
:value=
"item.discountType"
/>
{{
discountFormat
(
item
)
}}
</div>
</div>
<div
class=
"coupon-list-item-right"
>
送
<el-input
v-model=
"item.giveCount"
class=
"w-150px! p-x-20px!"
placeholder=
""
type=
"number"
/>
张
<el-button
class=
"ml-20px"
link
type=
"danger"
@
click=
"deleteCoupon(index)"
>
删除
</el-button>
</div>
</div>
<!-- 优惠券选择 -->
<CouponSelect
ref=
"couponSelectRef"
@
change=
"handleCouponChange"
/>
</
template
>
<
script
lang=
"ts"
setup
>
// TODO puhui999: 先简单选择后列表展示,后续继续 fix
import
{
CouponSelect
}
from
'@/views/mall/promotion/coupon/components'
import
*
as
CouponTemplateApi
from
'@/api/mall/promotion/coupon/couponTemplate'
import
{
RewardRule
}
from
'@/api/mall/promotion/reward/rewardActivity'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
discountFormat
,
remainedCountFormat
,
validityTypeFormat
}
from
'@/views/mall/promotion/coupon/formatter'
import
{
discountFormat
}
from
'@/views/mall/promotion/coupon/formatter'
import
{
isEmpty
}
from
'@/utils/is'
import
{
useVModel
}
from
'@vueuse/core'
import
{
findIndex
}
from
'@/utils'
defineOptions
({
name
:
'RewardRuleCouponShowcase'
})
const
list
=
ref
<
CouponTemplateApi
.
CouponTemplateVO
[]
>
([])
// 选择的优惠券列表
const
props
=
defineProps
<
{
modelValue
:
RewardRule
}
>
()
const
emits
=
defineEmits
<
{
(
e
:
'update:modelValue'
,
v
:
any
):
void
}
>
()
const
rewardRule
=
useVModel
(
props
,
'modelValue'
,
emits
)
// 赠送规则
const
list
=
ref
<
GiveCouponVO
[]
>
([])
// 选择的优惠券列表
/** 选择赠送的优惠卷类型拓展 */
interface
GiveCouponVO
extends
CouponTemplateApi
.
CouponTemplateVO
{
giveCount
?:
number
}
const
couponSelectRef
=
ref
<
InstanceType
<
typeof
CouponSelect
>>
()
// 优惠券选择
/** 选择优惠券 */
...
...
@@ -67,6 +72,59 @@ const handleCouponChange = (val: CouponTemplateApi.CouponTemplateVO[]) => {
list
.
value
.
push
(
item
)
}
}
/** 删除优惠券 */
const
deleteCoupon
=
(
index
:
number
)
=>
{
list
.
value
.
splice
(
index
,
1
)
}
/** 初始化赠送的优惠券列表-如果有的话*/
const
initGiveCouponList
=
async
()
=>
{
if
(
isEmpty
(
rewardRule
.
value
)
||
isEmpty
(
rewardRule
.
value
.
couponIds
))
{
return
}
const
data
=
await
CouponTemplateApi
.
getCouponTemplateList
(
rewardRule
.
value
.
couponIds
!
)
if
(
!
data
)
{
return
}
for
(
let
i
=
0
,
len
=
data
.
length
;
i
<
len
;
i
++
)
{
const
coupon
=
data
[
i
]
const
index
=
findIndex
(
rewardRule
.
value
.
couponIds
!
,
(
item
)
=>
item
.
id
===
coupon
.
id
)
list
.
value
.
push
({
...
coupon
,
giveCount
:
rewardRule
.
value
.
couponCounts
!
[
index
]
})
}
}
/** 设置赠送的优惠券 */
const
setGiveCouponList
=
()
=>
{
if
(
isEmpty
(
rewardRule
.
value
)
||
isEmpty
(
list
.
value
))
{
return
}
const
couponIds
:
number
[]
=
[]
const
couponCounts
:
number
[]
=
[]
for
(
let
i
=
0
,
len
=
list
.
value
.
length
;
i
<
len
;
i
++
)
{
couponIds
.
push
(
list
.
value
[
i
].
id
)
couponCounts
.
push
(
list
.
value
[
i
].
giveCount
!
)
}
rewardRule
.
value
.
couponIds
=
couponIds
rewardRule
.
value
.
couponCounts
=
couponCounts
}
defineExpose
({
setGiveCouponList
})
/** 组件初始化 */
onMounted
(
async
()
=>
{
await
nextTick
()
await
initGiveCouponList
()
})
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
<
style
lang=
"scss"
scoped
>
.coupon-list-item
{
border
:
1px
dashed
var
(
--el-border-color-darker
);
border-radius
:
8px
;
}
</
style
>
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