编辑 | blame | 历史 | 原始文档

档案管理模块 - 前端联调方案

模块:yudao-module-archive(主模块)+ yudao-module-archive-api(跨模块归档 RPC)
后端接口前缀:/archive/category、/archive/document、/archive/borrow、/archive/stat
附件关联:recordType = archive_document,application = file
权限点前缀:archive:category:*、archive:document:*、archive:borrow:*、archive:stat:query

一、涉及页面(前端文件清单)

文件 说明
src/packages/constants/src/dict-enum.ts 新增 ARCHIVE_DICT(6 个字典类型)并展开进 DICT_TYPE
src/api/archive/category/index.ts 档案分类 API
src/api/archive/document/index.ts 档案 API
src/api/archive/borrow/index.ts 借阅单 API
src/api/archive/stat/index.ts 档案统计 API
src/views/archive/category/index.vue 分类树表页(左树右表形态,treeConfig 展开)
src/views/archive/category/data.ts 分类表单 + 搜索表单 + 表格列
src/views/archive/category/modules/form.vue 分类新增/编辑弹窗(含「新增下级」)
src/views/archive/document/index.vue 档案列表页(检索 + 导出 + 附件标记)
src/views/archive/document/data.ts 档案表单 + 搜索表单 + 表格列
src/views/archive/document/modules/form.vue 档案新增/编辑/详情弹窗(实体位置四字段 + 电子附件上传)
src/views/archive/borrow/index.vue 借阅列表页(逾期 Tag、提交审批、归还登记)
src/views/archive/borrow/data.ts 借阅表单 + 搜索表单 + 表格列 + BorrowStatus 常量
src/views/archive/borrow/modules/form.vue 借阅登记/编辑/详情弹窗
src/views/archive/borrow/modules/process-select-modal.vue 选择审批流程弹窗
src/views/archive/borrow/modules/return-form.vue 归还登记弹窗
src/views/archive/borrow/detail/approve/index.vue BPM 审批详情页,路径必须与 bpm_process_definition_info.form_custom_view_path 完全一致
src/views/archive/stat/index.vue 档案统计页(4 卡片 + 3 图表)
src/views/archive/stat/data.ts 卡片定义 + 饼图/柱图 option 构造

字典枚举必须登记到 dict-enum.ts,否则 DICT_TYPE.ARCHIVE_* 取不到值,列表列与表单下拉会空白。

菜单已配置完成,本项目为动态路由,前端无需手工加路由文件:

菜单 id 路径 组件 权限标识
档案管理(顶级目录 parent_id=0,path=/archive) 1075600 /archive — —
档案分类 1075601 category archive/category/index archive:category:query
档案管理 1075602 document archive/document/index archive:document:query
借阅登记 1075603 borrow archive/borrow/index archive:borrow:query
档案统计 1075604 stat archive/stat/index archive:stat:query

按钮权限:archive:category:create/update/delete、archive:document:create/update/delete/export/sensitive、archive:borrow:create/update/delete/submit/return、archive:stat:query。

⚠ 授权易错点:这些菜单与权限点**未授予任何角色**,因此只有超级管理员(super_admin,代码直返全部菜单)能看到;普通角色需在「系统管理 → 角色」勾选授权。
⚠ 敏感权限:archive:document:sensitive(菜单 1075625「保密档案查看」)决定能否看到密级=保密的档案。**未授权时后端会强制过滤**,不是前端隐藏。

字典已配置完成,前端直接用 getDictOptions / DictTag 取值,无需自建枚举:

字典类型 名称 取值
archive_category_status 档案分类状态 0 启用 / 1 停用
archive_document_status 档案状态 10 在库 / 20 借出中
archive_secret_level 档案密级 1 公开 / 2 内部 / 3 保密
archive_carrier_type 档案载体 1 电子 / 2 实体 / 3 电子+实体
archive_source_type 档案来源 1 手工录入 / 2 课题归档 / 3 会员归档 / 4 财务归档
archive_borrow_status 档案借阅状态 0 草稿 / 15 审批中 / 20 借出中 / 30 已归还 / 35 已驳回

二、业务流程与数据带入

2.1 档案登记(手工)

选择档案分类(树形下拉,默认带出该分类的 default_secret_level)
        │
        ├── 档案标题、密级、载体、归档日期(必填)
        ├── 实体位置:书架号 / 层号 / 列号 / 册号(档案盒号)/ 存放位置描述
        └── 电子文件:走 /system/storage-blob/upload 拿 blobId,随 create/update 一起提交
                    │
                 保存(create)
                    ▼
        后端生成档案编号 DA+yyyyMMdd+6位流水,落库并 bindAttachments
                    │
                列表可检索(标题/关键词/来源单号/分类/密级/载体/状态/归档日期区间)
  • 附件字段:表单字段名 blobIds(number[])。**全量替换语义** —— 清空全部附件时必须显式传 [],传 null 视为「不动附件」。
  • 打开编辑/详情时:需把 attachmentList 映射成上传组件可识别的对象(uid/name/url/status/id),提交时按 valueKey: 'id' 提取为 blobId。
  • 只读字段:no(档案编号)、status(档案状态)、sourceType / sourceNo(来源)、archivistName(归档人)由后端维护,表单只展示不回传。

2.2 借阅闭环

登记借阅(选择在库档案 + 借阅人 + 借阅日期 + 归还期限)
        │
     保存(草稿 0)
        │
     提交审批(先调 approve-process-list 拿流程 key,再 submit)
        ▼
     审批中 15 ──[BPM 通过]──► 借出中 20 ──[归还登记]──► 已归还 30
        │                          │
        │                    (同时把档案置为「借出中」)
        │
        └──[BPM 驳回]──► 已驳回 35 ──(改后可重新提交)

关键带入规则:

  1. 借阅登记时:选中的档案会以 no + title 形式展示;提交时只传 documentId,档案编号与标题由后端快照到借阅单(documentNo / documentTitle)。
  2. 提交审批时:**流程 key 必须来自后端 approve-process-list,禁止前端写死**。列表为空时应提示「暂无可用审批流程,请先到 BPM 流程设计器发布档案借阅审批流程」。
  3. 归还登记时:只传 id + returnRemark。归还成功后档案自动回到「在库」,借阅单变「已归还」并写入 returnTime / returnConfirmUserName。

2.3 逾期提醒(实时计算,不落库、不发通知)

  • 后端在 page / overdue-page 返回时实时计算:overdue = (status == 20 && returnDeadline < 今天),overdueDays = 今天 - returnDeadline。
  • 前端**不需要**自行计算,直接用 row.overdue / row.overdueDays 渲染红色 Tag。
  • overdueOnly 不是查询参数,而是独立接口 GET /archive/borrow/overdue-page;前端用「只看逾期」按钮切换调用的接口即可。

2.4 三方归档联动(本模块的外部入口)

来源模块 接口 权限点 触发前提
课题 POST /research/application/archive?id research:application:archive 申报单 status=20 已立项 且未归档
会员 POST /ums/member/archive?id ums:member:archive 会员 status=1 正常 且未归档
财务 POST /finance/reimbursement/archive?id finance:reimbursement:archive(既有) 报销单 status=20 已通过 且未归档
  • 三个接口**均返回生成的档案编号**(CommonResult<String>,如 DA20260929000001),前端 toast 直接提示「归档成功,已生成档案 XXX」。
  • 三方列表页的响应体新增两个字段用于控制按钮显隐与「已归档」标记:
    | 字段 | 类型 | 说明 |
    |------|------|------|
    | archiveDocumentId | number | 归档生成的档案 ID(非空即已归档) |
    | archived | boolean | 是否已归档 |
  • 生成的档案:sourceType 为 2 课题 / 3 会员 / 4 财务,sourceNo 取来源单号(立项编号 / 会员编号 / 报销单号),分类固定取 research / member / finance。
  • 财务归档默认密级为「保密」(分类 finance 的 default_secret_level=3),因此财务档案在无 archive:document:sensitive 权限时**在档案列表里看不到**。
  • 重复归档会报错,提示中带来源单号与已生成的档案编号;前端应在归档成功后刷新列表(archiveDocumentId 非空后按钮自动隐藏)。
  • 财务归档是叠加语义:既有逻辑把报销单 20→40 并写 archiveTime,本次在此基础上追加生成档案,两者同事务。

三、API

3.1 档案分类 /archive/category

方法 路径 权限 说明
POST /archive/category/create archive:category:create 新增分类
PUT /archive/category/update archive:category:update 修改分类
DELETE /archive/category/delete?id archive:category:delete 删除(有子分类/有档案时拒绝)
GET /archive/category/get?id archive:category:query 分类详情
GET /archive/category/list archive:category:query 分类列表(**平铺**,供树表 transform 用)
GET /archive/category/tree archive:category:query 分类树(供左树与下拉用)

/list 请求参数:

参数 类型 必填 说明
name String 否 分类名称,模糊匹配
status Integer 否 状态:0 启用 / 1 停用

新增/修改请求体:

参数 类型 必填 说明
id Long 修改必填 编号
parentId Long 是 父分类 ID,0=顶级
name String 是 分类名称
code String 是 分类编码,唯一(member/research/finance 等,归档联动按此查找)
sort Integer 否 显示排序
description String 否 分类说明
defaultSecretLevel Integer 是 默认密级(1/2/3)
status Integer 否 状态(0 启用 / 1 停用)
remark String 否 备注

响应字段: id、parentId、name、code、sort、description、defaultSecretLevel、status、remark、createTime、children(树形接口才返回)。

树表接入要点:/list 返回**平铺**数组,前端 VXE 表格用 treeConfig: { parentField: 'parentId', rowField: 'id', transform: true, expandAll: true, reserve: true } 自行转树,pagerConfig.enabled = false,名称列加 treeNode: true。

3.2 档案 /archive/document

方法 路径 权限 说明
POST /archive/document/create archive:document:create 新增档案
PUT /archive/document/update archive:document:update 修改(借出中拒绝)
DELETE /archive/document/delete?id archive:document:delete 删除(借出中/存在未归还借阅单拒绝)
GET /archive/document/get?id archive:document:query 详情(保密档案需 archive:document:sensitive)
GET /archive/document/page archive:document:query 分页(无敏感权限时自动过滤保密档案)
GET /archive/document/export-excel archive:document:export 导出 Excel(同上过滤)

/page 请求参数:

参数 类型 必填 说明
pageNo / pageSize Integer 是 分页
no String 否 档案编号,模糊匹配
title String 否 档案标题,模糊匹配
categoryId Long 否 档案分类 ID
secretLevel Integer 否 密级
carrierType Integer 否 载体
sourceType Integer 否 来源类型
sourceNo String 否 来源单号,模糊匹配
tags String 否 关键词,模糊匹配 tags 字段
status Integer 否 档案状态
archiveDate LocalDate[] 否 归档日期区间,**格式 yyyy-MM-dd**(RangePicker 必须设 valueFormat: 'YYYY-MM-DD',不能带时分秒)

新增/修改请求体(SaveReqVO 只接受以下字段):

参数 类型 必填 说明
id Long 修改必填 编号
title String 是 档案标题
categoryId Long 是 档案分类 ID
secretLevel Integer 是 密级
carrierType Integer 是 载体
shelfNo / layerNo / columnNo / boxNo String 否 实体位置四字段
storePlace String 否 存放位置描述
archiveDate String(yyyy-MM-dd) 是 归档日期
summary String 否 摘要
tags String 否 关键词,英文逗号分隔
remark String 否 备注
blobIds Long[] 否 附件 ID 全量列表,**清空须传 []**

响应新增/只读字段: no、categoryName、sourceType、sourceNo、sourceId、sourceTitle、archivistUserId、archivistName、status、attachmentList、hasAttachment。

⚠ no / status / source* / archivist* 不要在提交体里回传(后端 SaveReqVO 不接收,回传无意义且会被忽略)。

3.3 借阅 /archive/borrow

方法 路径 权限 说明
POST /archive/borrow/create archive:borrow:create 登记借阅(草稿)
PUT /archive/borrow/update archive:borrow:update 修改(仅草稿/已驳回)
DELETE /archive/borrow/delete?id archive:borrow:delete 删除(仅草稿)
GET /archive/borrow/get?id archive:borrow:query 详情
GET /archive/borrow/page archive:borrow:query 分页
GET /archive/borrow/overdue-page archive:borrow:query 逾期未还分页(借出中 且 归还期限已过)
POST /archive/borrow/submit?id&processDefinitionKey archive:borrow:submit 提交审批
GET /archive/borrow/approve-process-list archive:borrow:query 审批流程定义列表({ id, key, name })
POST /archive/borrow/return archive:borrow:return 归还登记

/page 与 /overdue-page 请求参数:

参数 类型 必填 说明
pageNo / pageSize Integer 是 分页
no String 否 借阅单号,模糊匹配
documentNo String 否 档案编号,模糊匹配
documentTitle String 否 档案标题,模糊匹配
borrowerName String 否 借阅人姓名,模糊匹配
status Integer 否 状态
borrowDate LocalDate[] 否 借阅日期区间,yyyy-MM-dd
returnDeadline LocalDate[] 否 归还期限区间,yyyy-MM-dd

新增/修改请求体:

参数 类型 必填 说明
id Long 修改必填 编号
documentId Long 是 档案 ID(须为**在库**档案)
borrowerUserId Long 否 借阅人用户 ID
borrowerName String 是 借阅人姓名
borrowerDept String 否 借阅人部门
borrowerPhone String 否 联系电话
borrowDate String(yyyy-MM-dd) 是 借阅日期
borrowPurpose String 否 借阅目的
returnDeadline String(yyyy-MM-dd) 是 归还期限(不得早于借阅日期)
remark String 否 备注

归还登记请求体:

参数 类型 必填 说明
id Long 是 借阅单编号
returnRemark String 否 归还备注

响应新增只读字段: no、documentNo、documentTitle、approveTime、returnTime、returnConfirmUserId、returnConfirmUserName、rejectReason、rejectTime、overdue、overdueDays、processInstanceId。

响应示例:

{
  "code": 0,
  "data": {
    "list": [
      {
        "id": 1,
        "no": "JY20260929000001",
        "documentId": 1,
        "documentNo": "DA20260929000001",
        "documentTitle": "2026年度学会工作总结",
        "borrowerName": "张三",
        "borrowerDept": "秘书处",
        "borrowDate": "2026-09-20",
        "returnDeadline": "2026-10-05",
        "status": 20,
        "approveTime": "2026-09-20 10:12:33",
        "overdue": false,
        "overdueDays": 0
      }
    ],
    "total": 1
  },
  "msg": ""
}

3.4 统计 /archive/stat

方法 路径 权限 说明
GET /archive/stat/overview archive:stat:query 统计总览(存量 + 流转 + 三组分布)

响应字段:

字段 类型 说明
totalCount Long 档案总数
inStockCount Long 在库档案数
borrowedCount Long 借出中**档案**数
borrowingCount Long 借出中**借阅单**数
overdueCount Long 逾期未还借阅单数
byCategory Array 分类分布,元素 { categoryId, name, total }
bySecretLevel Array 密级分布,元素 { value, name, total }
byCarrierType Array 载体分布,元素 { value, name, total }

bySecretLevel / byCarrierType 的 name 已由后端转成字典标签,前端**直接当图例名用**,无需再查字典。

3.5 跨模块归档(本模块对外)

方法 路径 权限 返回
POST /research/application/archive?id research:application:archive CommonResult<String>(档案编号)
POST /ums/member/archive?id ums:member:archive CommonResult<String>(档案编号)
POST /finance/reimbursement/archive?id finance:reimbursement:archive CommonResult<String>(档案编号)

响应示例:

{ "code": 0, "data": "DA20260929000001", "msg": "" }

四、字段展示规则

字段 展示位置 规则
no 档案列表、详情 后端生成,只读
title 列表、详情、表单 列表可模糊搜索
categoryName 列表 后端 join 分类冗余,列表直接展示名称而非 ID
secretLevel 列表、表单 CellDict 取 archive_secret_level;**保密档案无权限时根本不返回**
carrierType 列表、表单 CellDict 取 archive_carrier_type
sourceType 列表 CellDict 取 archive_source_type
sourceNo 列表、详情 来源单号(立项编号/会员编号/报销单号)
storePlace + 四位置字段 列表、详情 实体位置;电子载体时可为空
archiveDate 列表、详情、表单 yyyy-MM-dd
status(档案) 列表、表单(只读) CellDict 取 archive_document_status
hasAttachment 列表 用 slot 渲染「有 / 无」Tag
overdue / overdueDays 借阅列表、借阅详情 用 slot 渲染,逾期时红色 Tag「逾期 N 天」
status(借阅) 借阅列表、审批详情 CellDict 取 archive_borrow_status
documentNo / documentTitle 借阅列表 归档时的快照,档案改名不影响历史借阅单
approveTime / returnTime 借阅列表 formatDateTime 格式化
archiveDocumentId 课题 / 会员 / 财务列表 非空即显示「已归档」,并隐藏「归档」按钮

五、业务规则说明

场景 规则
删除分类 有子分类或有档案时拒绝,提示中回显分类名与具体原因
修改分类父级 不能把分类设为自身或其子分类
修改档案 档案处于「借出中」时拒绝修改
删除档案 档案处于「借出中」或存在未归还借阅单时拒绝
删除借阅单 仅「草稿」可删除
提交借阅审批 仅「草稿」「已驳回」可提交;提交前校验同档案无「审批中/借出中」借阅单
归还期限 不得早于借阅日期
审批通过 借阅单 → 借出中并写 approveTime;**同时**把档案置为「借出中」
审批驳回 借阅单 → 已驳回并写 rejectReason / rejectTime,改后可重新提交
归还登记 仅「借出中」可登记;成功后档案回到「在库」
逾期 实时计算,不落库、不发站内信、不建定时任务;仅列表 Tag 与「只看逾期」接口体现
敏感档案 无 archive:document:sensitive 时,/page、/get、/export-excel 三个入口均过滤/拒绝
归档幂等 同一来源单据重复归档会报错,提示中带来源单号与已生成档案编号
财务归档 报销单 20→40(既有)**并**生成「保密」档案(本次新增),同事务

六、注意事项

  1. 附件一律走 system 模块:POST /system/storage-blob/upload → 拿 blobId;表单字段用全局 FileUpload 组件绑定 blobIds。**禁止**在档案表加 file_url 列、禁止新增上传接口、禁止用 infra 的 FileApi。
  2. blobIds 是全量替换语义:编辑时若清空了全部附件,必须提交 [];提交 null 后端会视为「不动附件」。打开编辑弹窗时应把 attachmentList 映射成 { uid, name, url, status: 'done', id } 数组。
  3. 日期区间一律 valueFormat: 'YYYY-MM-DD':后端 LocalDate[] 只接受 yyyy-MM-dd,带时分秒会解析失败。
  4. 流程 key 不写死:提交借阅审批前必须先调 approve-process-list;返回空数组时提示用户先去 BPM 发布流程。
  5. 审批详情页路径是硬约定:src/views/archive/borrow/detail/approve/index.vue 必须与 bpm_process_definition_info.form_custom_view_path 一致,且组件需接受 props: { id: string }(BPM 审批中心通过 businessKey 传入借阅单 ID)。改动路径会导致待办审批页打不开。
  6. 档案「借出中」是并发敏感的:审批通过时会条件更新档案状态,若档案已被另一条借阅单占用会返回业务异常;前端提示用户刷新后重试即可,不要静默忽略。
  7. 不要在归档按钮里判断 archived 之外的字段:按钮显隐条件建议用 status === 已通过/已立项/正常 && !archiveDocumentId,归档成功后刷新列表即可自动隐藏。
  8. 超管与普通角色的可见性差异:菜单与权限点默认只对超管可见,普通角色需先在「系统管理 → 角色」授权,否则整块 /archive 菜单不出现。