documents.yaml 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. Documents:
  2. get:
  3. operationId: listDocuments
  4. summary: 分页查询主案和子方案
  5. parameters:
  6. - $ref: '../components/parameters.yaml#/XRequestId'
  7. - {name: documentType, in: query, schema: {type: string, default: MAIN}}
  8. - {name: categoryId, in: query, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  9. - name: includeDescendants
  10. in: query
  11. description: 与categoryId同时使用时,是否包含全部有效后代分类;默认false。
  12. schema: {type: boolean, default: false}
  13. - {name: keyword, in: query, schema: {type: string}}
  14. - name: keywordScope
  15. in: query
  16. description: 契约1.55。keyword 的匹配范围:TITLE=标题(缺省)、CONTENT=正文、ALL=标题或正文任一命中;keyword 为空时忽略;aggregateHits=true 时仅支持 TITLE(否则 400)。
  17. schema: {type: string, enum: [TITLE, CONTENT, ALL], default: TITLE}
  18. - {name: securityLevel, in: query, schema: {$ref: '../components/schemas.yaml#/SecurityLevel'}}
  19. - {name: organizationId, in: query, schema: {$ref: '../components/schemas.yaml#/StringId'}, description: 契约1.55。提供单位:按该机构及其下级子树过滤。}
  20. - {name: status, in: query, schema: {$ref: '../components/schemas.yaml#/DocumentStatus'}}
  21. - $ref: '../components/parameters.yaml#/UpdatedFrom'
  22. - $ref: '../components/parameters.yaml#/UpdatedTo'
  23. - name: sortBy
  24. in: query
  25. schema:
  26. type: string
  27. enum: [documentName, createdAt, updatedAt, viewCount, downloadCount]
  28. default: updatedAt
  29. - {name: sortDirection, in: query, schema: {type: string, enum: [asc, desc], default: desc}}
  30. - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
  31. - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
  32. responses:
  33. '200': {description: 方案分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPageResponse'}}}}
  34. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  35. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  36. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  37. '404': {$ref: '../components/responses.yaml#/NotFound'}
  38. '500': {$ref: '../components/responses.yaml#/InternalError'}
  39. post:
  40. operationId: createDocument
  41. summary: 上传主案或子方案
  42. requestBody:
  43. required: true
  44. content:
  45. multipart/form-data:
  46. schema:
  47. type: object
  48. additionalProperties: false
  49. required: [file, metadata]
  50. properties:
  51. file: {type: string, format: binary}
  52. metadata:
  53. type: string
  54. description: DocumentCreateMetadata的JSON字符串。
  55. responses:
  56. '201': {description: 上传成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  57. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  58. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  59. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  60. '404': {$ref: '../components/responses.yaml#/NotFound'}
  61. '409': {$ref: '../components/responses.yaml#/Conflict'}
  62. '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'}
  63. '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'}
  64. '500': {$ref: '../components/responses.yaml#/InternalError'}
  65. Document:
  66. parameters:
  67. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  68. get:
  69. operationId: getDocument
  70. summary: 查询主案或子方案详情
  71. responses:
  72. '200': {description: 方案详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  73. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  74. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  75. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  76. '404': {$ref: '../components/responses.yaml#/NotFound'}
  77. '500': {$ref: '../components/responses.yaml#/InternalError'}
  78. put:
  79. operationId: updateDocument
  80. summary: 编辑方案文档元数据
  81. parameters:
  82. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  83. requestBody:
  84. required: true
  85. content:
  86. application/json:
  87. schema: {$ref: '../components/schemas.yaml#/UpdateDocumentRequest'}
  88. responses:
  89. '200': {description: 编辑成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  90. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  91. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  92. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  93. '404': {$ref: '../components/responses.yaml#/NotFound'}
  94. '409': {$ref: '../components/responses.yaml#/Conflict'}
  95. '500': {$ref: '../components/responses.yaml#/InternalError'}
  96. delete:
  97. operationId: deleteDocument
  98. summary: 逻辑删除方案文档
  99. parameters:
  100. - {name: rowVersion, in: query, required: true, schema: {type: integer, minimum: 0}}
  101. responses:
  102. '200': {description: 删除成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DeleteDocumentResponse'}}}}
  103. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  104. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  105. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  106. '404': {$ref: '../components/responses.yaml#/NotFound'}
  107. '409': {$ref: '../components/responses.yaml#/Conflict'}
  108. '500': {$ref: '../components/responses.yaml#/InternalError'}
  109. SubPlans:
  110. parameters:
  111. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  112. get:
  113. operationId: listMainPlanSubPlans
  114. summary: 查询主案的直接子方案
  115. parameters:
  116. - {name: keyword, in: query, schema: {type: string}}
  117. - {name: status, in: query, schema: {$ref: '../components/schemas.yaml#/DocumentStatus'}}
  118. - $ref: '../components/parameters.yaml#/UpdatedFrom'
  119. - $ref: '../components/parameters.yaml#/UpdatedTo'
  120. - name: sortBy
  121. in: query
  122. schema: {type: string, enum: [documentName, createdAt, updatedAt, viewCount, downloadCount], default: updatedAt}
  123. - {name: sortDirection, in: query, schema: {type: string, enum: [asc, desc], default: desc}}
  124. - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
  125. - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
  126. responses:
  127. '200': {description: 子方案分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPageResponse'}}}}
  128. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  129. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  130. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  131. '404': {$ref: '../components/responses.yaml#/NotFound'}
  132. '500': {$ref: '../components/responses.yaml#/InternalError'}
  133. Attachments:
  134. get:
  135. operationId: listAttachments
  136. summary: 分页查询独立共享附件库(全量可见;普通用户allowedActions按矩阵附件位OR挂载主案权限聚合下发1.41,无命中为空集且不返回description/contentSnippet)
  137. description: 所有登录用户可访问,支撑全局检索按标题命中全部附件;附件内容访问由详情/预览/下载接口按挂载主案权限独立拦截。
  138. parameters:
  139. - $ref: '../components/parameters.yaml#/XRequestId'
  140. - {name: keyword, in: query, schema: {type: string}}
  141. - name: keywordScope
  142. in: query
  143. description: 契约1.55。keyword 的匹配范围:TITLE=标题(缺省)、CONTENT=正文、ALL=标题或正文任一命中;keyword 为空时忽略。
  144. schema: {type: string, enum: [TITLE, CONTENT, ALL], default: TITLE}
  145. - {name: attachmentType, in: query, schema: {$ref: '../components/schemas.yaml#/AttachmentType'}}
  146. - {name: fileExtension, in: query, schema: {type: string}}
  147. - {name: securityLevel, in: query, schema: {$ref: '../components/schemas.yaml#/SecurityLevel'}, description: 契约1.55。数据密级单选过滤。}
  148. - {name: organizationId, in: query, schema: {$ref: '../components/schemas.yaml#/StringId'}, description: 契约1.55。提供单位:按该机构及其下级子树过滤。}
  149. - $ref: '../components/parameters.yaml#/UpdatedFrom'
  150. - $ref: '../components/parameters.yaml#/UpdatedTo'
  151. - name: sortBy
  152. in: query
  153. schema: {type: string, enum: [documentName, createdAt, updatedAt, viewCount, downloadCount], default: updatedAt}
  154. - {name: sortDirection, in: query, schema: {type: string, enum: [asc, desc], default: desc}}
  155. - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
  156. - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
  157. responses:
  158. '200': {description: 附件分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPageResponse'}}}}
  159. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  160. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  161. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  162. '404': {$ref: '../components/responses.yaml#/NotFound'}
  163. '500': {$ref: '../components/responses.yaml#/InternalError'}
  164. post:
  165. operationId: createAttachment
  166. summary: 上传共享附件(1.41改矩阵附件上传位:ADMIN恒可,USER按附件密级OWN行canAttachmentUpload,无权403)
  167. requestBody:
  168. required: true
  169. content:
  170. multipart/form-data:
  171. schema:
  172. type: object
  173. additionalProperties: false
  174. required: [file, metadata]
  175. properties:
  176. file: {type: string, format: binary}
  177. metadata:
  178. type: string
  179. description: AttachmentCreateMetadata的JSON字符串。
  180. responses:
  181. '201': {description: 上传成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  182. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  183. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  184. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  185. '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'}
  186. '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'}
  187. '500': {$ref: '../components/responses.yaml#/InternalError'}
  188. Attachment:
  189. parameters:
  190. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  191. get:
  192. operationId: getAttachment
  193. summary: 查询共享附件详情
  194. responses:
  195. '200': {description: 附件详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  196. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  197. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  198. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  199. '404': {$ref: '../components/responses.yaml#/NotFound'}
  200. '500': {$ref: '../components/responses.yaml#/InternalError'}
  201. put:
  202. operationId: updateAttachment
  203. summary: 编辑共享附件元数据(1.41:ADMIN恒可或矩阵附件编辑位canAttachmentEdit)
  204. requestBody:
  205. required: true
  206. content:
  207. application/json:
  208. schema: {$ref: '../components/schemas.yaml#/UpdateAttachmentRequest'}
  209. responses:
  210. '200': {description: 编辑成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  211. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  212. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  213. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  214. '404': {$ref: '../components/responses.yaml#/NotFound'}
  215. '409': {$ref: '../components/responses.yaml#/Conflict'}
  216. '500': {$ref: '../components/responses.yaml#/InternalError'}
  217. delete:
  218. operationId: deleteAttachment
  219. summary: 逻辑删除共享附件
  220. parameters:
  221. - {name: rowVersion, in: query, required: true, schema: {type: integer, minimum: 0}}
  222. responses:
  223. '200': {description: 删除成功, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DeleteDocumentResponse'}}}}
  224. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  225. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  226. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  227. '404': {$ref: '../components/responses.yaml#/NotFound'}
  228. '409': {$ref: '../components/responses.yaml#/Conflict'}
  229. '500': {$ref: '../components/responses.yaml#/InternalError'}
  230. DocumentBatchImport:
  231. post:
  232. operationId: batchImportDocuments
  233. summary: 批量导入主案和子方案
  234. requestBody:
  235. required: true
  236. content:
  237. multipart/form-data:
  238. schema:
  239. $ref: '../components/schemas.yaml#/BatchImportMultipart'
  240. responses:
  241. '200': {description: 逐文件导入结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/BatchImportResponse'}}}}
  242. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  243. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  244. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  245. '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'}
  246. '500': {$ref: '../components/responses.yaml#/InternalError'}
  247. AttachmentBatchImport:
  248. post:
  249. operationId: batchImportAttachments
  250. summary: 批量导入共享附件(鉴权同上传:ADMIN恒可或矩阵附件上传位)
  251. requestBody:
  252. required: true
  253. content:
  254. multipart/form-data:
  255. schema:
  256. $ref: '../components/schemas.yaml#/BatchImportMultipart'
  257. responses:
  258. '200': {description: 逐文件导入结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/BatchImportResponse'}}}}
  259. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  260. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  261. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  262. '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'}
  263. '500': {$ref: '../components/responses.yaml#/InternalError'}
  264. DocumentPreview:
  265. parameters:
  266. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  267. get:
  268. operationId: previewDocument
  269. summary: PDF直接预览;DOC、DOCX、WPS由LibreOffice离线转换为PDF后预览
  270. parameters:
  271. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  272. responses:
  273. '200':
  274. description: PDF文件流(PDF原文件或DOC/DOCX/WPS转换后的PDF)
  275. headers:
  276. X-Request-Id: {schema: {type: string, format: uuid}}
  277. content:
  278. application/pdf: {schema: {type: string, format: binary}}
  279. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  280. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  281. '404': {$ref: '../components/responses.yaml#/NotFound'}
  282. '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'}
  283. '502': {$ref: '../components/responses.yaml#/PreviewConversionFailed'}
  284. '503': {$ref: '../components/responses.yaml#/PreviewConverterUnavailable'}
  285. '504': {$ref: '../components/responses.yaml#/PreviewConversionTimeout'}
  286. '500': {$ref: '../components/responses.yaml#/InternalError'}
  287. DocumentDownload:
  288. parameters:
  289. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  290. get:
  291. operationId: downloadDocument
  292. summary: 下载原始文档
  293. parameters:
  294. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  295. responses:
  296. '200':
  297. description: 原始文件流
  298. headers:
  299. X-Request-Id: {schema: {type: string, format: uuid}}
  300. content:
  301. application/octet-stream: {schema: {type: string, format: binary}}
  302. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  303. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  304. '404': {$ref: '../components/responses.yaml#/NotFound'}
  305. '500': {$ref: '../components/responses.yaml#/InternalError'}
  306. AttachmentMainPlans:
  307. parameters:
  308. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  309. get:
  310. operationId: listAttachmentMainPlans
  311. summary: 查询共享附件挂载的可见主案
  312. responses:
  313. '200': {description: 主案简要集合, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/MainPlanBriefCollectionResponse'}}}}
  314. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  315. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  316. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  317. '404': {$ref: '../components/responses.yaml#/NotFound'}
  318. '500': {$ref: '../components/responses.yaml#/InternalError'}
  319. MainPlanAttachments:
  320. parameters:
  321. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  322. get:
  323. operationId: listMainPlanAttachments
  324. summary: 查询主案已挂载共享附件
  325. parameters:
  326. - {name: keyword, in: query, schema: {type: string}}
  327. - {name: attachmentType, in: query, schema: {$ref: '../components/schemas.yaml#/AttachmentType'}}
  328. - $ref: '../components/parameters.yaml#/UpdatedFrom'
  329. - $ref: '../components/parameters.yaml#/UpdatedTo'
  330. - {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
  331. - {name: pageSize, in: query, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
  332. responses:
  333. '200': {description: 挂载附件分页, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/AttachmentBindingPageResponse'}}}}
  334. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  335. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  336. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  337. '404': {$ref: '../components/responses.yaml#/NotFound'}
  338. '500': {$ref: '../components/responses.yaml#/InternalError'}
  339. MainPlanAttachmentBinding:
  340. parameters:
  341. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  342. post:
  343. operationId: bindMainPlanAttachments
  344. summary: 批量挂载共享附件到主案
  345. parameters:
  346. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  347. requestBody:
  348. required: true
  349. content:
  350. application/json:
  351. schema: {$ref: '../components/schemas.yaml#/BindAttachmentsRequest'}
  352. responses:
  353. '200': {description: 挂载结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/BindAttachmentsResponse'}}}}
  354. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  355. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  356. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  357. '404': {$ref: '../components/responses.yaml#/NotFound'}
  358. '409': {$ref: '../components/responses.yaml#/Conflict'}
  359. '500': {$ref: '../components/responses.yaml#/InternalError'}
  360. MainPlanAttachmentsReorder:
  361. parameters:
  362. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  363. put:
  364. operationId: reorderMainPlanAttachments
  365. summary: 调整主案下挂载附件的显示顺序
  366. description: 顺序存于挂载关系,同一附件在不同主案中可各自独立排序。
  367. parameters:
  368. - $ref: '../components/parameters.yaml#/XRequestId'
  369. requestBody:
  370. required: true
  371. content:
  372. application/json:
  373. schema: {$ref: '../components/schemas.yaml#/ReorderAttachmentsRequest'}
  374. responses:
  375. '200': {description: 重排结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/ReorderAttachmentsResponse'}}}}
  376. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  377. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  378. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  379. '404': {$ref: '../components/responses.yaml#/NotFound'}
  380. '409': {$ref: '../components/responses.yaml#/Conflict'}
  381. '500': {$ref: '../components/responses.yaml#/InternalError'}
  382. MainPlanAttachment:
  383. parameters:
  384. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  385. - {name: attachmentId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  386. delete:
  387. operationId: unbindMainPlanAttachment
  388. summary: 解除主案和共享附件的挂载
  389. parameters:
  390. - {name: mainPlanRowVersion, in: query, required: true, schema: {type: integer, minimum: 0}}
  391. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  392. responses:
  393. '200': {description: 解除挂载结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/UnbindAttachmentResponse'}}}}
  394. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  395. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  396. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  397. '404': {$ref: '../components/responses.yaml#/NotFound'}
  398. '409': {$ref: '../components/responses.yaml#/Conflict'}
  399. '500': {$ref: '../components/responses.yaml#/InternalError'}
  400. DocumentsTags:
  401. get:
  402. operationId: listMainPlanTags
  403. summary: 聚合当前用户可见的主案标签
  404. description: 标签集合不随分类、关键词等筛选变化;按Unicode升序返回。
  405. parameters:
  406. - $ref: '../components/parameters.yaml#/XRequestId'
  407. responses:
  408. '200': {description: 标签集合, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentTagsResponse'}}}}
  409. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  410. '500': {$ref: '../components/responses.yaml#/InternalError'}
  411. DocumentsReorder:
  412. put:
  413. operationId: reorderDocuments
  414. summary: 管理员拖动重排主案/子方案
  415. description: 主案在全局范围排序,子方案在所属主案内排序,共享附件不支持;orderedIds为拖动后的目标顺序。
  416. parameters:
  417. - $ref: '../components/parameters.yaml#/XRequestId'
  418. requestBody:
  419. required: true
  420. content:
  421. application/json:
  422. schema: {$ref: '../components/schemas.yaml#/ReorderDocumentsRequest'}
  423. responses:
  424. '200': {description: 重排结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/ReorderDocumentsResponse'}}}}
  425. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  426. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  427. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  428. '404': {$ref: '../components/responses.yaml#/NotFound'}
  429. '409': {$ref: '../components/responses.yaml#/Conflict'}
  430. '500': {$ref: '../components/responses.yaml#/InternalError'}
  431. DocumentPassword:
  432. parameters:
  433. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  434. put:
  435. operationId: saveDocumentPassword
  436. summary: 设置/修改/清除主案密码锁(仅MAIN)
  437. description: |
  438. 未设密时设置:password+protectedActions必填;已设密时修改/清除:oldPassword必填且正确;
  439. password缺省或空表示清除。任何人(含ADMIN)修改/清除均需原密码;rowVersion乐观锁校验。
  440. requestBody:
  441. required: true
  442. content:
  443. application/json:
  444. schema: {$ref: '../components/schemas.yaml#/UpdateDocumentPasswordRequest'}
  445. responses:
  446. '200': {description: 密码锁摘要, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentPasswordResponse'}}}}
  447. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  448. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  449. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  450. '404': {$ref: '../components/responses.yaml#/NotFound'}
  451. '409': {$ref: '../components/responses.yaml#/Conflict'}
  452. '500': {$ref: '../components/responses.yaml#/InternalError'}
  453. DocumentDescription:
  454. parameters:
  455. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  456. put:
  457. operationId: updateDocumentDescription
  458. summary: 维护文档详细说明(主案/子案/附件通用,不校验rowVersion)
  459. parameters:
  460. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  461. requestBody:
  462. required: true
  463. content:
  464. application/json:
  465. schema: {$ref: '../components/schemas.yaml#/UpdateDocumentDescriptionRequest'}
  466. responses:
  467. '200': {description: 保存后的文档详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  468. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  469. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  470. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  471. '404': {$ref: '../components/responses.yaml#/NotFound'}
  472. '500': {$ref: '../components/responses.yaml#/InternalError'}
  473. DocumentReExtract:
  474. parameters:
  475. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  476. post:
  477. operationId: reExtractDocumentContent
  478. summary: 重新提取文档正文(仅管理员,主案/子案/附件通用)
  479. description: |
  480. 按当前存储文件重新解析正文并回写 contentText/searchText 与提取状态;
  481. Office 类型(doc/wps/xls/xlsx/et)先经 LibreOffice 转 PDF 再提取。
  482. 提取结果(含失败原因 contentExtractError)覆盖写回,rowVersion 递增,
  483. 审计复用 EDIT_DOCUMENT(detail.scope=reExtractContent)。
  484. responses:
  485. '200': {description: 重新提取后的文档详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentDetailResponse'}}}}
  486. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  487. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  488. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  489. '404': {$ref: '../components/responses.yaml#/NotFound'}
  490. '500': {$ref: '../components/responses.yaml#/InternalError'}
  491. DocumentPermissions:
  492. parameters:
  493. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  494. get:
  495. operationId: getDocumentPermissions
  496. summary: 查询主案调阅授权或子方案继承授权
  497. parameters:
  498. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  499. responses:
  500. '200': {description: 权限详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionDetailResponse'}}}}
  501. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  502. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  503. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  504. '404': {$ref: '../components/responses.yaml#/NotFound'}
  505. '409': {$ref: '../components/responses.yaml#/Conflict'}
  506. '500': {$ref: '../components/responses.yaml#/InternalError'}
  507. put:
  508. operationId: saveDocumentPermissions
  509. summary: 全量保存主案调阅授权
  510. description: 敏感操作,强制二次认证(X-DMS-Reauth-Token,缺失或无效返回403 REAUTH_REQUIRED)。
  511. parameters:
  512. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  513. - $ref: '../components/parameters.yaml#/XDmsReauthToken'
  514. requestBody:
  515. required: true
  516. content:
  517. application/json:
  518. schema: {$ref: '../components/schemas.yaml#/SavePermissionsRequest'}
  519. responses:
  520. '200': {description: 保存后的权限详情, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionDetailResponse'}}}}
  521. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  522. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  523. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  524. '404': {$ref: '../components/responses.yaml#/NotFound'}
  525. '409': {$ref: '../components/responses.yaml#/Conflict'}
  526. '500': {$ref: '../components/responses.yaml#/InternalError'}
  527. DocumentPermissionVoucher:
  528. parameters:
  529. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  530. - {name: entryId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  531. post:
  532. operationId: uploadPermissionVoucher
  533. summary: 上传或替换授权条目的审批单凭证(仅主案,PDF/图片,契约1.72)
  534. description: 请求必须且只能包含文件字段file,不得携带任何表单字段;替换语义,新凭证在数据库事务提交后提升落位,旧文件随后清理;审计UPLOAD_PERMISSION_VOUCHER。敏感操作,强制二次认证(X-DMS-Reauth-Token,缺失或无效返回403 REAUTH_REQUIRED)。
  535. parameters:
  536. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  537. - $ref: '../components/parameters.yaml#/XDmsReauthToken'
  538. requestBody:
  539. required: true
  540. content:
  541. multipart/form-data:
  542. schema:
  543. type: object
  544. additionalProperties: false
  545. required: [file]
  546. properties:
  547. file: {type: string, format: binary, description: PDF或图片凭证(契约1.72扩图,魔数校验)}
  548. responses:
  549. '200': {description: 上传后的凭证信息, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionVoucherResultResponse'}}}}
  550. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  551. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  552. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  553. '404': {$ref: '../components/responses.yaml#/NotFound'}
  554. '413': {$ref: '../components/responses.yaml#/PayloadTooLarge'}
  555. '415': {$ref: '../components/responses.yaml#/UnsupportedMedia'}
  556. '500': {$ref: '../components/responses.yaml#/InternalError'}
  557. get:
  558. operationId: downloadPermissionVoucher
  559. summary: 下载授权条目的审批单凭证
  560. description: 成功返回附件二进制(含nosniff;Content-Type按扩展名映射——PDF为application/pdf、图片为对应image/*,契约1.72);条目未上传凭证或文件缺失返回404。
  561. parameters:
  562. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  563. responses:
  564. '200': {description: 审批单二进制(PDF或图片), content: {application/pdf: {schema: {type: string, format: binary}}, image/jpeg: {schema: {type: string, format: binary}}, image/png: {schema: {type: string, format: binary}}, image/gif: {schema: {type: string, format: binary}}, image/bmp: {schema: {type: string, format: binary}}, image/webp: {schema: {type: string, format: binary}}}}
  565. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  566. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  567. '404': {$ref: '../components/responses.yaml#/NotFound'}
  568. '500': {$ref: '../components/responses.yaml#/InternalError'}
  569. delete:
  570. operationId: deletePermissionVoucher
  571. summary: 清除授权条目的审批单凭证(授权条目本身保留)
  572. description: 凭证文件在数据库事务提交后清理;审计DELETE_PERMISSION_VOUCHER。敏感操作,强制二次认证(X-DMS-Reauth-Token,缺失或无效返回403 REAUTH_REQUIRED)。
  573. parameters:
  574. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  575. - $ref: '../components/parameters.yaml#/XDmsReauthToken'
  576. responses:
  577. '200': {description: 清除结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/PermissionVoucherDeleteResultResponse'}}}}
  578. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  579. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  580. '404': {$ref: '../components/responses.yaml#/NotFound'}
  581. '500': {$ref: '../components/responses.yaml#/InternalError'}
  582. DocumentMove:
  583. parameters:
  584. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  585. put:
  586. operationId: moveDocument
  587. summary: 跨页移动方案到浏览范围内指定位置(1.18)
  588. description: targetPosition与target二选一;位置为范围内1-based序号并自动收敛;目标位与当前位相同为无操作;权限要求对该文档有EDIT(无权403,1.30修订);审计MOVE_DOCUMENT。
  589. responses:
  590. '200': {description: 移动结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentMoveResponse'}}}}
  591. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  592. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  593. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  594. '404': {$ref: '../components/responses.yaml#/NotFound'}
  595. '409': {$ref: '../components/responses.yaml#/Conflict'}
  596. '500': {$ref: '../components/responses.yaml#/InternalError'}
  597. requestBody:
  598. required: true
  599. content:
  600. application/json:
  601. schema: {$ref: '../components/schemas.yaml#/DocumentMoveRequest'}
  602. MainPlanAttachmentMove:
  603. parameters:
  604. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  605. - {name: bindingId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  606. put:
  607. operationId: moveMainPlanAttachment
  608. summary: 跨页移动主案挂载附件到页签类型范围内指定位置(1.18)
  609. description: 载荷必填mainPlanRowVersion(乐观锁,过期409);有实际移动时主案rowVersion加1并回传;权限要求对主案有EDIT(1.30修订,原BIND_ATTACHMENT);审计MOVE_ATTACHMENT。
  610. responses:
  611. '200': {description: 移动结果, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/AttachmentMoveResponse'}}}}
  612. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  613. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  614. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  615. '404': {$ref: '../components/responses.yaml#/NotFound'}
  616. '409': {$ref: '../components/responses.yaml#/Conflict'}
  617. '500': {$ref: '../components/responses.yaml#/InternalError'}
  618. requestBody:
  619. required: true
  620. content:
  621. application/json:
  622. schema: {$ref: '../components/schemas.yaml#/AttachmentMoveRequest'}
  623. DocumentRelationPresets:
  624. get:
  625. operationId: listDocumentRelationPresets
  626. summary: 方案关联关系类型预置清单
  627. description: 启动期从document-relation-presets配置加载;预置类型用于编辑弹窗下拉,用户仍可自定义关系文本。
  628. parameters:
  629. - $ref: '../components/parameters.yaml#/XRequestId'
  630. responses:
  631. '200': {description: 预置关系清单, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentRelationPresetsResponse'}}}}
  632. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  633. '500': {$ref: '../components/responses.yaml#/InternalError'}
  634. DocumentRelations:
  635. parameters:
  636. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  637. get:
  638. operationId: listDocumentRelations
  639. summary: 查询方案声明的关联清单
  640. description: 与文档详情同套访问控制;被关联方进入回收站后自动隐藏,恢复后重新显示。
  641. parameters:
  642. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  643. responses:
  644. '200': {description: 关联清单, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentRelationsResponse'}}}}
  645. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  646. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  647. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  648. '404': {$ref: '../components/responses.yaml#/NotFound'}
  649. '500': {$ref: '../components/responses.yaml#/InternalError'}
  650. put:
  651. operationId: saveDocumentRelations
  652. summary: 整体替换方案的关联清单(管理员)
  653. description: |
  654. 关联发起方限主案/子方案,被关联方必须是主案且不可为自身;relations为空数组表示清空;
  655. relationType存最终文本(预置label或自定义,1~64字符);rowVersion乐观锁校验,
  656. 保存成功后rowVersion自增;设密主案需通过EDIT密码锁。
  657. parameters:
  658. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  659. requestBody:
  660. required: true
  661. content:
  662. application/json:
  663. schema: {$ref: '../components/schemas.yaml#/UpdateDocumentRelationsRequest'}
  664. responses:
  665. '200': {description: 保存后的关联清单与新版本号, content: {application/json: {schema: {$ref: '../components/schemas.yaml#/DocumentRelationsSaveResponse'}}}}
  666. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  667. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  668. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  669. '404': {$ref: '../components/responses.yaml#/NotFound'}
  670. '409': {$ref: '../components/responses.yaml#/Conflict'}
  671. '500': {$ref: '../components/responses.yaml#/InternalError'}
  672. MainPlanSubPlanBinding:
  673. parameters:
  674. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  675. post:
  676. operationId: bindMainPlanSubPlans
  677. summary: 批量挂载其他主案的子案到当前主案
  678. description: 仅建立展示关系,子案权限仍继承原主案;同一主案上的写入由主案行锁串行化。
  679. parameters:
  680. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  681. requestBody:
  682. required: true
  683. content:
  684. application/json:
  685. schema:
  686. type: object
  687. required: [subPlanIds, mainPlanRowVersion]
  688. additionalProperties: false
  689. properties:
  690. subPlanIds:
  691. type: array
  692. minItems: 1
  693. items: {$ref: '../components/schemas.yaml#/StringId'}
  694. mainPlanRowVersion: {type: integer, minimum: 0}
  695. responses:
  696. '200':
  697. description: 挂载结果
  698. content:
  699. application/json:
  700. schema:
  701. type: object
  702. required: [code, message, data, requestId]
  703. properties:
  704. code: {type: string}
  705. message: {type: string}
  706. requestId: {type: string}
  707. data:
  708. type: object
  709. required: [createdCount, existingCount, subPlanCount, mainPlanRowVersion]
  710. properties:
  711. createdCount: {type: integer, minimum: 0}
  712. existingCount: {type: integer, minimum: 0}
  713. subPlanCount: {type: integer, minimum: 0}
  714. mainPlanRowVersion: {type: integer, minimum: 0}
  715. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  716. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  717. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  718. '404': {$ref: '../components/responses.yaml#/NotFound'}
  719. '409': {$ref: '../components/responses.yaml#/Conflict'}
  720. '500': {$ref: '../components/responses.yaml#/InternalError'}
  721. MainPlanSubPlan:
  722. parameters:
  723. - {name: id, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  724. - {name: subPlanId, in: path, required: true, schema: {$ref: '../components/schemas.yaml#/StringId'}}
  725. delete:
  726. operationId: unbindMainPlanSubPlan
  727. summary: 解除主案与已挂载子案的展示关系
  728. parameters:
  729. - {name: mainPlanRowVersion, in: query, required: true, schema: {type: integer, minimum: 0}}
  730. - $ref: '../components/parameters.yaml#/XDocumentPassword'
  731. responses:
  732. '200':
  733. description: 解除挂载结果
  734. content:
  735. application/json:
  736. schema:
  737. type: object
  738. required: [code, message, data, requestId]
  739. properties:
  740. code: {type: string}
  741. message: {type: string}
  742. requestId: {type: string}
  743. data:
  744. type: object
  745. required: [subPlanCount, mainPlanRowVersion]
  746. properties:
  747. subPlanCount: {type: integer, minimum: 0}
  748. mainPlanRowVersion: {type: integer, minimum: 0}
  749. '400': {$ref: '../components/responses.yaml#/InvalidArgument'}
  750. '401': {$ref: '../components/responses.yaml#/AuthenticationError'}
  751. '403': {$ref: '../components/responses.yaml#/Forbidden'}
  752. '404': {$ref: '../components/responses.yaml#/NotFound'}
  753. '409': {$ref: '../components/responses.yaml#/Conflict'}
  754. '500': {$ref: '../components/responses.yaml#/InternalError'}