627 lines
23 KiB
Markdown
627 lines
23 KiB
Markdown
|
|
# 积分模块新增页面 — Coding Plan
|
|||
|
|
|
|||
|
|
> 版本:v1.0
|
|||
|
|
> 日期:2026-03-30
|
|||
|
|
> 范围:管理后台(backend-adminend)新增积分订单、用户积分、用户积分明细三个独立页面
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 需求概述
|
|||
|
|
|
|||
|
|
在管理后台中新增三个独立页面,用于积分业务的外部查看与运营。所有页面需跳过用户登录验证,按后端 API 最小修改原则,尽量复用现有后端接口。
|
|||
|
|
|
|||
|
|
| 序号 | 页面 | 参考原页面 | 说明 |
|
|||
|
|
|------|------|-----------|------|
|
|||
|
|
| 1 | 积分订单 | `/order/index` | 新建独立页面,展示积分相关订单 |
|
|||
|
|
| 2 | 用户积分 | `/user/index` | 新建独立页面,增加 `wa_users` 相关字段 |
|
|||
|
|
| 3 | 用户积分明细 | 用户管理 → 账户详情 → 积分明细 | 子页面,复用 `/admin/user/integral/list` 接口 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 技术架构分析
|
|||
|
|
|
|||
|
|
### 2.1 技术栈
|
|||
|
|
|
|||
|
|
管理后台前端基于 Vue 2 + Vue CLI + Element UI + Vue Router (history mode) + Vuex + Axios。
|
|||
|
|
|
|||
|
|
### 2.2 现有认证机制
|
|||
|
|
|
|||
|
|
认证逻辑位于 `src/permission.js`,通过 `router.beforeEach` 全局守卫实现。未登录时除白名单路由外,一律重定向至 `/login`。
|
|||
|
|
|
|||
|
|
白名单当前值:`['/login', '/auth-redirect']`
|
|||
|
|
|
|||
|
|
请求拦截器(`src/utils/request.js`)会在 header 中附加 `Authori-zation` token,后端返回 401 时自动跳转登录页。
|
|||
|
|
|
|||
|
|
### 2.3 关键参考文件
|
|||
|
|
|
|||
|
|
| 文件 | 说明 |
|
|||
|
|
|------|------|
|
|||
|
|
| `src/views/order/index.vue` | 订单列表页,约 40k 行,含筛选/表格/分页/操作 |
|
|||
|
|
| `src/views/user/list/index.vue` | 用户管理页,含多条件筛选、用户详情弹窗 |
|
|||
|
|
| `src/views/user/integral/index.vue` | 积分日志页(242 行),表格 + 搜索 + 分页 |
|
|||
|
|
| `src/api/integral.js` | 积分接口:`integralListApi` → POST `/admin/user/integral/list` |
|
|||
|
|
| `src/api/user.js` | 用户接口:`userListApi` → GET `/admin/user/list` |
|
|||
|
|
| `src/router/modules/order.js` | 订单路由定义 |
|
|||
|
|
| `src/router/modules/user.js` | 用户路由定义 |
|
|||
|
|
| `src/router/index.js` | 主路由,含 `constantRoutes` 和白名单 |
|
|||
|
|
| `src/permission.js` | 全局路由守卫(登录校验) |
|
|||
|
|
| `src/utils/request.js` | Axios 封装,token 注入 & 401 拦截 |
|
|||
|
|
|
|||
|
|
### 2.4 wa_users 表字段(需要在用户积分页展示)
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| `id` | int | 主键 |
|
|||
|
|
| `username` | string | 用户名 |
|
|||
|
|
| `nickname` | string | 昵称 |
|
|||
|
|
| `mobile` | string | 手机号 |
|
|||
|
|
| `money` | BigDecimal | 账户余额 |
|
|||
|
|
| `selfBonus` | BigDecimal | 个人奖金 |
|
|||
|
|
| `shareBonus` | BigDecimal | 分享奖金 |
|
|||
|
|
| `score` | BigDecimal | 积分 |
|
|||
|
|
| `level` | int | 等级 |
|
|||
|
|
| `status` | int | 状态(0=禁用, 1=启用) |
|
|||
|
|
| `isVip` | int | VIP(0=否, 1=是) |
|
|||
|
|
| `isResell` | int | 可转卖(0=否, 1=是) |
|
|||
|
|
| `joinTime` | timestamp | 注册时间 |
|
|||
|
|
| `lastTime` | timestamp | 最后登录 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 整体方案设计
|
|||
|
|
|
|||
|
|
### 3.1 目录结构规划
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
src/
|
|||
|
|
├── views/
|
|||
|
|
│ └── integral-external/ # 新增:积分外部页面目录
|
|||
|
|
│ ├── order/
|
|||
|
|
│ │ └── index.vue # 积分订单页面
|
|||
|
|
│ ├── user/
|
|||
|
|
│ │ └── index.vue # 用户积分页面
|
|||
|
|
│ └── user-integral-detail/
|
|||
|
|
│ └── index.vue # 用户积分明细子页面
|
|||
|
|
├── api/
|
|||
|
|
│ └── integralExternal.js # 新增:积分外部页面 API 集合
|
|||
|
|
├── router/
|
|||
|
|
│ └── modules/
|
|||
|
|
│ └── integralExternal.js # 新增:积分外部路由模块
|
|||
|
|
└── layout/
|
|||
|
|
└── EmptyLayout.vue # 新增:空白布局(无侧边栏/顶栏)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 跳过登录验证方案
|
|||
|
|
|
|||
|
|
采用**多层级免登录**策略,确保页面完全绕过认证:
|
|||
|
|
|
|||
|
|
**第一层:路由白名单**
|
|||
|
|
|
|||
|
|
在 `src/permission.js` 的 `whiteList` 中添加新页面路径前缀:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const whiteList = ['/login', '/auth-redirect', '/integral-external'];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
同时修改白名单匹配逻辑,从精确匹配改为前缀匹配:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
// 修改前
|
|||
|
|
if (whiteList.indexOf(to.path) !== -1)
|
|||
|
|
|
|||
|
|
// 修改后
|
|||
|
|
if (whiteList.some(path => to.path.startsWith(path)))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**第二层:无 token 请求支持**
|
|||
|
|
|
|||
|
|
新建一个不注入 token、不拦截 401 的 Axios 实例 `requestNoAuth`,供外部页面 API 使用:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
// src/utils/requestNoAuth.js
|
|||
|
|
import axios from 'axios';
|
|||
|
|
import { Message } from 'element-ui';
|
|||
|
|
import SettingMer from '@/utils/settingMer';
|
|||
|
|
|
|||
|
|
const service = axios.create({
|
|||
|
|
baseURL: SettingMer.apiBaseURL,
|
|||
|
|
timeout: 60000,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 不注入 token,不拦截 401 跳转
|
|||
|
|
service.interceptors.response.use(
|
|||
|
|
(response) => {
|
|||
|
|
const res = response.data;
|
|||
|
|
if (res.code !== 0 && res.code !== 200) {
|
|||
|
|
Message({ message: res.msg || '请求失败', type: 'error' });
|
|||
|
|
return Promise.reject(new Error(res.msg || '请求失败'));
|
|||
|
|
}
|
|||
|
|
return res.data;
|
|||
|
|
},
|
|||
|
|
(error) => {
|
|||
|
|
Message({ message: '网络请求失败', type: 'error' });
|
|||
|
|
return Promise.reject(error);
|
|||
|
|
},
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
export default service;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**第三层:空白布局**
|
|||
|
|
|
|||
|
|
新建 `EmptyLayout.vue`,不包含侧边栏、顶栏和权限组件,作为外部页面的容器:
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<div class="integral-external-layout">
|
|||
|
|
<router-view />
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 各页面详细设计
|
|||
|
|
|
|||
|
|
### 4.1 积分订单页面
|
|||
|
|
|
|||
|
|
**路由**:`/integral-external/order`
|
|||
|
|
**参考**:`src/views/order/index.vue`
|
|||
|
|
|
|||
|
|
#### 功能要点
|
|||
|
|
|
|||
|
|
从原订单页面中提取积分订单相关的核心功能,去除权限校验(`v-hasPermi`)和管理操作(编辑、发货、退款等),保留只读展示。
|
|||
|
|
|
|||
|
|
#### 筛选条件
|
|||
|
|
|
|||
|
|
| 筛选项 | 类型 | 说明 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| 订单状态 | RadioGroup | 全部/未支付/未发货/待收货/交易完成 等 |
|
|||
|
|
| 时间选择 | DateRangePicker | 快捷选项 + 自定义范围 |
|
|||
|
|
| 订单号 | Input | 精确搜索 |
|
|||
|
|
|
|||
|
|
#### 表格列
|
|||
|
|
|
|||
|
|
| 列 | 字段 | 宽度 |
|
|||
|
|
|----|------|------|
|
|||
|
|
| 订单号 | `orderId` | 210 |
|
|||
|
|
| 订单类型 | `orderType` | 110 |
|
|||
|
|
| 收货人 | `realName` | 100 |
|
|||
|
|
| 商品信息 | `productList` | 400 |
|
|||
|
|
| 支付金额 | `payPrice` | 100 |
|
|||
|
|
| 支付方式 | `payType` | 100 |
|
|||
|
|
| 订单状态 | `status` | 100 |
|
|||
|
|
| 创建时间 | `createTime` | 150 |
|
|||
|
|
|
|||
|
|
#### API 复用
|
|||
|
|
|
|||
|
|
直接复用现有订单列表接口。需确认后端是否允许无 token 调用,若不允许,需后端新增一个免认证的订单查询接口(或在已有接口上增加免认证标注)。
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
// src/api/integralExternal.js
|
|||
|
|
export function getIntegralOrderList(params) {
|
|||
|
|
return requestNoAuth({
|
|||
|
|
url: '/admin/order/list', // 复用原接口或后端新增免认证接口
|
|||
|
|
method: 'get',
|
|||
|
|
params,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 实现步骤
|
|||
|
|
|
|||
|
|
1. 复制 `order/index.vue` 为基础模板
|
|||
|
|
2. 删除所有 `v-hasPermi` 权限指令
|
|||
|
|
3. 删除操作列(编辑价格、发货、退款等按钮)
|
|||
|
|
4. 删除导出功能
|
|||
|
|
5. 将 API 调用替换为 `requestNoAuth` 版本
|
|||
|
|
6. 简化订单类型筛选,只保留积分相关类型
|
|||
|
|
7. 去除 Vuex store 依赖
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4.2 用户积分页面
|
|||
|
|
|
|||
|
|
**路由**:`/integral-external/user`
|
|||
|
|
**参考**:`src/views/user/list/index.vue`
|
|||
|
|
|
|||
|
|
#### 功能要点
|
|||
|
|
|
|||
|
|
基于用户列表页精简,增加 `wa_users` 表的积分/奖金相关字段展示,提供积分明细跳转入口。
|
|||
|
|
|
|||
|
|
#### 筛选条件
|
|||
|
|
|
|||
|
|
| 筛选项 | 类型 | 说明 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| 用户搜索 | Input | 姓名/手机号/用户名 |
|
|||
|
|
| 时间选择 | DateRangePicker | 注册时间范围 |
|
|||
|
|
|
|||
|
|
#### 表格列
|
|||
|
|
|
|||
|
|
| 列 | 字段 | 来源 | 说明 |
|
|||
|
|
|----|------|------|------|
|
|||
|
|
| 用户ID | `uid` | CRMEB | 系统用户ID |
|
|||
|
|
| 用户昵称 | `nickname` | CRMEB | — |
|
|||
|
|
| 手机号 | `phone` | CRMEB | — |
|
|||
|
|
| 系统积分 | `integral` | CRMEB | CRMEB 系统积分 |
|
|||
|
|
| WA用户名 | `wa_username` | wa_users | WA系统用户名 |
|
|||
|
|
| 账户余额 | `wa_money` | wa_users | WA账户余额 |
|
|||
|
|
| 个人奖金 | `wa_selfBonus` | wa_users | 可提现奖金 |
|
|||
|
|
| 分享奖金 | `wa_shareBonus` | wa_users | 推荐奖金 |
|
|||
|
|
| WA积分 | `wa_score` | wa_users | WA系统积分 |
|
|||
|
|
| 用户等级 | `wa_level` | wa_users | — |
|
|||
|
|
| 状态 | `wa_status` | wa_users | 启用/禁用 |
|
|||
|
|
| 注册时间 | `createTime` | CRMEB | — |
|
|||
|
|
| 操作 | — | — | 查看积分明细 |
|
|||
|
|
|
|||
|
|
#### API 方案
|
|||
|
|
|
|||
|
|
**方案 A(推荐 — 最小后端修改)**:前端分别调用用户列表接口和 WA 用户信息接口,在前端做数据合并。
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
// 复用原用户列表
|
|||
|
|
export function getUserListNoAuth(params) {
|
|||
|
|
return requestNoAuth({
|
|||
|
|
url: '/admin/user/list',
|
|||
|
|
method: 'get',
|
|||
|
|
params,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 复用前端 WA 用户信息接口(需确认是否免认证)
|
|||
|
|
export function getWaUserInfo(userId) {
|
|||
|
|
return requestNoAuth({
|
|||
|
|
url: '/api/front/wa/user/info',
|
|||
|
|
method: 'post',
|
|||
|
|
data: { userId },
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**方案 B(若后端配合)**:后端新增一个聚合接口,一次性返回 CRMEB 用户 + wa_users 的合并数据。
|
|||
|
|
|
|||
|
|
#### 操作列
|
|||
|
|
|
|||
|
|
"查看积分明细" 按钮,点击后跳转至用户积分明细子页面,携带 `uid` 参数:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
this.$router.push({
|
|||
|
|
path: '/integral-external/user/integral-detail',
|
|||
|
|
query: { uid: row.uid },
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 实现步骤
|
|||
|
|
|
|||
|
|
1. 以 `user/list/index.vue` 为参考创建精简版页面
|
|||
|
|
2. 删除所有权限指令、分组/标签/等级筛选、操作按钮(编辑、设为分销员等)
|
|||
|
|
3. 删除 Tab 切换(全部/有效/无效用户)
|
|||
|
|
4. 在表格中增加 wa_users 字段列
|
|||
|
|
5. 实现前端数据合并逻辑(逐行匹配或批量查询)
|
|||
|
|
6. 添加"查看积分明细"操作按钮
|
|||
|
|
7. 将所有 API 替换为 `requestNoAuth` 版本
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4.3 用户积分明细子页面
|
|||
|
|
|
|||
|
|
**路由**:`/integral-external/user/integral-detail`
|
|||
|
|
**参考**:`src/views/user/integral/index.vue`(242 行)
|
|||
|
|
**后端 API**:POST `/admin/user/integral/list`(复用)
|
|||
|
|
|
|||
|
|
#### 功能要点
|
|||
|
|
|
|||
|
|
该页面完整复用原积分日志页的展示逻辑,通过 URL query 参数 `uid` 锁定指定用户,隐藏"用户搜索"字段。
|
|||
|
|
|
|||
|
|
#### 筛选条件
|
|||
|
|
|
|||
|
|
| 筛选项 | 类型 | 说明 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| 用户ID | 隐藏字段 | 从 URL query `uid` 自动获取 |
|
|||
|
|
| 时间选择 | DateRangePicker | 日期范围 |
|
|||
|
|
|
|||
|
|
#### 表格列(完全复用原页面)
|
|||
|
|
|
|||
|
|
| 列 | 字段 | 说明 |
|
|||
|
|
|----|------|------|
|
|||
|
|
| ID | `id` | 记录ID |
|
|||
|
|
| 用户ID | `uid` | — |
|
|||
|
|
| 用户昵称 | `nickName` | — |
|
|||
|
|
| 标题 | `title` | 积分变动标题 |
|
|||
|
|
| 积分变动 | `integral` | +/- 显示 |
|
|||
|
|
| 剩余积分 | `balance` | 变动后余额 |
|
|||
|
|
| 类型 | `type` | 增加(1)/扣减(2) |
|
|||
|
|
| 关联类型 | `linkType` | 订单/签到/系统 |
|
|||
|
|
| 状态 | `status` | 订单创建/冻结期/完成/失效 |
|
|||
|
|
| 备注 | `mark` | — |
|
|||
|
|
| 创建时间 | `createTime` | — |
|
|||
|
|
|
|||
|
|
#### API 复用
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
export function getIntegralLogNoAuth(data) {
|
|||
|
|
return requestNoAuth({
|
|||
|
|
url: '/admin/user/integral/list', // 直接复用原接口
|
|||
|
|
method: 'post',
|
|||
|
|
data,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 页面头部信息
|
|||
|
|
|
|||
|
|
在表格上方展示当前用户的积分概览卡片:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌──────────────────────────────────────┐
|
|||
|
|
│ 用户:张三 (UID: 1001) │
|
|||
|
|
│ 积分:1,200 个人奖金:350 │
|
|||
|
|
│ [← 返回用户积分列表] │
|
|||
|
|
└──────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> **字段说明**:积分取自 `eb_user` 表的 `integral` 字段(`BigDecimal`,用户剩余积分);个人奖金取自 `wa_users` 表的 `selfBonus` 字段。
|
|||
|
|
|
|||
|
|
#### 实现步骤
|
|||
|
|
|
|||
|
|
1. 复制 `user/integral/index.vue` 作为基础
|
|||
|
|
2. 从 URL query 中读取 `uid`,自动注入搜索参数
|
|||
|
|
3. 隐藏"用户搜索"和"用户ID"输入框(已通过 query 锁定)
|
|||
|
|
4. 添加顶部用户信息概览卡片
|
|||
|
|
5. 添加"返回"按钮
|
|||
|
|
6. 替换 API 为 `requestNoAuth` 版本
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 路由配置
|
|||
|
|
|
|||
|
|
### 5.1 新增路由模块
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
// src/router/modules/integralExternal.js
|
|||
|
|
const EmptyLayout = () => import('@/layout/EmptyLayout');
|
|||
|
|
|
|||
|
|
const integralExternalRouter = {
|
|||
|
|
path: '/integral-external',
|
|||
|
|
component: EmptyLayout,
|
|||
|
|
redirect: '/integral-external/order',
|
|||
|
|
hidden: true, // 不在侧边栏显示
|
|||
|
|
children: [
|
|||
|
|
{
|
|||
|
|
path: 'order',
|
|||
|
|
component: () => import('@/views/integral-external/order/index'),
|
|||
|
|
name: 'IntegralExternalOrder',
|
|||
|
|
meta: { title: '积分订单' },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: 'user',
|
|||
|
|
component: () => import('@/views/integral-external/user/index'),
|
|||
|
|
name: 'IntegralExternalUser',
|
|||
|
|
meta: { title: '用户积分' },
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: 'user/integral-detail',
|
|||
|
|
component: () => import('@/views/integral-external/user-integral-detail/index'),
|
|||
|
|
name: 'IntegralExternalUserDetail',
|
|||
|
|
meta: { title: '用户积分明细' },
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
export default integralExternalRouter;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 注册路由
|
|||
|
|
|
|||
|
|
在 `src/router/index.js` 中将新模块加入 `constantRoutes`:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
import integralExternalRouter from './modules/integralExternal';
|
|||
|
|
|
|||
|
|
export const constantRoutes = [
|
|||
|
|
integralExternalRouter, // 积分外部页面(免登录)
|
|||
|
|
storeRouter,
|
|||
|
|
orderRouter,
|
|||
|
|
// ...其余路由
|
|||
|
|
];
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.3 修改权限守卫
|
|||
|
|
|
|||
|
|
在 `src/permission.js` 中扩展白名单:
|
|||
|
|
|
|||
|
|
```js
|
|||
|
|
const whiteList = ['/login', '/auth-redirect', '/integral-external'];
|
|||
|
|
|
|||
|
|
// 匹配逻辑改为前缀匹配
|
|||
|
|
if (whiteList.some(path => to.path.startsWith(path))) {
|
|||
|
|
next();
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 后端 API 影响评估
|
|||
|
|
|
|||
|
|
### 6.1 可直接复用的接口
|
|||
|
|
|
|||
|
|
| 接口 | Method | 免认证现状 | 所需改动 |
|
|||
|
|
|------|--------|-----------|---------|
|
|||
|
|
| `/admin/user/integral/list` | POST | 需认证 | 需后端为外部调用新增免认证入口,或前端伪造 token |
|
|||
|
|
| `/admin/user/list` | GET | 需认证 | 同上 |
|
|||
|
|
| `/admin/order/list` | GET | 需认证 | 同上 |
|
|||
|
|
|
|||
|
|
### 6.2 推荐的后端最小改动方案
|
|||
|
|
|
|||
|
|
按照"最小修改原则",建议后端在现有 Controller 基础上新增一套免认证的映射路径,内部直接调用相同的 Service 方法:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
新路径 → 复用的 Service 方法
|
|||
|
|
/api/external/integral/order/list → OrderService.list()
|
|||
|
|
/api/external/integral/user/list → UserService.list()(补充 wa_users 字段)
|
|||
|
|
/api/external/integral/log/list → IntegralService.list()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
只需新建一个 `ExternalIntegralController`,加 `@RestController` 免认证注解,约 50-80 行代码。
|
|||
|
|
|
|||
|
|
### 6.3 wa_users 字段集成
|
|||
|
|
|
|||
|
|
**方案 A**:后端在用户列表接口返回中直接 JOIN wa_users 表,新增字段返回。
|
|||
|
|
**方案 B**:前端先拿用户列表,再批量查 wa_users 信息,前端做合并。
|
|||
|
|
|
|||
|
|
推荐方案 A(后端改动更少,前端实现更简单)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 开发任务清单
|
|||
|
|
|
|||
|
|
### Phase 1:基础设施(预计 0.5 天)
|
|||
|
|
|
|||
|
|
| # | 任务 | 文件 |
|
|||
|
|
|---|------|------|
|
|||
|
|
| 1.1 | 创建 `EmptyLayout.vue` 空白布局 | `src/layout/EmptyLayout.vue` |
|
|||
|
|
| 1.2 | 创建 `requestNoAuth.js` 免认证请求实例 | `src/utils/requestNoAuth.js` |
|
|||
|
|
| 1.3 | 创建 `integralExternal.js` 路由模块 | `src/router/modules/integralExternal.js` |
|
|||
|
|
| 1.4 | 注册路由到 `constantRoutes` | `src/router/index.js` |
|
|||
|
|
| 1.5 | 修改 `permission.js` 白名单 | `src/permission.js` |
|
|||
|
|
| 1.6 | 创建 `integralExternal.js` API 文件 | `src/api/integralExternal.js` |
|
|||
|
|
|
|||
|
|
### Phase 2:积分订单页面(预计 1 天)
|
|||
|
|
|
|||
|
|
| # | 任务 |
|
|||
|
|
|---|------|
|
|||
|
|
| 2.1 | 基于 `order/index.vue` 创建精简版积分订单页 |
|
|||
|
|
| 2.2 | 去除权限校验、操作按钮、导出功能 |
|
|||
|
|
| 2.3 | 接入 `requestNoAuth` 请求 |
|
|||
|
|
| 2.4 | 测试筛选、分页、数据展示 |
|
|||
|
|
|
|||
|
|
### Phase 3:用户积分页面(预计 1.5 天)
|
|||
|
|
|
|||
|
|
| # | 任务 |
|
|||
|
|
|---|------|
|
|||
|
|
| 3.1 | 基于 `user/list/index.vue` 创建精简版用户积分页 |
|
|||
|
|
| 3.2 | 去除高级筛选、权限、操作按钮 |
|
|||
|
|
| 3.3 | 增加 wa_users 字段列(奖金、积分、余额等) |
|
|||
|
|
| 3.4 | 实现数据合并逻辑(前端或后端) |
|
|||
|
|
| 3.5 | 添加"查看积分明细"跳转按钮 |
|
|||
|
|
| 3.6 | 测试数据展示与跳转 |
|
|||
|
|
|
|||
|
|
### Phase 4:用户积分明细子页面(预计 0.5 天)
|
|||
|
|
|
|||
|
|
| # | 任务 |
|
|||
|
|
|---|------|
|
|||
|
|
| 4.1 | 基于 `user/integral/index.vue` 创建积分明细页 |
|
|||
|
|
| 4.2 | 通过 URL query 读取 uid 并锁定用户 |
|
|||
|
|
| 4.3 | 添加用户积分概览卡片 |
|
|||
|
|
| 4.4 | 添加返回按钮 |
|
|||
|
|
| 4.5 | 接入 `requestNoAuth` 请求 |
|
|||
|
|
| 4.6 | 测试分页、筛选、数据展示 |
|
|||
|
|
|
|||
|
|
### Phase 5:联调与验收(预计 0.5 天)
|
|||
|
|
|
|||
|
|
| # | 任务 |
|
|||
|
|
|---|------|
|
|||
|
|
| 5.1 | 无 token 状态下完整流程测试 |
|
|||
|
|
| 5.2 | 页面间跳转逻辑验证 |
|
|||
|
|
| 5.3 | 后端免认证接口联调 |
|
|||
|
|
| 5.4 | 兼容性和响应式测试 |
|
|||
|
|
|
|||
|
|
**总计预估工时:4 天**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 测试方案
|
|||
|
|
|
|||
|
|
### 8.1 免登录访问测试
|
|||
|
|
|
|||
|
|
| 编号 | 测试场景 | 操作步骤 | 预期结果 |
|
|||
|
|
|------|---------|---------|---------|
|
|||
|
|
| A-01 | 无 token 直接访问积分订单页 | 清除浏览器所有 cookie/sessionStorage,直接访问 `/integral-external/order` | 页面正常加载,不跳转至 `/login` |
|
|||
|
|
| A-02 | 无 token 直接访问用户积分页 | 同上,访问 `/integral-external/user` | 页面正常加载,不跳转至 `/login` |
|
|||
|
|
| A-03 | 无 token 直接访问积分明细页 | 同上,访问 `/integral-external/user/integral-detail?uid=1` | 页面正常加载,不跳转至 `/login` |
|
|||
|
|
| A-04 | 免登录页面不影响原有认证 | 无 token 访问 `/order/index`(原页面) | 仍然正常跳转至 `/login` |
|
|||
|
|
| A-05 | 已登录用户访问免登录页面 | 管理员登录后访问 `/integral-external/order` | 页面正常加载,不受登录态影响 |
|
|||
|
|
|
|||
|
|
### 8.2 积分订单页面测试
|
|||
|
|
|
|||
|
|
| 编号 | 测试场景 | 操作步骤 | 预期结果 |
|
|||
|
|
|------|---------|---------|---------|
|
|||
|
|
| B-01 | 默认加载 | 进入页面 | 表格展示订单列表,分页信息正确 |
|
|||
|
|
| B-02 | 按订单状态筛选 | 依次点击"未支付""未发货""交易完成"等状态 | 表格数据按状态正确过滤,数量标签更新 |
|
|||
|
|
| B-03 | 按时间范围筛选 | 选择起止日期 | 仅显示时间范围内的订单 |
|
|||
|
|
| B-04 | 按订单号搜索 | 输入完整订单号,点击搜索 | 精确匹配到对应订单 |
|
|||
|
|
| B-05 | 重置筛选条件 | 设置筛选条件后点击重置 | 所有筛选项恢复默认,表格展示全部数据 |
|
|||
|
|
| B-06 | 分页切换 | 切换页码、修改每页显示数 | 数据正确刷新,分页器状态正确 |
|
|||
|
|
| B-07 | 空数据状态 | 搜索不存在的订单号 | 表格显示空状态提示,无 JS 报错 |
|
|||
|
|
| B-08 | 无操作列 | 检查表格列 | 不存在编辑、发货、退款等操作按钮 |
|
|||
|
|
|
|||
|
|
### 8.3 用户积分页面测试
|
|||
|
|
|
|||
|
|
| 编号 | 测试场景 | 操作步骤 | 预期结果 |
|
|||
|
|
|------|---------|---------|---------|
|
|||
|
|
| C-01 | 默认加载 | 进入页面 | 用户列表正常展示,含 CRMEB 和 wa_users 字段 |
|
|||
|
|
| C-02 | wa_users 字段展示 | 查看表格列 | 个人奖金(`selfBonus`)、账户余额(`money`)等 wa_users 字段正确显示 |
|
|||
|
|
| C-03 | 积分字段来源验证 | 对比数据库 `eb_user.integral` 值 | 页面显示的积分与 `eb_user` 表一致 |
|
|||
|
|
| C-04 | wa_users 无关联数据 | 查看无 wa_users 记录的 CRMEB 用户行 | wa_users 相关列显示 `-` 或 `0`,不报错 |
|
|||
|
|
| C-05 | 用户搜索 | 输入姓名/手机号搜索 | 正确过滤,支持模糊匹配 |
|
|||
|
|
| C-06 | 跳转积分明细 | 点击某用户行的"查看积分明细" | 正确跳转至 `/integral-external/user/integral-detail?uid=xxx` |
|
|||
|
|
| C-07 | 分页功能 | 切换页码和每页条数 | 数据正确刷新 |
|
|||
|
|
| C-08 | 无权限指令残留 | 审查页面 DOM | 不存在 `v-hasPermi` 相关的隐藏元素或报错 |
|
|||
|
|
|
|||
|
|
### 8.4 用户积分明细子页面测试
|
|||
|
|
|
|||
|
|
| 编号 | 测试场景 | 操作步骤 | 预期结果 |
|
|||
|
|
|------|---------|---------|---------|
|
|||
|
|
| D-01 | 带 uid 参数加载 | 访问 `?uid=1001` | 自动加载 uid=1001 的积分明细,顶部概览卡片显示用户信息 |
|
|||
|
|
| D-02 | 概览卡片数据验证 | 对比数据库值 | 积分值 = `eb_user.integral`,个人奖金 = `wa_users.selfBonus` |
|
|||
|
|
| D-03 | 无 uid 参数访问 | 访问不带 `?uid` 参数的页面 | 页面给出"缺少用户参数"提示,或重定向至用户积分列表 |
|
|||
|
|
| D-04 | 无效 uid 访问 | 访问 `?uid=999999`(不存在的用户) | 表格为空,概览卡片显示空状态,无 JS 报错 |
|
|||
|
|
| D-05 | 时间范围筛选 | 选择日期范围 | 积分明细按时间正确过滤 |
|
|||
|
|
| D-06 | 积分变动显示 | 查看积分变动列 | 增加显示绿色 `+`,扣减显示红色 `-` |
|
|||
|
|
| D-07 | 状态与关联类型 | 查看状态和关联类型列 | 订单创建/冻结期/完成/失效 正确渲染标签颜色;订单/签到/系统 正确显示 |
|
|||
|
|
| D-08 | 返回按钮 | 点击"返回用户积分列表" | 正确跳转回 `/integral-external/user` |
|
|||
|
|
| D-09 | 分页功能 | 切换页码(15/30/45/60) | 数据正确刷新 |
|
|||
|
|
|
|||
|
|
### 8.5 接口与数据测试
|
|||
|
|
|
|||
|
|
| 编号 | 测试场景 | 操作步骤 | 预期结果 |
|
|||
|
|
|------|---------|---------|---------|
|
|||
|
|
| E-01 | 免认证接口可达性 | 无 token 调用各外部接口 | 返回 200 及正确业务数据,不返回 401 |
|
|||
|
|
| E-02 | 原认证接口不受影响 | 无 token 调用原 `/admin/user/list` 等接口 | 仍返回 401 |
|
|||
|
|
| E-03 | 接口仅读不写 | 尝试对免认证接口发送写操作请求 | 返回 403 或方法不允许 |
|
|||
|
|
| E-04 | 大数据量分页 | 请求 limit=60,数据总量 > 1000 | 分页正确,响应时间 < 3s |
|
|||
|
|
| E-05 | 边界参数 | page=0、limit=-1、uid=null 等异常参数 | 接口返回友好错误信息,不产生 500 |
|
|||
|
|
| E-06 | 数据脱敏验证 | 检查返回的手机号字段 | 中间 4 位做掩码处理(如 `138****8888`) |
|
|||
|
|
|
|||
|
|
### 8.6 兼容性与 UI 测试
|
|||
|
|
|
|||
|
|
| 编号 | 测试场景 | 预期结果 |
|
|||
|
|
|------|---------|---------|
|
|||
|
|
| F-01 | Chrome 最新版 | 页面布局正常,功能正常 |
|
|||
|
|
| F-02 | Firefox 最新版 | 页面布局正常,功能正常 |
|
|||
|
|
| F-03 | Edge 最新版 | 页面布局正常,功能正常 |
|
|||
|
|
| F-04 | 1920×1080 分辨率 | 表格列宽合理,无横向滚动条溢出 |
|
|||
|
|
| F-05 | 1366×768 分辨率 | 表格可横向滚动,筛选栏自动换行 |
|
|||
|
|
| F-06 | EmptyLayout 布局验证 | 页面无侧边栏、无顶部导航栏、无面包屑 |
|
|||
|
|
| F-07 | 加载状态 | 数据加载中显示 loading 动画 |
|
|||
|
|
|
|||
|
|
### 8.7 测试执行时间规划
|
|||
|
|
|
|||
|
|
| 阶段 | 内容 | 预计时间 |
|
|||
|
|
|------|------|---------|
|
|||
|
|
| 冒烟测试 | Phase 1 基础设施完成后,验证 A-01 ~ A-05 免登录链路 | 0.5h |
|
|||
|
|
| 功能测试 | 每个页面开发完成后,执行对应 B/C/D 组用例 | 每页面 1~2h |
|
|||
|
|
| 接口联调测试 | 后端免认证接口就绪后,执行 E 组用例 | 1h |
|
|||
|
|
| 回归测试 | 全部开发完成后,执行全量用例 | 2h |
|
|||
|
|
| 兼容性测试 | 回归通过后,执行 F 组用例 | 1h |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 注意事项
|
|||
|
|
|
|||
|
|
1. **安全风险**:免登录页面直接暴露后台数据,建议后端对免认证接口做 IP 白名单或 API Key 鉴权。
|
|||
|
|
2. **数据脱敏**:用户手机号等敏感字段建议做中间位掩码处理(如 `138****8888`)。
|
|||
|
|
3. **接口幂等**:所有免认证接口仅开放读取权限(GET/查询),禁止写操作。
|
|||
|
|
4. **路由隔离**:新页面使用 `EmptyLayout`,与管理后台主布局完全隔离,避免引入侧边栏/权限组件的副作用。
|
|||
|
|
5. **组件依赖**:新页面可复用 Element UI 组件,但避免引入需要 Vuex store(如用户信息、权限)的业务组件。
|