mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-05-17 20:13:48 +08:00
feat: 消息管理器支持显示系统消息
This commit is contained in:
@@ -135,7 +135,7 @@ export function trackDailyActive(): void {
|
||||
}
|
||||
|
||||
// 上报每日活跃事件
|
||||
trackEvent(isNew ? 'app_daily_active_new' : 'app_daily_active')
|
||||
trackEvent(isNew ? 'app_active_new' : 'app_active')
|
||||
|
||||
data.lastReportDate = today
|
||||
saveAnalyticsData(data)
|
||||
|
||||
@@ -49,7 +49,7 @@ export function registerMessagesHandlers({ win }: IpcContext): void {
|
||||
)
|
||||
|
||||
/**
|
||||
* 获取最近消息
|
||||
* 获取最近消息(AI Agent 专用)
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'ai:getRecentMessages',
|
||||
@@ -63,6 +63,21 @@ export function registerMessagesHandlers({ win }: IpcContext): void {
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* 获取所有最近消息(消息查看器专用)
|
||||
*/
|
||||
ipcMain.handle(
|
||||
'ai:getAllRecentMessages',
|
||||
async (_, sessionId: string, filter?: { startTs?: number; endTs?: number }, limit?: number) => {
|
||||
try {
|
||||
return await worker.getAllRecentMessages(sessionId, filter, limit)
|
||||
} catch (error) {
|
||||
console.error('获取所有最近消息失败:', error)
|
||||
return { messages: [], total: 0 }
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* 获取两人之间的对话
|
||||
*/
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
searchMessages,
|
||||
getMessageContext,
|
||||
getRecentMessages,
|
||||
getAllRecentMessages,
|
||||
getConversationBetween,
|
||||
getMessagesBefore,
|
||||
getMessagesAfter,
|
||||
@@ -106,6 +107,7 @@ const syncHandlers: Record<string, (payload: any) => any> = {
|
||||
searchMessages: (p) => searchMessages(p.sessionId, p.keywords, p.filter, p.limit, p.offset, p.senderId),
|
||||
getMessageContext: (p) => getMessageContext(p.sessionId, p.messageIds, p.contextSize),
|
||||
getRecentMessages: (p) => getRecentMessages(p.sessionId, p.filter, p.limit),
|
||||
getAllRecentMessages: (p) => getAllRecentMessages(p.sessionId, p.filter, p.limit),
|
||||
getConversationBetween: (p) => getConversationBetween(p.sessionId, p.memberId1, p.memberId2, p.filter, p.limit),
|
||||
getMessagesBefore: (p) => getMessagesBefore(p.sessionId, p.beforeId, p.limit, p.filter, p.senderId, p.keywords),
|
||||
getMessagesAfter: (p) => getMessagesAfter(p.sessionId, p.afterId, p.limit, p.filter, p.senderId, p.keywords),
|
||||
|
||||
@@ -41,6 +41,7 @@ export {
|
||||
searchMessages,
|
||||
getMessageContext,
|
||||
getRecentMessages,
|
||||
getAllRecentMessages,
|
||||
getConversationBetween,
|
||||
getMessagesBefore,
|
||||
getMessagesAfter,
|
||||
|
||||
@@ -113,7 +113,7 @@ const TEXT_ONLY_FILTER = 'AND msg.type = 0 AND msg.content IS NOT NULL AND msg.c
|
||||
// ==================== 查询函数 ====================
|
||||
|
||||
/**
|
||||
* 获取最近的消息
|
||||
* 获取最近的消息(AI Agent 专用,只返回文本消息)
|
||||
* @param sessionId 会话 ID
|
||||
* @param filter 时间过滤器
|
||||
* @param limit 返回数量限制
|
||||
@@ -176,6 +176,66 @@ export function getRecentMessages(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有最近的消息(消息查看器专用,包含所有类型消息)
|
||||
* @param sessionId 会话 ID
|
||||
* @param filter 时间过滤器
|
||||
* @param limit 返回数量限制
|
||||
*/
|
||||
export function getAllRecentMessages(
|
||||
sessionId: string,
|
||||
filter?: TimeFilter,
|
||||
limit: number = 100
|
||||
): MessagesWithTotal {
|
||||
// 确保数据库有 avatar 字段(兼容旧数据库)
|
||||
ensureAvatarColumn(sessionId)
|
||||
|
||||
const db = openDatabase(sessionId)
|
||||
if (!db) return { messages: [], total: 0 }
|
||||
|
||||
// 构建时间过滤条件
|
||||
const { clause: timeClause, params: timeParams } = buildTimeFilter(filter)
|
||||
const timeCondition = timeClause ? timeClause.replace('WHERE', 'AND') : ''
|
||||
|
||||
// 查询总数
|
||||
const countSql = `
|
||||
SELECT COUNT(*) as total
|
||||
FROM message msg
|
||||
JOIN member m ON msg.sender_id = m.id
|
||||
WHERE 1=1
|
||||
${timeCondition}
|
||||
`
|
||||
const totalRow = db.prepare(countSql).get(...timeParams) as { total: number }
|
||||
const total = totalRow?.total || 0
|
||||
|
||||
// 查询最近消息(按时间降序)
|
||||
const sql = `
|
||||
SELECT
|
||||
msg.id,
|
||||
COALESCE(m.group_nickname, m.account_name, m.platform_id) as senderName,
|
||||
m.platform_id as senderPlatformId,
|
||||
m.aliases,
|
||||
m.avatar,
|
||||
msg.content,
|
||||
msg.ts as timestamp,
|
||||
msg.type
|
||||
FROM message msg
|
||||
JOIN member m ON msg.sender_id = m.id
|
||||
WHERE 1=1
|
||||
${timeCondition}
|
||||
ORDER BY msg.ts DESC
|
||||
LIMIT ?
|
||||
`
|
||||
|
||||
const rows = db.prepare(sql).all(...timeParams, limit) as DbMessageRow[]
|
||||
|
||||
// 返回时按时间正序排列(便于阅读)
|
||||
return {
|
||||
messages: rows.map(sanitizeMessageRow).reverse(),
|
||||
total,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关键词搜索消息
|
||||
* @param sessionId 会话 ID
|
||||
@@ -221,7 +281,6 @@ export function searchMessages(
|
||||
JOIN member m ON msg.sender_id = m.id
|
||||
WHERE ${keywordCondition}
|
||||
${timeCondition}
|
||||
${SYSTEM_FILTER}
|
||||
${senderCondition}
|
||||
`
|
||||
const totalRow = db.prepare(countSql).get(...keywordParams, ...timeParams, ...senderParams) as { total: number }
|
||||
@@ -242,7 +301,6 @@ export function searchMessages(
|
||||
JOIN member m ON msg.sender_id = m.id
|
||||
WHERE ${keywordCondition}
|
||||
${timeCondition}
|
||||
${SYSTEM_FILTER}
|
||||
${senderCondition}
|
||||
ORDER BY msg.ts DESC
|
||||
LIMIT ? OFFSET ?
|
||||
@@ -384,7 +442,6 @@ export function getMessagesBefore(
|
||||
${timeCondition}
|
||||
${keywordCondition}
|
||||
${senderCondition}
|
||||
${SYSTEM_FILTER}
|
||||
ORDER BY msg.id DESC
|
||||
LIMIT ?
|
||||
`
|
||||
@@ -450,7 +507,6 @@ export function getMessagesAfter(
|
||||
${timeCondition}
|
||||
${keywordCondition}
|
||||
${senderCondition}
|
||||
${SYSTEM_FILTER}
|
||||
ORDER BY msg.id ASC
|
||||
LIMIT ?
|
||||
`
|
||||
|
||||
@@ -425,6 +425,17 @@ export async function getRecentMessages(
|
||||
return sendToWorker('getRecentMessages', { sessionId, filter, limit })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有最近消息(消息查看器专用,包含所有类型消息)
|
||||
*/
|
||||
export async function getAllRecentMessages(
|
||||
sessionId: string,
|
||||
filter?: any,
|
||||
limit?: number
|
||||
): Promise<{ messages: SearchMessageResult[]; total: number }> {
|
||||
return sendToWorker('getAllRecentMessages', { sessionId, filter, limit })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个成员之间的对话
|
||||
*/
|
||||
|
||||
Vendored
+7
@@ -159,6 +159,11 @@ interface AiApi {
|
||||
filter?: TimeFilter,
|
||||
limit?: number
|
||||
) => Promise<{ messages: SearchMessageResult[]; total: number }>
|
||||
getAllRecentMessages: (
|
||||
sessionId: string,
|
||||
filter?: TimeFilter,
|
||||
limit?: number
|
||||
) => Promise<{ messages: SearchMessageResult[]; total: number }>
|
||||
getConversationBetween: (
|
||||
sessionId: string,
|
||||
memberId1: number,
|
||||
@@ -380,6 +385,8 @@ interface CacheApi {
|
||||
filename: string,
|
||||
dataUrl: string
|
||||
) => Promise<{ success: boolean; filePath?: string; error?: string }>
|
||||
getLatestImportLog: () => Promise<{ success: boolean; path?: string; name?: string; error?: string }>
|
||||
showInFolder: (filePath: string) => Promise<{ success: boolean; error?: string }>
|
||||
}
|
||||
|
||||
// Network API 类型 - 网络代理配置
|
||||
|
||||
@@ -501,7 +501,7 @@ const aiApi = {
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取最近消息
|
||||
* 获取最近消息(AI Agent 专用)
|
||||
*/
|
||||
getRecentMessages: (
|
||||
sessionId: string,
|
||||
@@ -511,6 +511,17 @@ const aiApi = {
|
||||
return ipcRenderer.invoke('ai:getRecentMessages', sessionId, filter, limit)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取所有最近消息(消息查看器专用)
|
||||
*/
|
||||
getAllRecentMessages: (
|
||||
sessionId: string,
|
||||
filter?: { startTs?: number; endTs?: number },
|
||||
limit?: number
|
||||
): Promise<{ messages: SearchMessageResult[]; total: number }> => {
|
||||
return ipcRenderer.invoke('ai:getAllRecentMessages', sessionId, filter, limit)
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取两人之间的对话
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user