☰
从零开发律师事务所案件管理系统:Spring Boot+Vue全栈实战
2026/10/10 6:48:19 网站建设 项目流程

1. 选题动机:为什么是律师事务所案件管理系统

毕业设计选题目,我见过太多人卡在同一个地方:要么选一个烂大街的商城系统,跟一百个人撞车;要么选一个过于偏门的技术课题,做完都不知道给谁用。如果你也在为这个发愁,我非常推荐把律师事务所案件管理系统当成一个值得认真考虑的方向。

先聊聊这套题目的核心价值。律所的业务场景天然复杂:一个客户可能同时委托多个案件,一个案件要经历接待、立案、审理、结案多个阶段,每个阶段涉及的文档、时间节点、承办律师都不一样。这种"一对多、多对多又带状态流转"的业务模型,恰好能把Spring Boot + Vue + MySQL这套技术栈的能力完整逼出来。答辩的时候你不需要跟老师说"我用了什么框架",你直接把案件状态变更、权限控制、文档管理这几个场景摆出来,老师一眼就能看出你的系统是真正在解决业务问题,而不是停留在增删改查的demo层面。

从技术层面看,这套题目覆盖的内容足够全面:后端有Spring Boot的REST API设计、Spring Security权限认证、MyBatis-Plus的持久层操作;前端有Vue的生命周期管理、组件通信、Axios请求拦截、路由守卫;数据库有ER建模、多表关联查询、索引优化。一套做完,你等于把Java全栈开发的主干知识全部过了一遍。这对后面找工作或者继续深造,都是实打实能写进简历里的东西。

适用人群上,我个人的判断是:如果你已经学过Spring Boot和Vue的基本用法,做过的项目不超过三个,想通过一个完整的、有业务深度的系统来提升项目经验,这个选题非常匹配。反过来,如果连Spring Boot的依赖注入、注解开发都没跑通过,我建议先花两周时间把一个简单的CRUD项目做熟,再回来碰这套系统,不然卡在环境问题上容易消磨信心。

还有一个实际层面的理由:这类题目通常不需要依赖外部硬件,不需要对接第三方服务,一台普通电脑就能跑完全部开发、测试和演示工作。这在毕业设计里是很大的优势——你不用担心实验设备预约不到,也不用担心某个外部接口突然挂掉导致答辩演示翻车。整个系统从数据库设计到前后端联调都是自己可控的,节奏完全掌握在自己手里。

2. 系统需求与模块拆解:先搭骨架再填肉

2.1 角色体系:四个角色一套权限

律所案件管理系统和普通的管理系统最大的不同在于角色划分不是随便切分的,而是基于律师行业的真实分工。

我把系统角色设计为四类:系统管理员、律师、律师助理、客户。每个角色的权限边界必须清晰,这不仅是业务需要,也是Spring Security权限设计的天然切入点。

  • 系统管理员:负责账号管理、系统配置、数据统计,不参与案件具体业务。
  • 律师:案件的核心负责人,可以新增案件、分配任务、上传文档、记录进度、结案归档。
  • 律师助理:辅助角色,可以录入客户信息、协助上传资料、跟进案件节点,但不能对案件做结案操作。
  • 客户:只能查看与自己相关的案件进度和公开文档,不能看到其他客户的任何信息。

这里有一个容易被忽略的设计细节:客户虽然是外部角色,但在系统里也要作为一个独立的用户类型存在。很多同学做系统时,客户只是数据库里的一张表,没有登录能力,结果答辩时被问到"客户怎么查看案件进度"就答不上来。我在设计时让客户也拥有登录账号,通过权限控制让客户只能查询到自己名下的案件,这样既符合真实业务,也让权限模块的复杂度上了一个台阶。

2.2 业务模块:五块功能覆盖律所核心流程

整个系统我拆成了五个核心模块,每个模块都能对应到律所里一个真实的工作场景。

第一是案件管理模块。这是系统的中心,包含案件的创建、指派律师、状态流转、结案归档。案件状态我设计了六个:待受理、办理中、已结案、已归档、已中止、已撤销。状态不是随意跳转的,比如"待受理"只能由律师或管理员变成"办理中","办理中"只能变成"已结案"或"已中止"。这个状态机的设计是后来写论文时非常出彩的一个章节,因为不是每个毕业设计都有明确的业务规则。

第二是客户管理模块。包括客户信息的增删改查、客户与案件的关联关系、客户联系记录。这个模块看似简单,但它是案件模块的数据基础——一个案件必须关联到一个有效的客户,不能凭空存在。

第三是文档管理模块。律所的案件卷宗是典型的多对多关系:一个案件有起诉状、证据材料、判决书等多个文档,一个文档也可能属于多个案件(比如一份证据同时用于两个关联案件)。我用了文档表和关联表来解决多对多映射,文档本身支持上传、下载、在线预览。

第四是日程与任务提醒模块。包括开庭时间、举证期限、任务分配提醒。这里有一个我认为很关键的业务逻辑:超过举证期限没上传材料,系统要在登录时弹出提醒。这类"基于时间的业务规则"比单纯的CRUD有意思得多,也是后面论文里体现业务深度的重点。

第五是统计报表模块。用图表展示案件数量、结案率、各律师办案量、案件类型分布。这部分用ECharts实现,后端提供聚合查询接口。技术难度不算高,但视觉效果好,答辩时放在功能演示的后半段容易给评委留下好印象。

2.3 非功能需求:权限安全、操作日志与数据备份

很多毕业设计容易忽略非功能需求,但恰恰是这部分能让论文查重率降下来,也能让系统在答辩时显得更完整。

权限安全方面,除了登录认证,还要做接口级别的权限控制。我采用的是RBAC模型:用户-角色-权限三级结构,在Spring Boot里通过注解控制接口的访问权限,前端再配合按钮级权限控制,实现了"后端强控制、前端弱展示"的双层保障。

操作日志方面,记录用户的登录、案件新增、状态变更、文档上传等关键操作。这个需求听起来不复杂,但实现时要考虑是同步写入还是异步写入。我在最初的版本里是同步写的,结果高并发下接口响应明显变慢,后来改成向日志表写入时做了简化,把耗时控制在可接受范围内,同时也演示了一个性能优化的完整思路。

数据备份则是给管理员设计的一个手动入口,可以一键导出数据库备份文件。这个功能虽然在答辩时可能不会被追问,但它体现的是你对真实运维场景的理解,属于典型的"加分项不是主修项"。

3. Spring Boot后端落地:权限与案件状态流转是重头戏

3.1 Spring Security + JWT:无状态认证的完整落地

律所管理系统对权限的要求比普通系统高,因为案件数据涉密。我选择了Spring Security + JWT的方案,原因很简单:前后端分离项目里,JWT无状态认证天然适配Vue发Ajax请求的场景,不需要后端维护Session,扩展性也好。

认证流程是这样的:用户在前端输入账号密码,后端接收后调用AuthenticationManager校验,成功后生成JWT返回前端。前端把Token存在本地,每次请求时在请求头里带上Authorization: Bearer xxx。后端通过过滤器拦截请求,解析Token拿到用户信息和角色权限。

代码层面,我会定义一个JwtAuthenticationFilter,继承OncePerRequestFilter,在doFilterInternal里解析Token并设置SecurityContext。这里有两个必踩的坑要提醒你:第一个是Token密钥不能硬编码在代码里,至少放在配置文件中;第二个是Token过期时间的设置,我刚开始设了一个小时,结果演示时中途退出好几次,后来改成8小时——但也不要设置太长,过期的刷新机制本身也可以作为论文的一个研究点。

// JWT 生成与解析的核心逻辑(简化版) public String generateToken(String username, List<String> roles) { Map<String, Object> claims = new HashMap<>(); claims.put("roles", roles); return Jwts.builder() .setClaims(claims) .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + 8 * 60 * 60 * 1000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); }

权限控制上,除了通过拦截器统一校验Token,我会在Controller的方法上用@PreAuthorize("hasRole('ADMIN')")这类注解做细粒度控制。打个比方,Token是身份证,登录时发给你;拦截器是小区门口的保安,确认你有证;@PreAuthorize则是楼栋门禁,进一步确认你能进哪一层。三层配合,数据安全才有保障。

3.2 REST API 设计与分层约定

后端分层我遵循了标准的Controller-Service-Mapper三层结构,但在约定上做了几点设计:

  • 所有接口统一以/api开头,版本号放在路径第二段,比如/api/v1/cases。
  • 返回结果统一封装为Result<T>结构,包含code、message、data三个字段。
  • 分页查询统一使用Page对象返回,前端根据total字段计算总页数。

统一返回结构这个点虽然简单,但直接影响前后端联调的效率。没有统一封装之前,有的接口返回{data: {...}},有的直接返回数组,前端处理逻辑各写一套,改起来容易出错。封装之后,Axios拦截器里对code != 200的情况统一弹出错误提示,逻辑清晰了很多。

案件列表查询的API就是一个典型例子:

@GetMapping("/cases/page") @PreAuthorize("hasAnyRole('ADMIN', 'LAWYER', 'ASSISTANT')") public Result<IPage<CaseVO>> pageCases(@RequestParam Integer page, @RequestParam Integer size, @RequestParam(required = false) String keyword, @RequestParam(required = false) Integer status) { IPage<CaseVO> result = caseService.queryCasePage(page, size, keyword, status); return Result.success(result); }

3.3 案件状态流转:把业务规则写进代码里

这个部分是整套系统里我认为最有业务价值的地方。案件状态不是随便改的,每一步都要有合法来源。

具体实现上,我设计了一个状态流转校验的Service层方法。每次状态变更时,方法内部先校验当前状态和目标状态是否在合法的转移路径上,不合法直接抛出业务异常;合法则更新案件状态,同时插入一条案件流转记录,方便后续追踪历史。

状态流转规则我放在一个Map里定义:

private static final Map<Integer, List<Integer>> ALLOWED_TRANSITIONS = new HashMap<>(); static { // 待受理 -> 办理中 / 已撤销 ALLOWED_TRANSITIONS.put(0, Arrays.asList(1, 5)); // 办理中 -> 已结案 / 已中止 ALLOWED_TRANSITIONS.put(1, Arrays.asList(2, 4)); // 已结案 -> 已归档 ALLOWED_TRANSITIONS.put(2, Collections.singletonList(3)); }

这种写法的好处是状态规则集中管理,改起来一目了然。论文里可以配上状态图,面试时也可以直接讲"我把状态机的校验逻辑抽离成了一个可配置的规则集合",比模糊地说"我做了案件状态修改功能"高级得多。

这里有一个现实业务中的问题需要提醒你:真实案件里,一个"已结案"的案件也可能因为再审等特殊情况重新被激活。因此我在状态表中预留了一个"重启案件"的接口,由管理员操作,算是给系统留了一个后门。别小看这个小设计,答辩时如果有老师问边界情况,你能提出解决方案,效果会好很多。

3.4 文件上传与下载的实现要点

文档管理模块涉及文件的存储方案选择。刚开始我想把文件放数据库里存BLOB,后来一想不对——数据库备份会越来越臃肿,查询也会变慢。最终我选择了本地文件存储,数据库只保存文件的元信息(文件名、存储路径、大小、上传时间、关联案件ID)。

上传接口用MultipartFile接收,保存时用UUID重命名文件,避免同名文件互相覆盖。下载接口从数据库查出文件路径,再用StreamingResponseBody流式输出。这里有一个实现上的细节:返回下载文件名时需要对中文文件名做URL编码,不然部分浏览器下载时文件名会乱码,演示起来很尴尬。

4. Vue前端实现:从布局到按钮控制的完整方案

4.1 Vue3 + Element Plus:为什么放弃Vue2

我选的是Vue3 + Element Plus + Vite的组合。坦白说,如果放在两年前,Vue2 + Element UI还是主流,但现在新项目没有再选旧版本的理由。Vue3的组合式API让代码组织更灵活,同一个功能模块的响应式状态、计算属性、方法可以聚在一起,对代码可读性帮助很大。

Vite的开发体验也比Webpack好很多,启动一个几十个页面的项目基本秒开。对毕业设计来说,开发期频繁改代码试效果,构建工具快一点,你的耐心就能多保留一点。

页面布局上我采用了典型的后台管理系统结构:左侧菜单、顶部导航、右侧内容区。菜单根据登录用户的角色动态生成,不同角色看到的菜单项不一样。首页Dashboard放案件总数、待办事项、最近案件动态,用统计卡片加ECharts图表组合。

4.2 动态路由和按钮级权限

权限控制在前端体现在两个地方。一是路由层面,通过路由守卫在跳转前判断用户角色是否拥有该路由的访问权限;二是按钮层面,同一个页面上不同角色能看到的操作按钮不同,比如"结案"按钮只有律师和管理员能看到,助理看不见。

这里我推荐用一个指令v-permission来实现按钮权限:

// 自定义指令:控制按钮显示权限 const permission = { mounted(el, binding) { const required = binding.value; const roles = store.state.user.roles; if (!roles.includes(required)) { el.parentNode && el.parentNode.removeChild(el); } } }

使用方式很简单:<el-button v-permission="'LAWYER'">结案</el-button>。指令会在DOM挂载时检查当前用户是否拥有指定角色,没有就直接把元素从DOM树里移除。相比用CSS隐藏,直接移除更安全,毕竟隐藏的按钮用户可以通过改样式看到,移除更彻底。

4.3 Axios封装与请求拦截

整个项目的前端请求我都统一通过一个封装的Request模块发送。这个模块做三件事:

  • 请求拦截器:从localStorage取出Token,添加到请求头。
  • 响应拦截器:统一判断返回状态,code !== 200时弹出错误提示。
  • Token过期处理:收到401状态码时,清除本地登录信息,跳转到登录页。

还有一个细节:文件上传接口的Content-Type不是application/json,而是multipart/form-data。如果在封装时全局统一设置了JSON头,上传文件就会报错。我的做法是对上传接口单独放行,不设置默认的Content-Type,让浏览器根据FormData自动生成。

4.4 案件列表页和文档上传页的设计

案件列表页是整个系统使用频率最高的页面,我做了三个增强功能:关键词搜索、状态筛选、分页刷新。列表展示案件编号、案件名称、客户姓名、办案律师、当前状态、最近更新时间,状态用Tag标签显示不同颜色,比如办理中是蓝色、已结案是绿色、已撤销是灰色。

文档上传页涉及前面提到的多对多关联。交互上我用了两步操作:先选择所属案件(支持搜索选择),再上传文件。上传后展示文件列表,每一项可以预览或下载。预览功能用了一个pdf的库来渲染PDF文件,图片直接通过<img>标签显示,其他格式则提示下载后查看。

5. MySQL数据库设计:从ER图到索引优化

5.1 核心表结构:客户、用户、案件三张主表

数据库是整套系统的地基。我总共设计了8张主表加1张关联表,这里说几组关键的表设计。

用户表和客户表分开设计,这是我认为比较正确的建模方式。用户表存登录账号和角色信息,客户表存客户详细资料和联系方式,两张表通过user_id关联。分开的原因很现实:一个客户可能对应多个联系人登录账号(比如公司法人和代理人都要登录查看案件),如果混在一张表里,账号逻辑会变得混乱。

案件表是业务中心,字段包括案件编号、案件名称、案件类型、所属客户ID、办案律师ID、助理ID、当前状态、立案日期、结案日期、案情描述。案件编号我用了业务编码规则:AL-年份-序列号,比如AL-2025-0012,这个编码在纸面档案和系统之间对照时非常有用。

5.2 客户与案件:一对多业务关系的落库设计

一个客户可以有多个案件,一个案件只属于一个客户,这是典型的一对多关系。实现上很简单,案件表加一个customer_id外键字段即可。但这个简单的设计背后有一个容易踩坑的地方:删除客户时,如果客户名下还有未结案的案件,直接删除会导致案件表出现悬空引用。

我的解决策略是:删除前先检查该客户是否有进行中的案件,若有则禁止删除,只允许做标记作废。这个逻辑写在Service层,算是给数据库加了一道业务上的"软保护"。数据库本身可以用外键约束,但外键在MyBatis-Plus的单表操作里用起来不顺手,所以我选择在业务层做校验。

5.3 案件与文档:多对多关系怎么拆

一个案件对应多个文档,一个文档关联多个案件,这种情况需要中间表。我建了一张case_document表,字段只有case_id和document_id,外加一个create_time记录关联时间。

使用中间表的好处是查询灵活。你可以通过案件查文档,也可以通过文档反向查被哪些案件使用了。索引设计上,case_id和document_id都要建普通索引,因为两个方向都可能有查询需求。

这里提前说一个性能方面的真实体会:先用MyBatis-Plus的分页插件做案件列表分页时,关联客户和律师的姓名我是在Java内存里循环补齐的。案件量小看不出来,测试数据加到几百条后,接口响应明显变慢。后来改成在SQL里直接用JOIN把关联表的姓名一次性查出来,用ResultMap映射到VO里,性能提升非常明显。这个优化经历可以直接写进论文的性能测试章节,很有说服力。

5.4 索引设计:别在状态字段上建索引

Lawyer齐聚的案件表会有一些查询条件:案件状态、案件类型、归属律师。这三个字段我都建了索引,但有一个踩坑的经历——给status字段建索引后,查询速度反而没有提升多少。

原因很简单:status字段的区分度太低。整个表里大部分案件集中在"办理中"这个状态,索引区分度差,MySQL优化器觉得直接全表扫描比走索引更快,索引就形同虚设了。正确的做法是只给区分度高的字段建索引,比如case_no(案件编号)、customer_id、lawyer_id。

对毕业设计而言,索引优化不需要做得太深,但一定要能讲出"为什么这里建索引""为什么那里不建索引"的道理。我会在论文里用EXPLAIN命令展示几个典型查询的执行计划,对比加索引前后的type和rows差异,这个素材答辩时非常好用。

6. 论文撰写、部署与答辩:最后一公里的实际操作

6.1 论文结构:从开题报告到系统测试

论文的写法跟开发代码是两回事,但可以互相支撑。我的论文结构大致是这样的:

  • 第一章绪论:研究背景(律所信息化转型)、国内外研究现状、研究内容与方法。
  • 第二章相关技术:Spring Boot、Vue、MySQL、MyBatis-Plus、JWT,每项技术写原理和在系统中的作用。
  • 第三章需求分析:功能需求、非功能需求、用例图、流程梳理。
  • 第四章系统设计:架构设计、模块设计、数据库设计(ER图和表结构说明)。
  • 第五章系统实现:每个核心模块的代码截图、关键代码说明、界面截图。
  • 第六章系统测试:功能测试用例表、性能测试说明、测试结论。

写论文时有几个技巧值得分享。需求分析部分的用例图和建议一定要自己画,不要直接从网上找图,导师和答辩评委对图片的专业性很敏感。数据库设计部分,每张表都要写清楚字段含义和设计理由,不要只贴建表语句。系统测试部分要有实际测试数据,比如输入了测试用例、执行了什么操作、得到什么结果、是否符合预期,表格化呈现会让论文显得扎实。

论文查重方面,说实话,系统代码部分查重是查不太到同质化内容的,因为每个系统的代码逻辑多少有差异。容易被查重命中的是技术介绍章节,这部分要尽量避免大段抄书,用"我用这个技术做了什么""它在我这个系统里解决什么问题"的写法,自然就降低了重复率。

6.2 部署文档:别人能按你的文档跑起来才算完

部署文档往往是被忽略的一环,但却是交付物的硬性要求。一份好的部署文档至少要包括:环境版本要求(JDK版本、Node版本、MySQL版本)、数据库初始化脚本说明、后端配置文件的修改点、前端环境变量的设置、打包命令和启动步骤。

我最开始写部署文档的时候,默认了读者会配置环境变量,走了很多弯路。后来按"从零开始照着做"的标准重写了一遍,把每一步可能出的错误都写在文档里,比如MySQL密码认证方式导致的连接失败、端口占用提示、前端跨域配置缺失等。这个文档后来给B同学按步骤走了一遍,全程没卡壳,说明文档才算是真的合格了。

部署环节有一个高频坑:前后端联调时的跨域问题。前端开发环境通过Vite配置代理转发接口请求到后端,生产环境则需要在后端配置跨域允许或者用Nginx做反向代理。我在部署文档里同时提供了开发环境的Vite代理配置方案和生产环境的Nginx配置示例,这样无论在什么场景下部署,都能找到参考。

6.3 答辩演示:功能演示顺序和常见追问准备

答辩演示的顺序比很多人想象的更重要。我建议按"业务串讲"的逻辑来演示,而不是罗列功能。

我的演示流程是:先以管理员身份登录,展示系统首页的数据总览和统计图表;接着创建一个客户、再创建一个案件,把案件指派给某个律师;切换到律师账号,看到刚分配的待办案件,上传一份文档;再演示状态流转直到结案归档;最后演示权限对比——用助理账号登录,看不到结案操作按钮。整个流程串下来,相当于讲了一个完整的业务故事,评委很容易跟上思路。

关于评委追问,最常被问到的几个问题包括:密码的安全性(我用了BCrypt加密并加盐)、状态流转的合法性校验是怎么做的、Token过期了怎么办、如何防止一个客户查看别人的案件。这些问题我在做设计和开发时都考虑过,真正答辩时即使全场只答上来几个核心问题,也比支支吾吾强很多。

个人体会最深的还是把这个系统完整做完、跑通、写成论文的这个过程。与其说是写了一个毕业设计,不如说是把一个真实的业务需求从抽象到落地走了一遍全流程。后面如果有人要做类似题目,或者想在这个系统上扩展,我建议可以增加模块:比如费用管理(律师费的报价和结算)、卷宗归档的电子签章功能。这些方向都能让系统往真实商用场景再靠一步,毕业论文的深度也会跟着上一个台阶。

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

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

立即咨询