diff --git a/src/main/java/com/campus/water/controller/RepairmanNotificationController.java b/src/main/java/com/campus/water/controller/RepairmanNotificationController.java new file mode 100644 index 0000000..8d45fb3 --- /dev/null +++ b/src/main/java/com/campus/water/controller/RepairmanNotificationController.java @@ -0,0 +1,66 @@ +package com.campus.water.controller; + +import com.campus.water.entity.Notification; +import com.campus.water.service.NotificationService; +import com.campus.water.util.ResultVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 维修人员通知专属控制器 + * 负责APP端通知相关接口,与原有维修人员控制器解耦 + */ +@RestController +@RequestMapping("/api/app/repairman/notification") +@RequiredArgsConstructor +@Tag(name = "维修人员通知接口", description = "维修人员APP端通知查询/已读标记接口") +public class RepairmanNotificationController { + + private final NotificationService notificationService; + + /** + * 获取维修人员未读通知 + */ + @GetMapping("/unread") + @Operation(summary = "获取未读通知", description = "查询维修人员所有未读的派单/系统通知") + public ResultVO> getUnreadNotifications(@RequestParam String repairmanId) { + try { + List unreadNotifications = notificationService.getUnreadNotifications(repairmanId); + return ResultVO.success(unreadNotifications, "获取未读通知成功"); + } catch (Exception e) { + return ResultVO.error(500, "获取未读通知失败:" + e.getMessage()); + } + } + + /** + * 获取维修人员所有通知 + */ + @GetMapping("/all") + @Operation(summary = "获取所有通知", description = "查询维修人员所有通知(已读+未读)") + public ResultVO> getAllNotifications(@RequestParam String repairmanId) { + try { + List allNotifications = notificationService.getAllNotifications(repairmanId); + return ResultVO.success(allNotifications, "获取所有通知成功"); + } catch (Exception e) { + return ResultVO.error(500, "获取所有通知失败:" + e.getMessage()); + } + } + + /** + * 标记通知为已读 + */ + @PostMapping("/read") + @Operation(summary = "标记通知为已读", description = "将指定通知标记为已读状态") + public ResultVO markNotificationAsRead(@RequestParam Long notificationId) { + try { + notificationService.markAsRead(notificationId); + return ResultVO.success(true, "标记通知为已读成功"); + } catch (Exception e) { + return ResultVO.error(500, "标记通知为已读失败:" + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/controller/StudentDrinkStatsController.java b/src/main/java/com/campus/water/controller/StudentDrinkStatsController.java new file mode 100644 index 0000000..5ffc43c --- /dev/null +++ b/src/main/java/com/campus/water/controller/StudentDrinkStatsController.java @@ -0,0 +1,56 @@ +package com.campus.water.controller; + +import com.campus.water.entity.dto.request.StudentDrinkQueryDTO; +import com.campus.water.entity.vo.StudentDrinkStatsVO; +import com.campus.water.service.StudentDrinkStatsService; +import com.campus.water.util.ResultVO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 学生饮水量统计接口 + */ +@RestController +@RequestMapping("/api/student/drink-stats") +@RequiredArgsConstructor +@Tag(name = "学生端-饮水量统计", description = "学生查看本日/本周/本月饮水量") +public class StudentDrinkStatsController { + + private final StudentDrinkStatsService drinkStatsService; + + @PostMapping("/today") + @Operation(summary = "查询本日饮水量", description = "获取学生当日的饮水量、次数及明细") + public ResultVO getTodayStats(@RequestBody StudentDrinkQueryDTO request) { + // 手动校验学生ID非空 + if (request.getStudentId() == null || request.getStudentId().trim().isEmpty()) { + return ResultVO.badRequest("学生ID不能为空"); + } + StudentDrinkStatsVO stats = drinkStatsService.getTodayDrinkStats(request.getStudentId()); + return ResultVO.success(stats, "查询本日饮水量成功"); + } + + @PostMapping("/this-week") + @Operation(summary = "查询本周饮水量", description = "获取学生本周的饮水量、日均量及每日明细") + public ResultVO getThisWeekStats(@RequestBody StudentDrinkQueryDTO request) { + if (request.getStudentId() == null || request.getStudentId().trim().isEmpty()) { + return ResultVO.badRequest("学生ID不能为空"); + } + StudentDrinkStatsVO stats = drinkStatsService.getThisWeekDrinkStats(request.getStudentId()); + return ResultVO.success(stats, "查询本周饮水量成功"); + } + + @PostMapping("/this-month") + @Operation(summary = "查询本月饮水量", description = "获取学生本月的饮水量、日均量及每日明细") + public ResultVO getThisMonthStats(@RequestBody StudentDrinkQueryDTO request) { + if (request.getStudentId() == null || request.getStudentId().trim().isEmpty()) { + return ResultVO.badRequest("学生ID不能为空"); + } + StudentDrinkStatsVO stats = drinkStatsService.getThisMonthDrinkStats(request.getStudentId()); + return ResultVO.success(stats, "查询本月饮水量成功"); + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/entity/Notification.java b/src/main/java/com/campus/water/entity/Notification.java new file mode 100644 index 0000000..7c592ab --- /dev/null +++ b/src/main/java/com/campus/water/entity/Notification.java @@ -0,0 +1,51 @@ +package com.campus.water.entity; + +import lombok.Data; +import jakarta.persistence.*; +import java.time.LocalDateTime; + +/** + * 维修人员通知实体 + * 存储派单、系统通知等消息 + */ +@Data +@Entity +@Table(name = "notification") +public class Notification { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + /** 维修人员ID */ + @Column(name = "repairman_id", nullable = false, length = 50) + private String repairmanId; + + /** 关联工单ID */ + @Column(name = "order_id", length = 50) + private String orderId; + + /** 通知内容 */ + @Column(name = "content", nullable = false, length = 500) + private String content; + + /** 是否已读(默认未读) */ + @Column(name = "is_read") + private boolean isRead = false; + + /** 创建时间 */ + @Column(name = "created_time", nullable = false) + private LocalDateTime createdTime = LocalDateTime.now(); + + /** 通知类型 */ + @Enumerated(EnumType.STRING) + @Column(name = "type", nullable = false, length = 20) + private NotificationType type; + + /** 通知类型枚举 */ + public enum NotificationType { + ORDER_ASSIGNED, // 派单通知 + ORDER_GRABBED, // 抢单通知 + ORDER_REJECTED, // 拒单通知 + SYSTEM // 系统通知 + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/entity/dto/request/StudentDrinkQueryDTO.java b/src/main/java/com/campus/water/entity/dto/request/StudentDrinkQueryDTO.java new file mode 100644 index 0000000..fbad794 --- /dev/null +++ b/src/main/java/com/campus/water/entity/dto/request/StudentDrinkQueryDTO.java @@ -0,0 +1,12 @@ +package com.campus.water.entity.dto.request; + +import lombok.Data; + +/** + * 学生饮水量查询请求DTO + */ +@Data +public class StudentDrinkQueryDTO { + /** 学生ID */ + private String studentId; +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/entity/vo/DailyDrinkVO.java b/src/main/java/com/campus/water/entity/vo/DailyDrinkVO.java new file mode 100644 index 0000000..16890f3 --- /dev/null +++ b/src/main/java/com/campus/water/entity/vo/DailyDrinkVO.java @@ -0,0 +1,16 @@ +package com.campus.water.entity.vo; + +import lombok.Data; + +/** + * 每日饮水量明细VO + */ +@Data +public class DailyDrinkVO { + /** 日期(yyyy-MM-dd) */ + private String date; + /** 当日饮水量(升) */ + private Double consumption; + /** 当日饮水次数 */ + private Integer count; +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/entity/vo/StudentDrinkStatsVO.java b/src/main/java/com/campus/water/entity/vo/StudentDrinkStatsVO.java new file mode 100644 index 0000000..a09fecc --- /dev/null +++ b/src/main/java/com/campus/water/entity/vo/StudentDrinkStatsVO.java @@ -0,0 +1,28 @@ +package com.campus.water.entity.vo; + +import lombok.Data; +import java.util.List; +import com.campus.water.entity.DrinkRecord; +import com.campus.water.entity.vo.DailyDrinkVO; +/** + * 学生饮水量统计结果VO + */ +@Data +public class StudentDrinkStatsVO { + /** 学生ID */ + private String studentId; + /** 统计维度(本日/本周/本月) */ + private String timeDimension; + /** 统计时间范围(如"2025-12-25~2025-12-25") */ + private String timeRange; + /** 总饮水量(升) */ + private Double totalConsumption; + /** 日均饮水量(升) */ + private Double avgDailyConsumption; + /** 饮水次数 */ + private Integer drinkCount; + /** 按日期分组的每日饮水量明细 */ + private List dailyDetails; + /** 所有饮水记录明细 */ + private List drinkRecords; +} diff --git a/src/main/java/com/campus/water/mapper/NotificationRepository.java b/src/main/java/com/campus/water/mapper/NotificationRepository.java new file mode 100644 index 0000000..e8bf9d1 --- /dev/null +++ b/src/main/java/com/campus/water/mapper/NotificationRepository.java @@ -0,0 +1,22 @@ +package com.campus.water.mapper; + +import com.campus.water.entity.Notification; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.List; + +/** + * 通知数据访问层 + */ +@Repository +public interface NotificationRepository extends JpaRepository { + /** + * 查询维修人员未读通知(按创建时间倒序) + */ + List findByRepairmanIdAndIsReadFalseOrderByCreatedTimeDesc(String repairmanId); + + /** + * 查询维修人员所有通知(按创建时间倒序) + */ + List findByRepairmanIdOrderByCreatedTimeDesc(String repairmanId); +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/service/NotificationService.java b/src/main/java/com/campus/water/service/NotificationService.java new file mode 100644 index 0000000..6fddd6c --- /dev/null +++ b/src/main/java/com/campus/water/service/NotificationService.java @@ -0,0 +1,37 @@ +package com.campus.water.service; + +import com.campus.water.entity.Notification; +import java.util.List; + +/** + * 维修人员通知服务接口 + */ +public interface NotificationService { + /** + * 发送派单通知 + * @param repairmanId 维修人员ID + * @param orderId 工单ID + * @param content 通知内容 + */ + void sendOrderAssignedNotification(String repairmanId, String orderId, String content); + + /** + * 获取维修人员未读通知 + * @param repairmanId 维修人员ID + * @return 未读通知列表 + */ + List getUnreadNotifications(String repairmanId); + + /** + * 获取维修人员所有通知 + * @param repairmanId 维修人员ID + * @return 所有通知列表 + */ + List getAllNotifications(String repairmanId); + + /** + * 标记通知为已读 + * @param notificationId 通知ID + */ + void markAsRead(Long notificationId); +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/service/NotificationServiceImpl.java b/src/main/java/com/campus/water/service/NotificationServiceImpl.java new file mode 100644 index 0000000..9af8e5c --- /dev/null +++ b/src/main/java/com/campus/water/service/NotificationServiceImpl.java @@ -0,0 +1,59 @@ +package com.campus.water.service.impl; + +import com.campus.water.entity.Notification; +import com.campus.water.mapper.NotificationRepository; +import com.campus.water.service.NotificationService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 通知服务实现类 + */ +@Service +@RequiredArgsConstructor +public class NotificationServiceImpl implements NotificationService { + + private final NotificationRepository notificationRepository; + + /** + * 发送派单通知 + */ + @Override + public void sendOrderAssignedNotification(String repairmanId, String orderId, String content) { + Notification notification = new Notification(); + notification.setRepairmanId(repairmanId); + notification.setOrderId(orderId); + notification.setContent(content); + notification.setType(Notification.NotificationType.ORDER_ASSIGNED); + notificationRepository.save(notification); + } + + /** + * 获取未读通知 + */ + @Override + public List getUnreadNotifications(String repairmanId) { + return notificationRepository.findByRepairmanIdAndIsReadFalseOrderByCreatedTimeDesc(repairmanId); + } + + /** + * 获取所有通知 + */ + @Override + public List getAllNotifications(String repairmanId) { + return notificationRepository.findByRepairmanIdOrderByCreatedTimeDesc(repairmanId); + } + + /** + * 标记通知为已读 + */ + @Override + public void markAsRead(Long notificationId) { + notificationRepository.findById(notificationId).ifPresent(notification -> { + notification.setRead(true); + notificationRepository.save(notification); + }); + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/service/StudentDrinkStatsService.java b/src/main/java/com/campus/water/service/StudentDrinkStatsService.java new file mode 100644 index 0000000..5d01331 --- /dev/null +++ b/src/main/java/com/campus/water/service/StudentDrinkStatsService.java @@ -0,0 +1,105 @@ +package com.campus.water.service; + +import com.campus.water.entity.DrinkRecord; +import com.campus.water.entity.vo.DailyDrinkVO; +import com.campus.water.entity.vo.StudentDrinkStatsVO; +import com.campus.water.mapper.DrinkRecordRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import java.math.BigDecimal; +import java.time.*; +import java.time.temporal.TemporalAdjusters; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 学生饮水量统计服务 + */ +@Service +@RequiredArgsConstructor +public class StudentDrinkStatsService { + + private final DrinkRecordRepository drinkRecordRepository; + + /** + * 查询学生本日饮水量统计 + */ + public StudentDrinkStatsVO getTodayDrinkStats(String studentId) { + LocalDate today = LocalDate.now(); + LocalDateTime start = today.atStartOfDay(); + LocalDateTime end = LocalDateTime.now(); + return calculateStats(studentId, start, end, "本日", "today"); + } + + /** + * 查询学生本周饮水量统计 + */ + public StudentDrinkStatsVO getThisWeekDrinkStats(String studentId) { + LocalDate today = LocalDate.now(); + LocalDateTime start = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).atStartOfDay(); + LocalDateTime end = LocalDateTime.now(); + return calculateStats(studentId, start, end, "本周", "thisWeek"); + } + + /** + * 查询学生本月饮水量统计 + */ + public StudentDrinkStatsVO getThisMonthDrinkStats(String studentId) { + LocalDate today = LocalDate.now(); + LocalDateTime start = today.with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay(); + LocalDateTime end = LocalDateTime.now(); + return calculateStats(studentId, start, end, "本月", "thisMonth"); + } + + /** + * 核心统计逻辑 + */ + private StudentDrinkStatsVO calculateStats(String studentId, LocalDateTime start, LocalDateTime end, + String timeRangeDesc, String timeDimension) { + // 1. 查询时间范围内的饮水记录 + List records = drinkRecordRepository + .findByStudentIdAndDrinkTimeBetweenOrdered(studentId, start, end); + + // 2. 按日期分组统计 + Map> dailyGroup = records.stream() + .collect(Collectors.groupingBy(record -> record.getDrinkTime().toLocalDate())); + + // 3. 构建每日明细 + List dailyDetails = new ArrayList<>(); + dailyGroup.forEach((date, dailyRecords) -> { + DailyDrinkVO dailyVO = new DailyDrinkVO(); + dailyVO.setDate(date.toString()); + // 当日总饮水量 + double dailyTotal = dailyRecords.stream() + .map(DrinkRecord::getWaterConsumption) + .filter(Objects::nonNull) + .mapToDouble(BigDecimal::doubleValue) + .sum(); + dailyVO.setConsumption(dailyTotal); + dailyVO.setCount(dailyRecords.size()); + dailyDetails.add(dailyVO); + }); + // 按日期排序 + dailyDetails.sort(Comparator.comparing(DailyDrinkVO::getDate)); + + // 4. 计算总饮水量、总次数、日均饮水量 + double totalConsumption = dailyDetails.stream() + .mapToDouble(DailyDrinkVO::getConsumption) + .sum(); + int totalCount = records.size(); + double avgDaily = dailyDetails.isEmpty() ? 0 : totalConsumption / dailyDetails.size(); + + // 5. 封装结果VO + StudentDrinkStatsVO statsVO = new StudentDrinkStatsVO(); + statsVO.setStudentId(studentId); + statsVO.setTimeDimension(timeDimension); + statsVO.setTimeRange(timeRangeDesc + "(" + start.toLocalDate() + "~" + end.toLocalDate() + ")"); + statsVO.setTotalConsumption(totalConsumption); + statsVO.setDrinkCount(totalCount); + statsVO.setAvgDailyConsumption(avgDaily); + statsVO.setDailyDetails(dailyDetails); + statsVO.setDrinkRecords(records); + + return statsVO; + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/water/service/WorkOrderServiceImpl.java b/src/main/java/com/campus/water/service/WorkOrderServiceImpl.java index b9b1fa4..b5382ea 100644 --- a/src/main/java/com/campus/water/service/WorkOrderServiceImpl.java +++ b/src/main/java/com/campus/water/service/WorkOrderServiceImpl.java @@ -9,7 +9,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; - +import com.campus.water.service.NotificationService; +import com.campus.water.service.WorkOrderService; import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; @@ -28,6 +29,7 @@ public class WorkOrderServiceImpl implements WorkOrderService { private final WorkOrderRepository workOrderRepository; private final RepairmanRepository repairmanRepository; + private final NotificationService notificationService; @Override public WorkOrder getOrderDetail(String orderId) { @@ -288,6 +290,16 @@ public class WorkOrderServiceImpl implements WorkOrderService { order.setGrabbedTime(LocalDateTime.now()); workOrderRepository.save(order); + // ===== 新增:派单通知 ===== + try { + String notificationContent = String.format("您有新的维修工单待处理!工单ID:%s", orderId); + notificationService.sendOrderAssignedNotification(repairmanId, orderId, notificationContent); + } catch (Exception e) { + // 捕获异常,不影响原有派单逻辑 + System.err.println("派单通知发送失败:" + e.getMessage()); + } + // ============================================== + // 更新维修人员状态 Repairman repairman = repairmanOpt.get(); repairman.setStatus(Repairman.RepairmanStatus.busy); diff --git a/src/main/resources/app2/src/router/index.js b/src/main/resources/app2/src/router/index.js index b33adec..be0af48 100644 --- a/src/main/resources/app2/src/router/index.js +++ b/src/main/resources/app2/src/router/index.js @@ -18,6 +18,11 @@ const router = createRouter({ name: 'WaterQuality', component: () => import('../views/WaterQualityPage.vue') }, + { + path: '/realtime-data', + name: 'RealtimeData', + component: () => import('../views/RealtimeDataPage.vue') + }, { path: '/scan', name: 'ScanPage', diff --git a/src/main/resources/app2/src/services/deviceService.js b/src/main/resources/app2/src/services/deviceService.js index 0e14971..6eb0287 100644 --- a/src/main/resources/app2/src/services/deviceService.js +++ b/src/main/resources/app2/src/services/deviceService.js @@ -62,6 +62,17 @@ export const deviceService = { } } + throw error.response?.data || error.message + } + }, + // 新增:获取实时数据接口 + async getRealtimeData(terminalId) { + try { + const response = await api.get(`/api/water/realtime/${terminalId}`) + console.log(`终端 ${terminalId} 实时数据:`, response.data) + return response.data + } catch (error) { + console.error(`获取终端 ${terminalId} 实时数据失败:`, error) throw error.response?.data || error.message } } diff --git a/src/main/resources/app2/src/services/studentDrinkStatsService.js b/src/main/resources/app2/src/services/studentDrinkStatsService.js new file mode 100644 index 0000000..027be23 --- /dev/null +++ b/src/main/resources/app2/src/services/studentDrinkStatsService.js @@ -0,0 +1,49 @@ +// src/services/studentDrinkStatsService.js +import apiClient from '@/services/api' + +export const studentDrinkStatsService = { + /** + * 获取今日饮水统计 + */ + async getTodayStats(studentId) { + try { + const response = await apiClient.post('/api/student/drink-stats/today', { + studentId: studentId + }) + return response.data + } catch (error) { + console.error('获取今日饮水统计失败:', error) + throw error + } + }, + + /** + * 获取本周饮水统计 + */ + async getThisWeekStats(studentId) { + try { + const response = await apiClient.post('/api/student/drink-stats/this-week', { + studentId: studentId + }) + return response.data + } catch (error) { + console.error('获取本周饮水统计失败:', error) + throw error + } + }, + + /** + * 获取本月饮水统计 + */ + async getThisMonthStats(studentId) { + try { + const response = await apiClient.post('/api/student/drink-stats/this-month', { + studentId: studentId + }) + return response.data + } catch (error) { + console.error('获取本月饮水统计失败:', error) + throw error + } + } +} diff --git a/src/main/resources/app2/src/views/ProfilePage.vue b/src/main/resources/app2/src/views/ProfilePage.vue index 0669cfb..29fb07e 100644 --- a/src/main/resources/app2/src/views/ProfilePage.vue +++ b/src/main/resources/app2/src/views/ProfilePage.vue @@ -39,18 +39,36 @@
-
{{ userStats.days }}
-
累计用水天数
+
{{ userStats.totalConsumption }}ml
+
累计饮水量
-
{{ userStats.todayWater }}
-
今日饮水量
+
{{ userStats.drinkCount }}
+
饮水次数
+
+
+ +
+
+
{{ userStats.avgDaily }}ml
+
日均饮水量
+
+
+
{{ userStats.days }}天
+
饮水天数
+
+ 今日 +
-
800ml
-
600ml
-
400ml
-
200ml
+
{{ maxChartValue }}ml
+
{{ Math.round(maxChartValue * 0.75) }}ml
+
{{ Math.round(maxChartValue * 0.5) }}ml
+
{{ Math.round(maxChartValue * 0.25) }}ml
0ml
@@ -97,7 +115,7 @@ >
{{ item.value }}ml
@@ -110,6 +128,26 @@
+ +
+
每日详情
+
+
+
{{ formatDate(detail.date) }}
+
{{ detail.consumption }}ml
+
{{ detail.count }}次
+
+ +
+ 暂无饮水记录 +
+
+
+
@@ -430,7 +430,34 @@ const startWaterProcess = async () => { progress.value = 0 remainingTime.value = Math.ceil(selectedAmount.value / 50) - // 模拟取水进度 + // 先调用一次API,并保存结果 + let apiResult = null + try { + apiResult = await callWaterUsageAPI() + } catch (error) { + console.error('取水API调用失败:', error) + // 立即停止并显示错误 + isProcessing.value = false + showResult( + 'error', + '取水失败', + 'API调用失败,请重试' + ) + return + } + + // 如果API调用失败,立即停止 + if (!apiResult || apiResult.code !== 200) { + isProcessing.value = false + showResult( + 'error', + '取水失败', + apiResult?.message || '取水操作失败' + ) + return + } + + // API调用成功后,开始模拟进度 const interval = setInterval(() => { progress.value += 5 if (remainingTime.value > 0) { @@ -442,13 +469,13 @@ const startWaterProcess = async () => { completeWaterProcess() } }, 200) - - // 调用后端API - await callWaterUsageAPI() } // 调用后端取水API const callWaterUsageAPI = async () => { + // 添加调用计数,用于调试 + console.log('调用取水API,水量:', selectedAmount.value) + try { const result = await deviceService.scanToDrink( deviceInfo.value.id, @@ -457,6 +484,8 @@ const callWaterUsageAPI = async () => { ) if (result.code === 200) { + // 只在API成功时记录历史 + console.log('API调用成功,记录历史') recordWaterHistory(result.data) return result } else { @@ -473,32 +502,18 @@ const callWaterUsageAPI = async () => { const completeWaterProcess = async () => { isProcessing.value = false - const apiResult = await callWaterUsageAPI() - if (apiResult.code === 200) { - showResult( - 'success', - '取水成功', - `您已成功取水 ${selectedAmount.value}ml` - ) + showResult( + 'success', + '取水成功', + `您已成功取水 ${selectedAmount.value}ml` + ) - recordWaterHistory({ - deviceName: deviceInfo.value.name, - deviceId: deviceInfo.value.id, - amount: selectedAmount.value - }) - setTimeout(() => { - resetScan() - showResultDialog.value = false - }, 2000) - } else { - showResult( - 'error', - '取水失败', - apiResult.message || '取水操作失败,请重试' - ) - } + setTimeout(() => { + resetScan() + showResultDialog.value = false + }, 2000) } // 显示结果 @@ -516,6 +531,7 @@ const closeResultDialog = () => { } /// 记录取水历史 +// 记录取水历史 const recordWaterHistory = (data) => { // 只保存当前扫描的设备记录 if (!deviceInfo.value || !deviceInfo.value.id) { @@ -527,27 +543,42 @@ const recordWaterHistory = (data) => { id: Date.now(), date: '今日', deviceName: deviceInfo.value.name || '饮水机', - deviceId: deviceInfo.value.id, // 使用当前扫描的terminalID + deviceId: deviceInfo.value.id, time: new Date().toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }), amount: `${selectedAmount.value}ml`, timestamp: new Date().toISOString(), location: deviceInfo.value.location || '' } - console.log('保存取水历史:', history) - - // 获取现有历史记录 + // 添加去重机制 const existingHistory = JSON.parse(localStorage.getItem('waterHistory') || '[]') - // 过滤掉重复的terminalID记录(只保留最新的) - const filteredHistory = existingHistory.filter(record => record.deviceId !== deviceInfo.value.id) + // 检查5秒内是否有相同设备的记录 + const now = new Date() + const fiveSecondsAgo = new Date(now.getTime() - 5000) // 5秒前 - // 添加新记录到开头 - filteredHistory.unshift(history) + const duplicateIndex = existingHistory.findIndex(record => { + const recordTime = new Date(record.timestamp) + return ( + record.deviceId === deviceInfo.value.id && + recordTime >= fiveSecondsAgo && + recordTime <= now + ) + }) - // 只保存每个设备的最新一条记录 + if (duplicateIndex !== -1) { + // 如果5秒内有重复记录,替换它而不是添加新记录 + console.log('发现重复记录,替换而不是新增') + existingHistory[duplicateIndex] = history + } else { + // 没有重复记录,正常添加 + console.log('保存新记录') + existingHistory.unshift(history) + } + + // 过滤掉重复的terminalID记录(只保留最新的) const deviceRecords = {} - const finalHistory = filteredHistory.filter(record => { + const finalHistory = existingHistory.filter(record => { if (!deviceRecords[record.deviceId]) { deviceRecords[record.deviceId] = true return true @@ -556,17 +587,17 @@ const recordWaterHistory = (data) => { }) // 限制总记录数 - const limitedHistory = finalHistory.slice(0, 20) // 最多保存20条 + const limitedHistory = finalHistory.slice(0, 20) localStorage.setItem('waterHistory', JSON.stringify(limitedHistory)) console.log('更新后的历史记录:', limitedHistory) } // 查看水质 -const viewWaterQuality = () => { +const viewRealtimeData = () => { if (deviceInfo.value) { router.push({ - path: '/water-quality', + path: '/realtime-data', query: { terminalId: deviceInfo.value.id, deviceId: deviceInfo.value.deviceId