Compare commits

..

5 Commits

Author SHA1 Message Date
ae3c041745 feat: 本地开发调整 2026-04-15 15:23:06 +08:00
880006db5a docs: 添加登录验证码重构设计方案
将滑块验证改为数字+字母图形验证码,保持后端校验流程兼容。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 15:22:47 +08:00
b2d0c032df docs: 补充 E2E 测试要求到迁移设计方案
- 新增第6节 E2E 测试要求
- 包含 15 个迁移前基准测试场景
- 明确迁移后回归测试路径替换规则
- 更新验收标准纳入 E2E 测试判定

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 00:31:31 +08:00
856d6a73de docs: 添加 txw-gxzx 迁移到 txw-mhzc 设计方案
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 00:24:18 +08:00
8423f61a3f feat: 搜索实现spec技术方案 2026-04-10 16:24:32 +08:00
24 changed files with 3530 additions and 77 deletions

View File

@ -3,7 +3,8 @@
"allow": [ "allow": [
"Bash(yarn install:*)", "Bash(yarn install:*)",
"WebFetch(domain:)", "WebFetch(domain:)",
"Bash(git checkout:*)" "Bash(git checkout:*)",
"Bash(netstat -ano)"
] ]
} }
} }

4
.gitignore vendored
View File

@ -8,6 +8,7 @@ prd
# Log file # Log file
*.log *.log
log log
logs
# BlueJ files # BlueJ files
*.ctxt *.ctxt
@ -52,3 +53,6 @@ ewm.png
*.ntvs* *.ntvs*
*.njsproj *.njsproj
*.sln *.sln
# 本地开发配置(包含敏感信息)
**/bootstrap-local.yml

View File

@ -32,8 +32,6 @@ yarn dev
| `txw-gxzx-web` | 个人工作台 | | `txw-gxzx-web` | 个人工作台 |
| `txw-kxtfwzx-web` | 科学碳体重中心 | | `txw-kxtfwzx-web` | 科学碳体重中心 |
| `txw-mhzc-web` | 碳门户主页 | | `txw-mhzc-web` | 碳门户主页 |
| `txw-tzzx-web` | 碳资讯 |
| `txw-ytzx-web` | 碳云学堂 |
| `txw-yygl-web` | 运营管理 | | `txw-yygl-web` | 运营管理 |
| `local-nodemodules` | 本地私有包ggzc-web 组件库) | | `local-nodemodules` | 本地私有包ggzc-web 组件库) |

426
docs/sql/init_database.sql Normal file
View File

@ -0,0 +1,426 @@
-- =============================================
-- 碳信网 数据库初始化脚本
-- 数据库: MySQL
-- =============================================
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- 1. txw-gxzx 模块(供需中心)
-- ----------------------------
-- 供需信息表
DROP TABLE IF EXISTS `txw_gxzx_gxxxb`;
CREATE TABLE `txw_gxzx_gxxxb` (
`gx_uuid` varchar(64) NOT NULL COMMENT '供需UUID',
`bt_1` varchar(255) DEFAULT NULL COMMENT '标题',
`fwlxjh` varchar(255) DEFAULT NULL COMMENT '服务类型',
`sshy` varchar(64) DEFAULT NULL COMMENT '所属行业代码',
`fwfw` varchar(500) DEFAULT NULL COMMENT '服务范围',
`fwnr` text DEFAULT NULL COMMENT '服务描述',
`kzwj` varchar(255) DEFAULT NULL COMMENT '扩展文件',
`lxr` varchar(100) DEFAULT NULL COMMENT '联系人',
`lxdh` varchar(50) DEFAULT NULL COMMENT '联系电话',
`email` varchar(100) DEFAULT NULL COMMENT '电子邮箱',
`bqjh` varchar(500) DEFAULT NULL COMMENT '标签合集',
`zt` varchar(20) DEFAULT NULL COMMENT '状态',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`qymc` varchar(200) DEFAULT NULL COMMENT '企业名称',
`nsrsbh` varchar(50) DEFAULT NULL COMMENT '纳税人识别号',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`xgruuid` varchar(64) DEFAULT NULL COMMENT '修改人UUID',
`lrruuid` varchar(64) DEFAULT NULL COMMENT '录入人UUID',
`sjzt` varchar(20) DEFAULT NULL COMMENT '上架状态',
`ywlx_dm` varchar(20) DEFAULT NULL COMMENT '业务类型代码',
`ysfw_dm_1` varchar(20) DEFAULT NULL COMMENT '预算范围代码',
`qwwcsj` datetime DEFAULT NULL COMMENT '期望完成时间',
`xqjjcd_dm` varchar(20) DEFAULT NULL COMMENT '需求紧急程度代码',
`gjjg` decimal(18,2) DEFAULT NULL COMMENT '供给价格',
`gjdw_dm` varchar(20) DEFAULT NULL COMMENT '供给单位代码',
PRIMARY KEY (`gx_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供需信息表';
-- 供需标签表
DROP TABLE IF EXISTS `txw_gxzx_gxbqb`;
CREATE TABLE `txw_gxzx_gxbqb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`gx_uuid` varchar(64) DEFAULT NULL COMMENT '供需UUID',
`bquuid` varchar(64) DEFAULT NULL COMMENT '标签UUID',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`yxbz` varchar(10) DEFAULT NULL COMMENT '有效标志',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供需标签表';
-- 供需收藏表
DROP TABLE IF EXISTS `txw_gxzx_gxscb`;
CREATE TABLE `txw_gxzx_gxscb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`gx_uuid` varchar(64) DEFAULT NULL COMMENT '供需UUID',
`yh_uuid` varchar(64) DEFAULT NULL COMMENT '用户UUID',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='供需收藏表';
-- 企业标签表
DROP TABLE IF EXISTS `txw_gxzx_qybqb`;
CREATE TABLE `txw_gxzx_qybqb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`bq_dm` varchar(20) DEFAULT NULL COMMENT '标签代码',
`yxbz` varchar(10) DEFAULT NULL COMMENT '有效标志',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业标签表';
-- 入驻申请记录表
DROP TABLE IF EXISTS `txw_gxzx_rzsqjlb`;
CREATE TABLE `txw_gxzx_rzsqjlb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`ywlx_dm` varchar(20) DEFAULT NULL COMMENT '业务类型代码',
`nsrsbh` varchar(50) DEFAULT NULL COMMENT '纳税人识别号',
`qymc` varchar(200) DEFAULT NULL COMMENT '企业名称',
`sjhm1` varchar(50) DEFAULT NULL COMMENT '手机号码',
`sqly` varchar(500) DEFAULT NULL COMMENT '申请理由',
`lrruuid` varchar(64) DEFAULT NULL COMMENT '录入人UUID',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`shrsfid` varchar(64) DEFAULT NULL COMMENT '审核人',
`shsj` datetime DEFAULT NULL COMMENT '审核时间',
`shyj_1` varchar(500) DEFAULT NULL COMMENT '审核意见',
`shjg_1` varchar(20) DEFAULT NULL COMMENT '审核结果',
`dlzh` varchar(100) DEFAULT NULL COMMENT '登录账号',
`zsxm_1` varchar(100) DEFAULT NULL COMMENT '真实姓名',
`yh_uuid` varchar(64) DEFAULT NULL COMMENT '用户UUID',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='入驻申请记录表';
-- 审核情况表
DROP TABLE IF EXISTS `txw_gxzx_shqkb`;
CREATE TABLE `txw_gxzx_shqkb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`ywlx_dm` varchar(20) DEFAULT NULL COMMENT '业务类型代码',
`glid` varchar(64) DEFAULT NULL COMMENT '关联ID',
`shjg_1` varchar(20) DEFAULT NULL COMMENT '审核结果',
`shyj_1` varchar(500) DEFAULT NULL COMMENT '审核意见',
`shrsfid` varchar(64) DEFAULT NULL COMMENT '审核人',
`shsj` datetime DEFAULT NULL COMMENT '审核时间',
`ywqd_dm` varchar(20) DEFAULT NULL COMMENT '业务渠道代码',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`sjcsdq` varchar(50) DEFAULT NULL COMMENT '数据产生地区',
`sjgsdq` varchar(50) DEFAULT NULL COMMENT '数据归属地区',
`xgrsfid` varchar(64) DEFAULT NULL COMMENT '修改人身份ID',
`lrrsfid` varchar(64) DEFAULT NULL COMMENT '录入人身份ID',
`sjtb_sj` datetime DEFAULT NULL COMMENT '数据同步时间',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='审核情况表';
-- 贷款保险申请信息表
DROP TABLE IF EXISTS `txw_gxzx_dkbxsqxx`;
CREATE TABLE `txw_gxzx_dkbxsqxx` (
`squuid` varchar(64) NOT NULL COMMENT '申请UUID',
`sshy_dm` varchar(20) DEFAULT NULL COMMENT '业务分类代码(xd=信贷,bx=保险)',
`cpuuid` varchar(64) DEFAULT NULL COMMENT '产品UUID',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`qymc` varchar(200) DEFAULT NULL COMMENT '企业名称',
`nsrsbh` varchar(50) DEFAULT NULL COMMENT '纳税人识别号',
`lxr` varchar(100) DEFAULT NULL COMMENT '联系人',
`lxdh` varchar(50) DEFAULT NULL COMMENT '联系电话',
`kxtsjzl` varchar(500) DEFAULT NULL COMMENT '可信碳数据资料',
`sqdk_je` varchar(100) DEFAULT NULL COMMENT '申请贷款金额',
`sqdkyt` varchar(200) DEFAULT NULL COMMENT '申请贷款用途',
`tbje` varchar(100) DEFAULT NULL COMMENT '投保金额',
`bxbzqx` varchar(100) DEFAULT NULL COMMENT '保险保障期限',
`flzl` varchar(500) DEFAULT NULL COMMENT '附列资料',
`zt` varchar(20) DEFAULT NULL COMMENT '状态',
`wjmc` varchar(255) DEFAULT NULL COMMENT '文件名称',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`lrruuid` varchar(64) DEFAULT NULL COMMENT '录入人UUID',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`xgruuid` varchar(64) DEFAULT NULL COMMENT '修改人UUID',
PRIMARY KEY (`squuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='贷款保险申请信息表';
-- 绿色金融产品信息表
DROP TABLE IF EXISTS `txw_gxzx_lsjrcpxx`;
CREATE TABLE `txw_gxzx_lsjrcpxx` (
`cpuuid` varchar(64) NOT NULL COMMENT '产品UUID',
`sshy_dm` varchar(20) DEFAULT NULL COMMENT '所属行业代码',
`ywlx_dm` varchar(20) DEFAULT NULL COMMENT '业务类型代码',
`cpmc` varchar(200) DEFAULT NULL COMMENT '产品名称',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`qymc` varchar(200) DEFAULT NULL COMMENT '企业名称',
`edfw` varchar(100) DEFAULT NULL COMMENT '额度范围',
`llfw` varchar(100) DEFAULT NULL COMMENT '利率范围',
`dkqxfw` varchar(100) DEFAULT NULL COMMENT '贷款期限范围',
`bzqxfw` varchar(100) DEFAULT NULL COMMENT '保障期限范围',
`bfjsfs` varchar(100) DEFAULT NULL COMMENT '保费计算方式',
`fwcpms` text DEFAULT NULL COMMENT '服务产品描述',
`fprq` datetime DEFAULT NULL COMMENT '发布日期',
`zt` varchar(20) DEFAULT NULL COMMENT '状态',
`sjzt` varchar(20) DEFAULT NULL COMMENT '上架状态',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`lrruuid` varchar(64) DEFAULT NULL COMMENT '录入人UUID',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`xgruuid` varchar(64) DEFAULT NULL COMMENT '修改人UUID',
`yxlogo` varchar(500) DEFAULT NULL COMMENT '圆形Logo',
`carbon_type` int(11) DEFAULT NULL COMMENT '碳类型',
PRIMARY KEY (`cpuuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='绿色金融产品信息表';
-- 绿色交易资产信息表
DROP TABLE IF EXISTS `txw_gxzx_lsjy_zcxx`;
CREATE TABLE `txw_gxzx_lsjy_zcxx` (
`zcid` varchar(64) NOT NULL COMMENT '资产ID',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`qymc` varchar(200) DEFAULT NULL COMMENT '企业名称',
`zcmc` varchar(200) DEFAULT NULL COMMENT '资产名称',
`zclxdm` varchar(20) DEFAULT NULL COMMENT '资产类型代码',
`zcxq1` text DEFAULT NULL COMMENT '资产详情',
`zcsl` varchar(50) DEFAULT NULL COMMENT '资产数量',
`zcsysl` varchar(50) DEFAULT NULL COMMENT '资产剩余数量',
`dj_str` varchar(100) DEFAULT NULL COMMENT '单价(字符型)',
`dj_3` decimal(18,4) DEFAULT NULL COMMENT '单价',
`zcbh` varchar(64) DEFAULT NULL COMMENT '资产编号',
`lxr` varchar(100) DEFAULT NULL COMMENT '联系人',
`lxdh` varchar(50) DEFAULT NULL COMMENT '联系电话',
`fbrq` datetime DEFAULT NULL COMMENT '发布日期',
`yxqz` datetime DEFAULT NULL COMMENT '有效期止',
`zt` varchar(20) DEFAULT NULL COMMENT '状态',
`sjzt` varchar(20) DEFAULT NULL COMMENT '上架状态',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`lrruuid` varchar(64) DEFAULT NULL COMMENT '录入人UUID',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`xgruuid` varchar(64) DEFAULT NULL COMMENT '修改人UUID',
PRIMARY KEY (`zcid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='绿色交易资产信息表';
-- ----------------------------
-- 2. txw-mhzc 模块(门户站场)
-- ----------------------------
-- 用户信息表
DROP TABLE IF EXISTS `txw_mhzc_yhxxb`;
CREATE TABLE `txw_mhzc_yhxxb` (
`yh_uuid` varchar(64) NOT NULL COMMENT '用户UUID',
`did` varchar(64) DEFAULT NULL COMMENT '部门ID',
`dlzh` varchar(100) DEFAULT NULL COMMENT '登录账号',
`dlmm` varchar(255) DEFAULT NULL COMMENT '登录密码',
`zsxm_1` varchar(100) DEFAULT NULL COMMENT '真实姓名',
`sjhm_1` varchar(50) DEFAULT NULL COMMENT '手机号码',
`yxdz` varchar(100) DEFAULT NULL COMMENT '邮箱地址',
`txdzurl` varchar(500) DEFAULT NULL COMMENT '头像地址URL',
`sdbz` varchar(10) DEFAULT NULL COMMENT '锁定标志(Y为锁定)',
`sdyy` varchar(255) DEFAULT NULL COMMENT '锁定原因',
`sdsj_1` datetime DEFAULT NULL COMMENT '锁定时间',
`sdryid` varchar(64) DEFAULT NULL COMMENT '锁定人员ID',
`yxbz` varchar(10) DEFAULT NULL COMMENT '有效标志',
`ywqd_dm` varchar(20) DEFAULT NULL COMMENT '业务渠道代码',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`sjcsdq` varchar(50) DEFAULT NULL COMMENT '数据产生地区',
`sjgsdq` varchar(50) DEFAULT NULL COMMENT '数据归属地区',
`xgrsfid` varchar(64) DEFAULT NULL COMMENT '修改人身份ID',
`lrrsfid` varchar(64) DEFAULT NULL COMMENT '录入人身份ID',
`sjtb_sj` datetime DEFAULT NULL COMMENT '数据同步时间',
`sfzjlx` varchar(20) DEFAULT NULL COMMENT '身份证件类型',
`sfzjhm` varchar(50) DEFAULT NULL COMMENT '身份证件号码',
`scdljguuid` varchar(64) DEFAULT NULL COMMENT '上次登录机构UUID',
PRIMARY KEY (`yh_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
-- 后台用户信息表
DROP TABLE IF EXISTS `txw_mhzc_htyhxxb`;
CREATE TABLE `txw_mhzc_htyhxxb` (
`yh_uuid` varchar(64) NOT NULL COMMENT '用户UUID',
`dlzh` varchar(100) DEFAULT NULL COMMENT '登录账号',
`dlmm` varchar(255) DEFAULT NULL COMMENT '登录密码',
`zsxm_1` varchar(100) DEFAULT NULL COMMENT '真实姓名',
`sjhm_1` varchar(50) DEFAULT NULL COMMENT '手机号码',
`yxdz` varchar(100) DEFAULT NULL COMMENT '邮箱地址',
`txdzurl` varchar(500) DEFAULT NULL COMMENT '头像地址URL',
`sdbz` varchar(10) DEFAULT NULL COMMENT '锁定标志',
`sdyy` varchar(255) DEFAULT NULL COMMENT '锁定原因',
`sdsj_1` datetime DEFAULT NULL COMMENT '锁定时间',
`sdryid` varchar(64) DEFAULT NULL COMMENT '锁定人员ID',
`ywqd_dm` varchar(20) DEFAULT NULL COMMENT '业务渠道代码',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`sjcsdq` varchar(50) DEFAULT NULL COMMENT '数据产生地区',
`sjgsdq` varchar(50) DEFAULT NULL COMMENT '数据归属地区',
`xgrsfid` varchar(64) DEFAULT NULL COMMENT '修改人身份ID',
`lrrsfid` varchar(64) DEFAULT NULL COMMENT '录入人身份ID',
`sjtb_sj` datetime DEFAULT NULL COMMENT '数据同步时间',
`yxbz` varchar(10) DEFAULT NULL COMMENT '有效标志',
PRIMARY KEY (`yh_uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='后台用户信息表';
-- 企业信息表
DROP TABLE IF EXISTS `txw_mhzc_qyxxb`;
CREATE TABLE `txw_mhzc_qyxxb` (
`qyuuid` varchar(64) NOT NULL COMMENT '企业UUID',
`qymc` varchar(200) DEFAULT NULL COMMENT '企业名称',
`nsrsbh` varchar(50) DEFAULT NULL COMMENT '纳税人识别号',
`gxdtrzbz` varchar(10) DEFAULT NULL COMMENT '供需大厅入驻标志',
`yxbz` varchar(10) DEFAULT NULL COMMENT '有效标志',
`ywqd_dm` varchar(20) DEFAULT NULL COMMENT '业务渠道代码',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`sjcsdq` varchar(50) DEFAULT NULL COMMENT '数据产生地区',
`sjgsdq` varchar(50) DEFAULT NULL COMMENT '数据归属地区',
`xgrsfid` varchar(64) DEFAULT NULL COMMENT '修改人身份ID',
`lrrsfid` varchar(64) DEFAULT NULL COMMENT '录入人身份ID',
`sjtb_sj` datetime DEFAULT NULL COMMENT '数据同步时间',
PRIMARY KEY (`qyuuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业信息表';
-- 企业认证申请记录表
DROP TABLE IF EXISTS `txw_mhzc_qyrzsqjlb`;
CREATE TABLE `txw_mhzc_qyrzsqjlb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`qymc` varchar(200) DEFAULT NULL COMMENT '企业名称',
`nsrsbh` varchar(50) DEFAULT NULL COMMENT '纳税人识别号',
`sqsm` varchar(500) DEFAULT NULL COMMENT '申请说明',
`lrruuid` varchar(64) DEFAULT NULL COMMENT '录入人UUID',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`shrsfid` varchar(64) DEFAULT NULL COMMENT '审核人',
`shjg_1` varchar(20) DEFAULT NULL COMMENT '审核结果',
`shyj_1` varchar(500) DEFAULT NULL COMMENT '审核意见',
`shsj` datetime DEFAULT NULL COMMENT '审核时间',
`sjhm_1` varchar(50) DEFAULT NULL COMMENT '手机号码',
`dlzh` varchar(100) DEFAULT NULL COMMENT '登录账号',
`zsxm_1` varchar(100) DEFAULT NULL COMMENT '真实姓名',
`yh_uuid` varchar(64) DEFAULT NULL COMMENT '用户UUID',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业认证申请记录表';
-- 用户企业关系表
DROP TABLE IF EXISTS `txw_mhzc_yhqygxb`;
CREATE TABLE `txw_mhzc_yhqygxb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`yh_uuid` varchar(64) DEFAULT NULL COMMENT '用户UUID',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户企业关系表';
-- 咨询信息表
DROP TABLE IF EXISTS `txw_mhzc_zxxxb`;
CREATE TABLE `txw_mhzc_zxxxb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`bt_1` varchar(255) DEFAULT NULL COMMENT '标题',
`zx_nr` text DEFAULT NULL COMMENT '内容',
`fbsj` datetime DEFAULT NULL COMMENT '发布时间',
`zx_lx` varchar(50) DEFAULT NULL COMMENT '资讯类型',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='咨询信息表';
-- 广告栏表
DROP TABLE IF EXISTS `txw_mhzc_gglb`;
CREATE TABLE `txw_mhzc_gglb` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`bt_1` varchar(255) DEFAULT NULL COMMENT '标题',
`gg_nr` text DEFAULT NULL COMMENT '广告内容',
`tpid` varchar(64) DEFAULT NULL COMMENT '图片ID',
`tzdz` varchar(500) DEFAULT NULL COMMENT '跳转地址',
`xh` bigint(20) DEFAULT NULL COMMENT '序号',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
`lrruuid` varchar(64) DEFAULT NULL COMMENT '录入人UUID',
`xgruuid` varchar(64) DEFAULT NULL COMMENT '修改人UUID',
`yxbz` varchar(10) DEFAULT NULL COMMENT '有效标志',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='广告栏表';
-- ----------------------------
-- 3. txw-sso 模块(单点登录)
-- ----------------------------
-- OAuth2客户端表
DROP TABLE IF EXISTS `txw_sso_client`;
CREATE TABLE `txw_sso_client` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`clientid` varchar(100) DEFAULT NULL COMMENT '客户端ID',
`sqmy` varchar(255) DEFAULT NULL COMMENT '授权密钥',
`yxbz` varchar(10) DEFAULT NULL COMMENT '有效标志',
`fwlpyxq` varchar(50) DEFAULT NULL COMMENT '访问令牌有效期',
`sxlpyxq` varchar(50) DEFAULT NULL COMMENT '刷新令牌有效期',
`cdxdz` varchar(500) DEFAULT NULL COMMENT '重定向地址',
`sqnr` varchar(500) DEFAULT NULL COMMENT '授权内容',
`sm_1` varchar(255) DEFAULT NULL COMMENT '说明',
`dcdz` varchar(500) DEFAULT NULL COMMENT '导出地址',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OAuth2客户端表';
-- OAuth2授权码表
DROP TABLE IF EXISTS `txw_sso_code`;
CREATE TABLE `txw_sso_code` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`yh_uuid` varchar(64) DEFAULT NULL COMMENT '用户UUID',
`sqm` varchar(100) DEFAULT NULL COMMENT '授权码',
`clientid` varchar(100) DEFAULT NULL COMMENT '客户端ID',
`sqnr` varchar(500) DEFAULT NULL COMMENT '授权内容',
`gqsj` datetime DEFAULT NULL COMMENT '过期时间',
`cdxdz` varchar(500) DEFAULT NULL COMMENT '重定向地址',
`rzzt_1` varchar(20) DEFAULT NULL COMMENT '认证状态',
`access_token` varchar(255) DEFAULT NULL COMMENT '访问令牌',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OAuth2授权码表';
-- OAuth2访问令牌表
DROP TABLE IF EXISTS `txw_sso_access_token`;
CREATE TABLE `txw_sso_access_token` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`yh_uuid` varchar(64) DEFAULT NULL COMMENT '用户UUID',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`access_token` varchar(255) DEFAULT NULL COMMENT '访问令牌',
`refresh_token` varchar(255) DEFAULT NULL COMMENT '刷新令牌',
`clientid` varchar(100) DEFAULT NULL COMMENT '客户端ID',
`sqnr` varchar(500) DEFAULT NULL COMMENT '授权内容',
`gqsj` datetime DEFAULT NULL COMMENT '过期时间',
`gllp` varchar(64) DEFAULT NULL COMMENT '关联令牌',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OAuth2访问令牌表';
-- OAuth2刷新令牌表
DROP TABLE IF EXISTS `txw_sso_refresh_token`;
CREATE TABLE `txw_sso_refresh_token` (
`uuid` varchar(64) NOT NULL COMMENT 'UUID',
`yh_uuid` varchar(64) DEFAULT NULL COMMENT '用户UUID',
`qyuuid` varchar(64) DEFAULT NULL COMMENT '企业UUID',
`refresh_token` varchar(255) DEFAULT NULL COMMENT '刷新令牌',
`clientid` varchar(100) DEFAULT NULL COMMENT '客户端ID',
`sqnr` varchar(500) DEFAULT NULL COMMENT '授权内容',
`gqsj` datetime DEFAULT NULL COMMENT '过期时间',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OAuth2刷新令牌表';
-- OAuth2授权批准表
DROP TABLE IF EXISTS `system_oauth2_approve`;
CREATE TABLE `system_oauth2_approve` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`user_id` bigint(20) DEFAULT NULL COMMENT '用户编号',
`user_type` int(11) DEFAULT NULL COMMENT '用户类型',
`client_id` varchar(100) DEFAULT NULL COMMENT '客户端编号',
`scope` varchar(255) DEFAULT NULL COMMENT '授权范围',
`approved` tinyint(1) DEFAULT NULL COMMENT '是否接受(true接受,false拒绝)',
`expires_time` datetime DEFAULT NULL COMMENT '过期时间',
`lrrq` datetime DEFAULT NULL COMMENT '录入日期',
`xgrq` datetime DEFAULT NULL COMMENT '修改日期',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OAuth2授权批准表';
SET FOREIGN_KEY_CHECKS = 1;

View File

@ -0,0 +1,46 @@
spring:
cloud:
gateway:
x-forwarded:
prefix-enabled: false # 避免 Swagger 重复带上额外的 /ckts-api/system 前缀
routes:
- id: txw-mhzc
uri: grayLb://txw-mhzc
predicates:
- Path=/mhzc/**
- id: txw-sso
uri: grayLb://txw-sso
predicates:
- Path=/sso/**
- id: txw-gxzx
uri: grayLb://txw-gxzx
predicates:
- Path=/gxzx/**
- id: txw-yygl
uri: grayLb://txw-yygl
predicates:
- Path=/yygl/**
css:
gateway:
whitelist:
urls:
- /sso/verify/get
- /sso/auth/login
- /sso/admin/auth/login
- /sso/admin/auth/logout
- /sso/auth/logout
- /sso/auth/refresh-token
- /sso/auth/sendMsg
- /sso/auth/loginBySMS
- /api/**
- /mhzc/user/register
- /mhzc/sy/sjkb
- /mhzc/sy/hzhb
- /sso/userinfo/get
- /sso/oauth2/token
- /mhzc/sy/**
- /sso/did/pub/**
- /sso/auth/didBindPhone
api:
checkAccessToken: http://txw-sso/sso/oauth2/token/check

View File

@ -0,0 +1,80 @@
--- #################### sentinel相关配置 ####################
spring:
cloud:
sentinel:
transport:
dashboard: 10.23.10.75:8090 #控制台地址
http-method-specify: true #开启请求方式前缀
feign:
sentinel:
enabled: true
--- #################### xxl-job相关配置 ####################
xxl:
job:
admin:
addresses: http://10.23.10.89:30081/xxl-job-admin
executor:
appname: ${spring.application.name} # 执行器 AppName
logpath: ${user.dir}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
access-token: 9!75%Sw#QydXxlJobToken
spring:
# 数据源配置项
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: true
stat-view-servlet:
enabled: true
allow: # 设置白名单,不填则允许所有访问
url-pattern: /druid/*
login-username: # 控制台管理用户名和密码
login-password:
filter:
stat:
enabled: true
log-slow-sql: true # 慢 SQL 记录
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
primary: master
datasource:
master:
name: txw_gxzx
url: jdbc:mysql://10.23.8.38:3306/txw_gxzx?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
username: znsb_yy
password: zNdd_yY0322
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 10.23.10.91
port: 6379
password: 9!1%Sw#QydRedis0322
database: 9
css:
filemanager:
config:
type: minio
url: http://10.23.10.91:9000
bucket: qyd-ggzc
accessKey: qyddev
accessSecret: 9!1%Sw#QydMinioDev
enabled: true

View File

@ -0,0 +1,82 @@
--- #################### sentinel相关配置 ####################
spring:
cloud:
sentinel:
transport:
dashboard: 10.23.10.75:8090 #控制台地址
http-method-specify: true #开启请求方式前缀
feign:
sentinel:
enabled: true
--- #################### xxl-job相关配置 ####################
xxl:
job:
admin:
addresses: http://10.23.10.89:30081/xxl-job-admin
executor:
appname: ${spring.application.name} # 执行器 AppName
logpath: ${user.dir}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
access-token: 9!75%Sw#QydXxlJobToken
spring:
# 数据源配置项
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: true
stat-view-servlet:
enabled: true
allow: # 设置白名单,不填则允许所有访问
url-pattern: /druid/*
login-username: # 控制台管理用户名和密码
login-password:
filter:
stat:
enabled: true
log-slow-sql: true # 慢 SQL 记录
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
primary: master
datasource:
master:
name: txw_mhzc
url: jdbc:mysql://10.23.8.38:3306/txw_mhzc?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例
username: znsb_yy
password: zNdd_yY0322
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 10.23.10.91
port: 6379
password: 9!1%Sw#QydRedis0322
database: 9
css:
filemanager:
config:
type: minio
url: http://10.23.10.91:9000
bucket: qyd-dhls
accessKey: qyddev
accessSecret: 9!1%Sw#QydMinioDev
enabled: true
mhzc:
registerSmsCheck: false

View File

@ -0,0 +1,83 @@
--- #################### sentinel相关配置 ####################
spring:
cloud:
sentinel:
transport:
dashboard: 10.23.10.91:8090 #控制台地址
http-method-specify: true #开启请求方式前缀
feign:
sentinel:
enabled: true
--- #################### xxl-job相关配置 ####################
xxl:
job:
admin:
addresses: http://10.23.10.89:30080/xxl-job-admin
executor:
appname: ${spring.application.name} # 执行器 AppName
logpath: ${user.dir}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
access-token: 9!1%Sw#QydXxlJobToken
spring:
# 数据源配置项
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: true
stat-view-servlet:
enabled: true
allow: # 设置白名单,不填则允许所有访问
url-pattern: /druid/*
login-username: # 控制台管理用户名和密码
login-password:
filter:
stat:
enabled: true
log-slow-sql: true # 慢 SQL 记录
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
primary: master
datasource:
master:
name: txw_sso
url: jdbc:mysql://10.23.8.38:3306/txw_sso?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true
username: znsb_yy
password: zNdd_yY0322
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 10.23.10.91
port: 6379
password: 9!1%Sw#QydRedis0322
database: 9
css:
txw:
sms:
app: txw
host: http://127.0.0.1:9302/mhzc
key: testkey
template: 您的登录验证码 %s 请在3分钟内完成登录
sso:
loginCaptcha: true

View File

@ -0,0 +1,68 @@
spring:
# 数据源配置项
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: true
stat-view-servlet:
enabled: true
allow: # 设置白名单,不填则允许所有访问
url-pattern: /druid/*
login-username: # 控制台管理用户名和密码
login-password:
filter:
stat:
enabled: true
log-slow-sql: true # 慢 SQL 记录
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 1 # 初始连接数
min-idle: 1 # 最小连接池数量
max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
primary: master
datasource:
master:
url: jdbc:mysql://10.23.8.38:3306/txw_csdm?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true
username: znsb_yy
password: zNdd_yY0322
xxzx:
url: jdbc:mysql://10.23.8.38:3306/txw_yygl?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true
username: znsb_yy
password: zNdd_yY0322
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
redis:
host: 10.23.10.91
port: 6379
password: 9!1%Sw#QydRedis0322
database: 9
css:
job:
enable: true
admin:
#addresses: http://10.23.20.9:30080/xxl-job-admin
addresses: http://10.23.10.89:30080/xxl-job-admin
executor:
appname: ${spring.application.name} # 执行器 AppName
logpath: ${user.dir}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
address: http://yygl.qydtxw.tax.cn/yygl
access-token: 9!1%Sw#QydXxlJobToken
cache:
dsName: txw-csdm

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,359 @@
# 全站搜索功能设计文档
## 1. 概述
### 1.1 功能说明
为碳信网txw-mhzc-web提供全站统一的搜索功能支持搜索全站内容碳证中心、服务中心、行业专题等提供搜索建议、搜索历史、热门搜索等辅助功能。
### 1.2 项目背景
- 碳信网各子系统(供需大厅、绿色金融、绿色交易等)目前分散独立
- 用户需要在全站范围内快速查找内容
- 需要为后续子系统迁移到 txw-mhzc 做准备
### 1.3 设计原则
- 前端聚合在 txw-mhzc-web
- 后端聚合在 txw-mhzc
- 搜索服务架构先搭好,后期快速对接迁移后的子系统
---
## 2. 前端设计
### 2.1 路由
| 路径 | 组件 | 说明 |
|------|------|------|
| `/search` | SearchView | 搜索结果页 |
### 2.2 页面结构
```
┌─────────────────────────────────────────────────────────┐
│ Header (复用现有) - Logo + 网站名 + 登录/注册 + 工作台 │
├─────────────────────────────────────────────────────────┤
│ 搜索区域 (灰色背景 #F5F5F5) │
│ [分类 ▼] [搜索输入框........................] [搜索] │
│ 热门搜索:江苏电厂配额 | 林业碳汇开发 | CBAM 报告... │
├─────────────────────────────────────────────────────────┤
│ [全部] [碳证中心] [服务中心] ← 分类Tab (左侧) │
│ ───────────── (绿色下划线指示选中) │
├─────────────────────────────────────────────────────────┤
│ 搜索结果列表 (单列) │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [行业专题] 构建新型碳排放数据治理框架 │ │
│ │ 2025年5月29日 核算技术双轨并行发展... │ │
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ [碳减排服务] 碳排放... │ │
│ │ 2025年5月29日 ... │ │
│ └─────────────────────────────────────────────────┘ │
│ ... │
├─────────────────────────────────────────────────────────┤
│ [1] [2] [3] [4] [5] [下一页] ← 分页 │
├─────────────────────────────────────────────────────────┤
│ 版权信息等 │
└─────────────────────────────────────────────────────────┘
```
**说明:**
- 搜索区域包含:分类下拉、搜索输入框、搜索按钮、热门搜索词
- 搜索历史在搜索区域下方显示(横向排列,右侧有"清除全部"
- 分类Tab在分隔线下方左对齐
- 结果列表单列展示,包含分类标签、标题、日期、摘要
- 无左侧边栏
### 2.3 组件列表
| 组件 | 说明 |
|------|------|
| SearchView | 搜索结果页主组件(外层使用现有 Nav 组件) |
| SearchArea | 搜索区域(输入框+下拉+按钮+热门词) |
| SearchSuggestion | 搜索建议下拉 |
| SearchHistoryBar | 搜索历史横条(历史词+清除按钮) |
| SearchCategoryTabs | 分类Tab全部/碳证中心/服务中心) |
| SearchResultList | 结果列表 |
| SearchResultItem | 结果项 |
| SearchPagination | 分页组件(复用 TDesign |
| SearchEmpty | 空状态 |
| SearchLoading | 加载状态 |
> **Header/Nav 复用项目现有 `Nav` 组件**,搜索页只需开发 SearchArea 及以下部分
### 2.4 分类筛选
| 分类 | categoryType | 说明 |
|------|--------------|------|
| 全部 | all | 所有内容 |
| 碳证中心 | carbon_cert | 碳证相关 |
| 服务中心 | service | 服务市场、金融市场、需求市场、数据市场 |
| 行业专题 | news | 新闻资讯 |
### 2.5 搜索建议
触发方式:用户输入时,延迟 300ms 后请求(前端防抖)
限流:接口级别限流,相同关键词 1 分钟内不重复请求
数据来源:
- 用户输入匹配(模糊匹配标题/内容)
- 历史搜索词(取当前用户最近 10 条)
- 运营配置的热门词
---
## 3. 后端设计
### 3.1 技术栈
- Spring Boot
- MyBatis Plus
- Redis缓存搜索历史、热门词
### 3.2 接口设计
#### 3.2.1 搜索
```
GET /search?keyword=碳排放&categoryType=all&page=1&pageSize=10
参数说明:
- keyword: 搜索关键词(必填,最大 50 字符,需 XSS 过滤)
- categoryType: 分类筛选all, carbon_cert, service, news
- page: 页码(默认 1
- pageSize: 每页条数(默认 10最大 50
Response:
{
"code": 0,
"msg": "",
"data": {
"total": 18,
"categoryCount": {
"all": 18,
"carbon_cert": 2,
"service": 16,
"news": 0
},
"list": [
{
"id": "xxx",
"title": "构建新型<em>碳排放</em>数据治理框架",
"summary": "核算技术双轨并行发展...",
"category": "行业专题",
"categoryType": "news",
"source": "碳证中心",
"sourceType": "carbon_cert",
"publishTime": "2025-05-29",
"url": "/gxzx/detail/xxx"
}
]
}
}
```
#### 3.2.2 搜索建议
```
GET /search/suggest?keyword=碳排
参数说明:
- keyword: 搜索关键词(必填,最大 50 字符)
Response:
{
"code": 0,
"msg": "",
"data": {
"suggestions": [
"碳排放",
"碳排放权",
"碳排放核算"
]
}
}
```
#### 3.2.3 热门搜索
```
GET /search/hot
Response:
{
"code": 0,
"data": [
"江苏电厂配额",
"林业碳汇开发",
"CBAM 报告",
"零碳展会"
]
}
```
#### 3.2.4 搜索历史
```
GET /search/history
Response:
{
"code": 0,
"data": [
"碳排放",
"林业碳汇",
"CBAM"
]
}
```
#### 3.2.5 清除搜索历史
```
DELETE /search/history
Response:
{
"code": 0,
"msg": ""
}
```
### 3.3 数据模型
#### 3.3.1 搜索结果SearchResultVO
| 字段 | 类型 | 说明 |
|------|------|------|
| id | String | 内容ID |
| title | String | 标题(关键词高亮,使用 `<em>` 标签) |
| summary | String | 摘要(截取前 200 字符) |
| thumbnail | String | 缩略图URL可为空 |
| category | String | 分类标签(展示用,如"行业专题" |
| categoryType | String | 分类类型(筛选用,如"news" |
| source | String | 来源名称 |
| sourceType | String | 来源类型 |
| publishTime | String | 发布时间 |
| url | String | 跳转链接 |
#### 3.3.2 热门搜索配置HotSearchConfig
| 字段 | 类型 | 说明 |
|------|------|------|
| id | Long | 主键 |
| keyword | String | 关键词 |
| sort | Integer | 排序 |
| status | Integer | 状态0禁用1启用 |
| startTime | LocalDateTime | 生效开始时间(可选) |
| endTime | LocalDateTime | 生效结束时间(可选) |
> 注:支持临时活动配置热门词,通过生效时间控制
#### 3.3.3 搜索历史SearchHistory
| 字段 | 类型 | 说明 |
|------|------|------|
| id | Long | 主键 |
| userId | String | 用户ID登录用户 |
| deviceId | String | 设备ID游客用于关联未登录用户 |
| keyword | String | 搜索词 |
| searchTime | LocalDateTime | 搜索时间 |
> 注:搜索历史最多存储 20 条,超出后删除最早的记录
### 3.4 搜索聚合服务
由于目前各子系统还没有迁移,搜索聚合服务采用以下策略:
**阶段一(当前)**
- 只搜索资讯中心 `/sy/zxxx` 的内容
- 数据直接存储在 txw-mhzc 中
**阶段二(子系统迁移后)**
- 各子系统迁移到 txw-mhzc 后
- SearchAggregatorService 并行调用各子系统的搜索方法
- 聚合去重后返回
---
## 4. 文件结构
### 4.1 前端txw-mhzc-web
```
txw-mhzc-web/src/pages/index/
├── views/
│ └── search/
│ └── index.vue # 搜索结果页
├── components/
│ └── search/
│ ├── SearchArea.vue # 搜索区域
│ ├── SearchSuggestion.vue # 搜索建议下拉
│ ├── SearchHistoryBar.vue # 搜索历史横条
│ ├── SearchCategoryTabs.vue # 分类Tab
│ ├── SearchResultList.vue
│ └── SearchResultItem.vue
└── api/
└── search.js # 搜索接口
```
### 4.2 后端txw-mhzc
```
txw-mhzc/txw-mhzc-service-biz/src/main/java/com/css/txw/mhzc/
├── controller/
│ └── SearchController.java
├── service/
│ ├── SearchService.java
│ └── impl/
│ └── SearchServiceImpl.java
├── mapper/
│ └── SearchMapper.java
└── pojo/
├── dto/
│ └── SearchDTO.java
└── vo/
├── SearchReqVO.java
├── SearchResultVO.java
├── HotSearchConfig.java
└── SearchHistory.java
```
---
## 5. 开发计划
### 5.1 第一阶段(预计 3 天)
| 任务 | 优先级 | 预估工时 |
|------|--------|----------|
| 前端:搜索页面基础结构 | P0 | 0.5d |
| 前端:搜索框组件 + 搜索建议 | P0 | 0.5d |
| 前端:左侧边栏(历史+热门+分类) | P0 | 0.5d |
| 前端:结果列表展示 | P0 | 0.5d |
| 前端:分类筛选 + 分页 | P0 | 0.5d |
| 后端:搜索接口(资讯中心)| P0 | 1d |
| 后端:搜索建议接口 | P1 | 0.5d |
| 后端:热门搜索接口 | P1 | 0.5d |
| 后端:搜索历史接口 | P1 | 0.5d |
| **前后端联调 + 测试** | P0 | 1d |
### 5.2 第二阶段(子系统迁移后)
- [ ] 后端:聚合其他子系统搜索
- [ ] 搜索结果去重优化
- [ ] 搜索权重配置
### 5.3 数据埋点(可后续迭代)
- 搜索关键词上报
- 搜索结果点击上报
- 热门词曝光点击统计
---
## 6. 待确认
1. ~~ 搜索结果高亮标签使用 `<em>` 还是其他?~~ → **使用 `<em>`**
2. ~~每个分类的数量是否需要实时从后端获取?~~ → **随搜索结果一起返回,在 data.categoryCount 中**
3. 搜索结果点击后跳转到原详情页,详情页是否需要开发? → **由各子系统详情页处理,搜索只提供 URL**

View File

@ -0,0 +1,401 @@
# txw-gxzx 功能迁移到 txw-mhzc 设计方案
## 1. 背景与目标
### 1.1 背景
碳信网项目目前存在两个独立的后端服务:
- **txw-mhzc门户站场**:用户/企业管理、资讯、公共列表、企业入驻
- **txw-gxzx供需中心**:绿色金融、绿色交易、企业入驻、供需大厅
两个服务功能上有重叠,且 gxzx 的企业入驻实际通过 Feign 调用 mhzc 完成。长期维护两套独立服务增加复杂度。
### 1.2 目标
**txw-gxzx 全部功能迁移到 txw-mhzc**形成统一的后端服务。txw-gxzx 模块废弃gxzx-web 前端路由配置改为调用 mhzc 后端接口。
---
## 2. 现状分析
### 2.1 txw-gxzx 模块结构
| 模块 | Controller | API数量 | 业务描述 |
|------|-----------|---------|---------|
| 绿色金融 | `LsjrController` | 14 | 银行/保险机构查询、信贷/保险产品管理、贷款/投保申请 |
| 绿色交易 | `LsjyController` | 8 | 资产类型管理、资产信息管理、审批流程 |
| 企业入驻 | `QyRzController` | 4 | 企业入驻申请、审批、列表查询 |
| 供需大厅 | `GxdtController` | 10 | 供需信息发布、收藏、标签管理 |
**总计36 个 API 接口**
### 2.2 数据库表9张
| 表名 | 说明 | 记录类型 |
|------|------|---------|
| `txw_gxzx_gxxxb` | 供需信息表 | 供需大厅-供需发布 |
| `txw_gxzx_gxbqb` | 供需标签表 | 供需大厅-标签关联 |
| `txw_gxzx_gxscb` | 供需收藏表 | 供需大厅-收藏 |
| `txw_gxzx_qybqb` | 企业标签表 | 供需大厅-企业标签 |
| `txw_gxzx_rzsqjlb` | 入驻申请记录表 | 企业入驻 |
| `txw_gxzx_shqkb` | 审核情况表 | 通用审批流程 |
| `txw_gxzx_dkbxsqxx` | 贷款/保险申请信息表 | 绿色金融-申请 |
| `txw_gxzx_lsjrcpxx` | 绿色金融产品信息表 | 绿色金融-产品 |
| `txw_gxzx_lsjy_zcxx` | 绿色交易资产信息表 | 绿色交易-资产 |
### 2.3 关键依赖关系
```
txw-gxzx 外部依赖:
├── IMhzcApi (Feign Client) → txw-mhzc
│ └── 仅用于 qyrz 企业入驻gxzx实际是申请流程层
├── XxzxApi (消息中心) → 外部框架
│ └── 审批通过/拒绝后发送系统消息
└── txw-gxzx-service-api
└── 对外暴露的 Feign 接口(但接口体为空,无实际消费者)
```
### 2.4 Gateway 路由配置
```yaml
# txw-gateway bootstrap.yml (Nacos)
- id: txw-gxzx
uri: grayLb://txw-gxzx
predicates:
- Path=/gxzx/**
- id: txw-mhzc
uri: grayLb://txw-mhzc
predicates:
- Path=/mhzc/**
```
---
## 3. 迁移方案
### 3.1 数据库迁移
#### 3.1.1 表合并策略
| gxzx 表 → mhzc | 合并方式 |
|----------------|---------|
| `txw_gxzx_rzsqjlb``txw_mhzc_qyrzsqjlb` | **合并**:字段高度兼容,差异仅 `sqly`(gxzx) vs `sqsm`(mhzc)、多 `ywlx_dm` 字段 |
| 其余 8 张表 | **迁移**:直接迁移到 mhzc 库,表名保持 `txw_gxzx_*` 前缀(避免与其他表名冲突) |
#### 3.1.2 字段映射rzsqjlb 合并)
| gxzx 字段 | mhzc 字段 | 处理方式 |
|-----------|----------|---------|
| `uuid` | `uuid` | 直接映射 |
| `ywlx_dm` | 无 | **废弃**gxzx 代码中硬编码为 "01",不做业务判断 |
| `nsrsbh` | `nsrsbh` | 直接映射 |
| `qymc` | `qymc` | 直接映射 |
| `sjhm1` | `sjhm_1` | 直接映射 |
| `sqly` | `sqsm` | 直接映射(含义相同) |
| `lrruuid` | `lrruuid` | 直接映射 |
| `lrrq` | `lrrq` | 直接映射 |
| `shrsfid` | `shrsfid` | 直接映射 |
| `shsj` | `shsj` | 直接映射 |
| `shyj_1` | `shyj_1` | 直接映射 |
| `shjg_1` | `shjg_1` | 直接映射 |
| `dlzh` | `dlzh` | 直接映射 |
| `zsxm_1` | `zsxm_1` | 直接映射 |
| `yh_uuid` | `yh_uuid` | 直接映射 |
#### 3.1.3 数据迁移脚本
```sql
-- 1. 将 gxzx_rzsqjlb 数据迁移到 mhzc_qyrzsqjlb
INSERT INTO txw_mhzc_qyrzsqjlb
(uuid, qymc, nsrsbh, sqsm, lrruuid, lrrq, shrsfid, shjg_1, shyj_1, shsj, sjhm_1, dlzh, zsxm_1, yh_uuid)
SELECT
uuid, qymc, nsrsbh, sqly, lrruuid, lrrq, shrsfid, shjg_1, shyj_1, shsj, sjhm1, dlzh, zsxm_1, yh_uuid
FROM txw_gxzx_rzsqjlb;
-- 2. 将其余 8 张 gxzx 表迁移到 mhzc 库(表名不变)
-- gxxxb, gxbqb, gxscb, qybqb, shqkb, dkbxsqxx, lsjrcpxx, lsjy_zcxx
-- 直接 RENAME TABLE 或 INSERT INTO ... SELECT
```
### 3.2 代码迁移
#### 3.2.1 API 层txw-mhzc-service-api
新增 4 个业务接口,补充 gxzx 的功能:
| 新增接口 | 包路径 | 说明 |
|---------|--------|------|
| `ILsjrApi` | `com.css.txw.mhzc.api` | 绿色金融 Feign 接口 |
| `ILsjyApi` | `com.css.txw.mhzc.api` | 绿色交易 Feign 接口 |
| `IQyRzApi` | `com.css.txw.mhzc.api` | 企业入驻 Feign 接口(补充 gxzx 部分) |
| `IGxdtApi` | `com.css.txw.mhzc.api` | 供需大厅 Feign 接口 |
**注意**`txw-gxzx-service-api` 中的 `IGxzxApi` 为空接口体,无实际方法,无需迁移。
#### 3.2.2 BIZ 层txw-mhzc-service-biz
迁移文件清单:
**Controller 层4个**
```
txw-gxzx-service-biz/controller/
├── LsjrController.java → txw-mhzc-service-biz/controller/LsjrController.java
├── LsjyController.java → txw-mhzc-service-biz/controller/LsjyController.java
├── QyRzController.java → txw-mhzc-service-biz/controller/QyRzController.java
└── GxdtController.java → txw-mhzc-service-biz/controller/GxdtController.java
```
**Service 层(需迁移+新建):**
```
txw-gxzx-service-biz/service/lsjr/* → txw-mhzc-service-biz/service/lsjr/*
txw-gxzx-service-biz/service/lsjy/* → txw-mhzc-service-biz/service/lsjy/*
txw-gxzx-service-biz/service/impl/* → txw-mhzc-service-biz/service/impl/*
(TxwGxzxGxbqbServiceImpl, TxwGxzxGxscbServiceImpl, TxwGxzxGxxxbServiceImpl,
TxwGxzxQybqbServiceImpl, TxwGxzxRzsqjlbServiceImpl, TxwGxzxShqkbServiceImpl)
```
**Mapper 层(需迁移+合并):**
```
txw-gxzx-service-biz/mapper/lsjr/* → txw-mhzc-service-biz/mapper/lsjr/*
txw-gxzx-service-biz/mapper/lsjy/* → txw-mhzc-service-biz/mapper/lsjy/*
txw-gxzx-service-biz/mapper/* → txw-mhzc-service-biz/mapper/*
(TxwGxzxGxbqbMapper, TxwGxzxGxscbMapper, TxwGxzxGxxxbMapper,
TxwGxzxQybqbMapper, TxwGxzxRzsqjlbMapper, TxwGxzxShqkbMapper,
GxzxDkbxsqxxMapper, GxzxLsjrcpxxMapper, GxzxLsjyZcxxMapper)
```
**DO/POJO/DTO/VO 层:**
- `pojo/domain/*``pojo/domain/` (保持)
- `pojo/dto/*``pojo/dto/` (保持)
- `pojo/vo/*``pojo/vo/` (保持)
- `pojo/lsjr/*``pojo/lsjr/` (保持)
- `pojo/lsjy/*``pojo/lsjy/` (保持)
**Configuration**
- `GxzxServiceConfiguration.java``MhzcServiceConfiguration.java` (合并 MapperScan 路径)
#### 3.2.3 关键代码改动
**1. Feign 调用改为内部服务调用**
原 gxzx 代码:
```java
// GxzxRzsqjlbServiceImpl.java
@Resource
private IMhzcApi iMhzcApi;
// 审批通过后调用 mhzc 入驻
CommonResult<String> qyrz = iMhzcApi.qyrz(reqDTO);
```
迁移后:直接注入 mhzc 本地 Service不走 Feign
```java
// 改为直接调用本地 TxwMhzcQyxxbService
@Resource
private TxwMhzcQyxxbService qyxxbService;
// 审批通过后
qyxxbService.qyrz(reqDTO);
```
**2. 企业入驻 Service 合并**
gxzx 的 `TxwGxzxRzsqjlbServiceImpl` 合并到 mhzc 的 `TxwMhzcQyrzsqjlbServiceImpl`
- gxzx 申请 → 直接使用 mhzc 的 qyrzsqjlb 表和 Service
- 删除 gxzx 中对 `IMhzcApi.qyrz()` 的 Feign 调用,改为本地 `qyxxbService.qyrz()`
- 审批消息发送xxzxApi保留
**3. MapperScan 配置合并**
原 gxzx 配置:
```java
@MapperScan("com.css.txw.gxzx.mapper")
```
迁移后合并到 mhzc
```java
@MapperScan({
"com.css.txw.mhzc.mapper",
"com.css.txw.gxzx.mapper" // 迁移后改为 mhzc 包下的 gxzx mapper
})
```
**4. 包名重命名**
迁移过程中将 `com.css.txw.gxzx` 包逐步改为 `com.css.txw.mhzc`
- `Gxzx*` 类名 → 改为 `Mhzc*` 或保持(视情况)
- `TxwGxzx*``TxwMhzc*`
### 3.3 路由配置变更
#### 3.3.1 Gateway 路由txw-gateway
**变更前:**
```yaml
- id: txw-gxzx
uri: grayLb://txw-gxzx
predicates:
- Path=/gxzx/**
- id: txw-mhzc
uri: grayLb://txw-mhzc
predicates:
- Path=/mhzc/**
```
**变更后:**
```yaml
# 删除 txw-gxzx 路由,或将 /gxzx/** 指向 txw-mhzc
- id: txw-gxzx-migrated
uri: grayLb://txw-mhzc
predicates:
- Path=/gxzx/**
- id: txw-mhzc
uri: grayLb://txw-mhzc
predicates:
- Path=/mhzc/**
```
gxzx-web 前端调用 `/gxzx/lsjr/xxx` → 路由到 txw-mhzc 处理。
#### 3.3.2 Nacos 配置
更新 `txw-gateway.yaml``txw-mhzc.yaml`(如有服务名配置)。
### 3.4 前端适配
gxzx-web 前端无需代码迁移,仅需:
1. **路由配置变更**:将前端 API 请求路径从 `/gxzx/` 改为 `/mhzc/`
2. **接口调用路径**:确保前端调用的接口 URL 与 mhzc 后端一致
---
## 4. 迁移步骤
### 阶段一:数据库迁移(独立执行)
1. 备份 gxzx 和 mhzc 数据库
2. 执行数据迁移 SQLrzsqjlb 合并 + 8张表迁移
3. 验证数据完整性
### 阶段二API 层建设
1. 在 `txw-mhzc-service-api` 中新增 4 个 Feign 接口
2. 定义 gxzx 各业务模块的请求/响应 DTO
### 阶段三:业务代码迁移
1. 迁移 PO/DO/VO/DTO 到 mhzc 的 pojo 包
2. 迁移 Mapper 到 mhzc 的 mapper 包(含自定义 SQL
3. 迁移 Service 到 mhzc 的 service 包
4. 迁移 Controller 到 mhzc 的 controller 包
5. 更新 Feign 调用为本地注入
6. 更新 `MapperScan``ComponentScan` 配置
### 阶段四:依赖配置
1. 删除 gxzx-service-biz 对 gxzx-service-api 的依赖(迁移后不再需要)
2. 保留 `txw-gxzx-service-api` 依赖(已有代码可能引用)
### 阶段五:路由切换
1. 更新 txw-gateway 路由配置
2. 通知前端团队修改 API 调用路径
3. 灰度验证
### 阶段六:旧模块处理
1. 保留 txw-gxzx 模块代码(建议添加 deprecated 注释)
2. 或完全删除 txw-gxzx 模块
---
## 5. 风险点与注意事项
| 风险 | 描述 | 缓解措施 |
|------|------|---------|
| Feign 循环依赖 | gxzx → mhzc迁移后若 mhzc 也需调用 gxzx 会循环 | 迁移后 Feign 调用改为本地注入,消除循环 |
| 表名冲突 | gxzx 表名与 mhzc 现有表可能重名 | gxzx 表保持 `txw_gxzx_*` 前缀,不重命名 |
| 消息通知 | xxzxApi 调用在 gxzx 和 mhzc 中都可能存在 | 保持 Feign 调用方式,不变 |
| 审批流程 | gxzx 的 shqkb 是通用审批表mhzc 也有类似需求 | shqkb 迁移后作为 mhzc 的通用审批表使用 |
| Session 依赖 | 各 Controller 依赖 SessionUtils 获取当前用户 | 不变Session 获取方式相同 |
---
## 6. E2E 测试要求
### 6.1 测试目标
在迁移**前**和迁移**后**分别执行相同的 E2E 测试用例,验证功能完全等价,确保迁移过程无业务影响。
### 6.2 迁移前 E2E 测试(基准测试)
| 序号 | 模块 | 测试场景 | 测试路径 |
|------|------|---------|---------|
| 1 | 企业入驻 | 新用户提交入驻申请 → 管理员审批通过 → 企业入驻成功 | POST /gxzx/qyrz/qyrzsq → POST /gxzx/qyrz/qyrzsp → 查询企业列表 |
| 2 | 企业入驻 | 入驻申请审批拒绝 → 验证拒绝原因回写 | POST /gxzx/qyrz/qyrzsp(shjg=5) → 查询申请状态 |
| 3 | 绿色金融-产品管理 | 机构查询、信贷产品列表分页查询、产品详情查询 | POST /gxzx/lsjr/queryJgList → POST /gxzx/lsjr/queryXdbxcpList → GET /gxzx/lsjr/queryXdbxcpxq |
| 4 | 绿色金融-产品管理 | 新增产品 → 审批通过 → 上下架 | POST /gxzx/lsjr/saveOrUpdateCpxx → POST /gxzx/lsjr/cpSp → POST /gxzx/lsjr/cpsxj |
| 5 | 绿色金融-产品管理 | 批量导入产品模板下载 + 导入 | GET /gxzx/lsjr/getTemplate → POST /gxzx/lsjr/pldr |
| 6 | 绿色金融-申请管理 | 提交贷款申请 → 查询申请详情 → 下载申请文件 | POST /gxzx/lsjr/saveDksqxx → GET /gxzx/lsjr/queryXdbxcpsqxq → GET /gxzx/lsjr/querySqFileByid |
| 7 | 绿色金融-申请管理 | 提交投保申请 → 查询申请列表 | POST /gxzx/lsjr/saveTbsqxx → POST /gxzx/lsjr/queryXdbxcpsqList |
| 8 | 绿色交易-资产管理 | 资产类型查询、资产列表分页、资产详情 | GET /gxzx/lsjy/queryZclxList → POST /gxzx/lsjy/queryZcxxList → GET /gxzx/lsjy/queryZcxxxq |
| 9 | 绿色交易-资产管理 | 新增资产 → 审批通过 → 上下架 | POST /gxzx/lsjy/saveOrUpdate → POST /gxzx/lsjy/zcSp → POST /gxzx/lsjy/zcsxj |
| 10 | 绿色交易-资产管理 | 批量删除资产 | POST /gxzx/lsjy/batchDelete |
| 11 | 供需大厅-供需发布 | 发布供需信息 → 审批通过 → 收藏 | POST /gxzx/gxdt/gxfb → POST /gxzx/gxdt/gxfbSp → POST /gxzx/gxdt/gxsc |
| 12 | 供需大厅-供需查询 | 按标签查询供需列表、按企业查询、收藏状态过滤 | POST /gxzx/gxdt/gxxxList → POST /gxzx/gxdt/getGxSqList → POST /gxzx/gxdt/gxfbList |
| 13 | 供需大厅-供需管理 | 供需信息详情查询、供需上架/下架 | GET /gxzx/gxdt/getGxxx → POST /gxzx/gxdt/gxsj |
| 14 | 综合验证 | 所有接口响应格式一致CommonResult | 各接口返回结构校验 |
| 15 | 综合验证 | Session 用户信息在迁移前后一致 | 各接口获取当前用户信息对比 |
### 6.3 迁移后 E2E 测试(回归测试)
**路径替换规则:** `/gxzx/``/mhzc/`,其余路径不变。
| 序号 | 验证方式 |
|------|---------|
| 1-13 | **路径替换后重复迁移前测试**,验证结果一致 |
| 14-15 | **路径替换后重复迁移前测试**,验证结果一致 |
**新增验证点:**
| 验证项 | 说明 |
|--------|------|
| rzsqjlb 数据完整性 | 迁移前后的入驻申请记录数量一致 |
| 审批消息通知 | 迁移后 xxzx 消息仍能正常发送 |
| Gateway 路由 | /gxzx/** 正确路由到 txw-mhzc |
### 6.4 测试工具建议
- **Postman / Apifox**:接口测试
- **前端联调**gxzx-web 调用新接口验证完整链路
- **数据库比对**:迁移前后关键表数据一致性校验
### 6.5 判定标准
| 条件 | 结果 |
|------|------|
| 迁移前 15 个测试场景全部通过 | ✅ 基准测试通过 |
| 迁移后相同 15 个场景路径替换后全部通过 | ✅ 迁移成功 |
| 任意场景失败 | ❌ 需排查问题后重新迁移 |
---
## 7. 验收标准
1. **功能完整性**36 个 API 接口全部迁移,接口签名保持兼容
2. **数据完整性**9 张表数据完整迁移rzsqjlb 合并无数据丢失
3. **路由正确性**gxzx-web 调用 `/gxzx/*` 路径能正确路由到 mhzc 后端
4. **无编译错误**mvn compile 全部通过
5. **企业入驻流程**:申请→审批→入驻 全流程端到端验证通过
6. **E2E 回归测试**:迁移前 15 个 E2E 测试场景全部通过,迁移后路径替换(/gxzx/→/mhzc/)后相同场景全部回归通过
---
## 8. 后续工作
1. **旧模块废弃**:删除或归档 txw-gxzx 整个模块
2. **前端合并**(可选):长期可将 gxzx-web 合并到 mhzc-web
3. **数据库清理**:废弃 gxzx 原有表,保留迁移后的新表

View File

@ -0,0 +1,221 @@
# 登录验证码重构设计方案
## 1. 背景与目标
### 现状
当前登录使用滑块拖动验证,用户体验不够友好,且代码实现较为复杂(纯前端拖动逻辑 + 后端 token 校验)。
### 目标
将滑块验证改为图形数字+字母验证码,提升用户体验,简化前端逻辑,保持后端安全校验流程不变。
### 范围
- 前端:`txw-mhzc-web` 登录页面passwordlogin.vue、phonelogin.vue
- 后端:`txw-sso` 服务新增验证码生成接口
---
## 2. 验证码规格
| 项目 | 规格 |
|------|------|
| 字符集 | 数字 0-9 + 大小写字母 A-Z/a-z |
| 长度 | 4 位 |
| 样式 | 扭曲变形文字 + 干扰线/噪点 |
| 图片尺寸 | 120 x 40 px |
| 格式 | Base64 PNG |
| 有效期 | Redis 存储TTL 5 分钟 |
| 校验 | uuid + 验证码内容联合校验 |
---
## 3. 数据流
### 验证码获取流程
```
前端页面加载
→ POST /sso/verify/captcha
→ 后端生成 uuid + 验证码内容
→ 存入 Redis: captcha:{uuid} = 验证码内容, TTL 5min
→ 返回 { uuid, imageBase64 }
→ 前端渲染图片
```
### 登录流程
```
用户输入账号密码 + 验证码
→ POST /sso/auth/login
{
username: "xxx",
password: "xxx",
captchaVerification: "uuid",
captchaCode: "Kp7m"
}
→ 后端校验 captcha:{uuid} == captchaCode
→ 校验通过后继续账号密码验证
```
---
## 4. 前端改动
### 4.1 文件结构
| 文件 | 操作 | 说明 |
|------|------|------|
| `passwordlogin.vue` | 修改 | 注释滑块代码,新增验证码组件 |
| `phonelogin.vue` | 修改 | 同上 |
| `login.js` | 修改 | 新增 `getCaptcha()` API |
### 4.2 passwordlogin.vue 改动
**注释掉的代码(原滑块相关):**
- `mouseDown`, `mouseMoveFn`, `moseUpFn`, `successFunction` 方法 → 注释
- `maxWidth`, `beginClientX`, `mouseMoveState`, `confirmWords`, `confirmSuccess` 数据 → 注释
- `.drag` 模板区域 → 注释,替换为新验证码区域
- `mounted()` 中滑块初始化逻辑 → 注释
- `beforeDestroy()` 中的清理逻辑 → 注释
**新增代码:**
- 新增 `captchaCode` 表单字段
- 新增 `captchaUuid` 存储当前验证码 uuid
- 新增 `captchaImage` 存储验证码图片 base64
- 新增 `getCaptcha()` 方法调用后端接口
- 新增 `refreshCaptcha()` 刷新验证码方法
- 模板新增验证码图片 + 输入框 + 刷新按钮区域
### 4.3 验证码组件 UI新增模板区域
```html
<t-form-item name="captchaCode">
<div class="captcha-container">
<img :src="captchaImage" @click="refreshCaptcha" class="captcha-img" />
<t-input
v-model="loginForm.captchaCode"
placeholder="请输入验证码"
maxlength="4"
style="width: 120px"
/>
<span class="refresh-btn" @click="refreshCaptcha">刷新</span>
</div>
</t-form-item>
```
### 4.4 样式新增
```css
.captcha-container {
display: flex;
align-items: center;
gap: 12px;
}
.captcha-img {
width: 120px;
height: 40px;
cursor: pointer;
border-radius: 4px;
}
.refresh-btn {
color: #0052d9;
cursor: pointer;
font-size: 14px;
}
```
### 4.5 API 改动
**login.js 新增:**
```javascript
// 获取图形验证码
export const getCaptcha = () => {
return request({
url: '/sso/verify/captcha',
method: 'post'
})
}
```
---
## 5. 后端改动
### 5.1 文件结构
| 文件 | 操作 | 说明 |
|------|------|------|
| `VerifyController.java` | 修改 | 新增 `/verify/captcha` 接口 |
| `VerifyService.java` | 修改 | 新增 `getCaptcha()` 接口定义 |
| `VerifyServiceImpl.java` | 修改 | 实现验证码生成(使用 Hutool 的 CaptchaUtil |
| `AuthLoginReqVO.java` | 修改 | 新增 `captchaCode` 字段 |
| `AuthServiceImpl.java` | 修改 | login() 方法新增验证码校验逻辑 |
### 5.2 接口定义
**POST /sso/verify/captcha**
请求:
```json
{
"remoteId": "IP+UserAgent hash"
}
```
响应:
```json
{
"code": 0,
"data": {
"uuid": "abc123...",
"imageBase64": "data:image/png;base64,iVBORw0KGgo..."
}
}
```
### 5.3 Redis 存储结构
| Key | Value | TTL |
|-----|-------|-----|
| `captcha:{uuid}` | 验证码内容(如 "Kp7m" | 5 分钟 |
### 5.4 登录接口改动
`AuthLoginReqVO` 新增字段:
```java
private String captchaCode; // 用户输入的验证码
```
`AuthServiceImpl.login()` 改动:
```java
// 原有验证码 token 校验(滑块)
verifyService.checkVerifyToken(reqVO.getCaptchaVerification());
// 新增图形验证码校验
verifyService.checkCaptcha(reqVO.getCaptchaVerification(), reqVO.getCaptchaCode());
```
---
## 6. 安全考虑
1. **防暴力破解**:验证码校验失败后不暴露具体错误原因("验证码错误" vs "验证码已过期"
2. **一次性**:验证码验证成功后立即从 Redis 删除
3. **限频**:同一 IP 请求验证码频率限制TODO
4. **混淆**:图形验证码使用扭曲字体 + 干扰线,防止简单 OCR
---
## 7. 兼容性
- 原滑块相关代码**注释保留**,不删除,便于后续回滚
- `captchaVerification` 字段保留(复用为 uuid登录参数结构兼容
- 后端兼容旧版滑块 token 校验逻辑captcha check 可配置开关)
---
## 8. 测试要点
1. 验证码图片正确渲染(扭曲字符可见)
2. 点击刷新生成新验证码
3. 输入正确验证码 + 正确账号密码 → 登录成功
4. 输入错误验证码 → 登录失败,提示"验证码错误"
5. 验证码过期5分钟→ 登录失败,提示"验证码已过期"
6. 滑块相关代码注释后,页面功能不受影响

View File

@ -1,35 +0,0 @@
#!/bin/bash
# 复制 git 变更文件到 change 目录,保留原文件相对路径
set -e
TARGET_DIR="change"
# 创建目标目录
mkdir -p "$TARGET_DIR"
# 获取所有变更文件(包含未跟踪文件)
files=$(git status --porcelain | awk '{print $2}')
if [ -z "$files" ]; then
echo "没有变更文件"
exit 0
fi
count=0
for f in $files; do
# 跳过目录(如 docs/
if [ -d "$f" ]; then
mkdir -p "$TARGET_DIR/$f"
cp -r "$f" "$TARGET_DIR/$f"
echo "$f/"
elif [ -f "$f" ]; then
mkdir -p "$TARGET_DIR/$(dirname "$f")"
cp "$f" "$TARGET_DIR/$f"
echo "$f"
((count++))
fi
done
echo ""
echo "已完成,复制了 $count 个文件到 $TARGET_DIR 目录"

View File

@ -65,10 +65,10 @@
<artifactId>ggzc-framework-starter-mybatis</artifactId> <artifactId>ggzc-framework-starter-mybatis</artifactId>
</dependency> </dependency>
<dependency> <!-- <dependency>-->
<groupId>com.css.ggzc</groupId> <!-- <groupId>com.css.ggzc</groupId>-->
<artifactId>ggzc-framework-starter-cache</artifactId> <!-- <artifactId>ggzc-framework-starter-cache</artifactId>-->
</dependency> <!-- </dependency>-->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>

View File

@ -3,11 +3,11 @@
spring: spring:
cloud: cloud:
nacos: nacos:
server-addr: 10.23.10.91:8848 server-addr: 127.0.0.1:8848
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
discovery: discovery:
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
metadata: metadata:
version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布 version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布
@ -18,10 +18,10 @@ spring:
nacos: nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config: config:
server-addr: 10.23.10.91:8848 # Nacos 服务器地址 server-addr: 127.0.0.1:8848 # Nacos 服务器地址(本地开发环境)
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用 dev 开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties

View File

@ -3,11 +3,11 @@
spring: spring:
cloud: cloud:
nacos: nacos:
server-addr: 10.23.10.91:8848 server-addr: 127.0.0.1:8848
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
discovery: discovery:
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
metadata: metadata:
version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布 version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布
@ -18,10 +18,10 @@ spring:
nacos: nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config: config:
server-addr: 10.23.10.91:8848 # Nacos 服务器地址 server-addr: 127.0.0.1:8848 # Nacos 服务器地址(本地开发环境)
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用 dev 开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties

View File

@ -286,22 +286,26 @@ module.exports = {
// 会误伤 SPA 路由 /view/mhzc/...,刷新时整页请求被转发到后端导致 Proxy error。必须用 ^ 限定为路径前缀。 // 会误伤 SPA 路由 /view/mhzc/...,刷新时整页请求被转发到后端导致 Proxy error。必须用 ^ 限定为路径前缀。
proxy: { proxy: {
'^/sso': { '^/sso': {
target: 'http://carbon.liantu.tech', target: 'http://localhost:9301',
// target: 'http://carbon.liantu.tech',
// target: 'http://10.23.20.13:94/', // target: 'http://10.23.20.13:94/',
changeOrigin: true, changeOrigin: true,
}, },
'^/mhzc': { '^/mhzc': {
target: 'http://carbon.liantu.tech', target: 'http://localhost:9302',
// target: 'http://carbon.liantu.tech',
// target: 'http://10.23.20.13:94/', // target: 'http://10.23.20.13:94/',
changeOrigin: true, changeOrigin: true,
}, },
'^/gxzx': { '^/gxzx': {
target: 'http://carbon.liantu.tech', target: 'http://localhost:9303',
// target: 'http://carbon.liantu.tech',
// target: 'http://10.23.20.13:94/', // target: 'http://10.23.20.13:94/',
changeOrigin: true, changeOrigin: true,
}, },
'^/yygl': { '^/yygl': {
target: 'http://carbon.liantu.tech', target: 'http://localhost:20010',
// target: 'http://carbon.liantu.tech',
// target: 'http://10.23.20.13:94/', // target: 'http://10.23.20.13:94/',
changeOrigin: true, changeOrigin: true,
}, },

View File

@ -3,13 +3,11 @@
spring: spring:
cloud: cloud:
nacos: nacos:
server-addr: 10.23.10.91:8848 server-addr: 127.0.0.1:8848
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
discovery: discovery:
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
metadata:
version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布
--- #################### 配置中心相关配置 #################### --- #################### 配置中心相关配置 ####################
@ -18,10 +16,10 @@ spring:
nacos: nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config: config:
server-addr: 10.23.10.91:8848 # Nacos 服务器地址 server-addr: 127.0.0.1:8848 # Nacos 服务器地址(本地开发环境)
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用 dev 开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties

View File

@ -5,6 +5,8 @@ spring:
cloud: cloud:
nacos: nacos:
server-addr: 10.23.10.91:8848 server-addr: 10.23.10.91:8848
username: qyddev
password: "9!1%Sw#QydNacosDev"
discovery: discovery:
namespace: qyd-txw # 命名空间。这里使用 dev 开发环境 namespace: qyd-txw # 命名空间。这里使用 dev 开发环境
@ -16,6 +18,8 @@ spring:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config: config:
server-addr: 10.23.10.91:8848 # Nacos 服务器地址 server-addr: 10.23.10.91:8848 # Nacos 服务器地址
username: qyddev
password: "9!1%Sw#QydNacosDev"
namespace: qyd-txw # 命名空间。这里使用 dev 开发环境 namespace: qyd-txw # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name

View File

@ -3,11 +3,11 @@
spring: spring:
cloud: cloud:
nacos: nacos:
server-addr: 10.23.10.91:8848 server-addr: 127.0.0.1:8848
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
discovery: discovery:
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
metadata: metadata:
version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布 version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布
@ -18,10 +18,10 @@ spring:
nacos: nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config: config:
server-addr: 10.23.10.91:8848 # Nacos 服务器地址 server-addr: 127.0.0.1:8848 # Nacos 服务器地址(本地开发环境)
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: "9!1%Sw#QydNacosDev"
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用 dev 开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties

View File

@ -3,7 +3,7 @@ spring:
name: txw-sso name: txw-sso
profiles: profiles:
active: env active: local
server: server:
port: 9301 port: 9301

View File

@ -5,6 +5,8 @@ spring:
cloud: cloud:
nacos: nacos:
server-addr: 10.23.10.91:8848 server-addr: 10.23.10.91:8848
username: qyddev
password: "9!1%Sw#QydNacosDev"
discovery: discovery:
namespace: qyd-txw # 命名空间。这里使用 dev 开发环境 namespace: qyd-txw # 命名空间。这里使用 dev 开发环境
@ -16,6 +18,8 @@ spring:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config: config:
server-addr: 10.23.10.91:8848 # Nacos 服务器地址 server-addr: 10.23.10.91:8848 # Nacos 服务器地址
username: qyddev
password: "9!1%Sw#QydNacosDev"
namespace: qyd-txw # 命名空间。这里使用 dev 开发环境 namespace: qyd-txw # 命名空间。这里使用 dev 开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name

View File

@ -3,11 +3,11 @@
spring: spring:
cloud: cloud:
nacos: nacos:
server-addr: 10.23.10.91:8848 server-addr: 127.0.0.1:8848
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: 9!1%Sw#QydNacosDev
discovery: discovery:
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
metadata: metadata:
version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布 version: 1.0.0-SNAPSHOT # 服务实例的版本号,可用于灰度发布
@ -18,10 +18,10 @@ spring:
nacos: nacos:
# Nacos Config 配置项,对应 NacosConfigProperties 配置属性类 # Nacos Config 配置项,对应 NacosConfigProperties 配置属性类
config: config:
server-addr: 10.23.10.91:8848 # Nacos 服务器地址 server-addr: 127.0.0.1:8848 # Nacos 服务器地址(本地开发环境)
username: qyddev username: qyddev
password: 9!1%Sw#QydNacosDev password: 9!1%Sw#QydNacosDev
namespace: 0ac06fee-c2c9-4ca0-9a26-4921d553adde # 命名空间。这里使用 dev 开发环境 namespace: bcf8de57-7215-4934-aced-ab382d504aff # 命名空间。这里使用本地开发环境
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name name: ${spring.application.name} # 使用的 Nacos 配置集的 dataId默认为 spring.application.name
file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties file-extension: yaml # 使用的 Nacos 配置集的 dataId 的文件拓展名,同时也是 Nacos 配置集的配置格式,默认为 properties