This commit is contained in:
@@ -19,7 +19,9 @@
|
|||||||
"Bash(findstr:*)",
|
"Bash(findstr:*)",
|
||||||
"Bash(npm run:*)",
|
"Bash(npm run:*)",
|
||||||
"Bash(find src/views -name *.vue -type f -exec grep -l \"device.*detail\\\\|设备详情\" {})",
|
"Bash(find src/views -name *.vue -type f -exec grep -l \"device.*detail\\\\|设备详情\" {})",
|
||||||
"Bash(2)"
|
"Bash(2)",
|
||||||
|
"Bash(grep -E \"\\\\.\\(vue|ts\\)$\")",
|
||||||
|
"Bash(xargs grep:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
343
docs/API对接说明.md
343
docs/API对接说明.md
@@ -1,343 +0,0 @@
|
|||||||
# API 对接说明
|
|
||||||
|
|
||||||
> 更新时间: 2026-01-09
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 已完成的修改
|
|
||||||
|
|
||||||
### 1. 创建了认证 API 服务
|
|
||||||
**文件**: `src/api/authApi.ts`
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { AuthService } from '@/api/authApi'
|
|
||||||
|
|
||||||
// 登录
|
|
||||||
AuthService.login({ username, password, remember })
|
|
||||||
|
|
||||||
// 获取用户信息
|
|
||||||
AuthService.getUserInfo()
|
|
||||||
|
|
||||||
// 登出
|
|
||||||
AuthService.logout()
|
|
||||||
|
|
||||||
// 刷新Token
|
|
||||||
AuthService.refreshToken(refreshToken)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 修改了登录逻辑
|
|
||||||
**文件**: `src/composables/useLogin.ts`
|
|
||||||
|
|
||||||
**关键修改**:
|
|
||||||
- ✅ 添加了 `USE_MOCK` 开关(第 29 行)
|
|
||||||
- ✅ 创建了 `handleRealLogin()` 真实API登录函数
|
|
||||||
- ✅ 保留了 `handleMockLogin()` Mock登录函数(方便开发测试)
|
|
||||||
|
|
||||||
**切换方式**:
|
|
||||||
```typescript
|
|
||||||
// 文件: src/composables/useLogin.ts 第 29 行
|
|
||||||
|
|
||||||
// 使用 Mock 数据(开发测试)
|
|
||||||
const USE_MOCK = true
|
|
||||||
|
|
||||||
// 使用真实 API(生产环境)
|
|
||||||
const USE_MOCK = false // ← 当前设置
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔌 API 接口规范
|
|
||||||
|
|
||||||
### 登录接口
|
|
||||||
|
|
||||||
**请求地址**: `POST /api/auth/login`
|
|
||||||
|
|
||||||
**请求参数**:
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
username: string // 用户名
|
|
||||||
password: string // 密码
|
|
||||||
remember?: boolean // 是否记住密码
|
|
||||||
captcha?: string // 验证码(可选)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**响应格式**:
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
code: number // 状态码:200 成功
|
|
||||||
message: string // 消息
|
|
||||||
data: {
|
|
||||||
token: string // 访问令牌 (必需)
|
|
||||||
refreshToken?: string // 刷新令牌 (可选)
|
|
||||||
expiresIn?: number // 过期时间(秒) (可选)
|
|
||||||
userInfo: { // 用户信息 (推荐返回,避免二次请求)
|
|
||||||
id: string | number
|
|
||||||
username: string
|
|
||||||
realName: string
|
|
||||||
roles: string[] // 角色列表 ['R_SUPER', 'R_ADMIN', ...]
|
|
||||||
permissions: string[] // 权限列表 ['*:*:*', 'user:edit', ...]
|
|
||||||
avatar?: string
|
|
||||||
email?: string
|
|
||||||
phone?: string
|
|
||||||
// ... 其他用户信息
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 获取用户信息接口
|
|
||||||
|
|
||||||
**请求地址**: `GET /api/auth/userInfo`
|
|
||||||
|
|
||||||
**请求头**:
|
|
||||||
```
|
|
||||||
Authorization: Bearer {token}
|
|
||||||
```
|
|
||||||
|
|
||||||
**响应格式**:
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
code: 200,
|
|
||||||
message: 'success',
|
|
||||||
data: {
|
|
||||||
id: string | number
|
|
||||||
username: string
|
|
||||||
realName: string
|
|
||||||
roles: string[]
|
|
||||||
permissions: string[]
|
|
||||||
avatar?: string
|
|
||||||
email?: string
|
|
||||||
phone?: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔐 权限控制说明
|
|
||||||
|
|
||||||
### 角色定义
|
|
||||||
系统预定义了以下角色(可根据需求调整):
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
enum UserRole {
|
|
||||||
SUPER_ADMIN = 'R_SUPER', // 超级管理员
|
|
||||||
ADMIN = 'R_ADMIN', // 管理员
|
|
||||||
AGENT = 'R_AGENT', // 代理商
|
|
||||||
ENTERPRISE = 'R_ENTERPRISE' // 企业客户
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 权限格式
|
|
||||||
权限使用通配符格式:`模块:操作:范围`
|
|
||||||
|
|
||||||
**示例**:
|
|
||||||
- `*:*:*` - 所有权限
|
|
||||||
- `user:*:*` - 用户模块所有权限
|
|
||||||
- `user:edit:*` - 用户编辑权限
|
|
||||||
- `card:view:own` - 查看自己的卡
|
|
||||||
|
|
||||||
### 前端权限验证
|
|
||||||
|
|
||||||
**路由级权限**(在 `asyncRoutes.ts` 中配置):
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
path: '/system/user',
|
|
||||||
meta: {
|
|
||||||
roles: ['R_SUPER', 'R_ADMIN'] // 只有超管和管理员可访问
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**按钮级权限**(使用 `v-auth` 指令):
|
|
||||||
```vue
|
|
||||||
<el-button v-auth="'user:edit'">编辑</el-button>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 状态码规范
|
|
||||||
|
|
||||||
**推荐使用的状态码** (已在 `src/utils/http/status.ts` 定义):
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export enum ApiStatus {
|
|
||||||
success = 200, // 成功
|
|
||||||
unauthorized = 401, // 未授权
|
|
||||||
forbidden = 403, // 禁止访问
|
|
||||||
notFound = 404, // 未找到
|
|
||||||
serverError = 500 // 服务器错误
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 快速上手
|
|
||||||
|
|
||||||
### 1. 配置API地址
|
|
||||||
|
|
||||||
**文件**: `.env.development`
|
|
||||||
|
|
||||||
```env
|
|
||||||
# API 地址前缀
|
|
||||||
VITE_API_URL = http://your-backend-api.com
|
|
||||||
|
|
||||||
# 或者使用代理(推荐)
|
|
||||||
VITE_API_URL = /api
|
|
||||||
```
|
|
||||||
|
|
||||||
**文件**: `vite.config.ts` (如果使用代理)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
server: {
|
|
||||||
proxy: {
|
|
||||||
'/api': {
|
|
||||||
target: 'http://your-backend-api.com', // 后端地址
|
|
||||||
changeOrigin: true,
|
|
||||||
rewrite: (path) => path.replace(/^\/api/, '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 切换到真实API
|
|
||||||
|
|
||||||
**文件**: `src/composables/useLogin.ts` 第 29 行
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const USE_MOCK = false // 改为 false
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 测试登录
|
|
||||||
|
|
||||||
1. 启动开发服务器:`npm run dev`
|
|
||||||
2. 访问登录页面:`http://localhost:3006/#/auth/login`
|
|
||||||
3. 输入后端提供的测试账号密码
|
|
||||||
4. 点击登录
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 调试技巧
|
|
||||||
|
|
||||||
### 1. 查看请求/响应
|
|
||||||
|
|
||||||
打开浏览器开发者工具(F12)→ Network 标签,查看:
|
|
||||||
- 请求URL
|
|
||||||
- 请求参数
|
|
||||||
- 响应数据
|
|
||||||
- 状态码
|
|
||||||
|
|
||||||
### 2. Mock 和真实API切换
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// src/composables/useLogin.ts
|
|
||||||
|
|
||||||
const USE_MOCK = true // 开发时使用 Mock
|
|
||||||
const USE_MOCK = false // 对接时使用真实 API
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Token 检查
|
|
||||||
|
|
||||||
打开浏览器控制台(F12)→ Application → Local Storage → 查看 `user` 键:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"isLogin": true,
|
|
||||||
"accessToken": "your-token-here",
|
|
||||||
"info": { ... }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 请求拦截器日志
|
|
||||||
|
|
||||||
**文件**: `src/utils/http/interceptors.ts`
|
|
||||||
|
|
||||||
已自动添加请求/响应日志,在控制台可以看到:
|
|
||||||
- 🚀 发送请求
|
|
||||||
- ✅ 请求成功
|
|
||||||
- ❌ 请求失败
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚠️ 常见问题
|
|
||||||
|
|
||||||
### Q1: 登录后提示"获取用户角色失败"
|
|
||||||
|
|
||||||
**原因**: 后端返回的用户信息中没有 `roles` 字段
|
|
||||||
|
|
||||||
**解决**:
|
|
||||||
1. 确保后端返回的 `userInfo.roles` 是数组
|
|
||||||
2. 至少包含一个角色,如:`["R_ADMIN"]`
|
|
||||||
|
|
||||||
### Q2: 登录成功但页面一直转圈
|
|
||||||
|
|
||||||
**原因**: 路由守卫中没有通过权限验证
|
|
||||||
|
|
||||||
**解决**:
|
|
||||||
1. 检查用户信息中是否有 `roles` 字段
|
|
||||||
2. 临时开启开发模式跳过权限验证(见下文)
|
|
||||||
|
|
||||||
### Q3: 如何临时跳过权限验证?
|
|
||||||
|
|
||||||
**文件**: `src/router/guards/beforeEach.ts` 第 28 行
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const DEV_MODE_SKIP_AUTH = true // 改为 true,跳过所有权限验证
|
|
||||||
```
|
|
||||||
|
|
||||||
### Q4: Token 过期如何处理?
|
|
||||||
|
|
||||||
系统已自动处理 Token 过期:
|
|
||||||
1. 检测到 401 状态码自动跳转登录页
|
|
||||||
2. 可实现自动刷新 Token(需要后端支持)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 后端接口开发建议
|
|
||||||
|
|
||||||
### 1. 登录接口返回完整用户信息
|
|
||||||
避免前端登录后再次调用获取用户信息接口,减少请求次数。
|
|
||||||
|
|
||||||
### 2. 用户信息必须包含 roles
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"roles": ["R_ADMIN", "R_USER"] // 必须
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 支持 Token 刷新机制
|
|
||||||
```typescript
|
|
||||||
// 刷新Token接口
|
|
||||||
POST /api/auth/refresh
|
|
||||||
{
|
|
||||||
"refreshToken": "refresh-token-here"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 统一响应格式
|
|
||||||
```typescript
|
|
||||||
{
|
|
||||||
code: 200,
|
|
||||||
message: "success",
|
|
||||||
data: { ... }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ 下一步
|
|
||||||
|
|
||||||
1. ✅ 后端提供测试环境API地址
|
|
||||||
2. ✅ 配置 `VITE_API_URL` 或代理
|
|
||||||
3. ✅ 切换 `USE_MOCK = false`
|
|
||||||
4. ✅ 测试登录功能
|
|
||||||
5. ✅ 根据实际API调整请求/响应格式
|
|
||||||
6. ✅ 完善其他业务接口
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**联系支持**:
|
|
||||||
- 前端问题:查看本文档或项目 README
|
|
||||||
- 后端对接:与后端开发人员沟通接口格式
|
|
||||||
|
|
||||||
祝对接顺利!🚀
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
# 登录模块说明文档
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
本项目的登录模块已完成重构,采用了全新的架构设计,提供了完整的认证流程和权限管理功能。
|
|
||||||
|
|
||||||
## 功能特性
|
|
||||||
|
|
||||||
### 1. Mock 数据支持
|
|
||||||
|
|
||||||
系统内置了 4 个 Mock 账号,用于开发和演示:
|
|
||||||
|
|
||||||
| 账号类型 | 用户名 | 密码 | 角色 | 权限说明 |
|
|
||||||
|---------|--------|------|------|---------|
|
|
||||||
| 超级管理员 | super | 123456 | SUPER_ADMIN | 拥有所有权限 |
|
|
||||||
| 平台管理员 | admin | 123456 | ADMIN | 账号、网卡、套餐、设备等管理权限 |
|
|
||||||
| 代理商 | agent | 123456 | AGENT | 网卡查看/操作、佣金管理等权限 |
|
|
||||||
| 企业客户 | enterprise | 123456 | ENTERPRISE | 自有网卡和设备的查看/操作权限 |
|
|
||||||
|
|
||||||
**文件位置**: `src/mock/auth.ts`
|
|
||||||
|
|
||||||
### 2. 记住密码功能
|
|
||||||
|
|
||||||
- 用户可以勾选"记住密码"选项
|
|
||||||
- 登录成功后,用户名和密码会被加密存储到 localStorage
|
|
||||||
- 下次访问登录页时自动填充账号信息
|
|
||||||
- 取消勾选会清除已保存的凭证
|
|
||||||
|
|
||||||
**实现文件**: `src/utils/auth/rememberPassword.ts`
|
|
||||||
|
|
||||||
**核心函数**:
|
|
||||||
```typescript
|
|
||||||
// 保存凭证
|
|
||||||
saveCredentials(username, password, remember)
|
|
||||||
|
|
||||||
// 获取保存的凭证
|
|
||||||
getRememberedCredentials()
|
|
||||||
|
|
||||||
// 清除凭证
|
|
||||||
clearRememberedCredentials()
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 完善的表单验证
|
|
||||||
|
|
||||||
提供了多种验证规则,适用于不同场景:
|
|
||||||
|
|
||||||
- **用户名验证**: 3-20个字符,只能包含字母、数字和下划线
|
|
||||||
- **密码验证**: 6-20个字符
|
|
||||||
- **强密码验证**: 8-20个字符,必须包含大小写字母和数字
|
|
||||||
- **确认密码验证**: 必须与密码一致
|
|
||||||
- **手机号验证**: 支持中国大陆手机号格式
|
|
||||||
- **邮箱验证**: 标准邮箱格式验证
|
|
||||||
- **验证码验证**: 4位数字
|
|
||||||
|
|
||||||
**实现文件**: `src/utils/auth/loginValidation.ts`
|
|
||||||
|
|
||||||
**使用示例**:
|
|
||||||
```typescript
|
|
||||||
import { usernameRules, passwordRules } from '@/utils/auth/loginValidation'
|
|
||||||
|
|
||||||
const rules = {
|
|
||||||
username: usernameRules(t),
|
|
||||||
password: passwordRules(t)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 权限路由守卫
|
|
||||||
|
|
||||||
优化了路由守卫,增加了以下功能:
|
|
||||||
|
|
||||||
#### 白名单机制
|
|
||||||
不需要登录即可访问的路由:
|
|
||||||
- `/login` - 登录页
|
|
||||||
- `/register` - 注册页
|
|
||||||
- `/forget-password` - 忘记密码
|
|
||||||
- `/exception/*` - 异常页面
|
|
||||||
|
|
||||||
**文件位置**: `src/router/guards/permission.ts`
|
|
||||||
|
|
||||||
#### Token 验证
|
|
||||||
- 自动检查 Token 是否存在
|
|
||||||
- 验证 Token 是否有效
|
|
||||||
- Token 过期自动跳转到登录页
|
|
||||||
|
|
||||||
#### 页面级权限验证
|
|
||||||
- 根据路由 meta 中的 `roles` 和 `permissions` 进行验证
|
|
||||||
- 无权限访问时自动跳转到 403 页面
|
|
||||||
- 支持通配符权限(如 `*:*:*` 表示所有权限)
|
|
||||||
|
|
||||||
#### 登录重定向
|
|
||||||
- 访问需要登录的页面时,会记录当前路径
|
|
||||||
- 登录成功后自动跳转回之前访问的页面
|
|
||||||
- 如果是白名单路由,则跳转到首页
|
|
||||||
|
|
||||||
**核心函数**:
|
|
||||||
```typescript
|
|
||||||
// 检查是否在白名单
|
|
||||||
isInWhiteList(path)
|
|
||||||
|
|
||||||
// 检查路由权限
|
|
||||||
hasRoutePermission(route, userInfo)
|
|
||||||
|
|
||||||
// 检查 Token 是否有效
|
|
||||||
isTokenValid(token)
|
|
||||||
|
|
||||||
// 构建登录重定向URL
|
|
||||||
buildLoginRedirect(currentPath)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. useLogin Composable
|
|
||||||
|
|
||||||
将登录逻辑抽取为可复用的 Composable,提高代码可维护性。
|
|
||||||
|
|
||||||
**文件位置**: `src/composables/useLogin.ts`
|
|
||||||
|
|
||||||
**提供的功能**:
|
|
||||||
- 表单状态管理
|
|
||||||
- Mock 账号切换
|
|
||||||
- 登录逻辑处理
|
|
||||||
- 自动记住密码
|
|
||||||
- 登录成功通知
|
|
||||||
- 重定向处理
|
|
||||||
|
|
||||||
**使用示例**:
|
|
||||||
```vue
|
|
||||||
<script setup>
|
|
||||||
import { useLogin } from '@/composables/useLogin'
|
|
||||||
|
|
||||||
const {
|
|
||||||
formRef,
|
|
||||||
formData,
|
|
||||||
rules,
|
|
||||||
loading,
|
|
||||||
mockAccounts,
|
|
||||||
setupAccount,
|
|
||||||
handleLogin
|
|
||||||
} = useLogin()
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 文件结构
|
|
||||||
|
|
||||||
```
|
|
||||||
src/
|
|
||||||
├── mock/
|
|
||||||
│ └── auth.ts # Mock 账号数据
|
|
||||||
├── utils/auth/
|
|
||||||
│ ├── rememberPassword.ts # 记住密码工具
|
|
||||||
│ ├── loginValidation.ts # 表单验证规则
|
|
||||||
│ └── index.ts # 统一导出
|
|
||||||
├── router/guards/
|
|
||||||
│ ├── permission.ts # 权限验证工具
|
|
||||||
│ ├── beforeEach.ts # 路由前置守卫(已优化)
|
|
||||||
│ └── afterEach.ts # 路由后置守卫
|
|
||||||
├── composables/
|
|
||||||
│ └── useLogin.ts # 登录逻辑 Composable
|
|
||||||
└── views/auth/login/
|
|
||||||
└── index.vue # 登录页面(已重构)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 权限配置示例
|
|
||||||
|
|
||||||
### 路由权限配置
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 在路由配置中添加 meta
|
|
||||||
{
|
|
||||||
path: '/account/platform',
|
|
||||||
meta: {
|
|
||||||
title: '平台账号管理',
|
|
||||||
roles: ['R_SUPER', 'R_ADMIN'], // 允许的角色
|
|
||||||
permissions: ['account:view:*'] // 需要的权限
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 用户权限定义
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 用户信息中包含角色和权限
|
|
||||||
{
|
|
||||||
roles: ['R_ADMIN'],
|
|
||||||
permissions: [
|
|
||||||
'account:*:*', // 账号管理所有权限
|
|
||||||
'card:view:*', // 网卡查看权限
|
|
||||||
'card:operation:*' // 网卡操作权限
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 开发建议
|
|
||||||
|
|
||||||
### 1. 切换到真实接口
|
|
||||||
|
|
||||||
当后端接口就绪后,只需修改 `useLogin.ts` 中的登录逻辑:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 将 Mock 登录替换为真实 API
|
|
||||||
// const loginResult = mockLogin(formData.username, formData.password)
|
|
||||||
const loginResult = await AuthService.login({
|
|
||||||
username: formData.username,
|
|
||||||
password: formData.password
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Token 刷新
|
|
||||||
|
|
||||||
在 `src/router/guards/permission.ts` 的 `isTokenValid` 函数中添加真实的 JWT 验证逻辑。
|
|
||||||
|
|
||||||
### 3. 权限粒度
|
|
||||||
|
|
||||||
根据实际业务需求,可以在以下层级添加权限验证:
|
|
||||||
- **路由级**: 在路由 meta 中配置
|
|
||||||
- **页面级**: 在页面组件中使用 v-if 判断
|
|
||||||
- **按钮级**: 使用自定义指令(如 `v-permission`)
|
|
||||||
|
|
||||||
## 常见问题
|
|
||||||
|
|
||||||
### Q1: 如何添加新的 Mock 账号?
|
|
||||||
|
|
||||||
编辑 `src/mock/auth.ts`,在 `MOCK_ACCOUNTS` 数组中添加新账号即可。
|
|
||||||
|
|
||||||
### Q2: 记住密码的数据存在哪里?
|
|
||||||
|
|
||||||
存储在浏览器的 localStorage 中,key 为 `remembered_credentials`,数据经过 Base64 编码。
|
|
||||||
|
|
||||||
### Q3: 如何自定义白名单路由?
|
|
||||||
|
|
||||||
编辑 `src/router/guards/permission.ts` 的 `LOGIN_WHITE_LIST` 数组。
|
|
||||||
|
|
||||||
### Q4: 为什么登录后还是跳转到登录页?
|
|
||||||
|
|
||||||
检查以下几点:
|
|
||||||
1. Token 是否正确保存到 store
|
|
||||||
2. `userStore.isLogin` 是否设置为 true
|
|
||||||
3. 路由守卫中的权限验证是否通过
|
|
||||||
|
|
||||||
## 下一步计划
|
|
||||||
|
|
||||||
- [ ] 添加双因素认证(2FA)
|
|
||||||
- [ ] 实现 SSO 单点登录
|
|
||||||
- [ ] 添加第三方登录(微信、钉钉等)
|
|
||||||
- [ ] 完善密码强度检测
|
|
||||||
- [ ] 添加登录日志记录
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
touch README.md
|
|
||||||
git init
|
|
||||||
git checkout -b main
|
|
||||||
git add README.md
|
|
||||||
git commit -m "first commit"
|
|
||||||
git remote add origin https://git.boss160.cn/luo/admin-xm-iot.git
|
|
||||||
git push -u origin main
|
|
||||||
|
|
||||||
你需要注意下.gitignore 是否需要加一些文件进去
|
|
||||||
870
docs/代理账号管理.md
870
docs/代理账号管理.md
@@ -1,870 +0,0 @@
|
|||||||
# 账号管理下面新增一个代理账号管理, 页面样式可以参考/system/account 都需要token认证
|
|
||||||
|
|
||||||
# 代理账号列表
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shop-accounts:
|
|
||||||
get:
|
|
||||||
summary: 代理账号列表
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 代理账号管理
|
|
||||||
- 代理账号管理
|
|
||||||
parameters:
|
|
||||||
- name: page
|
|
||||||
in: query
|
|
||||||
description: 页码
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 页码
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
- name: page_size
|
|
||||||
in: query
|
|
||||||
description: 每页数量
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 每页数量
|
|
||||||
maximum: 100
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
- name: shop_id
|
|
||||||
in: query
|
|
||||||
description: 店铺ID过滤
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 店铺ID过滤
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
- name: username
|
|
||||||
in: query
|
|
||||||
description: 用户名(模糊查询)
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 用户名(模糊查询)
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
- name: phone
|
|
||||||
in: query
|
|
||||||
description: 手机号(精确查询)
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 手机号(精确查询)
|
|
||||||
maxLength: 11
|
|
||||||
minLength: 11
|
|
||||||
type: string
|
|
||||||
- name: status
|
|
||||||
in: query
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelShopAccountPageResult'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: '-jWpeN1-jYBl-SEBTmsrq'
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: '-jWpeN1-jYBl-SEBTmsrq'
|
|
||||||
scopes:
|
|
||||||
'-jWpeN1-jYBl-SEBTmsrq':
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 代理账号管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366334-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelShopAccountPageResult:
|
|
||||||
properties:
|
|
||||||
items:
|
|
||||||
description: 代理账号列表
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/ModelShopAccountResponse'
|
|
||||||
type: array
|
|
||||||
nullable: true
|
|
||||||
page:
|
|
||||||
description: 当前页码
|
|
||||||
type: integer
|
|
||||||
size:
|
|
||||||
description: 每页数量
|
|
||||||
type: integer
|
|
||||||
total:
|
|
||||||
description: 总记录数
|
|
||||||
type: integer
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- items
|
|
||||||
- page
|
|
||||||
- size
|
|
||||||
- total
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ModelShopAccountResponse:
|
|
||||||
properties:
|
|
||||||
created_at:
|
|
||||||
description: 创建时间
|
|
||||||
type: string
|
|
||||||
id:
|
|
||||||
description: 账号ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
phone:
|
|
||||||
description: 手机号
|
|
||||||
type: string
|
|
||||||
shop_id:
|
|
||||||
description: 店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
updated_at:
|
|
||||||
description: 更新时间
|
|
||||||
type: string
|
|
||||||
user_type:
|
|
||||||
description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)
|
|
||||||
type: integer
|
|
||||||
username:
|
|
||||||
description: 用户名
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- created_at
|
|
||||||
- id
|
|
||||||
- phone
|
|
||||||
- shop_id
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
- updated_at
|
|
||||||
- user_type
|
|
||||||
- username
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
# 创建代理账号
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shop-accounts:
|
|
||||||
post:
|
|
||||||
summary: 创建代理账号
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 代理账号管理
|
|
||||||
- 代理账号管理
|
|
||||||
parameters: []
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelCreateShopAccountRequest'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelShopAccountResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: LdX0-6IzkTw-pXBT8t4Km
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: LdX0-6IzkTw-pXBT8t4Km
|
|
||||||
scopes:
|
|
||||||
LdX0-6IzkTw-pXBT8t4Km:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 代理账号管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366335-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelCreateShopAccountRequest:
|
|
||||||
properties:
|
|
||||||
password:
|
|
||||||
description: 密码
|
|
||||||
maxLength: 32
|
|
||||||
minLength: 8
|
|
||||||
type: string
|
|
||||||
phone:
|
|
||||||
description: 手机号
|
|
||||||
maxLength: 11
|
|
||||||
minLength: 11
|
|
||||||
type: string
|
|
||||||
shop_id:
|
|
||||||
description: 店铺ID
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
username:
|
|
||||||
description: 用户名
|
|
||||||
maxLength: 50
|
|
||||||
minLength: 3
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- password
|
|
||||||
- phone
|
|
||||||
- shop_id
|
|
||||||
- username
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- password
|
|
||||||
- phone
|
|
||||||
- shop_id
|
|
||||||
- username
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ModelShopAccountResponse:
|
|
||||||
properties:
|
|
||||||
created_at:
|
|
||||||
description: 创建时间
|
|
||||||
type: string
|
|
||||||
id:
|
|
||||||
description: 账号ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
phone:
|
|
||||||
description: 手机号
|
|
||||||
type: string
|
|
||||||
shop_id:
|
|
||||||
description: 店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
updated_at:
|
|
||||||
description: 更新时间
|
|
||||||
type: string
|
|
||||||
user_type:
|
|
||||||
description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)
|
|
||||||
type: integer
|
|
||||||
username:
|
|
||||||
description: 用户名
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- created_at
|
|
||||||
- id
|
|
||||||
- phone
|
|
||||||
- shop_id
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
- updated_at
|
|
||||||
- user_type
|
|
||||||
- username
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
# 更新代理账号
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shop-accounts/{id}:
|
|
||||||
put:
|
|
||||||
summary: 更新代理账号
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 代理账号管理
|
|
||||||
- 代理账号管理
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
description: ID
|
|
||||||
required: true
|
|
||||||
example: 0
|
|
||||||
schema:
|
|
||||||
description: ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelUpdateShopAccountParams'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelShopAccountResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: TTw5I9JG_CJv8tEsi1Bk6
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: TTw5I9JG_CJv8tEsi1Bk6
|
|
||||||
scopes:
|
|
||||||
TTw5I9JG_CJv8tEsi1Bk6:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 代理账号管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366336-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelUpdateShopAccountParams:
|
|
||||||
properties:
|
|
||||||
username:
|
|
||||||
description: 用户名
|
|
||||||
maxLength: 50
|
|
||||||
minLength: 3
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- username
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- username
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ModelShopAccountResponse:
|
|
||||||
properties:
|
|
||||||
created_at:
|
|
||||||
description: 创建时间
|
|
||||||
type: string
|
|
||||||
id:
|
|
||||||
description: 账号ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
phone:
|
|
||||||
description: 手机号
|
|
||||||
type: string
|
|
||||||
shop_id:
|
|
||||||
description: 店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
updated_at:
|
|
||||||
description: 更新时间
|
|
||||||
type: string
|
|
||||||
user_type:
|
|
||||||
description: 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)
|
|
||||||
type: integer
|
|
||||||
username:
|
|
||||||
description: 用户名
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- created_at
|
|
||||||
- id
|
|
||||||
- phone
|
|
||||||
- shop_id
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
- updated_at
|
|
||||||
- user_type
|
|
||||||
- username
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
# 重置代理账号密码
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shop-accounts/{id}/password:
|
|
||||||
put:
|
|
||||||
summary: 重置代理账号密码
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 代理账号管理
|
|
||||||
- 代理账号管理
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
description: ID
|
|
||||||
required: true
|
|
||||||
example: 0
|
|
||||||
schema:
|
|
||||||
description: ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelUpdateShopAccountPasswordParams'
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: IeBLfzHchBWHbFru7Ma0u
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: IeBLfzHchBWHbFru7Ma0u
|
|
||||||
scopes:
|
|
||||||
IeBLfzHchBWHbFru7Ma0u:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 代理账号管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366337-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelUpdateShopAccountPasswordParams:
|
|
||||||
properties:
|
|
||||||
new_password:
|
|
||||||
description: 新密码
|
|
||||||
maxLength: 32
|
|
||||||
minLength: 8
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- new_password
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- new_password
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
列表显示中状态用开关那个组件
|
|
||||||
# 启用/禁用代理账号
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shop-accounts/{id}/status:
|
|
||||||
put:
|
|
||||||
summary: 启用/禁用代理账号
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 代理账号管理
|
|
||||||
- 代理账号管理
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
description: ID
|
|
||||||
required: true
|
|
||||||
example: 0
|
|
||||||
schema:
|
|
||||||
description: ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelUpdateShopAccountStatusParams'
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: QRYgZh2IcZgAVmdF1dNBU
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: QRYgZh2IcZgAVmdF1dNBU
|
|
||||||
scopes:
|
|
||||||
QRYgZh2IcZgAVmdF1dNBU:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 代理账号管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366338-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelUpdateShopAccountStatusParams:
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
required:
|
|
||||||
- status
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- status
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
488
docs/任务规划.md
488
docs/任务规划.md
@@ -1,488 +0,0 @@
|
|||||||
# 物联网卡管理系统 - 开发任务规划
|
|
||||||
|
|
||||||
> 项目开始日期: 2026-01-09
|
|
||||||
> 当前状态: 进行中
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 任务进度总览
|
|
||||||
|
|
||||||
- [ ] 阶段一:基础设施和认证模块(0/2)
|
|
||||||
- [ ] 阶段二:账号管理模块(0/7)
|
|
||||||
- [ ] 阶段三:财务管理模块(0/4)
|
|
||||||
- [ ] 阶段四:商品管理模块(0/5)
|
|
||||||
- [ ] 阶段五:资产管理模块(0/5)
|
|
||||||
- [ ] 阶段六:批量操作模块(0/3)
|
|
||||||
|
|
||||||
**总体完成度**: 0/26 任务
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 阶段一:基础设施和认证模块
|
|
||||||
|
|
||||||
### 1.1 登录模块
|
|
||||||
- [ ] 设计登录页面UI
|
|
||||||
- [ ] 实现用户名密码登录
|
|
||||||
- [ ] 实现记住密码功能
|
|
||||||
- [ ] 集成验证码/滑块验证
|
|
||||||
- [ ] 实现 Token 管理
|
|
||||||
- [ ] 实现自动刷新 Token
|
|
||||||
- [ ] 实现登出功能
|
|
||||||
- [ ] 添加登录错误处理
|
|
||||||
|
|
||||||
### 1.2 权限管理基础
|
|
||||||
- [ ] 设计权限控制策略(RBAC)
|
|
||||||
- [ ] 实现路由权限守卫
|
|
||||||
- [ ] 实现按钮级权限控制
|
|
||||||
- [ ] 实现数据权限过滤
|
|
||||||
- [ ] 完善角色权限映射
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 👥 阶段二:账号管理模块
|
|
||||||
|
|
||||||
### 2.1 平台角色管理
|
|
||||||
- [ ] 角色列表页面(表格展示)
|
|
||||||
- [ ] 新增角色功能
|
|
||||||
- [ ] 角色基础信息表单
|
|
||||||
- [ ] 权限分配(树形结构)
|
|
||||||
- [ ] 编辑角色功能
|
|
||||||
- [ ] 删除角色功能
|
|
||||||
- [ ] 角色搜索和筛选
|
|
||||||
- [ ] 角色权限预览
|
|
||||||
|
|
||||||
### 2.2 平台账号管理
|
|
||||||
- [ ] 平台账号列表页面
|
|
||||||
- [ ] 新增平台账号
|
|
||||||
- [ ] 账号信息表单
|
|
||||||
- [ ] 角色分配
|
|
||||||
- [ ] 账号状态设置
|
|
||||||
- [ ] 编辑平台账号
|
|
||||||
- [ ] 禁用/启用账号
|
|
||||||
- [ ] 重置密码功能
|
|
||||||
- [ ] 账号操作日志查看
|
|
||||||
|
|
||||||
### 2.3 客户角色管理
|
|
||||||
- [ ] 客户角色列表页面
|
|
||||||
- [ ] 新增客户角色
|
|
||||||
- [ ] 角色名称和描述
|
|
||||||
- [ ] 能力边界配置(权限树)
|
|
||||||
- [ ] 编辑客户角色
|
|
||||||
- [ ] 删除客户角色
|
|
||||||
- [ ] 角色能力说明文档
|
|
||||||
|
|
||||||
### 2.4 代理商管理
|
|
||||||
- [ ] 代理商列表页面
|
|
||||||
- [ ] 多级代理商树形展示
|
|
||||||
- [ ] 代理商等级标识
|
|
||||||
- [ ] 新增代理商
|
|
||||||
- [ ] 代理商基础信息
|
|
||||||
- [ ] 上级代理商选择
|
|
||||||
- [ ] 代理商等级设置
|
|
||||||
- [ ] 编辑代理商信息
|
|
||||||
- [ ] 代理商账号管理
|
|
||||||
- [ ] 查看代理商下的账号列表
|
|
||||||
- [ ] 为代理商创建子账号
|
|
||||||
- [ ] 代理商佣金配置
|
|
||||||
- [ ] 代理商数据统计面板
|
|
||||||
|
|
||||||
### 2.5 企业客户管理
|
|
||||||
- [ ] 企业客户列表页面
|
|
||||||
- [ ] 新增企业客户
|
|
||||||
- [ ] 企业基础信息
|
|
||||||
- [ ] 客户角色分配
|
|
||||||
- [ ] 联系人信息
|
|
||||||
- [ ] 编辑企业客户
|
|
||||||
- [ ] 企业客户账号管理
|
|
||||||
- [ ] 创建企业管理账号
|
|
||||||
- [ ] 账号权限设置
|
|
||||||
- [ ] 企业客户数据看板
|
|
||||||
|
|
||||||
### 2.6 客户账号管理
|
|
||||||
- [ ] 客户账号列表页面
|
|
||||||
- [ ] 支持按代理商/企业筛选
|
|
||||||
- [ ] 账号状态筛选
|
|
||||||
- [ ] 查看账号详情
|
|
||||||
- [ ] 解绑手机号
|
|
||||||
- [ ] 重置登录密码
|
|
||||||
- [ ] 禁用/启用账号
|
|
||||||
- [ ] 账号操作记录
|
|
||||||
|
|
||||||
### 2.7 客户账号佣金管理
|
|
||||||
- [ ] 客户账号佣金列表
|
|
||||||
- [ ] 佣金统计卡片
|
|
||||||
- [ ] 佣金明细表格
|
|
||||||
- [ ] 佣金详情查看
|
|
||||||
- [ ] 提现记录查看
|
|
||||||
- [ ] 佣金统计图表
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💰 阶段三:财务管理模块
|
|
||||||
|
|
||||||
### 3.1 佣金提现管理
|
|
||||||
- [ ] 提现申请列表
|
|
||||||
- [ ] 状态筛选(待审核、已通过、已拒绝)
|
|
||||||
- [ ] 时间范围筛选
|
|
||||||
- [ ] 提现申请详情
|
|
||||||
- [ ] 审核提现申请
|
|
||||||
- [ ] 通过操作
|
|
||||||
- [ ] 拒绝操作(需填写原因)
|
|
||||||
- [ ] 批量审核功能
|
|
||||||
- [ ] 提现记录导出
|
|
||||||
|
|
||||||
### 3.2 佣金提现设置
|
|
||||||
- [ ] 提现参数配置页面
|
|
||||||
- [ ] 最低提现金额
|
|
||||||
- [ ] 提现手续费设置
|
|
||||||
- [ ] 单日提现次数限制
|
|
||||||
- [ ] 提现规则说明
|
|
||||||
- [ ] 配置历史记录
|
|
||||||
- [ ] 参数生效管理
|
|
||||||
|
|
||||||
### 3.3 我的账户(当前登录账号)
|
|
||||||
- [ ] 账户概览页面
|
|
||||||
- [ ] 佣金总额卡片
|
|
||||||
- [ ] 可提现金额卡片
|
|
||||||
- [ ] 待入账金额卡片
|
|
||||||
- [ ] 佣金收入明细
|
|
||||||
- [ ] 提现申请功能
|
|
||||||
- [ ] 收支流水记录
|
|
||||||
- [ ] 佣金统计图表
|
|
||||||
|
|
||||||
### 3.4 收款商户设置
|
|
||||||
- [ ] 支付参数配置页面
|
|
||||||
- [ ] 支付商户信息
|
|
||||||
- [ ] API密钥配置
|
|
||||||
- [ ] 回调地址设置
|
|
||||||
- [ ] 支付方式管理
|
|
||||||
- [ ] 微信支付
|
|
||||||
- [ ] 支付宝
|
|
||||||
- [ ] 银行卡
|
|
||||||
- [ ] 支付测试功能
|
|
||||||
- [ ] 配置安全验证
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛍️ 阶段四:商品管理模块
|
|
||||||
|
|
||||||
### 4.1 号卡管理
|
|
||||||
- [ ] 号卡列表页面
|
|
||||||
- [ ] 号卡信息展示
|
|
||||||
- [ ] 状态筛选
|
|
||||||
- [ ] 新增号卡
|
|
||||||
- [ ] 号卡基础信息
|
|
||||||
- [ ] 运营商选择
|
|
||||||
- [ ] 套餐配置
|
|
||||||
- [ ] 编辑号卡
|
|
||||||
- [ ] 号卡上下架
|
|
||||||
- [ ] 号卡库存管理
|
|
||||||
- [ ] 号卡详情页面
|
|
||||||
|
|
||||||
### 4.2 号卡分配
|
|
||||||
- [ ] 分配记录列表
|
|
||||||
- [ ] 为代理商分配号卡
|
|
||||||
- [ ] 选择代理商
|
|
||||||
- [ ] 选择号卡商品
|
|
||||||
- [ ] 设置分配数量
|
|
||||||
- [ ] 设置佣金模式
|
|
||||||
- [ ] 查看分配详情
|
|
||||||
- [ ] 撤销分配
|
|
||||||
- [ ] 分配统计报表
|
|
||||||
|
|
||||||
### 4.3 套餐系列管理
|
|
||||||
- [ ] 套餐系列列表
|
|
||||||
- [ ] 新增套餐系列
|
|
||||||
- [ ] 系列名称
|
|
||||||
- [ ] 系列描述
|
|
||||||
- [ ] 系列图标
|
|
||||||
- [ ] 编辑套餐系列
|
|
||||||
- [ ] 删除套餐系列
|
|
||||||
- [ ] 套餐系列排序
|
|
||||||
|
|
||||||
### 4.4 套餐管理
|
|
||||||
- [ ] 套餐列表页面
|
|
||||||
- [ ] 权限过滤(管理员看全部,普通用户看自己的)
|
|
||||||
- [ ] 按套餐系列筛选
|
|
||||||
- [ ] 新增套餐
|
|
||||||
- [ ] 套餐基础信息
|
|
||||||
- [ ] 套餐类型(流量、语音、短信)
|
|
||||||
- [ ] 套餐价格
|
|
||||||
- [ ] 有效期设置
|
|
||||||
- [ ] 编辑套餐
|
|
||||||
- [ ] 套餐上下架
|
|
||||||
- [ ] 套餐详情页面
|
|
||||||
|
|
||||||
### 4.5 套餐分配
|
|
||||||
- [ ] 套餐分配列表
|
|
||||||
- [ ] 为直级代理分配套餐
|
|
||||||
- [ ] 选择代理商
|
|
||||||
- [ ] 选择套餐
|
|
||||||
- [ ] 设置佣金模式
|
|
||||||
- [ ] 固定佣金
|
|
||||||
- [ ] 比例佣金
|
|
||||||
- [ ] 查看分配详情
|
|
||||||
- [ ] 修改佣金设置
|
|
||||||
- [ ] 分配统计
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 阶段五:资产管理模块
|
|
||||||
|
|
||||||
### 5.1 单卡信息查询
|
|
||||||
- [ ] ICCID 查询界面
|
|
||||||
- [ ] 单卡详情页面
|
|
||||||
- [ ] 基础信息展示
|
|
||||||
- [ ] 套餐信息
|
|
||||||
- [ ] 使用情况
|
|
||||||
- [ ] 单卡操作功能
|
|
||||||
- [ ] 套餐充值
|
|
||||||
- [ ] 停机/复机
|
|
||||||
- [ ] 查看流量详情
|
|
||||||
- [ ] 更改过期时间
|
|
||||||
- [ ] 转新卡
|
|
||||||
- [ ] 查看停复机记录
|
|
||||||
- [ ] 查看往期订单
|
|
||||||
- [ ] 增减流量
|
|
||||||
- [ ] 变更钱包余额
|
|
||||||
- [ ] 充值支付密码
|
|
||||||
- [ ] 续充
|
|
||||||
- [ ] 设备操作入口
|
|
||||||
|
|
||||||
### 5.2 网卡管理
|
|
||||||
- [ ] 网卡列表页面
|
|
||||||
- [ ] 高级搜索
|
|
||||||
- [ ] 状态筛选
|
|
||||||
- [ ] 批量选择
|
|
||||||
- [ ] 网卡详情页面
|
|
||||||
- [ ] 批量操作入口
|
|
||||||
- [ ] 批量充值
|
|
||||||
- [ ] 批量停复机
|
|
||||||
- [ ] 批量分配
|
|
||||||
- [ ] 网卡导出功能
|
|
||||||
- [ ] 网卡数据统计
|
|
||||||
|
|
||||||
### 5.3 设备管理
|
|
||||||
- [ ] 设备列表页面
|
|
||||||
- [ ] 设备信息展示
|
|
||||||
- [ ] 在线状态
|
|
||||||
- [ ] 设备详情页面
|
|
||||||
- [ ] 设备基础信息
|
|
||||||
- [ ] 绑定卡信息
|
|
||||||
- [ ] 查看设备卡信息
|
|
||||||
- [ ] 修改设备卡绑定
|
|
||||||
- [ ] 设备相关操作
|
|
||||||
- [ ] 设备重启
|
|
||||||
- [ ] 设备诊断
|
|
||||||
- [ ] 设备数据统计
|
|
||||||
|
|
||||||
### 5.4 资产分配
|
|
||||||
- [ ] 资产分配页面
|
|
||||||
- [ ] 设备批量分配
|
|
||||||
- [ ] 选择代理商
|
|
||||||
- [ ] 上传设备列表
|
|
||||||
- [ ] 确认分配信息
|
|
||||||
- [ ] 网卡批量分配
|
|
||||||
- [ ] 选择代理商
|
|
||||||
- [ ] 上传网卡列表(ICCID)
|
|
||||||
- [ ] 自动关联设备处理
|
|
||||||
- [ ] 分配预览和确认
|
|
||||||
- [ ] 分配记录查看
|
|
||||||
- [ ] 分配回滚功能
|
|
||||||
|
|
||||||
### 5.5 换卡申请管理
|
|
||||||
- [ ] 换卡申请列表
|
|
||||||
- [ ] 状态筛选(待处理、已完成、已拒绝)
|
|
||||||
- [ ] 申请详情查看
|
|
||||||
- [ ] 旧卡信息
|
|
||||||
- [ ] 申请原因
|
|
||||||
- [ ] 处理换卡申请
|
|
||||||
- [ ] 填充新 ICCID
|
|
||||||
- [ ] 确认换卡
|
|
||||||
- [ ] 拒绝申请
|
|
||||||
- [ ] 换卡记录追溯
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 阶段六:批量操作模块
|
|
||||||
|
|
||||||
### 6.1 网卡批量导入
|
|
||||||
- [ ] 网卡导入页面
|
|
||||||
- [ ] 模板下载
|
|
||||||
- [ ] Excel 文件上传
|
|
||||||
- [ ] 数据预览
|
|
||||||
- [ ] 导入任务列表
|
|
||||||
- [ ] 任务状态
|
|
||||||
- [ ] 成功/失败统计
|
|
||||||
- [ ] 查看导入详情
|
|
||||||
- [ ] 成功记录
|
|
||||||
- [ ] 失败记录和原因
|
|
||||||
- [ ] 失败数据重新导入
|
|
||||||
|
|
||||||
### 6.2 设备批量导入
|
|
||||||
- [ ] 设备导入页面
|
|
||||||
- [ ] 模板下载
|
|
||||||
- [ ] Excel 文件上传(设备+ICCID关系)
|
|
||||||
- [ ] 数据预览和校验
|
|
||||||
- [ ] 导入任务列表
|
|
||||||
- [ ] 查看导入结果
|
|
||||||
- [ ] 导入失败处理
|
|
||||||
|
|
||||||
### 6.3 线下批量充值
|
|
||||||
- [ ] 批量充值记录列表
|
|
||||||
- [ ] 新建批量充值
|
|
||||||
- [ ] 模板下载
|
|
||||||
- [ ] Excel 上传
|
|
||||||
- [ ] 充值预览
|
|
||||||
- [ ] 确认充值
|
|
||||||
- [ ] 充值详情查看
|
|
||||||
- [ ] 成功列表
|
|
||||||
- [ ] 失败列表
|
|
||||||
- [ ] 充值结果导出
|
|
||||||
|
|
||||||
### 6.4 换卡通知
|
|
||||||
- [ ] 换卡通知列表
|
|
||||||
- [ ] 单独创建换卡通知
|
|
||||||
- [ ] 选择网卡
|
|
||||||
- [ ] 填写通知内容
|
|
||||||
- [ ] 选择通知方式(短信/邮件)
|
|
||||||
- [ ] 批量创建换卡通知
|
|
||||||
- [ ] 上传网卡列表
|
|
||||||
- [ ] 设置通知内容
|
|
||||||
- [ ] 查看通知记录
|
|
||||||
- [ ] 发送状态
|
|
||||||
- [ ] 已读状态
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 阶段七:开发能力和其他设置
|
|
||||||
|
|
||||||
### 7.1 开发能力管理
|
|
||||||
- [ ] 开发能力列表页面
|
|
||||||
- [ ] API 密钥管理
|
|
||||||
- [ ] 生成密钥
|
|
||||||
- [ ] 重置密钥
|
|
||||||
- [ ] 密钥权限设置
|
|
||||||
- [ ] Webhook 配置
|
|
||||||
- [ ] API 文档集成
|
|
||||||
- [ ] API 调用统计
|
|
||||||
|
|
||||||
### 7.2 分佣模板管理
|
|
||||||
- [ ] 分佣模板列表
|
|
||||||
- [ ] 新增分佣模板
|
|
||||||
- [ ] 模板名称
|
|
||||||
- [ ] 分佣规则配置
|
|
||||||
- [ ] 适用范围
|
|
||||||
- [ ] 编辑分佣模板
|
|
||||||
- [ ] 删除分佣模板
|
|
||||||
- [ ] 模板应用记录
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 阶段八:数据统计和报表
|
|
||||||
|
|
||||||
### 8.1 数据概览(Dashboard)
|
|
||||||
- [ ] 总体数据统计卡片
|
|
||||||
- [ ] 网卡总数
|
|
||||||
- [ ] 设备总数
|
|
||||||
- [ ] 今日充值金额
|
|
||||||
- [ ] 今日佣金
|
|
||||||
- [ ] 数据趋势图表
|
|
||||||
- [ ] 充值趋势
|
|
||||||
- [ ] 新增网卡趋势
|
|
||||||
- [ ] 代理商排行榜
|
|
||||||
- [ ] 套餐销售排行
|
|
||||||
|
|
||||||
### 8.2 业务报表
|
|
||||||
- [ ] 充值报表
|
|
||||||
- [ ] 佣金报表
|
|
||||||
- [ ] 代理商业绩报表
|
|
||||||
- [ ] 套餐使用报表
|
|
||||||
- [ ] 报表导出功能
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 阶段九:系统优化和完善
|
|
||||||
|
|
||||||
### 9.1 性能优化
|
|
||||||
- [ ] 长列表虚拟滚动
|
|
||||||
- [ ] 图片懒加载
|
|
||||||
- [ ] 接口请求优化
|
|
||||||
- [ ] 打包体积优化
|
|
||||||
|
|
||||||
### 9.2 用户体验优化
|
|
||||||
- [ ] 页面加载状态
|
|
||||||
- [ ] 错误提示优化
|
|
||||||
- [ ] 操作反馈优化
|
|
||||||
- [ ] 响应式适配
|
|
||||||
|
|
||||||
### 9.3 代码质量
|
|
||||||
- [ ] 代码规范检查
|
|
||||||
- [ ] 单元测试编写
|
|
||||||
- [ ] E2E 测试
|
|
||||||
- [ ] 代码注释完善
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 开发规范
|
|
||||||
|
|
||||||
### 命名规范
|
|
||||||
- 组件名:大驼峰,如 `UserManagement.vue`
|
|
||||||
- 文件名:小写+连字符,如 `user-list.vue`
|
|
||||||
- 接口名:RESTful 风格
|
|
||||||
- 路由名:小写+连字符
|
|
||||||
|
|
||||||
### 代码结构
|
|
||||||
```
|
|
||||||
src/
|
|
||||||
├── views/ # 页面组件
|
|
||||||
├── components/ # 公共组件
|
|
||||||
├── api/ # API 接口
|
|
||||||
├── store/ # 状态管理
|
|
||||||
├── router/ # 路由配置
|
|
||||||
├── utils/ # 工具函数
|
|
||||||
└── types/ # TypeScript 类型定义
|
|
||||||
```
|
|
||||||
|
|
||||||
### Git 提交规范
|
|
||||||
- `feat`: 新功能
|
|
||||||
- `fix`: 修复bug
|
|
||||||
- `docs`: 文档更新
|
|
||||||
- `style`: 代码格式调整
|
|
||||||
- `refactor`: 重构
|
|
||||||
- `test`: 测试相关
|
|
||||||
- `chore`: 构建/工具相关
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 里程碑
|
|
||||||
|
|
||||||
- [ ] **M1**: 基础设施完成(登录、权限) - 预计 3 天
|
|
||||||
- [ ] **M2**: 账号管理模块完成 - 预计 7 天
|
|
||||||
- [ ] **M3**: 财务管理模块完成 - 预计 5 天
|
|
||||||
- [ ] **M4**: 商品管理模块完成 - 预计 5 天
|
|
||||||
- [ ] **M5**: 资产管理模块完成 - 预计 7 天
|
|
||||||
- [ ] **M6**: 批量操作模块完成 - 预计 4 天
|
|
||||||
- [ ] **M7**: 数据统计和系统优化 - 预计 5 天
|
|
||||||
|
|
||||||
**预计总工期**: 36 个工作日
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📌 注意事项
|
|
||||||
|
|
||||||
1. **优先级**:按阶段顺序开发,基础设施 > 核心业务 > 辅助功能
|
|
||||||
2. **接口对接**:等待后端 API 完成后再进行集成
|
|
||||||
3. **数据安全**:涉及敏感数据的操作需要二次确认
|
|
||||||
4. **性能考虑**:列表超过 1000 条需要使用虚拟滚动
|
|
||||||
5. **错误处理**:所有接口调用必须有错误处理
|
|
||||||
6. **权限控制**:每个页面和操作都需要权限验证
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 更新日志
|
|
||||||
|
|
||||||
### 2026-01-09
|
|
||||||
- 创建任务规划文档
|
|
||||||
- 定义开发阶段和任务拆分
|
|
||||||
- 明确开发规范和里程碑
|
|
||||||
42
docs/功能.md
42
docs/功能.md
@@ -1,42 +0,0 @@
|
|||||||
# 物联网卡管理系统 - 功能列表
|
|
||||||
|
|
||||||
## 账号管理模块
|
|
||||||
- 账号管理-客户角色 客户角色用以决定客户能力边界
|
|
||||||
- 账号管理-代理商管理 用以创建代理商以及管理特定代理商账号
|
|
||||||
- 账号管理-企业客户管理 用以创建企业管理账号,只能登录企业端,依赖客户角色
|
|
||||||
- 账号管理-客户账号管理 管理客户(代理商+企业客户)的账号,解绑手机等或针对该账号的操作
|
|
||||||
|
|
||||||
## 账户管理/财务模块
|
|
||||||
- 账户管理-客户账号 查看账号下全部的客户账号的佣金情况以及提现情况
|
|
||||||
- 账户管理/我的财务-佣金提现 管理全部的提现申请
|
|
||||||
- 账户管理-佣金提现设置 设置提现参数,生效最新的一条
|
|
||||||
- 我的财务-我的账户 获取当前登录账号的佣金相关数据(这里不应该跟奇成一样用列表)
|
|
||||||
|
|
||||||
## 我的设置模块
|
|
||||||
- 我的设置-收款商户设置 设置支付参数
|
|
||||||
- 我的设置-开发能力管理 获取开发能力对接参数以及管理
|
|
||||||
- 我的设置-分佣模板 用以创建以及管理分佣模板方便给代理分配产品时设置分佣规则
|
|
||||||
|
|
||||||
## 商品管理模块
|
|
||||||
- 商品管理-号卡管理 新增管理号卡商品,管理基础信息
|
|
||||||
- 商品管理-号卡分配 为特定代理分配号卡商品,同时设置佣金模式
|
|
||||||
- 商品管理-套餐系列管理 新增以及管理套餐系列
|
|
||||||
- 商品管理-套餐管理 新增以及管理套餐系列(只能看到自己的/管理员可以看到全部)
|
|
||||||
- 商品管理-套餐分配 为直级代理分配套餐同时设置佣金模式
|
|
||||||
|
|
||||||
## 资产管理模块
|
|
||||||
- 资产管理-单卡信息 通过ICCID查询单卡相关信息,以及相关操作如,套餐充值,停复机,流量详情,更改过期时间,转新卡,停复机记录,往期订单,增减流量,变更钱包余额,充值支付密码,续充,设备操作
|
|
||||||
- 资产管理-网卡管理 查询网卡信息,提供相关批量操作入口
|
|
||||||
- 资产管理-设备管理 查看设备信息,提供相关操作入口,查看设备卡信息,修改设备卡信息,设备相关操作
|
|
||||||
- 资产管理-资产分配 为特定代理分配网卡,只支持批量操作,批量操作分为两种,一种是设备批量分配,一种是网卡批量分配,如果使用网卡批量分配且网卡有设备信息,那么会把该卡所属设备以及网卡都分配过去
|
|
||||||
- 资产管理-换卡申请 客户提交的换卡申请管理,处理换卡的申请,填充新的iccid
|
|
||||||
|
|
||||||
## 批量操作模块
|
|
||||||
- 网卡管理-批量操作-网卡导入 批量导入iccid,以及查看导入任务情况
|
|
||||||
- 设备管理-批量操作-设备导入 批量导入设备以及iccid关系,查看导入任务情况
|
|
||||||
- 网卡管理-批量操作-线下批量充值 查看批量充值记录,提供批量充值excel导入
|
|
||||||
- 网卡管理-批量操作-换卡通知 可单独/批量新建换卡通知,查看换卡通知记录
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**总计:25个功能模块**
|
|
||||||
364
docs/完成总结.md
364
docs/完成总结.md
@@ -1,364 +0,0 @@
|
|||||||
# 物联网卡管理系统 - 页面开发完成总结
|
|
||||||
|
|
||||||
## 📊 完成概况
|
|
||||||
|
|
||||||
**完成时间**: 2026-01-09
|
|
||||||
**开发进度**: 13/13 页面 (100%)
|
|
||||||
**总计文件**: 13 个 Vue 页面组件
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 已完成的页面列表
|
|
||||||
|
|
||||||
### 1. 账号管理模块 (3个页面)
|
|
||||||
|
|
||||||
#### 1.1 客户角色管理
|
|
||||||
- **文件路径**: `src/views/account-management/customer-role/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 角色列表展示(CRUD操作)
|
|
||||||
- 能力范围配置(使用 ElCheckboxGroup)
|
|
||||||
- 角色启用/禁用状态管理
|
|
||||||
- 应用统计
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElForm, ElCheckboxGroup, ElTag
|
|
||||||
|
|
||||||
#### 1.2 代理商管理
|
|
||||||
- **文件路径**: `src/views/account-management/agent/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 多层级代理商管理(支持3级)
|
|
||||||
- 代理商等级展示(一级/二级/三级)
|
|
||||||
- 子账号管理对话框
|
|
||||||
- 佣金配置(固定/比例佣金)
|
|
||||||
- 状态管理(正常/禁用)
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElDescriptions, ElRadioGroup, ElInputNumber
|
|
||||||
|
|
||||||
#### 1.3 客户账号管理
|
|
||||||
- **文件路径**: `src/views/account-management/customer-account/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 客户账号列表
|
|
||||||
- 账号类型筛选(个人/企业/代理商)
|
|
||||||
- 账号详情查看
|
|
||||||
- 解绑手机、重置密码、启用/禁用操作
|
|
||||||
- 操作记录追踪
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElDescriptions, ElTag, ElButton
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. 财务管理模块 (3个页面)
|
|
||||||
|
|
||||||
#### 2.1 提现管理
|
|
||||||
- **文件路径**: `src/views/finance/withdrawal/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 提现申请列表
|
|
||||||
- 状态筛选(待审核/已通过/已拒绝/已完成)
|
|
||||||
- 批量审核功能(ElTable selection)
|
|
||||||
- 审核/拒绝操作(带原因输入)
|
|
||||||
- 详情对话框展示完整提现信息
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElDescriptions, ElButton, ElTag
|
|
||||||
|
|
||||||
#### 2.2 我的账户
|
|
||||||
- **文件路径**: `src/views/finance/my-account/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 账户概览卡片(4个统计卡片,渐变背景)
|
|
||||||
- 提现申请表单(带手续费自动计算)
|
|
||||||
- 交易流水列表
|
|
||||||
- 类型筛选(全部/收入/提现)
|
|
||||||
- **组件使用**: ElCard, ElForm, ArtTable, ElTag
|
|
||||||
- **样式特色**: 渐变背景统计卡片
|
|
||||||
|
|
||||||
#### 2.3 提现设置
|
|
||||||
- **文件路径**: `src/views/finance/withdrawal-settings/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 提现参数配置
|
|
||||||
- 手续费模式(固定/比例)
|
|
||||||
- 单日提现次数限制
|
|
||||||
- 到账时间设置
|
|
||||||
- 工作日限制开关
|
|
||||||
- 提现时间段设置(ElTimePicker)
|
|
||||||
- 配置历史记录
|
|
||||||
- **组件使用**: ElForm, ElInputNumber, ElRadioGroup, ElSwitch, ElTimePicker, ArtTable
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 设置管理模块 (3个页面)
|
|
||||||
|
|
||||||
#### 3.1 支付商户配置
|
|
||||||
- **文件路径**: `src/views/settings/payment-merchant/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 商户基础信息配置
|
|
||||||
- API配置(AppID, AppSecret, API密钥)
|
|
||||||
- 密钥显示/隐藏切换
|
|
||||||
- 回调地址配置(支付/退款)
|
|
||||||
- 支付方式启用(微信/支付宝/银行卡)
|
|
||||||
- 测试模式开关
|
|
||||||
- 配置说明文档
|
|
||||||
- **组件使用**: ElCard, ElForm, ElInput, ElButton, ElCheckboxGroup, ElSwitch
|
|
||||||
|
|
||||||
#### 3.2 开发者API管理
|
|
||||||
- **文件路径**: `src/views/settings/developer-api/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- API密钥管理(生成/重置/删除)
|
|
||||||
- AppKey/AppSecret 展示(带复制功能)
|
|
||||||
- 密钥显示/隐藏切换
|
|
||||||
- 权限配置(读取/写入/删除)
|
|
||||||
- Webhook配置(URL + 签名密钥)
|
|
||||||
- 事件订阅(多选框)
|
|
||||||
- API调用统计(最近7天)
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElButton, ElTag, ElCheckboxGroup
|
|
||||||
- **交互特色**: 一键复制到剪贴板
|
|
||||||
|
|
||||||
#### 3.3 分佣模板管理
|
|
||||||
- **文件路径**: `src/views/settings/commission-template/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 分佣模板 CRUD
|
|
||||||
- 分佣模式(固定佣金/比例佣金)
|
|
||||||
- 佣金规则配置
|
|
||||||
- 适用范围设置
|
|
||||||
- 应用次数统计
|
|
||||||
- 应用记录查看
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElForm, ElRadioGroup, ElInputNumber, ElTag
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. 批量操作模块 (3个页面)
|
|
||||||
|
|
||||||
#### 4.1 网卡批量导入
|
|
||||||
- **文件路径**: `src/views/batch/sim-import/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- Excel模板下载
|
|
||||||
- 拖拽上传(ElUpload drag)
|
|
||||||
- 导入说明提示(ElAlert)
|
|
||||||
- 导入记录列表
|
|
||||||
- 导入进度展示(ElProgress)
|
|
||||||
- 导入状态(处理中/完成/失败)
|
|
||||||
- 详情查看(成功数/失败数/失败原因)
|
|
||||||
- 失败数据下载
|
|
||||||
- **组件使用**: ElCard, ElUpload, ArtTable, ElProgress, ElTag, ElDescriptions
|
|
||||||
|
|
||||||
#### 4.2 设备批量导入
|
|
||||||
- **文件路径**: `src/views/batch/device-import/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 设备批量导入(带ICCID绑定)
|
|
||||||
- 导入统计卡片(今日导入/成功绑定/失败数/成功率)
|
|
||||||
- 状态筛选
|
|
||||||
- 导入进度跟踪
|
|
||||||
- 失败明细表格
|
|
||||||
- 已绑定ICCID统计
|
|
||||||
- **组件使用**: ElCard, ElUpload, ArtTable, ElProgress, ElTag, ElTable
|
|
||||||
- **特色**: 统计卡片带图标
|
|
||||||
|
|
||||||
#### 4.3 换卡通知管理
|
|
||||||
- **文件路径**: `src/views/batch/card-change-notice/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 通知列表(标题/类型/状态)
|
|
||||||
- 通知类型(卡片更换/激活/停用/套餐变更)
|
|
||||||
- 目标用户设置(全部/指定/批量导入)
|
|
||||||
- 发送方式(短信/邮件/App推送)
|
|
||||||
- 定时发送功能
|
|
||||||
- 发送进度实时展示
|
|
||||||
- 立即发送操作
|
|
||||||
- 详情查看
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElForm, ElRadioGroup, ElCheckboxGroup, ElUpload, ElProgress
|
|
||||||
- **交互特色**: 实时发送进度动画
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. 产品管理模块 (1个页面)
|
|
||||||
|
|
||||||
#### 5.1 网卡产品管理
|
|
||||||
- **文件路径**: `src/views/product/sim-card/index.vue`
|
|
||||||
- **功能特性**:
|
|
||||||
- 网卡产品 CRUD
|
|
||||||
- 运营商筛选(移动/联通/电信)
|
|
||||||
- 套餐规格配置
|
|
||||||
- 价格设置
|
|
||||||
- 库存管理
|
|
||||||
- 上线/下线状态
|
|
||||||
- **组件使用**: ArtTable, ElDialog, ElForm, ElSelect, ElInputNumber, ElSwitch
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 配置文件更新
|
|
||||||
|
|
||||||
### 1. 路由别名配置
|
|
||||||
**文件**: `src/router/routesAlias.ts`
|
|
||||||
|
|
||||||
新增路由别名:
|
|
||||||
```typescript
|
|
||||||
// 账号管理
|
|
||||||
CustomerRole = '/account-management/customer-role'
|
|
||||||
AgentManagement = '/account-management/agent'
|
|
||||||
CustomerAccount = '/account-management/customer-account'
|
|
||||||
|
|
||||||
// 产品管理
|
|
||||||
SimCardManagement = '/product/sim-card'
|
|
||||||
|
|
||||||
// 财务管理
|
|
||||||
WithdrawalManagement = '/finance/withdrawal'
|
|
||||||
MyAccount = '/finance/my-account'
|
|
||||||
WithdrawalSettings = '/finance/withdrawal-settings'
|
|
||||||
|
|
||||||
// 设置管理
|
|
||||||
PaymentMerchant = '/settings/payment-merchant'
|
|
||||||
DeveloperApi = '/settings/developer-api'
|
|
||||||
CommissionTemplate = '/settings/commission-template'
|
|
||||||
|
|
||||||
// 批量操作
|
|
||||||
SimImport = '/batch/sim-import'
|
|
||||||
DeviceImport = '/batch/device-import'
|
|
||||||
CardChangeNotice = '/batch/card-change-notice'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 异步路由配置
|
|
||||||
**文件**: `src/router/routes/asyncRoutes.ts`
|
|
||||||
|
|
||||||
新增路由模块:
|
|
||||||
- **账号管理模块**: 扩展了3个子路由
|
|
||||||
- **产品管理模块**: 新增模块,1个子路由
|
|
||||||
- **财务管理模块**: 新增模块,3个子路由
|
|
||||||
- **设置管理模块**: 新增模块,3个子路由
|
|
||||||
- **批量操作模块**: 新增模块,3个子路由
|
|
||||||
|
|
||||||
### 3. 国际化配置
|
|
||||||
**文件**: `src/locales/langs/zh.json`
|
|
||||||
|
|
||||||
新增菜单标题:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"menus": {
|
|
||||||
"accountManagement": {
|
|
||||||
"customerRole": "客户角色",
|
|
||||||
"agent": "代理商管理",
|
|
||||||
"customerAccount": "客户账号"
|
|
||||||
},
|
|
||||||
"product": {
|
|
||||||
"title": "产品管理",
|
|
||||||
"simCard": "网卡产品管理"
|
|
||||||
},
|
|
||||||
"finance": {
|
|
||||||
"title": "财务管理",
|
|
||||||
"withdrawal": "提现管理",
|
|
||||||
"myAccount": "我的账户",
|
|
||||||
"withdrawalSettings": "提现设置"
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"title": "设置管理",
|
|
||||||
"paymentMerchant": "支付商户",
|
|
||||||
"developerApi": "开发者API",
|
|
||||||
"commissionTemplate": "分佣模板"
|
|
||||||
},
|
|
||||||
"batch": {
|
|
||||||
"title": "批量操作",
|
|
||||||
"simImport": "网卡批量导入",
|
|
||||||
"deviceImport": "设备批量导入",
|
|
||||||
"cardChangeNotice": "换卡通知"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 开发规范遵循
|
|
||||||
|
|
||||||
### 1. 代码风格
|
|
||||||
- ✅ 使用 Vue 3 Composition API
|
|
||||||
- ✅ 使用 `<script setup>` 语法
|
|
||||||
- ✅ TypeScript 类型定义完整
|
|
||||||
- ✅ 使用 defineOptions 定义组件名称
|
|
||||||
|
|
||||||
### 2. 组件使用
|
|
||||||
- ✅ 优先使用项目自定义组件(ArtTable)
|
|
||||||
- ✅ 使用 Element Plus 组件库
|
|
||||||
- ✅ 统一的表单验证规则
|
|
||||||
- ✅ 统一的对话框样式
|
|
||||||
|
|
||||||
### 3. 数据管理
|
|
||||||
- ✅ 使用 ref 和 reactive 管理状态
|
|
||||||
- ✅ 使用 computed 处理派生数据
|
|
||||||
- ✅ Mock 数据结构完整
|
|
||||||
- ✅ 包含完整的 CRUD 操作
|
|
||||||
|
|
||||||
### 4. 用户体验
|
|
||||||
- ✅ 操作反馈(ElMessage)
|
|
||||||
- ✅ 确认对话框(ElMessageBox)
|
|
||||||
- ✅ 加载状态展示
|
|
||||||
- ✅ 进度条展示
|
|
||||||
- ✅ 标签状态提示
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 界面特色
|
|
||||||
|
|
||||||
### 统计卡片
|
|
||||||
- 渐变背景色
|
|
||||||
- 图标装饰
|
|
||||||
- 数据对比
|
|
||||||
- 响应式布局
|
|
||||||
|
|
||||||
### 表格功能
|
|
||||||
- 搜索过滤
|
|
||||||
- 状态筛选
|
|
||||||
- 批量操作
|
|
||||||
- 排序功能
|
|
||||||
- 分页展示
|
|
||||||
|
|
||||||
### 表单交互
|
|
||||||
- 动态表单项(根据选择显示/隐藏)
|
|
||||||
- 实时验证
|
|
||||||
- 条件渲染
|
|
||||||
- 默认值设置
|
|
||||||
|
|
||||||
### 文件上传
|
|
||||||
- 拖拽上传
|
|
||||||
- 文件类型限制
|
|
||||||
- 大小限制
|
|
||||||
- 模板下载
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 下一步工作建议
|
|
||||||
|
|
||||||
### 1. API 对接
|
|
||||||
- 将所有 Mock 数据替换为真实 API 调用
|
|
||||||
- 统一错误处理
|
|
||||||
- 添加请求拦截器
|
|
||||||
- 实现 Token 刷新机制
|
|
||||||
|
|
||||||
### 2. 权限控制
|
|
||||||
- 按钮级权限控制
|
|
||||||
- 数据权限过滤
|
|
||||||
- 角色权限映射
|
|
||||||
|
|
||||||
### 3. 数据验证
|
|
||||||
- 表单验证规则完善
|
|
||||||
- 后端数据校验
|
|
||||||
- 异常数据处理
|
|
||||||
|
|
||||||
### 4. 性能优化
|
|
||||||
- 列表分页加载
|
|
||||||
- 虚拟滚动
|
|
||||||
- 图片懒加载
|
|
||||||
- 组件懒加载
|
|
||||||
|
|
||||||
### 5. 测试
|
|
||||||
- 单元测试
|
|
||||||
- 集成测试
|
|
||||||
- E2E 测试
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 相关文档
|
|
||||||
|
|
||||||
- [任务规划文档](./任务规划.md)
|
|
||||||
- [页面创建模板](./页面创建模板.md)
|
|
||||||
- [API对接说明](./API对接说明.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ 总结
|
|
||||||
|
|
||||||
本次开发共完成 **13 个页面组件**,涵盖账号管理、财务管理、设置管理、批量操作和产品管理 5 大模块。所有页面均遵循统一的代码规范,使用 Mock 数据进行开发,界面美观、交互流畅,为后续 API 对接和功能扩展打下了坚实基础。
|
|
||||||
|
|
||||||
**开发完成度**: 100% ✅
|
|
||||||
**代码质量**: 优秀 ⭐⭐⭐⭐⭐
|
|
||||||
**可维护性**: 良好 👍
|
|
||||||
875
docs/店铺管理.md
875
docs/店铺管理.md
@@ -1,875 +0,0 @@
|
|||||||
# 在商品管理 /account-management 下面新增一个 店铺管理 需要对接的API如下, 然后页面样式可以参考 /account-management/account
|
|
||||||
|
|
||||||
# 店铺列表
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shops:
|
|
||||||
get:
|
|
||||||
summary: 店铺列表
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 店铺管理
|
|
||||||
- 店铺管理
|
|
||||||
parameters:
|
|
||||||
- name: page
|
|
||||||
in: query
|
|
||||||
description: 页码
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 页码
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
- name: page_size
|
|
||||||
in: query
|
|
||||||
description: 每页数量
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 每页数量
|
|
||||||
maximum: 100
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
- name: shop_name
|
|
||||||
in: query
|
|
||||||
description: 店铺名称模糊查询
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 店铺名称模糊查询
|
|
||||||
maxLength: 100
|
|
||||||
type: string
|
|
||||||
- name: shop_code
|
|
||||||
in: query
|
|
||||||
description: 店铺编号模糊查询
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 店铺编号模糊查询
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
- name: parent_id
|
|
||||||
in: query
|
|
||||||
description: 上级店铺ID
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 上级店铺ID
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
- name: level
|
|
||||||
in: query
|
|
||||||
description: 店铺层级 (1-7级)
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 店铺层级 (1-7级)
|
|
||||||
maximum: 7
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
- name: status
|
|
||||||
in: query
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelShopPageResult'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: AiK0MKfrzIq2Np2gS4yVd
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: AiK0MKfrzIq2Np2gS4yVd
|
|
||||||
scopes:
|
|
||||||
AiK0MKfrzIq2Np2gS4yVd:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 店铺管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366339-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelShopPageResult:
|
|
||||||
properties:
|
|
||||||
items:
|
|
||||||
description: 店铺列表
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/ModelShopResponse'
|
|
||||||
type: array
|
|
||||||
nullable: true
|
|
||||||
page:
|
|
||||||
description: 当前页码
|
|
||||||
type: integer
|
|
||||||
size:
|
|
||||||
description: 每页数量
|
|
||||||
type: integer
|
|
||||||
total:
|
|
||||||
description: 总记录数
|
|
||||||
type: integer
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- items
|
|
||||||
- page
|
|
||||||
- size
|
|
||||||
- total
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ModelShopResponse:
|
|
||||||
properties:
|
|
||||||
address:
|
|
||||||
description: 详细地址
|
|
||||||
type: string
|
|
||||||
city:
|
|
||||||
description: 城市
|
|
||||||
type: string
|
|
||||||
contact_name:
|
|
||||||
description: 联系人姓名
|
|
||||||
type: string
|
|
||||||
contact_phone:
|
|
||||||
description: 联系人电话
|
|
||||||
type: string
|
|
||||||
created_at:
|
|
||||||
description: 创建时间
|
|
||||||
type: string
|
|
||||||
district:
|
|
||||||
description: 区县
|
|
||||||
type: string
|
|
||||||
id:
|
|
||||||
description: 店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
level:
|
|
||||||
description: 店铺层级 (1-7级)
|
|
||||||
type: integer
|
|
||||||
parent_id:
|
|
||||||
description: 上级店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
province:
|
|
||||||
description: 省份
|
|
||||||
type: string
|
|
||||||
shop_code:
|
|
||||||
description: 店铺编号
|
|
||||||
type: string
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
updated_at:
|
|
||||||
description: 更新时间
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- address
|
|
||||||
- city
|
|
||||||
- contact_name
|
|
||||||
- contact_phone
|
|
||||||
- created_at
|
|
||||||
- district
|
|
||||||
- id
|
|
||||||
- level
|
|
||||||
- parent_id
|
|
||||||
- province
|
|
||||||
- shop_code
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
- updated_at
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# 创建店铺
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shops:
|
|
||||||
post:
|
|
||||||
summary: 创建店铺
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 店铺管理
|
|
||||||
- 店铺管理
|
|
||||||
parameters: []
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelCreateShopRequest'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelShopResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: CgtLTd_zQ5XPrx3y7BdLh
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: CgtLTd_zQ5XPrx3y7BdLh
|
|
||||||
scopes:
|
|
||||||
CgtLTd_zQ5XPrx3y7BdLh:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 店铺管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366340-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelCreateShopRequest:
|
|
||||||
properties:
|
|
||||||
address:
|
|
||||||
description: 详细地址
|
|
||||||
maxLength: 255
|
|
||||||
type: string
|
|
||||||
city:
|
|
||||||
description: 城市
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
contact_name:
|
|
||||||
description: 联系人姓名
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
contact_phone:
|
|
||||||
description: 联系人电话
|
|
||||||
maxLength: 11
|
|
||||||
minLength: 11
|
|
||||||
type: string
|
|
||||||
district:
|
|
||||||
description: 区县
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
init_password:
|
|
||||||
description: 初始账号密码
|
|
||||||
maxLength: 32
|
|
||||||
minLength: 8
|
|
||||||
type: string
|
|
||||||
init_phone:
|
|
||||||
description: 初始账号手机号
|
|
||||||
maxLength: 11
|
|
||||||
minLength: 11
|
|
||||||
type: string
|
|
||||||
init_username:
|
|
||||||
description: 初始账号用户名
|
|
||||||
maxLength: 50
|
|
||||||
minLength: 3
|
|
||||||
type: string
|
|
||||||
parent_id:
|
|
||||||
description: 上级店铺ID(一级店铺可不填)
|
|
||||||
minimum: 1
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
province:
|
|
||||||
description: 省份
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
shop_code:
|
|
||||||
description: 店铺编号
|
|
||||||
maxLength: 50
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
maxLength: 100
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- init_password
|
|
||||||
- init_phone
|
|
||||||
- init_username
|
|
||||||
- shop_code
|
|
||||||
- shop_name
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- address
|
|
||||||
- city
|
|
||||||
- contact_name
|
|
||||||
- contact_phone
|
|
||||||
- district
|
|
||||||
- init_password
|
|
||||||
- init_phone
|
|
||||||
- init_username
|
|
||||||
- parent_id
|
|
||||||
- province
|
|
||||||
- shop_code
|
|
||||||
- shop_name
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ModelShopResponse:
|
|
||||||
properties:
|
|
||||||
address:
|
|
||||||
description: 详细地址
|
|
||||||
type: string
|
|
||||||
city:
|
|
||||||
description: 城市
|
|
||||||
type: string
|
|
||||||
contact_name:
|
|
||||||
description: 联系人姓名
|
|
||||||
type: string
|
|
||||||
contact_phone:
|
|
||||||
description: 联系人电话
|
|
||||||
type: string
|
|
||||||
created_at:
|
|
||||||
description: 创建时间
|
|
||||||
type: string
|
|
||||||
district:
|
|
||||||
description: 区县
|
|
||||||
type: string
|
|
||||||
id:
|
|
||||||
description: 店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
level:
|
|
||||||
description: 店铺层级 (1-7级)
|
|
||||||
type: integer
|
|
||||||
parent_id:
|
|
||||||
description: 上级店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
province:
|
|
||||||
description: 省份
|
|
||||||
type: string
|
|
||||||
shop_code:
|
|
||||||
description: 店铺编号
|
|
||||||
type: string
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
updated_at:
|
|
||||||
description: 更新时间
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- address
|
|
||||||
- city
|
|
||||||
- contact_name
|
|
||||||
- contact_phone
|
|
||||||
- created_at
|
|
||||||
- district
|
|
||||||
- id
|
|
||||||
- level
|
|
||||||
- parent_id
|
|
||||||
- province
|
|
||||||
- shop_code
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
- updated_at
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
# 删除店铺
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shops/{id}:
|
|
||||||
delete:
|
|
||||||
summary: 删除店铺
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 店铺管理
|
|
||||||
- 店铺管理
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
description: ID
|
|
||||||
required: true
|
|
||||||
example: 0
|
|
||||||
schema:
|
|
||||||
description: ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
responses:
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: ivp0VlbXbNhnY2xcsCWbS
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: ivp0VlbXbNhnY2xcsCWbS
|
|
||||||
scopes:
|
|
||||||
ivp0VlbXbNhnY2xcsCWbS:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 店铺管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366341-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
# 更新店铺
|
|
||||||
|
|
||||||
## OpenAPI Specification
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
openapi: 3.0.1
|
|
||||||
info:
|
|
||||||
title: ''
|
|
||||||
description: ''
|
|
||||||
version: 1.0.0
|
|
||||||
paths:
|
|
||||||
/api/admin/shops/{id}:
|
|
||||||
put:
|
|
||||||
summary: 更新店铺
|
|
||||||
deprecated: false
|
|
||||||
description: ''
|
|
||||||
tags:
|
|
||||||
- 店铺管理
|
|
||||||
- 店铺管理
|
|
||||||
parameters:
|
|
||||||
- name: id
|
|
||||||
in: path
|
|
||||||
description: ID
|
|
||||||
required: true
|
|
||||||
example: 0
|
|
||||||
schema:
|
|
||||||
description: ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelUpdateShopParams'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: OK
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/ModelShopResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'400':
|
|
||||||
description: 请求参数错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: &ref_0
|
|
||||||
$ref: '#/components/schemas/ErrorResponse'
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'401':
|
|
||||||
description: 未认证或认证已过期
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'403':
|
|
||||||
description: 无权访问
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
'500':
|
|
||||||
description: 服务器内部错误
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema: *ref_0
|
|
||||||
headers: {}
|
|
||||||
x-apifox-name: ''
|
|
||||||
security:
|
|
||||||
- BearerAuth: []
|
|
||||||
x-apifox:
|
|
||||||
schemeGroups:
|
|
||||||
- id: 2BoHA3GVAX6-zd8XmFxez
|
|
||||||
schemeIds:
|
|
||||||
- BearerAuth
|
|
||||||
required: true
|
|
||||||
use:
|
|
||||||
id: 2BoHA3GVAX6-zd8XmFxez
|
|
||||||
scopes:
|
|
||||||
2BoHA3GVAX6-zd8XmFxez:
|
|
||||||
BearerAuth: []
|
|
||||||
x-apifox-folder: 店铺管理
|
|
||||||
x-apifox-status: released
|
|
||||||
x-run-in-apifox: https://app.apifox.com/web/project/7591618/apis/api-408366342-run
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
ModelUpdateShopParams:
|
|
||||||
properties:
|
|
||||||
address:
|
|
||||||
description: 详细地址
|
|
||||||
maxLength: 255
|
|
||||||
type: string
|
|
||||||
city:
|
|
||||||
description: 城市
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
contact_name:
|
|
||||||
description: 联系人姓名
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
contact_phone:
|
|
||||||
description: 联系人电话
|
|
||||||
maxLength: 11
|
|
||||||
minLength: 11
|
|
||||||
type: string
|
|
||||||
district:
|
|
||||||
description: 区县
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
province:
|
|
||||||
description: 省份
|
|
||||||
maxLength: 50
|
|
||||||
type: string
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
maxLength: 100
|
|
||||||
minLength: 1
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
required:
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- address
|
|
||||||
- city
|
|
||||||
- contact_name
|
|
||||||
- contact_phone
|
|
||||||
- district
|
|
||||||
- province
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ModelShopResponse:
|
|
||||||
properties:
|
|
||||||
address:
|
|
||||||
description: 详细地址
|
|
||||||
type: string
|
|
||||||
city:
|
|
||||||
description: 城市
|
|
||||||
type: string
|
|
||||||
contact_name:
|
|
||||||
description: 联系人姓名
|
|
||||||
type: string
|
|
||||||
contact_phone:
|
|
||||||
description: 联系人电话
|
|
||||||
type: string
|
|
||||||
created_at:
|
|
||||||
description: 创建时间
|
|
||||||
type: string
|
|
||||||
district:
|
|
||||||
description: 区县
|
|
||||||
type: string
|
|
||||||
id:
|
|
||||||
description: 店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
level:
|
|
||||||
description: 店铺层级 (1-7级)
|
|
||||||
type: integer
|
|
||||||
parent_id:
|
|
||||||
description: 上级店铺ID
|
|
||||||
minimum: 0
|
|
||||||
type: integer
|
|
||||||
nullable: true
|
|
||||||
province:
|
|
||||||
description: 省份
|
|
||||||
type: string
|
|
||||||
shop_code:
|
|
||||||
description: 店铺编号
|
|
||||||
type: string
|
|
||||||
shop_name:
|
|
||||||
description: 店铺名称
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
description: 状态 (0:禁用, 1:启用)
|
|
||||||
type: integer
|
|
||||||
updated_at:
|
|
||||||
description: 更新时间
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- address
|
|
||||||
- city
|
|
||||||
- contact_name
|
|
||||||
- contact_phone
|
|
||||||
- created_at
|
|
||||||
- district
|
|
||||||
- id
|
|
||||||
- level
|
|
||||||
- parent_id
|
|
||||||
- province
|
|
||||||
- shop_code
|
|
||||||
- shop_name
|
|
||||||
- status
|
|
||||||
- updated_at
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
ErrorResponse:
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
description: 错误码
|
|
||||||
type: integer
|
|
||||||
message:
|
|
||||||
description: 错误消息
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
description: 时间戳
|
|
||||||
format: date-time
|
|
||||||
type: string
|
|
||||||
required:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
type: object
|
|
||||||
x-apifox-orders:
|
|
||||||
- code
|
|
||||||
- message
|
|
||||||
- timestamp
|
|
||||||
x-apifox-ignore-properties: []
|
|
||||||
x-apifox-folder: ''
|
|
||||||
securitySchemes:
|
|
||||||
BearerAuth:
|
|
||||||
bearerFormat: JWT
|
|
||||||
scheme: bearer
|
|
||||||
type: jwt
|
|
||||||
servers:
|
|
||||||
- url: https://cmp-api.xm-iot.cn
|
|
||||||
description: 测试环境
|
|
||||||
security: []
|
|
||||||
|
|
||||||
```
|
|
||||||
194
docs/开发进度.md
194
docs/开发进度.md
@@ -1,194 +0,0 @@
|
|||||||
# 物联网卡管理系统 - 开发进度
|
|
||||||
|
|
||||||
> 更新时间: 2026-01-09
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 已完成的页面(5个)
|
|
||||||
|
|
||||||
### 账号管理模块 (4/4) ✅
|
|
||||||
- [x] **客户角色管理** `account-management/customer-role/index.vue`
|
|
||||||
- 角色列表、新增、编辑、删除
|
|
||||||
- 能力边界配置(多选框)
|
|
||||||
- 状态管理
|
|
||||||
|
|
||||||
- [x] **代理商管理** `account-management/agent/index.vue`
|
|
||||||
- 代理商列表(多级代理)
|
|
||||||
- 新增/编辑代理商
|
|
||||||
- 账号管理(子账号列表)
|
|
||||||
- 佣金配置(固定/比例佣金)
|
|
||||||
|
|
||||||
- [x] **客户账号管理** `account-management/customer-account/index.vue`
|
|
||||||
- 客户账号列表
|
|
||||||
- 账号详情(Descriptions)
|
|
||||||
- 解绑手机、重置密码
|
|
||||||
- 禁用/启用账号
|
|
||||||
- 操作记录查看
|
|
||||||
|
|
||||||
- [x] **企业客户管理** `account-management/customer/index.vue`
|
|
||||||
- ⚠️ 已存在,无需创建
|
|
||||||
|
|
||||||
### 商品管理模块 (1/2)
|
|
||||||
- [x] **号卡管理** `product/sim-card/index.vue`
|
|
||||||
- 号卡列表(运营商筛选)
|
|
||||||
- 新增/编辑号卡
|
|
||||||
- 上架/下架管理
|
|
||||||
- 库存管理
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📋 待创建的页面(10个)
|
|
||||||
|
|
||||||
### 1. 账号管理模块
|
|
||||||
- [ ] **客户账号佣金** `account-management/customer-commission/index.vue`
|
|
||||||
- 佣金统计卡片
|
|
||||||
- 佣金明细列表
|
|
||||||
- 提现记录
|
|
||||||
|
|
||||||
### 2. 财务管理模块 (0/3)
|
|
||||||
- [ ] **佣金提现管理** `finance/withdrawal/index.vue`
|
|
||||||
- 提现申请列表(状态筛选)
|
|
||||||
- 审核功能(通过/拒绝)
|
|
||||||
- 批量审核
|
|
||||||
- 提现记录导出
|
|
||||||
|
|
||||||
- [ ] **佣金提现设置** `finance/withdrawal-settings/index.vue`
|
|
||||||
- 提现参数配置(最低金额、手续费等)
|
|
||||||
- 配置历史记录
|
|
||||||
|
|
||||||
- [ ] **我的账户** `finance/my-account/index.vue`
|
|
||||||
- 账户概览(卡片统计)
|
|
||||||
- 佣金收入明细
|
|
||||||
- 提现申请功能
|
|
||||||
- 收支流水记录
|
|
||||||
|
|
||||||
### 3. 设置管理模块 (0/3)
|
|
||||||
- [ ] **收款商户设置** `settings/payment-merchant/index.vue`
|
|
||||||
- 支付商户信息配置
|
|
||||||
- API 密钥管理
|
|
||||||
- 回调地址设置
|
|
||||||
- 支付方式管理(微信/支付宝/银行卡)
|
|
||||||
|
|
||||||
- [ ] **开发能力管理** `settings/developer-api/index.vue`
|
|
||||||
- API 密钥列表
|
|
||||||
- 生成/重置密钥
|
|
||||||
- Webhook 配置
|
|
||||||
- API 调用统计
|
|
||||||
|
|
||||||
- [ ] **分佣模板** `settings/commission-template/index.vue`
|
|
||||||
- 分佣模板列表
|
|
||||||
- 新增/编辑模板
|
|
||||||
- 分佣规则配置
|
|
||||||
- 模板应用记录
|
|
||||||
|
|
||||||
### 4. 商品管理模块
|
|
||||||
- [ ] **号卡分配** `product/sim-card-assign/index.vue`
|
|
||||||
- 分配记录列表
|
|
||||||
- 为代理商分配号卡
|
|
||||||
- 设置佣金模式
|
|
||||||
- 分配统计报表
|
|
||||||
|
|
||||||
### 5. 批量操作模块 (0/3)
|
|
||||||
- [ ] **网卡批量导入** `batch/sim-import/index.vue`
|
|
||||||
- Excel 上传(模板下载)
|
|
||||||
- 导入任务列表
|
|
||||||
- 导入结果查看(成功/失败)
|
|
||||||
|
|
||||||
- [ ] **设备批量导入** `batch/device-import/index.vue`
|
|
||||||
- Excel 上传(设备+ICCID关系)
|
|
||||||
- 导入任务列表
|
|
||||||
- 导入结果查看
|
|
||||||
|
|
||||||
- [ ] **换卡通知** `batch/card-change-notice/index.vue`
|
|
||||||
- 换卡通知列表
|
|
||||||
- 单独/批量创建通知
|
|
||||||
- 通知方式选择(短信/邮件)
|
|
||||||
- 通知记录查看
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📂 项目文件结构
|
|
||||||
|
|
||||||
```
|
|
||||||
src/views/
|
|
||||||
├── account-management/ # 账号管理
|
|
||||||
│ ├── customer/ ✅ 已存在
|
|
||||||
│ ├── customer-role/ ✅ 已创建
|
|
||||||
│ ├── agent/ ✅ 已创建
|
|
||||||
│ ├── customer-account/ ✅ 已创建
|
|
||||||
│ └── customer-commission/ ❌ 待创建
|
|
||||||
├── finance/ # 财务管理
|
|
||||||
│ ├── withdrawal/ ❌ 待创建
|
|
||||||
│ ├── withdrawal-settings/ ❌ 待创建
|
|
||||||
│ └── my-account/ ❌ 待创建
|
|
||||||
├── settings/ # 设置管理
|
|
||||||
│ ├── payment-merchant/ ❌ 待创建
|
|
||||||
│ ├── developer-api/ ❌ 待创建
|
|
||||||
│ └── commission-template/ ❌ 待创建
|
|
||||||
├── product/ # 商品管理
|
|
||||||
│ ├── sim-card/ ✅ 已创建
|
|
||||||
│ └── sim-card-assign/ ❌ 待创建
|
|
||||||
└── batch/ # 批量操作
|
|
||||||
├── sim-import/ ❌ 待创建
|
|
||||||
├── device-import/ ❌ 待创建
|
|
||||||
└── card-change-notice/ ❌ 待创建
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 快速创建指南
|
|
||||||
|
|
||||||
### 方法1: 使用模板快速创建
|
|
||||||
参考 `docs/页面创建模板.md` 中的标准模板,只需:
|
|
||||||
1. 复制模板代码
|
|
||||||
2. 修改组件名和接口定义
|
|
||||||
3. 调整 Mock 数据
|
|
||||||
4. 根据需求调整表单和表格
|
|
||||||
|
|
||||||
### 方法2: 复制现有页面修改
|
|
||||||
推荐复制以下页面作为基础:
|
|
||||||
- **列表+CRUD**: 复制 `customer-role/index.vue`
|
|
||||||
- **复杂列表+多对话框**: 复制 `agent/index.vue`
|
|
||||||
- **详情查看**: 复制 `customer-account/index.vue`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📌 下一步工作
|
|
||||||
|
|
||||||
### 优先级1 - 核心业务页面
|
|
||||||
1. ⚠️ 财务管理模块(3个页面)- 核心功能
|
|
||||||
2. ⚠️ 商品管理 - 号卡分配
|
|
||||||
|
|
||||||
### 优先级2 - 辅助功能页面
|
|
||||||
3. 设置管理模块(3个页面)
|
|
||||||
4. 批量操作模块(3个页面)
|
|
||||||
5. 客户账号佣金页面
|
|
||||||
|
|
||||||
### 优先级3 - 路由和配置
|
|
||||||
6. 更新 `src/router/routesAlias.ts` 添加新路由别名
|
|
||||||
7. 更新 `src/router/routes/asyncRoutes.ts` 添加路由配置
|
|
||||||
8. 测试所有页面是否正常访问
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ 已完成的文档
|
|
||||||
|
|
||||||
- ✅ `docs/任务规划.md` - 完整的任务规划和分解
|
|
||||||
- ✅ `docs/页面创建模板.md` - 标准页面模板和快速创建指南
|
|
||||||
- ✅ `docs/开发进度.md` - 当前开发进度追踪
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 开发建议
|
|
||||||
|
|
||||||
1. **使用模板**:严格按照模板创建,保持代码风格一致
|
|
||||||
2. **Mock 数据**:确保 Mock 数据完整且真实,方便测试
|
|
||||||
3. **组件复用**:最大化使用 ArtTable 等现有组件
|
|
||||||
4. **渐进开发**:先完成基础功能,再添加高级特性
|
|
||||||
5. **及时测试**:每完成一个页面立即测试功能
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**总体完成度**: 5/15 页面 (33.3%)
|
|
||||||
|
|
||||||
继续加油!🚀
|
|
||||||
378
docs/新功能.md
378
docs/新功能.md
@@ -1,378 +0,0 @@
|
|||||||
# 在账号管理下面新增一个平台账号, 然后需要写页面对接API, 页面样式可以参考/system/account 都需要token认证 逻辑啥的跟/system/account差不多
|
|
||||||
|
|
||||||
## 1. 平台账号列表
|
|
||||||
|
|
||||||
```json
|
|
||||||
"url": "/api/admin/platform-accounts",
|
|
||||||
"methods": "GET",
|
|
||||||
Query 参数:
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* 页码
|
|
||||||
*/
|
|
||||||
page?: number;
|
|
||||||
/**
|
|
||||||
* 每页数量
|
|
||||||
*/
|
|
||||||
page_size?: number;
|
|
||||||
/**
|
|
||||||
* 手机号模糊查询
|
|
||||||
*/
|
|
||||||
phone?: string;
|
|
||||||
/**
|
|
||||||
* 状态 (0:禁用, 1:启用)
|
|
||||||
*/
|
|
||||||
status?: number | null;
|
|
||||||
/**
|
|
||||||
* 用户名模糊查询
|
|
||||||
*/
|
|
||||||
username?: string;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
返回响应
|
|
||||||
/**
|
|
||||||
* ModelAccountPageResult
|
|
||||||
*/
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* 账号列表
|
|
||||||
*/
|
|
||||||
items?: ModelAccountResponse[] | null;
|
|
||||||
/**
|
|
||||||
* 当前页码
|
|
||||||
*/
|
|
||||||
page?: number;
|
|
||||||
/**
|
|
||||||
* 每页数量
|
|
||||||
*/
|
|
||||||
size?: number;
|
|
||||||
/**
|
|
||||||
* 总记录数
|
|
||||||
*/
|
|
||||||
total?: number;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ModelAccountResponse
|
|
||||||
*/
|
|
||||||
export interface ModelAccountResponse {
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
created_at?: string;
|
|
||||||
/**
|
|
||||||
* 创建人ID
|
|
||||||
*/
|
|
||||||
creator?: number;
|
|
||||||
/**
|
|
||||||
* 关联企业ID
|
|
||||||
*/
|
|
||||||
enterprise_id?: number | null;
|
|
||||||
/**
|
|
||||||
* 账号ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
phone?: string;
|
|
||||||
/**
|
|
||||||
* 关联店铺ID
|
|
||||||
*/
|
|
||||||
shop_id?: number | null;
|
|
||||||
/**
|
|
||||||
* 状态 (0:禁用, 1:启用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 更新时间
|
|
||||||
*/
|
|
||||||
updated_at?: string;
|
|
||||||
/**
|
|
||||||
* 更新人ID
|
|
||||||
*/
|
|
||||||
updater?: number;
|
|
||||||
/**
|
|
||||||
* 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)
|
|
||||||
*/
|
|
||||||
user_type?: number;
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username?: string;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"created_at": "string",
|
|
||||||
"creator": 0,
|
|
||||||
"enterprise_id": 0,
|
|
||||||
"id": 0,
|
|
||||||
"phone": "string",
|
|
||||||
"shop_id": 0,
|
|
||||||
"status": 0,
|
|
||||||
"updated_at": "string",
|
|
||||||
"updater": 0,
|
|
||||||
"user_type": 0,
|
|
||||||
"username": "string"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"page": 0,
|
|
||||||
"size": 0,
|
|
||||||
"total": 0
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. 新增平台账号
|
|
||||||
url: /api/admin/platform-accounts,
|
|
||||||
methods: post,
|
|
||||||
Body 参数
|
|
||||||
/**
|
|
||||||
* ModelCreateAccountRequest
|
|
||||||
*/
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* 关联企业ID(企业账号必填)
|
|
||||||
*/
|
|
||||||
enterprise_id?: number | null;
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
password: string;
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
phone: string;
|
|
||||||
/**
|
|
||||||
* 关联店铺ID(代理账号必填)
|
|
||||||
*/
|
|
||||||
shop_id?: number | null;
|
|
||||||
/**
|
|
||||||
* 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)
|
|
||||||
*/
|
|
||||||
user_type: number;
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username: string;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
返回响应:
|
|
||||||
/**
|
|
||||||
* ModelAccountResponse
|
|
||||||
*/
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
created_at?: string;
|
|
||||||
/**
|
|
||||||
* 创建人ID
|
|
||||||
*/
|
|
||||||
creator?: number;
|
|
||||||
/**
|
|
||||||
* 关联企业ID
|
|
||||||
*/
|
|
||||||
enterprise_id?: number | null;
|
|
||||||
/**
|
|
||||||
* 账号ID
|
|
||||||
*/
|
|
||||||
id?: number;
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
phone?: string;
|
|
||||||
/**
|
|
||||||
* 关联店铺ID
|
|
||||||
*/
|
|
||||||
shop_id?: number | null;
|
|
||||||
/**
|
|
||||||
* 状态 (0:禁用, 1:启用)
|
|
||||||
*/
|
|
||||||
status?: number;
|
|
||||||
/**
|
|
||||||
* 更新时间
|
|
||||||
*/
|
|
||||||
updated_at?: string;
|
|
||||||
/**
|
|
||||||
* 更新人ID
|
|
||||||
*/
|
|
||||||
updater?: number;
|
|
||||||
/**
|
|
||||||
* 用户类型 (1:超级管理员, 2:平台用户, 3:代理账号, 4:企业账号)
|
|
||||||
*/
|
|
||||||
user_type?: number;
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username?: string;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
*
|
|
||||||
{
|
|
||||||
"created_at": "string",
|
|
||||||
"creator": 0,
|
|
||||||
"enterprise_id": 0,
|
|
||||||
"id": 0,
|
|
||||||
"phone": "string",
|
|
||||||
"shop_id": 0,
|
|
||||||
"status": 0,
|
|
||||||
"updated_at": "string",
|
|
||||||
"updater": 0,
|
|
||||||
"user_type": 0,
|
|
||||||
"username": "string"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 3. 移除角色
|
|
||||||
url: /api/admin/platform-accounts/{account_id}/roles/{role_id}
|
|
||||||
methods: delete
|
|
||||||
path参数:
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* 账号ID
|
|
||||||
*/
|
|
||||||
account_id: number;
|
|
||||||
/**
|
|
||||||
* 角色ID
|
|
||||||
*/
|
|
||||||
role_id: number;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
* 返回响应:
|
|
||||||
* {
|
|
||||||
"code": 0,
|
|
||||||
"message": "string",
|
|
||||||
"timestamp": "2019-08-24T14:15:22.123Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## 4. 删除平台账号
|
|
||||||
url: /api/admin/platform-accounts/{id}
|
|
||||||
methods: delete
|
|
||||||
path参数:
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* ID
|
|
||||||
*/
|
|
||||||
id: number;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
响应:
|
|
||||||
* {
|
|
||||||
"code": 0,
|
|
||||||
"message": "string",
|
|
||||||
"timestamp": "2019-08-24T14:15:22.123Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## 5. 获取平台账号详情
|
|
||||||
url: /api/admin/platform-accounts/{id}
|
|
||||||
methods: get
|
|
||||||
响应: {
|
|
||||||
"created_at": "string",
|
|
||||||
"creator": 0,
|
|
||||||
"enterprise_id": 0,
|
|
||||||
"id": 0,
|
|
||||||
"phone": "string",
|
|
||||||
"shop_id": 0,
|
|
||||||
"status": 0,
|
|
||||||
"updated_at": "string",
|
|
||||||
"updater": 0,
|
|
||||||
"user_type": 0,
|
|
||||||
"username": "string"
|
|
||||||
}
|
|
||||||
|
|
||||||
## 6. 编辑平台账号
|
|
||||||
url: /api/admin/platform-accounts/{id}
|
|
||||||
methods: put
|
|
||||||
body:/**
|
|
||||||
* ModelUpdateAccountParams
|
|
||||||
*/
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* 密码
|
|
||||||
*/
|
|
||||||
password?: null | string;
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
phone?: null | string;
|
|
||||||
/**
|
|
||||||
* 状态 (0:禁用, 1:启用)
|
|
||||||
*/
|
|
||||||
status?: number | null;
|
|
||||||
/**
|
|
||||||
* 用户名
|
|
||||||
*/
|
|
||||||
username?: null | string;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
响应: {
|
|
||||||
"created_at": "string",
|
|
||||||
"creator": 0,
|
|
||||||
"enterprise_id": 0,
|
|
||||||
"id": 0,
|
|
||||||
"phone": "string",
|
|
||||||
"shop_id": 0,
|
|
||||||
"status": 0,
|
|
||||||
"updated_at": "string",
|
|
||||||
"updater": 0,
|
|
||||||
"user_type": 0,
|
|
||||||
"username": "string"
|
|
||||||
}
|
|
||||||
|
|
||||||
## 7. 修改密码
|
|
||||||
url: /api/admin/platform-accounts/{id}/password
|
|
||||||
methods: put
|
|
||||||
body:{
|
|
||||||
"new_password": "stringst"
|
|
||||||
}
|
|
||||||
response: {
|
|
||||||
"code": 0,
|
|
||||||
"message": "string",
|
|
||||||
"timestamp": "2019-08-24T14:15:22.123Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 8. 获取账号角色
|
|
||||||
url: /api/admin/platform-accounts/{id}/roles
|
|
||||||
methods: get
|
|
||||||
响应: [
|
|
||||||
{
|
|
||||||
"creator": 0,
|
|
||||||
"role_desc": "string",
|
|
||||||
"role_name": "string",
|
|
||||||
"role_type": 0,
|
|
||||||
"status": 0,
|
|
||||||
"updater": 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
## 9. 分配角色
|
|
||||||
url: /api/admin/platform-accounts/{id}/roles,
|
|
||||||
methods: post
|
|
||||||
body: {
|
|
||||||
"role_ids": [
|
|
||||||
0
|
|
||||||
]
|
|
||||||
}
|
|
||||||
响应: {
|
|
||||||
"code": 0,
|
|
||||||
"message": "string",
|
|
||||||
"timestamp": "2019-08-24T14:15:22.123Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
## 10. 启用/禁用账号
|
|
||||||
url: /api/admin/platform-accounts/{id}/status
|
|
||||||
methods: put,
|
|
||||||
body: {
|
|
||||||
"status": 0
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# 角色管理中少了三个接口对接
|
|
||||||
|
|
||||||
## 1. 获取角色权限
|
|
||||||
url: /api/admin/roles/{id}/permissions
|
|
||||||
methods: get
|
|
||||||
response: [
|
|
||||||
{
|
|
||||||
"available_for_role_types": "string",
|
|
||||||
"creator": 0,
|
|
||||||
"parent_id": 0,
|
|
||||||
"perm_code": "string",
|
|
||||||
"perm_name": "string",
|
|
||||||
"perm_type": 0,
|
|
||||||
"platform": "string",
|
|
||||||
"sort": 0,
|
|
||||||
"status": 0,
|
|
||||||
"updater": 0,
|
|
||||||
"url": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
/**
|
|
||||||
* ModelPermission
|
|
||||||
*/
|
|
||||||
export interface ApifoxModel {
|
|
||||||
available_for_role_types?: string;
|
|
||||||
creator?: number;
|
|
||||||
parent_id?: number | null;
|
|
||||||
perm_code?: string;
|
|
||||||
perm_name?: string;
|
|
||||||
perm_type?: number;
|
|
||||||
platform?: string;
|
|
||||||
sort?: number;
|
|
||||||
status?: number;
|
|
||||||
updater?: number;
|
|
||||||
url?: string;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
## 2. 分配权限
|
|
||||||
url: /api/admin/roles/{id}/permissions
|
|
||||||
methods: post
|
|
||||||
body: {
|
|
||||||
"perm_ids": [
|
|
||||||
0
|
|
||||||
]
|
|
||||||
}
|
|
||||||
response: {
|
|
||||||
"code": 0,
|
|
||||||
"message": "string",
|
|
||||||
"timestamp": "2019-08-24T14:15:22.123Z"
|
|
||||||
}
|
|
||||||
## 3. 移除权限
|
|
||||||
url: /api/admin/roles/{role_id}/permissions/{perm_id}
|
|
||||||
export interface ApifoxModel {
|
|
||||||
/**
|
|
||||||
* 权限ID
|
|
||||||
*/
|
|
||||||
perm_id: number;
|
|
||||||
/**
|
|
||||||
* 角色ID
|
|
||||||
*/
|
|
||||||
role_id: number;
|
|
||||||
[property: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
methods: delete
|
|
||||||
|
|
||||||
响应: {
|
|
||||||
"code": 0,
|
|
||||||
"message": "string",
|
|
||||||
"timestamp": "2019-08-24T14:15:22.123Z"
|
|
||||||
}
|
|
||||||
6146
docs/部分API.md
6146
docs/部分API.md
File diff suppressed because it is too large
Load Diff
297
docs/页面创建模板.md
297
docs/页面创建模板.md
@@ -1,297 +0,0 @@
|
|||||||
# 页面创建模板
|
|
||||||
|
|
||||||
本文档提供快速创建页面的模板,所有页面遵循统一的风格和结构。
|
|
||||||
|
|
||||||
## 📋 已完成的页面
|
|
||||||
|
|
||||||
### ✅ 账号管理模块
|
|
||||||
- [x] 客户角色管理 (`account-management/customer-role`)
|
|
||||||
- [x] 代理商管理 (`account-management/agent`)
|
|
||||||
- [x] 客户账号管理 (`account-management/customer-account`)
|
|
||||||
- [ ] 客户账号佣金 (`account-management/customer-commission`) - 待创建
|
|
||||||
|
|
||||||
### ✅ 商品管理模块
|
|
||||||
- [x] 号卡管理 (`product/sim-card`)
|
|
||||||
- [ ] 号卡分配 (`product/sim-card-assign`) - 待创建
|
|
||||||
|
|
||||||
## 🔨 待创建的页面
|
|
||||||
|
|
||||||
### 财务管理模块 (`finance/`)
|
|
||||||
1. **佣金提现管理** (`withdrawal/index.vue`)
|
|
||||||
2. **佣金提现设置** (`withdrawal-settings/index.vue`)
|
|
||||||
3. **我的账户** (`my-account/index.vue`)
|
|
||||||
|
|
||||||
### 设置管理模块 (`settings/`)
|
|
||||||
1. **收款商户设置** (`payment-merchant/index.vue`)
|
|
||||||
2. **开发能力管理** (`developer-api/index.vue`)
|
|
||||||
3. **分佣模板** (`commission-template/index.vue`)
|
|
||||||
|
|
||||||
### 批量操作模块 (`batch/`)
|
|
||||||
1. **网卡批量导入** (`sim-import/index.vue`)
|
|
||||||
2. **设备批量导入** (`device-import/index.vue`)
|
|
||||||
3. **换卡通知** (`card-change-notice/index.vue`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 标准页面模板
|
|
||||||
|
|
||||||
### 基础列表页面模板
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<div class="page-content">
|
|
||||||
<!-- 搜索栏 -->
|
|
||||||
<ElRow>
|
|
||||||
<ElCol :xs="24" :sm="12" :lg="6">
|
|
||||||
<ElInput v-model="searchQuery" placeholder="搜索关键词" clearable></ElInput>
|
|
||||||
</ElCol>
|
|
||||||
<div style="width: 12px"></div>
|
|
||||||
<ElCol :xs="24" :sm="12" :lg="6" class="el-col2">
|
|
||||||
<ElButton v-ripple @click="handleSearch">搜索</ElButton>
|
|
||||||
<ElButton v-ripple @click="showDialog('add')">新增</ElButton>
|
|
||||||
</ElCol>
|
|
||||||
</ElRow>
|
|
||||||
|
|
||||||
<!-- 表格 -->
|
|
||||||
<ArtTable :data="filteredData" index>
|
|
||||||
<template #default>
|
|
||||||
<ElTableColumn label="名称" prop="name" />
|
|
||||||
<ElTableColumn label="编码" prop="code" />
|
|
||||||
<ElTableColumn label="状态" prop="status">
|
|
||||||
<template #default="scope">
|
|
||||||
<ElTag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
|
||||||
{{ scope.row.status === 'active' ? '启用' : '禁用' }}
|
|
||||||
</ElTag>
|
|
||||||
</template>
|
|
||||||
</ElTableColumn>
|
|
||||||
<ElTableColumn label="创建时间" prop="createTime" width="180" />
|
|
||||||
<ElTableColumn fixed="right" label="操作" width="180">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-button link @click="showDialog('edit', scope.row)">编辑</el-button>
|
|
||||||
<el-button link @click="handleDelete(scope.row)">删除</el-button>
|
|
||||||
</template>
|
|
||||||
</ElTableColumn>
|
|
||||||
</template>
|
|
||||||
</ArtTable>
|
|
||||||
|
|
||||||
<!-- 新增/编辑对话框 -->
|
|
||||||
<ElDialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
:title="dialogType === 'add' ? '新增' : '编辑'"
|
|
||||||
width="600px"
|
|
||||||
align-center
|
|
||||||
>
|
|
||||||
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
|
|
||||||
<ElFormItem label="名称" prop="name">
|
|
||||||
<ElInput v-model="form.name" placeholder="请输入名称" />
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem label="编码" prop="code">
|
|
||||||
<ElInput v-model="form.code" placeholder="请输入编码" />
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem label="状态">
|
|
||||||
<ElSwitch v-model="form.status" active-value="active" inactive-value="inactive" />
|
|
||||||
</ElFormItem>
|
|
||||||
</ElForm>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<ElButton @click="dialogVisible = false">取消</ElButton>
|
|
||||||
<ElButton type="primary" @click="handleSubmit(formRef)">提交</ElButton>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</ElDialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
|
||||||
|
|
||||||
defineOptions({ name: 'YourPageName' })
|
|
||||||
|
|
||||||
interface DataItem {
|
|
||||||
id?: string
|
|
||||||
name: string
|
|
||||||
code: string
|
|
||||||
status: 'active' | 'inactive'
|
|
||||||
createTime?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mock 数据
|
|
||||||
const mockData = ref<DataItem[]>([
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
name: '示例数据1',
|
|
||||||
code: 'CODE001',
|
|
||||||
status: 'active',
|
|
||||||
createTime: '2026-01-01 10:00:00'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const searchQuery = ref('')
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const dialogType = ref<'add' | 'edit'>('add')
|
|
||||||
const formRef = ref<FormInstance>()
|
|
||||||
|
|
||||||
const form = reactive<DataItem>({
|
|
||||||
name: '',
|
|
||||||
code: '',
|
|
||||||
status: 'active'
|
|
||||||
})
|
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
|
||||||
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
|
||||||
code: [{ required: true, message: '请输入编码', trigger: 'blur' }]
|
|
||||||
})
|
|
||||||
|
|
||||||
const filteredData = computed(() => {
|
|
||||||
if (!searchQuery.value) return mockData.value
|
|
||||||
return mockData.value.filter((item) =>
|
|
||||||
item.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleSearch = () => {}
|
|
||||||
|
|
||||||
const showDialog = (type: 'add' | 'edit', row?: DataItem) => {
|
|
||||||
dialogType.value = type
|
|
||||||
dialogVisible.value = true
|
|
||||||
if (type === 'edit' && row) {
|
|
||||||
Object.assign(form, row)
|
|
||||||
} else {
|
|
||||||
Object.assign(form, { name: '', code: '', status: 'active' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async (formEl: FormInstance | undefined) => {
|
|
||||||
if (!formEl) return
|
|
||||||
await formEl.validate((valid) => {
|
|
||||||
if (valid) {
|
|
||||||
if (dialogType.value === 'add') {
|
|
||||||
mockData.value.push({
|
|
||||||
...form,
|
|
||||||
id: Date.now().toString(),
|
|
||||||
createTime: new Date().toLocaleString('zh-CN')
|
|
||||||
})
|
|
||||||
ElMessage.success('新增成功')
|
|
||||||
} else {
|
|
||||||
const index = mockData.value.findIndex((item) => item.id === form.id)
|
|
||||||
if (index !== -1) mockData.value[index] = { ...form }
|
|
||||||
ElMessage.success('修改成功')
|
|
||||||
}
|
|
||||||
dialogVisible.value = false
|
|
||||||
formEl.resetFields()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDelete = (row: DataItem) => {
|
|
||||||
ElMessageBox.confirm('确定删除吗?', '删除确认', {
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'error'
|
|
||||||
}).then(() => {
|
|
||||||
const index = mockData.value.findIndex((item) => item.id === row.id)
|
|
||||||
if (index !== -1) mockData.value.splice(index, 1)
|
|
||||||
ElMessage.success('删除成功')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.page-content {
|
|
||||||
// 自定义样式
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 快速创建步骤
|
|
||||||
|
|
||||||
1. **复制模板**:复制上面的标准模板
|
|
||||||
2. **修改组件名**:修改 `defineOptions({ name: 'YourPageName' })`
|
|
||||||
3. **调整接口**:根据业务需求修改 `DataItem` 接口
|
|
||||||
4. **修改 Mock 数据**:替换 `mockData` 中的示例数据
|
|
||||||
5. **调整表单字段**:根据需求增删表单项
|
|
||||||
6. **调整表格列**:修改 `ElTableColumn` 配置
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 常用组件
|
|
||||||
|
|
||||||
### 1. ArtTable - 表格组件
|
|
||||||
```vue
|
|
||||||
<ArtTable :data="tableData" index>
|
|
||||||
<template #default>
|
|
||||||
<ElTableColumn label="列名" prop="propName" />
|
|
||||||
</template>
|
|
||||||
</ArtTable>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 搜索栏布局
|
|
||||||
```vue
|
|
||||||
<ElRow>
|
|
||||||
<ElCol :xs="24" :sm="12" :lg="6">
|
|
||||||
<ElInput v-model="search" placeholder="搜索" clearable />
|
|
||||||
</ElCol>
|
|
||||||
<div style="width: 12px"></div>
|
|
||||||
<ElCol :xs="24" :sm="12" :lg="6">
|
|
||||||
<ElSelect v-model="filter" placeholder="筛选" clearable style="width: 100%">
|
|
||||||
<ElOption label="选项1" value="1" />
|
|
||||||
</ElSelect>
|
|
||||||
</ElCol>
|
|
||||||
<div style="width: 12px"></div>
|
|
||||||
<ElCol :xs="24" :sm="12" :lg="6" class="el-col2">
|
|
||||||
<ElButton v-ripple>搜索</ElButton>
|
|
||||||
</ElCol>
|
|
||||||
</ElRow>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 状态标签
|
|
||||||
```vue
|
|
||||||
<ElTag :type="getStatusType(status)">
|
|
||||||
{{ getStatusText(status) }}
|
|
||||||
</ElTag>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 操作按钮
|
|
||||||
```vue
|
|
||||||
<el-button link @click="handleEdit(row)">编辑</el-button>
|
|
||||||
<el-button link type="danger" @click="handleDelete(row)">删除</el-button>
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 💡 开发规范
|
|
||||||
|
|
||||||
1. **命名规范**
|
|
||||||
- 组件名:大驼峰 `YourComponent`
|
|
||||||
- 变量名:小驼峰 `yourVariable`
|
|
||||||
- 文件名:小写+连字符 `your-file.vue`
|
|
||||||
|
|
||||||
2. **Mock 数据格式**
|
|
||||||
- 统一使用 `ref<Type[]>([])` 定义
|
|
||||||
- 包含 `id`, `createTime` 等公共字段
|
|
||||||
- 数据应具有代表性,便于测试
|
|
||||||
|
|
||||||
3. **表单验证**
|
|
||||||
- 必填字段添加 `required` 规则
|
|
||||||
- 手机号/邮箱使用正则验证
|
|
||||||
- 提供友好的错误提示
|
|
||||||
|
|
||||||
4. **用户体验**
|
|
||||||
- 操作前使用 `ElMessageBox.confirm` 确认
|
|
||||||
- 操作后使用 `ElMessage` 提示结果
|
|
||||||
- 表单提交后关闭对话框并重置
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 下一步
|
|
||||||
|
|
||||||
1. 根据模板快速创建剩余页面
|
|
||||||
2. 完善 Mock 数据使其更真实
|
|
||||||
3. 添加路由配置
|
|
||||||
4. 测试页面功能
|
|
||||||
5. 优化用户体验
|
|
||||||
|
|
||||||
祝开发顺利!🚀
|
|
||||||
433
docs/项目完成总结.md
433
docs/项目完成总结.md
@@ -1,433 +0,0 @@
|
|||||||
# 物联网卡管理系统 - 完整项目总结
|
|
||||||
|
|
||||||
## 📊 完成概况
|
|
||||||
|
|
||||||
**完成时间**: 2026-01-09
|
|
||||||
**开发进度**: 18/18 页面 (100%)
|
|
||||||
**总计文件**: 18 个 Vue 页面组件
|
|
||||||
**状态**: ✅ 全部完成
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✅ 新创建的页面列表(18个)
|
|
||||||
|
|
||||||
### 第一批:基础模块(13个页面)
|
|
||||||
|
|
||||||
#### 1. 账号管理模块 (3个)
|
|
||||||
1. **客户角色管理** - `src/views/account-management/customer-role/index.vue`
|
|
||||||
2. **代理商管理** - `src/views/account-management/agent/index.vue`
|
|
||||||
3. **客户账号管理** - `src/views/account-management/customer-account/index.vue`
|
|
||||||
|
|
||||||
#### 2. 财务管理模块 (3个)
|
|
||||||
4. **提现管理** - `src/views/finance/withdrawal/index.vue`
|
|
||||||
5. **我的账户** - `src/views/finance/my-account/index.vue`
|
|
||||||
6. **提现设置** - `src/views/finance/withdrawal-settings/index.vue`
|
|
||||||
|
|
||||||
#### 3. 设置管理模块 (3个)
|
|
||||||
7. **支付商户配置** - `src/views/settings/payment-merchant/index.vue`
|
|
||||||
8. **开发者API管理** - `src/views/settings/developer-api/index.vue`
|
|
||||||
9. **分佣模板管理** - `src/views/settings/commission-template/index.vue`
|
|
||||||
|
|
||||||
#### 4. 批量操作模块 (3个)
|
|
||||||
10. **网卡批量导入** - `src/views/batch/sim-import/index.vue`
|
|
||||||
11. **设备批量导入** - `src/views/batch/device-import/index.vue`
|
|
||||||
12. **换卡通知管理** - `src/views/batch/card-change-notice/index.vue`
|
|
||||||
|
|
||||||
#### 5. 产品管理模块 (1个)
|
|
||||||
13. **网卡产品管理** - `src/views/product/sim-card/index.vue`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 第二批:补充模块(5个页面)
|
|
||||||
|
|
||||||
#### 6. 账号管理扩展 (2个)
|
|
||||||
14. **企业客户管理** - `src/views/account-management/enterprise-customer/index.vue`
|
|
||||||
- 创建企业管理账号,只能登录企业端
|
|
||||||
- 依赖客户角色,决定能力边界
|
|
||||||
- 营业执照上传,统一社会信用代码管理
|
|
||||||
- 角色分配和初始余额设置
|
|
||||||
|
|
||||||
15. **客户账号佣金** - `src/views/account-management/customer-commission/index.vue`
|
|
||||||
- 查看账号下全部客户的佣金情况
|
|
||||||
- 提现情况统计和查询
|
|
||||||
- 佣金明细和提现记录
|
|
||||||
- 统计卡片展示(总佣金、已提现、待提现)
|
|
||||||
|
|
||||||
#### 7. 商品管理扩展 (1个)
|
|
||||||
16. **号卡分配** - `src/views/product/sim-card-assign/index.vue`
|
|
||||||
- 为特定代理分配号卡商品
|
|
||||||
- 设置分佣模式(固定/比例/模板)
|
|
||||||
- 特殊折扣设置
|
|
||||||
- 分配记录和取消分配功能
|
|
||||||
|
|
||||||
#### 8. 资产管理模块 (2个)
|
|
||||||
17. **资产分配** - `src/views/asset-management/asset-assign/index.vue`
|
|
||||||
- 支持三种分配模式:网卡批量分配、设备批量分配、网卡+设备分配
|
|
||||||
- 网卡有设备信息时,可同时分配网卡和设备
|
|
||||||
- 批量选择和分配给代理商
|
|
||||||
- 分配记录和批次管理
|
|
||||||
|
|
||||||
18. **换卡申请管理** - `src/views/asset-management/card-replacement-request/index.vue`
|
|
||||||
- 客户提交的换卡申请管理
|
|
||||||
- 处理换卡申请,填充新ICCID
|
|
||||||
- 新卡验证和自动换卡操作
|
|
||||||
- 申请审核(通过/拒绝)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 已存在的页面(复用)
|
|
||||||
|
|
||||||
项目中以下页面已经存在,功能完整,无需重复创建:
|
|
||||||
|
|
||||||
### 卡片管理(card-management)
|
|
||||||
- ✓ 单卡信息 - `card-management/single-card`
|
|
||||||
- ✓ 网卡管理 - `card-management/card-list`
|
|
||||||
- ✓ 网卡明细 - `card-management/card-detail`
|
|
||||||
- ✓ 网卡分配 - `card-management/card-assign`
|
|
||||||
- ✓ 停机管理 - `card-management/card-shutdown`
|
|
||||||
- ✓ 我的网卡 - `card-management/my-cards`
|
|
||||||
- ✓ 线下批量充值 - `card-management/offline-batch-recharge`
|
|
||||||
- ✓ 网卡转接 - `card-management/card-transfer`
|
|
||||||
- ✓ 换卡管理 - `card-management/card-replacement`
|
|
||||||
- ✓ 套餐赠送 - `card-management/package-gift`
|
|
||||||
- ✓ 换卡网卡 - `card-management/card-change-card`
|
|
||||||
|
|
||||||
### 套餐管理(package-management)
|
|
||||||
- ✓ 新建套餐 - `package-management/package-create`
|
|
||||||
- ✓ 批量管理 - `package-management/package-batch`
|
|
||||||
- ✓ 我的套餐 - `package-management/package-list`
|
|
||||||
- ✓ 套餐变更 - `package-management/package-change`
|
|
||||||
- ✓ 套餐分配 - `package-management/package-assign`
|
|
||||||
- ✓ 套餐系列 - `package-management/package-series`
|
|
||||||
- ✓ 套餐佣金 - `package-management/package-commission`
|
|
||||||
|
|
||||||
### 设备管理(device-management)
|
|
||||||
- ✓ 设备管理 - `device-management/devices`
|
|
||||||
|
|
||||||
### 客户管理(account-management)
|
|
||||||
- ✓ 客户管理 - `account-management/customer`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔄 功能与页面对应关系
|
|
||||||
|
|
||||||
根据你提供的完整需求,所有功能已全部实现:
|
|
||||||
|
|
||||||
| 序号 | 功能名称 | 对应页面 | 状态 |
|
|
||||||
|------|---------|---------|------|
|
|
||||||
| 1 | 账号管理-客户角色 | account-management/customer-role | ✅ 已创建 |
|
|
||||||
| 2 | 账号管理-代理商管理 | account-management/agent | ✅ 已创建 |
|
|
||||||
| 3 | 账号管理-企业客户管理 | account-management/enterprise-customer | ✅ 已创建 |
|
|
||||||
| 4 | 账号管理-客户账号管理 | account-management/customer-account | ✅ 已创建 |
|
|
||||||
| 5 | 账户管理-客户账号佣金 | account-management/customer-commission | ✅ 已创建 |
|
|
||||||
| 6 | 账户管理-佣金提现 | finance/withdrawal | ✅ 已创建 |
|
|
||||||
| 7 | 账户管理-佣金提现设置 | finance/withdrawal-settings | ✅ 已创建 |
|
|
||||||
| 8 | 我的财务-我的账户 | finance/my-account | ✅ 已创建 |
|
|
||||||
| 9 | 我的设置-收款商户设置 | settings/payment-merchant | ✅ 已创建 |
|
|
||||||
| 10 | 我的设置-开发能力管理 | settings/developer-api | ✅ 已创建 |
|
|
||||||
| 11 | 我的设置-分佣模板 | settings/commission-template | ✅ 已创建 |
|
|
||||||
| 12 | 商品管理-号卡管理 | product/sim-card | ✅ 已创建 |
|
|
||||||
| 13 | 商品管理-号卡分配 | product/sim-card-assign | ✅ 已创建 |
|
|
||||||
| 14 | 商品管理-套餐系列管理 | package-management/package-series | ✅ 已存在 |
|
|
||||||
| 15 | 商品管理-套餐管理 | package-management/package-list | ✅ 已存在 |
|
|
||||||
| 16 | 商品管理-套餐分配 | package-management/package-assign | ✅ 已存在 |
|
|
||||||
| 17 | 资产管理-单卡信息 | card-management/single-card | ✅ 已存在 |
|
|
||||||
| 18 | 资产管理-网卡管理 | card-management/card-list | ✅ 已存在 |
|
|
||||||
| 19 | 资产管理-设备管理 | device-management/devices | ✅ 已存在 |
|
|
||||||
| 20 | 资产管理-资产分配 | asset-management/asset-assign | ✅ 已创建 |
|
|
||||||
| 21 | 资产管理-换卡申请 | asset-management/card-replacement-request | ✅ 已创建 |
|
|
||||||
| 22 | 批量操作-网卡导入 | batch/sim-import | ✅ 已创建 |
|
|
||||||
| 23 | 批量操作-设备导入 | batch/device-import | ✅ 已创建 |
|
|
||||||
| 24 | 批量操作-线下批量充值 | card-management/offline-batch-recharge | ✅ 已存在 |
|
|
||||||
| 25 | 批量操作-换卡通知 | batch/card-change-notice | ✅ 已创建 |
|
|
||||||
|
|
||||||
**总计:25个功能全部实现 ✅**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔧 配置文件更新
|
|
||||||
|
|
||||||
### 1. 路由别名配置
|
|
||||||
**文件**: `src/router/routesAlias.ts`
|
|
||||||
|
|
||||||
新增路由别名:
|
|
||||||
```typescript
|
|
||||||
// 账号管理(扩展)
|
|
||||||
EnterpriseCustomer = '/account-management/enterprise-customer'
|
|
||||||
CustomerCommission = '/account-management/customer-commission'
|
|
||||||
|
|
||||||
// 产品管理(扩展)
|
|
||||||
SimCardAssign = '/product/sim-card-assign'
|
|
||||||
|
|
||||||
// 资产管理(新增模块)
|
|
||||||
AssetAssign = '/asset-management/asset-assign'
|
|
||||||
CardReplacementRequest = '/asset-management/card-replacement-request'
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 异步路由配置
|
|
||||||
**文件**: `src/router/routes/asyncRoutes.ts`
|
|
||||||
|
|
||||||
新增路由模块:
|
|
||||||
- 账号管理模块:扩展2个子路由(企业客户、客户佣金)
|
|
||||||
- 产品管理模块:扩展1个子路由(号卡分配)
|
|
||||||
- 资产管理模块:新增模块,2个子路由(资产分配、换卡申请)
|
|
||||||
|
|
||||||
### 3. 国际化配置
|
|
||||||
**文件**: `src/locales/langs/zh.json`
|
|
||||||
|
|
||||||
新增菜单标题:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"menus": {
|
|
||||||
"accountManagement": {
|
|
||||||
"enterpriseCustomer": "企业客户管理",
|
|
||||||
"customerCommission": "客户账号佣金"
|
|
||||||
},
|
|
||||||
"product": {
|
|
||||||
"simCardAssign": "号卡分配"
|
|
||||||
},
|
|
||||||
"assetManagement": {
|
|
||||||
"title": "资产管理",
|
|
||||||
"assetAssign": "资产分配",
|
|
||||||
"cardReplacementRequest": "换卡申请"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 页面功能特性
|
|
||||||
|
|
||||||
### 🔑 核心功能亮点
|
|
||||||
|
|
||||||
#### 1. 企业客户管理(EnterpriseCustomer)
|
|
||||||
- ✨ 企业信息完整管理(企业名称、统一社会信用代码、地址)
|
|
||||||
- 📄 营业执照上传功能
|
|
||||||
- 👤 联系人信息管理
|
|
||||||
- 🔐 企业端独立登录账号(不能登录管理端)
|
|
||||||
- 🎭 角色分配,依赖客户角色决定能力边界
|
|
||||||
- 💰 初始余额设置
|
|
||||||
- 📊 卡片和设备数量统计
|
|
||||||
- ✅ 状态管理(正常/禁用/待审核)
|
|
||||||
|
|
||||||
#### 2. 客户账号佣金(CustomerCommission)
|
|
||||||
- 📈 统计卡片展示(客户总数、累计佣金、已提现、待提现)
|
|
||||||
- 🔍 多维度筛选(客户类型、佣金范围)
|
|
||||||
- 💵 佣金明细查看(来源、订单号、佣金金额、比例)
|
|
||||||
- 📜 提现记录追踪(提现单号、金额、手续费、状态)
|
|
||||||
- 📊 排序功能(按佣金、提现金额排序)
|
|
||||||
- 📤 数据导出功能
|
|
||||||
|
|
||||||
#### 3. 号卡分配(SimCardAssign)
|
|
||||||
- 🎯 为代理商分配号卡产品
|
|
||||||
- 💰 三种分佣模式:
|
|
||||||
- 固定佣金(每张固定金额)
|
|
||||||
- 比例佣金(按百分比)
|
|
||||||
- 模板佣金(使用预设模板)
|
|
||||||
- 🎁 特殊折扣设置
|
|
||||||
- 📊 库存管理和分配数量追踪
|
|
||||||
- 📝 分配记录查询
|
|
||||||
- ❌ 取消分配功能(恢复库存)
|
|
||||||
|
|
||||||
#### 4. 资产分配(AssetAssign)
|
|
||||||
- 🔀 三种分配模式:
|
|
||||||
- 网卡批量分配(仅分配网卡)
|
|
||||||
- 设备批量分配(仅分配设备)
|
|
||||||
- 网卡+设备分配(网卡有绑定设备时同时分配)
|
|
||||||
- ✅ 批量选择功能
|
|
||||||
- 🎯 分配给指定代理商
|
|
||||||
- 📝 分配说明和备注
|
|
||||||
- 📊 分配历史记录
|
|
||||||
- ⚠️ 资产所有权转移警告
|
|
||||||
|
|
||||||
#### 5. 换卡申请管理(CardReplacementRequest)
|
|
||||||
- 📈 统计卡片(待处理、处理中、已完成、已拒绝)
|
|
||||||
- 🔄 状态流转:待处理 → 处理中 → 已完成
|
|
||||||
- 🆕 填充新卡ICCID功能
|
|
||||||
- ✅ ICCID验证(长度、是否已使用)
|
|
||||||
- ❌ 申请拒绝(需填写拒绝原因)
|
|
||||||
- 📊 申请详情查看
|
|
||||||
- 🔍 多条件筛选(状态、日期范围)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎨 统一设计规范
|
|
||||||
|
|
||||||
### UI组件使用
|
|
||||||
- ✅ ArtTable - 自定义表格组件
|
|
||||||
- ✅ ElCard - 卡片容器
|
|
||||||
- ✅ ElDialog - 对话框
|
|
||||||
- ✅ ElForm - 表单
|
|
||||||
- ✅ ElDescriptions - 描述列表
|
|
||||||
- ✅ ElTag - 标签
|
|
||||||
- ✅ ElProgress - 进度条
|
|
||||||
- ✅ ElUpload - 文件上传
|
|
||||||
|
|
||||||
### 交互模式
|
|
||||||
- ✅ 搜索 + 筛选 + 操作按钮布局
|
|
||||||
- ✅ 列表 + 详情对话框模式
|
|
||||||
- ✅ 确认对话框(删除、状态变更)
|
|
||||||
- ✅ 表单验证和错误提示
|
|
||||||
- ✅ 加载状态和进度展示
|
|
||||||
|
|
||||||
### 数据展示
|
|
||||||
- ✅ 统计卡片(带图标和渐变色)
|
|
||||||
- ✅ 状态标签(不同颜色区分)
|
|
||||||
- ✅ 金额格式化显示
|
|
||||||
- ✅ 时间格式化显示
|
|
||||||
- ✅ 空状态提示
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 如何访问新页面
|
|
||||||
|
|
||||||
开发服务器运行在 `http://localhost:3006`
|
|
||||||
|
|
||||||
### 账号管理模块
|
|
||||||
- `/account-management/customer-role` - 客户角色
|
|
||||||
- `/account-management/agent` - 代理商管理
|
|
||||||
- `/account-management/customer-account` - 客户账号管理
|
|
||||||
- `/account-management/enterprise-customer` - 企业客户管理 ⭐ 新增
|
|
||||||
- `/account-management/customer-commission` - 客户账号佣金 ⭐ 新增
|
|
||||||
|
|
||||||
### 财务管理模块
|
|
||||||
- `/finance/withdrawal` - 提现管理
|
|
||||||
- `/finance/my-account` - 我的账户
|
|
||||||
- `/finance/withdrawal-settings` - 提现设置
|
|
||||||
|
|
||||||
### 设置管理模块
|
|
||||||
- `/settings/payment-merchant` - 支付商户
|
|
||||||
- `/settings/developer-api` - 开发者API
|
|
||||||
- `/settings/commission-template` - 分佣模板
|
|
||||||
|
|
||||||
### 商品管理模块
|
|
||||||
- `/product/sim-card` - 网卡产品管理
|
|
||||||
- `/product/sim-card-assign` - 号卡分配 ⭐ 新增
|
|
||||||
|
|
||||||
### 资产管理模块
|
|
||||||
- `/asset-management/asset-assign` - 资产分配 ⭐ 新增
|
|
||||||
- `/asset-management/card-replacement-request` - 换卡申请 ⭐ 新增
|
|
||||||
|
|
||||||
### 批量操作模块
|
|
||||||
- `/batch/sim-import` - 网卡批量导入
|
|
||||||
- `/batch/device-import` - 设备批量导入
|
|
||||||
- `/batch/card-change-notice` - 换卡通知
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 开发统计
|
|
||||||
|
|
||||||
### 代码规模
|
|
||||||
- **Vue组件**: 18个
|
|
||||||
- **总代码行数**: 约 6000+ 行
|
|
||||||
- **TypeScript接口**: 50+ 个
|
|
||||||
- **Mock数据**: 完整覆盖
|
|
||||||
|
|
||||||
### 开发时间
|
|
||||||
- **第一批页面**: 13个(约2小时)
|
|
||||||
- **第二批页面**: 5个(约1小时)
|
|
||||||
- **配置更新**: 路由+国际化(约30分钟)
|
|
||||||
- **总计**: 约3.5小时
|
|
||||||
|
|
||||||
### 功能覆盖率
|
|
||||||
- ✅ CRUD操作: 100%
|
|
||||||
- ✅ 搜索筛选: 100%
|
|
||||||
- ✅ 状态管理: 100%
|
|
||||||
- ✅ 表单验证: 100%
|
|
||||||
- ✅ 数据统计: 100%
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎯 下一步工作建议
|
|
||||||
|
|
||||||
### 1. API 对接 🔌
|
|
||||||
- [ ] 将所有 Mock 数据替换为真实 API 调用
|
|
||||||
- [ ] 统一错误处理和提示
|
|
||||||
- [ ] 添加请求拦截器和响应拦截器
|
|
||||||
- [ ] 实现 Token 刷新机制
|
|
||||||
- [ ] 处理接口超时和重试
|
|
||||||
|
|
||||||
### 2. 权限控制 🔐
|
|
||||||
- [ ] 按钮级权限控制(v-permission 指令)
|
|
||||||
- [ ] 数据权限过滤(根据用户角色)
|
|
||||||
- [ ] 路由权限守卫(动态路由注册)
|
|
||||||
- [ ] 操作日志记录
|
|
||||||
|
|
||||||
### 3. 数据验证 ✅
|
|
||||||
- [ ] 完善表单验证规则
|
|
||||||
- [ ] 后端数据校验
|
|
||||||
- [ ] 异常数据处理
|
|
||||||
- [ ] 防重复提交
|
|
||||||
|
|
||||||
### 4. 性能优化 ⚡
|
|
||||||
- [ ] 列表虚拟滚动(大数据量)
|
|
||||||
- [ ] 组件懒加载
|
|
||||||
- [ ] 图片懒加载
|
|
||||||
- [ ] 防抖节流
|
|
||||||
- [ ] 缓存策略
|
|
||||||
|
|
||||||
### 5. 用户体验 ✨
|
|
||||||
- [ ] 骨架屏loading
|
|
||||||
- [ ] 空状态优化
|
|
||||||
- [ ] 错误页面优化
|
|
||||||
- [ ] 操作引导(新手引导)
|
|
||||||
- [ ] 快捷键支持
|
|
||||||
|
|
||||||
### 6. 测试 🧪
|
|
||||||
- [ ] 单元测试(Vitest)
|
|
||||||
- [ ] 集成测试
|
|
||||||
- [ ] E2E 测试(Playwright)
|
|
||||||
- [ ] 性能测试
|
|
||||||
- [ ] 兼容性测试
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📚 相关文档
|
|
||||||
|
|
||||||
- [任务规划文档](./任务规划.md)
|
|
||||||
- [页面创建模板](./页面创建模板.md)
|
|
||||||
- [API对接说明](./API对接说明.md)
|
|
||||||
- [功能需求文档](./功能.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ 项目亮点
|
|
||||||
|
|
||||||
### 1. 完整性 ✅
|
|
||||||
- 25个功能需求全部实现
|
|
||||||
- 页面布局统一美观
|
|
||||||
- 交互流程完整合理
|
|
||||||
|
|
||||||
### 2. 规范性 📐
|
|
||||||
- 代码风格统一
|
|
||||||
- TypeScript 类型完整
|
|
||||||
- 组件复用率高
|
|
||||||
- 命名规范清晰
|
|
||||||
|
|
||||||
### 3. 可维护性 🔧
|
|
||||||
- 模块化清晰
|
|
||||||
- Mock数据结构完整
|
|
||||||
- 注释清晰
|
|
||||||
- 易于扩展
|
|
||||||
|
|
||||||
### 4. 用户体验 🎨
|
|
||||||
- 界面美观大方
|
|
||||||
- 操作流程顺畅
|
|
||||||
- 反馈及时明确
|
|
||||||
- 状态提示清晰
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 总结
|
|
||||||
|
|
||||||
本次开发共完成 **18 个新页面组件**,配合项目中已有的页面,完整实现了物联网卡管理系统的全部 **25 个功能模块**。
|
|
||||||
|
|
||||||
**开发完成度**: 100% ✅
|
|
||||||
**代码质量**: 优秀 ⭐⭐⭐⭐⭐
|
|
||||||
**可维护性**: 优秀 👍
|
|
||||||
**用户体验**: 优秀 🎨
|
|
||||||
|
|
||||||
所有页面均遵循统一的代码规范,使用 Mock 数据进行开发,界面美观、交互流畅,为后续 API 对接和功能扩展打下了坚实基础。
|
|
||||||
|
|
||||||
项目已经具备完整的功能框架,可以直接对接后端API进行真实数据调试。恭喜项目顺利完成!🎊
|
|
||||||
136
openspec/changes/update-exchange-flow-direct-type/design.md
Normal file
136
openspec/changes/update-exchange-flow-direct-type/design.md
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
## Context
|
||||||
|
|
||||||
|
现有换货管理系统仅支持物流换货流程,包含:创建 → 待填写信息 → 待发货 → 已发货 → 已完成 五个阶段。部分场景下(如现场换货、远程换货等),不需要物流环节,直接完成换货即可。
|
||||||
|
|
||||||
|
后端已实现直接换货类型的数据库字段和 API 接口升级,前端需要适配新的接口规范和 UI 交互。
|
||||||
|
|
||||||
|
## Goals / Non-Goals
|
||||||
|
|
||||||
|
### Goals
|
||||||
|
|
||||||
|
- 支持创建直接换货单,自动完成换货流程
|
||||||
|
- 适配后端新增的 flow_type、shipped_at、completed_at 字段
|
||||||
|
- 根据流程类型动态控制 UI 展示和操作权限
|
||||||
|
- 保持向后兼容,历史数据正常展示
|
||||||
|
|
||||||
|
### Non-Goals
|
||||||
|
|
||||||
|
- 不涉及客户端换货接口改造
|
||||||
|
- 不修改换货单状态定义
|
||||||
|
- 不改变物流换货的原有流程逻辑
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
### 1. 流程类型枚举定义
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export enum ExchangeFlowType {
|
||||||
|
SHIPPING = 'shipping', // 物流换货
|
||||||
|
DIRECT = 'direct' // 直接换货
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EXCHANGE_FLOW_TYPE_MAP = {
|
||||||
|
[ExchangeFlowType.SHIPPING]: '物流换货',
|
||||||
|
[ExchangeFlowType.DIRECT]: '直接换货'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rationale**: 使用枚举统一管理流程类型,避免硬编码字符串,方便维护和扩展。
|
||||||
|
|
||||||
|
### 2. 创建表单的条件渲染
|
||||||
|
|
||||||
|
使用 `v-if` 根据选中的 flow_type 动态显示字段:
|
||||||
|
|
||||||
|
- flow_type = 'direct' 时,显示"新资产标识符"和"是否迁移数据"
|
||||||
|
- flow_type = 'shipping' 时,隐藏这些字段
|
||||||
|
|
||||||
|
**Rationale**: 符合 Element Plus 表单最佳实践,避免不必要的字段提交。
|
||||||
|
|
||||||
|
**Alternatives considered**:
|
||||||
|
- 使用 `v-show` 隐藏:会导致隐藏字段仍参与表单验证
|
||||||
|
- 使用动态表单项:增加复杂度,不够直观
|
||||||
|
|
||||||
|
### 3. 详情页按钮权限控制
|
||||||
|
|
||||||
|
在详情页组件中定义计算属性:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const canShip = computed(() =>
|
||||||
|
exchange.value.flow_type === 'shipping' && exchange.value.status === 2
|
||||||
|
)
|
||||||
|
|
||||||
|
const canComplete = computed(() =>
|
||||||
|
exchange.value.flow_type === 'shipping' && exchange.value.status === 3
|
||||||
|
)
|
||||||
|
|
||||||
|
const canCancel = computed(() =>
|
||||||
|
exchange.value.flow_type === 'shipping' && [1, 2].includes(exchange.value.status)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rationale**: 将权限逻辑集中在计算属性中,模板中直接使用 `v-if`,代码清晰且易于测试。
|
||||||
|
|
||||||
|
### 4. 信息区块隐藏策略
|
||||||
|
|
||||||
|
对于 direct 类型,收货信息和物流信息区块采用以下策略:
|
||||||
|
|
||||||
|
- **选择方案**: 使用 `v-if="exchange.flow_type === 'shipping'"` 完全隐藏
|
||||||
|
- **原因**: direct 类型这些字段为 null,显示空白区块或"不适用"会造成页面冗余
|
||||||
|
|
||||||
|
**Alternatives considered**:
|
||||||
|
- 显示"不适用"占位:增加不必要的视觉噪音
|
||||||
|
- 显示空区块:用户体验不佳
|
||||||
|
|
||||||
|
### 5. API 错误处理
|
||||||
|
|
||||||
|
后端对不合法操作返回 400 错误,前端需要:
|
||||||
|
|
||||||
|
1. 在操作按钮级别根据 flow_type 和 status 做前置检查(优先)
|
||||||
|
2. 对后端返回的错误消息直接展示(兜底)
|
||||||
|
|
||||||
|
**Rationale**: 前置检查提供更好的用户体验,后端错误处理作为安全兜底。
|
||||||
|
|
||||||
|
## Risks / Trade-offs
|
||||||
|
|
||||||
|
### Risk: 历史数据 flow_type 为空
|
||||||
|
|
||||||
|
**Mitigation**: 后端承诺 flow_type 为空时等同于 'shipping',前端在渲染时做兼容处理:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const flowType = exchange.flow_type || 'shipping'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Trade-off: UI 复杂度增加
|
||||||
|
|
||||||
|
引入流程类型后,详情页的条件渲染逻辑增多。
|
||||||
|
|
||||||
|
**Mitigation**:
|
||||||
|
- 使用计算属性封装权限判断逻辑
|
||||||
|
- 添加单元测试覆盖不同流程类型的渲染场景
|
||||||
|
|
||||||
|
## Migration Plan
|
||||||
|
|
||||||
|
### 阶段 1: API 类型升级(无破坏性)
|
||||||
|
|
||||||
|
- 更新 TypeScript 接口定义
|
||||||
|
- 向后兼容,不影响现有调用
|
||||||
|
|
||||||
|
### 阶段 2: UI 适配(向后兼容)
|
||||||
|
|
||||||
|
- 列表页新增流程类型列和筛选
|
||||||
|
- 详情页新增时间戳展示
|
||||||
|
- 历史数据按 shipping 处理,正常显示
|
||||||
|
|
||||||
|
### 阶段 3: 创建功能升级(新增能力)
|
||||||
|
|
||||||
|
- 新增流程类型选择
|
||||||
|
- 支持创建 direct 类型换货单
|
||||||
|
|
||||||
|
### 阶段 4: 测试与发布
|
||||||
|
|
||||||
|
- 功能测试、回归测试
|
||||||
|
- 灰度发布,监控错误
|
||||||
|
|
||||||
|
## Open Questions
|
||||||
|
|
||||||
|
无
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Change: 换货流程升级 - 新增直接换货类型
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
现有换货流程仅支持物流换货(shipping),需要填写收货信息、发货、确认完成等多个步骤,流程较长。部分场景下需要支持直接换货(direct),即创建后立即完成,无需物流环节,提升换货效率。
|
||||||
|
|
||||||
|
## What Changes
|
||||||
|
|
||||||
|
- **新增** 换货流程类型(flow_type)字段,支持 `shipping`(物流换货)和 `direct`(直接换货)两种类型
|
||||||
|
- **新增** 发货时间(shipped_at)和完成时间(completed_at)字段,用于记录换货流程关键时间节点
|
||||||
|
- **修改** 创建换货单接口,支持选择流程类型和直接换货参数
|
||||||
|
- **修改** 换货单列表接口,新增流程类型筛选和资产标识符模糊查询
|
||||||
|
- **修改** 换货单详情接口,返回流程类型和时间戳信息
|
||||||
|
- **修改** 发货、确认完成、取消换货接口,增加流程类型限制逻辑
|
||||||
|
- **BREAKING** direct 类型换货单不支持发货、确认完成和取消操作
|
||||||
|
- **BREAKING** 取消换货仅支持 shipping 流程且状态为待填写信息或待发货时
|
||||||
|
|
||||||
|
## Impact
|
||||||
|
|
||||||
|
- **Affected specs**: exchange-management(新建)
|
||||||
|
- **Affected code**:
|
||||||
|
- `src/api/modules/exchange.ts` - API 类型定义和接口调用
|
||||||
|
- 换货单列表页面 - 新增流程类型列和筛选项
|
||||||
|
- 换货单详情页面 - 根据流程类型控制按钮和信息区块显示
|
||||||
|
- 创建换货单弹窗 - 新增流程类型选择和相关字段
|
||||||
|
- **Database**: `tb_exchange_order` 表新增 `flow_type`、`shipped_at`、`completed_at` 字段
|
||||||
|
- **API compatibility**: 向后兼容,历史数据 flow_type 为空时视为 shipping
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
## ADDED Requirements
|
||||||
|
|
||||||
|
### Requirement: 换货流程类型支持
|
||||||
|
|
||||||
|
系统 SHALL 支持两种换货流程类型:物流换货(shipping)和直接换货(direct),用于满足不同场景下的换货需求。
|
||||||
|
|
||||||
|
#### Scenario: 创建物流换货单
|
||||||
|
|
||||||
|
- **WHEN** 用户选择"物流换货"类型创建换货单
|
||||||
|
- **THEN** 换货单状态为"待填写信息"(status=1),flow_type 为 "shipping"
|
||||||
|
- **AND** 需要后续填写收货信息、发货、确认完成等步骤
|
||||||
|
|
||||||
|
#### Scenario: 创建直接换货单
|
||||||
|
|
||||||
|
- **WHEN** 用户选择"直接换货"类型并填写新资产标识符创建换货单
|
||||||
|
- **THEN** 换货单状态为"已完成"(status=4),flow_type 为 "direct"
|
||||||
|
- **AND** completed_at 字段记录当前时间
|
||||||
|
- **AND** 无需填写收货信息和发货流程
|
||||||
|
|
||||||
|
#### Scenario: 历史数据兼容
|
||||||
|
|
||||||
|
- **WHEN** 读取 flow_type 为空的历史换货单
|
||||||
|
- **THEN** 系统应将其视为"物流换货"(shipping)类型
|
||||||
|
- **AND** 按照物流换货流程展示和处理
|
||||||
|
|
||||||
|
### Requirement: 换货时间戳记录
|
||||||
|
|
||||||
|
系统 SHALL 记录换货流程中的关键时间节点,包括发货时间(shipped_at)和完成时间(completed_at)。
|
||||||
|
|
||||||
|
#### Scenario: 物流换货发货时间记录
|
||||||
|
|
||||||
|
- **WHEN** 物流换货单执行发货操作
|
||||||
|
- **THEN** shipped_at 字段记录发货时间
|
||||||
|
- **AND** 换货单状态变更为"已发货"(status=3)
|
||||||
|
|
||||||
|
#### Scenario: 物流换货完成时间记录
|
||||||
|
|
||||||
|
- **WHEN** 物流换货单确认完成
|
||||||
|
- **THEN** completed_at 字段记录完成时间
|
||||||
|
- **AND** 换货单状态变更为"已完成"(status=4)
|
||||||
|
|
||||||
|
#### Scenario: 直接换货完成时间记录
|
||||||
|
|
||||||
|
- **WHEN** 创建直接换货单
|
||||||
|
- **THEN** completed_at 字段立即记录创建时间
|
||||||
|
- **AND** shipped_at 字段为 null(无发货环节)
|
||||||
|
|
||||||
|
### Requirement: 创建换货单流程类型选择
|
||||||
|
|
||||||
|
用户在创建换货单时 SHALL 能够选择换货流程类型,并根据选择的类型填写相应的必填字段。
|
||||||
|
|
||||||
|
#### Scenario: 选择直接换货时必填新资产标识符
|
||||||
|
|
||||||
|
- **WHEN** 用户选择"直接换货"类型
|
||||||
|
- **THEN** 表单必须显示"新资产标识符"输入框(必填)
|
||||||
|
- **AND** 必须显示"是否迁移数据"开关(可选,默认 false)
|
||||||
|
|
||||||
|
#### Scenario: 选择物流换货时隐藏直接换货字段
|
||||||
|
|
||||||
|
- **WHEN** 用户选择"物流换货"类型
|
||||||
|
- **THEN** 表单不显示"新资产标识符"和"是否迁移数据"字段
|
||||||
|
- **AND** 仅需填写换货原因、旧资产类型和旧资产标识符
|
||||||
|
|
||||||
|
#### Scenario: 提交直接换货单参数
|
||||||
|
|
||||||
|
- **WHEN** 用户提交直接换货单
|
||||||
|
- **THEN** 请求参数 MUST 包含 flow_type="direct"、new_identifier 和 migrate_data
|
||||||
|
- **AND** 后端返回状态为"已完成"的换货单
|
||||||
|
|
||||||
|
### Requirement: 换货单列表流程类型筛选
|
||||||
|
|
||||||
|
用户在换货单列表页 SHALL 能够按流程类型筛选换货单,并查看流程类型信息。
|
||||||
|
|
||||||
|
#### Scenario: 显示流程类型列
|
||||||
|
|
||||||
|
- **WHEN** 用户查看换货单列表
|
||||||
|
- **THEN** 列表 MUST 显示"流程类型"列
|
||||||
|
- **AND** 该列显示"物流换货"或"直接换货"
|
||||||
|
|
||||||
|
#### Scenario: 按流程类型筛选
|
||||||
|
|
||||||
|
- **WHEN** 用户在筛选区选择流程类型(全部/物流换货/直接换货)
|
||||||
|
- **THEN** 列表仅显示选中类型的换货单
|
||||||
|
- **AND** 查询参数 flow_type 传递对应值(shipping/direct)
|
||||||
|
|
||||||
|
#### Scenario: 资产标识符模糊查询
|
||||||
|
|
||||||
|
- **WHEN** 用户输入资产标识符进行搜索
|
||||||
|
- **THEN** 系统同时匹配旧资产标识符和新资产标识符
|
||||||
|
- **AND** 返回所有匹配的换货单
|
||||||
|
|
||||||
|
### Requirement: 换货单详情流程类型展示
|
||||||
|
|
||||||
|
换货单详情页 SHALL 根据流程类型动态展示相关信息和时间戳。
|
||||||
|
|
||||||
|
#### Scenario: 显示流程类型和时间戳
|
||||||
|
|
||||||
|
- **WHEN** 用户查看换货单详情
|
||||||
|
- **THEN** 详情页 MUST 显示"流程类型"字段(物流换货/直接换货)
|
||||||
|
- **AND** 对于物流换货,显示"发货时间"(shipped_at,已发货后有值)
|
||||||
|
- **AND** 对于所有已完成的换货单,显示"完成时间"(completed_at)
|
||||||
|
|
||||||
|
#### Scenario: 直接换货隐藏收货和物流信息
|
||||||
|
|
||||||
|
- **WHEN** 用户查看直接换货单详情
|
||||||
|
- **THEN** 详情页不显示"收货信息"区块
|
||||||
|
- **AND** 详情页不显示"物流信息"区块
|
||||||
|
|
||||||
|
#### Scenario: 物流换货正常显示所有信息
|
||||||
|
|
||||||
|
- **WHEN** 用户查看物流换货单详情
|
||||||
|
- **THEN** 详情页显示"收货信息"区块(填写后有值)
|
||||||
|
- **AND** 详情页显示"物流信息"区块(发货后有值)
|
||||||
|
|
||||||
|
## MODIFIED Requirements
|
||||||
|
|
||||||
|
### Requirement: 换货单发货操作限制
|
||||||
|
|
||||||
|
系统 SHALL 仅允许物流换货单执行发货操作,直接换货单不支持发货。
|
||||||
|
|
||||||
|
**原有行为**: 所有状态为"待发货"的换货单均可执行发货操作。
|
||||||
|
|
||||||
|
**新行为**: 仅 flow_type="shipping" 且 status=2(待发货)的换货单可执行发货操作。
|
||||||
|
|
||||||
|
#### Scenario: 物流换货单可以发货
|
||||||
|
|
||||||
|
- **WHEN** 换货单 flow_type="shipping" 且 status=2
|
||||||
|
- **THEN** 详情页显示"发货"按钮
|
||||||
|
- **AND** 用户可以填写快递公司、快递单号等信息并提交
|
||||||
|
|
||||||
|
#### Scenario: 直接换货单不可发货
|
||||||
|
|
||||||
|
- **WHEN** 换货单 flow_type="direct"
|
||||||
|
- **THEN** 详情页不显示"发货"按钮
|
||||||
|
- **AND** 如果前端误调用发货接口,后端返回 400 错误:"流程类型不支持该操作"
|
||||||
|
|
||||||
|
#### Scenario: 前端阻止不合法发货操作
|
||||||
|
|
||||||
|
- **WHEN** 详情页加载换货单数据
|
||||||
|
- **THEN** 前端根据 flow_type 和 status 判断是否显示"发货"按钮
|
||||||
|
- **AND** 仅在 flow_type="shipping" 且 status=2 时显示
|
||||||
|
|
||||||
|
### Requirement: 换货单确认完成操作限制
|
||||||
|
|
||||||
|
系统 SHALL 仅允许物流换货单在已发货状态下执行确认完成操作,直接换货单自动完成。
|
||||||
|
|
||||||
|
**原有行为**: 状态为"已发货"的换货单可执行确认完成操作。
|
||||||
|
|
||||||
|
**新行为**: 仅 flow_type="shipping" 且 status=3(已发货)的换货单可执行确认完成操作。
|
||||||
|
|
||||||
|
#### Scenario: 物流换货单可以确认完成
|
||||||
|
|
||||||
|
- **WHEN** 换货单 flow_type="shipping" 且 status=3
|
||||||
|
- **THEN** 详情页显示"确认完成"按钮
|
||||||
|
- **AND** 用户点击后换货单状态变更为"已完成"
|
||||||
|
|
||||||
|
#### Scenario: 直接换货单不可确认完成
|
||||||
|
|
||||||
|
- **WHEN** 换货单 flow_type="direct"
|
||||||
|
- **THEN** 详情页不显示"确认完成"按钮
|
||||||
|
- **AND** 如果前端误调用完成接口,后端返回 400 错误
|
||||||
|
|
||||||
|
#### Scenario: 前端阻止不合法完成操作
|
||||||
|
|
||||||
|
- **WHEN** 详情页加载换货单数据
|
||||||
|
- **THEN** 前端根据 flow_type 和 status 判断是否显示"确认完成"按钮
|
||||||
|
- **AND** 仅在 flow_type="shipping" 且 status=3 时显示
|
||||||
|
|
||||||
|
### Requirement: 换货单取消操作限制
|
||||||
|
|
||||||
|
系统 SHALL 仅允许物流换货单在待填写信息或待发货状态下取消,直接换货单和已发货的物流换货单不可取消。
|
||||||
|
|
||||||
|
**原有行为**: 状态为"待填写信息"或"待发货"的换货单可取消。
|
||||||
|
|
||||||
|
**新行为**: 仅 flow_type="shipping" 且 status IN (1, 2) 的换货单可取消。
|
||||||
|
|
||||||
|
#### Scenario: 物流换货单待发货前可取消
|
||||||
|
|
||||||
|
- **WHEN** 换货单 flow_type="shipping" 且 status=1 或 status=2
|
||||||
|
- **THEN** 详情页显示"取消"按钮
|
||||||
|
- **AND** 用户可以取消换货单
|
||||||
|
|
||||||
|
#### Scenario: 物流换货单已发货后不可取消
|
||||||
|
|
||||||
|
- **WHEN** 换货单 flow_type="shipping" 且 status=3
|
||||||
|
- **THEN** 详情页不显示"取消"按钮
|
||||||
|
- **AND** 如果前端误调用取消接口,后端返回错误
|
||||||
|
|
||||||
|
#### Scenario: 直接换货单不可取消
|
||||||
|
|
||||||
|
- **WHEN** 换货单 flow_type="direct"
|
||||||
|
- **THEN** 详情页不显示"取消"按钮
|
||||||
|
- **AND** 如果前端误调用取消接口,后端返回 400 错误:"流程类型不支持该操作"
|
||||||
|
|
||||||
|
#### Scenario: 前端阻止不合法取消操作
|
||||||
|
|
||||||
|
- **WHEN** 详情页加载换货单数据
|
||||||
|
- **THEN** 前端根据 flow_type 和 status 判断是否显示"取消"按钮
|
||||||
|
- **AND** 仅在 flow_type="shipping" 且 status IN (1, 2) 时显示
|
||||||
55
openspec/changes/update-exchange-flow-direct-type/tasks.md
Normal file
55
openspec/changes/update-exchange-flow-direct-type/tasks.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
## 1. API 类型定义更新
|
||||||
|
|
||||||
|
- [x] 1.1 更新 `ExchangeQueryParams` 接口,新增 `flow_type` 和 `identifier` 查询参数
|
||||||
|
- [x] 1.2 更新 `CreateExchangeRequest` 接口,新增 `flow_type`、`new_identifier`、`migrate_data` 字段
|
||||||
|
- [x] 1.3 更新 `ExchangeResponse` 接口,新增 `flow_type`、`flow_type_name`、`shipped_at`、`completed_at` 字段
|
||||||
|
|
||||||
|
## 2. 创建换货单功能
|
||||||
|
|
||||||
|
- [x] 2.1 更新创建换货单弹窗,新增流程类型选择器(单选:物流换货/直接换货)
|
||||||
|
- [x] 2.2 实现流程类型切换逻辑,direct 时显示新资产标识符和数据迁移开关
|
||||||
|
- [x] 2.3 更新表单验证规则,direct 时 new_identifier 必填
|
||||||
|
- [x] 2.4 更新 API 调用,传递完整的创建参数
|
||||||
|
|
||||||
|
## 3. 换货单列表功能
|
||||||
|
|
||||||
|
- [x] 3.1 新增流程类型列,显示"物流换货"或"直接换货"
|
||||||
|
- [x] 3.2 新增流程类型筛选下拉框(全部/物流换货/直接换货)
|
||||||
|
- [x] 3.3 更新资产标识符搜索为模糊查询(同时匹配旧资产和新资产)
|
||||||
|
- [x] 3.4 更新列表查询参数,支持 flow_type 和 identifier 筛选
|
||||||
|
|
||||||
|
## 4. 换货单详情功能
|
||||||
|
|
||||||
|
- [x] 4.1 新增流程类型展示字段(flow_type_name)
|
||||||
|
- [x] 4.2 新增发货时间(shipped_at)和完成时间(completed_at)展示
|
||||||
|
- [x] 4.3 根据 flow_type 控制操作按钮显示:
|
||||||
|
- direct 类型隐藏"发货"、"确认完成"、"取消"按钮
|
||||||
|
- shipping + status=1 仅显示"取消"
|
||||||
|
- shipping + status=2 显示"发货"和"取消"
|
||||||
|
- shipping + status=3 仅显示"确认完成"
|
||||||
|
- [x] 4.4 根据 flow_type 控制信息区块显示:
|
||||||
|
- direct 类型隐藏或标记"不适用"收货信息和物流信息区块
|
||||||
|
|
||||||
|
## 5. 发货功能
|
||||||
|
|
||||||
|
- [x] 5.1 在发货前检查 flow_type,仅允许 shipping 类型
|
||||||
|
- [x] 5.2 对 direct 类型返回的 400 错误进行友好提示
|
||||||
|
|
||||||
|
## 6. 确认完成功能
|
||||||
|
|
||||||
|
- [x] 6.1 在确认完成前检查 flow_type,仅允许 shipping 且 status=3
|
||||||
|
- [x] 6.2 对 direct 类型返回的错误进行友好提示
|
||||||
|
|
||||||
|
## 7. 取消换货功能
|
||||||
|
|
||||||
|
- [x] 7.1 在取消前检查 flow_type 和 status,仅允许 shipping 且 status 为 1 或 2
|
||||||
|
- [x] 7.2 对不符合条件的操作返回友好提示
|
||||||
|
|
||||||
|
## 8. 测试与验证
|
||||||
|
|
||||||
|
- [ ] 8.1 测试创建物流换货单,验证原有流程正常
|
||||||
|
- [ ] 8.2 测试创建直接换货单,验证自动完成逻辑
|
||||||
|
- [ ] 8.3 测试列表筛选,验证 flow_type 和 identifier 查询正确
|
||||||
|
- [ ] 8.4 测试详情页按钮和区块显示,验证不同流程类型的 UI 差异
|
||||||
|
- [ ] 8.5 测试操作限制,验证 direct 类型不可发货、完成、取消
|
||||||
|
- [ ] 8.6 测试历史数据兼容性,验证 flow_type 为空时视为 shipping
|
||||||
@@ -10,7 +10,8 @@ export interface ExchangeQueryParams {
|
|||||||
page?: number
|
page?: number
|
||||||
page_size?: number
|
page_size?: number
|
||||||
status?: number // 换货状态
|
status?: number // 换货状态
|
||||||
identifier?: string // 资产标识符(模糊匹配)
|
flow_type?: string // 流程类型(shipping/direct)
|
||||||
|
identifier?: string // 资产标识符(模糊匹配,同时匹配旧资产、新资产)
|
||||||
created_at_start?: string // 创建时间起始
|
created_at_start?: string // 创建时间起始
|
||||||
created_at_end?: string // 创建时间结束
|
created_at_end?: string // 创建时间结束
|
||||||
}
|
}
|
||||||
@@ -20,6 +21,9 @@ export interface CreateExchangeRequest {
|
|||||||
exchange_reason: string // 换货原因
|
exchange_reason: string // 换货原因
|
||||||
old_asset_type: string // 旧资产类型 (iot_card 或 device)
|
old_asset_type: string // 旧资产类型 (iot_card 或 device)
|
||||||
old_identifier: string // 旧资产标识符(ICCID/虚拟号/IMEI/SN)
|
old_identifier: string // 旧资产标识符(ICCID/虚拟号/IMEI/SN)
|
||||||
|
flow_type?: string // 流程类型(shipping/direct),默认 shipping
|
||||||
|
new_identifier?: string // 新资产标识符(direct 时必填)
|
||||||
|
migrate_data?: boolean // 是否迁移数据(默认 false)
|
||||||
remark?: string // 备注(可选)
|
remark?: string // 备注(可选)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +38,10 @@ export interface ExchangeResponse {
|
|||||||
new_asset_identifier: string
|
new_asset_identifier: string
|
||||||
status: number // 换货状态(1:待填写信息, 2:待发货, 3:已发货待确认, 4:已完成, 5:已取消)
|
status: number // 换货状态(1:待填写信息, 2:待发货, 3:已发货待确认, 4:已完成, 5:已取消)
|
||||||
status_text: string
|
status_text: string
|
||||||
|
flow_type: string // 流程类型(shipping/direct)
|
||||||
|
flow_type_name: string // 流程类型名称
|
||||||
|
shipped_at?: string | null // 发货时间(仅 shipping 发货后有值)
|
||||||
|
completed_at?: string | null // 换货完成时间
|
||||||
recipient_name?: string
|
recipient_name?: string
|
||||||
recipient_phone?: string
|
recipient_phone?: string
|
||||||
recipient_address?: string
|
recipient_address?: string
|
||||||
|
|||||||
@@ -55,9 +55,15 @@
|
|||||||
return types[status] || 'info'
|
return types[status] || 'info'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 详情页配置
|
// 根据流程类型动态生成详情页配置
|
||||||
const detailSections: DetailSection[] = [
|
const detailSections = computed<DetailSection[]>(() => {
|
||||||
{
|
if (!exchangeDetail.value) return []
|
||||||
|
|
||||||
|
const flowType = exchangeDetail.value.flow_type || 'shipping' // 历史数据兼容
|
||||||
|
const sections: DetailSection[] = []
|
||||||
|
|
||||||
|
// 基本信息
|
||||||
|
sections.push({
|
||||||
title: '基本信息',
|
title: '基本信息',
|
||||||
fields: [
|
fields: [
|
||||||
{ label: '换货单号', prop: 'exchange_no' },
|
{ label: '换货单号', prop: 'exchange_no' },
|
||||||
@@ -65,6 +71,10 @@
|
|||||||
label: '状态',
|
label: '状态',
|
||||||
render: (data) => h(ElTag, { type: getStatusType(data.status) }, () => data.status_text)
|
render: (data) => h(ElTag, { type: getStatusType(data.status) }, () => data.status_text)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '流程类型',
|
||||||
|
formatter: (_, data) => data.flow_type_name || (flowType === 'direct' ? '直接换货' : '物流换货')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '换货原因',
|
label: '换货原因',
|
||||||
prop: 'exchange_reason',
|
prop: 'exchange_reason',
|
||||||
@@ -86,44 +96,57 @@
|
|||||||
prop: 'new_asset_identifier'
|
prop: 'new_asset_identifier'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
})
|
||||||
{
|
|
||||||
title: '收货信息',
|
// 收货信息(仅物流换货显示)
|
||||||
fields: [
|
if (flowType === 'shipping') {
|
||||||
{
|
sections.push({
|
||||||
label: '收货人姓名',
|
title: '收货信息',
|
||||||
formatter: (value) => value || '--',
|
fields: [
|
||||||
prop: 'recipient_name'
|
{
|
||||||
},
|
label: '收货人姓名',
|
||||||
{
|
formatter: (value) => value || '--',
|
||||||
label: '收货人电话',
|
prop: 'recipient_name'
|
||||||
formatter: (value) => value || '--',
|
},
|
||||||
prop: 'recipient_phone'
|
{
|
||||||
},
|
label: '收货人电话',
|
||||||
{
|
formatter: (value) => value || '--',
|
||||||
label: '收货地址',
|
prop: 'recipient_phone'
|
||||||
formatter: (value) => value || '--',
|
},
|
||||||
prop: 'recipient_address',
|
{
|
||||||
fullWidth: true
|
label: '收货地址',
|
||||||
}
|
formatter: (value) => value || '--',
|
||||||
]
|
prop: 'recipient_address',
|
||||||
},
|
fullWidth: true
|
||||||
{
|
}
|
||||||
title: '物流信息',
|
]
|
||||||
fields: [
|
})
|
||||||
{
|
|
||||||
label: '快递公司',
|
// 物流信息(仅物流换货显示)
|
||||||
formatter: (value) => value || '--',
|
sections.push({
|
||||||
prop: 'express_company'
|
title: '物流信息',
|
||||||
},
|
fields: [
|
||||||
{
|
{
|
||||||
label: '快递单号',
|
label: '快递公司',
|
||||||
formatter: (value) => value || '--',
|
formatter: (value) => value || '--',
|
||||||
prop: 'express_no'
|
prop: 'express_company'
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
},
|
label: '快递单号',
|
||||||
{
|
formatter: (value) => value || '--',
|
||||||
|
prop: 'express_no'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '发货时间',
|
||||||
|
formatter: (value) => (value ? formatDateTime(value) : '--'),
|
||||||
|
prop: 'shipped_at'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他信息
|
||||||
|
sections.push({
|
||||||
title: '其他信息',
|
title: '其他信息',
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
@@ -132,6 +155,11 @@
|
|||||||
prop: 'remark',
|
prop: 'remark',
|
||||||
fullWidth: true
|
fullWidth: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '完成时间',
|
||||||
|
formatter: (value) => (value ? formatDateTime(value) : '--'),
|
||||||
|
prop: 'completed_at'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '创建时间',
|
label: '创建时间',
|
||||||
formatter: (value) => formatDateTime(value),
|
formatter: (value) => formatDateTime(value),
|
||||||
@@ -143,8 +171,10 @@
|
|||||||
prop: 'updated_at'
|
prop: 'updated_at'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
})
|
||||||
]
|
|
||||||
|
return sections
|
||||||
|
})
|
||||||
|
|
||||||
// 加载换货单详情
|
// 加载换货单详情
|
||||||
const loadExchangeDetail = async () => {
|
const loadExchangeDetail = async () => {
|
||||||
|
|||||||
@@ -50,6 +50,25 @@
|
|||||||
@closed="handleCloseCreateDialog"
|
@closed="handleCloseCreateDialog"
|
||||||
>
|
>
|
||||||
<ElForm ref="createFormRef" :model="createForm" :rules="createRules" label-width="120px">
|
<ElForm ref="createFormRef" :model="createForm" :rules="createRules" label-width="120px">
|
||||||
|
<ElFormItem label="流程类型" prop="flow_type">
|
||||||
|
<ElSelect
|
||||||
|
v-model="createForm.flow_type"
|
||||||
|
placeholder="请选择流程类型"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleFlowTypeChange"
|
||||||
|
>
|
||||||
|
<ElOption label="物流换货" value="shipping" />
|
||||||
|
<ElOption label="直接换货" value="direct" />
|
||||||
|
</ElSelect>
|
||||||
|
<div style="margin-top: 4px; font-size: 12px; color: #909399">
|
||||||
|
<span v-if="createForm.flow_type === 'shipping'">
|
||||||
|
物流换货:需要填写收货信息、发货等步骤
|
||||||
|
</span>
|
||||||
|
<span v-else-if="createForm.flow_type === 'direct'">
|
||||||
|
直接换货:创建后自动完成,无需物流环节
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ElFormItem>
|
||||||
<ElFormItem label="换货原因" prop="exchange_reason">
|
<ElFormItem label="换货原因" prop="exchange_reason">
|
||||||
<ElSelect
|
<ElSelect
|
||||||
v-model="createForm.exchange_reason"
|
v-model="createForm.exchange_reason"
|
||||||
@@ -151,6 +170,74 @@
|
|||||||
</ElOption>
|
</ElOption>
|
||||||
</ElSelect>
|
</ElSelect>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
|
<ElFormItem
|
||||||
|
v-if="createForm.flow_type === 'direct' && createForm.old_asset_type === 'iot_card'"
|
||||||
|
label="新资产标识符"
|
||||||
|
prop="new_identifier"
|
||||||
|
>
|
||||||
|
<ElSelect
|
||||||
|
v-model="createForm.new_identifier"
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
|
reserve-keyword
|
||||||
|
placeholder="请输入ICCID搜索"
|
||||||
|
:remote-method="searchNewIotCards"
|
||||||
|
:loading="newCardSearchLoading"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<ElOption
|
||||||
|
v-for="card in newIotCardOptions"
|
||||||
|
:key="card.id"
|
||||||
|
:label="`${card.iccid} (${card.msisdn || '无接入号'})`"
|
||||||
|
:value="card.iccid"
|
||||||
|
>
|
||||||
|
<div style="display: flex; justify-content: space-between">
|
||||||
|
<span>{{ card.iccid }}</span>
|
||||||
|
<span style="font-size: 12px; color: var(--el-text-color-secondary)">
|
||||||
|
{{ card.msisdn || '无接入号' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ElOption>
|
||||||
|
</ElSelect>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem
|
||||||
|
v-if="createForm.flow_type === 'direct' && createForm.old_asset_type === 'device'"
|
||||||
|
label="新资产标识符"
|
||||||
|
prop="new_identifier"
|
||||||
|
>
|
||||||
|
<ElSelect
|
||||||
|
v-model="createForm.new_identifier"
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
|
reserve-keyword
|
||||||
|
placeholder="请输入虚拟号或IMEI搜索"
|
||||||
|
:remote-method="searchNewDevices"
|
||||||
|
:loading="newDeviceSearchLoading"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<ElOption
|
||||||
|
v-for="device in newDeviceOptions"
|
||||||
|
:key="device.id"
|
||||||
|
:label="`${device.virtual_no} (${device.device_name || device.imei})`"
|
||||||
|
:value="device.virtual_no"
|
||||||
|
>
|
||||||
|
<div style="display: flex; justify-content: space-between">
|
||||||
|
<span>{{ device.virtual_no }}</span>
|
||||||
|
<span style="font-size: 12px; color: var(--el-text-color-secondary)">
|
||||||
|
{{ device.device_name || device.imei }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ElOption>
|
||||||
|
</ElSelect>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem v-if="createForm.flow_type === 'direct'" label="是否迁移数据">
|
||||||
|
<ElSwitch v-model="createForm.migrate_data" />
|
||||||
|
<div style="margin-top: 4px; margin-left: 8px; font-size: 12px; color: #909399">
|
||||||
|
开启后将迁移钱包余额、套餐记录到新资产
|
||||||
|
</div>
|
||||||
|
</ElFormItem>
|
||||||
<ElFormItem label="备注">
|
<ElFormItem label="备注">
|
||||||
<ElInput
|
<ElInput
|
||||||
v-model="createForm.remark"
|
v-model="createForm.remark"
|
||||||
@@ -257,6 +344,7 @@
|
|||||||
// 搜索表单
|
// 搜索表单
|
||||||
const searchForm = reactive({
|
const searchForm = reactive({
|
||||||
status: undefined,
|
status: undefined,
|
||||||
|
flow_type: undefined, // 流程类型筛选
|
||||||
identifier: '',
|
identifier: '',
|
||||||
created_at_range: [],
|
created_at_range: [],
|
||||||
created_at_start: '',
|
created_at_start: '',
|
||||||
@@ -269,6 +357,9 @@
|
|||||||
exchange_reason_other: '',
|
exchange_reason_other: '',
|
||||||
old_asset_type: '',
|
old_asset_type: '',
|
||||||
old_identifier: '',
|
old_identifier: '',
|
||||||
|
flow_type: 'shipping', // 流程类型,默认物流换货
|
||||||
|
new_identifier: '', // 新资产标识符(direct 时必填)
|
||||||
|
migrate_data: false, // 是否迁移数据(默认 false)
|
||||||
remark: ''
|
remark: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -286,11 +377,27 @@
|
|||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validateNewIdentifier = (_rule: any, value: string, callback: any) => {
|
||||||
|
if (createForm.flow_type !== 'direct') {
|
||||||
|
callback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value || !value.trim()) {
|
||||||
|
callback(new Error('请输入新资产标识符'))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
const createRules = reactive<FormRules>({
|
const createRules = reactive<FormRules>({
|
||||||
exchange_reason: [{ required: true, message: '请选择换货原因', trigger: 'change' }],
|
exchange_reason: [{ required: true, message: '请选择换货原因', trigger: 'change' }],
|
||||||
exchange_reason_other: [{ validator: validateOtherExchangeReason, trigger: 'blur' }],
|
exchange_reason_other: [{ validator: validateOtherExchangeReason, trigger: 'blur' }],
|
||||||
old_asset_type: [{ required: true, message: '请选择旧资产类型', trigger: 'change' }],
|
old_asset_type: [{ required: true, message: '请选择旧资产类型', trigger: 'change' }],
|
||||||
old_identifier: [{ required: true, message: '请选择旧资产标识符', trigger: 'change' }]
|
old_identifier: [{ required: true, message: '请选择旧资产标识符', trigger: 'change' }],
|
||||||
|
flow_type: [{ required: true, message: '请选择流程类型', trigger: 'change' }],
|
||||||
|
new_identifier: [{ validator: validateNewIdentifier, trigger: 'blur' }]
|
||||||
})
|
})
|
||||||
|
|
||||||
// 旧资产搜索相关
|
// 旧资产搜索相关
|
||||||
@@ -299,6 +406,12 @@
|
|||||||
const oldDeviceOptions = ref<Device[]>([])
|
const oldDeviceOptions = ref<Device[]>([])
|
||||||
const oldDeviceSearchLoading = ref(false)
|
const oldDeviceSearchLoading = ref(false)
|
||||||
|
|
||||||
|
// 新资产搜索相关(直接换货使用)
|
||||||
|
const newIotCardOptions = ref<StandaloneIotCard[]>([])
|
||||||
|
const newCardSearchLoading = ref(false)
|
||||||
|
const newDeviceOptions = ref<Device[]>([])
|
||||||
|
const newDeviceSearchLoading = ref(false)
|
||||||
|
|
||||||
// 发货表单
|
// 发货表单
|
||||||
const shipForm = reactive({
|
const shipForm = reactive({
|
||||||
new_identifier: '',
|
new_identifier: '',
|
||||||
@@ -338,6 +451,19 @@
|
|||||||
{ label: '已取消', value: 5 }
|
{ label: '已取消', value: 5 }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '流程类型',
|
||||||
|
prop: 'flow_type',
|
||||||
|
type: 'select',
|
||||||
|
config: {
|
||||||
|
clearable: true,
|
||||||
|
placeholder: '全部'
|
||||||
|
},
|
||||||
|
options: () => [
|
||||||
|
{ label: '物流换货', value: 'shipping' },
|
||||||
|
{ label: '直接换货', value: 'direct' }
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '资产标识符',
|
label: '资产标识符',
|
||||||
prop: 'identifier',
|
prop: 'identifier',
|
||||||
@@ -384,6 +510,12 @@
|
|||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
showOverflowTooltip: true
|
showOverflowTooltip: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'flow_type',
|
||||||
|
label: '流程类型',
|
||||||
|
width: 120,
|
||||||
|
formatter: (row: any) => row.flow_type_name || (row.flow_type === 'direct' ? '直接换货' : '物流换货')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: 'old_asset_type',
|
prop: 'old_asset_type',
|
||||||
label: '旧资产类型',
|
label: '旧资产类型',
|
||||||
@@ -474,6 +606,9 @@
|
|||||||
if (searchForm.status !== undefined && searchForm.status !== null) {
|
if (searchForm.status !== undefined && searchForm.status !== null) {
|
||||||
params.status = searchForm.status
|
params.status = searchForm.status
|
||||||
}
|
}
|
||||||
|
if (searchForm.flow_type) {
|
||||||
|
params.flow_type = searchForm.flow_type
|
||||||
|
}
|
||||||
if (searchForm.identifier) {
|
if (searchForm.identifier) {
|
||||||
params.identifier = searchForm.identifier
|
params.identifier = searchForm.identifier
|
||||||
}
|
}
|
||||||
@@ -547,6 +682,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 流程类型变更
|
||||||
|
const handleFlowTypeChange = async () => {
|
||||||
|
// 清空新资产标识符和数据迁移选项
|
||||||
|
createForm.new_identifier = ''
|
||||||
|
createForm.migrate_data = false
|
||||||
|
newIotCardOptions.value = []
|
||||||
|
newDeviceOptions.value = []
|
||||||
|
createFormRef.value?.clearValidate('new_identifier')
|
||||||
|
|
||||||
|
// 如果选择直接换货且已选择旧资产类型,加载默认新资产列表
|
||||||
|
if (createForm.flow_type === 'direct' && createForm.old_asset_type) {
|
||||||
|
if (createForm.old_asset_type === 'iot_card') {
|
||||||
|
await loadDefaultNewIotCards()
|
||||||
|
} else if (createForm.old_asset_type === 'device') {
|
||||||
|
await loadDefaultNewDevices()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 旧资产类型变更
|
// 旧资产类型变更
|
||||||
const handleOldAssetTypeChange = async () => {
|
const handleOldAssetTypeChange = async () => {
|
||||||
// 清空旧资产标识符
|
// 清空旧资产标识符
|
||||||
@@ -554,11 +708,26 @@
|
|||||||
oldIotCardOptions.value = []
|
oldIotCardOptions.value = []
|
||||||
oldDeviceOptions.value = []
|
oldDeviceOptions.value = []
|
||||||
|
|
||||||
|
// 清空新资产标识符(如果是直接换货)
|
||||||
|
if (createForm.flow_type === 'direct') {
|
||||||
|
createForm.new_identifier = ''
|
||||||
|
newIotCardOptions.value = []
|
||||||
|
newDeviceOptions.value = []
|
||||||
|
}
|
||||||
|
|
||||||
// 根据类型加载默认数据
|
// 根据类型加载默认数据
|
||||||
if (createForm.old_asset_type === 'iot_card') {
|
if (createForm.old_asset_type === 'iot_card') {
|
||||||
await loadDefaultIotCards()
|
await loadDefaultIotCards()
|
||||||
|
// 如果是直接换货,也加载新资产列表
|
||||||
|
if (createForm.flow_type === 'direct') {
|
||||||
|
await loadDefaultNewIotCards()
|
||||||
|
}
|
||||||
} else if (createForm.old_asset_type === 'device') {
|
} else if (createForm.old_asset_type === 'device') {
|
||||||
await loadDefaultDevices()
|
await loadDefaultDevices()
|
||||||
|
// 如果是直接换货,也加载新资产列表
|
||||||
|
if (createForm.flow_type === 'direct') {
|
||||||
|
await loadDefaultNewDevices()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,6 +833,102 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 搜索新IoT卡(直接换货使用)
|
||||||
|
const searchNewIotCards = async (query: string) => {
|
||||||
|
if (!query) {
|
||||||
|
// 清空搜索时加载默认列表
|
||||||
|
await loadDefaultNewIotCards()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newCardSearchLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await CardService.getStandaloneIotCards({
|
||||||
|
iccid: query,
|
||||||
|
page: 1,
|
||||||
|
page_size: 20
|
||||||
|
})
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
newIotCardOptions.value = res.data.items || []
|
||||||
|
if (newIotCardOptions.value.length === 0) {
|
||||||
|
ElMessage.info('未找到匹配的IoT卡')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('搜索IoT卡失败:', error)
|
||||||
|
newIotCardOptions.value = []
|
||||||
|
} finally {
|
||||||
|
newCardSearchLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载默认新IoT卡列表
|
||||||
|
const loadDefaultNewIotCards = async () => {
|
||||||
|
newCardSearchLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await CardService.getStandaloneIotCards({
|
||||||
|
page: 1,
|
||||||
|
page_size: 10
|
||||||
|
})
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
newIotCardOptions.value = res.data.items || []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载IoT卡列表失败:', error)
|
||||||
|
newIotCardOptions.value = []
|
||||||
|
} finally {
|
||||||
|
newCardSearchLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索新设备(直接换货使用)
|
||||||
|
const searchNewDevices = async (query: string) => {
|
||||||
|
if (!query) {
|
||||||
|
// 清空搜索时加载默认列表
|
||||||
|
await loadDefaultNewDevices()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newDeviceSearchLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await DeviceService.getDevices({
|
||||||
|
keyword: query,
|
||||||
|
page: 1,
|
||||||
|
page_size: 20
|
||||||
|
})
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
newDeviceOptions.value = res.data.items || []
|
||||||
|
if (newDeviceOptions.value.length === 0) {
|
||||||
|
ElMessage.info('未找到匹配的设备')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('搜索设备失败:', error)
|
||||||
|
newDeviceOptions.value = []
|
||||||
|
} finally {
|
||||||
|
newDeviceSearchLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载默认新设备列表
|
||||||
|
const loadDefaultNewDevices = async () => {
|
||||||
|
newDeviceSearchLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await DeviceService.getDevices({
|
||||||
|
page: 1,
|
||||||
|
page_size: 10
|
||||||
|
})
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
newDeviceOptions.value = res.data.items || []
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载设备列表失败:', error)
|
||||||
|
newDeviceOptions.value = []
|
||||||
|
} finally {
|
||||||
|
newDeviceSearchLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 确认创建
|
// 确认创建
|
||||||
const handleConfirmCreate = () => {
|
const handleConfirmCreate = () => {
|
||||||
createFormRef.value?.validate(async (valid) => {
|
createFormRef.value?.validate(async (valid) => {
|
||||||
@@ -676,12 +941,21 @@
|
|||||||
? createForm.exchange_reason_other.trim()
|
? createForm.exchange_reason_other.trim()
|
||||||
: createForm.exchange_reason
|
: createForm.exchange_reason
|
||||||
|
|
||||||
const res = await ExchangeService.createExchange({
|
const requestData: any = {
|
||||||
exchange_reason: exchangeReason,
|
exchange_reason: exchangeReason,
|
||||||
old_asset_type: createForm.old_asset_type,
|
old_asset_type: createForm.old_asset_type,
|
||||||
old_identifier: createForm.old_identifier,
|
old_identifier: createForm.old_identifier,
|
||||||
|
flow_type: createForm.flow_type,
|
||||||
remark: createForm.remark || undefined
|
remark: createForm.remark || undefined
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// 直接换货时需要传递新资产标识符和数据迁移标志
|
||||||
|
if (createForm.flow_type === 'direct') {
|
||||||
|
requestData.new_identifier = createForm.new_identifier
|
||||||
|
requestData.migrate_data = createForm.migrate_data
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await ExchangeService.createExchange(requestData)
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
ElMessage.success('换货单创建成功')
|
ElMessage.success('换货单创建成功')
|
||||||
createDialogVisible.value = false
|
createDialogVisible.value = false
|
||||||
@@ -701,6 +975,8 @@
|
|||||||
// 清空搜索选项
|
// 清空搜索选项
|
||||||
oldIotCardOptions.value = []
|
oldIotCardOptions.value = []
|
||||||
oldDeviceOptions.value = []
|
oldDeviceOptions.value = []
|
||||||
|
newIotCardOptions.value = []
|
||||||
|
newDeviceOptions.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
@@ -712,7 +988,22 @@
|
|||||||
const getActions = (row: ExchangeResponse) => {
|
const getActions = (row: ExchangeResponse) => {
|
||||||
const actions: any[] = []
|
const actions: any[] = []
|
||||||
const status = row.status
|
const status = row.status
|
||||||
|
const flowType = row.flow_type || 'shipping' // 历史数据兼容
|
||||||
|
|
||||||
|
// 直接换货不支持任何操作(发货、确认完成、取消)
|
||||||
|
if (flowType === 'direct') {
|
||||||
|
// 状态4(已完成):旧资产转新(direct 也支持)
|
||||||
|
if (status === 4 && hasAuth('exchange:renew')) {
|
||||||
|
actions.push({
|
||||||
|
label: '旧资产转新',
|
||||||
|
handler: () => handleRenewExchange(row),
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return actions
|
||||||
|
}
|
||||||
|
|
||||||
|
// 物流换货流程
|
||||||
// 状态1(待填写信息):取消换货
|
// 状态1(待填写信息):取消换货
|
||||||
if (status === 1) {
|
if (status === 1) {
|
||||||
if (hasAuth('exchange:cancel')) {
|
if (hasAuth('exchange:cancel')) {
|
||||||
|
|||||||
@@ -968,7 +968,7 @@
|
|||||||
// 构建请求数据
|
// 构建请求数据
|
||||||
const data: any = {
|
const data: any = {
|
||||||
series_name: form.series_name,
|
series_name: form.series_name,
|
||||||
description: form.description || undefined,
|
description: form.description,
|
||||||
enable_one_time_commission: form.one_time_commission_config.enable
|
enable_one_time_commission: form.one_time_commission_config.enable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user