这是基于vue-vben-admin 模板适用于abp vNext的前端管理项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

192 lines
4.6 KiB

<script setup lang="ts">
import type { EventDataNode, Key } from 'ant-design-vue/es/vc-tree/interface';
import type { TreeProps } from 'ant-design-vue/es/vc-tree/props';
import type { OssContainerDto } from '../../types';
import type { OssObjectDto } from '../../types/objects';
import { defineAsyncComponent, onMounted, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { Button, Card, DirectoryTree, Empty, Select } from 'ant-design-vue';
import { useContainesApi } from '../../api';
const emits = defineEmits<{
(event: 'bucketChange', data: string): void;
(event: 'folderChange', data: string): void;
}>();
interface Folder {
children?: Folder[];
isLeaf?: boolean;
key: string;
name: string;
path?: string;
title: string;
}
const { getListApi: getContainersApi, getObjectsApi } = useContainesApi();
const [FolderModal, modalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(() => import('./FolderModal.vue')),
});
const rootFolder: Folder = {
isLeaf: false,
key: './',
name: './',
path: '',
title: $t('AbpOssManagement.Objects:Root'),
children: [],
};
const bucket = ref<string>('');
const loadedFolders = ref<string[]>([]);
const expandedFolders = ref<string[]>([]);
const selectedFolders = ref<string[]>([]);
const containers = ref<OssContainerDto[]>([]);
const folders = ref<Folder[]>([
{
...rootFolder,
},
]);
const onLoadChildFolders: TreeProps['loadData'] = async (treeNode) => {
let path = '';
if (treeNode.dataRef?.path) {
path = path + treeNode.dataRef?.path;
}
if (treeNode.dataRef?.name) {
path = path + treeNode.dataRef?.name;
}
try {
treeNode.dataRef!.children = await getFolders(bucket.value!, path);
} catch {
treeNode.dataRef!.children = [];
}
folders.value = [...folders.value];
loadedFolders.value = [...loadedFolders.value, treeNode.key.toString()];
};
async function onInit() {
const getContainersRes = await getContainersApi({
maxResultCount: 1000,
});
containers.value = getContainersRes.containers;
}
async function getFolders(bucket: string, path?: string) {
const { objects } = await getObjectsApi({
bucket,
delimiter: '/',
maxResultCount: 1000,
prefix: path ?? '',
});
return objects
.filter((f) => f.isFolder)
.map((folder) => {
return {
isLeaf: false,
key: `${folder.path ?? ''}${folder.name}`,
name: folder.name,
path: folder.path,
title: folder.name,
children: [],
};
});
}
function onFolderExpand(
_: Key[],
info: {
expanded: boolean;
node: EventDataNode;
},
) {
if (!info.expanded) {
const keys = loadedFolders.value;
const findIndex = keys.lastIndexOf(info.node.key.toString());
findIndex !== -1 && keys.splice(findIndex);
loadedFolders.value = keys;
}
}
function onFolderChange(selectedKeys: Key[]) {
if (selectedKeys.length === 1) {
emits('folderChange', selectedKeys[0]!.toString());
}
}
async function onBucketChange(bucket: string) {
emits('bucketChange', bucket);
expandedFolders.value = [];
loadedFolders.value = [];
folders.value = [
{
...rootFolder,
},
];
}
function onCreate() {
modalApi.setData({
bucket: bucket.value,
path: selectedFolders.value[0],
});
modalApi.open();
}
function onFolderCreated(ossObject: OssObjectDto) {
const keys = expandedFolders.value;
const findIndex = keys.lastIndexOf(ossObject.path);
if (findIndex !== -1) {
keys.splice(findIndex);
expandedFolders.value = keys;
loadedFolders.value = [];
}
}
onMounted(onInit);
</script>
<template>
<Card :title="$t('AbpOssManagement.Containers')">
<div class="flex flex-col gap-2">
<Select
:placeholder="$t('AbpOssManagement.Containers:Select')"
:options="containers"
:field-names="{ label: 'name', value: 'name' }"
v-model:value="bucket"
@change="(e) => onBucketChange(e!.toString())"
/>
<Button v-if="bucket" block type="primary" ghost @click="onCreate">
{{ $t('AbpOssManagement.Objects:CreateFolder') }}
</Button>
<DirectoryTree
v-if="bucket"
block-node
v-model:expanded-keys="expandedFolders"
v-model:selected-keys="selectedFolders"
:loaded-keys="loadedFolders"
:tree-data="folders"
:load-data="onLoadChildFolders"
@select="onFolderChange"
@expand="onFolderExpand"
/>
<Empty v-else />
</div>
</Card>
<FolderModal @change="onFolderCreated" />
</template>
<style scoped lang="scss">
:deep(.ant-tree) {
.ant-tree-title {
word-break: break-word;
white-space: normal;
}
}
</style>