1. 项目概述
作为一名长期从事法律科技系统开发的工程师,我深知律师事务所案件管理的痛点。传统纸质档案管理方式存在易丢失、查询困难、协作效率低等问题。去年为某中型律所开发的这套SpringBoot+Vue案件管理系统,经过半年实际运行验证,成功将案件处理效率提升了40%,客户满意度显著提高。
这个系统采用前后端分离架构,后端基于SpringBoot框架实现RESTful API,前端使用Vue.js构建动态交互界面,数据库采用MySQL存储案件相关数据。系统最核心的价值在于实现了案件全生命周期的数字化管理,从立案到结案的所有流程都能在线跟踪处理。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术选型解析
后端选择SpringBoot框架主要基于以下考量:
- 快速开发:SpringBoot的自动配置和起步依赖大幅减少了XML配置
- 生态丰富:Spring生态圈提供了完善的安全、数据库、缓存等解决方案
- 易于维护:约定优于配置的原则使项目结构清晰
- 性能稳定:内嵌Tomcat容器,经过大量生产环境验证
前端选用Vue.js+ElementUI组合是因为:
- 渐进式框架:可按需引入功能,学习曲线平缓
- 组件化开发:案件管理中的表单、表格等可高度复用
- 响应式设计:完美适配律所常见的PC端办公场景
- ElementUI:提供丰富的专业级UI组件,特别适合管理系统开发
数据库采用MySQL 8.0版本,主要考虑因素:
- ACID事务支持:确保案件数据操作的原子性和一致性
- JSON字段支持:便于存储案件的非结构化数据
- 完善的权限控制:与系统RBAC模型完美契合
- 成熟的分布式方案:为后续扩展预留空间
2.2 核心功能模块
系统主要包含以下功能模块:
- 用户权限管理:基于RBAC模型的精细化权限控制
- 案件信息管理:案件CRUD及高级检索功能
- 进度跟踪系统:可视化展示案件处理流程
- 文书生成工具:自动生成常用法律文书模板
- 数据统计看板:多维度的案件数据分析
特别值得一提的是进度跟踪模块,我们设计了状态机机制来管理案件生命周期:
java复制// 案件状态枚举定义
public enum CaseStatus {
DRAFT("草稿"),
SUBMITTED("已提交"),
UNDER_REVIEW("审核中"),
IN_PROGRESS("进行中"),
CLOSED("已结案"),
ARCHIVED("已归档");
// 状态转换规则
private static final Map<CaseStatus, Set<CaseStatus>> transitions = Map.of(
DRAFT, Set.of(SUBMITTED),
SUBMITTED, Set.of(UNDER_REVIEW, DRAFT),
UNDER_REVIEW, Set.of(IN_PROGRESS, SUBMITTED),
IN_PROGRESS, Set.of(CLOSED),
CLOSED, Set.of(ARCHIVED)
);
public static boolean isValidTransition(CaseStatus from, CaseStatus to) {
return transitions.getOrDefault(from, Set.of()).contains(to);
}
}
3. 数据库设计与优化
3.1 核心表结构实现
案件信息表的设计采用了垂直分表策略,将核心字段与扩展字段分离:
sql复制CREATE TABLE `legal_case` (
`case_id` bigint NOT NULL AUTO_INCREMENT,
`case_title` varchar(100) COLLATE utf8mb4_bin NOT NULL,
`case_type` enum('CIVIL','CRIMINAL','ADMINISTRATIVE','OTHER') NOT NULL,
`client_id` bigint NOT NULL,
`main_lawyer_id` bigint NOT NULL,
`assistant_lawyer_ids` json DEFAULT NULL,
`case_status` enum('DRAFT','SUBMITTED','UNDER_REVIEW','IN_PROGRESS','CLOSED','ARCHIVED') NOT NULL DEFAULT 'DRAFT',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`expected_end_date` date DEFAULT NULL,
`actual_end_date` date DEFAULT NULL,
PRIMARY KEY (`case_id`),
KEY `idx_client` (`client_id`),
KEY `idx_lawyer` (`main_lawyer_id`),
KEY `idx_status` (`case_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
关键设计要点:
- 使用ENUM类型限定案件状态和类型,确保数据一致性
- JSON字段存储协办律师ID数组,避免多对多关联表
- 自动维护的create_time和update_time字段
- 针对常用查询条件建立复合索引
3.2 查询性能优化实践
针对法律案件常见的复杂查询场景,我们总结了以下优化方案:
- 分页查询优化:
sql复制-- 反例:使用LIMIT偏移量大时性能差
SELECT * FROM legal_case ORDER BY create_time DESC LIMIT 10000, 20;
-- 正例:使用索引覆盖+延迟关联
SELECT * FROM legal_case
WHERE case_id >= (SELECT case_id FROM legal_case ORDER BY create_time DESC LIMIT 10000, 1)
ORDER BY create_time DESC LIMIT 20;
- 统计查询优化:
sql复制-- 创建物化视图提高统计性能
CREATE TABLE case_stats_mv (
lawyer_id BIGINT PRIMARY KEY,
active_case_count INT NOT NULL,
overdue_case_count INT NOT NULL,
last_updated TIMESTAMP NOT NULL
);
-- 使用事件调度定期刷新
CREATE EVENT refresh_case_stats
ON SCHEDULE EVERY 1 HOUR
DO
BEGIN
REPLACE INTO case_stats_mv
SELECT
lawyer_id,
SUM(CASE WHEN case_status = 'IN_PROGRESS' THEN 1 ELSE 0 END),
SUM(CASE WHEN case_status = 'IN_PROGRESS' AND expected_end_date < CURDATE() THEN 1 ELSE 0 END),
NOW()
FROM legal_case
GROUP BY lawyer_id;
END;
4. 前后端关键实现
4.1 安全认证方案
系统采用JWT+RBAC的认证授权方案,关键实现如下:
- 自定义Security配置:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/case/**").hasAnyRole("LAWYER", "ADMIN")
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public JwtFilter jwtFilter() {
return new JwtFilter();
}
}
- 权限注解控制:
java复制@PreAuthorize("hasRole('LAWYER') and @caseAccessControl.canAccessCase(authentication, #caseId)")
@GetMapping("/api/case/{caseId}")
public ResponseEntity<CaseDetailVO> getCaseDetail(@PathVariable Long caseId) {
// 业务逻辑
}
4.2 文件管理实现
法律案件通常涉及大量文档,我们的解决方案是:
- 文件元数据设计:
sql复制CREATE TABLE `case_document` (
`doc_id` bigint NOT NULL AUTO_INCREMENT,
`case_id` bigint NOT NULL,
`file_name` varchar(255) NOT NULL,
`file_type` varchar(50) NOT NULL,
`file_size` bigint NOT NULL,
`storage_path` varchar(512) NOT NULL,
`uploader_id` bigint NOT NULL,
`upload_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`description` text,
PRIMARY KEY (`doc_id`),
KEY `idx_case` (`case_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- 文件上传接口:
java复制@PostMapping("/api/case/{caseId}/documents")
public ResponseEntity<DocumentVO> uploadDocument(
@PathVariable Long caseId,
@RequestParam MultipartFile file,
@RequestParam(required = false) String description,
@CurrentUser UserPrincipal user) {
// 验证案件权限
Case legalCase = caseService.validateCaseAccess(caseId, user.getId());
// 验证文件类型
String fileType = FilenameUtils.getExtension(file.getOriginalFilename());
if (!ALLOWED_FILE_TYPES.contains(fileType.toLowerCase())) {
throw new InvalidFileTypeException("不支持的文件类型");
}
// 存储文件
String storagePath = fileStorageService.store(file);
// 保存元数据
CaseDocument doc = new CaseDocument();
doc.setCaseId(caseId);
doc.setFileName(file.getOriginalFilename());
doc.setFileType(fileType);
doc.setFileSize(file.getSize());
doc.setStoragePath(storagePath);
doc.setUploaderId(user.getId());
doc.setDescription(description);
documentRepository.save(doc);
return ResponseEntity.ok(mapper.toVO(doc));
}
5. 部署与运维实践
5.1 生产环境部署方案
推荐使用Docker Compose进行容器化部署:
yaml复制version: '3.8'
services:
backend:
image: legal-case-backend:1.0.0
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_URL=jdbc:mysql://db:3306/legal_case
- DB_USER=case_admin
- DB_PASSWORD=${DB_PASSWORD}
depends_on:
- db
- redis
frontend:
image: legal-case-frontend:1.0.0
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "80:80"
depends_on:
- backend
db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MYSQL_DATABASE=legal_case
- MYSQL_USER=case_admin
- MYSQL_PASSWORD=${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
command: --default-authentication-plugin=mysql_native_password
redis:
image: redis:6-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
db_data:
redis_data:
5.2 性能监控配置
建议配置以下监控指标:
- Spring Boot Actuator配置:
properties复制# application-prod.properties
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.metrics.export.prometheus.enabled=true
management.metrics.tags.application=legal-case-system
- Grafana监控看板关键指标:
- 系统吞吐量:http_server_requests_seconds_count
- 平均响应时间:http_server_requests_seconds_sum / http_server_requests_seconds_count
- JVM内存使用:jvm_memory_used_bytes
- 数据库连接池:hikaricp_connections_active
- 缓存命中率:redis_stats_keyspace_hits / (redis_stats_keyspace_hits + redis_stats_keyspace_misses)
6. 常见问题排查
6.1 典型问题解决方案
- 文件上传失败问题:
- 现象:前端报413 Request Entity Too Large
- 解决方案:
properties复制# 调整Spring Boot配置
spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB
# Nginx配置
client_max_body_size 50M;
- 案件状态转换异常:
- 检查点:
- 确认用户有操作权限
- 验证状态转换是否符合预定义规则
- 检查关联文档是否已全部上传
- 验证必填字段是否完整
- 性能下降处理流程:
mermaid复制graph TD
A[收到性能报警] --> B[检查CPU/内存]
B --> C{资源不足?}
C -->|是| D[扩容/优化]
C -->|否| E[检查慢查询]
E --> F[分析SQL执行计划]
F --> G[添加索引/重写SQL]
G --> H[验证改进效果]
6.2 系统扩展建议
- 后续可扩展功能:
- 电子签名集成:对接权威CA机构实现文书在线签署
- 语音转文字:庭审录音自动转文字归档
- 智能提醒:基于NLP自动识别案件关键时间节点
- 知识图谱:构建法律条文与案例关联网络
- 性能扩展方案:
- 数据库读写分离
- 引入Elasticsearch处理全文检索
- 使用Redis集群缓存热点数据
- 前端静态资源CDN加速
这套系统在实际运行中表现稳定,特别是在处理200+并发案件管理时仍能保持流畅响应。最大的收获是深刻理解了法律业务流程与IT系统的融合要点,比如案件状态机的严谨性要求远高于普通业务系统。
