feat(task): Add Global Task List (#7569)

This commit is contained in:
zhengkunwang 2024-12-26 14:13:28 +08:00 committed by GitHub
parent 008c369a9b
commit e56c0c7fba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 141 additions and 53 deletions

View file

@ -1,7 +1,7 @@
<template>
<div v-loading="initLog && isLoading">
<div v-if="defaultButton">
<el-checkbox border v-model="tailLog" class="float-left" @change="changeTail(false)">
<el-checkbox border v-model="tailLog" class="float-left" @change="changeTail(false)" v-if="showTail">
{{ $t('commons.button.watch') }}
</el-checkbox>
<el-button class="ml-2.5" @click="onDownload" icon="Download" :disabled="logs.length === 0">
@ -63,6 +63,10 @@ const props = defineProps({
type: Number,
default: 500,
},
showTail: {
type: Boolean,
default: true,
},
});
const stopSignals = [
'docker-compose up failed!',
@ -294,7 +298,6 @@ onMounted(async () => {
});
onUnmounted(() => {
console.log('onUnmounted');
onCloseLog();
});

View file

@ -62,6 +62,7 @@ const getType = (status: string) => {
case 'exceptional':
case 'disable':
case 'unhealthy':
case 'failed':
return 'danger';
case 'paused':
case 'exited':

View file

@ -0,0 +1,101 @@
<template>
<DrawerPro v-model="open" size="large" :header="$t('logs.task')" @close="handleClose">
<template #content>
<LayoutContent v-loading="loading" :title="$t('logs.task')">
<template #rightToolBar>
<el-select v-model="req.status" @change="search()" clearable class="p-w-200 mr-2.5">
<template #prefix>{{ $t('commons.table.status') }}</template>
<el-option :label="$t('commons.table.all')" value=""></el-option>
<el-option :label="$t('commons.status.success')" value="Success"></el-option>
<el-option :label="$t('commons.status.failed')" value="Failed"></el-option>
<el-option :label="$t('logs.taskRunning')" value="Executing"></el-option>
</el-select>
<TableRefresh @search="search()" />
<TableSetting title="task-log-refresh" @search="search()" />
</template>
<template #main>
<ComplexTable :pagination-config="paginationConfig" :data="data" @search="search" :heightDiff="370">
<el-table-column :label="$t('logs.taskName')" prop="name" />
<el-table-column :label="$t('commons.table.type')" prop="type" />
<el-table-column :label="$t('commons.table.status')" prop="status">
<template #default="{ row }">
<Status :status="row.status" :msg="row.errorMsg" />
</template>
</el-table-column>
<el-table-column :label="$t('website.log')" prop="log">
<template #default="{ row }">
<el-button @click="openTaskLog(row)" link type="primary">
{{ $t('website.check') }}
</el-button>
</template>
</el-table-column>
<el-table-column
prop="createdAt"
:label="$t('commons.table.date')"
:formatter="dateFormat"
show-overflow-tooltip
/>
</ComplexTable>
</template>
</LayoutContent>
<TaskLog ref="taskLogRef" width="70%" />
</template>
</DrawerPro>
</template>
<script setup lang="ts">
import { dateFormat } from '@/utils/util';
import { searchTasks } from '@/api/modules/log';
import { reactive, ref } from '@vue/runtime-core';
import { Log } from '@/api/interface/log';
import TaskLog from '@/components/task-log/index.vue';
const open = ref(false);
const handleClose = () => {
open.value = false;
};
const loading = ref();
const data = ref();
const paginationConfig = reactive({
cacheSizeKey: 'task-list-page-size',
currentPage: 1,
pageSize: 10,
total: 0,
});
const taskLogRef = ref();
const req = reactive({
type: '',
status: 'Executing',
page: 1,
pageSize: 10,
});
const search = async () => {
req.page = paginationConfig.currentPage;
req.pageSize = paginationConfig.pageSize;
loading.value = true;
try {
const res = await searchTasks(req);
loading.value = false;
data.value = res.data.items;
paginationConfig.total = res.data.total;
} catch (error) {
} finally {
loading.value = false;
}
};
const openTaskLog = (row: Log.Task) => {
taskLogRef.value.openWithTaskID(row.id, !(row.status == 'Executing'));
};
const acceptParams = () => {
search();
open.value = true;
};
defineExpose({
acceptParams,
});
</script>

View file

@ -9,7 +9,7 @@
:width="width"
>
<div>
<LogFile :config="config"></LogFile>
<LogFile :config="config" :showTail="showTail"></LogFile>
</div>
</el-dialog>
</template>
@ -37,12 +37,16 @@ const config = reactive({
taskOperate: '',
resourceID: 0,
taskType: '',
tail: true,
tail: false,
});
const open = ref(false);
const showTail = ref(true);
const openWithTaskID = (id: string) => {
const openWithTaskID = (id: string, tail: boolean) => {
config.taskID = id;
if (!tail) {
config.tail = false;
}
open.value = true;
};

View file

@ -36,7 +36,7 @@
</template>
</el-dropdown>
</div>
<el-tag type="danger" size="small" effect="light" class="mr-2">{{ taskCount }}</el-tag>
<el-tag type="danger" size="small" effect="light" class="mr-2" @click="openTask">{{ taskCount }}</el-tag>
</div>
<el-scrollbar>
<el-menu
@ -132,7 +132,7 @@ const listeningWindow = () => {
};
};
listeningWindow();
const emit = defineEmits(['menuClick']);
const emit = defineEmits(['menuClick', 'openTask']);
const handleMenuClick = (path) => {
emit('menuClick', path);
};
@ -252,6 +252,10 @@ const checkTask = async () => {
}
};
const openTask = () => {
emit('openTask');
};
onMounted(() => {
menuStore.setMenuList(menuList);
search();

View file

@ -2,7 +2,7 @@
<div :class="classObj" class="app-wrapper" v-loading="loading" :element-loading-text="loadingText" fullscreen>
<div v-if="classObj.mobile && classObj.openSidebar" class="drawer-bg" @click="handleClickOutside" />
<div class="app-sidebar" v-if="!globalStore.isFullScreen">
<Sidebar @menu-click="handleMenuClick" :menu-router="!classObj.openMenuTabs" />
<Sidebar @menu-click="handleMenuClick" :menu-router="!classObj.openMenuTabs" @open-task="openTask" />
</div>
<div class="main-container">
@ -10,6 +10,7 @@
<Tabs v-if="classObj.openMenuTabs" />
<app-main :keep-alive="classObj.openMenuTabs ? tabsStore.cachedTabs : null" class="app-main" />
<Footer class="app-footer" v-if="!globalStore.isFullScreen" />
<TaskList ref="taskListRef" />
</div>
</div>
</template>
@ -25,8 +26,14 @@ import { useRoute, useRouter } from 'vue-router';
import { loadMasterProductProFromDB, loadProductProFromDB } from '@/utils/xpack';
import { useTheme } from '@/global/use-theme';
const { switchTheme } = useTheme();
import TaskList from '@/components/task-list/index.vue';
useResize();
const taskListRef = ref();
const openTask = () => {
taskListRef.value.acceptParams();
};
const router = useRouter();
const route = useRoute();
const menuStore = MenuStore();

View file

@ -1,15 +1,7 @@
<template>
<div>
<div v-if="showButton">
<RouterButton :buttons="buttons">
<template #route-button>
<el-badge is-dot :hidden="!canUpdate" class="pr-5">
<el-button @click="sync" type="primary" plain :disabled="syncing">
{{ $t('app.syncAppList') }}
</el-button>
</el-badge>
</template>
</RouterButton>
<RouterButton :buttons="buttons"></RouterButton>
</div>
<LayoutContent>
<router-view></router-view>
@ -20,13 +12,9 @@
<script lang="ts" setup>
import i18n from '@/lang';
import { onMounted, ref } from 'vue';
import { SearchAppInstalled, SyncApp } from '@/api/modules/app';
import { SearchAppInstalled } from '@/api/modules/app';
import bus from './bus';
import { MsgSuccess } from '@/utils/message';
import { newUUID } from '@/utils/util';
let showButton = ref(false);
const syncing = ref(false);
const canUpdate = ref(false);
const buttons = [
{
@ -48,26 +36,6 @@ const buttons = [
},
];
const sync = () => {
syncing.value = true;
const taskID = newUUID();
const syncReq = {
taskID: taskID,
};
SyncApp(syncReq)
.then((res) => {
if (res.message != '') {
MsgSuccess(res.message);
} else {
MsgSuccess(i18n.global.t('app.syncStart'));
}
canUpdate.value = false;
})
.finally(() => {
syncing.value = false;
});
};
const search = () => {
SearchAppInstalled({ update: true, page: 1, pageSize: 100 })
.then((res) => {

View file

@ -56,7 +56,7 @@ import TaskLog from '@/components/task-log/index.vue';
const loading = ref();
const data = ref();
const paginationConfig = reactive({
cacheSizeKey: 'login-log-page-size',
cacheSizeKey: 'task-page-size',
currentPage: 1,
pageSize: 10,
total: 0,
@ -73,19 +73,19 @@ const search = async () => {
req.page = paginationConfig.currentPage;
req.pageSize = paginationConfig.pageSize;
loading.value = true;
await searchTasks(req)
.then((res) => {
loading.value = false;
data.value = res.data.items;
paginationConfig.total = res.data.total;
})
.catch(() => {
loading.value = false;
});
try {
const res = await searchTasks(req);
loading.value = false;
data.value = res.data.items;
paginationConfig.total = res.data.total;
} catch (error) {
} finally {
loading.value = false;
}
};
const openTaskLog = (row: Log.Task) => {
taskLogRef.value.openWithTaskID(row.id);
taskLogRef.value.openWithTaskID(row.id, !(row.status == 'Executing'));
};
onMounted(() => {