feat: 会员详情弹框样式
This commit is contained in:
parent
8aa41006de
commit
562a766257
|
@ -414,7 +414,7 @@ export default {
|
|||
menuId: getUUID(),
|
||||
parentId: 0,
|
||||
parentName: null,
|
||||
name: "用户管理",
|
||||
name: "会员列表",
|
||||
url: "marketing/user/index",
|
||||
perms: "",
|
||||
type: 1,
|
||||
|
|
|
@ -32,6 +32,12 @@ const globalRoutes = [
|
|||
component: _import("common/login"),
|
||||
name: "login",
|
||||
meta: { title: "登录" }
|
||||
},
|
||||
{
|
||||
path: "/test-member-detail",
|
||||
component: _import("test-member-detail"),
|
||||
name: "test-member-detail",
|
||||
meta: { title: "会员详情样式测试" }
|
||||
}
|
||||
//test用,会员管理
|
||||
];
|
||||
|
|
|
@ -6,34 +6,34 @@
|
|||
* @Description:
|
||||
* @FilePath: \background-front-end\src\utils\httpRequest.js
|
||||
*/
|
||||
import Vue from 'vue'
|
||||
import axios from 'axios'
|
||||
import router from '@/router'
|
||||
import qs from 'qs'
|
||||
import merge from 'lodash/merge'
|
||||
import { Message } from 'element-ui'
|
||||
import { clearLoginInfo } from '@/utils'
|
||||
import commonUtil from './common'
|
||||
import des from './des.js'
|
||||
import Vue from "vue";
|
||||
import axios from "axios";
|
||||
import router from "@/router";
|
||||
import qs from "qs";
|
||||
import merge from "lodash/merge";
|
||||
import { Message } from "element-ui";
|
||||
import { clearLoginInfo } from "@/utils";
|
||||
import commonUtil from "./common";
|
||||
import des from "./des.js";
|
||||
|
||||
const http = axios.create({
|
||||
baseURL:
|
||||
process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY
|
||||
? '/proxyApi/'
|
||||
process.env.NODE_ENV !== "production" && process.env.OPEN_PROXY
|
||||
? "/proxyApi/"
|
||||
: window.SITE_CONFIG.baseUrl,
|
||||
timeout: 1000 * 30,
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* 请求拦截
|
||||
*/
|
||||
http.interceptors.request.use(
|
||||
config => {
|
||||
config.headers['token'] = `Bearer ${Vue.cookie.get('token')}` // 请求头带上token
|
||||
config.headers["token"] = `Bearer ${Vue.cookie.get("token")}`; // 请求头带上token
|
||||
// 针对post请求加密
|
||||
// if (config.method.toLowerCase() === "post" && process.env.NODE_ENV === "production" ) {
|
||||
// //如果已经转成字符串了,就不用再转了
|
||||
|
@ -47,16 +47,16 @@ http.interceptors.request.use(
|
|||
// );
|
||||
// }
|
||||
// }
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log(`【请求】${config.url}`, config)
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
console.log(`【请求】${config.url}`, config);
|
||||
}
|
||||
|
||||
return config
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
return Promise.reject(error)
|
||||
return Promise.reject(error);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// /**
|
||||
// * 响应拦截
|
||||
|
@ -147,56 +147,56 @@ http.interceptors.request.use(
|
|||
http.interceptors.response.use(
|
||||
response => {
|
||||
//开发环境下才可以打印日志
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log(`【响应】${response.config.url}`, response)
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
console.log(`【响应】${response.config.url}`, response);
|
||||
}
|
||||
if (response.data && response.data.code == 401) {
|
||||
// 401, 权限未认证
|
||||
clearLoginInfo()
|
||||
router.push({ name: 'login' })
|
||||
return Promise.resolve(response)
|
||||
clearLoginInfo();
|
||||
router.push({ name: "login" });
|
||||
return Promise.resolve(response);
|
||||
} else if (response.data && response.data.code != 200) {
|
||||
// Message.closeAll();
|
||||
Message({
|
||||
message: response.data.msg || response.data.message,
|
||||
type: 'error'
|
||||
})
|
||||
return Promise.reject(response)
|
||||
type: "error"
|
||||
});
|
||||
return Promise.reject(response);
|
||||
} else {
|
||||
//请求成功的情况
|
||||
//如果是开发模式下,都要弹出
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
// Message.closeAll();
|
||||
if (!response.config.hidemsg) {
|
||||
Message({
|
||||
message: response.data.msg || response.data.message,
|
||||
type: 'success'
|
||||
})
|
||||
// Message({
|
||||
// message: response.data.msg || response.data.message,
|
||||
// type: 'success'
|
||||
// })
|
||||
}
|
||||
}
|
||||
// 生产环境下限制性弹出
|
||||
else {
|
||||
if (
|
||||
response.data.msg != 'success' &&
|
||||
response.data.msg != '查询成功' &&
|
||||
Object.prototype.toString.call(response.data) === '[object Object]'
|
||||
response.data.msg != "success" &&
|
||||
response.data.msg != "查询成功" &&
|
||||
Object.prototype.toString.call(response.data) === "[object Object]"
|
||||
) {
|
||||
// Message.closeAll();
|
||||
if (!response.config.hidemsg) {
|
||||
Message({
|
||||
message: response.data.msg || response.data.message,
|
||||
type: 'success'
|
||||
})
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.resolve(response)
|
||||
return Promise.resolve(response);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
return Promise.reject(error)
|
||||
return Promise.reject(error);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* 请求地址处理
|
||||
|
@ -205,11 +205,11 @@ http.interceptors.response.use(
|
|||
http.adornUrl = actionName => {
|
||||
// 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截!
|
||||
return (
|
||||
(process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY
|
||||
? '/proxyApi/'
|
||||
(process.env.NODE_ENV !== "production" && process.env.OPEN_PROXY
|
||||
? "/proxyApi/"
|
||||
: window.SITE_CONFIG.baseUrl) + actionName
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* get请求参数处理
|
||||
|
@ -219,9 +219,9 @@ http.adornUrl = actionName => {
|
|||
http.adornParams = (params = {}, openDefultParams = true) => {
|
||||
var defaults = {
|
||||
t: new Date().getTime()
|
||||
}
|
||||
return openDefultParams ? merge(defaults, params) : params
|
||||
}
|
||||
};
|
||||
return openDefultParams ? merge(defaults, params) : params;
|
||||
};
|
||||
|
||||
/**
|
||||
* post请求数据处理
|
||||
|
@ -231,12 +231,12 @@ http.adornParams = (params = {}, openDefultParams = true) => {
|
|||
* json: 'application/json; charset=utf-8'
|
||||
* form: 'application/x-www-form-urlencoded; charset=utf-8'
|
||||
*/
|
||||
http.adornData = (data = {}, openDefultdata = true, contentType = 'json') => {
|
||||
http.adornData = (data = {}, openDefultdata = true, contentType = "json") => {
|
||||
var defaults = {
|
||||
t: new Date().getTime()
|
||||
}
|
||||
data = openDefultdata ? merge(defaults, data) : data
|
||||
return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data)
|
||||
}
|
||||
};
|
||||
data = openDefultdata ? merge(defaults, data) : data;
|
||||
return contentType === "json" ? JSON.stringify(data) : qs.stringify(data);
|
||||
};
|
||||
|
||||
export default http
|
||||
export default http;
|
||||
|
|
|
@ -951,7 +951,6 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.level-detail {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
min-height: calc(100vh - 84px);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
>
|
||||
<template slot="tableTop">
|
||||
<el-form :inline="true" :model="form" class="demo-form-inline">
|
||||
<el-form-item v-if="storeList.length > 1" label="店铺">
|
||||
<el-form-item v-if="storeList.length > 1" label="所属店铺">
|
||||
<el-select v-model="formInline.shopId" placeholder="请选择店铺">
|
||||
<el-option
|
||||
v-for="item in storeList"
|
||||
|
@ -22,40 +22,23 @@
|
|||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户ID">
|
||||
<el-input
|
||||
placeholder="请输入用户ID"
|
||||
v-model="form.userId"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户昵称">
|
||||
<el-input
|
||||
placeholder="请输入用户昵称"
|
||||
v-model="form.username"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="会员等级id">
|
||||
<el-input
|
||||
placeholder="请输入会员等级id"
|
||||
<el-form-item label="会员等级">
|
||||
<el-select
|
||||
v-model="form.levelId"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号">
|
||||
<el-input
|
||||
placeholder="请输入手机号"
|
||||
v-model="form.mobile"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="会员状态">
|
||||
<el-select v-model="form.isMemberUser" placeholder="请选择会员状态">
|
||||
placeholder="请选择会员等级"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in [
|
||||
{ label: '是', value: 1 },
|
||||
{ label: '否', value: 0 },
|
||||
]"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
v-for="item in memberLevelList"
|
||||
:key="item.levelId"
|
||||
:label="item.levelName"
|
||||
:value="item.levelId"
|
||||
></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
@ -90,31 +73,32 @@
|
|||
<div class="stat-item">
|
||||
<i style="font-size: 22px" class="el-icon-user-solid"></i>
|
||||
<div class="stat-right">
|
||||
<div class="stat-title">用户数量(人)</div>
|
||||
<div class="stat-value">
|
||||
<span style="font-size: 20px">{{
|
||||
overviewList.totalCount
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="stat-title">会员总数</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<i style="font-size: 22px" class="el-icon-s-custom"></i>
|
||||
<div class="stat-right">
|
||||
<div class="stat-title">今日新增(人)</div>
|
||||
<div class="stat-value">
|
||||
<span style="font-size: 20px">{{
|
||||
overviewList.todayCount
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="stat-title">今日新增</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<el-button type="success" size="small" @click="userExport"
|
||||
>导出</el-button
|
||||
>
|
||||
</div>
|
||||
<!-- 测试按钮 -->
|
||||
<!-- <div class="test-buttons" style="margin-bottom: 10px;">
|
||||
<el-button type="success" size="small" @click="showTestDetail">
|
||||
测试查看会员详情样式
|
||||
</el-button>
|
||||
</div> -->
|
||||
</template>
|
||||
</obj-table-plus>
|
||||
<!-- 修改积分或成长值 -->
|
||||
|
@ -128,8 +112,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import * as XLSX from "xlsx";
|
||||
import { saveAs } from "file-saver";
|
||||
import modifyPoints from "./popup/modify-points.vue";
|
||||
import viewDetails from "./popup/view-details.vue";
|
||||
import { mapState } from "vuex";
|
||||
|
@ -141,7 +123,7 @@ export default {
|
|||
formInline: {
|
||||
marketId: "",
|
||||
shopId: "",
|
||||
unitType: "",
|
||||
unitType: ""
|
||||
},
|
||||
form: {},
|
||||
tableProp: {
|
||||
|
@ -149,12 +131,13 @@ export default {
|
|||
border: true,
|
||||
height: "auto",
|
||||
"row-id": "id",
|
||||
"show-overflow": false,
|
||||
"show-overflow": false
|
||||
},
|
||||
productFilterType: "SALE",
|
||||
selectList: [],
|
||||
value1: [],
|
||||
overviewList: {},
|
||||
memberLevelList: [] // 会员等级列表
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
@ -164,45 +147,57 @@ export default {
|
|||
? 3
|
||||
: 2,
|
||||
marketId: this.marketId,
|
||||
shopId: this.shopId,
|
||||
shopId: this.shopId
|
||||
};
|
||||
this.getMemberLevelList();
|
||||
this.$nextTick(() => {
|
||||
this.$refs.oTable.reload();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
// getData() {
|
||||
// this.$api.mer_admin
|
||||
// .storeList({ marketId: this.formInline.marketId })
|
||||
// .then((res) => {
|
||||
// this.storeList = res.data.data;
|
||||
// this.formInline.shopId = res.data.data[0].shopId;
|
||||
// this.$nextTick(() => {
|
||||
// this.$refs.oTable.reload();
|
||||
// });
|
||||
// });
|
||||
// },
|
||||
// 获取会员等级列表
|
||||
getMemberLevelList() {
|
||||
this.$api.marketing
|
||||
.marketingLevelPage({
|
||||
...this.formInline
|
||||
})
|
||||
.then(res => {
|
||||
if (res.data.code === 0) {
|
||||
this.memberLevelList = res.data.data || [];
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.memberLevelList = [];
|
||||
});
|
||||
},
|
||||
// 手机号脱敏处理
|
||||
maskMobile(mobile) {
|
||||
if (!mobile || mobile.length !== 11) {
|
||||
return mobile;
|
||||
}
|
||||
return mobile.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
|
||||
},
|
||||
queryList(pageNo, pageSize) {
|
||||
this.$api.marketing
|
||||
.marketingUserPage({
|
||||
pageNumber: pageNo,
|
||||
pageSize: pageSize,
|
||||
...this.formInline,
|
||||
...this.form,
|
||||
...this.form
|
||||
})
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
console.log(res);
|
||||
this.$refs.oTable.complete(
|
||||
res.data.data.data,
|
||||
Number(res.data.data.total)
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
.catch(() => {
|
||||
this.$refs.oTable.complete(false);
|
||||
});
|
||||
this.$api.marketing
|
||||
.overview({ ...this.formInline, ...this.form })
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
this.overviewList = res.data.data;
|
||||
});
|
||||
},
|
||||
|
@ -212,6 +207,27 @@ export default {
|
|||
this.$refs.oTable.reload();
|
||||
});
|
||||
},
|
||||
// 测试查看会员详情样式
|
||||
showTestDetail() {
|
||||
// 模拟会员数据
|
||||
const testMemberData = {
|
||||
userId: "3",
|
||||
username: "张三",
|
||||
mobile: "13812341234",
|
||||
birthday: "1990-05-15",
|
||||
headUrl:
|
||||
"https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
|
||||
levelName: "LV2",
|
||||
growthValue: 1250,
|
||||
memberPoints: 890,
|
||||
joinTime: "2023-01-15 10:30:00",
|
||||
registrationTime: "2023-01-15 10:30:00",
|
||||
id: 1 // 表示是会员
|
||||
};
|
||||
|
||||
// 调用详情弹框
|
||||
this.$refs.viewDetails.toggle(testMemberData).add();
|
||||
},
|
||||
changeTime(val) {
|
||||
if (val) {
|
||||
this.form.startRegistrationTime = val[0];
|
||||
|
@ -220,56 +236,24 @@ export default {
|
|||
this.form.startRegistrationTime = "";
|
||||
this.form.endRegistrationTime = "";
|
||||
}
|
||||
},
|
||||
async userExport() {
|
||||
let now = new Date();
|
||||
let year = now.getFullYear();
|
||||
let month = now.getMonth() + 1;
|
||||
let day = now.getDate();
|
||||
let res = await this.$api.marketing.marketingUserPage({
|
||||
pageNumber: 1,
|
||||
pageSize: 9999999,
|
||||
...this.formInline,
|
||||
...this.form,
|
||||
});
|
||||
console.log(res);
|
||||
let userData = res.data.data.data.map((item) => {
|
||||
return {
|
||||
用户ID: item.userId,
|
||||
用户头像: item.headUrl,
|
||||
用户昵称: item.username,
|
||||
手机号: item.mobile,
|
||||
会员等级id: item.levelId,
|
||||
会员等级名称: item.levelName,
|
||||
生日: item.birthday,
|
||||
注册时间: item.registrationTime,
|
||||
};
|
||||
});
|
||||
|
||||
const workbook = XLSX.utils.book_new();
|
||||
const worksheet = XLSX.utils.json_to_sheet(userData);
|
||||
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "用户管理");
|
||||
const excelData = XLSX.write(workbook, {
|
||||
type: "array",
|
||||
bookType: "xlsx",
|
||||
});
|
||||
const blob = new Blob([excelData], { type: "application/octet-stream" });
|
||||
saveAs(blob, `用户管理-${year + "" + month + day}.xlsx`);
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tableCols() {
|
||||
return [
|
||||
{ type: "checkbox", width: "60px", fixed: "left" },
|
||||
// { type: "seq", width: "60px", align: "center", title: "序号" },
|
||||
{
|
||||
title: "用戶ID",
|
||||
title: "所属店铺",
|
||||
align: "center",
|
||||
field: "userId",
|
||||
field: "shopName"
|
||||
},
|
||||
{
|
||||
title: "用戶头像",
|
||||
title: "用户ID",
|
||||
align: "center",
|
||||
field: "userId"
|
||||
},
|
||||
{
|
||||
title: "用户头像",
|
||||
align: "center",
|
||||
field: "headUrl",
|
||||
type: "jsx",
|
||||
|
@ -281,52 +265,60 @@ export default {
|
|||
preview-src-list={[row.headUrl]}
|
||||
></el-image>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "用戶昵称",
|
||||
title: "用户昵称",
|
||||
align: "center",
|
||||
field: "username",
|
||||
field: "username"
|
||||
},
|
||||
{
|
||||
title: "手机号",
|
||||
align: "center",
|
||||
field: "mobile",
|
||||
},
|
||||
// {
|
||||
// title: "进行中订单数",
|
||||
// align: "center",
|
||||
// field: "name",
|
||||
// },
|
||||
// {
|
||||
// title: "完成订单数",
|
||||
// align: "center",
|
||||
// field: "name",
|
||||
// },
|
||||
// {
|
||||
// title: "消费金额(元)",
|
||||
// align: "center",
|
||||
// field: "name",
|
||||
// },
|
||||
{
|
||||
title: "会员等级id",
|
||||
align: "center",
|
||||
field: "levelId",
|
||||
type: "jsx",
|
||||
render: ({ row }) => {
|
||||
return <span>{this.maskMobile(row.mobile)}</span>;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "会员等级名称",
|
||||
title: "会员等级",
|
||||
align: "center",
|
||||
field: "levelName",
|
||||
width: "120px",
|
||||
type: "jsx",
|
||||
render: ({ row }) => {
|
||||
if (!row.levelName) {
|
||||
return <span>-</span>;
|
||||
}
|
||||
// 根据等级名称设置不同颜色
|
||||
const getTagType = levelName => {
|
||||
if (levelName.includes("LV1") || levelName.includes("1"))
|
||||
return "";
|
||||
if (levelName.includes("LV2") || levelName.includes("2"))
|
||||
return "success";
|
||||
if (levelName.includes("LV3") || levelName.includes("3"))
|
||||
return "warning";
|
||||
if (levelName.includes("LV4") || levelName.includes("4"))
|
||||
return "danger";
|
||||
return "info";
|
||||
};
|
||||
return (
|
||||
<el-tag type={getTagType(row.levelName)} size="small">
|
||||
{row.levelName}
|
||||
</el-tag>
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "生日",
|
||||
align: "center",
|
||||
field: "birthday",
|
||||
field: "birthday"
|
||||
},
|
||||
{
|
||||
title: "注册时间",
|
||||
align: "center",
|
||||
field: "registrationTime",
|
||||
field: "registrationTime"
|
||||
},
|
||||
// {
|
||||
// title: "限量",
|
||||
|
@ -338,66 +330,28 @@ export default {
|
|||
fixed: "right",
|
||||
type: "jsx",
|
||||
align: "center",
|
||||
width: "280px",
|
||||
width: "100px",
|
||||
render: ({ row }) => {
|
||||
let viewDetails = () => {
|
||||
this.$api.marketing
|
||||
.memberUnitUserDetail({
|
||||
...this.formInline,
|
||||
userId: row.userId,
|
||||
userId: row.userId
|
||||
})
|
||||
.then((res) => {
|
||||
.then(res => {
|
||||
console.log(res);
|
||||
this.$refs.viewDetails.toggle(res.data.data).add();
|
||||
});
|
||||
};
|
||||
let points = () => {
|
||||
this.$api.marketing
|
||||
.memberUnitUserDetail({
|
||||
...this.formInline,
|
||||
userId: row.userId,
|
||||
})
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
this.$refs.modifyPoints.toggle(res.data.data).add();
|
||||
});
|
||||
};
|
||||
let growthValue = () => {
|
||||
this.$api.marketing
|
||||
.memberUnitUserDetail({
|
||||
...this.formInline,
|
||||
userId: row.userId,
|
||||
})
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
this.$refs.modifyPoints.toggle(res.data.data).update();
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<el-button size="mini" type="primary" onClick={viewDetails}>
|
||||
详情
|
||||
</el-button>
|
||||
<el-button
|
||||
v-show={!row.id}
|
||||
size="mini"
|
||||
type="primary"
|
||||
onClick={points}
|
||||
>
|
||||
修改积分
|
||||
</el-button>
|
||||
<el-button
|
||||
v-show={!row.id}
|
||||
size="mini"
|
||||
type="primary"
|
||||
onClick={growthValue}
|
||||
>
|
||||
修改成长值
|
||||
</el-button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
];
|
||||
},
|
||||
tableEvent() {
|
||||
|
@ -407,7 +361,7 @@ export default {
|
|||
},
|
||||
"checkbox-change": ({ records, reserves }) => {
|
||||
this.selectList = [...records, ...reserves];
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
...mapState("userData", [
|
||||
|
@ -415,9 +369,9 @@ export default {
|
|||
"marketList",
|
||||
"storeList",
|
||||
"marketId",
|
||||
"shopId",
|
||||
]),
|
||||
},
|
||||
"shopId"
|
||||
])
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
@ -433,7 +387,7 @@ export default {
|
|||
}
|
||||
.stat-item {
|
||||
width: 30%;
|
||||
margin: 20px 20px;
|
||||
margin: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
@ -444,4 +398,4 @@ export default {
|
|||
.stat-title {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
title="成长值详情"
|
||||
:visible.sync="visible"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="detail-content">
|
||||
<!-- 基础信息 -->
|
||||
<div class="detail-row">
|
||||
<span class="label">变化原因:</span>
|
||||
<span class="value">{{ detailData.changeReason || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">变化时间:</span>
|
||||
<span class="value">{{ detailData.changeTime || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">成长值增加:</span>
|
||||
<span class="value growth-value" :style="{ color: getGrowthColor(detailData.growthChange) }">
|
||||
{{ detailData.growthChange > 0 ? '+' : '' }}{{ detailData.growthChange || 0 }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 有关联订单时显示的字段 -->
|
||||
<template v-if="hasRelatedOrder">
|
||||
<div class="detail-row">
|
||||
<span class="label">订单编号:</span>
|
||||
<span class="value">{{ detailData.relatedOrder || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">订单总金额:</span>
|
||||
<span class="value">¥{{ detailData.orderAmount || '0.00' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">订单时间:</span>
|
||||
<span class="value">{{ detailData.orderTime || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">订单归属摊位:</span>
|
||||
<span class="value">{{ detailData.shopName || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">成长值变化:</span>
|
||||
<span class="value growth-value" :style="{ color: getGrowthColor(detailData.growthChange) }">
|
||||
{{ detailData.growthChange > 0 ? '+' : '' }}{{ detailData.growthChange || 0 }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 无关联订单时显示的描述 -->
|
||||
<template v-if="!hasRelatedOrder && detailData.description">
|
||||
<div class="description-section">
|
||||
<div class="description-text">
|
||||
{{ detailData.description }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "GrowthDetail",
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
detailData: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasRelatedOrder() {
|
||||
return this.detailData.relatedOrder && this.detailData.relatedOrder !== '-';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show(data) {
|
||||
this.detailData = data;
|
||||
this.visible = true;
|
||||
},
|
||||
handleClose() {
|
||||
this.visible = false;
|
||||
this.detailData = {};
|
||||
},
|
||||
getGrowthColor(value) {
|
||||
return value > 0 ? '#67C23A' : '#F56C6C';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detail-content {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.growth-value {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.description-section {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px dashed #e4e7ed;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
background: #f5f7fa;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #409eff;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,168 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
title="积分详情"
|
||||
:visible.sync="visible"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="detail-content">
|
||||
<!-- 基础信息 -->
|
||||
<div class="detail-row">
|
||||
<span class="label">变化原因:</span>
|
||||
<span class="value">{{ detailData.changeReason || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">变化时间:</span>
|
||||
<span class="value">{{ detailData.changeTime || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">积分变动:</span>
|
||||
<span class="value points-value" :style="{ color: getPointsColor(detailData.pointsChange) }">
|
||||
{{ detailData.pointsChange > 0 ? '+' : '' }}{{ detailData.pointsChange || 0 }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 有关联订单时显示的字段 -->
|
||||
<template v-if="hasRelatedOrder">
|
||||
<div class="detail-row">
|
||||
<span class="label">订单编号:</span>
|
||||
<span class="value">{{ detailData.relatedOrder || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">订单总金额:</span>
|
||||
<span class="value">¥{{ detailData.orderAmount || '0.00' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">订单时间:</span>
|
||||
<span class="value">{{ detailData.orderTime || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">订单归属摊位:</span>
|
||||
<span class="value">{{ detailData.shopName || '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 无关联订单且是使用积分时显示的字段 -->
|
||||
<template v-if="!hasRelatedOrder && isPointsUsage">
|
||||
<div class="detail-row">
|
||||
<span class="label">兑换商品:</span>
|
||||
<span class="value">{{ detailData.exchangeProduct || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-row">
|
||||
<span class="label">兑换数量:</span>
|
||||
<span class="value">{{ detailData.exchangeQuantity || '-' }}</span>
|
||||
</div>
|
||||
|
||||
<div class="description-section">
|
||||
<div class="description-text">
|
||||
{{ detailData.usageDescription || '使用积分兑换商品,兑换成功后积分将被扣除且不可退还。' }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 无关联订单且是获得积分时显示的描述 -->
|
||||
<template v-if="!hasRelatedOrder && !isPointsUsage && detailData.description">
|
||||
<div class="description-section">
|
||||
<div class="description-text">
|
||||
{{ detailData.description }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">关闭</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "PointsDetail",
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
detailData: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
hasRelatedOrder() {
|
||||
return this.detailData.relatedOrder && this.detailData.relatedOrder !== '-';
|
||||
},
|
||||
isPointsUsage() {
|
||||
return this.detailData.pointsChange < 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show(data) {
|
||||
this.detailData = data;
|
||||
this.visible = true;
|
||||
},
|
||||
handleClose() {
|
||||
this.visible = false;
|
||||
this.detailData = {};
|
||||
},
|
||||
getPointsColor(value) {
|
||||
return value > 0 ? '#67C23A' : '#F56C6C';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detail-content {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.points-value {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.description-section {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px dashed #e4e7ed;
|
||||
}
|
||||
|
||||
.description-text {
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
background: #f5f7fa;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
border-left: 4px solid #409eff;
|
||||
}
|
||||
</style>
|
|
@ -9,55 +9,285 @@
|
|||
:modalHandles="modalHandles"
|
||||
>
|
||||
<template slot="dialog__after">
|
||||
<div style="padding: 20px">
|
||||
<el-descriptions title="用户信息">
|
||||
<el-descriptions-item label="头像">
|
||||
<el-image
|
||||
style="width: 60px; height: 60px"
|
||||
:src="modalData.headUrl"
|
||||
:preview-src-list="[modalData.headUrl]"
|
||||
>
|
||||
</el-image>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="用户名">{{
|
||||
modalData.username
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="ID">{{
|
||||
modalData.userId
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{
|
||||
modalData.mobile
|
||||
}}</el-descriptions-item>
|
||||
<!-- <el-descriptions-item label=""
|
||||
>江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item
|
||||
> -->
|
||||
</el-descriptions>
|
||||
<!-- 用户信息顶部展示 -->
|
||||
<div class="user-info-header">
|
||||
<div class="user-basic-info">
|
||||
<div class="info-row">
|
||||
<div class="info-item">
|
||||
<span class="label">会员姓名:</span>
|
||||
<span class="value">{{ modalData.username || "-" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">系统编号:</span>
|
||||
<span class="value">{{ modalData.userId || "-" }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">手机号:</span>
|
||||
<span class="value">{{ maskMobile(modalData.mobile) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<div class="info-item">
|
||||
<span class="label">生日:</span>
|
||||
<span class="value">{{ modalData.birthday || "-" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-stats">
|
||||
<div class="stat-card">
|
||||
<div class="stat-number">{{ modalData.growthValue || 0 }}</div>
|
||||
<div class="stat-label">会员成长值</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number">{{ modalData.memberPoints || 0 }}</div>
|
||||
<div class="stat-label">会员积分</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-number">{{ couponCount }}</div>
|
||||
<div class="stat-label">会员优惠券</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="modalData.id"
|
||||
style="margin-top: 20px; border-top: 1px solid #ccc; padding: 20px"
|
||||
>
|
||||
<el-descriptions title="会员信息">
|
||||
<el-descriptions-item label="会员名称">{{
|
||||
modalData.levelName
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="生日">{{
|
||||
modalData.birthday
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="加入会员时间">{{
|
||||
modalData.joinTime
|
||||
}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<!-- Tab分页内容 -->
|
||||
<div class="tab-content">
|
||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="会员成长值明细" name="growth">
|
||||
<el-table
|
||||
:data="growthList"
|
||||
border
|
||||
style="width: 100%"
|
||||
v-loading="growthLoading"
|
||||
>
|
||||
<el-table-column
|
||||
prop="changeTime"
|
||||
label="变化时间"
|
||||
width="180"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="growthChange"
|
||||
label="成长值变动"
|
||||
width="120"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span
|
||||
:style="{
|
||||
color:
|
||||
scope.row.growthChange > 0 ? '#67C23A' : '#F56C6C'
|
||||
}"
|
||||
>
|
||||
{{ scope.row.growthChange > 0 ? "+" : ""
|
||||
}}{{ scope.row.growthChange }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="relatedOrder"
|
||||
label="关联订单"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column label="详情" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
@click="viewGrowthDetail(scope.row)"
|
||||
>
|
||||
查看详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@size-change="handleGrowthSizeChange"
|
||||
@current-change="handleGrowthCurrentChange"
|
||||
:current-page="growthPagination.currentPage"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="growthPagination.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="growthPagination.total"
|
||||
style="margin-top: 20px; text-align: center"
|
||||
>
|
||||
</el-pagination>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="会员积分明细" name="points">
|
||||
<el-table
|
||||
:data="pointsList"
|
||||
border
|
||||
style="width: 100%"
|
||||
v-loading="pointsLoading"
|
||||
>
|
||||
<el-table-column
|
||||
prop="changeTime"
|
||||
label="变化时间"
|
||||
width="180"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="pointsChange"
|
||||
label="积分变动"
|
||||
width="120"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span
|
||||
:style="{
|
||||
color:
|
||||
scope.row.pointsChange > 0 ? '#67C23A' : '#F56C6C'
|
||||
}"
|
||||
>
|
||||
{{ scope.row.pointsChange > 0 ? "+" : ""
|
||||
}}{{ scope.row.pointsChange }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="changeType"
|
||||
label="变动类型"
|
||||
width="120"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="relatedOrder"
|
||||
label="关联订单"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column label="详情" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
@click="viewPointsDetail(scope.row)"
|
||||
>
|
||||
查看详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@size-change="handlePointsSizeChange"
|
||||
@current-change="handlePointsCurrentChange"
|
||||
:current-page="pointsPagination.currentPage"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="pointsPagination.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="pointsPagination.total"
|
||||
style="margin-top: 20px; text-align: center"
|
||||
>
|
||||
</el-pagination>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="会员优惠券" name="coupons">
|
||||
<el-table
|
||||
:data="couponsList"
|
||||
border
|
||||
style="width: 100%"
|
||||
v-loading="couponsLoading"
|
||||
>
|
||||
<el-table-column
|
||||
prop="couponName"
|
||||
label="优惠券名称"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="couponType"
|
||||
label="类型"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="faceValue"
|
||||
label="面额"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.couponType === '折扣券'"
|
||||
>{{ scope.row.faceValue }}折</span
|
||||
>
|
||||
<span v-else>¥{{ scope.row.faceValue }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="useCondition"
|
||||
label="使用条件"
|
||||
width="120"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="receiveTime"
|
||||
label="获得时间"
|
||||
width="180"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="validPeriod"
|
||||
label="有效期"
|
||||
width="180"
|
||||
align="center"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="useStatus"
|
||||
label="使用状态"
|
||||
width="100"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag
|
||||
:type="getStatusTagType(scope.row.useStatus)"
|
||||
size="small"
|
||||
>
|
||||
{{ scope.row.useStatus }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
@size-change="handleCouponsSizeChange"
|
||||
@current-change="handleCouponsCurrentChange"
|
||||
:current-page="couponsPagination.currentPage"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="couponsPagination.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="couponsPagination.total"
|
||||
style="margin-top: 20px; text-align: center"
|
||||
>
|
||||
</el-pagination>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
</obj-modal>
|
||||
|
||||
<!-- 成长值详情弹框 -->
|
||||
<growth-detail ref="growthDetail"></growth-detail>
|
||||
|
||||
<!-- 积分详情弹框 -->
|
||||
<points-detail ref="pointsDetail"></points-detail>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { debounce, cloneDeep } from "lodash";
|
||||
import { Divider } from "element-ui";
|
||||
import { cloneDeep } from "lodash";
|
||||
import GrowthDetail from "./growth-detail.vue";
|
||||
import PointsDetail from "./points-detail.vue";
|
||||
export default {
|
||||
components: {},
|
||||
components: {
|
||||
GrowthDetail,
|
||||
PointsDetail
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAdd: true,
|
||||
|
@ -65,9 +295,36 @@ export default {
|
|||
modalConfig: {
|
||||
title: "用户详情",
|
||||
show: false,
|
||||
width: "60%",
|
||||
width: "80%"
|
||||
},
|
||||
modalData: {},
|
||||
// Tab相关数据
|
||||
activeTab: "growth",
|
||||
couponCount: 0,
|
||||
// 成长值明细
|
||||
growthList: [],
|
||||
growthLoading: false,
|
||||
growthPagination: {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
},
|
||||
// 积分明细
|
||||
pointsList: [],
|
||||
pointsLoading: false,
|
||||
pointsPagination: {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
},
|
||||
// 优惠券
|
||||
couponsList: [],
|
||||
couponsLoading: false,
|
||||
couponsPagination: {
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
|
@ -78,10 +335,17 @@ export default {
|
|||
this.$refs.modal.resetFields();
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
queryTableData(pageNo, pageSize) {},
|
||||
// 手机号脱敏处理
|
||||
maskMobile(mobile) {
|
||||
if (!mobile || mobile.length !== 11) {
|
||||
return mobile;
|
||||
}
|
||||
return mobile.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
|
||||
},
|
||||
queryTableData() {},
|
||||
toggle(e) {
|
||||
if (this.modalConfig.show == false) {
|
||||
this.modalConfig.show = true;
|
||||
|
@ -98,12 +362,222 @@ export default {
|
|||
},
|
||||
update: () => {
|
||||
this.isAdd = false;
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
init(row) {
|
||||
this.modalData = row;
|
||||
this.loadTabData();
|
||||
},
|
||||
// Tab切换处理
|
||||
handleTabClick(tab) {
|
||||
this.activeTab = tab.name;
|
||||
this.loadTabData();
|
||||
},
|
||||
// 加载Tab数据
|
||||
loadTabData() {
|
||||
switch (this.activeTab) {
|
||||
case "growth":
|
||||
this.loadGrowthData();
|
||||
break;
|
||||
case "points":
|
||||
this.loadPointsData();
|
||||
break;
|
||||
case "coupons":
|
||||
this.loadCouponsData();
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 加载成长值明细数据
|
||||
loadGrowthData() {
|
||||
this.growthLoading = true;
|
||||
// 模拟数据,实际应该调用API
|
||||
setTimeout(() => {
|
||||
this.growthList = [
|
||||
{
|
||||
changeTime: "2025-07-24 17:20",
|
||||
growthChange: 35,
|
||||
relatedOrder: "ORD9296",
|
||||
changeReason: "订单消费",
|
||||
orderAmount: "89.99",
|
||||
orderTime: "2025-07-24 17:20",
|
||||
shopName: "美食餐厅"
|
||||
},
|
||||
{
|
||||
changeTime: "2025-07-12 17:20",
|
||||
growthChange: 100,
|
||||
relatedOrder: "-",
|
||||
changeReason: "活动奖励",
|
||||
description: "参与平台活动获得的成长值奖励"
|
||||
},
|
||||
{
|
||||
changeTime: "2024-01-05 16:45:33",
|
||||
growthChange: 30,
|
||||
relatedOrder: "ORDER202401503",
|
||||
changeReason: "订单消费",
|
||||
orderAmount: "65.50",
|
||||
orderTime: "2024-01-05 16:45:33",
|
||||
shopName: "便利超市"
|
||||
}
|
||||
];
|
||||
this.growthPagination.total = 3;
|
||||
this.growthLoading = false;
|
||||
}, 500);
|
||||
},
|
||||
// 加载积分明细数据
|
||||
loadPointsData() {
|
||||
this.pointsLoading = true;
|
||||
// 模拟数据,实际应该调用API
|
||||
setTimeout(() => {
|
||||
this.pointsList = [
|
||||
{
|
||||
changeTime: "2025-07-24 17:20",
|
||||
pointsChange: 25,
|
||||
changeType: "订单消费",
|
||||
relatedOrder: "ORD9296",
|
||||
changeReason: "订单消费",
|
||||
orderAmount: "78.30",
|
||||
orderTime: "2025-07-24 17:20",
|
||||
shopName: "运动健身店"
|
||||
},
|
||||
{
|
||||
changeTime: "2025-07-20 15:30",
|
||||
pointsChange: -50,
|
||||
changeType: "兑换商品",
|
||||
relatedOrder: "-",
|
||||
changeReason: "兑换商品",
|
||||
exchangeProduct: "精美水杯",
|
||||
exchangeQuantity: "1个",
|
||||
usageDescription:
|
||||
"使用50积分兑换商品,兑换成功后积分将被扣除且不可退还。"
|
||||
},
|
||||
{
|
||||
changeTime: "2025-07-12 17:20",
|
||||
pointsChange: 80,
|
||||
changeType: "完成任务",
|
||||
relatedOrder: "-",
|
||||
changeReason: "完成任务",
|
||||
description: "完成平台指定任务获得的积分奖励"
|
||||
},
|
||||
{
|
||||
changeTime: "2024-01-08 15:45:30",
|
||||
pointsChange: 10,
|
||||
changeType: "签到奖励",
|
||||
relatedOrder: "-",
|
||||
changeReason: "签到奖励",
|
||||
description: "每日签到获得的积分奖励"
|
||||
}
|
||||
];
|
||||
this.pointsPagination.total = 4;
|
||||
this.pointsLoading = false;
|
||||
}, 500);
|
||||
},
|
||||
// 加载优惠券数据
|
||||
loadCouponsData() {
|
||||
this.couponsLoading = true;
|
||||
// 模拟数据,实际应该调用API
|
||||
setTimeout(() => {
|
||||
this.couponsList = [
|
||||
{
|
||||
couponName: "新用户专享券",
|
||||
couponType: "满减券",
|
||||
faceValue: 20,
|
||||
useCondition: "满100元可用",
|
||||
receiveTime: "2024-01-01 10:00:00",
|
||||
validPeriod: "2024-02-01",
|
||||
useStatus: "可使用"
|
||||
},
|
||||
{
|
||||
couponName: "生日特惠券",
|
||||
couponType: "折扣券",
|
||||
faceValue: 9,
|
||||
useCondition: "全品类可用",
|
||||
receiveTime: "2024-01-05 12:30:15",
|
||||
validPeriod: "2024-02-05",
|
||||
useStatus: "可使用"
|
||||
},
|
||||
{
|
||||
couponName: "积分兑换券",
|
||||
couponType: "满减券",
|
||||
faceValue: 50,
|
||||
useCondition: "满300元可用",
|
||||
receiveTime: "2024-01-10 16:20:30",
|
||||
validPeriod: "2024-03-10",
|
||||
useStatus: "可使用"
|
||||
},
|
||||
{
|
||||
couponName: "限时抢购券",
|
||||
couponType: "满减券",
|
||||
faceValue: 10,
|
||||
useCondition: "满50元可用",
|
||||
receiveTime: "2023-12-20 14:15:20",
|
||||
validPeriod: "2024-01-20",
|
||||
useStatus: "已过期"
|
||||
},
|
||||
{
|
||||
couponName: "会员专属券",
|
||||
couponType: "满减券",
|
||||
faceValue: 30,
|
||||
useCondition: "满200元可用",
|
||||
receiveTime: "2023-12-15 09:45:10",
|
||||
validPeriod: "2024-01-15",
|
||||
useStatus: "已使用"
|
||||
}
|
||||
];
|
||||
this.couponsPagination.total = 5;
|
||||
this.couponCount = this.couponsList.filter(
|
||||
item => item.useStatus === "可使用"
|
||||
).length;
|
||||
this.couponsLoading = false;
|
||||
}, 500);
|
||||
},
|
||||
// 成长值分页处理
|
||||
handleGrowthSizeChange(val) {
|
||||
this.growthPagination.pageSize = val;
|
||||
this.loadGrowthData();
|
||||
},
|
||||
handleGrowthCurrentChange(val) {
|
||||
this.growthPagination.currentPage = val;
|
||||
this.loadGrowthData();
|
||||
},
|
||||
// 积分分页处理
|
||||
handlePointsSizeChange(val) {
|
||||
this.pointsPagination.pageSize = val;
|
||||
this.loadPointsData();
|
||||
},
|
||||
handlePointsCurrentChange(val) {
|
||||
this.pointsPagination.currentPage = val;
|
||||
this.loadPointsData();
|
||||
},
|
||||
// 优惠券分页处理
|
||||
handleCouponsSizeChange(val) {
|
||||
this.couponsPagination.pageSize = val;
|
||||
this.loadCouponsData();
|
||||
},
|
||||
handleCouponsCurrentChange(val) {
|
||||
this.couponsPagination.currentPage = val;
|
||||
this.loadCouponsData();
|
||||
},
|
||||
// 查看详情方法
|
||||
viewGrowthDetail(row) {
|
||||
this.$refs.growthDetail.show(row);
|
||||
},
|
||||
viewPointsDetail(row) {
|
||||
this.$refs.pointsDetail.show(row);
|
||||
},
|
||||
// 获取状态标签类型
|
||||
getStatusTagType(status) {
|
||||
switch (status) {
|
||||
case "可使用":
|
||||
return "success";
|
||||
case "已使用":
|
||||
return "info";
|
||||
case "已过期":
|
||||
return "danger";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
modalCols() {
|
||||
|
@ -112,30 +586,70 @@ export default {
|
|||
modalHandles() {
|
||||
return [
|
||||
{
|
||||
label: "取消",
|
||||
label: "关闭",
|
||||
handle: () => {
|
||||
this.toggle();
|
||||
},
|
||||
},
|
||||
{
|
||||
label: this.isAdd ? "确认添加" : "确认",
|
||||
type: "primary",
|
||||
loading: this.isLoading,
|
||||
submit: true,
|
||||
handle: () => {
|
||||
console.log(JSON.parse(JSON.stringify(this.modalData)));
|
||||
this.$emit(
|
||||
"addCouponData",
|
||||
JSON.parse(JSON.stringify(this.modalData))
|
||||
);
|
||||
this.toggle();
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
];
|
||||
},
|
||||
}
|
||||
},
|
||||
asyncComputed: {},
|
||||
asyncComputed: {}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
.user-info-header {
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.user-basic-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #303133;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.user-stats {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
text-align: center;
|
||||
padding: 15px 20px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #409eff;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
<template>
|
||||
<div class="test-page">
|
||||
<div class="page-header">
|
||||
<h2>会员详情弹框样式测试页面</h2>
|
||||
<p>点击下面的按钮查看不同会员数据的详情弹框效果</p>
|
||||
</div>
|
||||
|
||||
<div class="test-buttons">
|
||||
<el-button type="primary" @click="showMemberDetail1">
|
||||
查看会员详情 - 张三 (LV2会员)
|
||||
</el-button>
|
||||
<el-button type="success" @click="showMemberDetail2">
|
||||
查看会员详情 - 李四 (LV3会员)
|
||||
</el-button>
|
||||
<el-button type="warning" @click="showMemberDetail3">
|
||||
查看会员详情 - 王五 (LV1会员)
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="feature-list">
|
||||
<h3>功能特点说明:</h3>
|
||||
<ul>
|
||||
<li>✅ 用户信息顶部展示:会员姓名、系统编号、手机号(脱敏)、生日</li>
|
||||
<li>✅ 右侧统计卡片:会员成长值、会员积分、会员优惠券数量</li>
|
||||
<li>✅ 三个Tab分页:会员成长值明细、会员积分明细、会员优惠券</li>
|
||||
<li>✅ 成长值明细:变化时间、成长值变动(带颜色)、关联订单、查看详情</li>
|
||||
<li>✅ 积分明细:变化时间、积分变动(带颜色)、变动类型、关联订单、查看详情</li>
|
||||
<li>✅ 优惠券列表:名称、类型、面额、使用条件、获得时间、有效期、使用状态(Tag)</li>
|
||||
<li>✅ 完整的分页功能</li>
|
||||
<li>✅ 响应式布局和美观的样式</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 会员详情弹框组件 -->
|
||||
<viewDetails ref="viewDetails"></viewDetails>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import viewDetails from "./modules/marketing/user/popup/view-details.vue";
|
||||
|
||||
export default {
|
||||
name: "TestMemberDetail",
|
||||
components: {
|
||||
viewDetails
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
// 测试会员1 - 张三
|
||||
showMemberDetail1() {
|
||||
const testMemberData = {
|
||||
userId: "3",
|
||||
username: "张三",
|
||||
mobile: "13812341234",
|
||||
birthday: "1990-05-15",
|
||||
headUrl: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
|
||||
levelName: "LV2",
|
||||
growthValue: 1250,
|
||||
memberPoints: 890,
|
||||
joinTime: "2023-01-15 10:30:00",
|
||||
registrationTime: "2023-01-15 10:30:00",
|
||||
id: 1
|
||||
};
|
||||
this.$refs.viewDetails.toggle(testMemberData).add();
|
||||
},
|
||||
|
||||
// 测试会员2 - 李四
|
||||
showMemberDetail2() {
|
||||
const testMemberData = {
|
||||
userId: "15",
|
||||
username: "李四",
|
||||
mobile: "15987654321",
|
||||
birthday: "1985-12-20",
|
||||
headUrl: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
|
||||
levelName: "LV3",
|
||||
growthValue: 2800,
|
||||
memberPoints: 1560,
|
||||
joinTime: "2022-08-10 14:20:00",
|
||||
registrationTime: "2022-08-10 14:20:00",
|
||||
id: 2
|
||||
};
|
||||
this.$refs.viewDetails.toggle(testMemberData).add();
|
||||
},
|
||||
|
||||
// 测试会员3 - 王五
|
||||
showMemberDetail3() {
|
||||
const testMemberData = {
|
||||
userId: "28",
|
||||
username: "王五",
|
||||
mobile: "18666888999",
|
||||
birthday: "1995-03-08",
|
||||
headUrl: "https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png",
|
||||
levelName: "LV1",
|
||||
growthValue: 350,
|
||||
memberPoints: 120,
|
||||
joinTime: "2024-01-05 09:15:00",
|
||||
registrationTime: "2024-01-05 09:15:00",
|
||||
id: 3
|
||||
};
|
||||
this.$refs.viewDetails.toggle(testMemberData).add();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.test-page {
|
||||
padding: 20px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
|
||||
h2 {
|
||||
color: #303133;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.test-buttons {
|
||||
text-align: center;
|
||||
margin-bottom: 40px;
|
||||
|
||||
.el-button {
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-list {
|
||||
background: #f5f7fa;
|
||||
padding: 20px;
|
||||
border-radius: 4px;
|
||||
|
||||
h3 {
|
||||
color: #303133;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
|
||||
li {
|
||||
margin-bottom: 8px;
|
||||
color: #606266;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue