西藏巴青项目

大屏畜牧资源技术方案.md 16KB

大屏 — 畜牧资源统计 — 技术方案

依据:同目录 大屏畜牧资源功能需求.md v1.3。数据源为 AI 诊断 既有表(会话、消息、使用用户台账)。本模块为大屏只读看板统计移动端「畜牧资源」资讯视图 v_livestock_resource


1. 技术架构

说明
后端 RuoYi v3.9.2springboot2 分支):JDK 8、Spring Boot 2.x、Spring MVC、MyBatis、Druid
数据库 MySQL 5.7.39,InnoDB,utf8mb4
前端 ruoyi-screen 畜牧资源专题页(/livestock-resources);切换 statYear 拉取看板主数据(本期单接口
代码包 com.ruoyi.web.modules.screenLivestockResourceScreenController / ILivestockResourceScreenService / vo / support

分层ControllerILivestockResourceScreenService(口径编排、statDate/statDateTime)→ LivestockResourceScreenMapper(只读 SQL)+ LivestockResourceScreenSupport(7 日/24 小时补点、分类归一、占比、分档、关键词)。

场景 行为
进入 / 切换 statYear 调用 §3.1
数据权限 全县聚合;不按提问人/机构过滤
统计日 statDate 复用 HomeScreenSupport.resolveStatDate(Y)Y=当前年 → 今日(Asia/Shanghai);历史年 → Y-12-31
统计时刻 statDateTime 请求时 LocalDateTime.now(Asia/Shanghai);响应回显用
年内上界 会话 create_time;AI 消息 create_timestatDate 23:59:59(当前年)
「今日」四项 仅当 Y = 当前自然年时按 statDate 自然日统计;否则固定 0
用户结构 biz_consult_user 全表快照Y
7 日 / 分时 7 日以 statDate 滚动;分时为 距 statDateTime 最近 24 整点小时与 Y 无关
已隐藏会话 过滤 vet_visible(对齐功能需求 §2.18#2
性能 默认实时聚合;可选 §2.3 缓存表

依赖表(只读)

用途
biz_consult_session AI 会话数、用户去重、7 日/24 小时会话、分档分母
biz_consult_message 提问量(AI 回复)、耗时、分类、状态、关键词语料
biz_consult_user 新老用户结构

业务常量(与 ConsultSessionRules / AiConsultConstants 一致)

常量
consult_type AI 问诊 2
sender_role 提问人 / AI 1 / 3
AI 消息 sender_user_id 0
msg_type 文本 1
提问分类编码 14(养殖技巧/疾病诊疗/用药指导/设备操作)

2. 数据库设计

2.1 本模块业务表

无新增业务台账表。 DDL:sql/biz_consult_session.sqlsql/biz_consult_message.sqlsql/biz_consult_user.sql

当前问诊表 del_flag;纳入条件为:consult_type=2 的会话及其消息。已隐藏(vet_visible=0仍统计

2.2 时间边界(公共参数)

statYear = YstatDatestatDateTime§1

边界 表达式
年区间起 Y-01-01 00:00:00
年区间止(会话 create_time、AI 消息 create_time statDate 23:59:59
统计日区间 statDate 00:00:00statDate 23:59:59
近 7 日 [statDate − 6 日 00:00:00, statDate 23:59:59]
最近 24 小时 [floor(statDateTime 到整点) − 23 小时, floor(statDateTime 到整点) + 59 分 59 秒];SQL 按 DATE_FORMAT(create_time,'%Y%m%d%H') 分组

会话别名(下文)s = biz_consult_session,条件 s.consult_type = 2
AI 消息别名m_ai = biz_consult_messagem_ai.sender_role = 3 AND m_ai.sender_user_id = 0,且 EXISTS 关联 s.id = m_ai.session_id
提问人消息别名m_ask = biz_consult_messagem_ask.sender_role = 1,且关联 AI 会话 s

2.3 可选表 biz_livestock_resource_screen_cache(性能优化)

非本期必建。

字段 类型 说明
id bigint(20) 主键
stat_year int(11) 统计年份
payload_json mediumtext §3.1 响应 JSON
expire_time datetime 过期时间
create_time datetime 写入时间

索引UNIQUE uk_stat_year (stat_year)。TTL 1~5 分钟

2.4 查询口径(按表)

2.4.1 核心总览

指标 SQL 要点
累计使用用户 COUNT(DISTINCT s.asker_user_id)s.create_time ∈ 年区间
今日活跃用户 Y=当前年:COUNT(DISTINCT asker_user_id)s.update_time ∈ 统计日;否则 0
日新增用户 Y=当前年:create_timeupdate_time 均在统计日,且 asker_user_id 不在 create_time < 统计日 的会话中;否则 0
累计会话数 COUNT(s.id)s.create_time ∈ 年区间
今日会话数 Y=当前年:COUNT(s.id)s.create_time ∈ 统计日区间;否则 0
累计提问量 COUNT(m_ai.id)m_ai.create_time ∈ 年区间
今日提问量 Y=当前年:COUNT(m_ai.id)m_ai.create_time ∈ 统计日;否则 0
平均响应时长(秒) AVG(m_ai.cost_time) / 1000.0,年区间内且 m_ai.cost_time IS NOT NULL含 0);无记录 → 0

2.4.2 近 7 日活跃度

维度 SQL 要点
会话数/日 DATE(s.create_time) 分组,COUNT(s.id)
提问量/日 DATE(m_ai.create_time) 分组,COUNT(m_ai.id)

应用层:固定输出 7 个点(statDate−6statDate),缺日补 0

2.4.3 用户结构 biz_consult_user

类型 条件
新用户 DATEDIFF(last_use_time, first_use_time) <= 180
老用户 > 180

COUNT(*) 各一类;占比 = 人数 / (新+老),Y 条件。

2.4.4 提问分类 / 模型调用 / 热点榜(同源)

条件
统计行 m_aisender_role=3sender_user_id=0),create_time ∈ 年区间
分类键 同会话内 send_time ≤ m_ai.send_time 的最近提问人消息 ai_category;空 → UNCAT
条数 GROUP BY 分类键 COUNT(*)MAX(m_ai.create_time) 供热点二次排序
占比 分类 AI 回复条数 / 当年全部 AI 回复 × 100
热点 Top5 条数降序;同分按 lastEventTime 降序;取 5

2.4.5 分时使用热度(最近 24 小时)

维度 SQL 要点
会话 s.create_time ∈ 24h 窗口,GROUP BY DATE_FORMAT(create_time,'%Y%m%d%H')
提问量 m_ai.create_time ∈ 24h 窗口,同上分组

应用层:固定 24 桶(锚点整点向前 23 小时);bucketStart=HH:mmbucketDateTime=yyyy-MM-dd HH:mmhourlyHeat.windowEnd = 锚点整点 yyyy-MM-dd HH:mm

2.4.6 单次会话提问数量分布

子查询:按 session_id 统计年内 m_ai 条数 reply_cnt,再分档:

档位 code reply_cnt
LIGHT 1~2
NORMAL 3~4
ACTIVE 5~10
DEEP >10

COUNT(session_id) / 年内会话总数 → 占比;四档固定返回,无数据为 0。

2.4.7 会话状态分布

状态 条件
OK 正常应答 m_ai.cost_time IS NOT NULL含 0
FAIL 调用失败 m_ai.cost_time IS NULL

年内 COUNT(*) 及占比;两者之和 = 年内 AI 消息总数。

2.4.8 高频关键词

条件
语料 m_ask.msg_type = 1m_ask.content 非空,m_ask.send_time ∈ 年区间
处理 LivestockResourceScreenSupport.extractTopKeywords(texts, 30):分词 + 停用词(application.yml 可配路径或内置短表)

2.5 索引建议(既有表)

建议
biz_consult_session (consult_type, create_time)(consult_type, update_time)
biz_consult_message (session_id, sender_role, create_time)(create_time, sender_role)

2.6 Mapper 方法(建议)

Mapper 方法 说明
LivestockResourceScreenMapper selectOverview(...) 总览 8 项(可拆 2~3 条 SQL)
selectDailySessionCounts(start, end) 7 日会话
selectDailyAiReplyCounts(start, end) 7 日提问量
selectUserStructure() 新老用户
selectAskerCategoryCounts(yearStart, yearEnd) AI 回复按分类键聚合
selectAiReplyTotal(yearStart, yearEnd) 分类占比分母(年内 AI 回复总数)
selectHourlySessionCounts(windowStart, windowEnd) 最近 24h 会话
selectHourlyAiReplyCounts(windowStart, windowEnd) 最近 24h 提问量
selectSessionReplyBuckets(yearStart, yearEnd) 四档会话数
selectYearSessionTotal(yearStart, yearEnd) 年内会话总数
selectAiReplyStatusCounts(yearStart, yearEnd) 正常/失败
selectTextAskerContents(yearStart, yearEnd) 关键词语料
selectDistinctSessionYears() 可选年份下拉

XML:mapper/screen/LivestockResourceScreenMapper.xml


3. 接口设计

统一响应AjaxResultcode / msg / data)。

Base Path/bigScreen/livestockResource

权限标识(示例)bigScreen:livestockResource:query

# 说明 Method URI
3.1 看板主数据(十区块合一) GET /bigScreen/livestockResource/dashboard

前端:进入页 / 切换 statYear / 刷新 → 仅 3.1


3.1 看板主数据

Query

参数 类型 必填 说明
statYear string Y 四位年份;非法 → 业务异常(AchievementReportValidation.parseStatYear
forceRefresh boolean N 默认 falsetrue 时跳过 §2.3 缓存

响应 data(顶层)

字段 类型 说明
statYear int 回显
statDate string yyyy-MM-dd
statDateTime string yyyy-MM-dd HH:mm:ss,24h 窗口终点
availableYears int[] biz_consult_sessionconsult_type=2YEAR(create_time) 并集 + 当前年,降序
overview object 核心总览 §3.1.1
activityTrend object 活跃度趋势 §3.1.2
userStructure object 用户结构 §3.1.3
categoryShare object 提问分类占比 §3.1.4
modelCallAnalysis array 模型调用分析(与分类同源) §3.1.5
hourlyHeat object 分时热度 §3.1.6
sessionReplyDistribution array 会话提问数量分布 §3.1.7
replyStatusDistribution object 会话状态分布 §3.1.8
hotTopics array 热点问题榜单 Top5 §3.1.9
topKeywords array 高频关键词 Top30 §3.1.10

3.1.1 overview

字段 类型 说明
totalUsers long 累计使用用户
todayActiveUsers long 今日活跃用户
todayNewUsers long 日新增用户
totalSessions long 累计会话数
todaySessions long 今日会话数
totalQuestionCount long 累计提问量(AI 回复条数)
todayQuestionCount long 今日提问量
avgResponseSeconds decimal 平均响应时长(秒),1 位小数

3.1.2 activityTrend

字段 类型 说明
dailySeries array 固定 7

dailySeries[]

字段 说明
date yyyy-MM-dd
sessionCount 会话数
questionCount 提问量(AI 回复)

3.1.3 userStructure

字段 类型 说明
newUserCount long 新用户
oldUserCount long 老用户
newUserRatio decimal 占比 0~100
oldUserRatio decimal 占比 0~100

3.1.4 categoryShare

字段 类型 说明
totalAskerMessages long 分母:年内全部 AI 回复(字段名沿用,与提问人无关)
items array 分类项

items[]categoryCodecategoryNamecountratio(0~100,1 位小数)。固定含 14 + UNCAT(未分类),无数据 count=0

3.1.5 modelCallAnalysis[]

categoryShare.items 同源(可复用引用):categoryCodecategoryNamecount。展示为柱状图时前端取 count

3.1.6 hourlyHeat

字段 类型 说明
windowEnd string 锚点整点 yyyy-MM-dd HH:mm
hourlySeries array 固定 24

hourlySeries[]bucketStartHH:mm)、bucketDateTimeyyyy-MM-dd HH:mm,悬停)、sessionCountquestionCount

3.1.7 sessionReplyDistribution[]

固定 4 条。

字段 说明
bandCode LIGHT / NORMAL / ACTIVE / DEEP
bandName 轻度 / 一般 / 活跃 / 深度
sessionCount 会话数
ratio 占年内会话总数 %

3.1.8 replyStatusDistribution

字段 说明
totalAiReplies 年内 AI 回复总数
items 固定 2 条:OK(正常应答)、FAIL(调用失败),含 countratio

3.1.9 hotTopics[]

最多 5 条:categoryCodecategoryNamecountratio,按 ratiocount 降序。

3.1.10 topKeywords[]

最多 30 条:keywordcount

响应示例(节选)

{
  "statYear": 2026,
  "statDate": "2026-05-20",
  "statDateTime": "2026-05-20 15:30:00",
  "overview": {
    "totalUsers": 120,
    "todayActiveUsers": 8,
    "todayNewUsers": 2,
    "totalSessions": 350,
    "todaySessions": 5,
    "totalQuestionCount": 980,
    "todayQuestionCount": 12,
    "avgResponseSeconds": 3.2
  },
  "activityTrend": {
    "dailySeries": [
      { "date": "2026-05-14", "sessionCount": 3, "questionCount": 10 }
    ]
  },
  "categoryShare": {
    "totalAskerMessages": 500,
    "items": [
      { "categoryCode": "2", "categoryName": "疾病诊疗", "count": 200, "ratio": 40.0 }
    ]
  }
}

服务端逻辑(摘要)

1. year = parseStatYear(statYear)
2. statDate = resolveStatDate(year); statDateTime = now(Shanghai)
3. yearStart/end, dayStart/end, sevenStart, window24Start = Support.bounds(...)
4. overview = Mapper 总览;avgResponseSeconds = Support.roundSeconds(avgMs/1000)
5. activityTrend = Mapper 7日 + buildDailySeries(7, statDate)
6. userStructure = Mapper 新老 + ratio
7. category = Mapper 分类 + total;categoryShare/modelCall/hotTopics = Support.buildCategoryViews(...)
8. hourlyHeat = Mapper 24h + buildHourlySeries(24, statDateTime)
9. sessionReplyDistribution = Mapper 分档 + ratio
10. replyStatusDistribution = Mapper OK/FAIL + ratio
11. topKeywords = Support.extractTopKeywords(Mapper 文本语料, 30)
12. availableYears = distinct session years ∪ current year
13. return AjaxResult.success(vo)

4. 菜单与权限(示例)

类型 名称 权限标识
菜单 大屏畜牧资源 bigScreen:livestockResource:query

SQL 示例:sql/big_screen_livestock_resource_perm.sql(挂载「大屏」父菜单下)。


5. 交付清单

  • LivestockResourceScreenController + ILivestockResourceScreenService + VO + LivestockResourceScreenSupport
  • LivestockResourceScreenMapper + XML(§2.6
  • ruoyi-screen 对接 GET /bigScreen/livestockResource/dashboard(本期不改前端)
  • 单元测试:历史年今日为 0、7 日补 0、统计日 24 桶、分类占比、耗时含 0
  • 接口测试:MockMvc dashboard
  • 菜单权限 SQL;依赖 biz_consult_user、消息 cost_time/ai_category 字段已上线

6. 修订记录

版本 日期 说明
1.0 2026-05-20 初稿:无新表;单接口十区块;对齐 大屏畜牧资源功能需求.md v1.1
1.2 2026-05-20 对齐草稿:今日活跃 update_time、日新增双时间、AI 回复+分类归因、统计日 0~23 时分、create_time 消息归属