Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
C
company_app
概览
概览
详情
活动
周期分析
版本库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
毛细亚
company_app
Commits
c446a18e
提交
c446a18e
authored
10月 31, 2025
作者:
毛细亚
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 新增权益使用功能和使用记录弹窗
上级
2faed5c0
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
537 行增加
和
6 行删除
+537
-6
game.js
src/api/game.js
+29
-0
benefitusageRecord.vue
...views/userInfo/components/gameInfo/benefitusageRecord.vue
+309
-0
vipLevel.vue
src/views/userInfo/components/gameInfo/vipLevel.vue
+199
-6
没有找到文件。
src/api/game.js
浏览文件 @
c446a18e
...
@@ -1424,3 +1424,32 @@ export function getClonePackageLink(data) {
...
@@ -1424,3 +1424,32 @@ export function getClonePackageLink(data) {
})
})
})
})
}
}
// 使用权益
export
function
useBenefit
(
data
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
cross_systemRequest
({
system
:
'zhangyou'
,
api
:
'/api/marketing_role_grade/useRight'
,
params
:
data
}).
then
((
res
)
=>
{
resolve
(
res
)
}).
catch
((
error
)
=>
{
reject
(
error
)
})
})
}
// 使用权益记录
export
function
useRightList
(
data
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
cross_systemRequest
({
system
:
'zhangyou'
,
api
:
'/api/marketing_role_grade/useRightList'
,
params
:
data
}).
then
((
res
)
=>
{
resolve
(
res
)
}).
catch
((
error
)
=>
{
reject
(
error
)
})
})
}
src/views/userInfo/components/gameInfo/benefitusageRecord.vue
0 → 100644
浏览文件 @
c446a18e
<!--
* @Author: maoxiya 937667504@qq.com
* @Date: 2025-10-31 15:00:00
* @LastEditors: maoxiya 937667504@qq.com
* @LastEditTime: 2025-10-31 17:18:17
* @FilePath: /company_wx_frontend/src/components/common/game/benefitUsageRecord.vue
* @Description: 权益使用记录组件
-->
<
template
>
<div
class=
"benefit-usage-record"
>
<!-- 搜索区域 -->
<div
class=
"search-content"
>
<el-form
label-position=
"top"
:model=
"formData"
class=
"search-form"
>
<el-form-item
label=
"权益"
>
<el-select
v-model=
"formData.type"
clearable
placeholder=
"请选择权益"
@
change=
"handleTypeChange"
style=
"width:100%;"
>
<el-option
v-for=
"item in benefitOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"时间范围"
>
<el-date-picker
v-model=
"formData.dateRange"
type=
"datetimerange"
format=
"yyyy-MM-dd HH:mm:ss"
value-format=
"yyyy-MM-dd HH:mm:ss"
range-separator=
"至"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
clearable
:default-time=
"['00:00:00', '23:59:59']"
style=
"width:100%;"
/>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
:loading=
"loading"
@
click=
"startSearch"
>
搜索
</el-button>
<el-button
@
click=
"resetForm"
>
重置
</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格区域 -->
<div
class=
"table-container"
>
<el-table
v-loading=
"loading"
:data=
"tableData"
style=
"width: 100%"
:header-cell-style=
"
{ background: '#f5f7fa', color: '#606266' }"
>
<el-table-column
label=
"角色名称/cp角色Id"
min-width=
"200"
>
<template
slot-scope=
"scope"
>
<p>
{{
scope
.
row
.
role_name
}}
</p>
<p
class=
"infoText"
>
{{
scope
.
row
.
cp_role_id
}}
</p>
</
template
>
</el-table-column>
<el-table-column
label=
"权益"
prop=
"type_name"
min-width=
"150"
/>
<el-table-column
label=
"使用人"
prop=
"create_user"
min-width=
"120"
/>
<el-table-column
label=
"使用时间"
prop=
"create_time"
min-width=
"180"
/>
</el-table>
<!-- 分页 -->
<div
class=
"pagination-container"
>
<el-pagination
@
current-change=
"handleCurrentChange"
@
size-change=
"handleSizeChange"
:current-page=
"page_info.page"
:page-sizes=
"[10, 20, 50, 100]"
:page-size=
"page_info.page_size"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"page_info.total"
/>
</div>
</div>
</div>
</template>
<
script
>
import
{
useRightList
,
selectSearch
}
from
'@/api/game'
export
default
{
name
:
'BenefitUsageRecord'
,
props
:
{
benefitItem
:
{
type
:
Object
,
default
:
()
=>
({})
},
roleInfo
:
{
type
:
Object
,
default
:
()
=>
({})
}
},
data
()
{
return
{
loading
:
false
,
formData
:
{
type
:
''
,
dateRange
:
[]
},
benefitOptions
:
[],
tableData
:
[],
tableColums
:
[
{
label
:
'角色名称/cp角色Id'
,
prop
:
'role_info'
,
minWidth
:
200
,
slotScope
:
true
},
{
label
:
'权益'
,
prop
:
'type_name'
,
minWidth
:
150
},
{
label
:
'使用人'
,
prop
:
'create_user'
,
minWidth
:
120
,
},
{
label
:
'使用时间'
,
prop
:
'create_time'
,
minWidth
:
180
}
],
page_info
:
{
page
:
1
,
page_size
:
20
,
total
:
0
}
}
},
mounted
()
{
this
.
getBenefitOptions
()
this
.
getTableData
()
},
methods
:
{
/**
* 获取权益下拉选项
*/
async
getBenefitOptions
()
{
try
{
const
data
=
{
type
:
'svip_right'
,
}
const
res
=
await
selectSearch
(
data
)
if
(
res
.
status_code
===
1
&&
res
.
data
&&
res
.
data
.
data
&&
res
.
data
.
data
.
length
>
0
)
{
this
.
benefitOptions
=
res
.
data
.
data
}
}
catch
(
error
)
{
console
.
error
(
'获取权益选项失败:'
,
error
)
}
},
/**
* 获取表格数据
*/
async
getTableData
()
{
try
{
this
.
loading
=
true
const
requestData
=
{
cp_role_id
:
this
.
roleInfo
.
cp_role_id
,
type
:
this
.
formData
.
type
,
create_time_start
:
this
.
formData
.
dateRange
&&
this
.
formData
.
dateRange
.
length
>
0
?
this
.
formData
.
dateRange
[
0
]
:
''
,
create_time_end
:
this
.
formData
.
dateRange
&&
this
.
formData
.
dateRange
.
length
>
0
?
this
.
formData
.
dateRange
[
1
]
:
''
,
page
:
this
.
page_info
.
page
,
page_size
:
this
.
page_info
.
page_size
}
const
res
=
await
useRightList
(
requestData
)
if
(
res
.
status_code
===
1
)
{
this
.
tableData
=
res
.
data
.
data
||
[]
this
.
page_info
.
total
=
Number
(
res
.
data
.
page_info
.
total
)
||
0
}
else
{
this
.
$message
({
message
:
res
.
data
.
msg
||
'获取数据失败'
,
type
:
'error'
})
}
}
catch
(
error
)
{
console
.
error
(
'获取权益使用记录失败:'
,
error
)
this
.
$message
({
message
:
'获取数据失败,请重试'
,
type
:
'error'
})
}
finally
{
this
.
loading
=
false
}
},
/**
* 处理页码变化
*/
handleCurrentChange
(
currentPage
)
{
this
.
page_info
.
page
=
currentPage
this
.
getTableData
()
},
/**
* 处理每页条数变化
*/
handleSizeChange
(
pageSize
)
{
this
.
page_info
.
page_size
=
pageSize
this
.
page_info
.
page
=
1
this
.
getTableData
()
},
/**
* 处理权益类型变化
*/
handleTypeChange
()
{
this
.
page_info
.
page
=
1
this
.
getTableData
()
},
/**
* 开始搜索
*/
startSearch
()
{
this
.
page_info
.
page
=
1
this
.
getTableData
()
},
/**
* 重置表单
*/
resetForm
()
{
this
.
formData
=
{
type
:
''
,
dateRange
:
[]
}
this
.
startSearch
()
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.benefit-usage-record
{
::v-deep
.el-table__header-wrapper{
position
:
static
;
top
:
0
;
}
.search-content
{
padding
:
20px
;
background
:
#fff
;
border-radius
:
4px
;
max-height
:
80%
;
overflow
:
auto
;
.search-form
{
.el-form-item
{
margin-bottom
:
16px
;
&:last-child
{
margin-bottom
:
0
;
}
}
}
}
.table-container
{
background
:
#fff
;
border-radius
:
4px
;
padding
:
20px
;
}
.pagination-container
{
margin-top
:
20px
;
text-align
:
right
;
}
.infoText
{
color
:
#c9cdd4
;
font-size
:
12px
;
margin-top
:
4px
;
}
}
</
style
>
src/views/userInfo/components/gameInfo/vipLevel.vue
浏览文件 @
c446a18e
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* @Author: maoxiya 937667504@qq.com
* @Author: maoxiya 937667504@qq.com
* @Date: 2025-09-13 14:05:01
* @Date: 2025-09-13 14:05:01
* @LastEditors: maoxiya 937667504@qq.com
* @LastEditors: maoxiya 937667504@qq.com
* @LastEditTime: 2025-
09-22 17:24:19
* @LastEditTime: 2025-
10-31 17:01:13
* @FilePath: /company_wx_frontend/src/views/works/component/gameInfo/vipLevel.vue
* @FilePath: /company_wx_frontend/src/views/works/component/gameInfo/vipLevel.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
-->
...
@@ -16,7 +16,7 @@
...
@@ -16,7 +16,7 @@
:disabled=
"loading"
:disabled=
"loading"
>
>
<!-- 最大宽度 400px -->
<!-- 最大宽度 400px -->
<div
class=
"vipLevelContent"
style=
"m
ax-width: 400px;max-height: 300px;overflow: auto
;"
>
<div
class=
"vipLevelContent"
style=
"m
in-width:250px
;"
>
<div
v-if=
"loading"
class=
"loading-content"
>
<div
v-if=
"loading"
class=
"loading-content"
>
<i
class=
"el-icon-loading"
></i>
<i
class=
"el-icon-loading"
></i>
<span>
加载中...
</span>
<span>
加载中...
</span>
...
@@ -25,7 +25,22 @@
...
@@ -25,7 +25,22 @@
<div
class=
"vipLevelItem rowFlex columnCenter"
v-for=
"(item,index) in vipLevelBenefit"
:key=
"index"
>
<div
class=
"vipLevelItem rowFlex columnCenter"
v-for=
"(item,index) in vipLevelBenefit"
:key=
"index"
>
<p
class=
"vipLevelItemRow"
v-if=
"item.num"
:style=
"
{color: item.target ? '#333333' : '#c9cdd4'}" >
<p
class=
"vipLevelItemRow"
v-if=
"item.num"
:style=
"
{color: item.target ? '#333333' : '#c9cdd4'}" >
<span
v-if=
"item.name"
class=
"label"
>
{{
item
.
name
}}
</span>
<span
v-if=
"item.name"
class=
"label"
>
{{
item
.
name
}}
</span>
<span
v-if=
"item.num"
:style=
"
{color: item.target ? '#00bf8a' : '#c9cdd4'}" class="value">
{{
item
.
num
}}
次
</span>
<span
v-if=
"item.num"
:style=
"
{color: item.target ? '#00bf8a' : '#c9cdd4'}" class="value">
{{
item
.
remain_num
||
item
.
num
}}
/
{{
item
.
num
}}
{{
item
.
unit
||
'次'
}}
</span>
<!-- 人工权益显示使用按钮 -->
<div
v-if=
"item.monitor_type === 2"
class=
"benefit-actions"
>
<el-button
type=
"primary"
size=
"mini"
style=
"margin-left: 10px;"
:disabled=
"!item.target"
@
click
.
stop=
"handleUseBenefit(item)"
class=
"use-button"
>
使用
</el-button>
</div>
</p>
</p>
</div>
</div>
<div
v-if=
"vipLevelBenefit.length === 0"
class=
"no-data"
>
<div
v-if=
"vipLevelBenefit.length === 0"
class=
"no-data"
>
...
@@ -37,11 +52,62 @@
...
@@ -37,11 +52,62 @@
<span
class=
"vipLevelText"
v-if=
"vip_role_info.vip_level"
@
click
.
stop=
"showVipLevel"
>
{{
`SVIP等级${vip_role_info.vip_level
}
`
}}
<
/span
>
<span
class=
"vipLevelText"
v-if=
"vip_role_info.vip_level"
@
click
.
stop=
"showVipLevel"
>
{{
`SVIP等级${vip_role_info.vip_level
}
`
}}
<
/span
>
<
/div
>
<
/div
>
<
/el-popover
>
<
/el-popover
>
<!--
使用权益确认弹窗
-->
<
el
-
dialog
v
-
if
=
"useBenefitDialogVisible"
title
=
"确认提示"
:
visible
.
sync
=
"useBenefitDialogVisible"
width
=
"400px"
:
before
-
close
=
"handleDialogClose"
>
<
div
class
=
"dialog-content"
>
<
div
class
=
"rowFlex columnCenter"
>
<
i
class
=
"el-icon-warning"
style
=
"color: #E6A23C; font-size: 24px; margin-right: 10px;"
><
/i
>
<
span
>
是否确认使用
{{
currentBenefitItem
?.
name
}}
权益?
<
/span
>
<
/div
>
<
p
class
=
"text-center"
style
=
"color: #999; font-size: 14px; margin-top: 10px;"
>
点击确定后
,
权益剩余使用数量将减
1
<
/p
>
<
/div
>
<
div
slot
=
"footer"
>
<
el
-
button
type
=
"text"
@
click
=
"showUsageRecordFromDialog"
class
=
"record-button"
>
使用记录
<
/el-button
>
<
el
-
button
@
click
=
"handleDialogClose"
>
取消
<
/el-button
>
<
el
-
button
type
=
"primary"
:
loading
=
"loading"
@
click
=
"confirmUseBenefit"
>
确认
<
/el-button
>
<
/div
>
<
/el-dialog
>
<!--
使用记录弹窗
-->
<
el
-
dialog
title
=
"权益使用记录"
:
visible
.
sync
=
"usageRecordVisible"
width
=
"80%"
:
before
-
close
=
"closeUsageRecord"
append
-
to
-
body
@
close
=
"closeUsageRecord"
>
<
BenefitUsageRecord
:
benefit
-
item
=
"currentBenefitItem"
:
role
-
info
=
"vip_role_info"
/>
<
/el-dialog
>
<
/div
>
<
/div
>
<
/template
>
<
/template
>
<
script
>
<
script
>
import
{
marketingRoleGradeBenefit
,
marketingMemberRoleGrade
}
from
'@/api/game'
import
{
marketingRoleGradeBenefit
,
marketingMemberRoleGrade
,
useBenefit
}
from
'@/api/game'
import
{
mapState
,
mapMutations
}
from
'vuex'
import
{
mapState
,
mapMutations
}
from
'vuex'
import
BenefitUsageRecord
from
'./benefitusageRecord.vue'
export
default
{
export
default
{
name
:
'VipLevel'
,
name
:
'VipLevel'
,
data
()
{
data
()
{
...
@@ -49,9 +115,15 @@ export default {
...
@@ -49,9 +115,15 @@ export default {
vip_role_info
:
{
}
,
vip_role_info
:
{
}
,
vipLevelBenefit
:
[],
vipLevelBenefit
:
[],
popoverVisible
:
false
,
popoverVisible
:
false
,
loading
:
false
loading
:
false
,
usageRecordVisible
:
false
,
currentBenefitItem
:
null
,
useBenefitDialogVisible
:
false
}
}
}
,
}
,
components
:
{
BenefitUsageRecord
}
,
props
:
{
props
:
{
roleInfo
:
{
roleInfo
:
{
type
:
Object
,
type
:
Object
,
...
@@ -73,7 +145,8 @@ export default {
...
@@ -73,7 +145,8 @@ export default {
}
}
}
,
}
,
computed
:
{
computed
:
{
...
mapState
(
'game'
,
[
'accountSelect'
])
...
mapState
(
'game'
,
[
'accountSelect'
]),
...
mapState
(
'user'
,
[
'userInfo'
]),
}
,
}
,
methods
:
{
methods
:
{
async
marketingMemberRoleGrade
()
{
async
marketingMemberRoleGrade
()
{
...
@@ -134,7 +207,80 @@ export default {
...
@@ -134,7 +207,80 @@ export default {
// 获取数据并显示popover
// 获取数据并显示popover
await
this
.
getVipLevel
();
await
this
.
getVipLevel
();
}
,
/**
* 处理使用权益
*/
handleUseBenefit
(
item
)
{
this
.
currentBenefitItem
=
item
;
this
.
useBenefitDialogVisible
=
true
;
}
,
/**
* 确认使用权益
*/
async
confirmUseBenefit
()
{
try
{
this
.
loading
=
true
;
const
requestData
=
{
role_id
:
this
.
vip_role_info
.
role_id
,
grade_config_id
:
this
.
currentBenefitItem
.
grade_config_id
,
user_name
:
this
.
userInfo
.
username
}
;
const
res
=
await
useBenefit
(
requestData
);
if
(
res
.
status_code
===
1
)
{
this
.
$message
({
message
:
res
.
data
.
msg
||
'使用成功'
,
type
:
'success'
}
);
// 直接更新本地权益数据
const
benefitIndex
=
this
.
vipLevelBenefit
.
findIndex
(
item
=>
item
.
grade_config_id
===
this
.
currentBenefitItem
.
grade_config_id
);
if
(
benefitIndex
!==
-
1
)
{
this
.
vipLevelBenefit
[
benefitIndex
].
remain_num
-=
1
;
}
this
.
useBenefitDialogVisible
=
false
;
this
.
currentBenefitItem
=
null
;
}
else
{
this
.
$message
({
message
:
res
.
data
.
msg
||
'使用失败'
,
type
:
'error'
}
);
}
}
catch
(
error
)
{
console
.
error
(
'使用权益失败:'
,
error
);
}
finally
{
this
.
loading
=
false
;
}
}
,
/**
* 处理dialog关闭
*/
handleDialogClose
()
{
this
.
useBenefitDialogVisible
=
false
;
this
.
currentBenefitItem
=
null
;
}
,
/**
* 从dialog中显示使用记录弹窗
*/
showUsageRecordFromDialog
()
{
this
.
usageRecordVisible
=
true
;
this
.
useBenefitDialogVisible
=
false
;
}
,
/**
* 关闭使用记录弹窗
*/
closeUsageRecord
()
{
this
.
usageRecordVisible
=
false
;
this
.
currentBenefitItem
=
null
;
}
}
}
}
}
}
<
/script
>
<
/script
>
...
@@ -185,8 +331,54 @@ export default {
...
@@ -185,8 +331,54 @@ export default {
.
value
{
.
value
{
font
-
weight
:
bold
;
font
-
weight
:
bold
;
}
}
.
benefit
-
actions
{
display
:
flex
;
align
-
items
:
center
;
gap
:
8
px
;
margin
-
left
:
auto
;
.
use
-
button
{
margin
-
left
:
10
px
;
}
.
record
-
button
{
font
-
size
:
12
px
;
padding
:
0
;
}
}
}
}
}
.
dialog
-
content
{
font
-
size
:
16
px
;
color
:
#
333
;
}
.
dialog
-
footer
{
display
:
flex
;
justify
-
content
:
flex
-
end
;
align
-
items
:
center
;
.
record
-
button
{
margin
-
left
:
10
px
;
color
:
#
409
EFF
;
cursor
:
pointer
;
&
:
hover
{
color
:
#
66
b1ff
;
}
}
}
}
}
}
// 使用记录弹窗样式
.
el
-
dialog
{
::
v
-
deep
.
el
-
dialog__body
{
padding
:
0
;
max
-
height
:
70
vh
;
overflow
-
y
:
auto
;
}
}
}
}
<
/style>
<
/style>
\ No newline at end of file
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论