Files
Nexus/frontend/src/components/push/PushHistoryTable.vue
T
Nexus Agent 540712500f fix: 移除 iframe 浏览器并优化推送页服务器展示
删除内置浏览器前后端;推送页支持卡片/列表切换、点击名称复制与长名称展示。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 01:43:51 +08:00

165 lines
4.9 KiB
Vue

<template>
<v-card elevation="0" border rounded="lg">
<v-card-title class="d-flex flex-wrap align-center ga-2">
<span>推送历史</span>
<v-spacer />
<v-select
:model-value="statusFilter"
:items="statusOptions"
item-title="label"
item-value="value"
label="状态"
variant="outlined"
density="compact"
hide-details
clearable
style="max-width: 120px"
@update:model-value="$emit('update:statusFilter', $event); $emit('filter-change')"
/>
<v-select
:model-value="syncModeFilter"
:items="syncModeOptions"
item-title="label"
item-value="value"
label="模式"
variant="outlined"
density="compact"
hide-details
clearable
style="max-width: 120px"
@update:model-value="$emit('update:syncModeFilter', $event); $emit('filter-change')"
/>
<v-select
:model-value="serverFilter"
:items="serverOptions"
item-title="title"
item-value="value"
label="服务器"
variant="outlined"
density="compact"
hide-details
clearable
style="max-width: 180px"
@update:model-value="$emit('update:serverFilter', $event); $emit('filter-change')"
/>
<v-btn
size="small"
variant="tonal"
prepend-icon="mdi-wrench"
:loading="reconciling"
@click="$emit('reconcile')"
>
修复卡住记录
</v-btn>
</v-card-title>
<v-data-table-server
:items="items"
:headers="headers"
:items-length="total"
:loading="loading"
:page="page"
:items-per-page="15"
hover
density="comfortable"
@update:page="$emit('update:page', $event); $emit('page-change')"
>
<template #item.server_name="{ item }">
<span
class="text-body-2 push-history-server-name"
:title="item.server_name ?? ''"
>{{ item.server_name }}</span>
</template>
<template #item.status="{ item }">
<v-chip :color="logStatusColor(item.status)" size="x-small" variant="tonal" label border="sm">
{{ logStatusLabel(item.status) }}
</v-chip>
</template>
<template #item.sync_mode="{ item }">
<span class="text-caption">{{ syncModeLabel(item.sync_mode) }}</span>
</template>
<template #item.started_at="{ item }">
<span class="text-caption text-medium-emphasis">{{ formatLogTime(item.started_at) }}</span>
</template>
<template #item.push_permission="{ item }">
<span
class="text-caption"
:class="item.push_permission ? '' : 'text-medium-emphasis'"
:title="item.push_permission || '本次推送未配置 rsync 属主/权限修正'"
>{{ formatPushPermission(item.push_permission) }}</span>
</template>
<template #item.error_message="{ item }">
<span
v-if="item.error_message"
class="text-caption text-error text-truncate d-inline-block"
style="max-width: 200px"
:title="formatPushErrorMessage(item.error_message)"
>{{ formatPushErrorMessage(item.error_message) }}</span>
<span v-else class="text-caption text-medium-emphasis"></span>
</template>
<template #item.actions="{ item }">
<v-btn
v-if="item.status === 'failed'"
size="x-small"
variant="tonal"
prepend-icon="mdi-stethoscope"
@click="$emit('diagnose', item)"
>
诊断
</v-btn>
</template>
<template #no-data>
<div class="text-center text-medium-emphasis py-6">暂无数据</div>
</template>
</v-data-table-server>
</v-card>
</template>
<script setup lang="ts">
import {
formatLogTime,
formatPushErrorMessage,
formatPushPermission,
logStatusColor,
logStatusLabel,
syncModeLabel,
} from '@/composables/push/labels'
import type { PushItem } from '@/types/api'
defineProps<{
items: PushItem[]
headers: { title: string; key: string; width?: number; sortable?: boolean }[]
total: number
loading: boolean
page: number
statusFilter: string | null
syncModeFilter: string | null
serverFilter: number | null
statusOptions: { label: string; value: string }[]
syncModeOptions: { label: string; value: string }[]
serverOptions: { title: string; value: number }[]
reconciling: boolean
}>()
defineEmits<{
'update:page': [page: number]
'update:statusFilter': [value: string | null]
'update:syncModeFilter': [value: string | null]
'update:serverFilter': [value: number | null]
'filter-change': []
'page-change': []
reconcile: []
diagnose: [item: PushItem]
}>()
</script>
<style scoped>
.push-history-server-name {
display: inline-block;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: bottom;
}
</style>