直接给结论:这套“档案管理系统(SpringBoot后端+Vue前端+MySQL)”是目前最适合拿来练手、改造成简历项目、或者直接二次开发做内部系统的组合。前后端分离、权限模型清晰、代码结构规范,而且能做到“拿到就能跑”。这篇文章我会从项目结构、表设计、后端核心实现、前端页面逻辑、本地启动全流程到高频踩坑,完整拆一遍。无论你是刚学完SpringBoot和Vue想找个完整项目练手,还是公司突然让你一周内交付一个档案管理模块,这篇都能帮你省下大量摸索时间。
1. 项目整体设计与功能拆解
1.1 档案管理系统到底在管什么
先别急着看代码,梳理业务比写代码重要得多。所谓档案管理系统,本质上解决的是纸质档案和电子档案的生命周期管理问题。核心流程就这几条:档案录入、分类归档、检索调阅、借阅审批、归还记录。
这个系统核心功能我梳理下来主要分五块:
- 档案管理:档案的新增、编辑、删除、批量导入,支持按档案编号、标题、归档年度、密级等条件组合检索。
- 档案分类:树形结构,一般默认按“年度-部门-类别”三层来组织,也能自定义层级。
- 借阅管理:用户提交借阅申请,管理员审批,记录借出时间和归还时间,超期自动标红。
- 用户与权限:登录认证、角色区分(管理员/普通用户/审批人)、菜单权限和操作权限控制。
- 系统管理:用户管理、角色管理、操作日志、数据字典等基础功能。
这套系统覆盖了大多数中小型单位档案管理的全部刚需。做毕业设计也好,做公司内部系统也好,这个功能边界刚好合适——不会大到难以维护,也足够撑起一个完整的前后端分离项目。
1.2 技术选型为什么是SpringBoot+Vue+MySQL
技术选型是这个项目最值得聊的部分。先说SpringBoot,它的价值不在于“新”,而在于“省事”。内置Tomcat、自动配置、Starter机制,让开发者不用再经历SSM时代那一堆XML配置的折磨。你在application.yml里写几行配置就能连上数据库,加一个依赖就能处理文件上传,这对快速交付项目来说是实打实的效率提升。
前端用Vue,最大的优势是组件化思维和响应式数据绑定。档案列表、借阅表单、审批弹窗、统计图表,每个模块都是一个独立的.vue文件,改样式、调逻辑互不干扰。配合Element UI这类组件库,后台管理界面的开发速度能提升好几倍——你不需要手动写分页组件、日期选择器、树形控件,拿现成的改改就能用。
数据库选MySQL没有悬念。成熟的生态、免费开源、性能和稳定性对中小型系统完全够用。更重要的是网上资料极其丰富,遇到问题随便一搜就有答案。这套组合之所以成为Java后端开发的事实标准,就是因为它让一个人也能撑起一个完整项目的“全栈交付”。
1.3 前后端分离架构的请求流转过程
理解这个项目的运行机制,记住一条数据流转链路就够了:浏览器中的Vue页面 → Axios发送HTTP请求 → SpringBoot的Controller接收参数 → Service处理业务逻辑 → Mapper操作MySQL数据库 → 结果逐层返回 → Vue响应式更新页面。
在这条链路里,有两个细节值得关注。第一个是跨域问题:Vue开发服务器默认跑在8080端口,SpringBoot跑在8081或8888端口,两个端口之间互相访问就属于跨域。项目里通常会用CorsFilter全局配置或者网关转发来处理,后面我会给出具体配置。
第二个是前后端的约定:前端所有请求都会带上统一的RESTful风格路径,比如/api/archive/list、/api/borrow/apply,后端把统一返回结果封装成Result对象,包含code、message、data三个字段。前端在请求拦截器里统一判断code是否为200,不为200就弹出错误提示。这样做的好处是,不管后端接口有多少个,前端的错误处理逻辑只需要写一遍。
这里顺便说下,拿到源码后第一件事一定是先看Result这个类的结构和全局异常处理。这是整个前后端联调的基础,很多人项目跑不起来、登录后没反应,往往就是没理清这里的约定。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与本地启动全流程
2.1 JDK、Maven、Node版本选型
这个项目标着“可直接运行”,但很多人恰恰挂在最前面——环境版本不匹配。这里我直接给出验证过最稳的组合,照着配基本不会出问题:
| 工具 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 8 或 11 | SpringBoot 2.x系列最稳,JDK 8完全够用 |
| Maven | 3.6.x | 兼容性最好,3.8+也能用 |
| Node.js | 14.x 或 16.x | Vue CLI项目在低版本Node下依赖安装更顺利 |
| MySQL | 5.7 或 8.0 | 两者都行,8.0需要注意驱动和时区配置 |
| IDEA | 2021以上 | 自带Spring Initializr和Vue插件支持,开箱即用 |
有个最常见的坑先提醒一下:如果你下载的源码是SpringBoot 3.x版本,那必须配JDK 17以上,Maven也要3.8以上。SpringBoot 3是基于Jakarta命名空间的,很多老代码里javax.servlet要改成jakarta.servlet。所以启动报错时先别怀疑代码有问题,先确认版本匹配没。
另外一个容易忽略的是Maven镜像源。国内直接访问Maven中央仓库经常超时或下载特别慢,建议在settings.xml里配置阿里云镜像。配置方法后面实操部分会写清楚。
2.2 MySQL数据库初始化与常见报错处理
拿到源码后,数据库初始化是最容易出问题的一环。通常项目里会附带一个sql文件夹,里面是建库建表脚本。我建议按下面的顺序操作:
-
用Navicat或者MySQL命令行创建一个空数据库,数据库名称默认是
archive_system,字符集选utf8mb4,排序规则选utf8mb4_general_ci。千万别用utf8,否则存不了生僻字和emoji。 -
直接选择刚创建的数据库,然后运行项目里的
archive.sql脚本。运行完检查一下,正常情况下至少会生成用户表、角色表、档案信息表、借阅记录表、分类表、操作日志表这6张核心表,外加数据字典之类的辅助表。 -
用账号
admin、密码admin123(具体看SQL脚本中的INSERT语句)验证能否正常登录。
连接数据库最常报的错是Access denied for user 'root'@'localhost',这个是因为MySQL8默认用了caching_sha2_password加密方式,而项目用的驱动版本比较老。解决方式有两个:一是把pom.xml中MySQL驱动版本升到8.0.33以上;二是在MySQL命令行执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';。我一般直接用第一种,改驱动最省事,还不用动数据库配置。
还有一个必须注意的坑:确认一下application.yml里的数据库密码是不是用自己的本地密码替换了,很多人源码拿到手直接启动,报错后发现是密码没改。另外 MySQL 8.0 的连接URL里必须要带serverTimezone=Asia/Shanghai,否则日期字段会报错或出现时间差8小时的问题。
2.3 后端启动步骤(IDEA实操)
后端启动是整个流程里最核心的一步,我用IDEA演示一次完整的启动流程:
-
打开IDEA,选择
File -> Open,选中项目里的后端文件夹(一般是archive-backend或类似名字),等待Maven自动导入依赖。如果pom.xml没有自动同步,右键pom.xml选择Add as Maven Project。 -
检查Maven配置:
File -> Settings -> Maven,确认Maven home path指向本地Maven,User settings file指向settings.xml,Local repository指向本地仓库。国内用户强烈建议配置阿里云镜像,不然下载SpringBoot依赖能等到怀疑人生。配置内容放在settings.xml的mirrors节点里:
xml复制<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
-
找到主启动类,类名一般叫
Application或者ArchiveApplication,上面有@SpringBootApplication注解。右键点击,选择Run。看到控制台出现Started Application in xxx seconds就说明启动成功了。 -
后端默认端口一般配在
application.yml里的server.port,通常是8080或者8888。启动成功后浏览器直接访问http://localhost:端口号,如果配了Swagger,访问http://localhost:端口号/swagger-ui.html就能看到接口文档。
这里插一个我实际开发中总结的经验:启动时报Port already in use,说明端口被占了。Windows下用netstat -ano | findstr 端口号查出占用进程的PID,然后taskkill /F /PID 进程号杀掉。如果不想杀进程,也可以直接在配置文件里换个端口,一劳永逸。
2.4 前端启动步骤(环境配置与安装依赖)
前端项目通常是一个叫archive-web或frontend的文件夹,技术栈是Vue2 + Element UI + Axios。启动步骤:
-
确认Node.js和npm已安装,命令行执行
node -v和npm -v查看版本。如果没有安装,去Node.js官网下载LTS版本,一路下一步装完即可。 -
进入前端目录后执行依赖安装:
bash复制cd archive-web
npm install
这里特别强调一下:npm install在国内大概率会卡住或者报ETIMEDOUT错误,这是网络问题。解决方案是使用淘宝镜像源:
bash复制npm config set registry https://registry.npmmirror.com
设置完成后删掉node_modules文件夹(如果已经存在),重新执行npm install。如果之前安装了一半卡住,一定要先删干净再重装,否则会留下残缺的依赖。
- 依赖安装完成后启动开发服务器:
bash复制npm run dev
- 看到终端输出
Compiled successfully以及一个本地访问地址(默认是http://localhost:8080),浏览器打开,能看到登录页,输入管理员账号密码就能进入系统首页。
如果你的后端端口不是8080,那就需要改前端项目的接口地址配置。通常在前端src/utils/request.js或者.env.development文件里配了baseURL,改成http://localhost:你的后端端口就行。
还有一个小经验:Vue项目报Module not found: Error: Can't resolve 'element-ui'这类错误,说明依赖没装全,重新执行npm install。如果反复出问题,检查Node版本是否过高,Vue CLI项目在Node 17以上有时会出现OpenSSL相关的ERR_OSSL_EVP_UNSUPPORTED报错,解决办法是执行set NODE_OPTIONS=--openssl-legacy-provider再重新npm run dev。
3. 数据库表设计思路与核心SQL解读
3.1 核心表的字段设计与关联关系
数据库是整个系统的地基,表设计得好不好,直接决定后续编码是行云流水还是处处别扭。这个项目的表结构虽然不是特别复杂,但每张表之间的关系安排得很讲究。我把核心表整理一下:
第一张表是用户表(sys_user),字段包括用户ID、用户名、密码(BCrypt加密存储)、真实姓名、手机号、状态、创建时间。密码一定不能存明文,这是底线。SpringSecurity或者JWT认证时,比对的是加密后的密文。
第二张表是角色表(sys_role),字段包括角色ID、角色名称、角色编码、备注。档案系统一般需要“系统管理员”、“档案管理员”、“普通用户”三个角色,分别对应不同的权限边界。
第三张表是用户角色关联表,因为用户和角色是多对多关系,必须用中间表来解耦。后面加权限的时候同理,角色和菜单之间也需要一张中间表。
第四张表是档案信息表(archive_info),这是业务核心。字段包括档案ID、档案编号、档案标题、档案内容摘要、所属分类ID、密级(公开/内部/秘密/机密)、归档年度、档案状态(在库/借出/销毁)、上传文件路径、创建人、创建时间。档案编号一般有业务规则,比如“DA-20240216-001”,表示档案+日期+当日序号,方便检索和追溯。
第五张表是借阅记录表(borrow_record),字段包括记录ID、档案ID、借阅人ID、借阅时间、预计归还时间、实际归还时间、审批状态(待审批/已通过/已驳回)、审批人、审批意见。这张表是系统里最活跃的表,每次借阅申请都会往里面插记录。
最后是操作日志表(sys_log),记录谁在什么时间做了什么操作,为审计追溯提供依据。
核心表之间的关联关系,我用一句话概括:用户通过角色关联获取操作权限,档案通过分类关联找到归属,借阅记录同时关联用户和档案,形成完整的业务闭环。
3.2 为什么要用逻辑删除而不是物理删除
系统里删除档案记录时,默认是逻辑删除而不是直接DELETE FROM。这个设计是大多数正规管理系统的共识,原因就一个:档案数据具有不可随意变更的审计属性。
项目里通常会在表里加一个deleted字段,默认值为0。执行删除操作时变成了UPDATE archive_info SET deleted = 1 WHERE archive_id = ?。查询列表时所有SQL统一加上deleted = 0条件。这样做的直接好处是数据不会因为误操作彻底消失,而且能完整保留操作痕迹。
如果你的项目用了MyBatis-Plus,逻辑删除有专门的注解支持,直接在实体类的deleted字段上加@TableLogic即可,所有CRUD方法会自动带上逻辑删除条件,省去手动写条件。
3.3 档案检索SQL的编写细节
档案检索是系统的高频核心操作,也是查询条件最复杂的模块。往往是档案编号、标题、分类、密级、年度多个条件组合查询。这里的SQL有一个性能关键点:使用动态SQL拼接where条件,同时配合合适索引。
比如一个典型的组合查询:
sql复制SELECT archive_id, archive_no, title, category_id, secret_level, archive_year, status, create_time
FROM archive_info
WHERE deleted = 0
<if test="archiveNo != null and archiveNo != ''">
AND archive_no LIKE CONCAT('%', #{archiveNo}, '%')
</if>
<if test="title != null and title != ''">
AND title LIKE CONCAT('%', #{title}, '%')
</if>
<if test="categoryId != null">
AND category_id = #{categoryId}
</if>
<if test="archiveYear != null">
AND archive_year = #{archiveYear}
</if>
ORDER BY create_time DESC
LIMIT #{offset}, #{pageSize}
注意这里用LIMIT做物理分页,而不是一次性查出全表数据再在内存里分页。当数据量到几十万条以后,物理分页的差距是天壤之别,这是必须养成的开发习惯。
索引设计方面,archive_no建议建唯一索引,category_id建议建普通索引,(archive_year, status)建议建联合索引。索引不是越多越好,每个索引都会拖慢写入速度,重点覆盖高频查询条件就行。
4. 后端核心模块实现与关键技术点
4.1 登录认证与JWT令牌机制
几乎所有管理系统都逃不开登录认证这个模块。这个项目里用的一般是JWT(JSON Web Token)技术。它的原理可以这样理解:用户提交用户名密码后,后端验证通过,生成一个加密签名的字符串返回给前端。前端后续每次请求都在Header里带着这个字符串,后端验证签名的有效性和过期时间来判断登录状态。
JWT的好处是服务端不需要存Session,天然适合前后端分离架构和后端横向扩展。项目里通常用拦截器或AOP来统一校验Token:
java复制public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 放行登录接口
if (request.getRequestURI().contains("/login")) {
return true;
}
// 从Header中获取token
String token = request.getHeader("Authorization");
if (token == null || !JwtUtil.verify(token)) {
response.setStatus(401);
return false;
}
return true;
}
}
关于JWT我建议大家在实际使用中要注意两点。第一是密钥一定要放到配置文件中,不能写死在代码里,否则代码泄露等于所有Token都可伪造。第二是过期时间不宜太长,一般2小时比较合适,前端配合响应拦截器在Token过期时自动跳转到登录页。
4.2 档案管理接口设计与参数校验
后端接口设计遵循RESTful风格,我简单列举几个核心接口定义:
| 接口路径 | 请求方式 | 功能说明 |
|---|---|---|
| /api/archive/list | POST | 分页条件查询档案列表 |
| /api/archive/detail | GET | 查看档案详情 |
| /api/archive/add | POST | 新增档案 |
| /api/archive/update | PUT | 编辑档案 |
| /api/archive/delete | DELETE | 逻辑删除档案 |
| /api/archive/import | POST | 批量导入档案 |
| /api/borrow/apply | POST | 提交借阅申请 |
| /api/borrow/approve | POST | 审批借阅申请 |
| /api/borrow/list | POST | 查询我的借阅记录 |
接口的入参都需要经过校验,后端不能信任前端传来的任何数据。项目里用了JSR 303参数校验,比手动if判空要优雅得多。只需要在实体类的字段上加注解,比如@NotBlank(message = "档案标题不能为空"),在Controller方法的参数上加上@Validated就能生效。另外还需要自定义异常处理,用@RestControllerAdvice统一捕获校验异常,转换成友好的提示信息返回给前端。
4.3 文件上传与静态资源访问
档案系统经常需要上传扫描件、电子文档,所以文件上传模块是刚需。SpringBoot里做文件上传非常简单,核心代码思路就是接收MultipartFile对象,保存到服务器本地指定目录,然后把文件路径存入数据库。
这里有两个关键配置必须注意。第一个是上传文件的大小限制,SpringBoot默认只允许1MB,实际项目肯定不够。在application.yml里要调整:
yaml复制spring:
servlet:
multipart:
max-file-size: 50MB
max-request-size: 100MB
第二个是文件访问路径映射。把本地磁盘的某个目录映射成URL路径,这样前端能通过http://localhost:8080/files/xxx.pdf直接访问上传的文件。配置方法是写一个WebMvcConfigurer的实现,重写addResourceHandlers方法:
java复制@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**")
.addResourceHandler("file:" + uploadPath + "/");
}
这里有个我自己踩过的坑:文件上传成功后,返回给前端的前缀地址一定要用可访问的完整URL,而不是本地磁盘路径。否则前端拿到D:\upload\xxx.pdf根本显示不了。最好是把上传路径做成配置项,服务器部署时改一处就行。
4.4 全局异常处理与统一返回结果
一个规范的项目,后端所有接口的返回值结构一定是一致的。这个项目里封装了一个统一的返回结果类,一般包含以下几个字段:
- code:状态码,200表示成功,500表示服务器错误,401表示未登录或Token失效
- message:提示信息
- data:业务数据,可以是对象、列表或者分页结果
有了统一返回结构,配合全局异常处理器,后端永远不会直接把异常堆栈抛给前端。全局异常处理器的做法是写一个类,加上@RestControllerAdvice注解,里面定义各类异常的处理方法。比如参数校验异常返回400和具体错误,业务异常返回500和自定义错误信息,兜底异常返回“系统繁忙,请稍后重试”。
这套机制的价值在日常开发中很实在:代码里只需要写业务逻辑,异常处理交给全局处理器统一兜底,前端拿到的永远是能直接提示给用户的信息。
5. 前端核心模块实现与页面交互逻辑
5.1 动态路由与权限控制
前端做权限控制一直是很多人头疼的问题,这个项目里用的是“动态路由”方案,思路是这样的:用户登录成功后,后端根据用户角色返回该角色可访问的菜单列表,前端拿到菜单列表后动态注册路由,同时根据菜单渲染侧边栏。
这样做的好处很明显:不同角色登录后看到的菜单不一样,操作按钮的显隐也不一样。菜单数据一般包含图标、路由路径、组件路径、父级ID等字段。前端根据组件路径去映射对应的.vue组件。
这里有一个关键的实现细节:组件映射需要用到require.context或者import.meta.glob批量引入,直接把views目录下的所有组件一次性打包进路由配置里,否则动态路由无法找到对应组件。Vue2项目的标准写法:
javascript复制const modules = require.context('../views', true, /\.vue$/)
const componentMap = {}
modules.keys().forEach(key => {
const name = key.replace(/^\.\/(.*)\.vue$/, '$1')
componentMap[name] = modules(key).default
})
路由守卫也必不可少,在全局前置守卫里判断用户是否已登录,未登录一律跳转到登录页:
javascript复制router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if (!token && to.path !== '/login') {
next('/login')
} else {
next()
}
})
5.2 核心业务页面功能拆解
登录页没什么好说的,一个是调接口拿Token,一个是把用户信息和菜单存到localStorage和Vuex。真正核心的是档案管理列表页和借阅申请页面。
档案管理列表页是最典型的CRUD页面,核心组件包括:搜索栏(档案编号、标题、分类下拉、密级下拉)、数据表格(展示列表数据)、分页组件、新增/编辑弹窗。列表请求的过程是这样的:页面加载时执行fetchList()方法,把查询条件和分页参数通过POST /api/archive/list发给后端,后端返回分页结果后,前端把data.records赋值给表格数据源,data.total赋值给分页组件。每次点击搜索按钮,重置页码为1并重新发起请求。
借阅申请页的交互逻辑稍微复杂一点。用户点击“申请借阅”按钮,弹出弹窗,选择需要的档案、填写预计归还时间、填写借阅事由,提交后生成待审批记录。在“我的借阅”列表里可以看到当前记录的状态。如果是管理员账号,还能看到所有待审批的记录,点“通过”或“驳回”按钮后,修改审批状态并填写审批意见。
5.3 Axios封装与接口调用规范
前端所有接口请求都通过Axios发起,但项目里通常不会每个页面都直接用axios.get这种零散写法,而是统一封装好。在utils/request.js里创建一个Axios实例,配置基础URL和超时时间:
javascript复制const request = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 10000
})
同时配置请求拦截器和响应拦截器。请求拦截器负责在每次请求的Header里加上Token,响应拦截器统一处理后端返回的结果,遇到code !== 200就弹出提示,遇到HTTP 401就清空登录信息并跳转到登录页。
具体接口的调用再单独封装成模块。比如api/archive.js文件里导出所有档案相关接口:
javascript复制export function getArchiveList(data) {
return request({
url: '/api/archive/list',
method: 'post',
data
})
}
export function addArchive(data) {
return request({
url: '/api/archive/add',
method: 'post',
data
})
}
页面里调用时只要import { getArchiveList } from '@/api/archive',用await拿到结果。这种分层写法的好处是接口路径改动时只需要改一个文件,不用全项目搜索替换。
6. 常见问题与排查技巧实录
6.1 数据库相关的坑
-
启动时报
Unknown database 'archive_system':先确认创建数据库了没有。很多人直接运行SQL脚本,但脚本里没有建库语句,需要先手动建库再运行脚本。 -
报
Access denied for user 'root'@'localhost' (using password: YES):密码错了或者连接配置里的密码没改成自己的。去application.yml里核对密码。 -
中文乱码:数据库连接URL要加
characterEncoding=utf8,建表时如果是老的latin1字符集,需要转成utf8mb4。已经乱码的数据可以执行ALTER TABLE 表名 CONVERT TO CHARACTER SET utf8mb4。 -
MySQL 8.0驱动报时区错误:连接URL中加
serverTimezone=Asia/Shanghai,并确认驱动版本在8.0以上。
6.2 后端启动的坑
-
端口被占用:控制台报
Web server failed to start. Port 8080 was already in use。改application.yml里的server.port端口,或者杀掉占用进程。 -
Maven依赖下载不成功:pom.xml下面红色波浪线或者报
Cannot resolve org.springframework.boot:spring-boot-starter-web之类的错。检查Maven仓库配置和镜像源,删掉本地仓库对应目录重新下载。 -
启动成功但接口访问报404:注意访问路径要和Controller里的
@RequestMapping路径匹配。另外如果是打成jar包运行的,注意maven打包时没有包含src/main/resources下的文件,导致配置文件缺失。 -
SpringBoot版本太高导致JDK不兼容:如果源码用的SpringBoot 3.x而本地是JDK 8,启动会直接报
UnsupportedClassVersionError。要么换JDK 17,要么把SpringBoot降级到2.7.x并修改javax到jakarta。
6.3 前端启动的坑
-
npm install报错:八成是网络问题。配置淘宝镜像后重试,如果还是不行,把node_modules删除干净重新安装。Node版本太新的情况可以指定Node 16再试。 -
npm run dev启动后白屏:先看浏览器控制台,通常是路由配置问题或者接口地址配置错误。登录页都出不来的话,检查入口文件main.js里是否正确挂载了App组件,路由模式是history还是hash。history模式在开发环境没问题,部署到服务器时需要额外配置nginx回调。 -
接口请求返回CORS错误:浏览器控制台报
No 'Access-Control-Allow-Origin' header is present。解决方式:后端写一个CORS配置类,或者使用代理方式,在vue.config.js里配置devServer的proxy转发。
javascript复制// vue.config.js
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
- 前端登录成功后刷新页面菜单丢失:这个非常常见。原因是你把动态菜单存在了Vuex里,而Vuex的数据在浏览器刷新后会清空。解决方式是在路由守卫里做了一个拦截:刷新时发现Vuex中没有菜单数据,就重新调用
getUserInfo接口拉取菜单,再重新动态注册路由。
6.4 文件上传失败的排查思路
文件上传失败时,先看后端日志。如果是FileSizeLimitExceededException,就是文件大小超过限制,调大配置即可。如果是Failed to parse multipart servlet request,一般也是大小限制问题。如果上传成功但访问404,检查资源映射路径是否配置正确,上传目录是否存在并且有写入权限。
还有一个细节是前端上传组件的请求头格式,用Element UI的el-upload组件时,如果默认的请求方式不符合后端接收格式,需要手动指定headers,确保请求头里有Content-Type: multipart/form-data。
7. 项目二次开发的一点个人心得
这个项目跑通以后,如果打算把它改成自己的简历项目或者在公司真正落地,有几个方向我觉得值得投入时间。第一是给档案增加OCR识别功能,拍照扫描的纸质档案自动识别关键信息并填充录入表单,这个功能很能体现技术亮点。第二是加一个统计分析模块,按归档年度、密级、部门维度展示柱状图、饼图,用ECharts就能实现,面试讲项目时可视化模块永远是最容易被记住的。第三是引入Redis做在线用户管理和热点档案缓存,给老旧的档案列表接口加上缓存以后,响应速度提升是非常直观的。
我在实际交付项目过程中还有一个体会:拿到的源码里如果带着完整的SQL脚本和接口文档,这个项目跨过“能跑”到“改得动”的周期会大大缩短。这套系统的代码组织方式适合作为起步基座,但真正用起来后你会发现很多东西要按业务场景重构。比如档案分类可能要从两级改成四级,借阅流程可能要加两级审批,密级权限要细化到字段级别。这些改动在清晰的表结构和规范的分层代码面前,都是工作量问题,而不是能不能做的问题。
最后说一个实在的:无论多好的源码,只看不敲等于零。给前端页面加一个字段、给后端加一个导出接口、给数据库加一张表,亲手走完这三个改动,这套技术栈就算是真正上手了。踩过第一次坑以后,后面就顺了。
