You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
41 lines
3.2 KiB
41 lines
3.2 KiB
<template>
|
|
<t-card title="📋 内容审计日志" :bordered="false">
|
|
<p class="desc-text">记录所有敏感词命中事件,包含输入/输出方向、违规内容、命中词及处理方式。</p>
|
|
<BaseTable :data="logs" :columns="columns" row-key="id" :loading="loading" :sort="sortInfo"
|
|
:pagination="{current:page,total:total,pageSize:pageSize,showJumper:true}" @page-change="onPageChange" @sort-change="onSortChange">
|
|
<template #direction="{row}"><span :style="{color:row.direction==='INPUT'?'var(--color-primary)':'var(--color-success)'}">{{ row.direction==='INPUT'?'输入':'输出' }}</span></template>
|
|
<template #originalText="{row}"><span :title="row.originalText" class="ellipsis-td">{{ row.originalText }}</span></template>
|
|
<template #actionTaken="{row}"><span :style="{color:row.actionTaken==='BLOCK'?'var(--color-error)':row.actionTaken==='MASK'?'var(--color-warning)':'var(--color-success)'}">{{ row.actionTaken==='BLOCK'?'拦截':row.actionTaken==='MASK'?'脱敏':'通过' }}</span></template>
|
|
<template #hitWords="{row}"><span class="hit-words">{{ formatHitWords(row.hitWords) }}</span></template>
|
|
</BaseTable>
|
|
</t-card>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue'
|
|
import { listAuditLogs } from '@/api/sensitive-word'
|
|
import { toast } from '@/utils/toast'
|
|
import { formatDate } from '@/utils/format'
|
|
|
|
const logs=ref<any[]>([]);const loading=ref(false);const page=ref(1);const pageSize=ref(30);const total=ref(0)
|
|
|
|
const columns=[{colKey:'createTime',title:'时间',width:160,sorter:true,cell:(_:any,{row}:any)=>formatDate(row.createTime)},{colKey:'direction',title:'方向',width:60,sorter:true},{colKey:'originalText',title:'违规内容',width:260},{colKey:'hitWords',title:'命中词',width:180},{colKey:'actionTaken',title:'处理方式',width:80,sorter:true}]
|
|
const sortInfo = ref<{ sortBy: string; descending: boolean } | null>(null)
|
|
|
|
onMounted(()=>loadLogs())
|
|
|
|
async function loadLogs(){loading.value=true
|
|
try{const r=await listAuditLogs(page.value,pageSize.value,undefined,sortInfo.value?.sortBy||undefined,sortInfo.value?(sortInfo.value.descending?'desc':'asc'):undefined);if(r.success){logs.value=r.data?.records||r.data||[];total.value=r.data?.total||r.total||0}else toast('加载失败:'+(r.message||''),'error')}catch(e:any){toast('加载失败:'+e.message,'error')}finally{loading.value=false}}
|
|
|
|
function onPageChange(i:{current:number;pageSize:number}){page.value=i.current;pageSize.value=i.pageSize;loadLogs()}
|
|
function onSortChange(s:any){sortInfo.value=s&&s.sortBy?{sortBy:s.sortBy,descending:!!s.descending}:null;loadLogs()}
|
|
|
|
function formatHitWords(hw:any):string{
|
|
if(!hw)return'';if(hw.type==='jsonb'&&hw.value){try{hw=JSON.parse(hw.value)}catch{return hw.value}}
|
|
if(typeof hw==='string'){try{hw=JSON.parse(hw)}catch{return hw}}
|
|
if(hw?.hits&&Array.isArray(hw.hits))return hw.hits.map((h:any)=>`${h.word||''}(${h.category||''})`).join('、')
|
|
if(Array.isArray(hw))return hw.map((h:any)=>typeof h==='string'?h:h.word||'').join('、')
|
|
return String(hw)
|
|
}
|
|
</script>
|
|
<style scoped>.ellipsis-td{max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;}.hit-words{font-size:12px;}</style>
|