diff --git a/README.md b/README.md index 1b55a3e..3d5d682 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ todo: 标签页,miaoDirectory切换动画 [finish] todo: 重构virtualPage,所有page以插件形式使用 [finish] -todo: miaoDirectory插件化,为后续插件功能开发做准备 [finish] -todo: miaoPopupInput, 弹出一个输入框 +todo: miaoDirectory插件化,为后续插件功能开发做准备 [finish] +todo: miaoPopupInput, 弹出一个输入框 [finish] +todo: miaoDirectory的重命名功能 [finish] +todo: miaoDirectory的剪切功能 [finish] +todo: miaoDirectory的上传按钮 [finish] +todo: VirtualDirectory更新时更新文件信息 todo: miaoDirectory的新建文件/文件夹功能 -todo: miaoDirectory的重命名功能 -todo: miaoDirectory的多选功能 -todo: VirtualDirectory更新时更新文件信息 \ No newline at end of file +todo: miaoDirectory的复制文件/文件夹功能 +todo: miaoDirectory的多选功能 \ No newline at end of file diff --git a/src/class/VirtualDirectory.ts b/src/class/VirtualDirectory.ts index 41e406c..34cb700 100644 --- a/src/class/VirtualDirectory.ts +++ b/src/class/VirtualDirectory.ts @@ -1,6 +1,9 @@ import generateId from "@/hooks/generateId"; +import useMiaoFetchApi from "@/hooks/useMiaoFetchApi"; import type { stats, file, directory } from "@/types/type.ts"; +const miaoFetchApi = useMiaoFetchApi(); + export class VirtualFile { constructor(info: file, parent: VirtualDirectory) { this.name = info.name; @@ -127,5 +130,14 @@ class VirtualDirectory { return this.files?.includes(item) ?? false; } } + + /** + * 调用后重新向远端拉取文件夹信息并进行更新 + * @returns {void} + */ + async update(): Promise { + const data: (file | directory)[] = await miaoFetchApi.get(this); + this.updateContent(data); + } } export default VirtualDirectory; diff --git a/src/components/miaoContextMenu.vue b/src/components/miaoContextMenu.vue index 42e4b69..802fc4b 100644 --- a/src/components/miaoContextMenu.vue +++ b/src/components/miaoContextMenu.vue @@ -35,12 +35,12 @@ const onClickoutside = async () => { } const handleMainMouseLeave = async () => { - // setTimeout(() => { - // showContextMenu.value -= 1 - // }, 200) - nextTick(()=>{ + setTimeout(() => { showContextMenu.value -= 1 - }) + }, 100) + // nextTick(()=>{ + // showContextMenu.value -= 1 + // }) } const handleSelect = async (key: string) => { diff --git a/src/components/miaoDirectory/miaoDirectoryItem.vue b/src/components/miaoDirectory/miaoDirectoryItem.vue index 51a6f60..c6ce7c1 100644 --- a/src/components/miaoDirectory/miaoDirectoryItem.vue +++ b/src/components/miaoDirectory/miaoDirectoryItem.vue @@ -40,6 +40,9 @@ import { } from '@vicons/ionicons5' import { computed, ref } from 'vue' import dateFormatter from '@/hooks/dateFormatter' +import useMiaoFetchApi from '@/hooks/useMiaoFetchApi' + +const miaoFetchApi = useMiaoFetchApi() const props = defineProps<{ item: VirtualDirectory | VirtualFile @@ -50,6 +53,7 @@ const props = defineProps<{ const emit = defineEmits<{ download: [] delete: [] + rename: [] dragStart: [event: DragEvent, item: VirtualDirectory | VirtualFile] }>() @@ -66,10 +70,14 @@ const time = computed(() => { const dropDownOptions = computed(() => { const options = [ + { + label: '重命名', + key: 'rename' + }, { label: '删除', key: 'delete' - } + }, ] if (itemType.value === 'file') { options.push( @@ -84,8 +92,11 @@ const dropDownOptions = computed(() => { return options }) +// 是不是可以直接在这里面实现? const handleDropdownSelect = (key: string) => { - if (key === 'download') { + if (key === 'rename') { + emit('rename') + } else if (key === 'download') { emit('download') } else if (key === 'delete') { emit('delete') diff --git a/src/components/miaoPopupInput.vue b/src/components/miaoPopupInput.vue index 3bce9f2..23096cd 100644 --- a/src/components/miaoPopupInput.vue +++ b/src/components/miaoPopupInput.vue @@ -24,6 +24,7 @@ const _resolve = ref() type popupConfigType = { title: string content?: string + inputValue?: string, inputProps?: InputProps options: { label: string @@ -36,6 +37,7 @@ const popupConfig = ref() const popup = async (config: popupConfigType) => { popupConfig.value = config + inputValue.value = config.inputValue ?? '' showMask.value = true const key = await new Promise((resolve: (key: unknown) => unknown) => { _resolve.value = resolve diff --git a/src/config.ts b/src/config.ts index d3db978..5100b80 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,7 +7,9 @@ export default { get: '/get', upload: '/upload', delete: '/delete', - query: '/query' + query: '/query', + rename: '/rename', + cut: '/cut' }, enableUpload: true, }; diff --git a/src/hooks/miaoTools.ts b/src/hooks/miaoTools.ts new file mode 100644 index 0000000..b1afac9 --- /dev/null +++ b/src/hooks/miaoTools.ts @@ -0,0 +1,47 @@ +export const filePicker = (() => { + let _resolve: ((files: File[]) => void) | undefined; + return (option?: { accept?: "string"; multiple: boolean }) => { + if (_resolve) { + _resolve([]); + _resolve = undefined; + } + return new Promise(resolve => { + const inpEle = document.createElement("input"); + inpEle.id = `__file_${Math.ceil(Math.random() * 100000000)}`; + inpEle.type = "file"; + inpEle.style.display = "none"; + _resolve = resolve; + // 文件类型限制 + // inpEle.accept="image/*" + option?.accept && (inpEle.accept = option?.accept); + // 多选限制 + option?.multiple && (inpEle.multiple = option?.multiple); + // inpEle.addEventListener("change", event => fn.call(inpEle, event, inpEle.files), { once: true }); + inpEle.addEventListener( + "change", + () => { + if (!inpEle.files) { + return; + } + const files: File[] = []; + let i = 0; + while (i < inpEle.files?.length) { + const _file = inpEle?.files?.item(i); + if (_file !== null) { + files.push(_file); + } + i += 1; + } + resolve(files); + _resolve = undefined + }, + { once: true } + ); + inpEle.click(); + }); + }; +})(); + +export default { + filePicker +}; diff --git a/src/hooks/useMiaoFetchApi.ts b/src/hooks/useMiaoFetchApi.ts index bd27f54..5f7b786 100644 --- a/src/hooks/useMiaoFetchApi.ts +++ b/src/hooks/useMiaoFetchApi.ts @@ -1,5 +1,5 @@ import VirtualDirectory, { VirtualFile } from "@/class/VirtualDirectory"; -import { getOption, getResponse, miaoFetchConfig, deleteOption, uploadOption, queryOption } from "@/types/fetch"; +import { getOption, getResponse, miaoFetchConfig, deleteOption, uploadOption, queryOption, renameOption, cutOption } from "@/types/fetch"; import Config from "@/config"; import axios, { AxiosRequestConfig } from "axios"; @@ -71,15 +71,15 @@ const miaoFetchApi = { const formData = new FormData(); formData.append("file", data); - // 必须这样传,不然中文乱码 - formData.append("fileName", data.name) + // 必须这样传,不然中文乱码 + formData.append("fileName", data.name); formData.append("oprateType", opType); return { abort: () => abortMiaoFetch(), response: new Promise<{ - message: 'success' | 'failed' - error?: string + message: "success" | "failed"; + error?: string; }>(async resolve => { const response = await miaoFetch({ url, @@ -107,7 +107,7 @@ const miaoFetchApi = { return { response: new Promise<{ - eventId: number + eventId: number; }>(async resolve => { const response = await miaoFetch({ url, @@ -117,6 +117,54 @@ const miaoFetchApi = { }) }; }, + /** + * 重命名对应的文件或文件夹 + */ + rename(target: VirtualFile | VirtualDirectory, newName: string, option?: renameOption) { + const { baseUrl, api } = Config; + const url = `${baseUrl}${api.rename}${target.path}`; + const retry = option?.retry ?? 0; + const { miaoFetch } = useMiaoFetch({ + retry + }); + + return { + response: new Promise<{ + eventId: number; + }>(async resolve => { + const response = await miaoFetch({ + url, + method: "post", + data: { newName } + }); + resolve(response.data); + }) + }; + }, + /** + * 剪切文件或文件夹 + */ + cut(target: VirtualFile | VirtualDirectory, to: VirtualDirectory, option?: cutOption) { + const newPath = to.path + const { baseUrl, api } = Config; + const url = `${baseUrl}${api.cut}${target.path}`; + const retry = option?.retry ?? 0; + const { miaoFetch } = useMiaoFetch({ + retry + }); + return { + response: new Promise<{ + eventId: number; + }>(async resolve => { + const response = await miaoFetch({ + url, + method: "post", + data: { newPath } + }); + resolve(response.data); + }) + }; + }, /** * 查询服务端操作事件的进展 @@ -130,15 +178,15 @@ const miaoFetchApi = { }); return { response: new Promise<{ - status: 'process' | 'success' | 'failed', - error?: unknown + status: "process" | "success" | "failed"; + error?: unknown; }>(async resolve => { const response = await miaoFetch({ url, method: "get", params: { - id: eventId - } + id: eventId + } }); resolve(response.data); }) diff --git a/src/types/fetch.ts b/src/types/fetch.ts index 4fe5c8d..9a21dae 100644 --- a/src/types/fetch.ts +++ b/src/types/fetch.ts @@ -1,29 +1,28 @@ import { directory, file } from "./type"; export type miaoFetchConfig = { - retry?: number -} + retry?: number; +}; -export type getOption = { -} & miaoFetchConfig +export type getOption = {} & miaoFetchConfig; -export type getResponse = (file | directory)[] +export type getResponse = (file | directory)[]; export type uploadOption = { - /** - * 上传进度回调函数 - * @param {any} percent 进度百分比,float类型 - */ - onProcess?: (percent: number) => void - /** - * 上传文件执行的操作 - * write即为覆盖写 - * append即为增量写 - */ - type?: 'write' | 'append' -} & miaoFetchConfig + /** + * 上传进度回调函数 + * @param {any} percent 进度百分比,float类型 + */ + onProcess?: (percent: number) => void; + /** + * 上传文件执行的操作 + * write即为覆盖写 + * append即为增量写 + */ + type?: "write" | "append"; +} & miaoFetchConfig; -export type deleteOption = { -} & miaoFetchConfig -export type queryOption = { -} & miaoFetchConfig \ No newline at end of file +export type deleteOption = {} & miaoFetchConfig; +export type renameOption = {} & miaoFetchConfig; +export type cutOption = {} & miaoFetchConfig; +export type queryOption = {} & miaoFetchConfig; diff --git a/src/views/miaoDirectory.vue b/src/views/miaoDirectory.vue index 2785620..7a72ddf 100644 --- a/src/views/miaoDirectory.vue +++ b/src/views/miaoDirectory.vue @@ -1,5 +1,6 @@