feat(文件管理): 文件管理部分接口&部分组件调整
This commit is contained in:
parent
289464050c
commit
7680537fc6
|
@ -95,6 +95,7 @@ module.exports = {
|
|||
'^jsencrypt$',
|
||||
'^echarts$',
|
||||
'^color$',
|
||||
'^localforage$',
|
||||
], // node依赖
|
||||
['.*/assets/.*', '^@/assets$'], // 项目静态资源
|
||||
['^@/components/pure/.*', '^@/components/business/.*', '.*\\.vue$'], // 组件
|
||||
|
|
|
@ -2,6 +2,7 @@ import MSR from '@/api/http/index';
|
|||
import {
|
||||
AddModuleUrl,
|
||||
BatchDownloadFileUrl,
|
||||
BatchMoveFileUrl,
|
||||
DeleteFileUrl,
|
||||
DeleteModuleUrl,
|
||||
DownloadFileUrl,
|
||||
|
@ -113,3 +114,8 @@ export function getFileDetail(id: string) {
|
|||
export function toggleJarFileStatus(id: string, status: boolean) {
|
||||
return MSR.get({ url: `${ToggleJarFileUrl}/${id}/${status}` });
|
||||
}
|
||||
|
||||
// 批量移动文件
|
||||
export function batchMoveFile(data: BatchFileApiParams) {
|
||||
return MSR.post({ url: BatchMoveFileUrl, data });
|
||||
}
|
||||
|
|
|
@ -16,3 +16,4 @@ export const CompressImgUrl = '/file/preview/compressed'; // 预览图片文件
|
|||
export const GetFileTypesUrl = '/project/file/type'; // 获取文件类型集合
|
||||
export const GetFileDetailUrl = '/project/file/get'; // 查看文件详情
|
||||
export const ToggleJarFileUrl = '/project/file/jar-file-status'; // jar 文件启用禁用
|
||||
export const BatchMoveFileUrl = '/project/file/batch-move'; // jar 文件启用禁用
|
||||
|
|
|
@ -532,52 +532,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
/** 穿梭框 **/
|
||||
.arco-transfer {
|
||||
@apply grid;
|
||||
|
||||
grid-template-columns: 4fr 1fr 4fr;
|
||||
.arco-transfer-view {
|
||||
@apply w-auto;
|
||||
|
||||
height: 370px;
|
||||
.arco-transfer-view-header {
|
||||
@apply bg-white;
|
||||
}
|
||||
}
|
||||
.arco-transfer-operations {
|
||||
.arco-btn-secondary {
|
||||
border-color: rgb(var(--primary-5));
|
||||
border-radius: var(--border-radius-small);
|
||||
background-color: rgb(var(--primary-1)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-5));
|
||||
}
|
||||
&:disabled {
|
||||
border-color: var(--color-text-input-border) !important;
|
||||
background-color: var(--color-text-n8) !important;
|
||||
.arco-btn-icon {
|
||||
color: var(--color-text-4);
|
||||
}
|
||||
}
|
||||
&:not(:disabled):hover {
|
||||
border-color: rgb(var(--primary-4)) !important;
|
||||
background-color: rgb(var(--primary-1)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-7));
|
||||
}
|
||||
}
|
||||
&:not(:disabled):active {
|
||||
border-color: rgb(var(--primary-7)) !important;
|
||||
background-color: rgb(var(--primary-9)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-7));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 滚动条 **/
|
||||
.arco-scrollbar-track-direction-horizontal {
|
||||
height: 6px;
|
||||
|
@ -768,22 +722,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
/** 穿梭框节点溢出省略 **/
|
||||
.arco-transfer {
|
||||
.arco-tree-node-title-text {
|
||||
overflow: hidden;
|
||||
width: 206px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.arco-checkbox-label {
|
||||
overflow: hidden;
|
||||
width: 207px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
/** Alter **/
|
||||
.arco-alert-title {
|
||||
font-size: 14px;
|
||||
|
|
|
@ -20,7 +20,13 @@
|
|||
block-node
|
||||
default-expand-all
|
||||
@check="onSelect"
|
||||
/>
|
||||
>
|
||||
<template #title="nodeData">
|
||||
<div class="one-line-text">
|
||||
{{ nodeData.title }}
|
||||
</div>
|
||||
</template>
|
||||
</MsTree>
|
||||
</template>
|
||||
</a-transfer>
|
||||
</template>
|
||||
|
@ -45,6 +51,7 @@
|
|||
data: MsTreeNodeData[]; // 树结构数据
|
||||
treeFiled?: MsTreeFieldNames; // 自定义树结构字段
|
||||
showSearch?: boolean; // 是否显示搜索框
|
||||
height?: string; // 穿梭框高度
|
||||
sourceInputSearchProps?: Record<string, any>;
|
||||
targetInputSearchProps?: Record<string, any>;
|
||||
}>(),
|
||||
|
@ -139,4 +146,46 @@
|
|||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less">
|
||||
/** 穿梭框 **/
|
||||
.arco-transfer {
|
||||
.arco-transfer-view {
|
||||
width: calc(50% - 34px);
|
||||
height: v-bind(height);
|
||||
.arco-transfer-view-header {
|
||||
@apply bg-white;
|
||||
}
|
||||
}
|
||||
.arco-transfer-operations {
|
||||
.arco-btn-secondary {
|
||||
border-color: rgb(var(--primary-5));
|
||||
border-radius: var(--border-radius-small);
|
||||
background-color: rgb(var(--primary-1)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-5));
|
||||
}
|
||||
&:disabled {
|
||||
border-color: var(--color-text-input-border) !important;
|
||||
background-color: var(--color-text-n8) !important;
|
||||
.arco-btn-icon {
|
||||
color: var(--color-text-4);
|
||||
}
|
||||
}
|
||||
&:not(:disabled):hover {
|
||||
border-color: rgb(var(--primary-4)) !important;
|
||||
background-color: rgb(var(--primary-1)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-7));
|
||||
}
|
||||
}
|
||||
&:not(:disabled):active {
|
||||
border-color: rgb(var(--primary-7)) !important;
|
||||
background-color: rgb(var(--primary-9)) !important;
|
||||
.arco-btn-icon {
|
||||
color: rgb(var(--primary-7));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -13,7 +13,13 @@
|
|||
@check="checked"
|
||||
>
|
||||
<template v-if="$slots['title']" #title="_props">
|
||||
<slot name="title" v-bind="_props"></slot>
|
||||
<a-tooltip
|
||||
:content="_props[props.fieldNames.title]"
|
||||
:mouse-enter-delay="500"
|
||||
:position="props.titleTooltipPosition"
|
||||
>
|
||||
<slot name="title" v-bind="_props"></slot>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="$slots['extra']" #extra="_props">
|
||||
<div
|
||||
|
@ -92,11 +98,26 @@
|
|||
checkedStrategy?: 'all' | 'parent' | 'child'; // 选中节点时的策略
|
||||
checkedKeys?: Array<string | number>; // 选中的节点 key
|
||||
virtualListProps?: Record<string, unknown>; // 虚拟滚动列表的属性
|
||||
titleTooltipPosition?:
|
||||
| 'top'
|
||||
| 'tl'
|
||||
| 'tr'
|
||||
| 'bottom'
|
||||
| 'bl'
|
||||
| 'br'
|
||||
| 'left'
|
||||
| 'lt'
|
||||
| 'lb'
|
||||
| 'right'
|
||||
| 'rt'
|
||||
| 'rb'; // 标题 tooltip 的位置
|
||||
}>(),
|
||||
{
|
||||
searchDebounce: 300,
|
||||
defaultExpandAll: false,
|
||||
selectable: true,
|
||||
draggable: false,
|
||||
titleTooltipPosition: 'right',
|
||||
fieldNames: () => ({
|
||||
key: 'key',
|
||||
title: 'title',
|
||||
|
@ -401,6 +422,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.arco-tree-node-title-block {
|
||||
width: 80%;
|
||||
}
|
||||
.ms-tree-node-extra {
|
||||
@apply relative hidden;
|
||||
&:hover {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { filter, orderBy, sortBy } from 'lodash-es';
|
||||
import localforage from 'localforage';
|
||||
|
||||
import { MsTableColumn, MsTableColumnData } from '@/components/pure/ms-table/type';
|
||||
|
||||
|
@ -8,8 +9,6 @@ import { isArraysEqualWithOrder } from '@/utils/equal';
|
|||
|
||||
import { SpecialColumnEnum } from '@/enums/tableEnum';
|
||||
|
||||
import localforage from 'localforage';
|
||||
|
||||
export default function useTableStore() {
|
||||
const state = reactive({
|
||||
baseSortIndex: 10,
|
||||
|
|
|
@ -59,6 +59,7 @@ export interface BatchFileApiParams extends BatchApiParams {
|
|||
projectId: string;
|
||||
fileType: string;
|
||||
moduleIds: string[];
|
||||
moveModuleId?: string | number; // 移动的模块ID
|
||||
}
|
||||
// 更新模块参数
|
||||
export interface UpdateModuleParams {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
count: 'count',
|
||||
}"
|
||||
block-node
|
||||
title-tooltip-position="left"
|
||||
@select="folderNodeSelect"
|
||||
@more-action-select="handleFolderMoreSelect"
|
||||
@more-actions-close="moreActionsClose"
|
||||
|
@ -30,9 +31,7 @@
|
|||
>
|
||||
<template #title="nodeData">
|
||||
<div class="inline-flex w-full">
|
||||
<a-tooltip :content="nodeData.name" :mouse-enter-delay="300" position="left">
|
||||
<div class="one-line-text w-[calc(100%-32px)] text-[var(--color-text-1)]">{{ nodeData.name }}</div>
|
||||
</a-tooltip>
|
||||
<div class="one-line-text w-[calc(100%-32px)] text-[var(--color-text-1)]">{{ nodeData.name }}</div>
|
||||
<div v-if="!props.isModal" class="ml-[4px] text-[var(--color-text-4)]">({{ nodeData.count || 0 }})</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -162,7 +161,7 @@
|
|||
folderTree.value = res.map((e) => ({
|
||||
...e,
|
||||
hideMoreAction: e.id === 'root',
|
||||
draggable: e.id !== 'root',
|
||||
draggable: e.id !== 'root' && !props.isModal,
|
||||
}));
|
||||
if (isSetDefaultKey) {
|
||||
selectedKeys.value = [folderTree.value[0].id];
|
||||
|
|
|
@ -234,7 +234,7 @@
|
|||
:ok-text="t('project.fileManagement.batchMoveConfirm')"
|
||||
:ok-button-props="{ disabled: selectedModuleKeys.length === 0 }"
|
||||
:cancel-button-props="{ disabled: batchMoveFileLoading }"
|
||||
:on-before-ok="batchMoveFile"
|
||||
:on-before-ok="handleFileMove"
|
||||
@close="handleMoveFileModalCancel"
|
||||
>
|
||||
<template #title>
|
||||
|
@ -292,6 +292,7 @@
|
|||
|
||||
import {
|
||||
batchDownloadFile,
|
||||
batchMoveFile,
|
||||
deleteFile,
|
||||
downloadFile,
|
||||
getFileList,
|
||||
|
@ -341,6 +342,9 @@
|
|||
const tableFileTypeOptions = ref<string[]>([]);
|
||||
const fileTypeLoading = ref(false);
|
||||
|
||||
/**
|
||||
* 初始化文件类型筛选选项
|
||||
*/
|
||||
async function initFileTypes() {
|
||||
try {
|
||||
fileTypeLoading.value = true;
|
||||
|
@ -464,7 +468,6 @@
|
|||
tableStore.initColumn(TableKeyEnum.FILE_MANAGEMENT_FILE, columns, 'drawer');
|
||||
const { propsRes, propsEvent, loadList, setLoadListParams } = useTable(getFileList, {
|
||||
tableKey: TableKeyEnum.FILE_MANAGEMENT_FILE,
|
||||
columns,
|
||||
showSetting: true,
|
||||
selectable: true,
|
||||
showSelectAll: true,
|
||||
|
@ -500,6 +503,13 @@
|
|||
],
|
||||
};
|
||||
const tableSelected = ref<(string | number)[]>([]);
|
||||
const batchParams = ref<BatchActionQueryParams>({
|
||||
selectedIds: [],
|
||||
selectAll: false,
|
||||
excludeIds: [],
|
||||
currentSelectCount: 0,
|
||||
});
|
||||
const combine = ref<Record<string, any>>({});
|
||||
|
||||
/**
|
||||
* 处理表格选中
|
||||
|
@ -510,16 +520,15 @@
|
|||
|
||||
/**
|
||||
* 批量下载文件
|
||||
* @param params 批量操作参数
|
||||
*/
|
||||
async function batchDownload(params: BatchActionQueryParams) {
|
||||
async function batchDownload() {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await batchDownloadFile({
|
||||
selectIds: params?.selectedIds || [],
|
||||
selectAll: !!params?.selectAll,
|
||||
excludeIds: params?.excludeIds || [],
|
||||
condition: { keyword: keyword.value },
|
||||
selectIds: batchParams.value?.selectedIds || [],
|
||||
selectAll: !!batchParams.value?.selectAll,
|
||||
excludeIds: batchParams.value?.excludeIds || [],
|
||||
condition: { keyword: keyword.value, comebine: combine.value },
|
||||
projectId: appStore.currentProjectId,
|
||||
fileType: tableFileType.value,
|
||||
moduleIds: [props.activeFolder],
|
||||
|
@ -555,14 +564,14 @@
|
|||
/**
|
||||
* 删除文件
|
||||
*/
|
||||
function delFile(record: FileItem | null, isBatch: boolean, params?: BatchActionQueryParams) {
|
||||
function delFile(record: FileItem | null, isBatch: boolean) {
|
||||
let title = t('project.fileManagement.deleteFileTipTitle', { name: characterLimit(record?.name) });
|
||||
let selectIds = [record?.id || ''];
|
||||
if (isBatch) {
|
||||
title = t('project.fileManagement.batchDeleteFileTipTitle', {
|
||||
count: params?.currentSelectCount || params?.selectedIds?.length,
|
||||
count: batchParams.value?.currentSelectCount || batchParams.value?.selectedIds?.length,
|
||||
});
|
||||
selectIds = params?.selectedIds || [];
|
||||
selectIds = batchParams.value?.selectedIds || [];
|
||||
}
|
||||
openModal({
|
||||
type: 'error',
|
||||
|
@ -578,9 +587,9 @@
|
|||
try {
|
||||
await deleteFile({
|
||||
selectIds,
|
||||
selectAll: !!params?.selectAll,
|
||||
excludeIds: params?.excludeIds || [],
|
||||
condition: { keyword: keyword.value },
|
||||
selectAll: !!batchParams.value?.selectAll,
|
||||
excludeIds: batchParams.value?.excludeIds || [],
|
||||
condition: { keyword: keyword.value, comebine: combine.value },
|
||||
projectId: appStore.currentProjectId,
|
||||
fileType: tableFileType.value,
|
||||
moduleIds: [props.activeFolder],
|
||||
|
@ -619,16 +628,17 @@
|
|||
*/
|
||||
function handleTableBatch(event: BatchActionParams, params: BatchActionQueryParams) {
|
||||
tableSelected.value = params?.selectedIds || [];
|
||||
batchParams.value = params;
|
||||
switch (event.eventTag) {
|
||||
case 'download':
|
||||
batchDownload(params);
|
||||
batchDownload();
|
||||
break;
|
||||
case 'move':
|
||||
moveModalVisible.value = true;
|
||||
isBatchMove.value = true;
|
||||
break;
|
||||
case 'delete':
|
||||
delFile(null, true, params);
|
||||
delFile(null, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -639,11 +649,18 @@
|
|||
/**
|
||||
* 单个/批量移动文件
|
||||
*/
|
||||
async function batchMoveFile() {
|
||||
async function handleFileMove() {
|
||||
try {
|
||||
batchMoveFileLoading.value = true;
|
||||
await new Promise((resolve) => {
|
||||
setTimeout(() => resolve(true), 2000);
|
||||
await batchMoveFile({
|
||||
selectIds: batchParams.value?.selectedIds || [activeFile.value?.id || ''],
|
||||
selectAll: !!batchParams.value?.selectAll,
|
||||
excludeIds: batchParams.value?.excludeIds || [],
|
||||
condition: { keyword: keyword.value, comebine: combine.value },
|
||||
projectId: appStore.currentProjectId,
|
||||
fileType: tableFileType.value,
|
||||
moduleIds: [props.activeFolder],
|
||||
moveModuleId: selectedModuleKeys.value[0],
|
||||
});
|
||||
Message.success(t('project.fileManagement.batchMoveSuccess'));
|
||||
if (isBatchMove.value) {
|
||||
|
@ -672,19 +689,18 @@
|
|||
}
|
||||
|
||||
function setTableParams() {
|
||||
const combine: Record<string, any> = {};
|
||||
if (props.activeFolder === 'my') {
|
||||
combine.createUser = userStore.id;
|
||||
combine.value.createUser = userStore.id;
|
||||
}
|
||||
if (fileType.value === 'storage') {
|
||||
combine.storage = 'git';
|
||||
combine.value.storage = 'git';
|
||||
}
|
||||
setLoadListParams({
|
||||
keyword: keyword.value,
|
||||
fileType: tableFileType.value,
|
||||
moduleIds: ['all', 'my'].includes(props.activeFolder) ? [] : [props.activeFolder],
|
||||
projectId: appStore.currentProjectId,
|
||||
comebine: combine,
|
||||
comebine: combine.value,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -885,6 +901,9 @@
|
|||
isUploading.value = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消上传二次确认
|
||||
*/
|
||||
function cancelUpload() {
|
||||
if (asyncTaskStore.uploadFileTask.eachTaskQueue.length > 0 && asyncTaskStore.eachUploadTaskProgress !== 100) {
|
||||
openModal({
|
||||
|
|
|
@ -4,7 +4,7 @@ export default {
|
|||
'project.fileManagement.defaultFile': 'Default files',
|
||||
'project.fileManagement.expandAll': 'Expand all submodules',
|
||||
'project.fileManagement.collapseAll': 'Collapse all submodules',
|
||||
'project.fileManagement.addSubModule': 'Add module',
|
||||
'project.fileManagement.addSubModule': 'Add submodule',
|
||||
'project.fileManagement.addStorage': 'Add repository',
|
||||
'project.fileManagement.rename': 'Rename',
|
||||
'project.fileManagement.nameNotNull': 'name cannot be empty',
|
||||
|
|
|
@ -4,7 +4,7 @@ export default {
|
|||
'project.fileManagement.defaultFile': '默认文件',
|
||||
'project.fileManagement.expandAll': '展开全部子模块',
|
||||
'project.fileManagement.collapseAll': '收起全部子模块',
|
||||
'project.fileManagement.addSubModule': '添加模块',
|
||||
'project.fileManagement.addSubModule': '添加子模块',
|
||||
'project.fileManagement.addStorage': '添加存储库',
|
||||
'project.fileManagement.rename': '重命名',
|
||||
'project.fileManagement.nameNotNull': '名字不能为空',
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
}}
|
||||
</div>
|
||||
</template>
|
||||
<a-spin :loading="loading">
|
||||
<a-spin class="w-full" :loading="loading">
|
||||
<a-alert v-if="batchModalMode === 'project'" class="mb-[16px]">
|
||||
{{ t('system.user.batchModalTip') }}
|
||||
</a-alert>
|
||||
|
@ -26,6 +26,7 @@
|
|||
children: 'children',
|
||||
disabled: 'disabled',
|
||||
}"
|
||||
height="370px"
|
||||
show-search
|
||||
/>
|
||||
</a-spin>
|
||||
|
|
Loading…
Reference in New Issue