This commit is contained in:
jxxghp
2023-08-26 12:48:04 +08:00
parent 4681c947c7
commit 476bd4bd19
6 changed files with 60 additions and 47 deletions

View File

@@ -913,5 +913,5 @@ export interface FileItem {
path: string path: string
extension: string extension: string
size: number size: number
children: [] children: FileItem[]
} }

View File

@@ -5,6 +5,7 @@ import axios from 'axios'
import Toolbar from './filebrowser/Toolbar.vue' import Toolbar from './filebrowser/Toolbar.vue'
import Tree from './filebrowser/Tree.vue' import Tree from './filebrowser/Tree.vue'
import List from './filebrowser/List.vue' import List from './filebrowser/List.vue'
import type { EndPoints } from '@/api/types'
// 输入参数 // 输入参数
const props = defineProps({ const props = defineProps({
@@ -12,16 +13,16 @@ const props = defineProps({
storage: String, storage: String,
path: String, path: String,
tree: String, tree: String,
endpoints: Object, endpoints: Object as PropType<EndPoints>,
axios: Object as PropType<Axios>, axios: Object as PropType<Axios>,
axiosConfig: Object, axiosconfig: Object,
maxUploadFilesCount: Number,
maxUploadFileSize: Number,
}) })
// 事件 // 事件f
const emit = defineEmits(['change']) const emit = defineEmits(['change'])
console.log('FileBrowser Init Path', props.path)
const availableStorages = [ const availableStorages = [
{ {
name: '本地', name: '本地',
@@ -30,12 +31,6 @@ const availableStorages = [
}, },
] ]
const endpoints = {
list: { url: '/filebrowser/list?path={path}', method: 'get' },
mkdir: { url: '/filebrowser/mkdir?path={path}', method: 'post' },
delete: { url: '/filebrowser/delete?path={path}', method: 'post' },
}
const fileIcons = { const fileIcons = {
zip: 'mdi-folder-zip-outline', zip: 'mdi-folder-zip-outline',
rar: 'mdi-folder-zip-outline', rar: 'mdi-folder-zip-outline',
@@ -65,7 +60,7 @@ const path = ref(props.path)
// 当前存储 // 当前存储
const activeStorage = ref('local') const activeStorage = ref('local')
// 刷新 // 刷新
const refreshPending = ref(false) const refreshPending = ref(true)
// axios实例 // axios实例
const axiosInstance = ref<Axios>() const axiosInstance = ref<Axios>()
@@ -89,13 +84,14 @@ function storageChanged(storage: string) {
function pathChanged(_path: string) { function pathChanged(_path: string) {
path.value = _path path.value = _path
console.log('Browser changePath', path.value)
emit('change', path) emit('change', path)
} }
// 初始化 // 初始化
onMounted(() => { onBeforeMount(() => {
activeStorage.value = props.storage ?? 'local' activeStorage.value = props.storage ?? 'local'
axiosInstance.value = props.axios ?? axios.create(props.axiosConfig) axiosInstance.value = props.axios ?? axios.create(props.axiosconfig)
if (!path.value) if (!path.value)
pathChanged('/') pathChanged('/')
}) })
@@ -107,7 +103,7 @@ onMounted(() => {
:path="path" :path="path"
:storages="storagesArray" :storages="storagesArray"
:storage="activeStorage" :storage="activeStorage"
:endpoints="endpoints" :endpoints="props.endpoints"
:axios="axiosInstance" :axios="axiosInstance"
@storagechanged="storageChanged" @storagechanged="storageChanged"
@pathchanged="pathChanged" @pathchanged="pathChanged"
@@ -136,10 +132,10 @@ onMounted(() => {
:endpoints="endpoints" :endpoints="endpoints"
:axios="axiosInstance" :axios="axiosInstance"
:refreshpending="refreshPending" :refreshpending="refreshPending"
@path-changed="pathChanged" @pathchanged="pathChanged"
@loading="loadingChanged" @loading="loadingChanged"
@refreshed="refreshPending = false" @refreshed="refreshPending = false"
@file-deleted="refreshPending = true" @filedeleted="refreshPending = true"
/> />
</VCol> </VCol>
</VRow> </VRow>

View File

@@ -2,6 +2,7 @@
import type { Axios } from 'axios' import type { Axios } from 'axios'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { useConfirm } from 'vuetify-use-dialog' import { useConfirm } from 'vuetify-use-dialog'
import axios from 'axios'
import { formatBytes } from '@core/utils/formatters' import { formatBytes } from '@core/utils/formatters'
import type { EndPoints, FileItem } from '@/api/types' import type { EndPoints, FileItem } from '@/api/types'
@@ -18,20 +19,25 @@ const props = defineProps({
// 对外事件 // 对外事件
const emit = defineEmits(['loading', 'pathchanged', 'refreshed', 'filedeleted']) const emit = defineEmits(['loading', 'pathchanged', 'refreshed', 'filedeleted'])
console.log('List Init Path', props.path)
// 确认框 // 确认框
const createConfirm = useConfirm() const createConfirm = useConfirm()
// axios实例
const axiosInstance = ref<Axios>(props.axios ?? axios)
// 内容列表 // 内容列表
const items = ref<FileItem[]>([]) const items = ref<FileItem[]>([])
// 当前路径 // 当前路径
const path = ref(props.path ?? '') const path = ref(props.path)
// 过滤条件 // 过滤条件
const filter = ref('') const filter = ref('')
// 存储空间类型 // 存储空间类型
const storage = ref(props.storage || '') const storage = ref(props.storage ?? '')
// 是否正在加载 // 是否正在加载
const refreshPending = ref(props.refreshpending || false) const refreshPending = ref(props.refreshpending || false)
@@ -47,13 +53,14 @@ const files = computed(() =>
) )
// 是否目录 // 是否目录
const isDir = computed(() => path.value.endsWith('/')) const isDir = computed(() => path.value?.endsWith('/'))
// 是否文件 // 是否文件
const isFile = computed(() => !isDir.value) const isFile = computed(() => !isDir.value)
// 调API加载内容 // 调API加载内容
async function load() { async function load() {
console.log('List load', path.value, isDir.value)
if (isDir.value) { if (isDir.value) {
const url = props.endpoints?.list.url const url = props.endpoints?.list.url
.replace(/{storage}/g, storage.value) .replace(/{storage}/g, storage.value)
@@ -63,9 +70,9 @@ async function load() {
url, url,
method: props.endpoints?.list.method || 'get', method: props.endpoints?.list.method || 'get',
} }
console.log('List load', url, config)
const response = await props.axios?.request(config) // 加载数据
items.value = response?.data items.value = await axiosInstance.value.request(config) ?? []
} }
} }
@@ -75,7 +82,7 @@ async function deleteItem(item: FileItem) {
title: '确认', title: '确认',
content: `是否确认删除${ content: `是否确认删除${
item.type === 'dir' ? '目录' : '文件' item.type === 'dir' ? '目录' : '文件'
}?<br><em>${item.basename}</em>?`, } ${item.basename}`,
confirmationText: '确认', confirmationText: '确认',
cancellationText: '取消', cancellationText: '取消',
dialogProps: { dialogProps: {
@@ -94,7 +101,7 @@ async function deleteItem(item: FileItem) {
method: props.endpoints?.delete.method || 'post', method: props.endpoints?.delete.method || 'post',
} }
await props.axios?.request(config) await axiosInstance.value.request(config)
emit('filedeleted') emit('filedeleted')
emit('loading', false) emit('loading', false)
} }
@@ -102,21 +109,26 @@ async function deleteItem(item: FileItem) {
// 切换路径 // 切换路径
function changePath(path: string) { function changePath(path: string) {
console.log('List changePath', path)
emit('pathchanged', path) emit('pathchanged', path)
} }
// 监听path变化 // 监听path变化
watch( watch(
() => path.value, path,
async () => { async () => {
console.log('List pathChanged', path.value)
items.value = [] items.value = []
await load()
if (refreshPending.value) { if (refreshPending.value) {
await load() await load()
emit('refreshed') emit('refreshed')
} }
}, },
) )
onMounted(() => {
load()
})
</script> </script>
<template> <template>
@@ -139,19 +151,17 @@ watch(
<VListItem <VListItem
v-for="(item, index) in dirs" v-for="(item, index) in dirs"
:key="index" :key="index"
class="pl-0" class="pl-2"
@click="changePath(item.path)" @click="changePath(item.path)"
> >
<template #prepend> <template #prepend>
<VIcon icon="mdi-folder-outline" /> <VIcon icon="mdi-folder-outline" />
</template> </template>
<VListItemTitle v-text="item.basename" /> <VListItemTitle v-text="item.name" />
<template #append> <template #append>
<VBtn icon @click.stop="deleteItem(item)"> <IconBtn @click.stop="deleteItem(item)">
<VIcon color="grey lighten-1"> <VIcon icon="mdi-delete-outline" />
mdi-delete-outline </IconBtn>
</VIcon>
</VBtn>
</template> </template>
</VListItem> </VListItem>
</VList> </VList>
@@ -161,22 +171,20 @@ watch(
<VListItem <VListItem
v-for="(item, index) in files" v-for="(item, index) in files"
:key="index" :key="index"
class="pl-0" class="pl-2"
@click="changePath(item.path)" @click="changePath(item.path)"
> >
<template #prepend> <template #prepend>
<VIcon v-if="props.icons" :icon="props.icons[item.extension.toLowerCase()] || props.icons?.other" /> <VIcon v-if="props.icons" :icon="props.icons[item.extension.toLowerCase()] || props.icons?.other" />
</template> </template>
<VListItemTitle v-text="item.basename" /> <VListItemTitle v-text="item.name" />
<VListItemSubtitle> {{ formatBytes(item.size) }}</VListItemSubtitle> <VListItemSubtitle> {{ formatBytes(item.size) }}</VListItemSubtitle>
<template #append> <template #append>
<VBtn icon @click.stop="deleteItem(item)"> <IconBtn @click.stop="deleteItem(item)">
<VIcon color="grey lighten-1"> <VIcon icon="mdi-delete-outline" />
mdi-delete-outline </IconBtn>
</VIcon>
</VBtn>
</template> </template>
</VListItem> </VListItem>
</VList> </VList>

View File

@@ -52,6 +52,7 @@ function changeStorage(code: string) {
// 路径变化 // 路径变化
function changePath(path: string) { function changePath(path: string) {
console.log('Toolbar changePath', path)
emit('pathchanged', path) emit('pathchanged', path)
} }

View File

@@ -38,8 +38,6 @@ function init() {
children: [], children: [],
size: 0, size: 0,
}] }]
if (props.path !== '')
emit('pathchanged', '')
} }
// 调用API读取文件夹 // 调用API读取文件夹
@@ -54,9 +52,9 @@ async function readFolder(item: FileItem) {
method: props.endpoints?.list.method || 'get', method: props.endpoints?.list.method || 'get',
} }
const response: any = await props.axios?.request(config) const response: FileItem[] = await props.axios?.request(config) ?? []
item.children = response.data.map((item: FileItem) => { item.children = response.map((item: FileItem) => {
if (item.type === 'dir') if (item.type === 'dir')
item.children = [] item.children = []
@@ -68,6 +66,7 @@ async function readFolder(item: FileItem) {
// 选中变化 // 选中变化
function activeChanged(_active: string[]) { function activeChanged(_active: string[]) {
console.log('Tree changePath', _active)
active.value = _active active.value = _active
let path = '' let path = ''
if (active.value.length) if (active.value.length)

View File

@@ -1,9 +1,18 @@
<script lang="ts" setup> <script lang="ts" setup>
import api from '@/api'
import FileBrowser from '@/components/FileBrowser.vue' import FileBrowser from '@/components/FileBrowser.vue'
const initPath = ref('/Users/jxxghp/Downloads/爱情生活 (2020)/')
const endpoints = {
list: { url: '/filebrowser/list?path={path}', method: 'get' },
mkdir: { url: '/filebrowser/mkdir?path={path}', method: 'get' },
delete: { url: '/filebrowser/delete?path={path}', method: 'get' },
}
</script> </script>
<template> <template>
<div> <div>
<FileBrowser storages="local" tree="true" path="/Users/jxxghp/Downloads/public" /> <FileBrowser storages="local" tree="true" :path="initPath" :endpoints="endpoints" :axios="api" />
</div> </div>
</template> </template>