Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 文件列表组件新增创建文件夹功能 #5647

Merged
merged 1 commit into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/i18n/lang/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ ErrFileToLarge: "file is too large"
ErrPathNotFound: "Path is not found"
ErrMovePathFailed: "The target path cannot contain the original path!"
ErrLinkPathNotFound: "Target path does not exist!"
ErrFileIsExit: "File already exists!"
ErrFileIsExit: "File or directory already exists!"
ErrFileUpload: "Failed to upload file {{.name}} {{.detail}}"
ErrFileDownloadDir: "Download folder not supported"
ErrCmdNotFound: "{{ .name}} command does not exist, please install this command on the host first"
Expand Down Expand Up @@ -131,7 +131,7 @@ ErrLocalExist: "The local database already exists with that name, please modify
#redis
ErrTypeOfRedis: "The recovery file type does not match the current persistence mode. Modify the file type and try again"

#container
#container
ErrInUsed: "{{ .detail }} is in use and cannot be deleted"
ErrObjectInUsed: "This object is in use and cannot be deleted"
ErrPortRules: "The number of ports does not match, please re-enter!"
Expand Down
2 changes: 1 addition & 1 deletion backend/i18n/lang/zh-Hant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ ErrFileToLarge: "文件超過10M,無法打開"
ErrPathNotFound: "目錄不存在"
ErrMovePathFailed: "目標路徑不能包含原路徑!"
ErrLinkPathNotFound: "目標路徑不存在!"
ErrFileIsExit: "文件已存在!"
ErrFileIsExit: "文件或文件夾已存在!"
ErrFileUpload: "{{ .name }} 上傳文件失敗 {{ .detail}}"
ErrFileDownloadDir: "不支持下載文件夾"
ErrCmdNotFound: "{{ .name}} 命令不存在,請先在宿主機安裝此命令"
Expand Down
4 changes: 2 additions & 2 deletions backend/i18n/lang/zh.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ ErrFileToLarge: "文件超过10M,无法打开"
ErrPathNotFound: "目录不存在"
ErrMovePathFailed: "目标路径不能包含原路径!"
ErrLinkPathNotFound: "目标路径不存在!"
ErrFileIsExit: "文件已存在!"
ErrFileIsExit: "文件或文件夹已存在!"
ErrFileUpload: "{{ .name }} 上传文件失败 {{ .detail}}"
ErrFileDownloadDir: "不支持下载文件夹"
ErrCmdNotFound: "{{ .name}} 命令不存在,请先在宿主机安装此命令"
Expand Down Expand Up @@ -134,7 +134,7 @@ ErrLocalExist: "本地数据库已存在该名称,请修改后重试"
#redis
ErrTypeOfRedis: "恢复文件类型与当前持久化方式不符,请修改后重试"

#container
#container
ErrInUsed: "{{ .detail }} 正被使用,无法删除"
ErrObjectInUsed: "该对象正被使用,无法删除"
ErrPortRules: "端口数目不匹配,请重新输入!"
Expand Down
115 changes: 100 additions & 15 deletions frontend/src/components/file-list/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,19 @@
<template #default="{ row }">
<svg-icon v-if="row.isDir" className="table-icon" iconName="p-file-folder"></svg-icon>
<svg-icon v-else className="table-icon" iconName="p-file-normal"></svg-icon>
<el-link :underline="false" @click="open(row)">{{ row.name }}</el-link>
<el-link v-if="!row.isCreate" :underline="false" @click="open(row)">{{ row.name }}</el-link>
<el-input
v-else
ref="rowRefs"
v-model="newFlower"
style="width: 240px"
placeholder="new flower"
@input="handleChange(newFlower, row)"
>
<template #append>
<el-button :icon="Check" @click="createFlower(row)" />
</template>
</el-input>
</template>
</el-table-column>
</el-table>
Expand All @@ -83,29 +95,41 @@
</el-tag>
</el-tooltip>
</div>
<div class="button">
<el-button @click="closePage">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="selectFile">{{ $t('commons.button.confirm') }}</el-button>
<div class="flex items-center justify-between">
<el-button link @click="onAddRow" type="primary">
{{ $t('commons.button.create') }}
</el-button>
<div class="button">
<el-button @click="closePage">{{ $t('commons.button.cancel') }}</el-button>
<el-button type="primary" @click="selectFile" :disabled="disBtn">
{{ $t('commons.button.confirm') }}
</el-button>
</div>
</div>
</div>
</el-popover>
</template>

<script lang="ts" setup>
import { File } from '@/api/interface/file';
import { GetFilesList } from '@/api/modules/files';
import { Folder } from '@element-plus/icons-vue';
import { CreateFile, GetFilesList } from '@/api/modules/files';
import { Folder, Check, HomeFilled, Close } from '@element-plus/icons-vue';
import BreadCrumbs from '@/components/bread-crumbs/index.vue';
import BreadCrumbItem from '@/components/bread-crumbs/bread-crumbs-item.vue';
import { onMounted, onUpdated, reactive, ref } from 'vue';
import { onMounted, onUpdated, reactive, ref, nextTick } from 'vue';
import i18n from '@/lang';
import { MsgSuccess, MsgWarning } from '@/utils/message';

const rowName = ref('');
const data = ref();
const data = ref([]);
const loading = ref(false);
const paths = ref<string[]>([]);
const req = reactive({ path: '/', expand: true, page: 1, pageSize: 300, showHidden: true });
const selectRow = ref();
const rowRefs = ref();
const popoverVisible = ref(false);
const newFlower = ref();
const disBtn = ref(false);

const props = defineProps({
path: {
Expand All @@ -129,6 +153,7 @@ const props = defineProps({
const em = defineEmits(['choose']);

const checkFile = (row: any) => {
disBtn.value = row.isCreate;
selectRow.value = row;
rowName.value = selectRow.value.name;
};
Expand Down Expand Up @@ -170,21 +195,25 @@ const open = async (row: File.File) => {
} else {
req.path = req.path + '/' + name;
}
search(req);
await search(req);
}
selectRow.value = {};
rowName.value = '';
};

const jump = async (index: number) => {
let path = '/';
let path = '';
if (index != -1) {
const jPaths = paths.value.slice(0, index + 1);
for (let i in jPaths) {
path = path + '/' + jPaths[i];
if (index !== -1) {
const jPaths = paths.value.slice(0, index + 1);
path = '/' + jPaths.join('/');
}
}
path = path || '/';
req.path = path;
search(req);
selectRow.value = {};
rowName.value = '';
await search(req);
popoverVisible.value = true;
};

Expand All @@ -193,7 +222,7 @@ const search = async (req: File.ReqFile) => {
loading.value = true;
await GetFilesList(req)
.then((res) => {
data.value = res.data.items;
data.value = res.data.items || [];
req.path = res.data.path;
const pathArray = req.path.split('/');
paths.value = [];
Expand All @@ -208,6 +237,62 @@ const search = async (req: File.ReqFile) => {
});
};

let addForm = reactive({ path: '', name: '', isDir: true, mode: 0o755, isLink: false, isSymlink: true, linkPath: '' });

const onAddRow = async () => {
const createRow = data.value?.find((row: { isCreate: any }) => row.isCreate);
if (createRow) {
MsgWarning(i18n.global.t('commons.msg.creatingInfo'));
return;
}
newFlower.value = i18n.global.t('file.noNameFolder');
rowName.value = newFlower.value;
selectRow.value.name = newFlower.value;
const basePath = req.path === '/' ? req.path : `${req.path}/`;
selectRow.value.path = `${basePath}${newFlower.value}`;
data.value?.unshift({
path: selectRow.value.path,
isCreate: true,
isDir: true,
name: newFlower.value,
});
disBtn.value = true;
await nextTick();
rowRefs.value.focus();
};

const handleChange = (value: string, row: any) => {
if (rowName.value === row.name) {
selectRow.value.name = value;
rowName.value = value;
row.name = value;
const basePath = req.path === '/' ? req.path : `${req.path}/`;
selectRow.value.path = `${basePath}${value}`;
}
};

const createFlower = async (row: any) => {
const basePath = req.path === '/' ? req.path : `${req.path}/`;
addForm.path = `${basePath}${newFlower.value}`;
if (addForm.path.indexOf('.1panel_clash') > -1) {
MsgWarning(i18n.global.t('file.clashDitNotSupport'));
return;
}
addForm.name = newFlower.value;
let addItem = {};
Object.assign(addItem, addForm);
loading.value = true;
CreateFile(addItem as File.FileCreate)
.then(() => {
row.isCreate = false;
disBtn.value = false;
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
})
.finally(() => {
loading.value = false;
});
};

onMounted(() => {
if (props.path != '') {
req.path = props.path;
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const message = {
refreshSuccess: 'Refresh successful',
rootInfoErr: "It's already the root directory",
resetSuccess: 'Reset successful',
creatingInfo: 'Creating, no need for this operation',
},
login: {
username: 'UserName',
Expand Down Expand Up @@ -1249,6 +1250,7 @@ const message = {
saveContentAndClose: 'The file has been modified, do you want to save and close it?',
saveAndOpenNewFile: 'The file has been modified, do you want to save and open the new file?',
noEdit: 'The file has not been modified, no need to do this!',
noNameFolder: 'Untitled Folder',
},
ssh: {
autoStart: 'Auto Start',
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const message = {
refreshSuccess: '重繪成功',
rootInfoErr: '已經是根目錄了',
resetSuccess: '重置成功',
creatingInfo: '正在創建,無需此操作',
},
login: {
username: '用戶名',
Expand Down Expand Up @@ -1186,6 +1187,7 @@ const message = {
saveContentAndClose: '檔案已被修改,是否保存並關閉?',
saveAndOpenNewFile: '檔案已被修改,是否保存並打開新檔案?',
noEdit: '檔案未修改,無需此操作!',
noNameFolder: '未命名資料夾',
},
ssh: {
autoStart: '開機自啟',
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const message = {
refreshSuccess: '刷新成功',
rootInfoErr: '已经是根目录了',
resetSuccess: '重置成功',
creatingInfo: '正在创建,无需此操作',
},
login: {
username: '用户名',
Expand Down Expand Up @@ -1187,6 +1188,7 @@ const message = {
saveContentAndClose: '文件已被修改,是否保存并关闭?',
saveAndOpenNewFile: '文件已被修改,是否保存并打开新文件?',
noEdit: '文件未修改,无需此操作!',
noNameFolder: '未命名文件夹',
},
ssh: {
autoStart: '开机自启',
Expand Down
Loading