更新:增加vip续费功能

This commit is contained in:
2025-10-24 14:53:07 +08:00
parent 0ddb75b7a5
commit 2a255a94ed
2 changed files with 242 additions and 8 deletions

View File

@@ -1,7 +1,7 @@
<template>
<el-dialog
width="1200px"
title="开通VIP"
:title="`${dataForm.id ? '续费' : '开通'}VIP`"
destroy-on-close
:close-on-click-modal="false"
:visible.sync="visible"
@@ -16,6 +16,7 @@
>
<div style="overflow: hidden;">
<el-form-item
v-if="!dataForm.id"
style="width: 50%;float: left;"
label="手机号/邮箱:"
prop="userKey"
@@ -26,6 +27,7 @@
size="small"
style="width: 100%;"
v-model="dataForm.userKey"
debounce="500"
:fetch-suggestions="loadAll"
placeholder="请输入手机号/邮箱"
@select="handleSelect"
@@ -62,12 +64,23 @@
<el-radio
style="margin-right: 10px;"
v-for="(option, index) in typeList"
:disabled="vipTypeDisabled(option.value)"
:key="index"
:label="option.value"
>
{{ option.label }}
</el-radio>
</el-radio-group>
<el-alert
v-if="showSelectVipTips"
:title="dataForm.id ? '只能续费已开通的VIP' : '已开通的VIP不允许再次开通如需续费请使用续费功能。'"
class="select-vip-tips"
type="warning"
close-text="不再提示"
@close="closeVipSelectedTips"
show-icon
>
</el-alert>
</el-form-item>
<el-form-item label="VIP年限" prop="year" class="year_block">
<div style="height: 40px;">
@@ -93,6 +106,14 @@
<span style=" color: #f56c6c;">{{ dataForm.price }}</span>
</el-form-item> -->
<el-form-item v-if="dataForm.type && dataForm.year" label="有效期预览">
<el-table :data="periodPreview" class="periodPreview-table" row-class-name="periodPreview-table-row" header-row-class-name="periodPreview-table-row">
<el-table-column prop="vipType" label="VIP类型" width="180"></el-table-column>
<el-table-column v-if="dataForm.id" prop="oldPeriod" label="续费前有效期"></el-table-column>
<el-table-column prop="currentPeriod" :label="`本次${dataForm.id ? '续费' : '开通'}的时长`"></el-table-column>
</el-table>
</el-form-item>
<el-form-item label="支付方式" class="coin_block">
<div>
<el-radio-group v-model="dataForm.payType" @input="payTypeChange">
@@ -143,7 +164,7 @@
</el-input>
</div>
</el-form-item>
<el-form-item label="抵扣积分" class="coin_block">
<el-form-item v-if="dataForm.payType == '天医币'" label="抵扣积分" class="coin_block">
<div>
<el-input
clearable
@@ -172,6 +193,7 @@
<script>
import global from "../../common/common.vue"; //引入共用组间
import { parseTime } from "@/utils";
export default {
data() {
return {
@@ -226,9 +248,77 @@ export default {
{ value: "1", label: "1年" },
{ value: "3", label: "3年" },
{ value: "4", label: "4年" }
]
],
superVipTypeDict: {
"11": ["4", "5", "6", "9", "7", "8"],
"12": ["4", "5", "6", "9", "8"],
"1": ["4", "5", "6", "9"],
"2": ["7", "8"]
},
hasVipList: [],
hasVipMaps: {}, // 初始化为空对象
vipTypeSet: new Set(), // 添加 vipTypeSet
isShowSelectVipTips_open: !!localStorage.getItem("closeVipSelectedTips_open"),
isShowSelectVipTips_renewal: !!localStorage.getItem("closeVipSelectedTips_renewal"),
};
},
computed: {
periodPreview() {
let types = [], result = []
if (this.superVipTypeDict[this.dataForm.type]) {
types = this.superVipTypeDict[this.dataForm.type]
} else {
types = [this.dataForm.type]
}
// 获取当前时间
const now = new Date();
// 计算本次开通的时长
const years = parseInt(this.dataForm.year) || 0;
types.forEach(item => {
const vipData = this.hasVipMaps[item];
// 确定开始日期
let startDate;
if (vipData && vipData.endTime) {
const endTime = new Date(vipData.endTime);
if (endTime > now) {
// 如果原有效期结束时间大于当前时间,开始日期为原结束时间
startDate = new Date(endTime);
startDate.setDate(startDate.getDate());
} else {
// 否则使用当前时间
startDate = new Date(now);
}
} else {
// 没有原有效期信息,使用当前时间
startDate = new Date(now);
}
// 计算结束日期
const endDate = new Date(startDate);
endDate.setFullYear(endDate.getFullYear() + years);
// 格式化日期
const formattedStartDate = parseTime(startDate, '{y}-{m}-{d}');
const formattedEndDate = parseTime(endDate, '{y}-{m}-{d}');
result.push({
vipType: this.typeList.find(e => e.value === item).label || item,
currentPeriod: `${formattedStartDate} ~ ${formattedEndDate}`,
oldPeriod: vipData ? (parseTime(vipData.startTime, '{y}-{m}-{d}') + " ~ " + parseTime(vipData.endTime, '{y}-{m}-{d}')) : '无'
});
});
return result;
},
showSelectVipTips() {
if (this.dataForm.id) {
return !this.isShowSelectVipTips_renewal
} else {
return !this.isShowSelectVipTips_open
}
}
},
methods: {
init(data) {
this.dataForm = {
@@ -255,6 +345,7 @@ export default {
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataForm = data.userVipInfo;
} else {
cb([]);
}
@@ -267,6 +358,72 @@ export default {
// this.dataForm.peanutCoin = data.peanutCoin;
// this.dataForm.jf = data.jf;
},
renewalInit(userId, data) {
this.dataForm = {
id: userId,
name: "",
tel: "",
email: "",
userId: userId,
pageType: "", //vip类型
type: "", //vip类型
year: "",
orderSn:'',
remark: "",
fee: 0, //金额
jf: 0 //积分
}
this.visible = true;
this.$http({
url: this.$http.adornUrl("/master/userVip/getUserVipInfoByUserId"),
method: "post",
data: this.$http.adornData({
state: "",
userId,
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.hasVipList = data.userVips || [];
// 在这里生成 hasVipMaps 和 vipTypeSet
this.generateVipMaps();
}
});
},
generateVipMaps() {
const hasVipMaps = {};
const vipTypeSet = new Set();
// 确保 this.hasVipList 是数组
(this.hasVipList || []).forEach(vip => {
const type = vip.type.toString();
vipTypeSet.add(type);
if (!hasVipMaps[type]) {
hasVipMaps[type] = vip;
}
});
this.hasVipMaps = hasVipMaps;
this.vipTypeSet = vipTypeSet;
},
vipTypeDisabled(type) {
let typeArr = [];
if (type === "11" || type === "12" || type === "1" || type === "2") {
typeArr = this.superVipTypeDict[type];
} else {
typeArr = [type];
}
// 如果是新开通没有id
if (!this.dataForm.id) {
// 如果用户已经拥有该类型或超V包含的任何一个类型则禁用
return typeArr.some(type => this.vipTypeSet.has(type));
}
// 如果是续费有id
else {
// 如果用户缺少该类型或超V包含的任何一个类型则禁用
return typeArr.some(type => !this.vipTypeSet.has(type));
}
},
handleSelect(data) {
console.log("data at line 161:", data);
this.dataForm.userKey = data.tel || data.email;
@@ -274,6 +431,13 @@ export default {
this.dataForm.name = data.name;
this.dataForm.tel = data.tel;
this.dataForm.email = data.email;
// 更改用户后清空已选vip类型
this.dataForm.type = "";
// 赋值当前用户已经拥有的vip用于禁用已开通过的vip类型
this.hasVipList = data.userVips;
this.generateVipMaps();
},
loadAll(queryString, cb) {
this.dataForm.userId = "";
@@ -287,7 +451,7 @@ export default {
method: "post",
data: this.$http.adornData({
page: 1,
limit: 9999,
limit: 20,
key: queryString
})
}).then(({ data }) => {
@@ -301,6 +465,8 @@ export default {
});
},
payTypeChange(e){
document.activeElement && document.activeElement.blur();
if(this.dataForm.payType){
delete this.dataForm.orderSn;
@@ -349,7 +515,7 @@ export default {
var data = {
...this.dataForm,
jf: this.dataForm.jf || 0,
jf: this.dataForm.payType === "天医币" ? this.dataForm.jf || 0 : 0,
fee: this.dataForm.fee || 0,
orderSn: this.dataForm.orderSn || '',
};
@@ -357,8 +523,9 @@ export default {
data.adminId = 1;
console.log("...this.dataForm at line 273:", this.dataForm);
const submitHttpUrl = this.dataForm.id ? "/master/userVip/renewUserVipByAdmin" : "/master/userVip/addUserVipByAdmin";
this.$http({
url: this.$http.adornUrl("/master/userVip/addUserVipByAdmin"),
url: this.$http.adornUrl(submitHttpUrl),
method: "post",
data: this.$http.adornData({
...data
@@ -384,6 +551,41 @@ export default {
//取消
handlereset() {
this.visible = false;
// 重置 VIP 相关状态
this.hasVipList = [];
this.hasVipMaps = {};
this.vipTypeSet = new Set();
// 重置表单数据
this.dataForm = {
id: 0,
name: "",
tel: "",
email: "",
userId: "",
pageType: "",
type: "",
year: "",
orderSn: "",
remark: "",
fee: 0,
jf: 0
};
// 重置表单验证
if (this.$refs.dataForm) {
this.$refs.dataForm.resetFields();
}
},
closeVipSelectedTips() {
if (this.dataForm.id) {
localStorage.setItem("closeVipSelectedTips_renewal", "true");
this.isShowSelectVipTips_renewal = true;
} else {
localStorage.setItem("closeVipSelectedTips_open", "true");
this.isShowSelectVipTips_open = true;
}
}
}
};
@@ -445,4 +647,20 @@ export default {
padding-right: 10px;
}
}
.periodPreview-table {
/deep/ tr,
/deep/ th {
background-color: #F8FAFF;
}
/deep/ .periodPreview-table-row .cell {
padding: 0 20px !important;
}
}
.select-vip-tips {
line-height: 1;
/deep/.el-alert__content {
height: 16px;
}
}
</style>

View File

@@ -251,6 +251,12 @@
@click="handleDetail(scope.row.id)"
>管理</el-button
>
<el-button
type="text"
size="small"
@click="handleRenewal(scope.row)"
>续费</el-button
>
<!-- <el-button
type="text"
size="small"
@@ -943,18 +949,28 @@ if (latest && latest.endTime) {
this.youVisible = true;
}
});
},
// 续费
handleRenewal(row) {
this.openVipVisible = true;
this.$nextTick(() => {
this.$refs.openVip.renewalInit(row.id, row);
});
}
}
};
</script>
<style scoped>
::v-deep .mod-config .el-table .el-table__cell {
.mod-config /deep/ .el-table .el-table__cell {
padding: 4px 0 !important;
box-sizing: border-box;
}
::v-deep .mod-config .el-table .cell,
.mod-config /deep/ .el-table .cell,
.el-table th div {
padding: 0 !important;
box-sizing: border-box;
}
.el-form /deep/ .el-form-item{
margin-bottom:10px !important;
}
</style>