18 KiB
18 KiB
设计文档:从正式系统恢复源码
概述
本设计文档描述了如何从正式系统的 Docker 容器中提取源码,对比本地差异,恢复缺失文件,并部署到影子系统进行测试验证的完整方案。
架构
系统组件
┌─────────────────────────────────────────────────────────────┐
│ 源码恢复流程 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 步骤1: 连接正式系统容器 │
│ - SSH 到服务器 192.168.58.20 │
│ - 访问容器 youyidian-3d-material │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 步骤2: 提取源码文件列表 │
│ - 列出容器内 /app 目录的所有文件 │
│ - 排除 node_modules, .next, uploads 等 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 步骤3: 对比本地源码 │
│ - 检查本地缺失的文件 │
│ - 检查内容不一致的文件 │
│ - 生成差异报告 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 步骤4: 复制缺失文件 │
│ - 使用 docker cp 或 scp 复制文件 │
│ - 保持目录结构 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 步骤5: 验证构建 │
│ - npm install │
│ - npm run build │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 步骤6: 部署到影子系统 │
│ - 运行 deploy-local-build.ps1 -Target shadow │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 步骤7: 功能测试 │
│ - 访问 http://192.168.58.20:5320 │
│ - 测试关键功能 │
└─────────────────────────────────────────────────────────────┘
组件和接口
1. 源码提取工具
功能: 从 Docker 容器中提取源码文件
方法:
-
方法 A: 使用
docker cp命令ssh root@192.168.58.20 "docker cp youyidian-3d-material:/app /tmp/source" scp -r root@192.168.58.20:/tmp/source/* D:\gongxiangp2\ -
方法 B: 使用
docker exec+ tarssh root@192.168.58.20 "docker exec youyidian-3d-material tar czf /tmp/source.tar.gz -C /app ." scp root@192.168.58.20:/tmp/source.tar.gz D:\gongxiangp2\ tar -xzf source.tar.gz
推荐: 方法 B,因为可以一次性打包,传输更快
2. 文件对比工具
功能: 对比本地源码和容器源码的差异
实现:
# 获取容器内文件列表
ssh root@192.168.58.20 "docker exec youyidian-3d-material find /app -type f" > container-files.txt
# 获取本地文件列表
Get-ChildItem -Recurse -File | Select-Object FullName > local-files.txt
# 对比差异
Compare-Object (Get-Content container-files.txt) (Get-Content local-files.txt)
3. 构建验证工具
功能: 验证恢复后的源码能否正常构建
步骤:
- 安装依赖:
npm install - 构建项目:
npm run build - 检查构建输出:
.next目录应该存在且包含构建文件
4. 部署工具
功能: 将恢复的源码部署到影子系统
使用:
.\deploy-local-build.ps1 -Target shadow
该脚本应该:
- 构建 Docker 镜像
- 停止旧的影子系统容器
- 启动新的影子系统容器
- 验证容器状态
数据模型
文件差异报告
interface FileDifference {
path: string; // 文件路径
status: 'missing' | 'different' | 'extra'; // 状态
importance: 'critical' | 'important' | 'optional'; // 重要性
category: 'api' | 'page' | 'component' | 'lib' | 'config' | 'other'; // 分类
}
interface DifferenceReport {
timestamp: Date; // 报告生成时间
totalFiles: number; // 总文件数
missingFiles: FileDifference[]; // 缺失的文件
differentFiles: FileDifference[]; // 内容不同的文件
extraFiles: FileDifference[]; // 本地多余的文件
}
功能验证清单
interface FeatureTest {
name: string; // 功能名称
category: string; // 功能分类
tested: boolean; // 是否已测试
passed: boolean; // 是否通过
notes: string; // 备注
}
interface FeatureReport {
timestamp: Date; // 报告生成时间
totalFeatures: number; // 总功能数
testedFeatures: number; // 已测试功能数
passedFeatures: number; // 通过的功能数
features: FeatureTest[]; // 功能列表
}
正确性属性
属性是一个特征或行为,应该在系统的所有有效执行中保持为真——本质上是关于系统应该做什么的正式陈述。属性作为人类可读规范和机器可验证正确性保证之间的桥梁。
属性 1: 文件完整性
对于任何从容器提取的源码文件,该文件应该在本地存在且内容一致
验证: 需求 1.2, 1.3
属性 2: 目录结构一致性
对于任何容器中的目录结构,本地应该有相同的目录结构
验证: 需求 1.2
属性 3: 构建可重复性
对于任何恢复后的源码,执行 npm run build 应该成功生成 .next 目录
验证: 需求 5.2
属性 4: 功能等价性
对于任何正式系统中的功能,影子系统应该有相同的功能表现
验证: 需求 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7
错误处理
1. SSH 连接失败
- 错误: 无法连接到服务器 192.168.58.20
- 处理: 检查网络连接,确认 SSH 密钥配置正确
2. Docker 容器不存在
- 错误: 容器 youyidian-3d-material 不存在
- 处理: 检查容器名称,确认容器正在运行
3. 文件复制失败
- 错误: 无法复制文件到本地
- 处理: 检查磁盘空间,确认文件权限
4. 构建失败
- 错误: npm run build 失败
- 处理:
- 检查 node_modules 是否完整
- 检查 package.json 依赖版本
- 查看构建错误日志
- 检查环境变量配置
5. 部署失败
- 错误: 部署脚本执行失败
- 处理:
- 检查 Docker 服务状态
- 检查端口占用情况
- 查看部署脚本日志
测试策略
单元测试
- 测试文件对比逻辑
- 测试文件复制功能
- 测试差异报告生成
集成测试
- 测试完整的源码提取流程
- 测试构建验证流程
- 测试部署流程
功能测试
- 在影子系统上测试所有关键功能
- 对比正式系统和影子系统的功能表现
- 记录测试结果
测试清单
用户认证
- 钉钉登录
- 邮箱密码登录
- 用户注册
素材管理
- 素材上传(所有类型)
- 素材浏览(瀑布流)
- 素材筛选(类型、店铺、场景、产品类别)
- 素材搜索(防抖处理)
- 素材详情
- 素材编辑
- 素材下载(包括模特类自动打包)
- 点赞功能
- 收藏功能
- 分享功能
滚动位置保存
- 从详情页返回首页时保持滚动位置
- 筛选条件保存和恢复
个人中心
- 我的素材
- 我的收藏
- 头像上传
- 个人信息修改
管理员功能
- 用户管理
- 素材管理
- 分类管理(店铺、场景、平台、产品类别)
- 部门管理
- 系统设置
- 回收站
辅助功能
- 排行榜
- AI 聊天
- 弹幕
- 网络诊断
- 更新日志
视频处理
- 视频上传
- 视频转码
- 视频预览
实施步骤
阶段 1: 源码提取(预计 30 分钟)
- 连接到服务器
- 从容器打包源码
- 下载到本地
- 解压并检查
阶段 2: 差异分析(预计 20 分钟)
- 生成文件列表
- 对比差异
- 生成差异报告
- 标注重要文件
阶段 3: 文件恢复(预计 10 分钟)
- 复制缺失文件
- 更新不一致文件
- 验证文件完整性
阶段 4: 构建验证(预计 15 分钟)
- 安装依赖
- 执行构建
- 检查构建输出
- 修复构建错误(如有)
阶段 5: 部署测试(预计 20 分钟)
- 部署到影子系统
- 验证容器状态
- 访问影子系统
- 初步功能测试
阶段 6: 功能验证(预计 60 分钟)
- 测试用户认证
- 测试素材管理
- 测试筛选和搜索
- 测试滚动位置保存
- 测试管理员功能
- 测试辅助功能
- 记录测试结果
阶段 7: 文档更新(预计 15 分钟)
- 更新功能恢复进度文档
- 记录遇到的问题和解决方案
- 更新部署文档
总预计时间: 约 2.5 小时
风险和缓解措施
风险 1: 源码提取不完整
- 影响: 恢复的源码缺少关键文件
- 缓解:
- 提取前先列出所有文件
- 提取后验证文件数量
- 对比文件大小
风险 2: 构建失败
- 影响: 无法生成可部署的镜像
- 缓解:
- 先在本地测试构建
- 检查依赖版本
- 查看构建日志
风险 3: 功能不一致
- 影响: 影子系统功能与正式系统不一致
- 缓解:
- 详细的功能测试清单
- 对比测试结果
- 记录差异并修复
风险 4: 数据库不兼容
- 影响: 影子系统无法连接数据库或数据结构不匹配
- 缓解:
- 检查数据库连接配置
- 验证数据库 schema
- 执行必要的迁移
生产系统问题分析(2025-12-20)
🔍 数据不一致问题调查结果
数据库状态(正常)
-
生产数据库 (
lobechat@ 192.168.58.20:5432):- 总记录数: 1530条
- 未删除素材: 1524条
- 软删除素材: 6条
- 结论: 数据库没有被覆盖,数据完整
-
影子数据库 (
lobechat_stage@ 192.168.58.20:5432):- 未删除素材: 1049条
- 结论: 影子系统数据独立,没有混乱
发现的BUG
BUG 1: 统计API包含软删除数据
- API:
/api/materials/stats - 问题: 返回
total: 1530(包含6条软删除数据) - 正确值: 应该是
1524 - 影响: "使用店铺"的"全部"按钮显示错误数字(1530)
- 修复: 添加
WHERE "deletedAt" IS NULL过滤条件
BUG 2: 分页API返回全部数据
- API:
/api/materials?page=X&pageSize=20 - 问题: 无论请求哪一页,都返回全部1524条数据
- 影响:
- 前端性能严重下降(一次加载1524条数据)
- 用户看到的"瀑布流"实际上是全部数据
- 用户报告滚动到底部只显示1026个素材(可能是前端渲染限制)
- 修复: 修复分页逻辑,确保正确使用
skip和take
BUG 3: 分类统计API未过滤软删除
- API:
/api/categories - 问题: 统计每个分类的素材数量时未过滤软删除数据
- 影响: 分类按钮显示的数字可能包含已删除素材
- 修复: 添加
WHERE "deletedAt" IS NULL过滤条件
容器状态
- 正式系统容器: 不在本地服务器上(在192.168.58.20服务器上运行)
- 端口4320: 正常运行,可以访问
- 本地源码: 与生产系统不一致,需要从生产容器恢复
📁 素材存储路径问题
重要说明:新老素材存储位置不同
老素材存储(2025-10-27之前)
-
预览图: MinIO S3(老bucket配置)
- Endpoint:
https://s3.1080p.hk - Bucket:
jsxiangche(老bucket,无路径前缀) - URL格式:
https://s3.1080p.hk/jsxiangche/preview-{timestamp}-{hash}.webp - 示例:
https://s3.1080p.hk/jsxiangche/preview-1761537819211-edb4a190180c24f9.webp
- Endpoint:
-
源文件(压缩包): 本地文件系统
- 路径:
uploads/material-{timestamp}-{hash}.zip - 相对路径格式(数据库存储)
- 示例:
uploads/material-1761537819728-8fb5090670b5b986.zip
- 路径:
新素材存储(2025-10-27之后)
-
预览图/视频缩略图: MinIO S3(新路径配置)
- Endpoint:
https://s3.1080p.hk - Bucket:
jsxiangche(同一bucket,但有路径前缀) - 路径前缀:
由壹点AI/ - URL格式:
https://s3.1080p.hk/jsxiangche/由壹点AI/video-thumb-{timestamp}-{hash}.jpg - 示例:
https://s3.1080p.hk/jsxiangche/由壹点AI/video-thumb-1766220802404-d6c20cf8f82c0c80.jpg
- Endpoint:
-
源文件(压缩包/视频): 本地文件系统
- 路径:
uploads/video-{timestamp}-{hash}.mp4或uploads/material-{timestamp}-{hash}.zip - 相对路径格式(数据库存储)
- 示例:
uploads/video-1766220805356-02770716caf02d9c.mp4
- 路径:
处理策略
- ⚠️ 不要移动或修改老素材
- 保持老素材在原位置,确保能正常访问和下载
- 老素材的路径信息已存储在数据库中
- 所有新上传的素材统一使用新位置(带
由壹点AI/前缀)
兼容性要求
- 下载功能已兼容新老路径(使用相同的
./uploads目录) - 根据数据库中的路径信息自动判断使用哪个存储位置
- 确保老素材和新素材都能正常下载
- S3 预览图通过
previewUrl字段直接访问,无需特殊处理
数据库字段说明
// materials 表
{
zipFilePath: string; // 本地压缩包路径(可能是老路径或新路径)
previewUrl: string; // 预览图URL(S3或老存储)
// ... 其他字段
}
🎯 源码恢复优先级
高优先级(必须恢复)
/api/materials/route.ts- 修复分页BUG/api/materials/stats/route.ts- 修复统计BUG/api/categories/route.ts- 修复分类统计BUG/api/materials/download/route.ts- 确保支持新老路径- 所有素材上传相关代码 - 确保新素材使用新路径
中优先级(建议恢复)
- 所有
/api目录下的文件 - 所有
/app目录下的页面文件 - 所有
/components目录下的组件文件
低优先级(可选)
- 配置文件(如果本地已正确配置)
- 文档文件
⚠️ 恢复注意事项
-
不要直接修改生产系统
- 只从生产系统读取和复制文件
- 所有修改先在本地测试
- 测试通过后部署到影子系统
- 影子系统验证通过后才部署到生产
-
保护用户数据
uploads目录不要删除或覆盖- 老素材路径不要修改
- 数据库操作前必须备份
-
环境隔离
- 生产系统(4320): 数据库
lobechat, Redis 6379 - 影子系统(5320): 数据库
lobechat_stage, Redis 6380 - 确保环境变量正确配置
- 生产系统(4320): 数据库
后续工作
- 建立版本控制: 恢复完成后立即初始化 Git 仓库
- 设置 CI/CD: 配置自动化构建和部署流程
- 代码审查: 审查恢复的代码,添加必要的注释
- 性能优化: 识别并优化性能瓶颈
- 安全加固: 检查安全漏洞,更新依赖包
- 修复已知BUG: 修复上述发现的3个BUG
- 路径兼容性测试: 确保新老素材都能正常下载