770 lines
22 KiB
Markdown
770 lines
22 KiB
Markdown
# 泊云智销通
|
||
|
||
## 项目简介
|
||
|
||
泊云智销通是一款面向企业渠道管理的 CRM 系统,旨在解决渠道管理中的核心问题——**客户报备冲突**与**保护期归属**。系统通过唯一有效报备机制与自动到期释放机制,确保同一客户在同一时间只能被一个经销商跟进,并在保护期结束后自动回归可报备池,避免长期占坑,提升渠道效率与公平性。
|
||
|
||
### 核心价值
|
||
|
||
- **防撞单机制**:同一客户同一时间只能有一个有效报备
|
||
- **保护期管理**:自动计算和跟踪保护期,保护期到期自动释放
|
||
- **公平竞争**:避免经销商长期占用客户资源
|
||
- **全程可追溯**:所有报备记录永久保留,支持审计
|
||
|
||
---
|
||
|
||
## 技术架构
|
||
|
||
### 后端技术栈
|
||
|
||
- **框架**: Spring Boot 2.7
|
||
- **ORM**: MyBatis
|
||
- **数据库**: MySQL 8
|
||
- **安全**: Spring Security + JWT + BCrypt
|
||
- **API 文档**: Swagger
|
||
- **构建工具**: Maven
|
||
|
||
### 前端技术栈
|
||
|
||
- **框架**: Vue 3 + TypeScript
|
||
- **UI 组件**: Element Plus
|
||
- **路由**: Vue Router
|
||
- **状态管理**: Pinia
|
||
- **HTTP 客户端**: Axios
|
||
- **构建工具**: Vite
|
||
- **代码规范**: ESLint + Prettier
|
||
|
||
### 架构模式
|
||
|
||
- **前后端分离**: RESTful API 架构
|
||
- **MVC 分层**: Controller → Service → Mapper → Entity
|
||
- **数据库设计**: 遵循范式,合理使用索引
|
||
- **安全设计**: 前端 SHA-256 哈希 + 后端 BCrypt 双重加密
|
||
|
||
---
|
||
|
||
## 用户角色与权限
|
||
|
||
### 1. 管理员
|
||
|
||
**角色标识**: `role = 0`
|
||
|
||
**权限范围**:
|
||
- ✅ 客户管理(全部客户的查看、新增、编辑、删除)
|
||
- ✅ 报备管理(全部报备的查看、审核、撤回)
|
||
- ✅ 经销商管理(经销商的增删改查、重置密码)
|
||
- ✅ 系统配置(保护期天数等参数配置)
|
||
- ✅ 数据报表(经销商活跃度、客户转化率等)
|
||
- ✅ 查看所有运营数据
|
||
|
||
**主要职责**:
|
||
- 维护客户信息
|
||
- 审核报备申请
|
||
- 管理经销商账号
|
||
- 配置系统参数
|
||
- 监控渠道数据
|
||
|
||
### 2. 经销商用户
|
||
|
||
**角色标识**: `role = 1`
|
||
|
||
**权限范围**:
|
||
- ✅ 查看自己的客户列表
|
||
- ✅ 提交报备申请(选择客户进行报备)
|
||
- ✅ 查看自己的报备记录
|
||
- ✅ 撤回待审核的报备
|
||
- ✅ 查看报备审核状态
|
||
- ✅ 修改个人密码
|
||
|
||
**主要职责**:
|
||
- 报备意向客户
|
||
- 跟进保护期内的客户
|
||
- 维护客户信息
|
||
- 管理报备记录
|
||
|
||
### 权限矩阵
|
||
|
||
| 功能模块 | 管理员 | 经销商 |
|
||
|---------|--------|--------|
|
||
| 客户管理 | ✅ 全部 | ✅ 仅查看 |
|
||
| 报备管理 | ✅ 全部 | ✅ 自己的报备 |
|
||
| 报备审核 | ✅ | ❌ |
|
||
| 经销商管理 | ✅ | ❌ |
|
||
| 系统配置 | ✅ | ❌ |
|
||
| 数据报表 | ✅ | ❌ |
|
||
| 密码管理 | ✅ 自己的 | ✅ 自己的 |
|
||
|
||
---
|
||
|
||
## 功能清单
|
||
|
||
### 1. 认证与授权
|
||
|
||
#### 1.1 用户登录
|
||
- **路径**: `POST /api/auth/login`
|
||
- **描述**: 用户登录系统,获取 JWT Token
|
||
- **安全**: 前端 SHA-256 哈希 + 后端 BCrypt 加密
|
||
- **返回**: Token + 用户基本信息
|
||
|
||
**默认账号**:
|
||
- 管理员: `admin` / `admin123`
|
||
- 经销商1: `user001` / `admin123`
|
||
- 经销商2: `user002` / `admin123`
|
||
- 经销商3: `user003` / `admin123`
|
||
|
||
#### 1.2 修改密码
|
||
- **路径**: `POST /api/auth/change-password`
|
||
- **权限**: 所有用户
|
||
- **功能**: 用户修改自己的登录密码
|
||
- **验证**: 需要输入原密码验证
|
||
- **安全**: 密码 6-20 位,传输前哈希加密
|
||
|
||
#### 1.3 重置密码
|
||
- **路径**: `POST /api/auth/reset-password`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 管理员重置经销商用户的密码
|
||
- **限制**: 不能重置管理员账号的密码
|
||
|
||
#### 1.4 退出登录
|
||
- **路径**: `POST /api/auth/logout`
|
||
- **功能**: 清除客户端 Token
|
||
|
||
---
|
||
|
||
### 2. 客户管理
|
||
|
||
#### 2.1 客户列表
|
||
- **路径**: `GET /api/customer/page`
|
||
- **权限**: 管理员查看全部,经销商查看全部
|
||
- **功能**: 分页查询客户信息
|
||
- **搜索字段**: 客户名称、所属行业、状态
|
||
- **状态说明**:
|
||
- `0 - 可报备`: 未被保护,可报备
|
||
- `1 - 保护中`: 正在保护期内
|
||
- `2 - 已失效`: 保护期已过
|
||
|
||
#### 2.2 新增客户
|
||
- **路径**: `POST /api/customer`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 创建新客户信息
|
||
- **必填字段**: 客户名称
|
||
- **可选字段**: 联系电话、地址、所属行业
|
||
- **学校联动**: 支持从学校库自动完成选择
|
||
|
||
#### 2.3 编辑客户
|
||
- **路径**: `PUT /api/customer/{id}`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 修改客户信息
|
||
|
||
#### 2.4 删除客户
|
||
- **路径**: `DELETE /api/customer/{id}`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 删除客户记录
|
||
- **限制**: 有报备记录的客户需谨慎处理
|
||
|
||
#### 2.5 客户搜索
|
||
- **路径**: `GET /api/customer/search`
|
||
- **功能**: 模糊搜索客户名称(用于报备时的客户选择)
|
||
|
||
---
|
||
|
||
### 3. 报备管理
|
||
|
||
#### 3.1 报备列表
|
||
- **路径**: `GET /api/report/page`
|
||
- **权限**: 管理员查看全部,经销商查看自己的
|
||
- **功能**: 分页查询报备记录
|
||
- **状态说明**:
|
||
- `0 - 待审核`: 等待管理员审核
|
||
- `1 - 已通过`: 审核通过,保护期内
|
||
- `2 - 已驳回`: 审核未通过
|
||
- `3 - 已失效`: 保护期已过
|
||
|
||
#### 3.2 提交报备
|
||
- **路径**: `POST /api/report`
|
||
- **权限**: 经销商
|
||
- **功能**: 经销商报备意向客户
|
||
- **必填字段**: 客户ID、报备说明
|
||
- **限制**:
|
||
- 同一客户同一时间只能有一个有效报备
|
||
- 已保护的客户无法再次报备
|
||
- 待审核的报备可撤回
|
||
|
||
#### 3.3 撤回报备
|
||
- **路径**: `DELETE /api/report/{id}`
|
||
- **权限**: 报备所属经销商
|
||
- **功能**: 撤回待审核的报备申请
|
||
- **限制**: 已通过和已驳回的报备无法撤回
|
||
|
||
#### 3.4 审核报备
|
||
- **路径**: `PUT /api/report/{id}/audit`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 审核报备申请
|
||
- **操作**:
|
||
- 通过:设置保护期(默认90天),客户状态改为"保护中"
|
||
- 驳回:填写驳回原因,客户保持可报备状态
|
||
|
||
#### 3.5 报备详情
|
||
- **路径**: `GET /api/report/{id}`
|
||
- **权限**: 根据权限查看
|
||
- **功能**: 查看报备详细信息
|
||
|
||
---
|
||
|
||
### 4. 经销商管理
|
||
|
||
#### 4.1 经销商列表
|
||
- **路径**: `GET /api/dealer/list`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 查询所有经销商信息
|
||
- **状态**: 启用/禁用
|
||
|
||
#### 4.2 新增经销商
|
||
- **路径**: `POST /api/dealer`
|
||
- **权限**: 仅管理员
|
||
- **必填字段**: 经销商名称、经销商账号(用作登录用户名)、联系人、联系电话
|
||
- **可选字段**: 邮箱、初始密码
|
||
- **自动创建**:
|
||
- 创建经销商记录
|
||
- 创建对应的登录用户
|
||
- 用户名 = 经销商账号
|
||
- 默认密码 = 123456(可自定义)
|
||
|
||
#### 4.3 编辑经销商
|
||
- **路径**: `PUT /api/dealer/{id}`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 修改经销商信息
|
||
|
||
#### 4.4 删除经销商
|
||
- **路径**: `DELETE /api/dealer/{id}`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 删除经销商及其关联用户
|
||
|
||
#### 4.5 重置密码
|
||
- **路径**: `POST /api/auth/reset-password`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 重置经销商用户的登录密码
|
||
|
||
---
|
||
|
||
### 5. 学校管理
|
||
|
||
#### 5.1 学校列表
|
||
- **路径**: `GET /api/school/list`
|
||
- **权限**: 所有用户
|
||
- **功能**: 查询所有学校信息
|
||
|
||
#### 5.2 学校搜索
|
||
- **路径**: `GET /api/school/search?keyword=xxx`
|
||
- **权限**: 所有用户
|
||
- **功能**: 模糊搜索学校名称(用于客户名称自动完成)
|
||
- **应用场景**: 新增客户时,输入学校名称,自动匹配学校库
|
||
|
||
#### 5.3 批量导入学校
|
||
- **路径**: `POST /api/school/import`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 上传 Excel 文件批量导入学校数据
|
||
- **文件格式**: `.xls` 或 `.xlsx`
|
||
|
||
#### 5.4 从 docs 目录导入
|
||
- **路径**: `POST /api/school/import-from-docs`
|
||
- **权限**: 仅管理员
|
||
- **功能**: 直接导入项目 docs 目录下的 `school.xls` 文件
|
||
|
||
**学校数据结构**:
|
||
- 学校标识码
|
||
- 学校名称
|
||
- 所在地(省份 + 城市)
|
||
|
||
---
|
||
|
||
### 6. 系统配置
|
||
|
||
#### 6.1 保护期配置
|
||
- **配置项**: `report.protect.days`
|
||
- **默认值**: `90` 天
|
||
- **说明**: 控制报备通过后的保护期时长
|
||
- **影响**:
|
||
- 保护期计算
|
||
- 自动失效定时任务
|
||
|
||
#### 6.2 报备冲突控制
|
||
- **配置项**: `report.allow-overlap`
|
||
- **默认值**: `false`
|
||
- **说明**: 是否允许同一客户的报备重叠(仅用于测试)
|
||
- **生产**: 必须为 `false`
|
||
|
||
---
|
||
|
||
## 业务流程
|
||
|
||
### 报备生命周期
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 报备完整流程 │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
|
||
1. 经销商提交报备
|
||
├─ 选择客户(只能选择"可报备"状态的客户)
|
||
├─ 填写报备说明
|
||
└─ 提交审核
|
||
↓
|
||
状态:待审核(0)
|
||
客户状态:可报备(0)
|
||
|
||
2. 管理员审核
|
||
├─ 通过 → 设置保护期(如90天)
|
||
│ ├─ 报备状态:已通过(1)
|
||
│ └─ 客户状态:保护中(1)
|
||
│
|
||
└─ 驳回 → 填写驳回原因
|
||
├─ 报备状态:已驳回(2)
|
||
└─ 客户状态:可报备(0)
|
||
|
||
3. 保护期内
|
||
├─ 客户被锁定,其他经销商无法报备
|
||
├─ 原报备经销商可跟进客户
|
||
└─ 剩余保护天数倒计时
|
||
|
||
4. 保护期到期(定时任务)
|
||
└─ 每天凌晨1点自动执行
|
||
├─ 报备状态:已通过 → 已失效(3)
|
||
└─ 客户状态:保护中 → 可报备(0)
|
||
|
||
5. 客户释放
|
||
└─ 所有经销商可再次报备该客户
|
||
```
|
||
|
||
### 客户状态流转
|
||
|
||
```
|
||
可报备(0) ──[提交报备]──> 锁定(其他经销商不可报备)
|
||
│
|
||
[管理员审核通过]
|
||
↓
|
||
保护中(1) ──[90天后]──> 可报备(0)
|
||
↑
|
||
[报备被驳回]
|
||
│
|
||
[管理员驳回]
|
||
↓
|
||
可报备(0)
|
||
```
|
||
|
||
---
|
||
|
||
## 数据库设计
|
||
|
||
### 核心表结构
|
||
|
||
#### 1. 客户表 (crm_customer)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | BIGINT | 客户ID(主键) |
|
||
| name | VARCHAR(200) | 客户名称 |
|
||
| phone | VARCHAR(20) | 联系电话 |
|
||
| address | VARCHAR(500) | 地址 |
|
||
| industry | VARCHAR(50) | 所属行业 |
|
||
| status | TINYINT | 状态:0-可报备 1-保护中 2-已失效 |
|
||
| current_dealer_id | BIGINT | 当前报备经销商ID |
|
||
| protect_end_date | DATE | 保护期结束日期 |
|
||
| created_at | DATETIME | 创建时间 |
|
||
| updated_at | DATETIME | 更新时间 |
|
||
|
||
#### 2. 报备表 (crm_report)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | BIGINT | 报备ID(主键) |
|
||
| dealer_id | BIGINT | 经销商ID |
|
||
| customer_id | BIGINT | 客户ID |
|
||
| description | VARCHAR(500) | 报备说明 |
|
||
| status | TINYINT | 状态:0-待审核 1-已通过 2-已驳回 3-已失效 |
|
||
| reject_reason | VARCHAR(255) | 驳回原因 |
|
||
| protect_start_date | DATE | 保护期开始日期 |
|
||
| protect_end_date | DATE | 保护期结束日期 |
|
||
| created_at | DATETIME | 创建时间 |
|
||
| updated_at | DATETIME | 更新时间 |
|
||
|
||
**唯一索引**: `uk_customer_valid (customer_id, status)` - 同一客户只能有一个有效报备
|
||
|
||
#### 3. 经销商表 (crm_dealer)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | BIGINT | 经销商ID(主键) |
|
||
| name | VARCHAR(200) | 经销商名称 |
|
||
| code | VARCHAR(50) | 经销商账号(唯一) |
|
||
| contact_person | VARCHAR(50) | 联系人 |
|
||
| contact_phone | VARCHAR(20) | 联系电话 |
|
||
| email | VARCHAR(100) | 邮箱 |
|
||
| status | TINYINT | 状态:0-禁用 1-启用 |
|
||
| created_at | DATETIME | 创建时间 |
|
||
| updated_at | DATETIME | 更新时间 |
|
||
|
||
#### 4. 用户表 (crm_user)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | BIGINT | 用户ID(主键) |
|
||
| username | VARCHAR(50) | 用户名(登录账号) |
|
||
| password | VARCHAR(255) | 密码(BCrypt加密) |
|
||
| real_name | VARCHAR(50) | 真实姓名 |
|
||
| dealer_id | BIGINT | 关联经销商ID(管理员为NULL) |
|
||
| role | TINYINT | 角色:0-管理员 1-经销商用户 |
|
||
| status | TINYINT | 状态:0-禁用 1-启用 |
|
||
| created_at | DATETIME | 创建时间 |
|
||
| updated_at | DATETIME | 更新时间 |
|
||
|
||
#### 5. 学校表 (crm_school)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | BIGINT | 学校ID(主键) |
|
||
| school_code | VARCHAR(50) | 学校标识码(唯一) |
|
||
| school_name | VARCHAR(200) | 学校名称 |
|
||
| location | VARCHAR(255) | 所在地(省份+城市) |
|
||
| created_at | DATETIME | 创建时间 |
|
||
| updated_at | DATETIME | 更新时间 |
|
||
|
||
---
|
||
|
||
## 定时任务
|
||
|
||
### 报备过期处理
|
||
|
||
**执行时间**: 每天凌晨 1 点
|
||
**Cron 表达式**: `0 0 1 * * ?`
|
||
|
||
**功能**:
|
||
1. 查询所有保护期已到的报备(`protect_end_date <= 今天` 且 `status = 1`)
|
||
2. 批量更新报备状态为"已失效"(`status = 3`)
|
||
3. 批量更新关联客户状态为"可报备"(`status = 0`)
|
||
4. 保证渠道资源公平分配
|
||
|
||
---
|
||
|
||
## 安全机制
|
||
|
||
### 1. 认证与授权
|
||
|
||
#### JWT Token 认证
|
||
- 用户登录后获取 JWT Token
|
||
- Token 包含:用户ID、用户名、角色、经销商ID
|
||
- Token 存储在客户端 `localStorage`
|
||
- 每次请求在 Header 中携带:`Authorization: Bearer {token}`
|
||
|
||
#### 权限拦截
|
||
- 前端路由守卫:未登录重定向到登录页
|
||
- 后端拦截器:验证 Token 有效性
|
||
- 接口权限注解:`@AuthRequired`
|
||
- 数据权限:经销商只能查看自己的报备
|
||
|
||
### 2. 密码安全
|
||
|
||
#### 双重加密
|
||
```
|
||
用户输入 → [前端 SHA-256 哈希] → HTTPS 传输 → [后端 BCrypt 加密] → 存储
|
||
```
|
||
|
||
#### 密码规则
|
||
- 长度:6-20 位
|
||
- 加密:BCrypt(自动加盐)
|
||
- 传输:SHA-256 哈希后传输
|
||
- 修改密码:需验证原密码
|
||
|
||
### 3. 数据安全
|
||
|
||
#### SQL 注入防护
|
||
- 使用 MyBatis 参数化查询
|
||
- 所有用户输入都经过参数绑定
|
||
|
||
#### XSS 防护
|
||
- 前端输出自动转义
|
||
- 后端返回 JSON 格式
|
||
|
||
#### CSRF 防护
|
||
- 使用 JWT 无状态认证
|
||
- 不依赖 Session Cookie
|
||
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
by-crm/
|
||
├── backend/ # 后端工程
|
||
│ ├── src/main/java/com/bycrm/
|
||
│ │ ├── annotations/ # 自定义注解(权限等)
|
||
│ │ ├── common/ # 公共类(Result、Constants等)
|
||
│ │ ├── config/ # 配置类(CORS、MyBatis、Swagger等)
|
||
│ │ ├── controller/ # 控制器层
|
||
│ │ │ ├── AuthController.java
|
||
│ │ │ ├── CustomerController.java
|
||
│ │ │ ├── ReportController.java
|
||
│ │ │ ├── DealerController.java
|
||
│ │ │ └── SchoolController.java
|
||
│ │ ├── dto/ # 数据传输对象
|
||
│ │ ├── entity/ # 实体类
|
||
│ │ ├── exception/ # 异常处理
|
||
│ │ ├── mapper/ # MyBatis Mapper 接口
|
||
│ │ ├── service/ # 业务逻辑层
|
||
│ │ ├── task/ # 定时任务
|
||
│ │ ├── util/ # 工具类(JWT、加密等)
|
||
│ │ ├── vo/ # 视图对象
|
||
│ │ └── ByCrmApplication.java
|
||
│ ├── src/main/resources/
|
||
│ │ ├── mapper/*.xml # MyBatis SQL 映射
|
||
│ │ └── application.yml # 配置文件
|
||
│ └── pom.xml # Maven 依赖
|
||
│
|
||
├── frontend/ # 前端工程
|
||
│ ├── src/
|
||
│ │ ├── api/ # API 接口封装
|
||
│ │ ├── assets/ # 静态资源
|
||
│ │ ├── components/ # 通用组件
|
||
│ │ ├── router/ # Vue Router 配置
|
||
│ │ ├── stores/ # Pinia 状态管理
|
||
│ │ ├── types/ # TypeScript 类型定义
|
||
│ │ ├── utils/ # 工具函数(请求、加密等)
|
||
│ │ ├── views/ # 页面组件
|
||
│ │ │ ├── Login.vue # 登录页
|
||
│ │ │ ├── Layout.vue # 主布局
|
||
│ │ │ ├── Dashboard.vue # 首页
|
||
│ │ │ ├── Customer.vue # 客户管理
|
||
│ │ │ ├── Report.vue # 报备管理
|
||
│ │ │ └── Dealer.vue # 经销商管理
|
||
│ │ ├── App.vue # 根组件
|
||
│ │ └── main.ts # 入口文件
|
||
│ ├── vite.config.ts # Vite 配置
|
||
│ ├── package.json # 依赖配置
|
||
│ └── tsconfig.json # TS 配置
|
||
│
|
||
├── sql/ # 数据库脚本
|
||
│ ├── init.sql # 初始化脚本
|
||
│ ├── school_table.sql # 学校表
|
||
│ └── *.sql # 其他 SQL 脚本
|
||
│
|
||
└── docs/ # 文档目录
|
||
├── api.md # API 文档(Swagger 导出)
|
||
└── password-security.md # 密码安全说明
|
||
```
|
||
|
||
---
|
||
|
||
## 环境配置
|
||
|
||
### 后端配置 (application.yml)
|
||
|
||
```yaml
|
||
server:
|
||
port: 8080
|
||
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://localhost:3306/by_crm
|
||
username: root
|
||
password: your_password
|
||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||
|
||
mybatis:
|
||
mapper-locations: classpath:mapper/*.xml
|
||
type-aliases-package: com.bycrm.entity
|
||
|
||
# JWT 配置
|
||
jwt:
|
||
secret: your-secret-key
|
||
expiration: 86400000 # 24小时(毫秒)
|
||
|
||
# 保护期配置
|
||
crm:
|
||
report:
|
||
ttl-days: 90 # 保护期天数(默认90天)
|
||
allow-overlap: false # 是否允许报备重叠(测试用,生产必须false)
|
||
```
|
||
|
||
### 前端配置
|
||
|
||
```typescript
|
||
// API 基础地址
|
||
const BASE_URL = 'http://localhost:8080/api'
|
||
|
||
// Token 存储
|
||
const TOKEN_KEY = 'token'
|
||
|
||
// 路由模式:history 或 hash
|
||
const routerMode = 'history'
|
||
```
|
||
|
||
---
|
||
|
||
## 部署说明
|
||
|
||
### 开发环境启动
|
||
|
||
**后端**:
|
||
```bash
|
||
cd backend
|
||
mvn spring-boot:run
|
||
# 访问: http://localhost:8080
|
||
# Swagger: http://localhost:8080/swagger-ui.html
|
||
```
|
||
|
||
**前端**:
|
||
```bash
|
||
cd frontend
|
||
pnpm install
|
||
pnpm dev
|
||
# 访问: http://localhost:5173
|
||
```
|
||
|
||
### 生产环境部署
|
||
|
||
**后端**:
|
||
```bash
|
||
# 编译打包
|
||
mvn clean package
|
||
|
||
# 运行 JAR
|
||
java -jar target/bycrm-0.0.1-SNAPSHOT.jar
|
||
```
|
||
|
||
**前端**:
|
||
```bash
|
||
# 编译打包
|
||
pnpm build
|
||
|
||
# 部署 dist 目录到 Web 服务器
|
||
```
|
||
|
||
### 数据库初始化
|
||
|
||
```bash
|
||
# 创建数据库
|
||
mysql -u root -p -e "CREATE DATABASE by_crm CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
|
||
|
||
# 导入初始化脚本
|
||
mysql -u root -p by_crm < sql/init.sql
|
||
```
|
||
|
||
---
|
||
|
||
## API 接口清单
|
||
|
||
### 认证接口
|
||
- `POST /api/auth/login` - 用户登录
|
||
- `GET /api/auth/user/info` - 获取当前用户信息
|
||
- `POST /api/auth/logout` - 用户退出
|
||
- `POST /api/auth/change-password` - 修改密码
|
||
- `POST /api/auth/reset-password` - 重置密码
|
||
|
||
### 客户接口
|
||
- `GET /api/customer/page` - 分页查询客户
|
||
- `GET /api/customer/{id}` - 获取客户详情
|
||
- `POST /api/customer` - 创建客户
|
||
- `PUT /api/customer/{id}` - 更新客户
|
||
- `DELETE /api/customer/{id}` - 删除客户
|
||
- `GET /api/customer/search?keyword=xxx` - 搜索客户
|
||
|
||
### 报备接口
|
||
- `GET /api/report/page` - 分页查询报备
|
||
- `GET /api/report/{id}` - 获取报备详情
|
||
- `POST /api/report` - 创建报备
|
||
- `DELETE /api/report/{id}` - 撤回报备
|
||
- `PUT /api/report/{id}/audit` - 审核报备
|
||
|
||
### 经销商接口(仅管理员)
|
||
- `GET /api/dealer/list` - 查询所有经销商
|
||
- `POST /api/dealer` - 创建经销商
|
||
- `PUT /api/dealer/{id}` - 更新经销商
|
||
- `DELETE /api/dealer/{id}` - 删除经销商
|
||
|
||
### 学校接口
|
||
- `GET /api/school/list` - 查询所有学校
|
||
- `GET /api/school/search?keyword=xxx` - 搜索学校
|
||
- `POST /api/school` - 创建学校
|
||
- `POST /api/school/import` - 文件上传导入
|
||
- `POST /api/school/import-from-docs` - 从 docs 目录导入
|
||
|
||
---
|
||
|
||
## 版本历史
|
||
|
||
### v1.0.0 (当前版本)
|
||
|
||
**新增功能**:
|
||
- ✅ 客户管理(增删改查)
|
||
- ✅ 报备管理(提交、审核、撤回)
|
||
- ✅ 经销商管理(增删改查、重置密码)
|
||
- ✅ 学校管理(查询、搜索、导入)
|
||
- ✅ 用户认证(登录、密码管理)
|
||
- ✅ 自动保护期到期处理
|
||
- ✅ 学校数据自动完成功能
|
||
- ✅ 密码传输加密(SHA-256 + BCrypt 双重加密)
|
||
|
||
**安全特性**:
|
||
- ✅ JWT Token 认证
|
||
- ✅ BCrypt 密码加密存储
|
||
- ✅ SHA-256 前端哈希传输
|
||
- ✅ 权限注解拦截
|
||
- ✅ SQL 注入防护
|
||
- ✅ XSS 防护
|
||
|
||
---
|
||
|
||
## 常见问题
|
||
|
||
### 1. 默认密码是什么?
|
||
- 新增经销商时,如果不设置初始密码,默认为 `123456`
|
||
- 管理员账号:`admin` / `admin123`
|
||
- 经销商账号:`user001~003` / `admin123`
|
||
|
||
### 2. 保护期可以修改吗?
|
||
- 可以,通过修改系统配置 `report.protect.days`
|
||
- 默认为 90 天,可根据业务需求调整
|
||
|
||
### 3. 同一客户可以同时被多个经销商报备吗?
|
||
- **不可以**,这是系统的核心规则
|
||
- 同一时间只能有一个"已通过"的报备
|
||
- 其他经销商报备该客户会被拒绝
|
||
|
||
### 4. 保护期到期后会发生什么?
|
||
- 定时任务每天凌晨1点自动执行
|
||
- 将过期报备状态改为"已失效"
|
||
- 客户状态自动变为"可报备"
|
||
- 其他经销商可以再次报备
|
||
|
||
### 5. 如何确保传输安全?
|
||
- 前端:使用 Web Crypto API 进行 SHA-256 哈希
|
||
- 传输:HTTPS + 哈希后的密码
|
||
- 后端:BCrypt 二次加密存储
|
||
- 三重安全保障
|
||
|
||
### 6. 管理员可以重置其他管理员密码吗?
|
||
- **不可以**,只能重置经销商用户的密码
|
||
- 管理员修改自己的密码通过"修改密码"功能
|
||
|
||
### 7. 学校数据从哪里来?
|
||
- 存放在 `docs/school.xls` 文件中
|
||
- 包含:学校标识码、学校名称、所在地
|
||
- 可通过 API 导入到数据库
|
||
|
||
---
|
||
|
||
## 技术支持
|
||
|
||
### 开发团队
|
||
- 后端开发:Spring Boot + MyBatis + MySQL
|
||
- 前端开发:Vue 3 + TypeScript + Element Plus
|
||
- 项目管理:Maven + pnpm
|
||
|
||
### 联系方式
|
||
- 问题反馈:提交 Issue 到项目仓库
|
||
- 技术文档:详见 `docs/` 目录
|
||
|
||
---
|
||
|
||
**版权声明**: 本系统为企业内部使用,未经授权不得复制或传播。
|