2025-08-10 14:32:24 +08:00
|
|
|
|
<script setup lang="ts">
|
2025-09-20 14:28:00 +08:00
|
|
|
|
import { ref, computed, reactive, onMounted, nextTick } from 'vue'
|
2025-08-10 14:32:24 +08:00
|
|
|
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
|
|
|
|
|
|
import { Button } from '@/components/ui/button'
|
|
|
|
|
|
import { Badge } from '@/components/ui/badge'
|
|
|
|
|
|
import { Input } from '@/components/ui/input'
|
|
|
|
|
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
|
|
|
|
|
|
import { Sheet, SheetContent, SheetHeader, SheetTitle } from '@/components/ui/sheet'
|
|
|
|
|
|
import EmptyTableState from '@/components/ui/EmptyTableState.vue'
|
|
|
|
|
|
import Pagination from '@/components/ui/Pagination.vue'
|
|
|
|
|
|
|
|
|
|
|
|
import { useRoute } from 'vue-router';
|
|
|
|
|
|
import { request } from '@/api/api';
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
|
import { getPageSize } from '@/util/pageUtils';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface LogItem {
|
|
|
|
|
|
id: number
|
|
|
|
|
|
task_id: number
|
|
|
|
|
|
task_name: string
|
|
|
|
|
|
log: string
|
|
|
|
|
|
created_on: string
|
|
|
|
|
|
caller_ip?: string
|
|
|
|
|
|
status: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const router = useRoute();
|
|
|
|
|
|
|
|
|
|
|
|
let state = reactive({
|
|
|
|
|
|
tableData: [] as LogItem[],
|
|
|
|
|
|
total: 0,
|
|
|
|
|
|
currPage: 1,
|
|
|
|
|
|
pageSize: getPageSize(),
|
|
|
|
|
|
search: '',
|
|
|
|
|
|
optionValue: '',
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 状态过滤
|
|
|
|
|
|
const selectedStatus = ref('all')
|
|
|
|
|
|
// Sheet 相关状态
|
|
|
|
|
|
const isSheetOpen = ref(false)
|
|
|
|
|
|
const selectedLog = ref('')
|
|
|
|
|
|
const selectedTaskName = ref('')
|
|
|
|
|
|
// 总页数
|
|
|
|
|
|
const totalPages = computed(() => Math.ceil(state.total / state.pageSize))
|
|
|
|
|
|
|
|
|
|
|
|
const getStatusText = (status: number) => {
|
|
|
|
|
|
return status === 1 ? '成功' : '失败'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 打开日志详情Sheet
|
|
|
|
|
|
const openLogSheet = (task: LogItem) => {
|
|
|
|
|
|
selectedLog.value = formatLogDisplayHtml(task);
|
|
|
|
|
|
selectedTaskName.value = task.task_name
|
|
|
|
|
|
isSheetOpen.value = true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const changePage = async (page: number) => {
|
|
|
|
|
|
if (page >= 1 && page <= totalPages.value) {
|
|
|
|
|
|
state.currPage = page
|
|
|
|
|
|
await queryListData(
|
|
|
|
|
|
state.currPage,
|
|
|
|
|
|
state.pageSize,
|
|
|
|
|
|
state.search,
|
|
|
|
|
|
state.optionValue
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 格式化处理显示的日志文本
|
|
|
|
|
|
const formatLogDisplayHtml = (task: LogItem) => {
|
|
|
|
|
|
let log = task.log;
|
|
|
|
|
|
log += '\n';
|
|
|
|
|
|
if (task.caller_ip) {
|
|
|
|
|
|
log += `调用来源IP:${task.caller_ip}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
return log;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//触发过滤筛选
|
|
|
|
|
|
const filterFunc = async () => {
|
|
|
|
|
|
await queryListData(state.currPage, state.pageSize, state.search, state.optionValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 按状态过滤
|
|
|
|
|
|
const filterByStatus = async (value: any) => {
|
2025-09-20 14:28:00 +08:00
|
|
|
|
selectedStatus.value = value;
|
|
|
|
|
|
state.currPage = 1; // 重置到第一页
|
|
|
|
|
|
await queryListData(state.currPage, state.pageSize, state.search, state.optionValue);
|
2025-08-10 14:32:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const queryListData = async (page: number, size: number, name = '', taskid = '', query = '', _status = '') => {
|
2025-09-20 14:28:00 +08:00
|
|
|
|
let params: any = { page: page, size: size, name: name, taskid: taskid };
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有状态筛选,添加到query参数中
|
2025-08-10 14:32:24 +08:00
|
|
|
|
if (selectedStatus.value !== '' && selectedStatus.value !== 'all') {
|
|
|
|
|
|
params.query = JSON.stringify({
|
2025-09-20 14:28:00 +08:00
|
|
|
|
status: selectedStatus.value
|
|
|
|
|
|
});
|
|
|
|
|
|
} else if (query) {
|
|
|
|
|
|
// 如果有其他query参数,使用传入的query
|
|
|
|
|
|
params.query = query;
|
2025-08-10 14:32:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const rsp = await request.get('/sendlogs/list', { params: params });
|
2025-09-20 14:28:00 +08:00
|
|
|
|
|
|
|
|
|
|
// 清空现有数据
|
|
|
|
|
|
state.tableData = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 使用 nextTick 确保响应式更新
|
|
|
|
|
|
await nextTick();
|
|
|
|
|
|
|
|
|
|
|
|
// 更新数据
|
|
|
|
|
|
state.tableData = rsp.data.data.lists || [];
|
|
|
|
|
|
state.total = rsp.data.data.total;
|
2025-08-10 14:32:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
// 页面加载触发日志显示
|
|
|
|
|
|
state.search = router.query.name?.toString() || '';
|
|
|
|
|
|
await queryListData(
|
|
|
|
|
|
1,
|
|
|
|
|
|
state.pageSize,
|
|
|
|
|
|
router.query.name?.toString() || '',
|
|
|
|
|
|
router.query.taskid?.toString() || '',
|
|
|
|
|
|
router.query.query?.toString() || ''
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="p-6 w-full max-w-6xl mx-auto space-y-2">
|
|
|
|
|
|
<div class="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
|
|
|
|
|
|
<div class="flex-1 sm:flex-initial">
|
|
|
|
|
|
<Input v-model="state.search" placeholder="搜索任务..." class="w-full sm:w-64" @keyup.enter="filterFunc"
|
|
|
|
|
|
@blur="filterFunc" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="flex-1 sm:flex-initial">
|
|
|
|
|
|
<Select v-model="selectedStatus" class="w-full" @update:model-value="filterByStatus">
|
|
|
|
|
|
<SelectTrigger>
|
|
|
|
|
|
<SelectValue placeholder="选择状态" />
|
|
|
|
|
|
</SelectTrigger>
|
|
|
|
|
|
<SelectContent>
|
|
|
|
|
|
<SelectGroup>
|
|
|
|
|
|
<SelectItem value="all">全部</SelectItem>
|
|
|
|
|
|
<SelectItem value="1">成功</SelectItem>
|
|
|
|
|
|
<SelectItem value="0">失败</SelectItem>
|
|
|
|
|
|
</SelectGroup>
|
|
|
|
|
|
</SelectContent>
|
|
|
|
|
|
</Select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 表格 -->
|
|
|
|
|
|
<Table>
|
|
|
|
|
|
<TableHeader>
|
|
|
|
|
|
<TableRow>
|
|
|
|
|
|
<TableHead class="w-20">ID</TableHead>
|
|
|
|
|
|
<TableHead>任务名称</TableHead>
|
|
|
|
|
|
<TableHead>发信日志</TableHead>
|
|
|
|
|
|
<TableHead>发送时间</TableHead>
|
|
|
|
|
|
<TableHead class="text-center">详情/状态</TableHead>
|
|
|
|
|
|
</TableRow>
|
|
|
|
|
|
</TableHeader>
|
|
|
|
|
|
|
|
|
|
|
|
<TableBody>
|
|
|
|
|
|
<!-- 空数据展示 -->
|
|
|
|
|
|
<TableRow v-if="state.tableData.length === 0">
|
|
|
|
|
|
<TableCell colspan="5" class="text-center py-12">
|
|
|
|
|
|
<EmptyTableState
|
|
|
|
|
|
title="暂无发信日志"
|
|
|
|
|
|
description="还没有任何发信日志记录"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #icon>
|
|
|
|
|
|
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</EmptyTableState>
|
|
|
|
|
|
</TableCell>
|
|
|
|
|
|
</TableRow>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 数据行 -->
|
|
|
|
|
|
<TableRow v-for="task in state.tableData" :key="task.id">
|
2025-08-10 18:54:29 +08:00
|
|
|
|
<TableCell>{{ task.id }}</TableCell>
|
2025-08-10 14:32:24 +08:00
|
|
|
|
<TableCell>{{ task.task_name }}</TableCell>
|
|
|
|
|
|
<TableCell class="max-w-xs truncate" :title="formatLogDisplayHtml(task)">{{ task.log }}</TableCell>
|
|
|
|
|
|
<TableCell>{{ task.created_on }}</TableCell>
|
|
|
|
|
|
<TableCell class="text-center space-x-2">
|
|
|
|
|
|
<Button size="sm" variant="outline" @click="openLogSheet(task)">查看</Button>
|
|
|
|
|
|
<!-- <Button size="sm" variant="destructive">删除</Button> -->
|
|
|
|
|
|
<Badge :class="task.status === 1 ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-600'">
|
|
|
|
|
|
{{ getStatusText(task.status) }}
|
|
|
|
|
|
</Badge>
|
|
|
|
|
|
</TableCell>
|
|
|
|
|
|
</TableRow>
|
|
|
|
|
|
</TableBody>
|
|
|
|
|
|
</Table>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 分页 -->
|
|
|
|
|
|
<Pagination
|
|
|
|
|
|
:total="state.total"
|
|
|
|
|
|
:current-page="state.currPage"
|
|
|
|
|
|
:page-size="state.pageSize"
|
|
|
|
|
|
@page-change="changePage"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 日志详情Sheet -->
|
2025-08-10 20:07:07 +08:00
|
|
|
|
<Sheet v-model:open="isSheetOpen" class="lg:w-[900px] ">
|
|
|
|
|
|
<SheetContent class="lg:w-[900px]">
|
2025-08-10 14:32:24 +08:00
|
|
|
|
<SheetHeader>
|
|
|
|
|
|
<SheetTitle>{{ selectedTaskName }} - 发信日志详情</SheetTitle>
|
|
|
|
|
|
</SheetHeader>
|
2025-08-10 18:07:38 +08:00
|
|
|
|
<div class="mt-4">
|
|
|
|
|
|
<div class="bg-gray-50 p-4 rounded-lg max-h-[82vh] overflow-y-auto break-words">
|
2025-08-10 14:32:24 +08:00
|
|
|
|
<pre class="whitespace-pre-wrap text-sm font-mono">{{ selectedLog }}</pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</SheetContent>
|
|
|
|
|
|
</Sheet>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|