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> <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"> <a-descriptions-item v-for="item of props.descriptions" :key="item.label" :label="item.label">
<template v-if="item.isTag"> <template v-if="item.isTag">
<a-tag <a-tag
@ -30,7 +38,11 @@
onClick?: () => void; onClick?: () => void;
} }
const props = defineProps<{ descriptions: Description[] }>(); const props = defineProps<{
showSkeleton?: boolean;
skeletonLine?: number;
descriptions: Description[];
}>();
function handleItemClick(item: Description) { function handleItemClick(item: Description) {
if (typeof item.onClick === 'function') { if (typeof item.onClick === 'function') {

View File

@ -19,7 +19,12 @@
</slot> </slot>
</template> </template>
<slot> <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> </slot>
</a-drawer> </a-drawer>
</template> </template>
@ -39,12 +44,15 @@
descriptions?: Description[]; descriptions?: Description[];
footer?: boolean; footer?: boolean;
mask?: boolean; mask?: boolean;
showDescription?: boolean;
showSkeleton?: boolean;
[key: string]: any; [key: string]: any;
} }
const props = withDefaults(defineProps<DrawerProps>(), { const props = withDefaults(defineProps<DrawerProps>(), {
footer: true, footer: true,
mask: true, mask: true,
showSkeleton: false,
}); });
const emit = defineEmits(['update:visible']); 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 multiple
allow-clear 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-select>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
@ -337,7 +337,7 @@
</template> </template>
<script setup lang="ts"> <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 { useRoute, useRouter } from 'vue-router';
import { Message, FormInstance, SelectOptionData } from '@arco-design/web-vue'; import { Message, FormInstance, SelectOptionData } from '@arco-design/web-vue';
import { useI18n } from '@/hooks/useI18n'; import { useI18n } from '@/hooks/useI18n';
@ -351,6 +351,7 @@
import { downloadStringFile, sleep } from '@/utils'; import { downloadStringFile, sleep } from '@/utils';
import { scrollIntoView } from '@/utils/dom'; import { scrollIntoView } from '@/utils/dom';
import { addPool, getPoolInfo, updatePoolInfo } from '@/api/modules/setting/resourcePool'; 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 { MsBatchFormInstance, FormItemModel } from '@/components/bussiness/ms-batch-form/types';
import type { UpdateResourcePoolParams, NodesListItem } from '@/models/setting/resourcePool'; import type { UpdateResourcePoolParams, NodesListItem } from '@/models/setting/resourcePool';
@ -406,6 +407,10 @@
]; ];
const defaultGrid = 'http://selenium-hub:4444'; const defaultGrid = 'http://selenium-hub:4444';
onBeforeMount(async () => {
orgOptons.value = await getAllOrgList();
});
async function initPoolInfo() { async function initPoolInfo() {
try { try {
loading.value = true; loading.value = true;
@ -487,6 +492,16 @@
() => isFillNameSpaces.value && form.value.testResourceDTO.deployName?.trim() !== '' () => 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 batchFormRef = ref<MsBatchFormInstance | null>(null);
const batchFormModels: Ref<FormItemModel[]> = ref([ const batchFormModels: Ref<FormItemModel[]> = ref([
{ {

View File

@ -47,16 +47,18 @@
:descriptions="activePoolDesc" :descriptions="activePoolDesc"
:footer="false" :footer="false"
:mask="false" :mask="false"
:show-skeleton="drawerLoading"
show-description
> >
<template #tbutton> <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') }} {{ t('system.resourcePool.editPool') }}
</a-button> </a-button>
</template> </template>
</MsDrawer> </MsDrawer>
<JobTemplateDrawer <JobTemplateDrawer
v-model:visible="showJobDrawer" v-model:visible="showJobDrawer"
:default-val="activePool?.testResourceDTO.jobDefinition || ''" :default-val="activePool?.testResourceReturnDTO.jobDefinition || ''"
read-only read-only
/> />
</div> </div>
@ -67,7 +69,7 @@
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
import { useI18n } from '@/hooks/useI18n'; 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 useModal from '@/hooks/useModal';
import MsCard from '@/components/pure/ms-card/index.vue'; import MsCard from '@/components/pure/ms-card/index.vue';
import MsBaseTable from '@/components/pure/ms-table/base-table.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 { Description } from '@/components/pure/ms-description/index.vue';
import type { MsTableColumn } from '@/components/pure/ms-table/type'; import type { MsTableColumn } from '@/components/pure/ms-table/type';
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types'; 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 { t } = useI18n();
const router = useRouter(); const router = useRouter();
@ -269,21 +272,29 @@
const showDetailDrawer = ref(false); const showDetailDrawer = ref(false);
const activePoolDesc: Ref<Description[]> = ref([]); const activePoolDesc: Ref<Description[]> = ref([]);
const activePool: Ref<ResourcePoolItem | null> = ref(null); const activePool: Ref<ResourcePoolDetail | null> = ref(null);
const showJobDrawer = ref(false); const showJobDrawer = ref(false);
const drawerLoading = ref(false);
/** /**
* 查看资源池详情 * 查看资源池详情
* @param record * @param record
*/ */
function showPoolDetail(record: any) { async function showPoolDetail(record: any) {
activePool.value = { ...record }; if (activePool.value?.id === record.id && showDetailDrawer.value) {
if (activePool.value) { return;
}
drawerLoading.value = true;
showDetailDrawer.value = true;
try {
const res = await getPoolInfo(record.id);
if (res) {
activePool.value = res;
const poolUses = [ const poolUses = [
activePool.value.loadTest ? t('system.resourcePool.usePerformance') : '', activePool.value.loadTest ? t('system.resourcePool.usePerformance') : '',
activePool.value.apiTest ? t('system.resourcePool.useAPI') : '', activePool.value.apiTest ? t('system.resourcePool.useAPI') : '',
activePool.value.uiTest ? t('system.resourcePool.useUI') : '', activePool.value.uiTest ? t('system.resourcePool.useUI') : '',
]; ];
const { type, testResourceDTO, loadTest, apiTest, uiTest } = activePool.value; const { type, testResourceReturnDTO, loadTest, apiTest, uiTest } = activePool.value;
const { const {
ip, ip,
token, // k8s token token, // k8s token
@ -297,7 +308,7 @@
loadTestImage, loadTestImage,
loadTestHeap, loadTestHeap,
uiGrid, uiGrid,
} = testResourceDTO; } = testResourceReturnDTO;
// Node // Node
const nodeResourceDesc = const nodeResourceDesc =
type === 'Node' type === 'Node'
@ -407,7 +418,7 @@
label: t('system.resourcePool.detailRange'), label: t('system.resourcePool.detailRange'),
value: activePool.value.allOrg value: activePool.value.allOrg
? [t('system.resourcePool.orgAll')] ? [t('system.resourcePool.orgAll')]
: activePool.value.testResourceDTO.orgIdNameMap.map((e) => e.name), : activePool.value.testResourceReturnDTO.orgIdNameMap.map((e) => e.name),
isTag: true, isTag: true,
}, },
{ {
@ -422,8 +433,11 @@
...jobTemplate, ...jobTemplate,
]; ];
} }
} catch (error) {
showDetailDrawer.value = true; console.log(error);
} finally {
drawerLoading.value = false;
}
} }
/** /**