当前位置: 首页 > news >正文

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()));}
}

六、系统特点

  1. 用户友好:直观的界面设计,操作简单便捷
  2. 实时响应:采用WebSocket实现实验室状态实时更新
  3. 高可用性:使用Redis缓存提升系统性能
  4. 安全可靠:完善的权限控制和数据加密机制

七、项目部署

环境要求

  • JDK 1.8+
  • Maven 3.6+
  • MySQL 5.7+
  • Redis 6.0+
  • Node.js 12+

部署步骤

  1. 数据库初始化
  2. 后端服务部署
  3. 前端项目打包
  4. Nginx配置

八、总结与展望

本项目实现了实验室预约管理的核心功能,通过现代化的技术栈,提供了良好的用户体验。未来计划添加以下功能:

  1. 引入人脸识别功能
  2. 集成物联网设备
  3. 开发移动端应用
  4. 添加数据分析功能

本文介绍了实验室预约管理系统的主要功能和技术实现,希望能为相似项目的开发提供参考。

实验室预约管理系统核心模块详解(上)

一、用户管理模块

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>

以上是用户管理模块和实验室管理模块的详细实现。包括了:

  1. 完整的数据库表设计
  2. 后端核心业务逻辑实现
  3. 前端组件示例代码

这些代码展示了基本的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>

以上是预约管理模块和系统管理模块的详细实现,包括:

  1. 完整的数据库表设计
  2. 后端核心服务实现
  3. 前端组件示例代码

这些代码展示了预约流程、审批流程、统计分析、系统配置、日志管理、数据备份等功能的具体实现方式。实际项目中还需要根据具体需求进行调整和扩展。

相关文章:

Java全栈项目:实验室预约管理系统的设计与实现

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

使用 esrally race 测试 Elasticsearch 性能及 Kibana 可视化分析指南

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

OpenAI 第七日 推出了一项新功能——ChatGPT的“Projects”

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

【小白51单片机专用教程】protues仿真AT89C51入门

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

正则表达式——元字符匹配(单字符)

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

快速在远程服务器执行命令、批量在多个服务器执行命令(基于sshpass的自定义脚本fastsh)

在日常服务器操作中&#xff0c;很多时候我们需要同时操作多个服务器。特别对于那些每个服务器都需要操作相同命令的场景&#xff0c;不断的切换命令会话窗口会比较麻烦。基于此&#xff0c;编写了本文中的 fastsh 脚本用于轻度解决这种问题&#xff0c;提高一定的便利性。 使…...

【中间件介绍及案例分析】

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

CRMEB PHP多商户版DOCKER部署实战

#首先&#xff0c;制作docker 镜像# 官方有一个镜像&#xff0c;但是拉不来下&#xff0c;也不知道是没是没有维护&#xff0c;嘎了。只能自己动手做一个。 这里选择ubuntu 24 为基础&#xff0c;制作crmeb-mer的镜像&#xff0c;Dockerfile内容如下&#xff1a; # 使用官方…...

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数据定义语言&#xff08;DDL&#xff09;概述1、DDL语法的作用2、Hive中DDL使用☆ 创建数据库☆ 查询数据库☆ 切换数据库☆ 修改数据库☆ 删除数据库 二、Hive DDL建表基础1、完整建表语法树2、H…...

vLLM 教程上新!覆盖从入门到进阶 4 种应用方式;中文文档同步上线,0 帧起手加速大模型推理

如今&#xff0c;大语言模型 (LLM) 的发展正在从规模参数迭代升级拓展至应用场景的适配与创新&#xff0c;在这个过程中&#xff0c;其也暴露出一系列问题。例如&#xff0c;在推理环节的效率较低&#xff0c;处理复杂任务时耗时较长&#xff0c;难以满足对实时性要求较高的场景…...

Kubernetes# RBAC访问控制

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

如何实现后端返回excel文件,在前端下载功能

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

编程:一场不设防的智慧江湖

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

电脑游戏运行时常见问题解析:穿越火线提示“unityplayer.dll丢失”的修复指南

电脑游戏运行时常见问题解析&#xff1a;穿越火线提示“unityplayer.dll丢失”的修复指南 在探索电脑游戏的无限乐趣时&#xff0c;我们时常会遇到一些不期而遇的挑战。今天&#xff0c;我们将聚焦于一个常见的游戏运行错误——穿越火线&#xff08;或其他使用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++

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

锂电池SOH预测 | 基于BiGRU双向门控循环单元的锂电池SOH预测,附锂电池最新文章汇集

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

半导体器件与物理篇5 1~4章课后习题

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

Pytest-Bdd-Playwright 系列教程(16):标准化JSON报告Gherkin格式命令行报告

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

机器学习之学习范式

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

PHPstudy中的数据库启动不了

法一 netstat -ano |findstr "3306" 查看占用该端口的进程号 taskkill /f /pid 6720 杀死进程 法二 sc delete mysql...

鸿蒙开发-ArkTS 创建自定义组件

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

记录学习《手动学习深度学习》这本书的笔记(五)

这一章是循环神经网络&#xff0c;太难了太难了&#xff0c;有很多卡壳的地方理解了好久&#xff0c;比如隐藏层和隐状态的区别、代码的含义&#xff08;为此专门另写了一篇【笔记】记录对自主实现一个神经网络的步骤的理解&#xff09;、梯度计算相关&#xff08;【笔记】记录…...

【Qt】Qt+Visual Studio 2022环境开发

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

云计算HCIP-OpenStack04

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

HCIA-Access V2.5_3_2_VLAN数据转发

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

transformer学习笔记-导航

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

功能篇:JAVA后端实现跨域配置

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

防火墙内局域网特殊的Nginx基于stream模块进行四层协议转发模块的监听443 端口并将所有接收转发到目标服务器

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