mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-06 19:07:25 +08:00
feat(会员管理): 添加第三方账户绑定和会员等级功能
- 在登录API中新增获取第三方账户绑定列表、绑定和解绑功能 - 在会员API中新增获取当前会员等级、等级规则和等级列表的接口 - 在会员中心页面中添加第三方账户绑定的UI和逻辑 - 新增会员等级页面,展示当前等级、经验值和经验值记录
This commit is contained in:
197
manager/src/views/member/grade/experience-log.vue
Normal file
197
manager/src/views/member/grade/experience-log.vue
Normal file
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Card>
|
||||
<Form
|
||||
ref="searchForm"
|
||||
:model="searchForm"
|
||||
inline
|
||||
:label-width="90"
|
||||
@keydown.enter.native="handleSearch"
|
||||
@submit.native.prevent
|
||||
class="search-form"
|
||||
>
|
||||
<FormItem label="客户手机号" prop="mobile">
|
||||
<Input
|
||||
v-model="searchForm.memberMobile"
|
||||
clearable
|
||||
placeholder="请输入客户手机号"
|
||||
style="width: 220px"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="规则" prop="ruleKey">
|
||||
<Select v-model="searchForm.ruleKey" clearable filterable style="width: 220px">
|
||||
<Option v-for="item in ruleOptions" :key="item.value" :value="item.value">
|
||||
{{ item.label }}
|
||||
</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<Button type="primary" icon="ios-search" @click="handleSearch">搜索</Button>
|
||||
</Form>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
class="mt_10"
|
||||
></Table>
|
||||
<Row type="flex" justify="end" class="mt_10">
|
||||
<Page
|
||||
:current="searchForm.pageNumber"
|
||||
:total="total"
|
||||
:page-size="searchForm.pageSize"
|
||||
@on-change="changePage"
|
||||
@on-page-size-change="changePageSize"
|
||||
:page-size-opts="[20, 50, 100]"
|
||||
size="small"
|
||||
show-total
|
||||
show-elevator
|
||||
show-sizer
|
||||
></Page>
|
||||
</Row>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Member from "@/api/member";
|
||||
|
||||
const RULE_OPTIONS = [
|
||||
{ value: "CONSUME", label: "消费" },
|
||||
{ value: "REGISTER", label: "注册" },
|
||||
{ value: "SIGN_IN", label: "签到" },
|
||||
{ value: "COMMENT", label: "评价" },
|
||||
{ value: "SHARE", label: "分享商城" },
|
||||
{ value: "PROFILE", label: "完善信息" },
|
||||
{ value: "FOLLOW_STORE", label: "关注店铺" },
|
||||
{ value: "BIND_WECHAT", label: "绑定微信" },
|
||||
{ value: "ADD_ADDRESS", label: "添加收货地址" },
|
||||
{ value: "SHARE_REGISTER", label: "分享注册" },
|
||||
{ value: "SHARE_BUY", label: "分享购买" },
|
||||
];
|
||||
|
||||
export default {
|
||||
name: "memberGradeExperienceLog",
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
total: 0,
|
||||
data: [],
|
||||
ruleOptions: RULE_OPTIONS,
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
memberMobile: "",
|
||||
ruleKey: "",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
title: "客户手机号",
|
||||
key: "memberMobile",
|
||||
width: 140,
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
const v = params.row.memberMobile || params.row.mobile || "-";
|
||||
return h("span", v);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "规则名称",
|
||||
key: "ruleName",
|
||||
width: 150,
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
const text = params.row.ruleName || this.findRuleName(params.row.ruleKey) || "-";
|
||||
return h("span", text);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "变化经验值",
|
||||
key: "value",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
const v =
|
||||
params.row.value ??
|
||||
params.row.variableExperience ??
|
||||
params.row.experience ??
|
||||
params.row.variableValue;
|
||||
return h("span", v == null ? "-" : v);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "经验值限额",
|
||||
key: "maxValue",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
const v = params.row.maxValue ?? params.row.maxExperience ?? params.row.limitValue;
|
||||
return h("span", v == null ? "-" : v);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作说明",
|
||||
key: "content",
|
||||
minWidth: 200,
|
||||
tooltip: true,
|
||||
render: (h, params) => {
|
||||
const text = params.row.content || params.row.remark || params.row.description || "-";
|
||||
return h("span", text);
|
||||
},
|
||||
},
|
||||
{ title: "创建时间", key: "createTime", width: 170 },
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
findRuleName(ruleKey) {
|
||||
const hit = this.ruleOptions.find((item) => item.value === ruleKey);
|
||||
return hit ? hit.label : "";
|
||||
},
|
||||
init() {
|
||||
this.getData();
|
||||
},
|
||||
buildParams() {
|
||||
const params = {
|
||||
pageNumber: this.searchForm.pageNumber,
|
||||
pageSize: this.searchForm.pageSize,
|
||||
};
|
||||
if (this.searchForm.memberMobile) params.mobile = this.searchForm.memberMobile;
|
||||
if (this.searchForm.ruleKey) params.ruleKey = this.searchForm.ruleKey;
|
||||
return params;
|
||||
},
|
||||
getData() {
|
||||
this.loading = true;
|
||||
API_Member.getMemberExperienceByPage(this.buildParams())
|
||||
.then((res) => {
|
||||
if (res && res.success && res.result) {
|
||||
this.data = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
} else {
|
||||
this.data = [];
|
||||
this.total = 0;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.getData();
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getData();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = v;
|
||||
this.getData();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
556
manager/src/views/member/grade/experience-setting.vue
Normal file
556
manager/src/views/member/grade/experience-setting.vue
Normal file
@@ -0,0 +1,556 @@
|
||||
<template>
|
||||
<div class="experience-setting">
|
||||
<Card>
|
||||
<Form :label-width="120" label-position="right">
|
||||
<Table :loading="loading" :columns="columns" :data="form.items" class="mt_10 experience-table"></Table>
|
||||
<FormItem label="经验值说明" style="margin-top: 16px" class="desc-item">
|
||||
<Input
|
||||
v-model="form.description"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
placeholder="请输入经验值说明"
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Button type="primary" :loading="submitLoading" @click="submit">保存</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSetting, setSetting } from "@/api/index";
|
||||
|
||||
const RULE_OPTIONS = [
|
||||
{ ruleKey: "CONSUME", ruleName: "消费" },
|
||||
{ ruleKey: "REGISTER", ruleName: "注册" },
|
||||
{ ruleKey: "SIGN_IN", ruleName: "签到" },
|
||||
{ ruleKey: "COMMENT", ruleName: "评价" },
|
||||
{ ruleKey: "SHARE", ruleName: "分享商城" },
|
||||
{ ruleKey: "PROFILE", ruleName: "完善信息" },
|
||||
{ ruleKey: "FOLLOW_STORE", ruleName: "关注店铺" },
|
||||
{ ruleKey: "BIND_WECHAT", ruleName: "绑定微信" },
|
||||
{ ruleKey: "ADD_ADDRESS", ruleName: "添加收货地址" },
|
||||
{ ruleKey: "SHARE_REGISTER", ruleName: "分享注册" },
|
||||
{ ruleKey: "SHARE_BUY", ruleName: "分享购买" },
|
||||
];
|
||||
|
||||
const defaultRuleItem = (rule) => ({
|
||||
ruleKey: rule.ruleKey,
|
||||
ruleName: rule.ruleName,
|
||||
enabled: false,
|
||||
value: 1,
|
||||
maxValue: null,
|
||||
});
|
||||
|
||||
const defaultForm = () => ({
|
||||
items: RULE_OPTIONS.map((item) => defaultRuleItem(item)),
|
||||
description: "",
|
||||
});
|
||||
|
||||
export default {
|
||||
name: "memberGradeExperienceSetting",
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
submitLoading: false,
|
||||
form: defaultForm(),
|
||||
columns: [
|
||||
{
|
||||
title: "是否开启",
|
||||
key: "enabled",
|
||||
width: 90,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
return h("Checkbox", {
|
||||
props: { value: !!this.form.items[params.index].enabled },
|
||||
on: {
|
||||
"on-change": (checked) => {
|
||||
this.updateRuleEnabled(params.index, checked);
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "类型",
|
||||
key: "ruleName",
|
||||
width: 160,
|
||||
},
|
||||
{
|
||||
title: "经验值(1-100)",
|
||||
key: "value",
|
||||
minWidth: 700,
|
||||
render: (h, params) => {
|
||||
const row = this.form.items[params.index] || {};
|
||||
const inputNode = h("Input", {
|
||||
style: { width: "120px" },
|
||||
props: {
|
||||
value: row.value == null ? "" : String(row.value),
|
||||
number: true,
|
||||
},
|
||||
on: {
|
||||
input: (val) => {
|
||||
this.updateRuleValue(params.index, val);
|
||||
},
|
||||
"on-change": (v) => {
|
||||
this.updateRuleValue(params.index, v);
|
||||
},
|
||||
"on-blur": () => {
|
||||
this.commitRuleValue(params.index);
|
||||
},
|
||||
},
|
||||
});
|
||||
const maxInputNode = h("Input", {
|
||||
style: { width: "120px" },
|
||||
props: {
|
||||
value: row.maxValue == null ? "" : String(row.maxValue),
|
||||
number: true,
|
||||
},
|
||||
on: {
|
||||
input: (val) => {
|
||||
this.updateRuleMaxValue(params.index, val);
|
||||
},
|
||||
"on-change": (v) => {
|
||||
this.updateRuleMaxValue(params.index, v);
|
||||
},
|
||||
"on-blur": () => {
|
||||
this.commitRuleMaxValue(params.index);
|
||||
},
|
||||
},
|
||||
});
|
||||
if (params.row.ruleKey === "REGISTER") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获得经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"会员注册成功后可获得经验值"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "SHARE") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", marginRight: "16px" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "分享商品详情页获得经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "可获得经验值限额:"), maxInputNode]
|
||||
),
|
||||
]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"会员分享商城页面可获得的经验值"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "COMMENT") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "对已购买商品完成提交评论获得经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"仅针对评论字数大于30字的评论进行发放"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "FOLLOW_STORE") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", marginRight: "16px" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获得经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "可获得经验值限额:"), maxInputNode]
|
||||
),
|
||||
]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"关注店铺可获得经验值,每个客户D相同店铺仅第一次关注可进行获得"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "PROFILE") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获得经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"完善个人基本信息可获得经验值,每个会员仅可获得一次"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "BIND_WECHAT") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获取经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"绑定微信成功获得经验值,每个会员仅可获得一次"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "ADD_ADDRESS") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获取经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"添加收货地址后获得经验值,每个会员仅可获得一次"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "SHARE_REGISTER") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", marginRight: "16px" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获取的经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "可获得经验值限额:"), maxInputNode]
|
||||
),
|
||||
]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"仅被注册成功后才可获得相应奖励经验值"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "SHARE_BUY") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", marginRight: "16px" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获取的经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "可获得经验值限额:"), maxInputNode]
|
||||
),
|
||||
]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"仅被购买成功后才可获得相应奖励经验值"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "SIGN_IN") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "获取的经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"客户每日签到后可获的经验值"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
if (params.row.ruleKey === "CONSUME") {
|
||||
return h(
|
||||
"div",
|
||||
{ style: { display: "flex", flexDirection: "column", alignItems: "flex-start" } },
|
||||
[
|
||||
h(
|
||||
"div",
|
||||
{ style: { display: "flex", alignItems: "center", flexWrap: "wrap" } },
|
||||
[h("span", { style: { marginRight: "8px" } }, "1元获取经验值:"), inputNode]
|
||||
),
|
||||
h(
|
||||
"div",
|
||||
{ style: { marginTop: "6px", color: "#808695", fontSize: "12px" } },
|
||||
"客户消费1元可获取经验值,向下取整"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
return inputNode;
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.loadData();
|
||||
},
|
||||
methods: {
|
||||
getRawInputValue(v) {
|
||||
return v && v.target ? v.target.value : v;
|
||||
},
|
||||
updateRuleEnabled(index, enabled) {
|
||||
const item = this.form.items[index] || {};
|
||||
this.$set(this.form.items, index, {
|
||||
...item,
|
||||
enabled: !!enabled,
|
||||
});
|
||||
},
|
||||
updateRuleValue(index, v) {
|
||||
const raw = this.getRawInputValue(v);
|
||||
const next = Number(raw);
|
||||
const item = this.form.items[index] || {};
|
||||
this.$set(this.form.items, index, {
|
||||
...item,
|
||||
value: Number.isFinite(next) ? next : null,
|
||||
});
|
||||
},
|
||||
commitRuleValue(index) {
|
||||
const item = this.form.items[index] || {};
|
||||
const next = Number(item.value);
|
||||
let value = 1;
|
||||
if (Number.isFinite(next)) {
|
||||
if (next < 1) value = 1;
|
||||
else if (next > 100) value = 100;
|
||||
else value = Math.floor(next);
|
||||
}
|
||||
this.$set(this.form.items, index, {
|
||||
...item,
|
||||
value,
|
||||
});
|
||||
},
|
||||
updateRuleMaxValue(index, v) {
|
||||
const raw = this.getRawInputValue(v);
|
||||
const item = this.form.items[index] || {};
|
||||
if (raw == null || raw === "") {
|
||||
this.$set(this.form.items, index, {
|
||||
...item,
|
||||
maxValue: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const next = Number(raw);
|
||||
this.$set(this.form.items, index, {
|
||||
...item,
|
||||
maxValue: Number.isFinite(next) ? next : null,
|
||||
});
|
||||
},
|
||||
commitRuleMaxValue(index) {
|
||||
const item = this.form.items[index] || {};
|
||||
if (item.maxValue == null || item.maxValue === "") {
|
||||
this.$set(this.form.items, index, {
|
||||
...item,
|
||||
maxValue: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const next = Number(item.maxValue);
|
||||
this.$set(this.form.items, index, {
|
||||
...item,
|
||||
maxValue: Number.isFinite(next) && next >= 1 ? Math.floor(next) : null,
|
||||
});
|
||||
},
|
||||
normalizeConfig(val) {
|
||||
if (!val) return {};
|
||||
if (typeof val === "string") {
|
||||
try {
|
||||
return JSON.parse(val);
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (typeof val === "object") return val;
|
||||
return {};
|
||||
},
|
||||
normalizeItems(items) {
|
||||
const map = {};
|
||||
if (Array.isArray(items)) {
|
||||
items.forEach((item) => {
|
||||
if (!item || !item.ruleKey) return;
|
||||
map[item.ruleKey] = item;
|
||||
});
|
||||
}
|
||||
return RULE_OPTIONS.map((rule) => {
|
||||
const hit = map[rule.ruleKey] || {};
|
||||
return {
|
||||
ruleKey: rule.ruleKey,
|
||||
ruleName: hit.ruleName || rule.ruleName,
|
||||
enabled: !!hit.enabled,
|
||||
value: Number(hit.value) > 0 ? Number(hit.value) : 1,
|
||||
maxValue: hit.maxValue == null || hit.maxValue === "" ? null : Number(hit.maxValue),
|
||||
};
|
||||
});
|
||||
},
|
||||
loadData() {
|
||||
this.loading = true;
|
||||
getSetting("EXPERIENCE_SETTING")
|
||||
.then((res) => {
|
||||
if (res && res.success) {
|
||||
const cfg = this.normalizeConfig(res.result);
|
||||
this.form = {
|
||||
items: this.normalizeItems(cfg.items),
|
||||
description: cfg.description || "",
|
||||
};
|
||||
} else {
|
||||
this.form = defaultForm();
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
validateForm() {
|
||||
const invalid = this.form.items.find((item) => {
|
||||
const v = Number(item.value);
|
||||
if (!Number.isInteger(v) || v < 1 || v > 100) return true;
|
||||
if (item.maxValue != null && item.maxValue !== "") {
|
||||
const m = Number(item.maxValue);
|
||||
if (!Number.isInteger(m) || m < 1) return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (invalid) {
|
||||
this.$Message.error("请检查经验值配置,经验值范围为1-100,限额需为正整数");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
submit() {
|
||||
if (!this.validateForm()) return;
|
||||
const payload = {
|
||||
items: this.form.items.map((item) => ({
|
||||
ruleKey: item.ruleKey,
|
||||
ruleName: item.ruleName,
|
||||
enabled: !!item.enabled,
|
||||
value: Number(item.value),
|
||||
maxValue: item.maxValue == null || item.maxValue === "" ? null : Number(item.maxValue),
|
||||
})),
|
||||
description: this.form.description || "",
|
||||
};
|
||||
this.submitLoading = true;
|
||||
setSetting("EXPERIENCE_SETTING", payload)
|
||||
.then((res) => {
|
||||
if (res && res.success) {
|
||||
this.$Message.success("保存成功");
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.submitLoading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.experience-setting {
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
::v-deep .experience-table .ivu-table th {
|
||||
background: #fafbfc;
|
||||
}
|
||||
|
||||
::v-deep .experience-table .ivu-table td {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
::v-deep .experience-table .ivu-table-cell {
|
||||
font-size: 13px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
::v-deep .desc-item .ivu-form-item-label {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
547
manager/src/views/member/grade/index.vue
Normal file
547
manager/src/views/member/grade/index.vue
Normal file
@@ -0,0 +1,547 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<Card>
|
||||
<Row class="operation padding-row">
|
||||
<Button type="primary" @click="openAdd">添加客户等级</Button>
|
||||
</Row>
|
||||
<Table
|
||||
:loading="loading"
|
||||
border
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
class="mt_10"
|
||||
></Table>
|
||||
</Card>
|
||||
|
||||
<Modal v-model="addFlag" title="添加客户等级" width="720" :z-index="950" :mask-closable="false">
|
||||
<Form ref="addForm" :model="formAdd" :rules="rules" :label-width="110">
|
||||
<FormItem label="等级名称" prop="gradeName">
|
||||
<Input v-model="formAdd.gradeName" maxlength="50" placeholder="请输入等级名称" />
|
||||
</FormItem>
|
||||
<FormItem label="是否默认" prop="isDefault">
|
||||
<RadioGroup v-model="formAdd.isDefault">
|
||||
<Radio :label="true">是</Radio>
|
||||
<Radio :label="false">否</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="等级图标" prop="gradeImage">
|
||||
<upload-pic-input v-model="formAdd.gradeImage"></upload-pic-input>
|
||||
</FormItem>
|
||||
<FormItem label="等级背景图" prop="gradeBackground">
|
||||
<upload-pic-input v-model="formAdd.gradeBackground"></upload-pic-input>
|
||||
</FormItem>
|
||||
<FormItem label="字体颜色" prop="gradeFontColor">
|
||||
<Input v-model="formAdd.gradeFontColor" maxlength="20" placeholder="如:#333333" />
|
||||
</FormItem>
|
||||
<FormItem label="所需经验值" prop="requiredExperience">
|
||||
<InputNumber v-model="formAdd.requiredExperience" :min="1" :precision="0" style="width: 220px"></InputNumber>
|
||||
</FormItem>
|
||||
<FormItem label="等级排序" prop="gradeSort">
|
||||
<InputNumber v-model="formAdd.gradeSort" :min="1" :max="9999" :precision="0" style="width: 220px"></InputNumber>
|
||||
</FormItem>
|
||||
<FormItem label="等级开关" prop="gradeState">
|
||||
<RadioGroup v-model="formAdd.gradeState">
|
||||
<Radio label="OPEN">开启</Radio>
|
||||
<Radio label="CLOSE">关闭</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="关联权益" prop="benefitIds">
|
||||
<Select
|
||||
:value="addBenefitOrder"
|
||||
multiple
|
||||
filterable
|
||||
placeholder="请选择客户权益"
|
||||
style="width: 100%"
|
||||
@on-change="onAddBenefitIdsChange"
|
||||
>
|
||||
<Option v-for="b in benefitOptions" :key="b.id" :value="String(b.id)">{{ benefitOptionLabel(b) }}</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button @click="addFlag = false">取消</Button>
|
||||
<Button type="primary" :loading="submitAddLoading" @click="submitAdd">确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal v-model="editFlag" title="编辑客户等级" width="720" :z-index="950" :mask-closable="false">
|
||||
<Form ref="editForm" :model="formEdit" :rules="rules" :label-width="110">
|
||||
<Input v-model="formEdit.id" v-show="false" />
|
||||
<FormItem label="等级名称" prop="gradeName">
|
||||
<Input v-model="formEdit.gradeName" maxlength="50" placeholder="请输入等级名称" />
|
||||
</FormItem>
|
||||
<FormItem label="是否默认" prop="isDefault">
|
||||
<RadioGroup v-model="formEdit.isDefault">
|
||||
<Radio :label="true">是</Radio>
|
||||
<Radio :label="false">否</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="等级图标" prop="gradeImage">
|
||||
<upload-pic-input v-model="formEdit.gradeImage"></upload-pic-input>
|
||||
</FormItem>
|
||||
<FormItem label="等级背景图" prop="gradeBackground">
|
||||
<upload-pic-input v-model="formEdit.gradeBackground"></upload-pic-input>
|
||||
</FormItem>
|
||||
<FormItem label="字体颜色" prop="gradeFontColor">
|
||||
<Input v-model="formEdit.gradeFontColor" maxlength="20" placeholder="如:#333333" />
|
||||
</FormItem>
|
||||
<FormItem label="所需经验值" prop="requiredExperience">
|
||||
<InputNumber v-model="formEdit.requiredExperience" :min="1" :precision="0" style="width: 220px"></InputNumber>
|
||||
</FormItem>
|
||||
<FormItem label="等级排序" prop="gradeSort">
|
||||
<InputNumber v-model="formEdit.gradeSort" :min="1" :max="9999" :precision="0" style="width: 220px"></InputNumber>
|
||||
</FormItem>
|
||||
<FormItem label="等级开关" prop="gradeState">
|
||||
<RadioGroup v-model="formEdit.gradeState">
|
||||
<Radio label="OPEN">开启</Radio>
|
||||
<Radio label="CLOSE">关闭</Radio>
|
||||
</RadioGroup>
|
||||
</FormItem>
|
||||
<FormItem label="关联权益" prop="benefitIds">
|
||||
<Select
|
||||
:value="editBenefitOrder"
|
||||
multiple
|
||||
filterable
|
||||
placeholder="请选择客户权益"
|
||||
style="width: 100%"
|
||||
@on-change="onEditBenefitIdsChange"
|
||||
>
|
||||
<Option v-for="b in benefitOptions" :key="b.id" :value="String(b.id)">{{ benefitOptionLabel(b) }}</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
<Button @click="editFlag = false">取消</Button>
|
||||
<Button type="primary" :loading="submitEditLoading" @click="submitEdit">确定</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Member from "@/api/member.js";
|
||||
import uploadPicInput from "@/components/lili/upload-pic-input";
|
||||
|
||||
const buildDefaultForm = () => ({
|
||||
id: "",
|
||||
gradeName: "",
|
||||
isDefault: false,
|
||||
gradeImage: "",
|
||||
gradeBackground: "",
|
||||
gradeFontColor: "",
|
||||
requiredExperience: 1,
|
||||
gradeSort: 1,
|
||||
gradeState: "OPEN",
|
||||
benefitIds: "",
|
||||
});
|
||||
|
||||
/** 权益多选:新勾选追加到末尾,取消勾选移除,保持已有顺序 */
|
||||
function syncOrderedBenefitIds(prevOrder, selected) {
|
||||
const sel = Array.isArray(selected) ? selected.map((id) => String(id)) : [];
|
||||
const out = [];
|
||||
(prevOrder || []).forEach((id) => {
|
||||
const s = String(id);
|
||||
if (sel.includes(s)) out.push(s);
|
||||
});
|
||||
sel.forEach((s) => {
|
||||
if (!out.includes(s)) out.push(s);
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "memberGrade",
|
||||
components: {
|
||||
uploadPicInput,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
columns: [
|
||||
{
|
||||
title: "等级名称",
|
||||
key: "gradeName",
|
||||
width: 130,
|
||||
tooltip: true,
|
||||
},
|
||||
{
|
||||
title: "默认等级",
|
||||
key: "isDefault",
|
||||
width: 95,
|
||||
render: (h, params) => {
|
||||
const yes = params.row.isDefault === true;
|
||||
return h(
|
||||
"Tag",
|
||||
{
|
||||
props: {
|
||||
color: yes ? "success" : "default",
|
||||
},
|
||||
},
|
||||
yes ? "是" : "否"
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "等级图标",
|
||||
key: "gradeImage",
|
||||
width: 100,
|
||||
render: (h, params) => {
|
||||
if (!params.row.gradeImage) return h("span", "-");
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: params.row.gradeImage,
|
||||
alt: "等级图标",
|
||||
},
|
||||
style: {
|
||||
width: "48px",
|
||||
height: "48px",
|
||||
objectFit: "contain",
|
||||
border: "1px solid #dcdee2",
|
||||
borderRadius: "4px",
|
||||
background: "#fff",
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "等级背景图",
|
||||
key: "gradeBackground",
|
||||
width: 120,
|
||||
render: (h, params) => {
|
||||
if (!params.row.gradeBackground) return h("span", "-");
|
||||
return h("img", {
|
||||
attrs: {
|
||||
src: params.row.gradeBackground,
|
||||
alt: "等级背景图",
|
||||
},
|
||||
style: {
|
||||
width: "64px",
|
||||
height: "40px",
|
||||
objectFit: "cover",
|
||||
border: "1px solid #dcdee2",
|
||||
borderRadius: "4px",
|
||||
background: "#fff",
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "所需经验值",
|
||||
key: "requiredExperience",
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
title: "等级排序",
|
||||
key: "gradeSort",
|
||||
width: 95,
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "gradeState",
|
||||
width: 118,
|
||||
align: "center",
|
||||
render: (h, params) => {
|
||||
const row = params.row;
|
||||
return h("i-switch", {
|
||||
props: {
|
||||
value: row.gradeState === "OPEN",
|
||||
size: "large",
|
||||
loading: !!row._gradeStateLoading,
|
||||
},
|
||||
on: {
|
||||
"on-change": (checked) => {
|
||||
this.onGradeStateSwitch(row, checked);
|
||||
},
|
||||
},
|
||||
}, [
|
||||
h("span", { slot: "open" }, "开启"),
|
||||
h("span", { slot: "close" }, "关闭"),
|
||||
]);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
key: "action",
|
||||
align: "center",
|
||||
width: 130,
|
||||
render: (h, params) => {
|
||||
const linkStyle = {
|
||||
color: "#2d8cf0",
|
||||
cursor: "pointer",
|
||||
textDecoration: "none",
|
||||
};
|
||||
const sep = h(
|
||||
"span",
|
||||
{ style: { margin: "0 8px", color: "#dcdee2" } },
|
||||
"|"
|
||||
);
|
||||
return h(
|
||||
"div",
|
||||
{ class: "ops", style: { display: "flex", justifyContent: "center" } },
|
||||
[
|
||||
h(
|
||||
"a",
|
||||
{ style: linkStyle, on: { click: () => this.openEdit(params.row) } },
|
||||
"编辑"
|
||||
),
|
||||
sep,
|
||||
h(
|
||||
"a",
|
||||
{ style: linkStyle, on: { click: () => this.remove(params.row) } },
|
||||
"删除"
|
||||
),
|
||||
]
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
data: [],
|
||||
addFlag: false,
|
||||
editFlag: false,
|
||||
submitAddLoading: false,
|
||||
submitEditLoading: false,
|
||||
formAdd: buildDefaultForm(),
|
||||
formEdit: buildDefaultForm(),
|
||||
/** 关联权益 id 顺序(与 benefitIds 一致) */
|
||||
addBenefitOrder: [],
|
||||
editBenefitOrder: [],
|
||||
benefitOptions: [],
|
||||
benefitTypeOptions: [],
|
||||
benefitOptionsLoading: false,
|
||||
editDetailLoading: false,
|
||||
rules: {
|
||||
gradeName: [{ required: true, message: "请输入等级名称", trigger: "blur" }],
|
||||
gradeImage: [{ required: true, message: "请上传等级图标", trigger: "change" }],
|
||||
requiredExperience: [{ required: true, type: "number", message: "请输入所需经验值", trigger: "change" }],
|
||||
gradeSort: [{ required: true, type: "number", message: "请输入等级排序", trigger: "change" }],
|
||||
gradeState: [{ required: true, message: "请选择等级开关", trigger: "change" }],
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
benefitOptionLabel(b) {
|
||||
if (!b) return "";
|
||||
const name = b.benefitName || String(b.id);
|
||||
const opt = this.benefitTypeOptions.find((o) => o.value === b.benefitType);
|
||||
const typeText = opt ? opt.description : b.benefitType || "";
|
||||
return typeText ? `${name}(${typeText})` : name;
|
||||
},
|
||||
onAddBenefitIdsChange(val) {
|
||||
this.addBenefitOrder = syncOrderedBenefitIds(this.addBenefitOrder, val);
|
||||
},
|
||||
onEditBenefitIdsChange(val) {
|
||||
this.editBenefitOrder = syncOrderedBenefitIds(this.editBenefitOrder, val);
|
||||
},
|
||||
loadBenefitTypes() {
|
||||
API_Member.getMemberBenefitTypes().then((res) => {
|
||||
if (res && res.success && Array.isArray(res.result)) {
|
||||
this.benefitTypeOptions = res.result;
|
||||
} else {
|
||||
this.benefitTypeOptions = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
loadBenefitOptions() {
|
||||
this.benefitOptionsLoading = true;
|
||||
const pageSize = 500;
|
||||
const fetchPage = (pageNumber) =>
|
||||
API_Member.getMemberBenefitByPage({ pageNumber, pageSize, sort: "benefitSort", order: "asc" });
|
||||
return fetchPage(1)
|
||||
.then((res) => {
|
||||
if (!(res && res.success && res.result)) {
|
||||
this.benefitOptions = [];
|
||||
return;
|
||||
}
|
||||
const records = Array.isArray(res.result.records) ? res.result.records : [];
|
||||
const total = Number(res.result.total) || records.length;
|
||||
let all = records.slice();
|
||||
if (total > pageSize) {
|
||||
const pages = Math.ceil(total / pageSize);
|
||||
const rest = [];
|
||||
for (let p = 2; p <= pages; p++) {
|
||||
rest.push(fetchPage(p));
|
||||
}
|
||||
return Promise.all(rest).then((results) => {
|
||||
results.forEach((r) => {
|
||||
if (r && r.success && r.result && Array.isArray(r.result.records)) {
|
||||
all = all.concat(r.result.records);
|
||||
}
|
||||
});
|
||||
this.benefitOptions = all;
|
||||
});
|
||||
}
|
||||
this.benefitOptions = all;
|
||||
})
|
||||
.catch(() => {
|
||||
this.benefitOptions = [];
|
||||
})
|
||||
.finally(() => {
|
||||
this.benefitOptionsLoading = false;
|
||||
});
|
||||
},
|
||||
parseBenefitIdsFromString(str) {
|
||||
return String(str || "")
|
||||
.split(",")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
},
|
||||
fillEditFormFromGrade(grade, benefitsOrderedIds) {
|
||||
this.formEdit = {
|
||||
id: grade.id || "",
|
||||
gradeName: grade.gradeName || "",
|
||||
isDefault: grade.isDefault === true,
|
||||
gradeImage: grade.gradeImage || "",
|
||||
gradeBackground: grade.gradeBackground || "",
|
||||
gradeFontColor: grade.gradeFontColor || "",
|
||||
requiredExperience: Number(grade.requiredExperience) > 0 ? Number(grade.requiredExperience) : 1,
|
||||
gradeSort: Number(grade.gradeSort) > 0 ? Number(grade.gradeSort) : 1,
|
||||
gradeState: grade.gradeState || "OPEN",
|
||||
benefitIds: grade.benefitIds || "",
|
||||
};
|
||||
this.editBenefitOrder = (benefitsOrderedIds || []).map((id) => String(id));
|
||||
},
|
||||
init() {
|
||||
this.getData();
|
||||
this.loadBenefitTypes();
|
||||
this.loadBenefitOptions();
|
||||
},
|
||||
getData() {
|
||||
this.loading = true;
|
||||
API_Member.getMemberGradeByPage().then((res) => {
|
||||
this.loading = false;
|
||||
if (res && res.success) {
|
||||
this.data = Array.isArray(res.result) ? res.result : [];
|
||||
}
|
||||
});
|
||||
},
|
||||
openAdd() {
|
||||
this.addFlag = true;
|
||||
this.submitAddLoading = false;
|
||||
if (!this.benefitOptions.length && !this.benefitOptionsLoading) {
|
||||
this.loadBenefitOptions();
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.addForm) this.$refs.addForm.resetFields();
|
||||
this.formAdd = buildDefaultForm();
|
||||
this.addBenefitOrder = [];
|
||||
});
|
||||
},
|
||||
submitAdd() {
|
||||
this.$refs.addForm.validate((valid) => {
|
||||
if (!valid) return;
|
||||
this.submitAddLoading = true;
|
||||
const { benefitIds: _omit, ...rest } = this.formAdd;
|
||||
const payload = {
|
||||
...rest,
|
||||
benefitIds: (this.addBenefitOrder || []).join(","),
|
||||
};
|
||||
API_Member.addMemberGrade(payload).then((res) => {
|
||||
this.submitAddLoading = false;
|
||||
if (res && res.success) {
|
||||
this.$Message.success("添加成功");
|
||||
this.addFlag = false;
|
||||
this.getData();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
openEdit(row) {
|
||||
this.editFlag = true;
|
||||
this.submitEditLoading = false;
|
||||
this.editDetailLoading = true;
|
||||
if (!this.benefitOptions.length && !this.benefitOptionsLoading) {
|
||||
this.loadBenefitOptions();
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.editForm) this.$refs.editForm.resetFields();
|
||||
});
|
||||
API_Member.getMemberGrade(row.id)
|
||||
.then((res) => {
|
||||
this.editDetailLoading = false;
|
||||
if (res && res.success && res.result) {
|
||||
const raw = res.result;
|
||||
const grade = raw.grade != null ? raw.grade : raw;
|
||||
const benefits = Array.isArray(raw.benefits) ? raw.benefits : [];
|
||||
const orderedIds = benefits.length
|
||||
? benefits.map((b) => b.id).filter((id) => id != null && id !== "")
|
||||
: String(grade.benefitIds || "")
|
||||
.split(",")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
this.fillEditFormFromGrade(grade, orderedIds);
|
||||
} else {
|
||||
this.fillEditFormFromGrade(row, this.parseBenefitIdsFromString(row.benefitIds));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.editDetailLoading = false;
|
||||
this.fillEditFormFromGrade(row, this.parseBenefitIdsFromString(row.benefitIds));
|
||||
});
|
||||
},
|
||||
submitEdit() {
|
||||
this.$refs.editForm.validate((valid) => {
|
||||
if (!valid) return;
|
||||
this.submitEditLoading = true;
|
||||
const { id, benefitIds: _omit, ...rest } = this.formEdit;
|
||||
const payload = {
|
||||
...rest,
|
||||
benefitIds: (this.editBenefitOrder || []).join(","),
|
||||
};
|
||||
API_Member.updateMemberGrade(id, payload).then((res) => {
|
||||
this.submitEditLoading = false;
|
||||
if (res && res.success) {
|
||||
this.$Message.success("修改成功");
|
||||
this.editFlag = false;
|
||||
this.getData();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
onGradeStateSwitch(row, checked) {
|
||||
const nextState = checked ? "OPEN" : "CLOSE";
|
||||
const prevState = row.gradeState;
|
||||
if (nextState === prevState) return;
|
||||
const text = checked ? "开启" : "关闭";
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
content: `<p>确定${text}该客户等级?</p>`,
|
||||
onOk: () => {
|
||||
this.$set(row, "_gradeStateLoading", true);
|
||||
return API_Member.updateMemberGradeState(row.id, nextState)
|
||||
.then((res) => {
|
||||
this.$set(row, "_gradeStateLoading", false);
|
||||
if (res && res.success) {
|
||||
this.$Message.success(`${text}成功`);
|
||||
this.$set(row, "gradeState", nextState);
|
||||
} else {
|
||||
this.getData();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$set(row, "_gradeStateLoading", false);
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
remove(row) {
|
||||
this.$Modal.confirm({
|
||||
title: "提示",
|
||||
content: "<p>确定删除该客户等级?</p>",
|
||||
onOk: () => {
|
||||
API_Member.deleteMemberGrade(row.id).then((res) => {
|
||||
if (res && res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.getData();
|
||||
} else if (res && res.message) {
|
||||
this.$Message.error(res.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user