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
beef6a0a
authored
Aug 26, 2023
by
owen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mall: 完善后台发送优惠券
parent
3a153900
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
263 additions
and
38 deletions
+263
-38
src/api/mall/promotion/coupon/coupon.ts
+8
-0
src/api/mall/promotion/coupon/couponTemplate.ts
+8
-0
src/views/mall/promotion/coupon/components/CouponSend.vue
+162
-0
src/views/mall/promotion/coupon/formatter.ts
+44
-0
src/views/mall/promotion/coupon/template/index.vue
+10
-37
src/views/member/user/index.vue
+31
-1
No files found.
src/api/mall/promotion/coupon/coupon.ts
View file @
beef6a0a
...
@@ -16,3 +16,11 @@ export const getCouponPage = async (params: PageParam) => {
...
@@ -16,3 +16,11 @@ export const getCouponPage = async (params: PageParam) => {
params
:
params
params
:
params
})
})
}
}
// 发送优惠券
export
const
sendCoupon
=
async
(
data
:
any
)
=>
{
return
request
.
post
({
url
:
'/promotion/coupon/send'
,
data
:
data
})
}
src/api/mall/promotion/coupon/couponTemplate.ts
View file @
beef6a0a
...
@@ -73,6 +73,14 @@ export function getCouponTemplatePage(params: PageParam) {
...
@@ -73,6 +73,14 @@ export function getCouponTemplatePage(params: PageParam) {
})
})
}
}
// 获得可用于领取的优惠劵模板分页
export
function
getCanTakeCouponTemplatePage
(
params
:
PageParam
)
{
return
request
.
get
({
url
:
'/promotion/coupon-template/can-take-page'
,
params
:
params
})
}
// 导出优惠劵模板 Excel
// 导出优惠劵模板 Excel
export
function
exportCouponTemplateExcel
(
params
:
PageParam
)
{
export
function
exportCouponTemplateExcel
(
params
:
PageParam
)
{
return
request
.
get
({
return
request
.
get
({
...
...
src/views/mall/promotion/coupon/components/CouponSend.vue
0 → 100644
View file @
beef6a0a
<
template
>
<Dialog
v-model=
"dialogVisible"
:appendToBody=
"true"
title=
"发送优惠券"
width=
"70%"
>
<el-form
ref=
"queryFormRef"
:inline=
"true"
:model=
"queryParams"
class=
"-mb-15px"
label-width=
"82px"
>
<el-form-item
label=
"优惠券名称"
prop=
"name"
>
<el-input
v-model=
"queryParams.name"
class=
"!w-240px"
placeholder=
"请输入优惠劵名"
clearable
@
keyup=
"handleQuery"
/>
</el-form-item>
<el-form-item>
<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-form-item>
</el-form>
<el-table
v-loading=
"loading"
:data=
"list"
show-overflow-tooltip
>
<el-table-column
align=
"center"
label=
"优惠券名称"
prop=
"name"
min-width=
"60"
/>
<el-table-column
label=
"优惠金额 / 折扣"
align=
"center"
prop=
"discount"
:formatter=
"discountFormat"
min-width=
"60"
/>
<el-table-column
align=
"center"
label=
"最低消费"
prop=
"usePrice"
min-width=
"60"
:formatter=
"userPriceFormat"
/>
<el-table-column
align=
"center"
label=
"有效期限"
prop=
"validityType"
min-width=
"140"
:formatter=
"validityTypeFormat"
/>
<el-table-column
align=
"center"
label=
"剩余数量"
min-width=
"60"
:formatter=
"remainedCountFormat"
/>
<el-table-column
label=
"操作"
align=
"center"
min-width=
"60px"
fixed=
"right"
>
<template
#
default=
"scope"
>
<el-button
link
type=
"primary"
:disabled=
"sendLoading"
:loading=
"sendLoading"
@
click=
"handleSendCoupon(scope.row.id)"
v-hasPermi=
"['member:level:update']"
>
发送
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
v-model:limit=
"queryParams.pageSize"
v-model:page=
"queryParams.pageNo"
:total=
"total"
@
pagination=
"getList"
/>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
CouponTemplateApi
from
'@/api/mall/promotion/coupon/couponTemplate'
import
*
as
CouponApi
from
'@/api/mall/promotion/coupon/coupon'
import
{
discountFormat
,
remainedCountFormat
,
userPriceFormat
,
validityTypeFormat
}
from
'@/views/mall/promotion/coupon/formatter'
defineOptions
({
name
:
'PromotionCouponSend'
})
const
message
=
useMessage
()
// 消息弹窗
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
<
any
[]
>
([])
// 列表的数据
const
loading
=
ref
(
false
)
// 列表的加载中
const
sendLoading
=
ref
(
false
)
// 发送按钮的加载中
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
queryParams
=
ref
({
pageNo
:
1
,
pageSize
:
10
,
name
:
null
})
// 查询参数
const
queryFormRef
=
ref
()
// 搜索的表单
// 领取人的编号列表
let
userIds
:
number
[]
=
[]
/** 打开弹窗 */
const
open
=
(
ids
:
number
[])
=>
{
userIds
=
ids
// 打开时重置查询,防止发送列表剩余数量未更新的问题
resetQuery
()
dialogVisible
.
value
=
true
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
CouponTemplateApi
.
getCanTakeCouponTemplatePage
(
queryParams
.
value
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryFormRef
?.
value
?.
resetFields
()
handleQuery
()
}
/** 发送操作 **/
const
handleSendCoupon
=
async
(
templateId
:
number
)
=>
{
try
{
sendLoading
.
value
=
true
await
CouponApi
.
sendCoupon
({
templateId
,
userIds
})
message
.
success
(
'发送成功'
)
dialogVisible
.
value
=
false
}
finally
{
sendLoading
.
value
=
false
}
}
/** 初始化 **/
// onMounted(async () => {
// await getList()
// })
</
script
>
src/views/mall/promotion/coupon/formatter.ts
0 → 100644
View file @
beef6a0a
import
{
CouponTemplateValidityTypeEnum
,
PromotionDiscountTypeEnum
}
from
'@/utils/constants'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
CouponTemplateVO
}
from
'@/api/mall/promotion/coupon/couponTemplate'
import
{
floatToFixed2
}
from
'@/utils'
// 格式化【优惠金额/折扣】
export
const
discountFormat
=
(
row
:
CouponTemplateVO
)
=>
{
if
(
row
.
discountType
===
PromotionDiscountTypeEnum
.
PRICE
.
type
)
{
return
`¥
${
floatToFixed2
(
row
.
discountPrice
)}
`
}
if
(
row
.
discountType
===
PromotionDiscountTypeEnum
.
PERCENT
.
type
)
{
return
`
${
row
.
discountPrice
}
%`
}
return
'未知【'
+
row
.
discountType
+
'】'
}
// 格式化【领取上限】
export
const
takeLimitCountFormat
=
(
row
:
CouponTemplateVO
)
=>
{
if
(
row
.
takeLimitCount
===
-
1
)
{
return
'无领取限制'
}
return
`
${
row
.
takeLimitCount
}
张/人`
}
// 格式化【有效期限】
export
const
validityTypeFormat
=
(
row
:
CouponTemplateVO
)
=>
{
if
(
row
.
validityType
===
CouponTemplateValidityTypeEnum
.
DATE
.
type
)
{
return
`
${
formatDate
(
row
.
validStartTime
)}
至
${
formatDate
(
row
.
validEndTime
)}
`
}
if
(
row
.
validityType
===
CouponTemplateValidityTypeEnum
.
TERM
.
type
)
{
return
`领取后第
${
row
.
fixedStartTerm
}
-
${
row
.
fixedEndTerm
}
天内可用`
}
return
'未知【'
+
row
.
validityType
+
'】'
}
// 格式化【剩余数量】
export
const
remainedCountFormat
=
(
row
:
CouponTemplateVO
)
=>
{
return
row
.
totalCount
-
row
.
takeCount
}
// 格式化【最低消费】
export
const
userPriceFormat
=
(
row
:
CouponTemplateVO
)
=>
{
return
`¥
${
floatToFixed2
(
row
.
usePrice
)}
`
}
src/views/mall/promotion/coupon/template/index.vue
View file @
beef6a0a
...
@@ -103,7 +103,7 @@
...
@@ -103,7 +103,7 @@
label=
"剩余数量"
label=
"剩余数量"
align=
"center"
align=
"center"
prop=
"totalCount"
prop=
"totalCount"
:formatter=
"
(row) => row.totalCount - row.takeCoun
t"
:formatter=
"
remainedCountForma
t"
/>
/>
<el-table-column
<el-table-column
label=
"领取上限"
label=
"领取上限"
...
@@ -171,14 +171,16 @@
...
@@ -171,14 +171,16 @@
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
*
as
CouponTemplateApi
from
'@/api/mall/promotion/coupon/couponTemplate'
import
*
as
CouponTemplateApi
from
'@/api/mall/promotion/coupon/couponTemplate'
import
{
import
{
CommonStatusEnum
}
from
'@/utils/constants'
CommonStatusEnum
,
CouponTemplateValidityTypeEnum
,
PromotionDiscountTypeEnum
}
from
'@/utils/constants'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
,
formatDate
}
from
'@/utils/formatTime'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
CouponTemplateForm
from
'./CouponTemplateForm.vue'
import
CouponTemplateForm
from
'./CouponTemplateForm.vue'
import
{
discountFormat
,
remainedCountFormat
,
takeLimitCountFormat
,
validityTypeFormat
}
from
'@/views/mall/promotion/coupon/formatter'
defineOptions
({
name
:
'PromotionCouponTemplate'
})
defineOptions
({
name
:
'PromotionCouponTemplate'
})
...
@@ -193,6 +195,7 @@ const queryParams = reactive({
...
@@ -193,6 +195,7 @@ const queryParams = reactive({
pageSize
:
10
,
pageSize
:
10
,
name
:
null
,
name
:
null
,
status
:
null
,
status
:
null
,
discountType
:
null
,
type
:
null
,
type
:
null
,
createTime
:
[]
createTime
:
[]
})
})
...
@@ -258,36 +261,6 @@ const handleDelete = async (id: number) => {
...
@@ -258,36 +261,6 @@ const handleDelete = async (id: number) => {
}
catch
{}
}
catch
{}
}
}
// 格式化【优惠金额/折扣】
const
discountFormat
=
(
row
:
any
)
=>
{
if
(
row
.
discountType
===
PromotionDiscountTypeEnum
.
PRICE
.
type
)
{
return
`¥
${(
row
.
discountPrice
/
100.0
).
toFixed
(
2
)}
`
}
if
(
row
.
discountType
===
PromotionDiscountTypeEnum
.
PERCENT
.
type
)
{
return
`¥
${(
row
.
discountPrice
/
100.0
).
toFixed
(
2
)}
`
}
return
'未知【'
+
row
.
discountType
+
'】'
}
// 格式化【领取上限】
const
takeLimitCountFormat
=
(
row
:
any
)
=>
{
if
(
row
.
takeLimitCount
===
-
1
)
{
return
'无领取限制'
}
return
`
${
row
.
takeLimitCount
}
张/人`
}
// 格式化【有效期限】
const
validityTypeFormat
=
(
row
:
any
)
=>
{
if
(
row
.
validityType
===
CouponTemplateValidityTypeEnum
.
DATE
.
type
)
{
return
`
${
formatDate
(
row
.
validStartTime
)}
至
${
formatDate
(
row
.
validEndTime
)}
`
}
if
(
row
.
validityType
===
CouponTemplateValidityTypeEnum
.
TERM
.
type
)
{
return
`领取后第
${
row
.
fixedStartTerm
}
-
${
row
.
fixedEndTerm
}
天内可用`
}
return
'未知【'
+
row
.
validityType
+
'】'
}
/** 初始化 **/
/** 初始化 **/
onMounted
(()
=>
{
onMounted
(()
=>
{
getList
()
getList
()
...
...
src/views/member/user/index.vue
View file @
beef6a0a
...
@@ -60,13 +60,21 @@
...
@@ -60,13 +60,21 @@
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
><Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"handleQuery"
><Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
><Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
@
click=
"resetQuery"
><Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
@
click=
"openCoupon"
v-hasPermi=
"['promotion:coupon:send']"
>
发送优惠券
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
</ContentWrap>
</ContentWrap>
<!-- 列表 -->
<!-- 列表 -->
<ContentWrap>
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
@
selection-change=
"handleSelectionChange"
>
<el-table-column
type=
"selection"
width=
"55"
/>
<el-table-column
label=
"用户编号"
align=
"center"
prop=
"id"
width=
"120px"
/>
<el-table-column
label=
"用户编号"
align=
"center"
prop=
"id"
width=
"120px"
/>
<el-table-column
label=
"头像"
align=
"center"
prop=
"avatar"
width=
"80px"
>
<el-table-column
label=
"头像"
align=
"center"
prop=
"avatar"
width=
"80px"
>
<template
#
default=
"scope"
>
<template
#
default=
"scope"
>
...
@@ -145,6 +153,8 @@
...
@@ -145,6 +153,8 @@
<UserForm
ref=
"formRef"
@
success=
"getList"
/>
<UserForm
ref=
"formRef"
@
success=
"getList"
/>
<!-- 修改用户等级弹窗 -->
<!-- 修改用户等级弹窗 -->
<UpdateLevelForm
ref=
"updateLevelFormRef"
@
success=
"getList"
/>
<UpdateLevelForm
ref=
"updateLevelFormRef"
@
success=
"getList"
/>
<!-- 发送优惠券弹窗 -->
<CouponSend
ref=
"couponSend"
/>
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
dateFormatter
}
from
'@/utils/formatTime'
...
@@ -154,9 +164,12 @@ import MemberTagSelect from '@/views/member/tag/components/MemberTagSelect.vue'
...
@@ -154,9 +164,12 @@ import MemberTagSelect from '@/views/member/tag/components/MemberTagSelect.vue'
import
MemberLevelSelect
from
'@/views/member/level/components/MemberLevelSelect.vue'
import
MemberLevelSelect
from
'@/views/member/level/components/MemberLevelSelect.vue'
import
MemberGroupSelect
from
'@/views/member/group/components/MemberGroupSelect.vue'
import
MemberGroupSelect
from
'@/views/member/group/components/MemberGroupSelect.vue'
import
UpdateLevelForm
from
'@/views/member/user/UpdateLevelForm.vue'
import
UpdateLevelForm
from
'@/views/member/user/UpdateLevelForm.vue'
import
CouponSend
from
'@/views/mall/promotion/coupon/components/CouponSend.vue'
defineOptions
({
name
:
'MemberUser'
})
defineOptions
({
name
:
'MemberUser'
})
const
message
=
useMessage
()
// 消息弹窗
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
list
=
ref
([])
// 列表的数据
...
@@ -173,6 +186,7 @@ const queryParams = reactive({
...
@@ -173,6 +186,7 @@ const queryParams = reactive({
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
const
updateLevelFormRef
=
ref
()
// 修改会员等级表单
const
updateLevelFormRef
=
ref
()
// 修改会员等级表单
const
selectedIds
=
ref
<
number
[]
>
([])
// 表格的选中 ID 数组
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
...
@@ -204,6 +218,22 @@ const openDetail = (id: number) => {
...
@@ -204,6 +218,22 @@ const openDetail = (id: number) => {
push
({
name
:
'MemberUserDetail'
,
params
:
{
id
}
})
push
({
name
:
'MemberUserDetail'
,
params
:
{
id
}
})
}
}
/** 表格选中事件 */
const
handleSelectionChange
=
(
rows
:
UserApi
.
UserVO
[])
=>
{
selectedIds
.
value
=
rows
.
map
((
row
)
=>
row
.
id
)
}
/** 发送优惠券 */
const
couponSend
=
ref
()
const
openCoupon
=
()
=>
{
if
(
selectedIds
.
value
.
length
===
0
)
{
message
.
warning
(
'请选择要发送优惠券的用户'
)
return
}
couponSend
.
value
.
open
(
selectedIds
.
value
)
}
/** 初始化 **/
/** 初始化 **/
onMounted
(()
=>
{
onMounted
(()
=>
{
getList
()
getList
()
...
...
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