feat: 资源池finished&抽屉描述列表新增骨架屏

This commit is contained in:
baiqi 2023-07-25 15:51:37 +08:00 committed by 刘瑞斌
parent 2dfd4588d9
commit b58e7eb9ec
7 changed files with 254 additions and 157 deletions

View File

@ -0,0 +1,10 @@
import MSR from '@/api/http/index';
import { OrganizationListItem } from '@/models/setting/orgnization';
import { GetAllOrgUrl } from '@/api/requrls/setting/orgnization';
// 获取全部组织列表
export function getAllOrgList() {
return MSR.post<OrganizationListItem[]>({ url: GetAllOrgUrl });
}
export function other() {}

View File

@ -0,0 +1,2 @@
export const GetAllOrgUrl = '/system/organization/list-all';
export const Other = '';

View File

@ -1,5 +1,13 @@
<template>
<a-descriptions :data="(props.descriptions as unknown as DescData[])" size="large" :column="1">
<a-skeleton v-if="props.showSkeleton" :loading="props.showSkeleton" :animation="true">
<a-space direction="vertical" class="w-[28%]" size="large">
<a-skeleton-line :rows="props.skeletonLine" :line-height="24" />
</a-space>
<a-space direction="vertical" class="ml-[4%] w-[68%]" size="large">
<a-skeleton-line :rows="props.skeletonLine" :line-height="24" />
</a-space>
</a-skeleton>
<a-descriptions v-else :data="(props.descriptions as unknown as DescData[])" size="large" :column="1">
<a-descriptions-item v-for="item of props.descriptions" :key="item.label" :label="item.label">
<template v-if="item.isTag">
<a-tag
@ -30,7 +38,11 @@
onClick?: () => void;
}
const props = defineProps<{ descriptions: Description[] }>();
const props = defineProps<{
showSkeleton?: boolean;
skeletonLine?: number;
descriptions: Description[];
}>();
function handleItemClick(item: Description) {
if (typeof item.onClick === 'function') {

View File

@ -19,7 +19,12 @@
</slot>
</template>
<slot>
<MsDescription v-if="props.descriptions?.length > 0" :descriptions="props.descriptions"></MsDescription>
<MsDescription
v-if="props.descriptions?.length > 0 || showDescription"
:descriptions="props.descriptions"
:show-skeleton="props.showSkeleton"
:skeleton-line="10"
></MsDescription>
</slot>
</a-drawer>
</template>
@ -39,12 +44,15 @@
descriptions?: Description[];
footer?: boolean;
mask?: boolean;
showDescription?: boolean;
showSkeleton?: boolean;
[key: string]: any;
}
const props = withDefaults(defineProps<DrawerProps>(), {
footer: true,
mask: true,
showSkeleton: false,
});
const emit = defineEmits(['update:visible']);

View File

@ -0,0 +1,36 @@
export interface OrgAdmin {
id: string;
name: string;
email: string;
password: string;
enable: boolean;
createTime: number;
updateTime: number;
language: string;
lastOrganizationId: string; // 当前组织ID
phone: string;
source: string; // 来源LOCAL OIDC CAS OAUTH2
lastProjectId: string;
createUser: string;
updateUser: string;
deleted: boolean;
}
export interface OrganizationListItem {
id: string;
num: number; // 组织编号
name: string;
description: string;
createTime: number;
updateTime: number;
createUser: string;
updateUser: string;
deleted: boolean;
deleteUser: string;
deleteTime: number;
enable: boolean;
memberCount: number;
projectCount: number;
orgAdmins: OrgAdmin[]; // 列表组织管理员集合
memberIds: string[]; // 组织管理员ID集合
}

View File

@ -60,7 +60,7 @@
multiple
allow-clear
>
<a-option v-for="org of orgOptons" :key="org.id" :value="org.value">{{ org.label }}</a-option>
<a-option v-for="org of orgOptons" :key="org.id" :value="org.id">{{ org.name }}</a-option>
</a-select>
</a-form-item>
<a-form-item
@ -337,7 +337,7 @@
</template>
<script setup lang="ts">
import { computed, Ref, ref, watchEffect } from 'vue';
import { computed, onBeforeMount, Ref, ref, watchEffect, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { Message, FormInstance, SelectOptionData } from '@arco-design/web-vue';
import { useI18n } from '@/hooks/useI18n';
@ -351,6 +351,7 @@
import { downloadStringFile, sleep } from '@/utils';
import { scrollIntoView } from '@/utils/dom';
import { addPool, getPoolInfo, updatePoolInfo } from '@/api/modules/setting/resourcePool';
import { getAllOrgList } from '@/api/modules/setting/orgnization';
import type { MsBatchFormInstance, FormItemModel } from '@/components/bussiness/ms-batch-form/types';
import type { UpdateResourcePoolParams, NodesListItem } from '@/models/setting/resourcePool';
@ -406,6 +407,10 @@
];
const defaultGrid = 'http://selenium-hub:4444';
onBeforeMount(async () => {
orgOptons.value = await getAllOrgList();
});
async function initPoolInfo() {
try {
loading.value = true;
@ -487,6 +492,16 @@
() => isFillNameSpaces.value && form.value.testResourceDTO.deployName?.trim() !== ''
);
watch(
() => isShowK8SResources.value,
(val) => {
if (val && !form.value.testResourceDTO.jobDefinition) {
// k8s jobDefinition null k8s
form.value.testResourceDTO.jobDefinition = job;
}
}
);
const batchFormRef = ref<MsBatchFormInstance | null>(null);
const batchFormModels: Ref<FormItemModel[]> = ref([
{

View File

@ -47,16 +47,18 @@
:descriptions="activePoolDesc"
:footer="false"
:mask="false"
:show-skeleton="drawerLoading"
show-description
>
<template #tbutton>
<a-button type="outline" size="mini" @click="editPool(activePool)">
<a-button type="outline" size="mini" :disabled="drawerLoading" @click="editPool(activePool)">
{{ t('system.resourcePool.editPool') }}
</a-button>
</template>
</MsDrawer>
<JobTemplateDrawer
v-model:visible="showJobDrawer"
:default-val="activePool?.testResourceDTO.jobDefinition || ''"
:default-val="activePool?.testResourceReturnDTO.jobDefinition || ''"
read-only
/>
</div>
@ -67,7 +69,7 @@
import { useRouter } from 'vue-router';
import { Message } from '@arco-design/web-vue';
import { useI18n } from '@/hooks/useI18n';
import { getPoolList, delPoolInfo, togglePoolStatus } from '@/api/modules/setting/resourcePool';
import { getPoolList, delPoolInfo, togglePoolStatus, getPoolInfo } from '@/api/modules/setting/resourcePool';
import useModal from '@/hooks/useModal';
import MsCard from '@/components/pure/ms-card/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.vue';
@ -82,7 +84,8 @@
import type { Description } from '@/components/pure/ms-description/index.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type';
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
import type { ResourcePoolItem } from '@/models/setting/resourcePool';
import type { ResourcePoolDetail } from '@/models/setting/resourcePool';
import { sleep } from '@/utils';
const { t } = useI18n();
const router = useRouter();
@ -269,161 +272,172 @@
const showDetailDrawer = ref(false);
const activePoolDesc: Ref<Description[]> = ref([]);
const activePool: Ref<ResourcePoolItem | null> = ref(null);
const activePool: Ref<ResourcePoolDetail | null> = ref(null);
const showJobDrawer = ref(false);
const drawerLoading = ref(false);
/**
* 查看资源池详情
* @param record
*/
function showPoolDetail(record: any) {
activePool.value = { ...record };
if (activePool.value) {
const poolUses = [
activePool.value.loadTest ? t('system.resourcePool.usePerformance') : '',
activePool.value.apiTest ? t('system.resourcePool.useAPI') : '',
activePool.value.uiTest ? t('system.resourcePool.useUI') : '',
];
const { type, testResourceDTO, loadTest, apiTest, uiTest } = activePool.value;
const {
ip,
token, // k8s token
nameSpaces, // k8s
concurrentNumber, // k8s
podThreads, // k8s pod线
apiTestImage, // k8s api
deployName, // k8s api
girdConcurrentNumber,
nodesList,
loadTestImage,
loadTestHeap,
uiGrid,
} = testResourceDTO;
// Node
const nodeResourceDesc =
type === 'Node'
? [
{
label: t('system.resourcePool.detailResources'),
value: nodesList?.map((e) => `${e.ip},${e.port},${e.monitor},${e.concurrentNumber}`),
isTag: true,
},
]
: [];
// K8S
const k8sResourceDesc =
type === 'Kubernetes'
? [
{
label: t('system.resourcePool.testResourceDTO.ip'),
value: ip,
},
{
label: t('system.resourcePool.testResourceDTO.token'),
value: token,
},
{
label: t('system.resourcePool.testResourceDTO.nameSpaces'),
value: nameSpaces,
},
{
label: t('system.resourcePool.testResourceDTO.deployName'),
value: deployName,
},
{
label: t('system.resourcePool.testResourceDTO.apiTestImage'),
value: apiTestImage,
},
{
label: t('system.resourcePool.testResourceDTO.concurrentNumber'),
value: concurrentNumber,
},
{
label: t('system.resourcePool.testResourceDTO.podThreads'),
value: podThreads,
},
]
: [];
const jobTemplate =
loadTest && type === 'Kubernetes'
? [
{
label: t('system.resourcePool.jobTemplate'),
value: t('system.resourcePool.customJobTemplate'),
isButton: true,
onClick: () => {
showJobDrawer.value = true;
},
},
]
: [];
//
const performanceDesc = loadTest
? [
{
label: t('system.resourcePool.mirror'),
value: loadTestImage,
},
{
label: t('system.resourcePool.testHeap'),
value: loadTestHeap,
},
]
: [];
// /
const resourceDesc = apiTest || loadTest ? [...nodeResourceDesc, ...k8sResourceDesc] : [];
// ui
const uiDesc = uiTest
? [
{
label: t('system.resourcePool.uiGrid'),
value: uiGrid,
},
{
label: t('system.resourcePool.concurrentNumber'),
value: girdConcurrentNumber,
},
]
: [];
const detailType =
apiTest || loadTest
? [
{
label: t('system.resourcePool.detailType'),
value: activePool.value.type,
},
]
: [];
activePoolDesc.value = [
{
label: t('system.resourcePool.detailDesc'),
value: activePool.value.description,
},
{
label: t('system.resourcePool.detailUrl'),
value: activePool.value.serverUrl,
},
{
label: t('system.resourcePool.detailRange'),
value: activePool.value.allOrg
? [t('system.resourcePool.orgAll')]
: activePool.value.testResourceDTO.orgIdNameMap.map((e) => e.name),
isTag: true,
},
{
label: t('system.resourcePool.detailUse'),
value: poolUses.filter((e) => e !== ''),
isTag: true,
},
...performanceDesc,
...uiDesc,
...detailType,
...resourceDesc,
...jobTemplate,
];
async function showPoolDetail(record: any) {
if (activePool.value?.id === record.id && showDetailDrawer.value) {
return;
}
drawerLoading.value = true;
showDetailDrawer.value = true;
try {
const res = await getPoolInfo(record.id);
if (res) {
activePool.value = res;
const poolUses = [
activePool.value.loadTest ? t('system.resourcePool.usePerformance') : '',
activePool.value.apiTest ? t('system.resourcePool.useAPI') : '',
activePool.value.uiTest ? t('system.resourcePool.useUI') : '',
];
const { type, testResourceReturnDTO, loadTest, apiTest, uiTest } = activePool.value;
const {
ip,
token, // k8s token
nameSpaces, // k8s
concurrentNumber, // k8s
podThreads, // k8s pod线
apiTestImage, // k8s api
deployName, // k8s api
girdConcurrentNumber,
nodesList,
loadTestImage,
loadTestHeap,
uiGrid,
} = testResourceReturnDTO;
// Node
const nodeResourceDesc =
type === 'Node'
? [
{
label: t('system.resourcePool.detailResources'),
value: nodesList?.map((e) => `${e.ip},${e.port},${e.monitor},${e.concurrentNumber}`),
isTag: true,
},
]
: [];
// K8S
const k8sResourceDesc =
type === 'Kubernetes'
? [
{
label: t('system.resourcePool.testResourceDTO.ip'),
value: ip,
},
{
label: t('system.resourcePool.testResourceDTO.token'),
value: token,
},
{
label: t('system.resourcePool.testResourceDTO.nameSpaces'),
value: nameSpaces,
},
{
label: t('system.resourcePool.testResourceDTO.deployName'),
value: deployName,
},
{
label: t('system.resourcePool.testResourceDTO.apiTestImage'),
value: apiTestImage,
},
{
label: t('system.resourcePool.testResourceDTO.concurrentNumber'),
value: concurrentNumber,
},
{
label: t('system.resourcePool.testResourceDTO.podThreads'),
value: podThreads,
},
]
: [];
const jobTemplate =
loadTest && type === 'Kubernetes'
? [
{
label: t('system.resourcePool.jobTemplate'),
value: t('system.resourcePool.customJobTemplate'),
isButton: true,
onClick: () => {
showJobDrawer.value = true;
},
},
]
: [];
//
const performanceDesc = loadTest
? [
{
label: t('system.resourcePool.mirror'),
value: loadTestImage,
},
{
label: t('system.resourcePool.testHeap'),
value: loadTestHeap,
},
]
: [];
// /
const resourceDesc = apiTest || loadTest ? [...nodeResourceDesc, ...k8sResourceDesc] : [];
// ui
const uiDesc = uiTest
? [
{
label: t('system.resourcePool.uiGrid'),
value: uiGrid,
},
{
label: t('system.resourcePool.concurrentNumber'),
value: girdConcurrentNumber,
},
]
: [];
const detailType =
apiTest || loadTest
? [
{
label: t('system.resourcePool.detailType'),
value: activePool.value.type,
},
]
: [];
activePoolDesc.value = [
{
label: t('system.resourcePool.detailDesc'),
value: activePool.value.description,
},
{
label: t('system.resourcePool.detailUrl'),
value: activePool.value.serverUrl,
},
{
label: t('system.resourcePool.detailRange'),
value: activePool.value.allOrg
? [t('system.resourcePool.orgAll')]
: activePool.value.testResourceReturnDTO.orgIdNameMap.map((e) => e.name),
isTag: true,
},
{
label: t('system.resourcePool.detailUse'),
value: poolUses.filter((e) => e !== ''),
isTag: true,
},
...performanceDesc,
...uiDesc,
...detailType,
...resourceDesc,
...jobTemplate,
];
}
} catch (error) {
console.log(error);
} finally {
drawerLoading.value = false;
}
}
/**