docs: organize project documentation
This commit is contained in:
587
docs/总方案/音乐元数据标准化与归档系统 需求梳理 + 架构技术方案.md
Normal file
587
docs/总方案/音乐元数据标准化与归档系统 需求梳理 + 架构技术方案.md
Normal file
@@ -0,0 +1,587 @@
|
||||
# 音乐元数据标准化与归档系统 需求梳理+架构技术方案
|
||||
**文档版本**:V1.0
|
||||
**修订日期**:2026年03月15日
|
||||
**文档状态**:正式版
|
||||
**技术约束**:后端Java + GraalVM原生编译、前端Vue技术栈
|
||||
**核心适配**:Navidrome音乐服务器官方最佳实践
|
||||
|
||||
---
|
||||
|
||||
## 一、文档概述
|
||||
### 1.1 文档目的
|
||||
本文档完整梳理「音乐元数据标准化与归档系统」的业务需求、架构设计、核心规则、技术实现与落地路径,为系统开发、测试、部署提供全流程指导,确保系统最终实现**元数据零错误识别、目录结构100%适配Navidrome、全流程自动化+人工兜底可控**的核心目标。
|
||||
|
||||
### 1.2 适用范围
|
||||
- 业务范围:个人/家庭级音乐库元数据标准化、自动归档、全生命周期管理
|
||||
- 技术范围:后端Java服务开发、GraalVM原生编译适配、Vue前端可视化界面开发、Navidrome音乐库适配
|
||||
- 读者对象:开发人员、测试人员、系统运维人员、最终用户
|
||||
|
||||
### 1.3 术语定义
|
||||
| 术语 | 全称 | 说明 |
|
||||
|------|------|------|
|
||||
| 元数据 | Music Metadata | 音乐文件内嵌的标签信息,包括歌曲标题、歌手、专辑、封面、曲目编号等核心信息 |
|
||||
| 音频指纹 | Acoustic Fingerprint | 基于音频内容生成的唯一特征码,不受元数据、格式、比特率影响,用于精准识别歌曲 |
|
||||
| 归档 | Archiving | 按规范规则重命名文件、生成标准化目录结构,将音乐文件整理到目标音乐库的过程 |
|
||||
| 增量入库 | Incremental Storage | 仅处理新增的音乐文件,跳过已处理完成的文件,避免重复归档 |
|
||||
| 原生镜像 | Native Image | 基于GraalVM将Java程序编译为平台相关的可执行文件,实现极速启动、低内存占用 |
|
||||
|
||||
---
|
||||
|
||||
## 二、项目背景与目标
|
||||
### 2.1 项目背景
|
||||
个人/家庭音乐库的文件来源多样(CD抓取、网络下载、音频转录等),普遍存在以下核心痛点:
|
||||
1. 元数据不规范:字段缺失、乱码、格式不统一,导致Navidrome等流媒体服务器无法正确识别歌手、专辑、封面、歌词等信息
|
||||
2. 目录结构混乱:无统一归档规则,文件存放分散,Navidrome扫描后出现歌手分裂、专辑错乱、曲目排序错误等问题
|
||||
3. 重复文件冗余:同一首歌存在多个版本,占用存储空间,音乐库管理混乱
|
||||
4. 无标准化管理能力:缺失元数据的文件无统一兜底处理流程,最终成为音乐库中的“无效文件”
|
||||
|
||||
### 2.2 核心目标
|
||||
1. **标准化适配**:建立严格的元数据校验规则,确保处理后的音乐文件100%被Navidrome及主流播放器完整识别
|
||||
2. **自动化归档**:按预设规则自动完成音乐文件的目录整理、重命名、元数据写入,无需人工干预合规文件
|
||||
3. **全流程可控**:对不符合规范的文件进行精准标记、全链路记录,通过可视化界面实现人工补全兜底
|
||||
4. **增量高效处理**:支持重复调用,仅处理新增文件,内置多级去重能力,避免重复入库
|
||||
5. **高性能轻量化**:基于GraalVM实现原生编译,实现毫秒级启动、低内存占用,适配家庭级单机部署场景
|
||||
|
||||
### 2.3 次要目标
|
||||
1. 支持多格式音频文件的元数据读写,覆盖主流无损/有损音频格式
|
||||
2. 提供可视化的处理进度监控、处理报告、数据统计能力
|
||||
3. 不修改、不删除用户原始源文件,保障源文件安全
|
||||
4. 提供可配置的规则扩展能力,适配不同播放器的元数据规范
|
||||
|
||||
---
|
||||
|
||||
## 三、需求详细梳理
|
||||
### 3.1 功能性需求
|
||||
#### 3.1.1 音乐源接入模块
|
||||
支持两种核心输入方式,覆盖批量处理与单文件快速处理场景:
|
||||
1. **本地目录批量接入**
|
||||
- 支持用户指定本地音乐源目录,支持多级目录递归扫描
|
||||
- 支持配置文件格式过滤,仅扫描指定后缀的音频文件
|
||||
- 支持扫描断点续传,异常中断后可从断点继续扫描,无需重新全量扫描
|
||||
- 支持扫描进度实时反馈,前端展示已扫描文件数、待处理文件数
|
||||
2. **前端页面文件上传**
|
||||
- 支持单个/多个音乐文件批量上传,支持拖拽上传
|
||||
- 支持大文件分片上传,断点续传
|
||||
- 上传完成后自动触发元数据校验与处理流程
|
||||
- 支持上传文件格式校验,拒绝非支持的音频格式
|
||||
|
||||
#### 3.1.2 元数据解析与校验模块(核心)
|
||||
1. **全格式元数据解析**:支持MP3(ID3v1/v2)、FLAC(Vorbis Comment)、M4A(MP4 Metadata)、OGG、WAV主流音频格式的元数据读取与写入
|
||||
2. **编码自动检测与校验**:自动检测元数据原始编码,强制校验是否为UTF-8编码,非UTF-8编码且无法正常转换的直接标记失败
|
||||
3. **一票否决制强制校验**:明确核心必填字段,任一必填字段不满足规范要求,直接标记为处理失败,不进行任何猜测式补全,仅记录失败原因
|
||||
4. **非必填字段提示**:对建议字段的缺失/不规范进行记录,不影响归档,仅在处理报告中提示用户补全
|
||||
5. **元数据快照存储**:对所有处理文件的原始元数据进行快照存储,用于后续人工处理溯源与回滚
|
||||
|
||||
#### 3.1.3 元数据权威补全模块
|
||||
仅保留**基于音频指纹的权威API补全**作为唯一自动补全手段,无任何文件名/目录结构的猜测式补全,确保元数据准确性:
|
||||
1. **音频指纹提取**:对校验失败的文件,自动提取音频指纹,生成唯一特征码
|
||||
2. **权威API对接**:对接AcoustID音频指纹识别API、MusicBrainz开源音乐元数据库API,获取歌曲权威元数据
|
||||
3. **补全数据二次校验**:API返回的元数据必须再次通过「一票否决制」强制校验,校验通过方可写入文件,校验不通过仍标记为失败
|
||||
4. **API调用限流与容错**:内置API调用频率限制、超时重试、异常降级机制,避免因第三方API故障导致处理流程中断
|
||||
|
||||
#### 3.1.4 文件去重与增量入库模块
|
||||
1. **多级去重算法**
|
||||
- 一级快速去重:计算文件SHA-256哈希值,与数据库中已归档文件哈希比对,完全一致直接跳过
|
||||
- 二级特征去重:哈希不同,但「歌手+歌曲标题+专辑+音频时长」完全一致,标记为疑似重复,进入人工确认队列,不自动归档
|
||||
- 三级指纹去重:音频指纹一致,判定为同一首歌的不同版本,标记为疑似重复,进入人工确认队列
|
||||
2. **增量入库能力**
|
||||
- 每次处理任务启动时,先扫描源目录生成文件哈希清单,与已处理完成的清单比对,仅对新增/修改的文件进行处理
|
||||
- 支持全量重扫配置,用户可手动触发全量文件重新校验
|
||||
- 已标记为失败的文件,支持手动触发重新处理,无需重新扫描全目录
|
||||
|
||||
#### 3.1.5 自动分类归档模块
|
||||
严格遵循双规则归档,100%适配Navidrome官方推荐最佳实践,归档文件默认采用**复制模式**,不修改/删除原始源文件:
|
||||
1. **一级分类规则**:按专辑艺术家名称首字母分为A-Z 26个目录,非字母开头(中文、数字、符号等)的专辑艺术家统一归入`#`目录
|
||||
2. **底层目录规则**:严格遵循Navidrome官方规范,最终目录结构为:
|
||||
```
|
||||
目标音乐库根目录/
|
||||
├── A/
|
||||
│ └── 专辑艺术家名称/
|
||||
│ └── 专辑名称/
|
||||
│ ├── 01 - 歌曲标题.flac
|
||||
│ ├── 02 - 歌曲标题.flac
|
||||
│ ├── cover.jpg
|
||||
│ └── 01 - 歌曲标题.lrc
|
||||
├── B/
|
||||
│ └── 专辑艺术家名称/
|
||||
...
|
||||
└── #/
|
||||
└── 非字母开头专辑艺术家名称/
|
||||
└── 专辑名称/
|
||||
└── 01 - 歌曲标题.mp3
|
||||
```
|
||||
3. **文件名规范化规则**:统一命名格式为`2位曲目编号 - 歌曲标题.文件扩展名`,曲目编号不足2位补前导零,去除文件名中不支持的特殊字符
|
||||
4. **封面与歌词归档规则**
|
||||
- 封面:必须内嵌到音频文件中,同时在专辑目录下生成`cover.jpg`(Navidrome优先读取),自动缩放为800x800正方形分辨率,格式为JPG
|
||||
- 歌词:支持内嵌LRC时间轴歌词,同时在同级目录下生成`与歌曲同名.lrc`文件,强制UTF-8编码
|
||||
5. **归档冲突处理**:目标目录已存在同名文件时,自动比对哈希值,哈希一致则跳过,哈希不一致则保留两个文件并标记冲突,等待人工处理
|
||||
|
||||
#### 3.1.6 失败文件统一管理模块(核心兜底)
|
||||
对所有处理失败的文件进行全生命周期管理,提供可视化人工处理界面,确保所有文件可追溯、可兜底:
|
||||
1. **失败文件全信息记录**:记录文件原始路径、文件名、哈希值、失败原因、原始元数据快照、失败时间、处理状态
|
||||
2. **失败原因结构化存储**:精准标记失败类型,包括:必填字段缺失、编码乱码、封面不符合规范、API未匹配、曲目编号格式错误等
|
||||
3. **可视化列表管理**
|
||||
- 支持按失败类型、处理状态、时间范围、歌手/专辑名称筛选搜索
|
||||
- 支持批量重新提交处理、批量删除操作
|
||||
- 列表展示文件核心信息、失败原因摘要、处理状态、操作按钮
|
||||
4. **元数据人工编辑页面**
|
||||
- 内置音频预览播放器,支持试听文件,确认歌曲信息
|
||||
- 核心必填字段表单编辑,带必填校验与格式校验
|
||||
- 封面上传/在线搜索获取功能,自动缩放裁剪
|
||||
- 歌词上传/在线搜索获取功能,支持LRC格式校验
|
||||
- 对接MusicBrainz API提供字段自动补全建议,提升人工处理效率
|
||||
5. **人工处理提交流程**:编辑完成后提交,系统自动重新执行全流程校验,校验通过则完成归档,更新状态为已解决;校验不通过则更新失败原因,返回编辑页面
|
||||
|
||||
#### 3.1.7 系统管理模块
|
||||
1. **基础配置管理**:目标音乐库根目录配置、归档模式(复制/移动)配置、封面分辨率配置、API密钥配置、必填字段可配置开关
|
||||
2. **任务管理**:处理任务的创建、暂停、继续、终止,任务进度实时监控,历史任务记录查询
|
||||
3. **处理报告**:每次任务完成后生成详细报告,包括处理总数、成功数、失败数、重复数、失败原因统计、文件清单导出
|
||||
4. **日志管理**:系统操作日志、处理日志、错误日志的查询与导出,支持日志级别配置
|
||||
5. **数据备份与恢复**:支持系统数据库、配置文件的手动/自动备份与恢复
|
||||
|
||||
### 3.2 非功能性需求
|
||||
1. **性能需求**
|
||||
- 批量处理能力:单机环境下,每秒可处理≥5个音频文件(不含第三方API调用时间)
|
||||
- 启动速度:基于GraalVM原生编译后,服务启动时间≤500ms
|
||||
- 内存占用:原生镜像运行时,稳态内存占用≤200MB
|
||||
- 大文件支持:支持最大2GB的单音频文件处理
|
||||
2. **兼容性需求**
|
||||
- 音频格式:兼容MP3、FLAC、M4A、OGG、WAV主流音频格式
|
||||
- 系统兼容:支持Windows、Linux、macOS三大主流操作系统
|
||||
- Navidrome兼容:严格适配Navidrome最新稳定版,确保扫描零错误、识别零异常
|
||||
- 浏览器兼容:前端界面支持Chrome、Edge、Firefox主流浏览器
|
||||
3. **稳定性需求**
|
||||
- 异常容错:单个文件处理失败不影响整体任务流程,异常文件自动标记并跳过
|
||||
- 断点续传:扫描、处理、上传流程均支持断点续传,异常中断后可恢复
|
||||
- 数据安全:不修改、不删除原始源文件,元数据写入前自动备份原始文件
|
||||
- 服务可用性:全年可用率≥99.9%,无内存泄漏、无进程崩溃问题
|
||||
4. **易用性需求**
|
||||
- 前端界面简洁直观,核心功能3步内可完成操作
|
||||
- 处理进度可视化,失败原因清晰易懂,人工编辑门槛低
|
||||
- 提供一键批量处理能力,无需复杂配置即可完成标准化归档
|
||||
5. **安全性需求**
|
||||
- 文件操作权限控制:仅对用户授权的目录进行读写操作
|
||||
- 无网络泄露:本地文件处理全程不传输原始音频文件,仅音频指纹特征码用于第三方API查询
|
||||
- 配置加密:第三方API密钥等敏感配置采用加密存储
|
||||
|
||||
### 3.3 约束条件
|
||||
1. **技术栈约束**:后端必须采用Java语言开发,基于GraalVM实现原生编译;前端必须采用Vue技术栈开发
|
||||
2. **兼容性约束**:归档目录结构、元数据规范必须严格遵循Navidrome官方最佳实践,不得自定义非兼容规则
|
||||
3. **数据安全约束**:默认采用复制模式归档,禁止未经用户授权修改、删除原始源文件
|
||||
4. **元数据规则约束**:必填字段不满足规范必须标记为失败,禁止任何无权威来源的猜测式自动补全
|
||||
|
||||
---
|
||||
|
||||
## 四、整体架构设计
|
||||
### 4.1 分层架构设计
|
||||
采用经典的DDD分层架构,实现业务与技术解耦,便于扩展与维护,同时适配GraalVM原生编译要求:
|
||||
|
||||
| 层级 | 核心职责 | 核心组件 |
|
||||
|------|----------|----------|
|
||||
| 接入层 | 负责系统对外的所有接入入口,处理用户请求与文件接入 | Vue前端界面、HTTP接口服务、本地目录扫描器、文件上传服务 |
|
||||
| 应用层 | 编排核心业务流程,处理事务控制,不包含核心业务规则 | 任务管理服务、文件处理流程编排服务、失败文件管理服务、系统配置服务 |
|
||||
| 领域层 | 实现系统核心业务规则与领域逻辑,是系统的核心 | 元数据校验规则、归档规则、去重规则、音频指纹识别领域服务、元数据读写领域服务 |
|
||||
| 基础设施层 | 为上层提供技术能力支撑,封装底层技术实现,适配GraalVM原生编译 | 文件操作组件、元数据读写组件、音频指纹提取组件、第三方API客户端、数据库访问组件、图片处理组件、日志组件 |
|
||||
| 数据层 | 负责系统数据持久化与文件存储 | 关系型数据库、本地文件系统、目标音乐库目录 |
|
||||
|
||||
### 4.2 核心业务全流程
|
||||
```mermaid
|
||||
graph TD
|
||||
A[任务启动:目录扫描/文件上传] --> B[生成文件清单,计算SHA-256哈希]
|
||||
B --> C{哈希比对:是否已归档?}
|
||||
C -->|是| D[标记为已重复,跳过处理]
|
||||
C -->|否| E[读取文件原始元数据,生成快照]
|
||||
E --> F{核心必填字段校验:是否全部合规?}
|
||||
F -->|是| G[进入去重二次校验]
|
||||
F -->|否| H[提取音频指纹,调用AcoustID+MusicBrainz API]
|
||||
H --> I{API是否返回完整合规元数据?}
|
||||
I -->|是| J[写入API元数据到文件,二次校验必填字段]
|
||||
J --> K{二次校验是否通过?}
|
||||
K -->|是| G
|
||||
K -->|否| L[标记为处理失败,记录结构化失败原因]
|
||||
I -->|否| L
|
||||
L --> M[存入失败文件数据库,状态为待处理]
|
||||
M --> N[前端失败管理页面人工编辑补全]
|
||||
N --> E
|
||||
G -->{二次去重:是否疑似重复?}
|
||||
-->|是| O[标记为疑似重复,进入人工确认队列]
|
||||
-->|否| P[按Navidrome规范生成目录与文件名]
|
||||
P --> Q[写入标准化元数据、封面、歌词]
|
||||
Q --> R[复制文件到目标音乐库归档目录]
|
||||
R --> S[更新数据库,标记为处理完成]
|
||||
S --> T[任务结束,生成处理报告]
|
||||
```
|
||||
|
||||
### 4.3 部署架构设计
|
||||
系统支持两种部署模式,优先适配家庭用户单机部署场景,同时支持Docker容器化部署:
|
||||
|
||||
#### 4.3.1 单机部署模式(推荐)
|
||||
基于GraalVM原生镜像部署,无需安装JDK环境,解压即可运行,适配Windows/Linux/macOS:
|
||||
1. 前端Vue项目打包为静态资源,内置到后端原生镜像中,单文件启动
|
||||
2. 数据库采用嵌入式H2数据库,无需额外安装数据库服务
|
||||
3. 直接读写本地文件系统,无网络转发损耗,性能最优
|
||||
|
||||
#### 4.3.2 Docker容器化部署模式
|
||||
1. 基于GraalVM原生镜像构建Docker镜像,镜像体积小(≤100MB),启动速度快
|
||||
2. 支持目录挂载,将源音乐目录、目标音乐库目录、配置目录挂载到宿主机
|
||||
3. 支持Docker Compose一键部署,适配NAS、家庭服务器等Linux环境
|
||||
|
||||
---
|
||||
|
||||
## 五、元数据标准化核心规则(强制执行)
|
||||
### 5.1 字段规范与一票否决制
|
||||
#### 5.1.1 核心必填字段(缺一不可,不满足直接标记失败)
|
||||
| 字段名 | 英文标识 | 强制规范要求 | Navidrome依赖等级 |
|
||||
|--------|----------|--------------|--------------------|
|
||||
| 歌曲标题 | title | 非空、无乱码、UTF-8编码、长度≥1字符,去除首尾空格 | ⭐⭐⭐⭐⭐ |
|
||||
| 歌手 | artist | 非空、无乱码、UTF-8编码、长度≥1字符,去除首尾空格 | ⭐⭐⭐⭐⭐ |
|
||||
| 专辑艺术家 | album_artist | 非空、无乱码、UTF-8编码、长度≥1字符,合辑/单曲默认与artist一致,必须显式存在 | ⭐⭐⭐⭐⭐ |
|
||||
| 专辑名 | album | 非空、无乱码、UTF-8编码、长度≥1字符,去除首尾空格 | ⭐⭐⭐⭐⭐ |
|
||||
| 曲目编号 | track | 格式必须为「序号/总曲目数」,序号与总曲目数均为正整数,序号≤总曲目数,序号不足2位补前导零 | ⭐⭐⭐⭐⭐ |
|
||||
| 专辑封面 | cover | 必须内嵌到音频文件中,图片格式为JPG/PNG,分辨率≥300x300,宽高比1:1 | ⭐⭐⭐⭐⭐ |
|
||||
|
||||
#### 5.1.2 建议补充字段(缺失不标记失败,仅提示补全)
|
||||
| 字段名 | 英文标识 | 规范要求 |
|
||||
|--------|----------|----------|
|
||||
| 发行年份 | year | 4位数字格式,范围1900-当前年份 |
|
||||
| 流派 | genre | 标准音乐流派术语,多个流派用分号分隔 |
|
||||
| 歌词 | lyrics | UTF-8编码,支持LRC时间轴格式,内嵌到音频文件中 |
|
||||
| 光盘编号 | disc | 格式为「序号/总光盘数」,多光盘专辑必填 |
|
||||
| 备注 | comment | 用于记录版本信息(Live/Remix等),无乱码 |
|
||||
|
||||
### 5.2 元数据清洗强制规则
|
||||
仅对合规字段进行标准化清洗,不修改字段核心含义,清洗后仍需满足必填规范:
|
||||
1. **编码规范**:所有元数据强制转换为UTF-8编码,无法正常转换、出现乱码的字段直接标记失败
|
||||
2. **特殊字符处理**:去除字段首尾空格、换行符、不可见特殊字符;目录/文件名不支持的字符`\ / : * ? " < > |`统一替换为`_`
|
||||
3. **分隔符规范**:多个歌手/流派统一用英文分号+空格`; `分隔,替换原有的`&`、`feat.`、`/`等分隔符
|
||||
4. **大小写规范**:英文单词首字母大写,特殊冠词(a/an/the)句中非首字母小写,统一格式
|
||||
5. **版本信息规范**:歌曲标题中的Live/Remix/伴奏等版本信息,统一移至comment字段,标题仅保留歌曲核心名称
|
||||
|
||||
### 5.3 唯一自动补全规则
|
||||
仅支持**基于音频指纹的权威API补全**,禁止任何基于文件名、目录结构的猜测式补全:
|
||||
1. 补全数据源仅认可AcoustID+MusicBrainz返回的权威元数据,其他第三方数据源不纳入自动补全范围
|
||||
2. API返回的元数据必须完整覆盖所有核心必填字段,且符合规范要求,方可自动写入
|
||||
3. 写入前必须进行二次校验,任一必填字段不满足规范,仍标记为失败,不进行部分字段补全
|
||||
4. 人工编辑场景下,可提供MusicBrainz API搜索建议,由用户手动确认后写入,不自动覆盖
|
||||
|
||||
---
|
||||
|
||||
## 六、数据库设计
|
||||
采用嵌入式H2数据库,适配GraalVM原生编译,支持单机运行无需额外部署,核心表结构如下:
|
||||
|
||||
### 6.1 文件处理记录表(t_file_process)
|
||||
记录所有文件的全流程处理信息,是系统的核心主表
|
||||
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|
||||
|--------|----------|------|------|------|
|
||||
| id | BIGINT | 是 | 是 | 自增主键 |
|
||||
| file_hash | VARCHAR(64) | 否 | 是 | 文件SHA-256哈希值,唯一索引 |
|
||||
| source_file_path | VARCHAR(1000) | 否 | 是 | 原始源文件完整路径 |
|
||||
| source_file_name | VARCHAR(200) | 否 | 是 | 原始文件名 |
|
||||
| file_extension | VARCHAR(10) | 否 | 是 | 文件扩展名 |
|
||||
| file_size | BIGINT | 否 | 是 | 文件大小(字节) |
|
||||
| audio_duration | INT | 否 | 否 | 音频时长(秒) |
|
||||
| raw_metadata | TEXT | 否 | 是 | 原始元数据快照,JSON格式存储 |
|
||||
| process_status | VARCHAR(20) | 否 | 是 | 处理状态:PENDING(待处理)/PROCESSING(处理中)/SUCCESS(已完成)/FAIL(处理失败)/DUPLICATE(已重复)/CONFLICT(冲突) |
|
||||
| fail_reason | TEXT | 否 | 否 | 失败原因,结构化JSON格式存储 |
|
||||
| target_file_path | VARCHAR(1000) | 否 | 否 | 归档后目标文件完整路径 |
|
||||
| task_id | BIGINT | 否 | 是 | 所属处理任务ID |
|
||||
| created_at | DATETIME | 否 | 是 | 记录创建时间 |
|
||||
| updated_at | DATETIME | 否 | 是 | 最后更新时间 |
|
||||
|
||||
### 6.2 失败文件管理表(t_fail_file)
|
||||
专门存储处理失败的文件信息,用于人工兜底处理
|
||||
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|
||||
|--------|----------|------|------|------|
|
||||
| id | BIGINT | 是 | 是 | 自增主键 |
|
||||
| file_process_id | BIGINT | 否 | 是 | 关联文件处理记录表ID,外键 |
|
||||
| file_hash | VARCHAR(64) | 否 | 是 | 文件SHA-256哈希值,唯一索引 |
|
||||
| source_file_path | VARCHAR(1000) | 否 | 是 | 原始源文件完整路径 |
|
||||
| file_name | VARCHAR(200) | 否 | 是 | 文件名 |
|
||||
| fail_type | VARCHAR(50) | 否 | 是 | 失败类型:MISSING_FIELD(字段缺失)/ENCODING_ERROR(编码乱码)/COVER_INVALID(封面无效)/API_NO_MATCH(API未匹配)/TRACK_FORMAT_ERROR(曲目格式错误)/OTHER(其他) |
|
||||
| fail_detail | TEXT | 否 | 是 | 失败详细原因,结构化JSON格式 |
|
||||
| raw_metadata | TEXT | 否 | 是 | 原始元数据快照,JSON格式 |
|
||||
| edit_metadata | TEXT | 否 | 否 | 人工编辑后的元数据草稿,JSON格式 |
|
||||
| status | VARCHAR(20) | 否 | 是 | 处理状态:PENDING(待处理)/EDITING(编辑中)/RESOLVED(已解决)/DISCARDED(已废弃) |
|
||||
| created_at | DATETIME | 否 | 是 | 失败记录创建时间 |
|
||||
| updated_at | DATETIME | 否 | 是 | 最后编辑时间 |
|
||||
| resolved_at | DATETIME | 否 | 否 | 解决时间 |
|
||||
|
||||
### 6.3 处理任务表(t_process_task)
|
||||
记录每次批量处理任务的信息,用于任务管理与进度追踪
|
||||
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|
||||
|--------|----------|------|------|------|
|
||||
| id | BIGINT | 是 | 是 | 自增主键 |
|
||||
| task_name | VARCHAR(100) | 否 | 是 | 任务名称 |
|
||||
| task_type | VARCHAR(20) | 否 | 是 | 任务类型:DIR_SCAN(目录扫描)/UPLOAD(文件上传)/REPROCESS(重新处理) |
|
||||
| source_path | VARCHAR(1000) | 否 | 否 | 源目录路径(目录扫描任务) |
|
||||
| total_file_count | INT | 否 | 是 | 总文件数 |
|
||||
| processed_count | INT | 否 | 是 | 已处理文件数 |
|
||||
| success_count | INT | 否 | 是 | 处理成功数 |
|
||||
| fail_count | INT | 否 | 是 | 处理失败数 |
|
||||
| duplicate_count | INT | 否 | 是 | 重复文件数 |
|
||||
| task_status | VARCHAR(20) | 否 | 是 | 任务状态:RUNNING(运行中)/PAUSED(已暂停)/FINISHED(已完成)/TERMINATED(已终止)/ERROR(异常中断) |
|
||||
| start_time | DATETIME | 否 | 是 | 任务启动时间 |
|
||||
| end_time | DATETIME | 否 | 否 | 任务结束时间 |
|
||||
| created_by | VARCHAR(50) | 否 | 是 | 创建人 |
|
||||
| remark | VARCHAR(500) | 否 | 否 | 任务备注 |
|
||||
|
||||
### 6.4 系统配置表(t_system_config)
|
||||
存储系统全局配置信息,支持可视化配置修改
|
||||
| 字段名 | 数据类型 | 主键 | 非空 | 说明 |
|
||||
|--------|----------|------|------|------|
|
||||
| id | BIGINT | 是 | 是 | 自增主键 |
|
||||
| config_key | VARCHAR(100) | 否 | 是 | 配置键,唯一索引 |
|
||||
| config_value | TEXT | 否 | 否 | 配置值 |
|
||||
| config_name | VARCHAR(100) | 否 | 是 | 配置名称 |
|
||||
| config_desc | VARCHAR(500) | 否 | 否 | 配置描述 |
|
||||
| is_editable | TINYINT | 否 | 是 | 是否可前端编辑:0-否,1-是 |
|
||||
| created_at | DATETIME | 否 | 是 | 创建时间 |
|
||||
| updated_at | DATETIME | 否 | 是 | 最后更新时间 |
|
||||
|
||||
---
|
||||
|
||||
## 七、技术栈选型与实现方案
|
||||
### 7.1 后端技术栈(Java + GraalVM)
|
||||
| 技术组件 | 选型 | 版本要求 | 选型说明 |
|
||||
|----------|------|----------|----------|
|
||||
| 核心框架 | Spring Boot 3.x | ≥3.2.0 | 原生支持GraalVM Native Image,生态完善,适配嵌入式开发 |
|
||||
| 原生编译支持 | Spring Native | 与Spring Boot版本一致 | 官方提供的GraalVM原生编译适配方案,解决反射、动态代理等原生镜像兼容问题 |
|
||||
| 数据库访问 | MyBatis-Plus | ≥3.5.5 | 轻量级ORM框架,适配GraalVM原生编译,简化数据库操作 |
|
||||
| 嵌入式数据库 | H2 Database | ≥2.2.224 | 嵌入式关系型数据库,无需额外部署,单文件运行,完美适配原生镜像 |
|
||||
| 元数据读写 | Jaudiotagger | ≥2.2.7 | 业界主流Java音频元数据处理库,支持全格式音频标签读写,API简单易用 |
|
||||
| 编码检测 | juniversalchardet | ≥2.4.0 | Mozilla开源编码检测库,自动识别元数据原始编码,适配中文/日文等多语言 |
|
||||
| 音频指纹提取 | AcoustID4J + FFmpeg | 最新稳定版 | AcoustID4J对接指纹识别API,FFmpeg提取音频特征,适配全格式音频 |
|
||||
| 图片处理 | Thumbnailator | ≥0.4.20 | 轻量级图片处理库,支持封面缩放、裁剪、格式转换,API简洁,适配原生编译 |
|
||||
| HTTP客户端 | Spring Cloud OpenFeign | 最新稳定版 | 声明式HTTP客户端,对接第三方API,适配GraalVM原生编译 |
|
||||
| 文件上传 | Spring Boot Standard Servlet | 原生支持 | 支持大文件分片上传、断点续传,适配大音频文件处理 |
|
||||
| 日志框架 | Logback | 与Spring Boot版本一致 | 适配原生编译,高性能日志框架,支持日志分级、滚动输出 |
|
||||
|
||||
#### 7.1.1 GraalVM原生编译核心实现方案
|
||||
1. **环境要求**:GraalVM JDK 21+,安装Native Image组件
|
||||
2. **原生镜像适配**
|
||||
- 对反射类、动态代理类、资源文件提前注册到`reflect-config.json`、`proxy-config.json`、`resource-config.json`配置文件中
|
||||
- 使用Spring Boot 3.x原生AOT提前处理,在编译期生成代理类、解析注解,避免运行期反射导致的原生镜像兼容问题
|
||||
- 对第三方库(Jaudiotagger、juniversalchardet等)进行原生镜像适配,解决第三方库的反射、资源加载问题
|
||||
3. **构建命令**:通过Spring Boot Maven插件一键构建原生镜像,命令如下:
|
||||
```bash
|
||||
mvn clean native:compile -Pnative
|
||||
```
|
||||
4. **产物输出**:构建完成后生成平台相关的可执行文件,无需JDK环境,直接双击即可运行
|
||||
|
||||
### 7.2 前端技术栈(Vue)
|
||||
| 技术组件 | 选型 | 版本要求 | 选型说明 |
|
||||
|----------|------|----------|----------|
|
||||
| 核心框架 | Vue 3 | ≥3.4.0 | 组合式API,性能优异,生态完善,符合用户技术栈要求 |
|
||||
| 构建工具 | Vite | ≥5.0.0 | 极速冷启动、热更新,开发体验优异,打包体积小 |
|
||||
| UI组件库 | Element Plus | ≥2.6.0 | 适配Vue 3,组件丰富,界面美观,支持暗黑模式,适配桌面端管理系统 |
|
||||
| 状态管理 | Pinia | ≥2.1.0 | Vue 3官方推荐状态管理库,轻量简洁,支持TypeScript |
|
||||
| 路由管理 | Vue Router | ≥4.2.0 | Vue官方路由库,适配Vue 3,支持嵌套路由、路由守卫 |
|
||||
| HTTP请求 | Axios | ≥1.6.0 | 业界主流HTTP客户端,支持请求拦截、响应拦截、超时重试 |
|
||||
| 文件上传 | vue-simple-uploader | ≥1.0.0 | 支持大文件分片上传、断点续传、拖拽上传,适配大音频文件 |
|
||||
| 音频播放 | vue3-audio | 最新稳定版 | 适配Vue 3的音频播放器组件,支持文件预览试听 |
|
||||
| 图表可视化 | ECharts | ≥5.4.0 | 百度开源图表库,性能优异,支持处理报告数据可视化展示 |
|
||||
| 代码规范 | TypeScript + ESLint | 最新稳定版 | 类型安全,代码规范统一,提升可维护性 |
|
||||
|
||||
#### 7.2.1 前端核心页面设计
|
||||
1. **仪表盘首页**:展示音乐库统计数据、近期任务处理情况、失败文件数量、磁盘占用情况,核心功能快捷入口
|
||||
2. **任务管理页面**:处理任务的创建、暂停、继续、终止,任务进度实时展示,历史任务查询,处理报告查看与导出
|
||||
3. **文件上传页面**:支持单个/多个文件拖拽上传,上传进度展示,上传完成后自动触发处理流程
|
||||
4. **失败文件管理页面**:失败文件列表筛选、搜索,批量操作,人工编辑入口,处理状态跟踪
|
||||
5. **元数据编辑页面**:音频预览播放器,元数据表单编辑,封面上传/搜索,歌词上传/搜索,校验与提交功能
|
||||
6. **系统配置页面**:全局配置可视化编辑,包括目标音乐库目录、归档模式、封面规格、API密钥配置等
|
||||
7. **日志管理页面**:系统日志查询、筛选、导出,日志级别配置
|
||||
|
||||
---
|
||||
|
||||
## 八、核心API接口设计
|
||||
采用RESTful风格设计,统一返回格式,适配前后端分离架构,核心接口如下:
|
||||
|
||||
### 8.1 统一返回格式
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": {},
|
||||
"timestamp": 1710000000000
|
||||
}
|
||||
```
|
||||
- 成功状态码:200
|
||||
- 业务异常状态码:400-499
|
||||
- 系统异常状态码:500
|
||||
|
||||
### 8.2 核心接口清单
|
||||
| 接口分类 | 请求方式 | 接口路径 | 接口说明 |
|
||||
|----------|----------|----------|----------|
|
||||
| 任务管理 | POST | /api/v1/task/create-dir-task | 创建目录扫描处理任务 |
|
||||
| 任务管理 | GET | /api/v1/task/list | 分页查询任务列表 |
|
||||
| 任务管理 | GET | /api/v1/task/{id}/detail | 查询任务详情与进度 |
|
||||
| 任务管理 | PUT | /api/v1/task/{id}/pause | 暂停任务 |
|
||||
| 任务管理 | PUT | /api/v1/task/{id}/resume | 继续任务 |
|
||||
| 任务管理 | PUT | /api/v1/task/{id}/terminate | 终止任务 |
|
||||
| 任务管理 | GET | /api/v1/task/{id}/report | 获取任务处理报告 |
|
||||
| 文件上传 | POST | /api/v1/file/upload | 音频文件分片上传 |
|
||||
| 文件上传 | POST | /api/v1/file/upload/merge | 分片上传完成后合并文件 |
|
||||
| 元数据处理 | POST | /api/v1/metadata/validate | 手动校验文件元数据合规性 |
|
||||
| 元数据处理 | POST | /api/v1/metadata/reprocess/{id} | 重新处理指定失败文件 |
|
||||
| 失败文件管理 | GET | /api/v1/fail-file/list | 分页查询失败文件列表 |
|
||||
| 失败文件管理 | GET | /api/v1/fail-file/{id}/detail | 查询失败文件详情与原始元数据 |
|
||||
| 失败文件管理 | PUT | /api/v1/fail-file/{id}/edit | 保存人工编辑的元数据草稿 |
|
||||
| 失败文件管理 | POST | /api/v1/fail-file/{id}/submit | 提交编辑后的元数据,重新触发处理流程 |
|
||||
| 失败文件管理 | POST | /api/v1/fail-file/batch-reprocess | 批量重新处理失败文件 |
|
||||
| 系统配置 | GET | /api/v1/config/list | 查询系统配置列表 |
|
||||
| 系统配置 | PUT | /api/v1/config/update | 更新系统配置 |
|
||||
| 系统配置 | POST | /api/v1/config/backup | 手动备份系统配置与数据库 |
|
||||
|
||||
---
|
||||
|
||||
## 九、部署与运维方案
|
||||
### 9.1 环境要求
|
||||
#### 9.1.1 开发环境
|
||||
| 组件 | 版本要求 |
|
||||
|------|----------|
|
||||
| JDK | GraalVM JDK 21+ |
|
||||
| Maven | ≥3.9.0 |
|
||||
| Node.js | ≥18.0.0 |
|
||||
| FFmpeg | 最新稳定版 |
|
||||
| 操作系统 | Windows 10+/macOS 12+/Linux 内核4.15+ |
|
||||
|
||||
#### 9.1.2 生产环境(原生镜像运行)
|
||||
| 组件 | 最低要求 | 推荐配置 |
|
||||
|------|----------|----------|
|
||||
| CPU | 2核4线程 | 4核8线程 |
|
||||
| 内存 | 512MB | 2GB |
|
||||
| 磁盘 | 剩余空间≥1GB | 剩余空间≥10GB(与音乐库大小匹配) |
|
||||
| 操作系统 | Windows 10+/macOS 12+/Linux 内核4.15+ | Linux 64位(NAS/家庭服务器) |
|
||||
| 依赖 | FFmpeg(音频指纹提取) | FFmpeg最新稳定版 |
|
||||
|
||||
### 9.2 部署步骤
|
||||
#### 9.2.1 原生镜像单机部署(Windows/Linux/macOS)
|
||||
1. **构建原生镜像**:通过Maven命令构建对应平台的原生可执行文件
|
||||
2. **环境准备**:目标机器安装FFmpeg,配置环境变量
|
||||
3. **文件部署**:将可执行文件、配置文件、数据库目录复制到目标机器
|
||||
4. **配置修改**:修改application.yml配置文件,设置目标音乐库目录、API密钥等配置
|
||||
5. **服务启动**:
|
||||
- Windows:双击可执行文件即可启动
|
||||
- Linux/macOS:赋予执行权限后,`./music-metadata-tool`启动
|
||||
6. **访问验证**:浏览器访问`http://localhost:8080`,进入前端管理界面
|
||||
|
||||
#### 9.2.2 Docker容器化部署
|
||||
1. **构建Docker镜像**:基于GraalVM原生镜像构建Docker镜像,Dockerfile示例如下:
|
||||
```dockerfile
|
||||
# 构建阶段
|
||||
FROM ghcr.io/graalvm/graalvm-community:21 AS builder
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN gu install native-image
|
||||
RUN mvn clean native:compile -Pnative -DskipTests
|
||||
|
||||
# 运行阶段
|
||||
FROM alpine:3.19
|
||||
WORKDIR /app
|
||||
# 安装依赖
|
||||
RUN apk add --no-cache ffmpeg libc6-compat
|
||||
# 复制原生可执行文件
|
||||
COPY --from=builder /app/target/music-metadata-tool /app/music-metadata-tool
|
||||
# 复制配置文件
|
||||
COPY src/main/resources/application.yml /app/config/application.yml
|
||||
# 暴露端口
|
||||
EXPOSE 8080
|
||||
# 挂载目录
|
||||
VOLUME ["/app/config", "/app/data", "/music/source", "/music/library"]
|
||||
# 启动命令
|
||||
ENTRYPOINT ["/app/music-metadata-tool", "--spring.config.location=/app/config/application.yml"]
|
||||
```
|
||||
2. **Docker Compose部署**:编写docker-compose.yml文件,一键启动服务
|
||||
3. **目录挂载**:将源音乐目录、目标音乐库目录、配置目录、数据目录挂载到宿主机
|
||||
4. **启动服务**:`docker-compose up -d`启动容器,浏览器访问对应端口即可使用
|
||||
|
||||
### 9.3 运维方案
|
||||
1. **日志管理**:系统日志按天滚动输出,保留30天日志,支持日志级别动态调整,异常日志自动标记告警
|
||||
2. **数据备份**:支持手动/自动备份数据库与配置文件,默认每天凌晨自动备份,保留最近7个备份文件
|
||||
3. **监控告警**:内置服务健康检查接口,支持Prometheus监控指标采集,磁盘空间不足、任务异常失败时自动告警
|
||||
4. **版本升级**:原生镜像版本升级只需替换可执行文件,重启服务即可完成,兼容历史数据;Docker版本升级只需替换镜像版本
|
||||
5. **故障恢复**:提供数据库恢复、配置回滚功能,任务异常中断后可自动恢复,无需重新全量处理
|
||||
|
||||
---
|
||||
|
||||
## 十、测试方案
|
||||
### 10.1 单元测试
|
||||
- 测试范围:核心领域层逻辑,包括元数据校验规则、去重算法、归档规则、编码转换等核心方法
|
||||
- 测试框架:JUnit 5 + Mockito
|
||||
- 覆盖率要求:核心业务逻辑代码覆盖率≥90%
|
||||
- 重点测试场景:必填字段校验、边界值测试、异常场景测试、编码转换测试
|
||||
|
||||
### 10.2 集成测试
|
||||
- 测试范围:第三方API对接、元数据读写、数据库操作、文件操作等组件集成能力
|
||||
- 重点测试场景:AcoustID/MusicBrainz API对接、音频文件元数据写入与读取、数据库CRUD操作、大文件上传与处理
|
||||
|
||||
### 10.3 功能测试
|
||||
| 测试模块 | 核心测试点 |
|
||||
|----------|------------|
|
||||
| 音乐源接入 | 多级目录递归扫描、断点续传、大文件分片上传、格式过滤、异常文件拒绝 |
|
||||
| 元数据校验 | 必填字段一票否决、编码乱码识别、格式规范校验、合规文件正常通过 |
|
||||
| 元数据补全 | API正常补全、补全数据二次校验、API异常容错、无猜测式补全 |
|
||||
| 去重与增量入库 | 哈希去重、特征去重、增量文件识别、重复文件跳过、异常去重处理 |
|
||||
| 自动归档 | 目录结构生成、文件名规范化、封面/歌词归档、Navidrome适配、冲突处理 |
|
||||
| 失败文件管理 | 失败原因记录、列表筛选、人工编辑、重新提交流程、批量操作 |
|
||||
| 系统管理 | 配置修改、任务管理、处理报告生成、日志查询、数据备份与恢复 |
|
||||
|
||||
### 10.4 兼容性测试
|
||||
1. **音频格式兼容**:覆盖MP3、FLAC、M4A、OGG、WAV格式的元数据读写与处理测试
|
||||
2. **系统兼容**:Windows、Linux、macOS三大操作系统的原生镜像部署与运行测试
|
||||
3. **Navidrome兼容**:处理后的音乐库导入Navidrome最新稳定版,验证扫描识别率、歌手/专辑/封面/歌词展示、曲目排序等核心场景
|
||||
4. **浏览器兼容**:Chrome、Edge、Firefox主流浏览器的前端界面功能测试
|
||||
|
||||
### 10.5 性能测试
|
||||
- 批量处理性能:1000个音频文件批量处理,验证处理速度、内存占用、CPU使用率
|
||||
- 启动性能:原生镜像启动时间测试,验证是否≤500ms
|
||||
- 大文件处理:2GB单音频文件上传、处理、归档全流程测试
|
||||
- 并发性能:多个任务同时运行,验证系统稳定性与处理能力
|
||||
|
||||
---
|
||||
|
||||
## 十一、风险与应对措施
|
||||
| 风险类型 | 风险描述 | 风险等级 | 应对措施 |
|
||||
|----------|----------|----------|----------|
|
||||
| 技术风险 | GraalVM原生镜像第三方库兼容问题,部分库存在反射、动态代理导致的编译失败 | 中 | 1. 提前对第三方库进行原生镜像适配验证;2. 优先选择支持GraalVM原生镜像的库;3. 提前注册反射、代理配置,通过Spring AOT提前处理 |
|
||||
| 业务风险 | 第三方API调用限流、故障,导致元数据补全失败 | 中 | 1. 内置API调用限流、超时重试机制;2. 提供API密钥配置,用户可使用自己的密钥;3. 异常时直接标记失败,不中断整体任务,后续支持手动重试 |
|
||||
| 数据风险 | 元数据写入导致音频文件损坏、原始文件丢失 | 高 | 1. 默认采用复制模式,不修改原始源文件;2. 元数据写入前自动备份源文件;3. 写入后校验文件完整性,异常时自动回滚;4. 提供移动模式开关,用户手动确认后开启 |
|
||||
| 性能风险 | 超大音乐库(10万+文件)全量扫描与处理性能瓶颈 | 中 | 1. 多线程并发处理,可配置线程数;2. 扫描与处理流程解耦,异步处理;3. 哈希比对优化,建立哈希索引,提升去重速度;4. 断点续传,支持分批次处理 |
|
||||
| 兼容性风险 | 小众音频格式元数据读写异常 | 低 | 1. 优先适配主流音频格式,小众格式提前校验,不支持的格式直接标记失败;2. 完善异常捕获,单个文件处理失败不影响整体任务 |
|
||||
| 安全风险 | 目录越权访问,误操作非授权目录文件 | 高 | 1. 目录白名单机制,仅对用户授权的目录进行读写;2. 严格校验文件路径,禁止路径穿越;3. 默认只读访问源目录,仅对目标目录有写入权限 |
|
||||
|
||||
---
|
||||
|
||||
## 十二、阶段文档索引与实施说明
|
||||
|
||||
为避免总方案文档随着阶段推进不断膨胀,P0、P1 及后续阶段的“开发落地说明、测试结果、验收证据、偏差说明”统一沉淀到项目仓库内的阶段文档中;本总文档仅保留全局设计、总体规则、阶段索引与里程碑说明。
|
||||
|
||||
### 12.1 文档组织规则
|
||||
|
||||
- 总方案文档:保留项目背景、需求、总体架构、统一规则、阶段规划
|
||||
- 阶段落地文档:写入每个阶段的实现内容、关键文件、测试策略、验收结果、已知偏差
|
||||
- 阶段落地文档统一存放于:`music-metadata-system/docs/`
|
||||
|
||||
### 12.2 当前阶段文档索引
|
||||
|
||||
| 阶段 | 文档 | 说明 |
|
||||
|------|------|------|
|
||||
| P0 | `music-metadata-system/docs/P0-基础架构-开发落地说明.md` | 记录基础架构、数据库底座、统一异常与响应规范的落地情况 |
|
||||
| P1 | `music-metadata-system/docs/P1-元数据解析与校验-开发落地说明.md` | 记录元数据读取、快照存储、一票否决校验、真实文件测试与覆盖率结果 |
|
||||
|
||||
### 12.3 当前状态摘要
|
||||
|
||||
- P0 已完成基础工程、数据库底座、基础持久化层和统一异常处理能力建设
|
||||
- P1 已完成元数据读取、编码检测与修复尝试、快照持久化、一票否决校验、目录扫描与去重相关验收能力
|
||||
- 详细实现、测试与验收结果请以对应阶段文档为准
|
||||
|
||||
## 十三、项目里程碑规划
|
||||
| 阶段 | 周期 | 核心交付物 | 完成标准 |
|
||||
|------|------|------------|----------|
|
||||
| 第一阶段:需求确认与架构设计 | 1周 | 需求规格说明书、架构设计文档、数据库设计文档、API接口文档 | 需求与架构方案确认完成,核心规则与技术选型敲定 |
|
||||
| 第二阶段:核心后端模块开发 | 3周 | 元数据解析与校验模块、文件去重模块、自动归档模块、API对接模块、数据库访问层 | 核心业务流程可跑通,音频文件可完成标准化校验与归档,适配Navidrome规范 |
|
||||
| 第三阶段:前端界面开发 | 2周 | Vue前端工程、所有核心页面、前后端接口联调 | 前端界面可正常访问,所有功能可通过界面操作完成 |
|
||||
| 第四阶段:GraalVM原生编译适配 | 1周 | 原生镜像适配配置、可执行文件构建脚本、Docker镜像构建文件 | 可正常构建对应平台的原生镜像,镜像可正常启动与运行,无兼容问题 |
|
||||
| 第五阶段:测试与Bug修复 | 2周 | 测试用例、测试报告、Bug修复记录 | 完成所有测试场景,核心功能无Bug,系统稳定运行,性能达标 |
|
||||
| 第六阶段:部署与上线 | 1周 | 部署文档、用户操作手册、正式版安装包、Docker镜像 | 系统可正常部署运行,用户可通过手册完成操作,正式版交付 |
|
||||
| 合计 | 10周 | 完整系统、全量文档、交付物 | 系统所有功能实现,满足所有需求与约束条件,可正式投入使用 |
|
||||
Reference in New Issue
Block a user