feat:新增通知调试台和导入历史页
This commit is contained in:
154
src/services/notificationDebugService.js
Normal file
154
src/services/notificationDebugService.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { getDb, saveDbToStore } from '../lib/sqlite.js'
|
||||
|
||||
export const NOTIFICATION_DEBUG_STATUS = {
|
||||
review: 'review',
|
||||
unmatched: 'unmatched',
|
||||
matched: 'matched',
|
||||
ignored: 'ignored',
|
||||
error: 'error',
|
||||
}
|
||||
|
||||
const mapRow = (row) => ({
|
||||
id: row.id,
|
||||
sourceId: row.source_id || '',
|
||||
channel: row.channel || '',
|
||||
title: row.title || '',
|
||||
text: row.text || '',
|
||||
postedAt: row.posted_at || '',
|
||||
status: row.status || NOTIFICATION_DEBUG_STATUS.unmatched,
|
||||
ruleId: row.rule_id || '',
|
||||
transactionId: row.transaction_id || '',
|
||||
errorMessage: row.error_message || '',
|
||||
})
|
||||
|
||||
const getLatestBySourceId = async (sourceId) => {
|
||||
if (!sourceId) return null
|
||||
const db = await getDb()
|
||||
const result = await db.query(
|
||||
`
|
||||
SELECT *
|
||||
FROM notifications_raw
|
||||
WHERE source_id = ?
|
||||
ORDER BY posted_at DESC
|
||||
LIMIT 1
|
||||
`,
|
||||
[sourceId],
|
||||
)
|
||||
return result?.values?.[0] ? mapRow(result.values[0]) : null
|
||||
}
|
||||
|
||||
export const ensureNotificationRaw = async (notification, options = {}) => {
|
||||
const sourceId = notification?.id || notification?.sourceId || ''
|
||||
const existing = await getLatestBySourceId(sourceId)
|
||||
if (existing) return existing
|
||||
|
||||
const db = await getDb()
|
||||
const id = notification?.rawId || uuidv4()
|
||||
await db.run(
|
||||
`
|
||||
INSERT INTO notifications_raw (
|
||||
id,
|
||||
source_id,
|
||||
channel,
|
||||
title,
|
||||
text,
|
||||
posted_at,
|
||||
status,
|
||||
rule_id,
|
||||
transaction_id,
|
||||
error_message
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`,
|
||||
[
|
||||
id,
|
||||
sourceId || null,
|
||||
notification?.channel || null,
|
||||
notification?.title || null,
|
||||
notification?.text || '',
|
||||
notification?.createdAt || notification?.postedAt || new Date().toISOString(),
|
||||
options.status || NOTIFICATION_DEBUG_STATUS.unmatched,
|
||||
options.ruleId || null,
|
||||
options.transactionId || null,
|
||||
options.errorMessage || null,
|
||||
],
|
||||
)
|
||||
await saveDbToStore()
|
||||
return {
|
||||
id,
|
||||
sourceId,
|
||||
channel: notification?.channel || '',
|
||||
title: notification?.title || '',
|
||||
text: notification?.text || '',
|
||||
postedAt: notification?.createdAt || notification?.postedAt || '',
|
||||
status: options.status || NOTIFICATION_DEBUG_STATUS.unmatched,
|
||||
ruleId: options.ruleId || '',
|
||||
transactionId: options.transactionId || '',
|
||||
errorMessage: options.errorMessage || '',
|
||||
}
|
||||
}
|
||||
|
||||
export const updateNotificationRawStatus = async (sourceId, next = {}) => {
|
||||
if (!sourceId) return null
|
||||
const existing = await getLatestBySourceId(sourceId)
|
||||
if (!existing) return null
|
||||
|
||||
const db = await getDb()
|
||||
await db.run(
|
||||
`
|
||||
UPDATE notifications_raw
|
||||
SET status = ?, rule_id = ?, transaction_id = ?, error_message = ?
|
||||
WHERE id = ?
|
||||
`,
|
||||
[
|
||||
next.status || existing.status,
|
||||
next.ruleId ?? existing.ruleId ?? null,
|
||||
next.transactionId ?? existing.transactionId ?? null,
|
||||
next.errorMessage ?? existing.errorMessage ?? null,
|
||||
existing.id,
|
||||
],
|
||||
)
|
||||
await saveDbToStore()
|
||||
return {
|
||||
...existing,
|
||||
status: next.status || existing.status,
|
||||
ruleId: next.ruleId ?? existing.ruleId,
|
||||
transactionId: next.transactionId ?? existing.transactionId,
|
||||
errorMessage: next.errorMessage ?? existing.errorMessage,
|
||||
}
|
||||
}
|
||||
|
||||
export const fetchNotificationDebugRecords = async (options = {}) => {
|
||||
const db = await getDb()
|
||||
const params = []
|
||||
const where = []
|
||||
|
||||
if (options.status && options.status !== 'all') {
|
||||
where.push('status = ?')
|
||||
params.push(options.status)
|
||||
}
|
||||
|
||||
if (options.keyword) {
|
||||
where.push('(channel LIKE ? OR title LIKE ? OR text LIKE ?)')
|
||||
const keyword = `%${String(options.keyword).trim()}%`
|
||||
params.push(keyword, keyword, keyword)
|
||||
}
|
||||
|
||||
const whereClause = where.length ? `WHERE ${where.join(' AND ')}` : ''
|
||||
const limit = Math.max(1, Math.min(Number(options.limit) || 80, 200))
|
||||
params.push(limit)
|
||||
|
||||
const result = await db.query(
|
||||
`
|
||||
SELECT *
|
||||
FROM notifications_raw
|
||||
${whereClause}
|
||||
ORDER BY posted_at DESC
|
||||
LIMIT ?
|
||||
`,
|
||||
params,
|
||||
)
|
||||
|
||||
return (result?.values || []).map(mapRow)
|
||||
}
|
||||
Reference in New Issue
Block a user