作为一名长期从事法律科技系统开发的工程师,我深知律师事务所日常案件管理中的痛点。传统律所往往依赖Excel表格和纸质档案来管理案件,这种方式不仅效率低下,还容易造成数据丢失和版本混乱。最近我开发了一套基于Spring Boot和Vue.js的律师事务所案件管理系统,经过三个月的实际使用测试,系统稳定性和实用性都得到了验证。
这套系统采用前后端分离架构,后端使用Spring Boot 2.7提供RESTful API接口,前端采用Vue 3组合式API开发,数据库选用MySQL 8.0。系统实现了案件全生命周期管理、客户信息维护、律师任务分配、文书自动生成等核心功能。特别值得一提的是,我们针对法律行业的特殊需求,设计了严谨的权限控制体系和数据加密机制,确保敏感案件信息的安全。
选择Spring Boot作为后端框架主要基于以下考虑:
前端选择Vue.js 3.x版本是因为:
数据库选用MySQL 8.0主要看中:
系统采用经典的三层架构设计:
code复制┌───────────────────────────────────────┐
│ 表现层 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Vue 3 │ │ Element UI │ │
│ └─────────────┘ └─────────────┘ │
└───────────────────────────────────────┘
┌───────────────────────────────────────┐
│ 业务逻辑层 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Spring Boot │ │ MyBatis │ │
│ └─────────────┘ └─────────────┘ │
└───────────────────────────────────────┘
┌───────────────────────────────────────┐
│ 数据持久层 │
│ ┌─────────────────────────────────┐ │
│ │ MySQL 8.0 │ │
│ └─────────────────────────────────┘ │
└───────────────────────────────────────┘
前后端通过RESTful API交互,采用JWT进行身份认证。考虑到法律数据的敏感性,我们在传输层全部使用HTTPS协议,并对敏感字段进行AES加密存储。
案件管理是系统的核心功能,我们设计了状态机来管理案件生命周期:
java复制// 案件状态枚举定义
public enum CaseStatus {
DRAFT("草稿", 0),
IN_PROGRESS("进行中", 1),
PENDING_REVIEW("待审核", 2),
COMPLETED("已结案", 3),
ARCHIVED("已归档", 4);
private final String desc;
private final int code;
// 构造方法等...
}
状态转换通过Spring StateMachine实现:
java复制@Configuration
@EnableStateMachineFactory
public class CaseStateMachineConfig extends EnumStateMachineConfigurerAdapter<CaseStatus, CaseEvent> {
@Override
public void configure(StateMachineStateConfigurer<CaseStatus, CaseEvent> states)
throws Exception {
states
.withStates()
.initial(CaseStatus.DRAFT)
.states(EnumSet.allOf(CaseStatus.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<CaseStatus, CaseEvent> transitions)
throws Exception {
transitions
.withExternal()
.source(CaseStatus.DRAFT).target(CaseStatus.IN_PROGRESS)
.event(CaseEvent.SUBMIT)
.and()
.withExternal()
.source(CaseStatus.IN_PROGRESS).target(CaseStatus.PENDING_REVIEW)
.event(CaseEvent.COMPLETE)
// 其他状态转换规则...
}
}
客户信息表设计考虑了法律行业的特殊需求:
sql复制CREATE TABLE `client` (
`client_id` bigint NOT NULL AUTO_INCREMENT,
`client_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`client_type` tinyint NOT NULL COMMENT '0-个人 1-企业',
`id_type` tinyint DEFAULT NULL COMMENT '证件类型',
`id_number` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '证件号码',
`contact_phone` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`contact_email` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`industry` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`address` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`remark` text COLLATE utf8mb4_unicode_ci,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`client_id`),
UNIQUE KEY `idx_id_number` (`id_number`),
KEY `idx_client_name` (`client_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
注意:身份证号等敏感信息在存储时需要使用AES加密,加密密钥应当通过密钥管理系统管理,不能硬编码在程序中。
任务分配算法考虑了律师的专业领域和工作负荷:
java复制public class TaskDispatcher {
private final LawyerService lawyerService;
@Async
public void dispatchCase(CaseInfo caseInfo) {
// 1. 根据案件类型筛选专业对口的律师
List<Lawyer> candidates = lawyerService.findBySpecialty(
caseInfo.getCaseType());
// 2. 根据当前工作量排序
candidates.sort(Comparator.comparingInt(
lawyer -> lawyer.getCurrentWorkload()));
// 3. 分配任务
if (!candidates.isEmpty()) {
Lawyer assignedLawyer = candidates.get(0);
createTask(caseInfo, assignedLawyer);
// 发送通知
notifyLawyer(assignedLawyer, caseInfo);
}
}
private void createTask(CaseInfo caseInfo, Lawyer lawyer) {
Task task = new Task();
task.setCaseId(caseInfo.getCaseId());
task.setLawyerId(lawyer.getLawyerId());
task.setTaskName("处理案件: " + caseInfo.getCaseTitle());
task.setDeadline(calculateDeadline(caseInfo));
// 其他字段设置...
taskRepository.save(task);
}
}
系统采用基于角色的访问控制(RBAC)模型:
code复制┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐
│ 用户 │───▶│ 角色 │───▶│ 权限 │───▶│ 资源/操作 │
└──────────┘ └──────────┘ └──────────┘ └────────────┘
数据库表结构设计:
sql复制CREATE TABLE `sys_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`real_name` varchar(50) DEFAULT NULL,
`phone` varchar(20) DEFAULT NULL,
`email` varchar(50) DEFAULT NULL,
`status` tinyint DEFAULT '1' COMMENT '0-禁用 1-启用',
PRIMARY KEY (`user_id`),
UNIQUE KEY `idx_username` (`username`)
);
CREATE TABLE `sys_role` (
`role_id` bigint NOT NULL AUTO_INCREMENT,
`role_name` varchar(50) NOT NULL,
`role_code` varchar(50) NOT NULL,
`description` varchar(100) DEFAULT NULL,
PRIMARY KEY (`role_id`),
UNIQUE KEY `idx_role_code` (`role_code`)
);
CREATE TABLE `sys_permission` (
`permission_id` bigint NOT NULL AUTO_INCREMENT,
`permission_name` varchar(50) NOT NULL,
`permission_code` varchar(50) NOT NULL,
`resource_type` tinyint DEFAULT NULL COMMENT '1-菜单 2-按钮 3-API',
`url` varchar(200) DEFAULT NULL,
`method` varchar(10) DEFAULT NULL,
PRIMARY KEY (`permission_id`),
UNIQUE KEY `idx_permission_code` (`permission_code`)
);
安全配置核心代码:
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/**").authenticated()
.anyRequest().permitAll()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
JWT认证过滤器实现:
java复制public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(
HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
try {
LoginRequest loginRequest = new ObjectMapper()
.readValue(request.getInputStream(), LoginRequest.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws IOException {
UserDetails userDetails = (UserDetails) authResult.getPrincipal();
String token = Jwts.builder()
.setSubject(userDetails.getUsername())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET.getBytes())
.compact();
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
}
}
推荐使用以下开发环境:
后端依赖管理使用Gradle,前端使用pnpm包管理器:
gradle复制// build.gradle 关键依赖
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.2'
implementation 'mysql:mysql-connector-java:8.0.28'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'com.baomidou:mybatis-plus-boot-starter:3.5.1'
}
推荐使用Docker Compose部署:
yaml复制version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: legal_case
MYSQL_USER: legal_user
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- legal-net
redis:
image: redis:6-alpine
ports:
- "6379:6379"
networks:
- legal-net
backend:
build: ./backend
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/legal_case
SPRING_DATASOURCE_USERNAME: legal_user
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
SPRING_REDIS_HOST: redis
ports:
- "8080:8080"
depends_on:
- mysql
- redis
networks:
- legal-net
frontend:
build: ./frontend
ports:
- "80:80"
networks:
- legal-net
volumes:
mysql_data:
networks:
legal-net:
driver: bridge
重要提示:生产环境必须配置SSL证书启用HTTPS,数据库连接应当使用SSL加密,敏感配置应当通过环境变量注入而非硬编码在配置文件中。
通过以下措施显著提升系统性能:
数据库优化:
缓存策略:
java复制@Cacheable(value = "cases", key = "#caseId")
public CaseDetail getCaseDetail(Long caseId) {
return caseMapper.selectById(caseId);
}
@CacheEvict(value = "cases", key = "#caseId")
public void updateCase(CaseInfo caseInfo) {
caseMapper.updateById(caseInfo);
}
前端性能优化:
智能文书生成:
案件预测分析:
python复制# 示例:使用机器学习预测案件胜诉概率
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_train, y_train)
probability = model.predict_proba([case_features])[0][1]
移动端适配:
区块链存证:
这套系统在实际部署中已经帮助多家律所提升了30%以上的工作效率,特别是在案件检索和文书生成方面节省了大量时间。系统设计时特别注意了法律行业的合规要求,所有数据修改都有完整的操作日志记录,满足审计需求。