|
|
|
@ -5,59 +5,60 @@
|
|
|
|
<span>任务列表</span>
|
|
|
|
<span>任务列表</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="panel-body table-body">
|
|
|
|
<div class="panel-body table-body">
|
|
|
|
<table class="task-table">
|
|
|
|
<el-table
|
|
|
|
<thead>
|
|
|
|
ref="tableRef"
|
|
|
|
<tr>
|
|
|
|
:data="taskRows"
|
|
|
|
<th>编号</th>
|
|
|
|
class="task-table"
|
|
|
|
<th>名称</th>
|
|
|
|
:show-header="true"
|
|
|
|
<th>类型</th>
|
|
|
|
:stripe="false"
|
|
|
|
<th>完成状态</th>
|
|
|
|
:border="false"
|
|
|
|
<th>结果</th>
|
|
|
|
:highlight-current-row="false"
|
|
|
|
</tr>
|
|
|
|
>
|
|
|
|
</thead>
|
|
|
|
<el-table-column prop="code" label="编号" width="100" show-overflow-tooltip />
|
|
|
|
<tbody ref="tbodyRef">
|
|
|
|
<el-table-column prop="name" label="名称" />
|
|
|
|
<tr v-for="row in taskRows" :key="row.id">
|
|
|
|
<el-table-column prop="type" label="类型" />
|
|
|
|
<td>{{ row.code }}</td>
|
|
|
|
<el-table-column label="完成状态">
|
|
|
|
<td>{{ row.name }}</td>
|
|
|
|
<template #default="scope">
|
|
|
|
<td>{{ row.type }}</td>
|
|
|
|
<el-tag
|
|
|
|
<td>
|
|
|
|
v-if="scope.row.finishStatusLabel"
|
|
|
|
<el-tag
|
|
|
|
class="status-tag"
|
|
|
|
v-if="row.finishStatusLabel"
|
|
|
|
size="small"
|
|
|
|
class="status-tag"
|
|
|
|
:disable-transitions="true"
|
|
|
|
size="small"
|
|
|
|
:hit="false"
|
|
|
|
:disable-transitions="true"
|
|
|
|
:round="true"
|
|
|
|
:hit="false"
|
|
|
|
:type="scope.row.finishStatusType || 'info'"
|
|
|
|
:round="true"
|
|
|
|
>
|
|
|
|
:type="row.finishStatusType || 'info'"
|
|
|
|
{{ scope.row.finishStatusLabel }}
|
|
|
|
>
|
|
|
|
</el-tag>
|
|
|
|
{{ row.finishStatusLabel }}
|
|
|
|
</template>
|
|
|
|
</el-tag>
|
|
|
|
</el-table-column>
|
|
|
|
</td>
|
|
|
|
<el-table-column label="结果">
|
|
|
|
<td class="status-cell">
|
|
|
|
<template #default="scope">
|
|
|
|
<el-tag
|
|
|
|
<div class="status-cell">
|
|
|
|
v-if="row.resultStatusLabel !== '-'"
|
|
|
|
<el-tag
|
|
|
|
class="status-tag"
|
|
|
|
v-if="scope.row.resultStatusLabel !== '-'"
|
|
|
|
size="small"
|
|
|
|
class="status-tag"
|
|
|
|
:disable-transitions="true"
|
|
|
|
size="small"
|
|
|
|
:hit="false"
|
|
|
|
:disable-transitions="true"
|
|
|
|
:round="true"
|
|
|
|
:hit="false"
|
|
|
|
:type="row.resultStatusType || 'info'"
|
|
|
|
:round="true"
|
|
|
|
>
|
|
|
|
:type="scope.row.resultStatusType || 'info'"
|
|
|
|
{{ row.resultStatusLabel }}
|
|
|
|
>
|
|
|
|
</el-tag>
|
|
|
|
{{ scope.row.resultStatusLabel }}
|
|
|
|
<span v-else>-</span>
|
|
|
|
</el-tag>
|
|
|
|
</td>
|
|
|
|
<span v-else>-</span>
|
|
|
|
</tr>
|
|
|
|
</div>
|
|
|
|
</tbody>
|
|
|
|
</template>
|
|
|
|
</table>
|
|
|
|
</el-table-column>
|
|
|
|
|
|
|
|
</el-table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
|
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
|
|
|
|
|
|
import type { ElTable } from 'element-plus'
|
|
|
|
import { DashboardApi, DashboardTaskItem } from '@/api/dashboard'
|
|
|
|
import { DashboardApi, DashboardTaskItem } from '@/api/dashboard'
|
|
|
|
import { colors } from '../utils'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface TaskRow {
|
|
|
|
interface TaskRow {
|
|
|
|
id: string
|
|
|
|
id: string
|
|
|
|
@ -69,9 +70,8 @@ interface TaskRow {
|
|
|
|
finishStatusType: '' | 'success' | 'warning' | 'danger' | 'info'
|
|
|
|
finishStatusType: '' | 'success' | 'warning' | 'danger' | 'info'
|
|
|
|
resultStatusType: '' | 'success' | 'warning' | 'danger' | 'info'
|
|
|
|
resultStatusType: '' | 'success' | 'warning' | 'danger' | 'info'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const taskRows = ref<TaskRow[]>([])
|
|
|
|
const taskRows = ref<TaskRow[]>([])
|
|
|
|
const tbodyRef = ref<HTMLElement | null>(null)
|
|
|
|
const tableRef = ref<InstanceType<typeof ElTable> | null>(null)
|
|
|
|
let scrollTimer: number | undefined
|
|
|
|
let scrollTimer: number | undefined
|
|
|
|
|
|
|
|
|
|
|
|
const mapItemToRow = (item: DashboardTaskItem, index: number): TaskRow => {
|
|
|
|
const mapItemToRow = (item: DashboardTaskItem, index: number): TaskRow => {
|
|
|
|
@ -124,22 +124,29 @@ const loadTaskList = async () => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const startAutoScroll = () => {
|
|
|
|
const startAutoScroll = () => {
|
|
|
|
if (!tbodyRef.value) return
|
|
|
|
const el = tableRef.value?.$el as HTMLElement | undefined
|
|
|
|
const rows = tbodyRef.value.querySelectorAll('tr')
|
|
|
|
if (!el) return
|
|
|
|
|
|
|
|
const tbody = el.querySelector('tbody') as HTMLElement | null
|
|
|
|
|
|
|
|
if (!tbody) return
|
|
|
|
|
|
|
|
const rows = tbody.querySelectorAll('tr')
|
|
|
|
if (!rows || rows.length <= 8) return
|
|
|
|
if (!rows || rows.length <= 8) return
|
|
|
|
scrollTimer = window.setInterval(() => {
|
|
|
|
scrollTimer = window.setInterval(() => {
|
|
|
|
if (!tbodyRef.value) return
|
|
|
|
const currentBody = (tableRef.value?.$el as HTMLElement | undefined)?.querySelector('tbody') as
|
|
|
|
const first = tbodyRef.value.firstElementChild as HTMLElement | null
|
|
|
|
HTMLElement | null
|
|
|
|
|
|
|
|
if (!currentBody) return
|
|
|
|
|
|
|
|
const first = currentBody.firstElementChild as HTMLElement | null
|
|
|
|
if (!first) return
|
|
|
|
if (!first) return
|
|
|
|
first.style.transition = 'all 0.35s'
|
|
|
|
first.style.transition = 'all 0.35s'
|
|
|
|
first.style.transform = 'translateY(-36px)'
|
|
|
|
first.style.transform = 'translateY(-36px)'
|
|
|
|
first.style.opacity = '0'
|
|
|
|
first.style.opacity = '0'
|
|
|
|
window.setTimeout(() => {
|
|
|
|
window.setTimeout(() => {
|
|
|
|
if (!tbodyRef.value) return
|
|
|
|
const bodyAgain = (tableRef.value?.$el as HTMLElement | undefined)?.querySelector('tbody') as
|
|
|
|
|
|
|
|
HTMLElement | null
|
|
|
|
|
|
|
|
if (!bodyAgain || !first.parentElement) return
|
|
|
|
first.style.transition = 'none'
|
|
|
|
first.style.transition = 'none'
|
|
|
|
first.style.transform = 'translateY(0)'
|
|
|
|
first.style.transform = 'translateY(0)'
|
|
|
|
first.style.opacity = '1'
|
|
|
|
first.style.opacity = '1'
|
|
|
|
tbodyRef.value.appendChild(first)
|
|
|
|
bodyAgain.appendChild(first)
|
|
|
|
}, 360)
|
|
|
|
}, 360)
|
|
|
|
}, 5000)
|
|
|
|
}, 5000)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -231,34 +238,64 @@ onUnmounted(() => {
|
|
|
|
|
|
|
|
|
|
|
|
.task-table {
|
|
|
|
.task-table {
|
|
|
|
width: 100%;
|
|
|
|
width: 100%;
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
|
|
|
table-layout: fixed;
|
|
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
|
|
/* Element Plus Table Variables Override */
|
|
|
|
|
|
|
|
--el-table-bg-color: transparent;
|
|
|
|
|
|
|
|
--el-table-tr-bg-color: transparent;
|
|
|
|
|
|
|
|
--el-table-header-bg-color: transparent;
|
|
|
|
|
|
|
|
--el-table-text-color: #e5f0ff;
|
|
|
|
|
|
|
|
--el-table-header-text-color: #22d3ee;
|
|
|
|
|
|
|
|
--el-table-row-hover-bg-color: rgba(56, 189, 248, 0.12);
|
|
|
|
|
|
|
|
--el-table-border-color: rgba(30, 64, 175, 0.3);
|
|
|
|
|
|
|
|
background-color: transparent !important;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Ensure inner wrapper is transparent */
|
|
|
|
|
|
|
|
.task-table :deep(.el-table__inner-wrapper) {
|
|
|
|
|
|
|
|
background-color: transparent !important;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-table thead {
|
|
|
|
/* Remove bottom border line */
|
|
|
|
background: radial-gradient(circle at 0 0, rgba(56,189,248,0.18), transparent 70%);
|
|
|
|
.task-table :deep(.el-table__inner-wrapper::before) {
|
|
|
|
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-table th {
|
|
|
|
/* Header Styles */
|
|
|
|
padding: 10px 8px;
|
|
|
|
.task-table :deep(thead th.el-table__cell) {
|
|
|
|
color: var(--accent);
|
|
|
|
background: radial-gradient(circle at 0 0, rgba(56,189,248,0.18), transparent 90%) !important;
|
|
|
|
font-weight: 700;
|
|
|
|
font-weight: 700;
|
|
|
|
text-align: left;
|
|
|
|
border-bottom: 1px solid rgba(51,65,85,0.9) !important;
|
|
|
|
border-bottom: 1px solid rgba(51,65,85,0.9);
|
|
|
|
padding: 8px 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-table td {
|
|
|
|
/* Cell Styles */
|
|
|
|
padding: 10px 8px;
|
|
|
|
.task-table :deep(td.el-table__cell) {
|
|
|
|
border-bottom: 1px solid rgba(30,64,175,0.3);
|
|
|
|
background-color: transparent !important;
|
|
|
|
color: #e5f0ff;
|
|
|
|
border-bottom: 1px solid rgba(30,64,175,0.3) !important;
|
|
|
|
|
|
|
|
padding: 8px 0;
|
|
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Ensure code, name, type columns show ellipsis */
|
|
|
|
|
|
|
|
.task-table :deep(td.el-table__cell:nth-child(1) .cell),
|
|
|
|
|
|
|
|
.task-table :deep(td.el-table__cell:nth-child(2) .cell),
|
|
|
|
|
|
|
|
.task-table :deep(td.el-table__cell:nth-child(3) .cell) {
|
|
|
|
white-space: nowrap;
|
|
|
|
white-space: nowrap;
|
|
|
|
overflow: hidden;
|
|
|
|
overflow: hidden;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.task-table tbody tr:hover td {
|
|
|
|
/* Ensure finishStatus and result columns DO NOT show ellipsis */
|
|
|
|
background: rgba(56,189,248,0.08);
|
|
|
|
.task-table :deep(td.el-table__cell:nth-child(4) .cell),
|
|
|
|
|
|
|
|
.task-table :deep(td.el-table__cell:nth-child(5) .cell) {
|
|
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
|
|
overflow: visible;
|
|
|
|
|
|
|
|
text-overflow: clip;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Hover Styles */
|
|
|
|
|
|
|
|
.task-table :deep(tbody tr:hover > td.el-table__cell) {
|
|
|
|
|
|
|
|
background-color: rgba(56,189,248,0.1) !important;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.status-cell {
|
|
|
|
.status-cell {
|
|
|
|
|