From b53faca1206f7e1e1a9a0fa19ea3680c96708dc4 Mon Sep 17 00:00:00 2001 From: wangys <3401275564@qq.com> Date: Thu, 1 Jan 2026 16:19:55 +0800 Subject: [PATCH] =?UTF-8?q?overview=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/workcase/service/ChatRoomService.java | 8 + .../workcase/service/WordCloudService.java | 29 ++ .../api/workcase/service/WorkcaseService.java | 16 ++ .../java/org/xyzh/common/dto/BaseDTO.java | 3 + .../controller/WorkcaseChatController.java | 9 +- .../controller/WorkcaseController.java | 46 ++++ .../workcase/mapper/TbWorkcaseMapper.java | 2 + .../workcase/service/ChatRoomServiceImpl.java | 6 + .../workcase/service/WorkcaseServiceImpl.java | 12 + .../resources/mapper/TbChatRoomMapper.xml | 3 + .../resources/mapper/TbWordCloudMapper.xml | 3 + .../resources/mapper/TbWorkcaseMapper.xml | 9 + .../workcase/src/api/workcase/workcase.ts | 20 ++ .../workcase/src/api/workcase/workcaseChat.ts | 11 + .../workcase/src/assets/css/common.scss | 1 + .../views/admin/overview/OverviewView.scss | 32 ++- .../src/views/admin/overview/OverviewView.vue | 255 +++++++++++++++--- 17 files changed, 425 insertions(+), 40 deletions(-) create mode 100644 urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WordCloudService.java diff --git a/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/ChatRoomService.java b/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/ChatRoomService.java index 3389b485..03867adc 100644 --- a/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/ChatRoomService.java +++ b/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/ChatRoomService.java @@ -72,6 +72,14 @@ public interface ChatRoomService { */ ResultDomain getChatRoomPage(PageRequest pageRequest, String userId); + /** + * @description 统计聊天室数量 + * @param filter 筛选条件 + * @author yslg + * @since 2026-01-01 + */ + ResultDomain countChatRooms(TbChatRoomDTO filter); + // ========================= 聊天室成员管理 ========================== /** diff --git a/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WordCloudService.java b/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WordCloudService.java new file mode 100644 index 00000000..14b71287 --- /dev/null +++ b/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WordCloudService.java @@ -0,0 +1,29 @@ +package org.xyzh.api.workcase.service; + +import org.xyzh.api.workcase.dto.TbWordCloudDTO; +import org.xyzh.common.core.domain.ResultDomain; +import org.xyzh.common.core.page.PageRequest; + +/** + * @description 词云服务接口 + * @filename WordCloudService.java + * @author yslg + * @copyright xyzh + * @since 2025-12-19 + */ +public interface WordCloudService { + + /** + * 查询词云列表 + * @param filter 筛选条件 + * @return 词云列表 + */ + ResultDomain getWordCloudList(TbWordCloudDTO filter); + + /** + * 分页查询词云 + * @param pageRequest 分页请求 + * @return 词云分页数据 + */ + ResultDomain getWordCloudPage(PageRequest pageRequest); +} diff --git a/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WorkcaseService.java b/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WorkcaseService.java index 1855263a..34eee9dd 100644 --- a/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WorkcaseService.java +++ b/urbanLifelineServ/apis/api-workcase/src/main/java/org/xyzh/api/workcase/service/WorkcaseService.java @@ -55,6 +55,22 @@ public interface WorkcaseService { */ ResultDomain getWorkcasePage(PageRequest pageRequest); + /** + * @description 统计各个类型的工单数量 + * @param filter + * @author yslg + * @since 2026-01-01 + */ + ResultDomain countWorkcasesByType(TbWorkcaseDTO filter); + + /** + * @description 统计工单数量 + * @param filter + * @author yslg + * @since 2026-01-01 + */ + ResultDomain countWorkcases(TbWorkcaseDTO filter); + /** * @description 获取工单详情 * @param workcaseId diff --git a/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java b/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java index 65e207c8..1cc25646 100644 --- a/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java +++ b/urbanLifelineServ/common/common-dto/src/main/java/org/xyzh/common/dto/BaseDTO.java @@ -50,6 +50,9 @@ public class BaseDTO implements Serializable { @Schema(description = "数量限制") private Integer limit; + @Schema(description = "统计数量") + private Integer count; + @Schema(description = "开始时间") private Date startTime; diff --git a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseChatController.java b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseChatController.java index 56358d3b..e96aec9b 100644 --- a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseChatController.java +++ b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseChatController.java @@ -162,7 +162,7 @@ public class WorkcaseChatController { if (!vr.isValid()) { return ResultDomain.failure(vr.getAllErrors()); } - + LoginDomain loginDomain = LoginUtil.getCurrentLogin(); String userId = loginDomain.getUser().getUserId(); if("guest".equals(loginDomain.getUser().getStatus())){ @@ -171,6 +171,13 @@ public class WorkcaseChatController { return chatRoomService.getChatRoomPage(pageRequest, userId); } + @Operation(summary = "统计聊天室数量") + @PreAuthorize("hasAuthority('workcase:room:view')") + @PostMapping("/room/count") + public ResultDomain countChatRooms(@RequestBody TbChatRoomDTO filter) { + return chatRoomService.countChatRooms(filter); + } + // ========================= ChatRoom成员管理 ========================= @Operation(summary = "添加聊天室成员") diff --git a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseController.java b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseController.java index e746e1d5..c6903cdd 100644 --- a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseController.java +++ b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/controller/WorkcaseController.java @@ -19,6 +19,7 @@ import org.xyzh.common.auth.utils.LoginUtil; import org.xyzh.common.core.domain.LoginDomain; import org.xyzh.common.core.domain.ResultDomain; import org.xyzh.common.core.page.PageRequest; +import org.xyzh.common.utils.validation.ValidationParam; import org.xyzh.common.utils.validation.ValidationResult; import org.xyzh.common.utils.validation.ValidationUtils; @@ -26,6 +27,8 @@ import com.alibaba.fastjson2.JSONObject; import io.swagger.v3.oas.annotations.Operation; import java.util.Arrays; +import java.util.Date; + import io.swagger.v3.oas.annotations.tags.Tag; /** @@ -116,6 +119,49 @@ public class WorkcaseController { return workcaseService.getWorkcasePage(pageRequest); } + @Operation(summary = "查询工单问题统计") + @PreAuthorize("hasAuthority('workcase:ticket:view')") + @PostMapping("/category/count") + public ResultDomain countWorkcasesByType(@RequestBody TbWorkcaseDTO workcase) { + ValidationResult vr = ValidationUtils.validate(workcase, Arrays.asList( + ValidationParam.builder() + .fieldName("startTime") + .fieldLabel("统计开始时间") + .required() + .build(), + // 校验结束时间不为空 + ValidationParam.builder() + .fieldName("endTime") + .fieldLabel("统计结束时间") + .required() + .build(), + // 校验开始时间小于结束时间(使用 fieldCompare 比较两个字段) + ValidationUtils.fieldCompare( + "startTime", + "endTime", + "统计时间", + (startTime, endTime) -> { + if (startTime instanceof Date && endTime instanceof Date) { + return ((Date) startTime).before((Date) endTime); + } + return true; + }, + "统计开始时间不能晚于结束时间" + ) + )); + if (!vr.isValid()) { + return ResultDomain.failure(vr.getAllErrors()); + } + return workcaseService.countWorkcasesByType(workcase); + } + + @Operation(summary = "统计工单数量") + @PreAuthorize("hasAuthority('workcase:ticket:view')") + @PostMapping("/count") + public ResultDomain countWorkcases(@RequestBody TbWorkcaseDTO workcase) { + return workcaseService.countWorkcases(workcase); + } + // ========================= CRM同步接口 ========================= @Operation(summary = "同步工单到CRM") diff --git a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/mapper/TbWorkcaseMapper.java b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/mapper/TbWorkcaseMapper.java index 99f5f55f..9e52ab0b 100644 --- a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/mapper/TbWorkcaseMapper.java +++ b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/mapper/TbWorkcaseMapper.java @@ -52,4 +52,6 @@ public interface TbWorkcaseMapper { */ long countWorkcases(@Param("filter") TbWorkcaseDTO filter); + List countWorkcasesByType(@Param("filter") TbWorkcaseDTO filter); + } diff --git a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/ChatRoomServiceImpl.java b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/ChatRoomServiceImpl.java index 03d5d3cd..294af30e 100644 --- a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/ChatRoomServiceImpl.java +++ b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/ChatRoomServiceImpl.java @@ -219,6 +219,12 @@ public class ChatRoomServiceImpl implements ChatRoomService { return ResultDomain.success("查询聊天室成功", pageDomain); } + @Override + public ResultDomain countChatRooms(TbChatRoomDTO filter) { + long count = chatRoomMapper.countChatRooms(filter); + return ResultDomain.success("查询成功", count); + } + // ========================= 聊天室成员管理 ========================== @Override diff --git a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/WorkcaseServiceImpl.java b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/WorkcaseServiceImpl.java index 686e75ca..476084b2 100644 --- a/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/WorkcaseServiceImpl.java +++ b/urbanLifelineServ/workcase/src/main/java/org/xyzh/workcase/service/WorkcaseServiceImpl.java @@ -227,6 +227,18 @@ public class WorkcaseServiceImpl implements WorkcaseService { return ResultDomain.success("查询成功", pageDomain); } + @Override + public ResultDomain countWorkcasesByType(TbWorkcaseDTO filter) { + List workcases = workcaseMapper.countWorkcasesByType(filter); + return ResultDomain.success("查询成功", workcases); + } + + @Override + public ResultDomain countWorkcases(TbWorkcaseDTO filter) { + long count = workcaseMapper.countWorkcases(filter); + return ResultDomain.success("查询成功", count); + } + // ====================== 同步到CRM和接收 =================== @Override diff --git a/urbanLifelineServ/workcase/src/main/resources/mapper/TbChatRoomMapper.xml b/urbanLifelineServ/workcase/src/main/resources/mapper/TbChatRoomMapper.xml index 91c5ce17..e10bab7e 100644 --- a/urbanLifelineServ/workcase/src/main/resources/mapper/TbChatRoomMapper.xml +++ b/urbanLifelineServ/workcase/src/main/resources/mapper/TbChatRoomMapper.xml @@ -158,6 +158,9 @@ AND status = #{filter.status} AND guest_id = #{filter.guestId} AND guest_name LIKE CONCAT('%', #{filter.guestName}, '%') + + AND create_time BETWEEN #{filter.startTime} AND #{filter.endTime} + AND deleted = false diff --git a/urbanLifelineServ/workcase/src/main/resources/mapper/TbWordCloudMapper.xml b/urbanLifelineServ/workcase/src/main/resources/mapper/TbWordCloudMapper.xml index a635f9f0..764bd9f7 100644 --- a/urbanLifelineServ/workcase/src/main/resources/mapper/TbWordCloudMapper.xml +++ b/urbanLifelineServ/workcase/src/main/resources/mapper/TbWordCloudMapper.xml @@ -83,6 +83,9 @@ ORDER BY frequency DESC, create_time DESC + + LIMIT #{filter.limit} + + + diff --git a/urbanLifelineWeb/packages/workcase/src/api/workcase/workcase.ts b/urbanLifelineWeb/packages/workcase/src/api/workcase/workcase.ts index 4c7d7a5b..af9c8453 100644 --- a/urbanLifelineWeb/packages/workcase/src/api/workcase/workcase.ts +++ b/urbanLifelineWeb/packages/workcase/src/api/workcase/workcase.ts @@ -181,5 +181,25 @@ export const workcaseAPI = { async getWorkcaseDevicePage(pageRequest: PageRequest): Promise> { const response = await api.post(`${this.baseUrl}/device/page`, pageRequest) return response.data + }, + + // ========================= 工单统计 ========================= + + /** + * 查询工单问题分类统计 + * @param filter 筛选条件(startTime, endTime) + */ + async countWorkcasesByType(filter: TbWorkcaseDTO): Promise> { + const response = await api.post(`${this.baseUrl}/category/count`, filter) + return response.data + }, + + /** + * 统计工单数量 + * @param filter 筛选条件(status等) + */ + async countWorkcases(filter: TbWorkcaseDTO): Promise> { + const response = await api.post(`${this.baseUrl}/count`, filter) + return response.data } } diff --git a/urbanLifelineWeb/packages/workcase/src/api/workcase/workcaseChat.ts b/urbanLifelineWeb/packages/workcase/src/api/workcase/workcaseChat.ts index 70fc50d9..68912ce9 100644 --- a/urbanLifelineWeb/packages/workcase/src/api/workcase/workcaseChat.ts +++ b/urbanLifelineWeb/packages/workcase/src/api/workcase/workcaseChat.ts @@ -312,5 +312,16 @@ export const workcaseChatAPI = { Object.keys(body).length > 0 ? body : {} ) return response.data + }, + + // ====================== 统计接口 ====================== + + /** + * 统计聊天室数量 + * @param filter 筛选条件(startTime, endTime, status等) + */ + async countChatRooms(filter: TbChatRoomDTO): Promise> { + const response = await api.post(`${this.baseUrl}/room/count`, filter) + return response.data } } diff --git a/urbanLifelineWeb/packages/workcase/src/assets/css/common.scss b/urbanLifelineWeb/packages/workcase/src/assets/css/common.scss index 6c2752e0..c5a2781d 100644 --- a/urbanLifelineWeb/packages/workcase/src/assets/css/common.scss +++ b/urbanLifelineWeb/packages/workcase/src/assets/css/common.scss @@ -139,6 +139,7 @@ $brand-color-hover: #004488; .product-cloud { display: flex; + justify-content: center; flex-wrap: wrap; gap: 8px 12px; padding: 8px 0; diff --git a/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.scss b/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.scss index b5303b00..b6019418 100644 --- a/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.scss +++ b/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.scss @@ -1 +1,31 @@ -// OverviewView 样式占位符 +// OverviewView 样式 + +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 60px 20px; + color: #909399; + + p { + margin-top: 16px; + font-size: 14px; + color: #909399; + } +} + +.question-stats { + min-height: 200px; +} + +.product-cloud { + min-height: 150px; +} + +// 趋势样式 +.stat-trend { + &.down { + color: #f56c6c !important; + } +} diff --git a/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.vue b/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.vue index dc837d6e..b2841ab3 100644 --- a/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.vue +++ b/urbanLifelineWeb/packages/workcase/src/views/admin/overview/OverviewView.vue @@ -8,11 +8,12 @@
-
1,258
+
{{ dashboardData.consultCount }}
咨询次数
-
- - 较昨日 +12.5% +
+ + + 较昨日 {{ dashboardData.consultTrend >= 0 ? '+' : '' }}{{ dashboardData.consultTrend }}%
@@ -60,15 +61,21 @@
-
-
- {{ item.name }} - {{ item.count }} 次 -
-
-
+
+
+
+ {{ item.name }} + {{ item.count }} 次 +
+
+
+
+
+ +

暂无数据

+
@@ -83,10 +90,16 @@
- - {{ product.name }} - +
+ + {{ product.name }} + +
+
+ +

暂无数据

+
@@ -120,49 +133,215 @@