-
{{ view.title }}
-
-
- view.setTitle(_t)">
+
@@ -58,53 +81,70 @@ $controler-height: 25px;
display: flex;
height: $controler-height;
width: 100%;
- overflow: hidden;
+ background-color: #f2f2f2;
+ // overflow: hidden;
- .tag-short {
- position: relative;
- // margin-left: 5px;
- height: $controler-height;
- width: $controler-height;
+ .tags-container {
display: flex;
- justify-content: center;
- align-items: center;
- }
-
- .tag {
- position: relative;
- width: 170px;
- // flex: 1;
- margin: 0 5px;
- display: flex;
- border-radius: 5px 5px 0 0;
- align-items: center;
-
- &::after {
- content: '';
- height: calc($controler-height*0.6);
- width: 1px;
- border-right: 1px solid black;
- position: absolute;
- right: 0px;
- }
-
- .tag-title {
- margin-left: 4px;
- width: 70%;
- user-select: none;
- }
-
- .tag-control {
- position: absolute;
- right: 10px;
+ margin-left: 5px;
+ flex: 1;
+ // overflow-x: scroll;
+ .tag {
+ position: relative;
+ width: 170px;
+ margin: 0 5px;
+ // flex: 1;
display: flex;
+ border-radius: 5px 5px 0 0;
align-items: center;
-
-
- .tag-control-icon:not(:last-child) {
- margin-right: 5px;
+ .tag-title {
+ margin-left: 4px;
+ width: 70%;
+ user-select: none;
}
+
+ .tag-control {
+ position: absolute;
+ right: 10px;
+ display: flex;
+ align-items: center;
+
+ .tag-control-icon:not(:last-child) {
+ margin-right: 5px;
+ }
+ }
+
+ &:not(:last-child)::after {
+ content: '';
+ height: calc($controler-height*0.6);
+ width: 1px;
+ border-right: 1px solid black;
+ position: absolute;
+ right: 0px;
+ }
+ }
+ }
+
+ .view-controler-menu {
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding: 0 5px;
+ .view-controler-menu-item {
+ height: 100%;
+ aspect-ratio: 1;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+ &::before {
+ content: '';
+ height: calc($controler-height*0.6);
+ width: 1px;
+ border-right: 1px solid black;
+ position: absolute;
+ left: 2px;
}
}
@@ -123,23 +163,40 @@ $controler-height: 25px;
background-color: rgba(128, 128, 128, 0.4);
}
}
-
- .icon-larger {
- height: calc($controler-height * 0.85);
- width: calc($controler-height * 0.85);
- }
}
.view-container {
position: relative;
display: flex;
+ // flex-direction: column;
height: calc(100% - $controler-height);
+ overflow-y: overlay;
+ overflow-x: overlay;
+ &::-webkit-scrollbar {
+ position: absolute;
+ width: 4px;
+ }
+ // 滚动条轨道
+ &::-webkit-scrollbar-track {
+ // background: rgb(239, 239, 239);
+ border-radius: 2px;
+ }
+ // 小滑块
+ &::-webkit-scrollbar-thumb {
+ background: #e0e0e0;
+ // border-radius: 5px;
+ }
+ &::-webkit-scrollbar-thumb:hover {
+ background: #999999;
+ }
.view {
- border: 1px solid black;
- margin: 0 5px;
- padding: 3px;
+ // border: 1px solid black;
+ // outline: 1px solid black;
+ // margin: 0 5px;
+ // padding: 3px;
flex: 1;
+ height: 100%;
}
}
diff --git a/src/class/virtualDirectory.ts b/src/class/virtualDirectory.ts
index 6b7986a..2fbd0d1 100644
--- a/src/class/virtualDirectory.ts
+++ b/src/class/virtualDirectory.ts
@@ -1,18 +1,21 @@
+import generateId from "@/hooks/generateId";
import type { stats, file, directory } from "@/types/type.ts";
-class VirtualFile {
+export class VirtualFile {
constructor(info: file, parent: VirtualDirectory) {
this.name = info.name;
this.size = info.size;
this.stats = info.stats;
this.parent = parent;
this.type = "file";
+ this.uid = generateId()
}
name: string;
type: "file";
size: number;
stats: stats;
parent: VirtualDirectory;
+ uid: number
get path() {
return `${this.parent.path}${this.name}`;
}
@@ -24,7 +27,7 @@ class VirtualDirectory {
this.type = "directory";
this.stats = info.stats;
this.parent = parent ?? undefined;
- // 这里要改
+ this.uid = generateId()
}
// 文件夹名
name: string;
@@ -39,6 +42,8 @@ class VirtualDirectory {
// 父文件夹
parent?: VirtualDirectory;
+ uid: number
+
/**
* 获取相对于根目录的路径的层数
* 用于目录下文件定位
@@ -83,13 +88,34 @@ class VirtualDirectory {
}
setContent(content: (file | directory)[]) {
- this.files = [];
- this.directorys = [];
+ this.files = this.files ?? [];
+ this.directorys = this.directorys ?? [];
+ const fileNames:string[] = this.files.map(v=>v.name)
+ const dirNames:string[] = this.directorys.map(v=>v.name)
+ const itemNames:string[] = content.map(v=>v.name)
+ // 删去远程端已不存在的文件与文件夹
+ const _delete = (target: (VirtualFile | VirtualDirectory)[]) => {
+ let index = 0
+ while(index < target.length){
+ if(!itemNames.includes(target[index].name)){
+ target.splice(index, 1)
+ }else{
+ index += 1
+ }
+ }
+ }
+ _delete(this.files)
+ _delete(this.directorys)
+ // 加入新的文件与文件夹
for (let item of content) {
if (item.type === "file") {
- this.files.push(new VirtualFile(item, this));
+ if(!fileNames.includes(item.name)){
+ this.files.push(new VirtualFile(item, this));
+ }
} else if (item.type === "directory") {
- this.directorys.push(new VirtualDirectory(item, this));
+ if(!dirNames.includes(item.name)){
+ this.directorys.push(new VirtualDirectory(item, this));
+ }
}
}
}
diff --git a/src/class/virtualPage.ts b/src/class/virtualPage.ts
index ce34a42..7601145 100644
--- a/src/class/virtualPage.ts
+++ b/src/class/virtualPage.ts
@@ -1,22 +1,36 @@
-import { ref, Ref } from "vue";
+import VirtualDirectory from "./virtualDirectory";
+import generateId from "@/hooks/generateId";
export default class VirtualPage {
- constructor() {
- this.visible = ref
(true);
- this.title = ref("");
- this.uid = Math.ceil(Math.random() * 10000000000000);
+ constructor(initDirectory: VirtualDirectory) {
+ this.visible = true;
+ this.uid = generateId()
+ this.currentDirectory = initDirectory
+ this.refreshKey = Math.random()
}
- visible: Ref;
- title: Ref;
+ visible: boolean;
+ currentDirectory: VirtualDirectory;
+ // 区分每一个页面的唯一id
uid: number;
+ // 当refreshKey改变时需要刷新页面,目前还没接入刷新
+ refreshKey:number;
+ get title(){
+ return this.currentDirectory.name
+ }
+
+ // 切换显示状态
switchShow() {
- // @ts-ignore 你只要知道这是对的就行了
this.visible = !this.visible;
}
-
- setTitle(newTitle: string) {
- // @ts-ignore 你只要知道这是对的就行了
- this.title = newTitle;
+
+ // 设置(同步)正在展示的文件夹
+ setCurrrentDirectory(currDir: VirtualDirectory) {
+ this.currentDirectory = currDir
}
+
+ refresh(){
+ this.refreshKey = Math.random()
+ }
+
}
diff --git a/src/components/miaoDirectory/miaoDirectoryItem.vue b/src/components/miaoDirectory/miaoDirectoryItem.vue
new file mode 100644
index 0000000..f560203
--- /dev/null
+++ b/src/components/miaoDirectory/miaoDirectoryItem.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+ {{ name }}
+
+
+ {{ time }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/miaoDirectory/miaoHeader.vue b/src/components/miaoDirectory/miaoHeader.vue
new file mode 100644
index 0000000..f8a2d5a
--- /dev/null
+++ b/src/components/miaoDirectory/miaoHeader.vue
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/miaoHeader.vue b/src/components/miaoHeader.vue
deleted file mode 100644
index 32bdeb0..0000000
--- a/src/components/miaoHeader.vue
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/components/miaoMask.vue b/src/components/miaoMask.vue
new file mode 100644
index 0000000..72f3796
--- /dev/null
+++ b/src/components/miaoMask.vue
@@ -0,0 +1,47 @@
+
+
+
+ {{}}
+
+
+
+
+
diff --git a/src/hooks/dateFormatter.ts b/src/hooks/dateFormatter.ts
new file mode 100644
index 0000000..f32f9dc
--- /dev/null
+++ b/src/hooks/dateFormatter.ts
@@ -0,0 +1,20 @@
+export default function dateFormatter(date: Date, fmt: string) {
+ var o:any = {
+ "M+": date.getMonth() + 1, //月份
+ "d+": date.getDate(), //日
+ "h+": date.getHours(), //小时
+ "m+": date.getMinutes(), //分
+ "s+": date.getSeconds(), //秒
+ "q+": Math.floor((date.getMonth() + 3) / 3), //季度
+ "S": date.getMilliseconds() //毫秒
+ };
+ if (/(y+)/.test(fmt)) {
+ fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
+ }
+ for (var k in o) {
+ if (new RegExp("(" + k + ")").test(fmt)) {
+ fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
+ }
+ }
+ return fmt;
+}
diff --git a/src/hooks/dropHandler.ts b/src/hooks/dropHandler.ts
index 638c1bd..c17e1d0 100644
--- a/src/hooks/dropHandler.ts
+++ b/src/hooks/dropHandler.ts
@@ -2,14 +2,30 @@ import config from "@/config";
const { uploadSizeLimit } = config;
-type dropHandlerHooks = {
- onDrop?: (files: File[]) => void;
- onEnter?: () => void;
+export type dropHandlerHooks = {
+ /**
+ * 仅返回小于config.ts中大小限制的文件,不会返回文件夹
+ */
+ onDropFiles?: (files: File[]) => void;
/**
* 当拖动时
*/
onOver?: () => void;
+ /**
+ * 当进入时
+ */
+ onEnter?: () => void;
+
+ /**
+ * 当离开时
+ */
onLeave?: () => void;
+
+ /**
+ * 离开或是放下时都会触发
+ * @returns {any}
+ */
+ onEnd?: () => void;
};
const isFile = (file: File) =>
@@ -26,7 +42,6 @@ const isFile = (file: File) =>
reader.readAsText(file);
});
-
/**
* 只保留文件,移去文件夹
* @param {File[]} files
@@ -36,7 +51,6 @@ const filesFilter = async (files: File[]) => {
while (index < files.length) {
const currentFile = files[index];
const _isFile = await isFile(currentFile);
- console.log(_isFile);
if (_isFile) {
index += 1;
continue;
@@ -48,7 +62,6 @@ const filesFilter = async (files: File[]) => {
};
export default function dropHandler(dom: HTMLDivElement, hooks?: dropHandlerHooks) {
- console.log(dom);
dom.addEventListener(
"dragenter",
function (e) {
@@ -75,6 +88,7 @@ export default function dropHandler(dom: HTMLDivElement, hooks?: dropHandlerHook
e.preventDefault();
e.stopPropagation();
hooks?.onLeave && hooks?.onLeave();
+ hooks?.onEnd && hooks.onEnd();
},
false
);
@@ -87,7 +101,8 @@ export default function dropHandler(dom: HTMLDivElement, hooks?: dropHandlerHook
e.stopPropagation();
const files = [...(e.dataTransfer?.files ?? [])].filter(file => file.size < uploadSizeLimit);
await filesFilter(files);
- hooks?.onDrop && hooks.onDrop(files);
+ hooks?.onDropFiles && hooks.onDropFiles(files);
+ hooks?.onEnd && hooks.onEnd();
},
false
);
diff --git a/src/hooks/generateId.ts b/src/hooks/generateId.ts
new file mode 100644
index 0000000..ff0fb08
--- /dev/null
+++ b/src/hooks/generateId.ts
@@ -0,0 +1,16 @@
+const idList: number[] = [];
+
+/**
+ * 生成一个唯一的id
+ * @param {any} length 生成id的长度
+ * @returns {number}
+ */
+export default function generateId(length?: number) {
+ length || (length = 16);
+ let id;
+ while (!id || idList.includes(id)) {
+ id = Math.ceil(Math.random() * 10 ** 16);
+ }
+ idList.push(id)
+ return id
+}
diff --git a/src/hooks/useDataBus.ts b/src/hooks/useDataBus.ts
new file mode 100644
index 0000000..30721cc
--- /dev/null
+++ b/src/hooks/useDataBus.ts
@@ -0,0 +1,15 @@
+const dataStorage: any = {};
+
+export default function useDataBus() {
+ return {
+ set(key: string | number, value: any) {
+ dataStorage[key] = value;
+ return value;
+ },
+ get(key: string | number) {
+ const value = dataStorage[key];
+ dataStorage[key] = undefined;
+ return value;
+ }
+ };
+}
diff --git a/src/hooks/useMiaoFetch.ts b/src/hooks/useMiaoFetch.ts
new file mode 100644
index 0000000..f82f5cc
--- /dev/null
+++ b/src/hooks/useMiaoFetch.ts
@@ -0,0 +1,22 @@
+type miaoFetchConfig = {
+ retry: number;
+};
+
+export default function useMiaoFetch(config: miaoFetchConfig) {
+ const { retry } = config;
+
+ return async (input: RequestInfo | URL, init?: RequestInit) => {
+ let retryTimes = 0;
+ let err: any;
+ while (retryTimes <= retry) {
+ try {
+ const response = await fetch(input, init);
+ return response;
+ } catch (e) {
+ err = e;
+ retryTimes += 1;
+ }
+ }
+ throw err;
+ };
+}
diff --git a/src/views/miaoDirectory.vue b/src/views/miaoDirectory.vue
index b63d019..81989a7 100644
--- a/src/views/miaoDirectory.vue
+++ b/src/views/miaoDirectory.vue
@@ -1,16 +1,23 @@
-
-
-
- {{ dir.name }}
-
-
-
-
- {{ `file ===> ${file.name}` }}
-
+
+
+
+
+ {{ dir.name }}
+
+
+
+
+
+
+
+
+
+
@@ -20,53 +27,102 @@ import type { file, directory } from '@/types/type.ts'
import VirtualDirectory from '@/class/virtualDirectory';
import { onMounted, ref } from 'vue';
import Config from '@/config'
-import dropHandler from '@/hooks/dropHandler';
-
-const emit = defineEmits<{
- (e: 'onTitleChange', title: string): void
-}>()
+import dropHandler, { dropHandlerHooks } from '@/hooks/dropHandler';
+import miaoMask from '@/components/miaoMask.vue';
+import miaoDirectoryItem from '@/components/miaoDirectory/miaoDirectoryItem.vue';
+import useMiaoFetch from '@/hooks/useMiaoFetch';
+import useDataBus from '@/hooks/useDataBus';
const { baseUrl } = Config
+const dataBus = useDataBus()
-const rootDom = ref
()
-
-const rootDirectory = new VirtualDirectory({
- name: '根目录',
- stats: {
- atimeMs: 0,
- birthtimeMs: 0,
- ctimeMs: 0,
- mtimeMs: 0,
- }
+const miaoFetch = useMiaoFetch({
+ retry: 5,
})
-const currentDirectory = ref(rootDirectory)
+// 目前展示的Dir
+const currentDirectory = defineModel('currentDirectory', { required: true })
+
+// 是否显示模态框
+const showModel = ref(0)
+
+// 用于监听拖拽文件事件
+const rootDomRef = ref()
// 设置显示的dir
const setCurrentDirectory = async (virtualDirectory: VirtualDirectory) => {
- if (virtualDirectory.files === undefined && virtualDirectory.directorys === undefined) {
- const data: (file | directory)[] = await (await fetch(`${baseUrl}/get${virtualDirectory.path}`)).json()
+ // 若没有缓存数据则同步刷新,有缓存数据则异步刷新
+ if (virtualDirectory.files === undefined || virtualDirectory.directorys === undefined) {
+ const data: (file | directory)[] = await (await miaoFetch(`${baseUrl}/get${virtualDirectory.path}`)).json()
virtualDirectory.setContent(data)
+ } else {
+ ; (async () => {
+ const data: (file | directory)[] = await (await miaoFetch(`${baseUrl}/get${virtualDirectory.path}`)).json()
+ virtualDirectory.setContent(data)
+ currentDirectory.value = undefined
+ currentDirectory.value = virtualDirectory
+ })()
}
// 刷新一下
currentDirectory.value = undefined
currentDirectory.value = virtualDirectory
- emit("onTitleChange", currentDirectory.value.name)
+ // emit("onCurrentDirectoryChange", currentDirectory.value)
+}
+
+const openUrl = (href: string) => {
+ var oA = document.createElement("a");
+ oA.href = href;
+ oA.target = "_blank";
+ oA.click();
}
onMounted(async () => {
- await setCurrentDirectory(rootDirectory)
- rootDom.value && dropHandler(rootDom.value, {
- onDrop(files){
- console.log(files, files.map(v=>v.name))
- }
- })
+ currentDirectory.value && await setCurrentDirectory(currentDirectory.value)
+ // 拖动事件处理
+ const dropFileOption:dropHandlerHooks = {
+ onDropFiles(files: File[]) {
+ const dragData = dataBus.get('dragData')
+ console.log({dragData, files})
+ },
+ onEnter() {
+ showModel.value += 1
+ },
+ onEnd() {
+ showModel.value -= 1
+ },
+ }
+ rootDomRef.value && dropHandler(rootDomRef.value, dropFileOption)
})