From a32af2fc374bb5f84c8f79ce99bebfb1d49f9346 Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Mon, 2 Mar 2026 09:52:28 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E6=B5=81=E6=B0=B4?= =?UTF-8?q?=E5=88=86=E6=9E=90=E5=AF=B9=E6=8E=A5=E6=96=87=E6=A1=A3=E5=92=8C?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E8=BF=81=E7=A7=BB=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db_config.conf.template | 32 - doc/database/backup/ccdi_data.sql | 4 +- doc/database/backup/ccdi_structure.sql | 4 +- .../2026-02-28-frontend-test-report.md | 308 ++++ doc/对接流水分析/task.md | 7 + doc/对接流水分析/兰溪-流水分析对接.docx | Bin 0 -> 168365 bytes doc/对接流水分析/兰溪-流水分析对接.md | 561 ++++++++ .../2026-02-28-database-migration-design.md | 282 ++++ docs/plans/2026-02-28-database-migration.md | 1248 +++++++++++++++++ export_database.sh | 269 ---- import_database.sh | 300 ---- 11 files changed, 2410 insertions(+), 605 deletions(-) delete mode 100644 db_config.conf.template create mode 100644 doc/test-scripts/2026-02-28-frontend-test-report.md create mode 100644 doc/对接流水分析/task.md create mode 100644 doc/对接流水分析/兰溪-流水分析对接.docx create mode 100644 doc/对接流水分析/兰溪-流水分析对接.md create mode 100644 docs/plans/2026-02-28-database-migration-design.md create mode 100644 docs/plans/2026-02-28-database-migration.md delete mode 100644 export_database.sh delete mode 100644 import_database.sh diff --git a/db_config.conf.template b/db_config.conf.template deleted file mode 100644 index e18b746..0000000 --- a/db_config.conf.template +++ /dev/null @@ -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 diff --git a/doc/database/backup/ccdi_data.sql b/doc/database/backup/ccdi_data.sql index 3367488..ea07c58 100644 --- a/doc/database/backup/ccdi_data.sql +++ b/doc/database/backup/ccdi_data.sql @@ -1,5 +1,5 @@ -- CCDI 数据库数据 --- 导出时间: 2026-02-28 15:23:04 +-- 导出时间: 2026-02-28 15:26:26 -- 源数据库: 116.62.17.81:3306/ccdi -- 字符集: utf8mb4 @@ -445,6 +445,6 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!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; diff --git a/doc/database/backup/ccdi_structure.sql b/doc/database/backup/ccdi_structure.sql index 9427914..3debedb 100644 --- a/doc/database/backup/ccdi_structure.sql +++ b/doc/database/backup/ccdi_structure.sql @@ -1,5 +1,5 @@ -- CCDI 数据库表结构 --- 导出时间: 2026-02-28 15:22:54 +-- 导出时间: 2026-02-28 15:26:16 -- 源数据库: 116.62.17.81:3306/ccdi -- 字符集: utf8mb4 @@ -1092,4 +1092,4 @@ CREATE TABLE `sys_user_role` ( /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!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 diff --git a/doc/test-scripts/2026-02-28-frontend-test-report.md b/doc/test-scripts/2026-02-28-frontend-test-report.md new file mode 100644 index 0000000..37410c0 --- /dev/null +++ b/doc/test-scripts/2026-02-28-frontend-test-report.md @@ -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 diff --git a/doc/对接流水分析/task.md b/doc/对接流水分析/task.md new file mode 100644 index 0000000..8aa3542 --- /dev/null +++ b/doc/对接流水分析/task.md @@ -0,0 +1,7 @@ +# 系统需要对接流水分析平台,调用流水分析平台的接口 +- 新建一个模块ccdi_lsfx,保存所有调用流水分析平台的代码 +- 创建一个用于发起http请求的工具类,使用RestTemplate +- 读取接口文档 D:\ccdi\ccdi\doc\对接流水分析\兰溪-流水分析对接.docx,分析每个接口的入参和返回值格式,封装入参和出参的对象 +- 在配置文档中添加每个接口对应的url配置 +- 在后端服务层中实现这些接口的调用,获取返回值 +- 创建一个控制层,可以调用这些接口,用于测试 diff --git a/doc/对接流水分析/兰溪-流水分析对接.docx b/doc/对接流水分析/兰溪-流水分析对接.docx new file mode 100644 index 0000000000000000000000000000000000000000..932def3e8521c8ebb8ab231e109c390d31103740 GIT binary patch literal 168365 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 n6#m0YT{8YIR`N=LC>CNnwLh!4Cs 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 z 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 literal 0 HcmV?d00001 diff --git a/doc/对接流水分析/兰溪-流水分析对接.md b/doc/对接流水分析/兰溪-流水分析对接.md new file mode 100644 index 0000000..66bbc92 --- /dev/null +++ b/doc/对接流水分析/兰溪-流水分析对接.md @@ -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请求 | diff --git a/docs/plans/2026-02-28-database-migration-design.md b/docs/plans/2026-02-28-database-migration-design.md new file mode 100644 index 0000000..7ad1370 --- /dev/null +++ b/docs/plans/2026-02-28-database-migration-design.md @@ -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. ✅ 应用程序可正常连接和操作数据库 diff --git a/docs/plans/2026-02-28-database-migration.md b/docs/plans/2026-02-28-database-migration.md new file mode 100644 index 0000000..cab425b --- /dev/null +++ b/docs/plans/2026-02-28-database-migration.md @@ -0,0 +1,1248 @@ +# 数据库迁移实施计划 + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** 创建自动化脚本完成 CCDI 数据库的完整导出和导入,包括表结构和数据,确保字符集正确无乱码 + +**Architecture:** 使用 mysqldump 命令导出数据库,分离表结构和数据为两个 SQL 文件,通过 Bash 脚本自动化管理导出和导入流程,配置文件管理多环境数据库连接信息 + +**Tech Stack:** Bash 脚本、mysqldump/mysql 命令行工具、UTF-8/utf8mb4 字符集 + +--- + +## Task 1: 创建配置文件模板和安全措施 + +**Files:** +- Create: `db_config.conf.template` +- Modify: `.gitignore` + +**Step 1: 创建配置文件模板** + +创建 `db_config.conf.template` 文件: + +```bash +# 数据库迁移配置文件模板 +# 使用方法:复制此文件为 db_config.conf 并填写实际值 + +# 源数据库配置(开发环境) +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=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 +``` + +**Step 2: 更新 .gitignore 文件** + +在 `.gitignore` 文件末尾添加: + +``` +# 数据库配置文件(包含敏感信息) +db_config.conf +``` + +**Step 3: 提交配置模板** + +```bash +git add db_config.conf.template .gitignore +git commit -m "feat: 添加数据库迁移配置模板和安全措施" +``` + +--- + +## Task 2: 创建备份目录结构 + +**Files:** +- Create: `doc/database/backup/.gitkeep` + +**Step 1: 创建备份目录** + +```bash +mkdir -p doc/database/backup +``` + +**Step 2: 创建 .gitkeep 文件保持目录** + +```bash +touch doc/database/backup/.gitkeep +``` + +**Step 3: 提交目录结构** + +```bash +git add doc/database/backup/.gitkeep +git commit -m "feat: 创建数据库备份目录结构" +``` + +--- + +## Task 3: 创建自动化导出脚本(框架和导出功能) + +**Files:** +- Create: `export_database.sh` + +**Step 1: 创建脚本文件并添加基本框架** + +创建 `export_database.sh` 文件: + +```bash +#!/bin/bash + +# CCDI 数据库迁移自动化脚本 +# 功能:数据库导出和导入自动化 + +set -e # 遇到错误立即退出 + +# 颜色定义 +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)" +CONFIG_FILE="${SCRIPT_DIR}/db_config.conf" + +# 检查配置文件 +check_config() { + if [ ! -f "$CONFIG_FILE" ]; then + log_error "配置文件不存在: $CONFIG_FILE" + log_info "请先复制配置模板: cp db_config.conf.template db_config.conf" + log_info "然后编辑 db_config.conf 填写实际数据库连接信息" + exit 1 + fi + + # 加载配置文件 + source "$CONFIG_FILE" + log_info "配置文件加载成功" +} + +# 检查 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 "$SOURCE_DB_HOST" \ + -P "$SOURCE_DB_PORT" \ + -u "$SOURCE_DB_USER" \ + -p"$SOURCE_DB_PASS" \ + --no-data \ + --skip-triggers \ + --skip-add-drop-table \ + --default-character-set=$CHARACTER_SET \ + --single-transaction \ + --max_allowed_packet=$MAX_ALLOWED_PACKET \ + "$SOURCE_DB_NAME" > "$temp_file" 2>/dev/null + + if [ $? -eq 0 ]; then + # 添加字符集声明到文件头部 + { + echo "-- CCDI 数据库表结构" + echo "-- 导出时间: $(date '+%Y-%m-%d %H:%M:%S')" + echo "-- 源数据库: ${SOURCE_DB_HOST}:${SOURCE_DB_PORT}/${SOURCE_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 "$SOURCE_DB_HOST" \ + -P "$SOURCE_DB_PORT" \ + -u "$SOURCE_DB_USER" \ + -p"$SOURCE_DB_PASS" \ + --no-create-info \ + --skip-triggers \ + --default-character-set=$CHARACTER_SET \ + --single-transaction \ + --complete-insert \ + --extended-insert \ + --max_allowed_packet=$MAX_ALLOWED_PACKET \ + "$SOURCE_DB_NAME" > "$temp_file" 2>/dev/null + + if [ $? -eq 0 ]; then + # 添加字符集声明到文件头部 + { + echo "-- CCDI 数据库数据" + echo "-- 导出时间: $(date '+%Y-%m-%d %H:%M:%S')" + echo "-- 源数据库: ${SOURCE_DB_HOST}:${SOURCE_DB_PORT}/${SOURCE_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_config + check_mysqldump + create_backup_dir + export_structure + export_data + verify_export + + log_info "========== 数据库导出完成 ==========" +} + +# 使用帮助 +show_usage() { + echo "用法: $0 " + echo "" + echo "命令:" + echo " export 导出数据库" + echo " help 显示帮助信息" + echo "" + echo "示例:" + echo " $0 export # 导出数据库到 doc/database/backup/ 目录" +} + +# 主函数 +main() { + case "$1" in + export) + export_database + ;; + help|--help|-h) + show_usage + ;; + *) + log_error "未知命令: $1" + show_usage + exit 1 + ;; + esac +} + +# 执行主函数 +main "$@" +``` + +**Step 2: 设置脚本执行权限** + +```bash +chmod +x export_database.sh +``` + +**Step 3: 提交导出脚本** + +```bash +git add export_database.sh +git commit -m "feat: 创建数据库导出自动化脚本" +``` + +--- + +## Task 4: 执行数据库导出 + +**Files:** +- Generate: `doc/database/backup/ccdi_structure.sql` +- Generate: `doc/database/backup/ccdi_data.sql` + +**Step 1: 创建配置文件** + +```bash +cp db_config.conf.template db_config.conf +``` + +**Step 2: 验证配置文件内容** + +检查 `db_config.conf` 文件确保源数据库配置正确: +```bash +cat db_config.conf | grep "SOURCE_DB" +``` + +预期输出: +``` +SOURCE_DB_HOST=116.62.17.81 +SOURCE_DB_PORT=3306 +SOURCE_DB_USER=root +SOURCE_DB_PASS=Kfcx@1234 +SOURCE_DB_NAME=ccdi +``` + +**Step 3: 执行导出脚本** + +```bash +./export_database.sh export +``` + +预期输出: +``` +[INFO] 配置文件加载成功 +[INFO] mysqldump 命令检查通过 +[INFO] 开始导出表结构... +[INFO] 表结构导出成功: doc/database/backup/ccdi_structure.sql +[INFO] 文件大小: XXX +[INFO] 开始导出数据... +[INFO] 数据导出成功: doc/database/backup/ccdi_data.sql +[INFO] 文件大小: XXX +[INFO] 验证导出文件... +[INFO] 导出文件验证通过 +[INFO] ========== 数据库导出完成 ========== +``` + +**Step 4: 验证导出文件** + +检查表结构文件头部: +```bash +head -20 doc/database/backup/ccdi_structure.sql +``` + +预期输出应包含: +```sql +-- CCDI 数据库表结构 +-- 导出时间: 2026-02-28 XX:XX:XX +-- 源数据库: 116.62.17.81:3306/ccdi +-- 字符集: utf8mb4 + +SET NAMES utf8mb4; +SET CHARACTER SET utf8mb4; +... +``` + +检查数据文件头部: +```bash +head -20 doc/database/backup/ccdi_data.sql +``` + +预期输出应包含: +```sql +-- CCDI 数据库数据 +-- 导出时间: 2026-02-28 XX:XX:XX +-- 源数据库: 116.62.17.81:3306/ccdi +-- 字符集: utf8mb4 + +SET NAMES utf8mb4; +SET CHARACTER SET utf8mb4; +SET FOREIGN_KEY_CHECKS=0; +... +``` + +**Step 5: 检查文件大小** + +```bash +ls -lh doc/database/backup/ +``` + +预期输出应显示两个文件的大小。 + +--- + +## Task 5: 添加导入功能到脚本 + +**Files:** +- Modify: `export_database.sh` (添加导入函数) + +**Step 1: 在脚本中添加导入函数** + +在 `export_database.sh` 文件的 `verify_export()` 函数后添加以下函数: + +```bash + +# 导入表结构 +import_structure() { + local env_type=$1 + local db_host db_port db_user db_pass db_name + + case "$env_type" in + 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" + ;; + 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" + ;; + *) + log_error "未知的环境类型: $env_type" + exit 1 + ;; + esac + + log_info "导入表结构到 ${env_type} 环境: ${db_host}:${db_port}/${db_name}" + + local structure_file="${BACKUP_DIR}/${STRUCTURE_FILE}" + + if [ ! -f "$structure_file" ]; then + log_error "表结构文件不存在: $structure_file" + log_info "请先执行导出: ./export_database.sh export" + exit 1 + fi + + # 导入表结构 + mysql -h "$db_host" \ + -P "$db_port" \ + -u "$db_user" \ + -p"$db_pass" \ + --default-character-set=$CHARACTER_SET \ + "$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 + local db_host db_port db_user db_pass db_name + + case "$env_type" in + 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" + ;; + 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" + ;; + *) + log_error "未知的环境类型: $env_type" + exit 1 + ;; + esac + + log_info "导入数据到 ${env_type} 环境: ${db_host}:${db_port}/${db_name}" + + local data_file="${BACKUP_DIR}/${DATA_FILE}" + + if [ ! -f "$data_file" ]; then + log_error "数据文件不存在: $data_file" + log_info "请先执行导出: ./export_database.sh export" + exit 1 + fi + + # 导入数据 + mysql -h "$db_host" \ + -P "$db_port" \ + -u "$db_user" \ + -p"$db_pass" \ + --default-character-set=$CHARACTER_SET \ + "$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 + local db_host db_port db_user db_pass db_name + + case "$env_type" in + 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" + ;; + 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" + ;; + *) + log_error "未知的环境类型: $env_type" + exit 1 + ;; + esac + + log_info "验证导入结果..." + + # 查询表数量 + local table_count=$(mysql -h "$db_host" \ + -P "$db_port" \ + -u "$db_user" \ + -p"$db_pass" \ + --default-character-set=$CHARACTER_SET \ + -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=$CHARACTER_SET \ + -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=$CHARACTER_SET \ + -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 "请指定目标环境: production 或 test" + log_info "用法: $0 import [production|test]" + exit 1 + fi + + log_info "========== 开始导入数据库到 ${env_type} 环境 ==========" + + check_config + import_structure "$env_type" + import_data "$env_type" + verify_import "$env_type" + + log_info "========== 数据库导入完成 ==========" +} +``` + +**Step 2: 更新 show_usage() 函数** + +替换 `show_usage()` 函数为: + +```bash +# 使用帮助 +show_usage() { + echo "用法: $0 [options]" + echo "" + echo "命令:" + echo " export 导出数据库" + echo " import 导入数据库到指定环境" + echo " help 显示帮助信息" + echo "" + echo "环境:" + echo " production, prod 生产环境" + echo " test 测试环境" + echo "" + echo "示例:" + echo " $0 export # 导出数据库到 doc/database/backup/ 目录" + echo " $0 import test # 导入数据库到测试环境" + echo " $0 import prod # 导入数据库到生产环境" +} +``` + +**Step 3: 更新 main() 函数** + +替换 `main()` 函数为: + +```bash +# 主函数 +main() { + case "$1" in + export) + export_database + ;; + import) + import_database "$2" + ;; + help|--help|-h) + show_usage + ;; + *) + log_error "未知命令: $1" + show_usage + exit 1 + ;; + esac +} +``` + +**Step 4: 提交导入功能** + +```bash +git add export_database.sh +git commit -m "feat: 添加数据库导入功能到自动化脚本" +``` + +--- + +## Task 6: 创建操作指南文档 + +**Files:** +- Create: `doc/database/backup/export_guide.md` + +**Step 1: 创建操作指南文档** + +创建 `doc/database/backup/export_guide.md` 文件: + +```markdown +# CCDI 数据库迁移操作指南 + +## 概述 + +本文档提供 CCDI 纪检初核系统数据库迁移的详细操作步骤,包括从开发环境导出数据库和导入到生产/测试环境。 + +## 前置条件 + +### 必需工具 +- MySQL 客户端工具(包含 mysqldump 和 mysql 命令) +- Bash shell 环境 +- 网络访问权限(能连接源数据库和目标数据库) + +### 检查 mysqldump 是否安装 +```bash +mysqldump --version +``` + +如果未安装,请根据操作系统安装 MySQL 客户端: +- **Windows**: 安装 MySQL Community Server +- **Linux (Ubuntu/Debian)**: `sudo apt-get install mysql-client` +- **Linux (CentOS/RHEL)**: `sudo yum install mysql` +- **macOS**: `brew install mysql-client` + +## 配置步骤 + +### 1. 创建配置文件 + +```bash +# 复制配置模板 +cp db_config.conf.template db_config.conf + +# 编辑配置文件 +nano db_config.conf # 或使用其他编辑器 +``` + +### 2. 填写配置信息 + +编辑 `db_config.conf` 文件,填写以下信息: + +**源数据库(开发环境):** +- `SOURCE_DB_HOST`: 开发环境数据库地址 +- `SOURCE_DB_PORT`: 数据库端口(默认 3306) +- `SOURCE_DB_USER`: 数据库用户名 +- `SOURCE_DB_PASS`: 数据库密码 +- `SOURCE_DB_NAME`: 数据库名称(ccdi) + +**生产环境数据库:** +- `PROD_DB_HOST`: 生产环境数据库地址 +- `PROD_DB_PORT`: 数据库端口 +- `PROD_DB_USER`: 生产环境数据库用户名 +- `PROD_DB_PASS`: 生产环境数据库密码 +- `PROD_DB_NAME`: 数据库名称(ccdi) + +**测试环境数据库(可选):** +- `TEST_DB_HOST`: 测试环境数据库地址 +- `TEST_DB_PORT`: 数据库端口 +- `TEST_DB_USER`: 测试环境数据库用户名 +- `TEST_DB_PASS`: 测试环境数据库密码 +- `TEST_DB_NAME`: 数据库名称(ccdi) + +### 3. 验证配置 + +检查配置文件格式: +```bash +cat db_config.conf | grep -E "^[A-Z]" +``` + +确保所有必需的配置项都已填写。 + +## 数据库导出 + +### 执行导出 + +```bash +./export_database.sh export +``` + +### 预期输出 + +``` +[INFO] 配置文件加载成功 +[INFO] mysqldump 命令检查通过 +[INFO] 开始导出表结构... +[INFO] 表结构导出成功: doc/database/backup/ccdi_structure.sql +[INFO] 文件大小: XXX +[INFO] 开始导出数据... +[INFO] 数据导出成功: doc/database/backup/ccdi_data.sql +[INFO] 文件大小: XXX +[INFO] 验证导出文件... +[INFO] 导出文件验证通过 +[INFO] ========== 数据库导出完成 ========== +``` + +### 验证导出文件 + +**1. 检查文件是否存在** +```bash +ls -lh doc/database/backup/ +``` + +应该看到: +- `ccdi_structure.sql` - 表结构文件 +- `ccdi_data.sql` - 数据文件 + +**2. 检查字符集声明** +```bash +head -20 doc/database/backup/ccdi_structure.sql +``` + +应该包含: +```sql +SET NAMES utf8mb4; +SET CHARACTER SET utf8mb4; +``` + +**3. 检查文件内容** +```bash +# 查看表结构 +grep "CREATE TABLE" doc/database/backup/ccdi_structure.sql | wc -l + +# 查看数据量(INSERT 语句数量) +grep "INSERT" doc/database/backup/ccdi_data.sql | wc -l +``` + +## 数据库导入 + +### 准备工作 + +**1. 确认目标数据库已创建** + +连接到目标数据库服务器: +```bash +mysql -h 目标IP -P 3306 -u 用户名 -p +``` + +创建数据库(如果不存在): +```sql +CREATE DATABASE ccdi CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; +``` + +**2. 确认用户权限** + +目标数据库用户需要以下权限: +- CREATE、ALTER、DROP(创建和修改表) +- INSERT、UPDATE、DELETE(数据操作) +- INDEX(创建索引) +- REFERENCES(外键约束) + +### 导入到测试环境 + +```bash +./export_database.sh import test +``` + +### 导入到生产环境 + +```bash +./export_database.sh import production +``` + +或简写: +```bash +./export_database.sh import prod +``` + +### 预期输出 + +``` +[INFO] ========== 开始导入数据库到 test 环境 ========== +[INFO] 导入表结构到 test 环境: XXX:3306/ccdi +[INFO] 表结构导入成功 +[INFO] 导入数据到 test 环境: XXX:3306/ccdi +[INFO] 数据导入成功 +[INFO] 验证导入结果... +[INFO] 目标数据库表数量: XX +[INFO] sys_user 表数据行数: XX +[INFO] 数据库字符集: utf8mb4 +[INFO] ========== 数据库导入完成 ========== +``` + +## 导入后验证 + +### 1. 验证表数量 + +连接到目标数据库: +```bash +mysql -h 目标IP -P 3306 -u 用户名 -p ccdi +``` + +查询表数量: +```sql +SELECT COUNT(*) FROM information_schema.tables +WHERE table_schema='ccdi'; +``` + +对比源数据库和目标数据库的表数量是否一致。 + +### 2. 验证数据行数 + +查询各表数据行数: +```sql +SELECT table_name, table_rows +FROM information_schema.tables +WHERE table_schema='ccdi' +ORDER BY table_rows DESC +LIMIT 20; +``` + +对比源数据库和目标数据库的关键表行数。 + +### 3. 验证字符集 + +检查数据库字符集: +```sql +SHOW CREATE DATABASE ccdi; +``` + +应该显示:`DEFAULT CHARACTER SET utf8mb4` + +检查表字符集: +```sql +SHOW CREATE TABLE sys_user; +``` + +应该显示:`ENGINE=InnoDB DEFAULT CHARSET=utf8mb4` + +### 4. 验证中文数据 + +查询包含中文的数据: +```sql +-- 查询用户表 +SELECT user_name, nick_name FROM sys_user LIMIT 10; + +-- 查询字典数据 +SELECT dict_label, dict_value FROM sys_dict_data LIMIT 10; +``` + +确保中文字符显示正常,无乱码。 + +### 5. 应用程序连接测试 + +修改应用程序配置文件连接到目标数据库,启动应用程序进行功能测试。 + +## 完整迁移流程示例 + +### 场景:从开发环境迁移到生产环境 + +**1. 配置数据库连接** +```bash +cp db_config.conf.template db_config.conf +nano db_config.conf +# 填写开发环境和生产环境数据库信息 +``` + +**2. 导出数据库** +```bash +./export_database.sh export +``` + +**3. 验证导出文件** +```bash +ls -lh doc/database/backup/ +head -20 doc/database/backup/ccdi_structure.sql +``` + +**4. 先在测试环境验证** +```bash +./export_database.sh import test +``` + +**5. 验证测试环境** +- 连接测试数据库验证数据 +- 应用程序连接测试环境进行功能测试 + +**6. 导入到生产环境** +```bash +./export_database.sh import production +``` + +**7. 验证生产环境** +- 连接生产数据库验证数据 +- 应用程序连接生产环境进行功能测试 + +**8. 完成迁移** + +## 常见问题 + +### 1. mysqldump: command not found + +**原因**: MySQL 客户端未安装或未添加到 PATH + +**解决**: +- 安装 MySQL 客户端工具 +- 或使用完整路径:`/usr/bin/mysqldump` + +### 2. 配置文件不存在 + +**错误信息**: `配置文件不存在: db_config.conf` + +**解决**: +```bash +cp db_config.conf.template db_config.conf +# 编辑 db_config.conf 填写实际配置 +``` + +### 3. 连接数据库失败 + +**可能原因**: +- 数据库地址、端口、用户名或密码错误 +- 防火墙阻止连接 +- 数据库服务未启动 + +**解决**: +- 检查配置文件中的连接信息 +- 使用 mysql 命令手动测试连接 +- 检查防火墙规则 + +### 4. 导入时字符集乱码 + +**原因**: 未正确指定字符集 + +**解决**: +- 确保导出文件包含字符集声明 +- 导入命令添加 `--default-character-set=utf8mb4` 参数 +- 脚本已自动处理,如仍有问题请检查数据库默认字符集 + +### 5. 外键约束失败 + +**错误信息**: `ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails` + +**解决**: +- 脚本已自动添加 `SET FOREIGN_KEY_CHECKS=0;` 和 `SET FOREIGN_KEY_CHECKS=1;` +- 如仍有问题,请检查数据完整性 + +### 6. 数据包过大 + +**错误信息**: `ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes` + +**解决**: +- 配置文件中的 `MAX_ALLOWED_PACKET=512M` 已处理此问题 +- 如数据量特别大,可增大此值 + +### 7. 权限不足 + +**错误信息**: `ERROR 1044 (42000): Access denied for user` + +**解决**: +- 使用具有足够权限的用户(如 root) +- 或授予用户必要权限 + +## 回滚方案 + +如果迁移失败或出现问题: + +1. **保留源数据库**: 不要删除开发环境数据库 +2. **重新迁移**: 修复问题后重新执行迁移流程 +3. **从备份恢复**: 如生产环境有备份,可从备份恢复 + +## 注意事项 + +1. **安全性**: + - `db_config.conf` 包含敏感信息,已添加到 `.gitignore` + - 不要将配置文件提交到版本控制系统 + - 迁移完成后建议删除配置文件中的密码 + +2. **性能**: + - 大数据库导出/导入可能需要较长时间 + - 建议在低峰期执行迁移 + - 确保有足够的磁盘空间 + +3. **数据一致性**: + - 导出期间源数据库应避免写入操作 + - 或使用 `--single-transaction` 参数(已包含) + +4. **字符集**: + - 确保所有步骤都使用 utf8mb4 字符集 + - 验证阶段重点检查中文数据 + +## 技术支持 + +如遇到问题: +1. 检查本文档的常见问题部分 +2. 查看脚本执行的错误信息 +3. 检查数据库连接和权限 +4. 查看数据库日志 + +## 相关文件 + +- 自动化脚本: `export_database.sh` +- 配置模板: `db_config.conf.template` +- 实际配置: `db_config.conf` +- 表结构文件: `doc/database/backup/ccdi_structure.sql` +- 数据文件: `doc/database/backup/ccdi_data.sql` +- 设计文档: `docs/plans/2026-02-28-database-migration-design.md` +``` + +**Step 2: 提交操作指南** + +```bash +git add doc/database/backup/export_guide.md +git commit -m "docs: 添加数据库迁移操作指南" +``` + +--- + +## Task 7: 完整验证流程 + +**Files:** +- 无文件修改,仅验证操作 + +**Step 1: 验证脚本帮助信息** + +```bash +./export_database.sh help +``` + +预期输出: +``` +用法: ./export_database.sh [options] + +命令: + export 导出数据库 + import 导入数据库到指定环境 + help 显示帮助信息 + +环境: + production, prod 生产环境 + test 测试环境 + +示例: + ./export_database.sh export # 导出数据库到 doc/database/backup/ 目录 + ./export_database.sh import test # 导入数据库到测试环境 + ./export_database.sh import prod # 导入数据库到生产环境 +``` + +**Step 2: 验证配置文件** + +```bash +cat db_config.conf +``` + +确保包含所有必需配置项。 + +**Step 3: 验证导出文件** + +```bash +# 检查文件存在 +ls -lh doc/database/backup/ccdi_*.sql + +# 检查文件内容 +head -30 doc/database/backup/ccdi_structure.sql +head -30 doc/database/backup/ccdi_data.sql + +# 统计表数量 +grep "CREATE TABLE" doc/database/backup/ccdi_structure.sql | wc -l + +# 统计 INSERT 语句 +grep "INSERT INTO" doc/database/backup/ccdi_data.sql | wc -l +``` + +**Step 4: 创建验证报告** + +创建临时验证报告: +```bash +cat > /tmp/migration_verify.txt << 'EOF' +数据库迁移验证报告 +================== +导出时间: $(date) + +文件信息: +- 表结构文件: $(ls -lh doc/database/backup/ccdi_structure.sql) +- 数据文件: $(ls -lh doc/database/backup/ccdi_data.sql) + +表数量: $(grep "CREATE TABLE" doc/database/backup/ccdi_structure.sql | wc -l) + +字符集检查: +$(grep "SET NAMES utf8mb4" doc/database/backup/ccdi_structure.sql) + +验证结果: 通过 +EOF +cat /tmp/migration_verify.txt +``` + +--- + +## 成功标准 + +完成后,应满足以下所有条件: + +1. ✅ 配置文件模板 `db_config.conf.template` 已创建 +2. ✅ `db_config.conf` 已添加到 `.gitignore` +3. ✅ 自动化脚本 `export_database.sh` 可执行 +4. ✅ 执行 `./export_database.sh export` 成功生成两个 SQL 文件 +5. ✅ `ccdi_structure.sql` 包含所有表结构和字符集声明 +6. ✅ `ccdi_data.sql` 包含所有数据和字符集声明 +7. ✅ SQL 文件无乱码,字符集正确 +8. ✅ 操作指南文档清晰完整 +9. ✅ 所有代码已提交到 Git + +## 执行建议 + +**建议执行顺序**: +1. 在测试环境完整执行一遍流程 +2. 验证测试环境导入的数据完整性 +3. 确认无问题后,在生产环境执行 +4. 验证生产环境数据完整性 +5. 应用程序连接测试 + +**时间估算**: +- Task 1-3: 15分钟(脚本开发) +- Task 4: 20-30分钟(导出执行,取决于数据量) +- Task 5: 10分钟(添加导入功能) +- Task 6-7: 15分钟(文档和验证) + +**总计**: 约 60-70 分钟 diff --git a/export_database.sh b/export_database.sh deleted file mode 100644 index c22a5e6..0000000 --- a/export_database.sh +++ /dev/null @@ -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 导入到目标环境" -} - -# 使用帮助 -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 导入到目标环境" -} - -# 主函数 -main() { - case "$1" in - export|"") - export_database - ;; - help|--help|-h) - show_usage - ;; - *) - log_error "未知命令: $1" - show_usage - exit 1 - ;; - esac -} - -# 执行主函数 -main "$@" diff --git a/import_database.sh b/import_database.sh deleted file mode 100644 index 10ea609..0000000 --- a/import_database.sh +++ /dev/null @@ -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 " - 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 " - 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 "$@"