Documents: get: operationId: listDocuments summary: 分页查询主案和子方案 parameters: - $ref: '../components/parameters.yaml#/XRequestId' - {name: documentType, in: query, schema: {type: string, default: MAIN}} - {name: categoryId, in: query, schema: {$ref: '../components/schemas.yaml#/StringId'}} - name: includeDescendants in: query description: 与categoryId同时使用时,是否包含全部有效后代分类;默认false。 schema: {type: boolean, default: false} - {name: keyword, in: query, schema: {type: string}} - {name: securityLevel, in: query, schema: {$ref: '../components/schemas.yaml#/SecurityLevel'}} - {name: status, in: query, schema: {$ref: '../components/schemas.yaml#/DocumentStatus'}} - $ref: '../components/parameters.yaml#/UpdatedFrom' - $ref: '../components/parameters.yaml#/UpdatedTo' - name: sortBy in: query schema: type: string enum: [documentName, createdAt, updatedAt, viewCount, downloadCount] default: updatedAt - {name: sortDirection, in: query, schema: {type: string, enum: [asc, desc], default: desc}} - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}} - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}} responses: '200': {description: 方案分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPageResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} post: operationId: createDocument summary: 上传主案或子方案 requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: false required: [file, metadata] properties: file: {type: string, format: binary} metadata: type: string description: DocumentCreateMetadata的JSON字符串。 responses: '201': {description: 上传成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'} '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'} '500': {$ref: '../components/responses.yaml#/InternalError'} Document: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: getDocument summary: 查询主案或子方案详情 responses: '200': {description: 方案详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} put: operationId: updateDocument summary: 编辑方案文档元数据 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/UpdateDocumentRequest'} responses: '200': {description: 编辑成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} delete: operationId: deleteDocument summary: 逻辑删除方案文档 parameters: - {name: rowVersion, in: query, required: true, schema: {type: integer, minimum: 0}} responses: '200': {description: 删除成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DeleteDocumentResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} SubPlans: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: listMainPlanSubPlans summary: 查询主案的直接子方案 parameters: - {name: keyword, in: query, schema: {type: string}} - {name: status, in: query, schema: {$ref: '../components/schemas.yaml#/DocumentStatus'}} - $ref: '../components/parameters.yaml#/UpdatedFrom' - $ref: '../components/parameters.yaml#/UpdatedTo' - name: sortBy in: query schema: {type: string, enum: [documentName, createdAt, updatedAt, viewCount, downloadCount], default: updatedAt} - {name: sortDirection, in: query, schema: {type: string, enum: [asc, desc], default: desc}} - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}} - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}} responses: '200': {description: 子方案分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPageResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} Attachments: get: operationId: listAttachments summary: 分页查询独立共享附件库(全量可见,普通用户allowedActions为空且不返回description/contentSnippet) description: 所有登录用户可访问,支撑全局检索按标题命中全部附件;附件内容访问由详情/预览/下载接口按挂载主案权限独立拦截。 parameters: - $ref: '../components/parameters.yaml#/XRequestId' - {name: keyword, in: query, schema: {type: string}} - {name: attachmentType, in: query, schema: {$ref: '../components/schemas.yaml#/AttachmentType'}} - {name: fileExtension, in: query, schema: {type: string}} - $ref: '../components/parameters.yaml#/UpdatedFrom' - $ref: '../components/parameters.yaml#/UpdatedTo' - name: sortBy in: query schema: {type: string, enum: [documentName, createdAt, updatedAt, viewCount, downloadCount], default: updatedAt} - {name: sortDirection, in: query, schema: {type: string, enum: [asc, desc], default: desc}} - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}} - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}} responses: '200': {description: 附件分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPageResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} post: operationId: createAttachment summary: 上传共享附件 requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: false required: [file, metadata] properties: file: {type: string, format: binary} metadata: type: string description: AttachmentCreateMetadata的JSON字符串。 responses: '201': {description: 上传成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'} '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'} '500': {$ref: '../components/responses.yaml#/InternalError'} Attachment: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: getAttachment summary: 查询共享附件详情 responses: '200': {description: 附件详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} put: operationId: updateAttachment summary: 编辑共享附件元数据 requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/UpdateAttachmentRequest'} responses: '200': {description: 编辑成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} delete: operationId: deleteAttachment summary: 逻辑删除共享附件 parameters: - {name: rowVersion, in: query, required: true, schema: {type: integer, minimum: 0}} responses: '200': {description: 删除成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DeleteDocumentResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentBatchImport: post: operationId: batchImportDocuments summary: 批量导入主案和子方案 requestBody: required: true content: multipart/form-data: schema: $ref: '../components/schemas.yaml#/BatchImportMultipart' responses: '200': {description: 逐文件导入结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/BatchImportResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'} '500': {$ref: '../components/responses.yaml#/InternalError'} AttachmentBatchImport: post: operationId: batchImportAttachments summary: 批量导入共享附件 requestBody: required: true content: multipart/form-data: schema: $ref: '../components/schemas.yaml#/BatchImportMultipart' responses: '200': {description: 逐文件导入结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/BatchImportResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentPreview: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: previewDocument summary: PDF直接预览;DOC、DOCX、WPS由LibreOffice离线转换为PDF后预览 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': description: PDF文件流(PDF原文件或DOC/DOCX/WPS转换后的PDF) headers: X-Request-Id: {schema: {type: string, format: uuid}} content: application/pdf: {schema: {type: string, format: binary}} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'} '502': {$ref: '../components/responses.yaml#/PreviewConversionFailed'} '503': {$ref: '../components/responses.yaml#/PreviewConverterUnavailable'} '504': {$ref: '../components/responses.yaml#/PreviewConversionTimeout'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentDownload: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: downloadDocument summary: 下载原始文档 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': description: 原始文件流 headers: X-Request-Id: {schema: {type: string, format: uuid}} content: application/octet-stream: {schema: {type: string, format: binary}} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} AttachmentMainPlans: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: listAttachmentMainPlans summary: 查询共享附件挂载的可见主案 responses: '200': {description: 主案简要集合, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/MainPlanBriefCollectionResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} MainPlanAttachments: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: listMainPlanAttachments summary: 查询主案已挂载共享附件 parameters: - {name: keyword, in: query, schema: {type: string}} - {name: attachmentType, in: query, schema: {$ref: '../components/schemas.yaml#/AttachmentType'}} - $ref: '../components/parameters.yaml#/UpdatedFrom' - $ref: '../components/parameters.yaml#/UpdatedTo' - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}} - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}} responses: '200': {description: 挂载附件分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/AttachmentBindingPageResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} MainPlanAttachmentBinding: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} post: operationId: bindMainPlanAttachments summary: 批量挂载共享附件到主案 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/BindAttachmentsRequest'} responses: '200': {description: 挂载结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/BindAttachmentsResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} MainPlanAttachmentsReorder: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} put: operationId: reorderMainPlanAttachments summary: 调整主案下挂载附件的显示顺序 description: 顺序存于挂载关系,同一附件在不同主案中可各自独立排序。 parameters: - $ref: '../components/parameters.yaml#/XRequestId' requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/ReorderAttachmentsRequest'} responses: '200': {description: 重排结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/ReorderAttachmentsResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} MainPlanAttachment: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} - {name: attachmentId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} delete: operationId: unbindMainPlanAttachment summary: 解除主案和共享附件的挂载 parameters: - {name: mainPlanRowVersion, in: query, required: true, schema: {type: integer, minimum: 0}} - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': {description: 解除挂载结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/UnbindAttachmentResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentsTags: get: operationId: listMainPlanTags summary: 聚合当前用户可见的主案标签 description: 标签集合不随分类、关键词等筛选变化;按Unicode升序返回。 parameters: - $ref: '../components/parameters.yaml#/XRequestId' responses: '200': {description: 标签集合, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentTagsResponse'}}}} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentsReorder: put: operationId: reorderDocuments summary: 管理员拖动重排主案/子方案 description: 主案在全局范围排序,子方案在所属主案内排序,共享附件不支持;orderedIds为拖动后的目标顺序。 parameters: - $ref: '../components/parameters.yaml#/XRequestId' requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/ReorderDocumentsRequest'} responses: '200': {description: 重排结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/ReorderDocumentsResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentPassword: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} put: operationId: saveDocumentPassword summary: 设置/修改/清除主案密码锁(仅MAIN) description: | 未设密时设置:password+protectedActions必填;已设密时修改/清除:oldPassword必填且正确; password缺省或空表示清除。任何人(含ADMIN)修改/清除均需原密码;rowVersion乐观锁校验。 requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/UpdateDocumentPasswordRequest'} responses: '200': {description: 密码锁摘要, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPasswordResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentDescription: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} put: operationId: updateDocumentDescription summary: 维护文档详细说明(主案/子案/附件通用,不校验rowVersion) parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/UpdateDocumentDescriptionRequest'} responses: '200': {description: 保存后的文档详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentReExtract: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} post: operationId: reExtractDocumentContent summary: 重新提取文档正文(仅管理员,主案/子案/附件通用) description: | 按当前存储文件重新解析正文并回写 contentText/searchText 与提取状态; Office 类型(doc/wps/xls/xlsx/et)先经 LibreOffice 转 PDF 再提取。 提取结果(含失败原因 contentExtractError)覆盖写回,rowVersion 递增, 审计复用 EDIT_DOCUMENT(detail.scope=reExtractContent)。 responses: '200': {description: 重新提取后的文档详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentPermissions: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: getDocumentPermissions summary: 查询主案借阅授权或子方案继承授权 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': {description: 权限详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} put: operationId: saveDocumentPermissions summary: 全量保存主案借阅授权 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/SavePermissionsRequest'} responses: '200': {description: 保存后的权限详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionDetailResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentPermissionVoucher: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} - {name: entryId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} post: operationId: uploadPermissionVoucher summary: 上传或替换授权条目的审批单凭证(仅主案,仅PDF) description: 请求必须且只能包含文件字段file,不得携带任何表单字段;替换语义,新凭证在数据库事务提交后提升落位,旧文件随后清理;审计UPLOAD_PERMISSION_VOUCHER。 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: false required: [file] properties: file: {type: string, format: binary} responses: '200': {description: 上传后的凭证信息, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionVoucherResultResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'} '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'} '500': {$ref: '../components/responses.yaml#/InternalError'} get: operationId: downloadPermissionVoucher summary: 下载授权条目的审批单凭证 description: 成功返回application/pdf附件二进制(含nosniff);条目未上传凭证或文件缺失返回404。 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': {description: 审批单PDF二进制, content: {application/pdf: {schema: {type: string, format: binary}}}} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} delete: operationId: deletePermissionVoucher summary: 清除授权条目的审批单凭证(授权条目本身保留) description: 凭证文件在数据库事务提交后清理;审计DELETE_PERMISSION_VOUCHER。 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': {description: 清除结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionVoucherDeleteResultResponse'}}}} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentMove: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} put: operationId: moveDocument summary: 跨页移动方案到浏览范围内指定位置(1.18) description: targetPosition与target二选一;位置为范围内1-based序号并自动收敛;目标位与当前位相同为无操作;审计MOVE_DOCUMENT。 responses: '200': {description: 移动结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentMoveResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/DocumentMoveRequest'} MainPlanAttachmentMove: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} - {name: bindingId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} put: operationId: moveMainPlanAttachment summary: 跨页移动主案挂载附件到页签类型范围内指定位置(1.18) description: 载荷必填mainPlanRowVersion(乐观锁,过期409);有实际移动时主案rowVersion加1并回传;审计MOVE_ATTACHMENT。 responses: '200': {description: 移动结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/AttachmentMoveResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/AttachmentMoveRequest'} DocumentRelationPresets: get: operationId: listDocumentRelationPresets summary: 方案关联关系类型预置清单 description: 启动期从document-relation-presets配置加载;预置类型用于编辑弹窗下拉,用户仍可自定义关系文本。 parameters: - $ref: '../components/parameters.yaml#/XRequestId' responses: '200': {description: 预置关系清单, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentRelationPresetsResponse'}}}} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '500': {$ref: '../components/responses.yaml#/InternalError'} DocumentRelations: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} get: operationId: listDocumentRelations summary: 查询方案声明的关联清单 description: 与文档详情同套访问控制;被关联方进入回收站后自动隐藏,恢复后重新显示。 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': {description: 关联清单, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentRelationsResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '500': {$ref: '../components/responses.yaml#/InternalError'} put: operationId: saveDocumentRelations summary: 整体替换方案的关联清单(管理员) description: | 关联发起方限主案/子方案,被关联方必须是主案且不可为自身;relations为空数组表示清空; relationType存最终文本(预置label或自定义,1~64字符);rowVersion乐观锁校验, 保存成功后rowVersion自增;设密主案需通过EDIT密码锁。 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' requestBody: required: true content: application/json: schema: {$ref: '../components/schemas.yaml#/UpdateDocumentRelationsRequest'} responses: '200': {description: 保存后的关联清单与新版本号, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentRelationsSaveResponse'}}}} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} MainPlanSubPlanBinding: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} post: operationId: bindMainPlanSubPlans summary: 批量挂载其他主案的子案到当前主案 description: 仅建立展示关系,子案权限仍继承原主案;同一主案上的写入由主案行锁串行化。 parameters: - $ref: '../components/parameters.yaml#/XDocumentPassword' requestBody: required: true content: application/json: schema: type: object required: [subPlanIds, mainPlanRowVersion] additionalProperties: false properties: subPlanIds: type: array minItems: 1 items: {$ref: '../components/schemas.yaml#/StringId'} mainPlanRowVersion: {type: integer, minimum: 0} responses: '200': description: 挂载结果 content: application/json: schema: type: object required: [code, message, data, requestId] properties: code: {type: string} message: {type: string} requestId: {type: string} data: type: object required: [createdCount, existingCount, subPlanCount, mainPlanRowVersion] properties: createdCount: {type: integer, minimum: 0} existingCount: {type: integer, minimum: 0} subPlanCount: {type: integer, minimum: 0} mainPlanRowVersion: {type: integer, minimum: 0} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'} MainPlanSubPlan: parameters: - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} - {name: subPlanId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}} delete: operationId: unbindMainPlanSubPlan summary: 解除主案与已挂载子案的展示关系 parameters: - {name: mainPlanRowVersion, in: query, required: true, schema: {type: integer, minimum: 0}} - $ref: '../components/parameters.yaml#/XDocumentPassword' responses: '200': description: 解除挂载结果 content: application/json: schema: type: object required: [code, message, data, requestId] properties: code: {type: string} message: {type: string} requestId: {type: string} data: type: object required: [subPlanCount, mainPlanRowVersion] properties: subPlanCount: {type: integer, minimum: 0} mainPlanRowVersion: {type: integer, minimum: 0} '400': {$ref: '../components/responses.yaml#/InvalidArgument'} '401': {$ref: '../components/responses.yaml#/AuthenticationError'} '403': {$ref: '../components/responses.yaml#/Forbidden'} '404': {$ref: '../components/responses.yaml#/NotFound'} '409': {$ref: '../components/responses.yaml#/Conflict'} '500': {$ref: '../components/responses.yaml#/InternalError'}