feat(platform): Implement legacy system integration with Wrapper Bridge architecture

Complete integration of the old clinical research platform (www.xunzhengyixue.com)
into the new AI platform via Token injection + iframe embedding:

Backend:
- Add legacy-bridge module (MySQL pool, auth service, routes)
- POST /api/v1/legacy/auth: JWT -> phone lookup -> Token injection into old MySQL
- Auto-create user in old system if not found (matched by phone number)

Frontend:
- LegacySystemPage: iframe container with Bridge URL construction
- ResearchManagement + StatisticalTools entry components
- Module registry updated from external links to iframe embed mode

ECS (token-bridge.html deployed to www.xunzhengyixue.com):
- Wrapper Bridge: sets cookies within same-origin context
- Storage Access API for cross-site dev environments
- CSS injection: hide old system nav/footer, remove padding gaps
- Inner iframe loads target page with full DOM access (same-origin)

Key technical decisions:
- Token injection (direct MySQL write) instead of calling login API
- Wrapper Bridge instead of parent-page cookie setting (cross-origin fix)
- Storage Access API + SameSite=None;Secure for third-party cookie handling
- User isolation guaranteed by phone number matching

Documentation:
- Integration plan v4.0 with full implementation record
- Implementation summary with 6 pitfalls documented
- System status guide updated (ST module now integrated)

Tested: Local E2E verified - auto login, research management, 126 statistical
tools, report generation, download, UI layout all working correctly

Made-with: Cursor
This commit is contained in:
2026-02-27 21:54:38 +08:00
parent 6124c7abc6
commit c3f7d54fdf
21 changed files with 1407 additions and 63 deletions

View File

@@ -1,10 +1,11 @@
# AIclinicalresearch 系统当前状态与开发指南
> **文档版本:** v6.4
> **文档版本:** v6.5
> **创建日期:** 2025-11-28
> **维护者:** 开发团队
> **最后更新:** 2026-02-27
> **🎉 重大里程碑:**
> - **🆕 2026-02-27旧版系统集成完成** Token 注入自动登录 + Wrapper Bridge 架构 + Storage Access API + iframe 嵌入(研究管理 + 统计分析工具 126 个) + CSS 注入样式定制 + 本地 E2E 验证通过
> - **🆕 2026-02-27数据库文档体系 + 部署文档体系 + Prisma Schema 对齐完成!** 6 篇数据库核心文档 + 部署文档归档整理 + 统一操作手册 + 数据库开发规范 v3.0 + Cursor Rule 自动提醒 + Schema 类型漂移修正
> - **🆕 2026-02-26ASL 工具 4 SR 图表生成器 + 工具 5 Meta 分析引擎开发完成!** PRISMA 流程图(中英切换)+ 基线特征表 + Meta 分析HR/二分类/连续型)+ 森林图/漏斗图 + R Docker meta 包 + E2E 36/36 通过
> - **🆕 2026-02-26CRA Agent V3.0 P0+P1 全部完成!** 自驱动质控流水线 + ChatOrchestrator + LLM Function Calling + E2E 54/54 通过
@@ -31,7 +32,8 @@
> - **2026-01-24Protocol Agent 框架完成!** 可复用Agent框架+5阶段对话流程
> - **2026-01-22OSS 存储集成完成!** 阿里云 OSS 正式接入平台基础层
>
> **🆕 最新进展(数据库文档体系 + 部署文档整理 2026-02-27**
> **🆕 最新进展(旧版系统集成 + 数据库文档体系 2026-02-27**
> - ✅ **🆕 旧版系统集成** — Token 注入自动登录 + Wrapper BridgeCookie 设置 + CSS 注入)+ Storage Access API + 本地 E2E 全部通过
> - ✅ **🆕 数据库文档体系建立** — 6 篇核心文档(架构总览/迁移历史/环境对照/技术债务/种子数据/PG扩展位于 `docs/01-平台基础层/07-数据库/`
> - ✅ **🆕 Prisma Schema 类型漂移修正** — IIT/SSA 模型 @db.* 注解对齐 + 手动迁移 + Tech Debt 注释
> - ✅ **🆕 部署文档体系整理** — 归档 2025 旧文档 + 统一操作手册 + 待部署变更清单 + README 重写
@@ -81,7 +83,7 @@
| **DC** | 数据清洗整理 | ETL + 医学NER百万行级数据 | ⭐⭐⭐⭐⭐ | ✅ **Tool B完成 + Tool C 99%(异步架构+性能优化-99%+多指标转换+7大功能** | **P0** |
| **IIT** | IIT Manager Agent | CRA Agent - LLM Tool Use + 自驱动质控 + 统一驾驶舱 | ⭐⭐⭐⭐⭐ | 🎉 **V3.0 P0+P1完成** ChatOrchestrator + 4工具 + E2E 54/54 | **P1-2** |
| **SSA** | 智能统计分析 | **QPER架构** + 四层七工具 + 对话层LLM + 意图路由器 | ⭐⭐⭐⭐⭐ | 🎉 **Phase I-IV 开发完成** — QPER闭环 + Session黑板 + 意图路由 + 对话LLM + 方法咨询 + 对话驱动分析E2E 107/107 | **P1** |
| **ST** | 统计分析工具 | 100+轻量化统计工具 | ⭐⭐⭐⭐ | 📋 规划中 | P2 |
| **ST** | 统计分析工具 | 126 个轻量化统计工具(旧系统 iframe 嵌入) | ⭐⭐⭐⭐ | ✅ **旧系统集成完成** — Token 注入 + Wrapper Bridge + E2E 验证通过 | P2 |
| **RVW** | 稿件审查系统 | 方法学评估 + 🆕数据侦探L1/L2/L2.5验证)+ Skills架构 + Word导出 | ⭐⭐⭐⭐ | 🚀 **V2.0 Week3完成85%** - 统计验证扩展+负号归一化+文件格式提示+用户体验优化 | P1 |
| **ADMIN** | 运营管理端 | Prompt管理、租户管理、用户管理、运营监控、系统知识库 | ⭐⭐⭐⭐⭐ | 🎉 **Phase 4.6完成88%** - Prompt知识库集成+动态注入 | **P0** |

View File

@@ -0,0 +1,418 @@
# 新旧系统集成方案
> **版本:** v4.0
> **创建日期:** 2026-02-27
> **最后更新:** 2026-02-27Wrapper Bridge 架构 + Storage Access API + 本地 E2E 验证通过)
> **维护者:** 开发团队
> **状态:** ✅ Phase 0-2 全部完成,本地开发环境 E2E 验证通过,待部署生产环境
---
## 1. 背景
### 1.1 两套系统概览
| 维度 | 新系统AI临床研究平台 | 老系统(循证医学平台) |
|------|------------------------|----------------------|
| 域名 | `iit.xunzhengyixue.com` | `www.xunzhengyixue.com` |
| API 域名 | `iit.xunzhengyixue.com/api` (SAE) | `api.xunzhengyixue.com` (ECS Nginx 反代) |
| 部署 | 阿里云 SAEServerless | 阿里云 ECS`8.154.22.149` |
| 技术栈 | Node.js + React 19 + PostgreSQL | Spring Boot 1.4.1 + Java 8 + MySQL |
| 前端部署 | SAE 静态资源 | Nginx 直接 serve 静态文件 |
| 认证方式 | JWTAccess 2h + Refresh 7d | 自定义 MD5 TokenMySQL 存储3.5 天有效期) |
| 数据库 | PostgreSQL 1514 个 Schema | MariaDB/MySQL`xzyx_online` |
### 1.2 老系统模块
| 模块 | 入口地址 | 集成状态 |
|------|---------|---------|
| 研究管理 | `https://www.xunzhengyixue.com/index.html` | Phase 0 外链已完成 → Phase 2 将改为 iframe 内嵌 |
| 统计分析工具 | `https://www.xunzhengyixue.com/tool.html` | Phase 0 外链已完成 → Phase 2 将改为 iframe 内嵌 |
| AI 问答 | 老系统内 | 已在新系统完全重写AIA 模块),无需集成 |
### 1.3 约束条件
- Java 团队已离职,未正式交接源码
- 后找到一份源码,经 ECS 侦察确认 **与生产环境完全一致**
- 线上系统可通过 ECS SSH 访问MySQL 数据库可完全读写
- 两系统同属 `xunzhengyixue.com` 根域Cookie 可共享)
### 1.4 用户关系
- 两套系统的用户是 **同一批人**,由运营人员统一开账号
- 老系统按用户隔离数据(每个用户有自己的研究项目)
- 自动登录必须以用户本人身份进行,不能使用公共账号
---
## 2. ECS 侦察结果Phase 1 - 已完成)
> 2026-02-27 通过 SSH 登录 `8.154.22.149` 实地验证
### 2.1 部署架构
```
┌─────────────────────────────────────────┐
│ ECS 8.154.22.149 │
│ │
www.xunzhengyixue.com ──► Nginx:443 │
│ │ │
│ ├─ / → 静态文件 │
│ │ /home/work/www/xunzhengyixue/ │
│ │ │
│ └─ /api-proxy/ → rag.xunzhengyixue│
│ │
api.xunzhengyixue.com ──► Nginx:443 │
│ └─ / → proxy_pass 127.0.0.1:8899 │
│ │ │
│ Java JAR (Spring Boot) │
│ XZYXServer-0.0.1-SNAPSHOT.jar │
│ -Xms800m -Xmx4000m │
│ 运行自 2025 年至今 │
│ │ │
│ MariaDB/MySQL :3306 │
│ xzyx_online │
└─────────────────────────────────────────┘
```
### 2.2 关键确认事项
| 项目 | 侦察结果 |
|------|---------|
| 源码一致性 | **生产 `common.js` 与本地源码 100% 一致** |
| 前端静态文件路径 | `/home/work/www/xunzhengyixue/` |
| 要修改的文件 | `/home/work/www/xunzhengyixue/static/js/common.js` |
| Java 部署方式 | 直接 JAR 运行(非 DockerPID 66548 |
| API 地址 | `https://api.xunzhengyixue.com``config.js` 确认) |
| Cookie 域名 | **`xunzhengyixue.com`**`config.js` 退出登录逻辑确认) |
| Cookie 名称 | `token`, `nickname`, `id`3 个) |
| 登录检查逻辑 | 仅检查 `$.cookie("nickname")` 是否存在 |
| API 认证逻辑 | `$.cookie("token")``Authorization` 请求头 |
| X-Frame-Options | **未设置** → iframe 嵌入可行 |
| Nginx 改 common.js | **无需重启 Java**,静态文件改完即生效 |
### 2.3 认证机制详解
```
Token 生成公式MD5("KyKz1.0:" + userId + ":" + timestamp)
Token 存储位置MySQL u_user_token 表
Token 有效期:可配置(生产 5000 分钟 ≈ 3.5 天)
Token 传递方式Cookie → JS 读取 → Authorization 请求头
老系统 AuthInterceptor 验证流程:
1. 从 Authorization header 取 Token
2. 查 u_user_token 表是否存在该 Token
3. 检查是否过期gen_time + timeout
4. 不涉及密码验证 ← 这是直接写 Token 方案可行的根本原因
```
### 2.4 对集成友好的 6 个关键发现
| 发现 | 对集成的意义 |
|------|-------------|
| **无 CSRF 保护** | 可以从新系统直接 POST 调用 API |
| **CORS 全开**`Access-Control-Allow-Origin: *` | 新系统前端可直接 fetch 调用老系统 API |
| **无 X-Frame-Options** | iframe 嵌入完全可行 |
| **Token 仅查表验证,不校验密码** | 直接写 Token 到 DB 即可,绕过密码 |
| **同根域名 `.xunzhengyixue.com`** | 新系统 `iit.*` 可设置 Cookie 供 `www.*` 读取 |
| **前端纯静态 + 后端分离** | 改 `common.js` 无需碰 Java 代码或重启服务 |
---
## 3. 最终方案Token 注入 + iframe 嵌入
经过 Phase 0外链验证和 Phase 1ECS 侦察),最终确认采用 **方案 B+E 组合**
- **方案 EToken 注入)**:新系统后端直接写 Token 到老系统 MySQL实现自动登录
- **方案 Biframe 嵌入)**:在新系统内用 iframe 加载老系统页面,隐藏老系统导航
### 3.1 为什么选 Token 注入而非调用登录 API
| 对比项 | 调用登录 API方案 C | 直接写 Token方案 E |
|--------|----------------------|----------------------|
| 需要知道用户密码 | 是 | **否** |
| 用户改了老系统密码 | 失败 | **不受影响** |
| 依赖老系统 API 可用 | 是 | **否**(只依赖 MySQL |
| 可同时创建账号 | 否 | **是** |
| 安全性 | 密码在网络传输 | Token 仅写入 DB |
### 3.2 整体流程
```
用户在新系统点击"研究管理"或"统计分析工具"
新系统前端 → POST /api/legacy/auth携带 JWT
新系统后端:
1. 从 JWT 解出当前用户手机号
2. 连接老系统 MySQLxzyx_online
3. SELECT id FROM u_user_info WHERE phone = 手机号
├─ 不存在 → INSERT 创建账号(默认密码 MD5
└─ 存在 → 获取 userId
4. 生成 Token = MD5("KyKz1.0:" + userId + ":" + Date.now())
5. INSERT INTO u_user_token (user_id, token, gen_time, user_role)
6. 返回 { token, nickname, id, userRole }
新系统前端:
7. 构建 Bridge URLtoken/nickname/id/userRole/redirect 作为参数)
8. iframe src = https://www.xunzhengyixue.com/token-bridge.html?...
Bridge 页面www.xunzhengyixue.com 域内执行):
9. Storage Access API 检查(同站自动授权,跨站需一次性用户点击)
10. document.cookie = "token=xxx; domain=.xunzhengyixue.com"(同域设置)
11. 创建内部 iframe 加载目标页面(/index.html 或 /tool.html
12. 每次内部页面加载后,注入自定义 CSS隐藏导航栏、页脚等
老系统页面Bridge 内部 iframe同源
13. 读取 Cookie nickname → 存在 → 正常渲染
14. AJAX 请求带 Cookie 中的 token → AuthInterceptor 验证通过
用户看到自己的研究项目iframe 内),新系统导航栏保持在顶部
```
### 3.3 账号同步策略
| 场景 | 处理方式 |
|------|---------|
| 用户在老系统已有账号 | 直接注入 Token使用原有账号 |
| 用户在老系统无账号 | 自动创建INSERT u_user_info默认密码 `123456` 的 MD5 |
| 用户改了老系统密码 | **不影响**Token 注入不依赖密码 |
| 用户在老系统被删除 | 自动重新创建 |
匹配规则:以 **手机号phone** 作为两套系统的用户关联键。
---
## 4. 实施计划
### Phase 0 — 外链跳转(已完成)
顶部导航加外链按钮,点击后 `window.open()` 打开老系统新标签页。
**已改动文件:**
| 文件 | 改动 |
|------|------|
| `frontend-v2/src/framework/modules/types.ts` | 新增 `externalUrl?: string` 字段 |
| `frontend-v2/src/framework/modules/moduleRegistry.ts` | 新增「研究管理」模块 + 「统计分析工具」加 `externalUrl` |
| `frontend-v2/src/framework/layout/TopNavigation.tsx` | 外部模块 `window.open` + 外链图标 + 跳过权限检查 |
| `frontend-v2/src/App.tsx` | 外部模块跳过内部路由注册 |
### Phase 1 — ECS 侦察(已完成)
SSH 登录 ECS验证部署架构、Nginx 配置、Cookie 机制、源码一致性。
**结论:** 全部确认,方案可行。详见第 2 节。
### Phase 2 — 新系统代码改动清单
**后端新增文件:**
| 文件 | 说明 |
|------|------|
| `backend/src/modules/legacy-bridge/legacy-auth.service.ts` | 连接老系统 MySQL查询用户、写入 token |
| `backend/src/modules/legacy-bridge/routes.ts` | `POST /api/v1/legacy/auth` 接口 |
**后端改动文件:**
| 文件 | 改动 |
|------|------|
| `backend/.env` | 新增 `LEGACY_MYSQL_*` 连接配置 |
| `backend/src/index.ts` | 注册 `/api/v1/legacy` 路由 |
**前端新增文件:**
| 文件 | 说明 |
|------|------|
| `frontend-v2/src/modules/legacy/LegacySystemPage.tsx` | iframe 容器页面(调后端注入 token → 加载 iframe |
| `frontend-v2/src/modules/legacy/ResearchManagement.tsx` | 研究管理入口(指向 index.html |
| `frontend-v2/src/modules/legacy/StatisticalTools.tsx` | 统计分析工具入口(指向 tool.html |
**前端改动文件:**
| 文件 | 改动 |
|------|------|
| `frontend-v2/src/framework/modules/types.ts` | 新增 `legacyUrl` 字段 |
| `frontend-v2/src/framework/modules/moduleRegistry.ts` | 研究管理/统计分析模块改为 iframe 内嵌模式 |
| `frontend-v2/src/App.tsx` | legacy 模块路由注册 |
**ECS 改动文件:**
| 文件 | 改动 |
|------|------|
| `/home/work/www/xunzhengyixue/token-bridge.html` | **新增**Wrapper Bridge 页面(设 Cookie + 内嵌 iframe + 注入 CSS |
| `/home/work/www/xunzhengyixue/static/js/common.js` | iframe 检测:隐藏 header + footerbridge 的 CSS 注入已覆盖,可选回退) |
| `/home/work/www/xunzhengyixue/tool/js/appajax.js` | iframe 检测:隐藏 menu + footerbridge 的 CSS 注入已覆盖,可选回退) |
### Phase 2 — Token 注入 + iframe 嵌入(已完成)
| 步骤 | 内容 | 位置 | 状态 |
|------|------|------|------|
| 2.1 | 新系统后端添加 MySQL 连接(老系统数据库) | `backend/` | ✅ 已完成 |
| 2.2 | 新增 `POST /api/v1/legacy/auth` 接口 | `backend/` | ✅ 已完成 |
| 2.3 | 前端创建 iframe 容器页面组件 | `frontend-v2/` | ✅ 已完成 |
| 2.4 | 修改模块注册:从外链改为内嵌 iframe 页面 | `frontend-v2/` | ✅ 已完成 |
| 2.5 | ECS 部署 Token Bridge 页面 | ECS 服务器 | ✅ 已部署 |
| 2.6 | Token 注入测试 + iframe 显示测试 | 浏览器 | ✅ 已验证 |
### Phase 2.5 — Wrapper Bridge 架构升级
**动机:** 原方案由父页面(新系统)设置 Cookie但在 localhost 开发环境无法跨域设置
`.xunzhengyixue.com` 的 Cookie。改为 Wrapper Bridge 方案后Cookie 在老系统域名内
由 bridge 页面自己设置,同时利用同源 DOM 访问注入自定义 CSS。
**架构:**
```
新系统 iframe
└─ token-bridge.htmlwww.xunzhengyixue.com设 Cookie + 注入 CSS
└─ inner iframewww.xunzhengyixue.com/index.html 或 /tool.html
↑ 同源bridge 可直接操作其 DOM
```
**优势:**
- 本地开发环境localhost可正常测试
- 所有样式定制集中在 bridge 页面一处
- 不再需要修改老系统的 `common.js` / `appajax.js`(之前的改动可选回退)
- 未来可随时调整老系统的外观,无需登录 ECS 改文件
**`token-bridge.html` 工作流程:**
1. 检查 Storage Access API`document.hasStorageAccess()`
- 同站(生产环境):自动授权 → 直接进入步骤 2
- 跨站(本地开发)首次:显示"点击授权并继续"按钮 → 用户点击 → `requestStorageAccess()` → 浏览器授权(缓存 30 天)
- 跨站(本地开发)后续:已缓存授权 → 直接进入步骤 2
2. 读取 URL 参数,在 `.xunzhengyixue.com` 域下设置 Cookie`SameSite=None; Secure`
3. 创建内部 iframe 加载目标页面
4. 每次内部 iframe 导航后,注入自定义 CSS
- 隐藏 `#header-navbar``#footer-bar`(主页面)
- 隐藏 `#menu``#footer`(工具详情页)
- 清除 `body``#page-wrapper` 的顶部间距
**源码位置:** `backend/src/modules/legacy-bridge/token-bridge.html`
**浏览器兼容性:**
| 环境 | 结果 | 说明 |
|------|------|------|
| 生产环境(同站) | ✅ 自动工作 | `iit.*``www.*` 是 same-site |
| 本地开发普通模式 | ✅ 自动工作 | Storage Access API 自动授权 |
| 本地开发无痕模式 | ❌ 不可用 | Chrome 无痕模式禁止所有第三方 Cookie |
### Phase 2 — ECS 历史操作记录
> 以下 `common.js` 和 `appajax.js` 的改动在 Bridge 升级后**已冗余**bridge 的 CSS 注入覆盖了相同功能)。
> 保留这些改动作为双重保障;如需回退,用 `.bak` 文件恢复即可。
**文件 1`/home/work/www/xunzhengyixue/static/js/common.js`**
`navigation:function () {` 开头加入的 iframe 检测代码。
**文件 2`/home/work/www/xunzhengyixue/tool/js/appajax.js`**
在文件开头加入的 iframe 检测代码。
### Phase 2 — 踩坑记录
| 问题 | 原因 | 修复 |
|------|------|------|
| Token 注入后 tool.html 正常,但 index.html 跳转登录页 | `gen_time` 字段用了 MySQL `NOW()`datetime 格式),老系统期望 Java `System.currentTimeMillis()`(毫秒时间戳) | 改为 `Date.now()`,同时先 DELETE 旧 token 再 INSERT |
| 研究管理没有左侧导航 | iframe 检测代码隐藏了 `#nav-col``return` 导致侧边栏内容未生成 | 只隐藏 header + footer不 return |
| 工具详情页仍显示顶部导航 | 工具详情页是独立前端,不加载 `common.js`,使用 `tool/js/appajax.js` | 在 `appajax.js` 开头也加 iframe 检测 |
| localhost 无法测试 iframe 嵌入 | 父页面(localhost)无法为 `.xunzhengyixue.com` 设 Cookie | 升级为 Wrapper Bridge由 bridge 页面在同域内设 Cookie |
| Bridge 设了 Cookie 但老系统仍跳登录页 | 浏览器第三方 Cookie 隔离cross-site iframe 的 `document.cookie` 被静默拒绝 | 添加 `SameSite=None; Secure` + Storage Access API 双重保障 |
| 隐藏导航栏后页面顶部多出空白条 | `#header-navbar` 隐藏后 body 的 `padding-top` 仍在 | Bridge CSS 注入额外清除 `body``#page-wrapper` 的 padding-top/margin-top |
---
## 5. 验证结果2026-02-27 本地 E2E 测试)
| 测试项 | 结果 |
|------|------|
| Token 注入 + 自动登录 | ✅ 通过 |
| 研究管理index.html— 左侧导航正常 | ✅ 通过 |
| 统计分析工具tool.html— 126 个工具 | ✅ 通过 |
| 工具详情页tool/isttest1.html 等) | ✅ 通过 |
| 统计分析 + 出报告 + 下载报告 | ✅ 通过 |
| 导航栏/页脚隐藏 + 顶部间距消除 | ✅ 通过 |
| 用户隔离(不同用户看不到彼此项目) | ✅ 设计保证(按手机号绑定) |
| 普通模式 Storage Access API | ✅ 自动授权 |
| 无痕模式 | ❌ 预期不可用(浏览器限制) |
## 6. 后续步骤
| 事项 | 说明 |
|------|------|
| 部署新系统后端到 SAE | 确保 `.env``LEGACY_MYSQL_*` 配置指向 ECS MySQL |
| 部署新系统前端到 SAE | 包含 `LegacySystemPage` 等新组件 |
| 生产端到端验证 | 同站环境(`iit.*``www.*`),应自动工作无需 Storage Access API |
| 可选:回退 ECS JS 改动 | `common.js``appajax.js` 的 iframe 检测代码已被 bridge CSS 覆盖,可用 `.bak` 恢复 |
| 监控 | 关注 `/api/v1/legacy/auth` 接口调用量和失败率 |
---
## 7. 曾考虑但未选用的方案
### 方案 A直接外链跳转
作为 Phase 0 已实施。用户需手动登录老系统,两个标签页切换,体验不佳。
### 方案 C前端直调登录 API
需要知道用户在老系统的密码。如果用户改了密码就会失败。已被方案 EToken 注入)取代。
### 方案 DNginx 反向代理统一入口
在新系统 Nginx 配置 `/legacy/*` 反代到老系统。路径改写复杂流量多一次中转SAE 环境配置不便。
---
## 附录 ANginx 配置摘要(生产环境)
```nginx
# api.xunzhengyixue.com → Java 后端
server {
listen 443 ssl;
server_name api.xunzhengyixue.com;
location / {
proxy_pass http://127.0.0.1:8899;
proxy_cookie_path / /;
}
}
# www.xunzhengyixue.com → 静态文件
server {
listen 443 ssl;
server_name xunzhengyixue.com www.xunzhengyixue.com;
root /home/work/www/xunzhengyixue;
index index.html;
location /api-proxy/ {
proxy_pass https://rag.xunzhengyixue.com/api/v1/;
}
}
```
## 附录 B老系统源码关键文件索引
| 文件 | 位置(相对于 Java_old_system/XZYXServer | 说明 |
|------|----------------------------------------|------|
| 登录 Controller | `src/main/java/com/xzyx/controller/UserController.java` | 3 个登录端点 |
| Token 生成 | `src/main/java/com/xzyx/biz/service/impl/MysqlTokenValidator.java` | MD5 Token 公式 |
| 认证拦截器 | `src/main/java/com/xzyx/framework/AuthInterceptor.java` | 仅查表验证 Token |
| CORS 配置 | `src/main/java/com/xzyx/framework/CorsFilter.java` | 全开(`*` |
| MVC 配置 | `src/main/java/com/xzyx/framework/MvcConfig.java` | 拦截路径注册 |
| 前端导航+登录检查 | ECS `/home/work/www/xunzhengyixue/static/js/common.js` | **已修改**iframe 检测 |
| 工具详情页 JS | ECS `/home/work/www/xunzhengyixue/tool/js/appajax.js` | **已修改**iframe 检测 |
| 前端 API 配置 | ECS `/home/work/www/xunzhengyixue/static/js/config.js` | Cookie 域名逻辑 |
| 前端 HTTP 工具 | ECS `/home/work/www/xunzhengyixue/static/js/request.js` | Token → Authorization |
| 前端入口页 | ECS `/home/work/www/xunzhengyixue/index.html`, `tool.html` | iframe 加载目标 |
## 附录 C老系统数据库表结构
详见 [02-服务器与数据库配置说明.md](./02-服务器与数据库配置说明.md)

View File

@@ -0,0 +1,115 @@
# 旧版系统集成实施总结
> **日期:** 2026-02-27
> **耗时:** 1 天(含 ECS 侦察 + 代码开发 + Bridge 架构升级 + E2E 验证)
> **状态:** ✅ 本地 E2E 验证通过,待部署生产环境
---
## 1. 目标
将老系统(循证医学平台 `www.xunzhengyixue.com`)的两个核心模块——**研究管理**和**统计分析工具**——无缝嵌入新系统AI 临床研究平台),实现:
- 用户在新系统内一键访问老系统功能,无需重复登录
- 老系统导航栏/页脚隐藏,视觉融入新系统
- 用户数据隔离AAA 用户看不到 BBB 的项目)
## 2. 最终架构
```
新系统页面iit.xunzhengyixue.com
├─ 顶部导航栏:研究管理 | 统计分析工具
└─ 点击后 ─► POST /api/v1/legacy/auth
新系统后端:
- JWT 解出用户手机号
- 连老系统 MySQL查找/创建用户
- 生成 MD5 Token 写入 u_user_token
- 返回 { token, nickname, id, userRole }
前端构建 Bridge URL ─► iframe 加载
token-bridge.htmlwww.xunzhengyixue.com
- Storage Access API 检查(同站自动授权)
- 设置 CookieSameSite=None; Secure
- 内嵌 iframe 加载目标页面
- 注入自定义 CSS隐藏导航栏/页脚/清除间距)
老系统页面正常渲染,用户看到自己的数据
```
## 3. 代码改动清单
### 新系统后端3 个文件)
| 文件 | 类型 | 说明 |
|------|------|------|
| `backend/src/modules/legacy-bridge/legacy-auth.service.ts` | 新增 | 连接老系统 MySQLToken 生成与注入 |
| `backend/src/modules/legacy-bridge/routes.ts` | 新增 | `POST /api/v1/legacy/auth` |
| `backend/src/modules/legacy-bridge/mysql-pool.ts` | 新增 | MySQL 连接池(懒加载) |
| `backend/src/index.ts` | 改动 | 注册 legacy 路由 |
| `backend/.env` | 改动 | `LEGACY_MYSQL_*` 配置 |
### 新系统前端5 个文件)
| 文件 | 类型 | 说明 |
|------|------|------|
| `frontend-v2/src/modules/legacy/LegacySystemPage.tsx` | 新增 | Bridge iframe 容器 |
| `frontend-v2/src/modules/legacy/ResearchManagement.tsx` | 新增 | 研究管理入口 |
| `frontend-v2/src/modules/legacy/StatisticalTools.tsx` | 新增 | 统计分析工具入口 |
| `frontend-v2/src/framework/modules/types.ts` | 改动 | 新增 `legacyUrl` 字段 |
| `frontend-v2/src/framework/modules/moduleRegistry.ts` | 改动 | 模块注册改为 iframe 模式 |
| `frontend-v2/src/App.tsx` | 改动 | legacy 路由注册 |
### ECS 服务器3 个文件)
| 文件 | 类型 | 说明 |
|------|------|------|
| `/home/work/www/xunzhengyixue/token-bridge.html` | **新增** | Wrapper Bridge核心 |
| `/home/work/www/xunzhengyixue/static/js/common.js` | 改动 | iframe 检测(已被 bridge CSS 覆盖,保留为双重保障) |
| `/home/work/www/xunzhengyixue/tool/js/appajax.js` | 改动 | iframe 检测(已被 bridge CSS 覆盖,保留为双重保障) |
## 4. 关键技术决策
| 决策 | 方案 | 原因 |
|------|------|------|
| 认证方式 | Token 注入(直写 MySQL | 不依赖老系统 API、不需要用户密码 |
| 嵌入方式 | Wrapper Bridge + 内嵌 iframe | 同源 DOM 访问,可注入 CSS |
| Cookie 跨域 | Storage Access API + SameSite=None | 解决 localhost 开发环境第三方 Cookie 限制 |
| 用户关联 | 手机号匹配 | 两套系统唯一可靠的关联键 |
| 样式定制 | Bridge 页面 CSS 注入 | 集中管理,无需改老系统文件 |
## 5. 踩坑与修复
| # | 问题 | 修复 |
|---|------|------|
| 1 | `gen_time` 用 MySQL `NOW()` 导致登录失败 | 改为 `Date.now()`(毫秒时间戳) |
| 2 | 隐藏 `#nav-col` 导致研究管理无左侧导航 | 只隐藏 header + footer不隐藏侧边栏 |
| 3 | 工具详情页有独立 JS 不受 `common.js` 控制 | 在 `appajax.js` 也加 iframe 检测 |
| 4 | localhost 无法为 `.xunzhengyixue.com` 设 Cookie | 升级为 Wrapper Bridge同域内设 Cookie |
| 5 | `SameSite=None` 在 Chrome 中仍被拒绝 | 添加 Storage Access API 双重保障 |
| 6 | 隐藏导航栏后顶部留白 | CSS 清除 body/page-wrapper 的 padding-top |
## 6. 验证结果
| 测试项 | 结果 |
|------|------|
| Token 注入 + 自动登录 | ✅ |
| 研究管理 — 左侧导航 + 内容 | ✅ |
| 统计分析工具 — 126 个工具列表 | ✅ |
| 工具详情页 — 统计分析 + 出报告 + 下载 | ✅ |
| 导航栏/页脚隐藏 + 无顶部间距 | ✅ |
| 普通模式自动授权 | ✅ |
| 无痕模式 | ❌ 浏览器限制,预期行为 |
## 7. 后续
1. 部署新系统到 SAE 生产环境
2. 生产端到端验证(同站环境,预期无需 Storage Access API
3. 可选:回退 ECS `common.js` / `appajax.js` 的 iframe 检测改动bridge CSS 已完全覆盖)