feat(系统设置): 资源池容量详情&详情列表联调
This commit is contained in:
parent
620b834789
commit
9f3aecc67a
|
@ -4,6 +4,8 @@ import {
|
|||
DeletePoolUrl,
|
||||
DetailPoolUrl,
|
||||
EnablePoolUrl,
|
||||
PoolCapacityDetailUrl,
|
||||
PoolCapacityTaskUrl,
|
||||
PoolListUrl,
|
||||
UpdatePoolUrl,
|
||||
} from '@/api/requrls/setting/resourcePool';
|
||||
|
@ -11,6 +13,8 @@ import {
|
|||
import type { CommonList, TableQueryParams } from '@/models/common';
|
||||
import type {
|
||||
AddResourcePoolParams,
|
||||
CapacityDetailType,
|
||||
CapacityTaskItem,
|
||||
ResourcePoolDetail,
|
||||
ResourcePoolItem,
|
||||
UpdateResourcePoolParams,
|
||||
|
@ -47,3 +51,13 @@ export function delPoolInfo(poolId: string) {
|
|||
export function togglePoolStatus(poolId: string) {
|
||||
return MSR.post({ url: EnablePoolUrl, params: poolId });
|
||||
}
|
||||
|
||||
// 获取资源池容量列表
|
||||
export function getCapacityTaskList(data: TableQueryParams) {
|
||||
return MSR.post<CommonList<CapacityTaskItem>>({ url: PoolCapacityTaskUrl, data });
|
||||
}
|
||||
|
||||
// 获取资源池容量详情
|
||||
export function getCapacityDetail(data: TableQueryParams) {
|
||||
return MSR.post<CapacityDetailType>({ url: PoolCapacityDetailUrl, data });
|
||||
}
|
||||
|
|
|
@ -4,3 +4,5 @@ export const AddPoolUrl = '/test/resource/pool/add';
|
|||
export const DeletePoolUrl = '/test/resource/pool/delete';
|
||||
export const DetailPoolUrl = '/test/resource/pool/detail';
|
||||
export const EnablePoolUrl = '/test/resource/pool/set/enable/';
|
||||
export const PoolCapacityTaskUrl = '/test/resource/pool/capacity/task/list'; // 资源池容量列表
|
||||
export const PoolCapacityDetailUrl = '/test/resource/pool/capacity/detail'; // 资源池容量详情
|
||||
|
|
|
@ -63,3 +63,35 @@ export type UpdateResourcePoolParams = Omit<ResourcePoolInfo, 'testResourceDTO'>
|
|||
id: string;
|
||||
testResourceDTO?: Partial<TestResourceDTO>;
|
||||
};
|
||||
// 资源池容量列表项
|
||||
export interface CapacityTaskItem {
|
||||
id: string;
|
||||
taskId: string;
|
||||
resourceId: string;
|
||||
resourceName: string;
|
||||
taskOrigin: string; // 任务来源(任务组下的任务id
|
||||
status: string; // 执行状态
|
||||
result: string; // 执行结果
|
||||
resourcePoolId: string;
|
||||
resourcePoolNode: string;
|
||||
resourceType: string; // 资源类型
|
||||
projectId: string;
|
||||
organizationId: string;
|
||||
threadId: string; // 线程id
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
executor: string; // 执行人
|
||||
num: number;
|
||||
taskName: string;
|
||||
userName: string;
|
||||
resourcePoolName: string;
|
||||
triggerMode: string;
|
||||
lineNum: number;
|
||||
}
|
||||
|
||||
export interface CapacityDetailType {
|
||||
concurrentNumber: number; // 最大并发数
|
||||
occupiedConcurrentNumber: number; // 剩余并发数
|
||||
memoryUsage: number; // 内存使用量
|
||||
cpuusage: number; // CPU占用量
|
||||
}
|
||||
|
|
|
@ -11,15 +11,14 @@
|
|||
<div class="flex items-center gap-[16px]">
|
||||
<div class="count-resources">
|
||||
{{ t('system.resourcePool.concurrentNumber') }}
|
||||
<span class="capacity-count">100</span>
|
||||
<span class="capacity-count">{{ capacityDetail.concurrentNumber }}</span>
|
||||
</div>
|
||||
<div class="count-resources">
|
||||
{{ t('system.resourcePool.remainingConcurrency') }}
|
||||
<span class="capacity-count">100</span>
|
||||
<span class="capacity-count">{{ capacityDetail.occupiedConcurrentNumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- TODO 等待联调 -->
|
||||
<div class="flex items-center justify-between p-[16px]">
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<a-select
|
||||
|
@ -27,18 +26,23 @@
|
|||
class="mr-[16px] w-[200px]"
|
||||
:placeholder="t('common.pleaseSelect')"
|
||||
allow-clear
|
||||
@change="(val)=>changeNode(val as string)"
|
||||
>
|
||||
<template #prefix>
|
||||
<div class="text-[var(--color-text-brand)]">{{ t('system.resourcePool.capacityNode') }}</div>
|
||||
</template>
|
||||
<template #tree-slot-title="node">
|
||||
<a-tooltip :content="`${node.name}`" position="tl">
|
||||
<div class="one-line-text w-[180px]">{{ node.name }}</div>
|
||||
<a-tooltip v-for="item of nodeList" :key="item.ip" :mouse-enter-delay="500" :content="item.ip">
|
||||
<a-option :value="item.ip">
|
||||
{{ item.ip }}
|
||||
</a-option>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-select>
|
||||
<CapacityProgress :name="t('system.resourcePool.memory')" :percent="0.3" color="rgb(var(--link-6))" />
|
||||
<CapacityProgress name="CPU" :percent="0.3" color="rgb(var(--success-6))" />
|
||||
<CapacityProgress
|
||||
:name="t('system.resourcePool.memory')"
|
||||
:percent="capacityDetail.memoryUsage"
|
||||
color="rgb(var(--link-6))"
|
||||
/>
|
||||
<CapacityProgress name="CPU" :percent="capacityDetail.cpuusage" color="rgb(var(--success-6))" />
|
||||
</div>
|
||||
<MsTag no-margin size="large" :tooltip-disabled="true" class="cursor-pointer" theme="outline" @click="searchList">
|
||||
<MsIcon class="text-[16px] text-[var(color-text-4)]" :size="32" type="icon-icon_reset_outlined" />
|
||||
|
@ -49,15 +53,15 @@
|
|||
<template #[FilterSlotNameEnum.TEST_PLAN_REPORT_EXEC_STATUS]="{ filterContent }">
|
||||
<ExecStatus :status="filterContent.value" />
|
||||
</template>
|
||||
<template #execStatus="{ record }">
|
||||
<ExecStatus :status="record.execStatus" />
|
||||
<template #result="{ record }">
|
||||
<ExecutionStatus v-if="record.result !== '-'" :status="record.result" :module-type="ReportEnum.API_REPORT" />
|
||||
</template>
|
||||
|
||||
<template #[FilterSlotNameEnum.API_TEST_CASE_API_REPORT_STATUS]="{ filterContent }">
|
||||
<ExecutionStatus :module-type="ReportEnum.API_REPORT" :status="filterContent.value" />
|
||||
</template>
|
||||
<template #status="{ record }">
|
||||
<ExecutionStatus :module-type="ReportEnum.API_REPORT" :status="record.status" />
|
||||
<ExecStatus :status="record.status" />
|
||||
</template>
|
||||
</ms-base-table>
|
||||
</div>
|
||||
|
@ -76,10 +80,11 @@
|
|||
import ExecutionStatus from '@/views/api-test/report/component/reportStatus.vue';
|
||||
import ExecStatus from '@/views/test-plan/report/component/execStatus.vue';
|
||||
|
||||
import { getCapacityDetail, getCapacityTaskList } from '@/api/modules/setting/resourcePool';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { useTableStore } from '@/store';
|
||||
|
||||
import type { ResourcePoolItem } from '@/models/setting/resourcePool';
|
||||
import type { CapacityDetailType, NodesListItem, ResourcePoolItem } from '@/models/setting/resourcePool';
|
||||
import { ReportExecStatus } from '@/enums/apiEnum';
|
||||
import { ReportEnum, ReportStatus } from '@/enums/reportEnum';
|
||||
import { TableKeyEnum } from '@/enums/tableEnum';
|
||||
|
@ -106,33 +111,35 @@
|
|||
});
|
||||
|
||||
const statusList = computed(() => {
|
||||
return Object.keys(ReportStatus).map((key) => {
|
||||
return Object.keys(ReportStatus)
|
||||
.map((key) => {
|
||||
return {
|
||||
value: key,
|
||||
label: t(ReportStatus[key].label),
|
||||
};
|
||||
});
|
||||
})
|
||||
.filter((e) => e.value !== 'FAKE_ERROR');
|
||||
});
|
||||
|
||||
const columns: MsTableColumn = [
|
||||
{
|
||||
title: 'system.resourcePool.taskID',
|
||||
slotName: 'ID',
|
||||
dataIndex: 'id',
|
||||
dataIndex: 'num',
|
||||
showTooltip: true,
|
||||
width: 200,
|
||||
width: 120,
|
||||
columnSelectorDisabled: true,
|
||||
},
|
||||
{
|
||||
title: 'system.resourcePool.taskName',
|
||||
slotName: 'taskName',
|
||||
dataIndex: 'enable',
|
||||
dataIndex: 'taskName',
|
||||
showDrag: true,
|
||||
},
|
||||
{
|
||||
title: 'system.resourcePool.useCaseName',
|
||||
slotName: 'useCaseName',
|
||||
dataIndex: 'useCaseName',
|
||||
slotName: 'resourceName',
|
||||
dataIndex: 'resourceName',
|
||||
showTooltip: true,
|
||||
width: 150,
|
||||
showDrag: true,
|
||||
|
@ -151,9 +158,9 @@
|
|||
},
|
||||
{
|
||||
title: 'common.executionResult',
|
||||
slotName: 'execStatus',
|
||||
dataIndex: 'execStatus',
|
||||
|
||||
slotName: 'result',
|
||||
dataIndex: 'result',
|
||||
width: 200,
|
||||
filterConfig: {
|
||||
options: statusList.value,
|
||||
filterSlotName: FilterSlotNameEnum.API_TEST_CASE_API_REPORT_STATUS,
|
||||
|
@ -171,9 +178,9 @@
|
|||
},
|
||||
];
|
||||
|
||||
const { propsRes, propsEvent, loadList, setKeyword } = useTable(undefined, {
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getCapacityTaskList, {
|
||||
tableKey: TableKeyEnum.SYSTEM_RESOURCE_POOL_CAPACITY,
|
||||
scroll: { y: 'auto' },
|
||||
scroll: { x: '100%' },
|
||||
selectable: false,
|
||||
showSetting: true,
|
||||
heightUsed: 310,
|
||||
|
@ -181,11 +188,71 @@
|
|||
});
|
||||
|
||||
const selectedNode = ref<string>('');
|
||||
const nodeList = computed<NodesListItem[]>(() => props.activeRecord?.testResourceDTO.nodesList ?? []);
|
||||
const nodePort = computed(() => nodeList.value.find((e) => e.ip === selectedNode.value)?.port ?? '');
|
||||
|
||||
async function searchList() {
|
||||
setLoadListParams({
|
||||
poolId: props.activeRecord?.id,
|
||||
ip: selectedNode.value,
|
||||
port: nodePort.value,
|
||||
});
|
||||
loadList();
|
||||
}
|
||||
|
||||
const defaultCapacityDetail: CapacityDetailType = {
|
||||
concurrentNumber: 0,
|
||||
occupiedConcurrentNumber: 0,
|
||||
memoryUsage: 0,
|
||||
cpuusage: 0,
|
||||
};
|
||||
|
||||
const capacityDetail = ref<CapacityDetailType>({
|
||||
...defaultCapacityDetail,
|
||||
});
|
||||
|
||||
function resetCapacityDetail() {
|
||||
capacityDetail.value = {
|
||||
...defaultCapacityDetail,
|
||||
};
|
||||
}
|
||||
|
||||
async function initCapacityDetail() {
|
||||
try {
|
||||
capacityDetail.value = await getCapacityDetail({
|
||||
poolId: props.activeRecord?.id,
|
||||
ip: selectedNode.value,
|
||||
port: nodePort.value,
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
function changeNode(value: string) {
|
||||
searchList();
|
||||
if (value) {
|
||||
initCapacityDetail();
|
||||
} else {
|
||||
resetCapacityDetail();
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => innerVisible.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
searchList();
|
||||
} else {
|
||||
selectedNode.value = '';
|
||||
resetCapacityDetail();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
await tableStore.initColumn(TableKeyEnum.SYSTEM_RESOURCE_POOL_CAPACITY, columns, 'drawer');
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<template>
|
||||
<!-- TODO 等待联调 -->
|
||||
<div class="progress-capacity">
|
||||
<div class="capacity-attr">
|
||||
<span>{{ props.name }}</span>
|
||||
<span class="capacity-value"> {{ props.percent * 100 }} %</span>
|
||||
<span class="capacity-value"> {{ Number.isNaN(props.percent) ? 0 : Number(props.percent.toFixed(1)) }} %</span>
|
||||
</div>
|
||||
<a-progress :percent="props.percent" :show-text="false" :color="props.color" />
|
||||
<a-progress :percent="percentValue" :show-text="false" :color="props.color" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -15,6 +14,10 @@
|
|||
percent: number;
|
||||
color: string;
|
||||
}>();
|
||||
|
||||
const percentValue = computed(() => {
|
||||
return Number(props.percent / 100);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
|
|
@ -431,7 +431,6 @@
|
|||
girdConcurrentNumber: 1,
|
||||
podThreads: 1,
|
||||
concurrentNumber: 10,
|
||||
// TODO 单个任务并发数等待联调
|
||||
singleTaskConcurrentNumber: 3,
|
||||
nodesList: [
|
||||
{
|
||||
|
|
|
@ -20,25 +20,30 @@
|
|||
</div>
|
||||
<ms-base-table v-bind="propsRes" no-disable v-on="propsEvent">
|
||||
<template #name="{ record }">
|
||||
<div class="flex w-full items-center justify-start gap-[8px]">
|
||||
<a-tooltip :content="t('system.resourcePool.viewCapacityInfo')" :mouse-enter-delay="300" position="bottom">
|
||||
<div class="flex items-center gap-[8px]">
|
||||
<a-tooltip
|
||||
v-if="record.type !== 'Kubernetes'"
|
||||
:content="t('system.resourcePool.viewCapacityInfo')"
|
||||
:mouse-enter-delay="300"
|
||||
position="bottom"
|
||||
>
|
||||
<div class="w-[16px]">
|
||||
<MsIcon
|
||||
type="icon-icon_pie_filled"
|
||||
class="cursor-pointer text-[rgb(var(--primary-5))]"
|
||||
size="16"
|
||||
@click="capacityDetail(record)"
|
||||
/>
|
||||
</div>
|
||||
</a-tooltip>
|
||||
<a-button
|
||||
type="text"
|
||||
class="px-0"
|
||||
:class="record.id === '100001100001' ? '' : 'max-w-full justify-start'"
|
||||
<div
|
||||
:class="`one-line-text cursor-pointer text-[rgb(var(--primary-5))] ${
|
||||
record.id === '100001100001' ? 'max-w-[calc(100%-60px)]' : 'max-w-[calc(100%-16px)]'
|
||||
}`"
|
||||
@click="showPoolDetail(record.id)"
|
||||
>
|
||||
<div class="one-line-text">
|
||||
{{ record.name }}
|
||||
</div>
|
||||
</a-button>
|
||||
<MsTag v-if="record.id === '100001100001'" size="small" tooltip-disabled>{{ t('common.default') }}</MsTag>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -62,9 +67,6 @@
|
|||
</a-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template #lastConcurrentNumber="{ record }">
|
||||
{{ record.lastConcurrentNumber || 0 }}
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<MsButton v-permission="['SYSTEM_TEST_RESOURCE_POOL:READ+UPDATE']" @click="editPool(record)">
|
||||
{{ t('system.resourcePool.editPool') }}
|
||||
|
@ -126,7 +128,7 @@
|
|||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import { MsAdvanceFilter } from '@/components/pure/ms-advance-filter';
|
||||
import { FilterFormItem, FilterResult } from '@/components/pure/ms-advance-filter/type';
|
||||
import { FilterFormItem } from '@/components/pure/ms-advance-filter/type';
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsCard from '@/components/pure/ms-card/index.vue';
|
||||
import type { Description } from '@/components/pure/ms-description/index.vue';
|
||||
|
@ -226,13 +228,22 @@
|
|||
columns.pop();
|
||||
}
|
||||
await tableStore.initColumn(TableKeyEnum.SYSTEM_RESOURCEPOOL, columns, 'drawer');
|
||||
const { propsRes, propsEvent, loadList, setKeyword } = useTable(getPoolList, {
|
||||
const { propsRes, propsEvent, loadList, setKeyword } = useTable(
|
||||
getPoolList,
|
||||
{
|
||||
tableKey: TableKeyEnum.SYSTEM_RESOURCEPOOL,
|
||||
columns,
|
||||
scroll: { y: 'auto' },
|
||||
selectable: false,
|
||||
showSelectAll: false,
|
||||
});
|
||||
},
|
||||
(item) => {
|
||||
return {
|
||||
...item,
|
||||
lastConcurrentNumber: item.type === 'Kubernetes' ? '-' : item.lastConcurrentNumber || 0,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const keyword = ref('');
|
||||
const filterConfigList = ref<FilterFormItem[]>([]);
|
||||
|
|
Loading…
Reference in New Issue