feat(系统设置): 穿梭框组件&资源池配置调整

This commit is contained in:
baiqi 2023-08-24 18:56:08 +08:00 committed by 刘瑞斌
parent e2b713d0f1
commit 14d401342b
3 changed files with 148 additions and 70 deletions

View File

@ -0,0 +1,137 @@
<template>
<a-transfer
v-model="innerTarget"
:title="props.title || [t('system.user.batchOptional'), t('system.user.batchChosen')]"
:data="transferData"
show-search
>
<template #source="{ data: tData, selectedKeys, onSelect }">
<a-tree
:checkable="true"
checked-strategy="child"
:checked-keys="selectedKeys"
:data="getTreeData(tData)"
block-node
@check="onSelect"
/>
</template>
</a-transfer>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useI18n } from '@/hooks/useI18n';
export interface TreeDataItem {
key?: string;
title?: string;
children?: TreeDataItem[];
disabled?: boolean;
[key: string]: any;
}
export interface TransferDataItem {
value: string;
label: string;
disabled: boolean;
[key: string]: any;
}
const props = withDefaults(
defineProps<{
modelValue: string[];
title?: string[]; // [left, right]
data: TreeDataItem[]; //
treeFiled?: Record<keyof TreeDataItem, string>; //
}>(),
{
treeFiled: () => ({
key: 'key',
title: 'title',
children: 'children',
disabled: 'disabled',
}),
}
);
const emit = defineEmits(['update:modelValue']);
const { t } = useI18n();
const innerTarget = ref<string[]>([]);
const transferData = ref<TransferDataItem[]>([]);
watch(
() => props.modelValue,
(val) => {
innerTarget.value = val;
}
);
watch(
() => innerTarget.value,
(val) => {
emit('update:modelValue', val);
}
);
/**
* 获取穿梭框数据根据树结构获取
* @param _treeData 树结构
* @param transferDataSource 穿梭框数组
*/
const getTransferData = (_treeData: TreeDataItem[], transferDataSource: TransferDataItem[]) => {
_treeData.forEach((item) => {
const itemChildren = item[props.treeFiled.children];
if (Array.isArray(itemChildren) && itemChildren.length > 0) getTransferData(itemChildren, transferDataSource);
else
transferDataSource.push({
label: item[props.treeFiled.title],
value: item[props.treeFiled.key],
disabled: item[props.treeFiled.disabled],
});
});
return transferDataSource;
};
/**
* 获取树结构数据根据穿梭框过滤的数据获取
*/
const getTreeData = (data: TransferDataItem[]) => {
const values = data.map((item) => item[props.treeFiled.key]);
const travel = (_treeData: TreeDataItem[]) => {
const treeDataSource: TreeDataItem[] = [];
_treeData.forEach((item) => {
const itemChildren = item[props.treeFiled.children];
const itemKey = item[props.treeFiled.key];
const itemTitle = item[props.treeFiled.title];
// push 穿
const allSelected =
innerTarget.value.length > 0 &&
Array.isArray(itemChildren) &&
itemChildren.length > 0 &&
itemChildren?.every((child: TreeDataItem) => innerTarget.value.includes(child[props.treeFiled.key]));
if (!allSelected && !innerTarget.value.includes(itemKey) && (itemChildren || values.includes(itemKey))) {
//
treeDataSource.push({
title: itemTitle,
key: itemKey,
children: itemChildren ? travel(itemChildren) : [],
});
}
});
return treeDataSource;
};
return travel(props.data);
};
watch(
() => props.data,
(arr) => {
transferData.value = getTransferData(arr, []);
}
);
</script>
<style lang="less" scoped></style>

View File

@ -632,7 +632,7 @@
let yamlStr = ''; let yamlStr = '';
const { nameSpaces, deployName } = form.value.testResourceDTO; const { nameSpaces, deployName } = form.value.testResourceDTO;
// -xxx // -xxx
const apiImage = `registry.cn-qingdao.aliyuncs.com/metersphere/node-controller:${appStore.version.substring( const apiImage = `registry.cn-qingdao.aliyuncs.com/metersphere/task-runner:${appStore.version.substring(
0, 0,
appStore.version.lastIndexOf('-') appStore.version.lastIndexOf('-')
)}`; )}`;

View File

@ -10,23 +10,16 @@
<a-alert v-if="batchModalMode === 'project'" class="mb-[16px]"> <a-alert v-if="batchModalMode === 'project'" class="mb-[16px]">
{{ t('system.user.batchModalTip') }} {{ t('system.user.batchModalTip') }}
</a-alert> </a-alert>
<a-transfer <MsTransfer
v-model="target" v-model="target"
:title="[t('system.user.batchOptional'), t('system.user.batchChosen')]" :data="treeData"
:data="transferData" :tree-filed="{
show-search key: 'id',
> title: 'name',
<template #source="{ data, selectedKeys, onSelect }"> children: 'children',
<a-tree disabled: 'disabled',
:checkable="true" }"
checked-strategy="child" />
:checked-keys="selectedKeys"
:data="getTreeData(data)"
block-node
@check="onSelect"
/>
</template>
</a-transfer>
</a-spin> </a-spin>
<template #footer> <template #footer>
<a-button type="secondary" :disabled="batchLoading" @click="cancelBatch">{{ <a-button type="secondary" :disabled="batchLoading" @click="cancelBatch">{{
@ -51,23 +44,12 @@
getSystemProjects, getSystemProjects,
getSystemRoles, getSystemRoles,
} from '@/api/modules/setting/user'; } from '@/api/modules/setting/user';
import MsTransfer from '@/components/pure/ms-transfer/index.vue';
import type { OrgsItem } from '@/models/setting/user'; import type { OrgsItem } from '@/models/setting/user';
const { t } = useI18n(); const { t } = useI18n();
interface TreeDataItem {
key: string;
title: string;
children?: TreeDataItem[];
}
interface TransferDataItem {
value: string;
label: string;
disabled: boolean;
}
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
tableSelected: (string | number)[]; tableSelected: (string | number)[];
@ -87,46 +69,6 @@
const batchModalMode = ref<'project' | 'userGroup' | 'organization'>('project'); const batchModalMode = ref<'project' | 'userGroup' | 'organization'>('project');
const treeData = ref<OrgsItem[]>([]); const treeData = ref<OrgsItem[]>([]);
const loading = ref(false); const loading = ref(false);
const transferData = ref<TransferDataItem[]>([]);
/**
* 获取穿梭框数据根据树结构获取
* @param _treeData 树结构
* @param transferDataSource 穿梭框数组
*/
const getTransferData = (_treeData: OrgsItem[], transferDataSource: TransferDataItem[]) => {
_treeData.forEach((item) => {
if (!item.leafNode && item.children) getTransferData(item.children, transferDataSource);
else transferDataSource.push({ label: item.name, value: item.id, disabled: false });
});
return transferDataSource;
};
/**
* 获取树结构数据根据穿梭框过滤的数据获取
*/
const getTreeData = (data: TransferDataItem[]) => {
const values = data.map((item) => item.value);
const travel = (_treeData: OrgsItem[]) => {
const treeDataSource: TreeDataItem[] = [];
_treeData.forEach((item) => {
// push 穿
const allSelected =
target.value.length > 0 && !item.leafNode && item.children?.every((child) => target.value.includes(child.id));
if (!allSelected && !target.value.includes(item.id) && (item.children || values.includes(item.id))) {
treeDataSource.push({
title: item.name,
key: item.id,
children: item.children ? travel(item.children) : [],
});
}
});
return treeDataSource;
};
return travel(treeData.value);
};
async function handleTableBatch(action: string) { async function handleTableBatch(action: string) {
showBatchModal.value = true; showBatchModal.value = true;
@ -153,7 +95,6 @@
break; break;
} }
treeData.value = resTree; treeData.value = resTree;
transferData.value = getTransferData(treeData.value, []);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {