gongxiangp2/README.md

391 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 由壹点 3D 素材平台
当前仓库对应的是一个已经在线上运行的业务项目,不是演示性质的素材站。项目围绕素材上传、管理、下载、分享、权限控制和运维诊断构建,当前代码已经明显超出早期 README 里那种“注册登录 + 预览图 + 压缩包”的简单形态。
> 本 README 已于 2026-03-06 按当前代码结构重写,优先反映现状。
## 项目概览
- 基于 Next.js 14 App Router 的素材协作与分发系统
- 默认以新素材流程为主,不再把“新老素材兼容”作为日常主路径
- 同时使用 PostgreSQL、Prisma、S3/MinIO、本地 `uploads` 目录,以及可选 Redis 上传会话
- 已覆盖首页浏览、素材上传、分享下载、后台管理、外部接口、内外网状态识别、健康检查等完整链路
- 当前项目已经在线上运行,涉及权限、下载、上传、转码、批量删除等改动时需要先验证再发布
## 当前核心能力
### 1. 用户与登录
- 账号密码登录
- 钉钉登录与账号补全流程
- NextAuth 会话管理
- 个人资料页、个人素材、收藏与点赞
### 2. 素材浏览与分发
- 首页搜索、筛选、分页加载
- 收藏、点赞、排行榜、分享页
- 下载前校验与前端客户端下载兜底
- 素材分享链接与外部下载接口
### 3. 素材上传与处理
- 分片上传、断点续传、上传会话管理
- 支持多种素材类型上传,当前代码中已覆盖:
- 3D 原图
- AI 原图
- 实拍图
- 视频截图
- 任务页素材
- 商品套包
- 标准模特白底图
- SKU 维度文件管理、排序、批量下载
- 详情图 / 素材资产管理
- 直播切片(仅视频):直播日期 / 主播 / 平台元数据,批量多选上传,关键词搜主播与平台,按平台与日期区间筛选,豁免 15 天视频下载保护期
- 证书-检测报告元数据:报告标题、报告类型(成品 / 原材料)、检测与到期日期(到期默认检测日期 + 1 年)
- 商品套包未完成上传的中止与回滚
- 视频转码、封面 / 预览片段生成、PostgreSQL 租约任务恢复与重试
- 默认生成 720P H.265 主预览和 10 秒片段;素材建档后异步经历 `pending → processing → done/failed`
### 4. 后台与权限
- 素材管理、用户管理、分类管理
- 部门管理与部门素材权限控制
- 数据统计、统计导出、素材操作日志
- 回收站永久删除:数据库 outbox 任务 + 应用内 worker(租约、重试、断点续跑、审计),引用检查走 GIN 表达式索引
- 权限组绑定花名册组织身份;品牌中心"团队职能"数据库化配置
- API Key、API 日志、系统设置、回收站、超级管理员相关能力
### 5. 运行与诊断
- 内外网状态识别、健康检查与受控运维监控
- 健康检查接口与内存检查接口
- 快速性能检查接口
- 内外网 URL 重写与下载链路适配
### 6. AI 能力(灰度中,默认关闭)
- AI 模型接入管理(仅超管):上游服务商与模型注册表,按用途做"真实协议测试"(真读图、真出图)后才允许开放;能力变更即要求重新验证
- AI 商品详情页生成器(正式验收前仅超管):资料分析 → 卖点大纲 → 逐屏生成 → 导出 PNG / 长图 / 分层 PSD;渲染走独立子进程 `workers/detail-renderer`(自带依赖锁,与主应用隔离)
## 技术栈
- 前端:Next.js 14、React 18、TypeScript、Tailwind CSS
- 认证:NextAuth.js
- 数据库:PostgreSQL + Prisma ORM
- 对象存储:S3 / MinIO
- 本地文件:`uploads` 目录
- 缓存 / 会话:Redis(可选,上传会话优先使用)
- 文件与媒体处理:`sharp`、`jszip`、`adm-zip`、`archiver`
- 测试:Jest + Testing Library
## 目录结构
```text
gongxiangp2/
├── app/ # 页面、App Router、API 路由
│ ├── admin/ # 管理后台页面(素材库管理,旧壳待统一)
│ ├── api/ # 业务 API
│ ├── login/ # 登录页
│ ├── materials/ # 创意资产库(原素材库首页)
│ ├── organization/ # 组织管理(人员架构顶层页)
│ ├── register/ # 注册页
│ ├── share/ # 分享页
│ └── page.tsx # 登录与权限跳转至实际工作面
├── components/ # 通用组件、后台组件、上传组件、看板壳(board/)
├── lib/ # 业务工具、上传/下载/转码/权限逻辑
├── prisma/ # Prisma schema
├── scripts/ # 运维/修复/清理脚本
├── workers/ # 独立子进程:detail-renderer(详情页渲染)、database-migrator(精简迁移镜像)
├── docs/ # 网络、接口与部署等项目文档
├── uploads/ # 本地上传与处理中间文件
└── README.md
```
## 数据模型概览
当前 Prisma 模型已经不止早期的 `User` / `Material` 两张表,核心模型包括但不限于:
- `User`
- `Material`
- `MaterialSku`
- `MaterialAsset`
- `MaterialLog`
- `MaterialDownloadLog`
- `Department`
- `DepartmentMaterialPermission`
- `ApiKey`
- `ApiCallLog`
- `VideoTranscodeProgress`
- `SystemSettings`
- AI 模型注册表:`AiModelProvider` / `AiModelCatalog` / `AiModelVerification` / `AiModelConfiguration` / `AiModelAudit`
- 详情页生成器:`DetailGeneratorProject` / `DetailGeneratorBrandProfile` / `DetailGeneratorAsset` / `DetailGeneratorJob`
- 回收站永久删除:`MaterialPurgeJob` / `MaterialPurgeAudit`
- 组织与团队职能:`TeamFunctionConfig` / `TeamFunctionConfigAudit`
角色枚举当前包含:
- `USER`
- `ADMIN`
- `DEPT_ADMIN`
- `SYSTEM_ADMIN`
## 快速开始
### 1. 安装依赖
```bash
npm install
```
### 2. 配置环境变量
仓库当前没有维护独立的 `.env.example`,请自行准备本地环境变量文件,并且不要把真实密钥再次提交到仓库。
最小必需:
```bash
DATABASE_URL=postgresql://...
NEXTAUTH_SECRET=replace-this-with-a-strong-secret
```
启用素材平台 API Key 创建和后续查看时,还必须配置独立且稳定的加密密钥:
```bash
# 至少 32 个字符;生产环境必须独立生成并稳定保存
API_KEY_ENCRYPTION_KEY=replace-this-with-a-separate-strong-secret
```
常用配置:
```bash
# 站点地址
NEXTAUTH_URL=http://localhost:3000
APP_PUBLIC_URL=http://localhost:3000
# 仅限直接运行 `npm run dev` 的非容器本地开发目录
UPLOAD_DIR=./uploads
# S3 / MinIO
S3_ENDPOINT=http://127.0.0.1:9000
S3_BUCKET=your-bucket
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
S3_REGION=us-east-1
S3_PUBLIC_DOMAIN=https://your-s3-domain
S3_FILE_PATH=your-prefix/
# Redis(上传会话)
USE_REDIS=true
REDIS_URL=redis://127.0.0.1:6379
# 钉钉登录
DINGTALK_CLIENT_ID=your-dingtalk-app-key
DINGTALK_CLIENT_SECRET=your-dingtalk-app-secret
NEXT_PUBLIC_DINGTALK_CLIENT_ID=your-dingtalk-app-key
# 考核调研通知:work_notice(工作通知)或 robot_oto(机器人单聊)
DINGTALK_PERFORMANCE_SURVEY_NOTIFICATION_CHANNEL=robot_oto
DINGTALK_ROBOT_CODE=your-dingtalk-robot-code
# 灰度阶段填写允许走机器人单聊的钉钉 userId,多个用逗号分隔;留空表示全量启用
DINGTALK_ROBOT_OTO_TEST_USER_IDS=user-id-1,user-id-2
# 通知中心管理后台代理(仅服务端使用,绝不能下发到浏览器)
YYD_NOTIFICATION_CENTER_ADMIN_URL=https://notify-admin.example.com/notification-center/admin
YYD_NOTIFICATION_CENTER_ADMIN_API_SECRET=replace-with-server-side-admin-secret
# 可选,请求超时毫秒;默认 8000
YYD_NOTIFICATION_CENTER_ADMIN_TIMEOUT_MS=8000
# 下载与外部接口
DOWNLOAD_TOKEN_SECRET=replace-this
ADMIN_API_KEY=replace-this-if-needed
# 标题栏商品搜索(淘宝详情代理)
TAOBAO_DETAIL_PLUS_API_BASE_URL=http://156.225.27.52:60024
TAOBAO_DETAIL_PLUS_API_KEY=your-api-key
TAOBAO_DETAIL_PLUS_TIMEOUT_MS=12000
# 内外网链路改写
SERVER_IP=127.0.0.1
MINIO_API_PORT=9000
# 视频转码(按需)
VIDEO_TRANSCODE_MAX_CONCURRENT=1
VIDEO_TRANSCODE_THREADS=1
VIDEO_TRANSCODE_TIMEOUT=3600000
VIDEO_PREVIEW_RESOLUTION=720
VIDEO_CLIP_DURATION=10
VIDEO_PREVIEW_CRF=20
VIDEO_CLIP_CRF=24
VIDEO_MAX_TEMP_FILE_SIZE=10737418240
# AI 聊天(按需)
GEMINI_API_KEY=your-api-key
GEMINI_API_BASE_URL=https://generativelanguage.googleapis.com/v1beta
GEMINI_MODEL=gemini-2.0-flash-exp
```
### 3. 初始化数据库
```bash
npm run prisma:generate
npm run prisma:push
```
### 4. 初始化管理员账号
首次启动后,可以先注册一个普通账号,再在数据库里把角色改成 `ADMIN`。
```sql
UPDATE users
SET role = 'ADMIN'
WHERE email = 'your@email.com';
```
### 5. 启动开发环境
```bash
npm run dev
```
直接运行 `npm run dev` 时,`UPLOAD_DIR=./uploads` 只保存本机开发数据。容器化的本地集成测试请使用 `docker-compose.local-test.yml` 中的独立命名卷,不要把相对目录配置复制到默认 Compose 或生产环境。
### 6. 默认 Compose 的 uploads 挂载门禁
根目录 `docker-compose.yml` 是生产形态的单机参考配置(正式发布仍以 `scripts/git-incremental-deploy.ps1` 为准)。它不会再自动创建或挂载仓库内的 `./uploads`,启动前必须显式提供已经核验的宿主机 uploads 挂载:
```bash
export GONGXIANGP2_UPLOADS_MOUNT=/mnt/PoolOne/youyidian-uploads
docker compose config
docker compose up -d
```
- 当前生产宿主机的真实独立 ZFS 数据集路径是 `/mnt/PoolOne/youyidian-uploads`;先在宿主机用 `findmnt` 核验它确实是预期挂载,不能只确认目录存在。
- 容器内统一使用 `UPLOAD_DIR=/app/uploads`,不要把宿主机路径写进容器环境变量。
- `create_host_path: false` 会在路径缺失时直接失败,避免 Docker 静默新建空目录后让素材写入错误磁盘。
- 相对 `./uploads` 只允许用于明确的非容器开发;影子环境使用其独立的 `uploads-shadow`,本地集成测试使用命名卷,二者都不能当作生产数据目录。
默认访问地址:
```text
http://localhost:3000
```
登录后的一级入口为“品牌中心部门看板”,当前页面路由如下:
```text
品牌中心部门看板:http://localhost:3000/
小项二级框架示例:http://localhost:3000/workspaces/dashboard/core-metrics
由壹点3D素材:http://localhost:3000/assets/material-library
```
### 无本机 Node 环境时使用 Docker 开发
仓库提供一套隔离的 Docker 开发环境,包含 Node.js 22、PostgreSQL、Redis、MinIO 和支持源码热更新的 Next.js。它使用独立数据卷,不连接生产数据库或生产对象存储。
```bash
docker compose \
--env-file .env.docker-test.local \
-f docker-compose.local-test.yml \
-f docker-compose.dev.yml \
up -d --build
```
首次启动会自动执行 `prisma generate` 和 `prisma db push`。启动完成后访问:
```text
应用:http://localhost:4321
MinIO 控制台:http://localhost:59001
```
查看应用日志或停止环境:
```bash
docker compose \
--env-file .env.docker-test.local \
-f docker-compose.local-test.yml \
-f docker-compose.dev.yml \
logs -f app
docker compose \
--env-file .env.docker-test.local \
-f docker-compose.local-test.yml \
-f docker-compose.dev.yml \
down
```
`down` 会保留本地数据库和上传文件;只有显式增加 `--volumes` 才会清除本地开发数据。
## 常用脚本
```bash
npm run dev
npm run build
npm run start
npm run lint
npm run test
npm run test:watch
npm run test:coverage
npm run prisma:generate
npm run prisma:push
npm run prisma:studio
```
## 部署说明
### 当前标准部署
当前线上默认使用 Git 增量部署:
```powershell
.\scripts\git-incremental-deploy.ps1 -DryRun
.\scripts\git-incremental-deploy.ps1 -Commit '<40位小写提交SHA>'
```
部署链路是:源码推送到 Git -> 构建机增量拉取并构建镜像 -> 生产机拉取镜像并替换应用容器。旧的 `deploy-remote-build.ps1` 属于本地历史脚本名,只作为识别应急资料使用,不是仓库交付入口,也不再作为默认推荐方式。
详细说明见:
- `docs/Git增量部署方案.md`
- `docs/部署规范.md`
- `docs/部署脚本安全说明.md`
### 本地或单机生产启动
```bash
npm run build
npm run start
```
### Docker / Compose
仓库内已经包含以下部署文件:
- `Dockerfile`
- `Dockerfile.base`
- `docker-compose.yml`
- `docker-compose.shadow.yml`
但当前线上环境并不只依赖容器本身,还依赖网络入口、FRP、域名与反向代理链路。因此如果要碰部署问题,建议连同项目文档一起看,而不是只看 Compose 文件。
### 发布前重点核对
- 登录是否正常
- 首页筛选、上传、下载、分享是否正常
- 管理后台核心页签是否可用
- 视频转码数据库任务 / 租约是否异常堆积(Redis 仅检查上传会话,不作为视频队列)
- `/api/health` 是否正常
- 如果改了网络或下载链路,再验证一次内外网访问
## 相关文档
- `docs/NETWORK_TOPOLOGY.md`:当前网络拓扑与故障排查
- `docs/部署规范.md`:当前部署规范
- `docs/Git增量部署方案.md`:Git 增量部署方案
- `docs/生产存储桶接入信息.md`:当前 MinIO / uploads 存储事实
- `docs/外部接口文档.md`:当前对外接口说明
## 说明
- 当前仓库 `package.json` 为 `private: true`
- 本仓库目前没有单独声明开源许可证,不应继续沿用旧 README 中的 `MIT` 说法
- 项目已在线上运行,任何会影响上传、下载、权限、批量删除、资源链路的改动,都应先验证再发布