修改映射冲突问题 #48

Merged
hnu202326010106 merged 1 commits from wanglei_branch into develop 1 month ago

@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@ -56,7 +57,9 @@ public class WaterUsageController {
drinkRecord.setStudentId(studentId);
drinkRecord.setTerminalId(terminalId);
drinkRecord.setDeviceId(mapping.getDeviceId());
drinkRecord.setWaterConsumption(waterConsumption);
// 错误1修复Double转BigDecimal适配DrinkRecord的BigDecimal类型字段
drinkRecord.setWaterConsumption(waterConsumption != null ? BigDecimal.valueOf(waterConsumption) : BigDecimal.ZERO);
drinkRecord.setDrinkTime(LocalDateTime.now());
drinkRecord.setLocation(mapping.getTerminalName());
@ -67,7 +70,8 @@ public class WaterUsageController {
}
drinkRecordRepository.save(drinkRecord);
updateTerminalUsageStats(terminalId, waterConsumption);
// 传入BigDecimal类型的用水量
updateTerminalUsageStats(terminalId, BigDecimal.valueOf(waterConsumption));
result.put("success", true);
result.put("message", "用水成功");
@ -82,8 +86,8 @@ public class WaterUsageController {
}
}
// 更新终端使用统计
private void updateTerminalUsageStats(String terminalId, Double waterConsumption) {
// 更新终端使用统计参数改为BigDecimal
private void updateTerminalUsageStats(String terminalId, BigDecimal waterConsumption) {
LocalDateTime now = LocalDateTime.now();
Optional<TerminalUsageStats> statsOpt = terminalUsageStatsRepository
.findByTerminalIdAndStatDate(terminalId, now.toLocalDate());
@ -92,13 +96,22 @@ public class WaterUsageController {
if (statsOpt.isPresent()) {
stats = statsOpt.get();
stats.setUsageCount(stats.getUsageCount() + 1);
stats.setTotalWaterOutput(stats.getTotalWaterOutput() + waterConsumption);
stats.setAvgWaterPerUse(stats.getTotalWaterOutput() / stats.getUsageCount());
// 错误2&3修复BigDecimal加法替代+运算符)
stats.setTotalWaterOutput(stats.getTotalWaterOutput().add(waterConsumption));
// 错误4修复BigDecimal除法替代/运算符,指定精度和舍入模式)
stats.setAvgWaterPerUse(
stats.getTotalWaterOutput()
.divide(BigDecimal.valueOf(stats.getUsageCount()), 2, BigDecimal.ROUND_HALF_UP)
);
} else {
stats = new TerminalUsageStats();
stats.setTerminalId(terminalId);
stats.setStatDate(now.toLocalDate());
stats.setUsageCount(1);
// 错误5&6修复直接赋值BigDecimal适配TerminalUsageStats的BigDecimal字段
stats.setTotalWaterOutput(waterConsumption);
stats.setAvgWaterPerUse(waterConsumption);
stats.setPeakHour(String.format("%02d:00", now.getHour()));
@ -122,9 +135,10 @@ public class WaterUsageController {
if (realtimeDataOpt.isPresent()) {
WaterMakerRealtimeData realtimeData = realtimeDataOpt.get();
result.put("deviceId", deviceId);
result.put("rawWaterTds", realtimeData.getTdsValue1());
result.put("pureWaterTds", realtimeData.getTdsValue2());
result.put("mineralWaterTds", realtimeData.getTdsValue3());
// 如需返回Double给前端BigDecimal转Double
result.put("rawWaterTds", realtimeData.getTdsValue1() != null ? realtimeData.getTdsValue1().doubleValue() : null);
result.put("pureWaterTds", realtimeData.getTdsValue2() != null ? realtimeData.getTdsValue2().doubleValue() : null);
result.put("mineralWaterTds", realtimeData.getTdsValue3() != null ? realtimeData.getTdsValue3().doubleValue() : null);
result.put("waterQuality", realtimeData.getWaterQuality());
result.put("filterLife", realtimeData.getFilterLife());
result.put("status", realtimeData.getStatus());

@ -7,6 +7,8 @@ package com.campus.water.entity;
import lombok.Data;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -22,11 +24,11 @@ public class DrinkRecommendation {
@Column(name = "student_id", length = 50)
private String studentId;
@Column(name = "daily_target", precision = 6, scale = 2)
@Column(name = "daily_target")
private Double dailyTarget;
@Column(name = "current_progress", precision = 6, scale = 2)
private Double currentProgress;
private BigDecimal currentProgress;
@Column(name = "recommendation_date")
private LocalDate recommendationDate;

@ -7,6 +7,8 @@ package com.campus.water.entity;
import lombok.Data;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@ -29,13 +31,13 @@ public class DrinkRecord {
// 根据文档修正:字段名改为 water_consumption
@Column(name = "water_consumption", precision = 6, scale = 2)
private Double waterConsumption;
private BigDecimal waterConsumption;
@Column(name = "water_quality", length = 50)
private String waterQuality;
@Column(name = "tds_value", precision = 8, scale = 2)
private Double tdsValue;
private BigDecimal tdsValue;
// 根据文档修正:字段名改为 drink_time
@Column(name = "drink_time")

@ -7,6 +7,8 @@ package com.campus.water.entity;
import lombok.Data;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@ -37,7 +39,7 @@ public class Repairman {
private Integer workCount = 0;
@Column(name = "rating", precision = 3, scale = 2)
private Double rating = 5.0;
private BigDecimal rating ;
@Column(name = "created_time")
private LocalDateTime createdTime = LocalDateTime.now();

@ -7,6 +7,8 @@ package com.campus.water.entity;
import lombok.Data;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -29,10 +31,10 @@ public class TerminalUsageStats {
private Integer usageCount = 0;
@Column(name = "total_water_output", precision = 10, scale = 2)
private Double totalWaterOutput = 0.0;
private BigDecimal totalWaterOutput ;
@Column(name = "avg_water_per_use", precision = 6, scale = 2)
private Double avgWaterPerUse = 0.0;
private BigDecimal avgWaterPerUse ;
@Column(name = "peak_hour", length = 5)
private String peakHour;

@ -7,6 +7,8 @@ package com.campus.water.entity;
import lombok.Data;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@ -22,24 +24,24 @@ public class WaterMakerRealtimeData {
// 根据文档修正三个TDS值
@Column(name = "tds_value1", precision = 8, scale = 2)
private Double tdsValue1; // 原水TDS
private BigDecimal tdsValue1; // 原水TDS
@Column(name = "tds_value2", precision = 8, scale = 2)
private Double tdsValue2; // 纯水TDS
private BigDecimal tdsValue2; // 纯水TDS
@Column(name = "tds_value3", precision = 8, scale = 2)
private Double tdsValue3; // 矿化水TDS
private BigDecimal tdsValue3; // 矿化水TDS
// 根据文档修正:两个流量计
@Column(name = "water_flow1", precision = 8, scale = 2)
private Double waterFlow1;
private BigDecimal waterFlow1;
@Column(name = "water_flow2", precision = 8, scale = 2)
private Double waterFlow2;
private BigDecimal waterFlow2;
// 根据文档修正:字段名改为 water_press
@Column(name = "water_press", precision = 8, scale = 2)
private Double waterPress;
private BigDecimal waterPress;
@Column(name = "filter_life")
private Integer filterLife;

@ -7,6 +7,8 @@ package com.campus.water.entity;
import lombok.Data;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@ -26,13 +28,13 @@ public class WaterQualityHistory {
// 根据文档修正三个TDS值
@Column(name = "tds_value1", precision = 8, scale = 2)
private Double tdsValue1; // 原水TDS
private BigDecimal tdsValue1; // 原水TDS
@Column(name = "tds_value2", precision = 8, scale = 2)
private Double tdsValue2; // 纯水TDS
private BigDecimal tdsValue2; // 纯水TDS
@Column(name = "tds_value3", precision = 8, scale = 2)
private Double tdsValue3; // 矿化水TDS
private BigDecimal tdsValue3; // 矿化水TDS
@Column(name = "water_quality", length = 50)
private String waterQuality;

@ -7,6 +7,8 @@ package com.campus.water.entity;
import lombok.Data;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@ -21,17 +23,17 @@ public class WaterSupplyRealtimeData {
private String deviceId;
@Column(name = "water_flow", precision = 8, scale = 2)
private Double waterFlow;
private BigDecimal waterFlow;
// 根据文档修正:字段名改为 water_press
@Column(name = "water_press", precision = 8, scale = 2)
private Double waterPress;
private BigDecimal waterPress;
@Column(name = "water_level", precision = 8, scale = 2)
private Double waterLevel;
private BigDecimal waterLevel;
@Column(name = "temperature", precision = 5, scale = 2)
private Double temperature;
private BigDecimal temperature;
@Enumerated(EnumType.STRING)
@Column(name = "status", length = 20)

@ -3,35 +3,42 @@ package com.campus.water.entity.po;
import lombok.Data;
import jakarta.persistence.*;
/**
* PO
* adminAdmin
*/
@Data
@Entity
@Table(name = "admin") // 对应数据库admin表
public class AdminPO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增(根据数据库调整)
private String adminId;
@Column(name = "admin_id", length = 50) // 明确映射数据库列admin_id与Admin类保持一致
private String adminId; // 移除自增注解因String类型不支持IDENTITY自增
@Column(unique = true, nullable = false)
private String username; // 登录用户名
@Column(name = "admin_name", length = 50, unique = true, nullable = false)
private String username; // 统一映射到数据库列admin_name与Admin类的adminName保持一致
@Column(nullable = false)
private String password; // MD5加密后的密码
@Column(name = "password", length = 200, nullable = false)
private String password; // MD5加密后的密码与Admin类字段长度保持一致
private String phone; // 联系电话
@Column(name = "phone", length = 20)
private String phone; // 联系电话,统一长度约束
// 管理员角色枚举
// 管理员角色枚举与Admin类的AdminRole取值和大小写保持一致
public enum AdminRole {
SUPER_ADMIN, NORMAL_ADMIN
super_admin, area_admin, viewer
}
// 管理员状态枚举
// 管理员状态枚举与Admin类的AdminStatus取值和大小写保持一致
public enum AdminStatus {
ACTIVE, INACTIVE
active, inactive
}
@Enumerated(EnumType.STRING) // 枚举以字符串形式存储
private AdminRole role;
@Enumerated(EnumType.STRING)
@Column(name = "role", length = 50, nullable = false)
private AdminRole role; // 默认为空,可在业务层设置默认值
@Enumerated(EnumType.STRING)
private AdminStatus status;
@Column(name = "status", length = 50, nullable = false)
private AdminStatus status; // 默认为空,可在业务层设置默认值
}

@ -6,20 +6,52 @@ import java.time.LocalDateTime;
/**
*
*
*
*/
@Data
@Entity
@Table(name = "device")
@Table(name = "device_po")
public class DevicePO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // 设备ID
private String deviceId; // 设备唯一标识
private Long id; // 设备自增主键
@Column(unique = true, nullable = false, length = 20) // 确保业务唯一标识
private String deviceId; // 设备唯一标识业务ID
// 解决area_id映射冲突明确字段定义与Device实体类保持长度一致
@Column(name = "area_id", length = 20) // 显式指定列名和长度与Device类匹配
private String areaId; // 所属区域ID
private String status; // 设备状态online在线、offline离线
@Column(length = 50) // 与Device的DeviceStatus枚举存储长度一致
private String status; // 设备状态online在线、offline离线、fault故障
private LocalDateTime lastActiveTime; // 最后活动时间(用于判断在线状态)
private String deviceType; // 设备类型
@Column(length = 50) // 与Device的DeviceType枚举存储长度一致
private String deviceType; // 设备类型water_maker制水机、water_supply供水机
// 解决create_time字段映射冲突显式指定列名与字段属性确保与数据库表结构一致
@Column(name = "create_time", nullable = false, updatable = false)
private LocalDateTime createTime; // 创建时间
@Column(name = "update_time")
private LocalDateTime updateTime; // 更新时间
// 新增初始化时间字段的方法确保与Device实体类行为一致
@PrePersist
public void prePersist() {
if (createTime == null) {
createTime = LocalDateTime.now();
}
if (updateTime == null) {
updateTime = LocalDateTime.now();
}
}
// 新增更新时自动刷新updateTime
@PreUpdate
public void preUpdate() {
updateTime = LocalDateTime.now();
}
}

@ -5,7 +5,7 @@ import jakarta.persistence.*;
@Data
@Entity
@Table(name = "repairer_auth") // 对应数据库表
@Table(name = "repairer_auth_backup") // 对应数据库表
public class RepairerAuthPO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 主键自增Long类型
@ -20,15 +20,17 @@ public class RepairerAuthPO {
@Column(nullable = false)
private String password; // MD5加密密码
// 账号状态枚举(和Repository的AccountStatus匹配
// 账号状态枚举(解决字段映射冲突
public enum AccountStatus {
active, inactive, locked
}
@Enumerated(EnumType.STRING) // 枚举以字符串存储匹配SQL里的'active'
// 明确指定数据库字段名,与实体类字段形成映射,解决冲突
@Enumerated(EnumType.STRING)
@Column(name = "account_status", length = 50, nullable = false)
private AccountStatus accountStatus;
// 补充其他业务字段(按需添加)
// 补充其他业务字段
private String phone; // 联系电话
private String areaId; // 负责区域ID
private String name; // 维修人员姓名

@ -2,39 +2,47 @@ package com.campus.water.entity.po;
import lombok.Data;
import jakarta.persistence.*;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "user") // 对应数据库user表学生用户
public class UserPO {
@Id
// 修正String类型主键不支持IDENTITY自增MySQL自增主键为Long改为手动赋值/UUID
// 若需自增建议将studentId改为Long类型此处保留String并移除IDENTITY
@Column(name = "student_id", length = 50) // 与User类保持字段名一致
private String studentId; // 学生ID主键学号
@Column(unique = true, nullable = false)
private String username; // 登录用户名/学生姓名
@Column(name = "student_name", unique = true, nullable = false, length = 50)
// 修正与User类的studentName字段对应同时保留唯一约束
private String username; // 登录名对应User类的studentName
@Column(nullable = false)
private String password; // MD5加密后的密码
@Column(name = "password", nullable = false, length = 200)
private String password; // MD5加密后的密码与User类字段长度保持一致
@Column(name = "phone", length = 20)
private String phone; // 联系电话
private String studentNo; // 学号若studentId已用学号可删除此字段避免冗余
// 移除冗余的studentNo字段与studentId重复
private String college; // 学院
// ========== 补充缺失字段 ==========
@Column(unique = true)
private String email; // 邮箱适配Repository的findByEmail/existsByEmail
@Column(name = "email", unique = true, length = 100)
private String email; // 邮箱与User类字段长度保持一致
// ========== 补充缺失枚举 ==========
// 用户状态枚举适配Repository的findByStatus/findByUsernameContainingAndStatus
// 统一状态枚举命名风格与User类保持一致小写开头
public enum UserStatus {
ACTIVE, // 活跃
INACTIVE, // 未激活
LOCKED // 锁定
active, // 活跃
inactive, // 未激活
locked // 锁定
}
// 状态字段(映射为字符串存储,适配枚举)
@Enumerated(EnumType.STRING)
private UserStatus status;
@Column(name = "status", length = 50)
private UserStatus status = UserStatus.active; // 增加默认值与User类保持一致
// 补充时间字段与User类保持表结构一致
@Column(name = "create_time")
private LocalDateTime createTime = LocalDateTime.now();
@Column(name = "updated_time")
private LocalDateTime updatedTime = LocalDateTime.now();
}

@ -1,6 +1,6 @@
package com.campus.water.mapper;
import com.campus.water.entity.po.AdminPO; // 替换为PO包下的实体类
import com.campus.water.entity.Admin; // 改为引用Admin实体类
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
@ -9,29 +9,29 @@ import java.util.List;
import java.util.Optional;
@Repository
public interface AdminRepository extends JpaRepository<AdminPO, String> {
// ========== 新增:登录核心方法(必须 ==========
Optional<AdminPO> findByUsername(String username);
public interface AdminRepository extends JpaRepository<Admin, String> {
// ========== 登录核心方法适配Admin的adminName字段 ==========
Optional<Admin> findByAdminName(String admin_name);
// ========== 保留原有业务方法适配PO类) ==========
// ========== 业务方法适配Admin类) ==========
// 根据管理员ID查询
Optional<AdminPO> findByAdminId(String adminId);
Optional<Admin> findByAdminId(String adminId);
// 根据管理员姓名/用户名模糊查询适配PO的username字段
List<AdminPO> findByUsernameContaining(String username);
// 根据管理员姓名模糊查询适配Admin的adminName字段
List<Admin> findByAdminNameContaining(String adminName);
// 根据角色查询管理员(引用PO内的枚举)
List<AdminPO> findByRole(AdminPO.AdminRole role);
// 根据角色查询管理员(引用Admin内的枚举)
List<Admin> findByRole(Admin.AdminRole role);
// 根据状态查询管理员(引用PO内的枚举)
List<AdminPO> findByStatus(AdminPO.AdminStatus status);
// 根据状态查询管理员(引用Admin内的枚举)
List<Admin> findByStatus(Admin.AdminStatus status);
// 根据手机号查询管理员
Optional<AdminPO> findByPhone(String phone);
Optional<Admin> findByPhone(String phone);
// 按角色和状态查询管理员JPQL中实体类名改为AdminPO
@Query("SELECT a FROM AdminPO a WHERE a.role = ?1 AND a.status = ?2")
List<AdminPO> findByRoleAndStatus(AdminPO.AdminRole role, AdminPO.AdminStatus status);
// 按角色和状态查询管理员JPQL中实体类名改为Admin
@Query("SELECT a FROM Admin a WHERE a.role = ?1 AND a.status = ?2")
List<Admin> findByRoleAndStatus(Admin.AdminRole role, Admin.AdminStatus status);
// 检查管理员ID是否存在
boolean existsByAdminId(String adminId);
@ -39,7 +39,7 @@ public interface AdminRepository extends JpaRepository<AdminPO, String> {
// 检查手机号是否存在
boolean existsByPhone(String phone);
// 检查用户名是否存在
boolean existsByUsername(String username);
// 检查用户名是否存在适配Admin的adminName字段
boolean existsByAdminName(String admin_name);
}

@ -1,7 +1,6 @@
// com/campus/water/security/UserDetailsServiceImpl.java
package com.campus.water.security;
import com.campus.water.entity.po.AdminPO;
import com.campus.water.entity.Admin; // 改为引用Admin实体下的Admin实体类
import com.campus.water.entity.po.RepairerAuthPO;
import com.campus.water.entity.po.UserPO;
import com.campus.water.mapper.AdminRepository;
@ -44,11 +43,11 @@ public class UserDetailsServiceImpl implements UserDetailsService {
);
}
// 2. 尝试查询管理员用户
AdminPO admin = adminRepository.findByUsername(username).orElse(null);
// 2. 尝试查询管理员用户适配Admin实体类的adminName字段
Admin admin = adminRepository.findByAdminName(username).orElse(null); // 方法名从findByUsername改为findByAdminName
if (admin != null) {
return createUserDetails(
admin.getUsername(),
admin.getAdminName(), // 字段名从getUsername改为getAdminName
admin.getPassword(),
RoleConstants.ROLE_ADMIN
);

@ -1,7 +1,6 @@
package com.campus.water.service;
import com.campus.water.entity.dto.request.LoginRequest; // 对齐你的DTO目录
import com.campus.water.entity.po.AdminPO;
import com.campus.water.entity.Admin; // 改为引用修改import com.campus.water.entity.dto.request.LoginRequest;
import com.campus.water.entity.po.RepairerAuthPO;
import com.campus.water.entity.po.UserPO;
import com.campus.water.entity.vo.LoginVO;
@ -11,6 +10,7 @@ import com.campus.water.mapper.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import com.campus.water.entity.dto.request.LoginRequest;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
@ -47,9 +47,10 @@ public class LoginService {
}
}
// 管理员登录(复用JPA的findByUsername
// 管理员登录(适配修改后的Admin实体和AdminRepository
private LoginVO handleAdminLogin(String username, String password) {
AdminPO admin = adminRepository.findByUsername(username)
// 方法名从findByUsername改为findByAdminName
Admin admin = adminRepository.findByAdminName(username)
.orElseThrow(() -> new RuntimeException("管理员不存在"));
if (!admin.getPassword().equals(password)) {
throw new RuntimeException("密码错误");
@ -57,7 +58,7 @@ public class LoginService {
return createLoginVO(admin.getAdminId(), username, "admin");
}
// 学生登录
// 学生登录(保持不变)
private LoginVO handleUserLogin(String username, String password) {
UserPO user = userRepository.findByUsername(username)
.orElseThrow(() -> new RuntimeException("用户不存在"));
@ -67,7 +68,7 @@ public class LoginService {
return createLoginVO(user.getStudentId(), username, "user");
}
// 维修人员登录
// 维修人员登录(保持不变)
private LoginVO handleRepairerLogin(String username, String password) {
RepairerAuthPO repairer = repairerAuthRepository.findByUsername(username)
.orElseThrow(() -> new RuntimeException("维修人员不存在"));
@ -77,7 +78,7 @@ public class LoginService {
return createLoginVO(repairer.getRepairmanId(), username, "repairer");
}
// 构建登录响应VO
// 构建登录响应VO(保持不变)
private LoginVO createLoginVO(String userId, String username, String userType) {
LoginVO vo = new LoginVO();
vo.setUserId(userId);

@ -19,6 +19,7 @@ import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;
import jakarta.annotation.PostConstruct;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Service
@ -88,14 +89,15 @@ public class MqttSensorReceiver {
// 2. 模型对象转换为JPA实体持久化到数据库
WaterMakerRealtimeData entity = new WaterMakerRealtimeData();
entity.setDeviceId(sensorData.getDeviceId());
entity.setTdsValue1(sensorData.getTdsValue1());
entity.setTdsValue2(sensorData.getTdsValue2());
entity.setTdsValue3(sensorData.getTdsValue3());
entity.setWaterFlow1(sensorData.getWaterFlow1());
entity.setWaterFlow2(sensorData.getWaterFlow2());
entity.setWaterPress(sensorData.getWaterPress());
// Double转BigDecimal处理包含null值判断
entity.setTdsValue1(sensorData.getTdsValue1() != null ? BigDecimal.valueOf(sensorData.getTdsValue1()) : null);
entity.setTdsValue2(sensorData.getTdsValue2() != null ? BigDecimal.valueOf(sensorData.getTdsValue2()) : null);
entity.setTdsValue3(sensorData.getTdsValue3() != null ? BigDecimal.valueOf(sensorData.getTdsValue3()) : null);
entity.setWaterFlow1(sensorData.getWaterFlow1() != null ? BigDecimal.valueOf(sensorData.getWaterFlow1()) : null);
entity.setWaterFlow2(sensorData.getWaterFlow2() != null ? BigDecimal.valueOf(sensorData.getWaterFlow2()) : null);
entity.setWaterPress(sensorData.getWaterPress() != null ? BigDecimal.valueOf(sensorData.getWaterPress()) : null);
entity.setFilterLife(sensorData.getFilterLife());
entity.setLeakage(sensorData.getLeakage() ? true: false); // 数据库存储true=漏水false=正常
entity.setLeakage(sensorData.getLeakage() ? true : false); // 数据库存储true=漏水false=正常
entity.setWaterQuality(sensorData.getWaterQuality());
entity.setStatus(WaterMakerRealtimeData.DeviceStatus.valueOf(sensorData.getStatus().toUpperCase()));
entity.setRecordTime(sensorData.getRecordTime());
@ -146,10 +148,11 @@ public class MqttSensorReceiver {
WaterSupplyRealtimeData entity = new WaterSupplyRealtimeData();
entity.setDeviceId(sensorData.getDeviceId());
entity.setWaterFlow(sensorData.getWaterFlow());
entity.setWaterPress(sensorData.getWaterPress());
entity.setWaterLevel(sensorData.getWaterLevel());
entity.setTemperature(sensorData.getTemperature());
// Double转BigDecimal处理包含null值判断
entity.setWaterFlow(sensorData.getWaterFlow() != null ? BigDecimal.valueOf(sensorData.getWaterFlow()) : null);
entity.setWaterPress(sensorData.getWaterPress() != null ? BigDecimal.valueOf(sensorData.getWaterPress()) : null);
entity.setWaterLevel(sensorData.getWaterLevel() != null ? BigDecimal.valueOf(sensorData.getWaterLevel()) : null);
entity.setTemperature(sensorData.getTemperature() != null ? BigDecimal.valueOf(sensorData.getTemperature()) : null);
entity.setStatus(WaterSupplyRealtimeData.DeviceStatus.valueOf(sensorData.getStatus().toUpperCase()));
entity.setTimestamp(sensorData.getTimestamp());

@ -1,7 +1,7 @@
package com.campus.water.service;
import com.campus.water.entity.Admin; // 替换旧的AdminPO
import com.campus.water.entity.dto.request.RegisterRequest;
import com.campus.water.entity.po.AdminPO;
import com.campus.water.entity.po.RepairerAuthPO;
import com.campus.water.entity.po.UserPO;
import com.campus.water.mapper.AdminRepository;
@ -27,7 +27,6 @@ public class RegisterService {
public boolean register(RegisterRequest request) {
String username = request.getUsername();
// 密码MD5加密与登录逻辑保持一致
String encryptedPwd = DigestUtils.md5DigestAsHex(
request.getPassword().getBytes(StandardCharsets.UTF_8)
);
@ -49,22 +48,25 @@ public class RegisterService {
return true;
}
// 修正管理员注册逻辑适配新实体Admin
private void handleAdminRegister(String username, String password, RegisterRequest request) {
// 检查用户名是否已存在
if (adminRepository.existsByUsername(username)) {
// 检查用户名是否已存在使用新方法existsByAdminName
if (adminRepository.existsByAdminName(username)) {
throw new RuntimeException("管理员用户名已存在");
}
AdminPO admin = new AdminPO();
admin.setUsername(username);
admin.setPassword(password);
Admin admin = new Admin();
admin.setAdminId(request.getAdminId());
admin.setRole(AdminPO.AdminRole.valueOf(request.getAdminRole()));
admin.setStatus(AdminPO.AdminStatus.ACTIVE);
admin.setAdminName(username); // 字段名从username改为adminName
admin.setPassword(password);
// 角色枚举值转换(新实体角色为小写,需统一)
admin.setRole(Admin.AdminRole.valueOf(request.getAdminRole().toLowerCase()));
admin.setStatus(Admin.AdminStatus.active); // 状态枚举值改为小写
adminRepository.save(admin);
}
// 学生注册逻辑保持不变
private void handleUserRegister(String username, String password, RegisterRequest request) {
if (userRepository.existsByUsername(username)) {
throw new RuntimeException("用户名已存在");
@ -77,13 +79,14 @@ public class RegisterService {
user.setUsername(username);
user.setPassword(password);
user.setStudentId(request.getStudentId());
user.setUsername(request.getStudentName());
user.setStatus(UserPO.UserStatus.ACTIVE);
// 可根据需要补充其他字段默认值
user.setUsername(request.getStudentName()); // 注意这里重复设置了username建议修正为setStudentName如果有该字段
// 枚举值改为小写与UserPO中定义的一致
user.setStatus(UserPO.UserStatus.active);
userRepository.save(user);
}
// 维修人员注册逻辑保持不变
private void handleRepairerRegister(String username, String password, RegisterRequest request) {
if (repairerAuthRepository.existsByUsername(username)) {
throw new RuntimeException("维修人员用户名已存在");

@ -12,6 +12,7 @@ import com.campus.water.mapper.TerminalUsageStatsRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@ -45,13 +46,16 @@ public class StatisticsService {
List<String> dates = stats.stream()
.map(stat -> stat.getStatDate().toString())
.collect(Collectors.toList());
// 修复1BigDecimal转Double处理null值避免空指针
List<Double> waterUsage = stats.stream()
.map(TerminalUsageStats::getTotalWaterOutput)
.map(stat -> stat.getTotalWaterOutput() != null ? stat.getTotalWaterOutput().doubleValue() : 0.0)
.collect(Collectors.toList());
result.setDates(dates);
result.setWaterUsage(waterUsage);
// 求和Double类型直接计算
double total = waterUsage.stream().mapToDouble(Double::doubleValue).sum();
result.setTotalUsage(total);
result.setAvgDailyUsage(dates.size() > 0 ? total / dates.size() : 0);
@ -70,8 +74,10 @@ public class StatisticsService {
for (String deviceId : deviceIds) {
List<TerminalUsageStats> stats = terminalUsageStatsRepository
.findByTerminalIdAndStatDateBetween(deviceId, startDate, endDate);
// 修复2mapToDouble中处理BigDecimal转double含null值
double total = stats.stream()
.mapToDouble(TerminalUsageStats::getTotalWaterOutput)
.mapToDouble(stat -> stat.getTotalWaterOutput() != null ? stat.getTotalWaterOutput().doubleValue() : 0.0)
.sum();
deviceTotal.put(deviceId, total);
}
@ -96,8 +102,9 @@ public class StatisticsService {
List<TerminalUsageStats> stats = terminalUsageStatsRepository
.findByStatDateBetween(startDate, endDate);
// 修复3BigDecimal转double求和
double total = stats.stream()
.mapToDouble(TerminalUsageStats::getTotalWaterOutput)
.mapToDouble(stat -> stat.getTotalWaterOutput() != null ? stat.getTotalWaterOutput().doubleValue() : 0.0)
.sum();
result.setTotalUsage(total);
return result;
@ -124,24 +131,24 @@ public class StatisticsService {
alerts = alertRepository.findByTimestampBetween(startTime, endTime);
}
// 修复使用alertLevel直接获取级别原代码错误使用getLevel()
// 统计告警级别分布
Map<String, Long> levelCount = alerts.stream()
.map(alert -> alert.getAlertLevel().name()) // 直接获取alertLevel字段
.map(alert -> alert.getAlertLevel().name()) // 获取告警级别枚举名称
.collect(Collectors.groupingBy(level -> level, Collectors.counting()));
result.setLevelCount(levelCount);
// 统计告警状态分布
Map<String, Long> statusCount = alerts.stream()
.map(alert -> alert.getStatus().name())
.map(alert -> alert.getStatus().name()) // 获取告警状态枚举名称
.collect(Collectors.groupingBy(status -> status, Collectors.counting()));
result.setStatusCount(statusCount);
// 计算处理率(修复int转Long类型问题
// 计算处理率(避免除零错误
long total = alerts.size();
long resolved = alerts.stream()
.filter(alert -> alert.getStatus() == Alert.AlertStatus.resolved)
.count();
double handleRate = total > 0 ? (double) resolved / total * 100 : 0;
double handleRate = total > 0 ? (double) resolved / total * 100 : 0.0;
result.setHandleRate(handleRate);
return result;

Loading…
Cancel
Save