Files
ChatLab/electron/preload/apis/chat.ts
T
2026-02-02 01:00:15 +08:00

482 lines
13 KiB
TypeScript

/**
* 聊天记录 API - 导入、分析、管理聊天记录
*/
import { ipcRenderer } from 'electron'
import type { AnalysisSession, MessageType, ImportProgress } from '../../../src/types/base'
import type {
MemberActivity,
MemberNameHistory,
HourlyActivity,
DailyActivity,
WeekdayActivity,
MonthlyActivity,
RepeatAnalysis,
CatchphraseAnalysis,
NightOwlAnalysis,
DragonKingAnalysis,
DivingAnalysis,
MentionAnalysis,
LaughAnalysis,
CheckInAnalysis,
MemeBattleAnalysis,
MemberWithStats,
} from '../../../src/types/analysis'
import type { FileParseInfo, ConflictCheckResult, MergeParams, MergeResult } from '../../../src/types/format'
// Chat Analysis API
export const chatApi = {
// ==================== 数据库迁移 ====================
/**
* 检查是否需要数据库迁移
*/
checkMigration: (): Promise<{
needsMigration: boolean
count: number
currentVersion: number
pendingMigrations: Array<{ version: number; userMessage: string }>
}> => {
return ipcRenderer.invoke('chat:checkMigration')
},
/**
* 执行数据库迁移
*/
runMigration: (): Promise<{ success: boolean; migratedCount: number; error?: string }> => {
return ipcRenderer.invoke('chat:runMigration')
},
// ==================== 聊天记录导入与分析 ====================
/**
* 选择聊天记录文件
*/
selectFile: (): Promise<{ filePath?: string; format?: string; error?: string } | null> => {
return ipcRenderer.invoke('chat:selectFile')
},
/**
* 导入聊天记录
*/
import: (filePath: string): Promise<{ success: boolean; sessionId?: string; error?: string }> => {
return ipcRenderer.invoke('chat:import', filePath)
},
/**
* 获取所有分析会话列表
*/
getSessions: (): Promise<AnalysisSession[]> => {
return ipcRenderer.invoke('chat:getSessions')
},
/**
* 获取单个会话信息
*/
getSession: (sessionId: string): Promise<AnalysisSession | null> => {
return ipcRenderer.invoke('chat:getSession', sessionId)
},
/**
* 删除会话
*/
deleteSession: (sessionId: string): Promise<boolean> => {
return ipcRenderer.invoke('chat:deleteSession', sessionId)
},
/**
* 重命名会话
*/
renameSession: (sessionId: string, newName: string): Promise<boolean> => {
return ipcRenderer.invoke('chat:renameSession', sessionId, newName)
},
/**
* 获取可用年份列表
*/
getAvailableYears: (sessionId: string): Promise<number[]> => {
return ipcRenderer.invoke('chat:getAvailableYears', sessionId)
},
/**
* 获取成员活跃度排行
*/
getMemberActivity: (sessionId: string, filter?: { startTs?: number; endTs?: number }): Promise<MemberActivity[]> => {
return ipcRenderer.invoke('chat:getMemberActivity', sessionId, filter)
},
/**
* 获取成员历史昵称
*/
getMemberNameHistory: (sessionId: string, memberId: number): Promise<MemberNameHistory[]> => {
return ipcRenderer.invoke('chat:getMemberNameHistory', sessionId, memberId)
},
/**
* 获取每小时活跃度分布
*/
getHourlyActivity: (sessionId: string, filter?: { startTs?: number; endTs?: number }): Promise<HourlyActivity[]> => {
return ipcRenderer.invoke('chat:getHourlyActivity', sessionId, filter)
},
/**
* 获取每日活跃度趋势
*/
getDailyActivity: (sessionId: string, filter?: { startTs?: number; endTs?: number }): Promise<DailyActivity[]> => {
return ipcRenderer.invoke('chat:getDailyActivity', sessionId, filter)
},
/**
* 获取星期活跃度分布
*/
getWeekdayActivity: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<WeekdayActivity[]> => {
return ipcRenderer.invoke('chat:getWeekdayActivity', sessionId, filter)
},
/**
* 获取月份活跃度分布
*/
getMonthlyActivity: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<MonthlyActivity[]> => {
return ipcRenderer.invoke('chat:getMonthlyActivity', sessionId, filter)
},
/**
* 获取年份活跃度分布
*/
getYearlyActivity: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<Array<{ year: number; messageCount: number }>> => {
return ipcRenderer.invoke('chat:getYearlyActivity', sessionId, filter)
},
/**
* 获取消息长度分布
*/
getMessageLengthDistribution: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<{
detail: Array<{ len: number; count: number }>
grouped: Array<{ range: string; count: number }>
}> => {
return ipcRenderer.invoke('chat:getMessageLengthDistribution', sessionId, filter)
},
/**
* 获取消息类型分布
*/
getMessageTypeDistribution: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<Array<{ type: MessageType; count: number }>> => {
return ipcRenderer.invoke('chat:getMessageTypeDistribution', sessionId, filter)
},
/**
* 获取时间范围
*/
getTimeRange: (sessionId: string): Promise<{ start: number; end: number } | null> => {
return ipcRenderer.invoke('chat:getTimeRange', sessionId)
},
/**
* 获取数据库存储目录
*/
getDbDirectory: (): Promise<string | null> => {
return ipcRenderer.invoke('chat:getDbDirectory')
},
/**
* 获取支持的格式列表
*/
getSupportedFormats: (): Promise<Array<{ name: string; platform: string }>> => {
return ipcRenderer.invoke('chat:getSupportedFormats')
},
/**
* 监听导入进度
*/
onImportProgress: (callback: (progress: ImportProgress) => void) => {
const handler = (_event: Electron.IpcRendererEvent, progress: ImportProgress) => {
callback(progress)
}
ipcRenderer.on('chat:importProgress', handler)
return () => {
ipcRenderer.removeListener('chat:importProgress', handler)
}
},
/**
* 获取复读分析数据
*/
getRepeatAnalysis: (sessionId: string, filter?: { startTs?: number; endTs?: number }): Promise<RepeatAnalysis> => {
return ipcRenderer.invoke('chat:getRepeatAnalysis', sessionId, filter)
},
/**
* 获取口头禅分析数据
*/
getCatchphraseAnalysis: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<CatchphraseAnalysis> => {
return ipcRenderer.invoke('chat:getCatchphraseAnalysis', sessionId, filter)
},
/**
* 获取夜猫分析数据
*/
getNightOwlAnalysis: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<NightOwlAnalysis> => {
return ipcRenderer.invoke('chat:getNightOwlAnalysis', sessionId, filter)
},
/**
* 获取龙王分析数据
*/
getDragonKingAnalysis: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<DragonKingAnalysis> => {
return ipcRenderer.invoke('chat:getDragonKingAnalysis', sessionId, filter)
},
/**
* 获取潜水分析数据
*/
getDivingAnalysis: (sessionId: string, filter?: { startTs?: number; endTs?: number }): Promise<DivingAnalysis> => {
return ipcRenderer.invoke('chat:getDivingAnalysis', sessionId, filter)
},
/**
* 获取 @ 互动分析数据
*/
getMentionAnalysis: (sessionId: string, filter?: { startTs?: number; endTs?: number }): Promise<MentionAnalysis> => {
return ipcRenderer.invoke('chat:getMentionAnalysis', sessionId, filter)
},
/**
* 获取 @ 互动关系图数据
*/
getMentionGraph: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<{
nodes: Array<{ id: number; name: string; value: number; symbolSize: number }>
links: Array<{ source: string; target: string; value: number }>
maxLinkValue: number
}> => {
return ipcRenderer.invoke('chat:getMentionGraph', sessionId, filter)
},
/**
* 获取含笑量分析数据
*/
getLaughAnalysis: (
sessionId: string,
filter?: { startTs?: number; endTs?: number },
keywords?: string[]
): Promise<LaughAnalysis> => {
return ipcRenderer.invoke('chat:getLaughAnalysis', sessionId, filter, keywords)
},
/**
* 获取斗图分析数据
*/
getMemeBattleAnalysis: (
sessionId: string,
filter?: { startTs?: number; endTs?: number }
): Promise<MemeBattleAnalysis> => {
return ipcRenderer.invoke('chat:getMemeBattleAnalysis', sessionId, filter)
},
/**
* 获取打卡分析数据(火花榜 + 忠臣榜)
*/
getCheckInAnalysis: (sessionId: string, filter?: { startTs?: number; endTs?: number }): Promise<CheckInAnalysis> => {
return ipcRenderer.invoke('chat:getCheckInAnalysis', sessionId, filter)
},
// ==================== 成员管理 ====================
/**
* 获取所有成员列表(含消息数和别名)
*/
getMembers: (sessionId: string): Promise<MemberWithStats[]> => {
return ipcRenderer.invoke('chat:getMembers', sessionId)
},
/**
* 获取成员列表(分页版本)
*/
getMembersPaginated: (
sessionId: string,
params: { page: number; pageSize: number; search?: string; sortOrder?: 'asc' | 'desc' }
): Promise<{
members: MemberWithStats[]
total: number
page: number
pageSize: number
totalPages: number
}> => {
return ipcRenderer.invoke('chat:getMembersPaginated', sessionId, params)
},
/**
* 更新成员别名
*/
updateMemberAliases: (sessionId: string, memberId: number, aliases: string[]): Promise<boolean> => {
return ipcRenderer.invoke('chat:updateMemberAliases', sessionId, memberId, aliases)
},
/**
* 删除成员及其所有消息
*/
deleteMember: (sessionId: string, memberId: number): Promise<boolean> => {
return ipcRenderer.invoke('chat:deleteMember', sessionId, memberId)
},
/**
* 更新会话的所有者(ownerId)
* @param ownerId 成员的 platformId,设置为 null 则清除
*/
updateSessionOwnerId: (sessionId: string, ownerId: string | null): Promise<boolean> => {
return ipcRenderer.invoke('chat:updateSessionOwnerId', sessionId, ownerId)
},
// ==================== SQL 实验室 ====================
/**
* 执行用户 SQL 查询
*/
executeSQL: (
sessionId: string,
sql: string
): Promise<{
columns: string[]
rows: any[][]
rowCount: number
duration: number
limited: boolean
}> => {
return ipcRenderer.invoke('chat:executeSQL', sessionId, sql)
},
/**
* 获取数据库 Schema
*/
getSchema: (
sessionId: string
): Promise<
Array<{
name: string
columns: Array<{
name: string
type: string
notnull: boolean
pk: boolean
}>
}>
> => {
return ipcRenderer.invoke('chat:getSchema', sessionId)
},
// ==================== 增量导入 ====================
/**
* 分析增量导入(检测去重后能新增多少消息)
*/
analyzeIncrementalImport: (
sessionId: string,
filePath: string
): Promise<{
newMessageCount: number
duplicateCount: number
totalInFile: number
error?: string
diagnosis?: { suggestion?: string }
}> => {
return ipcRenderer.invoke('chat:analyzeIncrementalImport', sessionId, filePath)
},
/**
* 执行增量导入
*/
incrementalImport: (
sessionId: string,
filePath: string
): Promise<{
success: boolean
newMessageCount: number
error?: string
}> => {
return ipcRenderer.invoke('chat:incrementalImport', sessionId, filePath)
},
/**
* 导出多个会话为临时文件(用于批量管理中的合并)
*/
exportSessionsToTempFiles: (
sessionIds: string[]
): Promise<{
success: boolean
tempFiles: string[]
error?: string
}> => {
return ipcRenderer.invoke('chat:exportSessionsToTempFiles', sessionIds)
},
/**
* 清理临时导出文件
*/
cleanupTempExportFiles: (
filePaths: string[]
): Promise<{
success: boolean
error?: string
}> => {
return ipcRenderer.invoke('chat:cleanupTempExportFiles', filePaths)
},
}
// Merge API - 合并功能
export const mergeApi = {
/**
* 解析文件获取基本信息(用于合并预览)
* 解析后结果会被缓存,后续合并时无需再次读取原始文件
*/
parseFileInfo: (filePath: string): Promise<FileParseInfo> => {
return ipcRenderer.invoke('merge:parseFileInfo', filePath)
},
/**
* 检测合并冲突
*/
checkConflicts: (filePaths: string[]): Promise<ConflictCheckResult> => {
return ipcRenderer.invoke('merge:checkConflicts', filePaths)
},
/**
* 执行合并
*/
mergeFiles: (params: MergeParams): Promise<MergeResult> => {
return ipcRenderer.invoke('merge:mergeFiles', params)
},
/**
* 清理解析缓存
* @param filePath 可选,指定文件路径则清理该文件的缓存,否则清理所有缓存
*/
clearCache: (filePath?: string): Promise<boolean> => {
return ipcRenderer.invoke('merge:clearCache', filePath)
},
}