openapi: 3.0.3 info: title: 方案计划文档管理系统 API version: 1.39.0 description: DMS第一阶段接口;Q3-B正文检索、原文件预览、1.6 LibreOffice离线文档转换与PDF预览、1.7 机构用户维护与详细说明、1.8 角色管理与权限矩阵、1.9 方案关联关系、1.10 部门IP登录限制、1.11 统一门户跳转登录与子案挂载、1.12 正文提取状态可见与重新解析、1.13 登录界面自定义背景图、1.17 管理类权限矩阵化(管理位挂角色)、1.19 借阅授权收敛(限时用户借阅+审批单凭证)、1.21 安全加固(访问令牌有效期配置化默认1小时、敏感操作二次认证X-DMS-Reauth-Token、应用层信封加密KEK/DEK)、1.22 数据备份定版(全量/增量链、rsync异机/本机目录、定时与手动、进度与历史、离线恢复CLI)、1.23 系统管理(manage_system/manage_audit_log管理位、CPU内存监控与趋势、存储占用、转换器状态、一键体检、系统信息、运行参数、运行日志、预览缓存清理、强制下线、备份目标测试)、1.24 门户设密自选机构(SET_PASSWORD响应内嵌机构列表,setup-password可选organizationId)、1.25 本地单点登录代理(仅Java版POST /auth/portal/proxy-verify,REST直连本机代理GET /middle/token/get.json取token、经用户服务POST /auth/user/getUserBasicInfo验身份,响应同门户验签双阶段,前端打开页面静默探测失败回落登录页)、1.26 监控信息展示开关(DMS_SYSTEM_MONITOR_ENABLED缺省false,system/info响应新增monitoringEnabled,false时前端隐藏系统管理页维护操作之上的监控区块)、1.27 列表拖动重排(机构/用户/角色列表PUT reorder接口,槽位置换语义+步长10重编号sort_no,新增审计动作REORDER_ORGANIZATION/REORDER_USER/REORDER_ROLE,sys_user新增sort_no列)、1.28 IP条目范围形式(ipValue新增「起IP-止IP」范围录入,两端同为IPv4或IPv6且起≤止,规范化存储,登录IP校验支持范围闭区间命中)、1.29 页面空闲自动登出与机构树默认语义(登录/设密响应data新增idleLogoutMinutes,取DMS_IDLE_LOGOUT_MINUTES缺省5分钟、0表示关闭,前端监测鼠标/键盘/滚动等活动超时自动退出;organizations/tree不传status时返回全部机构含停用)、1.30 用户级管理范围(sys_user新增managed_org_id三态:null=全局、0=SELF跟随本人所在机构、机构ID=固定锚点;createUser/updateUser请求新增可选managedOrgId字段(create缺省落SELF、update缺省保持原值),UserSummary.managedOrgId改回用户级三态;实际生效范围以生效角色锚点为准,角色锚点"SELF"语义改为「跟随用户的管理范围设置」)、1.32 登录图片验证码(安全需求4,GET /auth/captcha签发data URL图片132×44、4位字符、120秒过期一次性消费;DMS_CAPTCHA_ENABLED缺省true,开启时登录请求体扩为五键captchaId/captchaCode,校验先于用户查询与锁定检查,错误返回400 INVALID_CAPTCHA)、1.33 超级管理员隐藏与机构树管理范围裁剪(安全需求7/8,DMS_ALLOW_ADMIN_LOGIN缺省true,false时内置admin登录按用户名不存在处理报错一致、用户列表隐藏、创建同名用户400"不能创建该名称的用户";organizations/tree按请求者生效管理范围裁剪,锚点管理员仅返回管理范围子树、全局管理员不受限)、1.34 站内通知(sys_notification表,GET /notifications当前用户通知列表id倒序、GET /notifications/unread-count未读数、POST /notifications/read-all全部已读、POST /notifications/{id}/handle待办同意或拒绝(仅action=PENDING且归属本人,处理完置READ并记handledAt);通知为审批流等待办的呈现通道,当前版本由后续审批流写入)、1.35 菜单显示方式(allowedModules按角色权限矩阵与管理位纯权限推导,与用户类别无关、不查文档存在性:管理类列任一或分类管理位→方案管理替代方案浏览,浏览类列任一→方案浏览,审计/系统/机构用户管理位独立渲染页签,全空兜底方案浏览,内置admin恒全量四页签)、1.36 操作位完全拆分(allowedActions与写路径鉴权各操作位独立判定,查看不再是其他位前置:矩阵操作位命中即独立下发与放行,下载位由矩阵或借阅ACL独立命中不再要求同时可查看,附件聚合任一主案命中下载即可,查看类能力仍按查看权拦截)、1.37 借阅申请审批流(借阅授权由手工配置改为申请-审批:POST /documents/{id}/borrow-requests提交申请(multipart:request part JSON字符串{entries,expiresAt}+可选file part PDF审批单,一批用户共用一张,敏感操作需二次认证)、GET /borrow-requests/{id}申请详情(申请人本人或文档授权位可见)、GET /borrow-requests/{id}/voucher审批单下载;NotificationSummary新增bizId指向申请单,APPROVAL待办经notifications/{id}/handle联动审批、任一审批人处理即定,同意逐条目落地doc_permission;新增审计动作BORROW_REQUEST_CREATE/APPROVE/REJECT)、1.38 一次一码轮换(安全需求:写操作防重放,仅Java版实现,开关DMS_TOKEN_ROTATION_ENABLED缺省true;GET/HEAD读请求沿用原授权码不轮换不比对,POST/PUT/DELETE/PATCH写请求严格比对sys_user.session_jti=JWT jti,业务成功后轮换新授权码经响应头X-DMS-Access-Token返回、旧码写操作立即失效返回401 SESSION_ROTATED;新码继承原码剩余有效期与全部身份声明,并发写由服务端CAS保证乱序下客户端拿到最新码;session_jti为NULL(存量会话/开关关闭期间登录/Python版签发)跳过比对与轮换自然过渡;登录与门户设密完成响应data新增tokenRotation布尔回显)、1.39 禁用用户名密码登录(安全管控,仅Java版实现,开关DMS_PASSWORD_LOGIN_DISABLED双版同名缺省false:开启后POST /auth/login对全部用户含内置admin最前置403 FORBIDDEN「用户名密码登录已被禁用,请使用单点登录」,守卫先于验证码校验与用户查询、不消耗验证码、不泄露账号存在;门户验签与本地SSO代理登录不受影响为仅存入口;GET /auth/captcha响应data新增必返passwordLoginDisabled布尔回显,前端据此隐藏登录页账号密码表单仅显示单点登录提示)。 servers: - url: / paths: /api/v1/health: get: operationId: getDmsHealth summary: DMS健康检查 security: [] parameters: - $ref: './components/parameters.yaml#/XRequestId' responses: '200': $ref: './components/responses.yaml#/HealthSuccess' '500': $ref: './components/responses.yaml#/InternalError' /api/v1/auth/captcha: $ref: './paths/auth.yaml#/Captcha' /api/v1/auth/login: $ref: './paths/auth.yaml#/Login' /api/v1/auth/logout: $ref: './paths/auth.yaml#/Logout' /api/v1/auth/reauth: $ref: './paths/auth.yaml#/Reauth' /api/v1/auth/portal/verify: $ref: './paths/auth.yaml#/PortalVerify' /api/v1/auth/portal/proxy-verify: $ref: './paths/auth.yaml#/PortalProxyVerify' /api/v1/auth/portal/setup-password: $ref: './paths/auth.yaml#/PortalSetupPassword' /api/v1/users/me: $ref: './paths/users.yaml#/CurrentUser' /api/v1/users/me/ui-theme: $ref: './paths/users.yaml#/CurrentUserUiTheme' /api/v1/organizations/tree: $ref: './paths/organizations.yaml#/OrganizationTree' /api/v1/organizations: $ref: './paths/organizations.yaml#/Organizations' /api/v1/organizations/{id}: $ref: './paths/organizations.yaml#/Organization' /api/v1/organizations/{id}/ip-assignments: $ref: './paths/organizations.yaml#/OrganizationIpAssignments' /api/v1/organizations/reorder: $ref: './paths/organizations.yaml#/OrganizationsReorder' /api/v1/ip-entries: $ref: './paths/ip-entries.yaml#/IpEntries' /api/v1/ip-entries/{id}: $ref: './paths/ip-entries.yaml#/IpEntry' /api/v1/users: $ref: './paths/users.yaml#/Users' /api/v1/users/{id}: $ref: './paths/users.yaml#/User' /api/v1/users/{id}/reset-password: $ref: './paths/users.yaml#/UserResetPassword' /api/v1/users/reorder: $ref: './paths/users.yaml#/UsersReorder' /api/v1/roles: $ref: './paths/roles.yaml#/Roles' /api/v1/roles/{id}: $ref: './paths/roles.yaml#/Role' /api/v1/roles/{id}/permissions: $ref: './paths/roles.yaml#/RolePermissions' /api/v1/roles/{id}/users: $ref: './paths/roles.yaml#/RoleUsers' /api/v1/roles/reorder: $ref: './paths/roles.yaml#/RolesReorder' /api/v1/notifications: $ref: './paths/notifications.yaml#/Notifications' /api/v1/notifications/unread-count: $ref: './paths/notifications.yaml#/NotificationsUnreadCount' /api/v1/notifications/read-all: $ref: './paths/notifications.yaml#/NotificationsReadAll' /api/v1/notifications/{id}/handle: $ref: './paths/notifications.yaml#/NotificationHandle' /api/v1/documents/{id}/borrow-requests: $ref: './paths/borrow-requests.yaml#/BorrowRequestCreate' /api/v1/borrow-requests/{id}: $ref: './paths/borrow-requests.yaml#/BorrowRequestDetail' /api/v1/borrow-requests/{id}/voucher: $ref: './paths/borrow-requests.yaml#/BorrowRequestVoucher' /api/v1/config/ui-dictionaries: $ref: './paths/configuration.yaml#/UiDictionaries' /api/v1/config/login-background: $ref: './paths/configuration.yaml#/LoginBackground' /api/v1/categories/tree: $ref: './paths/categories.yaml#/CategoryTree' /api/v1/categories: $ref: './paths/categories.yaml#/Categories' /api/v1/categories/reorder: $ref: './paths/categories.yaml#/CategoriesReorder' /api/v1/categories/{id}: $ref: './paths/categories.yaml#/Category' /api/v1/documents: $ref: './paths/documents.yaml#/Documents' /api/v1/documents/tags: $ref: './paths/documents.yaml#/DocumentsTags' /api/v1/documents/reorder: $ref: './paths/documents.yaml#/DocumentsReorder' /api/v1/documents/{id}: $ref: './paths/documents.yaml#/Document' /api/v1/documents/{id}/re-extract: $ref: './paths/documents.yaml#/DocumentReExtract' /api/v1/documents/{id}/move: $ref: './paths/documents.yaml#/DocumentMove' /api/v1/documents/batch-import: $ref: './paths/documents.yaml#/DocumentBatchImport' /api/v1/documents/{id}/preview: $ref: './paths/documents.yaml#/DocumentPreview' /api/v1/documents/{id}/download: $ref: './paths/documents.yaml#/DocumentDownload' /api/v1/main-plans/{id}/sub-plans: $ref: './paths/documents.yaml#/SubPlans' /api/v1/main-plans/{id}/sub-plans/bind: $ref: './paths/documents.yaml#/MainPlanSubPlanBinding' /api/v1/main-plans/{id}/sub-plans/{subPlanId}: $ref: './paths/documents.yaml#/MainPlanSubPlan' /api/v1/attachments: $ref: './paths/documents.yaml#/Attachments' /api/v1/attachments/{id}: $ref: './paths/documents.yaml#/Attachment' /api/v1/attachments/batch-import: $ref: './paths/documents.yaml#/AttachmentBatchImport' /api/v1/attachments/{id}/main-plans: $ref: './paths/documents.yaml#/AttachmentMainPlans' /api/v1/main-plans/{id}/attachments: $ref: './paths/documents.yaml#/MainPlanAttachments' /api/v1/main-plans/{id}/attachments/bind: $ref: './paths/documents.yaml#/MainPlanAttachmentBinding' /api/v1/main-plans/{id}/attachments/reorder: $ref: './paths/documents.yaml#/MainPlanAttachmentsReorder' /api/v1/main-plans/{id}/attachments/{attachmentId}: $ref: './paths/documents.yaml#/MainPlanAttachment' /api/v1/main-plans/{id}/attachments/{bindingId}/move: $ref: './paths/documents.yaml#/MainPlanAttachmentMove' /api/v1/documents/{id}/description: $ref: './paths/documents.yaml#/DocumentDescription' /api/v1/documents/{id}/permissions: $ref: './paths/documents.yaml#/DocumentPermissions' /api/v1/documents/{id}/permissions/entries/{entryId}/voucher: $ref: './paths/documents.yaml#/DocumentPermissionVoucher' /api/v1/documents/{id}/password: $ref: './paths/documents.yaml#/DocumentPassword' /api/v1/documents/relation-presets: $ref: './paths/documents.yaml#/DocumentRelationPresets' /api/v1/documents/{id}/relations: $ref: './paths/documents.yaml#/DocumentRelations' /api/v1/audit/logs: $ref: './paths/audit.yaml#/AuditLogs' /api/v1/statistics/documents: $ref: './paths/audit.yaml#/DocumentStatistics' /api/v1/audit/statistics/trend: $ref: './paths/audit.yaml#/AuditTrendStatistics' /api/v1/audit/statistics/actions: $ref: './paths/audit.yaml#/AuditActionStatistics' /api/v1/audit/statistics/users: $ref: './paths/audit.yaml#/AuditUserStatistics' /api/v1/recycle-bin/documents: $ref: './paths/recycle-bin.yaml#/RecycleBinDocuments' /api/v1/recycle-bin/documents/{id}/restore: $ref: './paths/recycle-bin.yaml#/RestoreRecycleBinDocument' /api/v1/backup/config: $ref: './paths/backup.yaml#/BackupConfig' /api/v1/backup/jobs: $ref: './paths/backup.yaml#/BackupJobs' /api/v1/backup/jobs/current: $ref: './paths/backup.yaml#/BackupJobCurrent' /api/v1/backup/jobs/current/cancel: $ref: './paths/backup.yaml#/BackupJobCancel' /api/v1/backup/test-target: $ref: './paths/backup.yaml#/BackupTestTarget' /api/v1/system/metrics/current: $ref: './paths/system.yaml#/SystemMetricsCurrent' /api/v1/system/metrics/history: $ref: './paths/system.yaml#/SystemMetricsHistory' /api/v1/system/process: $ref: './paths/system.yaml#/SystemProcess' /api/v1/system/storage-usage: $ref: './paths/system.yaml#/SystemStorageUsage' /api/v1/system/converter: $ref: './paths/system.yaml#/SystemConverter' /api/v1/system/health: $ref: './paths/system.yaml#/SystemHealth' /api/v1/system/info: $ref: './paths/system.yaml#/SystemInfo' /api/v1/system/runtime-config: $ref: './paths/system.yaml#/SystemRuntimeConfig' /api/v1/system/logs: $ref: './paths/system.yaml#/SystemLogs' /api/v1/system/logs/download: $ref: './paths/system.yaml#/SystemLogsDownload' /api/v1/system/maintenance/preview-cache: $ref: './paths/system.yaml#/SystemMaintenancePreviewCache' /api/v1/system/users/{user_id}/force-offline: $ref: './paths/system.yaml#/SystemForceOffline' components: securitySchemes: BearerAuth: $ref: './components/security-schemes.yaml#/BearerAuth' schemas: StringId: $ref: './components/schemas.yaml#/StringId' UtcDateTime: $ref: './components/schemas.yaml#/UtcDateTime' PageResult: $ref: './components/schemas.yaml#/PageResult' ErrorResponse: $ref: './components/schemas.yaml#/ErrorResponse' LoginRequest: $ref: './components/schemas.yaml#/LoginRequest' LoginResponse: $ref: './components/schemas.yaml#/LoginResponse' UserSummary: $ref: './components/schemas.yaml#/UserSummary' OrganizationNode: $ref: './components/schemas.yaml#/OrganizationNode' UserPageResponse: $ref: './components/schemas.yaml#/UserPageResponse' CategoryNode: $ref: './components/schemas.yaml#/CategoryNode' CreateCategoryRequest: $ref: './components/schemas.yaml#/CreateCategoryRequest' UpdateCategoryRequest: $ref: './components/schemas.yaml#/UpdateCategoryRequest' DocumentSummary: $ref: './components/schemas.yaml#/DocumentSummary' DocumentDetail: $ref: './components/schemas.yaml#/DocumentDetail' AttachmentBindingSummary: $ref: './components/schemas.yaml#/AttachmentBindingSummary' BindAttachmentsRequest: $ref: './components/schemas.yaml#/BindAttachmentsRequest' BindAttachmentsResponse: $ref: './components/schemas.yaml#/BindAttachmentsResponse' UnbindAttachmentResponse: $ref: './components/schemas.yaml#/UnbindAttachmentResponse' ReorderDocumentsRequest: $ref: './components/schemas.yaml#/ReorderDocumentsRequest' ReorderDocumentsResponse: $ref: './components/schemas.yaml#/ReorderDocumentsResponse' ReorderAttachmentsRequest: $ref: './components/schemas.yaml#/ReorderAttachmentsRequest' ReorderAttachmentsResponse: $ref: './components/schemas.yaml#/ReorderAttachmentsResponse' PermissionEntry: $ref: './components/schemas.yaml#/PermissionEntry' SavePermissionsRequest: $ref: './components/schemas.yaml#/SavePermissionsRequest' PermissionDetailResponse: $ref: './components/schemas.yaml#/PermissionDetailResponse' PermissionVoucherResultResponse: $ref: './components/schemas.yaml#/PermissionVoucherResultResponse' PermissionVoucherDeleteResultResponse: $ref: './components/schemas.yaml#/PermissionVoucherDeleteResultResponse' AuditLogSummary: $ref: './components/schemas.yaml#/AuditLogSummary' AuditLogPageResponse: $ref: './components/schemas.yaml#/AuditLogPageResponse' DocumentStatisticsResponse: $ref: './components/schemas.yaml#/DocumentStatisticsResponse' AuditTrendResponse: $ref: './components/schemas.yaml#/AuditTrendResponse' AuditActionStatisticsResponse: $ref: './components/schemas.yaml#/AuditActionStatisticsResponse' AuditUserStatisticsResponse: $ref: './components/schemas.yaml#/AuditUserStatisticsResponse' DeletedBySnapshot: $ref: './components/schemas.yaml#/DeletedBySnapshot' RecycleBinDocumentSummary: $ref: './components/schemas.yaml#/RecycleBinDocumentSummary' RecycleBinDocumentPageResponse: $ref: './components/schemas.yaml#/RecycleBinDocumentPageResponse' RestoreDocumentRequest: $ref: './components/schemas.yaml#/RestoreDocumentRequest' RestoreDocumentResult: $ref: './components/schemas.yaml#/RestoreDocumentResult' RestoreDocumentResponse: $ref: './components/schemas.yaml#/RestoreDocumentResponse' DictionaryOption: $ref: './components/schemas.yaml#/DictionaryOption' UiDictionaries: $ref: './components/schemas.yaml#/UiDictionaries' UiDictionariesResponse: $ref: './components/schemas.yaml#/UiDictionariesResponse' RoleCode: $ref: './components/schemas.yaml#/RoleCode' AllowedModule: $ref: './components/schemas.yaml#/AllowedModule' DocumentType: $ref: './components/schemas.yaml#/DocumentType' DocumentStatus: $ref: './components/schemas.yaml#/DocumentStatus' SecurityLevel: $ref: './components/schemas.yaml#/SecurityLevel' AttachmentType: $ref: './components/schemas.yaml#/AttachmentType' AllowedAction: $ref: './components/schemas.yaml#/AllowedAction' CategoryType: $ref: './components/schemas.yaml#/CategoryType' EnabledStatus: $ref: './components/schemas.yaml#/EnabledStatus' AuditResult: $ref: './components/schemas.yaml#/AuditResult' AuditAction: $ref: './components/schemas.yaml#/AuditAction' AuditTarget: $ref: './components/schemas.yaml#/AuditTarget' CreateOrganizationRequest: $ref: './components/schemas.yaml#/CreateOrganizationRequest' UpdateOrganizationRequest: $ref: './components/schemas.yaml#/UpdateOrganizationRequest' OrganizationResponse: $ref: './components/schemas.yaml#/OrganizationResponse' DeleteOrganizationResponse: $ref: './components/schemas.yaml#/DeleteOrganizationResponse' CreateUserRequest: $ref: './components/schemas.yaml#/CreateUserRequest' UpdateUserRequest: $ref: './components/schemas.yaml#/UpdateUserRequest' ResetUserPasswordRequest: $ref: './components/schemas.yaml#/ResetUserPasswordRequest' DeleteUserResponse: $ref: './components/schemas.yaml#/DeleteUserResponse' ResetPasswordResponse: $ref: './components/schemas.yaml#/ResetPasswordResponse' DocumentTagsResponse: $ref: './components/schemas.yaml#/DocumentTagsResponse' DeptScope: $ref: './components/schemas.yaml#/DeptScope' RoleSummary: $ref: './components/schemas.yaml#/RoleSummary' RolePageResponse: $ref: './components/schemas.yaml#/RolePageResponse' CreateRoleRequest: $ref: './components/schemas.yaml#/CreateRoleRequest' UpdateRoleRequest: $ref: './components/schemas.yaml#/UpdateRoleRequest' RoleResponse: $ref: './components/schemas.yaml#/RoleResponse' DeleteRoleResponse: $ref: './components/schemas.yaml#/DeleteRoleResponse' RolePermissionRow: $ref: './components/schemas.yaml#/RolePermissionRow' RoleMatrixListResponse: $ref: './components/schemas.yaml#/RoleMatrixListResponse' UpdateRolePermissionsRequest: $ref: './components/schemas.yaml#/UpdateRolePermissionsRequest' RolePermissionsResponse: $ref: './components/schemas.yaml#/RolePermissionsResponse' RoleUsersResponse: $ref: './components/schemas.yaml#/RoleUsersResponse' UpdateRoleUsersRequest: $ref: './components/schemas.yaml#/UpdateRoleUsersRequest' IpEntrySummary: $ref: './components/schemas.yaml#/IpEntrySummary' IpEntryPageResponse: $ref: './components/schemas.yaml#/IpEntryPageResponse' CreateIpEntryRequest: $ref: './components/schemas.yaml#/CreateIpEntryRequest' UpdateIpEntryRequest: $ref: './components/schemas.yaml#/UpdateIpEntryRequest' IpEntryResponse: $ref: './components/schemas.yaml#/IpEntryResponse' DeleteIpEntryResponse: $ref: './components/schemas.yaml#/DeleteIpEntryResponse' BackupConfigView: $ref: './components/schemas.yaml#/BackupConfigView' UpdateBackupConfigRequest: $ref: './components/schemas.yaml#/UpdateBackupConfigRequest' BackupConfigResponse: $ref: './components/schemas.yaml#/BackupConfigResponse' BackupJobStartRequest: $ref: './components/schemas.yaml#/BackupJobStartRequest' BackupProgress: $ref: './components/schemas.yaml#/BackupProgress' BackupJobStartResponse: $ref: './components/schemas.yaml#/BackupJobStartResponse' BackupCurrentJob: $ref: './components/schemas.yaml#/BackupCurrentJob' BackupJobCurrentResponse: $ref: './components/schemas.yaml#/BackupJobCurrentResponse' BackupCancelResponse: $ref: './components/schemas.yaml#/BackupCancelResponse' BackupHistoryEntry: $ref: './components/schemas.yaml#/BackupHistoryEntry' BackupHistoryResponse: $ref: './components/schemas.yaml#/BackupHistoryResponse' OrgIpAssignmentListResponse: $ref: './components/schemas.yaml#/OrgIpAssignmentListResponse' UpdateOrgIpAssignmentsRequest: $ref: './components/schemas.yaml#/UpdateOrgIpAssignmentsRequest' OrgIpAssignmentsResponse: $ref: './components/schemas.yaml#/OrgIpAssignmentsResponse' DocumentRelationPreset: $ref: './components/schemas.yaml#/DocumentRelationPreset' DocumentRelationPresetsResponse: $ref: './components/schemas.yaml#/DocumentRelationPresetsResponse' DocumentRelationItem: $ref: './components/schemas.yaml#/DocumentRelationItem' DocumentRelationsResponse: $ref: './components/schemas.yaml#/DocumentRelationsResponse' UpdateDocumentRelationsRequest: $ref: './components/schemas.yaml#/UpdateDocumentRelationsRequest' DocumentRelationsSaveResponse: $ref: './components/schemas.yaml#/DocumentRelationsSaveResponse' security: - BearerAuth: []