加入图形

main
陈博文 5 days ago
parent 46ce7503a9
commit 67719c5547

@ -3,17 +3,35 @@ import { useRouter } from 'vue-router';
export default function useParentAction() {
const router = useRouter();
const sendRouteChange = (url) => {
const sendRouteChange = (url, type) => {
if (window.parent !== window) {
// 在 iframe 中,通知父窗口
const message = {
let message = {
type: 'ChangeThePath',
data: url
data: url,
};
if (type === 'open') {
message = {
type: 'OpenThePath',
data: url,
};
}
if (type === 'back') {
message = {
type: 'BackThePath',
data: url,
};
}
window.parent.postMessage(JSON.stringify(message), '*');
} else {
// 不在 iframe 中,直接使用 router 跳转
router.push(url);
if (type === 'open') {
window.open(url);
} else if (type === 'back') {
router.go(-1);
} else {
router.push(url);
}
}
};
const hasParentWindow = window.parent !== window;

@ -33,6 +33,9 @@ import searchSchema from '~/vgpu/views/card/admin/searchSchema';
import PreviewBar from '~/vgpu/components/previewBar.vue';
import { defineProps, ref, watch } from 'vue';
import { roundToDecimal } from '@/utils';
import useParentAction from '~/vgpu/hooks/useParentAction';
const { sendRouteChange } = useParentAction();
const props = defineProps(['hideTitle', 'filters']);
@ -41,9 +44,7 @@ const router = useRouter();
const tableRef = ref({});
const handleClick = (params) => {
router.push({
path: `/admin/vgpu/card/admin/${params.data.name}`,
});
sendRouteChange(`/admin/vgpu/card/admin/${params.data.name}`);
};
const columns = [
@ -76,6 +77,11 @@ const columns = [
title: '所属节点',
dataIndex: 'nodeName',
},
{
title: '所属资源池',
dataIndex: 'resourcePools',
render: ({ resourcePools }) => `${resourcePools.join('、')}`,
},
{
title: '显卡型号',
dataIndex: 'type',
@ -114,9 +120,7 @@ const rowAction = [
{
title: '查看详情',
onClick: (row) => {
router.push({
path: `/admin/vgpu/card/admin/${row.uuid}`,
});
sendRouteChange(`/admin/vgpu/card/admin/${row.uuid}`);
},
},
];

@ -106,7 +106,7 @@ export const rangeConfigInit = [
},
{
name: 'CPU',
query: `sum(hami_container_cpu_allocated) / sum(hami_cpu_count) * 100`,
query: `sum(hami_container_vcore_allocated) / sum(hami_core_size) * 100`,
data: [],
type: 'line',
areaStyle: {
@ -140,7 +140,7 @@ export const rangeConfigInit = [
},
{
name: '内存',
query: `sum(hami_container_memory_allocated) / sum(hami_memory_capacity) * 100`,
query: `sum(hami_container_vmemory_allocated) / sum(hami_memory_size) * 100`,
data: [],
type: 'line',
areaStyle: {
@ -245,7 +245,7 @@ export const rangeConfigInit = [
},
{
name: 'CPU',
query: `sum(hami_container_cpu_allocated) / sum(hami_cpu_count) * 100`,
query: `100 * (1 - sum(irate(node_cpu_seconds_total{mode="idle"}[1m])) / count(node_cpu_seconds_total{mode="idle"}))`,
data: [],
type: 'line',
areaStyle: {
@ -279,7 +279,7 @@ export const rangeConfigInit = [
},
{
name: '内存',
query: `sum(hami_container_memory_allocated) / sum(hami_memory_capacity) * 100`,
query: `(1 - sum(node_memory_MemAvailable_bytes) / sum(node_memory_MemTotal_bytes)) * 100`,
data: [],
type: 'line',
areaStyle: {

@ -416,18 +416,18 @@ const nodeTotalTop = {
key: 'used',
config: [
{
tab: 'GPU',
key: 'gpu',
nameKey: 'node',
tab: 'CPU',
key: 'cpu',
nameKey: 'instance',
data: [],
query: `topk(5, avg(hami_container_vgpu_allocated{}) by (node) / avg(hami_vgpu_count{}) by (node) * 100)`,
query: `topk(5, sum(hami_container_vcore_allocated) by (instance) / sum(hami_core_size) by (instance) * 100)`,
},
{
tab: '内存',
key: 'internal',
nameKey: 'node',
nameKey: 'instance',
data: [],
query: `topk(5, avg(hami_container_vgpu_allocated{}) by (node) / avg(hami_vgpu_count{}) by (node) * 100)`,
query: `topk(5, sum(hami_container_vmemory_allocated) by (instance) / sum(hami_memory_size) by (instance) * 100)`,
},
{
tab: 'vGPU',

@ -250,7 +250,7 @@ const gaugeConfig = useInstantVector(
percent: 0,
query: ``,
totalQuery: ``,
percentQuery: `avg(sum(hami_container_memory_allocated{node=~"$node"}) by (instance) / sum(hami_memory_size{node=~"$node"}) by (instance) * 100)`,
percentQuery: `avg(sum(hami_container_vmemory_allocated{node=~"$node"}) by (instance) / sum(hami_memory_size{node=~"$node"}) by (instance) * 100)`,
total: 0,
used: 0,
unit: 'GiB',

@ -393,7 +393,7 @@ const gaugeConfig = useInstantVector(
percent: 0,
query: ``,
totalQuery: ``,
percentQuery: `avg(sum(hami_container_memory_allocated{node=~"$node"}) by (instance) / sum(hami_memory_size{node=~"$node"}) by (instance) * 100)`,
percentQuery: `avg(sum(hami_container_vmemory_allocated{node=~"$node"}) by (instance) / sum(hami_memory_size{node=~"$node"}) by (instance) * 100)`,
total: 0,
used: 0,
unit: 'GiB',

@ -26,7 +26,7 @@
<el-button type="text">配置</el-button>
</template>
<template v-else>
<el-button @click="dialogVisible = true; editId = poolId; nodeSelect = nodeList; input = poolName"
<el-button @click="dialogVisible = true; editId = poolId; nodeSelect = nodeList.map(e=>e.nodeIp); input = poolName"
type="text">编辑</el-button>
<el-button @click="() => handleDelete(poolId)" type="text">删除</el-button>
</template>

@ -1,44 +1,31 @@
<template>
<list-header
v-if="!hideTitle"
description="任务管理用于监控物理显卡的状态。它用于监控物理显卡的分配使用情况,以及查看物理显卡上运行的所有任务。"
/>
<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="style"
hideTag
staticPage
>
<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"
/>
<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} from '@/utils';
import { calculateDuration, roundToDecimal, timeParse } from '@/utils';
import { QuestionFilled } from '@element-plus/icons-vue';
import api from '~/vgpu/api/task';
import {ElMessage, ElMessageBox, ElPopover} from 'element-plus';
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']);
@ -51,17 +38,22 @@ const state = reactive({
schema: {},
formValues: {},
title: '',
ok: () => {},
ok: () => { },
});
const columns = [
{
title: '任务名称',
dataIndex: 'name',
render: ({ name,podUid }) => (
<text-plus text={name} to={`/admin/vgpu/task/admin/detail?name=${name}&podUid=${podUid}`} />
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',
@ -95,21 +87,39 @@ const columns = [
></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>
<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',
},
{
title: '使用者角色',
dataIndex: 'nataskTypeme',
render: ({ taskType }) => taskType === 'big_model' ? '大模型' : '实训',
},
{
title: '用户名',
dataIndex: 'role',
},
{
title: '所属资源池',
dataIndex: 'resourcePools',
render: ({ resourcePools }) => `${resourcePools.join('、')}`,
},
{
title: '所属节点',
dataIndex: 'nodeName',
@ -166,10 +176,14 @@ const rowAction = [
{
title: '查看详情',
onClick: (row) => {
router.push({
path: '/admin/vgpu/task/admin/detail',
query: pick(row, ['name', 'podUid']),
});
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');
},
},
];

@ -11,11 +11,14 @@
<script setup lang="jsx">
import { useRouter } from 'vue-router';
import useParentAction from '~/vgpu/hooks/useParentAction';
const router = useRouter();
const { sendRouteChange } = useParentAction();
const goBack = () => {
router.go(-1);
sendRouteChange('', 'back')
};
</script>

@ -11,6 +11,7 @@ import '@tabler/core/dist/css/tabler.min.css';
import { AppMain, Sidebar, TopBar } from './components';
import { useRouter } from 'vue-router'
import useParentAction from '~/vgpu/hooks/useParentAction';
import { parseUrl } from '@/utils';
export default {
@ -48,9 +49,13 @@ export default {
try {
const messageData = JSON.parse(event.data);
if (messageData.type === "ChangeTheRoute") {
this.router.push({
path: messageData.data,
});
// const { pathname, query } = parseUrl(messageData.data)
// console.log(messageData.data, 'messageData.data')
// this.router.push({
// path: pathname,
// query
// });
this.router.replace(messageData.data)
}
} catch (e) { }
},

@ -571,3 +571,17 @@ export const clearEdges = (items) =>
export const bytesToGB = (bytes) => {
return Math.round(bytes / (1024 * 1024 * 1024));
}
export function parseUrl(url) {
const [pathname, queryString] = url.split('?');
const query = {};
if (queryString) {
queryString.split('&').forEach(pair => {
const [key, value] = pair.split('=');
query[decodeURIComponent(key)] = decodeURIComponent(value || '');
});
}
return { pathname, query };
}

Loading…
Cancel
Save