mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
feat(risk-control): record matched keyword in keyword-block logs
The risk control center's moderation log records had no field for the keyword that triggered a keyword block, so the admin UI couldn't show which keyword was hit (only the application slog logged it). - migration 156: add matched_keyword column to content_moderation_logs - ContentModerationLog gains MatchedKeyword; set it on keyword block - repo CreateLog/ListLogs persist and read the column - frontend: show "命中关键词" inline in the log table and detail modal - i18n: add matchedKeyword (zh/en) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -182,6 +182,7 @@ export interface ContentModerationLog {
|
||||
flagged: boolean
|
||||
highest_category: string
|
||||
highest_score: number
|
||||
matched_keyword: string
|
||||
category_scores: Record<string, number>
|
||||
threshold_snapshot: Record<string, number>
|
||||
input_excerpt: string
|
||||
|
||||
@@ -2648,6 +2648,7 @@ export default {
|
||||
unbanFailed: 'Failed to unban user',
|
||||
inputDetailTitle: 'Input Summary Detail',
|
||||
inputDetailContent: 'Full Content',
|
||||
matchedKeyword: 'Matched Keyword',
|
||||
queueDelay: 'Queued {ms} ms',
|
||||
allGroups: 'All Groups',
|
||||
allGroupsHint: 'Auditing all groups',
|
||||
|
||||
@@ -2725,6 +2725,7 @@ export default {
|
||||
unbanFailed: '解封用户失败',
|
||||
inputDetailTitle: '输入摘要详情',
|
||||
inputDetailContent: '完整内容',
|
||||
matchedKeyword: '命中关键词',
|
||||
queueDelay: '排队 {ms} ms',
|
||||
allGroups: '全部分组',
|
||||
allGroupsHint: '当前审计全部分组',
|
||||
|
||||
@@ -317,6 +317,9 @@
|
||||
<td class="whitespace-nowrap px-5 py-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
<div>{{ row.highest_category || '-' }}</div>
|
||||
<div class="text-xs text-gray-400">{{ percent(row.highest_score) }}</div>
|
||||
<div v-if="row.matched_keyword" class="mt-0.5 text-xs font-medium text-red-600 dark:text-red-300" :title="t('admin.riskControl.matchedKeyword') + ': ' + row.matched_keyword">
|
||||
{{ t('admin.riskControl.matchedKeyword') }}: {{ row.matched_keyword }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-5 py-4 text-sm text-gray-700 dark:text-gray-300">
|
||||
<div>{{ violationCountText(row) }}</div>
|
||||
@@ -1078,6 +1081,10 @@
|
||||
{{ inputDetailRow.highest_category || '-' }} / {{ percent(inputDetailRow.highest_score) }}
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="inputDetailRow.matched_keyword" class="rounded-lg border border-red-100 bg-red-50 p-4 dark:border-red-900/60 dark:bg-red-900/20">
|
||||
<p class="text-xs font-medium text-red-500 dark:text-red-300">{{ t('admin.riskControl.matchedKeyword') }}</p>
|
||||
<p class="mt-1 truncate text-sm font-semibold text-red-700 dark:text-red-200" :title="inputDetailRow.matched_keyword">{{ inputDetailRow.matched_keyword }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border border-gray-100 bg-white p-4 shadow-sm dark:border-dark-700 dark:bg-dark-800">
|
||||
|
||||
Reference in New Issue
Block a user