Protect upload cleanup and atomic completion paths, add durable media worker leases and brand asset validation, and introduce verified migration/bootstrap/deployment gates.
10 KiB
inclusion
| inclusion |
|---|
| always |
由壹点3D素材平台 - 项目记忆库
企业内部素材分享系统,支持15种素材类型的上传、管理和下载。
用户偏好
- 能用中文就用中文(文档、注释)
- 不写不重要的文档
- 不喜欢垃圾文件、残留文件
- 修复原则: 优先找到问题根源彻底解决,不要打补丁(除非不得已)
技术栈
Next.js 14 + React 18 + TypeScript + TailwindCSS + Prisma + PostgreSQL + MinIO S3 + NextAuth + 钉钉登录
处理库:FFmpeg(视频)、Sharp(图片)、music-metadata(音频)、ag-psd(PSD)
生产环境
- 数据库:
lobechat@192.168.58.20:5432(影子:lobechat_stage) - S3:
https://s3.jiansun.vip,Bucket:gongxiangpan,前缀:由壹点AI/ - 正式: 端口4320 | 影子: 端口5320
- 本地存储:
/mnt/PoolOne/youyidian-uploads(当前正式独立 ZFS 数据集);历史路径/mnt/PoolOne/apps/youyidian-3d/uploads仅在人工显式选择兼容模式时使用,禁止据旧容器或旧文档自动推断。
SSH 远程调用
推荐方式:使用专用查询脚本
# 查询3D原图等类型的资产信息
.\scripts\query-3d-original-assets.ps1
# 查询所有素材类型
.\scripts\query-material-types.ps1
# 指定正式环境
.\scripts\query-3d-original-assets.ps1 -Target production
原始方式(如需手动调用):
# 使用 ssh(推荐)
ssh root@192.168.58.20 '命令'
# 查询数据库(通过 PostgreSQL 容器)
ssh root@192.168.58.20 "docker exec -i gongxiangpan-postgres-1 psql -U gongxiangpan -d lobechat -c 'SQL语句'"
注意事项:
- PostgreSQL 容器名:
gongxiangpan-postgres-1 - 数据库表名:
materials(复数,全小写) - 列名:驼峰式(如
materialType),需要用双引号包裹 - 外键列名:下划线式(如
material_id),不需要引号 - 复杂 SQL 查询建议使用专用脚本(Base64 编码避免引号问题)
分界点:2025-10-27
| 项目 | 老素材 | 新素材 |
|---|---|---|
| S3 | s3.1080p.hk/jsxiangche(仅历史读取) |
s3.jiansun.vip/gongxiangpan/由壹点AI/ |
| 识别 | previewUrl不含由壹点AI/ |
previewUrl含由壹点AI/ |
原则: 老素材地址只做读取兼容,不得用于默认值、新上传、重置或新数据库写入 | 视频/音频源文件存本地 | 下载兼容新老路径
站点 Header Logo、登录 Logo、favicon 属于当前系统配置,不属于“老素材不改”的范围;它们必须使用仓库内置品牌资源或当前 s3.jiansun.vip/gongxiangpan/ 对象。
关键文件
- 上传:
components/UploadModal.tsx、components/upload/ - API:
app/api/materials/upload/(含init/chunk/complete)、download/、transcode/ - Lib:
lib/s3.ts、lib/video-processor.ts、lib/url-rewrite.ts
文件命名
- 视频:
video-{ts}-{hash}.mp4(不是video-source) - 音频:
audio-source-{id}-{ts}.mp3 - 其他:
material-{ts}-{hash}.zip
要点
- 分片上传: >5MB自动启用,IndexedDB断点续传,动态分片大小(内网20MB/公网10MB)
- 视频转码: 自动触发,720P预览+10秒片段+封面,状态
pending→processing→done/failed - 图片: 预览图压缩800×2000,展示图>1500px自动切片
- 数据库: 所有查询必须
deletedAt: null
Redis 上传会话管理
用途: 存储分片上传的会话信息,支持断点续传和多实例部署
配置:
- 容器:
gongxiangpan-redis - 过期时间: 4小时(基础),完成后缩短为1小时
- 内存限制: 100MB,淘汰策略
allkeys-lru
关键文件:
lib/upload-sessions-redis.ts- Redis存储实现lib/upload-sessions.ts- 统一会话管理接口lib/chunk-upload-config.ts- 动态分片大小配置
性能优化:
- 应用内存从 1.9GB 降到 184MB(降低90%)
- 支持多实例部署
- 自动过期清理机制
查询命令:
# 查看会话数量
ssh root@192.168.58.20 'docker exec gongxiangpan-redis redis-cli DBSIZE'
# 查看特定会话
ssh root@192.168.58.20 'docker exec gongxiangpan-redis redis-cli GET "upload:session:upload-xxx"'
# 查看会话TTL
ssh root@192.168.58.20 'docker exec gongxiangpan-redis redis-cli TTL "upload:session:upload-xxx"'
分片上传优化
动态分片大小:
- 内网用户: 20MB(网络检测自动识别)
- 公网用户: 10MB
- 目的: 平衡上传效率和网络稳定性
实现:
lib/network.ts- 网络检测lib/chunk-upload-config.ts- 分片配置
效果:
- 内网用户上传速度提升 40-60%
- 公网用户上传速度提升 2-5%
部署日志脚本
新建脚本: deploy-with-log.ps1
用途: 实时输出部署日志到文件,解决 Trae IDE 无法实时查看进度的问题
使用方法:
# 终端1:启动部署
pwsh -File ".\deploy-with-log.ps1" -Target production
# 终端2:实时查看日志
Get-Content "deploy.log" -Wait -Tail 30
输出文件:
deploy.log- 部署日志deploy.pid- 进程ID(完成后自动删除)
操作规范
- 数据库修改前必须备份
- 部署默认正式系统,明确要求才部署影子
- uploads目录不可删除
部署方式 ⚠️ 强制要求:
- ✅ 唯一标准方式:
.\deploy-remote-build.ps1(使用专用构建机) - 🚫 其他方式(
deploy-local-build.ps1、deploy-git-build.ps1)不推荐,除非项目负责人明确要求 - 📖 详细说明:部署规范
专用构建机部署
构建机: 192.168.42.134(Ubuntu,密码:Jsjj@8888)
架构: 本地电脑 → 构建机(构建+Registry)→ 生产服务器(SSH密钥免密登录)
组件:
- Docker Compose v5.0.1
- Registry API:
http://192.168.42.134:5000 - Registry UI:
http://192.168.42.134:5001 - SSH 免密登录(构建机 → 生产服务器)
- Clash 代理:
127.0.0.1:7897(已运行,可选使用)
部署命令:
# 部署到影子系统(端口 5320)
.\deploy-remote-build.ps1 -Target shadow
# 部署到正式系统(端口 4320)
.\deploy-remote-build.ps1 -Target production
智能缓存:
- 自动检测依赖文件变化(package-lock.json)
- 只有依赖变化时才重新构建
- Docker 层缓存自动复用(依赖安装层会被缓存)
- 基础镜像预先缓存(使用本地
node:18-alpine) - npm 使用淘宝镜像加速(
https://registry.npmmirror.com)
构建优化:
- 首次构建:约 3-5 分钟(下载依赖)
- 后续构建:约 1-2 分钟(利用 Docker 层缓存)
- 镜像大小:约 580MB
- 容器启动:约 120ms
优势:
- 保护本地 SSD(构建在远程)
- 智能缓存(大幅减少构建时间)
- 可视化管理(Registry UI)
- 镜像版本管理
- 代码传输小(15MB),镜像走内网
安全保证:
- ❌ 不操作 uploads 目录(只挂载)
- ❌ 不操作数据库
- ❌ 不操作存储桶
- ✅ 只操作应用容器和 Docker 资源
关键配置:
- 基础镜像:
node:18-alpine(Alpine Linux 3.21) - Prisma 引擎:
binaryTargets = ["native", "linux-musl-openssl-3.0.x"] - 依赖安装:直接
npm install,利用 Docker 层缓存 - 构建时警告:
DATABASE_URL缺失警告可忽略(运行时从环境变量读取)
故障排查:
- 如遇 Docker Hub 超时:使用本地已有镜像或淘宝镜像
- 如遇 Prisma OpenSSL 警告:可忽略,不影响运行
- 如遇 Sharp 错误:
npm install会自动下载正确版本
FRP穿透配置
穿透服务器: 180.97.221.140:7000(SSH端口:9527)
公网访问端口: 2320 → 内网 4320
客户端配置(生产服务器)
配置文件: /etc/frp/frpc.toml
关键配置:
poolCount = 150- 支持150个并发连接tcpMux = true- TCP多路复用useCompression = true- 启用压缩(按需)
服务管理:
# 查看状态
ssh root@192.168.58.20 "systemctl status frpc"
# 重启服务
ssh root@192.168.58.20 "systemctl restart frpc"
# 查看日志
ssh root@192.168.58.20 "tail -f /root/frp/frpc.log"
服务端配置(穿透服务器)
SSH访问(必须使用专用密钥):
ssh -i "$env:USERPROFILE\.ssh\id_rsa_frp_180.97.221.140" -p 9527 root@180.97.221.140 "命令"
配置文件: /etc/frp/frps.toml
关键配置:
maxPoolCount = 200- 最大连接池数量tcpMux = true- TCP多路复用heartbeatTimeout = 90- 心跳超时90秒tcpMuxKeepaliveInterval = 60- TCP Mux心跳检测间隔60秒tcpKeepalive = 30- 底层TCP连接保活间隔30秒
服务管理:
# 查看状态
ssh -i "$env:USERPROFILE\.ssh\id_rsa_frp_180.97.221.140" -p 9527 root@180.97.221.140 "systemctl status frps"
# 查看日志
ssh -i "$env:USERPROFILE\.ssh\id_rsa_frp_180.97.221.140" -p 9527 root@180.97.221.140 "tail -f /var/log/frps.log"
# 查看端口监听
ssh -i "$env:USERPROFILE\.ssh\id_rsa_frp_180.97.221.140" -p 9527 root@180.97.221.140 "ss -tuln | grep -E '7000|2320|9527'"
注意: 修改配置后必须重启服务才能生效
终端提示
推荐 Git Bash 作为默认终端(PowerShell批量操作语法差)
VSCode: terminal.integrated.defaultProfile.windows: "Git Bash"
Claude Code 插件
已安装插件:
- Superpowers (v4.1.1) - 结构化工作流
/brainstorm- 头脑风暴,探索方案/write-plan- 制定计划/execute-plan- 执行计划
- Claude mem (v9.0.6) - 自动记忆
- 自动记住项目结构、技术栈、重要决策
- 跨会话保留上下文
命令速查: .claude/Claude-命令速查.md
常用命令:
claude plugin list # 查看插件
claude plugin install xxx@yyy # 安装插件
/help # 帮助
/clear # 清空对话
/compact # 压缩对话
/commit # Git提交
更新: 2026-01-25