# 方案计划文档管理系统功能与接口规格 > 文档转换与 PDF 预览同步版本:1.6。实现以 `DMS_FUNCTION_CONTRACT.md` 1.4和 `DMS_API_CONTRACT.md` 1.4为最终依据。 ## 1. 文档目的 本文档用于对齐方案计划文档管理系统第一阶段的功能边界、业务规则和后端接口颗粒度,作为前后端开发、联调和验收依据。 如本文档与界面模拟数据不一致,以本文档中的业务规则为准;如需要改变业务规则,应先修改本文档并确认,再修改代码。 ## 2. 第一阶段范围 ### 2.1 本阶段包含 - 用户登录、退出和当前用户信息。 - 组织机构和人员查询。 - 方案计划分类树管理。 - 主案管理。 - 子方案管理。 - 共享附件库管理。 - 主案与共享附件的多对多挂载。 - 主案和子方案权限配置。 - 文档文件上传、预览和下载。 - 文档逻辑删除和恢复。 - 操作日志和基础统计。 - MySQL结构化数据持久化。 - `backend/dms-storage/`文件持久化。 ### 2.2 本阶段不包含 - 前端视觉风格重构。 - Milvus和文档向量化。 - AI模块改造。 - 电子签章。 - 审批工作流。 - 在线Office编辑。 - 国产化适配。 - 复杂文件历史版本管理。 - 匿名访问。 - 分类、用户或组织恢复。 - 批量恢复、物理删除和自动清理。 - 独立恢复ACL或挂载关系。 - 将逻辑删除文件移动到`recycle`目录。 ## 3. 角色定义 | 角色 | 说明 | 默认功能 | |---|---|---| | 普通用户 `USER` | 浏览方案资料的已登录用户 | 浏览有权访问的主案、子方案及其已挂载附件 | | 管理员 `ADMIN` | 系统、文档及审计管理人员 | 分类、主案、子方案、共享附件、权限、文件和审计管理 | 第一阶段角色固定,不提供动态角色配置页面。 ## 4. 核心术语 | 术语 | 定义 | |---|---| | 主案 | 顶层方案文档,可以包含多个子方案并挂载多个共享附件 | | 子方案 | 直接归属于一个主案的方案文档,第一阶段不允许继续嵌套 | | 共享附件 | 独立于主案存在、对全部已登录用户共享的附件文档 | | 挂载 | 建立主案与共享附件之间的引用关系,不复制文件 | | 解除挂载 | 删除主案与附件的关系,不删除附件文件 | | 方案分类 | 用于组织主案和子方案的树形分类 | | 组织机构 | 用于用户归属和文档权限配置的组织树,不作为方案分类 | ## 5. 全局业务规则 ### BR-001 登录范围 “所有人共享”是指所有已登录且状态正常的系统用户,不允许匿名访问。 ### BR-002 附件独立性 共享附件是独立文档,不属于某一个主案: - 附件自身只保存一份文件和一份元数据。 - 同一附件可以挂载到多个主案。 - 同一主案不能重复挂载同一附件。 - 解除挂载不能删除附件文件。 - 删除主案不能删除共享附件。 ### BR-003 附件访问权限 共享附件不配置组织或人员ACL。所有已登录用户均可查看和下载共享附件。 共享附件的上传、编辑、删除和挂载管理只允许管理员操作。 ### BR-004 附件删除 - 未挂载到任何主案的附件允许逻辑删除。 - 已挂载到一个或多个主案的附件,普通删除请求必须返回冲突错误。 - 第一阶段不提供“强制解除全部挂载并删除”接口。 - 管理员需要先处理全部挂载关系,再删除附件。 ### BR-005 主案与子方案 - 一个子方案只能属于一个主案。 - 一个主案可以包含多个子方案。 - 第一阶段不允许子方案继续包含子方案。 - 删除存在有效子方案的主案时默认拒绝。 ### BR-006 文件存储 - 文件存放在`backend/dms-storage/`。 - 数据库只保存相对路径。 - 文件必须通过后端鉴权接口读取,不能暴露静态磁盘目录。 - 文件删除与业务记录删除分离,业务删除默认不立即物理删除文件。 ### BR-007 逻辑删除 核心业务数据使用`is_deleted`和`deleted_at`逻辑删除。正常查询默认不返回已删除数据。 ### BR-008 操作审计 登录、查看、下载、上传、编辑、删除、恢复成功、权限变更、挂载和解除挂载必须记录审计日志。恢复成功使用 `RESTORE_DOCUMENT`;最小范围内恢复失败不写业务审计,只写安全应用日志。 ### BR-009 冗余字段 文档计数、附件挂载数、分类路径、人员名称等冗余字段由后端维护,前端不得将其作为可修改字段提交。 ## 6. 功能描述 ## 6.1 用户认证 ### F-AUTH-001 用户登录 **功能说明** 用户通过用户名和密码登录系统。 **输入** - 用户名。 - 密码。 - 是否保持登录状态。 **处理规则** 1. 用户名和密码不能为空。 2. 用户必须存在、未逻辑删除且状态为`ENABLED`。 3. 后端验证密码哈希。 4. 登录成功后返回访问凭证和当前用户概要。 5. 更新最近登录时间和IP。 6. 登录成功或失败均写入审计日志。 **输出** - 登录凭证。 - 用户ID、姓名、组织、角色和安全等级。 - 可访问的顶部功能入口。 **异常** - 用户名或密码错误。 - 用户被锁定或禁用。 - 系统内部错误。 ### F-AUTH-002 用户退出 使当前登录凭证失效并记录退出日志。 ### F-AUTH-003 当前用户 返回当前登录用户、所属组织和固定角色,用于恢复前端登录状态。 ## 6.2 方案分类 ### F-CAT-001 查询分类树 返回全部有效方案分类的树形结构,按`sort_no`排序。 ### F-CAT-002 新增分类 管理员可以新增顶级分类或指定父分类下的子分类。 ### F-CAT-003 编辑分类 管理员可以修改分类名称、类型和排序。修改后同步更新后代路径及关联文档的分类冗余字段。 ### F-CAT-004 删除分类 存在有效子分类或有效文档时拒绝删除;否则进行逻辑删除。 ## 6.3 主案管理 ### F-MAIN-001 查询主案列表 **筛选条件** - 分类ID。 - 关键词。 - 密级。 -可见范围。 - 状态。 - 更新时间。 - 页码、每页数量和排序。 **列表输出** - 文档ID。 - 文档名称。 - 类型。 - 密级。 - 可见范围。 - 子方案数量。 - 已挂载附件数量。 - 更新时间。 - 当前用户允许的操作。 普通用户列表必须在后端完成权限过滤。 ### F-MAIN-002 查询主案详情 返回文档元数据、文件信息、分类路径、标签、权限概要、子方案数量和附件数量。 ### F-MAIN-003 上传主案或子案 单文件上传统一在一个弹框中选择方案类型。子案选择所属主案后自动继承主案分类。主案名称全局唯一,子案名称在所属主案内唯一;重名时必须经用户确认后覆盖原记录,不采用先删后传。 管理员上传一个文件并填写文档元数据。文件和数据库记录必须具有失败补偿。 ### F-MAIN-004 编辑主案 管理员修改文档名称、概述、分类、密级、可见范围、标签和状态,不直接在线编辑文件内容。 ### F-MAIN-005 删除与恢复主案 - 删除使用逻辑删除。 - 存在有效子方案时拒绝删除。 - 删除时只删除主案与附件的挂载关系,不删除共享附件。 - 恢复只使用 `/api/v1/recycle-bin/documents/{id}/restore`;旧 `/api/v1/documents/{id}/restore` 永久废止。 - 恢复时校验安全相对路径、原始文件、大小、哈希、格式和分类。 - 恢复主案时恢复同一删除批次中仍有效且不冲突的ACL和挂载关系;无效主体或已删除附件跳过并计数。 - `ORGANIZATION`恢复后必须有有效可查看ORG权限;`CUSTOM`允许空权限集合。 ## 6.4 子方案管理 ### F-SUB-001 查询主案的子方案 根据主案ID返回其直接子方案列表。 ### F-SUB-002 上传子方案 管理员在指定主案下上传子方案,创建时继承或复制主案权限。 ### F-SUB-003 编辑、查看、下载和删除 行为与主案对应功能一致,但删除子方案不影响主案和共享附件。 ## 6.5 共享附件库 ### F-ATT-001 查询共享附件 **筛选条件** - 关键词:名称、概述和标签。 - 附件类型。 - 文件格式。 - 更新时间。 - 页码、每页数量和排序。 **列表输出** - 附件ID。 - 附件名称。 - 附件类型。 - 文件格式。 - 标签。 - 上传人。 - 更新时间。 - 已挂载主案数量。 - 当前用户允许的操作。 ### F-ATT-002 上传附件 管理员将文件上传到共享附件库。上传成功后附件立即对全部已登录用户可见。 ### F-ATT-003 批量导入附件 管理员一次选择多个文件;每个文件独立返回成功或失败结果,不因一个文件失败回滚全部成功文件。 ### F-ATT-004 查看和下载附件 全部已登录用户均可调用。接口仍需验证登录状态并写入审计日志。 ### F-ATT-005 编辑附件 管理员可以编辑名称、附件类型、概述和标签。不能通过编辑接口改变附件ID和挂载关系。 ### F-ATT-006 删除附件 后端先计算有效挂载数量: - 数量为0:逻辑删除。 - 数量大于0:返回`409 ATTACHMENT_IN_USE`及影响主案概要。 ### F-ATT-007 查看附件挂载关系 返回附件当前挂载的全部有效主案,用于“挂载主案数”和挂载关系弹窗。 ## 6.6 附件挂载 ### F-BIND-001 查询主案已挂载附件 根据主案ID返回有效挂载附件,包含挂载顺序和附件当前挂载主案总数。 ### F-BIND-002 批量挂载附件 管理员一次选择一个或多个共享附件挂载到当前主案。 **处理规则** 1. 主案必须存在且类型为`MAIN`。 2. 所有附件必须存在且类型为`ATTACHMENT`。 3. 已挂载附件不重复创建关系。 4. 一个请求内重复的附件ID自动去重。 5. 在一个数据库事务内创建挂载关系并更新主案附件计数。 6. 写入挂载审计日志。 **输出** - 新增挂载数量。 - 已存在数量。 - 当前有效挂载总数。 ### F-BIND-003 解除挂载 逻辑删除指定主案和附件的挂载关系,更新主案附件计数,附件本身保持不变。 ### F-BIND-004 上传新附件并挂载 这是前端组合功能,不设计独立原子接口: 1. 调用“上传附件”。 2. 上传成功后调用“批量挂载附件”。 3. 如果挂载失败,新附件仍保留在共享附件库,前端提示用户可以稍后重新挂载。 ## 6.7 文档权限 ### F-PERM-001 查询权限 返回主案或子方案的组织权限和人员权限。共享附件不调用该功能。 ### F-PERM-002 保存权限 管理员提交完整权限集合,后端在一个事务内完成新增、更新和逻辑删除。 权限维度: - 查看。 - 下载。 - 编辑。 - 权限管理。 - 删除。 ## 6.8 文件预览与下载 ### F-FILE-001 预览文件 后端验证文档有效性和用户查看权限后返回文件。PDF 直接返回原文件;DOC、DOCX 先由 LibreOffice 离线转换为 PDF 再返回;XLS、XLSX 不支持在线预览。转换失败返回 `PREVIEW_CONVERTER_UNAVAILABLE`、`PREVIEW_CONVERSION_TIMEOUT` 或 `PREVIEW_CONVERSION_FAILED`。 ### F-FILE-002 下载文件 后端验证下载权限、返回原始文件、更新下载计数并写入审计日志。 共享附件只检查登录状态;主案和子方案检查文档ACL。 ## 6.9 审计日志与统计 ### F-AUDIT-001 查询日志 支持按关键词、时间范围、用户、组织、操作类型、结果和目标对象分页查询。 ### F-AUDIT-002 后台文档统计 返回: - 有效文档总数。 - 主案数量。 - 子方案数量。 - 共享附件数量。 - 今日查看人数。 ### F-AUDIT-003 审计图表 返回最近操作趋势、操作类型分布和人员活跃度。 ## 6.10 回收站与恢复 ### F-RECYCLE-001 查询文档回收站 仅ADMIN可以查询逻辑删除且 `deleted_at` 非空的MAIN、SUB_PLAN和ATTACHMENT。支持: - keyword; - documentType; - categoryId; - deletedFrom、deletedTo; - page、pageSize; - sortField、sortDirection。 删除时间使用带 `Z` 的UTC时间和 `[deletedFrom, deletedTo)`区间。默认按 `deletedAt desc, id desc`稳定排序。删除人从最近一次匹配的成功 `DELETE_DOCUMENT`审计批量获取;无可靠审计时返回null,不得用最后更新人冒充。 ### F-RECYCLE-002 恢复文档 仅ADMIN可以单条恢复。请求必须携带删除记录当前 `rowVersion`。恢复采用事务前完整文件校验和事务内提交前文件状态复核;恢复、关系、冗余计数和 `RESTORE_DOCUMENT`审计原子提交。 - MAIN恢复同一删除批次的有效ACL和挂载关系;无效主体、已删除附件跳过,关系唯一冲突整体回滚。 - SUB_PLAN要求父主案和根主案指向同一有效MAIN,恢复后继承主案当前权限。 - ATTACHMENT保持PUBLIC和ALL_AUTHENTICATED,不恢复ACL或历史挂载。 - 恢复响应使用纯序列化,不增加查看次数或产生 `VIEW_DOCUMENT`审计。 - 不移动、复制或删除原始文件。 ## 7. 接口通用约定 ### 7.1 基础路径 ```text /api/v1 ``` 现有AI相关`/api`接口本阶段不调整。 ### 7.2 认证 除登录接口外,所有接口都需要有效登录凭证。 推荐请求头: ```http Authorization: Bearer X-Request-Id: ``` ### 7.3 成功响应 ```json { "code": "OK", "message": "success", "data": {}, "requestId": "8ed3e305-73a8-4af7-8f39-1b86b9a2dad2", "timestamp": "2026-07-23T02:00:00.000Z" } ``` ### 7.4 分页响应 ```json { "code": "OK", "message": "success", "data": { "items": [], "page": 1, "pageSize": 20, "total": 0, "totalPages": 0 }, "requestId": "uuid", "timestamp": "2026-07-23T02:00:00.000Z" } ``` ### 7.5 错误响应 ```json { "code": "ATTACHMENT_IN_USE", "message": "附件已挂载到其他主案,不能删除", "details": { "attachmentId": 101, "mountedPlanCount": 3 }, "requestId": "uuid", "timestamp": "2026-07-23T02:00:00.000Z" } ``` ### 7.6 HTTP状态码 | 状态码 | 用途 | |---:|---| | 200 | 查询、编辑、删除成功 | | 201 | 创建成功 | | 400 | 参数格式错误 | | 401 | 未登录或凭证失效 | | 403 | 权限不足 | | 404 | 数据不存在或已删除 | | 409 | 数据冲突、附件正在使用、并发版本冲突 | | 413 | 上传文件或请求体过大 | | 415 | 不支持的文件格式 | | 500 | 未处理的系统错误 | ### 7.7 并发更新 编辑和删除请求携带`rowVersion`。版本不一致返回: ```text 409 DATA_VERSION_CONFLICT ``` ## 8. 接口目录 ## 8.1 认证接口 | 方法 | 路径 | 功能 | |---|---|---| | POST | `/api/v1/auth/login` | 登录 | | POST | `/api/v1/auth/logout` | 退出 | | GET | `/api/v1/users/me` | 当前用户 | ## 8.2 组织和人员 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/organizations/tree` | 组织树 | | GET | `/api/v1/users` | 人员查询 | ## 8.3 分类 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/categories/tree` | 分类树 | | POST | `/api/v1/categories` | 新增分类 | | PUT | `/api/v1/categories/{id}` | 编辑分类 | | DELETE | `/api/v1/categories/{id}` | 逻辑删除分类 | ## 8.4 主案和子方案 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/documents` | 文档分页查询 | | POST | `/api/v1/documents` | 上传主案或子方案 | | GET | `/api/v1/documents/{id}` | 文档详情 | | PUT | `/api/v1/documents/{id}` | 编辑文档 | | DELETE | `/api/v1/documents/{id}` | 逻辑删除文档 | | GET | `/api/v1/main-plans/{id}/sub-plans` | 查询主案子方案 | 旧 `/api/v1/documents/{id}/restore` 永久废止,不得重定向或兼容调用。 ## 8.5 文档回收站 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/recycle-bin/documents` | 查询回收站文档 | | POST | `/api/v1/recycle-bin/documents/{id}/restore` | 单条恢复文档 | ## 8.6 共享附件 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/attachments` | 附件分页查询 | | POST | `/api/v1/attachments` | 上传附件 | | POST | `/api/v1/attachments/batch-import` | 批量导入附件 | | GET | `/api/v1/attachments/{id}` | 附件详情 | | PUT | `/api/v1/attachments/{id}` | 编辑附件 | | DELETE | `/api/v1/attachments/{id}` | 删除未挂载附件 | | GET | `/api/v1/attachments/{id}/main-plans` | 查询附件挂载的主案 | ## 8.7 附件挂载 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/main-plans/{id}/attachments` | 查询主案已挂载附件 | | POST | `/api/v1/main-plans/{id}/attachments/bind` | 批量挂载附件 | | DELETE | `/api/v1/main-plans/{id}/attachments/{attachmentId}` | 解除挂载 | ## 8.8 权限 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/documents/{id}/permissions` | 查询文档权限 | | PUT | `/api/v1/documents/{id}/permissions` | 保存文档权限 | ## 8.9 文件 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/documents/{id}/preview` | 预览文档 | | GET | `/api/v1/documents/{id}/download` | 下载文档 | 共享附件同样使用统一的 `/api/v1/documents/{id}/preview` 和 `/api/v1/documents/{id}/download` 路径;不提供附件专用的重复文件读取路径。 ## 8.10 审计和统计 | 方法 | 路径 | 功能 | |---|---|---| | GET | `/api/v1/audit/logs` | 日志查询 | | GET | `/api/v1/statistics/documents` | 后台统计卡片 | | GET | `/api/v1/audit/statistics/trend` | 操作趋势 | | GET | `/api/v1/audit/statistics/actions` | 操作类型分布 | | GET | `/api/v1/audit/statistics/users` | 人员活跃度 | ## 9. 关键接口详细描述 ### 9.1 上传主案或子方案 ```http POST /api/v1/documents Content-Type: multipart/form-data ``` 表单字段: | 字段 | 必填 | 说明 | |---|---|---| | `file` | 是 | 原始文件 | | `documentName` | 是 | 文档名称 | | `documentType` | 是 | `MAIN`或`SUB_PLAN` | | `parentDocumentId` | 子方案必填 | 所属主案 | | `categoryId` | 是 | 方案分类 | | `summary` | 否 | 文档概述 | | `securityLevel` | 是 | 密级 | | `visibilityType` | 是 | 可见范围类型 | | `tags` | 否 | JSON数组字符串 | | `versionNo` | 否 | 默认`V1` | 成功响应`data`至少包含: ```json { "id": 125, "documentName": "综合应急预案", "documentType": "MAIN", "fileOriginalName": "综合应急预案.docx", "fileSize": 102400, "fileHash": "sha256", "createdAt": "2026-07-23T02:00:00.000Z", "rowVersion": 0 } ``` ### 9.2 查询共享附件 ```http GET /api/v1/attachments?page=1&pageSize=20&keyword=应急&attachmentType=POLICY&fileFormat=PDF ``` 附件项: ```json { "id": 101, "attachmentName": "中华人民共和国突发事件应对法", "attachmentType": "POLICY", "attachmentTypeName": "政策法规", "fileFormat": "DOCX", "tags": ["应急", "法规"], "uploaderId": 1, "uploaderName": "系统管理员", "updatedAt": "2026-07-20T08:00:00.000Z", "mountedPlanCount": 6, "allowedActions": ["VIEW", "DOWNLOAD", "EDIT", "DELETE"] } ``` 普通用户的`allowedActions`只返回`VIEW`和`DOWNLOAD`。 ### 9.3 批量挂载共享附件 ```http POST /api/v1/main-plans/1/attachments/bind Content-Type: application/json ``` 请求: ```json { "attachmentIds": [101, 102, 108], "rowVersion": 3 } ``` 响应: ```json { "code": "OK", "message": "挂载完成", "data": { "mainPlanId": 1, "createdCount": 2, "alreadyMountedCount": 1, "totalMountedCount": 5, "rowVersion": 4 } } ``` ### 9.4 解除附件挂载 ```http DELETE /api/v1/main-plans/1/attachments/108 Content-Type: application/json ``` 请求: ```json { "rowVersion": 4 } ``` 响应需要明确附件未被删除: ```json { "code": "OK", "message": "已解除挂载,共享附件仍保留在附件库", "data": { "mainPlanId": 1, "attachmentId": 108, "totalMountedCount": 4, "rowVersion": 5 } } ``` ### 9.5 删除共享附件 ```http DELETE /api/v1/attachments/101 Content-Type: application/json ``` 请求: ```json { "rowVersion": 2 } ``` 如果附件仍被使用: ```json { "code": "ATTACHMENT_IN_USE", "message": "附件已挂载到6个主案,请先解除挂载关系", "details": { "attachmentId": 101, "mountedPlanCount": 6, "mainPlans": [ {"id": 1, "name": "2024年度综合应急预案"}, {"id": 2, "name": "战备物资管理规程"} ] } } ``` ### 9.6 保存文档权限 ```http PUT /api/v1/documents/1/permissions Content-Type: application/json ``` 请求: ```json { "rowVersion": 2, "permissions": [ { "subjectType": "ORG", "subjectId": 11, "canView": true, "canDownload": true, "canEdit": false, "canManagePermission": false, "canDelete": false }, { "subjectType": "USER", "subjectId": 1001, "canView": true, "canDownload": true, "canEdit": true, "canManagePermission": false, "canDelete": false } ] } ``` 共享附件不能调用此接口,调用时返回: ```text 400 SHARED_ATTACHMENT_PERMISSION_NOT_CONFIGURABLE ``` ## 10. 前端按钮与接口映射 | 页面按钮 | 功能编号 | 接口 | |---|---|---| | 登录 | F-AUTH-001 | `POST /auth/login` | | 添加顶级分类 | F-CAT-002 | `POST /categories` | | 编辑分类 | F-CAT-003 | `PUT /categories/{id}` | | 删除分类 | F-CAT-004 | `DELETE /categories/{id}` | | 上传主案 | F-MAIN-003 | `POST /documents` | | 查看主案 | F-MAIN-002 | `GET /documents/{id}`、`GET /documents/{id}/preview` | | 编辑主案 | F-MAIN-004 | `PUT /documents/{id}` | | 主案权限 | F-PERM-001/002 | `GET/PUT /documents/{id}/permissions` | | 删除主案 | F-MAIN-005 | `DELETE /documents/{id}` | | 查询回收站 | F-RECYCLE-001 | `GET /recycle-bin/documents` | | 恢复文档 | F-RECYCLE-002 | `POST /recycle-bin/documents/{id}/restore` | | 上传子方案 | F-SUB-002 | `POST /documents` | | 共享附件库 | F-ATT-001 | `GET /attachments` | | 上传附件 | F-ATT-002 | `POST /attachments` | | 批量导入附件 | F-ATT-003 | `POST /attachments/batch-import` | | 从共享附件库挂载 | F-BIND-002 | `POST /main-plans/{id}/attachments/bind` | | 解除挂载 | F-BIND-003 | `DELETE /main-plans/{id}/attachments/{attachmentId}` | | 查看挂载主案数 | F-ATT-007 | `GET /attachments/{id}/main-plans` | | 删除共享附件 | F-ATT-006 | `DELETE /attachments/{id}` | | 日志筛选 | F-AUDIT-001 | `GET /audit/logs` | ## 11. 第一阶段验收场景 ### AC-001 同一附件挂载多个主案 上传一个共享附件,将其分别挂载到两个主案。附件库只存在一条附件记录,挂载主案数为2。 ### AC-002 重复挂载 对同一主案重复挂载同一附件,不产生重复关系,接口返回已存在数量。 ### AC-003 解除挂载 从一个主案解除附件后: - 该主案的附件数量减少; - 其他主案挂载不受影响; - 附件库仍可查看和下载附件。 ### AC-004 删除正在使用的附件 删除已挂载附件时返回`409 ATTACHMENT_IN_USE`,附件和全部挂载关系保持不变。 ### AC-005 全员共享 任意状态正常的普通用户登录后,可以查询、预览和下载共享附件,但不能上传、编辑、删除或挂载附件。 ### AC-006 主案权限不影响共享附件 用户无权查看某一主案,但仍可以从共享附件库访问该主案所挂载的共享附件。 ### AC-007 文件和数据库一致性 上传文件失败时不产生有效文档记录;数据库事务失败时不留下正式目录孤儿文件。 ### AC-008 逻辑删除 逻辑删除后的主案、子方案或附件不出现在正常列表,也不能继续预览和下载。 ## 12. 待确认但不阻塞当前设计的事项 以下事项后续可以单独确认,不影响当前功能和接口颗粒度: 1. 共享附件是否允许用户收藏。 2. 附件类型是否固定为政策法规、工作规范、表格资料、图示资料和其他资料。 3. 主案删除时是否自动解除附件挂载,当前定义为自动解除但不删除附件。 4. 回收站页面采用独立资源路径,不启用已废止的文档恢复旧路径。 5. 批量导入是否升级为持久化异步任务,当前第一阶段定义为受限的同步逐文件结果。 ## 13. B8恢复数据和迁移补充 - 文档名称、原文件名、分类下名称、同一主案下子方案名称和文件哈希允许重复。 - 恢复冲突仅处理有效ACL、有效挂载及主键或结构一致性冲突。 - B8实现创建 `0002_add_restore_audit_action`,扩展审计动作CHECK并在 `doc_document`增加 `(is_deleted, deleted_at, id)`索引。 - 不修改 `0001_initial_schema`,不新增表,不修改历史审计。 - B8实现同步将OpenAPI `info.version`升级为 `1.1.0`。 - 恢复错误码统一为: ```text DOCUMENT_NOT_DELETED FILE_INTEGRITY_MISMATCH FILE_PATH_INVALID RESTORE_FILE_CHANGED RESTORE_CATEGORY_INVALID RESTORE_PARENT_INVALID RESTORE_PERMISSION_INVALID RESTORE_RELATION_CONFLICT ``` HTTP状态、message和details结构以 `DMS_API_CONTRACT.md` 1.1为准,响应不得泄露绝对路径、哈希、SQL、数据库连接信息或内部异常堆栈。 ## 14. Q1-B统一UI字典补充 - 新增只读接口 `GET /api/v1/config/ui-dictionaries`,所有有效登录用户均可访问。 - API和数据库继续使用稳定英文枚举代码;中文标签仅用于展示,由后端配置文件统一提供。 - 默认配置文件为 `backend/dms/resources/ui-dictionaries.zh-CN.json`,可通过 `DMS_UI_DICTIONARY_CONFIG_PATH`覆盖。外部路径仅供服务端使用,不得进入响应。 - 配置完整覆盖14组正式界面枚举,并在启动时与Python枚举代码集合进行严格一致性校验。 - 配置加载为不可变内存对象,请求不重复读取磁盘;修改配置后重启生效,本阶段不支持热更新。 - 字典查询不产生业务审计,字典读取本身不访问数据库;现有认证基础设施继续执行令牌和用户状态校验。 - 不新增数据库表、字段或迁移,不提供配置写接口,不修改既有业务语义。 - Q1-B实现同步将OpenAPI `info.version`升级为 `1.2.0`。 ## 15. Q2-B更新时间范围检索补充 - `GET /api/v1/documents`、`GET /api/v1/main-plans/{id}/sub-plans`、`GET /api/v1/main-plans/{id}/attachments`统一接受可选 `updatedFrom`和 `updatedTo`。 - 两个边界分别表示文档自身 `updated_at >= updatedFrom`和 `updated_at <= updatedTo`,同时提供时为闭区间。 - 子方案使用子方案自身更新时间;挂载附件使用附件文档自身更新时间,不使用挂载关系时间或排序号。 - 时间必须是包含明确时区的ISO 8601格式,前端统一发送UTC `Z`;空字符串、无时区、非法格式和反向区间返回 `400 INVALID_ARGUMENT`。 - 时间条件在数据库查询和分页前执行,且不改变权限、密级、状态、排序、DTO、计数和审计语义。 - Q2-B不新增数据库、字段、索引或迁移;当时OpenAPI升级为 `1.3.0`。 ## 22. Q3-B 1.4同步说明 Q3-B将正式角色收敛为ADMIN和USER,审计能力归入ADMIN;分类仅允许叶子节点直接存放MAIN,分类树计数按当前用户在完整子树中的可见MAIN计算;文档列表支持`includeDescendants`。MAIN/SUB_PLAN创建和编辑不再接收status、visibilityType,SUB_PLAN分类继承主案。独立附件库仅ADMIN可枚举,USER按已挂载主案权限访问附件。统一preview路径原样返回PDF或DOCX,DOC/XLS/XLSX返回415,不调用Office类软件。`0003_q3_business_alignment_and_content_search`增加正文提取字段并将search_text扩展为LONGTEXT,keyword组合检索元数据与正文;当前参数化LIKE适用于现阶段规模,但数据量增长后存在全表/大文本扫描风险,后续索引或搜索引擎方案必须另行评审。OpenAPI为1.4.0。