You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.8 KiB

<template>
<list-header v-if="!hideTitle" description="任务管理用于监控物理显卡的状态。它用于监控物理显卡的分配使用情况,以及查看物理显卡上运行的所有任务。" />
<Top v-if="!hideTitle" />
<table-plus :api="taskApi.getTaskList({ filters })" :columns="columns" :rowAction="rowAction"
:searchSchema="searchSchema" ref="table" :style="{ height: 'auto', ...style }" hideTag staticPage>
</table-plus>
<form-plus-drawer v-model="state.visible" v-model:form="state.formValues" :schema="state.schema" :title="state.title"
@ok="state.ok" />
</template>
<script setup lang="jsx">
import taskApi from '~/vgpu/api/task';
import { calculateDuration, roundToDecimal, timeParse, bytesToGB } from '@/utils';
import { QuestionFilled } from '@element-plus/icons-vue';
import api from '~/vgpu/api/task';
import { ElMessage, ElMessageBox, ElPopover } from 'element-plus';
import { reactive, ref, defineProps } from 'vue';
import editSchema from './editSchema';
import { mapValues, isNumber, pick } from 'lodash';
import { useRouter } from 'vue-router';
import searchSchema from './searchSchema';
import Top from './top.vue';
import useParentAction from '~/vgpu/hooks/useParentAction';
const { sendRouteChange, hasParentWindow } = useParentAction();
const props = defineProps(['hideTitle', 'filters', 'style']);
const table = ref();
const router = useRouter();
const state = reactive({
visible: false,
schema: {},
formValues: {},
title: '',
ok: () => { },
});
const columns = [
{
title: '任务名称',
dataIndex: 'name',
render: ({ name, podUid }) => (
<text-plus text={name} to={`/admin/vgpu/task/admin/detail?name=${name}&podUid=${podUid}`} />
),
},
{
title: '类型',
dataIndex: 'nataskTypeme',
render: ({ taskType }) => taskType === 'big_model' ? '大模型' : '实训',
},
{
title: '任务状态',
dataIndex: 'status',
render: ({ status, deviceIds }) => {
if (!status) return '/';
const enums = {
closed: { text: '已完成', color: '#999' },
success: { text: '运行中', color: '#2563eb' },
unknown: { text: '未知', color: '#FACC15' },
failed: { text: '错误', color: '#EF4444' },
};
const { text, color } = enums[status];
return (
<div
style={{
color,
position: 'relative',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '5px',
}}
>
<div
style={{
height: '7px',
width: '7px',
borderRadius: '50%',
backgroundColor: color,
display: 'inline-block',
}}
></div>{' '}
{text}
{(status === 'unknown' || status === 'failed') && (
<ElPopover trigger="hover" popper-style={{ width: '180px' }}>
{{
reference: () => <el-icon color="#939EA9" size="14"><QuestionFilled /></el-icon>,
default: () => (
<span style={{ marginLeft: '5px', }}>
请跳转云平台查看详情
</span>
),
}}
</ElPopover>
)}
</div>
);
},
},
{
title: '实训名称',
dataIndex: 'shixunName',
render: ({ shixunName }) => shixunName || '/',
},
{
title: '使用者角色',
width: 100,
dataIndex: 'role',
render: ({ role }) => role || '/',
},
{
title: '用户名',
dataIndex: 'username',
render: ({ username }) => username || '/',
},
// {
// title: '所属资源池',
// width: 100,
// dataIndex: 'resourcePools',
// render: ({ resourcePools }) => `${resourcePools?.length ? resourcePools.join('、') : '/'}`,
// },
{
title: '所属节点',
dataIndex: 'nodeName',
render: ({ nodeName }) => nodeName || '/',
},
{
title: 'CPU',
dataIndex: 'requestedCpuCores',
render: ({ requestedCpuCores }) => `${requestedCpuCores}核`,
},
{
title: '内存',
dataIndex: 'requestedMemory',
render: ({ requestedMemory }) => `${bytesToGB(requestedMemory)}GiB`,
},
{
title: '分配 vGPU',
width: 100,
dataIndex: 'deviceIds',
render: ({ deviceIds }) => {
return (
<ElPopover trigger="hover" popper-style={{ width: '350px' }}>
{{
reference: () => <el-tag disable-transitions>{deviceIds.length} 个</el-tag>,
default: () => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: '10px',
width: '100%',
justifyContent: 'center',
}}
>
{deviceIds.map((item) => (
<ElTag type="info">{item}</ElTag>
))}
</div>
),
}}
</ElPopover>
);
},
},
{
title: '分配算力',
dataIndex: 'allocatedCores',
render: ({ allocatedCores }) => `${allocatedCores} `,
},
{
title: '分配显存',
dataIndex: 'allocatedMem',
render: ({ allocatedMem }) =>
`${roundToDecimal(allocatedMem / 1024, 1)} GiB`,
},
{
title: '任务创建时间',
width: 140,
dataIndex: 'createTime',
render: ({ createTime }) => timeParse(createTime),
},
];
const rowAction = [
{
title: '查看详情',
onClick: (row) => {
sendRouteChange(`/admin/vgpu/task/admin/detail?name=${row.name}&podUid=${row.podUid}`);
},
},
{
title: '查看实训',
hidden: (row) => !hasParentWindow || row.taskType === 'big_model',
onClick: (row) => {
sendRouteChange(`/admins/running_pods?pod_name=${row.podName}`, 'open');
},
},
];
</script>
<style lang="scss"></style>