# 由壹点 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` 说法 - 项目已在线上运行,任何会影响上传、下载、权限、批量删除、资源链路的改动,都应先验证再发布