manager 升级到vue3

This commit is contained in:
pikachu1995@126.com
2026-05-25 10:49:09 +08:00
parent e7350899bf
commit 615ee91511
239 changed files with 22907 additions and 30841 deletions

View File

@@ -1,208 +1,163 @@
<template>
<div class="search">
<Card>
<Form
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<Form-item label="会员名称" prop="memberName">
<Input
type="text"
<el-form-item label="会员名称" prop="memberName">
<el-input
v-model="searchForm.memberName"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="充值单号" prop="rechargeSn">
<Input
type="text"
</el-form-item>
<el-form-item label="充值单号" prop="rechargeSn">
<el-input
v-model="searchForm.rechargeSn"
placeholder="请输入充值单号"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="支付时间">
<DatePicker
</el-form-item>
<el-form-item label="支付时间">
<el-date-picker
v-model="selectDate"
type="datetimerange"
format="yyyy-MM-dd HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
clearable
@on-change="selectDateRange"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择起始时间"
style="width: 240px"
></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
</Form>
</Card>
<Card>
<Table
:loading="loading"
style="width: 360px"
@change="selectDateRange"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card>
<el-table
v-loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
style="width: 100%"
>
<el-table-column prop="memberName" label="会员名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="rechargeSn" label="订单号" min-width="180" show-overflow-tooltip />
<el-table-column label="充值金额" width="160" sortable>
<template #default="{ row }">
<priceColorScheme v-if="row" :value="row.rechargeMoney" :color="$mainColor" unit="+" />
</template>
</el-table-column>
<el-table-column label="充值方式" width="120">
<template #default="{ row }">
<span v-if="row">{{ rechargeWayText(row.rechargeWay) }}</span>
</template>
</el-table-column>
<el-table-column label="支付状态" width="120">
<template #default="{ row }">
<el-tag v-if="row" :type="row.payStatus === 'PAID' ? 'success' : 'danger'">
{{ row.payStatus === "PAID" ? "已付款" : "未付款" }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="充值时间" width="190" />
<el-table-column prop="payTime" label="支付时间" width="190" />
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
</div>
</template>
<script>
import {
getUserRecharge,
} from "@/api/member";
export default {
name: "recharge",
data() {
return {
loading: true, // 表单加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startDate: "", // 起始时间
endDate: "", // 终止时间
memberName:""
},
selectDate: null, // 选择区间时间
columns: [
{
title: "会员名称",
key: "memberName",
minWidth: 120,
tooltip: true
},
{
title: "订单号",
key: "rechargeSn",
minWidth: 180,
tooltip: true
},
{
title: "充值金额",
key: "rechargeMoney",
width: 160,
sortable: true,
render: (h, params) => {
return h("priceColorScheme", {props:{value:params.row.rechargeMoney,color:this.$mainColor,unit:"+"}} );
},
},
{
title: "充值方式",
key: "rechargeWay",
width: 120,
render: (h, params) => {
if (params.row.rechargeWay === 'ALIPAY') {
return h('div', [h('span', {}, '支付宝')]);
} else if (params.row.rechargeWay === 'WECHAT') {
return h('div', [h('span', {}, '微信')]);
} else if (params.row.rechargeWay === 'BANK_TRANSFER') {
return h('div', [h('span', {}, '线下转账')]);
} else {
return h('div', [h('span', {}, '')]);
}
}
},
{
title: "支付状态",
key: "payStatus",
align: "left",
width: 120,
sortable: false,
render: (h, params) => {
if (params.row.payStatus == "PAID") {
return h("Tag", {props: {color: "green",},}, "已付款");
} else {
return h("Tag", {props: {color: "red",},}, "未付款");
}
},
},
{
title: "充值时间",
key: "createTime",
align: "left",
width: 190,
sortable: false,
},
{
title: "支付时间",
key: "payTime",
align: "left",
width: 190,
sortable: false,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
};
import { getUserRecharge } from "@/api/member";
export default {
name: "recharge",
data() {
return {
loading: true,
searchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
memberName: "",
},
selectDate: null,
data: [],
total: 0,
};
},
methods: {
rechargeWayText(way) {
if (way === "ALIPAY") return "支付宝";
if (way === "WECHAT") return "微信";
if (way === "BANK_TRANSFER") return "线下转账";
return "";
},
init() {
this.getDataList();
},
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
methods: {
// 初始化数据
init() {
this.getDataList();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 时间段赋值
selectDateRange(v) {
if (v) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
}
},
// 获取列表数据
getDataList() {
this.loading = true;
getUserRecharge(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
this.total = this.data.length;
selectDateRange(v) {
if (v && v.length === 2) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
} else {
this.searchForm.startDate = "";
this.searchForm.endDate = "";
}
},
getDataList() {
this.loading = true;
getUserRecharge(this.searchForm).then((res) => {
this.loading = false;
},
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
mounted() {
this.init();
},
};
},
mounted() {
this.init();
},
};
</script>

View File

@@ -1,132 +1,148 @@
<template>
<div class="search">
<Card>
<Row @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="会员名称" prop="memberName">
<Input type="text" v-model="searchForm.memberName" placeholder="请输入会员名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="支付时间">
<DatePicker v-model="selectDate" type="datetimerange" format="yyyy-MM-dd HH:mm:ss" clearable @on-change="selectDateRange" placeholder="选择起始时间" style="width: 240px"></DatePicker>
</Form-item>
<Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">搜索</Button>
</Form>
</Row>
</Card>
<Card>
<Table class="mt_10" :loading="loading" border :columns="columns" :data="data" ref="table"></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>
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<el-form-item label="会员名称" prop="memberName">
<el-input
v-model="searchForm.memberName"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item label="支付时间">
<el-date-picker
v-model="selectDate"
type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss"
clearable
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择起始时间"
style="width: 360px"
@change="selectDateRange"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card>
<el-table
v-loading="loading"
border
:data="data"
ref="table"
class="mt_10"
style="width: 100%"
>
<el-table-column prop="memberName" label="会员名称" min-width="100" />
<el-table-column label="变动金额" width="150">
<template #default="{ row }">
<template v-if="row">
<priceColorScheme
v-if="row.money > 0"
:value="row.money"
color="green"
/>
<priceColorScheme
v-else-if="row.money < 0"
:value="row.money"
:color="$mainColor"
/>
</template>
</template>
</el-table-column>
<el-table-column prop="createTime" label="变更时间" width="200" />
<el-table-column label="业务类型" width="200">
<template #default="{ row }">
<span v-if="row">{{ serviceTypeText(row.serviceType) }}</span>
</template>
</el-table-column>
<el-table-column prop="detail" label="详细" min-width="300" show-overflow-tooltip />
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
size="small"
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
</div>
</template>
<script>
import { getUserWallet } from "@/api/member";
export default {
name: "walletLog",
data() {
return {
loading: true, // 表单加载状态
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startDate: "", // 起始时间
endDate: "", // 终止时间
memberName: "",
},
selectDate: null, // 选择时间段
columns: [
// 表头
{
title: "会员名称",
key: "memberName",
minWidth: 100,
},
{
title: "变动金额",
key: "money",
width: 150,
render: (h, params) => {
if (params.row.money >0) {
return h("priceColorScheme", {props:{value:params.row.money,color:'green'}} );
} else if (params.row.money < 0) {
return h("priceColorScheme", {props:{value:params.row.money,color:this.$mainColor}} );
}
},
},
{
title: "变更时间",
key: "createTime",
width: 200,
},
{
title: "业务类型",
key: "serviceType",
width: 200,
render: (h, params) => {
if (params.row.serviceType == "WALLET_WITHDRAWAL") {
return h("div", [h("span", {}, "余额提现")]);
} else if (params.row.serviceType == "WALLET_PAY") {
return h("div", [h("span", {}, "余额支付")]);
} else if (params.row.serviceType == "WALLET_REFUND") {
return h("div", [h("span", {}, "余额退款")]);
} else if (params.row.serviceType == "WALLET_RECHARGE") {
return h("div", [h("span", {}, "余额充值")]);
} else {
return h("div", [h("span", {}, "佣金提成")]);
}
},
},
{
title: "详细",
key: "detail",
minWidth: 300,
tooltip: true,
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
loading: true,
searchForm: {
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
memberName: "",
},
selectDate: null,
data: [],
total: 0,
};
},
methods: {
// 初始化数据
serviceTypeText(type) {
if (type === "WALLET_WITHDRAWAL") return "余额提现";
if (type === "WALLET_PAY") return "余额支付";
if (type === "WALLET_REFUND") return "余额退款";
if (type === "WALLET_RECHARGE") return "余额充值";
return "佣金提成";
},
init() {
this.getDataList();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getDataList();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getDataList();
},
// 时间段赋值
selectDateRange(v) {
if (v) {
if (v && v.length === 2) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
} else {
this.searchForm.startDate = "";
this.searchForm.endDate = "";
}
},
// 获取列表数据
getDataList() {
this.loading = true;
getUserWallet(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
@@ -134,8 +150,6 @@ export default {
this.total = res.result.total;
}
});
this.total = this.data.length;
this.loading = false;
},
},
mounted() {

View File

@@ -1,102 +1,171 @@
<template>
<div class="search">
<Card>
<Row @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<Form-item label="会员名称" prop="memberName">
<Input type="text" v-model="searchForm.memberName" placeholder="请输入会员名称" clearable style="width: 240px" />
</Form-item>
<Form-item label="提现状态" prop="applyStatus">
<Select v-model="searchForm.applyStatus" clearable style="width: 240px">
<Option value="APPLY">申请中</Option>
<Option value="VIA_AUDITING">审核通过</Option>
<Option value="WAIT_USER_CONFIRM">用户确认</Option>
<Option value="FAIL_AUDITING">审核拒绝</Option>
<Option value="SUCCESS">提现成功</Option>
<Option value="ERROR">提现失败</Option>
</Select>
</Form-item>
<Form-item label="申请时间">
<DatePicker v-model="selectDate" type="datetimerange" format="yyyy-MM-dd HH:mm:ss" clearable @on-change="selectDateRange" placeholder="选择起始时间" style="width: 240px"></DatePicker>
</Form-item>
<Form-item style="margin-left: -35px" class="br">
<Button @click="handleSearch" type="primary" icon="ios-search">搜索
</Button>
</Form-item>
</Form>
</Row>
</Card>
<Card>
<Table class="mt_10" :loading="loading" border :columns="columns" :data="data" ref="table" sortable="custom" @on-sort-change="changeSort" @on-selection-change="changeSelect"></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>
<Modal :title="modalTitle" v-model="roleModalVisible" :mask-closable="false" :width="500">
<Form :label-width="80">
<FormItem label="申请编号">
<span>{{showList.sn}}</span>
</FormItem>
<FormItem label="用户名称">
<span>{{showList.memberName}}</span>
</FormItem>
<FormItem label="申请金额">
<priceColorScheme :value="showList.applyMoney" :color="$mainColor"></priceColorScheme>
</FormItem>
<FormItem label="提现状态">
<span>{{showList.applyStatus | paramTypeFilter}}</span>
</FormItem>
<FormItem label="申请时间">
<span>{{showList.createTime}}</span>
</FormItem>
<FormItem label="审核备注">
<Input v-model="audit" type="textarea" />
</FormItem>
</Form>
<div slot="footer" v-if="showList.applyStatus == 'APPLY'">
<Button type="text" @click="submitRole(false)">拒绝</Button>
<Button type="primary" :loading="submitLoading" @click="submitRole(true)">通过
</Button>
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<el-form-item label="会员名称" prop="memberName">
<el-input
v-model="searchForm.memberName"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item label="提现状态" prop="applyStatus">
<el-select v-model="searchForm.applyStatus" clearable style="width: 240px">
<el-option label="申请中" value="APPLY" />
<el-option label="审核通过" value="VIA_AUDITING" />
<el-option label="用户确认" value="WAIT_USER_CONFIRM" />
<el-option label="审核拒绝" value="FAIL_AUDITING" />
<el-option label="提现成功" value="SUCCESS" />
<el-option label="提现失败" value="ERROR" />
</el-select>
</el-form-item>
<el-form-item label="申请时间">
<el-date-picker
v-model="selectDate"
type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss"
clearable
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择起始时间"
style="width: 360px"
@change="selectDateRange"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card>
<el-table
v-loading="loading"
border
:data="data"
ref="table"
class="mt_10"
style="width: 100%"
@sort-change="changeSort"
@selection-change="changeSelect"
>
<el-table-column prop="sn" label="申请编号" min-width="160" show-overflow-tooltip />
<el-table-column prop="memberName" label="用户名称" min-width="120" show-overflow-tooltip />
<el-table-column label="申请金额" width="120">
<template #default="{ row }">
<priceColorScheme v-if="row" :value="row.applyMoney" :color="$mainColor" />
</template>
</el-table-column>
<el-table-column label="提现状态" width="120">
<template #default="{ row }">
<el-tag v-if="row" :type="applyStatusTagType(row.applyStatus)">
{{ applyStatusText(row.applyStatus) }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="申请时间" width="170" sortable="custom" />
<el-table-column prop="inspectTime" label="审核时间" width="170" />
<el-table-column label="操作" width="120" align="center" fixed="right">
<template #default="{ row }">
<div v-if="row" class="ops">
<a class="link-text" v-if="row.applyStatus === 'APPLY'" @click="openAudit(row)">审核</a>
<a class="link-text" v-else @click="openQuery(row)">查看</a>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
size="small"
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</Modal>
</el-card>
<Modal :title="modalTitle" v-model="queryModalVisible" :mask-closable="false" :width="500">
<Form :label-width="80">
<FormItem label="申请编号:">
<span>{{showList.sn}}</span>
</FormItem>
<FormItem label="用户名称:">
<span>{{showList.memberName}}</span>
</FormItem>
<FormItem label="申请金额:">
<priceColorScheme :value="showList.applyMoney" :color="$mainColor"></priceColorScheme>
<el-dialog
v-model="roleModalVisible"
:title="modalTitle"
width="500px"
:close-on-click-modal="false"
>
<el-form label-width="80px">
<el-form-item label="申请编号">
<span>{{ showList.sn }}</span>
</el-form-item>
<el-form-item label="用户名称">
<span>{{ showList.memberName }}</span>
</el-form-item>
<el-form-item label="申请金额">
<priceColorScheme :value="showList.applyMoney" :color="$mainColor" />
</el-form-item>
<el-form-item label="提现状态">
<span>{{ paramTypeFilter(showList.applyStatus) }}</span>
</el-form-item>
<el-form-item label="申请时间">
<span>{{ showList.createTime }}</span>
</el-form-item>
<el-form-item label="审核备注">
<el-input v-model="audit" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<template v-if="showList.applyStatus === 'APPLY'">
<el-button @click="submitRole(false)">拒绝</el-button>
<el-button type="primary" :loading="submitLoading" @click="submitRole(true)">通过</el-button>
</template>
</template>
</el-dialog>
</FormItem>
<FormItem label="提现状态:">
<span>{{showList.applyStatus | paramTypeFilter}}</span>
</FormItem>
<FormItem label="申请时间:">
<span>{{showList.createTime}}</span>
</FormItem>
<FormItem label="审核时间">
<span>{{showList.inspectTime}}</span>
</FormItem>
<FormItem label="审核备注">
<span>{{showList.inspectRemark || '暂无备注'}}</span>
</FormItem>
</Form>
<div slot="footer" v-if="showList.applyStatus == 'APPLY'">
<Button type="text" @click="submitRole(false)">拒绝</Button>
<Button type="primary" :loading="submitLoading" @click="submitRole(true)">通过
</Button>
</div>
<div slot="footer" v-else>
<Button type="text" @click="queryModalVisible = false">取消</Button>
</div>
</Modal>
<el-dialog
v-model="queryModalVisible"
:title="modalTitle"
width="500px"
:close-on-click-modal="false"
>
<el-form label-width="100px">
<el-form-item label="申请编号">
<span>{{ showList.sn }}</span>
</el-form-item>
<el-form-item label="用户名称">
<span>{{ showList.memberName }}</span>
</el-form-item>
<el-form-item label="申请金额:">
<priceColorScheme :value="showList.applyMoney" :color="$mainColor" />
</el-form-item>
<el-form-item label="提现状态:">
<span>{{ paramTypeFilter(showList.applyStatus) }}</span>
</el-form-item>
<el-form-item label="申请时间:">
<span>{{ showList.createTime }}</span>
</el-form-item>
<el-form-item label="审核时间:">
<span>{{ showList.inspectTime }}</span>
</el-form-item>
<el-form-item label="审核备注:">
<span>{{ showList.inspectRemark || "暂无备注" }}</span>
</el-form-item>
</el-form>
<template #footer>
<template v-if="showList.applyStatus === 'APPLY'">
<el-button @click="submitRole(false)">拒绝</el-button>
<el-button type="primary" :loading="submitLoading" @click="submitRole(true)">通过</el-button>
</template>
<el-button v-else @click="queryModalVisible = false">取消</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -105,169 +174,68 @@ import { getUserWithdrawApply, withdrawApply } from "@/api/member";
export default {
name: "withdrawApply",
components: {},
data() {
return {
modalTitle: "", //弹出框标题
openSearch: true, // 显示搜索
openTip: true, // 显示提示
loading: true, // 表单加载状态
audit: "", // 审核备注
roleModalVisible: false, // 审核模态框
queryModalVisible: false, // 审核模态框
modalTitle: "",
loading: true,
audit: "",
roleModalVisible: false,
queryModalVisible: false,
searchForm: {
// 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
startDate: "", // 起始时间
endDate: "", // 终止时间
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
startDate: "",
endDate: "",
memberName: "",
applyStatus: "",
},
selectDate: null, // 选择时间段
submitLoading: false, // 添加或编辑提交状态
selectList: [], // 多选数据
selectCount: 0, // 多选计数
showList: {}, // 可操作选项
columns: [
{
title: "申请编号",
key: "sn",
align: "left",
tooltip: true,
},
{
title: "用户名称",
key: "memberName",
align: "left",
tooltip: true,
},
{
title: "申请金额",
key: "applyMoney",
align: "left",
width: 120,
render: (h, params) => {
return h("priceColorScheme", {props:{value:params.row.applyMoney,color:this.$mainColor}} );
},
},
{
title: "提现状态",
align: "left",
key: "applyStatus",
width: 120,
render: (h, params) => {
if (params.row.applyStatus == "APPLY") {
return h("Tag", { props: { color: "volcano" } }, "申请中");
} else if (params.row.applyStatus == "VIA_AUDITING") {
return h("Tag", { props: { color: "green" } }, "审核通过");
} else if (params.row.applyStatus == "WAIT_USER_CONFIRM") {
return h("Tag", { props: { color: "gold" } }, "用户确认");
} else if (params.row.applyStatus == "SUCCESS") {
return h("Tag", { props: { color: "blue" } }, "提现成功");
} else if (params.row.applyStatus == "ERROR") {
return h("Tag", { props: { color: "blue" } }, "提现失败");
} else {
return h("Tag", { props: { color: "red" } }, "审核拒绝");
}
}
},
{
title: "申请时间",
key: "createTime",
align: "left",
width: 170,
},
{
title: "审核时间",
key: "inspectTime",
align: "left",
width: 170,
},
{
title: "操作",
key: "action",
width: 120,
align: "center",
fixed: "right",
render: (h, params) => {
if (params.row.applyStatus == "APPLY") {
return h("div", { class: "ops" }, [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.showList = {};
this.roleModalVisible = true;
this.showList = params.row;
this.audit = "";
},
},
},
"审核"
),
]);
} else {
return h("div", { class: "ops" }, [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.showList = {};
this.queryModalVisible = true;
this.showList = params.row;
this.modalTitle = "查看";
},
},
},
"查看"
),
]);
}
},
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
selectDate: null,
submitLoading: false,
selectList: [],
selectCount: 0,
showList: {},
data: [],
total: 0,
};
},
filters: {
paramTypeFilter(val) {
if (val === "APPLY") {
return "申请中";
} else if (val === "VIA_AUDITING") {
return "审核通过(提现成功)";
} else if (val === "WAIT_USER_CONFIRM") {
return "用户确认";
} else if (val === "FAIL_AUDITING") {
return "审核拒绝";
} else if (val === "SUCCESS") {
return "提现成功";
} else if (val === "ERROR") {
return "提现失败";
} else {
return "未知状态";
}
},
},
methods: {
paramTypeFilter(val) {
if (val === "APPLY") return "申请中";
if (val === "VIA_AUDITING") return "审核通过(提现成功)";
if (val === "WAIT_USER_CONFIRM") return "用户确认";
if (val === "FAIL_AUDITING") return "审核拒绝";
if (val === "SUCCESS") return "提现成功";
if (val === "ERROR") return "提现失败";
return "未知状态";
},
applyStatusText(status) {
if (status === "APPLY") return "申请中";
if (status === "VIA_AUDITING") return "审核通过";
if (status === "WAIT_USER_CONFIRM") return "用户确认";
if (status === "SUCCESS") return "提现成功";
if (status === "ERROR") return "提现失败";
return "审核拒绝";
},
applyStatusTagType(status) {
if (status === "APPLY") return "warning";
if (status === "VIA_AUDITING") return "success";
if (status === "WAIT_USER_CONFIRM") return "warning";
if (status === "SUCCESS") return "primary";
if (status === "ERROR") return "primary";
return "danger";
},
openAudit(row) {
this.showList = { ...row };
this.audit = "";
this.roleModalVisible = true;
},
openQuery(row) {
this.showList = { ...row };
this.modalTitle = "查看";
this.queryModalVisible = true;
},
submitRole(res) {
const params = {};
params.applyId = this.showList.id;
@@ -319,33 +287,36 @@ export default {
this.searchForm.startDate = "";
this.searchForm.endDate = "";
this.searchForm.memberName = "";
// 重新加载数据
this.getDataList();
},
changeSort(e) {
this.searchForm.sort = e.key;
this.searchForm.order = e.order;
if (e.order === "normal") {
this.searchForm.sort = e.prop || e.key;
this.searchForm.order = e.order === "ascending" ? "asc" : e.order === "descending" ? "desc" : "";
if (!e.order) {
this.searchForm.order = "";
}
this.getDataList();
},
clearSelectAll() {
this.$refs.table.selectAll(false);
if (this.$refs.table) {
this.$refs.table.clearSelection();
}
},
changeSelect(e) {
this.selectList = e;
this.selectCount = e.length;
},
selectDateRange(v) {
if (v) {
if (v && v.length === 2) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
} else {
this.searchForm.startDate = "";
this.searchForm.endDate = "";
}
},
getDataList() {
this.loading = true;
// 带多条件搜索参数获取表单数据 请自行修改接口
getUserWithdrawApply(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
@@ -353,8 +324,6 @@ export default {
this.total = res.result.total;
}
});
this.total = this.data.length;
this.loading = false;
},
},
mounted() {
@@ -374,4 +343,3 @@ export default {
color: #dcdee2;
}
</style>

View File

@@ -1,42 +1,90 @@
<template>
<div class="search member-benefit">
<Card>
<Row class="operation padding-row">
<Button type="primary" @click="openAdd">添加权益设置</Button>
</Row>
<Table
:loading="loading"
<el-card>
<div class="operation padding-row">
<el-button type="primary" @click="openAdd">添加权益设置</el-button>
</div>
<el-table
v-loading="loading"
stripe
:columns="columns"
:data="data"
no-data-text="暂无数据"
empty-text="暂无数据"
class="mt_10 benefit-list-table benefit-list-table--no-vertical-borders"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
style="width: 100%"
>
<el-table-column label="权益类型" width="132">
<template #default="{ row }">
<span
v-if="row"
:title="benefitTypeLabel(row.benefitType)"
class="benefit-list-cell-ellipsis benefit-list-cell-ellipsis--type"
>
{{ benefitTypeLabel(row.benefitType) }}</span>
</template>
</el-table-column>
<el-table-column label="权益名称" width="188">
<template #default="{ row }">
<span
v-if="row"
:title="row.benefitName || '-'"
class="benefit-list-cell-ellipsis benefit-list-cell-ellipsis--name"
>
{{ row.benefitName || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="权益LOGO" width="116" align="center">
<template #default="{ row }">
<span v-if="row && !row.benefitLogo">-</span>
<div v-else-if="row" class="benefit-logo-thumb benefit-logo-thumb--table">
<img :src="row.benefitLogo" alt="" />
</div>
</template>
</el-table-column>
<el-table-column label="状态" width="118" align="center">
<template #default="{ row }">
<el-switch
v-if="row"
:model-value="row.benefitState === 'OPEN'"
inline-prompt
active-text="开启"
inactive-text="关闭"
:loading="!!row._benefitStateLoading"
@change="(checked) => onBenefitStateSwitch(row, checked)"
/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="140">
<template #default="{ row }">
<div v-if="row" class="ops" style="display: flex; justify-content: center">
<a class="link-text" @click="openEdit(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="remove(row)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 30, 50]"
:page-sizes="[20, 30, 50]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
<!-- 平台优惠券选择添加优惠券活动coupon-publish 相同组件 -->
<Modal
<el-dialog
v-model="couponPickerVisible"
title="选择优惠券"
width="80%"
:z-index="3000"
:mask-closable="false"
@on-ok="handleCouponPickerClose"
@on-cancel="handleCouponPickerClose"
:close-on-click-modal="false"
destroy-on-close
@close="handleCouponPickerClose"
>
<couponTemplate
v-if="couponPickerVisible"
@@ -45,38 +93,41 @@
promotionStatus="START"
@selected="onCouponTemplateSelected"
/>
</Modal>
</el-dialog>
<Drawer
<el-drawer
v-model="addFlag"
title="添加权益设置"
width="1120"
placement="right"
size="1120px"
direction="rtl"
:z-index="950"
:mask-closable="false"
:closable="true"
scrollable
class-name="benefit-form-drawer"
:close-on-click-modal="false"
class="benefit-form-drawer"
>
<Form ref="addForm" :model="formAdd" :rules="rulesAdd" :label-width="110">
<FormItem label="权益类型" prop="benefitType">
<Select
<el-form ref="addForm" :model="formAdd" :rules="rulesAdd" label-width="110px">
<el-form-item label="权益类型" prop="benefitType">
<el-select
v-model="formAdd.benefitType"
clearable
placeholder="请选择权益类型"
style="width: 100%"
@on-change="onAddBenefitTypeChange"
@change="onAddBenefitTypeChange"
>
<Option v-for="item in benefitTypeOptions" :key="item.value" :value="item.value">{{ item.description }}</Option>
</Select>
</FormItem>
<FormItem
<el-option
v-for="item in benefitTypeOptions"
:key="item.value"
:value="item.value"
:label="item.description"
/>
</el-select>
</el-form-item>
<el-form-item
v-show="formAdd.benefitType === 'GIFT_POINT'"
label="赠送积分"
prop="giftPoint"
:required="formAdd.benefitType === 'GIFT_POINT'"
>
<InputNumber
<el-input-number
v-model="formAdd.giftPoint"
:min="0"
:max="99999"
@@ -84,28 +135,54 @@
style="width: 220px"
placeholder="必填,范围 0-99999"
/>
</FormItem>
<FormItem
</el-form-item>
<el-form-item
v-show="formAdd.benefitType === 'COUPON_PACKAGE'"
label="赠送优惠券"
prop="couponPackageRows"
:required="formAdd.benefitType === 'COUPON_PACKAGE'"
>
<div>
<Button type="dashed" icon="ios-add" class="mb_10" @click="openCouponPicker('add')">添加优惠券</Button>
<Table
<el-button plain class="mb_10" @click="openCouponPicker('add')">添加优惠券</el-button>
<el-table
border
size="small"
:columns="couponPackageTableColumns"
:data="formAdd.couponPackageRows"
no-data-text="请添加优惠券"
></Table>
empty-text="请添加优惠券"
style="width: 100%"
>
<el-table-column prop="couponName" label="优惠券名称" min-width="100" show-overflow-tooltip />
<el-table-column label="有效期" min-width="100">
<template #default="{ row }">
<span v-if="row" v-html="row.validRange || '-'" />
</template>
</el-table-column>
<el-table-column prop="faceValueLabel" label="面额" min-width="100" />
<el-table-column label="赠送张数" width="150">
<template #default="{ row, $index }">
<el-input-number
v-if="row"
:model-value="row.quantity"
:min="1"
:max="10"
:precision="0"
style="width: 100px"
@change="(val) => onCouponQuantityChange('add', $index, val)"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="90" align="center">
<template #default="{ row, $index }">
<a v-if="row" class="link-text" @click="removeCouponRow('add', $index)">删除</a>
</template>
</el-table-column>
</el-table>
</div>
</FormItem>
<FormItem label="权益名称" prop="benefitName">
<Input v-model="formAdd.benefitName" maxlength="50" placeholder="请输入权益名称" />
</FormItem>
<FormItem label="权益LOGO" prop="benefitLogo">
</el-form-item>
<el-form-item label="权益名称" prop="benefitName">
<el-input v-model="formAdd.benefitName" maxlength="50" placeholder="请输入权益名称" />
</el-form-item>
<el-form-item label="权益LOGO" prop="benefitLogo">
<div class="benefit-logo-field">
<div v-if="formAdd.benefitLogo" class="benefit-logo-thumb">
<img :src="formAdd.benefitLogo" alt="" />
@@ -114,57 +191,60 @@
<upload-pic-input v-model="formAdd.benefitLogo" placeholder="请上传权益 LOGO 图片地址" style="width: 100%" />
</div>
</div>
</FormItem>
<FormItem label="权益介绍" prop="benefitDesc">
<Input v-model="formAdd.benefitDesc" type="textarea" :rows="4" maxlength="500" placeholder="请输入权益介绍" />
</FormItem>
<FormItem label="启用状态" prop="benefitState">
<RadioGroup v-model="formAdd.benefitState">
<Radio label="OPEN">开启</Radio>
<Radio label="CLOSE">关闭</Radio>
</RadioGroup>
</FormItem>
<FormItem label="排序" prop="benefitSort">
<InputNumber v-model="formAdd.benefitSort" :min="1" :max="9999" :precision="0" style="width: 220px" />
</FormItem>
</Form>
</el-form-item>
<el-form-item label="权益介绍" prop="benefitDesc">
<el-input v-model="formAdd.benefitDesc" type="textarea" :rows="4" maxlength="500" placeholder="请输入权益介绍" />
</el-form-item>
<el-form-item label="启用状态" prop="benefitState">
<el-radio-group v-model="formAdd.benefitState">
<el-radio value="OPEN">开启</el-radio>
<el-radio value="CLOSE">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序" prop="benefitSort">
<el-input-number v-model="formAdd.benefitSort" :min="1" :max="9999" :precision="0" style="width: 220px" />
</el-form-item>
</el-form>
<div class="benefit-drawer-footer-btns">
<Button @click="addFlag = false">取消</Button>
<Button type="primary" :loading="submitAddLoading" @click="submitAdd">提交</Button>
<el-button @click="addFlag = false">取消</el-button>
<el-button type="primary" :loading="submitAddLoading" @click="submitAdd">提交</el-button>
</div>
</Drawer>
</el-drawer>
<Drawer
<el-drawer
v-model="editFlag"
title="编辑权益设置"
width="1120"
placement="right"
size="1120px"
direction="rtl"
:z-index="950"
:mask-closable="false"
:closable="true"
scrollable
class-name="benefit-form-drawer"
:close-on-click-modal="false"
class="benefit-form-drawer"
>
<Form ref="editForm" :model="formEdit" :rules="rulesEdit" :label-width="110">
<Input v-model="formEdit.id" v-show="false" />
<FormItem label="权益类型" prop="benefitType">
<Select
<el-form ref="editForm" :model="formEdit" :rules="rulesEdit" label-width="110px">
<el-input v-model="formEdit.id" v-show="false" />
<el-form-item label="权益类型" prop="benefitType">
<el-select
v-model="formEdit.benefitType"
clearable
placeholder="请选择权益类型"
style="width: 100%"
@on-change="onEditBenefitTypeChange"
@change="onEditBenefitTypeChange"
>
<Option v-for="item in benefitTypeOptions" :key="item.value" :value="item.value">{{ item.description }}</Option>
</Select>
</FormItem>
<FormItem
<el-option
v-for="item in benefitTypeOptions"
:key="item.value"
:value="item.value"
:label="item.description"
/>
</el-select>
</el-form-item>
<el-form-item
v-show="formEdit.benefitType === 'GIFT_POINT'"
label="赠送积分"
prop="giftPoint"
:required="formEdit.benefitType === 'GIFT_POINT'"
>
<InputNumber
<el-input-number
v-model="formEdit.giftPoint"
:min="0"
:max="99999"
@@ -172,28 +252,54 @@
style="width: 220px"
placeholder="必填,范围 0-99999"
/>
</FormItem>
<FormItem
</el-form-item>
<el-form-item
v-show="formEdit.benefitType === 'COUPON_PACKAGE'"
label="赠送优惠券"
prop="couponPackageRows"
:required="formEdit.benefitType === 'COUPON_PACKAGE'"
>
<div>
<Button type="dashed" icon="ios-add" class="mb_10" @click="openCouponPicker('edit')">添加优惠券</Button>
<Table
<el-button plain class="mb_10" @click="openCouponPicker('edit')">添加优惠券</el-button>
<el-table
border
size="small"
:columns="couponPackageTableColumnsEdit"
:data="formEdit.couponPackageRows"
no-data-text="请添加优惠券"
></Table>
empty-text="请添加优惠券"
style="width: 100%"
>
<el-table-column prop="couponName" label="优惠券名称" min-width="100" show-overflow-tooltip />
<el-table-column label="有效期" min-width="100">
<template #default="{ row }">
<span v-if="row" v-html="row.validRange || '-'" />
</template>
</el-table-column>
<el-table-column prop="faceValueLabel" label="面额" min-width="100" />
<el-table-column label="赠送张数" width="150">
<template #default="{ row, $index }">
<el-input-number
v-if="row"
:model-value="row.quantity"
:min="1"
:max="10"
:precision="0"
style="width: 100px"
@change="(val) => onCouponQuantityChange('edit', $index, val)"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="90" align="center">
<template #default="{ row, $index }">
<a v-if="row" class="link-text" @click="removeCouponRow('edit', $index)">删除</a>
</template>
</el-table-column>
</el-table>
</div>
</FormItem>
<FormItem label="权益名称" prop="benefitName">
<Input v-model="formEdit.benefitName" maxlength="50" placeholder="请输入权益名称" />
</FormItem>
<FormItem label="权益LOGO" prop="benefitLogo">
</el-form-item>
<el-form-item label="权益名称" prop="benefitName">
<el-input v-model="formEdit.benefitName" maxlength="50" placeholder="请输入权益名称" />
</el-form-item>
<el-form-item label="权益LOGO" prop="benefitLogo">
<div class="benefit-logo-field">
<div v-if="formEdit.benefitLogo" class="benefit-logo-thumb">
<img :src="formEdit.benefitLogo" alt="" />
@@ -202,25 +308,25 @@
<upload-pic-input v-model="formEdit.benefitLogo" placeholder="请上传权益 LOGO 图片地址" style="width: 100%" />
</div>
</div>
</FormItem>
<FormItem label="权益介绍" prop="benefitDesc">
<Input v-model="formEdit.benefitDesc" type="textarea" :rows="4" maxlength="500" placeholder="请输入权益介绍" />
</FormItem>
<FormItem label="启用状态" prop="benefitState">
<RadioGroup v-model="formEdit.benefitState">
<Radio label="OPEN">开启</Radio>
<Radio label="CLOSE">关闭</Radio>
</RadioGroup>
</FormItem>
<FormItem label="排序" prop="benefitSort">
<InputNumber v-model="formEdit.benefitSort" :min="1" :max="9999" :precision="0" style="width: 220px" />
</FormItem>
</Form>
</el-form-item>
<el-form-item label="权益介绍" prop="benefitDesc">
<el-input v-model="formEdit.benefitDesc" type="textarea" :rows="4" maxlength="500" placeholder="请输入权益介绍" />
</el-form-item>
<el-form-item label="启用状态" prop="benefitState">
<el-radio-group v-model="formEdit.benefitState">
<el-radio value="OPEN">开启</el-radio>
<el-radio value="CLOSE">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序" prop="benefitSort">
<el-input-number v-model="formEdit.benefitSort" :min="1" :max="9999" :precision="0" style="width: 220px" />
</el-form-item>
</el-form>
<div class="benefit-drawer-footer-btns">
<Button @click="editFlag = false">取消</Button>
<Button type="primary" :loading="submitEditLoading" @click="submitEdit">提交</Button>
<el-button @click="editFlag = false">取消</el-button>
<el-button type="primary" :loading="submitEditLoading" @click="submitEdit">提交</el-button>
</div>
</Drawer>
</el-drawer>
</div>
</template>
@@ -244,9 +350,7 @@ const buildDefaultForm = () => ({
benefitSort: 1,
benefitState: "OPEN",
benefitConfig: "",
/** 仅 UI赠送积分数量提交时写入 benefitConfig */
giftPoint: null,
/** 仅 UI券礼包已选优惠券含展示字段提交时写入 benefitConfig.coupons */
couponPackageRows: [],
});
@@ -265,109 +369,6 @@ export default {
pageNumber: 1,
pageSize: 20,
},
columns: [
{
title: "权益类型",
key: "benefitType",
width: 132,
render: (h, params) => {
const v = params.row.benefitType;
let text = "-";
if (v) {
const opt = this.benefitTypeOptions.find((o) => o.value === v);
text = opt ? opt.description : v;
}
return h(
"span",
{
attrs: { title: text },
class: "benefit-list-cell-ellipsis benefit-list-cell-ellipsis--type",
},
text
);
},
},
{
title: "权益名称",
key: "benefitName",
width: 188,
render: (h, params) => {
const text = params.row.benefitName || "-";
return h(
"span",
{
attrs: { title: text },
class: "benefit-list-cell-ellipsis benefit-list-cell-ellipsis--name",
},
text
);
},
},
{
title: "权益LOGO",
key: "benefitLogo",
width: 116,
align: "center",
render: (h, params) => {
const src = params.row.benefitLogo;
if (!src) return h("span", "-");
return h(
"div",
{
class: "benefit-logo-thumb benefit-logo-thumb--table",
},
[
h("img", {
attrs: { src, alt: "" },
}),
]
);
},
},
{
title: "状态",
key: "benefitState",
width: 118,
align: "center",
render: (h, params) => {
const row = params.row;
return h("i-switch", {
props: {
value: row.benefitState === "OPEN",
size: "large",
loading: !!row._benefitStateLoading,
},
on: {
"on-change": (checked) => {
this.onBenefitStateSwitch(row, checked);
},
},
}, [
h("span", { slot: "open" }, "开启"),
h("span", { slot: "close" }, "关闭"),
]);
},
},
{
title: "操作",
key: "action",
align: "center",
width: 140,
render: (h, params) => {
const linkStyle = {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
};
const sep = h("span", { style: { margin: "0 8px", color: "#dcdee2" } }, "|");
return h("div", { 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,
@@ -386,13 +387,6 @@ export default {
rulesEdit() {
return this.buildFormRules("edit");
},
couponPackageTableColumns() {
return this.buildCouponPackageTableColumns("add");
},
couponPackageTableColumnsEdit() {
return this.buildCouponPackageTableColumns("edit");
},
/** 传给优惠券列表组件,用于勾选回显(与 coupon-publish 一致用 id */
couponPickerSelectedList() {
const form = this.couponPickerWhich === "add" ? this.formAdd : this.formEdit;
return (form.couponPackageRows || []).map((r) => ({
@@ -402,6 +396,20 @@ export default {
},
},
methods: {
benefitTypeLabel(v) {
if (!v) return "-";
const opt = this.benefitTypeOptions.find((o) => o.value === v);
return opt ? opt.description : v;
},
onCouponQuantityChange(which, index, val) {
const formKey = which === "add" ? "formAdd" : "formEdit";
const refName = which === "add" ? "addForm" : "editForm";
this[formKey].couponPackageRows[index].quantity = val;
this.$nextTick(() => {
const ref = this.$refs[refName];
if (ref) ref.validateField("couponPackageRows");
});
},
buildFormRules(which) {
const formKey = which === "add" ? "formAdd" : "formEdit";
return {
@@ -478,66 +486,6 @@ export default {
validRange: this.formatCouponValidity(detail),
};
},
buildCouponPackageTableColumns(which) {
const formKey = which === "add" ? "formAdd" : "formEdit";
const linkStyle = { color: "#2d8cf0", cursor: "pointer" };
return [
{ title: "优惠券名称", key: "couponName", minWidth: 100, tooltip: true },
{
title: "有效期",
minWidth: 100,
render: (h, p) =>
h("span", {
domProps: { innerHTML: p.row.validRange || "-" },
}),
},
{ title: "面额", key: "faceValueLabel", minWidth: 100 },
{
title: "赠送张数",
key: "quantity",
width: 150,
render: (h, params) =>
h("InputNumber", {
props: {
min: 1,
max: 10,
precision: 0,
value: params.row.quantity,
},
style: { width: "100px" },
on: {
"on-change": (val) => {
this.$set(this[formKey].couponPackageRows[params.index], "quantity", val);
this.$nextTick(() => {
const ref = which === "add" ? this.$refs.addForm : this.$refs.editForm;
if (ref) ref.validateField("couponPackageRows");
});
},
},
}),
},
{
title: "操作",
key: "action",
width: 90,
align: "center",
render: (h, params) =>
h(
"a",
{
style: linkStyle,
on: {
click: () => {
this.removeCouponRow(which, params.index);
},
},
},
"删除"
),
},
];
},
/** 构造 benefitConfig JSON 字符串 */
buildBenefitConfigString(slice) {
const { benefitType, giftPoint, couponPackageRows } = slice;
if (benefitType === GIFT_POINT) {
@@ -552,7 +500,6 @@ export default {
}
return "";
},
/** 从详情 benefitConfig 解析赠送积分,解析失败时返回 null */
parseGiftPointFromConfig(benefitType, benefitConfigStr) {
if (benefitType !== GIFT_POINT || !benefitConfigStr) return null;
try {
@@ -613,7 +560,6 @@ export default {
}
return [];
},
/** 与添加时 formatCouponFace 一致;仅有 faceValueText 时去掉「减免」前缀 */
normalizeCouponFaceFromDetail(item) {
let face = this.formatCouponFace(item);
if (face !== "-") return face;
@@ -624,7 +570,6 @@ export default {
.replace(/^减免\s*/, "")
.trim() || "-";
},
/** 管理端详情 couponItems → 表格行(面额展示与添加一致) */
mapCouponItemsToPackageRows(items) {
if (!Array.isArray(items)) return [];
return items.map((item) => {
@@ -669,7 +614,7 @@ export default {
});
}
}
this.$set(this.formEdit, "couponPackageRows", rows);
this.formEdit.couponPackageRows = rows;
},
handleCouponPickerClose() {
this.couponPickerVisible = false;
@@ -678,7 +623,6 @@ export default {
this.couponPickerWhich = which;
this.couponPickerVisible = true;
},
/** 与 coupon-publish `selectedCoupon`:表格多选变更时同步到券礼包配置 */
onCouponTemplateSelected(selectedRows) {
const which = this.couponPickerWhich;
const form = which === "add" ? this.formAdd : this.formEdit;
@@ -689,7 +633,7 @@ export default {
const qty = existing ? existing.quantity : 1;
return this.buildCouponDisplayRow(row, qty);
});
this.$set(form, "couponPackageRows", rows);
form.couponPackageRows = rows;
this.$nextTick(() => {
const ref = this.$refs[refName];
if (ref) ref.validateField("couponPackageRows");
@@ -791,7 +735,6 @@ export default {
API_Member.getMemberBenefit(row.id).then((res) => {
if (res && res.success && res.result) {
const raw = res.result;
/** 新接口:{ benefit, couponItems };旧接口:扁平 MemberBenefit */
const detail = raw.benefit != null ? raw.benefit : raw;
const couponItems = raw.couponItems;
const bt = detail.benefitType || "";
@@ -866,19 +809,19 @@ export default {
title: "提示",
content: `<p>确定${text}该客户权益?</p>`,
onOk: () => {
this.$set(row, "_benefitStateLoading", true);
row._benefitStateLoading = true;
return API_Member.updateMemberBenefitState(row.id, nextState)
.then((res) => {
this.$set(row, "_benefitStateLoading", false);
row._benefitStateLoading = false;
if (res && res.success) {
this.$Message.success(`${text}成功`);
this.$set(row, "benefitState", nextState);
row.benefitState = nextState;
} else {
this.getData();
}
})
.catch(() => {
this.$set(row, "_benefitStateLoading", false);
row._benefitStateLoading = false;
});
},
});
@@ -913,17 +856,20 @@ export default {
border-top: 1px solid #e8eaec;
text-align: right;
}
.benefit-drawer-footer-btns .ivu-btn + .ivu-btn {
.benefit-drawer-footer-btns .el-button + .el-button {
margin-left: 8px;
}
.link-text {
color: #409eff;
cursor: pointer;
text-decoration: none;
}
.op-split {
margin: 0 8px;
color: #dcdfe6;
}
</style>
<!--
权益 LOGO 缩略图固定 100×100
不使用 .member-benefit 前缀Modal 默认 transfer body弹窗内节点不在 .member-benefit
Table render 生成的节点在子组件内同样用非 scoped
-->
<style lang="scss">
.benefit-logo-thumb {
width: 100px;
@@ -952,7 +898,6 @@ export default {
margin: 0 auto;
}
/* 权益列表:固定类型/名称列宽并省略过长文案(悬浮 title 可看全文) */
.member-benefit .benefit-list-table table {
table-layout: fixed;
}
@@ -971,9 +916,8 @@ export default {
max-width: 172px;
}
/* 列表不出现列与列之间的竖线(保留行间分隔) */
.member-benefit .benefit-list-table--no-vertical-borders .ivu-table th,
.member-benefit .benefit-list-table--no-vertical-borders .ivu-table td {
.member-benefit .benefit-list-table--no-vertical-borders .el-table th,
.member-benefit .benefit-list-table--no-vertical-borders .el-table td {
border-right: none !important;
}
</style>

View File

@@ -1,57 +1,80 @@
<template>
<div class="search">
<Card>
<Form
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
:label-width="90"
@keydown.enter.native="handleSearch"
@submit.native.prevent
label-width="90px"
class="search-form"
@keyup.enter="handleSearch"
>
<FormItem label="客户手机号" prop="mobile">
<Input
<el-form-item label="客户手机号" prop="mobile">
<el-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>
</el-form-item>
<el-form-item label="规则" prop="ruleKey">
<el-select v-model="searchForm.ruleKey" clearable filterable style="width: 220px">
<el-option
v-for="item in ruleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-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"
<el-card>
<el-table v-loading="loading" border :data="data" class="mt_10" style="width: 100%">
<el-table-column label="客户手机号" width="140" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row">{{ row.memberMobile || row.mobile || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="规则名称" width="150" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row">{{ row.ruleName || findRuleName(row.ruleKey) || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="变化经验值" width="120">
<template #default="{ row }">
<span v-if="row">{{ formatExperienceValue(row) }}</span>
</template>
</el-table-column>
<el-table-column label="经验值限额" width="120">
<template #default="{ row }">
<span v-if="row">{{ formatMaxValue(row) }}</span>
</template>
</el-table-column>
<el-table-column label="操作说明" min-width="200" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row">{{ row.content || row.remark || row.description || "-" }}</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" width="170" />
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
</div>
</template>
@@ -86,67 +109,20 @@ export default {
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: {
formatExperienceValue(row) {
const v = row.value ?? row.variableExperience ?? row.experience ?? row.variableValue;
return v == null ? "-" : v;
},
formatMaxValue(row) {
const v = row.maxValue ?? row.maxExperience ?? row.limitValue;
return v == null ? "-" : v;
},
findRuleName(ruleKey) {
const hit = this.ruleOptions.find((item) => item.value === ruleKey);
return hit ? hit.label : "";

View File

@@ -1,10 +1,226 @@
<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
<el-card>
<el-form label-width="120px" label-position="right">
<el-table
v-loading="loading"
:data="form.items"
class="mt_10 experience-table"
style="width: 100%"
>
<el-table-column label="是否开启" width="90" align="center">
<template #default="{ row, $index }">
<el-checkbox
v-if="row"
:model-value="!!form.items[$index].enabled"
@change="(checked) => updateRuleEnabled($index, checked)"
/>
</template>
</el-table-column>
<el-table-column prop="ruleName" label="类型" width="160" />
<el-table-column label="经验值(1-100)" min-width="700">
<template #default="{ row, $index }">
<template v-if="row">
<div v-if="row.ruleKey === 'REGISTER'" class="rule-cell">
<div class="rule-row">
<span class="rule-label">获得经验值:</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-tip">会员注册成功后可获得经验值</div>
</div>
<div v-else-if="row.ruleKey === 'SHARE'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<div class="rule-inline">
<span class="rule-label">分享商品详情页获得经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-inline">
<span class="rule-label">可获得经验值限额</span>
<el-input
:model-value="formatInputValue(form.items[$index].maxValue)"
style="width: 120px"
@input="(val) => updateRuleMaxValue($index, val)"
@blur="() => commitRuleMaxValue($index)"
/>
</div>
</div>
<div class="rule-tip">会员分享商城页面可获得的经验值</div>
</div>
<div v-else-if="row.ruleKey === 'COMMENT'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<span class="rule-label">对已购买商品完成提交评论获得经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-tip">仅针对评论字数大于30字的评论进行发放</div>
</div>
<div v-else-if="row.ruleKey === 'FOLLOW_STORE'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<div class="rule-inline">
<span class="rule-label">获得经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-inline">
<span class="rule-label">可获得经验值限额</span>
<el-input
:model-value="formatInputValue(form.items[$index].maxValue)"
style="width: 120px"
@input="(val) => updateRuleMaxValue($index, val)"
@blur="() => commitRuleMaxValue($index)"
/>
</div>
</div>
<div class="rule-tip">关注店铺可获得经验值每个客户D相同店铺仅第一次关注可进行获得</div>
</div>
<div v-else-if="row.ruleKey === 'PROFILE'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<span class="rule-label">获得经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-tip">完善个人基本信息可获得经验值每个会员仅可获得一次</div>
</div>
<div v-else-if="row.ruleKey === 'BIND_WECHAT'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<span class="rule-label">获取经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-tip">绑定微信成功获得经验值每个会员仅可获得一次</div>
</div>
<div v-else-if="row.ruleKey === 'ADD_ADDRESS'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<span class="rule-label">获取经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-tip">添加收货地址后获得经验值每个会员仅可获得一次</div>
</div>
<div v-else-if="row.ruleKey === 'SHARE_REGISTER'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<div class="rule-inline">
<span class="rule-label">获取的经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-inline">
<span class="rule-label">可获得经验值限额</span>
<el-input
:model-value="formatInputValue(form.items[$index].maxValue)"
style="width: 120px"
@input="(val) => updateRuleMaxValue($index, val)"
@blur="() => commitRuleMaxValue($index)"
/>
</div>
</div>
<div class="rule-tip">仅被注册成功后才可获得相应奖励经验值</div>
</div>
<div v-else-if="row.ruleKey === 'SHARE_BUY'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<div class="rule-inline">
<span class="rule-label">获取的经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-inline">
<span class="rule-label">可获得经验值限额</span>
<el-input
:model-value="formatInputValue(form.items[$index].maxValue)"
style="width: 120px"
@input="(val) => updateRuleMaxValue($index, val)"
@blur="() => commitRuleMaxValue($index)"
/>
</div>
</div>
<div class="rule-tip">仅被购买成功后才可获得相应奖励经验值</div>
</div>
<div v-else-if="row.ruleKey === 'SIGN_IN'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<span class="rule-label">获取的经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-tip">客户每日签到后可获的经验值</div>
</div>
<div v-else-if="row.ruleKey === 'CONSUME'" class="rule-cell">
<div class="rule-row rule-row-wrap">
<span class="rule-label">1元获取经验值</span>
<el-input
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</div>
<div class="rule-tip">客户消费1元可获取经验值向下取整</div>
</div>
<el-input
v-else
:model-value="formatInputValue(form.items[$index].value)"
style="width: 120px"
@input="(val) => updateRuleValue($index, val)"
@blur="() => commitRuleValue($index)"
/>
</template>
</template>
</el-table-column>
</el-table>
<el-form-item label="经验值说明" style="margin-top: 16px" class="desc-item">
<el-input
v-model="form.description"
type="textarea"
:rows="4"
@@ -12,12 +228,12 @@
show-word-limit
placeholder="请输入经验值说明"
/>
</FormItem>
<FormItem>
<Button type="primary" :loading="submitLoading" @click="submit">保存</Button>
</FormItem>
</Form>
</Card>
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="submitLoading" @click="submit">保存</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
@@ -58,340 +274,33 @@ export default {
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: {
formatInputValue(v) {
return v == null ? "" : String(v);
},
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, {
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, {
this.form.items[index] = {
...item,
value: Number.isFinite(next) ? next : null,
});
};
},
commitRuleValue(index) {
const item = this.form.items[index] || {};
@@ -402,41 +311,41 @@ export default {
else if (next > 100) value = 100;
else value = Math.floor(next);
}
this.$set(this.form.items, index, {
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, {
this.form.items[index] = {
...item,
maxValue: null,
});
};
return;
}
const next = Number(raw);
this.$set(this.form.items, index, {
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, {
this.form.items[index] = {
...item,
maxValue: null,
});
};
return;
}
const next = Number(item.maxValue);
this.$set(this.form.items, index, {
this.form.items[index] = {
...item,
maxValue: Number.isFinite(next) && next >= 1 ? Math.floor(next) : null,
});
};
},
normalizeConfig(val) {
if (!val) return {};
@@ -535,21 +444,52 @@ export default {
padding: 2px 0;
}
::v-deep .experience-table .ivu-table th {
.rule-cell {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.rule-row {
display: flex;
align-items: center;
}
.rule-row-wrap {
flex-wrap: wrap;
}
.rule-inline {
display: flex;
align-items: center;
margin-right: 16px;
}
.rule-label {
margin-right: 8px;
}
.rule-tip {
margin-top: 6px;
color: #808695;
font-size: 12px;
}
:deep(.experience-table .el-table__header th) {
background: #fafbfc;
}
::v-deep .experience-table .ivu-table td {
:deep(.experience-table .el-table__body td) {
padding-top: 12px;
padding-bottom: 12px;
}
::v-deep .experience-table .ivu-table-cell {
:deep(.experience-table .cell) {
font-size: 13px;
line-height: 1.7;
}
::v-deep .desc-item .ivu-form-item-label {
:deep(.desc-item .el-form-item__label) {
font-size: 16px;
font-weight: 600;
}

View File

@@ -1,120 +1,180 @@
<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>
<el-card>
<div class="operation padding-row">
<el-button type="primary" @click="openAdd">添加客户等级</el-button>
</div>
<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"
<el-table v-loading="loading" border :data="data" class="mt_10" style="width: 100%">
<el-table-column prop="gradeName" label="等级名称" width="130" show-overflow-tooltip />
<el-table-column label="默认等级" width="95">
<template #default="{ row }">
<el-tag v-if="row" :type="row.isDefault === true ? 'success' : 'info'">
{{ row.isDefault === true ? "" : "" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="等级图标" width="100">
<template #default="{ row }">
<span v-if="row && !row.gradeImage">-</span>
<img
v-else-if="row"
:src="row.gradeImage"
alt="等级图标"
style="width: 48px; height: 48px; object-fit: contain; border: 1px solid #dcdee2; border-radius: 4px; background: #fff"
/>
</template>
</el-table-column>
<el-table-column label="等级背景图" width="120">
<template #default="{ row }">
<span v-if="row && !row.gradeBackground">-</span>
<img
v-else-if="row"
:src="row.gradeBackground"
alt="等级背景图"
style="width: 64px; height: 40px; object-fit: cover; border: 1px solid #dcdee2; border-radius: 4px; background: #fff"
/>
</template>
</el-table-column>
<el-table-column prop="requiredExperience" label="所需经验值" width="110" />
<el-table-column prop="gradeSort" label="等级排序" width="95" />
<el-table-column label="状态" width="118" align="center">
<template #default="{ row }">
<el-switch
v-if="row"
:model-value="row.gradeState === 'OPEN'"
inline-prompt
active-text="开启"
inactive-text="关闭"
:loading="!!row._gradeStateLoading"
@change="(checked) => onGradeStateSwitch(row, checked)"
/>
</template>
</el-table-column>
<el-table-column label="操作" width="130" align="center">
<template #default="{ row }">
<div v-if="row" class="ops" style="display: flex; justify-content: center">
<a class="link-text" @click="openEdit(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="remove(row)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog v-model="addFlag" title="添加客户等级" width="720px" :z-index="950" :close-on-click-modal="false" destroy-on-close>
<el-form ref="addForm" :model="formAdd" :rules="rules" label-width="110px">
<el-form-item label="等级名称" prop="gradeName">
<el-input v-model="formAdd.gradeName" maxlength="50" placeholder="请输入等级名称" />
</el-form-item>
<el-form-item label="是否默认" prop="isDefault">
<el-radio-group v-model="formAdd.isDefault">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="等级图标" prop="gradeImage">
<upload-pic-input v-model="formAdd.gradeImage" />
</el-form-item>
<el-form-item label="等级背景图" prop="gradeBackground">
<upload-pic-input v-model="formAdd.gradeBackground" />
</el-form-item>
<el-form-item label="字体颜色" prop="gradeFontColor">
<el-input v-model="formAdd.gradeFontColor" maxlength="20" placeholder="如:#333333" />
</el-form-item>
<el-form-item label="所需经验值" prop="requiredExperience">
<el-input-number v-model="formAdd.requiredExperience" :min="1" :precision="0" style="width: 220px" />
</el-form-item>
<el-form-item label="等级排序" prop="gradeSort">
<el-input-number v-model="formAdd.gradeSort" :min="1" :max="9999" :precision="0" style="width: 220px" />
</el-form-item>
<el-form-item label="等级开关" prop="gradeState">
<el-radio-group v-model="formAdd.gradeState">
<el-radio value="OPEN">开启</el-radio>
<el-radio value="CLOSE">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="关联权益" prop="benefitIds">
<el-select
:model-value="addBenefitOrder"
multiple
filterable
placeholder="请选择客户权益"
style="width: 100%"
@on-change="onAddBenefitIdsChange"
@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>
<el-option
v-for="b in benefitOptions"
:key="b.id"
:value="String(b.id)"
:label="benefitOptionLabel(b)"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="addFlag = false">取消</el-button>
<el-button type="primary" :loading="submitAddLoading" @click="submitAdd">确定</el-button>
</template>
</el-dialog>
<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"
<el-dialog v-model="editFlag" title="编辑客户等级" width="720px" :z-index="950" :close-on-click-modal="false" destroy-on-close>
<el-form ref="editForm" :model="formEdit" :rules="rules" label-width="110px">
<el-input v-model="formEdit.id" style="display: none" />
<el-form-item label="等级名称" prop="gradeName">
<el-input v-model="formEdit.gradeName" maxlength="50" placeholder="请输入等级名称" />
</el-form-item>
<el-form-item label="是否默认" prop="isDefault">
<el-radio-group v-model="formEdit.isDefault">
<el-radio :value="true"></el-radio>
<el-radio :value="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="等级图标" prop="gradeImage">
<upload-pic-input v-model="formEdit.gradeImage" />
</el-form-item>
<el-form-item label="等级背景图" prop="gradeBackground">
<upload-pic-input v-model="formEdit.gradeBackground" />
</el-form-item>
<el-form-item label="字体颜色" prop="gradeFontColor">
<el-input v-model="formEdit.gradeFontColor" maxlength="20" placeholder="如:#333333" />
</el-form-item>
<el-form-item label="所需经验值" prop="requiredExperience">
<el-input-number v-model="formEdit.requiredExperience" :min="1" :precision="0" style="width: 220px" />
</el-form-item>
<el-form-item label="等级排序" prop="gradeSort">
<el-input-number v-model="formEdit.gradeSort" :min="1" :max="9999" :precision="0" style="width: 220px" />
</el-form-item>
<el-form-item label="等级开关" prop="gradeState">
<el-radio-group v-model="formEdit.gradeState">
<el-radio value="OPEN">开启</el-radio>
<el-radio value="CLOSE">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="关联权益" prop="benefitIds">
<el-select
:model-value="editBenefitOrder"
multiple
filterable
placeholder="请选择客户权益"
style="width: 100%"
@on-change="onEditBenefitIdsChange"
@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>
<el-option
v-for="b in benefitOptions"
:key="b.id"
:value="String(b.id)"
:label="benefitOptionLabel(b)"
/>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editFlag = false">取消</el-button>
<el-button type="primary" :loading="submitEditLoading" @click="submitEdit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -135,7 +195,6 @@ const buildDefaultForm = () => ({
benefitIds: "",
});
/** 权益多选:新勾选追加到末尾,取消勾选移除,保持已有顺序 */
function syncOrderedBenefitIds(prevOrder, selected) {
const sel = Array.isArray(selected) ? selected.map((id) => String(id)) : [];
const out = [];
@@ -157,144 +216,6 @@ export default {
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,
@@ -302,7 +223,6 @@ export default {
submitEditLoading: false,
formAdd: buildDefaultForm(),
formEdit: buildDefaultForm(),
/** 关联权益 id 顺序(与 benefitIds 一致) */
addBenefitOrder: [],
editBenefitOrder: [],
benefitOptions: [],
@@ -506,19 +426,19 @@ export default {
title: "提示",
content: `<p>确定${text}该客户等级?</p>`,
onOk: () => {
this.$set(row, "_gradeStateLoading", true);
row._gradeStateLoading = true;
return API_Member.updateMemberGradeState(row.id, nextState)
.then((res) => {
this.$set(row, "_gradeStateLoading", false);
row._gradeStateLoading = false;
if (res && res.success) {
this.$Message.success(`${text}成功`);
this.$set(row, "gradeState", nextState);
row.gradeState = nextState;
} else {
this.getData();
}
})
.catch(() => {
this.$set(row, "_gradeStateLoading", false);
row._gradeStateLoading = false;
});
},
});
@@ -545,3 +465,15 @@ export default {
},
};
</script>
<style scoped>
.ops a {
color: #2d8cf0;
cursor: pointer;
text-decoration: none;
}
.ops span {
display: inline-block;
margin: 0 8px;
color: #dcdee2;
}
</style>

View File

@@ -1,61 +1,72 @@
<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"
ref="table"
class="mt_10"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="searchForm.pageNumber"
<el-card>
<div class="operation padding-row">
<el-button type="primary" @click="openAdd">添加分组</el-button>
</div>
</el-card>
<el-card>
<el-table ref="table" v-loading="loading" :data="data" border class="mt_10" style="width: 100%">
<el-table-column prop="groupName" label="分组名称" min-width="160" show-overflow-tooltip />
<el-table-column prop="description" label="分组描述" min-width="240" show-overflow-tooltip />
<el-table-column prop="createTime" label="创建时间" min-width="180" />
<el-table-column prop="updateTime" label="更新时间" min-width="180" />
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<div v-if="row" class="ops" style="display: flex; justify-content: center">
<a class="link-text" @click="openEdit(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="remove(row)">删除</a>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
:page-size="searchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
<Modal v-model="addFlag" title="添加分组">
<Form ref="addForm" :model="formAdd" :rules="rulesAdd" :label-width="90">
<FormItem label="分组名称" prop="groupName" style="width: 90%;">
<Input v-model="formAdd.groupName" maxlength="30" placeholder="请输入分组名称" />
</FormItem>
<FormItem label="分组描述" prop="description" style="width: 90%;">
<Input v-model="formAdd.description" maxlength="200" placeholder="请输入分组描述" />
</FormItem>
</Form>
<div slot="footer">
<Button @click="addFlag = false">取消</Button>
<Button type="primary" :loading="submitAddLoading" @click="submitAdd">确定</Button>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</Modal>
<Modal v-model="editFlag" title="编辑分组">
<Form ref="editForm" :model="formEdit" :rules="rulesEdit" :label-width="90">
<Input v-model="formEdit.id" v-show="false" />
<FormItem label="分组名称" prop="groupName" style="width: 90%;">
<Input v-model="formEdit.groupName" maxlength="30" placeholder="请输入分组名称" />
</FormItem>
<FormItem label="分组描述" prop="description" style="width: 90%;">
<Input v-model="formEdit.description" maxlength="200" placeholder="请输入分组描述" />
</FormItem>
</Form>
<div slot="footer">
<Button @click="editFlag = false">取消</Button>
<Button type="primary" :loading="submitEditLoading" @click="submitEdit">确定</Button>
</div>
</Modal>
</el-card>
<el-dialog v-model="addFlag" title="添加分组" width="500px" :close-on-click-modal="false" destroy-on-close>
<el-form ref="addForm" :model="formAdd" :rules="rulesAdd" label-width="90px">
<el-form-item label="分组名称" prop="groupName" style="width: 90%">
<el-input v-model="formAdd.groupName" maxlength="30" placeholder="请输入分组名称" />
</el-form-item>
<el-form-item label="分组描述" prop="description" style="width: 90%">
<el-input v-model="formAdd.description" maxlength="200" placeholder="请输入分组描述" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="addFlag = false">取消</el-button>
<el-button type="primary" :loading="submitAddLoading" @click="submitAdd">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="editFlag" title="编辑分组" width="500px" :close-on-click-modal="false" destroy-on-close>
<el-form ref="editForm" :model="formEdit" :rules="rulesEdit" label-width="90px">
<el-input v-model="formEdit.id" style="display: none" />
<el-form-item label="分组名称" prop="groupName" style="width: 90%">
<el-input v-model="formEdit.groupName" maxlength="30" placeholder="请输入分组名称" />
</el-form-item>
<el-form-item label="分组描述" prop="description" style="width: 90%">
<el-input v-model="formEdit.description" maxlength="200" placeholder="请输入分组描述" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editFlag = false">取消</el-button>
<el-button type="primary" :loading="submitEditLoading" @click="submitEdit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
@@ -71,67 +82,6 @@ export default {
pageNumber: 1,
pageSize: 20,
},
columns: [
{
title: "分组名称",
key: "groupName",
minWidth: 160,
tooltip: true,
},
{
title: "分组描述",
key: "description",
minWidth: 240,
tooltip: true,
},
{
title: "创建时间",
key: "createTime",
width: 180,
},
{
title: "更新时间",
key: "updateTime",
width: 180,
},
{
title: "操作",
key: "action",
align: "center",
width: 200,
fixed: "right",
render: (h, params) => {
const linkStyle = {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
};
const sep = h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
);
const children = [
h(
"a",
{ style: linkStyle, on: { click: () => this.openEdit(params.row) } },
"编辑"
),
sep,
h(
"a",
{ style: linkStyle, on: { click: () => this.remove(params.row) } },
"删除"
),
];
return h(
"div",
{ class: "ops", style: { display: "flex", justifyContent: "center" } },
children
);
},
},
],
data: [],
total: 0,
addFlag: false,
@@ -148,10 +98,10 @@ export default {
description: "",
},
rulesAdd: {
groupName: [{ required: true, message: "请输入分组名称" }],
groupName: [{ required: true, message: "请输入分组名称", trigger: "blur" }],
},
rulesEdit: {
groupName: [{ required: true, message: "请输入分组名称" }],
groupName: [{ required: true, message: "请输入分组名称", trigger: "blur" }],
},
};
},
@@ -236,7 +186,7 @@ export default {
remove(row) {
this.$Modal.confirm({
title: "提示",
content: "<p>确定删除该分组?</p>",
content: "确定删除该分组?",
onOk: () => {
API_Member.deleteMemberGroup(row.id).then((res) => {
if (res && res.success) {
@@ -255,3 +205,16 @@ export default {
},
};
</script>
<style scoped>
.ops a {
color: #2d8cf0;
cursor: pointer;
text-decoration: none;
}
.ops span {
display: inline-block;
margin: 0 8px;
color: #dcdee2;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,175 +1,173 @@
<template>
<div class="search">
<Row>
<Card>
<Row @keydown.enter.native="handleSearch">
<Form
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
class="search-form"
>
<Form-item label="会员名称" prop="username">
<Input
type="text"
v-model="searchForm.username"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</Form-item>
<Form-item label="联系方式" prop="mobile">
<Input
type="text"
v-model="searchForm.mobile"
placeholder="请输入会员联系方式"
clearable
style="width: 240px"
/>
</Form-item>
<Button
@click="handleSearch"
class="search-btn"
type="primary"
icon="ios-search"
>搜索</Button
>
</Form>
</Row>
</Card>
<Card>
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10"
sortable="custom"
>
</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>
</Row>
<!-- 修改模态框 -->
<Modal
v-model="descFlag"
:title="descTitle"
@on-ok="handleSubmitModal"
width="500"
>
<Form
ref="formValidate"
:model="formValidate"
:rules="ruleValidate"
:label-width="80"
<el-card>
<el-form
ref="searchForm"
:model="searchForm"
inline
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<FormItem label="头像">
<el-form-item label="会员名称" prop="username">
<el-input
v-model="searchForm.username"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item label="联系方式" prop="mobile">
<el-input
v-model="searchForm.mobile"
placeholder="请输入会员联系方式"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card>
<el-table
ref="table"
v-loading="loading"
border
:data="data"
class="mt_10"
style="width: 100%"
>
<el-table-column prop="username" label="会员名称" min-width="150" align="left" show-overflow-tooltip />
<el-table-column prop="nickName" label="昵称" min-width="120" align="left" show-overflow-tooltip />
<el-table-column label="联系方式" min-width="130">
<template #default="{ row }">
<span v-if="row">{{ row.mobile || "" }}</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="注册时间" min-width="180" />
<el-table-column label="积分数量" min-width="120" align="left">
<template #default="{ row }">
<span v-if="row">{{ row.point == void 0 ? "0" : row.point }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<div v-if="row" class="ops" style="display: flex; justify-content: center">
<template v-if="selectedMember">
<a class="link-text" @click="callback(row)">选择</a>
<span class="op-split">|</span>
</template>
<a class="link-text" @click="detail(row)">查看</a>
<template v-if="!selectedMember">
<span class="op-split">|</span>
<a class="link-text" @click="enable(row)">启用</a>
<span class="op-split">|</span>
<a class="link-text" @click="editPerm(row)">编辑</a>
</template>
</div>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
size="small"
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</el-card>
<el-dialog v-model="descFlag" :title="descTitle" width="500px" destroy-on-close>
<el-form ref="formValidate" :model="formValidate" :rules="ruleValidate" label-width="80px">
<el-form-item label="头像">
<img :src="formValidate.face" class="face" />
<Button
type="text"
<el-button
type="primary"
link
class="upload"
@click="
() => {
this.picModelFlag = true;
this.$refs.ossManage.selectImage = true;
picModelFlag = true;
$refs.ossManage.selectImage = true;
}
"
>修改
</Button>
>修改</el-button>
<input type="file" style="display: none" id="file" />
</FormItem>
<FormItem label="会员名称" prop="name">
<Input
v-model="formValidate.username"
style="width: 200px"
disabled
/>
</FormItem>
<FormItem label="用户昵称" prop="name">
<Input v-model="formValidate.nickName" style="width: 200px" />
</FormItem>
<FormItem label="性别" prop="sex">
<RadioGroup
type="button"
button-style="solid"
v-model="formValidate.sex"
>
<Radio :label="1">
<span></span>
</Radio>
<Radio :label="0">
<span></span>
</Radio>
</RadioGroup>
</FormItem>
<FormItem label="修改密码" prop="password">
<Input
type="password"
style="width: 220px"
password
v-model="formValidate.newPassword"
/>
</FormItem>
<FormItem label="生日" prop="birthday">
<DatePicker
type="date"
format="yyyy-MM-dd"
</el-form-item>
<el-form-item label="会员名称" prop="name">
<el-input v-model="formValidate.username" style="width: 200px" disabled />
</el-form-item>
<el-form-item label="用户昵称" prop="name">
<el-input v-model="formValidate.nickName" style="width: 200px" />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="formValidate.sex">
<el-radio-button :value="1"></el-radio-button>
<el-radio-button :value="0"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="修改密码" prop="password">
<el-input v-model="formValidate.newPassword" type="password" show-password style="width: 220px" />
</el-form-item>
<el-form-item label="生日" prop="birthday">
<el-date-picker
v-model="formValidate.birthday"
type="date"
value-format="YYYY-MM-DD"
style="width: 220px"
></DatePicker>
</FormItem>
<FormItem label="所在地" prop="mail">
{{ formValidate.region || '暂无地址' }}
<Button style="margin-left: 10px;" @click="$refs.map.open()">选择</Button>
</FormItem>
</Form>
</Modal>
<Modal width="1200px" v-model="picModelFlag">
<ossManage @callback="callbackSelected" :isComponent="true" :initialize="picModelFlag" ref="ossManage" />
</Modal>
/>
</el-form-item>
<el-form-item label="所在地" prop="mail">
{{ formValidate.region || "暂无地址" }}
<el-button style="margin-left: 10px" @click="$refs.map.open()">选择</el-button>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="descFlag = false">取消</el-button>
<el-button type="primary" @click="handleSubmitModal">确定</el-button>
</template>
</el-dialog>
<el-dialog v-model="picModelFlag" width="1200px">
<ossManage
ref="ossManage"
@callback="callbackSelected"
:isComponent="true"
:initialize="picModelFlag"
/>
</el-dialog>
<multipleMap ref="map" @callback="selectedRegion" />
</div>
</template>
<script>
import * as API_Member from "@/api/member.js";
import ossManage from "@/views/sys/oss-manage/ossManage";
import multipleMap from "@/components/map/multiple-map";
export default {
name: "memberRecycle",
components: {
ossManage,
multipleMap
multipleMap,
},
data() {
return {
selectedMember: false, //是否是其他组件调用
descTitle: "", // modal标题
descFlag: false, //编辑查看框
openSearch: true, // 显示搜索
loading: true, // 表单加载状态
selectedMember: false,
descTitle: "",
descFlag: false,
openSearch: true,
loading: true,
searchForm: {
// 请求参数
pageNumber: 1,
pageSize: 20,
order: "desc",
@@ -177,198 +175,72 @@ export default {
mobile: "",
disabled: "CLOSE",
},
picModelFlag: false, // 选择图片
formValidate: {}, // 表单数据
ruleValidate: {}, //修改验证
columns: [
{
title: "会员名称",
align: "left",
key: "username",
tooltip: true,
},
{
title: "昵称",
align: "left",
key: "nickName",
tooltip: true,
},
{
title: "联系方式",
width: 130,
key: "mobile",
render: (h, params) => {
if (params.row.mobile == null) {
return h("div", [h("span", {}, "")]);
} else {
return h("div", [h("span", {}, params.row.mobile)]);
}
},
},
{
title: "注册时间",
key: "createTime",
width: 180,
},
{
title: "积分数量",
align: "left",
width: 120,
render: (h, params) => {
return h(
"div",
{},
params.row.point == void 0 ? "0" : params.row.point
);
},
},
{
title: "操作",
key: "action",
align: "center",
width: 200,
fixed: "right",
render: (h, params) => {
const linkStyle = {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
};
const sep = h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
);
const children = [];
if (this.selectedMember) {
children.push(
h(
"a",
{ style: linkStyle, on: { click: () => this.callback(params.row) } },
"选择"
)
);
children.push(sep);
}
children.push(
h(
"a",
{ style: linkStyle, on: { click: () => this.detail(params.row) } },
"查看"
)
);
if (!this.selectedMember) {
children.push(sep);
children.push(
h(
"a",
{ style: linkStyle, on: { click: () => this.enable(params.row) } },
"启用"
)
);
children.push(sep);
children.push(
h(
"a",
{ style: linkStyle, on: { click: () => this.editPerm(params.row) } },
"编辑"
)
);
}
return h(
"div",
{ class: "ops", style: { display: "flex", justifyContent: "center" } },
children
);
},
},
],
data: [], // 表单数据
total: 0, // 表单数据总数
picModelFlag: false,
formValidate: {},
ruleValidate: {},
data: [],
total: 0,
};
},
methods: {
// 回调给父级
callback(val) {
this.$emit("callback", val);
},
// 初始化数据
init() {
this.getData();
},
// 分页 修改页码
changePage(v) {
this.searchForm.pageNumber = v;
changePage() {
this.getData();
},
// 分页 修改页数
changePageSize(v) {
changePageSize() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getData();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getData();
},
//查看详情修改
editPerm(val) {
this.descTitle = `查看用户 ${val.username}`;
this.descFlag = true;
this.getMemberInfo(val.id);
},
/**
* 查询查看会员详情
*/
getMemberInfo(id) {
API_Member.getMemberInfoData(id).then((res) => {
if (res.result) {
this.$set(this, "formValidate", res.result);
this.formValidate = res.result;
}
});
},
//查询会员列表
getData() {
this.loading = true;
API_Member.getMemberListData(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.loading = false;
this.data = res.result.records;
this.total = res.result.total;
}
});
},
// 选中的图片
callbackSelected(val) {
this.picModelFlag = false;
this.formValidate.face = val.url;
},
// 选中的地址
selectedRegion(val) {
if(val.type === 'select'){
const paths = val.data.map(item => item.name).join(',')
const ids = val.data.map(item => item.id).join(',')
this.$set(this.formValidate,'region',paths)
this.$set(this.formValidate,'regionId',ids)
}
else{
this.$set(this.formValidate,'region',val.data.addr)
this.$set(this.formValidate,'regionId',val.data.addrId)
if (val.type === "select") {
const paths = val.data.map((item) => item.name).join(",");
const ids = val.data.map((item) => item.id).join(",");
this.formValidate.region = paths;
this.formValidate.regionId = ids;
} else {
this.formValidate.region = val.data.addr;
this.formValidate.regionId = val.data.addrId;
}
},
//详细
detail(row) {
this.$options.filters.customRouterPush({ name: "member-detail", query: { id: row.id } })
this.$filters.customRouterPush({ name: "member-detail", query: { id: row.id } });
},
//启用会员
enable(v) {
let params = {
memberIds: [v.id],
@@ -382,26 +254,19 @@ export default {
if (res.success) {
this.$Message.success("启用成功");
this.getData();
} else {
// this.$Message.error(res.message);
}
});
},
});
},
// 提交修改数据
handleSubmitModal() {
const { nickName, sex, username, face, newPassword, id ,regionId,region} =
this.formValidate;
const { nickName, sex, username, face, newPassword, id, regionId, region } = this.formValidate;
let time = new Date(this.formValidate.birthday);
let birthday =
time.getFullYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate();
let birthday = time.getFullYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate();
let submit = {
regionId:regionId,
regionId: regionId,
region: region,
nickName,
sex,
birthday,
face: face || "",
@@ -413,6 +278,7 @@ export default {
API_Member.updateMember(submit).then((res) => {
if (res.result) {
this.$Message.success("修改成功!");
this.descFlag = false;
this.init();
}
});

View File

@@ -1,98 +1,108 @@
<template>
<div>
<!--微信模板-->
<Modal v-model="wechatModal" width="530">
<p slot="header">
<Icon type="edit"></Icon>
<span>微信设置</span>
</p>
<div>
<Form ref="wechatFormData" :model="wechatFormData" label-position="left" :label-width="100">
<FormItem v-if="tab === 'WECHAT'" label="模板名称">
<Input v-model="wechatFormData.name" size="large" maxlength="9" disabled></Input>
</FormItem>
<FormItem v-if="tab === 'WECHAT'" label="头部信息" prop="first">
<Input v-model="wechatFormData.first" size="large" maxlength="50"></Input>
</FormItem>
<FormItem v-if="tab === 'WECHAT'" label="备注" prop="remark">
<Input class='textarea' :rows="5" :autosize="{maxRows:5,minRows: 5}" v-model="wechatFormData.remark"
type="textarea" maxlength="150"/>
</FormItem>
<FormItem label="是否开启" prop="enable">
<i-switch v-model="wechatFormData.enable" size="large">
<span slot="open">开启</span>
<span slot="close">关闭</span>
</i-switch>
</FormItem>
</Form>
<el-dialog v-model="wechatModal" title="微信设置" width="530px">
<el-form ref="wechatFormData" :model="wechatFormData" label-width="100px">
<el-form-item v-if="tab === 'WECHAT'" label="模板名称">
<el-input v-model="wechatFormData.name" maxlength="9" disabled />
</el-form-item>
<el-form-item v-if="tab === 'WECHAT'" label="头部信息" prop="first">
<el-input v-model="wechatFormData.first" maxlength="50" />
</el-form-item>
<el-form-item v-if="tab === 'WECHAT'" label="备注" prop="remark">
<el-input v-model="wechatFormData.remark" type="textarea" :rows="5" maxlength="150" />
</el-form-item>
<el-form-item label="是否开启" prop="enable">
<el-switch v-model="wechatFormData.enable" active-text="开启" inactive-text="关闭" />
</el-form-item>
</el-form>
<template #footer>
<el-button v-if="tab === 'WECHAT'" type="primary" @click="wechatFormDataEdit">保存</el-button>
<el-button v-else type="primary" @click="wechatMPFormDataEdit">保存</el-button>
</template>
</el-dialog>
</div>
<div slot="footer" style="text-align: right">
<Button v-if="tab === 'WECHAT'" type="primary" @click="wechatFormDataEdit">保存</Button>
<Button v-else type="primary" @click="wechatMPFormDataEdit">保存</Button>
</div>
</Modal>
<Card>
<Tabs @on-click="tabPaneChange" v-model="tab">
<TabPane label="微信消息" name="WECHAT">
<div class="search">
<Row class="operation mt_10">
<Button @click="weChatSync" type="primary">初始化微信消息</Button>
</Row>
<Table
:loading="loading"
border
:columns="weChatColumns"
:data="weChatData"
ref="weChatTable"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="weChatSearchForm.pageNumber"
<el-card>
<el-tabs v-model="tab" @tab-click="tabPaneChange">
<el-tab-pane label="微信消息" name="WECHAT">
<div class="search">
<div class="operation mt_10">
<el-button type="primary" @click="weChatSync">初始化微信消息</el-button>
</div>
<el-table v-loading="loading" border :data="weChatData" ref="weChatTable" style="width: 100%">
<el-table-column prop="code" label="模板编号" width="500" sortable />
<el-table-column label="是否开启" width="150" sortable>
<template #default="{ row }">
<span v-if="row">{{ row.enable ? "开启" : "关闭" }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="模板名称" width="200" sortable />
<el-table-column prop="createTime" label="创建时间" sortable />
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<template v-if="row">
<a class="link-text" @click="wechatSettingAlert(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="delWeChat(row)">删除</a>
</template>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="weChatSearchForm.pageNumber"
v-model:page-size="weChatSearchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="weChatTotal"
:page-size="weChatSearchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next"
size="small"
></Page>
</Row>
</div>
</TabPane>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</div>
</el-tab-pane>
<TabPane label="微信小程序订阅消息" name="WECHATMP">
<div class="search">
<Row class="operation mt_10">
<Button @click="weChatSync('mp')" type="primary">初始化微信小程序订阅消息</Button>
</Row>
<Table
:loading="loading"
border
:columns="weChatColumns"
:data="weChatMPData"
sortable="custom"
ref="weChatMPTable"
></Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="weChatMPSearchForm.pageNumber"
<el-tab-pane label="微信小程序订阅消息" name="WECHATMP">
<div class="search">
<div class="operation mt_10">
<el-button type="primary" @click="weChatSync('mp')">初始化微信小程序订阅消息</el-button>
</div>
<el-table v-loading="loading" border :data="weChatMPData" ref="weChatMPTable" style="width: 100%">
<el-table-column prop="code" label="模板编号" width="500" sortable />
<el-table-column label="是否开启" width="150" sortable>
<template #default="{ row }">
<span v-if="row">{{ row.enable ? "开启" : "关闭" }}</span>
</template>
</el-table-column>
<el-table-column prop="name" label="模板名称" width="200" sortable />
<el-table-column prop="createTime" label="创建时间" sortable />
<el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }">
<template v-if="row">
<a class="link-text" @click="wechatSettingAlert(row)">编辑</a>
<span class="op-split">|</span>
<a class="link-text" @click="delWeChat(row)">删除</a>
</template>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="weChatMPSearchForm.pageNumber"
v-model:page-size="weChatMPSearchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="weChatMPTotal"
:page-size="weChatMPSearchForm.pageSize"
@on-change="changePage"
@on-page-size-change="changePageSize"
:page-size-opts="[20, 50, 100]"
layout="total, sizes, prev, pager, next"
size="small"
></Page>
</Row>
</div>
</TabPane>
</Tabs>
</Card>
@current-change="changePage"
@size-change="changePageSize"
/>
</div>
</div>
</el-tab-pane>
</el-tabs>
</el-card>
</div>
</template>
<script>
@@ -101,257 +111,147 @@ import {
getWechatMessagePage,
editWechatMessageTemplate,
delWechatMessageTemplate,
wechatMPMessageSync,
getWechatMPMessagePage,
editWechatMPMessageTemplate,
delWechatMPMessageTemplate
delWechatMPMessageTemplate,
} from "@/api/setting";
export default {
title: "wechat-message-manage",
data() {
return {
wechatModal: false,// modal展示
wechatFormData: {}, // 微信数据
wechatMPFormData: {}, // 微信订阅消息
tab: "WECHAT", // tab栏分类
searchForm: { // 请求参数
type: "WECHAT"
},
loading: true, // 表单加载状态
id: '', // 模板id
//微信消息查询
weChatSearchForm: {
// 搜索框对应data对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
},
weChatMPSearchForm: {
// 搜索框对应data对象
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
},
weChatColumns: [
{
title: "模板编号",
key: "code",
width: 500,
sortable: true
},
{
title: "是否开启",
key: "enable",
sortable: true,
width: 150,
render: (h, params) => {
if (params.row.enable == true) {
return h('div', [
h('span', {}, '开启'),
]);
} else {
return h('div', [
h('span', {}, '关闭'),
]);
}
},
},
{
title: "模板名称",
key: "name",
width: 200,
sortable: true
},
{
title: "创建时间",
key: "createTime",
sortable: true,
sortType: "desc",
},
{
title: "操作",
key: "action",
width: 200,
align: "center",
fixed: "right",
render: (h, params) => {
return h("div", [
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.wechatSettingAlert(params.row);
}
}
},
"编辑"
),
h(
"span",
{ style: { margin: "0 8px", color: "#dcdee2" } },
"|"
),
h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none"
},
on: {
click: () => {
this.delWeChat(params.row);
}
}
},
"删除"
)
]);
}
}
],
weChatData: [], // 表单数据
weChatMPData: [], // 表单数据
weChatTotal: 0, // 表单数据总数
weChatMPTotal: 0, // 表单数据总数
wechatModal: false,
wechatFormData: {},
wechatMPFormData: {},
tab: "WECHAT",
searchForm: { type: "WECHAT" },
loading: true,
id: "",
weChatSearchForm: { pageNumber: 1, pageSize: 20 },
weChatMPSearchForm: { pageNumber: 1, pageSize: 20 },
weChatData: [],
weChatMPData: [],
weChatTotal: 0,
weChatMPTotal: 0,
};
},
methods: {
// 初始化数据
init() {
this.getDataList();
},
changePage(v) {
this.searchForm.type = this.tab;
this.getDataList();
if (this.tab === "WECHAT") {
this.weChatSearchForm.pageNumber = v;
this.getWechatMessagePage();
} else {
this.weChatMPSearchForm.pageNumber = v;
this.getWechatMPMessagePage();
}
},
changePageSize(v) {
this.searchForm.type = this.tab;
this.getDataList();
if (this.tab === "WECHAT") {
this.weChatSearchForm.pageSize = v;
this.getWechatMessagePage();
} else {
this.weChatMPSearchForm.pageSize = v;
this.getWechatMPMessagePage();
}
},
//微信弹出框
wechatSettingAlert(v) {
this.wechatFormData = v
this.id = v.id
this.wechatModal = true
this.wechatFormData = v;
this.id = v.id;
this.wechatModal = true;
},
//同步微信消息
weChatSync(mp) {
this.$Modal.confirm({
title: "提示",
// 记得确认修改此处
content: "确认要初始化微信小程序消息订阅?",
loading: true,
onOk: () => {
// 同步微信消息模板
if (mp === "mp") {
wechatMPMessageSync().then(res => {
wechatMPMessageSync().then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success('微信小程序消息订阅初始化');
this.$Message.success("微信小程序消息订阅初始化");
this.getWechatMPMessagePage();
}
});
} else {
// 同步微信消息模板
wechatMessageSync().then(res => {
wechatMessageSync().then((res) => {
this.$Modal.remove();
if (res.success) {
this.$Message.success('微信消息模板初始化成功');
this.$Message.success("微信消息模板初始化成功");
this.getWechatMessagePage();
}
});
}
},
});
},
wechatFormDataEdit() {
this.$refs.wechatFormData.validate((valid) => {
if (valid) {
if (!this.wechatFormData.updateTime) {
this.wechatFormData.updateTime = "";
}
editWechatMessageTemplate(this.id, this.wechatFormData).then((res) => {
if (res.message === "success") {
this.$Message.success("微信模板修改成功");
this.wechatModal = false;
this.getWechatMessagePage();
}
});
}
});
},
//微信设置保存
wechatFormDataEdit() {
this.$refs['wechatFormData'].validate((valid) => {
if (valid) {
if(!this.wechatFormData.updateTime){
this.wechatFormData.updateTime = ''
}
editWechatMessageTemplate(this.id, this.wechatFormData).then(res => {
if (res.message === 'success') {
this.$Message.success('微信模板修改成功');
this.wechatModal = false;
this.getWechatMessagePage();
}
});
}
})
},
wechatMPFormDataEdit() {
this.$refs['wechatFormData'].validate((valid) => {
this.$refs.wechatFormData.validate((valid) => {
if (valid) {
editWechatMPMessageTemplate(this.id, this.wechatMPFormData).then(res => {
if (res.message === 'success') {
this.$Message.success('微信消息订阅模板修改成功');
editWechatMPMessageTemplate(this.id, this.wechatMPFormData).then((res) => {
if (res.message === "success") {
this.$Message.success("微信消息订阅模板修改成功");
this.wechatModal = false;
this.getWechatMessagePage();
this.getWechatMPMessagePage();
}
});
}
})
});
},
//删除微信模消息
delWeChat(v) {
this.$Modal.confirm({
title: "提示",
content: "确定删除此模板?",
loading: true,
onOk: () => {
// 删除微信消息模板
if (this.tab === "WECHAT") {
delWechatMessageTemplate(v.id).then(res => {
delWechatMessageTemplate(v.id).then((res) => {
if (res.success) {
this.$Modal.remove();
this.$Message.success('微信模板删除成功');
this.getWechatMessagePage()
this.$Message.success("微信模板删除成功");
this.getWechatMessagePage();
}
});
} else {
delWechatMPMessageTemplate(v.id).then(res => {
delWechatMPMessageTemplate(v.id).then((res) => {
if (res.success) {
this.$Modal.remove();
this.$Message.success('微信消息订阅删除成功');
this.getWechatMessagePage()
this.$Message.success("微信消息订阅删除成功");
this.getWechatMPMessagePage();
}
});
}
}
},
});
},
selectDateRange(v) {
if (v) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
}
},
getDataList() {
this.loading = true;
getWechatMessagePage(this.searchWe).then(res => {
this.loading = false;
if (res.success) {
this.weChatData = res.result.records;
this.weChatTotal = res.result.total;
}
});
this.getWechatMessagePage();
},
//分页获取微信消息
getWechatMessagePage() {
getWechatMessagePage(this.weChatSearchForm).then(res => {
this.loading = true;
getWechatMessagePage(this.weChatSearchForm).then((res) => {
this.loading = false;
if (res.success) {
this.weChatData = res.result.records;
@@ -359,9 +259,9 @@ export default {
}
});
},
//分页获取微信小程序消息订阅
getWechatMPMessagePage() {
getWechatMPMessagePage(this.weChatMPSearchForm).then(res => {
this.loading = true;
getWechatMPMessagePage(this.weChatMPSearchForm).then((res) => {
this.loading = false;
if (res.success) {
this.weChatMPData = res.result.records;
@@ -369,20 +269,30 @@ export default {
}
});
},
//tab切换事件
tabPaneChange(v) {
tabPaneChange(tab) {
const v = tab.paneName || this.tab;
this.searchForm.type = v;
//如果是微信消息则走单独的接口
if (v === "WECHAT") {
this.getWechatMessagePage();
} else if (v === "WECHATMP") {
this.getWechatMPMessagePage();
}
}
},
},
mounted() {
this.init();
}
},
};
</script>
<style scoped>
.link-text {
color: #2d8cf0;
cursor: pointer;
text-decoration: none;
}
.op-split {
display: inline-block;
margin: 0 8px;
color: #dcdee2;
}
</style>

View File

@@ -1,518 +1,434 @@
<template>
<div class="search">
<Card class="points-statistics-card">
<Row type="flex" justify="space-around" align="middle" class="points-statistics">
<Col :xs="24" :sm="12" class="points-statistics-item">
<el-card class="points-statistics-card">
<el-row type="flex" justify="space-around" align="middle" class="points-statistics">
<el-col :xs="24" :sm="12" class="points-statistics-item">
<div class="points-statistics-title">已发放积分数</div>
<div class="points-statistics-subtitle">历史累计发放积分数</div>
<div class="points-statistics-value">{{ formatNumber(pointsStatistics.totalPoint) }}</div>
</Col>
<Col :xs="24" :sm="12" class="points-statistics-item">
</el-col>
<el-col :xs="24" :sm="12" class="points-statistics-item">
<div class="points-statistics-title">未使用积分数</div>
<div class="points-statistics-subtitle">会员账户未使用积分数</div>
<div class="points-statistics-value">{{ formatNumber(pointsStatistics.unUsedPoint) }}</div>
</Col>
</Row>
</Card>
</el-col>
</el-row>
</el-card>
<div class="point-tabs-wrap">
<Tabs v-model="activeTab" class="point-tabs">
<TabPane label="积分列表" name="pointList">
<Card class="point-content-card">
<Form
@keydown.enter.native="handleMemberSearch"
ref="memberSearchForm"
:model="memberSearchForm"
inline
:label-width="70"
@submit.native.prevent
class="search-form"
>
<Form-item label="客户名称" prop="nickName">
<Input
v-model="memberSearchForm.nickName"
placeholder="请输入客户名称"
clearable
style="width: 180px"
<el-tabs v-model="activeTab" class="point-tabs">
<el-tab-pane label="积分列表" name="pointList">
<el-card class="point-content-card">
<el-form
ref="memberSearchForm"
:model="memberSearchForm"
inline
label-width="70px"
class="search-form"
@keyup.enter="handleMemberSearch"
>
<el-form-item label="客户名称" prop="nickName">
<el-input
v-model="memberSearchForm.nickName"
placeholder="请输入客户名称"
clearable
style="width: 180px"
/>
</el-form-item>
<el-form-item label="客户账号" prop="username">
<el-input
v-model="memberSearchForm.username"
placeholder="请输入客户账号"
clearable
style="width: 180px"
/>
</el-form-item>
<el-form-item label="账号状态" prop="disabled">
<el-select
v-model="memberSearchForm.disabled"
clearable
placeholder="请选择账号状态"
style="width: 160px"
>
<el-option label="启用" value="OPEN" />
<el-option label="禁用" value="CLOSE" />
</el-select>
</el-form-item>
<el-form-item label="积分值">
<el-input-number
v-model="memberSearchForm.minPoint"
:min="0"
:precision="0"
placeholder="最小积分值"
style="width: 140px"
/>
<span class="point-range-separator">-</span>
<el-input-number
v-model="memberSearchForm.maxPoint"
:min="0"
:precision="0"
placeholder="最大积分值"
style="width: 140px"
/>
</el-form-item>
<el-form-item>
<el-button class="search-btn" type="primary" @click="handleMemberSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="point-content-card member-list-card">
<template #header>
<div class="card-title">用户列表</div>
</template>
<el-table
v-loading="memberLoading"
:data="memberData"
class="member-table"
style="width: 100%"
>
<el-table-column label="客户名称" width="180" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row">{{ row.nickName || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="客户账号" width="180" show-overflow-tooltip>
<template #default="{ row }">
<span v-if="row">{{ row.username || "-" }}</span>
</template>
</el-table-column>
<el-table-column label="账号状态" width="180">
<template #default="{ row }">
<el-tag v-if="row" :type="row.disabled === true ? 'success' : 'info'">
{{ row.disabled === true ? "启用" : "禁用" }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="积分余额" width="180">
<template #default="{ row }">
<span v-if="row">{{ row.point == null ? 0 : row.point }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<template #default="{ row }">
<a v-if="row" class="link-text" @click="detail(row)">详情</a>
</template>
</el-table-column>
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="memberSearchForm.pageNumber"
v-model:page-size="memberSearchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="memberTotal"
layout="total, sizes, prev, pager, next, jumper"
size="small"
@current-change="changeMemberPage"
@size-change="changeMemberPageSize"
/>
</Form-item>
<Form-item label="客户账号" prop="username">
<Input
v-model="memberSearchForm.username"
placeholder="请输入客户账号"
clearable
style="width: 180px"
</div>
</el-card>
</el-tab-pane>
<el-tab-pane label="积分增减记录" name="pointChangeRecord">
<el-card class="point-content-card">
<el-form
ref="searchForm"
:model="searchForm"
inline
label-width="70px"
class="search-form"
@keyup.enter="handleSearch"
>
<el-form-item label="会员名称" prop="username">
<el-input
v-model="searchForm.memberName"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</el-form-item>
<el-form-item>
<el-button class="search-btn" type="primary" @click="handleSearch">搜索</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="point-content-card">
<el-table
v-loading="loading"
border
:data="data"
ref="table"
class="mt_10 point-table"
style="width: 100%"
>
<el-table-column prop="memberName" label="会员名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="content" label="操作内容" min-width="200" show-overflow-tooltip />
<el-table-column prop="beforePoint" label="之前积分" width="200" />
<el-table-column label="变动积分" width="200">
<template #default="{ row }">
<template v-if="row">
<priceColorScheme
v-if="row.pointType === 'INCREASE'"
:value="row.variablePoint"
color="green"
unit="+"
/>
<priceColorScheme
v-else
:value="row.variablePoint"
:color="$mainColor"
unit="-"
/>
</template>
</template>
</el-table-column>
<el-table-column prop="point" label="当前积分" width="200" />
<el-table-column prop="createTime" label="操作时间" width="200" />
</el-table>
<div class="mt_10" style="display: flex; justify-content: flex-end">
<el-pagination
v-model:current-page="searchForm.pageNumber"
v-model:page-size="searchForm.pageSize"
:page-sizes="[20, 50, 100]"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
size="small"
@current-change="changePage"
@size-change="changePageSize"
/>
</Form-item>
<Form-item label="账号状态" prop="disabled">
<Select
v-model="memberSearchForm.disabled"
clearable
placeholder="请选择账号状态"
style="width: 160px"
>
<Option value="OPEN">启用</Option>
<Option value="CLOSE">禁用</Option>
</Select>
</Form-item>
<Form-item label="积分值">
<InputNumber
v-model="memberSearchForm.minPoint"
:min="0"
:precision="0"
placeholder="最小积分值"
style="width: 140px"
/>
<span class="point-range-separator">-</span>
<InputNumber
v-model="memberSearchForm.maxPoint"
:min="0"
:precision="0"
placeholder="最大积分值"
style="width: 140px"
/>
</Form-item>
<Button @click="handleMemberSearch" class="search-btn" type="primary" icon="ios-search">搜索</Button>
</Form>
</Card>
<Card class="point-content-card member-list-card">
<div slot="title" class="card-title">用户列表</div>
<Table
:loading="memberLoading"
:columns="memberColumns"
:data="memberData"
class="member-table"
>
</Table>
<Row type="flex" justify="end" class="mt_10">
<Page
:current="memberSearchForm.pageNumber"
:total="memberTotal"
:page-size="memberSearchForm.pageSize"
@on-change="changeMemberPage"
@on-page-size-change="changeMemberPageSize"
:page-size-opts="[20, 50, 100]"
size="small"
show-total
show-elevator
show-sizer
></Page>
</Row>
</Card>
</TabPane>
<TabPane label="积分增减记录" name="pointChangeRecord">
<Card class="point-content-card">
<Form
@keydown.enter.native="handleSearch"
ref="searchForm"
:model="searchForm"
inline
:label-width="70"
@submit.native.prevent
class="search-form"
>
<Form-item label="会员名称" prop="username">
<Input
type="text"
v-model="searchForm.memberName"
placeholder="请输入会员名称"
clearable
style="width: 240px"
/>
</Form-item>
<Button @click="handleSearch" class="search-btn" type="primary" icon="ios-search">搜索</Button>
</Form>
</Card>
<Card class="point-content-card">
<Table
:loading="loading"
border
:columns="columns"
:data="data"
ref="table"
class="mt_10 point-table"
>
</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>
</TabPane>
</Tabs>
</div>
</el-card>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script>
import * as API_Member from "@/api/member.js";
import * as API_Member from "@/api/member.js";
export default {
// 积分历史页面
name: "point",
data() {
return {
activeTab: "pointList",
loading: true, // 表单加载状态
memberLoading: false,
pointsStatistics: {
totalPoint: 0,
unUsedPoint: 0,
},
searchForm: { // 请求参数
pageNumber: 1,
pageSize: 20,
},
memberSearchForm: {
pageNumber: 1,
pageSize: 20,
nickName: "",
username: "",
disabled: "",
minPoint: null,
maxPoint: null,
},
columns: [
{
title: "会员名称",
key: "memberName",
minWidth: 120,
tooltip: true
},
{
title: "操作内容",
key: "content",
minWidth: 200,
tooltip: true
},
{
title: "之前积分",
key: "beforePoint",
width: 200,
},
{
title: "变动积分",
key: "variablePoint",
width: 200,
render: (h, params) => {
if (params.row.pointType == 'INCREASE') {
return h("priceColorScheme", {props:{value:params.row.variablePoint,color:'green',unit:"+"}} );
} else {
return h("priceColorScheme", {props:{value:params.row.variablePoint,color:this.$mainColor,unit:"-"}} );
}
}
},
{
title: "当前积分",
key: "point",
width: 200,
},
{
title: "操作时间",
key: "createTime",
width: 200
},
],
memberColumns: [
{
title: "客户名称",
key: "nickName",
width: 180,
tooltip: true,
render: (h, params) => {
return h("span", params.row.nickName || "-");
},
},
{
title: "客户账号",
key: "username",
width: 180,
tooltip: true,
render: (h, params) => {
return h("span", params.row.username || "-");
},
},
{
title: "账号状态",
key: "disabled",
width: 180,
render: (h, params) => {
const enabled = params.row.disabled === true;
return h(
"Tag",
{
props: {
color: enabled ? "success" : "default",
},
},
enabled ? "启用" : "禁用"
);
},
},
{
title: "积分余额",
key: "point",
width: 180,
render: (h, params) => {
const point = params.row.point == null ? 0 : params.row.point;
return h("span", point);
},
},
{
title: "操作",
key: "action",
width: 100,
align: "center",
render: (h, params) => {
return h(
"a",
{
style: {
color: "#2d8cf0",
cursor: "pointer",
textDecoration: "none",
},
on: {
click: () => {
this.detail(params.row);
},
},
},
"详情"
);
},
},
],
data: [], // 表单数据
memberData: [],
memberTotal: 0,
total: 0, // 表单数据总数
};
export default {
name: "point",
data() {
return {
activeTab: "pointList",
loading: true,
memberLoading: false,
pointsStatistics: {
totalPoint: 0,
unUsedPoint: 0,
},
searchForm: {
pageNumber: 1,
pageSize: 20,
},
memberSearchForm: {
pageNumber: 1,
pageSize: 20,
nickName: "",
username: "",
disabled: "",
minPoint: null,
maxPoint: null,
},
data: [],
memberData: [],
memberTotal: 0,
total: 0,
};
},
methods: {
callback(val) {
this.$emit("callback", val);
},
methods: {
// 回调给父级
callback(val) {
this.$emit("callback", val);
},
// 查看会员详情
detail(row) {
this.$options.filters.customRouterPush({ name: "member-detail", query: { id: row.id } });
},
// 初始化数据
init() {
this.getStatistics();
this.getMemberList();
this.getData();
},
getStatistics() {
API_Member.queryMemberPointsStatistics().then((res) => {
if (res && res.success && res.result) {
this.pointsStatistics = {
totalPoint: res.result.totalPoint || 0,
unUsedPoint: res.result.unUsedPoint || 0,
};
}
});
},
formatNumber(value) {
const numericValue = Number(value || 0);
if (!Number.isFinite(numericValue)) return "0";
return numericValue.toLocaleString();
},
// 分页 改变页码
changePage(v) {
this.searchForm.pageNumber = v;
this.getData();
},
// 分页 改变页数
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getData();
},
// 搜索
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getData();
},
handleMemberSearch() {
this.memberSearchForm.pageNumber = 1;
this.getMemberList();
},
changeMemberPage(v) {
this.memberSearchForm.pageNumber = v;
this.getMemberList();
},
changeMemberPageSize(v) {
this.memberSearchForm.pageNumber = 1;
this.memberSearchForm.pageSize = v;
this.getMemberList();
},
getMemberList() {
this.memberLoading = true;
const params = {
pageNumber: this.memberSearchForm.pageNumber,
pageSize: this.memberSearchForm.pageSize,
nickName: this.memberSearchForm.nickName || undefined,
username: this.memberSearchForm.username || undefined,
disabled: this.memberSearchForm.disabled || undefined,
minPoint: this.memberSearchForm.minPoint,
maxPoint: this.memberSearchForm.maxPoint,
};
API_Member.getMemberListData(params).then((res) => {
detail(row) {
this.$filters.customRouterPush({ name: "member-detail", query: { id: row.id } });
},
init() {
this.getStatistics();
this.getMemberList();
this.getData();
},
getStatistics() {
API_Member.queryMemberPointsStatistics().then((res) => {
if (res && res.success && res.result) {
this.pointsStatistics = {
totalPoint: res.result.totalPoint || 0,
unUsedPoint: res.result.unUsedPoint || 0,
};
}
});
},
formatNumber(value) {
const numericValue = Number(value || 0);
if (!Number.isFinite(numericValue)) return "0";
return numericValue.toLocaleString();
},
changePage(v) {
this.searchForm.pageNumber = v;
this.getData();
},
changePageSize(v) {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = v;
this.getData();
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 20;
this.getData();
},
handleMemberSearch() {
this.memberSearchForm.pageNumber = 1;
this.getMemberList();
},
changeMemberPage(v) {
this.memberSearchForm.pageNumber = v;
this.getMemberList();
},
changeMemberPageSize(v) {
this.memberSearchForm.pageNumber = 1;
this.memberSearchForm.pageSize = v;
this.getMemberList();
},
getMemberList() {
this.memberLoading = true;
const params = {
pageNumber: this.memberSearchForm.pageNumber,
pageSize: this.memberSearchForm.pageSize,
nickName: this.memberSearchForm.nickName || undefined,
username: this.memberSearchForm.username || undefined,
disabled: this.memberSearchForm.disabled || undefined,
minPoint: this.memberSearchForm.minPoint,
maxPoint: this.memberSearchForm.maxPoint,
};
API_Member.getMemberListData(params)
.then((res) => {
this.memberLoading = false;
if (res && res.success && res.result && res.result.records) {
this.memberData = res.result.records;
this.memberTotal = res.result.total;
}
}).catch(() => {
})
.catch(() => {
this.memberLoading = false;
});
},
//查新积分列表
getData() {
this.loading = true;
API_Member.getHistoryPointData(this.searchForm).then((res) => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
getData() {
this.loading = true;
API_Member.getHistoryPointData(this.searchForm).then((res) => {
this.loading = false;
},
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
},
mounted() {
this.init();
},
};
},
mounted() {
this.init();
},
};
</script>
<style lang="scss" scoped>
.points-statistics-card {
margin-bottom: 10px;
.points-statistics-card {
margin-bottom: 10px;
}
.point-tabs-wrap {
padding: 12px 16px 16px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(23, 35, 61, 0.04);
}
.point-tabs {
:deep(.el-tabs__header) {
margin-bottom: 16px;
}
.point-tabs-wrap {
padding: 12px 16px 16px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(23, 35, 61, 0.04);
:deep(.el-tabs__item) {
padding: 8px 18px;
color: #515a6e;
transition: all 0.2s ease;
}
.point-tabs {
::v-deep .ivu-tabs-bar {
margin-bottom: 16px;
border-bottom: 1px solid #f0f0f0;
}
::v-deep .ivu-tabs-nav .ivu-tabs-tab {
padding: 8px 18px;
color: #515a6e;
background: #fff;
transition: all 0.2s ease;
}
::v-deep .ivu-tabs-nav .ivu-tabs-tab-active {
color: #2d8cf0;
font-weight: 500;
}
::v-deep .ivu-tabs-ink-bar {
height: 2px;
border-radius: 2px;
}
}
.points-statistics {
width: 100%;
}
.points-statistics-item {
padding: 10px 0;
text-align: center;
}
.points-statistics-title {
font-size: 14px;
color: #17233d;
line-height: 20px;
}
.points-statistics-subtitle {
font-size: 12px;
color: #808695;
line-height: 18px;
margin-top: 4px;
}
.points-statistics-value {
font-size: 18px;
font-weight: 600;
color: #fa6419;
line-height: 26px;
margin-top: 8px;
}
.point-table {
::v-deep .ivu-table-border th,
::v-deep .ivu-table-border td {
border-right: 0;
}
}
.point-content-card {
margin-bottom: 12px;
::v-deep .ivu-card-body {
padding: 18px 20px;
}
}
.member-list-card {
::v-deep .ivu-card-head {
border-bottom: 1px solid #f5f5f5;
}
}
.card-title {
font-size: 14px;
:deep(.el-tabs__item.is-active) {
color: #409eff;
font-weight: 500;
color: #17233d;
}
.member-table {
::v-deep .ivu-table-header th {
background: #fafafa;
}
::v-deep .ivu-tag {
margin-right: 0;
}
:deep(.el-tabs__active-bar) {
height: 2px;
border-radius: 2px;
}
}
.point-range-separator {
display: inline-block;
margin: 0 8px;
color: #808695;
}
.points-statistics {
width: 100%;
}
.face {
width: 60px;
height: 60px;
border-radius: 50%;
.points-statistics-item {
padding: 10px 0;
text-align: center;
}
.points-statistics-title {
font-size: 14px;
color: #17233d;
line-height: 20px;
}
.points-statistics-subtitle {
font-size: 12px;
color: #808695;
line-height: 18px;
margin-top: 4px;
}
.points-statistics-value {
font-size: 18px;
font-weight: 600;
color: #fa6419;
line-height: 26px;
margin-top: 8px;
}
.point-content-card {
margin-bottom: 12px;
}
.member-list-card {
:deep(.el-card__header) {
border-bottom: 1px solid #f5f5f5;
}
}
.card-title {
font-size: 14px;
font-weight: 500;
color: #17233d;
}
.member-table {
:deep(.el-table__header th) {
background: #fafafa;
}
}
.point-range-separator {
display: inline-block;
margin: 0 8px;
color: #808695;
}
.link-text {
color: #409eff;
cursor: pointer;
text-decoration: none;
}
.face {
width: 60px;
height: 60px;
border-radius: 50%;
}
</style>