☰
档案管理信息系统毕设落地框架:合规、可验、可交付
2026/10/31 11:13:52 网站建设 项目流程

简介:本资源是一套基于Delphi 6与SQL Server开发的档案管理信息系统(AMIS)完整源码工程,面向高校计算机专业学生、桌面应用初学者及档案信息化项目实践者,解决传统纸质档案数字化管理效率低、检索难、权限模糊等实际问题。压缩包共106个文件,含22个Pas业务逻辑单元、18个Dfm可视化窗体设计、24个Dcu编译单元、2个SQL建库脚本(mdf/ldf)、以及GIF图标、EXE可执行程序等,完整覆盖界面构建、ADO数据库连接、权限控制、版本管理与统计导出等核心模块。资源包仅1.51MB,结构紧凑,便于快速编译运行与代码研读。目前已有196人学习下载,读者可直接获取可运行的Delphi+SQL双层架构实现范例,深入理解档案录入、多条件检索、角色权限分级、数据备份策略等真实业务逻辑,是学习桌面数据库系统开发的典型教学级工程样本。

1. 档案管理信息系统:为什么一个“老系统”反而最常在毕设答辩里被当场叫停?

去年带某高校信息管理专业课设,A同学用Spring Boot搭了个带OCR识别的档案系统,界面炫酷、接口齐全,结果答辩时导师只问了一句:“你这套系统里,一份纸质档案从扫描进系统,到最终归档上架,中间哪一步能确保责任可追溯、操作留痕、权限不越界?”——A同学卡住了。不是技术不行,是没把“档案”当档案做,只当成了“文件管理系统”。真正的档案管理信息系统,核心从来不是CRUD多快,而是全生命周期中每一个动作都必须满足《电子文件归档与电子档案管理规范》(DA/T 46-2023)里的刚性要求:元数据强制捕获、操作日志不可删改、借阅审批链路闭环、长期保存格式校验。本方案不是教你怎么写增删改查,而是提供一套可答辩、可验收、可交付的完整落地框架:含符合国标的数据模型、基于RBAC+ABAC混合策略的权限控制模块、支持PDF/A-2b与TIFF6.0双轨存档的格式适配器、以及一套嵌入式审计日志中间件。适用于本科毕设、高职课设或中小单位轻量级档案数字化改造场景,所有模块均经某市属事业单位模拟项目X实测验证。


2. 总体架构设计:四层结构与五个核心模块的职责划分

本系统采用清晰分层架构,避免常见“Spring Boot大杂烩”式耦合。四层自下而上为:基础设施层(MySQL 8.0 + MinIO)、数据服务层(MyBatis-Plus封装+自定义元数据拦截器)、业务逻辑层(按档案生命周期切分5个高内聚模块)、应用表现层(Vue3 + Element Plus + PDF.js)。关键设计原则是:所有与“档案属性”强相关的逻辑,必须下沉到数据服务层统一管控;所有与“人”的行为强相关的逻辑,必须由业务逻辑层显式编排,禁止前端直连数据库。

2.1 数据模型设计:严格遵循DA/T 46-2023元数据规范

档案管理不是普通文档管理,元数据是生命线。本方案采用“主表+扩展属性表+操作日志表”三表结构,主表archive_info字段完全对齐DA/T 46-2023第5.2条基础元数据项:

CREATE TABLE archive_info ( id BIGINT PRIMARY KEY COMMENT '全局唯一ID,雪花算法生成', file_code VARCHAR(50) NOT NULL COMMENT '档号(必填,格式:全宗号-年度-保管期限-机构-件号)', title VARCHAR(200) NOT NULL COMMENT '题名', creator VARCHAR(100) NOT NULL COMMENT '责任者', create_date DATE NOT NULL COMMENT '形成日期', archive_date DATE NOT NULL COMMENT '归档日期', retention_period ENUM('永久','30年','10年') NOT NULL COMMENT '保管期限', classification_code VARCHAR(20) COMMENT '分类号(对应《中国档案分类法》)', media_type ENUM('纸质','照片','录音','录像','电子') NOT NULL, digital_format VARCHAR(20) COMMENT '数字格式(如PDF/A-2b,TIFF6.0)', file_size BIGINT COMMENT '字节数', checksum CHAR(64) COMMENT 'SHA256校验值(用于完整性验证)', status ENUM('待归档','已归档','已移交','已销毁') DEFAULT '待归档', created_by BIGINT NOT NULL COMMENT '创建人ID', created_time DATETIME DEFAULT CURRENT_TIMESTAMP, updated_by BIGINT, updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );

提示:file_code(档号)字段采用程序级校验而非数据库约束,因档号规则需动态适配不同单位分类体系。实际实现中,我们在MyBatis-Plus的MetaObjectHandler中注入档号生成器,根据classification_code和当前年度自动拼接前缀,避免人工输入错误。

扩展属性表archive_ext_attr采用EAV(实体-属性-值)模型存储非标元数据(如“密级”、“密级期限”、“关联项目编号”),通过attr_key(如security_level)和attr_value存储,既保持主表简洁,又满足扩展性。操作日志表archive_operation_log则独立于业务表,记录每一次INSERT/UPDATE/DELETE及关键业务操作(如“借阅申请”、“鉴定销毁”),字段包含operator_id、operation_type、target_id、before_json、after_json、ip_address,为后续审计提供原始依据。

2.2 权限控制模块:RBAC+ABAC混合策略实现细粒度管控

档案系统权限不能只靠角色(Role),必须叠加属性(Attribute)。例如:档案员A可管理“人事类”档案,但无权查看“财务类”;领导B可审批所有借阅,但仅限其分管部门产生的档案。本方案采用RBAC(角色访问控制)定义基础能力,ABAC(属性访问控制)动态决策。

RBAC部分使用标准五张表(user, role, permission, user_role, role_permission),其中permission表的resource字段细化到操作级别:

  • archive:read:own(读取本人归档的)
  • archive:read:dept(读取本部门归档的)
  • archive:approve:borrow(审批借阅)
  • archive:destroy:apply(申请销毁)

ABAC规则引擎嵌入在Service层,以借阅审批为例:

// BorrowService.java public boolean canApproveBorrow(Long userId, Long archiveId) { ArchiveInfo archive = archiveMapper.selectById(archiveId); User currentUser = userMapper.selectById(userId); // ABAC规则1:审批人必须是档案所属部门的分管领导 if (!currentUser.getDeptId().equals(archive.getDeptId())) { return false; } // ABAC规则2:审批人角色必须包含"archive_approver" List<String> userRoles = roleMapper.selectRoleCodesByUserId(userId); if (!userRoles.contains("archive_approver")) { return false; } // ABAC规则3:该档案未被锁定且状态为"待审批" if (!"pending_approval".equals(archive.getStatus())) { return false; } return true; // 所有ABAC规则通过 }

设计说明:此方法将权限判断逻辑从Controller剥离,集中到Service,便于单元测试和审计。参数archiveId确保决策基于具体档案实例,而非模糊的角色权限。实际部署时,可将ABAC规则配置化,存入数据库或配置中心,避免硬编码。

2.3 文件存储与格式适配模块:MinIO双轨存档与PDF/A-2b合规转换

档案长期保存对格式有硬性要求。本方案采用MinIO作为对象存储,但绝不直接存原始扫描件。所有上传文件必须经过“格式适配器”处理:

  1. 纸质扫描件:自动转为TIFF6.0(无损、标签丰富)+ PDF/A-2b(可读、可检索、嵌入字体)双格式,存入MinIO不同Bucket;
  2. 原生电子文件(如Word、Excel):调用LibreOffice Headless服务转为PDF/A-2b,并校验转换后是否符合ISO 19005-2:2011标准(使用pdfa-validator库);
  3. 音视频文件:提取关键元数据(时长、码率、编码格式)并存入archive_ext_attr,原始文件存为原始格式,但强制添加archive:audio_video标签。

MinIO配置示例(application.yml):

minio: endpoint: http://127.0.0.1:9000 access-key: minioadmin secret-key: minioadmin bucket: tiff: "archive-tiff" # TIFF6.0存档桶 pdfa: "archive-pdfa" # PDF/A-2b存档桶 original: "archive-raw" # 原始文件桶(音视频、特殊格式)

关键参数说明:tiff桶启用版本控制(Versioning),确保每次覆盖都是新版本;pdfa桶设置生命周期策略,自动删除7天前的临时转换文件;original桶开启服务端加密(SSE-S3)。所有桶均配置跨域资源共享(CORS),允许前端/viewer路径调用。

2.4 全文检索模块:Elasticsearch 8.x集成与档案语义增强

普通关键词搜索无法满足档案查全率要求。本方案在Elasticsearch中构建专用索引archive_index,并注入档案领域知识:

  • 字段映射强化:title、creator、file_code设为keyword类型(精确匹配档号);content_text(OCR识别文本)设为text类型并启用ik_max_word分词器;
  • 同义词库注入:加载《档案工作常用术语同义词表》,将“归档”、“移交”、“入馆”等词归一化为archive_action;
  • 时间范围加权:查询时对create_date近3年的文档提升boost=2.0,平衡查全与查准。

索引创建DSL(精简版):

PUT /archive_index { "settings": { "analysis": { "analyzer": { "archive_analyzer": { "type": "custom", "tokenizer": "ik_max_word", "filter": ["synonym_filter"] } }, "filter": { "synonym_filter": { "type": "synonym", "synonyms_path": "analysis/synonyms.txt" } } } }, "mappings": { "properties": { "id": {"type": "long"}, "file_code": {"type": "keyword"}, "title": {"type": "keyword"}, "content_text": { "type": "text", "analyzer": "archive_analyzer" }, "create_date": {"type": "date", "format": "strict_date_optional_time||epoch_millis"}, "retention_period": {"type": "keyword"} } } }

设计说明:synonyms.txt文件需手动维护,存放于ES配置目录。首次启动时,系统自动调用RestHighLevelClient执行此DSL创建索引。全文检索API返回结果中,highlight字段会标记匹配关键词,前端PDF.js查看器可据此高亮显示,极大提升用户体验。

2.5 审计日志中间件:嵌入式日志采集与不可篡改存储

档案系统审计日志不是“锦上添花”,而是“底线要求”。本方案不依赖Logback日志文件,而是开发嵌入式审计中间件,所有关键业务操作(归档、借阅、销毁、权限变更)必须调用AuditLogService.record()。

核心逻辑在AuditLogAspect切面中实现:

@Around("@annotation(org.example.audit.AuditLog)") public Object recordAuditLog(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = joinPoint.proceed(); long duration = System.currentTimeMillis() - startTime; // 获取注解参数 AuditLog auditLog = ((MethodSignature) joinPoint.getSignature()).getMethod() .getAnnotation(AuditLog.class); // 构建日志实体 AuditLogEntity log = new AuditLogEntity(); log.setOperatorId(SecurityContext.getUserId()); // 从SecurityContext获取当前用户 log.setOperationType(auditLog.value()); log.setTargetId(getTargetId(joinPoint)); // 从参数中提取目标ID(如archiveId) log.setBeforeJson(getBeforeState(joinPoint)); // 序列化操作前状态 log.setAfterJson(getAfterState(result)); // 序列化操作后状态 log.setDuration(duration); log.setIpAddress(RequestContextHolder.getRequestAttributes() .getAttribute("ip", RequestAttributes.SCOPE_REQUEST).toString()); // 异步写入数据库(避免阻塞主流程) auditLogMapper.insertAsync(log); return result; }

关键设计点:@AuditLog注解标注在Service方法上,value()指定操作类型(如"ARCHIVE_CREATE")。getBeforeState()通过反射获取数据库查询结果,getAfterState()序列化返回值。异步插入使用MyBatis-Plus的insertAsync,底层为线程池+批量提交,保障性能。日志表audit_log的id为自增主键,created_time为DATETIME(3),精确到毫秒,满足审计时间戳要求。


3. 核心功能模块实现:从归档到借阅的闭环业务流

本章聚焦档案生命周期中最关键、也最容易在答辩中被深挖的三个闭环业务:电子文件归档、在线借阅审批、定期鉴定销毁。每个流程均体现“人-事-物-证”四要素可追溯,代码与配置均来自某跨平台系统实测版本。

3.1 电子文件归档流程:元数据强制校验与双格式存档

归档不是“上传文件”,而是“建立档案关系”。本流程强制用户填写file_code(档号)并实时校验格式合法性(正则:^[A-Z]{2,4}-\d{4}-[A-Z]{1,2}-[A-Z]{1,3}-\d{1,6}$),同时自动填充create_date(取文件属性)和archive_date(取当前系统时间)。

后端归档入口(ArchiveController.java):

@PostMapping("/archive") public Result archiveFile(@RequestBody ArchiveArchiveDTO dto) { // 1. 档号格式校验(前端校验+后端二次校验) if (!Pattern.matches("^[A-Z]{2,4}-\\d{4}-[A-Z]{1,2}-[A-Z]{1,3}-\\d{1,6}$", dto.getFileCode())) { return Result.fail("档号格式错误,请参考:全宗号-年度-保管期限-机构-件号"); } // 2. 查询是否存在相同档号(防止重复归档) if (archiveMapper.selectCount(new QueryWrapper<ArchiveInfo>().eq("file_code", dto.getFileCode())) > 0) { return Result.fail("档号已存在,请勿重复归档"); } // 3. 创建档案主记录(状态为"待归档") ArchiveInfo archive = new ArchiveInfo(); BeanUtils.copyProperties(dto, archive); archive.setStatus("pending_archive"); // 待归档状态 archive.setCreatedTime(LocalDateTime.now()); archive.setCreatedBy(SecurityContext.getUserId()); archiveMapper.insert(archive); // 4. 启动异步双格式转换与存档任务 asyncArchiveTaskService.convertAndStore(archive.getId(), dto.getOriginalFileId()); return Result.success("归档申请已提交,正在处理..."); }

设计说明:ArchiveArchiveDTO包含file_code、title、creator等必填元数据及originalFileId(指向MinIO中原始文件的UUID)。asyncArchiveTaskService.convertAndStore()是核心异步任务,内部调用Tesseract OCR(针对扫描件)、LibreOffice(针对Office文档)、ImageMagick(针对TIFF生成),并将生成的TIFF6.0和PDF/A-2b文件分别存入MinIO对应Bucket,最后更新archive_info表的digital_format、file_size、checksum字段,并将状态改为"已归档"。整个过程在事务外执行,失败时通过定时任务补偿。

3.2 在线借阅审批流程:多级审批链与电子签名嵌入

借阅不是“点一下就看”,而是“谁申请、谁审批、谁领取、谁归还”全链路闭环。本流程采用状态机驱动,状态流转图如下(文字描述):待申请→(申请人提交)→待部门负责人审批→(同意)→待档案管理员审核→(同意)→已批准→(申请人领取)→已借出→(申请人归还)→已归还

关键实现是审批环节的电子签名嵌入。当审批人点击“同意”时,系统调用SignatureService.generateSign()生成基于RSA2048的数字签名,并将签名值、签名时间、审批人ID、审批意见一同存入archive_borrow_approval表:

// SignatureService.java public String generateSign(Long userId, String approvalOpinion, Long borrowId) { try { // 1. 构造待签名字符串:borrowId + userId + approvalOpinion + timestamp String content = borrowId + "|" + userId + "|" + approvalOpinion + "|" + System.currentTimeMillis(); // 2. 使用私钥签名(私钥存于HSM或安全配置中心,此处简化为本地密钥库) PrivateKey privateKey = keyStoreService.getPrivateKey("archive-sign-key"); Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(content.getBytes(StandardCharsets.UTF_8)); byte[] signBytes = signature.sign(); // 3. Base64编码返回 return Base64.getEncoder().encodeToString(signBytes); } catch (Exception e) { throw new RuntimeException("签名生成失败", e); } }

关键参数说明:keyStoreService.getPrivateKey()从安全密钥库获取私钥,生产环境必须使用硬件安全模块(HSM)或云KMS服务。签名字符串content包含所有关键要素,确保不可抵赖。签名值存入数据库后,前端PDF.js查看器可在借阅单PDF上渲染电子签名印章,满足《电子签名法》要求。

3.3 定期鉴定销毁流程:基于保管期限的自动触发与人工复核

档案销毁是高风险操作,必须“系统预警+人工复核+领导终审”三重保险。本方案通过Quartz定时任务每日凌晨执行DestructionCheckJob:

@Component public class DestructionCheckJob implements Job { @Override public void execute(JobExecutionContext context) { // 1. 查询所有"已归档"且"保管期限"到期的档案(永久除外) LocalDateTime now = LocalDateTime.now(); List<ArchiveInfo> candidates = archiveMapper.selectList( new QueryWrapper<ArchiveInfo>() .eq("status", "已归档") .ne("retention_period", "永久") .apply("DATE_ADD(create_date, INTERVAL retention_period YEAR) <= ?", now.toLocalDate()) ); // 2. 对每个候选档案,生成鉴定报告(含元数据快照、内容摘要、关联借阅记录) for (ArchiveInfo archive : candidates) { DestructionReport report = generateReport(archive); destructionReportMapper.insert(report); // 存入鉴定报告表 // 3. 发送站内信通知档案管理员进行人工复核 noticeService.sendToRole("archive_admin", String.format("【鉴定提醒】档案 %s 已到保管期限,请复核是否销毁", archive.getFileCode())); } } }

设计说明:generateReport()方法会调用archive_operation_log表查询该档案所有历史操作日志,并调用content_service.extractSummary()提取OCR文本前200字作为内容摘要,确保复核人员掌握全貌。人工复核环节,管理员在Web界面勾选“同意销毁”并填写理由,系统记录操作日志;最终由分管领导在“销毁终审”菜单中确认,此时系统才真正执行DELETE操作,并将archive_info记录移入archive_destroyed历史表(含销毁时间、终审人、销毁方式),原始MinIO文件被DELETE指令永久擦除(非简单删除,调用MinIO的removeObject并清空回收站)。


4. 避坑指南:档案系统开发中5个最高频翻车点与解决方案

档案系统看似是“增删改查”,实则处处是合规雷区。以下5个问题,在某高校近三年毕设答辩中出现频率超70%,务必提前规避。

4.1 翻车点1:档号生成纯靠前端JS,后端无校验,导致数据污染

  • 现象:学生用JavaScript随机生成档号(如"ABC-"+new Date().getFullYear()+"-"+Math.random().toString(36).substr(2,5)),后端Controller直接接收并入库。答辩时导师导入100份测试数据,发现档号重复、格式混乱、无法按年度排序。
  • 原因:档号是档案的“身份证”,必须全局唯一、格式规范、可追溯来源。前端生成完全不可控,且绕过服务端业务规则。
  • 解决:档号生成必须由后端统一提供REST API(如POST /api/archive/generate-code?classification=RS&year=2024),API内部调用ArchiveCodeGenerator服务,该服务连接数据库序列(Sequence)或Redis原子计数器,确保并发安全,并严格校验classification参数是否在预设白名单内(如["RS","CW","JX"]代表人事、财务、教学)。

4.2 翻车点2:OCR识别文本直接存数据库,未做敏感词过滤与脱敏

  • 现象:系统集成Tesseract OCR后,将扫描件识别出的全部文本(含身份证号、手机号、银行卡号)原样存入content_text字段。答辩演示时,导师输入“身份证”关键词,瞬间暴露出大量个人隐私信息。
  • 原因:未理解《个人信息保护法》对档案系统的要求。OCR文本是原始数据,必须经过“识别-过滤-脱敏-存储”四步。
  • 解决:在OCR识别后、存库前,插入PrivacyFilterService:
    public String filterAndMask(String rawText) { // 1. 识别身份证号(15位或18位) rawText = rawText.replaceAll("(\\d{15}|\\d{17}[\\dxX])", "[ID_HIDDEN]"); // 2. 识别手机号 rawText = rawText.replaceAll("1[3-9]\\d{9}", "[PHONE_HIDDEN]"); // 3. 识别银行卡号(连续16-19位数字) rawText = rawText.replaceAll("\\d{16,19}", "[CARD_HIDDEN]"); return rawText; }

    注意:脱敏后的文本存入content_text,原始OCR结果(加密后)存入archive_ext_attr表,键为ocr_raw_encrypted,值为AES-256加密的Base64字符串,密钥由HSM管理。

4.3 翻车点3:权限控制只做菜单级,未控制数据行级,导致越权访问

  • 现象:学生实现“角色-菜单”权限,档案员登录后只能看到“档案管理”菜单,但通过浏览器F12修改请求URL中的archiveId=1001为archiveId=9999,竟能成功查看其他部门的绝密档案。
  • 原因:权限校验仅停留在Controller层的@PreAuthorize("hasRole('ARCHIVE_STAFF')"),未在Service层对archiveId参数做归属校验。
  • 解决:所有涉及archiveId的查询接口,必须在Service方法开头调用archiveSecurityService.checkAccess(userId, archiveId):
    public void checkAccess(Long userId, Long archiveId) { ArchiveInfo archive = archiveMapper.selectById(archiveId); if (archive == null) throw new BusinessException("档案不存在"); // 规则1:本人归档可访问 if (archive.getCreatedBy().equals(userId)) return; // 规则2:同部门归档可访问(需查用户部门) User user = userMapper.selectById(userId); if (user.getDeptId().equals(archive.getDeptId())) return; // 规则3:拥有"archive_all_read"权限 if (permissionService.hasPermission(userId, "archive:read:all")) return; throw new BusinessException("无权访问该档案"); }

4.4 翻车点4:PDF/A-2b转换仅调用命令行,未校验转换结果合规性

  • 现象:系统调用libreoffice --convert-to pdf ...生成PDF后,直接存入MinIO。答辩时导师用Adobe Acrobat Pro打开,提示“此PDF不符合PDF/A-2b标准”,导致“长期保存”功能被一票否决。
  • 原因:LibreOffice转换是“尽力而为”,不保证100%合规。必须用专业工具校验。
  • 解决:转换后立即调用pdfa-validator库校验:
    public boolean isValidPdfA2b(String pdfPath) { try (PDDocument doc = PDDocument.load(new File(pdfPath))) { PdfAConformanceLevel level = PdfAConformanceLevel.PDF_A_2B; PdfAValidator validator = new PdfAValidator(doc, level); ValidationResult result = validator.validate(); return result.isCompliant(); } catch (Exception e) { log.error("PDF/A-2b校验异常", e); return false; } }
    若校验失败,则回滚本次归档,记录错误日志,并通知管理员人工介入。

4.5 翻车点5:审计日志只记录“谁干了什么”,未记录“干得怎么样”

  • 现象:日志表有operator_id、operation_type、target_id,但缺少before_state和after_state。答辩时导师问:“请展示这份档案归档前后的元数据对比”,学生只能手动截图,无法提供系统级证据。
  • 原因:日志设计只关注“动作”,忽略“状态变化”,违背审计“可追溯、可还原”原则。
  • 解决:强制在AuditLogAspect中采集状态快照。getBeforeState()方法示例:
    private String getBeforeState(ProceedingJoinPoint joinPoint) { // 对于update操作,从数据库查原记录 if (joinPoint.getSignature().getName().contains("update")) { Object[] args = joinPoint.getArgs(); if (args.length > 0 && args[0] instanceof ArchiveInfo) { ArchiveInfo archive = (ArchiveInfo) args[0]; ArchiveInfo before = archiveMapper.selectById(archive.getId()); return JSON.toJSONString(before); // 使用FastJSON序列化 } } return "{}"; }
    after_state同理,在result返回后序列化。日志表字段before_json和after_json均为TEXT类型,支持JSON全文检索。

5. 答辩与验收:用三份清单让评委一眼认可你的系统“真可用”

答辩不是讲PPT,是交答卷。评委最关心的永远是:“这东西能不能真用?怎么证明它能用?”我带过的所有项目,只要在答辩前完成以下三份清单的自查与演示,通过率接近100%。这不是技巧,是工程习惯。

5.1 清单一:合规性检查清单(DA/T 46-2023逐条对标)

不要泛泛而谈“符合规范”,要拿出证据。打印一份表格,左边是标准条款,右边是你的系统实现位置与截图证据:

DA/T 46-2023 条款你的系统实现证据位置(截图编号)
5.2.1 档号必须唯一、可解析archive_info.file_code字段+后端正则校验+档号生成API图1:API文档截图;图2:数据库字段约束截图
5.3.4 归档时必须捕获形成日期、归档日期create_date、archive_date为NOT NULL字段,归档接口强制传入图3:归档DTO定义截图;图4:数据库建表SQL截图
6.2.2 电子档案必须采用PDF/A-2b或TIFF6.0格式MinIO双桶存储+digital_format字段值校验+PDF/A校验日志图5:MinIO桶列表截图;图6:archive_info表中digital_format值截图;图7:pdfa-validator成功日志截图
7.1.3 操作日志必须包含操作人、时间、IP、前后状态audit_log表结构+before_json/after_json字段+审计日志查询页面图8:audit_log表结构截图;图9:审计日志查询页面截图(含状态对比)

提示:答辩时,评委若质疑某一条,你立刻翻到对应截图页,指着说:“老师您看,这里就是我们落实该条款的地方。” 这比讲十分钟原理管用。

5.2 清单二:核心业务场景演示脚本(5分钟闭环演示)

评委没时间看你点100下。准备一个5分钟、无断点、闭环的演示脚本,覆盖“归档-借阅-销毁”全链路。脚本必须真实,所有数据用预置测试账号(如test_archivist/123456)操作,避免现场注册耗时。

演示脚本(计时练习):

  1. 0:00-0:45:以档案员身份登录,上传一份模拟“2024年人事合同”扫描件(PDF),填写档号RS-2024-RS-001-0001,点击归档。强调:“看,档号格式校验通过,系统自动生成归档日期,状态变为‘已归档’。”
  2. 0:46-2:10:切换至借阅人账号,搜索档号RS-2024-RS-001-0001,点击“申请借阅”,填写用途“续签合同”。强调:“看,申请已提交,状态进入‘待部门负责人审批’。”
  3. 2:11-3:30:切换至部门负责人账号,审批通过。强调:“看,审批人电子签名已嵌入,状态变为‘已批准’,借阅单PDF可下载。”
  4. 3:31-4:50:回到档案员账号,进入“鉴定销毁”菜单,筛选“2022年”到期档案,找到RS-2022-RS-001-0001,点击“生成鉴定报告”。强调:“看,系统自动生成含元数据、操作日志、内容摘要的PDF报告,供人工复核。”
  5. 4:51-5:00:点击“导出所有清单”,展示生成的《元数据检查清单》《权限配置清单》《审计日志摘要》三个PDF。收尾:“老师,这三份清单,就是我们系统‘真可用’的证据。”

血泪经验:演示前,用录屏软件(如OBS)完整录一遍,掐表。如果超5分10秒,删减旁白;如果卡在某个环节,立刻查日志定位。答辩当天,把录屏文件存在U盘里,万一现场网络故障,直接播放录屏。

5.3 清单三:部署与运维交接清单(让老师相信你能交付)

毕设不是玩具,是作品。评委潜意识会想:“这学生毕业后,单位真敢用吗?” 用这份清单打消疑虑。

部署清单(交付给指导老师):

  • 环境要求:Ubuntu 22.04 LTS / MySQL 8.0.33 / MinIO RELEASE.2023-03-22T19-28-41Z / Elasticsearch 8.11.3 / JDK 17
  • 一键部署脚本:deploy.sh(含MySQL初始化、MinIO桶创建、ES索引创建、后端Jar包启动、Nginx反向代理配置)
  • 配置文件模板:application-prod.yml(已脱敏,含数据库密码占位符${DB_PASSWORD})
  • 初始账号:admin/123456(超级管理员)、archivist/123456(档案员)、borrower/123456(借阅人)

运维清单(写在README.md末尾):

  • 日常备份:每天凌晨2点,mysqldump全库备份至/backup/mysql/,rclone同步至远程NAS
  • 日志轮转:Logback配置<timeBasedFileNamingAndTriggeringPolicy>,按天分割,保留30天
  • 健康检查:curl http://localhost:8080/actuator/health返回{"status":"UP"}即正常
  • 紧急恢复:若MinIO损坏,从/backup/minio/恢复桶数据;若ES索引损坏,从MySQL重新同步archive_info表

从那以后我每次带学生做毕设,都会在开题后第一周,强制他们用这个三份清单的框架,把所有功能点往里填。不是为了应付答辩,而是逼自己把“能跑”和“真可用”划清界限。档案系统,本质是信任系统——它存的不是纸,是责任。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询