Files
nuttyreading-master-html/src/views/modules/vipList/userList.vue
2025-09-11 17:43:46 +08:00

831 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="mod-config">
<el-form
:inline="true"
:model="dataForm"
@keyup.enter.native="getDataList()"
>
<el-form-item>
<el-input
v-model="dataForm.key"
placeholder="参数名"
clearable
size="small"
>
</el-input>
</el-form-item>
<el-form-item>
<el-select
size="small"
v-model="dataForm.vipType"
placeholder="请选择VIP类型"
clearable
>
<!-- <el-option label="医学SVIP" value="1"></el-option> -->
<!-- <el-option label="国学与心理学SVIP" value="2"></el-option> -->
<el-option label="中医VIP" value="4"></el-option>
<el-option label="针灸VIP" value="5"></el-option>
<el-option label="肿瘤VIP" value="6"></el-option>
<el-option label="国学VIP" value="7"></el-option>
<el-option label="心理学VIP" value="8"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-date-picker
size="small"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button
size="small"
@click="
pageIndex = 1;
getDataList();
"
>查询</el-button
>
<el-button
size="small"
v-if="isAuth('book:user:save')"
type="primary"
@click="openVip()"
>开通VIP</el-button
>
<!-- <el-button
size="small"
plain
v-if="isAuth('book:user:save')"
type="danger"
@click="addOrUpdateHandle()"
>补录人工开通 VIP 记录</el-button
> -->
</el-form-item>
</el-form>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
style="width: 100%;"
>
<!-- <el-table-column type="selection" header-align="center" align="center" width="50">
</el-table-column> -->
<!-- <el-table-column label="序号" width="70" align="center">
<template slot-scope="scope">
{{ (pageIndex - 1) * pageSize + scope.$index + 1 }}
</template>
</el-table-column> -->
<el-table-column
width="120"
prop="id"
header-align="center"
align="center"
label="用户ID"
>
<template slot-scope="scope">
<span
@click="detailHandle(scope.row)"
style="cursor: pointer;color: #006699;position: absolute;top: 0;left: 6px;font-size: 12px;"
>详情</span
>
<div>
<el-image
v-if="scope.row.avatar && scope.row.avatar != ''"
style="width: 30px; height: 30px;cursor: pointer;"
:src="scope.row.avatar"
:preview-src-list="[scope.row.avatar]"
>
</el-image>
<img
v-else
src="/static/img/morenAvavter.png"
width="30"
height="30"
class="tableImg"
/>
</div>
<div style="line-height: 20px;">
<span>ID:{{ scope.row.id }}</span>
</div>
</template>
</el-table-column>
<el-table-column
width="260"
prop="nickname"
header-align="center"
align="center"
label="用户信息"
>
<template slot-scope="scope">
<div style="display: flex;align-items: center;padding-left: 10px;">
<span style="margin-right: 10px;color: #888;">昵称 ( 姓名 ):</span>
<div
style="font-size: 13px;"
v-if="!scope.row.nickname && !scope.row.name"
>
<span style="color: #999;">
未设置
</span>
</div>
<div
style="font-size: 13px;"
v-else-if="scope.row.nickname == scope.row.name"
>
<span style="color: #999;">
未设置
</span>
</div>
<div style="font-size: 13px;" v-else>
<span v-if="scope.row.nickname">{{ scope.row.nickname }}</span>
<span v-else style="color: #999;">
未设置
</span>
<span style="color: #999;">(</span>
<span v-if="scope.row.name">{{ scope.row.name }}</span>
<span v-else style="color: #999;">
未设置
</span>
<span style="color: #999;">)</span>
</div>
</div>
<div style="display: flex;align-items: flex-start;padding-left: 10px;margin-top: 4px;">
<span style="margin-right: 10px;display: inline-block;color: #888;">联系方式:</span>
<div style="font-size: 14px;padding-left: 4px;font-weight: bold;text-align: left;">
<div v-if="scope.row.tel">
<img
src="../../../assets/img/tel.png"
width="15"
height="15"
/>{{ scope.row.tel ? scope.row.tel : "-" }}
</div>
<div v-if="scope.row.email">
<img
src="../../../assets/img/email.png"
width="15"
height="15"
/>
{{ scope.row.email ? scope.row.email : "-" }}
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column
min-width="120"
prop="nickname"
header-align="center"
align="center"
label="VIP信息 ( 时间 )"
>
<template slot-scope="scope">
<span v-if="!scope.row.userVips || scope.row.userVips.length == 0"
>-</span
>
<span v-else v-html="computedVipType(scope.row.userVips)"> </span>
<span>{{ scope.row.createTime?scope.row.createTime.split(' ')[0]:'' }}</span>
<span >{{ scope.row.endTime?scope.row.endTime.split(' ')[0]:'' }}</span>
</template>
</el-table-column>
<el-table-column
width="190"
prop="nickname"
header-align="center"
align="center"
label="摊销金额"
>
<template slot-scope="scope">
</template>
</el-table-column>
<!-- <el-table-column
width="190"
prop="nickname"
header-align="center"
align="center"
label="金额 ( 支付方式 ) "
>
<template slot-scope="scope">
<div>金额:</div>
<div>订单:</div>
</template>
</el-table-column> -->
<!-- <el-table-column prop="age" header-align="center" align="center" label="年龄">
</el-table-column> -->
<!-- <el-table-column prop="sex" header-align="center" align="center" label="性别">
<template slot-scope="scope">
<span v-if="scope.row.sex == 0">女</span><span v-if="scope.row.sex == 1">男</span><span v-if="scope.row.sex == 2">保密</span>
</template>
</el-table-column> -->
<el-table-column
fixed="right"
header-align="center"
align="center"
width="110"
label="操作"
>
<template slot-scope="scope">
<el-button
type="text"
size="small"
@click="handleDetail(scope.row.id)"
>管理</el-button
>
<el-button
type="text"
size="small"
@click="addOrUpdateHandle(scope.row.id)"
>操作VIP</el-button
>
<!-- <el-dropdown>
<span
class="el-dropdown-link"
style="font-size:12px; color:#17B3A3; cursor: pointer;"
>
更多操作<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
><el-button type="text" size="small" @click="ck(scope.row)"
>/扣天医币</el-button
></el-dropdown-item
>
<el-dropdown-item>
<router-link
:to="{
path: 'user-point-memery',
query: {
tel: scope.row.tel,
id: scope.row.id,
userName: scope.row.nickname
}
}"
>
<el-button type="text" size="small"
>/扣天医币记录</el-button
>
</router-link>
</el-dropdown-item>
<el-dropdown-item
><el-button
type="text"
size="small"
@click="
thisUserID = scope.row.id;
youVisible = true;
"
>优惠券管理</el-button
></el-dropdown-item
>
<el-dropdown-item
><el-button
type="text"
size="small"
@click="resetPassword(scope.row)"
>修改密码</el-button
></el-dropdown-item
>
<el-dropdown-item>
<router-link
:to="{ path: '/userCourse', query: { id: scope.row.id } }"
>
<el-button type="text" size="small">
用户课程管理
</el-button>
</router-link>
</el-dropdown-item>
<el-dropdown-item>
<router-link
:to="{ path: '/userPoints', query: { id: scope.row.id } }"
>
<el-button type="text" size="small">
湖分管理
</el-button>
</router-link>
</el-dropdown-item>
<el-dropdown-item>
<router-link
:to="{
path: '/userCertificate',
query: { id: scope.row.id }
}"
>
<el-button type="text" size="small">
证书管理
</el-button>
</router-link>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown> -->
</template>
</el-table-column>
<!-- <el-dropdown-item>
<el-button type="text" size="small" @click="openVip(scope.row)">
开通VIP
</el-button>
</el-dropdown-item> -->
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
>
</el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update
v-if="addOrUpdateVisible"
ref="addOrUpdate"
@refreshDataList="getDataList"
></add-or-update>
<!-- 开通VIP -->
<open-vip v-if="openVipVisible" ref="openVip"> </open-vip>
<el-dialog
title="充/扣天医币"
:close-on-click-modal="false"
:visible.sync="adc"
append-to-body
width="30%"
:before-close="closeDia"
>
<el-form
:model="pointForm"
label-width="100px"
:rules="pointFormRules"
ref="pointForm"
>
<el-form-item label="用户">
{{ pointForm.tel }}
<span v-if="pointForm.name != ''">({{ pointForm.name }})</span>
<span
>账户余额<em
style="font-style: normal; font-size: 16px; color: #17B3A3;"
>{{ pointForm.peanutCoin }}</em
></span
>
</el-form-item>
<!-- <el-form-item label="充/扣主题">
<el-input v-model="pointForm.title"></el-input>
</el-form-item> -->
<el-form-item label="充值类型" prop="pointType">
<!-- <el-input v-model="pointForm.pointType" placeholder="0-普通 1-vip"></el-input>
-->
<el-select v-model="pointForm.pointType" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="金额" prop="pointAmount">
<el-input-number
v-model="pointForm.pointAmount"
:placeholder="pointForm.peanutCoin + '可用'"
>
</el-input-number>
</el-form-item>
<el-form-item label="充扣明细">
<el-input
type="textarea"
rows="5"
v-model="pointForm.remark"
placeholder="操作说明"
>
</el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="closeDia">取消</el-button>
<el-button type="primary" @click="huaSheng(pointForm.peanutCoin)"
>确定</el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import OpenVip from "./user-open-vip";
export default {
data() {
return {
dataForm: {
key: ""
},
pointFormRules: {
pointAmount: [
{ required: true, message: "请输入金额", trigger: "blur" }
],
pointType: {
required: true,
message: "请选择操作类型",
trigger: "blur"
}
},
vipList: [],
options: [
{
value: 0,
label: "充天医币"
},
{
value: 1,
label: "扣天医币"
}
],
adc: false,
pointForm: {
pointType: 0,
remark: "",
// title:'',
pointAmount: 0
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
total: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false,
youVisible: false,
youForm: {},
currentuserInfo: {},
courperList: [],
courperHistList: [],
//开通vip
openVipVisible: false
};
},
components: {OpenVip},
activated() {
this.getDataList();
},
methods: {
handleDetail(id){
this.$router.push({
name: "vipList-vipDetail",
query: {
id: id
}
})
},
detailHandle(row) {
console.log("row at line 447:", row);
this.$router.push({
name: "user-user",
params: {
key: row.tel || row.email
}
});
},
//批量开通课程
addOpenCourse() {
this.$router.push("/user-add-course");
},
//开通vip
openVip() {
this.openVipVisible = true;
this.$nextTick(() => {
this.$refs.openVip.init();
});
},
computedVipType(userVips) {
if (!userVips || userVips.length === 0) return "";
const vipMap = {
4: "中医VIP",
5: "针灸VIP",
6: "肿瘤VIP",
7: "国学VIP",
8: "心理学VIP"
};
// 将 userVips 转为数组形式,以便处理(如果是数字则转为数字数组)
let vipTypes = [];
if (typeof userVips === "number") {
vipTypes = String(userVips)
.split("")
.map(Number); // 数字转为数组
} else {
vipTypes = userVips.map(vip => vip.type); // 如果是对象数组,获取每个对象的 type
}
// 判断是否同时包含 4、5、6医学SVIP
const hasMedicalSVip = [4, 5, 6].every(type => vipTypes.includes(type));
// 判断是否同时包含 7、8心理学SVIP
const hasPsychologySVip = [7, 8].every(type => vipTypes.includes(type));
const tags = [];
vipTypes.forEach(type => {
if (type == 4 || type == 5 || type == 6) {
tags.push(
`<el-tag size="mini" type="info" style="font-weight: bold; color: #fff;display:inline-block;margin-bottom: 6px; padding:0 6px; border-radius: 2px; font-size: 11px; background: #409EFF;" effect="dark">${vipMap[type]}</el-tag>`
);
} else if (type == 7 ) {
tags.push(
`<el-tag size="mini" type="info" style="font-weight: bold; color: #fff;display:inline-block;margin-bottom: 6px; padding:0 6px; border-radius: 2px; font-size: 11px; background:#67c23a" effect="dark">${vipMap[type]}</el-tag>`
);
} else if (type == 8 ) {
tags.push(
`<el-tag size="mini" type="info" style="font-weight: bold; color: #fff;display:inline-block;margin-bottom: 6px; background: #00bcd4; padding:0 6px; border-radius: 2px; font-size: 11px; " effect="dark">${vipMap[type]}</el-tag>`
);
}
});
// 1. 医学SVIP只显示一次
// if (hasMedicalSVip) {
// tags.push(
// `<el-tag size="mini" type="warning" style="font-weight: bold; background-image: linear-gradient(90deg, #ff1f00 0%, #fa9f93 100%); color: #fff; padding: 2px; border-radius: 2px; font-size: 11px;" effect="dark">医学SVIP</el-tag>`
// );
// }
// // 2. 心理学SVIP只显示一次
// if (hasPsychologySVip) {
// tags.push(
// `<el-tag size="mini" type="warning" style="font-weight: bold; background-image: linear-gradient(90deg, #67c23a 0%, #e1f3d8 100%); color: #fff; padding: 2px; border-radius: 2px; font-size: 11px;" effect="dark">心理学SVIP</el-tag>`
// );
// }
// // 3. 普通VIP标签确保不重复显示SVIP相关的类型
// vipTypes
// .filter(
// type =>
// vipMap[type] &&
// !(
// (
// (hasMedicalSVip && [4, 5, 6].includes(type)) || // 医学SVIP已显示排除 4、5、6
// (hasPsychologySVip && [7, 8].includes(type))
// ) // 心理学SVIP已显示排除 7、8
// )
// )
// .forEach(type => {
// tags.push(
// `<el-tag size="mini" type="info" style="font-weight: bold; color: #fff; padding: 2px; border-radius: 2px; font-size: 11px; background: #409EFF;" effect="dark">${vipMap[type]}</el-tag>`
// );
// });
return tags.join("<br/>");
},
getVipMoney(data) {
this.$http({
url: this.$http.adornUrl("/master/userVip/getVipProductForUser"),
method: "post",
data: this.$http.adornData({
uid: data.id
})
}).then(({ data }) => {
if (data && data.code === 0) {
var list = [];
console.log("data at line 436:", data.list);
for (let i in data.list) {
if (data.list[i].length > 0) {
list.push([...data.list[i]]);
}
}
this.vipList = list.flat(Infinity);
console.log("this.vipList at line 440:", this.vipList);
} else {
this.$message.error(data.msg);
this.vipList = [];
}
});
},
closeCoupon(val) {
this.youVisible = false;
},
// 用户课程
userCourse(val) {},
// 获取数据列表
getDataList() {
this.dataListLoading = true;
this.$http({
// url: this.$http.adornUrl('/book/user/list'),
url: this.$http.adornUrl("/book/user/getUserList"),
method: "post",
data: this.$http.adornData({
page: this.pageIndex,
limit: this.pageSize,
key: this.dataForm.key,
vipType: this.dataForm.vipType
})
// params: this.$http.adornParams({
// 'page': 1,
// 'limit': this.pageSize,
// 'key': this.dataForm.key
// })
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.user.records;
this.totalPage = data.user.pages;
this.total = data.user.total;
this.dataListLoading = false;
}
});
},
// 重置密码
resetPassword(row) {
console.log(row, "row");
this.$prompt("请输入新密码", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消"
// inputPattern: /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
// inputErrorMessage: '邮箱格式不正确'
})
.then(({ value }) => {
this.$http({
url: this.$http.adornUrl("/book/user/updateUserPassword"),
method: "post",
data: this.$http.adornData({
id: row.id,
password: value
})
})
.then(({ data }) => {
if (data && data.code === 0) {
this.$message.success("修改密码成功");
}
})
.catch(({ e }) => {
console.log(e, "e");
});
// this.$message({
// type: 'success',
// message: '你的邮箱是: ' + value
// });
})
.catch(() => {
// this.$message({
// type: 'info',
// message: '取消输入'
// });
});
},
// 每页数
sizeChangeHandle(val) {
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
// 当前页
currentChangeHandle(val) {
this.pageIndex = val;
this.getDataList();
},
// 多选
selectionChangeHandle(val) {
this.dataListSelections = val;
},
// 新增 / 修改
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id);
});
},
closeDia() {
this.adc = false;
this.$refs.pointForm.resetFields();
// this.pointForm.pointType == 0
},
// 删除
deleteHandle(id) {
var ids = id
? [id]
: this.dataListSelections.map(item => {
return item.id;
});
this.$confirm(
`确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).then(() => {
this.$http({
url: this.$http.adornUrl("/book/user/delete"),
method: "post",
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.getDataList();
}
});
} else {
this.$message.error(data.msg);
}
});
});
},
// 充值扣款天医币
ck(e) {
this.pointForm = e;
this.adc = true;
},
handleRecharge(val) {
this.currentuserInfo = val;
this.$nextTick(() => {
this.$refs.addCertificate.init("add", {});
});
},
handleJF(val) {
this.currentuserInfo = val;
this.$nextTick(() => {
this.$refs.addJF.init("add", {});
});
},
huaSheng(point) {
// console.log(this.pointForm.pointAmount, point)
if (this.pointForm.pointAmount <= 0) {
this.$message.error("金额不能小于0");
return false;
}
if (this.pointForm.pointAmount > point && this.pointForm.pointType == 1) {
return this.$message.error("扣除金额不能大于总金额");
}
this.$refs["pointForm"].validate(valid => {
this.$http({
url: this.$http.adornUrl(
`/book/user/pointChange?pointType=${this.pointForm.pointType}&note=${this.pointForm.remark}&pointAmount=${this.pointForm.pointAmount}&id=${this.pointForm.id}`
),
method: "get",
params: this.$http.adornParams()
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success("操作成功");
this.getDataList();
this.adc = false;
}
});
});
},
courDelete(e) {
let arrList = [];
arrList.push(e.id);
this.$http({
url: this.$http.adornUrl("/book/couponhistory/delete"),
method: "post",
data: this.$http.adornData(arrList, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "删除成功",
type: "success",
duration: 1500
});
this.youhui(this.youForm);
this.youVisible = true;
}
});
}
}
};
</script>
<style scoped>
/deep/ .mod-config .el-table .el-table__cell {
padding: 4px 0 !important;
box-sizing: border-box;
}
/deep/ .mod-config .el-table .cell,
.el-table th div {
padding: 0 !important;
box-sizing: border-box;
}
</style>