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
This commit is contained in:
2026-01-16 13:42:10 +08:00
parent 98d862dbd4
commit 66255368b7
560 changed files with 70424 additions and 52353 deletions

View File

@@ -3,7 +3,7 @@
**文档版本**: v1.0
**创建时间**: 2024-12-24
**适用范围**: AIclinicalresearch 平台 - Node.js 后端服务
**<EFBFBD><EFBFBD>霂餉<EFBFBD>?*: 餈鞟輕撌亦<E6928C><EFBFBD><E692A3><EFBFBD><EFBFBD>蝡臬<E89DA1><E887AC>穃極蝔见<E89D94>
**目标读者**: 运维工程师、后端开发工程师
---
@@ -14,7 +14,7 @@
3. [构建流程](#构建流程)
4. [镜像信息](#镜像信息)
5. [故障排查](#故障排查)
6. [<EFBFBD><EFBFBD>雿喳<EFBFBD>頝琶(#<23><>雿喳<E99BBF>頝?
6. [最佳实践](#最佳实践)
---
@@ -22,21 +22,21 @@
### 1.1 构建策略
<EFBFBD>祆活<EFBFBD><EFBFBD><EFBFBD><EFBFBD>鍂**<2A><EFBFBD><E5AFA1><EFBFBD>䲮獢㇂嚗<E38782>𧋦<EFBFBD><EFBFBD>霂?Docker<65><EFBFBD>嚗?*嚗𣬚㮾瘥𥪯<E798A5><EFBFBD>䲮獢<E4B2AE><E78DA2>隞乩<E99A9E>隡睃飵嚗?
本次构建采用**改进版方案B本地编译+Docker打包**,相比传统方案有以下优势:
| 撖寞<EFBFBD>憿?| 隡删<E99AA1><E588A0><EFBFBD> | <20><EFBFBD><E5AFA1><EFBFBD>䲮獢㇂ |
| 对比项 | 传统方案 | 改进版方案B |
|--------|----------|-------------|
| **TypeScript蝻𤥁<EFBFBD>** | Docker銝剜<EFBFBD>銵?| <20>砍𧑐憸<F0A79190><E686B8>霂?<3F>?|
| **靘肽<EFBFBD>摰㕑<EFBFBD>** | 摰峕㟲靘肽<EFBFBD> | 隞<><E99A9E>鈭找<E988AD>韏?<3F>?|
| **蝵𤑳<EFBFBD>靘肽<EFBFBD>** | 擃矋<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | 雿𠬍<E99BBF><F0A0AC8D>渡迅摰𡄯<E691B0> <20>?|
| **<EFBFBD><EFBFBD><EFBFBD>園𡢿** | ~10<EFBFBD><EFBFBD><EFBFBD> | ~5<EFBFBD><EFBFBD><EFBFBD> <20>?|
| **撟喳蝱<EFBFBD>澆捆<EFBFBD>?* | <20><EFBFBD><E58EB0>?| <20>𣳇<EFBFBD><F0A3B387>?<3F>?|
| **TypeScript编译** | Docker中执行 | 本地预编译 ✅ |
| **依赖安装** | 完整依赖 | 仅生产依赖 ✅ |
| **网络依赖** | 高(易超时) | 低(更稳定) ✅ |
| **构建时间** | ~10分钟 | ~5分钟 ✅ |
| **平台兼容性** | 有风险 | 无风险 ✅ |
### 1.2 构建成果
```
镜像名称: backend-service:v1.0
<EFBFBD>𨅯<EFBFBD>憭批<EFBFBD>: 838MB (<EFBFBD>讠憬<EFBFBD>?~186MB)
镜像大小: 838MB (压缩后 ~186MB)
镜像ID: a4ffb61c15af
构建时间: ~5分钟
ACR地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
@@ -46,10 +46,10 @@ ACR地址: crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical
## 2. 前置准备
### 2.1 <EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
### 2.1 环境检查
```powershell
# 1. <EFBFBD><EFBFBD>ocker<EFBFBD><EFBFBD>?
# 1. 检查Docker状态
docker --version
docker ps
@@ -63,7 +63,7 @@ cd D:\MyCursor\AIclinicalresearch\backend
### 2.2 代码准备
#### <EFBFBD>?敹<>◆摰峕<E691B0><E5B395><EFBFBD>郊撉?
#### ✅ 必须完成的步骤
**步骤1Prisma反向同步必须**
@@ -74,8 +74,8 @@ $env:DATABASE_URL = "postgresql://airesearch:Xibahe%40fengzhibo117@pgm-2zex1m2y3
# 执行Prisma反向同步
npx prisma db pull
# 颲枏枂摨磰砲<EFBFBD>曄內嚗?
# <EFBFBD>?Introspected 32 models and wrote them into prisma\schema.prisma
# 输出应该显示:
# Introspected 32 models and wrote them into prisma\schema.prisma
```
**步骤2生成Prisma Client**
@@ -83,8 +83,8 @@ npx prisma db pull
```powershell
npx prisma generate
# 颲枏枂摨磰砲<EFBFBD>曄內嚗?
# <EFBFBD>?Generated Prisma Client (v6.17.0)
# 输出应该显示:
# Generated Prisma Client (v6.17.0)
```
**步骤3TypeScript编译必须**
@@ -93,16 +93,16 @@ npx prisma generate
# 编译TypeScript代码
npm run build
# <EFBFBD>𣂼<EFBFBD>颲枏枂嚗?
# 成功输出:
# > ai-clinical-backend@1.0.0 build
# > tsc
# (<EFBFBD>𣳇<EFBFBD>霂臭縑<EFBFBD>?
# (无错误信息)
# 检查dist目录是否生成
ls dist
```
<EFBFBD>𩤃<EFBFBD> **<EFBFBD><EFBFBD><EFBFBD>鞟內**嚗𡁜<E59A97><F0A1819C>𦦵<EFBFBD>霂穃仃韐伐<E99F90><EFBFBD><EFBFBD><E29786>耨憭齿<E686AD><E9BDBF>ypeScript<EFBFBD>躰秤嚗?
⚠️ **重要提示**如果编译失败必须先修复所有TypeScript错误!
---
@@ -114,11 +114,11 @@ ls dist
# 1. 确保在backend目录
cd D:\MyCursor\AIclinicalresearch\backend
# 2. <EFBFBD><EFBFBD>ockerfile<EFBFBD>?dockerignore
# 2. 检查Dockerfile和.dockerignore
ls Dockerfile
ls .dockerignore
# 3. <EFBFBD>憪𧢲<EFBFBD>撱綽<EFBFBD><EFBFBD><EFBFBD>閬?<3F><><EFBFBD>嚗?
# 3. 开始构建需要5分钟
docker build -t backend-service:v1.0 .
# 4. 查看构建结果
@@ -127,22 +127,22 @@ docker images backend-service:v1.0
### 3.2 构建过程说明
**<EFBFBD>嗆挾1嚗帋<EFBFBD>韏硋<EFBFBD><EFBFBD><EFBFBD>蝥?<3F><><EFBFBD>嚗?*
**阶段1依赖安装约4分钟**
```dockerfile
FROM node:alpine AS builder
RUN apk add --no-cache openssl
COPY package*.json ./
COPY prisma ./prisma/
RUN npm ci --production # <EFBFBD><EFBFBD><EFBFBD><EFBFBD>鈭找<EFBFBD>韏?
RUN npm ci --production # 仅安装生产依赖
RUN npx prisma generate # 生成Prisma Client
```
**<EFBFBD>嗆挾2嚗𡁜<EFBFBD><EFBFBD>嗆𧋦<EFBFBD><EFBFBD>霂𤑳<EFBFBD><EFBFBD><EFBFBD>蝥?0蝘𡜐<E89D98>**
**阶段2复制本地编译结果约10秒**
```dockerfile
COPY dist ./dist # 复制本地已编译的TypeScript代码
```
**<EFBFBD>嗆挾3嚗朞<EFBFBD>銵屸<EFBFBD><EFBFBD>𤩺<EFBFBD><EFBFBD><EFBFBD><EFBFBD>蝥?<3F><><EFBFBD>嚗?*
**阶段3运行镜像打包约1分钟**
```dockerfile
FROM node:alpine
COPY --from=builder /app/node_modules ./node_modules
@@ -153,20 +153,20 @@ COPY --from=builder /app/prisma ./prisma
### 3.3 推送到ACR
```powershell
# 1. <EFBFBD><EFBFBD>ACR嚗<EFBFBD><EFBFBD>其葵鈭箇<EFBFBD>摰硺<EFBFBD><EFBFBD><EFBFBD>嚗?
# 1. 登录ACR使用个人版实例地址
echo "fengzhibo117" | docker login --username=gofeng117@163.com --password-stdin crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
# 输出Login Succeeded
# 2. <EFBFBD>𤘪<EFBFBD>蝑?
# 2. 打标签
docker tag backend-service:v1.0 crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
docker tag backend-service:v1.0 crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:latest
# 3. <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
# 3. 推送镜像
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:latest
# 颲枏枂嚗?
# 输出:
# v1.0: digest: sha256:a4ffb61c15af... size: 856
# latest: digest: sha256:a4ffb61c15af... size: 856
```
@@ -191,7 +191,7 @@ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-se
```yaml
镜像摘要: sha256:a4ffb61c15af1cd1ed9de187b4464a1aab773918e5b41b4df5b8ad96514f9941
憭批<EFBFBD>: 838MB (<EFBFBD>讠憬<EFBFBD>?~186MB)
大小: 838MB (压缩后 ~186MB)
架构: linux/amd64
基础镜像: node:alpine
Node版本: 22.x
@@ -205,7 +205,7 @@ Node版本: 22.x
├── node_modules/ # 生产依赖
├── dist/ # 编译后的JS代码
├── prisma/ # Prisma Schema
<EFBFBD>? <20><EFBFBD><E5A999><EFBFBD> schema.prisma
│ └── schema.prisma
├── package.json
└── uploads/ # 临时文件目录
```
@@ -216,7 +216,7 @@ Node版本: 22.x
CMD ["node", "dist/index.js"]
```
### 4.5 <EFBFBD>亙熒璉<EFBFBD><EFBFBD>?
### 4.5 健康检查
```dockerfile
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
@@ -229,19 +229,19 @@ HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
### 5.1 常见问题
#### <EFBFBD>?<3F><EFBFBD>1嚗関ypeScript蝻𤥁<EFBFBD>憭梯揖
#### ❌ 问题1TypeScript编译失败
**<EFBFBD><EFBFBD>𠶖嚗?*
**症状:**
```
error TS2554: Expected 2-3 arguments, but got 1.
error TS2322: Type 'XXX' is not assignable to type 'YYY'.
```
**<EFBFBD><EFBFBD>嚗?*
- Prisma<EFBFBD><EFBFBD><EFBFBD>峕郊<EFBFBD>𡒊撩撠穃<EFBFBD>蝟餃<EFBFBD>畾?
**原因:**
- Prisma反向同步后缺少关系字段
- 代码与Prisma生成的类型不匹配
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?*
**解决方案:**
```powershell
# 1. 重新同步Prisma
npx prisma db pull
@@ -253,57 +253,57 @@ npm run build
# 3. 如果还有错误检查tsconfig.json配置
```
#### <EFBFBD>?<3F><EFBFBD>2嚗鋽ocker<65><72>遣蝵𤑳<E89DB5><EFBFBD>𧒄
#### ❌ 问题2Docker构建网络超时
**<EFBFBD><EFBFBD>𠶖嚗?*
**症状:**
```
npm error code ECONNRESET
npm error network aborted
```
**<EFBFBD><EFBFBD>嚗?*
**原因:**
- npm镜像源网络不稳定
- npm ci 下载依赖失败
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?*
<EFBFBD>?**雿輻鍂<E8BCBB><EFBFBD><E5AFA1><EFBFBD>䲮獢㇂嚗<E38782>𧋦甈⊿<E79488><E28ABF><EFBFBD><E587BD><EFBFBD>嚗?*
**解决方案:**
**使用改进版方案B本次采用的方案**
- 本地预编译跳过Docker中的编译步骤
- 只安装生产依赖,减少网络传输
#### <EFBFBD>?<3F><EFBFBD>3嚗𡁏綫<F0A1818F><E7B6AB><EFBFBD>ACR憭梯揖嚗?03 Forbidden嚗?
#### ❌ 问题3推送到ACR失败403 Forbidden
**<EFBFBD><EFBFBD>𠶖嚗?*
**症状:**
```
Error response from daemon: login attempt to https://registry.cn-beijing.aliyuncs.com/v2/ failed with status: 403 Forbidden
```
**<EFBFBD><EFBFBD>嚗?*
**原因:**
- 使用了错误的ACR地址
- 应该使用个人版实例地址,不是企业版地址
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?*
**解决方案:**
```powershell
# <EFBFBD>?甇<><EFBFBD><EFBC86>蒈敶訫𧑐<E8A8AB><F0A79190><EFBFBD>葵鈭箇<E988AD>摰硺<E691B0>嚗?
# ✅ 正确的登录地址(个人版实例)
docker login crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com
# <EFBFBD>?<3F>躰秤<E8BAB0><E7A7A4>蒈敶訫𧑐<E8A8AB><F0A79190><EFBFBD><E59A97>銝𡁶<E98A9D>嚗?
# ❌ 错误的登录地址(企业版)
docker login registry.cn-beijing.aliyuncs.com
```
#### <EFBFBD>?<3F><EFBFBD>4嚗间PC<50><43><EFBFBD><EFBFBD><EFBFBD><E595A3><EFBFBD><E588B8><EFBFBD><EFBFBD>?
#### ❌ 问题4VPC内网地址推送超时
**<EFBFBD><EFBFBD>𠶖嚗?*
**症状:**
```
failed to do request: Head "https://crpi-cd5ij4pjt65mweeo-vpc.cn-beijing.personal.cr.aliyuncs.com/...": net/http: TLS handshake timeout
```
**<EFBFBD><EFBFBD>嚗?*
- VPC<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>券燵<EFBFBD><EFBFBD>VPC<EFBFBD><EFBFBD><EFBFBD>?
**原因:**
- VPC内网地址只能在阿里云VPC内访问
- 本地开发环境无法访问VPC内网
**<EFBFBD><EFBFBD><EFBFBD><EFBFBD>嚗?*
**解决方案:**
```powershell
# <EFBFBD>砍𧑐撘<EFBFBD><EFBFBD>𤑳㴓憓<EFBFBD><EFBFBD><EFBFBD>蝵穃𧑐<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
# 本地开发环境使用公网地址推送
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
# SAE部署时使用VPC内网地址拉取在SAE控制台配置
@@ -312,7 +312,7 @@ docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinica
### 5.2 验证镜像
```powershell
# 1. <EFBFBD><EFBFBD>仿<EFBFBD><EFBFBD>𤩺糓<EFBFBD><EFBFBD><EFBFBD>?
# 1. 检查镜像是否存在
docker images backend-service:v1.0
# 2. 查看镜像详细信息
@@ -329,7 +329,7 @@ docker run -d `
# 4. 查看容器日志
docker logs backend-test
# 5. 瘚贝<EFBFBD><EFBFBD>亙熒璉<EFBFBD><EFBFBD>?
# 5. 测试健康检查
curl http://localhost:3001/health
# 6. 清理测试容器
@@ -339,23 +339,23 @@ docker rm backend-test
---
## 6. <EFBFBD><EFBFBD>雿喳<EFBFBD>頝?
## 6. 最佳实践
### 6.1 <EFBFBD><EFBFBD><EFBFBD>齿<EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
### 6.1 构建前检查清单
- [ ] 撌脣<EFBFBD><EFBFBD>辥risma<EFBFBD><EFBFBD><EFBFBD>峕郊嚗Ǒnpx prisma db pull`嚗?
- [ ] 撌脩<EFBFBD><EFBFBD>risma Client嚗Ǒnpx prisma generate`嚗?
- [ ] TypeScript蝻𤥁<EFBFBD><EFBFBD>𣂼<EFBFBD>嚗Ǒnpm run build`嚗?
- [ ] 已完成Prisma反向同步`npx prisma db pull`
- [ ] 已生成Prisma Client`npx prisma generate`
- [ ] TypeScript编译成功(`npm run build`
- [ ] dist目录已生成且包含所有编译后的JS文件
- [ ] Docker Desktop已启动并运行
- [ ] 网络连接正常
### 6.2 版本管理
**<EFBFBD>𨅯<EFBFBD><EFBFBD><EFBFBD>倌閫<EFBFBD><EFBFBD>嚗?*
**镜像标签规范:**
```
v1.0 - 特定版本(推荐用于生产环境)
latest - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>穿<EFBFBD><EFBFBD><EFBFBD>瘚贝<EFBFBD><EFBFBD><EFBFBD>嚗?
latest - 最新版本(用于测试环境)
v1.0.1 - Bug修复版本
v1.1.0 - 功能更新版本
```
@@ -365,7 +365,7 @@ v1.1.0 - 功能更新版本
# 生产环境部署(推送特定版本)
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
# 瘚贝<EFBFBD><EFBFBD><EFBFBD><EFBFBD>函蔡嚗<EFBFBD><EFBFBD><EFBFBD>嗆綫<EFBFBD><EFBFBD>atest嚗?
# 测试环境部署同时推送latest
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:v1.0
docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-service:latest
```
@@ -374,11 +374,11 @@ docker push crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinica
**1. 利用Docker缓存**
```dockerfile
# <EFBFBD>?<3F><><EFBFBD><EFBFBD>ackage.json<EFBFBD><EFBFBD><EFBFBD>韏𣇉<EFBFBD>摮?
# ✅ 先复制package.json,利用依赖缓存
COPY package*.json ./
RUN npm ci --production
# <EFBFBD>?<3F><><EFBFBD>𤾸<EFBFBD><F0A4BEB8>嗡誨<E597A1><E8AAA8><EFBFBD><EFBFBD><E99A9E><EFBFBD><EFBFBD>銝滚蔣<E6BB9A><EFBFBD>韏硋<E99F8F>蝻枏<E89DBB>
# ✅ 最后复制代码,代码变化不影响依赖层缓存
COPY dist ./dist
```
@@ -394,9 +394,9 @@ tests
.git
```
**3. 憭𡁻𧫴畾菜<EFBFBD>撱?*
**3. 多阶段构建**
```dockerfile
# <EFBFBD>嗆挾1嚗帋<EFBFBD>韏硋<EFBFBD>鋆?
# 阶段1依赖安装
FROM node:alpine AS builder
...
@@ -408,8 +408,8 @@ COPY --from=builder ...
### 6.4 安全建议
1. **不要在镜像中包含敏感信息**
- <EFBFBD>?銝滩<E98A9D><E6BBA9>𢲩.env`<60><>辣憭滚<E686AD><E6BB9A><EFBFBD><E59C88>?
- <EFBFBD>?雿輻鍂SAE<41><EFBFBD><E887AC><EFBFBD>瘜典<E7989C><E585B8>滨蔭
- ❌ 不要把`.env`文件复制到镜像
- ✅ 使用SAE环境变量注入配置
2. **使用非root用户运行**
```dockerfile
@@ -431,10 +431,10 @@ COPY --from=builder ...
# ==================== 阶段 1: 依赖安装阶段 ====================
FROM node:alpine AS builder
# <EFBFBD>踵揢Alpine<EFBFBD>𨅯<EFBFBD>皞𣂷蛹<EFBFBD><EFBFBD>鈭煾<EFBFBD><EFBFBD>𧶏<EFBFBD><EFBFBD><EFBFBD>蝵𤑳<EFBFBD><EFBFBD><EFBFBD>嚗?
# 替换Alpine镜像源为阿里云镜像(解决网络问题)
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# 摰㕑<EFBFBD> Prisma 餈鞱<EFBFBD><EFBFBD><EFBFBD>韏?
# 安装 Prisma 运行时依赖
RUN apk add --no-cache openssl
WORKDIR /app
@@ -442,7 +442,7 @@ WORKDIR /app
# 1. 复制依赖文件
COPY package*.json ./
# 2. 憭滚<EFBFBD> Prisma Schema<EFBFBD>鍂鈭𡒊<EFBFBD><EFBFBD>risma Client嚗?
# 2. 复制 Prisma Schema用于生成Prisma Client
COPY prisma ./prisma/
# 3. 只安装生产依赖(大幅减少网络传输和安装时间)
@@ -455,16 +455,16 @@ RUN npm config set registry https://registry.npmmirror.com && \
# 4. 生成 Prisma Client生产环境需要
RUN npx prisma generate
# 5. 憭滚<EFBFBD><EFBFBD>砍𧑐撌脩<EFBFBD>霂穃末<EFBFBD>?dist <20><>辣憭對<E686AD>頝唾<E9A09D>TypeScript蝻𤥁<EFBFBD>嚗?
# 5. 复制本地已编译好的 dist 文件夹(跳过TypeScript编译)
COPY dist ./dist
# ==================== 阶段 2: 运行阶段 ====================
FROM node:alpine
# <EFBFBD>踵揢Alpine<EFBFBD>𨅯<EFBFBD>皞𣂷蛹<EFBFBD><EFBFBD>鈭煾<EFBFBD><EFBFBD>𧶏<EFBFBD><EFBFBD><EFBFBD>蝵𤑳<EFBFBD><EFBFBD><EFBFBD>嚗?
# 替换Alpine镜像源为阿里云镜像(解决网络问题)
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# 摰㕑<EFBFBD>餈鞱<EFBFBD><EFBFBD><EFBFBD>韏?+ <20>嗅躹<E59785>唳旿
# 安装运行时依赖 + 时区数据
RUN apk add --no-cache \
openssl \
curl \
@@ -474,13 +474,13 @@ RUN apk add --no-cache \
# ⚠️ 统一时区Asia/Shanghai
ENV TZ=Asia/Shanghai
# <EFBFBD>𥕦遣<EFBFBD>?root <20><EFBFBD><EFBFBD><E59A97><EFBFBD><EFBFBD>雿喳<E99BBF>頝蛛<E9A09D>
# 创建非 root 用户(安全最佳实践)
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
WORKDIR /app
# 隞擧<EFBFBD>撱粹𧫴畾萄<EFBFBD><EFBFBD>嗡漣<EFBFBD>?
# 从构建阶段复制产物
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
@@ -492,7 +492,7 @@ RUN mkdir -p /app/uploads && chown -R nodejs:nodejs /app/uploads
# 切换到非 root 用户
USER nodejs
# <EFBFBD>亙熒璉<EFBFBD><EFBFBD>?
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD node -e "require('http').get('http://localhost:3001/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1); })"
@@ -505,7 +505,7 @@ CMD ["node", "dist/index.js"]
---
## <EFBFBD><EFBFBD><EFBFBD>B嚗?dockerignore摰峕㟲<EFBFBD><EFBFBD>
## 附录B.dockerignore完整内容
```
# Node.js
@@ -513,12 +513,12 @@ node_modules
npm-debug.log
yarn-error.log
# <EFBFBD><EFBFBD><EFBFBD>隞?
# 开发文件
.env
.env.*
*.local
# <EFBFBD><EFBFBD>遣鈭抒<EFBFBD><EFBFBD>㺿餈𥟇䲮獢㇂嚗帋蝙<EFBFBD>冽𧋦<EFBFBD><EFBFBD>霂穃末<EFBFBD><EFBFBD>ist嚗?
# 构建产物改进方案B使用本地编译好的dist
# dist # 暂时注释掉允许复制本地dist
# 测试文件
@@ -528,7 +528,7 @@ tests
*.spec.ts
coverage
# <EFBFBD><EFBFBD><EFBFBD>䔶葩<EFBFBD><EFBFBD>隞?
# 文档和临时文件
docs
*.md
.vscode
@@ -536,7 +536,7 @@ docs
.DS_Store
Thumbs.db
# 銝𠹺<EFBFBD><EFBFBD><EFBFBD>辣嚗<EFBFBD><EFBFBD>銵峕𧒄<EFBFBD><EFBFBD><EFBFBD>嚗?
# 上传文件(运行时生成)
uploads/*
# Git
@@ -554,7 +554,7 @@ tmp
*.swo
*~
# <EFBFBD>唳旿摨𤘪<EFBFBD>隞塚<EFBFBD>SQLite嚗<EFBFBD><EFBFBD><EFBFBD>𨀣<EFBFBD>嚗?
# 数据库文件SQLite如果有
*.db
*.sqlite
@@ -566,17 +566,17 @@ scripts/*.ts
---
## <EFBFBD><EFBFBD><EFBFBD>C嚗𡁶㮾<EFBFBD><EFBFBD>獢?
## 附录C相关文档
- [Node.js后端-SAE容器部署指南](./05-Node.js后端-SAE容器部署指南.md)
- [部署进度总览](./00-部署进度总览.md)
- [PostgreSQL<EFBFBD>唳旿摨㯄<EFBFBD>蝵脫<EFBFBD>雿𨀣<EFBFBD><EFBFBD>䀉(./08-PostgreSQL<EFBFBD>唳旿摨㯄<EFBFBD>蝵脫<EFBFBD>雿𨀣<EFBFBD><EFBFBD>?md)
- [Python敺格<EFBFBD><EFBFBD>?SAE<41>函蔡<E587BD><EFBFBD><E6BBA2><EFBFBD>](./09-Python敺格<E695BA><E6A0BC>?SAE<41>函蔡<E587BD><EFBFBD><E6BBA2><EFBFBD>.md)
- [PostgreSQL数据库部署操作手册](./08-PostgreSQL数据库部署操作手册.md)
- [Python微服务-SAE部署操作手册](./09-Python微服务-SAE部署操作手册.md)
---
**<EFBFBD><EFBFBD>﹝蝏湔擪<EFBFBD>?*: AI Assistant
**<EFBFBD><EFBFBD><EFBFBD>擧凒<EFBFBD>?*: 2024-12-24
**文档维护者**: AI Assistant
**最后更新**: 2024-12-24
**版本**: v1.0
@@ -606,6 +606,5 @@ scripts/*.ts