mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 07:57:21 +08:00
feat: alova.js替换axios
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
"gen-auto-import": "tsx gen-auto-import.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alova/adapter-xhr": "^2.1.1",
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.1.1",
|
||||
"@guolao/vue-monaco-editor": "^1.5.4",
|
||||
|
||||
29
web/pnpm-lock.yaml
generated
29
web/pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@alova/adapter-xhr':
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1(alova@3.2.8)
|
||||
'@eslint/eslintrc':
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.0
|
||||
@@ -207,6 +210,11 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@alova/adapter-xhr@2.1.1':
|
||||
resolution: {integrity: sha512-053tY4wVEL5PUX8HwvFrp/y1wTObGjMvwVBLUVSOcZKuZwcoUraWdQoWAdNRnSWfwJoPEd+ta9EdS4KPqTcz9g==}
|
||||
peerDependencies:
|
||||
alova: ^3.0.20
|
||||
|
||||
'@alova/shared@1.1.2':
|
||||
resolution: {integrity: sha512-8q/gMHFpzm7XYcaUlsyTCMDRRhFnewwheTeObMjPl1+bFdr+wZuBEHEPYIyd8tyzLwfrqpBeonaMN2tlngM8EA==}
|
||||
|
||||
@@ -989,36 +997,42 @@ packages:
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@parcel/watcher-win32-arm64@2.5.1':
|
||||
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||
@@ -1096,51 +1110,61 @@ packages:
|
||||
resolution: {integrity: sha512-MW6N3AoC61OfE1VgnN5O1OW0gt8VTbhx9s/ZEPLBM11wEdHjeilPzOxVmmsrx5YmejpGPvez8QwGGvMU+pGxpw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.34.3':
|
||||
resolution: {integrity: sha512-2SQkhr5xvatYq0/+H6qyW0zvrQz9LM4lxGkpWURLoQX5+yP8MsERh4uWmxFohOvwCP6l/+wgiHZ1qVwLDc7Qmw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-R3JLYt8YoRwKI5shJsovLpcR6pwIMui/MGG/MmxZ1DYI3iRSKI4qcYrvYgDf4Ss2oCR3RL3F3dYK7uAGQgMIuQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.34.3':
|
||||
resolution: {integrity: sha512-4XQhG8v/t3S7Rxs7rmFUuM6j09hVrTArzONS3fUZ6oBRSN/ps9IPQjVhp62P0W3KhqJdQADo/MRlYRMdgxr/3w==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loongarch64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-QlW1jCUZ1LHUIYCAK2FciVw1ptHsxzApYVi05q7bz2A8oNE8QxQ85NhM4arLxkAlcnS42t4avJbSfzSQwbIaKg==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-powerpc64le-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-kMbLToizVeCcN69+nnm20Dh0hrRIAjgaaL+Wh0gWZcNt8e542d2FUGtsyuNsHVNNF3gqTJrpzUGIdwMGLEUM7g==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-YgD0DnZ3CHtvXRH8rzjVSxwI0kMTr0RQt3o1N92RwxGdx7YejzbBO0ELlSU48DP96u1gYYVWfUhDRyaGNqJqJg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-dIOoOz8altjp6UjAi3U9EW99s8nta4gzi52FeI45GlPyrUH4QixUoBMH9VsVjt+9A2RiZBWyjYNHlJ/HmJOBCQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.34.3':
|
||||
resolution: {integrity: sha512-lOyG3aF4FTKrhpzXfMmBXgeKUUXdAWmP2zSNf8HTAXPqZay6QYT26l64hVizBjq+hJx3pl0DTEyvPi9sTA6VGA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.34.3':
|
||||
resolution: {integrity: sha512-usztyYLu2i+mYzzOjqHZTaRXbUOqw3P6laNUh1zcqxbPH1P2Tz/QdJJCQSnGxCtsRQeuU2bCyraGMtMumC46rw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.34.3':
|
||||
resolution: {integrity: sha512-ojFOKaz/ZyalIrizdBq2vyc2f0kFbJahEznfZlxdB6pF9Do6++i1zS5Gy6QLf8D7/S57MHrmBLur6AeRYeQXSA==}
|
||||
@@ -3732,6 +3756,11 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@alova/adapter-xhr@2.1.1(alova@3.2.8)':
|
||||
dependencies:
|
||||
'@alova/shared': 1.1.2
|
||||
alova: 3.2.8
|
||||
|
||||
'@alova/shared@1.1.2': {}
|
||||
|
||||
'@ampproject/remapping@2.3.0':
|
||||
|
||||
@@ -1,47 +1,39 @@
|
||||
import { request } from '@/utils'
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 创建文件/文件夹
|
||||
create: (path: string, dir: boolean): any => request.post('/file/create', { path, dir }),
|
||||
create: (path: string, dir: boolean): any => http.Post('/file/create', { path, dir }),
|
||||
// 获取文件内容
|
||||
content: (path: string): any => request.get('/file/content', { params: { path } }),
|
||||
content: (path: string): any => http.Get('/file/content', { params: { path } }),
|
||||
// 保存文件
|
||||
save: (path: string, content: string): any => request.post('/file/save', { path, content }),
|
||||
save: (path: string, content: string): any => http.Post('/file/save', { path, content }),
|
||||
// 删除文件
|
||||
delete: (path: string): any => request.post('/file/delete', { path }),
|
||||
delete: (path: string): any => http.Post('/file/delete', { path }),
|
||||
// 上传文件
|
||||
upload: (path: string, formData: FormData, onProgress: any): any => {
|
||||
formData.append('path', path)
|
||||
return request.post('/file/upload', formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
onProgress({ percent: Math.ceil((progressEvent.loaded / progressEvent.total) * 100) })
|
||||
}
|
||||
})
|
||||
},
|
||||
upload: (formData: FormData): any => http.Post('/file/upload', formData),
|
||||
// 检查文件是否存在
|
||||
exist: (paths: string[]): any => request.post('/file/exist', paths),
|
||||
exist: (paths: string[]): any => http.Post('/file/exist', paths),
|
||||
// 移动文件
|
||||
move: (paths: any[]): any => request.post('/file/move', paths),
|
||||
move: (paths: any[]): any => http.Post('/file/move', paths),
|
||||
// 复制文件
|
||||
copy: (paths: any[]): any => request.post('/file/copy', paths),
|
||||
copy: (paths: any[]): any => http.Post('/file/copy', paths),
|
||||
// 远程下载
|
||||
remoteDownload: (path: string, url: string): any =>
|
||||
request.post('/file/remoteDownload', { path, url }),
|
||||
http.Post('/file/remoteDownload', { path, url }),
|
||||
// 获取文件信息
|
||||
info: (path: string): any => request.get('/file/info', { params: { path } }),
|
||||
info: (path: string): any => http.Get('/file/info', { params: { path } }),
|
||||
// 修改文件权限
|
||||
permission: (path: string, mode: string, owner: string, group: string): any =>
|
||||
request.post('/file/permission', { path, mode, owner, group }),
|
||||
http.Post('/file/permission', { path, mode, owner, group }),
|
||||
// 压缩文件
|
||||
compress: (dir: string, paths: string[], file: string): any =>
|
||||
request.post('/file/compress', { dir, paths, file }),
|
||||
http.Post('/file/compress', { dir, paths, file }),
|
||||
// 解压文件
|
||||
unCompress: (file: string, path: string): any => request.post('/file/unCompress', { file, path }),
|
||||
unCompress: (file: string, path: string): any => http.Post('/file/unCompress', { file, path }),
|
||||
// 搜索文件
|
||||
search: (path: string, keyword: string, sub: boolean, page: number, limit: number): any =>
|
||||
request.get('/file/search', { params: { path, keyword, sub, page, limit } }),
|
||||
http.Get('/file/search', { params: { path, keyword, sub, page, limit } }),
|
||||
// 获取文件列表
|
||||
list: (path: string, page: number, limit: number, sort: string): any =>
|
||||
request.get('/file/list', { params: { path, page, limit, sort } })
|
||||
http.Get('/file/list', { params: { path, page, limit, sort } })
|
||||
}
|
||||
|
||||
@@ -18,25 +18,25 @@ const props = defineProps({
|
||||
const disabled = ref(false) // 在出现错误的情况下禁用保存
|
||||
const data = ref('')
|
||||
|
||||
const get = async () => {
|
||||
await file
|
||||
.content(props.path)
|
||||
.then((res) => {
|
||||
data.value = decodeBase64(res.data.content)
|
||||
const get = () => {
|
||||
useRequest(file.content(props.path))
|
||||
.onSuccess(({ data }) => {
|
||||
data.value = decodeBase64(data.content)
|
||||
window.$message.success('获取成功')
|
||||
})
|
||||
.catch(() => {
|
||||
.onError(() => {
|
||||
disabled.value = true
|
||||
})
|
||||
}
|
||||
|
||||
const save = async () => {
|
||||
const save = () => {
|
||||
if (disabled.value) {
|
||||
window.$message.error('当前状态下不可保存')
|
||||
return
|
||||
}
|
||||
await file.save(props.path, data.value)
|
||||
window.$message.success('保存成功')
|
||||
useRequest(file.save(props.path, data.value)).onSuccess(() => {
|
||||
window.$message.success('保存成功')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { resolveResError } from '@/utils/http/helpers'
|
||||
import type { AlovaXHRResponse } from '@alova/adapter-xhr'
|
||||
import { xhrRequestAdapter } from '@alova/adapter-xhr'
|
||||
import { createAlova, Method } from 'alova'
|
||||
import adapterFetch from 'alova/fetch'
|
||||
import VueHook from 'alova/vue'
|
||||
import axios from 'axios'
|
||||
import { reqReject, reqResolve, resReject, resResolve } from './interceptors'
|
||||
@@ -27,15 +28,21 @@ export const http = createAlova({
|
||||
id: 'panel',
|
||||
cacheFor: null,
|
||||
statesHook: VueHook,
|
||||
requestAdapter: adapterFetch(),
|
||||
requestAdapter: xhrRequestAdapter(),
|
||||
baseURL: import.meta.env.VITE_BASE_API,
|
||||
responded: {
|
||||
onSuccess: async (response: Response, method: Method) => {
|
||||
const ct = response.headers.get('Content-Type')
|
||||
const json =
|
||||
ct && ct.includes('application/json')
|
||||
? await response.json()
|
||||
: { code: response.status, message: await response.text() }
|
||||
onSuccess: async (response: AlovaXHRResponse, method: Method) => {
|
||||
const ct = response.headers['Content-Type'] || response.headers['content-type']
|
||||
let json
|
||||
try {
|
||||
if (ct && ct.includes('application/json')) {
|
||||
json = typeof response.data === 'string' ? JSON.parse(response.data) : response.data
|
||||
} else {
|
||||
json = { code: response.status, message: response.data }
|
||||
}
|
||||
} catch (error) {
|
||||
json = { code: response.status, message: 'JSON 解析失败' }
|
||||
}
|
||||
const { status, statusText } = response
|
||||
const { meta } = method
|
||||
if (status !== 200) {
|
||||
|
||||
@@ -24,26 +24,24 @@ const ensureExtension = (extension: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleArchive = async () => {
|
||||
const handleArchive = () => {
|
||||
ensureExtension(format.value)
|
||||
loading.value = true
|
||||
const message = window.$message.loading('正在压缩中...', {
|
||||
duration: 0
|
||||
})
|
||||
const paths = selected.value.map((item) => item.replace(path.value, '').replace(/^\//, ''))
|
||||
await api
|
||||
.compress(path.value, paths, file.value)
|
||||
.then(() => {
|
||||
window.$message.success('压缩成功')
|
||||
useRequest(api.compress(path.value, paths, file.value))
|
||||
.onSuccess(() => {
|
||||
show.value = false
|
||||
selected.value = []
|
||||
window.$message.success('压缩成功')
|
||||
})
|
||||
.catch(() => {
|
||||
window.$message.error('压缩失败')
|
||||
.onComplete(() => {
|
||||
message?.destroy()
|
||||
loading.value = false
|
||||
window.$bus.emit('file:refresh')
|
||||
})
|
||||
message?.destroy()
|
||||
loading.value = false
|
||||
window.$bus.emit('file:refresh')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NEllipsis, NFlex, NInput, NPopconfirm, NPopselect, NTag } from 'naive-ui'
|
||||
import {
|
||||
NButton,
|
||||
NDataTable,
|
||||
NEllipsis,
|
||||
NFlex,
|
||||
NInput,
|
||||
NPopconfirm,
|
||||
NPopselect,
|
||||
NTag
|
||||
} from 'naive-ui'
|
||||
|
||||
import type { DataTableColumns, DropdownOption } from 'naive-ui'
|
||||
import type { RowData } from 'naive-ui/es/data-table/src/interface'
|
||||
@@ -19,7 +28,6 @@ import EditModal from '@/views/file/EditModal.vue'
|
||||
import PreviewModal from '@/views/file/PreviewModal.vue'
|
||||
import type { Marked } from '@/views/file/types'
|
||||
|
||||
const loading = ref(false)
|
||||
const sort = ref<string>('')
|
||||
const path = defineModel<string>('path', { type: String, required: true })
|
||||
const selected = defineModel<any[]>('selected', { type: Array, default: () => [] })
|
||||
@@ -253,9 +261,9 @@ const columns: DataTableColumns<RowData> = [
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => {
|
||||
file.delete(row.full).then(() => {
|
||||
window.$message.success('删除成功')
|
||||
useRequest(file.delete(row.full)).onComplete(() => {
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('删除成功')
|
||||
})
|
||||
},
|
||||
onNegativeClick: () => {}
|
||||
@@ -362,47 +370,17 @@ const rowProps = (row: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
const data = ref<RowData[]>([])
|
||||
const { loading, data, page, total, pageSize, pageCount, refresh } = usePagination(
|
||||
(page, pageSize) => file.list(path.value, page, pageSize, sort.value),
|
||||
{
|
||||
initialData: { total: 0, list: [] },
|
||||
initialPageSize: 20,
|
||||
total: (res: any) => res.total,
|
||||
data: (res: any) => res.items
|
||||
}
|
||||
)
|
||||
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageCount: 1,
|
||||
pageSize: 100,
|
||||
itemCount: 0,
|
||||
showQuickJumper: true,
|
||||
showSizePicker: true,
|
||||
pageSizes: [100, 200, 500, 1000, 1500, 2000, 5000]
|
||||
})
|
||||
|
||||
const handlePageSizeChange = (pageSize: number) => {
|
||||
pagination.pageSize = pageSize
|
||||
handlePageChange(1)
|
||||
}
|
||||
|
||||
const handlePageChange = async (page: number) => {
|
||||
loading.value = true
|
||||
await getList(path.value, page, pagination.pageSize!).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const handleRefresh = async () => {
|
||||
loading.value = true
|
||||
await getList(path.value, pagination.page, pagination.pageSize!).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const getList = async (path: string, page: number, limit: number) => {
|
||||
await file.list(path, page, limit, sort.value).then((res) => {
|
||||
data.value = res.data.items
|
||||
pagination.page = page
|
||||
pagination.itemCount = res.data.total
|
||||
pagination.pageCount = res.data.total / pagination.pageSize! + 1
|
||||
})
|
||||
}
|
||||
|
||||
const handleRename = async () => {
|
||||
const handleRename = () => {
|
||||
const source = path.value + '/' + renameModel.value.source
|
||||
const target = path.value + '/' + renameModel.value.target
|
||||
if (!checkName(renameModel.value.source) || !checkName(renameModel.value.target)) {
|
||||
@@ -410,31 +388,39 @@ const handleRename = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
await file.exist([target]).then(async (res) => {
|
||||
if (res.data[0]) {
|
||||
useRequest(file.exist([target])).onSuccess(({ data }) => {
|
||||
if (data[0]) {
|
||||
window.$dialog.warning({
|
||||
title: '警告',
|
||||
content: `存在同名项,是否强制覆盖?`,
|
||||
positiveText: '覆盖',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
await file.move([{ source, target, force: true }])
|
||||
window.$message.success(
|
||||
`重命名 ${renameModel.value.source} 为 ${renameModel.value.target} 成功`
|
||||
)
|
||||
window.$bus.emit('file:refresh')
|
||||
onPositiveClick: () => {
|
||||
useRequest(file.move([{ source, target, force: true }]))
|
||||
.onSuccess(() => {
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success(
|
||||
`重命名 ${renameModel.value.source} 为 ${renameModel.value.target} 成功`
|
||||
)
|
||||
})
|
||||
.onComplete(() => {
|
||||
renameModal.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
await file.move([{ source, target, force: false }])
|
||||
window.$message.success(
|
||||
`重命名 ${renameModel.value.source} 为 ${renameModel.value.target} 成功`
|
||||
)
|
||||
window.$bus.emit('file:refresh')
|
||||
useRequest(file.move([{ source, target, force: false }]))
|
||||
.onSuccess(() => {
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success(
|
||||
`重命名 ${renameModel.value.source} 为 ${renameModel.value.target} 成功`
|
||||
)
|
||||
})
|
||||
.onComplete(() => {
|
||||
renameModal.value = false
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
renameModal.value = false
|
||||
}
|
||||
|
||||
const handleUnCompress = () => {
|
||||
@@ -449,17 +435,14 @@ const handleUnCompress = () => {
|
||||
const message = window.$message.loading('正在解压中...', {
|
||||
duration: 0
|
||||
})
|
||||
file
|
||||
.unCompress(unCompressModel.value.file, unCompressModel.value.path)
|
||||
.then(() => {
|
||||
message?.destroy()
|
||||
window.$message.success('解压成功')
|
||||
useRequest(file.unCompress(unCompressModel.value.file, unCompressModel.value.path))
|
||||
.onSuccess(() => {
|
||||
unCompressModal.value = false
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('解压成功')
|
||||
})
|
||||
.catch(() => {
|
||||
.onComplete(() => {
|
||||
message?.destroy()
|
||||
window.$message.error('解压失败')
|
||||
})
|
||||
}
|
||||
|
||||
@@ -467,7 +450,7 @@ const onChecked = (rowKeys: any) => {
|
||||
selected.value = rowKeys
|
||||
}
|
||||
|
||||
const handlePaste = async () => {
|
||||
const handlePaste = () => {
|
||||
if (!marked.value.length) {
|
||||
window.$message.error('请先标记需要复制或移动的文件/文件夹')
|
||||
return
|
||||
@@ -484,9 +467,9 @@ const handlePaste = async () => {
|
||||
}
|
||||
})
|
||||
const sources = paths.map((item: any) => item.target)
|
||||
await file.exist(sources).then(async (res) => {
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
if (res.data[i]) {
|
||||
useRequest(file.exist(sources)).onSuccess(({ data }) => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i]) {
|
||||
flag = true
|
||||
paths[i].force = true
|
||||
}
|
||||
@@ -501,13 +484,13 @@ const handlePaste = async () => {
|
||||
.join(', ')} 是否覆盖?`,
|
||||
positiveText: '覆盖',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
onPositiveClick: () => {
|
||||
if (markedType.value == 'copy') {
|
||||
await file.copy(paths).then(() => {
|
||||
useRequest(file.copy(paths)).onSuccess(() => {
|
||||
window.$message.success('复制成功')
|
||||
})
|
||||
} else {
|
||||
await file.move(paths).then(() => {
|
||||
useRequest(file.move(paths)).onSuccess(() => {
|
||||
window.$message.success('移动成功')
|
||||
})
|
||||
}
|
||||
@@ -521,11 +504,11 @@ const handlePaste = async () => {
|
||||
})
|
||||
} else {
|
||||
if (markedType.value == 'copy') {
|
||||
await file.copy(paths).then(() => {
|
||||
useRequest(file.copy(paths)).onSuccess(() => {
|
||||
window.$message.success('复制成功')
|
||||
})
|
||||
} else {
|
||||
await file.move(paths).then(() => {
|
||||
useRequest(file.move(paths)).onSuccess(() => {
|
||||
window.$message.success('移动成功')
|
||||
})
|
||||
}
|
||||
@@ -595,9 +578,9 @@ const handleSelect = (key: string) => {
|
||||
renameModal.value = true
|
||||
break
|
||||
case 'delete':
|
||||
file.delete(selectedRow.value.full).then(() => {
|
||||
window.$message.success('删除成功')
|
||||
useRequest(file.delete(selectedRow.value.full)).onSuccess(() => {
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('删除成功')
|
||||
})
|
||||
break
|
||||
}
|
||||
@@ -618,15 +601,15 @@ const handleSorterChange = (sorter: {
|
||||
switch (sorter.order) {
|
||||
case 'ascend':
|
||||
sort.value = 'asc'
|
||||
handleRefresh()
|
||||
refresh()
|
||||
break
|
||||
case 'descend':
|
||||
sort.value = 'desc'
|
||||
handleRefresh()
|
||||
refresh()
|
||||
break
|
||||
default:
|
||||
sort.value = ''
|
||||
handleRefresh()
|
||||
refresh()
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -638,12 +621,12 @@ onMounted(() => {
|
||||
path,
|
||||
() => {
|
||||
selected.value = []
|
||||
handlePageChange(1)
|
||||
refresh()
|
||||
window.$bus.emit('push-history', path.value)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
window.$bus.on('file:refresh', handleRefresh)
|
||||
window.$bus.on('file:refresh', refresh)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
@@ -662,14 +645,22 @@ onUnmounted(() => {
|
||||
:data="data"
|
||||
:row-props="rowProps"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-key="(row: any) => row.full"
|
||||
:checked-row-keys="selected"
|
||||
max-height="60vh"
|
||||
@update:page="handlePageChange"
|
||||
@update:page-size="handlePageSizeChange"
|
||||
@update:sorter="handleSorterChange"
|
||||
@update:checked-row-keys="onChecked"
|
||||
v-model:page="page"
|
||||
v-model:pageSize="pageSize"
|
||||
:pagination="{
|
||||
page: page,
|
||||
pageCount: pageCount,
|
||||
pageSize: pageSize,
|
||||
itemCount: total,
|
||||
showQuickJumper: true,
|
||||
showSizePicker: true,
|
||||
pageSizes: [100, 200, 500, 1000, 1500, 2000, 5000]
|
||||
}"
|
||||
/>
|
||||
<n-dropdown
|
||||
placement="bottom-start"
|
||||
|
||||
@@ -16,11 +16,14 @@ const checkbox = ref({
|
||||
})
|
||||
|
||||
const handlePermission = async () => {
|
||||
for (const path of selected.value) {
|
||||
await file.permission(path, `0${mode.value}`, owner.value, group.value).then(() => {
|
||||
const promises = selected.value.map((path) =>
|
||||
useRequest(file.permission(path, `0${mode.value}`, owner.value, group.value)).onSuccess(() => {
|
||||
window.$message.success(`修改 ${path} 成功`)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
show.value = false
|
||||
selected.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
|
||||
@@ -14,9 +14,9 @@ watch(
|
||||
() => path.value,
|
||||
() => {
|
||||
content.value = ''
|
||||
file.content(path.value).then((res) => {
|
||||
mime.value = res.data.mime
|
||||
content.value = res.data.content
|
||||
useRequest(file.content(path.value)).onSuccess(({ data }) => {
|
||||
mime.value = data.mime
|
||||
content.value = data.content
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
@@ -72,9 +72,9 @@ const columns: DataTableColumns<RowData> = [
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => {
|
||||
file.delete(row.full).then(() => {
|
||||
window.$message.success('删除成功')
|
||||
useRequest(file.delete(row.full)).onSuccess(() => {
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('删除成功')
|
||||
})
|
||||
},
|
||||
onNegativeClick: () => {}
|
||||
@@ -126,12 +126,11 @@ const handlePageChange = (page: number) => {
|
||||
|
||||
const search = async (page: number) => {
|
||||
loading.value = true
|
||||
await file
|
||||
.search(path.value, keyword.value, sub.value, page, pagination.pageSize!)
|
||||
.then((res) => {
|
||||
data.value = res.data.items
|
||||
pagination.itemCount = res.data.total
|
||||
pagination.pageCount = res.data.total / pagination.pageSize! + 1
|
||||
useRequest(file.search(path.value, keyword.value, sub.value, page, pagination.pageSize!))
|
||||
.then(({ data }) => {
|
||||
data.value = data.items
|
||||
pagination.itemCount = data.total
|
||||
pagination.pageCount = data.total / pagination.pageSize! + 1
|
||||
})
|
||||
.catch(() => {
|
||||
window.$message.error('搜索失败')
|
||||
|
||||
@@ -36,10 +36,10 @@ const handleCreate = () => {
|
||||
}
|
||||
|
||||
const fullPath = path.value + '/' + createModel.value.path
|
||||
file.create(fullPath, createModel.value.dir).then(() => {
|
||||
useRequest(file.create(fullPath, createModel.value.dir)).onSuccess(() => {
|
||||
create.value = false
|
||||
window.$message.success('创建成功')
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('创建成功')
|
||||
})
|
||||
}
|
||||
|
||||
@@ -49,13 +49,13 @@ const handleDownload = () => {
|
||||
return
|
||||
}
|
||||
|
||||
file
|
||||
.remoteDownload(path.value + '/' + downloadModel.value.path, downloadModel.value.url)
|
||||
.then(() => {
|
||||
download.value = false
|
||||
window.$message.success('下载任务创建成功')
|
||||
window.$bus.emit('file:refresh')
|
||||
})
|
||||
useRequest(
|
||||
file.remoteDownload(path.value + '/' + downloadModel.value.path, downloadModel.value.url)
|
||||
).onSuccess(() => {
|
||||
download.value = false
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('下载任务创建成功')
|
||||
})
|
||||
}
|
||||
|
||||
const handleCopy = () => {
|
||||
@@ -92,7 +92,7 @@ const handleCancel = () => {
|
||||
marked.value = []
|
||||
}
|
||||
|
||||
const handlePaste = async () => {
|
||||
const handlePaste = () => {
|
||||
if (!marked.value.length) {
|
||||
window.$message.error('请先标记需要复制或移动的文件/文件夹')
|
||||
return
|
||||
@@ -109,9 +109,9 @@ const handlePaste = async () => {
|
||||
}
|
||||
})
|
||||
const sources = paths.map((item: any) => item.target)
|
||||
await file.exist(sources).then(async (res) => {
|
||||
for (let i = 0; i < res.data.length; i++) {
|
||||
if (res.data[i]) {
|
||||
useRequest(file.exist(sources)).onSuccess(({ data }) => {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i]) {
|
||||
flag = true
|
||||
paths[i].force = true
|
||||
}
|
||||
@@ -128,16 +128,18 @@ const handlePaste = async () => {
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
if (markedType.value == 'copy') {
|
||||
await file.copy(paths).then(() => {
|
||||
useRequest(file.copy(paths)).onSuccess(() => {
|
||||
marked.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('复制成功')
|
||||
})
|
||||
} else {
|
||||
await file.move(paths).then(() => {
|
||||
useRequest(file.move(paths)).onSuccess(() => {
|
||||
marked.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('移动成功')
|
||||
})
|
||||
}
|
||||
marked.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
marked.value = []
|
||||
@@ -146,16 +148,18 @@ const handlePaste = async () => {
|
||||
})
|
||||
} else {
|
||||
if (markedType.value == 'copy') {
|
||||
await file.copy(paths).then(() => {
|
||||
useRequest(file.copy(paths)).onSuccess(() => {
|
||||
marked.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('复制成功')
|
||||
})
|
||||
} else {
|
||||
await file.move(paths).then(() => {
|
||||
useRequest(file.move(paths)).onSuccess(() => {
|
||||
marked.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success('移动成功')
|
||||
})
|
||||
}
|
||||
marked.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -166,14 +170,16 @@ const bulkDelete = async () => {
|
||||
return
|
||||
}
|
||||
|
||||
for (const path of selected.value) {
|
||||
await file.delete(path).then(() => {
|
||||
const promises = selected.value.map((path) =>
|
||||
useRequest(file.delete(path)).onSuccess(() => {
|
||||
window.$message.success(`删除 ${path} 成功`)
|
||||
window.$bus.emit('file:refresh')
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
selected.value = []
|
||||
window.$bus.emit('file:refresh')
|
||||
}
|
||||
|
||||
// 自动填充下载文件名
|
||||
|
||||
@@ -9,17 +9,23 @@ const upload = ref<any>(null)
|
||||
|
||||
const uploadRequest = ({ file, onFinish, onError, onProgress }: UploadCustomRequestOptions) => {
|
||||
const formData = new FormData()
|
||||
formData.append('path', `${path.value}/${file.name}`)
|
||||
formData.append('file', file.file as File)
|
||||
api
|
||||
.upload(`${path.value}/${file.name}`, formData, onProgress)
|
||||
.then(() => {
|
||||
window.$message.success(`上传 ${file.name} 成功`)
|
||||
window.$bus.emit('file:refresh')
|
||||
const { uploading } = useRequest(api.upload(formData))
|
||||
.onSuccess(() => {
|
||||
onFinish()
|
||||
window.$bus.emit('file:refresh')
|
||||
window.$message.success(`上传 ${file.name} 成功`)
|
||||
})
|
||||
.catch(() => {
|
||||
.onError(() => {
|
||||
onError()
|
||||
})
|
||||
.onComplete(() => {
|
||||
stopWatch()
|
||||
})
|
||||
const stopWatch = watch(uploading, (progress) => {
|
||||
onProgress({ percent: Math.ceil((progress.loaded / progress.total) * 100) })
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -34,7 +40,6 @@ const uploadRequest = ({ file, onFinish, onError, onProgress }: UploadCustomRequ
|
||||
:segmented="false"
|
||||
>
|
||||
<n-flex vertical>
|
||||
<n-alert type="info">若上传报网络错误,请开启面板 HTTPS 后重试</n-alert>
|
||||
<n-upload
|
||||
ref="upload"
|
||||
multiple
|
||||
@@ -47,7 +52,7 @@ const uploadRequest = ({ file, onFinish, onError, onProgress }: UploadCustomRequ
|
||||
<the-icon :size="48" icon="bi:arrow-up-square" />
|
||||
</div>
|
||||
<NText text-18> 点击或者拖动文件到该区域来上传</NText>
|
||||
<NP depth="3" m-10> 大文件建议使用 SFTP 上传 </NP>
|
||||
<NP depth="3" m-10> 大文件建议使用 SFTP 等方式上传 </NP>
|
||||
</n-upload-dragger>
|
||||
</n-upload>
|
||||
</n-flex>
|
||||
|
||||
@@ -131,21 +131,21 @@ const handleDelete = (row: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
const batchDelete = () => {
|
||||
const batchDelete = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要删除的规则')
|
||||
return
|
||||
}
|
||||
|
||||
for (const key of selectedRowKeys.value) {
|
||||
// 解析json
|
||||
const promises = selectedRowKeys.value.map((key: any) => {
|
||||
const rule = JSON.parse(key)
|
||||
useRequest(firewall.deleteForward(rule)).onSuccess(() => {
|
||||
return useRequest(firewall.deleteForward(rule)).then(() => {
|
||||
window.$message.success(`${rule.protocol} ${rule.target_ip}:${rule.target_port} 删除成功`)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
refresh()
|
||||
await Promise.all(promises)
|
||||
await refresh()
|
||||
}
|
||||
|
||||
const onChecked = (rowKeys: any) => {
|
||||
|
||||
@@ -173,21 +173,21 @@ const handleDelete = (row: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
const batchDelete = () => {
|
||||
const batchDelete = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要删除的规则')
|
||||
return
|
||||
}
|
||||
|
||||
for (const key of selectedRowKeys.value) {
|
||||
// 解析json
|
||||
const promises = selectedRowKeys.value.map((key: any) => {
|
||||
const rule = JSON.parse(key)
|
||||
useRequest(firewall.deleteIpRule(rule)).onSuccess(() => {
|
||||
return useRequest(firewall.deleteIpRule(rule)).then(() => {
|
||||
window.$message.success(`${rule.address} 删除成功`)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
refresh()
|
||||
await Promise.all(promises)
|
||||
await refresh()
|
||||
}
|
||||
|
||||
const onChecked = (rowKeys: any) => {
|
||||
|
||||
@@ -210,23 +210,23 @@ const handleDelete = async (row: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
const batchDelete = () => {
|
||||
const batchDelete = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要删除的规则')
|
||||
return
|
||||
}
|
||||
|
||||
for (const key of selectedRowKeys.value) {
|
||||
// 解析json
|
||||
const promises = selectedRowKeys.value.map((key: any) => {
|
||||
const rule = JSON.parse(key)
|
||||
useRequest(firewall.deleteRule(rule)).onSuccess(() => {
|
||||
return useRequest(firewall.deleteRule(rule)).then(() => {
|
||||
const port =
|
||||
rule.port_start == rule.port_end ? rule.port_start : `${rule.port_start}-${rule.port_end}`
|
||||
window.$message.success(`${rule.family} 规则 ${port}/${rule.protocol} 删除成功`)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
refresh()
|
||||
await Promise.all(promises)
|
||||
await refresh()
|
||||
}
|
||||
|
||||
const onChecked = (rowKeys: any) => {
|
||||
|
||||
@@ -307,19 +307,21 @@ const handleCreate = async () => {
|
||||
})
|
||||
}
|
||||
|
||||
const batchDelete = async () => {
|
||||
const bulkDelete = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要删除的网站')
|
||||
return
|
||||
}
|
||||
|
||||
for (const id of selectedRowKeys.value) {
|
||||
useRequest(website.delete(id, true, false)).onSuccess(() => {
|
||||
refresh()
|
||||
const site = data.value.find((item: any) => item.id === id)
|
||||
const promises = selectedRowKeys.value.map((id: any) => {
|
||||
const site = data.value.find((item: any) => item.id === id)
|
||||
return useRequest(website.delete(id, true, false)).then(() => {
|
||||
window.$message.success('网站 ' + site?.name + ' 删除成功')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.all(promises)
|
||||
await refresh()
|
||||
}
|
||||
|
||||
const formatDbValue = (value: string) => {
|
||||
@@ -346,7 +348,7 @@ onMounted(() => {
|
||||
<n-button type="primary" @click="createModal = true">
|
||||
{{ $t('websiteIndex.create.trigger') }}
|
||||
</n-button>
|
||||
<n-popconfirm @positive-click="batchDelete">
|
||||
<n-popconfirm @positive-click="bulkDelete">
|
||||
<template #trigger>
|
||||
<n-button type="error"> 批量删除 </n-button>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user