feat(文件管理): 重构文件上传和操作界面
- 将上传按钮改为下拉菜单,支持选择上传文件或文件夹 - 优化操作按钮布局和图标使用方式 - 添加文件排序功能,支持按文件名、创建时间和状态排序 - 改进状态筛选交互,使用下拉菜单方式 - 统一图标大小和使用方式,提升视觉一致性 - 调整主题色为更明亮的蓝色(#198cb2)
This commit is contained in:
parent
3c77755a78
commit
88aecfbebc
@ -33,11 +33,11 @@
|
|||||||
<a-dropdown :trigger="['click']" @click.stop>
|
<a-dropdown :trigger="['click']" @click.stop>
|
||||||
<template #overlay>
|
<template #overlay>
|
||||||
<a-menu>
|
<a-menu>
|
||||||
<a-menu-item key="rename" @click.stop="renameChat(chat.id)">
|
<a-menu-item key="rename" @click.stop="renameChat(chat.id)" :icon="h(EditOutlined)">
|
||||||
<EditOutlined /> 重命名
|
重命名
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="delete" @click.stop="deleteChat(chat.id)">
|
<a-menu-item key="delete" @click.stop="deleteChat(chat.id)" :icon="h(DeleteOutlined)">
|
||||||
<DeleteOutlined /> 删除
|
删除
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -1,54 +1,88 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="file-table-container">
|
<div class="file-table-container">
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<div class="search-container">
|
<div class="upload-btn-group">
|
||||||
<a-button
|
<a-dropdown trigger="click">
|
||||||
type="secondary"
|
<a-button type="primary" size="small" class="upload-btn">
|
||||||
@click="showAddFilesModal"
|
<FileUp size="14" style="margin-left: 4px;" />
|
||||||
:loading="refreshing"
|
上传
|
||||||
:icon="h(PlusOutlined)"
|
<ChevronDown size="14" style="margin-left: 4px;" />
|
||||||
>文件</a-button>
|
</a-button>
|
||||||
<a-button
|
<template #overlay>
|
||||||
type="secondary"
|
<a-menu>
|
||||||
@click="showCreateFolderModal"
|
<a-menu-item key="upload-file" @click="showAddFilesModal({ isFolder: false })" :icon="h(FileUp, { size: 16 })">
|
||||||
:loading="refreshing"
|
上传文件
|
||||||
:icon="h(FolderAddOutlined)"
|
</a-menu-item>
|
||||||
>文件夹</a-button>
|
<a-menu-item key="upload-folder" @click="showAddFilesModal({ isFolder: true })" :icon="h(FolderUp, { size: 16 })">
|
||||||
|
上传文件夹
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
|
||||||
|
<a-button class="panel-action-btn" type="text" size="small" @click="showCreateFolderModal" title="新建文件夹">
|
||||||
|
<template #icon><FolderPlus size="16" /></template>
|
||||||
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-actions">
|
<div class="panel-actions">
|
||||||
<a-select
|
|
||||||
v-model:value="statusFilter"
|
|
||||||
placeholder="状态"
|
|
||||||
size="small"
|
|
||||||
style="width: 100px; margin-right: 8px;"
|
|
||||||
allow-clear
|
|
||||||
:options="statusOptions"
|
|
||||||
@change="onFilterChange"
|
|
||||||
/>
|
|
||||||
<a-input
|
<a-input
|
||||||
v-model:value="filenameFilter"
|
v-model:value="filenameFilter"
|
||||||
placeholder="搜索文件名"
|
placeholder="搜索"
|
||||||
size="small"
|
size="small"
|
||||||
class="action-searcher"
|
class="action-searcher"
|
||||||
allow-clear
|
allow-clear
|
||||||
@change="onFilterChange"
|
@change="onFilterChange"
|
||||||
/>
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<Search size="14" style="color: var(--gray-400);" />
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
|
|
||||||
|
<a-dropdown trigger="click">
|
||||||
|
<a-button type="text" class="panel-action-btn" title="排序">
|
||||||
|
<template #icon><ArrowUpDown size="16" /></template>
|
||||||
|
</a-button>
|
||||||
|
<template #overlay>
|
||||||
|
<a-menu :selectedKeys="[sortField]" @click="handleSortMenuClick">
|
||||||
|
<a-menu-item v-for="opt in sortOptions" :key="opt.value">
|
||||||
|
{{ opt.label }}
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
|
||||||
|
<a-dropdown trigger="click">
|
||||||
|
<a-button type="text" class="panel-action-btn" :class="{ 'active': statusFilter }" title="筛选状态">
|
||||||
|
<template #icon><Filter size="16" /></template>
|
||||||
|
</a-button>
|
||||||
|
<template #overlay>
|
||||||
|
<a-menu :selectedKeys="statusFilter ? [statusFilter] : []" @click="handleStatusMenuClick">
|
||||||
|
<a-menu-item key="all">全部状态</a-menu-item>
|
||||||
|
<a-menu-item v-for="opt in statusOptions" :key="opt.value">
|
||||||
|
{{ opt.label }}
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
|
||||||
<a-button
|
<a-button
|
||||||
type="text"
|
type="text"
|
||||||
@click="handleRefresh"
|
@click="handleRefresh"
|
||||||
:loading="refreshing"
|
:loading="refreshing"
|
||||||
:icon="h(ReloadOutlined)"
|
|
||||||
title="刷新"
|
title="刷新"
|
||||||
class="panel-action-btn"
|
class="panel-action-btn"
|
||||||
/>
|
>
|
||||||
|
<template #icon><RotateCw size="16" /></template>
|
||||||
|
</a-button>
|
||||||
<a-button
|
<a-button
|
||||||
type="text"
|
type="text"
|
||||||
@click="toggleSelectionMode"
|
@click="toggleSelectionMode"
|
||||||
:icon="h(CheckSquare)"
|
|
||||||
title="多选"
|
title="多选"
|
||||||
class="panel-action-btn"
|
class="panel-action-btn"
|
||||||
:class="{ 'active': isSelectionMode }"
|
:class="{ 'active': isSelectionMode }"
|
||||||
/>
|
>
|
||||||
|
<template #icon><CheckSquare size="16" /></template>
|
||||||
|
</a-button>
|
||||||
<!-- <a-button
|
<!-- <a-button
|
||||||
@click="toggleAutoRefresh"
|
@click="toggleAutoRefresh"
|
||||||
size="small"
|
size="small"
|
||||||
@ -61,11 +95,12 @@
|
|||||||
<a-button
|
<a-button
|
||||||
type="text"
|
type="text"
|
||||||
@click="toggleRightPanel"
|
@click="toggleRightPanel"
|
||||||
:icon="h(ChevronLast)"
|
|
||||||
title="切换右侧面板"
|
title="切换右侧面板"
|
||||||
class="panel-action-btn expand"
|
class="panel-action-btn expand"
|
||||||
:class="{ 'expanded': props.rightPanelVisible }"
|
:class="{ 'expanded': props.rightPanelVisible }"
|
||||||
/>
|
>
|
||||||
|
<template #icon><ChevronLast size="16" /></template>
|
||||||
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -79,7 +114,7 @@
|
|||||||
@click="handleBatchParse"
|
@click="handleBatchParse"
|
||||||
:loading="batchParsing"
|
:loading="batchParsing"
|
||||||
:disabled="!canBatchParse"
|
:disabled="!canBatchParse"
|
||||||
:icon="h(FileText)"
|
:icon="h(FileText, { size: 16 })"
|
||||||
title="批量解析"
|
title="批量解析"
|
||||||
/>
|
/>
|
||||||
<a-button
|
<a-button
|
||||||
@ -87,7 +122,7 @@
|
|||||||
@click="handleBatchIndex"
|
@click="handleBatchIndex"
|
||||||
:loading="batchIndexing"
|
:loading="batchIndexing"
|
||||||
:disabled="!canBatchIndex"
|
:disabled="!canBatchIndex"
|
||||||
:icon="h(Database)"
|
:icon="h(Database, { size: 16 })"
|
||||||
title="批量入库"
|
title="批量入库"
|
||||||
/>
|
/>
|
||||||
<a-button
|
<a-button
|
||||||
@ -96,7 +131,7 @@
|
|||||||
@click="handleBatchDelete"
|
@click="handleBatchDelete"
|
||||||
:loading="batchDeleting"
|
:loading="batchDeleting"
|
||||||
:disabled="!canBatchDelete"
|
:disabled="!canBatchDelete"
|
||||||
:icon="h(Trash2)"
|
:icon="h(Trash2, { size: 16 })"
|
||||||
title="批量删除"
|
title="批量删除"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -198,40 +233,40 @@
|
|||||||
<div class="file-action-list">
|
<div class="file-action-list">
|
||||||
<template v-if="record.is_folder">
|
<template v-if="record.is_folder">
|
||||||
<a-button type="text" block @click="showCreateFolderModal(record.file_id)">
|
<a-button type="text" block @click="showCreateFolderModal(record.file_id)">
|
||||||
<template #icon><component :is="h(FolderPlus)" style="width: 14px; height: 14px;" /></template>
|
<template #icon><component :is="h(FolderPlus)" size="14" /></template>
|
||||||
新建子文件夹
|
新建子文件夹
|
||||||
</a-button>
|
</a-button>
|
||||||
<a-button type="text" block danger @click="handleDeleteFolder(record)">
|
<a-button type="text" block danger @click="handleDeleteFolder(record)">
|
||||||
<template #icon><component :is="h(Trash2)" style="width: 14px; height: 14px;" /></template>
|
<template #icon><component :is="h(Trash2)" size="14" /></template>
|
||||||
删除文件夹
|
删除文件夹
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-button type="text" block @click="handleDownloadFile(record)" :disabled="lock || !['done', 'indexed', 'parsed', 'error_indexing'].includes(record.status)">
|
<a-button type="text" block @click="handleDownloadFile(record)" :disabled="lock || !['done', 'indexed', 'parsed', 'error_indexing'].includes(record.status)">
|
||||||
<template #icon><component :is="h(Download)" style="width: 14px; height: 14px;" /></template>
|
<template #icon><component :is="h(Download)" size="14" /></template>
|
||||||
下载文件
|
下载文件
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
<!-- Parse Action -->
|
<!-- Parse Action -->
|
||||||
<a-button v-if="record.status === 'uploaded' || record.status === 'error_parsing'" type="text" block @click="handleParseFile(record)" :disabled="lock">
|
<a-button v-if="record.status === 'uploaded' || record.status === 'error_parsing'" type="text" block @click="handleParseFile(record)" :disabled="lock">
|
||||||
<template #icon><component :is="h(FileText)" style="width: 14px; height: 14px;" /></template>
|
<template #icon><component :is="h(FileText)" size="14" /></template>
|
||||||
{{ record.status === 'error_parsing' ? '重试解析' : '解析文件' }}
|
{{ record.status === 'error_parsing' ? '重试解析' : '解析文件' }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
<!-- Index Action -->
|
<!-- Index Action -->
|
||||||
<a-button v-if="record.status === 'parsed' || record.status === 'error_indexing'" type="text" block @click="handleIndexFile(record)" :disabled="lock">
|
<a-button v-if="record.status === 'parsed' || record.status === 'error_indexing'" type="text" block @click="handleIndexFile(record)" :disabled="lock">
|
||||||
<template #icon><component :is="h(Database)" style="width: 14px; height: 14px;" /></template>
|
<template #icon><component :is="h(Database)" size="14" /></template>
|
||||||
{{ record.status === 'error_indexing' ? '重试入库' : '入库' }}
|
{{ record.status === 'error_indexing' ? '重试入库' : '入库' }}
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
<!-- Reindex Action -->
|
<!-- Reindex Action -->
|
||||||
<a-button v-if="!isLightRAG && (record.status === 'done' || record.status === 'indexed')" type="text" block @click="handleReindexFile(record)" :disabled="lock">
|
<a-button v-if="!isLightRAG && (record.status === 'done' || record.status === 'indexed')" type="text" block @click="handleReindexFile(record)" :disabled="lock">
|
||||||
<template #icon><component :is="h(RefreshCw)" style="width: 14px; height: 14px;" /></template>
|
<template #icon><component :is="h(RotateCw)" size="14" /></template>
|
||||||
重新入库
|
重新入库
|
||||||
</a-button>
|
</a-button>
|
||||||
|
|
||||||
<a-button type="text" block danger @click="handleDeleteFile(record.file_id)" :disabled="lock || ['processing', 'parsing', 'indexing'].includes(record.status)">
|
<a-button type="text" block danger @click="handleDeleteFile(record.file_id)" :disabled="lock || ['processing', 'parsing', 'indexing'].includes(record.status)">
|
||||||
<template #icon><component :is="h(Trash2)" style="width: 14px; height: 14px;" /></template>
|
<template #icon><component :is="h(Trash2)" size="14" /></template>
|
||||||
删除文件
|
删除文件
|
||||||
</a-button>
|
</a-button>
|
||||||
</template>
|
</template>
|
||||||
@ -260,14 +295,11 @@ import {
|
|||||||
FolderFilled,
|
FolderFilled,
|
||||||
FolderOpenFilled,
|
FolderOpenFilled,
|
||||||
FileTextFilled,
|
FileTextFilled,
|
||||||
PlusOutlined,
|
|
||||||
FolderAddOutlined,
|
|
||||||
ReloadOutlined,
|
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import {
|
import {
|
||||||
Trash2,
|
Trash2,
|
||||||
Download,
|
Download,
|
||||||
RefreshCw,
|
RotateCw,
|
||||||
ChevronLast,
|
ChevronLast,
|
||||||
Ellipsis,
|
Ellipsis,
|
||||||
FolderPlus,
|
FolderPlus,
|
||||||
@ -276,11 +308,36 @@ import {
|
|||||||
FileCheck,
|
FileCheck,
|
||||||
Plus,
|
Plus,
|
||||||
Database,
|
Database,
|
||||||
|
FileUp,
|
||||||
|
FolderUp,
|
||||||
|
Search,
|
||||||
|
Filter,
|
||||||
|
ArrowUpDown,
|
||||||
|
ChevronDown,
|
||||||
} from 'lucide-vue-next';
|
} from 'lucide-vue-next';
|
||||||
|
|
||||||
const store = useDatabaseStore();
|
const store = useDatabaseStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const sortField = ref('filename');
|
||||||
|
const sortOptions = [
|
||||||
|
{ label: '文件名', value: 'filename' },
|
||||||
|
{ label: '创建时间', value: 'created_at' },
|
||||||
|
{ label: '状态', value: 'status' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleSortMenuClick = (e) => {
|
||||||
|
sortField.value = e.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStatusMenuClick = (e) => {
|
||||||
|
if (e.key === 'all') {
|
||||||
|
statusFilter.value = null;
|
||||||
|
} else {
|
||||||
|
statusFilter.value = e.key;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Status text mapping
|
// Status text mapping
|
||||||
const getStatusText = (status) => {
|
const getStatusText = (status) => {
|
||||||
const map = {
|
const map = {
|
||||||
@ -613,7 +670,21 @@ const buildFileTree = (fileList) => {
|
|||||||
nodes.sort((a, b) => {
|
nodes.sort((a, b) => {
|
||||||
if (a.is_folder && !b.is_folder) return -1;
|
if (a.is_folder && !b.is_folder) return -1;
|
||||||
if (!a.is_folder && b.is_folder) return 1;
|
if (!a.is_folder && b.is_folder) return 1;
|
||||||
return (a.filename || '').localeCompare(b.filename || '');
|
|
||||||
|
if (sortField.value === 'filename') {
|
||||||
|
return (a.filename || '').localeCompare(b.filename || '');
|
||||||
|
} else if (sortField.value === 'created_at') {
|
||||||
|
return new Date(b.created_at || 0) - new Date(a.created_at || 0);
|
||||||
|
} else if (sortField.value === 'status') {
|
||||||
|
const statusOrder = {
|
||||||
|
'done': 1, 'indexed': 1,
|
||||||
|
'processing': 2, 'indexing': 2, 'parsing': 2,
|
||||||
|
'waiting': 3, 'uploaded': 3, 'parsed': 3,
|
||||||
|
'failed': 4, 'error_indexing': 4, 'error_parsing': 4
|
||||||
|
};
|
||||||
|
return (statusOrder[a.status] || 5) - (statusOrder[b.status] || 5);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
});
|
});
|
||||||
nodes.forEach(node => {
|
nodes.forEach(node => {
|
||||||
if (node.children) sortNodes(node.children);
|
if (node.children) sortNodes(node.children);
|
||||||
@ -699,8 +770,8 @@ const canBatchIndex = computed(() => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const showAddFilesModal = () => {
|
const showAddFilesModal = (options = {}) => {
|
||||||
emit('showAddFilesModal');
|
emit('showAddFilesModal', options);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRefresh = () => {
|
const handleRefresh = () => {
|
||||||
@ -978,29 +1049,10 @@ import ChunkParamsConfig from '@/components/ChunkParamsConfig.vue';
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 4px;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
padding: 4px 4px;
|
padding: 8px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
button {
|
|
||||||
padding: 0 8px;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
|
||||||
background-color: var(--gray-50);
|
|
||||||
color: var(--main-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-actions {
|
.panel-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -1225,14 +1277,29 @@ import ChunkParamsConfig from '@/components/ChunkParamsConfig.vue';
|
|||||||
|
|
||||||
:deep(.drop-over-folder) {
|
:deep(.drop-over-folder) {
|
||||||
background-color: var(--primary-50) !important;
|
background-color: var(--primary-50) !important;
|
||||||
outline: 2px dashed var(--main-color);
|
outline: 2px dashed var(--main-color);
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
td {
|
td {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-btn-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.upload-btn {
|
||||||
|
height: 28px;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|||||||
@ -52,7 +52,6 @@
|
|||||||
tree-node-filter-prop="title"
|
tree-node-filter-prop="title"
|
||||||
>
|
>
|
||||||
</a-tree-select>
|
</a-tree-select>
|
||||||
<a-checkbox v-model:checked="isFolderUpload" class="folder-checkbox">上传文件夹</a-checkbox>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -185,6 +184,10 @@ const props = defineProps({
|
|||||||
currentFolderId: {
|
currentFolderId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
isFolderMode: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -213,6 +216,7 @@ const folderTreeData = computed(() => {
|
|||||||
watch(() => props.visible, (newVal) => {
|
watch(() => props.visible, (newVal) => {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
selectedFolderId.value = props.currentFolderId;
|
selectedFolderId.value = props.currentFolderId;
|
||||||
|
isFolderUpload.value = props.isFolderMode;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -21,21 +21,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-divider />
|
<a-menu-divider />
|
||||||
<a-menu-item key="docs" @click="openDocs">
|
<a-menu-item key="docs" @click="openDocs" :icon="h(BookOpen, { size: '16' })">
|
||||||
<BookOpen size="16"/>
|
|
||||||
<span class="menu-text">文档中心</span>
|
<span class="menu-text">文档中心</span>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="theme" @click="toggleTheme">
|
<a-menu-item key="theme" @click="toggleTheme" :icon="h(themeStore.isDark ? Sun : Moon, { size: '16' })">
|
||||||
<component :is="themeStore.isDark ? Sun : Moon" size="16"/>
|
|
||||||
<span class="menu-text">{{ themeStore.isDark ? '切换到浅色模式' : '切换到深色模式 (Beta)' }}</span>
|
<span class="menu-text">{{ themeStore.isDark ? '切换到浅色模式' : '切换到深色模式 (Beta)' }}</span>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-divider v-if="userStore.isAdmin"/>
|
<a-menu-divider v-if="userStore.isAdmin"/>
|
||||||
<a-menu-item v-if="userStore.isAdmin" key="setting" @click="goToSetting">
|
<a-menu-item v-if="userStore.isAdmin" key="setting" @click="goToSetting" :icon="h(Settings, { size: '16' })">
|
||||||
<Settings size="16"/>
|
|
||||||
<span class="menu-text">系统设置</span>
|
<span class="menu-text">系统设置</span>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
<a-menu-item key="logout" @click="logout">
|
<a-menu-item key="logout" @click="logout" :icon="h(LogOut, { size: '16' })">
|
||||||
<LogOut size="16"/>
|
|
||||||
<span class="menu-text">退出登录</span>
|
<span class="menu-text">退出登录</span>
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
</a-menu>
|
</a-menu>
|
||||||
@ -158,7 +154,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, inject } from 'vue';
|
import { computed, ref, inject, h } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useUserStore } from '@/stores/user';
|
import { useUserStore } from '@/stores/user';
|
||||||
//
|
//
|
||||||
|
|||||||
@ -10,7 +10,7 @@ export const useThemeStore = defineStore('theme', () => {
|
|||||||
const commonTheme = {
|
const commonTheme = {
|
||||||
token: {
|
token: {
|
||||||
fontFamily: "'HarmonyOS Sans SC', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;",
|
fontFamily: "'HarmonyOS Sans SC', Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;",
|
||||||
colorPrimary: '#1c7796',
|
colorPrimary: '#198cb2',
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
wireframe: false,
|
wireframe: false,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
v-model:visible="addFilesModalVisible"
|
v-model:visible="addFilesModalVisible"
|
||||||
:folder-tree="folderTree"
|
:folder-tree="folderTree"
|
||||||
:current-folder-id="currentFolderId"
|
:current-folder-id="currentFolderId"
|
||||||
|
:is-folder-mode="isFolderUploadMode"
|
||||||
@success="onFileUploadSuccess"
|
@success="onFileUploadSuccess"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -224,12 +225,15 @@ const openSearchConfigModal = () => {
|
|||||||
// 添加文件弹窗
|
// 添加文件弹窗
|
||||||
const addFilesModalVisible = ref(false);
|
const addFilesModalVisible = ref(false);
|
||||||
const currentFolderId = ref(null);
|
const currentFolderId = ref(null);
|
||||||
|
const isFolderUploadMode = ref(false);
|
||||||
|
|
||||||
// 标记是否是初次加载
|
// 标记是否是初次加载
|
||||||
const isInitialLoad = ref(true);
|
const isInitialLoad = ref(true);
|
||||||
|
|
||||||
// 显示添加文件弹窗
|
// 显示添加文件弹窗
|
||||||
const showAddFilesModal = () => {
|
const showAddFilesModal = (options = {}) => {
|
||||||
|
const { isFolder = false } = options;
|
||||||
|
isFolderUploadMode.value = isFolder;
|
||||||
addFilesModalVisible.value = true;
|
addFilesModalVisible.value = true;
|
||||||
currentFolderId.value = null; // 重置
|
currentFolderId.value = null; // 重置
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user