Files
AIclinicalresearch/docs/05-部署文档/01-快速部署SOP-零基础版.md
HaHafeng 66255368b7 feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1):
- Database: Add user_modules table for fine-grained module permissions
- Database: Add 4 user permissions (view/create/edit/delete) to role_permissions
- Backend: UserService (780 lines) - CRUD with tenant isolation
- Backend: UserController + UserRoutes (648 lines) - 13 API endpoints
- Backend: Batch import users from Excel
- Frontend: UserListPage (412 lines) - list/filter/search/pagination
- Frontend: UserFormPage (341 lines) - create/edit with module config
- Frontend: UserDetailPage (393 lines) - details/tenant/module management
- Frontend: 3 modal components (592 lines) - import/assign/configure
- API: GET/POST/PUT/DELETE /api/admin/users/* endpoints

Architecture Upgrade - Module Permission System:
- Backend: Add getUserModules() method in auth.service
- Backend: Login API returns modules array in user object
- Frontend: AuthContext adds hasModule() method
- Frontend: Navigation filters modules based on user.modules
- Frontend: RouteGuard checks requiredModule instead of requiredVersion
- Frontend: Remove deprecated version-based permission system
- UX: Only show accessible modules in navigation (clean UI)
- UX: Smart redirect after login (avoid 403 for regular users)

Fixes:
- Fix UTF-8 encoding corruption in ~100 docs files
- Fix pageSize type conversion in userService (String to Number)
- Fix authUser undefined error in TopNavigation
- Fix login redirect logic with role-based access check
- Update Git commit guidelines v1.2 with UTF-8 safety rules

Database Changes:
- CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled)
- ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code)
- INSERT 4 permissions + role assignments
- UPDATE PUBLIC tenant with 8 module subscriptions

Technical:
- Backend: 5 new files (~2400 lines)
- Frontend: 10 new files (~2500 lines)
- Docs: 1 development record + 2 status updates + 1 guideline update
- Total: ~4900 lines of code

Status: User management 100% complete, module permission system operational
2026-01-16 13:42:10 +08:00

34 KiB
Raw Blame History

AI临床研究平台 - 阿里云快速部署SOP零基础版

文档版本: v1.0
创建日期: 2025-12-16
适用场景: 从零开始部署到阿里云不含Dify
预计时间: 3-4小时
目标: 系统能够正常访问,基本功能可用


📋 部署检查清单

在开始之前,请确认:

  • 已有阿里云账号,且已完成实名认证
  • 账户余额 ≥ 500元建议1000元包含3个月运行费用
  • 已安装Docker Desktop用于构建镜像
  • 已安装Git用于获取代码
  • 本地能够正常运行项目(数据库已初始化)

📌 已部署资源快速参考

以下资源已经在阿里云上部署完成,部署过程中可以直接使用这些信息:

VPC网络信息

VPC ID: vpc-2ze055cptkew9c38w4r06
VPC名称: ai-clinical-vpc
网段: 172.17.0.0/16
地域: 华北2北京
交换机ID: vsw-2zevacop039bxrmj6yc0c (可用区F)
         vsw-2zehoeyw9ldncymcyvfwq (可用区A)
安全组ID: sg-2zedk6fi8sgmmcwdu7tu

RDS PostgreSQL数据库

实例ID: pgm-2zex1m2y3r23hdn5
内网地址: pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432
数据库账号: airesearch
数据库密码: Xibahe@fengzhibo117
数据库名称: ai_clinical_research
规格: 2核4GB (pg.n2.2c.1m)
最大连接数: 400
PostgreSQL版本: 15.0
白名单: 172.17.0.0/16 ✅
时区: Asia/Shanghai ✅

SAE命名空间

命名空间ID: cn-beijing:test-airesearch
地域: 华北2北京

OSS对象存储

Bucket名称: ai-clinical-research
地域: 华北2北京
存储类型: 标准存储
读写权限: 私有
存储冗余类型: 同城冗余存储
外网Endpoint: oss-cn-beijing.aliyuncs.com
内网Endpoint: oss-cn-beijing-internal.aliyuncs.com
Bucket域名内网: ai-clinical-research.oss-cn-beijing-internal.aliyuncs.com
创建时间: 2025-12-16 20:22 

# RAM用户访问凭证用于OSS写入
RAM用户名: oss-bucket-put-object@1991407246109125.onaliyun.com
AccessKeyId: LTAI5tB2Dt3NdvBL3G7nYGv7
AccessKeySecret: 1iSN9k39RkApP93QjUhC1DcPIeMG4V
UID: 203256565888301026
创建时间: 2025-12-16 20:31:41 

⚠️ 安全警告AccessKey是敏感信息请勿提交到公开Git仓库

NAT网关与公网访问

NAT网关名称: NAT_airesearch
NAT网关ID: ngw-2zeec9ulzgw7ywvx1pst6
SNAT表ID: stb-2zesszmzx1qpwf1cb2bry
公网IP(EIP): 182.92.176.14
创建时间: 2025-12-16 20:58:12 

# SNAT条目配置2条覆盖所有交换机
SNAT条目1:
  ID: snat-2zerlp4z0ed2isvq399gn
  源网段: 172.17.160.0/20
  交换机: vsw-2zevacop039bxrmj6yc0c (可用区F)
  公网IP: 182.92.176.14
  状态: 可用 ✅

SNAT条目2:
  ID: snat-2zegvesjxjwmw7j51m89m
  源网段: 172.17.192.0/20
  交换机: vsw-2zehoeyw9ldncymcyvfwq (可用区A)
  公网IP: 182.92.176.14
  状态: 可用 ✅

ACR容器镜像服务

服务类型: 个人版(免费)
命名空间: ai-clinical
用户名: gofeng117@163.com
Registry密码: fengzhibo117
公网域名: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
专有网络域名: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com

# 镜像仓库3个
仓库1 - 前端Nginx:
  仓库名称: ai-clinical_frontend-nginx
  公网地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx
  专有网络地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx

仓库2 - Python微服务:
  仓库名称: python-extraction
  公网地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction
  专有网络地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction

仓库3 - Node.js后端:
  仓库名称: nodejs-backend
  公网地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend
  专有网络地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend

⚠️ 安全警告Registry密码是敏感信息请勿提交到公开Git仓库

⚠️ 待部署资源

  • NAT网关 已创建SNAT已配置
  • OSS存储桶 已创建
  • ACR容器镜像仓库 已创建
  • SAE应用3个Python/Node.js/Frontend

🎯 部署全流程概览

第一阶段阿里云资源准备60分钟
├── 创建VPC网络
├── 创建NAT网关关键
├── 购买RDS PostgreSQL
├── 创建OSS存储桶
└── 创建SAE应用3个空应用

第二阶段数据库初始化30分钟
├── 导出本地数据库
├── 通过ECS跳板机连接RDS
└── 导入数据到RDS

第三阶段Docker镜像准备60分钟
├── 创建阿里云容器镜像服务ACR
├── 构建Python微服务镜像
├── 构建Node.js后端镜像
└── 构建前端Nginx镜像

第四阶段SAE应用部署60分钟
├── 部署Python微服务
├── 部署Node.js后端
└── 部署前端Nginx

第五阶段验证与测试30分钟
├── 健康检查
├── 功能测试
└── 日志排查

总预计时间3.5-4小时


第一阶段阿里云资源准备60分钟

1.1 创建VPC专有网络10分钟

目的: 为所有云资源提供内网隔离环境

操作步骤:

  1. 登录阿里云控制台:https://vpc.console.aliyun.com/
  2. 点击【创建专有网络】
  3. 填写配置:
名称: ai-clinical-vpc
地域: 华北2北京
IPv4网段: 172.17.0.0/16
  1. 创建交换机vSwitch
名称: ai-clinical-vswitch-1
可用区: 北京 可用区H
IPv4网段: 172.17.0.0/20
  1. 点击【确定】等待创建完成约30秒

验证: 在VPC列表中看到"ai-clinical-vpc",状态为"可用"


1.2 创建NAT网关15分钟

目的: 为SAE容器提供公网访问能力调用DeepSeek/OpenAI API必需

⚠️ 重要警告: 没有NAT网关AI功能100%超时!

实际NAT网关信息已部署

NAT网关名称: NAT_airesearch
NAT网关ID: ngw-2zeec9ulzgw7ywvx1pst6
地域: 华北2北京
VPC: vpc-2ze055cptkew9c38w4r06
SNAT表ID: stb-2zesszmzx1qpwf1cb2bry
创建时间: 2025-12-16 20:58:12 

# 弹性公网IP (EIP)
公网IP: 182.92.176.14 

# SNAT条目配置2条覆盖所有交换机
SNAT条目1:
  ID: snat-2zerlp4z0ed2isvq399gn
  源网段: 172.17.160.0/20
  交换机: vsw-2zevacop039bxrmj6yc0c (可用区F)
  公网IP: 182.92.176.14
  状态: ✅ 可用

SNAT条目2:
  ID: snat-2zegvesjxjwmw7j51m89m
  源网段: 172.17.192.0/20
  交换机: vsw-2zehoeyw9ldncymcyvfwq (可用区A)
  公网IP: 182.92.176.14
  状态: ✅ 可用

⚠️ 如果需要重新创建,操作步骤:

  1. 进入NAT网关控制台https://vpc.console.aliyun.com/nat
  2. 点击【创建NAT网关】
  3. 填写配置:
地域: 华北2北京
VPC: ai-clinical-vpc (vpc-2ze055cptkew9c38w4r06)
规格: 小型默认¥60/月)
计费方式: 按量付费
  1. 购买弹性公网IPEIP

    • 点击【绑定弹性公网IP】
    • 选择【购买并绑定EIP】
    • 带宽5Mbps按使用流量计费
    • 点击【确定】
  2. 配置SNAT规则让SAE能访问公网

    • 点击【SNAT管理】→【创建SNAT条目】
    • 选择交换机为每个交换机创建SNAT条目
    • 交换机1vsw-2zevacop039bxrmj6yc0c (可用区F)
    • 交换机2vsw-2zehoeyw9ldncymcyvfwq (可用区A)
    • 选择公网IP绑定的EIP
    • 点击【确定】

验证:

  • NAT网关状态为"运行中"
  • EIP已绑定182.92.176.14
  • SNAT条目状态为"可用"2条
  • 覆盖了所有交换机的网段

成本估算:

  • NAT网关¥60/月
  • EIP¥0.8/GB流量预计¥40/月)
  • 合计约¥100/月

1.3 购买RDS PostgreSQL数据库20分钟

目的: 托管的PostgreSQL数据库支持10个Schema隔离

操作步骤:

  1. 进入RDS控制台https://rdsnext.console.aliyun.com/
  2. 点击【创建实例】
  3. 填写配置:
付费类型: 包年包月首月¥70
地域: 华北2北京
可用区: 北京 可用区H
数据库类型: PostgreSQL
版本: 15
系列: 基础版(节省成本,不支持主备切换)
规格: 
  - CPU: 2核
  - 内存: 4GB
  - 存储: 50GB云盘ESSD
网络类型: 专有网络VPC
VPC: ai-clinical-vpc (vpc-2ze055cptkew9c38w4r06)
交换机: ai-clinical-vswitch-1 (vsw-2zevacop039bxrmj6yc0c)
  1. 高级配置:
数据库账号: airesearch
密码: 设置复杂密码记录到密码管理器Xibahe@fengzhibo117
数据库名称: ai_clinical_research
字符集: UTF8
  1. 点击【立即购买】等待创建约5分钟

⚠️ 关键配置(创建后):

  1. 白名单配置(必须配置,否则无法连接):

    • 进入实例详情 → 数据安全性 → 白名单设置
    • 点击【修改】
    • 添加:172.17.0.0/16整个VPC网段不要用单机IP
    • 点击【确定】
  2. 时区配置(避免日志时间错乱):

    • 进入实例详情 → 参数设置
    • 搜索:timezone
    • 修改值:Asia/Shanghai
    • 点击【提交参数】
    • 已配置可维护时间窗02:00-06:00 Asia/Shanghai UTC+8

实际RDS信息已部署

实例ID: pgm-2zex1m2y3r23hdn5
内网地址: pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432
数据库账号: airesearch
数据库密码: Xibahe@fengzhibo117
数据库名称: ai_clinical_research
VPC: vpc-2ze055cptkew9c38w4r06 (172.17.0.0/16)
资源组ID: rg-acfm4nrrfnu6tri
规格: 2核4GB (pg.n2.2c.1m)
最大连接数: 400
最大IOPS: 7550
PostgreSQL版本: 15.0
存储类型: 高性能云盘
白名单: 172.17.0.0/16 ✅
时区: Asia/Shanghai (UTC+8) ✅

验证:

  • 实例状态为"运行中"
  • 白名单已包含VPC网段 (172.17.0.0/16)
  • 时区已设置为 Asia/Shanghai
  • 可维护时间窗02:00-06:00夜间维护不影响白天使用

1.4 创建OSS存储桶10分钟

目的: 存储文献PDF、稿件文档等文件

实际OSS信息已部署

Bucket名称: ai-clinical-research
地域: 华北2北京
存储类型: 标准存储
读写权限: 私有
存储冗余类型: 同城冗余存储
外网Endpoint: oss-cn-beijing.aliyuncs.com
内网Endpoint: oss-cn-beijing-internal.aliyuncs.com
Bucket域名内网: ai-clinical-research.oss-cn-beijing-internal.aliyuncs.com
创建时间: 2025-12-16 20:22 
访问控制: 文件不可以被公共访问 ✅

⚠️ 如果需要重新创建,操作步骤:

  1. 进入OSS控制台https://oss.console.aliyun.com/
  2. 点击【创建Bucket】
  3. 填写配置:
Bucket名称: ai-clinical-research全局唯一
地域: 华北2北京
存储类型: 标准存储
读写权限: 私有(默认)
存储冗余类型: 同城冗余存储(推荐)
版本控制: 不开启
  1. 推荐的目录结构(应用会自动创建):
asl/        # AI文献筛选模块
  ├── source/      # 原始PDF文件
  └── extracted/   # 解析结果JSON
pkb/        # 个人知识库模块
  └── documents/   # 知识库文档
dc/         # 数据清洗模块
  ├── raw/         # 原始数据文件
  └── cleaned/     # 清洗后的数据
  1. OSS访问授权配置

方案A使用AccessKey已创建推荐初期使用

RAM用户: oss-bucket-put-object@1991407246109125.onaliyun.com
AccessKeyId: LTAI5tB2Dt3NdvBL3G7nYGv7
AccessKeySecret: 1iSN9k39RkApP93QjUhC1DcPIeMG4V
权限: OSS Bucket写入权限

⚠️ 安全警告:

  • AccessKey是敏感信息等同于密码
  • 请勿将AccessKey提交到Git仓库
  • 只在SAE环境变量中配置不要写入代码
  • 定期轮换AccessKey建议每3个月

方案B使用RAM角色推荐生产环境

  • 进入RAM控制台https://ram.console.aliyun.com/
  • 创建角色AliyunSAEDefaultRoleSAE默认角色
  • 授予权限AliyunOSSFullAccess
  • 优势无需管理AccessKey更安全

验证:

  • Bucket已创建成功
  • 内网Endpointoss-cn-beijing-internal.aliyuncs.com
  • Bucket域名ai-clinical-research.oss-cn-beijing-internal.aliyuncs.com
  • RAM用户已创建AccessKey已生成

1.5 创建容器镜像服务ACR5分钟

目的: 存储Docker镜像供SAE拉取部署

实际ACR信息已部署

服务类型: 个人版(免费)
命名空间: ai-clinical
用户名: gofeng117@163.com
Registry密码: fengzhibo117
公网域名: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
专有网络域名: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com

# 镜像仓库3个
仓库1 - 前端Nginx:
  仓库名称: ai-clinical_frontend-nginx
  公网地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx
  专有网络地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx
  类型: 私有
  状态: ✅ 已创建

仓库2 - Python微服务:
  仓库名称: python-extraction
  公网地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction
  专有网络地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction
  类型: 私有
  状态: ✅ 已创建

仓库3 - Node.js后端:
  仓库名称: nodejs-backend
  公网地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend
  专有网络地址: crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend
  类型: 私有
  状态: ✅ 已创建

⚠️ 如果需要重新创建,操作步骤:

  1. 进入容器镜像服务控制台:https://cr.console.aliyun.com/
  2. 选择【个人版】(免费)
  3. 设置Registry密码用于docker login
  4. 创建命名空间:ai-clinical
  5. 创建3个镜像仓库类型私有代码源本地仓库

验证:

  • 3个仓库创建成功
  • Registry地址crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
  • 专有网络地址:crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com

⚠️ 安全警告:

  • Registry密码是敏感信息等同于Docker镜像访问权限
  • 请勿将密码提交到Git仓库
  • 定期轮换密码建议每3个月

第二阶段数据库初始化30分钟

2.1 导出本地数据库5分钟

在本地项目根目录执行:

# 确保Docker正在运行
docker ps

# 导出数据库
docker exec ai-clinical-postgres pg_dump \
  -U postgres \
  -d ai_clinical_research \
  --no-owner \
  --no-acl \
  --clean \
  --if-exists \
  > rds_init.sql

# 验证文件大小应该有几百KB
ls -lh rds_init.sql

验证: rds_init.sql 文件存在,且大小 > 100KB


2.2 通过ECS跳板机连接RDS15分钟

⚠️ 为什么需要跳板机?

  • RDS在VPC内网本地电脑无法直接连接
  • 需要一台ECS服务器作为"桥梁"

操作步骤:

方案A使用现有Dify ECS如果已有

跳过ECS创建步骤直接使用Dify的ECS作为跳板机。

方案B创建临时ECS推荐初期使用

  1. 进入ECS控制台创建按量付费实例
地域: 华北2北京
规格: ecs.t6-c1m1.large1核1GB¥0.05/小时)
镜像: Ubuntu 22.04
网络: ai-clinical-vpc (vpc-2ze055cptkew9c38w4r06) / ai-clinical-vswitch-1
安全组: sg-2zedk6fi8sgmmcwdu7tu允许22端口SSH
购买时长: 按量付费
  1. 在本地创建SSH隧道
# 替换以下参数:
# - ECS_PUBLIC_IP: ECS的公网IP

ssh -N -L 5433:pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432 \
  root@ECS_PUBLIC_IP

# 输入ECS密码成功后命令会"卡住"(正常现象)
# 保持这个终端窗口打开

验证: 打开新终端,执行:

# 测试RDS连接通过SSH隧道
psql -h localhost -p 5433 -U airesearch -d ai_clinical_research

# 输入密码Xibahe@fengzhibo117
# 如果成功连接,说明隧道已建立

2.3 导入数据到RDS10分钟

在新终端窗口执行:

# 导入数据通过SSH隧道
psql -h localhost -p 5433 \
  -U airesearch \
  -d ai_clinical_research \
  -f rds_init.sql

# 输入密码Xibahe@fengzhibo117

# 验证导入成功
psql -h localhost -p 5433 \
  -U airesearch \
  -d ai_clinical_research \
  -c "\dt platform_schema.*"

# 应该看到 platform_schema 下的表

验证:

  • 看到 platform_schema.users
  • 看到 aia_schema.*
  • 看到 _prisma_migrations

⚠️ 重要: pg-boss的6个表job/queue等不在导出文件中会在应用首次启动时自动创建。


第三阶段Docker镜像构建与推送60分钟

3.1 登录阿里云容器镜像服务

在本地终端执行:

# 登录ACR个人版使用真实信息
docker login --username=gofeng117@163.com crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com

# 输入密码fengzhibo117
# 看到 "Login Succeeded" 表示登录成功

⚠️ 注意事项:

  • 个人版使用自定义域名,不是标准的 registry.cn-beijing.aliyuncs.com
  • 用户名:gofeng117@163.com(完整邮箱地址)
  • 密码:fengzhibo117Registry密码不是阿里云账号密码

3.2 构建Python微服务镜像15分钟

在项目根目录执行:

cd extraction_service

# 构建镜像确保Dockerfile存在
docker build -t ai-clinical/python-extraction:v1.0.0 .

# 打标签使用真实ACR地址
docker tag ai-clinical/python-extraction:v1.0.0 \
  crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0.0

docker tag ai-clinical/python-extraction:v1.0.0 \
  crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:latest

# 推送到ACR
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:latest

cd ..

验证:

  • 在ACR控制台看到镜像标签为 v1.0.0latest
  • 镜像地址:crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0.0

3.3 构建Node.js后端镜像20分钟

⚠️ 重要前置步骤复制Prisma目录

# 在项目根目录执行
cp -r prisma backend/

# 验证
ls backend/prisma/schema.prisma  # 应该存在

构建镜像:

cd backend

# 构建镜像
docker build -t ai-clinical/nodejs-backend:v1.0.0 .

# 打标签并推送使用真实ACR地址
docker tag ai-clinical/nodejs-backend:v1.0.0 \
  crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend:v1.0.0

docker tag ai-clinical/nodejs-backend:v1.0.0 \
  crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend:latest

docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend:v1.0.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend:latest

cd ..

验证:

  • ACR控制台看到Node.js镜像
  • 镜像地址:crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend:v1.0.0

3.4 构建前端Nginx镜像25分钟

在项目根目录执行:

cd frontend-v2

# 构建镜像包含React构建 + Nginx打包
docker build -t ai-clinical/frontend-nginx:v1.0.0 .

# 打标签并推送使用真实ACR地址注意仓库名称带下划线
docker tag ai-clinical/frontend-nginx:v1.0.0 \
  crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.0

docker tag ai-clinical/frontend-nginx:v1.0.0 \
  crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:latest

docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:latest

cd ..

⚠️ 注意: 前端仓库名称是 ai-clinical_frontend-nginx(带下划线),与后端不同。

验证:

  • ACR控制台看到3个镜像仓库每个都有 v1.0.0latest 标签
  • 前端镜像地址:crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.0

第四阶段SAE应用部署60分钟

4.1 部署Python微服务15分钟

操作步骤:

  1. 进入SAE控制台https://sae.console.aliyun.com/
  2. 点击【创建应用】
  3. 基础配置:
应用名称: python-extraction-service
命名空间: cn-beijing:test-airesearch已创建
地域: 华北2北京
VPC: ai-clinical-vpc (vpc-2ze055cptkew9c38w4r06)
安全组: sg-2zedk6fi8sgmmcwdu7tu
  1. 应用配置:
技术栈: 容器镜像
镜像: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/python-extraction:v1.0.0
镜像拉取策略: Always重要
版本: v1.0.0

⚠️ 重要: 使用个人版ACR地址不是标准的 registry.cn-beijing.aliyuncs.com

  1. 应用实例:
CPU: 1核
内存: 2GB
实例数: 1
  1. 高级配置:
端口: 8000
健康检查: HTTP
  - 路径: /health
  - 初始延迟: 30秒
  - 超时: 3秒
  - 检查间隔: 5秒

环境变量: 暂时为空Python微服务是纯计算服务
  1. 点击【创建】等待部署约5分钟

验证:

  • 应用状态为"运行中"
  • 健康检查通过
  • 记录内网地址(格式:172.17.x.x:8000

4.2 部署Node.js后端20分钟

操作步骤:

  1. 创建新应用:nodejs-backend-service
  2. 应用配置:
镜像: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/nodejs-backend:v1.0.0
镜像拉取策略: Always
CPU: 2核
内存: 4GB
实例数: 1
端口: 3001

⚠️ 重要: 使用个人版ACR地址

  1. 环境变量配置( 重要):
# ==================== 数据库配置 ====================
# ⚠️ 注意:密码中的 @ 符号必须转义为 %40
DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research
# ✅ 已使用实际RDS信息密码已转义

# ==================== 存储配置 ====================
STORAGE_TYPE=oss
OSS_REGION=oss-cn-beijing
OSS_BUCKET=ai-clinical-research
OSS_ENDPOINT=oss-cn-beijing-internal.aliyuncs.com
# ✅ OSS配置已使用实际Bucket信息
# Bucket域名: ai-clinical-research.oss-cn-beijing-internal.aliyuncs.com

# OSS访问凭证方案A使用AccessKey
OSS_ACCESS_KEY_ID=LTAI5tB2Dt3NdvBL3G7nYGv7
OSS_ACCESS_KEY_SECRET=1iSN9k39RkApP93QjUhC1DcPIeMG4V
# ⚠️ 注意AccessKey是敏感信息请勿提交到Git

# OSS访问凭证方案B使用RAM角色更安全
# 在SAE控制台配置RAM角色AliyunSAEDefaultRole
# 优势无需在环境变量中配置AccessKey

# ==================== 微服务地址 ====================
EXTRACTION_SERVICE_URL=http://172.17.x.x:8000
# ⚠️ 替换172.17.x.x从Python微服务控制台获取内网IP

DIFY_API_URL=http://placeholder/v1
DIFY_API_KEY=temp_placeholder
# ⚠️ 暂不部署Dify使用占位符PKB模块会自动禁用

# ==================== LLM配置 ====================
DEEPSEEK_API_KEY=sk-xxxxxxxx
# ⚠️ 替换为真实的DeepSeek API Key

# ==================== 应用配置 ====================
NODE_ENV=production
PORT=3001
  1. 启动命令(重要!):
/bin/sh -c "npx prisma migrate deploy && node dist/index.js"

⚠️ 说明:

  • npx prisma migrate deploy:部署数据库迁移
  • node dist/index.js:启动应用
  1. 健康检查:
路径: /health
初始延迟: 60秒留时间给Prisma迁移
超时: 5秒
  1. 点击【创建】等待部署约10分钟

验证:

  • 查看"实时日志",看到:
    ✅ Prisma migrate deploy 完成
    ✅ pg-boss 自动创建6个表
    ✅ 应用启动成功,监听 0.0.0.0:3001
    
  • 健康检查通过
  • 记录内网地址(格式:172.17.x.x:3001

⚠️ 如果启动失败:

常见原因:

  1. DATABASE_URL错误 → 检查密码、RDS地址
    • 当前RDSpgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com
    • 用户名airesearch
    • 密码中有特殊字符@URL中需要转义为 %40
  2. 白名单未配置 → 已确认配置172.17.0.0/16
  3. Prisma迁移失败 → 查看日志,确认数据库权限

⚠️ 密码特殊字符转义(重要):

# 原始密码Xibahe@fengzhibo117
# @ 符号需要转义为 %40

# 错误写法(会导致连接失败):
DATABASE_URL=postgresql://airesearch:Xibahe@fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research

# 正确写法:
DATABASE_URL=postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research

4.3 部署前端Nginx15分钟

操作步骤:

  1. 创建新应用:frontend-nginx
  2. 应用配置:
镜像: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/ai-clinical_frontend-nginx:v1.0.0
镜像拉取策略: Always
CPU: 1核
内存: 2GB
实例数: 1
端口: 80

⚠️ 重要:

  • 使用个人版ACR地址
  • 注意仓库名称是 ai-clinical_frontend-nginx(带下划线)
  1. 环境变量配置:
# 后端服务地址(内网)
BACKEND_SERVICE_HOST=172.17.x.x
BACKEND_SERVICE_PORT=3001
# ⚠️ 替换172.17.x.x从Node.js后端控制台获取内网IP
  1. 健康检查:
路径: /health
初始延迟: 10秒
超时: 3秒
  1. 配置公网访问(重要!):

    • 在应用详情 → 基本信息 → 公网访问
    • 点击【开启】
    • 获得公网域名(格式:xxxx.cn-beijing.alicontainer.com
  2. 点击【创建】等待部署约5分钟

验证:

  • 应用状态为"运行中"
  • 通过公网域名访问,看到登录页面

第五阶段验证与测试30分钟

5.1 健康检查验证5分钟

Python微服务

# 在本地终端执行(替换为实际公网地址,如果开启了)
# 或通过Node.js后端间接验证

# 直接测试如果Python开启了公网
curl http://python-service-public-url/health

# 预期响应:
{"status":"healthy"}

Node.js后端

curl http://backend-public-url/health

# 预期响应:
{"status":"ok","database":"connected","timestamp":"..."}

前端Nginx

curl http://frontend-public-url/health

# 预期响应:
{"status":"ok"}

5.2 功能测试15分钟

5.2.1 用户登录测试

  1. 访问前端公网地址:http://xxxxx.cn-beijing.alicontainer.com
  2. 使用测试账号登录:
    • 账号:admin@test.com
    • 密码:admin123(或你本地数据库中的密码)
  3. 验证:成功跳转到主页,显示用户名

5.2.2 文献筛选测试ASL模块

  1. 进入【AI智能文献】模块
  2. 创建新项目:
    项目名称: 测试项目
    研究主题: 糖尿病治疗
    
  3. 上传测试文献(小文件,< 5MB
  4. 验证:
    • 文件上传到OSS成功
    • 后端调用Python服务解析PDF
    • 数据库中生成记录

5.2.3 数据清洗测试DC模块

  1. 进入【数据清洗】模块
  2. 上传测试Excel文件
  3. 验证:
    • OSS上传成功
    • Python服务处理数据
    • 下载清洗结果

5.3 日志排查10分钟

查看SAE实时日志

Python微服务

SAE控制台 → python-extraction-service → 日志 → 实时日志

查看是否有错误日志ERROR/WARN

Node.js后端

SAE控制台 → nodejs-backend-service → 日志 → 实时日志

关键日志:
✅ Prisma connected
✅ pg-boss started
✅ Server listening on 0.0.0.0:3001

前端Nginx

SAE控制台 → frontend-nginx → 日志 → 访问日志

查看HTTP请求日志200/404/500状态码

🚨 常见问题与解决方案

问题1后端无法连接数据库

症状: Node.js日志显示 connection timeoutFATAL: no pg_hba.conf entry

解决方案:

  1. 检查RDS白名单

    RDS控制台 → 数据安全性 → 白名单设置
    确保包含172.17.0.0/16VPC网段
    
  2. 检查DATABASE_URL

    # ✅ 正确格式(特殊字符已转义):
    postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432/ai_clinical_research
    
    # 常见错误:
    - 密码中的 @ 符号未转义为 %40最常见
    - RDS地址错误应该用内网地址
    - 数据库名称错误
    
    # 特殊字符转义规则:
    @ -> %40
    # -> %23
    $ -> %24
    % -> %25
    

问题2后端调用Python微服务超时

症状: 日志显示 ECONNREFUSEDtimeout

解决方案:

  1. 检查Python微服务内网地址

    SAE控制台 → python-extraction-service → 基本信息 → 内网地址
    复制IP地址格式172.17.x.x
    
  2. 更新Node.js后端环境变量

    EXTRACTION_SERVICE_URL=http://172.17.x.x:8000
    
  3. 重启Node.js后端应用


问题3前端调用后端404

症状: 浏览器控制台显示 /api/xxx 404

解决方案:

  1. 检查前端环境变量:

    # 确认 BACKEND_SERVICE_HOST 是Node.js的内网IP
    BACKEND_SERVICE_HOST=172.17.x.x
    BACKEND_SERVICE_PORT=3001
    
  2. 检查Nginx配置已内置在镜像中

    location /api/ {
        proxy_pass http://${BACKEND_SERVICE_HOST}:${BACKEND_SERVICE_PORT};
    }
    
  3. 重启前端应用


问题4文件上传到OSS失败

症状: 上传文件时报错 OSS access denied

解决方案:

  1. 方案A使用AccessKey已配置

    # 确认Node.js后端环境变量已配置
    OSS_ACCESS_KEY_ID=LTAI5tB2Dt3NdvBL3G7nYGv7
    OSS_ACCESS_KEY_SECRET=1iSN9k39RkApP93QjUhC1DcPIeMG4V
    

    验证方法:

    • SAE控制台 → nodejs-backend-service → 应用设置 → 环境变量
    • 检查是否包含 OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET
  2. 方案B使用RAM角色推荐生产环境

    SAE控制台 → 应用设置 → 高级设置 → RAM角色
    选择AliyunSAEDefaultRole
    确保该角色有 AliyunOSSFullAccess 权限
    

    优势:

    • 无需在环境变量中配置AccessKey
    • 更安全避免AccessKey泄露风险
    • 支持自动轮换凭证
  3. 检查RAM用户权限

    RAM控制台 → 用户 → oss-bucket-put-object@1991407246109125.onaliyun.com
    确认权限PutObject写入权限
    

问题5AI功能无法调用DeepSeek API超时

症状: LLM对话功能报错 network timeout

解决方案:

  1. 检查NAT网关SNAT规则

    VPC控制台 → NAT网关 → NAT_airesearch → SNAT管理
    
    ✅ 已确认配置:
    - 交换机F (vsw-2zevacop039bxrmj6yc0c): 172.17.160.0/20 → 182.92.176.14 (可用)
    - 交换机A (vsw-2zehoeyw9ldncymcyvfwq): 172.17.192.0/20 → 182.92.176.14 (可用)
    
  2. 验证公网访问能力:

    # 在SAE应用实例中执行命令通过WebIDE
    curl https://api.deepseek.com/v1/models
    
    # 应该返回模型列表,而不是 timeout
    
  3. 如果SNAT未生效

    • 检查EIP是否已绑定
    • 检查SNAT条目状态是否为"可用"
    • 重启SAE应用

📊 成本估算

资源 规格 月成本 说明
RDS PostgreSQL 2核4GB/50GB ¥200-300 包年包月(已购买)
SAE - Python 1核2GB × 1实例 ¥60 按量付费闲时¥0
SAE - Node.js 2核4GB × 1实例 ¥120 按量付费
SAE - Frontend 1核2GB × 1实例 ¥60 按量付费
NAT网关 小型 ¥60 固定费用(已创建)
EIP流量费 5Mbps ¥40 按使用量计费(已配置)
OSS存储 10GB ¥2 ¥0.12/GB/月(已创建)
ACR容器镜像 个人版 ¥0 免费
总计 - ¥542-622/月 初创团队成本

节省成本建议:

  1. RDS购买包年包月首月¥70续费¥200/月)
  2. 开发环境只开1个SAE实例其他实例缩容到0
  3. 使用SAE的"闲时停机"功能(晚上自动停机)

🎯 下一步工作

短期1周内

  • 绑定自定义域名(阿里云域名服务 + SAE绑定
  • 配置HTTPS证书Let's Encrypt免费证书
  • 配置OSS CDN加速前端静态资源加速
  • 开启RDS自动备份数据安全第一

中期1个月内

  • 部署Dify平台启用PKB个人知识库功能
  • 配置监控告警ARMS应用监控
  • 优化数据库索引(提升查询性能)
  • 实施CI/CD自动化部署GitHub Actions

长期3个月后

  • 多实例部署(提升高可用性)
  • 数据库读写分离RDS主备版
  • OSS生命周期管理自动清理临时文件
  • 性能优化与成本优化

📚 相关文档


🆘 紧急联系

如果遇到无法解决的问题:

  1. 查看SAE实时日志90%的问题能从日志中发现)
  2. 检查环境变量配置DATABASE_URL、服务地址等
  3. 验证网络连通性VPC、白名单、NAT网关
  4. 参考详细部署文档(每个模块有独立的完整指南)

文档版本: v1.0
最后更新: 2025-12-16
维护者: AI临床研究平台技术团队