mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-04-23 18:19:01 +08:00
feat: 实现消息长度分布图
This commit is contained in:
@@ -302,6 +302,84 @@ export function getMessageTypeDistribution(sessionId: string, filter?: TimeFilte
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取消息长度分布(仅统计文字消息)
|
||||
* 返回两组数据:
|
||||
* - detail: 1-25 字逐字分布
|
||||
* - grouped: 5-100+ 每5字一组
|
||||
*/
|
||||
export function getMessageLengthDistribution(sessionId: string, filter?: TimeFilter): {
|
||||
detail: Array<{ len: number; count: number }>
|
||||
grouped: Array<{ range: string; count: number }>
|
||||
} {
|
||||
const db = openDatabase(sessionId)
|
||||
if (!db) return { detail: [], grouped: [] }
|
||||
|
||||
const { clause, params } = buildTimeFilter(filter)
|
||||
const clauseWithSystem = buildSystemMessageFilter(clause)
|
||||
|
||||
// 只统计文字消息 (type = 0),并且 content 不为空
|
||||
const typeCondition = clauseWithSystem
|
||||
? clauseWithSystem + ' AND msg.type = 0 AND msg.content IS NOT NULL AND LENGTH(msg.content) > 0'
|
||||
: 'WHERE msg.type = 0 AND msg.content IS NOT NULL AND LENGTH(msg.content) > 0'
|
||||
|
||||
// 直接获取每条消息的长度
|
||||
const rows = db
|
||||
.prepare(
|
||||
`
|
||||
SELECT LENGTH(msg.content) as len, COUNT(*) as count
|
||||
FROM message msg
|
||||
JOIN member m ON msg.sender_id = m.id
|
||||
${typeCondition}
|
||||
GROUP BY len
|
||||
ORDER BY len
|
||||
`
|
||||
)
|
||||
.all(...params) as Array<{ len: number; count: number }>
|
||||
|
||||
// 构建 detail:1-25 逐字
|
||||
const detail: Array<{ len: number; count: number }> = []
|
||||
for (let i = 1; i <= 25; i++) {
|
||||
const found = rows.find((r) => r.len === i)
|
||||
detail.push({
|
||||
len: i,
|
||||
count: found ? found.count : 0,
|
||||
})
|
||||
}
|
||||
|
||||
// 构建 grouped:每5字一段
|
||||
const ranges5 = [
|
||||
{ min: 1, max: 5, label: '1-5' },
|
||||
{ min: 6, max: 10, label: '6-10' },
|
||||
{ min: 11, max: 15, label: '11-15' },
|
||||
{ min: 16, max: 20, label: '16-20' },
|
||||
{ min: 21, max: 25, label: '21-25' },
|
||||
{ min: 26, max: 30, label: '26-30' },
|
||||
{ min: 31, max: 35, label: '31-35' },
|
||||
{ min: 36, max: 40, label: '36-40' },
|
||||
{ min: 41, max: 45, label: '41-45' },
|
||||
{ min: 46, max: 50, label: '46-50' },
|
||||
{ min: 51, max: 60, label: '51-60' },
|
||||
{ min: 61, max: 70, label: '61-70' },
|
||||
{ min: 71, max: 80, label: '71-80' },
|
||||
{ min: 81, max: 100, label: '81-100' },
|
||||
{ min: 101, max: Infinity, label: '100+' },
|
||||
]
|
||||
|
||||
const grouped: Array<{ range: string; count: number }> = []
|
||||
for (const r of ranges5) {
|
||||
const count = rows
|
||||
.filter((row) => row.len >= r.min && row.len <= r.max)
|
||||
.reduce((sum, row) => sum + row.count, 0)
|
||||
grouped.push({
|
||||
range: r.label,
|
||||
count,
|
||||
})
|
||||
}
|
||||
|
||||
return { detail, grouped }
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间范围
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ export {
|
||||
getWeekdayActivity,
|
||||
getMonthlyActivity,
|
||||
getYearlyActivity,
|
||||
getMessageLengthDistribution,
|
||||
getMessageTypeDistribution,
|
||||
getTimeRange,
|
||||
getMemberNameHistory,
|
||||
|
||||
Reference in New Issue
Block a user