From 1f6c924e11b13fc3983dbd4e04753cc798e44432 Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Sat, 24 Aug 2024 14:20:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201.=E6=96=B0=E5=A2=9E=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E6=92=AD=E6=94=BE=E6=8F=92=E4=BB=B6=E3=80=822.=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=8F=92=E4=BB=B6=E4=B8=AD=E5=BF=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +- pnpm-lock.yaml | 128 ++ src/App.vue | 36 +- src/class/PluginCenter.ts | 60 + src/class/VirtualDirectory.ts | 5 + src/class/VirtualPage.ts | 66 +- .../miaoDirectory/miaoDirectoryItem.vue | 37 +- src/hooks/init.ts | 22 + src/hooks/usePluginCenter.ts | 11 + src/hooks/useVirtualPages.ts | 7 +- src/style/xgplayer.scss | 2017 +++++++++++++++++ src/views/miaoDirectory.vue | 17 +- src/views/miaoVideoPlayer.vue | 100 + 13 files changed, 2465 insertions(+), 44 deletions(-) create mode 100644 src/class/PluginCenter.ts create mode 100644 src/hooks/init.ts create mode 100644 src/hooks/usePluginCenter.ts create mode 100644 src/style/xgplayer.scss create mode 100644 src/views/miaoVideoPlayer.vue diff --git a/package.json b/package.json index 1f0ee8c..e8e4359 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "lodash": "^4.17.21", "naive-ui": "^2.39.0", "sass": "^1.77.8", - "vue": "^3.4.35" + "vue": "^3.4.35", + "xgplayer": "^3.0.20" }, "devDependencies": { "@types/lodash": "^4.17.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47a85c7..6275140 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: vue: specifier: ^3.4.35 version: 3.4.37(typescript@5.5.4) + xgplayer: + specifier: ^3.0.20 + version: 3.0.20(core-js@3.38.1) devDependencies: '@types/lodash': specifier: ^4.17.7 @@ -430,6 +433,9 @@ packages: computeds@0.0.1: resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + core-js@3.38.1: + resolution: {integrity: sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==} + css-render@0.15.14: resolution: {integrity: sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg==} @@ -439,6 +445,13 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + d@1.0.2: + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} + engines: {node: '>=0.12'} + + danmu.js@1.1.13: + resolution: {integrity: sha512-knFd0/cB2HA4FFWiA7eB2suc5vCvoHdqio33FyyCSfP7C+1A+zQcTvnvwfxaZhrxsGj4qaQI2I8XiTqedRaVmg==} + date-fns-tz@2.0.1: resolution: {integrity: sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==} peerDependencies: @@ -455,21 +468,51 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + delegate@3.2.0: + resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==} + + downloadjs@1.4.7: + resolution: {integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==} + entities@5.0.0: resolution: {integrity: sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==} engines: {node: '>=0.12'} + es5-ext@0.10.64: + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} + engines: {node: '>=0.10'} + + es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + + es6-symbol@3.1.4: + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} + engines: {node: '>=0.12'} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true + esniff@2.0.1: + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} + engines: {node: '>=0.10'} + estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + evtd@0.2.4: resolution: {integrity: sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==} + ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -561,6 +604,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -622,6 +668,9 @@ packages: treemate@0.3.11: resolution: {integrity: sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg==} + type@2.7.3: + resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} + typescript@5.5.4: resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} engines: {node: '>=14.17'} @@ -700,6 +749,16 @@ packages: peerDependencies: vue: ^3.0.11 + xgplayer-subtitles@3.0.20: + resolution: {integrity: sha512-I1bjsIY+aKOrhYQspLdneOkYg+Vf4cJVGPnDSFnNebnxXl9Mhz5SEpWGzYizMYxL9UvsQ9pgjeEY0o4hkwM+kQ==} + peerDependencies: + core-js: '>=3.12.1' + + xgplayer@3.0.20: + resolution: {integrity: sha512-UNKZJRyODOZGdka83ao8fI18xdhzOV8qG4aNEOOkuOQbXFXfXsJMr/dazRHFP+uXmTqiCXr568euee3ch7CS7g==} + peerDependencies: + core-js: '>=3.12.1' + snapshots: '@babel/helper-string-parser@7.24.8': {} @@ -1003,6 +1062,8 @@ snapshots: computeds@0.0.1: {} + core-js@3.38.1: {} + css-render@0.15.14: dependencies: '@emotion/hash': 0.8.0 @@ -1012,6 +1073,15 @@ snapshots: csstype@3.1.3: {} + d@1.0.2: + dependencies: + es5-ext: 0.10.64 + type: 2.7.3 + + danmu.js@1.1.13: + dependencies: + event-emitter: 0.3.5 + date-fns-tz@2.0.1(date-fns@2.30.0): dependencies: date-fns: 2.30.0 @@ -1024,8 +1094,30 @@ snapshots: delayed-stream@1.0.0: {} + delegate@3.2.0: {} + + downloadjs@1.4.7: {} + entities@5.0.0: {} + es5-ext@0.10.64: + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.4 + esniff: 2.0.1 + next-tick: 1.1.0 + + es6-iterator@2.0.3: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + es6-symbol: 3.1.4 + + es6-symbol@3.1.4: + dependencies: + d: 1.0.2 + ext: 1.7.0 + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -1052,10 +1144,28 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + esniff@2.0.1: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + event-emitter: 0.3.5 + type: 2.7.3 + estree-walker@2.0.2: {} + event-emitter@0.3.5: + dependencies: + d: 1.0.2 + es5-ext: 0.10.64 + + eventemitter3@4.0.7: {} + evtd@0.2.4: {} + ext@1.7.0: + dependencies: + type: 2.7.3 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1143,6 +1253,8 @@ snapshots: nanoid@3.3.7: {} + next-tick@1.1.0: {} + normalize-path@3.0.0: {} path-browserify@1.0.1: {} @@ -1207,6 +1319,8 @@ snapshots: treemate@0.3.11: {} + type@2.7.3: {} + typescript@5.5.4: {} undici-types@6.13.0: {} @@ -1266,3 +1380,17 @@ snapshots: vdirs: 0.1.8(vue@3.4.37(typescript@5.5.4)) vooks: 0.2.12(vue@3.4.37(typescript@5.5.4)) vue: 3.4.37(typescript@5.5.4) + + xgplayer-subtitles@3.0.20(core-js@3.38.1): + dependencies: + core-js: 3.38.1 + eventemitter3: 4.0.7 + + xgplayer@3.0.20(core-js@3.38.1): + dependencies: + core-js: 3.38.1 + danmu.js: 1.1.13 + delegate: 3.2.0 + downloadjs: 1.4.7 + eventemitter3: 4.0.7 + xgplayer-subtitles: 3.0.20(core-js@3.38.1) diff --git a/src/App.vue b/src/App.vue index 27fc24c..a84e60b 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,12 +9,12 @@ import { EllipsisVertical, QrCodeOutline } from '@vicons/ionicons5' -import miaoDirectory from './views/miaoDirectory.vue' -import VirtualPage from './class/VirtualPage' +import miaoDirectory from '@/views/miaoDirectory.vue' import VirtualDirectory, { VirtualFile } from './class/VirtualDirectory' import MiaoMask from './components/miaoMask.vue' import config from './config' import useVirtualPages from './hooks/useVirtualPages' +import init from './hooks/init' const { baseUrl } = config @@ -46,21 +46,11 @@ const createView = ( currentFiles?: VirtualFile[], index?: number ) => { - index ?? (index = views.length) - views.splice( - index, - 0, - reactive( - new VirtualPage(component, { - directorys: [...(currentDirectorys ?? [])], - files: [...(currentFiles ?? [])] - }) - ) - ) + views.push(component, currentDirectorys, currentFiles, index) } const deleteView = (index: number) => { - views.splice(index, 1) + views.deleteView(index) if (views.length === 0) { createView(miaoDirectory, [rootDirectory]) } @@ -68,14 +58,14 @@ const deleteView = (index: number) => { // 点击标题是隐藏其他标签或显示其他标签,还挺好用的 const handleClickTitle = (index: number) => { - let count = views.filter((v) => v.visible).length - let op = !views[index].visible || count > 1 ? 'hideOthers' : 'showOthers' + let count = views._views.filter((v) => v.visible).length + let op = !views._views[index].visible || count > 1 ? 'hideOthers' : 'showOthers' let _index = 0 - while (_index < views.length) { + while (_index < views._views.length) { if (_index !== index) { - views[_index].visible = op === 'hideOthers' ? false : true + views._views[_index].visible = op === 'hideOthers' ? false : true } else { - views[_index].visible = true + views._views[_index].visible = true } _index += 1 } @@ -113,6 +103,7 @@ const handleMenuSelect = (key: string) => { } onMounted(() => { + init() createView(miaoDirectory, [rootDirectory]) }) @@ -125,7 +116,7 @@ onMounted(() => {
{
diff --git a/src/class/PluginCenter.ts b/src/class/PluginCenter.ts new file mode 100644 index 0000000..f27c07d --- /dev/null +++ b/src/class/PluginCenter.ts @@ -0,0 +1,60 @@ +import useViretualPages from "@/hooks/useVirtualPages" +import VirtualDirectory, { VirtualFile } from "./VirtualDirectory" + +type plugin = { + // 用于显示的名字 + name: string + // 判断是否可以使用这个组件 + // 使用组件即调用下面的func + filter: (VDirectorys: VirtualDirectory[], VFiles: VirtualFile[]) => boolean + func: (VDirectorys: VirtualDirectory[], VFiles: VirtualFile[]) => void +} + +export default class PluginCenter { + constructor() { + this.pluginsMap = {} + } + pluginsMap: { + [key: string]: plugin + } + + register(key: string, plugin: plugin){ + this.pluginsMap[key] = plugin + console.log(this.pluginsMap) + } + + /** + * 便捷地注册一个组件为插件,触发时直接用新页面打开 + */ + registerComponent(key: string,name: string, component: any, filter:(VDirectorys: VirtualDirectory[], VFiles: VirtualFile[]) => boolean): void { + this.register(key, { + name, + filter, + func: (VDirectorys: VirtualDirectory[], VFiles: VirtualFile[]) => { + if(filter(VDirectorys, VFiles) === false){ + return + } + const views = useViretualPages() + views.push(component, VDirectorys, VFiles) + } + }) + } + + getUsablePlugin(VDirectorys: VirtualDirectory[], VFiles: VirtualFile[]) { + const usableList = [] + for(let key of Object.keys(this.pluginsMap)) { + if(this.pluginsMap[key].filter(VDirectorys, VFiles)) { + usableList.push(key) + } + } + return usableList.map(key=>({ + key, + ...this.pluginsMap[key] + })) + } + + usePlugin(key: string, VDirectorys: VirtualDirectory[], VFiles: VirtualFile[]) { + this.pluginsMap[key].func(VDirectorys, VFiles) + } + +} \ No newline at end of file diff --git a/src/class/VirtualDirectory.ts b/src/class/VirtualDirectory.ts index 9f5c33d..78de134 100644 --- a/src/class/VirtualDirectory.ts +++ b/src/class/VirtualDirectory.ts @@ -1,3 +1,4 @@ +import config from "@/config"; import generateId from "@/hooks/generateId"; import useMiaoFetchApi from "@/hooks/useMiaoFetchApi"; // import { debounce } from "lodash"; @@ -23,6 +24,10 @@ export class VirtualFile { get path() { return `${this.parent.path}${this.name}`; } + + get url() { + return `${config.api.get}${this.parent.path}${this.name}` + } } class VirtualDirectory { diff --git a/src/class/VirtualPage.ts b/src/class/VirtualPage.ts index e67dc85..63031ee 100644 --- a/src/class/VirtualPage.ts +++ b/src/class/VirtualPage.ts @@ -1,4 +1,4 @@ -import { shallowRef } from "vue"; +import { reactive, shallowRef } from "vue"; import VirtualDirectory, { VirtualFile } from "./VirtualDirectory"; import generateId from "@/hooks/generateId"; @@ -13,7 +13,7 @@ const getRandomWebSafeColor = (() => { })(); export default class VirtualPage { - constructor(component: any, initObjects?:{ directorys?: VirtualDirectory[], files?: VirtualFile[]}) { + constructor(component: any, initObjects?: { directorys?: VirtualDirectory[]; files?: VirtualFile[] }) { this.component = shallowRef(component); this.currentDirectorys = initObjects?.directorys ?? []; this.currentFiles = initObjects?.files ?? []; @@ -43,7 +43,7 @@ export default class VirtualPage { if (this._title) { return this._title; } - return this.currentDirectorys[0].name; + return this?.currentDirectorys[0]?.name ?? this?.currentFiles[0]?.name ?? "未命名标签"; } setTitle(title: string) { @@ -61,3 +61,63 @@ export default class VirtualPage { this.refreshKey = Math.random(); } } + +export class VirtualPages { + constructor() { + this._views = reactive([]); + } + _views: VirtualPage[]; + + get length() { + return this._views.length; + } + + /** + * 查询一个页面位于_views中的次序 + * @param {any} id 要查询的页面的id + * @returns {any} + */ + getIndex(id: number) { + for (let i in this._views) { + if (this._views[i].uid === id) { + return parseInt(i); + } + } + return -1; + } + /** + * 根据id得到view + * @param {any} id 要查询的页面的id + */ + getView(id: number) { + for (let v of this._views) { + if (v.uid === id) { + return v; + } + } + return undefined; + } + + /** + * 推入一个新的页面 + */ + push(component: any, currentDirectorys?: VirtualDirectory[], currentFiles?: VirtualFile[], index?: number) { + index ?? (index = this.length); + this._views.splice( + index, + 0, + reactive( + new VirtualPage(component, { + directorys: [...(currentDirectorys ?? [])], + files: [...(currentFiles ?? [])] + }) + ) + ); + } + /** + * 根据次序删除一个页面 + */ + deleteView(index: number) { + this._views.splice(index, 1); + } +} diff --git a/src/components/miaoDirectory/miaoDirectoryItem.vue b/src/components/miaoDirectory/miaoDirectoryItem.vue index 5aebdb8..df7bef5 100644 --- a/src/components/miaoDirectory/miaoDirectoryItem.vue +++ b/src/components/miaoDirectory/miaoDirectoryItem.vue @@ -1,7 +1,7 @@