fix: 移除任务列表骨架屏
This commit is contained in:
@@ -451,9 +451,14 @@ const refreshQueueItems = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 使用nextTick确保数据更新不会导致渲染问题
|
||||
await nextTick()
|
||||
currentQueueItems.value = [...queueItems]
|
||||
// 只在数据真正发生变化时才更新,避免不必要的界面闪烁
|
||||
const oldItemsString = JSON.stringify(currentQueueItems.value)
|
||||
const newItemsString = JSON.stringify(queueItems)
|
||||
|
||||
if (oldItemsString !== newItemsString) {
|
||||
currentQueueItems.value = [...queueItems]
|
||||
}
|
||||
|
||||
console.log('刷新后的队列项数据:', queueItems) // 调试日志
|
||||
} catch (error) {
|
||||
console.error('刷新队列项列表失败:', error)
|
||||
@@ -626,6 +631,19 @@ const saveQueueData = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 监听队列项变化,但避免频繁刷新导致的界面闪烁
|
||||
watch(
|
||||
() => currentQueueItems.value,
|
||||
(newItems, oldItems) => {
|
||||
// 深度比较避免不必要的更新
|
||||
if (JSON.stringify(newItems) !== JSON.stringify(oldItems)) {
|
||||
// 只有当数据真正改变时才触发更新
|
||||
console.log('队列项数据变化,触发更新')
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 自动保存功能
|
||||
watch(
|
||||
() => [
|
||||
|
||||
@@ -109,15 +109,15 @@ const clearLogs = () => {
|
||||
|
||||
.log-content {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
background: var(--ant-color-bg-layout);
|
||||
padding: 16px;
|
||||
background: var(--ant-color-bg-container);
|
||||
border: 1px solid var(--ant-color-border);
|
||||
border-radius: 6px;
|
||||
overflow-y: auto;
|
||||
max-height: 400px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.empty-state-mini {
|
||||
@@ -125,7 +125,7 @@ const clearLogs = () => {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 200px;
|
||||
min-height: 200px;
|
||||
color: var(--ant-color-text-tertiary);
|
||||
}
|
||||
|
||||
@@ -145,8 +145,8 @@ const clearLogs = () => {
|
||||
|
||||
.log-line {
|
||||
margin-bottom: 2px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
@@ -198,8 +198,9 @@ const clearLogs = () => {
|
||||
}
|
||||
|
||||
.log-content {
|
||||
background: var(--ant-color-bg-layout, #141414);
|
||||
background: var(--ant-color-bg-container, #1f1f1f);
|
||||
border: 1px solid var(--ant-color-border, #424242);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.empty-state-mini {
|
||||
@@ -250,3 +251,11 @@ const clearLogs = () => {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
@media (max-width: 768px) {
|
||||
.log-content {
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -74,6 +74,11 @@ const getStatusColor = (status: string) => getQueueStatusColor(status)
|
||||
.queue-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
background: var(--ant-color-bg-layout);
|
||||
border: 1px solid var(--ant-color-border);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.empty-state-mini {
|
||||
@@ -81,13 +86,13 @@ const getStatusColor = (status: string) => getQueueStatusColor(status)
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 200px;
|
||||
min-height: 200px;
|
||||
color: var(--ant-color-text-tertiary);
|
||||
}
|
||||
|
||||
.empty-image-mini {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
opacity: 0.5;
|
||||
margin-bottom: 8px;
|
||||
filter: var(--ant-color-scheme-dark, brightness(0.8));
|
||||
@@ -109,11 +114,13 @@ const getStatusColor = (status: string) => getQueueStatusColor(status)
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
background-color: var(--ant-color-bg-container);
|
||||
border-color: var(--ant-color-border);
|
||||
border: 1px solid var(--ant-color-border);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.queue-card:hover {
|
||||
box-shadow: 0 2px 8px var(--ant-color-shadow);
|
||||
border-color: var(--ant-color-primary);
|
||||
}
|
||||
|
||||
.running-card {
|
||||
@@ -144,6 +151,12 @@ const getStatusColor = (status: string) => getQueueStatusColor(status)
|
||||
color: var(--ant-color-text-heading, #ffffff);
|
||||
}
|
||||
|
||||
.queue-content {
|
||||
background: var(--ant-color-bg-layout, #141414);
|
||||
border: 1px solid var(--ant-color-border, #424242);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.empty-state-mini {
|
||||
color: var(--ant-color-text-tertiary, #8c8c8c);
|
||||
}
|
||||
@@ -159,19 +172,17 @@ const getStatusColor = (status: string) => getQueueStatusColor(status)
|
||||
.queue-card {
|
||||
background-color: var(--ant-color-bg-container, #1f1f1f);
|
||||
border-color: var(--ant-color-border, #424242);
|
||||
}
|
||||
|
||||
.queue-card:hover {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.running-card {
|
||||
border-color: var(--ant-color-primary, #1890ff);
|
||||
box-shadow: 0 0 0 1px rgba(24, 144, 255, 0.2);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.item-name {
|
||||
color: var(--ant-color-text, #ffffff);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.queue-content {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -131,33 +131,70 @@ const filterTaskOption = (input: string, option: any) => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px;
|
||||
background: var(--ant-color-bg-layout);
|
||||
padding: 20px;
|
||||
background: var(--ant-color-bg-container);
|
||||
border: 1px solid var(--ant-color-border);
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 暗色模式适配 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.control-row {
|
||||
background: var(--ant-color-bg-layout, #141414);
|
||||
border: 1px solid var(--ant-color-border, #424242);
|
||||
}
|
||||
.control-row:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.control-label {
|
||||
font-weight: 500;
|
||||
color: var(--ant-color-text);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.control-select {
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.control-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.control-button {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
/* 暗色模式适配 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.control-row {
|
||||
background: var(--ant-color-bg-container, #1f1f1f);
|
||||
border: 1px solid var(--ant-color-border, #424242);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.control-row:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.control-label {
|
||||
color: var(--ant-color-text, #ffffff);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.control-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.control-select {
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.control-spacer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.control-button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -225,22 +225,21 @@ onUnmounted(() => {
|
||||
<style scoped>
|
||||
/* 页面容器 */
|
||||
.scheduler-page {
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background-color: var(--ant-color-bg-container);
|
||||
color: var(--ant-color-text);
|
||||
background: var(--ant-color-bg-layout);
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
/* 页面头部样式 */
|
||||
.scheduler-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 4px 24px;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--ant-color-bg-layout);
|
||||
align-items: flex-end;
|
||||
margin-bottom: 24px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.header-left {
|
||||
@@ -248,7 +247,7 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.page-title {
|
||||
margin: 0;
|
||||
margin: 0 0 8px 0;
|
||||
font-size: 32px;
|
||||
font-weight: 700;
|
||||
color: var(--ant-color-text);
|
||||
@@ -277,6 +276,9 @@ onUnmounted(() => {
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background-color: var(--ant-color-bg-container);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.scheduler-tabs :deep(.ant-tabs) {
|
||||
@@ -301,10 +303,12 @@ onUnmounted(() => {
|
||||
.scheduler-tabs :deep(.ant-tabs-tab) {
|
||||
background-color: var(--ant-color-bg-layout);
|
||||
border-color: var(--ant-color-border);
|
||||
border-radius: 6px 6px 0 0;
|
||||
}
|
||||
|
||||
.scheduler-tabs :deep(.ant-tabs-tab-active) {
|
||||
background-color: var(--ant-color-bg-container);
|
||||
border-bottom: 1px solid var(--ant-color-bg-container);
|
||||
}
|
||||
|
||||
.tab-title {
|
||||
@@ -333,6 +337,7 @@ onUnmounted(() => {
|
||||
.status-row {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.status-row :deep(.ant-col) {
|
||||
@@ -366,12 +371,8 @@ onUnmounted(() => {
|
||||
/* 暗色模式适配 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.scheduler-page {
|
||||
background-color: var(--ant-color-bg-container, #1f1f1f);
|
||||
color: var(--ant-color-text, #ffffff);
|
||||
}
|
||||
|
||||
.scheduler-header {
|
||||
background-color: var(--ant-color-bg-layout, #141414);
|
||||
color: var(--ant-color-text, #ffffff);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
@@ -384,6 +385,7 @@ onUnmounted(() => {
|
||||
|
||||
.scheduler-tabs {
|
||||
background-color: var(--ant-color-bg-container, #1f1f1f);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.scheduler-tabs :deep(.ant-tabs) {
|
||||
@@ -407,6 +409,7 @@ onUnmounted(() => {
|
||||
.scheduler-tabs :deep(.ant-tabs-tab-active) {
|
||||
background-color: var(--ant-color-bg-container, #1f1f1f);
|
||||
color: var(--ant-color-text, #ffffff);
|
||||
border-bottom: 1px solid var(--ant-color-bg-container, #1f1f1f);
|
||||
}
|
||||
|
||||
.tab-title {
|
||||
@@ -446,16 +449,25 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.scheduler-page {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.scheduler-header {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.scheduler-tabs {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.status-row {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ export const TAB_STATUS_COLOR: Record<SchedulerStatus, string> = {
|
||||
|
||||
// 队列状态 -> 颜色
|
||||
export const getQueueStatusColor = (status: string): string => {
|
||||
if (/成功|完成|已完成/.test(status)) return 'green'
|
||||
if (/失败|错误|异常/.test(status)) return 'red'
|
||||
if (/等待|排队|挂起/.test(status)) return 'orange'
|
||||
if (/进行|执行|运行/.test(status)) return 'blue'
|
||||
if (/成功|完成|已完成/.test(status)) return 'success'
|
||||
if (/失败|错误|异常/.test(status)) return 'error'
|
||||
if (/等待|排队|挂起/.test(status)) return 'warning'
|
||||
if (/进行|执行|运行/.test(status)) return 'processing'
|
||||
return 'default'
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ export const POWER_ACTION_TEXT: Record<PowerIn.signal, string> = {
|
||||
[PowerIn.signal.SHUTDOWN_FORCE]: '强制关机',
|
||||
}
|
||||
|
||||
export const getPowerActionText = (action: PowerIn.signal) => POWER_ACTION_TEXT[action] || '无动<EFBFBD><EFBFBD>'
|
||||
export const getPowerActionText = (action: PowerIn.signal) => POWER_ACTION_TEXT[action] || '无动作'
|
||||
|
||||
// 日志相关
|
||||
export const LOG_MAX_LENGTH = 2000 // 最多保留日志条数
|
||||
@@ -77,4 +77,4 @@ export interface TaskMessage {
|
||||
needInput: boolean
|
||||
messageId?: string
|
||||
taskId?: string
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user