feat: 增强管理员工作台聊天统计看板

- 工作台接入聊天消息总数、会话总数、活跃智能体数、趋势与 Top5 排行

- dashboard 接口新增 chatStatus 与聊天统计字段,分析库不可用时明确降级

- today 维度按小时聚合聊天趋势,并补充后端查询与测试覆盖
This commit is contained in:
2026-04-19 17:40:01 +08:00
parent 1d8b9d9662
commit 5827ecde42
16 changed files with 1206 additions and 90 deletions

View File

@@ -0,0 +1,67 @@
package tech.easyflow.chatlog.service;
import tech.easyflow.chatlog.domain.dto.ChatAssistantUsageRank;
import tech.easyflow.chatlog.domain.dto.ChatDashboardSummary;
import tech.easyflow.chatlog.domain.dto.ChatDashboardTrend;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* 聊天工作台统计查询服务。
*/
public interface ChatDashboardQueryService {
/**
* 查询聊天汇总指标。
*
* @param startDate 开始日期,包含当天
* @param endDate 结束日期,不包含当天
* @param tenantId 租户 ID空表示全局
* @return 聊天汇总指标
*/
ChatDashboardSummary querySummary(LocalDate startDate, LocalDate endDate, BigInteger tenantId);
/**
* 查询聊天日趋势。
*
* @param startDate 开始日期,包含当天
* @param endDate 结束日期,不包含当天
* @param tenantId 租户 ID空表示全局
* @return 聊天日趋势
*/
List<ChatDashboardTrend> queryTrends(LocalDate startDate, LocalDate endDate, BigInteger tenantId);
/**
* 查询聊天小时趋势。
*
* @param startTime 开始时间,包含
* @param endTime 结束时间,不包含
* @param tenantId 租户 ID空表示全局
* @return 聊天小时趋势
*/
List<ChatDashboardTrend> queryHourlyTrends(LocalDateTime startTime, LocalDateTime endTime, BigInteger tenantId);
/**
* 查询智能体使用排行。
*
* @param startDate 开始日期,包含当天
* @param endDate 结束日期,不包含当天
* @param tenantId 租户 ID空表示全局
* @param limit 返回条数
* @return 智能体使用排行
*/
List<ChatAssistantUsageRank> queryAssistantUsageRanks(LocalDate startDate,
LocalDate endDate,
BigInteger tenantId,
int limit);
/**
* 当前分析库是否可用。
*
* @return true 表示可用
*/
boolean available();
}

View File

@@ -0,0 +1,105 @@
package tech.easyflow.chatlog.service.impl;
import org.springframework.stereotype.Service;
import tech.easyflow.chatlog.domain.dto.ChatAssistantUsageRank;
import tech.easyflow.chatlog.domain.dto.ChatDashboardSummary;
import tech.easyflow.chatlog.domain.dto.ChatDashboardTrend;
import tech.easyflow.chatlog.repository.analyticaldb.ChatAnalyticalDBRepository;
import tech.easyflow.chatlog.service.ChatDashboardQueryService;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
/**
* 基于分析库的聊天工作台统计查询实现。
*/
@Service
public class ChatDashboardQueryServiceImpl implements ChatDashboardQueryService {
private final ChatAnalyticalDBRepository analyticalDBRepository;
public ChatDashboardQueryServiceImpl(ChatAnalyticalDBRepository analyticalDBRepository) {
this.analyticalDBRepository = analyticalDBRepository;
}
/**
* 查询聊天汇总指标。
*
* @param startDate 开始日期,包含当天
* @param endDate 结束日期,不包含当天
* @param tenantId 租户 ID空表示全局
* @return 聊天汇总指标
*/
@Override
public ChatDashboardSummary querySummary(LocalDate startDate, LocalDate endDate, BigInteger tenantId) {
if (!available()) {
return ChatDashboardSummary.empty();
}
return analyticalDBRepository.queryDashboardSummary(startDate, endDate, tenantId);
}
/**
* 查询聊天日趋势。
*
* @param startDate 开始日期,包含当天
* @param endDate 结束日期,不包含当天
* @param tenantId 租户 ID空表示全局
* @return 聊天日趋势
*/
@Override
public List<ChatDashboardTrend> queryTrends(LocalDate startDate, LocalDate endDate, BigInteger tenantId) {
if (!available()) {
return Collections.emptyList();
}
return analyticalDBRepository.queryDashboardTrends(startDate, endDate, tenantId);
}
/**
* 查询聊天小时趋势。
*
* @param startTime 开始时间,包含
* @param endTime 结束时间,不包含
* @param tenantId 租户 ID空表示全局
* @return 聊天小时趋势
*/
@Override
public List<ChatDashboardTrend> queryHourlyTrends(LocalDateTime startTime, LocalDateTime endTime, BigInteger tenantId) {
if (!available()) {
return Collections.emptyList();
}
return analyticalDBRepository.queryDashboardHourlyTrends(startTime, endTime, tenantId);
}
/**
* 查询智能体使用排行。
*
* @param startDate 开始日期,包含当天
* @param endDate 结束日期,不包含当天
* @param tenantId 租户 ID空表示全局
* @param limit 返回条数
* @return 智能体使用排行
*/
@Override
public List<ChatAssistantUsageRank> queryAssistantUsageRanks(LocalDate startDate,
LocalDate endDate,
BigInteger tenantId,
int limit) {
if (!available()) {
return Collections.emptyList();
}
return analyticalDBRepository.queryAssistantUsageRanks(startDate, endDate, tenantId, limit);
}
/**
* 当前分析库是否可用。
*
* @return true 表示可用
*/
@Override
public boolean available() {
return analyticalDBRepository.enabled();
}
}