feat(integral-external): order/user list, integral log, wa selfBonus
- Fix ExternalIntegral order list (no double restPage); default 普通订单; UI columns for useIntegral and buyer uid/nickname/phone; enrich StoreOrderDetailResponse and admin query select. - External user list: UserResponse.selfBonus and fillWaSelfBonus from wa_users.id=uid. - Integral log: AdminIntegralSearchRequest nickName/phone; findAdminList filters and ordering; integralExternal API sends page/limit as query params. - Integral detail page: linkType Chinese mapping including selfbonus; update docs/newpage.md. - Dashboard grid menu entries for integral-external routes. Made-with: Cursor
This commit is contained in:
@@ -28,12 +28,14 @@ export function getExternalUserList(params) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户积分明细分页列表
|
||||
* 用户积分明细分页列表(page/limit 走 query,与 /admin/user/integral/list 一致)
|
||||
*/
|
||||
export function getExternalIntegralLog(data) {
|
||||
const { page, limit, ...body } = data;
|
||||
return requestNoAuth({
|
||||
url: 'external/integral/log/list',
|
||||
method: 'post',
|
||||
data,
|
||||
params: { page, limit },
|
||||
data: body,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,13 +79,6 @@ export default {
|
||||
url: '/order/index',
|
||||
perms: ['admin:order:list'],
|
||||
},
|
||||
{
|
||||
bgColor: '#A277FF',
|
||||
icon: 'iconduanxinpeizhi',
|
||||
title: '一号通',
|
||||
url: '/operation/onePass',
|
||||
perms: ['admin:pass:login'],
|
||||
},
|
||||
{
|
||||
bgColor: '#E8B600',
|
||||
icon: 'iconwenzhangguanli',
|
||||
@@ -107,6 +100,27 @@ export default {
|
||||
url: '/marketing/coupon/list',
|
||||
perms: ['admin:coupon:list'],
|
||||
},
|
||||
{
|
||||
bgColor: '#13c2c2',
|
||||
icon: 'icondingdanguanli',
|
||||
title: '积分订单',
|
||||
url: '/integral-external/order',
|
||||
alwaysShow: true,
|
||||
},
|
||||
{
|
||||
bgColor: '#722ed1',
|
||||
icon: 'iconhuiyuanguanli',
|
||||
title: '用户积分',
|
||||
url: '/integral-external/user',
|
||||
alwaysShow: true,
|
||||
},
|
||||
{
|
||||
bgColor: '#eb2f96',
|
||||
icon: 'iconfenxiaoguanli',
|
||||
title: '用户积分明细',
|
||||
url: '/integral-external/user/integral-detail',
|
||||
alwaysShow: true,
|
||||
},
|
||||
],
|
||||
statisticData: [
|
||||
{ title: '待发货订单', num: 0, path: '/order/index', perms: ['admin:order:list'] },
|
||||
@@ -128,7 +142,7 @@ export default {
|
||||
permList: function () {
|
||||
let arr = [];
|
||||
this.nav_list.forEach((item) => {
|
||||
if (this.checkPermi(item.perms)) {
|
||||
if (item.alwaysShow || this.checkPermi(item.perms)) {
|
||||
arr.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,13 +4,6 @@
|
||||
<div class="clearfix">
|
||||
<div class="container">
|
||||
<el-form size="small" label-width="100px">
|
||||
<el-form-item label="订单类型:">
|
||||
<el-radio-group v-model="tableFrom.type" type="button" class="mr20" size="small" @change="seachList">
|
||||
<el-radio-button v-for="(item, i) in typeOptions" :key="i" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单状态:">
|
||||
<el-radio-group v-model="tableFrom.status" type="button" @change="seachList">
|
||||
<el-radio-button label="all">全部</el-radio-button>
|
||||
@@ -78,7 +71,17 @@
|
||||
<span v-if="scope.row.isDel" style="color: #ed4014; display: block">用户已删除</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="orderType" label="订单类型" min-width="110" />
|
||||
<el-table-column prop="uid" label="用户ID" min-width="80" />
|
||||
<el-table-column prop="nickname" label="用户昵称" min-width="120" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.nickname || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="用户手机号" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.userPhone | phoneDesensitize }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="realName" label="收货人" min-width="100" />
|
||||
<el-table-column label="商品信息" min-width="280">
|
||||
<template slot-scope="scope">
|
||||
@@ -101,6 +104,11 @@
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="使用积分" min-width="90">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.useIntegral != null ? scope.row.useIntegral : '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="payPrice" label="实际支付" min-width="90">
|
||||
<template slot-scope="scope">
|
||||
<span>¥{{ scope.row.payPrice }}</span>
|
||||
@@ -149,7 +157,7 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
tableFrom: {
|
||||
type: '',
|
||||
type: 0,
|
||||
status: 'all',
|
||||
dateLimit: '',
|
||||
orderNo: '',
|
||||
@@ -168,14 +176,6 @@ export default {
|
||||
{ text: '本年', val: 'year' },
|
||||
],
|
||||
},
|
||||
typeOptions: [
|
||||
{ label: '全部', value: '' },
|
||||
{ label: '普通订单', value: '0' },
|
||||
{ label: '秒杀订单', value: '1' },
|
||||
{ label: '砍价订单', value: '2' },
|
||||
{ label: '拼团订单', value: '3' },
|
||||
{ label: '视频号订单', value: '4' },
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@@ -185,7 +185,6 @@ export default {
|
||||
getList() {
|
||||
this.listLoading = true;
|
||||
const params = { ...this.tableFrom };
|
||||
if (!params.type) delete params.type;
|
||||
if (!params.dateLimit) delete params.dateLimit;
|
||||
if (!params.orderNo) delete params.orderNo;
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<el-button size="small" icon="el-icon-arrow-left" @click="goBack">返回</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 用户概览卡片 -->
|
||||
<el-card class="box-card overview-card">
|
||||
<!-- 用户概览卡片(从用户列表进入时展示;无 uid 时为全部明细模式) -->
|
||||
<el-card v-if="uid" class="box-card overview-card">
|
||||
<div class="overview-header">
|
||||
<span class="user-title">
|
||||
{{ userInfo.nickname || ('UID: ' + uid) }}
|
||||
@@ -30,6 +30,12 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card v-else class="box-card overview-card overview-card--all">
|
||||
<div class="overview-header">
|
||||
<span class="user-title">全部积分明细</span>
|
||||
<span class="hint-text">未指定用户时将展示全部记录,支持下方条件筛选</span>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 积分明细列表 -->
|
||||
<el-card class="box-card mt10">
|
||||
@@ -37,8 +43,41 @@
|
||||
<span>积分明细</span>
|
||||
</div>
|
||||
<div class="container mb10">
|
||||
<el-form inline size="small" :model="searchForm" label-width="80px">
|
||||
<el-form inline size="small" :model="searchForm" label-width="96px">
|
||||
<el-row>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="用户ID:">
|
||||
<el-input
|
||||
v-model="searchForm.uidStr"
|
||||
placeholder="可选,留空查全部"
|
||||
clearable
|
||||
class="filter-input"
|
||||
@keyup.enter.native="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="用户名称:">
|
||||
<el-input
|
||||
v-model="searchForm.nickName"
|
||||
placeholder="昵称模糊匹配"
|
||||
clearable
|
||||
class="filter-input"
|
||||
@keyup.enter.native="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="手机号:">
|
||||
<el-input
|
||||
v-model="searchForm.phone"
|
||||
placeholder="手机号模糊匹配"
|
||||
clearable
|
||||
class="filter-input"
|
||||
@keyup.enter.native="handleSearch"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6">
|
||||
<el-form-item label="时间选择:">
|
||||
<el-date-picker
|
||||
@@ -150,7 +189,9 @@ export default {
|
||||
total: 0,
|
||||
},
|
||||
searchForm: {
|
||||
uid: null,
|
||||
uidStr: '',
|
||||
nickName: '',
|
||||
phone: '',
|
||||
dateLimit: '',
|
||||
page: 1,
|
||||
limit: 15,
|
||||
@@ -159,26 +200,38 @@ export default {
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 从路由 query 中注入 uid 及概览信息
|
||||
const { uid, nickname, integral, selfBonus } = this.$route.query;
|
||||
this.uid = uid ? Number(uid) : null;
|
||||
this.userInfo.nickname = nickname || '';
|
||||
this.userInfo.integral = integral !== '' && integral != null ? Number(integral) : null;
|
||||
this.userInfo.selfBonus = selfBonus !== '' && selfBonus != null ? Number(selfBonus) : null;
|
||||
this.searchForm.uid = this.uid;
|
||||
if (this.uid) {
|
||||
this.searchForm.uidStr = String(this.uid);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.uid) {
|
||||
this.getList();
|
||||
} else {
|
||||
this.$message.error('缺少用户ID,无法加载积分明细');
|
||||
}
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listLoading = true;
|
||||
const params = { ...this.searchForm };
|
||||
if (!params.dateLimit) delete params.dateLimit;
|
||||
const uidParsed = this.searchForm.uidStr === '' || this.searchForm.uidStr == null
|
||||
? null
|
||||
: parseInt(String(this.searchForm.uidStr).trim(), 10);
|
||||
const uid = Number.isNaN(uidParsed) ? null : uidParsed;
|
||||
const params = {
|
||||
page: this.searchForm.page,
|
||||
limit: this.searchForm.limit,
|
||||
uid,
|
||||
nickName: this.searchForm.nickName ? this.searchForm.nickName.trim() : undefined,
|
||||
phone: this.searchForm.phone ? this.searchForm.phone.trim() : undefined,
|
||||
dateLimit: this.searchForm.dateLimit || undefined,
|
||||
};
|
||||
Object.keys(params).forEach((k) => {
|
||||
if (params[k] === undefined || params[k] === null || params[k] === '') {
|
||||
delete params[k];
|
||||
}
|
||||
});
|
||||
|
||||
getExternalIntegralLog(params)
|
||||
.then((res) => {
|
||||
@@ -195,9 +248,14 @@ export default {
|
||||
this.getList();
|
||||
},
|
||||
handleReset() {
|
||||
this.searchForm.uidStr = '';
|
||||
this.searchForm.nickName = '';
|
||||
this.searchForm.phone = '';
|
||||
this.searchForm.dateLimit = '';
|
||||
this.searchForm.page = 1;
|
||||
this.timeVal = [];
|
||||
this.uid = null;
|
||||
this.userInfo = { nickname: '', integral: null, selfBonus: null };
|
||||
this.getList();
|
||||
},
|
||||
onchangeTime(e) {
|
||||
@@ -217,8 +275,17 @@ export default {
|
||||
this.$router.push('/integral-external/user');
|
||||
},
|
||||
linkTypeFilter(type) {
|
||||
const typeMap = { order: '订单', sign: '签到', system: '系统' };
|
||||
return typeMap[type] || type || '-';
|
||||
if (type == null || type === '') return '-';
|
||||
const raw = String(type).trim();
|
||||
if (!raw) return '-';
|
||||
const key = raw.toLowerCase();
|
||||
const typeMap = {
|
||||
order: '订单',
|
||||
sign: '签到',
|
||||
system: '系统',
|
||||
selfbonus: '个人奖金',
|
||||
};
|
||||
return typeMap[key] || `其他(${raw})`;
|
||||
},
|
||||
statusFilter(status) {
|
||||
const statusMap = { 1: '订单创建', 2: '冻结期', 3: '完成', 4: '失效' };
|
||||
@@ -288,4 +355,14 @@ export default {
|
||||
.block {
|
||||
text-align: right;
|
||||
}
|
||||
.filter-input {
|
||||
width: 180px;
|
||||
}
|
||||
.overview-card--all .hint-text {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
font-size: 13px;
|
||||
color: #909399;
|
||||
font-weight: normal;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user