Java全栈项目:实验室预约管理系统的设计与实现
一、项目介绍
实验室预约管理系统是一个基于Java全栈技术开发的Web应用系统,旨在提供便捷的实验室预约、管理和使用体验。本系统主要面向高校师生,实现实验室资源的智能化、信息化管理。
二、技术栈
前端技术
- Vue.js
- Element UI
- Axios
- Vue Router
- Vuex
后端技术
- Spring Boot
- Spring Security
- MyBatis Plus
- MySQL
- Redis
- JWT
三、核心功能模块
1. 用户管理模块
- 用户注册与登录
- 角色权限管理
- 个人信息维护
2. 实验室管理模块
- 实验室信息管理
- 设备资源管理
- 实验室状态监控
3. 预约管理模块
- 在线预约申请
- 预约审批流程
- 预约记录查询
- 使用情况统计
4. 系统管理模块
- 系统参数配置
- 日志管理
- 数据备份
四、数据库设计
主要数据表
-- 用户表
CREATE TABLE user (id BIGINT PRIMARY KEY,username VARCHAR(50),password VARCHAR(100),role VARCHAR(20),create_time DATETIME
);-- 实验室表
CREATE TABLE laboratory (id BIGINT PRIMARY KEY,name VARCHAR(100),capacity INT,status VARCHAR(20),description TEXT
);-- 预约记录表
CREATE TABLE reservation (id BIGINT PRIMARY KEY,user_id BIGINT,lab_id BIGINT,start_time DATETIME,end_time DATETIME,status VARCHAR(20)
);
五、核心功能实现
1. 预约流程实现
@Service
public class ReservationService {@Autowiredprivate ReservationMapper reservationMapper;@Transactionalpublic Result createReservation(ReservationDTO dto) {// 检查实验室是否可用if (!checkLabAvailable(dto.getLabId())) {return Result.fail("实验室不可用");}// 检查时间冲突if (checkTimeConflict(dto)) {return Result.fail("预约时间冲突");}// 创建预约记录Reservation reservation = new Reservation();BeanUtils.copyProperties(dto, reservation);reservationMapper.insert(reservation);return Result.success();}
}
2. 权限控制实现
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/api/public/**").permitAll().antMatchers("/api/admin/**").hasRole("ADMIN").antMatchers("/api/user/**").hasRole("USER").anyRequest().authenticated().and().addFilter(new JWTAuthenticationFilter(authenticationManager())).addFilter(new JWTAuthorizationFilter(authenticationManager()));}
}
六、系统特点
- 用户友好:直观的界面设计,操作简单便捷
- 实时响应:采用WebSocket实现实验室状态实时更新
- 高可用性:使用Redis缓存提升系统性能
- 安全可靠:完善的权限控制和数据加密机制
七、项目部署
环境要求
- JDK 1.8+
- Maven 3.6+
- MySQL 5.7+
- Redis 6.0+
- Node.js 12+
部署步骤
- 数据库初始化
- 后端服务部署
- 前端项目打包
- Nginx配置
八、总结与展望
本项目实现了实验室预约管理的核心功能,通过现代化的技术栈,提供了良好的用户体验。未来计划添加以下功能:
- 引入人脸识别功能
- 集成物联网设备
- 开发移动端应用
- 添加数据分析功能
本文介绍了实验室预约管理系统的主要功能和技术实现,希望能为相似项目的开发提供参考。
实验室预约管理系统核心模块详解(上)
一、用户管理模块
1. 数据库设计
-- 用户表
CREATE TABLE sys_user (id BIGINT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL COMMENT '用户名',password VARCHAR(100) NOT NULL COMMENT '密码',real_name VARCHAR(50) COMMENT '真实姓名',phone VARCHAR(20) COMMENT '手机号',email VARCHAR(100) COMMENT '邮箱',avatar VARCHAR(200) COMMENT '头像URL',status TINYINT DEFAULT 1 COMMENT '状态:0-禁用,1-启用',create_time DATETIME COMMENT '创建时间',update_time DATETIME COMMENT '更新时间'
);-- 角色表
CREATE TABLE sys_role (id BIGINT PRIMARY KEY AUTO_INCREMENT,role_name VARCHAR(50) NOT NULL COMMENT '角色名称',role_code VARCHAR(50) NOT NULL COMMENT '角色编码',description VARCHAR(200) COMMENT '角色描述',status TINYINT DEFAULT 1 COMMENT '状态'
);-- 用户角色关联表
CREATE TABLE sys_user_role (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL COMMENT '用户ID',role_id BIGINT NOT NULL COMMENT '角色ID'
);-- 权限表
CREATE TABLE sys_permission (id BIGINT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) COMMENT '权限名称',code VARCHAR(50) COMMENT '权限编码',type TINYINT COMMENT '类型:1-菜单,2-按钮',parent_id BIGINT COMMENT '父级ID',path VARCHAR(200) COMMENT '路由路径',icon VARCHAR(50) COMMENT '图标'
);
2. 核心功能实现
2.1 用户注册
@Service
public class UserService {@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate UserMapper userMapper;@Transactionalpublic Result register(UserRegisterDTO dto) {// 验证用户名是否存在if(checkUsernameExist(dto.getUsername())) {return Result.fail("用户名已存在");}// 密码加密String encodedPassword = passwordEncoder.encode(dto.getPassword());// 创建用户SysUser user = new SysUser();user.setUsername(dto.getUsername());user.setPassword(encodedPassword);user.setPhone(dto.getPhone());user.setEmail(dto.getEmail());user.setCreateTime(new Date());userMapper.insert(user);// 分配默认角色assignDefaultRole(user.getId());return Result.success();}
}
2.2 用户登录
@Service
public class AuthService {@Autowiredprivate UserService userService;@Autowiredprivate JwtUtils jwtUtils;public Result login(LoginDTO loginDTO) {// 用户认证UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword());Authentication authentication = authenticationManager.authenticate(authenticationToken);if (authentication == null) {throw new BadCredentialsException("用户名或密码错误");}// 生成JWT tokenString token = jwtUtils.generateToken(authentication);// 获取用户信息UserVO userInfo = userService.getUserInfo(loginDTO.getUsername());Map<String, Object> result = new HashMap<>();result.put("token", token);result.put("userInfo", userInfo);return Result.success(result);}
}
2.3 角色权限管理
@Service
public class RoleService {@Autowiredprivate RoleMapper roleMapper;@Autowiredprivate UserRoleMapper userRoleMapper;@Transactionalpublic Result assignRoles(Long userId, List<Long> roleIds) {// 删除原有角色userRoleMapper.deleteByUserId(userId);// 分配新角色if (!CollectionUtils.isEmpty(roleIds)) {List<SysUserRole> userRoles = roleIds.stream().map(roleId -> new SysUserRole(userId, roleId)).collect(Collectors.toList());userRoleMapper.batchInsert(userRoles);}return Result.success();}public List<PermissionVO> getRolePermissions(Long roleId) {return roleMapper.selectPermissionsByRoleId(roleId);}
}
二、实验室管理模块
1. 数据库设计
-- 实验室表
CREATE TABLE lab_info (id BIGINT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100) NOT NULL COMMENT '实验室名称',location VARCHAR(200) COMMENT '位置',capacity INT COMMENT '容量',description TEXT COMMENT '描述',status TINYINT DEFAULT 1 COMMENT '状态:0-维护中,1-可用',create_time DATETIME,update_time DATETIME
);-- 设备表
CREATE TABLE lab_equipment (id BIGINT PRIMARY KEY AUTO_INCREMENT,lab_id BIGINT COMMENT '实验室ID',name VARCHAR(100) COMMENT '设备名称',model VARCHAR(100) COMMENT '型号',serial_number VARCHAR(100) COMMENT '序列号',status TINYINT COMMENT '状态:0-故障,1-正常',purchase_date DATE COMMENT '购买日期',maintenance_date DATE COMMENT '上次维护日期'
);-- 实验室状态记录表
CREATE TABLE lab_status_log (id BIGINT PRIMARY KEY AUTO_INCREMENT,lab_id BIGINT COMMENT '实验室ID',status TINYINT COMMENT '状态',remark VARCHAR(500) COMMENT '备注',create_time DATETIME
);
2. 核心功能实现
2.1 实验室信息管理
@Service
public class LabService {@Autowiredprivate LabMapper labMapper;@Autowiredprivate LabEquipmentMapper equipmentMapper;@Transactionalpublic Result createLab(LabCreateDTO dto) {// 创建实验室基本信息LabInfo lab = new LabInfo();BeanUtils.copyProperties(dto, lab);lab.setCreateTime(new Date());labMapper.insert(lab);// 添加设备信息if (!CollectionUtils.isEmpty(dto.getEquipments())) {List<LabEquipment> equipments = dto.getEquipments().stream().map(e -> {LabEquipment equipment = new LabEquipment();equipment.setLabId(lab.getId());BeanUtils.copyProperties(e, equipment);return equipment;}).collect(Collectors.toList());equipmentMapper.batchInsert(equipments);}return Result.success();}public PageResult<LabVO> queryLabs(LabQueryDTO query) {Page<LabInfo> page = new Page<>(query.getPageNum(), query.getPageSize());IPage<LabVO> labPage = labMapper.selectLabPage(page, query);return new PageResult<>(labPage);}
}
2.2 设备资源管理
@Service
public class EquipmentService {@Autowiredprivate LabEquipmentMapper equipmentMapper;@Autowiredprivate MaintenanceRecordMapper maintenanceMapper;public Result updateEquipmentStatus(Long equipmentId, Integer status, String remark) {LabEquipment equipment = equipmentMapper.selectById(equipmentId);if (equipment == null) {return Result.fail("设备不存在");}// 更新设备状态equipment.setStatus(status);equipmentMapper.updateById(equipment);// 记录维护信息if (status == EquipmentStatusEnum.MAINTENANCE.getCode()) {MaintenanceRecord record = new MaintenanceRecord();record.setEquipmentId(equipmentId);record.setMaintenanceDate(new Date());record.setRemark(remark);maintenanceMapper.insert(record);}return Result.success();}public List<EquipmentVO> getLabEquipments(Long labId) {return equipmentMapper.selectByLabId(labId);}
}
2.3 实验室状态监控
@Service
public class LabMonitorService {@Autowiredprivate LabStatusLogMapper statusLogMapper;@Autowiredprivate WebSocketServer webSocketServer;@Asyncpublic void monitorLabStatus() {// 定时检查实验室状态List<LabInfo> labs = labMapper.selectList(null);for (LabInfo lab : labs) {LabStatusDTO status = checkLabStatus(lab.getId());// 记录状态变更if (isStatusChanged(lab.getId(), status.getStatus())) {LabStatusLog log = new LabStatusLog();log.setLabId(lab.getId());log.setStatus(status.getStatus());log.setRemark(status.getRemark());statusLogMapper.insert(log);// 推送状态更新webSocketServer.sendMessage(String.format("lab_%d", lab.getId()),JSON.toJSONString(status));}}}public List<LabStatusVO> getLabStatusHistory(Long labId, Date startTime, Date endTime) {return statusLogMapper.selectStatusHistory(labId, startTime, endTime);}
}
3. 前端实现示例
3.1 用户登录组件
<template><div class="login-container"><el-form :model="loginForm" :rules="loginRules" ref="loginForm"><el-form-item prop="username"><el-input v-model="loginForm.username" placeholder="用户名"><i slot="prefix" class="el-icon-user"></i></el-input></el-form-item><el-form-item prop="password"><el-input type="password" v-model="loginForm.password" placeholder="密码"><i slot="prefix" class="el-icon-lock"></i></el-input></el-form-item><el-button type="primary" @click="handleLogin" :loading="loading">登录</el-button></el-form></div>
</template><script>
export default {data() {return {loginForm: {username: '',password: ''},loginRules: {username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],password: [{ required: true, message: '请输入密码', trigger: 'blur' }]},loading: false}},methods: {async handleLogin() {try {await this.$refs.loginForm.validate()this.loading = trueconst res = await this.$api.login(this.loginForm)if (res.code === 0) {this.$store.commit('SET_TOKEN', res.data.token)this.$store.commit('SET_USER_INFO', res.data.userInfo)this.$router.push('/')}} catch (error) {console.error(error)} finally {this.loading = false}}}
}
</script>
3.2 实验室管理组件
<template><div class="lab-manage"><!-- 搜索栏 --><div class="search-bar"><el-form :inline="true" :model="queryForm"><el-form-item label="实验室名称"><el-input v-model="queryForm.name" placeholder="请输入"></el-input></el-form-item><el-form-item label="状态"><el-select v-model="queryForm.status" placeholder="请选择"><el-option label="可用" :value="1"></el-option><el-option label="维护中" :value="0"></el-option></el-select></el-form-item><el-form-item><el-button type="primary" @click="handleSearch">查询</el-button><el-button @click="handleReset">重置</el-button></el-form-item></el-form></div><!-- 实验室列表 --><el-table :data="labList" border><el-table-column prop="name" label="实验室名称"></el-table-column><el-table-column prop="location" label="位置"></el-table-column><el-table-column prop="capacity" label="容量"></el-table-column><el-table-column label="状态"><template slot-scope="scope"><el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">{{ scope.row.status === 1 ? '可用' : '维护中' }}</el-tag></template></el-table-column><el-table-column label="操作" width="200"><template slot-scope="scope"><el-button type="text" @click="handleEdit(scope.row)">编辑</el-button><el-button type="text" @click="handleEquipment(scope.row)">设备管理</el-button><el-button type="text" @click="handleStatus(scope.row)">状态记录</el-button></template></el-table-column></el-table><!-- 分页 --><el-pagination@current-change="handleCurrentChange"@size-change="handleSizeChange":current-page="queryForm.pageNum":page-sizes="[10, 20, 50]":page-size="queryForm.pageSize"layout="total, sizes, prev, pager, next":total="total"></el-pagination></div>
</template><script>
export default {data() {return {queryForm: {name: '',status: '',pageNum: 1,pageSize: 10},labList: [],total: 0}},created() {this.fetchLabList()},methods: {async fetchLabList() {try {const res = await this.$api.queryLabs(this.queryForm)this.labList = res.data.recordsthis.total = res.data.total} catch (error) {console.error(error)}},handleSearch() {this.queryForm.pageNum = 1this.fetchLabList()},handleReset() {this.queryForm = {name: '',status: '',pageNum: 1,pageSize: 10}this.fetchLabList()}// ... 其他方法实现}
}
</script>
以上是用户管理模块和实验室管理模块的详细实现。包括了:
- 完整的数据库表设计
- 后端核心业务逻辑实现
- 前端组件示例代码
这些代码展示了基本的CRUD操作、状态管理、实时监控等功能的实现方式。实际项目中还需要根据具体需求进行调整和扩展。
实验室预约管理系统模块详解(下)
一、预约管理模块
1. 数据库设计
-- 预约记录表
CREATE TABLE lab_reservation (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL COMMENT '预约用户ID',lab_id BIGINT NOT NULL COMMENT '实验室ID',start_time DATETIME NOT NULL COMMENT '开始时间',end_time DATETIME NOT NULL COMMENT '结束时间',purpose VARCHAR(500) COMMENT '用途说明',participants INT COMMENT '使用人数',status TINYINT DEFAULT 0 COMMENT '状态:0-待审核,1-已通过,2-已拒绝,3-已取消,4-已完成',create_time DATETIME,update_time DATETIME
);-- 预约审批记录表
CREATE TABLE reservation_approval (id BIGINT PRIMARY KEY AUTO_INCREMENT,reservation_id BIGINT NOT NULL COMMENT '预约ID',approver_id BIGINT NOT NULL COMMENT '审批人ID',approval_status TINYINT COMMENT '审批状态:1-通过,2-拒绝',approval_comment VARCHAR(500) COMMENT '审批意见',approval_time DATETIME COMMENT '审批时间'
);-- 实验室使用记录表
CREATE TABLE lab_usage_record (id BIGINT PRIMARY KEY AUTO_INCREMENT,reservation_id BIGINT COMMENT '预约ID',check_in_time DATETIME COMMENT '签到时间',check_out_time DATETIME COMMENT '签退时间',actual_participants INT COMMENT '实际使用人数',status TINYINT COMMENT '状态:1-正常,2-超时,3-爽约',remark VARCHAR(500) COMMENT '备注'
);
2. 核心功能实现
2.1 预约申请服务
@Service
public class ReservationService {@Autowiredprivate LabReservationMapper reservationMapper;@Autowiredprivate LabService labService;@Transactionalpublic Result createReservation(ReservationCreateDTO dto) {// 验证实验室是否可用LabInfo lab = labService.getLabById(dto.getLabId());if (lab == null || lab.getStatus() != 1) {return Result.fail("实验室不可用");}// 检查时间冲突if (checkTimeConflict(dto.getLabId(), dto.getStartTime(), dto.getEndTime())) {return Result.fail("所选时间段已被预约");}// 创建预约记录LabReservation reservation = new LabReservation();BeanUtils.copyProperties(dto, reservation);reservation.setUserId(SecurityUtils.getCurrentUserId());reservation.setStatus(ReservationStatusEnum.PENDING.getCode());reservation.setCreateTime(new Date());reservationMapper.insert(reservation);// 发送审批通知sendApprovalNotification(reservation);return Result.success();}private boolean checkTimeConflict(Long labId, Date startTime, Date endTime) {return reservationMapper.countConflictReservations(labId, startTime, endTime) > 0;}
}
2.2 预约审批服务
@Service
public class ApprovalService {@Autowiredprivate ReservationApprovalMapper approvalMapper;@Autowiredprivate ReservationService reservationService;@Transactionalpublic Result approveReservation(ApprovalDTO dto) {// 验证预约状态LabReservation reservation = reservationService.getById(dto.getReservationId());if (reservation == null || reservation.getStatus() != ReservationStatusEnum.PENDING.getCode()) {return Result.fail("预约记录不存在或状态异常");}// 记录审批信息ReservationApproval approval = new ReservationApproval();approval.setReservationId(dto.getReservationId());approval.setApproverId(SecurityUtils.getCurrentUserId());approval.setApprovalStatus(dto.getApprovalStatus());approval.setApprovalComment(dto.getComment());approval.setApprovalTime(new Date());approvalMapper.insert(approval);// 更新预约状态Integer newStatus = dto.getApprovalStatus() == 1 ? ReservationStatusEnum.APPROVED.getCode() : ReservationStatusEnum.REJECTED.getCode();reservationService.updateStatus(dto.getReservationId(), newStatus);// 发送通知sendNotification(reservation.getUserId(), newStatus, dto.getComment());return Result.success();}
}
2.3 使用统计服务
@Service
public class LabStatisticsService {@Autowiredprivate LabUsageRecordMapper usageRecordMapper;public Map<String, Object> getLabUsageStatistics(StatisticsQueryDTO query) {Map<String, Object> result = new HashMap<>();// 获取使用率统计List<LabUsageRateVO> usageRates = usageRecordMapper.selectUsageRateByLab(query.getStartDate(), query.getEndDate());result.put("usageRates", usageRates);// 获取预约状态分布List<ReservationStatusVO> statusDistribution = usageRecordMapper.selectReservationStatusDistribution(query.getStartDate(), query.getEndDate());result.put("statusDistribution", statusDistribution);// 获取高峰时段分析List<PeakTimeVO> peakTimes = usageRecordMapper.selectPeakTimeAnalysis(query.getStartDate(), query.getEndDate());result.put("peakTimes", peakTimes);return result;}
}
二、系统管理模块
1. 数据库设计
-- 系统参数表
CREATE TABLE sys_config (id BIGINT PRIMARY KEY AUTO_INCREMENT,param_key VARCHAR(50) NOT NULL COMMENT '参数键',param_value VARCHAR(500) COMMENT '参数值',param_desc VARCHAR(200) COMMENT '参数描述',type TINYINT COMMENT '参数类型:1-系统参数,2-业务参数',create_time DATETIME,update_time DATETIME
);-- 系统日志表
CREATE TABLE sys_log (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT COMMENT '操作用户ID',module VARCHAR(50) COMMENT '操作模块',operation VARCHAR(50) COMMENT '操作类型',method VARCHAR(200) COMMENT '请求方法',params TEXT COMMENT '请求参数',time BIGINT COMMENT '执行时长(ms)',ip VARCHAR(50) COMMENT 'IP地址',create_time DATETIME
);-- 数据备份记录表
CREATE TABLE sys_backup (id BIGINT PRIMARY KEY AUTO_INCREMENT,backup_name VARCHAR(100) COMMENT '备份名称',backup_type TINYINT COMMENT '备份类型:1-全量,2-增量',file_path VARCHAR(200) COMMENT '备份文件路径',file_size BIGINT COMMENT '文件大小(byte)',status TINYINT COMMENT '状态:0-备份中,1-成功,2-失败',start_time DATETIME COMMENT '开始时间',end_time DATETIME COMMENT '结束时间',remark VARCHAR(500) COMMENT '备注'
);
2. 核心功能实现
2.1 系统参数配置服务
@Service
public class SysConfigService {@Autowiredprivate SysConfigMapper configMapper;@Autowiredprivate RedisTemplate<String, String> redisTemplate;private static final String CONFIG_KEY_PREFIX = "sys:config:";public String getConfigValue(String key) {// 先从Redis缓存获取String value = redisTemplate.opsForValue().get(CONFIG_KEY_PREFIX + key);if (value != null) {return value;}// 从数据库获取SysConfig config = configMapper.selectByKey(key);if (config != null) {// 放入缓存redisTemplate.opsForValue().set(CONFIG_KEY_PREFIX + key, config.getParamValue(),24, TimeUnit.HOURS);return config.getParamValue();}return null;}@Transactionalpublic Result updateConfig(ConfigUpdateDTO dto) {SysConfig config = configMapper.selectByKey(dto.getKey());if (config == null) {return Result.fail("参数不存在");}config.setParamValue(dto.getValue());config.setUpdateTime(new Date());configMapper.updateById(config);// 更新缓存redisTemplate.opsForValue().set(CONFIG_KEY_PREFIX + dto.getKey(), dto.getValue(),24, TimeUnit.HOURS);return Result.success();}
}
2.2 系统日志服务
@Aspect
@Component
public class SysLogAspect {@Autowiredprivate SysLogMapper logMapper;@Around("@annotation(com.xxx.annotation.SysLog)")public Object around(ProceedingJoinPoint point) throws Throwable {long beginTime = System.currentTimeMillis();try {// 执行方法Object result = point.proceed();// 保存日志saveLog(point, System.currentTimeMillis() - beginTime);return result;} catch (Exception e) {// 保存异常日志saveExceptionLog(point, e, System.currentTimeMillis() - beginTime);throw e;}}private void saveLog(ProceedingJoinPoint point, long time) {MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();SysLog sysLog = method.getAnnotation(SysLog.class);SysLogEntity log = new SysLogEntity();log.setUserId(SecurityUtils.getCurrentUserId());log.setModule(sysLog.module());log.setOperation(sysLog.operation());log.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());log.setParams(JSON.toJSONString(point.getArgs()));log.setTime(time);log.setIp(IPUtils.getIpAddr());log.setCreateTime(new Date());logMapper.insert(log);}
}
2.3 数据备份服务
@Service
public class BackupService {@Autowiredprivate SysBackupMapper backupMapper;@Value("${backup.path}")private String backupPath;@Asyncpublic void createBackup(BackupCreateDTO dto) {SysBackup backup = new SysBackup();backup.setBackupName(dto.getName());backup.setBackupType(dto.getType());backup.setStatus(0);backup.setStartTime(new Date());backupMapper.insert(backup);try {// 执行备份String fileName = executeBackup(dto);// 更新备份记录File backupFile = new File(fileName);backup.setFilePath(fileName);backup.setFileSize(backupFile.length());backup.setStatus(1);backup.setEndTime(new Date());backupMapper.updateById(backup);} catch (Exception e) {log.error("数据备份失败", e);backup.setStatus(2);backup.setRemark(e.getMessage());backup.setEndTime(new Date());backupMapper.updateById(backup);}}private String executeBackup(BackupCreateDTO dto) throws Exception {String fileName = backupPath + "/" + DateUtils.format(new Date(), "yyyyMMddHHmmss") + ".sql";ProcessBuilder builder = new ProcessBuilder();if (dto.getType() == 1) {// 全量备份builder.command("mysqldump", "-h" + dbHost,"-u" + dbUsername,"-p" + dbPassword,dbName,"--result-file=" + fileName);} else {// 增量备份builder.command("mysqldump","-h" + dbHost,"-u" + dbUsername,"-p" + dbPassword,"--skip-add-locks","--no-create-info",dbName,"--result-file=" + fileName);}Process process = builder.start();int exitCode = process.waitFor();if (exitCode != 0) {throw new RuntimeException("备份执行失败");}return fileName;}
}
3. 前端实现示例
3.1 预约管理组件
<template><div class="reservation-manage"><!-- 预约表单 --><el-form :model="reservationForm" :rules="rules" ref="reservationForm"><el-form-item label="实验室" prop="labId"><el-select v-model="reservationForm.labId" placeholder="请选择实验室"><el-optionv-for="lab in labList":key="lab.id":label="lab.name":value="lab.id"></el-option></el-select></el-form-item><el-form-item label="使用时间" prop="timeRange"><el-date-pickerv-model="reservationForm.timeRange"type="datetimerange"range-separator="至"start-placeholder="开始时间"end-placeholder="结束时间"></el-date-picker></el-form-item><el-form-item label="用途说明" prop="purpose"><el-inputtype="textarea"v-model="reservationForm.purpose"placeholder="请输入用途说明"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitReservation">提交预约</el-button></el-form-item></el-form><!-- 预约记录列表 --><el-table :data="reservationList" border><el-table-column prop="labName" label="实验室"></el-table-column><el-table-column label="使用时间"><template slot-scope="scope">{{ formatDateTime(scope.row.startTime) }} 至 {{ formatDateTime(scope.row.endTime) }}</template></el-table-column><el-table-column prop="purpose" label="用途" show-overflow-tooltip></el-table-column><el-table-column label="状态"><template slot-scope="scope"><el-tag :type="getStatusType(scope.row.status)">{{ getStatusText(scope.row.status) }}</el-tag></template></el-table-column><el-table-column label="操作" width="150"><template slot-scope="scope"><el-button type="text" @click="cancelReservation(scope.row)"v-if="scope.row.status === 0">取消预约</el-button><el-button type="text" @click="viewDetail(scope.row)">查看详情</el-button></template></el-table-column></el-table></div>
</template><script>
export default {data() {return {reservationForm: {labId: '',timeRange: [],purpose: ''},rules: {labId: [{ required: true, message: '请选择实验室', trigger: 'change' }],timeRange: [{ required: true, message: '请选择使用时间', trigger: 'change' }],purpose: [{ required: true, message: '请输入用途说明', trigger: 'blur' }]},labList: [],reservationList: []}},methods: {async submitReservation() {try {await this.$refs.reservationForm.validate()const [startTime, endTime] = this.reservationForm.timeRangeconst params = {labId: this.reservationForm.labId,startTime,endTime,purpose: this.reservationForm.purpose}await this.$api.createReservation(params)this.$message.success('预约申请提交成功')this.fetchReservationList()} catch (error) {console.error(error)}},getStatusType(status) {const typeMap = {0: 'info',1: 'success',2: 'danger',3: 'info',4: ''}return typeMap[status]},getStatusText(status) {const textMap = {0: '待审核',1: '已通过',2: '已拒绝',3: '已取消',4: '已完成'}return textMap[status]}}
}
</script>
3.2 系统配置组件
<template><div class="sys-config"><el-card class="config-card"><div slot="header"><span>系统参数配置</span></div><el-form :model="configForm" label-width="120px"><el-form-item v-for="item in configList":key="item.key":label="item.desc"><el-input v-model="configForm[item.key]":placeholder="'请输入' + item.desc"></el-input></el-form-item><el-form-item><el-button type="primary" @click="saveConfig">保存配置</el-button></el-form-item></el-form></el-card><el-card class="backup-card"><div slot="header"><span>数据备份</span></div><div class="backup-actions"><el-button type="primary" @click="createBackup(1)">全量备份</el-button><el-button type="warning" @click="createBackup(2)">增量备份</el-button></div><el-table :data="backupList" border style="margin-top: 20px;"><el-table-column prop="backupName" label="备份名称"></el-table-column><el-table-column label="备份类型"><template slot-scope="scope">{{ scope.row.backupType === 1 ? '全量' : '增量' }}</template></el-table-column><el-table-column prop="fileSize" label="文件大小"><template slot-scope="scope">{{ formatFileSize(scope.row.fileSize) }}</template></el-table-column><el-table-column label="状态"><template slot-scope="scope"><el-tag :type="getBackupStatusType(scope.row.status)">{{ getBackupStatusText(scope.row.status) }}</el-tag></template></el-table-column><el-table-column label="操作" width="150"><template slot-scope="scope"><el-button type="text" @click="downloadBackup(scope.row)"v-if="scope.row.status === 1">下载</el-button><el-button type="text" @click="deleteBackup(scope.row)">删除</el-button></template></el-table-column></el-table></el-card></div>
</template><script>
export default {data() {return {configForm: {},configList: [],backupList: []}},created() {this.fetchConfigList()this.fetchBackupList()},methods: {async fetchConfigList() {const res = await this.$api.getConfigList()this.configList = res.data// 初始化表单数据this.configList.forEach(item => {this.$set(this.configForm, item.key, item.value)})},async saveConfig() {try {const params = Object.entries(this.configForm).map(([key, value]) => ({key,value}))await this.$api.updateConfig(params)this.$message.success('配置保存成功')} catch (error) {console.error(error)}},async createBackup(type) {try {const params = {name: `backup_${Date.now()}`,type}await this.$api.createBackup(params)this.$message.success('备份任务已启动')this.fetchBackupList()} catch (error) {console.error(error)}},formatFileSize(size) {if (size < 1024) {return size + 'B'} else if (size < 1024 * 1024) {return (size / 1024).toFixed(2) + 'KB'} else {return (size / 1024 / 1024).toFixed(2) + 'MB'}}}
}
</script>
以上是预约管理模块和系统管理模块的详细实现,包括:
- 完整的数据库表设计
- 后端核心服务实现
- 前端组件示例代码
这些代码展示了预约流程、审批流程、统计分析、系统配置、日志管理、数据备份等功能的具体实现方式。实际项目中还需要根据具体需求进行调整和扩展。
相关文章:

Java全栈项目:实验室预约管理系统的设计与实现
一、项目介绍 实验室预约管理系统是一个基于Java全栈技术开发的Web应用系统,旨在提供便捷的实验室预约、管理和使用体验。本系统主要面向高校师生,实现实验室资源的智能化、信息化管理。 二、技术栈 前端技术 Vue.jsElement UIAxiosVue RouterVuex …...

使用 esrally race 测试 Elasticsearch 性能及 Kibana 可视化分析指南
前言: 在对 Elasticsearch 集群进行性能测试与调优的过程中,esrally 是官方推荐的测试工具。通过 esrally race 命令,我们可以模拟各种查询与索引负载,对集群进行基准测试。然而,仅看 esrally 的终端输出并不直观&…...

OpenAI 第七日 推出了一项新功能——ChatGPT的“Projects”
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

【小白51单片机专用教程】protues仿真AT89C51入门
课程特点 无需开发板0基础教学软件硬件双修辅助入门 本课程面对纯小白,因此会对各个新出现的知识点在实例基础上进行详细讲解,有相关知识的可以直接跳过。课程涉及protues基本操作、原理图设计、数电模电、kell使用、C语言基本内容,所有涉及…...

正则表达式——元字符匹配(单字符)
单字符匹配: ###注意事项:前面要加r:如(re.findall(r\w,字符串名)) #. :匹配任意一个字符 (.本身通过\.匹配) # [ ]: 匹配[ ]中的字符 # \d: 匹配数字 # \D: 匹配非数字 # \s: 匹配空白(空格) # \S:匹配非空白 # \w: 匹配单词字符(a…...

快速在远程服务器执行命令、批量在多个服务器执行命令(基于sshpass的自定义脚本fastsh)
在日常服务器操作中,很多时候我们需要同时操作多个服务器。特别对于那些每个服务器都需要操作相同命令的场景,不断的切换命令会话窗口会比较麻烦。基于此,编写了本文中的 fastsh 脚本用于轻度解决这种问题,提高一定的便利性。 使…...

【中间件介绍及案例分析】
中间件介绍及案例分析 一、中间件的定义 中间件是一种位于操作系统、网络和数据库之上,应用软件之下的软件。它的主要作用是为处于不同系统中的软件组件提供通用服务,使得这些软件组件能够更好地通信、协同工作,并且帮助开发人员更高效地构…...

CRMEB PHP多商户版DOCKER部署实战
#首先,制作docker 镜像# 官方有一个镜像,但是拉不来下,也不知道是没是没有维护,嘎了。只能自己动手做一个。 这里选择ubuntu 24 为基础,制作crmeb-mer的镜像,Dockerfile内容如下: # 使用官方…...

Node.js基础入门
1.Node.js 简介 Node 是一个让 JavaScript (独立)运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。 发布于2009年5月,由Ryan Dahl开发,实质是对Chrome V8引擎进行了封装。 简单的说 Node.js 就是运行在服务端的…...

Hive——HQL数据定义语言
文章目录 Hive HQL数据查询语言更多大数据资源持续更新中。。。学习目标一、HQL数据定义语言(DDL)概述1、DDL语法的作用2、Hive中DDL使用☆ 创建数据库☆ 查询数据库☆ 切换数据库☆ 修改数据库☆ 删除数据库 二、Hive DDL建表基础1、完整建表语法树2、H…...

vLLM 教程上新!覆盖从入门到进阶 4 种应用方式;中文文档同步上线,0 帧起手加速大模型推理
如今,大语言模型 (LLM) 的发展正在从规模参数迭代升级拓展至应用场景的适配与创新,在这个过程中,其也暴露出一系列问题。例如,在推理环节的效率较低,处理复杂任务时耗时较长,难以满足对实时性要求较高的场景…...

Kubernetes# RBAC访问控制
目录 定义 配置对象 Role ClusterRole ServiceAccount RoleBinding ClusterRoleBinding 配置示例 定义 Kubernetes的运行是由多种类型的资源组合起来,每种资源各司其职完成整个集群的功能。那么自然也需要一套机制控制资源的访问权限,保证安全性…...

如何实现后端返回excel文件,在前端下载功能
前言 简单记录一下,excel文件导出下载功能 一、后端接口返回excel文件 把自己生成的workbook 以文件流的方式,返回前台 Workbook workbook employeeConfirmationDefectService.exportPoorPolishExcel(budatBegin, budatEnd, queryWrapper);//传输到…...

编程:一场不设防的智慧江湖
在数字的汪洋中,有一片从未设置年龄禁区的领地——编程世界。许多人会问:35岁了,还能学编程吗?答案是:不仅能学,还能学得很精彩。 时光荏苒,科技浪潮汹涌澎湃。曾经,人们以为编程是…...

电脑游戏运行时常见问题解析:穿越火线提示“unityplayer.dll丢失”的修复指南
电脑游戏运行时常见问题解析:穿越火线提示“unityplayer.dll丢失”的修复指南 在探索电脑游戏的无限乐趣时,我们时常会遇到一些不期而遇的挑战。今天,我们将聚焦于一个常见的游戏运行错误——穿越火线(或其他使用Unity引擎的游戏…...

【C++】CUDA线程在全局索引中的计算方式
文章目录 1. 一维网格一维线程块2. 二维网格二维线程块3. 三维网格三维线程块4. 不同组合形式4.1 一维网格一维线程块4.2 一维网格二维线程块4.3 一维网格三维线程块4.4 二维网格一维线程块4.5 二维网格二维线程块4.6 二维网格三维线程块4.7 三维网格一维线程块4.8 三维网格二维…...

【笔记】C语言转C++
网课链接:【C语言 转 C 简单教程】 https://www.bilibili.com/video/BV1UE411j7Ti/?p27&share_sourcecopy_web&vd_source4abe1433c2a7ef632aeed6a3d5c0b22a 网课老师B站id:别喷我id 视频总时长:01:55:27 以下笔记是我通过此网课整理 建议先…...

锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集
锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集 目录 锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集预测效果基本描述程序设计参考资料 预测效果 基本描述 锂电池SOH预测 | 基于Bi…...

半导体器件与物理篇5 1~4章课后习题
热平衡时的能带和载流子浓度 例 一硅晶掺入每立方厘米10^{16}个砷原子,求室温下(300K)的载流子浓度与费米能级。 需要用到的公式包括1.本征载流子浓度公式 2.从导带底算起的本征费米能级 2.从本征费米能级算起的费米能级 载流子输运现象 例1:计算在300K下&#x…...

Pytest-Bdd-Playwright 系列教程(16):标准化JSON报告Gherkin格式命令行报告
Pytest-Bdd-Playwright 系列教程(16):标准化JSON报告&Gherkin格式命令行报告 前言一、创建Feature文件二、创建步骤定义文件三、生成Cucumber格式的JSON报告四、使用Gherkin格式的命令行报告五、将BDD报告集成到Jenkins中总结 前言 在自动…...

机器学习之学习范式
机器学习的四种主要范式分别是:监督学习、非监督学习、强化学习和半监督学习。以下是每种范式的详细介绍: 1. 监督学习(Supervised Learning) 定义: 通过已标注的数据训练模型,以预测或分类未知数据。 目…...

PHPstudy中的数据库启动不了
法一 netstat -ano |findstr "3306" 查看占用该端口的进程号 taskkill /f /pid 6720 杀死进程 法二 sc delete mysql...

鸿蒙开发-ArkTS 创建自定义组件
在 ArkTS 中创建自定义组件是一个相对简单但功能强大的过程。以下是如何在 ArkTS 中创建和使用自定义组件的详细步骤: 一、定义自定义组件 使用Component注解:为了注册一个组件,使其能够在其他文件中被引用,你需要使用Component…...

记录学习《手动学习深度学习》这本书的笔记(五)
这一章是循环神经网络,太难了太难了,有很多卡壳的地方理解了好久,比如隐藏层和隐状态的区别、代码的含义(为此专门另写了一篇【笔记】记录对自主实现一个神经网络的步骤的理解)、梯度计算相关(【笔记】记录…...

【Qt】Qt+Visual Studio 2022环境开发
在使用Qt Creator的过程中,项目一大就会卡,所以我一般都是用VS开发Cmake开发, 在上一篇文章中,我已经安装了CMake,如果你没有安装就自己按一下。 记得配置Qt环境变量,不然CMake无法生成VS项目:…...

云计算HCIP-OpenStack04
书接上回: 云计算HCIP-OpenStack03-CSDN博客 12.Nova计算管理 Nova作为OpenStack的核心服务,最重要的功能就是提供对于计算资源的管理。 计算资源的管理就包含了已封装的资源和未封装的资源。已封装的资源就包含了虚拟机、容器。未封装的资源就是物理机提…...

HCIA-Access V2.5_3_2_VLAN数据转发
802.1Q的转发原则--Access-Link 首先看一下Access,对于Access端口来说, 它只属于一个VLAN,它的VLANID等于PVID。 首先看一下接收方向,前面说过交换机内部一定要带标签转发,所以当交换机接收到一个不带tag的数据帧时,会给它打上端…...

transformer学习笔记-导航
本系列专栏,主要是对transformer的基本原理做简要笔记,目前也是主要针对个人比较感兴趣的部分,包括:神经网络基本原理、词嵌入embedding、自注意力机制、多头注意力、位置编码、RoPE旋转位置编码等部分。transformer涉及的知识体系…...

功能篇:JAVA后端实现跨域配置
在Java后端实现跨域配置(CORS,Cross-Origin Resource Sharing)有多种方法,具体取决于你使用的框架。如果你使用的是Spring Boot或Spring MVC,可以通过以下几种方式来配置CORS。 ### 方法一:全局配置 对于所…...

防火墙内局域网特殊的Nginx基于stream模块进行四层协议转发模块的监听443 端口并将所有接收转发到目标服务器
在一些特殊场合下, 公司内部网络防火墙限制, 不能做端口映射, 此时可以使用nginx的做从四层协议转发, 只走tcp/ip协议, 而不走http方式, 可以做waf设置, 就可以做443, 或其它端口, 从而达到被直接转发到远程服务器效果 机房只映射了一个IP:22280, 而需求是这个SDK只能通过…...