docs: 添加流水分析对接文档和数据库迁移计划
This commit is contained in:
@@ -1,32 +0,0 @@
|
|||||||
# 数据库迁移配置文件模板
|
|
||||||
# 使用方法:复制此文件为 db_config.conf 并填写实际值
|
|
||||||
|
|
||||||
# 源数据库配置(开发环境)
|
|
||||||
SOURCE_DB_HOST=your_source_host
|
|
||||||
SOURCE_DB_PORT=3306
|
|
||||||
SOURCE_DB_USER=your_source_user
|
|
||||||
SOURCE_DB_PASS=your_source_password
|
|
||||||
SOURCE_DB_NAME=ccdi
|
|
||||||
|
|
||||||
# 生产环境数据库配置
|
|
||||||
PROD_DB_HOST=your_production_host
|
|
||||||
PROD_DB_PORT=3306
|
|
||||||
PROD_DB_USER=your_production_user
|
|
||||||
PROD_DB_PASS=your_production_password
|
|
||||||
PROD_DB_NAME=ccdi
|
|
||||||
|
|
||||||
# 测试环境数据库配置(可选)
|
|
||||||
TEST_DB_HOST=your_test_host
|
|
||||||
TEST_DB_PORT=3306
|
|
||||||
TEST_DB_USER=your_test_user
|
|
||||||
TEST_DB_PASS=your_test_password
|
|
||||||
TEST_DB_NAME=ccdi
|
|
||||||
|
|
||||||
# 导出文件配置
|
|
||||||
BACKUP_DIR=doc/database/backup
|
|
||||||
STRUCTURE_FILE=ccdi_structure.sql
|
|
||||||
DATA_FILE=ccdi_data.sql
|
|
||||||
|
|
||||||
# mysqldump 参数配置
|
|
||||||
CHARACTER_SET=utf8mb4
|
|
||||||
MAX_ALLOWED_PACKET=512M
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
-- CCDI 数据库数据
|
-- CCDI 数据库数据
|
||||||
-- 导出时间: 2026-02-28 15:23:04
|
-- 导出时间: 2026-02-28 15:26:26
|
||||||
-- 源数据库: 116.62.17.81:3306/ccdi
|
-- 源数据库: 116.62.17.81:3306/ccdi
|
||||||
-- 字符集: utf8mb4
|
-- 字符集: utf8mb4
|
||||||
|
|
||||||
@@ -445,6 +445,6 @@ UNLOCK TABLES;
|
|||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2026-02-28 15:23:04
|
-- Dump completed on 2026-02-28 15:26:26
|
||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS=1;
|
SET FOREIGN_KEY_CHECKS=1;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
-- CCDI 数据库表结构
|
-- CCDI 数据库表结构
|
||||||
-- 导出时间: 2026-02-28 15:22:54
|
-- 导出时间: 2026-02-28 15:26:16
|
||||||
-- 源数据库: 116.62.17.81:3306/ccdi
|
-- 源数据库: 116.62.17.81:3306/ccdi
|
||||||
-- 字符集: utf8mb4
|
-- 字符集: utf8mb4
|
||||||
|
|
||||||
@@ -1092,4 +1092,4 @@ CREATE TABLE `sys_user_role` (
|
|||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2026-02-28 15:22:54
|
-- Dump completed on 2026-02-28 15:26:16
|
||||||
|
|||||||
308
doc/test-scripts/2026-02-28-frontend-test-report.md
Normal file
308
doc/test-scripts/2026-02-28-frontend-test-report.md
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
# 前端功能测试报告
|
||||||
|
|
||||||
|
## 测试概述
|
||||||
|
|
||||||
|
**测试日期**: 2026-02-28
|
||||||
|
**测试人员**: Claude Code
|
||||||
|
**测试环境**:
|
||||||
|
- 后端: http://localhost:8080
|
||||||
|
- 前端: http://localhost:84
|
||||||
|
- 浏览器: Chrome 145.0.0.0
|
||||||
|
- 测试账号: admin/admin123
|
||||||
|
|
||||||
|
## 测试目标
|
||||||
|
|
||||||
|
验证项目管理页面状态统计数字显示正确,并在用户交互(搜索、分页、状态切换)过程中保持稳定。
|
||||||
|
|
||||||
|
## 测试场景
|
||||||
|
|
||||||
|
### ✅ 场景 1: 页面初始加载
|
||||||
|
|
||||||
|
**操作步骤**:
|
||||||
|
1. 访问前端应用 http://localhost:84
|
||||||
|
2. 使用 admin/admin123 登录系统
|
||||||
|
3. 导航到"初核项目管理"页面
|
||||||
|
|
||||||
|
**预期结果**:
|
||||||
|
- 页面正常加载
|
||||||
|
- 标签页显示正确的统计数字
|
||||||
|
- 两个 API 请求成功(list 和 statusCounts)
|
||||||
|
|
||||||
|
**实际结果**: ✅ **通过**
|
||||||
|
|
||||||
|
**验证数据**:
|
||||||
|
- 标签页统计:
|
||||||
|
- 全部项目(29) ✅
|
||||||
|
- 进行中(27) ✅
|
||||||
|
- 已完成(1) ✅
|
||||||
|
- 已归档(1) ✅
|
||||||
|
- 列表显示: 共 29 条 ✅
|
||||||
|
- API 请求:
|
||||||
|
- `/ccdi/project/list?pageNum=1&pageSize=10` → 200 OK
|
||||||
|
- `/ccdi/project/statusCounts` → 200 OK
|
||||||
|
|
||||||
|
**响应数据验证**:
|
||||||
|
```json
|
||||||
|
// list 接口响应
|
||||||
|
{
|
||||||
|
"total": 29,
|
||||||
|
"rows": [ ...10条记录... ],
|
||||||
|
"code": 200,
|
||||||
|
"msg": "查询成功"
|
||||||
|
}
|
||||||
|
|
||||||
|
// statusCounts 接口响应
|
||||||
|
{
|
||||||
|
"msg": "操作成功",
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"all": 29,
|
||||||
|
"status0": 27,
|
||||||
|
"status1": 1,
|
||||||
|
"status2": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ 场景 2: 搜索功能
|
||||||
|
|
||||||
|
**操作步骤**:
|
||||||
|
1. 在搜索框输入 "测试4"
|
||||||
|
2. 按回车键触发搜索
|
||||||
|
|
||||||
|
**预期结果**:
|
||||||
|
- 列表只显示匹配的项目
|
||||||
|
- 标签页数字保持不变(显示总数)
|
||||||
|
|
||||||
|
**实际结果**: ✅ **通过**
|
||||||
|
|
||||||
|
**验证数据**:
|
||||||
|
- 搜索结果: 1 条(测试4) ✅
|
||||||
|
- 标签页统计(保持不变):
|
||||||
|
- 全部项目(29) ✅
|
||||||
|
- 进行中(27) ✅
|
||||||
|
- 已完成(1) ✅
|
||||||
|
- 已归档(1) ✅
|
||||||
|
- 分页显示: 共 1 条 ✅
|
||||||
|
|
||||||
|
**API 请求验证**:
|
||||||
|
```
|
||||||
|
GET /ccdi/project/list?pageNum=1&pageSize=10&projectName=测试4 → 200 OK
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ 场景 3: 分页功能
|
||||||
|
|
||||||
|
**操作步骤**:
|
||||||
|
1. 清空搜索框,刷新页面恢复初始状态
|
||||||
|
2. 点击分页组件的"2"按钮,切换到第 2 页
|
||||||
|
|
||||||
|
**预期结果**:
|
||||||
|
- 列表切换到第 2 页数据
|
||||||
|
- 标签页数字保持不变
|
||||||
|
|
||||||
|
**实际结果**: ✅ **通过**
|
||||||
|
|
||||||
|
**验证数据**:
|
||||||
|
- 当前页码: 第 2 页 ✅
|
||||||
|
- 标签页统计(保持不变):
|
||||||
|
- 全部项目(29) ✅
|
||||||
|
- 进行中(27) ✅
|
||||||
|
- 已完成(1) ✅
|
||||||
|
- 已归档(1) ✅
|
||||||
|
- 分页显示: 共 29 条 ✅
|
||||||
|
|
||||||
|
**API 请求验证**:
|
||||||
|
```
|
||||||
|
GET /ccdi/project/list?pageNum=2&pageSize=10 → 200 OK
|
||||||
|
GET /ccdi/project/statusCounts → 200 OK
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ 场景 4: 状态切换功能
|
||||||
|
|
||||||
|
**操作步骤**:
|
||||||
|
1. 点击"进行中"标签
|
||||||
|
|
||||||
|
**预期结果**:
|
||||||
|
- 列表只显示"进行中"状态的项目
|
||||||
|
- 标签页数字保持不变(仍显示总数)
|
||||||
|
|
||||||
|
**实际结果**: ✅ **通过**
|
||||||
|
|
||||||
|
**验证数据**:
|
||||||
|
- 列表过滤: 所有项目状态都是"进行中" ✅
|
||||||
|
- 标签页统计(保持不变):
|
||||||
|
- 全部项目(29) ✅
|
||||||
|
- 进行中(27) ✅
|
||||||
|
- 已完成(1) ✅
|
||||||
|
- 已归档(1) ✅
|
||||||
|
- 分页显示: 共 27 条(正确反映当前状态的项目数) ✅
|
||||||
|
|
||||||
|
**API 请求验证**:
|
||||||
|
```
|
||||||
|
GET /ccdi/project/list?pageNum=1&pageSize=10&status=0 → 200 OK
|
||||||
|
GET /ccdi/project/statusCounts → 200 OK
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应数据验证**:
|
||||||
|
```json
|
||||||
|
// status=0 过滤后的列表
|
||||||
|
{
|
||||||
|
"total": 27,
|
||||||
|
"rows": [
|
||||||
|
{"projectId": 31, "projectName": "测试123", "status": "0", ...},
|
||||||
|
{"projectId": 23, "projectName": "测试23", "status": "0", ...},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
"code": 200,
|
||||||
|
"msg": "查询成功"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态统计(始终返回总数)
|
||||||
|
{
|
||||||
|
"msg": "操作成功",
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"all": 29,
|
||||||
|
"status0": 27,
|
||||||
|
"status1": 1,
|
||||||
|
"status2": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ 场景 5: 浏览器控制台检查
|
||||||
|
|
||||||
|
**操作步骤**:
|
||||||
|
1. 打开浏览器开发者工具的 Console 标签
|
||||||
|
|
||||||
|
**预期结果**:
|
||||||
|
- 没有 JavaScript 错误
|
||||||
|
- 看到两个 API 请求成功
|
||||||
|
|
||||||
|
**实际结果**: ✅ **通过**
|
||||||
|
|
||||||
|
**控制台消息**:
|
||||||
|
- ✅ 没有 JavaScript 错误
|
||||||
|
- ⚠️ 1 个警告: "A form field element should have an id or name attribute" (不影响功能)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 网络请求统计
|
||||||
|
|
||||||
|
**总请求数**: 40 个
|
||||||
|
|
||||||
|
**关键 API 请求**:
|
||||||
|
1. 初始加载:
|
||||||
|
- `/ccdi/project/list?pageNum=1&pageSize=10` → 200 OK
|
||||||
|
- `/ccdi/project/statusCounts` → 200 OK
|
||||||
|
|
||||||
|
2. 搜索功能:
|
||||||
|
- `/ccdi/project/list?pageNum=1&pageSize=10&projectName=测试4` → 200 OK
|
||||||
|
|
||||||
|
3. 分页功能:
|
||||||
|
- `/ccdi/project/list?pageNum=2&pageSize=10` → 200 OK
|
||||||
|
- `/ccdi/project/statusCounts` → 200 OK
|
||||||
|
|
||||||
|
4. 状态切换:
|
||||||
|
- `/ccdi/project/list?pageNum=1&pageSize=10&status=0` → 200 OK
|
||||||
|
- `/ccdi/project/statusCounts` → 200 OK
|
||||||
|
|
||||||
|
**所有请求状态**: ✅ 全部成功(200 OK)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 核心修复验证
|
||||||
|
|
||||||
|
### 问题回顾
|
||||||
|
|
||||||
|
**原始问题**: 标签页数字随分页变化,不稳定
|
||||||
|
|
||||||
|
**根本原因**: 前端使用列表响应的 total 字段来更新标签页数字,导致搜索/分页/过滤时数字会变化
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 后端新增 `/statusCounts` 接口,始终返回所有状态的总数
|
||||||
|
2. 前端在每次加载时并行请求 list 和 statusCounts
|
||||||
|
3. 标签页数字只使用 statusCounts 的数据,不受列表过滤影响
|
||||||
|
|
||||||
|
### 修复效果验证
|
||||||
|
|
||||||
|
✅ **搜索时**: 标签页数字保持 29/27/1/1 不变
|
||||||
|
✅ **分页时**: 标签页数字保持 29/27/1/1 不变
|
||||||
|
✅ **状态切换时**: 标签页数字保持 29/27/1/1 不变
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 测试结论
|
||||||
|
|
||||||
|
### ✅ 所有测试场景通过
|
||||||
|
|
||||||
|
| 测试场景 | 状态 | 备注 |
|
||||||
|
|---------|------|------|
|
||||||
|
| 页面初始加载 | ✅ 通过 | 标签页数字正确显示 |
|
||||||
|
| 搜索功能 | ✅ 通过 | 数字保持稳定 |
|
||||||
|
| 分页功能 | ✅ 通过 | 数字保持稳定 |
|
||||||
|
| 状态切换功能 | ✅ 通过 | 数字保持稳定 |
|
||||||
|
| 浏览器控制台 | ✅ 通过 | 无 JavaScript 错误 |
|
||||||
|
|
||||||
|
### 关键指标
|
||||||
|
|
||||||
|
- ✅ **功能正确性**: 100% 通过
|
||||||
|
- ✅ **数据一致性**: 标签页数字在所有操作中保持稳定
|
||||||
|
- ✅ **用户体验**: 符合预期,数字显示直观清晰
|
||||||
|
- ✅ **性能**: API 请求并行执行,响应迅速
|
||||||
|
- ✅ **代码质量**: 无 JavaScript 错误,警告不影响功能
|
||||||
|
|
||||||
|
### 建议
|
||||||
|
|
||||||
|
1. ✅ **功能完善**: 建议将此修复方案应用到其他类似的列表页面
|
||||||
|
2. ⚠️ **警告处理**: 建议为搜索框添加 id 或 name 属性以消除控制台警告
|
||||||
|
3. ✅ **文档更新**: 更新用户手册,说明标签页数字表示总数而非当前过滤结果
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录
|
||||||
|
|
||||||
|
### 测试环境信息
|
||||||
|
|
||||||
|
```
|
||||||
|
操作系统: Windows 11 Pro 10.0.26200
|
||||||
|
浏览器: Chrome 145.0.0.0
|
||||||
|
后端服务: http://localhost:8080
|
||||||
|
前端服务: http://localhost:84
|
||||||
|
数据库: MySQL 8.2.0
|
||||||
|
Java 版本: 17
|
||||||
|
Spring Boot 版本: 3.5.8
|
||||||
|
Vue.js 版本: 2.6.12
|
||||||
|
```
|
||||||
|
|
||||||
|
### 相关文件
|
||||||
|
|
||||||
|
**后端**:
|
||||||
|
- `D:/ccdi/ccdi/ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/domain/vo/ProjectStatusCountsVO.java`
|
||||||
|
- `D:/ccdi/ccdi/ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/ICcdiProjectService.java`
|
||||||
|
- `D:/ccdi/ccdi/ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/service/impl/CcdiProjectServiceImpl.java`
|
||||||
|
- `D:/ccdi/ccdi/ruoyi-info-collection/src/main/java/com/ruoyi/info/collection/controller/CcdiProjectController.java`
|
||||||
|
|
||||||
|
**前端**:
|
||||||
|
- `D:/ccdi/ccdi/ruoyi-ui/src/api/ccdiProject.js`
|
||||||
|
- `D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiProject/index.vue`
|
||||||
|
- `D:/ccdi/ccdi/ruoyi-ui/src/views/ccdiProject/components/SearchBar.vue`
|
||||||
|
|
||||||
|
### 测试执行时间
|
||||||
|
|
||||||
|
- 开始时间: 2026-02-28 09:46:48
|
||||||
|
- 结束时间: 2026-02-28 09:50:00
|
||||||
|
- 总耗时: 约 3 分钟
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**测试人员签名**: Claude Code
|
||||||
|
**测试日期**: 2026-02-28
|
||||||
7
doc/对接流水分析/task.md
Normal file
7
doc/对接流水分析/task.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# 系统需要对接流水分析平台,调用流水分析平台的接口
|
||||||
|
- 新建一个模块ccdi_lsfx,保存所有调用流水分析平台的代码
|
||||||
|
- 创建一个用于发起http请求的工具类,使用RestTemplate
|
||||||
|
- 读取接口文档 D:\ccdi\ccdi\doc\对接流水分析\兰溪-流水分析对接.docx,分析每个接口的入参和返回值格式,封装入参和出参的对象
|
||||||
|
- 在配置文档中添加每个接口对应的url配置
|
||||||
|
- 在后端服务层中实现这些接口的调用,获取返回值
|
||||||
|
- 创建一个控制层,可以调用这些接口,用于测试
|
||||||
BIN
doc/对接流水分析/兰溪-流水分析对接.docx
Normal file
BIN
doc/对接流水分析/兰溪-流水分析对接.docx
Normal file
Binary file not shown.
561
doc/对接流水分析/兰溪-流水分析对接.md
Normal file
561
doc/对接流水分析/兰溪-流水分析对接.md
Normal file
@@ -0,0 +1,561 @@
|
|||||||
|
# 兰溪-流水分析对接文档
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
本文档描述与**见知现金流尽调系统**的对接接口,用于拉取银行流水数据。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 新建项目并获取Token
|
||||||
|
|
||||||
|
### 1.1 接口请求地址
|
||||||
|
|
||||||
|
- **测试环境**: `http://158.234.196.5:82/c4c3/account/common/getToken`
|
||||||
|
- **请求方法**: POST
|
||||||
|
|
||||||
|
### 1.2 请求参数说明
|
||||||
|
|
||||||
|
> 接口备注:第三方系统中,点击需要查看的项目向见知现金流尽调系统请求访问token,每个项目的token不同。现金流尽调系统根据 ProjectNo为唯一标识查找项目,如果对应的项目不存在则自动创建项目。注意token使用一次后即失效,再次访问项目需要重新申请。(支持拉取金综和行内流水)
|
||||||
|
|
||||||
|
| 参数名 | 示例值 | 参数类型 | 是否必填 | 参数描述 |
|
||||||
|
|--------|--------|----------|----------|----------|
|
||||||
|
| projectNo | test-zjnx-1204 | String | 是 | 项目编号 |
|
||||||
|
| entityName | 浙江农信test1204 | String | 是 | 项目名称 |
|
||||||
|
| userId | test001 | String | 是 | 操作人员编号 |
|
||||||
|
| userName | 测试001 | String | 是 | 操作人员姓名 |
|
||||||
|
| appId | remote_app | String | 是 | 见知提供appId |
|
||||||
|
| appSecretCode | 6ee87a361f29234ad25d7893da9975a9 | String | 是 | 安全码 md5(projectNo + "_" + entityName + "_" + appSecret) |
|
||||||
|
| role | VIEWER | String | 否 | 人员角色(VIEWER:普通用户,READER:只读用户)默认值:VIEWER |
|
||||||
|
| orgCode | 800000 | String | 是 | 行社机构号 |
|
||||||
|
| entityId | ZJNX1234567890 | String | 否 | 企业统信码或个人身份证号 |
|
||||||
|
| xdRelatedPersons | [{"relatedPerson":"上海上水纯净水有限公司","relation":"董事长"}] | String | 否 | 信贷关联人信息 |
|
||||||
|
| jzDataDateId | 0 | String | 否 | 拉取指定日期推送过来的金综链流水,为0时标识不需要拉取金综链流水 |
|
||||||
|
| innerBSStartDateId | 0 | String | 否 | 拉取行内流水开始日期,0:不需要拉取行内流水。流水分析系统根据entityId到数仓中查询行内流水 |
|
||||||
|
| innerBSEndDateId | 0 | String | 否 | 拉取行内流水结束日期,0:不需要拉取行内流水。流水分析系统根据entityId到数仓中查询行内流水 |
|
||||||
|
| analysisType | -1 | String | 是 | 固定值 |
|
||||||
|
| departmentCode | 800111 | String | 是 | 客户经理所属营业部/分理处的机构编码 |
|
||||||
|
|
||||||
|
### 1.3 返回参数说明
|
||||||
|
|
||||||
|
#### 成功响应 (200)
|
||||||
|
|
||||||
|
| 参数名 | 示例值 | 参数类型 | 参数描述 |
|
||||||
|
|--------|--------|----------|----------|
|
||||||
|
| code | 200 | String | 返回码 |
|
||||||
|
| data.token | eyJ0eXAi... | String | token |
|
||||||
|
| data.projectId | 77 | Integer | 见知项目Id |
|
||||||
|
| data.projectNo | test-zjnx-1204 | String | 项目编号 |
|
||||||
|
| data.entityName | 浙江农信test1204 | String | 项目名称 |
|
||||||
|
| data.analysisType | 0 | Integer | 分析类型 |
|
||||||
|
| message | create.token.success | String | 消息 |
|
||||||
|
| status | 200 | String | 状态 |
|
||||||
|
| successResponse | true | Boolean | 成功标识 |
|
||||||
|
|
||||||
|
#### 错误码说明
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| 200 | 请求成功 |
|
||||||
|
| 40100 | 未知异常 |
|
||||||
|
| 40101 | appId错误 |
|
||||||
|
| 40102 | appSecretCode错误 |
|
||||||
|
| 40104 | 可使用项目次数为0,无法创建项目 |
|
||||||
|
| 40105 | 只读模式下无法新建项目 |
|
||||||
|
| 40106 | 错误的分析类型,不在规定的取值范围内 |
|
||||||
|
| 40107 | 当前系统不支持的分析类型 |
|
||||||
|
| 40108 | 当前用户所属行社无权限 |
|
||||||
|
|
||||||
|
### 1.4 返回示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"data": {
|
||||||
|
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
|
||||||
|
"projectId": 77,
|
||||||
|
"projectNo": "test-zjnx-1204",
|
||||||
|
"entityName": "浙江农信test1204",
|
||||||
|
"analysisType": 0
|
||||||
|
},
|
||||||
|
"message": "create.token.success",
|
||||||
|
"status": "200",
|
||||||
|
"successResponse": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 上传文件接口
|
||||||
|
|
||||||
|
### 2.1 接口请求地址
|
||||||
|
|
||||||
|
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/remoteUploadSplitFile`
|
||||||
|
- **请求方法**: POST
|
||||||
|
- **请求头**: `X-Xencio-Client-Id: c2017e8d105c435a96f86373635b6a09`
|
||||||
|
|
||||||
|
### 2.2 请求参数说明
|
||||||
|
|
||||||
|
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|
||||||
|
|------|------|----------|----------|------|
|
||||||
|
| groupId | Int | 项目id | 是 | - |
|
||||||
|
| files | File | 上传的文件 | 是 | - |
|
||||||
|
|
||||||
|
### 2.3 响应结果信息
|
||||||
|
|
||||||
|
| 字段 | 类型 | 备注 |
|
||||||
|
|------|------|------|
|
||||||
|
| code | String | 200成功,其他状态码失败 |
|
||||||
|
| data | Object | 列表 |
|
||||||
|
| accountName | - | 主体名称 |
|
||||||
|
| accountNo | - | 账号 |
|
||||||
|
| uploadFileName | - | 文件名称 |
|
||||||
|
| fileSize | - | 文件大小,单位Byte |
|
||||||
|
| status | - | 状态值 |
|
||||||
|
| uploadStatusDesc | - | 文件状态描述 |
|
||||||
|
| bank | - | 所属银行 |
|
||||||
|
| currency | - | 币种 |
|
||||||
|
| accountId | - | 账号id |
|
||||||
|
| logId | - | 文件id |
|
||||||
|
|
||||||
|
> **注意**: `status`等于-5且`uploadStatusDesc`等于`data.wait.confirm.newaccount`表示当前流水文件上传后解析成功。反之则没有成功。
|
||||||
|
|
||||||
|
### 2.4 返回示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"data": {
|
||||||
|
"accountsOfLog": {
|
||||||
|
"13976": [
|
||||||
|
{
|
||||||
|
"bank": "BSX",
|
||||||
|
"accountName": "",
|
||||||
|
"accountNo": "虞海良绍兴银行流水",
|
||||||
|
"currency": "CNY"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"uploadLogList": [
|
||||||
|
{
|
||||||
|
"accountNoList": [],
|
||||||
|
"bankName": "BSX",
|
||||||
|
"dataTypeInfo": ["CSV", ","],
|
||||||
|
"downloadFileName": "虞海良绍兴银行流水.csv",
|
||||||
|
"enterpriseNameList": [],
|
||||||
|
"filePackageId": "14b13103010e4d32b5406c764cfe3644",
|
||||||
|
"fileSize": 46724,
|
||||||
|
"fileUploadBy": 448,
|
||||||
|
"fileUploadByUserName": "admin@support.com",
|
||||||
|
"fileUploadTime": "2025-03-12 18:53:29",
|
||||||
|
"leId": 10724,
|
||||||
|
"logId": 13976,
|
||||||
|
"logMeta": "{\"lostHeader\":[],\"balanceAmount\":true}",
|
||||||
|
"logType": "bankstatement",
|
||||||
|
"loginLeId": 10724,
|
||||||
|
"realBankName": "BSX",
|
||||||
|
"rows": 0,
|
||||||
|
"source": "http",
|
||||||
|
"status": -5,
|
||||||
|
"templateName": "BSX_T240925",
|
||||||
|
"totalRecords": 280,
|
||||||
|
"trxDateEndId": 20240905,
|
||||||
|
"trxDateStartId": 20230914,
|
||||||
|
"uploadFileName": "虞海良绍兴银行流水.csv",
|
||||||
|
"uploadStatusDesc": "data.wait.confirm.newaccount"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uploadStatus": 1
|
||||||
|
},
|
||||||
|
"status": "200",
|
||||||
|
"successResponse": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 拉取行内流水接口
|
||||||
|
|
||||||
|
### 3.1 接口请求地址
|
||||||
|
|
||||||
|
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/getJZFileOrZjrcuFile`
|
||||||
|
- **请求方法**: POST
|
||||||
|
- **请求头**: `X-Xencio-Client-Id: c2017e8d105c435a96f86373635b6a09`
|
||||||
|
|
||||||
|
### 3.2 请求参数说明
|
||||||
|
|
||||||
|
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|
||||||
|
|------|------|----------|----------|------|
|
||||||
|
| groupId | Int | 项目id | 是 | - |
|
||||||
|
| customerNo | String | 客户身份证号 | 是 | - |
|
||||||
|
| dataChannelCode | String | 校验码 | 是 | 固定值: ZJRCU |
|
||||||
|
| requestDateId | Int | 发起请求的时间 | 是 | 当天请求时间 |
|
||||||
|
| dataStartDateId | Int | 拉取开始日期 | 是 | - |
|
||||||
|
| dataEndDateId | Int | 拉取结束日期 | 是 | - |
|
||||||
|
| uploadUserId | int | 柜员号 | 是 | - |
|
||||||
|
|
||||||
|
### 3.3 响应结果信息
|
||||||
|
|
||||||
|
| 序号 | 字段 | 类型 | 备注 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 1 | code | String | 200成功,其他状态码失败 |
|
||||||
|
| 2 | data | Object | 列表 |
|
||||||
|
|
||||||
|
### 3.4 返回示例(无行内流水)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"data": {
|
||||||
|
"code": "501014",
|
||||||
|
"message": "无行内流水文件"
|
||||||
|
},
|
||||||
|
"status": "200",
|
||||||
|
"successResponse": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 判断文件是否解析结束
|
||||||
|
|
||||||
|
### 4.1 接口请求地址
|
||||||
|
|
||||||
|
- **测试环境**: `http://158.234.196.5:82/c4c3/watson/api/project/upload/getpendings`
|
||||||
|
- **请求方法**: POST
|
||||||
|
- **请求头**: `X-Xencio-Client-Id: c2017e8d105c435a96f86373635b6a09`
|
||||||
|
|
||||||
|
### 4.2 请求参数说明
|
||||||
|
|
||||||
|
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|
||||||
|
|------|------|----------|----------|------|
|
||||||
|
| groupId | Int | 项目id | 是 | - |
|
||||||
|
| inprogressList | String | 文件id | 是 | - |
|
||||||
|
|
||||||
|
### 4.3 响应结果信息
|
||||||
|
|
||||||
|
| 序号 | 字段 | 类型 | 备注 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 1 | code | String | 200成功,其他状态码失败 |
|
||||||
|
| 2 | data | Object | 列表 |
|
||||||
|
| 3 | uploadFileName | - | 上传文件名称 |
|
||||||
|
| 4 | status | - | 文件解析后状态值 |
|
||||||
|
| 5 | uploadStatusDesc | - | 文件解析后状态描述 |
|
||||||
|
| 6 | parsing | - | 文件解析状态,true表示解析中,false表示解析结束 |
|
||||||
|
|
||||||
|
> **注意**: 文件解析有个处理过程,`parsing`为false表示解析结束,可以轮询调用此接口,`status`等于-5且`uploadStatusDesc`等于`data.wait.confirm.newaccount`表示文件解析成功。
|
||||||
|
|
||||||
|
### 4.4 返回示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"data": {
|
||||||
|
"parsing": false,
|
||||||
|
"pendingList": [
|
||||||
|
{
|
||||||
|
"accountNoList": [],
|
||||||
|
"bankName": "ZJRCU",
|
||||||
|
"dataTypeInfo": ["CSV", ","],
|
||||||
|
"downloadFileName": "230902199012261247_20260201_20260201_1772096608615.csv",
|
||||||
|
"enterpriseNameList": [],
|
||||||
|
"filePackageId": "cde6c7cf5cab48e8892f0c1c36b2aa7d",
|
||||||
|
"fileSize": 53101,
|
||||||
|
"fileUploadBy": 448,
|
||||||
|
"fileUploadByUserName": "admin@support.com",
|
||||||
|
"fileUploadTime": "2026-02-27 09:50:18",
|
||||||
|
"isSplit": 0,
|
||||||
|
"leId": 16210,
|
||||||
|
"logId": 19116,
|
||||||
|
"logMeta": "{\"lostHeader\":[],\"balanceAmount\":true}",
|
||||||
|
"logType": "bankstatement",
|
||||||
|
"loginLeId": 16210,
|
||||||
|
"lostHeader": [],
|
||||||
|
"realBankName": "ZJRCU",
|
||||||
|
"rows": 0,
|
||||||
|
"source": "http",
|
||||||
|
"status": -5,
|
||||||
|
"templateName": "ZJRCU_T251114",
|
||||||
|
"totalRecords": 131,
|
||||||
|
"trxDateEndId": 20240228,
|
||||||
|
"trxDateStartId": 20240201,
|
||||||
|
"uploadFileName": "230902199012261247_20260201_20260201_1772096608615.csv",
|
||||||
|
"uploadStatusDesc": "data.wait.confirm.newaccount"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"status": "200",
|
||||||
|
"successResponse": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 生成尽调报告接口
|
||||||
|
|
||||||
|
### 5.1 接口请求地址
|
||||||
|
|
||||||
|
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/confirmStageUploadLogs`
|
||||||
|
- **请求方法**: POST
|
||||||
|
- **请求头**: `X-Xencio-Client-Id: c2017e8d105c435a96f86373635b6a09`
|
||||||
|
|
||||||
|
### 5.2 请求参数说明
|
||||||
|
|
||||||
|
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|
||||||
|
|------|------|----------|----------|------|
|
||||||
|
| groupId | Int | 项目id | 是 | - |
|
||||||
|
| logIds | Array | 文件id数组 | 是 | 上传几个文件就用几个 |
|
||||||
|
| userLogin | Int | 登录柜员号 | 是 | - |
|
||||||
|
|
||||||
|
### 5.3 响应结果信息
|
||||||
|
|
||||||
|
| 序号 | 字段 | 类型 | 备注 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 1 | Code | String | 200成功,其他状态码失败 |
|
||||||
|
| 2 | Data | Object | 列表 |
|
||||||
|
|
||||||
|
### 5.4 返回示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"data": {
|
||||||
|
"message": "upload.confirm.ok"
|
||||||
|
},
|
||||||
|
"status": "200",
|
||||||
|
"successResponse": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 判断尽调报告是否生成
|
||||||
|
|
||||||
|
### 6.1 接口请求地址
|
||||||
|
|
||||||
|
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/upload/getallpendings?groupId=#{groupId}`
|
||||||
|
- **请求方法**: GET
|
||||||
|
- **请求头**: `X-Xencio-Client-Id: c2017e8d105c435a96f86373635b6a09`
|
||||||
|
|
||||||
|
### 6.2 请求参数说明
|
||||||
|
|
||||||
|
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|
||||||
|
|------|------|----------|----------|------|
|
||||||
|
| groupId | Int | 项目id | 是 | - |
|
||||||
|
|
||||||
|
### 6.3 响应结果信息
|
||||||
|
|
||||||
|
| 序号 | 字段 | 类型 | 备注 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 1 | code | String | 200成功,其他状态码失败 |
|
||||||
|
| 2 | data | Object | 列表 |
|
||||||
|
|
||||||
|
> **注意**: 生成尽调报告有个处理过程,`pendingList`为[]表示处理结束,可以轮询调用此接口。
|
||||||
|
|
||||||
|
### 6.4 返回示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"data": {
|
||||||
|
"pendingList": []
|
||||||
|
},
|
||||||
|
"status": "200",
|
||||||
|
"successResponse": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 获取流水列表并存储到兰溪本地
|
||||||
|
|
||||||
|
### 7.1 接口请求地址
|
||||||
|
|
||||||
|
- **测试环境**: `158.234.196.5:82/c4c3/watson/api/project/upload/getBankStatement`
|
||||||
|
- **请求方法**: POST
|
||||||
|
- **请求头**: `X-Xencio-Client-Id: c2017e8d105c435a96f86373635b6a09`
|
||||||
|
|
||||||
|
### 7.2 请求参数说明
|
||||||
|
|
||||||
|
| 参数 | 类型 | 参数名称 | 是否必填 | 说明 |
|
||||||
|
|------|------|----------|----------|------|
|
||||||
|
| groupId | Int | 项目id | 是 | - |
|
||||||
|
| logId | Int | 文件id | 是 | - |
|
||||||
|
| pageNow | Int | 当前页码 | 是 | - |
|
||||||
|
| pageSize | Int | 查询条数 | 是 | - |
|
||||||
|
|
||||||
|
### 7.3 响应结果信息
|
||||||
|
|
||||||
|
| 序号 | 字段 | 类型 | 备注 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 1 | code | String | 200成功,其他状态码失败 |
|
||||||
|
| 2 | data | Object | 列表 |
|
||||||
|
| 3 | bankStatementList | - | 流水列表 |
|
||||||
|
| 4 | pageable | - | 分页参数 |
|
||||||
|
| 5 | searchable | - | 查询参数 |
|
||||||
|
|
||||||
|
### 7.4 流水字段说明
|
||||||
|
|
||||||
|
| 字段名 | 说明 | 示例值 |
|
||||||
|
|--------|------|--------|
|
||||||
|
| accountId | 账户ID | 0 |
|
||||||
|
| accountMaskNo | 账号 | 6228580199062321798 |
|
||||||
|
| accountingDate | 记账日期 | 2025-02-03 |
|
||||||
|
| accountingDateId | 记账日期ID | 20250203 |
|
||||||
|
| balanceAmount | 余额 | 85688.37 |
|
||||||
|
| bank | 银行代码 | AI |
|
||||||
|
| bankComments | 银行备注 | - |
|
||||||
|
| bankStatementId | 流水ID | 4585279 |
|
||||||
|
| catalogName | 交易名称 | 收单收入 |
|
||||||
|
| crAmount | 贷方金额 | 290 |
|
||||||
|
| currency | 币种 | CNY |
|
||||||
|
| customerAccountMaskNo | 客户账号 | 80100001471621000100 |
|
||||||
|
| customerAccountName | 客户账户名 | 系统内清算资金往来-全渠道收单平台 |
|
||||||
|
| customerName | 客户名称 | 系统内清算资金往来-全渠道收单平台 |
|
||||||
|
| drAmount | 借方金额 | 0 |
|
||||||
|
| leName | 企业名称 | 徐设华 |
|
||||||
|
| transAmount | 交易金额 | 290 |
|
||||||
|
| transFlag | 交易标志 | R |
|
||||||
|
| transTypeName | 交易名称 | 收单收入 |
|
||||||
|
| trxDate | 交易日期 | 2025-02-03 00:00:00 |
|
||||||
|
| userMemo | 用户备注 | 收单 |
|
||||||
|
|
||||||
|
### 7.5 返回示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": "200",
|
||||||
|
"data": {
|
||||||
|
"bankStatementList": [
|
||||||
|
{
|
||||||
|
"accountId": 0,
|
||||||
|
"accountMaskNo": "6228580199062321798",
|
||||||
|
"accountingDate": "2025-02-03",
|
||||||
|
"accountingDateId": 20250203,
|
||||||
|
"archivingFlag": 0,
|
||||||
|
"attachments": 0,
|
||||||
|
"balanceAmount": 85688.37,
|
||||||
|
"bank": "AI",
|
||||||
|
"bankComments": "",
|
||||||
|
"bankStatementId": 4585279,
|
||||||
|
"bankTrxNumber": "",
|
||||||
|
"cashType": "",
|
||||||
|
"catalogName": "收单收入",
|
||||||
|
"commentsNum": 0,
|
||||||
|
"crAmount": 290,
|
||||||
|
"currency": "CNY",
|
||||||
|
"customNoteCount": 0,
|
||||||
|
"customerAccountMaskNo": "80100001471621000100",
|
||||||
|
"customerAccountName": "系统内清算资金往来-全渠道收单平台",
|
||||||
|
"customerId": 0,
|
||||||
|
"customerName": "系统内清算资金往来-全渠道收单平台",
|
||||||
|
"customerReference": "",
|
||||||
|
"downPaymentFlag": 0,
|
||||||
|
"drAmount": 0,
|
||||||
|
"hasCustomNote": 0,
|
||||||
|
"internalFlag": 0,
|
||||||
|
"isMarked": 0,
|
||||||
|
"leId": 16260,
|
||||||
|
"leName": "徐设华",
|
||||||
|
"sourceCatalogId": 405625,
|
||||||
|
"split": 0,
|
||||||
|
"subBankstatementId": 0,
|
||||||
|
"toDoFlag": 0,
|
||||||
|
"transAmount": 290,
|
||||||
|
"transFlag": "R",
|
||||||
|
"transTypeId": 405625,
|
||||||
|
"transTypeName": "收单收入",
|
||||||
|
"transformAmount": 290,
|
||||||
|
"transformCrAmount": 290,
|
||||||
|
"transformDrAmount": 0,
|
||||||
|
"transfromBalanceAmount": 85688.37,
|
||||||
|
"trxBalance": 0,
|
||||||
|
"trxDate": "2025-02-03 00:00:00",
|
||||||
|
"trxFlag": "R",
|
||||||
|
"userMemo": "收单"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pageable": {
|
||||||
|
"hasNext": true,
|
||||||
|
"hasPre": false,
|
||||||
|
"isFirst": true,
|
||||||
|
"isLast": false,
|
||||||
|
"pageNow": 1,
|
||||||
|
"pageSize": 1,
|
||||||
|
"startPos": 0,
|
||||||
|
"totalCount": 3392,
|
||||||
|
"totalPageCount": 3392
|
||||||
|
},
|
||||||
|
"searchable": {
|
||||||
|
"appInput": 0,
|
||||||
|
"dayFromId": 0,
|
||||||
|
"dayToId": 0,
|
||||||
|
"endDateId": 0,
|
||||||
|
"enterpriseId": 0,
|
||||||
|
"groupTypeId": 0,
|
||||||
|
"logId": 19060,
|
||||||
|
"pageNow": 1,
|
||||||
|
"pageSize": 1,
|
||||||
|
"showDownPayment": 0,
|
||||||
|
"startDateId": 0,
|
||||||
|
"trxAmount": 0,
|
||||||
|
"trxTypeId": 0,
|
||||||
|
"uploadFromDateId": 0,
|
||||||
|
"uploadToDateId": 0,
|
||||||
|
"useForBsSearch": 0,
|
||||||
|
"useNameExactMatching": 0,
|
||||||
|
"withOrderBy": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "200",
|
||||||
|
"successResponse": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 接口调用流程
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ 1. 初始化调用 /account/common/getToken 接口创建项目 │
|
||||||
|
│ ↓ │
|
||||||
|
│ 2. 调用 /remoteUploadSplitFile 接口上传文件 │
|
||||||
|
│ 或调用 /getJZFileOrZjrcuFile 拉取行内流水 │
|
||||||
|
│ ↓ │
|
||||||
|
│ 3. 调用 /getpendings 获取文件解析状态 │
|
||||||
|
│ - parsing=true 时,间隔1s轮询 │
|
||||||
|
│ - parsing=false 且 status=-5 表示解析成功 │
|
||||||
|
│ ↓ │
|
||||||
|
│ 4. 调用 /confirmStageUploadLogs 接口生成尽调报告 │
|
||||||
|
│ ↓ │
|
||||||
|
│ 5. 调用 /getallpending 检查尽调报告生成状态 │
|
||||||
|
│ - pendingList 不为空时,间隔1s轮询 │
|
||||||
|
│ - pendingList=[] 表示生成完成 │
|
||||||
|
│ ↓ │
|
||||||
|
│ 6. 调用 /getBankStatement 接口获取流水数据存储到兰溪本地 │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 生产环境配置
|
||||||
|
|
||||||
|
| 配置项 | 值 |
|
||||||
|
|--------|-----|
|
||||||
|
| 生产IP | 64.202.32.176 |
|
||||||
|
| 生产X-Xencio-Client-Id | 通过接口获取 |
|
||||||
|
|
||||||
|
### 获取生产环境 Client-Id
|
||||||
|
|
||||||
|
```
|
||||||
|
GET http://64.202.32.176/c4c3/watson/api/common/GenerateAccessKey?userLogin={流水分析平台登录柜员号}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录:公共请求头
|
||||||
|
|
||||||
|
| 请求头 | 值 | 说明 |
|
||||||
|
|--------|-----|------|
|
||||||
|
| X-Xencio-Client-Id | c2017e8d105c435a96f86373635b6a09 | 测试环境固定值 |
|
||||||
|
| Content-Type | application/json | POST请求 |
|
||||||
282
docs/plans/2026-02-28-database-migration-design.md
Normal file
282
docs/plans/2026-02-28-database-migration-design.md
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
# 数据库迁移设计文档
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
将 CCDI 纪检初核系统的开发环境数据库完整迁移到生产环境,包括所有表结构和数据的导出与导入。
|
||||||
|
|
||||||
|
## 需求分析
|
||||||
|
|
||||||
|
### 迁移目标
|
||||||
|
- **源数据库**: 116.62.17.81:3306/ccdi
|
||||||
|
- **目标环境**: 全新的生产数据库(空库)
|
||||||
|
- **迁移范围**: 所有表的结构和数据
|
||||||
|
|
||||||
|
### 关键要求
|
||||||
|
1. 表结构和数据分离导出(两个独立文件)
|
||||||
|
2. 只导出表,不包括视图、存储过程、触发器等
|
||||||
|
3. 完整导出所有数据,不需要脱敏
|
||||||
|
4. 确保字符集正确,避免乱码问题
|
||||||
|
5. 使用 mysqldump 命令导出
|
||||||
|
6. 提供自动化脚本简化操作
|
||||||
|
|
||||||
|
## 技术方案
|
||||||
|
|
||||||
|
### 导出工具
|
||||||
|
使用 MySQL 官方工具 `mysqldump` 进行导出,优势:
|
||||||
|
- 标准化工具,兼容性最佳
|
||||||
|
- 性能优秀,适合大数据库
|
||||||
|
- 生成的 SQL 文件通用性强
|
||||||
|
|
||||||
|
### 字符集处理
|
||||||
|
- **字符集**: utf8mb4(支持完整 Unicode,包括 emoji)
|
||||||
|
- **排序规则**: utf8mb4_general_ci
|
||||||
|
- **客户端字符集**: utf8mb4
|
||||||
|
|
||||||
|
关键措施:
|
||||||
|
1. mysqldump 命令添加 `--default-character-set=utf8mb4` 参数
|
||||||
|
2. SQL 文件头部添加字符集声明语句
|
||||||
|
3. 导入时指定字符集参数
|
||||||
|
4. 导入后验证中文数据正确性
|
||||||
|
|
||||||
|
## 导出设计
|
||||||
|
|
||||||
|
### 文件组织
|
||||||
|
```
|
||||||
|
ccdi/
|
||||||
|
├── export_database.sh # 自动化脚本
|
||||||
|
├── db_config.conf.template # 配置模板
|
||||||
|
├── db_config.conf # 实际配置(不纳入版本控制)
|
||||||
|
└── doc/
|
||||||
|
└── database/
|
||||||
|
└── backup/
|
||||||
|
├── ccdi_structure.sql # 表结构文件
|
||||||
|
├── ccdi_data.sql # 数据文件
|
||||||
|
└── export_guide.md # 操作指南
|
||||||
|
```
|
||||||
|
|
||||||
|
### 表结构导出命令
|
||||||
|
```bash
|
||||||
|
mysqldump -h 116.62.17.81 -P 3306 -u root -p \
|
||||||
|
--no-data \
|
||||||
|
--skip-triggers \
|
||||||
|
--skip-add-drop-table \
|
||||||
|
--default-character-set=utf8mb4 \
|
||||||
|
--single-transaction \
|
||||||
|
ccdi > ccdi_structure.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数说明**:
|
||||||
|
- `--no-data`: 只导出表结构,不导出数据
|
||||||
|
- `--skip-triggers`: 跳过触发器
|
||||||
|
- `--skip-add-drop-table`: 不添加 DROP TABLE 语句(避免误删)
|
||||||
|
- `--default-character-set=utf8mb4`: 指定字符集
|
||||||
|
- `--single-transaction`: InnoDB 表一致性导出,不锁表
|
||||||
|
|
||||||
|
### 数据导出命令
|
||||||
|
```bash
|
||||||
|
mysqldump -h 116.62.17.81 -P 3306 -u root -p \
|
||||||
|
--no-create-info \
|
||||||
|
--skip-triggers \
|
||||||
|
--default-character-set=utf8mb4 \
|
||||||
|
--single-transaction \
|
||||||
|
--complete-insert \
|
||||||
|
--extended-insert \
|
||||||
|
ccdi > ccdi_data.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数说明**:
|
||||||
|
- `--no-create-info`: 只导出数据,不导出表结构
|
||||||
|
- `--complete-insert`: INSERT 语句包含列名
|
||||||
|
- `--extended-insert`: 使用多行 INSERT,提高导入效率
|
||||||
|
|
||||||
|
### SQL 文件字符集声明
|
||||||
|
```sql
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
SET CHARACTER SET utf8mb4;
|
||||||
|
SET GLOBAL character_set_client=utf8mb4;
|
||||||
|
SET GLOBAL character_set_connection=utf8mb4;
|
||||||
|
SET GLOBAL character_set_results=utf8mb4;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 导入设计
|
||||||
|
|
||||||
|
### 导入顺序
|
||||||
|
1. 先导入表结构:`ccdi_structure.sql`
|
||||||
|
2. 再导入数据:`ccdi_data.sql`
|
||||||
|
|
||||||
|
### 导入命令
|
||||||
|
```bash
|
||||||
|
# 导入表结构
|
||||||
|
mysql -h 生产环境IP -P 3306 -u 用户名 -p \
|
||||||
|
--default-character-set=utf8mb4 \
|
||||||
|
数据库名 < ccdi_structure.sql
|
||||||
|
|
||||||
|
# 导入数据
|
||||||
|
mysql -h 生产环境IP -P 3306 -u 用户名 -p \
|
||||||
|
--default-character-set=utf8mb4 \
|
||||||
|
数据库名 < ccdi_data.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 前置条件
|
||||||
|
1. 目标数据库已创建(如:`CREATE DATABASE ccdi CHARACTER SET utf8mb4;`)
|
||||||
|
2. 目标用户有足够权限
|
||||||
|
3. 磁盘空间充足
|
||||||
|
|
||||||
|
## 自动化脚本设计
|
||||||
|
|
||||||
|
### 脚本功能
|
||||||
|
- **导出模式**: `./export_database.sh export`
|
||||||
|
- 检查 mysqldump 命令可用性
|
||||||
|
- 创建备份目录
|
||||||
|
- 执行结构导出和数据导出
|
||||||
|
- 添加字符集声明到文件头部
|
||||||
|
- 验证文件生成
|
||||||
|
- 记录操作日志
|
||||||
|
|
||||||
|
- **导入模式**: `./export_database.sh import [production|test]`
|
||||||
|
- 读取配置文件获取目标环境信息
|
||||||
|
- 检查目标数据库连接
|
||||||
|
- 依次导入结构和数据文件
|
||||||
|
- 验证导入结果
|
||||||
|
- 记录操作日志
|
||||||
|
|
||||||
|
### 配置文件设计
|
||||||
|
```bash
|
||||||
|
# 源数据库配置(开发环境)
|
||||||
|
SOURCE_DB_HOST=116.62.17.81
|
||||||
|
SOURCE_DB_PORT=3306
|
||||||
|
SOURCE_DB_USER=root
|
||||||
|
SOURCE_DB_PASS=Kfcx@1234
|
||||||
|
SOURCE_DB_NAME=ccdi
|
||||||
|
|
||||||
|
# 生产环境数据库配置
|
||||||
|
PROD_DB_HOST=生产环境IP
|
||||||
|
PROD_DB_PORT=3306
|
||||||
|
PROD_DB_USER=生产环境用户名
|
||||||
|
PROD_DB_PASS=生产环境密码
|
||||||
|
PROD_DB_NAME=ccdi
|
||||||
|
|
||||||
|
# 测试环境数据库配置(可选)
|
||||||
|
TEST_DB_HOST=测试环境IP
|
||||||
|
TEST_DB_PORT=3306
|
||||||
|
TEST_DB_USER=测试环境用户名
|
||||||
|
TEST_DB_PASS=测试环境密码
|
||||||
|
TEST_DB_NAME=ccdi
|
||||||
|
|
||||||
|
# 导出文件配置
|
||||||
|
BACKUP_DIR=doc/database/backup
|
||||||
|
STRUCTURE_FILE=ccdi_structure.sql
|
||||||
|
DATA_FILE=ccdi_data.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### 安全措施
|
||||||
|
1. `db_config.conf` 添加到 `.gitignore`
|
||||||
|
2. 提供 `db_config.conf.template` 模板文件
|
||||||
|
3. 首次运行时检测配置文件,提示用户填写
|
||||||
|
|
||||||
|
## 验证测试
|
||||||
|
|
||||||
|
### 导出验证
|
||||||
|
1. 检查生成的 SQL 文件大小是否合理
|
||||||
|
2. 检查文件头部是否包含字符集声明
|
||||||
|
3. 随机抽取数据检查是否有乱码
|
||||||
|
4. 统计表数量和数据行数
|
||||||
|
|
||||||
|
### 导入验证
|
||||||
|
1. 在测试环境先进行导入测试
|
||||||
|
2. 对比源数据库和目标数据库的表数量
|
||||||
|
3. 抽查关键表的数据行数
|
||||||
|
4. 查询包含中文的数据验证编码正确性
|
||||||
|
5. 使用 `SHOW CREATE TABLE` 检查表字符集
|
||||||
|
|
||||||
|
### 验证命令
|
||||||
|
```sql
|
||||||
|
-- 查看数据库字符集
|
||||||
|
SHOW CREATE DATABASE ccdi;
|
||||||
|
|
||||||
|
-- 查看表数量
|
||||||
|
SELECT COUNT(*) FROM information_schema.tables
|
||||||
|
WHERE table_schema='ccdi';
|
||||||
|
|
||||||
|
-- 查看各表行数
|
||||||
|
SELECT table_name, table_rows
|
||||||
|
FROM information_schema.tables
|
||||||
|
WHERE table_schema='ccdi'
|
||||||
|
ORDER BY table_rows DESC;
|
||||||
|
|
||||||
|
-- 检查表字符集
|
||||||
|
SHOW CREATE TABLE sys_user;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 错误处理
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
1. **字符集乱码**
|
||||||
|
- 原因:未指定字符集参数
|
||||||
|
- 解决:确保所有命令都添加 `--default-character-set=utf8mb4`
|
||||||
|
|
||||||
|
2. **导入失败**
|
||||||
|
- 原因:外键约束冲突
|
||||||
|
- 解决:导入前临时禁用外键检查 `SET FOREIGN_KEY_CHECKS=0;`
|
||||||
|
|
||||||
|
3. **连接超时**
|
||||||
|
- 原因:数据库过大或网络慢
|
||||||
|
- 解决:添加 `--max_allowed_packet=512M` 参数
|
||||||
|
|
||||||
|
4. **权限不足**
|
||||||
|
- 原因:用户权限不够
|
||||||
|
- 解决:使用 root 用户或授予足够权限
|
||||||
|
|
||||||
|
## 操作流程
|
||||||
|
|
||||||
|
### 完整迁移流程
|
||||||
|
1. 配置 `db_config.conf` 文件
|
||||||
|
2. 执行导出:`./export_database.sh export`
|
||||||
|
3. 验证导出文件正确性
|
||||||
|
4. 在测试环境验证导入:`./export_database.sh import test`
|
||||||
|
5. 验证测试环境数据完整性
|
||||||
|
6. 在生产环境执行导入:`./export_database.sh import production`
|
||||||
|
7. 验证生产环境数据完整性
|
||||||
|
8. 应用程序连接测试
|
||||||
|
|
||||||
|
### 回滚方案
|
||||||
|
保留源数据库,如迁移失败可继续使用源数据库,重新执行迁移流程。
|
||||||
|
|
||||||
|
## 交付物
|
||||||
|
|
||||||
|
1. **自动化脚本**: `export_database.sh`
|
||||||
|
2. **配置模板**: `db_config.conf.template`
|
||||||
|
3. **表结构文件**: `doc/database/backup/ccdi_structure.sql`
|
||||||
|
4. **数据文件**: `doc/database/backup/ccdi_data.sql`
|
||||||
|
5. **操作指南**: `doc/database/backup/export_guide.md`
|
||||||
|
6. **设计文档**: `docs/plans/2026-02-28-database-migration-design.md`
|
||||||
|
|
||||||
|
## 时间估算
|
||||||
|
|
||||||
|
- 脚本开发:30分钟
|
||||||
|
- 导出执行:10-30分钟(取决于数据量)
|
||||||
|
- 测试环境导入验证:10-30分钟
|
||||||
|
- 生产环境导入:10-30分钟
|
||||||
|
- 验证测试:10分钟
|
||||||
|
|
||||||
|
**总计**: 约1.5-2小时
|
||||||
|
|
||||||
|
## 风险评估
|
||||||
|
|
||||||
|
| 风险项 | 等级 | 缓解措施 |
|
||||||
|
|--------|------|----------|
|
||||||
|
| 数据量过大导致超时 | 中 | 添加 max_allowed_packet 参数,分批导出 |
|
||||||
|
| 字符集乱码 | 高 | 严格遵循字符集规范,导入后验证 |
|
||||||
|
| 网络中断 | 低 | 本地保存SQL文件,可重复导入 |
|
||||||
|
| 生产环境数据冲突 | 无 | 全新空库,无冲突风险 |
|
||||||
|
| 权限问题 | 低 | 使用 root 用户或确保权限充足 |
|
||||||
|
|
||||||
|
## 成功标准
|
||||||
|
|
||||||
|
1. ✅ 所有表结构成功导出,无遗漏
|
||||||
|
2. ✅ 所有表数据成功导出,无丢失
|
||||||
|
3. ✅ SQL 文件字符集正确,无乱码
|
||||||
|
4. ✅ 测试环境导入成功,数据完整
|
||||||
|
5. ✅ 生产环境导入成功,数据完整
|
||||||
|
6. ✅ 中文数据正确显示,编码无误
|
||||||
|
7. ✅ 应用程序可正常连接和操作数据库
|
||||||
1248
docs/plans/2026-02-28-database-migration.md
Normal file
1248
docs/plans/2026-02-28-database-migration.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,269 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# CCDI 数据库导出脚本
|
|
||||||
# 功能:从开发环境导出数据库到 backup 文件夹
|
|
||||||
|
|
||||||
set -e # 遇到错误立即退出
|
|
||||||
|
|
||||||
# =====================================================
|
|
||||||
# 数据库配置(请根据实际情况修改)
|
|
||||||
# =====================================================
|
|
||||||
|
|
||||||
# 源数据库配置(开发环境)
|
|
||||||
DB_HOST="116.62.17.81"
|
|
||||||
DB_PORT="3306"
|
|
||||||
DB_USER="root"
|
|
||||||
DB_PASS="Kfcx@1234"
|
|
||||||
DB_NAME="ccdi"
|
|
||||||
|
|
||||||
# 导出文件配置
|
|
||||||
BACKUP_DIR="doc/database/backup"
|
|
||||||
STRUCTURE_FILE="ccdi_structure.sql"
|
|
||||||
DATA_FILE="ccdi_data.sql"
|
|
||||||
|
|
||||||
# mysqldump 参数配置
|
|
||||||
CHARACTER_SET="utf8mb4"
|
|
||||||
MAX_ALLOWED_PACKET="512M"
|
|
||||||
|
|
||||||
# =====================================================
|
|
||||||
# 脚本逻辑(无需修改)
|
|
||||||
# =====================================================
|
|
||||||
|
|
||||||
# 颜色定义
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# 日志函数
|
|
||||||
log_info() {
|
|
||||||
echo -e "${GREEN}[INFO]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warn() {
|
|
||||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}[ERROR]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 脚本目录
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
|
|
||||||
# 检查 mysqldump 命令
|
|
||||||
check_mysqldump() {
|
|
||||||
if ! command -v mysqldump &> /dev/null; then
|
|
||||||
log_error "mysqldump 命令未找到"
|
|
||||||
log_info "请安装 MySQL 客户端工具"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_info "mysqldump 命令检查通过"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 创建备份目录
|
|
||||||
create_backup_dir() {
|
|
||||||
if [ ! -d "$BACKUP_DIR" ]; then
|
|
||||||
mkdir -p "$BACKUP_DIR"
|
|
||||||
log_info "创建备份目录: $BACKUP_DIR"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 导出表结构
|
|
||||||
export_structure() {
|
|
||||||
log_info "开始导出表结构..."
|
|
||||||
|
|
||||||
local output_file="${BACKUP_DIR}/${STRUCTURE_FILE}"
|
|
||||||
|
|
||||||
# 创建临时文件
|
|
||||||
local temp_file=$(mktemp)
|
|
||||||
|
|
||||||
# 导出表结构到临时文件
|
|
||||||
mysqldump -h "$DB_HOST" \
|
|
||||||
-P "$DB_PORT" \
|
|
||||||
-u "$DB_USER" \
|
|
||||||
-p"$DB_PASS" \
|
|
||||||
--no-data \
|
|
||||||
--skip-triggers \
|
|
||||||
--skip-add-drop-table \
|
|
||||||
--default-character-set=$CHARACTER_SET \
|
|
||||||
--single-transaction \
|
|
||||||
--max_allowed_packet=$MAX_ALLOWED_PACKET \
|
|
||||||
"$DB_NAME" > "$temp_file" 2>/dev/null
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
# 添加字符集声明到文件头部
|
|
||||||
{
|
|
||||||
echo "-- CCDI 数据库表结构"
|
|
||||||
echo "-- 导出时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
||||||
echo "-- 源数据库: ${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
|
||||||
echo "-- 字符集: ${CHARACTER_SET}"
|
|
||||||
echo ""
|
|
||||||
echo "SET NAMES utf8mb4;"
|
|
||||||
echo "SET CHARACTER SET utf8mb4;"
|
|
||||||
echo "SET GLOBAL character_set_client=utf8mb4;"
|
|
||||||
echo "SET GLOBAL character_set_connection=utf8mb4;"
|
|
||||||
echo "SET GLOBAL character_set_results=utf8mb4;"
|
|
||||||
echo ""
|
|
||||||
cat "$temp_file"
|
|
||||||
} > "$output_file"
|
|
||||||
|
|
||||||
rm -f "$temp_file"
|
|
||||||
log_info "表结构导出成功: $output_file"
|
|
||||||
log_info "文件大小: $(du -h "$output_file" | cut -f1)"
|
|
||||||
else
|
|
||||||
rm -f "$temp_file"
|
|
||||||
log_error "表结构导出失败"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 导出数据
|
|
||||||
export_data() {
|
|
||||||
log_info "开始导出数据..."
|
|
||||||
|
|
||||||
local output_file="${BACKUP_DIR}/${DATA_FILE}"
|
|
||||||
|
|
||||||
# 创建临时文件
|
|
||||||
local temp_file=$(mktemp)
|
|
||||||
|
|
||||||
# 导出数据到临时文件
|
|
||||||
mysqldump -h "$DB_HOST" \
|
|
||||||
-P "$DB_PORT" \
|
|
||||||
-u "$DB_USER" \
|
|
||||||
-p"$DB_PASS" \
|
|
||||||
--no-create-info \
|
|
||||||
--skip-triggers \
|
|
||||||
--default-character-set=$CHARACTER_SET \
|
|
||||||
--single-transaction \
|
|
||||||
--complete-insert \
|
|
||||||
--extended-insert \
|
|
||||||
--max_allowed_packet=$MAX_ALLOWED_PACKET \
|
|
||||||
"$DB_NAME" > "$temp_file" 2>/dev/null
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
# 添加字符集声明到文件头部
|
|
||||||
{
|
|
||||||
echo "-- CCDI 数据库数据"
|
|
||||||
echo "-- 导出时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
||||||
echo "-- 源数据库: ${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
|
||||||
echo "-- 字符集: ${CHARACTER_SET}"
|
|
||||||
echo ""
|
|
||||||
echo "SET NAMES utf8mb4;"
|
|
||||||
echo "SET CHARACTER SET utf8mb4;"
|
|
||||||
echo "SET GLOBAL character_set_client=utf8mb4;"
|
|
||||||
echo "SET GLOBAL character_set_connection=utf8mb4;"
|
|
||||||
echo "SET GLOBAL character_set_results=utf8mb4;"
|
|
||||||
echo "SET FOREIGN_KEY_CHECKS=0;"
|
|
||||||
echo ""
|
|
||||||
cat "$temp_file"
|
|
||||||
echo ""
|
|
||||||
echo "SET FOREIGN_KEY_CHECKS=1;"
|
|
||||||
} > "$output_file"
|
|
||||||
|
|
||||||
rm -f "$temp_file"
|
|
||||||
log_info "数据导出成功: $output_file"
|
|
||||||
log_info "文件大小: $(du -h "$output_file" | cut -f1)"
|
|
||||||
else
|
|
||||||
rm -f "$temp_file"
|
|
||||||
log_error "数据导出失败"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证导出文件
|
|
||||||
verify_export() {
|
|
||||||
log_info "验证导出文件..."
|
|
||||||
|
|
||||||
local structure_file="${BACKUP_DIR}/${STRUCTURE_FILE}"
|
|
||||||
local data_file="${BACKUP_DIR}/${DATA_FILE}"
|
|
||||||
|
|
||||||
# 检查文件是否存在
|
|
||||||
if [ ! -f "$structure_file" ]; then
|
|
||||||
log_error "表结构文件不存在: $structure_file"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$data_file" ]; then
|
|
||||||
log_error "数据文件不存在: $data_file"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 检查字符集声明
|
|
||||||
if ! grep -q "SET NAMES utf8mb4" "$structure_file"; then
|
|
||||||
log_error "表结构文件缺少字符集声明"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -q "SET NAMES utf8mb4" "$data_file"; then
|
|
||||||
log_error "数据文件缺少字符集声明"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "导出文件验证通过"
|
|
||||||
log_info "表结构文件: $structure_file ($(du -h "$structure_file" | cut -f1))"
|
|
||||||
log_info "数据文件: $data_file ($(du -h "$data_file" | cut -f1))"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 导出数据库
|
|
||||||
export_database() {
|
|
||||||
log_info "========== 开始导出数据库 =========="
|
|
||||||
|
|
||||||
check_mysqldump
|
|
||||||
create_backup_dir
|
|
||||||
export_structure
|
|
||||||
export_data
|
|
||||||
verify_export
|
|
||||||
|
|
||||||
log_info "========== 数据库导出完成 =========="
|
|
||||||
log_info "使用 ./import_database.sh <env> 导入到目标环境"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 使用帮助
|
|
||||||
show_usage() {
|
|
||||||
echo "用法: $0 [command]"
|
|
||||||
echo ""
|
|
||||||
echo "命令:"
|
|
||||||
echo " export 导出数据库(默认命令)"
|
|
||||||
echo " help 显示帮助信息"
|
|
||||||
echo ""
|
|
||||||
echo "说明:"
|
|
||||||
echo " 此脚本从开发环境导出数据库到 doc/database/backup/ 文件夹"
|
|
||||||
echo " 生成文件:"
|
|
||||||
echo " - ccdi_structure.sql (表结构)"
|
|
||||||
echo " - ccdi_data.sql (数据)"
|
|
||||||
echo ""
|
|
||||||
echo "配置:"
|
|
||||||
echo " 数据库配置已内置在脚本顶部,请根据实际情况修改"
|
|
||||||
echo " 配置项: DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME"
|
|
||||||
echo ""
|
|
||||||
echo "前置条件:"
|
|
||||||
echo " 已安装 MySQL 客户端工具(mysqldump)"
|
|
||||||
echo ""
|
|
||||||
echo "示例:"
|
|
||||||
echo " $0 # 导出数据库(默认)"
|
|
||||||
echo " $0 export # 导出数据库"
|
|
||||||
echo ""
|
|
||||||
echo "后续操作:"
|
|
||||||
echo " 使用 ./import_database.sh <env> 导入到目标环境"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 主函数
|
|
||||||
main() {
|
|
||||||
case "$1" in
|
|
||||||
export|"")
|
|
||||||
export_database
|
|
||||||
;;
|
|
||||||
help|--help|-h)
|
|
||||||
show_usage
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_error "未知命令: $1"
|
|
||||||
show_usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行主函数
|
|
||||||
main "$@"
|
|
||||||
@@ -1,300 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# CCDI 数据库导入脚本
|
|
||||||
# 功能:从 backup 文件夹导入数据库到目标环境
|
|
||||||
|
|
||||||
set -e # 遇到错误立即退出
|
|
||||||
|
|
||||||
# =====================================================
|
|
||||||
# 数据库配置(请根据实际情况修改)
|
|
||||||
# =====================================================
|
|
||||||
|
|
||||||
# 开发环境数据库配置
|
|
||||||
DEV_DB_HOST="116.62.17.81"
|
|
||||||
DEV_DB_PORT="3306"
|
|
||||||
DEV_DB_USER="root"
|
|
||||||
DEV_DB_PASS="Kfcx@1234"
|
|
||||||
DEV_DB_NAME="ccdi"
|
|
||||||
|
|
||||||
# 测试环境数据库配置
|
|
||||||
TEST_DB_HOST="your_test_host"
|
|
||||||
TEST_DB_PORT="3306"
|
|
||||||
TEST_DB_USER="your_test_user"
|
|
||||||
TEST_DB_PASS="your_test_password"
|
|
||||||
TEST_DB_NAME="ccdi"
|
|
||||||
|
|
||||||
# 生产环境数据库配置
|
|
||||||
PROD_DB_HOST="your_production_host"
|
|
||||||
PROD_DB_PORT="3306"
|
|
||||||
PROD_DB_USER="your_production_user"
|
|
||||||
PROD_DB_PASS="your_production_password"
|
|
||||||
PROD_DB_NAME="ccdi"
|
|
||||||
|
|
||||||
# 备份文件配置
|
|
||||||
BACKUP_DIR="doc/database/backup"
|
|
||||||
STRUCTURE_FILE="ccdi_structure.sql"
|
|
||||||
DATA_FILE="ccdi_data.sql"
|
|
||||||
|
|
||||||
# =====================================================
|
|
||||||
# 脚本逻辑(无需修改)
|
|
||||||
# =====================================================
|
|
||||||
|
|
||||||
# 颜色定义
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# 日志函数
|
|
||||||
log_info() {
|
|
||||||
echo -e "${GREEN}[INFO]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warn() {
|
|
||||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}[ERROR]${NC} $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 脚本目录
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
|
|
||||||
# 检查 mysql 命令
|
|
||||||
check_mysql() {
|
|
||||||
if ! command -v mysql &> /dev/null; then
|
|
||||||
log_error "mysql 命令未找到"
|
|
||||||
log_info "请安装 MySQL 客户端工具"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_info "mysql 命令检查通过"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 检查备份文件
|
|
||||||
check_backup_files() {
|
|
||||||
log_info "检查备份文件..."
|
|
||||||
|
|
||||||
local structure_file="${BACKUP_DIR}/${STRUCTURE_FILE}"
|
|
||||||
local data_file="${BACKUP_DIR}/${DATA_FILE}"
|
|
||||||
|
|
||||||
if [ ! -f "$structure_file" ]; then
|
|
||||||
log_error "表结构文件不存在: $structure_file"
|
|
||||||
log_info "请先执行导出: ./export_database.sh"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -f "$data_file" ]; then
|
|
||||||
log_error "数据文件不存在: $data_file"
|
|
||||||
log_info "请先执行导出: ./export_database.sh"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "备份文件检查通过"
|
|
||||||
log_info "表结构文件: $structure_file ($(du -h "$structure_file" | cut -f1))"
|
|
||||||
log_info "数据文件: $data_file ($(du -h "$data_file" | cut -f1))"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 获取环境数据库配置
|
|
||||||
get_db_config() {
|
|
||||||
local env_type=$1
|
|
||||||
|
|
||||||
case "$env_type" in
|
|
||||||
dev|development)
|
|
||||||
DB_HOST="$DEV_DB_HOST"
|
|
||||||
DB_PORT="$DEV_DB_PORT"
|
|
||||||
DB_USER="$DEV_DB_USER"
|
|
||||||
DB_PASS="$DEV_DB_PASS"
|
|
||||||
DB_NAME="$DEV_DB_NAME"
|
|
||||||
;;
|
|
||||||
test)
|
|
||||||
DB_HOST="$TEST_DB_HOST"
|
|
||||||
DB_PORT="$TEST_DB_PORT"
|
|
||||||
DB_USER="$TEST_DB_USER"
|
|
||||||
DB_PASS="$TEST_DB_PASS"
|
|
||||||
DB_NAME="$TEST_DB_NAME"
|
|
||||||
;;
|
|
||||||
production|prod)
|
|
||||||
DB_HOST="$PROD_DB_HOST"
|
|
||||||
DB_PORT="$PROD_DB_PORT"
|
|
||||||
DB_USER="$PROD_DB_USER"
|
|
||||||
DB_PASS="$PROD_DB_PASS"
|
|
||||||
DB_NAME="$PROD_DB_NAME"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log_error "未知的环境类型: $env_type"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# 导入表结构
|
|
||||||
import_structure() {
|
|
||||||
local env_type=$1
|
|
||||||
|
|
||||||
get_db_config "$env_type"
|
|
||||||
|
|
||||||
log_info "导入表结构到 ${env_type} 环境: ${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
|
||||||
|
|
||||||
local structure_file="${BACKUP_DIR}/${STRUCTURE_FILE}"
|
|
||||||
|
|
||||||
# 导入表结构
|
|
||||||
mysql -h "$DB_HOST" \
|
|
||||||
-P "$DB_PORT" \
|
|
||||||
-u "$DB_USER" \
|
|
||||||
-p"$DB_PASS" \
|
|
||||||
--default-character-set=utf8mb4 \
|
|
||||||
"$DB_NAME" < "$structure_file" 2>/dev/null
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
log_info "表结构导入成功"
|
|
||||||
else
|
|
||||||
log_error "表结构导入失败"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 导入数据
|
|
||||||
import_data() {
|
|
||||||
local env_type=$1
|
|
||||||
|
|
||||||
get_db_config "$env_type"
|
|
||||||
|
|
||||||
log_info "导入数据到 ${env_type} 环境: ${DB_HOST}:${DB_PORT}/${DB_NAME}"
|
|
||||||
|
|
||||||
local data_file="${BACKUP_DIR}/${DATA_FILE}"
|
|
||||||
|
|
||||||
# 导入数据
|
|
||||||
mysql -h "$DB_HOST" \
|
|
||||||
-P "$DB_PORT" \
|
|
||||||
-u "$DB_USER" \
|
|
||||||
-p"$DB_PASS" \
|
|
||||||
--default-character-set=utf8mb4 \
|
|
||||||
"$DB_NAME" < "$data_file" 2>/dev/null
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
log_info "数据导入成功"
|
|
||||||
else
|
|
||||||
log_error "数据导入失败"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证导入结果
|
|
||||||
verify_import() {
|
|
||||||
local env_type=$1
|
|
||||||
|
|
||||||
get_db_config "$env_type"
|
|
||||||
|
|
||||||
log_info "验证导入结果..."
|
|
||||||
|
|
||||||
# 查询表数量
|
|
||||||
local table_count=$(mysql -h "$DB_HOST" \
|
|
||||||
-P "$DB_PORT" \
|
|
||||||
-u "$DB_USER" \
|
|
||||||
-p"$DB_PASS" \
|
|
||||||
--default-character-set=utf8mb4 \
|
|
||||||
-N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$DB_NAME';" "$DB_NAME" 2>/dev/null)
|
|
||||||
|
|
||||||
log_info "目标数据库表数量: $table_count"
|
|
||||||
|
|
||||||
# 查询关键表行数(示例:sys_user 表)
|
|
||||||
local user_count=$(mysql -h "$DB_HOST" \
|
|
||||||
-P "$DB_PORT" \
|
|
||||||
-u "$DB_USER" \
|
|
||||||
-p"$DB_PASS" \
|
|
||||||
--default-character-set=utf8mb4 \
|
|
||||||
-N -e "SELECT COUNT(*) FROM sys_user;" "$DB_NAME" 2>/dev/null)
|
|
||||||
|
|
||||||
log_info "sys_user 表数据行数: $user_count"
|
|
||||||
|
|
||||||
# 检查数据库字符集
|
|
||||||
local db_charset=$(mysql -h "$DB_HOST" \
|
|
||||||
-P "$DB_PORT" \
|
|
||||||
-u "$DB_USER" \
|
|
||||||
-p"$DB_PASS" \
|
|
||||||
--default-character-set=utf8mb4 \
|
|
||||||
-N -e "SELECT DEFAULT_CHARACTER_SET_NAME FROM information_schema.schemata WHERE schema_name='$DB_NAME';" 2>/dev/null)
|
|
||||||
|
|
||||||
log_info "数据库字符集: $db_charset"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 导入数据库
|
|
||||||
import_database() {
|
|
||||||
local env_type=$1
|
|
||||||
|
|
||||||
if [ -z "$env_type" ]; then
|
|
||||||
log_error "请指定目标环境: dev, test 或 production"
|
|
||||||
log_info "用法: $0 <env>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "========== 开始导入数据库到 ${env_type} 环境 =========="
|
|
||||||
|
|
||||||
check_mysql
|
|
||||||
check_backup_files
|
|
||||||
import_structure "$env_type"
|
|
||||||
import_data "$env_type"
|
|
||||||
verify_import "$env_type"
|
|
||||||
|
|
||||||
log_info "========== 数据库导入完成 =========="
|
|
||||||
}
|
|
||||||
|
|
||||||
# 使用帮助
|
|
||||||
show_usage() {
|
|
||||||
echo "用法: $0 <environment>"
|
|
||||||
echo ""
|
|
||||||
echo "环境:"
|
|
||||||
echo " dev, development 开发环境"
|
|
||||||
echo " test 测试环境"
|
|
||||||
echo " production, prod 生产环境"
|
|
||||||
echo ""
|
|
||||||
echo "说明:"
|
|
||||||
echo " 此脚本从 doc/database/backup/ 文件夹读取备份文件并导入到指定环境"
|
|
||||||
echo " 备份文件:"
|
|
||||||
echo " - ccdi_structure.sql (表结构)"
|
|
||||||
echo " - ccdi_data.sql (数据)"
|
|
||||||
echo ""
|
|
||||||
echo "配置:"
|
|
||||||
echo " 数据库配置已内置在脚本顶部,请根据实际情况修改"
|
|
||||||
echo " 配置项: DEV_DB_*, TEST_DB_*, PROD_DB_*"
|
|
||||||
echo ""
|
|
||||||
echo "前置条件:"
|
|
||||||
echo " 1. 已执行 ./export_database.sh 导出数据库"
|
|
||||||
echo " 2. 已在脚本顶部配置目标环境数据库信息"
|
|
||||||
echo ""
|
|
||||||
echo "示例:"
|
|
||||||
echo " $0 test # 导入到测试环境"
|
|
||||||
echo " $0 prod # 导入到生产环境"
|
|
||||||
echo " $0 dev # 导入到开发环境"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 主函数
|
|
||||||
main() {
|
|
||||||
case "$1" in
|
|
||||||
dev|development)
|
|
||||||
import_database "dev"
|
|
||||||
;;
|
|
||||||
test)
|
|
||||||
import_database "test"
|
|
||||||
;;
|
|
||||||
production|prod)
|
|
||||||
import_database "production"
|
|
||||||
;;
|
|
||||||
help|--help|-h)
|
|
||||||
show_usage
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
log_error "缺少环境参数"
|
|
||||||
else
|
|
||||||
log_error "未知的环境: $1"
|
|
||||||
fi
|
|
||||||
show_usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# 执行主函数
|
|
||||||
main "$@"
|
|
||||||
Reference in New Issue
Block a user