2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 11:27:17 +08:00

feat: 文件操作支持覆盖

This commit is contained in:
耗子
2024-10-27 01:00:02 +08:00
parent 42dd00c5ea
commit 658b6a79eb
4 changed files with 200 additions and 24 deletions

View File

@@ -175,7 +175,7 @@ func (s *FileService) Move(w http.ResponseWriter, r *http.Request) {
}
if io.Exists(req.Target) && !req.Force {
Error(w, http.StatusForbidden, "target path %s already exists", req.Target)
Error(w, http.StatusForbidden, "target path already exists") // no translate, frontend will use it to determine whether to continue
return
}
@@ -200,7 +200,7 @@ func (s *FileService) Copy(w http.ResponseWriter, r *http.Request) {
}
if io.Exists(req.Target) && !req.Force {
Error(w, http.StatusForbidden, "target path %s already exists", req.Target)
Error(w, http.StatusForbidden, "target path already exists") // no translate, frontend will use it to determine whether to continue
return
}

View File

@@ -1,6 +1,7 @@
import type { AxiosResponse } from 'axios'
import { request } from '@/utils'
import type { RequestConfig } from '~/types/axios'
export default {
// 创建文件/文件夹
@@ -25,11 +26,11 @@ export default {
})
},
// 移动文件
move: (source: string, target: string): Promise<AxiosResponse<any>> =>
request.post('/file/move', { source, target }),
move: (source: string, target: string, force: boolean): Promise<AxiosResponse<any>> =>
request.post('/file/move', { source, target, force }, { noNeedTip: true } as RequestConfig),
// 复制文件
copy: (source: string, target: string): Promise<AxiosResponse<any>> =>
request.post('/file/copy', { source, target }),
copy: (source: string, target: string, force: boolean): Promise<AxiosResponse<any>> =>
request.post('/file/copy', { source, target, force }, { noNeedTip: true } as RequestConfig),
// 远程下载
remoteDownload: (path: string, url: string): Promise<AxiosResponse<any>> =>
request.post('/file/remoteDownload', { path, url }),

View File

@@ -38,7 +38,7 @@ const unCompressModel = ref({
const options = computed<DropdownOption[]>(() => {
if (selectedRow.value == null) return []
return [
let options = [
{
label: selectedRow.value.dir ? '打开' : '编辑',
key: selectedRow.value.dir ? 'open' : 'edit'
@@ -59,6 +59,14 @@ const options = computed<DropdownOption[]>(() => {
{ label: '重命名', key: 'rename' },
{ label: () => h('span', { style: { color: 'red' } }, '删除'), key: 'delete' }
]
if (marked.value.length) {
options.unshift({
label: '粘贴',
key: 'paste'
})
}
return options
})
const columns: DataTableColumns<RowData> = [
@@ -385,11 +393,43 @@ const handleRename = () => {
return
}
file.move(source, target).then(() => {
window.$message.success('重命名成功')
renameModal.value = false
window.$bus.emit('file:refresh')
})
file
.move(source, target, false)
.then(() => {
window.$message.success(
`重命名 ${renameModel.value.source}${renameModel.value.target} 成功`
)
renameModal.value = false
window.$bus.emit('file:refresh')
})
.catch((err) => {
if (err.message == 'target path already exists') {
window.$dialog.warning({
title: '警告',
content: `存在同名项,是否强制覆盖?`,
positiveText: '覆盖',
negativeText: '取消',
onPositiveClick: () => {
file
.move(source, target, true)
.then(() => {
window.$message.success(
`重命名 ${renameModel.value.source}${renameModel.value.target} 成功`
)
renameModal.value = false
window.$bus.emit('file:refresh')
})
.catch((err) => {
window.$message.error(err.message)
})
},
onNegativeClick: () => {
renameModal.value = false
window.$bus.emit('file:refresh')
}
})
}
})
}
const handleUnCompress = () => {
@@ -422,8 +462,89 @@ const onChecked = (rowKeys: any) => {
selected.value = rowKeys
}
const handlePaste = async () => {
if (!marked.value.length) {
window.$message.error('请先标记需要复制或移动的文件/文件夹')
return
}
for (const { name, source, type } of marked.value) {
const target = path.value + '/' + name
if (type === 'copy') {
file
.copy(source, target, false)
.then(() => {
window.$message.success(`复制 ${source}${target} 成功`)
})
.catch((err) => {
if (err.message == 'target path already exists') {
window.$dialog.warning({
title: '警告',
content: `目标 ${target} 已存在,是否覆盖?`,
positiveText: '覆盖',
negativeText: '取消',
onPositiveClick: () => {
file
.copy(source, target, true)
.then(() => {
window.$message.success(`复制 ${source}${target} 成功`)
})
.catch((err) => {
window.$message.error(err.message)
})
},
onNegativeClick: () => {
marked.value = []
}
})
}
})
.finally(() => {
window.$bus.emit('file:refresh')
})
} else {
file
.move(source, target, false)
.then(() => {
window.$message.success(`移动 ${source}${target} 成功`)
})
.catch((err) => {
if (err.message == 'target path already exists') {
window.$dialog.warning({
title: '警告',
content: `目标 ${target} 已存在,是否覆盖?`,
positiveText: '覆盖',
negativeText: '取消',
onPositiveClick: () => {
file
.move(source, target, true)
.then(() => {
window.$message.success(`移动 ${source}${target} 成功`)
})
.catch((err) => {
window.$message.error(err.message)
})
},
onNegativeClick: () => {
marked.value = []
}
})
}
})
.finally(() => {
window.$bus.emit('file:refresh')
})
}
}
marked.value = []
}
const handleSelect = (key: string) => {
switch (key) {
case 'paste':
handlePaste()
break
case 'open':
path.value = selectedRow.value.full
break

View File

@@ -83,6 +83,10 @@ const handleMove = () => {
window.$message.success('标记成功,请前往目标路径粘贴')
}
const handleCancel = () => {
marked.value = []
}
const handlePaste = async () => {
if (!marked.value.length) {
window.$message.error('请先标记需要复制或移动的文件/文件夹')
@@ -92,25 +96,75 @@ const handlePaste = async () => {
for (const { name, source, type } of marked.value) {
const target = path.value + '/' + name
if (type === 'copy') {
await file.copy(source, target).then(() => {
window.$message.success(`复制 ${source}${target} 成功`)
window.$bus.emit('file:refresh')
})
file
.copy(source, target, false)
.then(() => {
window.$message.success(`复制 ${source}${target} 成功`)
})
.catch((err) => {
if (err.message == 'target path already exists') {
window.$dialog.warning({
title: '警告',
content: `目标 ${target} 已存在,是否覆盖?`,
positiveText: '覆盖',
negativeText: '取消',
onPositiveClick: () => {
file
.copy(source, target, true)
.then(() => {
window.$message.success(`复制 ${source}${target} 成功`)
})
.catch((err) => {
window.$message.error(err.message)
})
},
onNegativeClick: () => {
handleCancel()
}
})
}
})
.finally(() => {
window.$bus.emit('file:refresh')
})
} else {
await file.move(source, target).then(() => {
window.$message.success(`移动 ${source}${target} 成功`)
window.$bus.emit('file:refresh')
})
file
.move(source, target, false)
.then(() => {
window.$message.success(`移动 ${source}${target} 成功`)
})
.catch((err) => {
if (err.message == 'target path already exists') {
window.$dialog.warning({
title: '警告',
content: `目标 ${target} 已存在,是否覆盖?`,
positiveText: '覆盖',
negativeText: '取消',
onPositiveClick: () => {
file
.move(source, target, true)
.then(() => {
window.$message.success(`移动 ${source}${target} 成功`)
})
.catch((err) => {
window.$message.error(err.message)
})
},
onNegativeClick: () => {
handleCancel()
}
})
}
})
.finally(() => {
window.$bus.emit('file:refresh')
})
}
}
marked.value = []
}
const handleCancel = () => {
marked.value = []
}
const bulkDelete = () => {
if (!selected.value.length) {
window.$message.error('请选择要删除的文件/文件夹')