feat(文件管理): 文件管理页面&树组件调整
This commit is contained in:
parent
5f6bf18411
commit
8c7ab91265
|
@ -42,6 +42,14 @@
|
|||
</div>
|
||||
</template>
|
||||
</a-tree>
|
||||
<slot name="empty">
|
||||
<div
|
||||
v-show="treeData.length === 0 && props.emptyText"
|
||||
class="rounded-[var(--border-radius-small)] bg-[var(--color-fill-1)] p-[8px] text-[12px] text-[var(--color-text-4)]"
|
||||
>
|
||||
{{ props.emptyText }}
|
||||
</div>
|
||||
</slot>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -69,6 +77,7 @@
|
|||
focusNodeKey?: string | number; // 聚焦的节点 key
|
||||
nodeMoreActions?: ActionsItem[]; // 节点展示在省略号按钮内的更多操作
|
||||
expandAll?: boolean; // 是否展开/折叠所有节点,true 为全部展开,false 为全部折叠
|
||||
emptyText?: string; // 空数据时的文案
|
||||
}>(),
|
||||
{
|
||||
searchDebounce: 300,
|
||||
|
@ -256,7 +265,7 @@
|
|||
watch(
|
||||
() => innerFocusNodeKey.value,
|
||||
(val) => {
|
||||
if (val) {
|
||||
if (val.toString() !== '') {
|
||||
focusEl.value = treeRef.value?.$el.querySelector(`[data-key=${val}]`);
|
||||
if (focusEl.value) {
|
||||
focusEl.value.style.backgroundColor = 'rgb(var(--primary-1))';
|
||||
|
@ -334,6 +343,7 @@
|
|||
.ms-tree-node-extra__btn,
|
||||
.ms-tree-node-extra__more {
|
||||
padding: 4px;
|
||||
border-radius: var(--border-radius-mini);
|
||||
&:hover {
|
||||
background-color: rgb(var(--primary-9));
|
||||
.arco-icon {
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<template>
|
||||
<div class="flex items-center gap-[4px]">
|
||||
<popConfirm mode="add" :all-names="[]" @close="emit('close')">
|
||||
<MsButton type="text" size="mini" class="action-btn" @click="emit('add', props.item)">
|
||||
<MsIcon type="icon-icon_add_outlined" size="14" class="text-[var(--color-text-4)]" />
|
||||
</MsButton>
|
||||
</popConfirm>
|
||||
<MsTableMoreAction
|
||||
:list="folderMoreActions"
|
||||
trigger="click"
|
||||
@select="emit('select', $event, props.item)"
|
||||
@close="emit('actionsClose')"
|
||||
>
|
||||
<MsButton type="text" size="mini" class="action-btn" @click="emit('clickMore', props.item)">
|
||||
<MsIcon type="icon-icon_more_outlined" size="14" class="text-[var(--color-text-4)]" />
|
||||
</MsButton>
|
||||
</MsTableMoreAction>
|
||||
<popConfirm mode="rename" :title="item.name" :all-names="[]" @close="emit('close')">
|
||||
<span ref="renameSpanRef" class="relative"></span>
|
||||
</popConfirm>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import popConfirm from './popConfirm.vue';
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import MsTableMoreAction from '@/components/pure/ms-table-more-action/index.vue';
|
||||
|
||||
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||
|
||||
const props = defineProps<{
|
||||
item: Record<string, any>;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['add', 'close', 'select', 'actionsClose', 'clickMore']);
|
||||
|
||||
const folderMoreActions: ActionsItem[] = [
|
||||
{
|
||||
label: 'project.fileManagement.rename',
|
||||
eventTag: 'rename',
|
||||
},
|
||||
{
|
||||
label: 'project.fileManagement.delete',
|
||||
eventTag: 'delete',
|
||||
danger: true,
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.action-btn {
|
||||
@apply !mr-0;
|
||||
|
||||
padding: 4px;
|
||||
border-radius: var(--border-radius-mini);
|
||||
&:hover {
|
||||
background-color: rgb(var(--primary-9));
|
||||
.arco-icon {
|
||||
color: rgb(var(--primary-5));
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,125 @@
|
|||
<template>
|
||||
<a-popconfirm
|
||||
v-model:popup-visible="innerVisible"
|
||||
class="ms-pop-confirm--hidden-icon"
|
||||
position="bottom"
|
||||
:ok-loading="loading"
|
||||
:cancel-button-props="{ disabled: loading }"
|
||||
:on-before-ok="beforeConfirm"
|
||||
:popup-container="props.popupContainer || 'body'"
|
||||
@popup-visible-change="reset"
|
||||
>
|
||||
<template #content>
|
||||
<div class="mb-[8px] font-medium">
|
||||
{{ props.mode === 'add' ? t('project.fileManagement.addSubModule') : t('project.fileManagement.rename') }}
|
||||
</div>
|
||||
<a-form ref="formRef" :model="form" layout="vertical">
|
||||
<a-form-item
|
||||
class="hidden-item"
|
||||
field="name"
|
||||
:rules="[{ required: true, message: t('project.fileManagement.nameNotNull') }, { validator: validateName }]"
|
||||
>
|
||||
<a-input
|
||||
v-model:model-value="form.name"
|
||||
:max-length="50"
|
||||
:placeholder="props.placeholder || t('project.fileManagement.namePlaceholder')"
|
||||
class="w-[245px]"
|
||||
@press-enter="beforeConfirm(undefined)"
|
||||
></a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
<slot></slot>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
|
||||
import type { FormInstance } from '@arco-design/web-vue';
|
||||
|
||||
const props = defineProps<{
|
||||
mode: 'add' | 'rename';
|
||||
visible?: boolean;
|
||||
title?: string;
|
||||
allNames: string[];
|
||||
popupContainer?: string;
|
||||
placeholder?: string;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits(['update:visible', 'close']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const innerVisible = ref(props.visible || false);
|
||||
const form = ref({
|
||||
name: props.title || '',
|
||||
});
|
||||
const formRef = ref<FormInstance>();
|
||||
const loading = ref(false);
|
||||
|
||||
watch(
|
||||
() => props.title,
|
||||
(val) => {
|
||||
form.value.name = val || '';
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
innerVisible.value = val;
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => innerVisible.value,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
emit('close');
|
||||
}
|
||||
emit('update:visible', val);
|
||||
}
|
||||
);
|
||||
|
||||
function beforeConfirm(done?: (closed: boolean) => void) {
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
loading.value = true;
|
||||
if (props.mode === 'add') {
|
||||
Message.success(t('project.fileManagement.addSubModuleSuccess'));
|
||||
} else {
|
||||
Message.success(t('project.fileManagement.renameSuccess'));
|
||||
}
|
||||
if (done) {
|
||||
done(true);
|
||||
} else {
|
||||
innerVisible.value = false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
} else if (done) {
|
||||
done(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function validateName(value: any, callback: (error?: string | undefined) => void) {
|
||||
if (props.allNames.includes(value)) {
|
||||
callback(t('project.fileManagement.nameExist'));
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
form.value.name = '';
|
||||
formRef.value?.resetFields();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
|
@ -0,0 +1,64 @@
|
|||
<template>
|
||||
<div class="p-[24px]">
|
||||
<div class="header">
|
||||
<a-button type="primary">{{ t('project.fileManagement.addFile') }}</a-button>
|
||||
<div class="header-right">
|
||||
<a-input-search
|
||||
v-model:model-value="keyword"
|
||||
:placeholder="t('project.fileManagement.folderSearchPlaceholder')"
|
||||
allow-clear
|
||||
class="w-[240px]"
|
||||
></a-input-search>
|
||||
<a-radio-group v-model:model-value="fileType" type="button" class="file-show-type" @change="changeFileType">
|
||||
<a-radio value="Module" class="show-type-icon">{{ t('project.fileManagement.module') }}</a-radio>
|
||||
<a-radio value="Storage" class="show-type-icon">{{ t('project.fileManagement.storage') }}</a-radio>
|
||||
</a-radio-group>
|
||||
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type" @change="changeShowType">
|
||||
<a-radio value="list" class="show-type-icon p-[2px]"><MsIcon type="icon-icon_view-list_outlined" /></a-radio>
|
||||
<a-radio value="card" class="show-type-icon p-[2px]"><MsIcon type="icon-icon_card_outlined" /></a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const keyword = ref('');
|
||||
const fileType = ref('Module');
|
||||
|
||||
function changeFileType() {
|
||||
console.log(fileType.value);
|
||||
}
|
||||
|
||||
const showType = ref('list');
|
||||
|
||||
function changeShowType() {
|
||||
console.log(showType.value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.header {
|
||||
@apply flex items-center justify-between;
|
||||
.header-right {
|
||||
@apply ml-auto flex items-center justify-end;
|
||||
|
||||
width: 70%;
|
||||
gap: 8px;
|
||||
.show-type-icon {
|
||||
:deep(.arco-radio-button-content) {
|
||||
@apply flex;
|
||||
|
||||
padding: 4px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,664 @@
|
|||
<template>
|
||||
<div class="page">
|
||||
<MsSplitBox>
|
||||
<template #left>
|
||||
<div class="p-[24px]">
|
||||
<div class="folder" @click="setActiveFolder('my')">
|
||||
<div :class="getFolderClass('my')">
|
||||
<MsIcon type="icon-icon_folder_filled1" class="folder-icon" />
|
||||
<div class="folder-name">{{ t('project.fileManagement.myFile') }}</div>
|
||||
<div class="folder-count">({{ myFileCount }})</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder">
|
||||
<div :class="getFolderClass('all')" @click="setActiveFolder('all')">
|
||||
<MsIcon type="icon-icon_folder_filled1" class="folder-icon" />
|
||||
<div class="folder-name">{{ t('project.fileManagement.allFile') }}</div>
|
||||
<div class="folder-count">({{ allFileCount }})</div>
|
||||
</div>
|
||||
<div class="ml-auto flex items-center">
|
||||
<a-tooltip
|
||||
:content="isExpandAll ? t('project.fileManagement.collapseAll') : t('project.fileManagement.expandAll')"
|
||||
>
|
||||
<a-button type="text" size="mini" class="p-[4px]" @click="changeExpand">
|
||||
<MsIcon :type="isExpandAll ? 'icon-icon_folder_collapse1' : 'icon-icon_folder_expansion'" />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<popConfirm mode="add" :all-names="[]">
|
||||
<a-tooltip :content="t('project.fileManagement.addSubModule')">
|
||||
<a-button type="text" size="mini" class="p-[2px]">
|
||||
<MsIcon type="icon-icon_create_planarity" size="18" />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</popConfirm>
|
||||
</div>
|
||||
</div>
|
||||
<a-divider class="my-[8px]" />
|
||||
<a-radio-group v-model:model-value="showType" type="button" class="file-show-type" @change="changeShowType">
|
||||
<a-radio value="Module">{{ t('project.fileManagement.module') }}</a-radio>
|
||||
<a-radio value="Storage">{{ t('project.fileManagement.storage') }}</a-radio>
|
||||
</a-radio-group>
|
||||
<div v-show="showType === 'Module'">
|
||||
<a-input
|
||||
v-model:model-value="moduleKeyword"
|
||||
:placeholder="t('project.fileManagement.folderSearchPlaceholder')"
|
||||
allow-clear
|
||||
class="mb-[8px]"
|
||||
></a-input>
|
||||
<MsTree
|
||||
v-model:focus-node-key="focusNodeKey"
|
||||
:data="folderTree"
|
||||
:keyword="moduleKeyword"
|
||||
:node-more-actions="folderMoreActions"
|
||||
:expand-all="isExpandAll"
|
||||
:empty-text="t('project.fileManagement.noFolder')"
|
||||
draggable
|
||||
block-node
|
||||
@select="folderNodeSelect"
|
||||
@more-action-select="handleFolderMoreSelect"
|
||||
@more-actions-close="moreActionsClose"
|
||||
>
|
||||
<template #title="nodeData">
|
||||
<span class="text-[var(--color-text-1)]">{{ nodeData.title }}</span>
|
||||
<span class="ml-[4px] text-[var(--color-text-4)]">({{ nodeData.count }})</span>
|
||||
</template>
|
||||
<template #extra="nodeData">
|
||||
<popConfirm mode="add" :all-names="[]" @close="resetFocusNodeKey">
|
||||
<MsButton
|
||||
type="text"
|
||||
size="mini"
|
||||
class="ms-tree-node-extra__btn !mr-0"
|
||||
@click="setFocusNodeKe(nodeData)"
|
||||
>
|
||||
<MsIcon type="icon-icon_add_outlined" size="14" class="text-[var(--color-text-4)]" />
|
||||
</MsButton>
|
||||
</popConfirm>
|
||||
<popConfirm mode="rename" :title="renameFolderTitle" :all-names="[]" @close="resetFocusNodeKey">
|
||||
<span :id="`renameSpan${nodeData.key}`" class="relative"></span>
|
||||
</popConfirm>
|
||||
</template>
|
||||
</MsTree>
|
||||
</div>
|
||||
<div v-show="showType === 'Storage'">
|
||||
<a-input
|
||||
v-model:model-value="storageKeyword"
|
||||
:placeholder="t('project.fileManagement.folderSearchPlaceholder')"
|
||||
allow-clear
|
||||
class="mb-[8px]"
|
||||
></a-input>
|
||||
<a-list
|
||||
:virtual-list-props="{
|
||||
height: 'calc(100vh - 310px)',
|
||||
}"
|
||||
:data="storageList"
|
||||
:bordered="false"
|
||||
:split="false"
|
||||
>
|
||||
<template #item="{ item, index }">
|
||||
<div
|
||||
:key="index"
|
||||
:class="['folder', focusNodeKey === item.key ? 'ms-tree-node-extra--focus' : '']"
|
||||
@click="setActiveFolder(item.key)"
|
||||
>
|
||||
<div :class="getFolderClass(item.key)">
|
||||
<MsIcon type="icon-icon_git" class="folder-icon" />
|
||||
<div class="folder-name">{{ item.title }}</div>
|
||||
<div class="folder-count">({{ item.count }})</div>
|
||||
</div>
|
||||
<itemActions
|
||||
:item="item"
|
||||
@click.stop
|
||||
@add="setFocusNodeKe"
|
||||
@close="resetFocusNodeKey"
|
||||
@actions-close="moreActionsClose"
|
||||
@click-more="setFocusNodeKe"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #empty>
|
||||
<div
|
||||
class="rounded-[var(--border-radius-small)] bg-[var(--color-fill-1)] p-[8px] text-[12px] text-[var(--color-text-4)]"
|
||||
>
|
||||
{{ t('project.fileManagement.noStorage') }}
|
||||
</div>
|
||||
</template>
|
||||
</a-list>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #right>
|
||||
<rightBox />
|
||||
</template>
|
||||
</MsSplitBox>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { debounce } from 'lodash-es';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import MsSplitBox from '@/components/pure/ms-split-box/index.vue';
|
||||
import MsIcon from '@/components/pure/ms-icon-font/index.vue';
|
||||
import MsTree from '@/components/business/ms-tree/index.vue';
|
||||
import MsButton from '@/components/pure/ms-button/index.vue';
|
||||
import useModal from '@/hooks/useModal';
|
||||
import popConfirm from './components/popConfirm.vue';
|
||||
import rightBox from './components/rightBox.vue';
|
||||
import itemActions from './components/itemActions.vue';
|
||||
|
||||
import type { MsTreeNodeData } from '@/components/business/ms-tree/types';
|
||||
import type { ActionsItem } from '@/components/pure/ms-table-more-action/types';
|
||||
|
||||
const { t } = useI18n();
|
||||
const { openModal } = useModal();
|
||||
|
||||
const myFileCount = ref(0);
|
||||
const allFileCount = ref(0);
|
||||
const isExpandAll = ref(false);
|
||||
const activeFolderType = ref<'folder' | 'module' | 'storage'>('folder');
|
||||
|
||||
function changeExpand() {
|
||||
isExpandAll.value = !isExpandAll.value;
|
||||
}
|
||||
|
||||
const activeFolder = ref<string | number>('all');
|
||||
|
||||
function setActiveFolder(id: string) {
|
||||
activeFolder.value = id;
|
||||
if (['my', 'all'].includes(id)) {
|
||||
activeFolderType.value = 'folder';
|
||||
} else {
|
||||
activeFolderType.value = 'storage';
|
||||
}
|
||||
}
|
||||
|
||||
function getFolderClass(id: string) {
|
||||
return activeFolder.value === id ? 'folder-text folder-text--active' : 'folder-text';
|
||||
}
|
||||
|
||||
type FileShowType = 'Module' | 'Storage';
|
||||
const showType = ref<FileShowType>('Module');
|
||||
|
||||
function changeShowType(val: string | number | boolean) {
|
||||
showType.value = val as FileShowType;
|
||||
}
|
||||
|
||||
const moduleKeyword = ref('');
|
||||
|
||||
const folderTree = ref([
|
||||
{
|
||||
title: 'Trunk',
|
||||
key: 'node1',
|
||||
count: 18,
|
||||
children: [
|
||||
{
|
||||
title: 'Leaf',
|
||||
key: 'node2',
|
||||
count: 28,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Trunk',
|
||||
key: 'node3',
|
||||
count: 180,
|
||||
children: [
|
||||
{
|
||||
title: 'Leaf',
|
||||
key: 'node4',
|
||||
count: 138,
|
||||
},
|
||||
{
|
||||
title: 'Leaf',
|
||||
key: 'node5',
|
||||
count: 108,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Trunk',
|
||||
key: 'node6',
|
||||
children: [],
|
||||
count: 0,
|
||||
},
|
||||
]);
|
||||
|
||||
const focusNodeKey = ref<string | number>('');
|
||||
|
||||
function setFocusNodeKe(node: MsTreeNodeData) {
|
||||
focusNodeKey.value = node.key || '';
|
||||
}
|
||||
|
||||
const folderMoreActions: ActionsItem[] = [
|
||||
{
|
||||
label: 'project.fileManagement.rename',
|
||||
eventTag: 'rename',
|
||||
},
|
||||
{
|
||||
label: 'project.fileManagement.delete',
|
||||
eventTag: 'delete',
|
||||
danger: true,
|
||||
},
|
||||
];
|
||||
const renamePopVisible = ref(false);
|
||||
|
||||
/**
|
||||
* 删除文件夹
|
||||
* @param node 节点信息
|
||||
*/
|
||||
function deleteFolder(node: MsTreeNodeData) {
|
||||
openModal({
|
||||
type: 'error',
|
||||
title: t('project.fileManagement.deleteTipTitle', { name: node.title }),
|
||||
content: t('project.fileManagement.deleteTipContent'),
|
||||
okText: t('project.fileManagement.deleteConfirm'),
|
||||
okButtonProps: {
|
||||
status: 'danger',
|
||||
},
|
||||
maskClosable: false,
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
Message.success(t('project.fileManagement.deleteSuccess'));
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
hideCancel: false,
|
||||
});
|
||||
}
|
||||
|
||||
const renameFolderTitle = ref(''); // 重命名的文件夹名称
|
||||
|
||||
function resetFocusNodeKey() {
|
||||
focusNodeKey.value = '';
|
||||
renamePopVisible.value = false;
|
||||
renameFolderTitle.value = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理文件夹树节点选中事件
|
||||
*/
|
||||
function folderNodeSelect(selectedKeys: (string | number)[]) {
|
||||
[activeFolder.value] = selectedKeys;
|
||||
activeFolderType.value = 'module';
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理树节点更多按钮事件
|
||||
* @param item
|
||||
*/
|
||||
function handleFolderMoreSelect(item: ActionsItem, node: MsTreeNodeData) {
|
||||
switch (item.eventTag) {
|
||||
case 'delete':
|
||||
deleteFolder(node);
|
||||
resetFocusNodeKey();
|
||||
break;
|
||||
case 'rename':
|
||||
renameFolderTitle.value = node.title || '';
|
||||
renamePopVisible.value = true;
|
||||
document.querySelector(`#renameSpan${node.key}`)?.dispatchEvent(new Event('click'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function moreActionsClose() {
|
||||
if (!renamePopVisible.value) {
|
||||
// 当下拉菜单关闭时,若不是触发重命名气泡显示,则清空聚焦节点 key
|
||||
resetFocusNodeKey();
|
||||
}
|
||||
}
|
||||
|
||||
const storageKeyword = ref('');
|
||||
const originStorageList = ref([
|
||||
{
|
||||
title: 'storage1',
|
||||
key: '1',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage2',
|
||||
key: '2',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage1',
|
||||
key: '1',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage2',
|
||||
key: '2',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage1',
|
||||
key: '1',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage2',
|
||||
key: '2',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
{
|
||||
title: 'storage3',
|
||||
key: '3',
|
||||
count: 129,
|
||||
},
|
||||
]);
|
||||
const storageList = ref(originStorageList.value);
|
||||
|
||||
const searchStorage = debounce(() => {
|
||||
storageList.value = originStorageList.value.filter((item) => item.title.includes(storageKeyword.value));
|
||||
}, 300);
|
||||
|
||||
watch(
|
||||
() => storageKeyword.value,
|
||||
() => {
|
||||
if (storageKeyword.value === '') {
|
||||
storageList.value = originStorageList.value;
|
||||
}
|
||||
searchStorage();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.page {
|
||||
@apply bg-white;
|
||||
|
||||
height: calc(100vh - 88px);
|
||||
border-radius: var(--border-radius-large);
|
||||
.folder {
|
||||
@apply flex cursor-pointer items-center justify-between;
|
||||
|
||||
padding: 8px 4px;
|
||||
border-radius: var(--border-radius-small);
|
||||
&:hover {
|
||||
background-color: rgb(var(--primary-1));
|
||||
}
|
||||
.folder-text {
|
||||
@apply flex cursor-pointer items-center;
|
||||
.folder-icon {
|
||||
margin-right: 4px;
|
||||
color: var(--color-text-4);
|
||||
}
|
||||
.folder-name {
|
||||
color: var(--color-text-1);
|
||||
}
|
||||
.folder-count {
|
||||
margin-left: 4px;
|
||||
color: var(--color-text-4);
|
||||
}
|
||||
}
|
||||
.folder-text--active {
|
||||
.folder-icon,
|
||||
.folder-name,
|
||||
.folder-count {
|
||||
color: rgb(var(--primary-5));
|
||||
}
|
||||
}
|
||||
}
|
||||
.file-show-type {
|
||||
@apply grid grid-cols-2;
|
||||
|
||||
margin-bottom: 8px;
|
||||
:deep(.arco-radio-button-content) {
|
||||
@apply text-center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1 @@
|
|||
export default {};
|
|
@ -0,0 +1,25 @@
|
|||
export default {
|
||||
'project.fileManagement.myFile': '我的文件',
|
||||
'project.fileManagement.allFile': '全部文件',
|
||||
'project.fileManagement.defaultFile': '默认文件',
|
||||
'project.fileManagement.expandAll': '展开全部子模块',
|
||||
'project.fileManagement.collapseAll': '收起全部子模块',
|
||||
'project.fileManagement.addSubModule': '添加子模块',
|
||||
'project.fileManagement.rename': '重命名',
|
||||
'project.fileManagement.nameNotNull': '名字不能为空',
|
||||
'project.fileManagement.namePlaceholder': '请输入分组名称,按回车键保存',
|
||||
'project.fileManagement.renameSuccess': '重命名成功',
|
||||
'project.fileManagement.addSubModuleSuccess': '添加成功',
|
||||
'project.fileManagement.nameExist': '该层级已有此模块名称',
|
||||
'project.fileManagement.module': '模块',
|
||||
'project.fileManagement.storage': '存储库',
|
||||
'project.fileManagement.folderSearchPlaceholder': '输入名称搜索',
|
||||
'project.fileManagement.delete': '删除',
|
||||
'project.fileManagement.deleteSuccess': '删除成功',
|
||||
'project.fileManagement.deleteTipTitle': '是否删除 `{name}` 模块?',
|
||||
'project.fileManagement.deleteTipContent': '该操作会删除模块及其下所有资源,请谨慎操作!',
|
||||
'project.fileManagement.deleteConfirm': '确认删除',
|
||||
'project.fileManagement.noFolder': '暂无匹配的相关模块',
|
||||
'project.fileManagement.noStorage': '暂无匹配的相关存储库',
|
||||
'project.fileManagement.addFile': '添加文件',
|
||||
};
|
|
@ -437,11 +437,27 @@
|
|||
);
|
||||
|
||||
function searchLog() {
|
||||
const ranges = operateRange.value.map((e) => e);
|
||||
const ranges = operateRange.value.map((e) => {
|
||||
if (typeof e === 'object') {
|
||||
return e.value;
|
||||
}
|
||||
return e;
|
||||
});
|
||||
let projectIds = [];
|
||||
let organizationIds = [];
|
||||
|
||||
if (!MENU_LEVEL.includes(level.value) && typeof operateRange.value[0] === 'object') {
|
||||
if (operateRange.value[0].level === MENU_LEVEL[1]) {
|
||||
organizationIds = ranges;
|
||||
} else if (operateRange.value[0].level === MENU_LEVEL[2]) {
|
||||
projectIds = ranges;
|
||||
}
|
||||
}
|
||||
|
||||
setLoadListParams({
|
||||
operUser: operUser.value,
|
||||
projectIds: level.value === 'PROJECT' && ranges[0] !== 'PROJECT' ? ranges : [],
|
||||
organizationIds: level.value === 'ORGANIZATION' && ranges[0] !== 'ORGANIZATION' ? ranges : [],
|
||||
projectIds,
|
||||
organizationIds,
|
||||
type: type.value,
|
||||
module: _module.value,
|
||||
content: content.value,
|
||||
|
|
|
@ -268,12 +268,14 @@
|
|||
title: 'system.user.tableColumnOrg',
|
||||
slotName: 'organization',
|
||||
dataIndex: 'organizationList',
|
||||
showTooltip: true,
|
||||
showInTable: true,
|
||||
},
|
||||
{
|
||||
title: 'system.user.tableColumnUserGroup',
|
||||
slotName: 'userRole',
|
||||
dataIndex: 'userRoleList',
|
||||
showTooltip: true,
|
||||
showInTable: true,
|
||||
},
|
||||
{
|
||||
|
@ -297,7 +299,6 @@
|
|||
{
|
||||
tableKey: TableKeyEnum.SYSTEM_USER,
|
||||
columns,
|
||||
scroll: { y: 'auto' },
|
||||
selectable: true,
|
||||
},
|
||||
(record) => ({
|
||||
|
|
Loading…
Reference in New Issue