2026-06-24 23:12:43 +08:00
|
|
|
|
# 蜜雪冰城企业管理系统 —— 后端 API 文档
|
|
|
|
|
|
|
|
|
|
|
|
> 蜜雪冰城总部用于管理加盟商、合同、员工、产品、供应商及售后服务的企业信息管理系统后端服务。
|
|
|
|
|
|
|
|
|
|
|
|
## 目录
|
|
|
|
|
|
|
|
|
|
|
|
- [快速开始](#快速开始)
|
|
|
|
|
|
- [技术栈](#技术栈)
|
|
|
|
|
|
- [项目结构](#项目结构)
|
|
|
|
|
|
- [认证机制](#认证机制)
|
|
|
|
|
|
- [API 接口总览](#api-接口总览)
|
|
|
|
|
|
- [用户认证](#1-用户认证)
|
|
|
|
|
|
- [用户管理](#2-用户管理)
|
|
|
|
|
|
- [加盟商管理](#3-加盟商管理)
|
|
|
|
|
|
- [员工管理](#4-员工管理)
|
|
|
|
|
|
- [合同管理](#5-合同管理)
|
|
|
|
|
|
- [售后管理](#6-售后管理)
|
|
|
|
|
|
- [产品管理](#7-产品管理)
|
|
|
|
|
|
- [供应商管理](#8-供应商管理)
|
|
|
|
|
|
- [统一响应格式](#统一响应格式)
|
|
|
|
|
|
- [数据库设计](#数据库设计)
|
|
|
|
|
|
- [表结构详情](#表结构详情)
|
|
|
|
|
|
- [表关系 ER 图](#表关系-er-图)
|
|
|
|
|
|
- [RBAC 权限系统](#rbac-权限系统)
|
|
|
|
|
|
- [角色定义](#角色定义)
|
|
|
|
|
|
- [权限列表](#权限列表)
|
|
|
|
|
|
- [角色-权限映射](#角色-权限映射)
|
|
|
|
|
|
- [数据范围隔离](#数据范围隔离)
|
|
|
|
|
|
- [预置账号](#预置账号)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 快速开始
|
|
|
|
|
|
|
|
|
|
|
|
### 环境要求
|
|
|
|
|
|
|
|
|
|
|
|
- Node.js >= 18
|
|
|
|
|
|
- MySQL 5.7+ / MariaDB 10.2+
|
|
|
|
|
|
|
|
|
|
|
|
### 安装与运行
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 1. 安装依赖
|
|
|
|
|
|
npm install
|
|
|
|
|
|
|
|
|
|
|
|
# 2. 配置环境变量
|
|
|
|
|
|
cp .env.example .env
|
|
|
|
|
|
# 编辑 .env 填入数据库连接信息和 JWT 密钥
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 启动开发服务(自动重启)
|
|
|
|
|
|
npm run dev
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 启动生产服务
|
|
|
|
|
|
npm start
|
|
|
|
|
|
|
|
|
|
|
|
# 5. 运行集成测试(需先启动服务)
|
|
|
|
|
|
node test-all.js
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 环境变量 (.env)
|
|
|
|
|
|
|
|
|
|
|
|
| 变量 | 说明 | 默认值 |
|
|
|
|
|
|
|------|------|--------|
|
|
|
|
|
|
| `PORT` | 服务端口 | `3000` |
|
|
|
|
|
|
| `DB_HOST` | MySQL 主机 | — |
|
|
|
|
|
|
| `DB_PORT` | MySQL 端口 | `3306` |
|
|
|
|
|
|
| `DB_USER` | MySQL 用户名 | — |
|
|
|
|
|
|
| `DB_PASSWORD` | MySQL 密码 | — |
|
|
|
|
|
|
| `DB_NAME` | 数据库名 | `backmanager` |
|
|
|
|
|
|
| `JWT_SECRET` | JWT 签名密钥 | — |
|
|
|
|
|
|
| `JWT_EXPIRES_IN` | Token 有效期 | `2h` |
|
|
|
|
|
|
|
|
|
|
|
|
> 首次启动时,系统会自动创建数据库、建表、初始化角色权限和预置用户。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 技术栈
|
|
|
|
|
|
|
|
|
|
|
|
| 技术 | 用途 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| Express 5 | Web 框架 |
|
|
|
|
|
|
| mysql2/promise | MySQL 驱动(连接池 + Promise) |
|
|
|
|
|
|
| jsonwebtoken | JWT 认证 |
|
|
|
|
|
|
| bcryptjs | 密码哈希加密 |
|
|
|
|
|
|
| dotenv | 环境变量管理 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
backmanager-server/
|
|
|
|
|
|
├── server.js # 入口:Express 应用、鉴权中间件、路由注册
|
|
|
|
|
|
├── db.js # 数据库:连接池、建表、种子数据
|
|
|
|
|
|
├── middleware/
|
|
|
|
|
|
│ └── permissions.js # RBAC:权限检查 + 数据范围过滤
|
|
|
|
|
|
├── routes/
|
|
|
|
|
|
│ ├── users.js # 用户登录/信息/CRUD
|
|
|
|
|
|
│ ├── customers.js # 加盟商 CRUD
|
|
|
|
|
|
│ ├── employees.js # 员工 CRUD
|
|
|
|
|
|
│ ├── contracts.js # 合同 CRUD
|
|
|
|
|
|
│ ├── afterSales.js # 售后 CRUD
|
|
|
|
|
|
│ ├── products.js # 产品 CRUD
|
|
|
|
|
|
│ └── suppliers.js # 供应商 CRUD
|
|
|
|
|
|
├── test-all.js # 集成测试(覆盖 6 个角色的权限与数据隔离)
|
|
|
|
|
|
├── .env.example # 环境变量模板
|
|
|
|
|
|
└── package.json
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 认证机制
|
|
|
|
|
|
|
|
|
|
|
|
所有 API(除登录外)需要在请求头中携带 JWT Token:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Authorization: Bearer <token>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Token 获取
|
|
|
|
|
|
|
|
|
|
|
|
通过 `POST /api/user/login` 登录获取 Token。
|
|
|
|
|
|
|
|
|
|
|
|
### Token 有效载荷 (Payload)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"username": "admin",
|
|
|
|
|
|
"name": "系统管理员",
|
|
|
|
|
|
"role_id": 1,
|
|
|
|
|
|
"roleName": "admin",
|
|
|
|
|
|
"department": "信息技术部",
|
|
|
|
|
|
"permissions": ["customer:read", "customer:create", "customer:update", "customer:delete", "contract:read", "..."]
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 认证流程
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
客户端请求 → auth 中间件验证 Token → checkPermission 检查权限 → 路由处理 → 数据范围过滤(getDataScope)→ 返回响应
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 错误响应
|
|
|
|
|
|
|
|
|
|
|
|
| HTTP 状态码 | 场景 |
|
|
|
|
|
|
|------------|------|
|
|
|
|
|
|
| 401 | 未携带 Token 或 Token 无效/过期 |
|
|
|
|
|
|
| 403 | 权限不足(无对应操作权限或数据不在可见范围内) |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## API 接口总览
|
|
|
|
|
|
|
|
|
|
|
|
### 通用说明
|
|
|
|
|
|
|
|
|
|
|
|
- **分页参数**:所有列表接口支持 `page`(页码,从 1 开始,默认 1)和 `pageSize`(每页条数,默认 10,最大 100)
|
|
|
|
|
|
- **分页响应**:列表接口返回 `{ list, total, page, pageSize, totalPages }`
|
|
|
|
|
|
- **搜索参数**:通过 URL Query String 传递,如 `GET /api/customers?name=张&phone=138`
|
|
|
|
|
|
- **部分更新**:PUT 接口只传需要修改的字段即可,未传字段保持不变
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 用户认证
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/user/login — 登录
|
|
|
|
|
|
|
|
|
|
|
|
无需 Token。
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"username": "admin",
|
|
|
|
|
|
"password": "123456"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**成功响应:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "ok",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"token": "eyJhbGciOiJIUzI1NiIs...",
|
|
|
|
|
|
"userInfo": {
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"username": "admin",
|
|
|
|
|
|
"name": "系统管理员",
|
|
|
|
|
|
"role_id": 1,
|
|
|
|
|
|
"roleName": "admin",
|
|
|
|
|
|
"department": "信息技术部",
|
|
|
|
|
|
"permissions": ["customer:read", "customer:create", "..."]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
> **注意**:登录成功返回 `code: 200`,其他接口统一返回 `code: 0`。前端通过 `res.code === 0 || res.code === 200` 兼容判断。
|
|
|
|
|
|
|
2026-06-24 23:12:43 +08:00
|
|
|
|
**错误响应:**
|
|
|
|
|
|
|
|
|
|
|
|
| code | message |
|
|
|
|
|
|
|------|---------|
|
|
|
|
|
|
| 400 | 用户名和密码必填 |
|
|
|
|
|
|
| 400 | 账号或密码错误 |
|
|
|
|
|
|
| 403 | 账号已被禁用,请联系管理员 |
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/user/info — 获取当前用户信息
|
|
|
|
|
|
|
|
|
|
|
|
需要 Token。返回当前登录用户的完整信息(含角色名、员工名)。
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
#### GET /api/user/list — 简易用户列表
|
|
|
|
|
|
|
|
|
|
|
|
需要 Token。返回所有启用用户的基本信息(id、用户名、真实姓名),用于前端下拉选择负责人。
|
|
|
|
|
|
|
|
|
|
|
|
**响应数据字段:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 用户 ID |
|
|
|
|
|
|
| `username` | string | 用户名 |
|
|
|
|
|
|
| `real_name` | string | 真实姓名(来自员工表,可能为 null) |
|
|
|
|
|
|
|
2026-06-24 23:12:43 +08:00
|
|
|
|
#### POST /api/user/logout — 登出
|
|
|
|
|
|
|
|
|
|
|
|
需要 Token。服务端无状态,仅返回成功应答,客户端自行清除 Token。
|
|
|
|
|
|
|
|
|
|
|
|
#### PUT /api/user/password — 修改密码
|
|
|
|
|
|
|
|
|
|
|
|
需要 Token。修改当前登录用户自己的密码。
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"oldPassword": "123456",
|
|
|
|
|
|
"newPassword": "654321"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**校验规则:**
|
|
|
|
|
|
- 旧密码和新密码必填
|
|
|
|
|
|
- 新密码至少 6 位
|
|
|
|
|
|
- 新密码不能与旧密码相同
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 用户管理
|
|
|
|
|
|
|
|
|
|
|
|
> 需要 `user:manage` 权限(仅系统管理员拥有)。
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/users — 用户列表
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 | 示例 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `username` | 按用户名模糊搜索 | `?username=admin` |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `real_name` | 按真实姓名模糊搜索 | `?real_name=张` |
|
|
|
|
|
|
| `id` | 按用户 ID 精确搜索 | `?id=1` |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `role_id` | 按角色 ID 过滤 | `?role_id=2` |
|
|
|
|
|
|
| `is_active` | 按状态过滤(0-禁用, 1-启用) | `?is_active=1` |
|
|
|
|
|
|
| `page` | 页码 | `?page=1` |
|
|
|
|
|
|
| `pageSize` | 每页条数 | `?pageSize=10` |
|
|
|
|
|
|
|
|
|
|
|
|
**响应数据字段:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 用户 ID |
|
|
|
|
|
|
| `username` | string | 用户名 |
|
|
|
|
|
|
| `is_active` | number | 状态:0-禁用, 1-启用 |
|
|
|
|
|
|
| `role_id` | number | 角色 ID |
|
|
|
|
|
|
| `role_name` | string | 角色标识(如 `admin`) |
|
|
|
|
|
|
| `role_description` | string | 角色描述(如 系统管理员) |
|
|
|
|
|
|
| `employee_id` | number | 关联员工 ID |
|
|
|
|
|
|
| `real_name` | string | 真实姓名(来自员工表) |
|
|
|
|
|
|
| `department` | string | 所属部门 |
|
|
|
|
|
|
| `created_at` | datetime | 创建时间 |
|
|
|
|
|
|
| `updated_at` | datetime | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/users/:id — 用户详情
|
|
|
|
|
|
|
|
|
|
|
|
返回单个用户完整信息。
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/users — 创建用户
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `username` | ✅ | 用户名(3-50 字符) |
|
|
|
|
|
|
| `password` | ✅ | 密码(至少 6 位) |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `role_id` | ❌ | 角色 ID(需为已存在的角色) |
|
|
|
|
|
|
| `employee_id` | ❌ | 关联员工 ID(需为已存在的员工,会自动同步部门信息) |
|
|
|
|
|
|
| `department` | ❌ | 所属部门(若填了 employee_id 且未传 department,会自动从员工表同步) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `is_active` | ❌ | 状态,默认 1 |
|
|
|
|
|
|
|
|
|
|
|
|
#### PUT /api/users/:id — 更新用户
|
|
|
|
|
|
|
|
|
|
|
|
**可更新字段:** `username`、`role_id`、`employee_id`、`department`、`is_active`、`password`
|
|
|
|
|
|
|
|
|
|
|
|
**限制:**
|
|
|
|
|
|
- 不能修改自己的角色
|
|
|
|
|
|
- 不能禁用自己
|
|
|
|
|
|
|
|
|
|
|
|
#### DELETE /api/users/:id — 删除用户
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
**限制:**
|
|
|
|
|
|
- 不能删除自己
|
|
|
|
|
|
- 不能删除最后一个管理员账号(当系统中仅剩 1 个 admin 角色用户时,拒绝删除)
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 加盟商管理
|
|
|
|
|
|
|
|
|
|
|
|
> 需要 `customer:read` / `customer:create` / `customer:update` / `customer:delete` 权限。
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/customers — 加盟商列表
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 |
|
|
|
|
|
|
|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `id` | 按 ID 精确搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `name` | 按加盟商名称模糊搜索 |
|
|
|
|
|
|
| `phone` | 按电话模糊搜索 |
|
|
|
|
|
|
| `province` | 按省份精确匹配 |
|
|
|
|
|
|
| `city` | 按城市精确匹配 |
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
**响应数据字段(含 JOIN 字段):**
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 加盟商 ID |
|
|
|
|
|
|
| `name` | string | 加盟商姓名 |
|
|
|
|
|
|
| `phone` | string | 联系电话 |
|
|
|
|
|
|
| `province` | string | 省 |
|
|
|
|
|
|
| `city` | string | 市 |
|
|
|
|
|
|
| `district` | string | 区 |
|
|
|
|
|
|
| `address` | string | 详细地址 |
|
|
|
|
|
|
| `email` | string | 电子邮箱 |
|
|
|
|
|
|
| `remark` | string | 备注信息 |
|
|
|
|
|
|
| `responsible_user_id` | number | 负责人用户 ID |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `responsible_user_name` | string | 负责人姓名(JOIN 自 users → employees) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `created_at` | datetime | 创建时间 |
|
|
|
|
|
|
| `updated_at` | datetime | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/customers — 新增加盟商
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `name` | ✅ | 加盟商姓名 |
|
|
|
|
|
|
| `phone` | ❌ | 联系电话 |
|
|
|
|
|
|
| `province` | ❌ | 省 |
|
|
|
|
|
|
| `city` | ❌ | 市 |
|
|
|
|
|
|
| `district` | ❌ | 区 |
|
|
|
|
|
|
| `address` | ❌ | 详细地址 |
|
|
|
|
|
|
| `email` | ❌ | 电子邮箱 |
|
|
|
|
|
|
| `remark` | ❌ | 备注 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `responsible_user_id` | ❌ | 负责人(默认为当前登录用户,仅管理员可在前端修改) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
#### PUT /api/customers/:id — 更新加盟商
|
|
|
|
|
|
|
|
|
|
|
|
所有字段均可选,只传需要修改的字段。
|
|
|
|
|
|
|
|
|
|
|
|
#### DELETE /api/customers/:id — 删除加盟商
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 员工管理
|
|
|
|
|
|
|
|
|
|
|
|
> 需要 `employee:read` / `employee:create` / `employee:update` / `employee:delete` 权限。
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
#### GET /api/employees/simple — 简易员工列表
|
|
|
|
|
|
|
|
|
|
|
|
需要 Token。无数据范围限制,用于前端下拉选择(如售后分配业务员)。支持按部门过滤。
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| `department` | 按部门精确过滤(如 `?department=运营部`) |
|
|
|
|
|
|
|
|
|
|
|
|
**响应数据字段:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 员工 ID |
|
|
|
|
|
|
| `name` | string | 姓名 |
|
|
|
|
|
|
| `department` | string | 所属部门 |
|
|
|
|
|
|
| `position` | string | 职务/岗位 |
|
|
|
|
|
|
|
2026-06-24 23:12:43 +08:00
|
|
|
|
#### GET /api/employees — 员工列表
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 |
|
|
|
|
|
|
|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `id` | 按 ID 精确搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `name` | 按姓名模糊搜索 |
|
|
|
|
|
|
| `department` | 按部门模糊搜索 |
|
|
|
|
|
|
| `status` | 按在职状态过滤(0-离职, 1-在职) |
|
|
|
|
|
|
|
|
|
|
|
|
**响应数据字段:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 员工 ID |
|
|
|
|
|
|
| `name` | string | 姓名 |
|
|
|
|
|
|
| `gender` | string | 性别(男/女) |
|
|
|
|
|
|
| `age` | number | 年龄 |
|
|
|
|
|
|
| `education` | string | 学历 |
|
|
|
|
|
|
| `department` | string | 所属部门 |
|
|
|
|
|
|
| `entry_date` | date | 入职时间 |
|
|
|
|
|
|
| `position` | string | 职务/岗位 |
|
|
|
|
|
|
| `salary` | number | 工资金额 |
|
|
|
|
|
|
| `phone` | string | 联系电话 |
|
|
|
|
|
|
| `email` | string | 电子邮箱 |
|
|
|
|
|
|
| `status` | number | 在职状态:0-离职, 1-在职 |
|
|
|
|
|
|
| `remark` | string | 备注 |
|
|
|
|
|
|
| `created_at` | datetime | 创建时间 |
|
|
|
|
|
|
| `updated_at` | datetime | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/employees — 新增员工
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `name` | ✅ | 员工姓名 |
|
|
|
|
|
|
| `gender` | ❌ | 性别 |
|
|
|
|
|
|
| `age` | ❌ | 年龄 |
|
|
|
|
|
|
| `education` | ❌ | 学历 |
|
|
|
|
|
|
| `department` | ❌ | 部门 |
|
|
|
|
|
|
| `entry_date` | ❌ | 入职时间(格式:YYYY-MM-DD) |
|
|
|
|
|
|
| `position` | ❌ | 职务 |
|
|
|
|
|
|
| `salary` | ❌ | 工资 |
|
|
|
|
|
|
| `phone` | ❌ | 电话 |
|
|
|
|
|
|
| `email` | ❌ | 邮箱 |
|
|
|
|
|
|
| `status` | ❌ | 在职状态,默认 1 |
|
|
|
|
|
|
| `remark` | ❌ | 备注 |
|
|
|
|
|
|
|
|
|
|
|
|
#### PUT /api/employees/:id — 更新员工
|
|
|
|
|
|
|
|
|
|
|
|
所有字段均可选,只传需要修改的字段。
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
**特殊行为:** 更新 `department` 字段时,会自动同步到关联的 users 表的 `department` 字段。
|
|
|
|
|
|
|
2026-06-24 23:12:43 +08:00
|
|
|
|
#### DELETE /api/employees/:id — 删除员工
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
**特殊行为:**
|
|
|
|
|
|
- 删除员工时会同步删除关联的用户账号(users 表中 `employee_id` 匹配的记录)
|
|
|
|
|
|
- 不能删除当前登录用户自己关联的员工账号
|
|
|
|
|
|
|
2026-06-24 23:12:43 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 合同管理
|
|
|
|
|
|
|
|
|
|
|
|
> 需要 `contract:read` / `contract:create` / `contract:update` / `contract:delete` 权限。
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/contracts — 合同列表
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 |
|
|
|
|
|
|
|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `id` | 按 ID 精确搜索 |
|
|
|
|
|
|
| `status` | 按合同状态过滤(草稿/生效中/已完成/作废) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `customer_name` | 按客户名称模糊搜索 |
|
|
|
|
|
|
| `contract_no` | 按合同编号模糊搜索 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `contract_name` | 按合同名称模糊搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `employee_name` | 按业务员姓名模糊搜索 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `effective_date_start` | 按生效日期起始过滤(格式:YYYY-MM-DD) |
|
|
|
|
|
|
| `effective_date_end` | 按生效日期截止过滤(格式:YYYY-MM-DD) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
**响应数据字段(含 JOIN 字段):**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 合同 ID |
|
|
|
|
|
|
| `customer_id` | number | 客户 ID |
|
|
|
|
|
|
| `customer_name` | string | 客户名称(JOIN 自 customers) |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `supplier_id` | number | 供应商 ID(采购合同必填) |
|
|
|
|
|
|
| `supplier_name` | string | 供应商名称(JOIN 自 suppliers) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `contract_name` | string | 合同名称 |
|
|
|
|
|
|
| `contract_no` | string | 合同编号 |
|
|
|
|
|
|
| `contract_content` | string | 合同内容/条款 |
|
|
|
|
|
|
| `amount` | number | 合同金额 |
|
|
|
|
|
|
| `effective_date` | date | 生效日期 |
|
|
|
|
|
|
| `expiry_date` | date | 到期日期 |
|
|
|
|
|
|
| `employee_id` | number | 业务员 ID |
|
|
|
|
|
|
| `employee_name` | string | 业务员姓名(JOIN 自 employees) |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `status` | string | 状态:草稿/生效中/已完成/作废 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `remark` | string | 备注 |
|
|
|
|
|
|
| `type` | string | 合同类型:`franchise`(加盟)/ `supply`(采购) |
|
|
|
|
|
|
| `responsible_user_id` | number | 负责人用户 ID |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `responsible_user_name` | string | 负责人姓名(JOIN 自 users → employees) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `created_at` | datetime | 创建时间 |
|
|
|
|
|
|
| `updated_at` | datetime | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/contracts — 新增合同
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `customer_id` | 条件必填 | 关联客户 ID(加盟合同必填) |
|
|
|
|
|
|
| `supplier_id` | 条件必填 | 关联供应商 ID(采购合同必填) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `contract_name` | ✅ | 合同名称 |
|
|
|
|
|
|
| `contract_no` | ❌ | 合同编号 |
|
|
|
|
|
|
| `contract_content` | ❌ | 合同内容 |
|
|
|
|
|
|
| `amount` | ❌ | 合同金额 |
|
|
|
|
|
|
| `effective_date` | ❌ | 生效日期 |
|
|
|
|
|
|
| `expiry_date` | ❌ | 到期日期 |
|
|
|
|
|
|
| `employee_id` | ❌ | 业务员 ID |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `status` | ❌ | 状态,默认 `生效中` |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `remark` | ❌ | 备注 |
|
|
|
|
|
|
| `type` | ❌ | 合同类型(见下方说明) |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `responsible_user_id` | ❌ | 负责人(默认为当前用户,仅管理员可在前端修改) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
**合同类型自动设置与角色限制规则:**
|
|
|
|
|
|
- 采购经理(`procurement_manager`)创建的合同**只能**为 `supply`(采购合同),且必须选择 `supplier_id`
|
|
|
|
|
|
- 招商经理(`franchise_manager`)创建的合同**只能**为 `franchise`(加盟合同),且必须选择 `customer_id`
|
|
|
|
|
|
- 其他角色默认 `franchise`,也可手动指定 `type`
|
|
|
|
|
|
|
|
|
|
|
|
**校验规则:**
|
|
|
|
|
|
- `customer_id` 必须为已存在的客户
|
|
|
|
|
|
- `supplier_id` 必须为已存在的供应商
|
|
|
|
|
|
- `employee_id`(如填写)必须为已存在的员工
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
#### PUT /api/contracts/:id — 更新合同
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
所有字段均可选。可更新字段包括 `type`、`supplier_id` 和 `responsible_user_id`。
|
|
|
|
|
|
|
|
|
|
|
|
**校验规则:** 更新 `customer_id`、`supplier_id`、`employee_id` 时会校验关联记录是否存在。
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
#### DELETE /api/contracts/:id — 删除合同
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 6. 售后管理
|
|
|
|
|
|
|
|
|
|
|
|
> 需要 `after_sale:read` / `after_sale:create` / `after_sale:update` / `after_sale:delete` 权限。
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/after-sales — 售后列表
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 |
|
|
|
|
|
|
|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `id` | 按 ID 精确搜索 |
|
|
|
|
|
|
| `customer_id` | 按客户 ID 精确搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `customer_name` | 按客户名称模糊搜索 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `handle_status` | 按处理状态过滤(待处理/处理中/已完成) |
|
|
|
|
|
|
| `feedback` | 按反馈内容模糊搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
**响应数据字段(含 JOIN 字段):**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 售后记录 ID |
|
|
|
|
|
|
| `customer_id` | number | 客户 ID |
|
|
|
|
|
|
| `customer_name` | string | 客户名称(JOIN 自 customers) |
|
|
|
|
|
|
| `feedback` | string | 客户反馈意见 |
|
|
|
|
|
|
| `employee_id` | number | 处理业务员 ID |
|
|
|
|
|
|
| `employee_name` | string | 业务员姓名(JOIN 自 employees) |
|
|
|
|
|
|
| `handle_method` | string | 处理方式/解决方案 |
|
|
|
|
|
|
| `handle_status` | string | 处理状态:待处理/处理中/已完成 |
|
|
|
|
|
|
| `service_date` | date | 售后日期 |
|
|
|
|
|
|
| `remark` | string | 备注 |
|
|
|
|
|
|
| `responsible_user_id` | number | 负责人用户 ID |
|
|
|
|
|
|
| `created_at` | datetime | 创建时间 |
|
|
|
|
|
|
| `updated_at` | datetime | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/after-sales — 新增售后
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `customer_id` | ✅ | 关联客户 ID |
|
|
|
|
|
|
| `feedback` | ✅ | 售后反馈内容 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `employee_id` | ❌ | 处理业务员 ID(前端仅显示运营部员工) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `handle_method` | ❌ | 处理方式 |
|
|
|
|
|
|
| `handle_status` | ❌ | 处理状态,默认 `待处理` |
|
|
|
|
|
|
| `service_date` | ❌ | 售后日期 |
|
|
|
|
|
|
| `remark` | ❌ | 备注 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `responsible_user_id` | ❌ | 负责人(默认为当前用户,仅管理员可在前端修改) |
|
|
|
|
|
|
|
|
|
|
|
|
**校验规则:**
|
|
|
|
|
|
- `customer_id` 必须为已存在的客户
|
|
|
|
|
|
- `employee_id`(如填写)必须为已存在的员工
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
#### PUT /api/after-sales/:id — 更新售后
|
|
|
|
|
|
|
|
|
|
|
|
所有字段均可选。
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
**校验规则:** 更新 `customer_id`、`employee_id` 时会校验关联记录是否存在。
|
|
|
|
|
|
|
2026-06-24 23:12:43 +08:00
|
|
|
|
#### DELETE /api/after-sales/:id — 删除售后
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 7. 产品管理
|
|
|
|
|
|
|
|
|
|
|
|
> 需要 `product:read` / `product:create` / `product:update` / `product:delete` 权限。
|
|
|
|
|
|
> 无数据范围隔离,拥有权限即可查看所有产品。
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/products — 产品列表
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 |
|
|
|
|
|
|
|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `id` | 按 ID 精确搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `name` | 按产品名称模糊搜索 |
|
|
|
|
|
|
| `type` | 按产品类型模糊搜索 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `supplier` | 按供应商名称模糊搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
|
|
|
|
|
|
**响应数据字段:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 产品 ID |
|
|
|
|
|
|
| `name` | string | 产品名称 |
|
|
|
|
|
|
| `type` | string | 产品类型/分类 |
|
|
|
|
|
|
| `quantity` | number | 库存数量 |
|
|
|
|
|
|
| `price` | number | 单价 |
|
|
|
|
|
|
| `unit` | string | 计量单位(默认"件") |
|
|
|
|
|
|
| `specification` | string | 规格/型号 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `supplier` | string | 供应商名称 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `remark` | string | 备注 |
|
|
|
|
|
|
| `created_at` | datetime | 创建时间 |
|
|
|
|
|
|
| `updated_at` | datetime | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/products — 新增产品
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `name` | ✅ | 产品名称 |
|
|
|
|
|
|
| `type` | ❌ | 类型 |
|
|
|
|
|
|
| `quantity` | ❌ | 库存数量,默认 0 |
|
|
|
|
|
|
| `price` | ❌ | 单价,默认 0.00 |
|
|
|
|
|
|
| `unit` | ❌ | 单位,默认"件" |
|
|
|
|
|
|
| `specification` | ❌ | 规格 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `supplier` | ❌ | 供应商名称 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `remark` | ❌ | 备注 |
|
|
|
|
|
|
|
|
|
|
|
|
#### PUT /api/products/:id — 更新产品
|
|
|
|
|
|
|
|
|
|
|
|
所有字段均可选。
|
|
|
|
|
|
|
|
|
|
|
|
#### DELETE /api/products/:id — 删除产品
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 8. 供应商管理
|
|
|
|
|
|
|
|
|
|
|
|
> 需要 `supplier:read` / `supplier:create` / `supplier:update` / `supplier:delete` 权限。
|
|
|
|
|
|
> 无数据范围隔离,拥有权限即可查看所有供应商。
|
|
|
|
|
|
|
|
|
|
|
|
#### GET /api/suppliers — 供应商列表
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 说明 |
|
|
|
|
|
|
|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `id` | 按 ID 精确搜索 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `name` | 按供应商名称模糊搜索 |
|
|
|
|
|
|
| `type` | 按类型模糊搜索 |
|
|
|
|
|
|
| `status` | 按状态过滤(0-停用, 1-正常) |
|
|
|
|
|
|
|
|
|
|
|
|
**响应数据字段:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `id` | number | 供应商 ID |
|
|
|
|
|
|
| `name` | string | 供应商名称 |
|
|
|
|
|
|
| `contact` | string | 联系人 |
|
|
|
|
|
|
| `phone` | string | 联系电话 |
|
|
|
|
|
|
| `address` | string | 地址 |
|
|
|
|
|
|
| `type` | string | 类型(原材料/包装/设备) |
|
|
|
|
|
|
| `content` | string | 备注说明 |
|
|
|
|
|
|
| `status` | number | 状态:0-停用, 1-正常 |
|
|
|
|
|
|
| `created_at` | datetime | 创建时间 |
|
|
|
|
|
|
| `updated_at` | datetime | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### POST /api/suppliers — 新增供应商
|
|
|
|
|
|
|
|
|
|
|
|
**请求体:**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 必填 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `name` | ✅ | 供应商名称 |
|
|
|
|
|
|
| `contact` | ❌ | 联系人 |
|
|
|
|
|
|
| `phone` | ❌ | 联系电话 |
|
|
|
|
|
|
| `address` | ❌ | 地址 |
|
|
|
|
|
|
| `type` | ❌ | 类型 |
|
|
|
|
|
|
| `content` | ❌ | 备注说明 |
|
|
|
|
|
|
| `status` | ❌ | 状态,默认 1 |
|
|
|
|
|
|
|
|
|
|
|
|
#### PUT /api/suppliers/:id — 更新供应商
|
|
|
|
|
|
|
|
|
|
|
|
所有字段均可选。
|
|
|
|
|
|
|
|
|
|
|
|
#### DELETE /api/suppliers/:id — 删除供应商
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 统一响应格式
|
|
|
|
|
|
|
|
|
|
|
|
### 成功响应
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"message": "ok",
|
|
|
|
|
|
"data": { ... }
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 列表响应
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"message": "ok",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [ ... ],
|
|
|
|
|
|
"total": 100,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"pageSize": 10,
|
|
|
|
|
|
"totalPages": 10
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 错误响应
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 403,
|
|
|
|
|
|
"message": "权限不足"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
| HTTP 状态码 | code | 说明 |
|
|
|
|
|
|
|------------|------|------|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| 400 | 400 | 参数错误 / 校验失败 / 关联记录不存在 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| 401 | 401 | 未登录 / Token 无效 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| 403 | 403 | 权限不足 / 账号被禁用 / 角色操作限制 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| 404 | 404 | 资源不存在 |
|
|
|
|
|
|
| 409 | 409 | 数据冲突(如用户名重复) |
|
|
|
|
|
|
| 500 | 500 | 服务器内部错误 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 数据库设计
|
|
|
|
|
|
|
|
|
|
|
|
### 表结构详情
|
|
|
|
|
|
|
|
|
|
|
|
#### 1. users — 系统用户表
|
|
|
|
|
|
|
|
|
|
|
|
存储系统登录账号,每个用户关联一个角色和一个员工。
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 用户 ID |
|
|
|
|
|
|
| `username` | VARCHAR(50) | NOT NULL, UNIQUE | 用户名(登录账号) |
|
|
|
|
|
|
| `password` | VARCHAR(255) | NOT NULL | 密码(bcrypt 哈希) |
|
|
|
|
|
|
| `is_active` | TINYINT(1) | NOT NULL DEFAULT 1 | 账号状态:0-禁用, 1-启用 |
|
|
|
|
|
|
| `role_id` | INT | NULLABLE | 角色 ID → roles.id |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `employee_id` | INT | NULLABLE, UNIQUE | 员工 ID → employees.id |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `department` | VARCHAR(100) | NULLABLE | 所属部门(冗余字段,从 employees 同步) |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 2. roles — 角色表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 角色 ID |
|
|
|
|
|
|
| `name` | VARCHAR(50) | NOT NULL, UNIQUE | 角色标识(英文) |
|
|
|
|
|
|
| `description` | VARCHAR(200) | NULLABLE | 角色描述(中文) |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 3. permissions — 权限表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 权限 ID |
|
|
|
|
|
|
| `name` | VARCHAR(100) | NOT NULL, UNIQUE | 权限标识(`resource:action` 格式) |
|
|
|
|
|
|
| `description` | VARCHAR(200) | NULLABLE | 权限描述(中文) |
|
|
|
|
|
|
| `resource` | VARCHAR(50) | NOT NULL | 资源名称 |
|
|
|
|
|
|
| `action` | VARCHAR(50) | NOT NULL | 操作类型 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 4. role_permissions — 角色-权限关联表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `role_id` | INT | PK (联合) | 角色 ID → roles.id |
|
|
|
|
|
|
| `permission_id` | INT | PK (联合) | 权限 ID → permissions.id |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5. customers — 加盟商信息表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 加盟商 ID |
|
|
|
|
|
|
| `name` | VARCHAR(100) | NOT NULL, INDEX | 加盟商姓名 |
|
|
|
|
|
|
| `phone` | VARCHAR(20) | INDEX | 联系电话 |
|
|
|
|
|
|
| `province` | VARCHAR(50) | — | 省 |
|
|
|
|
|
|
| `city` | VARCHAR(50) | — | 市 |
|
|
|
|
|
|
| `district` | VARCHAR(50) | — | 区 |
|
|
|
|
|
|
| `address` | VARCHAR(200) | — | 详细地址 |
|
|
|
|
|
|
| `email` | VARCHAR(100) | — | 电子邮箱 |
|
|
|
|
|
|
| `remark` | TEXT | — | 备注信息 |
|
|
|
|
|
|
| `responsible_user_id` | INT | — | 负责人用户 ID → users.id |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 6. employees — 员工信息表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 员工 ID |
|
|
|
|
|
|
| `name` | VARCHAR(100) | NOT NULL, INDEX | 姓名 |
|
|
|
|
|
|
| `gender` | VARCHAR(4) | — | 性别:男/女 |
|
|
|
|
|
|
| `age` | INT | — | 年龄 |
|
|
|
|
|
|
| `education` | VARCHAR(50) | — | 学历 |
|
|
|
|
|
|
| `department` | VARCHAR(100) | INDEX | 所属部门 |
|
|
|
|
|
|
| `entry_date` | DATE | — | 入职时间 |
|
|
|
|
|
|
| `position` | VARCHAR(100) | — | 职务/岗位 |
|
|
|
|
|
|
| `salary` | DECIMAL(10,2) | — | 工资金额 |
|
|
|
|
|
|
| `phone` | VARCHAR(20) | — | 联系电话 |
|
|
|
|
|
|
| `email` | VARCHAR(100) | — | 电子邮箱 |
|
|
|
|
|
|
| `status` | TINYINT(1) | NOT NULL DEFAULT 1 | 在职状态:0-离职, 1-在职 |
|
|
|
|
|
|
| `remark` | TEXT | — | 备注 |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 7. contracts — 合同信息表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 合同 ID |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `customer_id` | INT | NULLABLE, INDEX | 客户 ID → customers.id(加盟合同必填) |
|
|
|
|
|
|
| `supplier_id` | INT | NULLABLE, INDEX | 供应商 ID → suppliers.id(采购合同必填) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `contract_name` | VARCHAR(200) | NOT NULL | 合同名称 |
|
|
|
|
|
|
| `contract_no` | VARCHAR(100) | — | 合同编号 |
|
|
|
|
|
|
| `contract_content` | TEXT | — | 合同内容/条款 |
|
|
|
|
|
|
| `amount` | DECIMAL(12,2) | — | 合同金额 |
|
|
|
|
|
|
| `effective_date` | DATE | INDEX | 生效日期 |
|
|
|
|
|
|
| `expiry_date` | DATE | — | 到期日期 |
|
|
|
|
|
|
| `employee_id` | INT | INDEX | 业务员 ID → employees.id |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| `status` | VARCHAR(20) | NOT NULL DEFAULT '生效中' | 状态:草稿/生效中/已完成/作废 |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| `remark` | TEXT | — | 备注 |
|
|
|
|
|
|
| `type` | VARCHAR(20) | NOT NULL DEFAULT 'franchise' | 类型:`franchise`(加盟) / `supply`(采购) |
|
|
|
|
|
|
| `responsible_user_id` | INT | — | 负责人用户 ID → users.id |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 8. after_sales — 售后信息表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 售后记录 ID |
|
|
|
|
|
|
| `customer_id` | INT | NOT NULL, INDEX | 客户 ID → customers.id |
|
|
|
|
|
|
| `feedback` | TEXT | NOT NULL | 客户反馈意见 |
|
|
|
|
|
|
| `employee_id` | INT | INDEX | 处理业务员 ID → employees.id |
|
|
|
|
|
|
| `handle_method` | TEXT | — | 处理方式/解决方案 |
|
|
|
|
|
|
| `handle_status` | VARCHAR(20) | NOT NULL DEFAULT '待处理', INDEX | 状态:待处理/处理中/已完成 |
|
|
|
|
|
|
| `service_date` | DATE | — | 售后日期 |
|
|
|
|
|
|
| `remark` | TEXT | — | 备注 |
|
|
|
|
|
|
| `responsible_user_id` | INT | — | 负责人用户 ID → users.id |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 9. products — 产品信息表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 产品 ID |
|
|
|
|
|
|
| `name` | VARCHAR(200) | NOT NULL, INDEX | 产品名称 |
|
|
|
|
|
|
| `type` | VARCHAR(100) | INDEX | 产品类型/分类 |
|
|
|
|
|
|
| `quantity` | INT | NOT NULL DEFAULT 0 | 库存数量 |
|
|
|
|
|
|
| `price` | DECIMAL(10,2) | NOT NULL DEFAULT 0.00 | 单价 |
|
|
|
|
|
|
| `unit` | VARCHAR(20) | DEFAULT '件' | 计量单位 |
|
|
|
|
|
|
| `specification` | VARCHAR(200) | — | 规格/型号 |
|
|
|
|
|
|
| `supplier` | VARCHAR(200) | — | 供应商名称 |
|
|
|
|
|
|
| `remark` | TEXT | — | 备注 |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 10. suppliers — 供应商信息表
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 约束 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `id` | INT | PK, AUTO_INCREMENT | 供应商 ID |
|
|
|
|
|
|
| `name` | VARCHAR(200) | NOT NULL, INDEX | 供应商名称 |
|
|
|
|
|
|
| `contact` | VARCHAR(100) | — | 联系人 |
|
|
|
|
|
|
| `phone` | VARCHAR(50) | — | 联系电话 |
|
|
|
|
|
|
| `address` | VARCHAR(500) | — | 地址 |
|
|
|
|
|
|
| `type` | VARCHAR(50) | — | 类型(原材料/包装/设备) |
|
|
|
|
|
|
| `content` | TEXT | — | 备注说明 |
|
|
|
|
|
|
| `status` | TINYINT(1) | NOT NULL DEFAULT 1 | 状态:0-停用, 1-正常 |
|
|
|
|
|
|
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | 创建时间 |
|
|
|
|
|
|
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 表关系 ER 图
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
|
|
|
|
|
|
│ roles │ │ permissions │ │ role_permissions │
|
|
|
|
|
|
│──────────────│ │──────────────│ │──────────────────│
|
|
|
|
|
|
│ id (PK) │◄─┐ │ id (PK) │◄─┐ │ role_id (PK,FK) │
|
|
|
|
|
|
│ name │ │ │ name │ └──│ permission_id │
|
|
|
|
|
|
│ description │ │ │ description │ │ (PK,FK) │
|
|
|
|
|
|
└──────────────┘ │ │ resource │ └──────────────────┘
|
|
|
|
|
|
│ │ action │
|
|
|
|
|
|
│ └──────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
┌──────────────┐ │ ┌──────────────┐
|
|
|
|
|
|
│ users │ │ │ employees │
|
|
|
|
|
|
│──────────────│ │ │──────────────│
|
|
|
|
|
|
│ id (PK) │ │ │ id (PK) │
|
|
|
|
|
|
│ username │ │ │ name │
|
|
|
|
|
|
│ password │ │ │ gender │
|
|
|
|
|
|
│ is_active │ │ │ age │
|
|
|
|
|
|
│ role_id (FK)─┼──┘ │ education │
|
|
|
|
|
|
│ employee_id │─ ─ ─│ department │◄──────── users.department (冗余)
|
|
|
|
|
|
│ (FK) ──────┼──→ │ entry_date │
|
|
|
|
|
|
│ department │ │ position │
|
|
|
|
|
|
│ (冗余) │ │ salary │
|
|
|
|
|
|
└──────┬───────┘ │ phone │
|
|
|
|
|
|
│ │ email │
|
|
|
|
|
|
│ │ status │
|
|
|
|
|
|
│ └──────┬───────┘
|
|
|
|
|
|
│ │
|
|
|
|
|
|
▼ ▼
|
|
|
|
|
|
┌──────────────────────────────────────────────┐
|
|
|
|
|
|
│ customers (加盟商) │
|
|
|
|
|
|
│──────────────────────────────────────────────│
|
|
|
|
|
|
│ id (PK) │
|
|
|
|
|
|
│ name, phone, province, city, district, ... │
|
|
|
|
|
|
│ responsible_user_id ──────────→ users.id │
|
|
|
|
|
|
└────────────────────┬─────────────────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
┌──────────┴──────────┐
|
|
|
|
|
|
▼ ▼
|
|
|
|
|
|
┌──────────────────┐ ┌──────────────────┐
|
|
|
|
|
|
│ contracts │ │ after_sales │
|
|
|
|
|
|
│──────────────────│ │──────────────────│
|
|
|
|
|
|
│ id (PK) │ │ id (PK) │
|
|
|
|
|
|
│ customer_id (FK) │ │ customer_id (FK) │
|
|
|
|
|
|
│ → customers.id │ │ → customers.id │
|
2026-06-25 21:53:24 +08:00
|
|
|
|
│ supplier_id (FK) │ │ feedback │
|
|
|
|
|
|
│ → suppliers.id │ │ employee_id (FK) │
|
|
|
|
|
|
│ contract_name │ │ → employees.id │
|
|
|
|
|
|
│ contract_no │ │ handle_method │
|
|
|
|
|
|
│ amount │ │ handle_status │
|
|
|
|
|
|
│ employee_id (FK) │ │ service_date │
|
|
|
|
|
|
│ → employees.id │ │ responsible_user │
|
|
|
|
|
|
│ status │ │ _id → users.id │
|
|
|
|
|
|
│ type │ └──────────────────┘
|
|
|
|
|
|
│ franchise/ │
|
|
|
|
|
|
│ supply │
|
2026-06-24 23:12:43 +08:00
|
|
|
|
│ responsible_user │
|
|
|
|
|
|
│ _id → users.id │
|
|
|
|
|
|
└──────────────────┘
|
|
|
|
|
|
|
|
|
|
|
|
┌──────────────┐ ┌──────────────┐
|
|
|
|
|
|
│ products │ │ suppliers │
|
|
|
|
|
|
│──────────────│ │──────────────│
|
|
|
|
|
|
│ id (PK) │ │ id (PK) │
|
|
|
|
|
|
│ name │ │ name │
|
|
|
|
|
|
│ type │ │ contact │
|
|
|
|
|
|
│ quantity │ │ phone │
|
|
|
|
|
|
│ price │ │ address │
|
|
|
|
|
|
│ unit │ │ type │
|
|
|
|
|
|
│ specification│ │ content │
|
|
|
|
|
|
│ supplier │ │ status │
|
|
|
|
|
|
└──────────────┘ └──────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**关系说明:**
|
|
|
|
|
|
|
|
|
|
|
|
| 关系 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| users → roles | 多对一 | 一个用户属于一个角色,一个角色可以有多个用户 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| users → employees | 一对一 | 一个用户关联一个员工(通过 employee_id,唯一约束) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| roles ↔ permissions | 多对多 | 通过 role_permissions 中间表关联 |
|
|
|
|
|
|
| customers → users | 多对一 | 通过 responsible_user_id 指定负责人 |
|
2026-06-25 21:53:24 +08:00
|
|
|
|
| contracts → customers | 多对一 | 通过 customer_id 关联客户(加盟合同必填) |
|
|
|
|
|
|
| contracts → suppliers | 多对一 | 通过 supplier_id 关联供应商(采购合同必填) |
|
2026-06-24 23:12:43 +08:00
|
|
|
|
| contracts → employees | 多对一 | 通过 employee_id 关联业务员 |
|
|
|
|
|
|
| contracts → users | 多对一 | 通过 responsible_user_id 指定负责人 |
|
|
|
|
|
|
| after_sales → customers | 多对一 | 通过 customer_id 关联客户 |
|
|
|
|
|
|
| after_sales → employees | 多对一 | 通过 employee_id 关联业务员 |
|
|
|
|
|
|
| after_sales → users | 多对一 | 通过 responsible_user_id 指定负责人 |
|
|
|
|
|
|
|
|
|
|
|
|
> **注意**:数据库未设置外键约束,引用完整性由应用代码保证(插入/更新前检查关联记录是否存在)。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## RBAC 权限系统
|
|
|
|
|
|
|
|
|
|
|
|
### 角色定义
|
|
|
|
|
|
|
|
|
|
|
|
系统预置 6 个角色,对应蜜雪冰城总部的组织架构:
|
|
|
|
|
|
|
|
|
|
|
|
| 角色标识 | 中文名 | 所属部门 | 职责概述 |
|
|
|
|
|
|
|---------|--------|---------|---------|
|
|
|
|
|
|
| `admin` | 系统管理员 | 信息技术部 | 系统全权管理,拥有所有权限 |
|
|
|
|
|
|
| `general_manager` | 总经理 | 总经理办公室 | 全局只读,查看所有业务数据 |
|
|
|
|
|
|
| `franchise_manager` | 招商经理 | 招商部 | 管理加盟商和加盟合同 |
|
|
|
|
|
|
| `operations_manager` | 运营经理 | 运营部 | 维护加盟商信息、处理售后 |
|
|
|
|
|
|
| `procurement_manager` | 采购经理 | 采购部 | 管理产品、供应商和采购合同 |
|
|
|
|
|
|
| `finance` | 财务人员 | 财务部 | 只读查看业务数据(加盟商、合同、售后、员工) |
|
|
|
|
|
|
|
|
|
|
|
|
### 权限列表
|
|
|
|
|
|
|
|
|
|
|
|
共 25 个权限,按 `资源:操作` 格式命名:
|
|
|
|
|
|
|
|
|
|
|
|
| 权限标识 | 中文描述 |
|
|
|
|
|
|
|---------|---------|
|
|
|
|
|
|
| **加盟商 (customer)** | |
|
|
|
|
|
|
| `customer:read` | 查看加盟商 |
|
|
|
|
|
|
| `customer:create` | 新增加盟商 |
|
|
|
|
|
|
| `customer:update` | 修改加盟商 |
|
|
|
|
|
|
| `customer:delete` | 删除加盟商 |
|
|
|
|
|
|
| **合同 (contract)** | |
|
|
|
|
|
|
| `contract:read` | 查看合同 |
|
|
|
|
|
|
| `contract:create` | 新增合同 |
|
|
|
|
|
|
| `contract:update` | 修改合同 |
|
|
|
|
|
|
| `contract:delete` | 删除合同 |
|
|
|
|
|
|
| **售后 (after_sale)** | |
|
|
|
|
|
|
| `after_sale:read` | 查看售后 |
|
|
|
|
|
|
| `after_sale:create` | 新增售后 |
|
|
|
|
|
|
| `after_sale:update` | 修改售后 |
|
|
|
|
|
|
| `after_sale:delete` | 删除售后 |
|
|
|
|
|
|
| **产品 (product)** | |
|
|
|
|
|
|
| `product:read` | 查看产品原料 |
|
|
|
|
|
|
| `product:create` | 新增产品原料 |
|
|
|
|
|
|
| `product:update` | 修改产品原料 |
|
|
|
|
|
|
| `product:delete` | 删除产品原料 |
|
|
|
|
|
|
| **供应商 (supplier)** | |
|
|
|
|
|
|
| `supplier:read` | 查看供应商 |
|
|
|
|
|
|
| `supplier:create` | 新增供应商 |
|
|
|
|
|
|
| `supplier:update` | 修改供应商 |
|
|
|
|
|
|
| `supplier:delete` | 删除供应商 |
|
|
|
|
|
|
| **员工 (employee)** | |
|
|
|
|
|
|
| `employee:read` | 查看员工 |
|
|
|
|
|
|
| `employee:create` | 新增员工 |
|
|
|
|
|
|
| `employee:update` | 修改员工 |
|
|
|
|
|
|
| `employee:delete` | 删除员工 |
|
|
|
|
|
|
| **用户 (user)** | |
|
|
|
|
|
|
| `user:manage` | 管理用户账号 |
|
|
|
|
|
|
|
|
|
|
|
|
### 角色-权限映射
|
|
|
|
|
|
|
|
|
|
|
|
| 权限 | admin | general_manager | franchise_manager | operations_manager | procurement_manager | finance |
|
|
|
|
|
|
|------|:-----:|:---------------:|:-----------------:|:------------------:|:-------------------:|:-------:|
|
|
|
|
|
|
| customer:read | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ |
|
|
|
|
|
|
| customer:create | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
|
|
|
|
|
|
| customer:update | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ |
|
|
|
|
|
|
| customer:delete | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
|
|
|
|
|
|
| contract:read | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
|
|
|
|
| contract:create | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| contract:update | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| contract:delete | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| after_sale:read | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ |
|
|
|
|
|
|
| after_sale:create | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
|
|
|
|
|
|
| after_sale:update | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
|
|
|
|
|
|
| after_sale:delete | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
|
|
|
|
|
|
| product:read | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| product:create | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| product:update | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| product:delete | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| supplier:read | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| supplier:create | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| supplier:update | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| supplier:delete | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
|
|
|
|
|
|
| employee:read | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
|
|
|
|
| employee:create | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
|
|
|
|
| employee:update | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
|
|
|
|
| employee:delete | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
|
|
|
|
| user:manage | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
|
|
|
|
|
|
|
|
|
|
### 数据范围隔离
|
|
|
|
|
|
|
|
|
|
|
|
拥有操作权限 ≠ 能看到所有数据。系统通过 `getDataScope()` 函数在 SQL 查询层面做数据隔离:
|
|
|
|
|
|
|
|
|
|
|
|
| 资源 | admin | general_manager | franchise_manager | operations_manager | procurement_manager | finance |
|
|
|
|
|
|
|------|-------|-----------------|-------------------|--------------------|--------------------|---------|
|
|
|
|
|
|
| customers | 全部 | 全部 | 仅自己负责 | 仅自己负责 | — | 全部 |
|
|
|
|
|
|
| contracts | 全部 | 全部 | 仅自己负责的加盟合同 | 仅自己负责的加盟合同 | 仅采购合同 | 全部 |
|
|
|
|
|
|
| after_sales | 全部 | 全部 | — | 仅自己负责 | — | 全部 |
|
|
|
|
|
|
| employees | 全部 | 全部 | 仅本部门 | 仅本部门 | 仅本部门 | 全部 |
|
|
|
|
|
|
| products | 全部 | 全部 | — | — | 全部 | — |
|
|
|
|
|
|
| suppliers | 全部 | 全部 | — | — | 全部 | — |
|
|
|
|
|
|
| users | 全部 | — | — | — | — | — |
|
|
|
|
|
|
|
|
|
|
|
|
> **"—"** 表示该角色无此资源的权限,请求会被权限中间件直接拦截(返回 403)。
|
|
|
|
|
|
|
|
|
|
|
|
**隔离机制说明:**
|
|
|
|
|
|
- **负责人类资源**(customers、contracts、after_sales):通过 `responsible_user_id` 字段过滤,只能看到自己负责的记录
|
|
|
|
|
|
- **合同类型过滤**(contracts):除了负责人类过滤,还按合同 `type` 字段过滤(franchise/supply)
|
|
|
|
|
|
- **部门类资源**(employees):通过 `department` 字段过滤,只能看到自己部门的员工
|
|
|
|
|
|
- **全局类资源**(products、suppliers):无数据范围过滤,只要有权限就能看到全部
|
|
|
|
|
|
|
2026-06-25 21:53:24 +08:00
|
|
|
|
**合同类型与角色限制:**
|
|
|
|
|
|
- 采购经理(`procurement_manager`)只能查看和操作采购合同(`type = 'supply'`)
|
|
|
|
|
|
- 招商经理(`franchise_manager`)和运营经理(`operations_manager`)只能查看和操作加盟合同(`type = 'franchise'`)中自己负责的记录
|
|
|
|
|
|
- 创建合同时,采购经理只能创建采购合同,招商经理只能创建加盟合同
|
|
|
|
|
|
|
2026-06-24 23:12:43 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 预置账号
|
|
|
|
|
|
|
|
|
|
|
|
系统首次启动时自动创建以下账号,密码均为 `123456`:
|
|
|
|
|
|
|
|
|
|
|
|
| 用户名 | 姓名 | 角色 | 部门 | 职位 |
|
|
|
|
|
|
|--------|------|------|------|------|
|
|
|
|
|
|
| `admin` | 系统管理员 | admin | 信息技术部 | 系统管理员 |
|
|
|
|
|
|
| `zhangchao` | 张超 | general_manager | 总经理办公室 | 总经理 |
|
|
|
|
|
|
| `liming` | 李明 | franchise_manager | 招商部 | 招商经理 |
|
|
|
|
|
|
| `wangli` | 王丽 | operations_manager | 运营部 | 运营经理 |
|
|
|
|
|
|
| `zhaoqiang` | 赵强 | procurement_manager | 采购部 | 采购经理 |
|
|
|
|
|
|
| `chenfang` | 陈芳 | finance | 财务部 | 财务主管 |
|
|
|
|
|
|
|
|
|
|
|
|
### 快速测试
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 以管理员身份登录
|
|
|
|
|
|
curl -X POST http://127.0.0.1:3000/api/user/login \
|
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
|
-d '{"username":"admin","password":"123456"}'
|
|
|
|
|
|
|
|
|
|
|
|
# 以招商经理身份登录(只能看到自己负责的加盟商)
|
|
|
|
|
|
curl -X POST http://127.0.0.1:3000/api/user/login \
|
|
|
|
|
|
-H "Content-Type: application/json" \
|
|
|
|
|
|
-d '{"username":"liming","password":"123456"}'
|
|
|
|
|
|
```
|