红色革命文物作为特殊的历史见证物,其数字化管理系统的开发需要兼顾文物保护规范与信息化技术的融合。这套基于SpringBoot+Vue的文物征集管理系统,采用前后端分离架构,实现了从文物信息采集、分类管理到权限控制的完整闭环。
在实际开发中,我们遇到了几个关键挑战:首先是文物信息的复杂性,需要设计灵活的字段结构;其次是多角色协作的权限控制需求;最后是历史数据的长期保存要求。针对这些特点,系统采用MySQL作为主数据库,通过MyBatis实现高效数据操作,同时利用Vue.js的响应式特性构建动态表单,满足不同类别文物的信息录入需求。
提示:文物管理系统的字段设计需要预留扩展空间,我们采用JSON格式存储非结构化描述信息,避免后期频繁修改表结构。
SpringBoot 2.7.x作为后端核心框架,其自动配置特性大幅减少了XML配置工作量。我们特别优化了以下配置:
java复制@Configuration
@MapperScan(basePackages = "com.relic.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
}
java复制@Service
public class RelicServiceImpl implements RelicService {
@Transactional(rollbackFor = Exception.class)
public void updateRelicStatus(Long relicId, String status) {
// 文物状态变更逻辑
}
}
Vue 3.x的组合式API大幅提升了代码可维护性。核心实现包括:
javascript复制const formConfig = reactive({
fields: computed(() => {
return relicType.value === 'document' ?
documentFields : artifactFields
})
})
javascript复制const vPermission = {
mounted(el, binding) {
if (!checkPermission(binding.value)) {
el.parentNode?.removeChild(el)
}
}
}
在原有设计基础上,我们增加了以下优化:
sql复制ALTER TABLE relic_info ADD COLUMN
image_paths JSON COMMENT '图片路径数组';
sql复制CREATE FULLTEXT INDEX ft_idx_description
ON relic_basic(description);
采用POI处理Excel导入,关键代码:
java复制public List<RelicImportDTO> parseExcel(MultipartFile file) {
Workbook workbook = WorkbookFactory.create(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);
return StreamSupport.stream(sheet.spliterator(), false)
.skip(1) // 跳过标题行
.map(row -> RelicImportDTO.builder()
.name(getCellValue(row, 0))
.category(getCellValue(row, 1))
.build())
.collect(Collectors.toList());
}
数据库关系设计:
mermaid复制erDiagram
USER ||--o{ USER_ROLE : has
ROLE ||--o{ ROLE_PERMISSION : has
PERMISSION ||--o{ MENU : corresponds
Spring Security配置要点:
java复制@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/relics/**").hasAnyRole("ADMIN","EDITOR")
.antMatchers("/api/audit/**").hasRole("ADMIN");
return http.build();
}
}
采用多级缓存架构:
java复制@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(1000));
return cacheManager;
}
properties复制# application-redis.properties
spring.redis.timeout=3000
spring.redis.lettuce.pool.max-active=8
sql复制EXPLAIN SELECT relic_id, relic_name
FROM relic_basic
WHERE category = 'document';
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 10
connection-timeout: 30000
java复制@Convert(converter = CryptoConverter.class)
private String collectorPhone;
java复制@Aspect
@Component
public class AuditLogAspect {
@AfterReturning("execution(* com.relic.service..*.*(..))")
public void logMethodAccess(JoinPoint jp) {
AuditLog log = new AuditLog();
log.setOperation(jp.getSignature().getName());
auditLogRepository.save(log);
}
}
java复制@RestController
@RequestMapping("/api")
public class RelicController {
@PostMapping("/relics")
@NonRepeated(expire = 300)
public Result addRelic(@RequestBody RelicDTO dto) {
// 业务逻辑
}
}
javascript复制// 前端过滤函数
const sanitize = (html) => {
return html.replace(/<script.*?>.*?<\/script>/gi, '');
}
Docker Compose配置示例:
yaml复制version: '3'
services:
app:
image: relic-system:1.0
ports:
- "8080:8080"
depends_on:
- redis
- mysql
redis:
image: redis:6-alpine
ports:
- "6379:6379"
Prometheus监控指标示例:
yaml复制- name: spring_http_requests_seconds
help: HTTP请求耗时监控
labels:
endpoint: "/api/relics"
method: "GET"
query: 'rate(spring_http_requests_seconds_sum[1m])'
xml复制<insert id="batchInsert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO relic_collection
(relic_id, collector_name) VALUES
<foreach collection="list" item="item" separator=",">
(#{item.relicId}, #{item.collectorName})
</foreach>
</insert>
javascript复制// 虚拟滚动优化大数据列表
<template>
<RecycleScroller
:items="relics"
:item-size="56"
key-field="id"
>
<template #default="{ item }">
<RelicItem :data="item"/>
</template>
</RecycleScroller>
</template>
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://domain.com")
.allowCredentials(true)
.maxAge(3600);
}
}
在项目开发过程中,我们发现文物图片处理是个性能瓶颈。最终采用以下解决方案:
对于复杂查询场景,我们总结出最佳实践: