知识库文件日志
This commit is contained in:
@@ -139,7 +139,8 @@ declare module 'shared/types' {
|
||||
ChatMessageListParam,
|
||||
SSEMessageData,
|
||||
SSECallbacks,
|
||||
SSETask
|
||||
SSETask,
|
||||
TbKnowledgeFileLog
|
||||
} from '../../../shared/src/types/ai'
|
||||
|
||||
// 重新导出 menu
|
||||
|
||||
@@ -11,49 +11,72 @@
|
||||
<!-- 筛选区域 -->
|
||||
<el-card class="filter-card">
|
||||
<div class="ticket-filters">
|
||||
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" style="width: 280px;" />
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
style="width: 280px;"
|
||||
@change="handleSearch"
|
||||
/>
|
||||
|
||||
<div class="filter-right">
|
||||
<el-select v-model="operationFilter" placeholder="操作类型" clearable style="width: 140px;">
|
||||
<el-select v-model="filter.action" placeholder="操作类型" clearable style="width: 140px;" @change="handleSearch">
|
||||
<el-option label="上传" value="upload" />
|
||||
<el-option label="下载" value="download" />
|
||||
<el-option label="删除" value="delete" />
|
||||
<el-option label="更新" value="update" />
|
||||
</el-select>
|
||||
<el-select v-model="kbTypeFilter" placeholder="知识库类型" clearable style="width: 140px;">
|
||||
<el-option label="外部知识库" value="external" />
|
||||
<el-option label="内部知识库" value="internal" />
|
||||
<el-select v-model="filter.knowledgeId" placeholder="知识库" clearable style="width: 180px;" @change="handleSearch">
|
||||
<el-option
|
||||
v-for="kb in knowledgeList"
|
||||
:key="kb.knowledgeId"
|
||||
:label="kb.title"
|
||||
:value="kb.knowledgeId"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input v-model="searchKeyword" placeholder="搜索文件名/操作人" style="width: 200px;" :prefix-icon="Search" clearable />
|
||||
<el-input
|
||||
v-model="filter.fileName"
|
||||
placeholder="搜索文件名"
|
||||
style="width: 200px;"
|
||||
:prefix-icon="Search"
|
||||
clearable
|
||||
@clear="handleSearch"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 日志列表 -->
|
||||
<el-card>
|
||||
<el-table :data="filteredLogs" style="width: 100%">
|
||||
<el-table-column prop="logId" label="日志ID" width="120">
|
||||
<el-card v-loading="loading">
|
||||
<el-table :data="logs" style="width: 100%">
|
||||
<el-table-column prop="logId" label="日志ID" width="180">
|
||||
<template #default="{ row }">
|
||||
<span style="color: #409eff; font-weight: 500;">{{ row.logId }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fileName" label="文件名" min-width="200" />
|
||||
<el-table-column prop="operation" label="操作类型" width="100">
|
||||
<el-table-column prop="fileName" label="文件名" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="action" label="操作类型" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getOperationType(row.operation)" size="small">
|
||||
{{ row.operationName }}
|
||||
<el-tag :type="getOperationType(row.action)" size="small">
|
||||
{{ getOperationName(row.action) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="kbType" label="知识库" width="100">
|
||||
<el-table-column prop="version" label="版本" width="80">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.kbType === 'external' ? '外部' : '内部' }}</span>
|
||||
<span>v{{ row.version || 1 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operator" label="操作人" width="100" />
|
||||
<el-table-column prop="operationTime" label="操作时间" width="160" />
|
||||
<el-table-column prop="fileSize" label="文件大小" width="100" />
|
||||
<el-table-column label="操作" width="120" fixed="right">
|
||||
<el-table-column prop="creatorName" label="操作人" width="120" />
|
||||
<el-table-column prop="createTime" label="操作时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatTime(row.createTime) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link size="small" @click="viewDetail(row)">详情</el-button>
|
||||
</template>
|
||||
@@ -61,7 +84,15 @@
|
||||
</el-table>
|
||||
|
||||
<div class="table-pagination">
|
||||
<el-pagination v-model:current-page="currentPage" :page-size="10" :total="logs.length" layout="total, prev, pager, next" />
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.page"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:total="pagination.total"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
@size-change="loadLogs"
|
||||
@current-change="loadLogs"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
@@ -76,19 +107,22 @@
|
||||
<span>{{ selectedLog.fileName }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作类型">
|
||||
<el-tag :type="getOperationType(selectedLog.operation)">{{ selectedLog.operationName }}</el-tag>
|
||||
<el-tag :type="getOperationType(selectedLog.action)">{{ getOperationName(selectedLog.action) }}</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="知识库">
|
||||
<span>{{ selectedLog.kbType === 'external' ? '外部知识库' : '内部知识库' }}</span>
|
||||
<el-form-item label="文件版本">
|
||||
<span>v{{ selectedLog.version || 1 }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人">
|
||||
<span>{{ selectedLog.operator }}</span>
|
||||
<span>{{ selectedLog.creatorName }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作时间">
|
||||
<span>{{ selectedLog.operationTime }}</span>
|
||||
<span>{{ formatTime(selectedLog.createTime) }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件大小">
|
||||
<span>{{ selectedLog.fileSize }}</span>
|
||||
<el-form-item label="知识库ID">
|
||||
<span>{{ selectedLog.knowledgeId }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件ID">
|
||||
<span>{{ selectedLog.fileId }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
@@ -96,63 +130,140 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import AdminLayout from '@/views/admin/AdminLayout.vue'
|
||||
import { Download, Search } from 'lucide-vue-next'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { aiKnowledgeAPI } from 'shared/api/ai'
|
||||
import type { TbKnowledgeFileLog, TbKnowledge } from 'shared/types'
|
||||
|
||||
const loading = ref(false)
|
||||
const dateRange = ref<[Date, Date] | null>(null)
|
||||
const operationFilter = ref('')
|
||||
const kbTypeFilter = ref('')
|
||||
const searchKeyword = ref('')
|
||||
const currentPage = ref(1)
|
||||
const showDetailDialog = ref(false)
|
||||
const selectedLog = ref<any>(null)
|
||||
const selectedLog = ref<TbKnowledgeFileLog | null>(null)
|
||||
|
||||
const logs = ref([
|
||||
{ logId: 'LOG001', fileName: 'TH-500GF操作手册.pdf', operation: 'upload', operationName: '上传', kbType: 'external', operator: '张三', operationTime: '2024-12-10 14:30', fileSize: '2.5MB' },
|
||||
{ logId: 'LOG002', fileName: 'TH-300D故障排查指南.pdf', operation: 'upload', operationName: '上传', kbType: 'external', operator: '李四', operationTime: '2024-12-09 10:15', fileSize: '1.8MB' },
|
||||
{ logId: 'LOG003', fileName: '内部技术规范v2.0.pdf', operation: 'update', operationName: '更新', kbType: 'internal', operator: '赵六', operationTime: '2024-12-11 16:20', fileSize: '3.2MB' },
|
||||
{ logId: 'LOG004', fileName: '售后服务流程.pdf', operation: 'download', operationName: '下载', kbType: 'internal', operator: '孙七', operationTime: '2024-12-10 11:00', fileSize: '1.1MB' },
|
||||
{ logId: 'LOG005', fileName: '员工培训手册.pdf', operation: 'delete', operationName: '删除', kbType: 'internal', operator: '周八', operationTime: '2024-12-09 15:30', fileSize: '2.0MB' }
|
||||
])
|
||||
|
||||
const filteredLogs = computed(() => {
|
||||
let result = logs.value
|
||||
if (operationFilter.value) {
|
||||
result = result.filter(l => l.operation === operationFilter.value)
|
||||
}
|
||||
if (kbTypeFilter.value) {
|
||||
result = result.filter(l => l.kbType === kbTypeFilter.value)
|
||||
}
|
||||
if (searchKeyword.value) {
|
||||
const keyword = searchKeyword.value.toLowerCase()
|
||||
result = result.filter(l =>
|
||||
l.fileName.toLowerCase().includes(keyword) ||
|
||||
l.operator.toLowerCase().includes(keyword)
|
||||
)
|
||||
}
|
||||
return result.slice((currentPage.value - 1) * 10, currentPage.value * 10)
|
||||
// 筛选条件
|
||||
const filter = reactive<TbKnowledgeFileLog>({
|
||||
action: '',
|
||||
knowledgeId: '',
|
||||
fileName: '',
|
||||
service: 'workcase'
|
||||
})
|
||||
|
||||
const getOperationType = (operation: string) => {
|
||||
const map: Record<string, string> = {
|
||||
upload: 'success',
|
||||
download: 'info',
|
||||
delete: 'danger',
|
||||
update: 'warning'
|
||||
}
|
||||
return map[operation] || 'info'
|
||||
// 分页
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 日志列表
|
||||
const logs = ref<TbKnowledgeFileLog[]>([])
|
||||
|
||||
// 知识库列表(用于筛选)
|
||||
const knowledgeList = ref<TbKnowledge[]>([])
|
||||
|
||||
// 操作类型映射
|
||||
const operationTypeMap: Record<string, string> = {
|
||||
upload: 'success',
|
||||
download: 'info',
|
||||
delete: 'danger',
|
||||
update: 'warning'
|
||||
}
|
||||
|
||||
const viewDetail = (row: any) => {
|
||||
const operationNameMap: Record<string, string> = {
|
||||
upload: '上传',
|
||||
download: '下载',
|
||||
delete: '删除',
|
||||
update: '更新'
|
||||
}
|
||||
|
||||
const getOperationType = (action: string) => operationTypeMap[action] || 'info'
|
||||
const getOperationName = (action: string) => operationNameMap[action] || action
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (time?: string | number): string => {
|
||||
if (!time) return '-'
|
||||
const date = new Date(time)
|
||||
return date.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
})
|
||||
}
|
||||
|
||||
// 加载知识库列表
|
||||
const loadKnowledgeList = async () => {
|
||||
try {
|
||||
const result = await aiKnowledgeAPI.listKnowledges({})
|
||||
if (result.success && result.dataList) {
|
||||
knowledgeList.value = result.dataList
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载知识库列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载日志列表
|
||||
const loadLogs = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 构建查询条件
|
||||
const queryFilter: TbKnowledgeFileLog = { ...filter }
|
||||
console.log(queryFilter)
|
||||
// 处理日期范围
|
||||
if (dateRange.value && dateRange.value[0] && dateRange.value[1]) {
|
||||
queryFilter.createTimeStart = dateRange.value[0].toISOString()
|
||||
queryFilter.createTimeEnd = dateRange.value[1].toISOString()
|
||||
}
|
||||
|
||||
const result = await aiKnowledgeAPI.getFileLogPage({
|
||||
filter: queryFilter,
|
||||
pageParam: {
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
total: 0
|
||||
}
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
logs.value = result.dataList || []
|
||||
pagination.total = result.pageParam?.total || 0
|
||||
} else {
|
||||
ElMessage.error(result.message || '加载日志失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载日志失败:', error)
|
||||
ElMessage.error('加载日志失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
pagination.page = 1
|
||||
loadLogs()
|
||||
}
|
||||
|
||||
// 查看详情
|
||||
const viewDetail = (row: TbKnowledgeFileLog) => {
|
||||
selectedLog.value = row
|
||||
showDetailDialog.value = true
|
||||
}
|
||||
|
||||
// 导出日志
|
||||
const exportLogs = () => {
|
||||
ElMessage.success('日志导出成功')
|
||||
ElMessage.success('日志导出功能开发中')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadKnowledgeList()
|
||||
loadLogs()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -163,4 +274,4 @@ const exportLogs = () => {
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user