diff --git a/src/api/types.ts b/src/api/types.ts index d45f8281..02b12c62 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -903,6 +903,7 @@ export interface EndPoints { list: any mkdir: any delete: any + download: any } // 文件浏览项目 diff --git a/src/components/FileBrowser.vue b/src/components/FileBrowser.vue index 827cfa79..02d4ea6a 100644 --- a/src/components/FileBrowser.vue +++ b/src/components/FileBrowser.vue @@ -12,17 +12,12 @@ const props = defineProps({ storages: String, storage: String, path: String, - tree: String, + tree: Boolean, endpoints: Object as PropType, axios: Object as PropType, axiosconfig: Object, }) -// 事件f -const emit = defineEmits(['change']) - -console.log('FileBrowser Init Path', props.path) - const availableStorages = [ { name: '本地', @@ -53,14 +48,14 @@ const fileIcons = { other: 'mdi-file-outline', } -// 加载次数 -const loading = ref(0) // 当前路径 const path = ref(props.path) +// 加载次数 +const loading = ref(0) // 当前存储 const activeStorage = ref('local') // 刷新 -const refreshPending = ref(true) +const refreshPending = ref(false) // axios实例 const axiosInstance = ref() @@ -84,8 +79,6 @@ function storageChanged(storage: string) { function pathChanged(_path: string) { path.value = _path - console.log('Browser changePath', path.value) - emit('change', path) } // 初始化 diff --git a/src/components/filebrowser/List.vue b/src/components/filebrowser/List.vue index f9ea2bf0..a99c6c3e 100644 --- a/src/components/filebrowser/List.vue +++ b/src/components/filebrowser/List.vue @@ -19,8 +19,6 @@ const props = defineProps({ // 对外事件 const emit = defineEmits(['loading', 'pathchanged', 'refreshed', 'filedeleted']) -console.log('List Init Path', props.path) - // 确认框 const createConfirm = useConfirm() @@ -30,18 +28,12 @@ const axiosInstance = ref(props.axios ?? axios) // 内容列表 const items = ref([]) -// 当前路径 -const path = ref(props.path) - // 过滤条件 const filter = ref('') // 存储空间类型 const storage = ref(props.storage ?? '') -// 是否正在加载 -const refreshPending = ref(props.refreshpending || false) - // 目录过滤 const dirs = computed(() => items.value.filter(item => item.type === 'dir' && item.basename.includes(filter.value)), @@ -53,27 +45,27 @@ const files = computed(() => ) // 是否目录 -const isDir = computed(() => path.value?.endsWith('/')) +const isDir = computed(() => props.path?.endsWith('/')) // 是否文件 const isFile = computed(() => !isDir.value) // 调API加载内容 async function load() { - console.log('List load', path.value, isDir.value) + emit('loading', true) if (isDir.value) { const url = props.endpoints?.list.url .replace(/{storage}/g, storage.value) - .replace(/{path}/g, path.value) + .replace(/{path}/g, props.path) const config = { url, method: props.endpoints?.list.method || 'get', } - console.log('List load', url, config) // 加载数据 items.value = await axiosInstance.value.request(config) ?? [] } + emit('loading', false) } // 删除项目 @@ -104,23 +96,41 @@ async function deleteItem(item: FileItem) { await axiosInstance.value.request(config) emit('filedeleted') emit('loading', false) + // 重新加载 + load() } } // 切换路径 function changePath(_path: string) { - path.value = _path - console.log('List changePath', path.value) - emit('pathchanged', path) + emit('pathchanged', _path) +} + +// 新窗口中下载文件 +function download(path: string) { + if (!path) + return + const url = props.endpoints?.download.url + .replace(/{storage}/g, storage.value) + .replace(/{path}/g, path) + // FIXME 下载文件 + window.open(url, '_blank') } // 监听path变化 watch( - path, + () => props.path, async () => { - console.log('List pathChanged', path.value) items.value = [] - if (refreshPending.value) { + await load() + }, +) + +// 监听refreshPending变化 +watch( + () => props.refreshpending, + async () => { + if (props.refreshpending) { await load() emit('refreshed') } @@ -147,7 +157,7 @@ onMounted(() => { 文件: {{ path }} - + 目录 { - + 文件 { 空目录 - + { prepend-inner-icon="mdi-filter-outline" class="me-2" /> - + + mdi-download - + mdi-refresh diff --git a/src/components/filebrowser/Toolbar.vue b/src/components/filebrowser/Toolbar.vue index 9fe6132a..5e8d87d2 100644 --- a/src/components/filebrowser/Toolbar.vue +++ b/src/components/filebrowser/Toolbar.vue @@ -14,9 +14,6 @@ const inProps = defineProps({ // 对外事件 const emit = defineEmits(['storagechanged', 'pathchanged', 'loading', 'foldercreated']) -// 当前路径 -const path = ref(inProps.path ?? '') - // 新建文件夹名称 const newFolderPopper = ref(false) @@ -26,16 +23,16 @@ const newFolderName = ref('') // 计算PATH面包屑 const pathSegments = computed(() => { let path_str = '/' - const isFolder = path.value.endsWith('/') - const segments = path.value.split('/').filter(item => item) + const isFolder = inProps.path?.endsWith('/') + const segments = inProps.path?.split('/').filter(item => item) - return segments.map((item, index) => { + return segments?.map((item, index) => { path_str += item + ((index < segments.length - 1 || isFolder) ? '/' : '') return { name: item, path: path_str, } - }) + }) ?? [] }) const storageObject = computed(() => { @@ -52,15 +49,13 @@ function changeStorage(code: string) { // 路径变化 function changePath(_path: string) { - path.value = _path - console.log('Toolbar changePath', path.value) - emit('pathchanged', path) + emit('pathchanged', _path) } // 返回上一级 function goUp() { - const segments = pathSegments.value - const path = segments.length === 1 ? '/' : segments[segments.length - 2].path + const segments = pathSegments.value ?? [] + const path = segments?.length === 1 ? '/' : segments[segments.length - 2].path changePath(path) } @@ -76,11 +71,15 @@ async function mkdir() { method: inProps.endpoints?.mkdir.method || 'post', } + // 调API await inProps.axios?.request(config) - emit('foldercreated', newFolderName.value) + newFolderPopper.value = false newFolderName.value = '' emit('loading', false) + + // 通知重新加载 + emit('foldercreated') } diff --git a/src/components/filebrowser/Tree.vue b/src/components/filebrowser/Tree.vue index af18586d..7e998432 100644 --- a/src/components/filebrowser/Tree.vue +++ b/src/components/filebrowser/Tree.vue @@ -15,9 +15,6 @@ const props = defineProps({ // 对外事件 const emit = defineEmits(['pathchanged', 'loading', 'refreshed']) -// 当前路径 -const path = ref(props.path) - // 变量 const open = ref([]) // 活跃的文件夹 @@ -26,8 +23,6 @@ const active = ref([]) const items = ref([]) // 过滤 const filter = ref('') -// 刷新状态 -const refreshPending = ref(props.refreshpending || false) // 方法 function init() { @@ -69,8 +64,6 @@ async function readFolder(item: FileItem) { // 选中变化 function activeChanged(_active: string[]) { - console.log('Tree changePath', _active) - active.value = _active let path = '' if (active.value.length) path = active.value[0] @@ -103,7 +96,7 @@ watch(() => props.storage, () => { // 监听路径变化 watch( - path, + () => props.path, () => { if (props.path) { active.value = [props.path] @@ -114,9 +107,9 @@ watch( // 监听 refreshPending watch( - refreshPending, + () => props.refreshpending, async () => { - if (refreshPending.value && props.path) { + if (props.refreshpending && props.path) { const item = findItem(props.path) if (item) { await readFolder(item) diff --git a/src/views/reorganize/FileBrowserView.vue b/src/views/reorganize/FileBrowserView.vue index 424f3a96..15d9f342 100644 --- a/src/views/reorganize/FileBrowserView.vue +++ b/src/views/reorganize/FileBrowserView.vue @@ -2,17 +2,18 @@ import api from '@/api' import FileBrowser from '@/components/FileBrowser.vue' -const initPath = ref('/Users/jxxghp/Downloads/爱情生活 (2020)/') +const initPath = '/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' }, + download: { url: '/filebrowser/download?path={path}', method: 'get' }, }