1. 项目概述
作为一名长期参与公益组织技术支持的开发者,我深知宠物救助机构在信息化管理方面的痛点。传统的手工登记、Excel表格管理方式已经无法满足现代宠物救助组织的需求。为此,我设计开发了一套基于SpringBoot+Vue.js的前后端分离宠物爱心组织管理系统,经过半年多的实际运行检验,系统显著提升了组织的工作效率。
这套系统最核心的价值在于:
- 实现了宠物从救助到领养的全生命周期数字化管理
- 规范了志愿者服务流程和工时记录
- 建立了透明的捐赠物资追踪机制
- 提供了多维度数据统计分析功能
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术选型考量
后端采用SpringBoot框架主要基于以下考虑:
- 快速构建RESTful API
- 内置Tomcat服务器,简化部署
- 丰富的starter依赖,集成MyBatis、Redis等组件只需简单配置
- 完善的生态和社区支持
前端选择Vue.js+Element UI组合是因为:
- 渐进式框架,学习曲线平缓
- 组件化开发,便于功能模块复用
- Element UI提供了丰富的现成组件,加速开发
- 响应式设计,适配不同终端
数据库选用MySQL 8.0版本,主要利用其:
- 完善的ACID事务支持
- JSON数据类型便于存储半结构化数据
- 窗口函数等高级特性支持复杂统计分析
2.2 系统分层架构
系统采用经典的三层架构:
code复制表现层:Vue.js + Element UI + Axios
业务逻辑层:SpringBoot + Spring Security
数据访问层:MyBatis + MySQL
各层之间通过明确定义的接口进行通信,降低了耦合度。例如前端通过Axios调用后端的RESTful API,后端服务通过MyBatis Mapper接口访问数据库。
3. 核心功能实现
3.1 宠物信息管理模块
宠物信息表设计时特别注意了以下几个点:
sql复制CREATE TABLE `pet_info` (
`pet_id` int NOT NULL AUTO_INCREMENT,
`pet_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
`pet_type` enum('DOG','CAT','OTHER') COLLATE utf8mb4_unicode_ci NOT NULL,
`breed` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`gender` enum('MALE','FEMALE','UNKNOWN') COLLATE utf8mb4_unicode_ci NOT NULL,
`age` smallint DEFAULT NULL COMMENT '月龄',
`weight` decimal(5,2) DEFAULT NULL COMMENT '千克',
`health_status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`rescue_date` datetime NOT NULL,
`rescue_location` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`description` text COLLATE utf8mb4_unicode_ci,
`adopt_status` tinyint NOT NULL DEFAULT '0',
`feature_photo` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pet_id`),
KEY `idx_adopt_status` (`adopt_status`),
KEY `idx_pet_type` (`pet_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
关键实现细节:
- 使用AUTO_INCREMENT自增主键,避免业务主键带来的维护成本
- 对枚举类型字段使用ENUM类型,既节省存储空间又保证数据一致性
- 添加适当的索引提高查询效率
- 自动维护create_time和update_time时间戳
3.2 领养申请流程设计
领养申请的状态机设计:
code复制待提交 → 已提交(待审核) → 审核中 → 审核通过/拒绝 → 完成领养
后端审核接口实现示例:
java复制@PostMapping("/adoption/audit")
@PreAuthorize("hasRole('ADMIN')")
public Result auditAdoption(@RequestBody AuditDTO auditDTO) {
AdoptionRecord record = adoptionService.getById(auditDTO.getApplyId());
if (record == null) {
return Result.fail("申请记录不存在");
}
if (record.getStatus() != AdoptionStatus.PENDING) {
return Result.fail("当前状态不允许审核");
}
record.setStatus(auditDTO.isPass() ? AdoptionStatus.APPROVED : AdoptionStatus.REJECTED);
record.setAuditComment(auditDTO.getComment());
record.setAuditTime(LocalDateTime.now());
record.setAuditor(SecurityUtil.getCurrentUserId());
if (auditDTO.isPass()) {
Pet pet = petService.getById(record.getPetId());
pet.setAdoptStatus(AdoptStatus.ADOPTED);
petService.updateById(pet);
}
adoptionService.updateById(record);
return Result.success();
}
3.3 志愿者管理实现
志愿者服务记录表设计考虑:
sql复制CREATE TABLE `volunteer_service` (
`id` int NOT NULL AUTO_INCREMENT,
`volunteer_id` int NOT NULL,
`activity_id` int NOT NULL,
`task_type` enum('CARE','FEEDING','CLEANING','TRANSPORT','OTHER') COLLATE utf8mb4_unicode_ci NOT NULL,
`start_time` datetime NOT NULL,
`end_time` datetime NOT NULL,
`hours` decimal(4,1) GENERATED ALWAYS AS (TIMESTAMPDIFF(MINUTE,start_time,end_time)/60) STORED,
`task_description` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`admin_comment` text COLLATE utf8mb4_unicode_ci,
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_volunteer` (`volunteer_id`),
KEY `idx_activity` (`activity_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
使用MySQL 5.7+的生成列特性自动计算服务时长,确保数据一致性。
4. 系统部署实践
4.1 后端部署要点
- 生产环境推荐使用JDK17+SpringBoot2.7的组合
- 应用配置分离:
yaml复制# application-prod.yml
spring:
datasource:
url: jdbc:mysql://mysql-prod:3306/pet_rescue?useSSL=false&characterEncoding=utf8
username: prod_user
password: ${DB_PASSWORD}
redis:
host: redis-prod
port: 6379
password: ${REDIS_PASSWORD}
- 使用Docker部署时注意:
dockerfile复制FROM eclipse-temurin:17-jdk-jammy
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
4.2 前端部署优化
- 生产环境构建命令:
bash复制npm run build -- --mode production
- Nginx配置优化:
nginx复制server {
listen 80;
server_name pet-rescue.org;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
}
}
5. 开发经验分享
5.1 前后端协作实践
- 使用Swagger UI维护API文档,后端通过注解自动生成:
java复制@Operation(summary = "获取宠物详情")
@GetMapping("/pets/{id}")
public Result<PetVO> getPetDetail(
@Parameter(description = "宠物ID") @PathVariable Integer id) {
Pet pet = petService.getById(id);
return Result.success(convertToVO(pet));
}
- 前端API请求封装示例:
javascript复制const service = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL,
timeout: 10000
})
// 请求拦截器
service.interceptors.request.use(config => {
const token = store.getters.token
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
})
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 200) {
Message.error(res.message || 'Error')
return Promise.reject(new Error(res.message || 'Error'))
}
return res.data
}
)
5.2 性能优化技巧
- 宠物列表接口优化:
- 添加Redis缓存
- 实现分页查询
- 使用DTO投影减少数据传输量
java复制@Cacheable(value = "petList", key = "#pageNum+'-'+#pageSize")
@GetMapping("/pets")
public PageResult<PetListItemDTO> listPets(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
Page<Pet> page = new Page<>(pageNum, pageSize);
IPage<Pet> petPage = petService.page(page, new QueryWrapper<Pet>()
.select("pet_id", "pet_name", "pet_type", "gender", "age", "feature_photo")
.eq("adopt_status", 0)
.orderByDesc("create_time"));
return PageResult.success(petPage.convert(this::convertToListItemDTO));
}
- 前端图片懒加载实现:
vue复制<template>
<el-image
:src="imageUrl"
lazy
:preview-src-list="[imageUrl]">
<template #placeholder>
<div class="image-placeholder">
<i class="el-icon-picture-outline"></i>
</div>
</template>
</el-image>
</template>
6. 常见问题排查
6.1 跨域问题解决方案
开发环境常见跨域问题,可通过以下方式解决:
- 后端配置CORS:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
- 前端开发环境代理配置(vue.config.js):
javascript复制module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
6.2 文件上传大小限制
SpringBoot默认文件上传限制为1MB,需要调整配置:
- application.yml配置:
yaml复制spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 20MB
- 后端接口实现示例:
java复制@PostMapping("/upload")
public Result upload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return Result.fail("请选择文件");
}
if (file.getSize() > 10 * 1024 * 1024) {
return Result.fail("文件大小不能超过10MB");
}
String filename = fileStorageService.store(file);
return Result.success(filename);
}
7. 系统扩展方向
在实际使用过程中,可以考虑以下几个扩展方向:
- 微信小程序端开发,方便志愿者随时随地记录服务情况
- 接入第三方支付平台,实现在线捐赠功能
- 增加宠物健康档案管理,记录疫苗接种、体检等信息
- 实现智能匹配功能,根据领养人条件推荐合适宠物
- 接入地图API,实现救助地点可视化展示
这套系统经过多个宠物救助组织的实际使用验证,显著提高了工作效率。特别是在领养流程管理、志愿者调度和捐赠物资追踪方面,数字化管理带来的优势非常明显。
