Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e75a35d10 | ||
|
|
ae476413df | ||
|
|
dcdb3a1ab8 | ||
|
|
baec1856c9 | ||
|
|
a03623a0a0 | ||
|
|
aec7fcabc9 | ||
|
|
9611e9f4ed |
No files matched your search
@@ -21,8 +21,7 @@
|
|||||||
|
|
||||||
| 长期计划 |
|
| 长期计划 |
|
||||||
|---|
|
|---|
|
||||||
| 重构virtualDirectory,使其不用直接拥有父文件夹 |
|
| 无 |
|
||||||
| 重构virtualDirectory,使其不用直接拥有父文件夹 |
|
|
||||||
|
|
||||||
## 碎碎念:
|
## 碎碎念:
|
||||||
|
|
||||||
|
|||||||
+211
-179
@@ -1,203 +1,235 @@
|
|||||||
import config from "@/config";
|
import config from '@/config'
|
||||||
import generateId from "@/hooks/generateId";
|
import generateId from '@/hooks/generateId'
|
||||||
import useMiaoFetchApi from "@/hooks/useMiaoFetchApi";
|
import useMiaoFetchApi from '@/hooks/useMiaoFetchApi'
|
||||||
import type { stats, file, directory } from "@/types/type.ts";
|
import type { stats, file, directory } from '@/types/type.ts'
|
||||||
|
import difference from 'lodash/difference'
|
||||||
|
|
||||||
const miaoFetchApi = useMiaoFetchApi();
|
const miaoFetchApi = useMiaoFetchApi()
|
||||||
|
|
||||||
const vItemMap = new Map();
|
// const vDirectoryMap = new Map<string, VirtualDirectory>()
|
||||||
|
// const vFileMap = new Map<string, VirtualFile>()
|
||||||
|
|
||||||
export interface Tree {
|
export interface Tree {
|
||||||
name: string;
|
name: string
|
||||||
type: "directory";
|
type: 'directory'
|
||||||
path: string;
|
path: string
|
||||||
stats: stats;
|
stats: stats
|
||||||
files?: {
|
files?: {
|
||||||
name: string;
|
name: string
|
||||||
type: "file";
|
type: 'file'
|
||||||
size: number;
|
size: number
|
||||||
stats: stats;
|
stats: stats
|
||||||
url: string;
|
url: string
|
||||||
}[];
|
}[]
|
||||||
directories?: Tree[];
|
directories?: Tree[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VirtualFile {
|
export class VirtualFile {
|
||||||
constructor(info: file, parent: VirtualDirectory) {
|
constructor(info: file, parent: VirtualDirectory) {
|
||||||
this.name = info.name;
|
this.name = info.name
|
||||||
this.size = info.size;
|
this.size = info.size
|
||||||
this.stats = info.stats;
|
this.stats = info.stats
|
||||||
this.parent = parent;
|
this.parent = parent
|
||||||
this.type = "file";
|
this.type = 'file'
|
||||||
this.id = generateId();
|
this.id = generateId()
|
||||||
vItemMap.set(this.path, this);
|
// if (vFileMap.get(this.path) !== undefined) {
|
||||||
}
|
// throw `${this.path} is already exist`
|
||||||
name: string;
|
// }
|
||||||
type: "file";
|
// vFileMap.set(this.path, this)
|
||||||
size: number;
|
}
|
||||||
stats: stats;
|
name: string
|
||||||
parent: VirtualDirectory;
|
type: 'file'
|
||||||
id: number;
|
size: number
|
||||||
storage: { [key: string]: any } = {};
|
stats: stats
|
||||||
get path() {
|
parent: VirtualDirectory
|
||||||
return `${this.parent.path}${this.name}`;
|
id: number
|
||||||
}
|
storage: { [key: string]: any } = {}
|
||||||
|
get path() {
|
||||||
|
return `${this.parent.path}${this.name}`
|
||||||
|
}
|
||||||
|
|
||||||
get url() {
|
get url() {
|
||||||
return `${config.api.get}${this.parent.path}${this.name}`;
|
return `${config.api.get}${this.parent.path}${this.name}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// destroy() {
|
||||||
|
// vFileMap.delete(this.path)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
class VirtualDirectory {
|
class VirtualDirectory {
|
||||||
/**
|
/**
|
||||||
* 除非为根节点,否则必须设置parent
|
* 除非为根节点,否则必须设置parent
|
||||||
*/
|
*/
|
||||||
constructor(info: directory, parent?: VirtualDirectory) {
|
constructor(info: directory, parent?: VirtualDirectory) {
|
||||||
this.name = info.name;
|
this.name = info.name
|
||||||
this.stats = info.stats;
|
this.stats = info.stats
|
||||||
this.parent = parent ?? undefined;
|
this.parent = parent ?? undefined
|
||||||
this.id = generateId();
|
this.id = generateId()
|
||||||
vItemMap.set(this.path, this);
|
// if (vDirectoryMap.get(this.path) !== undefined) {
|
||||||
}
|
// throw `${this.path} is already exist`
|
||||||
// 文件夹名
|
// }
|
||||||
name: string;
|
// vDirectoryMap.set(this.path, this)
|
||||||
// 子文件
|
}
|
||||||
files?: VirtualFile[];
|
// 文件夹名
|
||||||
// 子目录
|
name: string
|
||||||
directories?: VirtualDirectory[];
|
// 子文件
|
||||||
// 没啥意义,标注一下就是了
|
files: VirtualFile[] = []
|
||||||
type: "directory" = "directory";
|
// 子目录
|
||||||
// 文件夹创建时间等杂项属性
|
directories: VirtualDirectory[] = []
|
||||||
stats: stats;
|
// 没啥意义,标注一下就是了
|
||||||
// 父文件夹
|
type: 'directory' = 'directory'
|
||||||
parent?: VirtualDirectory;
|
// 文件夹创建时间等杂项属性
|
||||||
|
stats: stats
|
||||||
|
// 父文件夹
|
||||||
|
parent?: VirtualDirectory
|
||||||
|
|
||||||
_isUpdated: boolean = false;
|
_isUpdated: boolean = false
|
||||||
|
|
||||||
id: number;
|
id: number
|
||||||
|
|
||||||
// 用来存储一些标记信息啥的
|
// 用来存储一些标记信息啥的
|
||||||
storage: { [key: string]: any } = {};
|
storage: { [key: string]: any } = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取相对于根目录的路径的层数
|
* 获取相对于根目录的路径的层数
|
||||||
* 用于目录下文件定位
|
* 用于目录下文件定位
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
get layer(): number {
|
get layer(): number {
|
||||||
return this.parent ? this.parent.layer + 1 : 0;
|
return this.parent ? this.parent.layer + 1 : 0
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 相对于根目录的路径, 如: "/", "/123/321/"
|
* 相对于根目录的路径, 如: "/", "/123/321/"
|
||||||
* 用于目录下文件定位
|
* 用于目录下文件定位
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
get path(): string {
|
get path(): string {
|
||||||
if (!this.parent) {
|
if (!this.parent) {
|
||||||
return "/";
|
return '/'
|
||||||
}
|
}
|
||||||
return `${this.parent.path}${this.name}/`;
|
return `${this.parent.path}${this.name}/`
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取从根目录开始的按顺序的文件夹
|
* 获取从根目录开始的按顺序的文件夹
|
||||||
* @returns {VirtualDirectory[]}
|
* @returns {VirtualDirectory[]}
|
||||||
*/
|
*/
|
||||||
get getParents(): VirtualDirectory[] {
|
get getParents(): VirtualDirectory[] {
|
||||||
if (!this.parent) {
|
if (!this.parent) {
|
||||||
return [this];
|
return [this]
|
||||||
}
|
}
|
||||||
return [...this.parent.getParents, this];
|
return [...this.parent.getParents, this]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前文件夹是否已经请求过至少一次数据
|
* 获取当前文件夹是否已经请求过至少一次数据
|
||||||
*/
|
*/
|
||||||
get isUpdated() {
|
get isUpdated() {
|
||||||
return this._isUpdated;
|
return this._isUpdated
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 layer 级父文件夹, 如getParent(1)就返回父级
|
* 获取 layer 级父文件夹, 如getParent(1)就返回父级
|
||||||
* @param {number} layer 需要跳转的层数
|
* @param {number} layer 需要跳转的层数
|
||||||
* @returns {VirtualDirectory}
|
* @returns {VirtualDirectory}
|
||||||
*/
|
*/
|
||||||
getParent(layer: number): VirtualDirectory {
|
getParent(layer: number): VirtualDirectory {
|
||||||
if (layer <= 0 || !this.parent) {
|
if (layer <= 0 || !this.parent) {
|
||||||
return this;
|
return this
|
||||||
}
|
}
|
||||||
return this.parent.getParent(layer - 1);
|
return this.parent.getParent(layer - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
get tree(): Tree {
|
get tree(): Tree {
|
||||||
return {
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
path: this.path,
|
path: this.path,
|
||||||
stats: this.stats,
|
stats: this.stats,
|
||||||
files:
|
files:
|
||||||
this.files?.map(v => ({
|
this.files?.map((v) => ({
|
||||||
name: v.name,
|
name: v.name,
|
||||||
type: v.type,
|
type: v.type,
|
||||||
size: v.size,
|
size: v.size,
|
||||||
stats: v.stats,
|
stats: v.stats,
|
||||||
url: v.url
|
url: v.url
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
directories: this.directories?.map(v => v.tree) ?? []
|
directories: this.directories?.map((v) => v.tree) ?? []
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: 重构这个函数
|
// 时间复杂度大爆炸
|
||||||
updateContent(content: (file | directory)[]) {
|
updateContent(content: (file | directory)[]) {
|
||||||
this._isUpdated = true;
|
this._isUpdated = true
|
||||||
|
|
||||||
this.files = this.files ?? [];
|
const itemNames: string[] = content.map((v) => v.name)
|
||||||
this.directories = this.directories ?? [];
|
// 删去远程端已不存在的文件与文件夹
|
||||||
const fileNames: string[] = this.files.map(v => v.name);
|
const _delete = (target: (VirtualFile | VirtualDirectory)[]) => {
|
||||||
const dirNames: string[] = this.directories.map(v => v.name);
|
let index = 0
|
||||||
const itemNames: string[] = content.map(v => v.name);
|
while (index < target.length) {
|
||||||
// 删去远程端已不存在的文件与文件夹
|
if (!itemNames.includes(target[index].name)) {
|
||||||
const _delete = (target: (VirtualFile | VirtualDirectory)[]) => {
|
target.splice(index, 1)
|
||||||
let index = 0;
|
} else {
|
||||||
while (index < target.length) {
|
index += 1
|
||||||
if (!itemNames.includes(target[index].name)) {
|
}
|
||||||
target.splice(index, 1);
|
}
|
||||||
} else {
|
}
|
||||||
index += 1;
|
const _addFile = (item: file) => {
|
||||||
}
|
const nvf =
|
||||||
}
|
// vFileMap.get(`${this.path}${item.name}`) ??
|
||||||
};
|
new VirtualFile(item, this)
|
||||||
_delete(this.files);
|
this.files.push(nvf)
|
||||||
_delete(this.directories);
|
}
|
||||||
// 加入新的文件与文件夹
|
const _addDirectory = (item: directory) => {
|
||||||
for (let item of content) {
|
const nvd =
|
||||||
if (item.type === "file") {
|
// vDirectoryMap.get(`${this.path}${item.name}/`) ??
|
||||||
if (!fileNames.includes(item.name)) {
|
new VirtualDirectory(item, this)
|
||||||
this.files.push(new VirtualFile(item, this));
|
this.directories.push(nvd)
|
||||||
}
|
}
|
||||||
} else if (item.type === "directory") {
|
const newFileNames: string[] = difference(
|
||||||
if (!dirNames.includes(item.name)) {
|
content.filter((v) => v.type === 'file').map((v) => v.name),
|
||||||
this.directories.push(new VirtualDirectory(item, this));
|
this.files.map((v) => v.name)
|
||||||
}
|
)
|
||||||
}
|
const newDirectoryNames: string[] = difference(
|
||||||
}
|
content.filter((v) => v.type === 'directory').map((v) => v.name),
|
||||||
}
|
this.directories.map((v) => v.name)
|
||||||
|
)
|
||||||
|
_delete(this.files)
|
||||||
|
_delete(this.directories)
|
||||||
|
// 加入新的文件与文件夹
|
||||||
|
for (let item of content.filter((v) => newFileNames.includes(v.name))) {
|
||||||
|
_addFile(item as file)
|
||||||
|
}
|
||||||
|
for (let item of content.filter((v) =>
|
||||||
|
newDirectoryNames.includes(v.name)
|
||||||
|
)) {
|
||||||
|
_addDirectory(item as directory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hasChild(item: VirtualDirectory | VirtualFile): boolean {
|
hasChild(item: VirtualDirectory | VirtualFile): boolean {
|
||||||
if (item.type === "directory") {
|
if (item.type === 'directory') {
|
||||||
return this.directories?.includes(item) ?? false;
|
return this.directories?.includes(item) ?? false
|
||||||
} else {
|
} else {
|
||||||
return this.files?.includes(item) ?? false;
|
return this.files?.includes(item) ?? false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// destroy() {
|
||||||
* 调用后重新向远端拉取文件夹信息并进行更新
|
// for(const item of [...this.files, ...this.directories]){
|
||||||
* @returns {void}
|
// item.destroy()
|
||||||
*/
|
// }
|
||||||
async update(): Promise<void> {
|
// vDirectoryMap.delete(this.path)
|
||||||
const data: (file | directory)[] = await miaoFetchApi.get(this);
|
// }
|
||||||
this.updateContent(data);
|
|
||||||
}
|
/**
|
||||||
|
* 调用后重新向远端拉取文件夹信息并进行更新
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
async update(): Promise<void> {
|
||||||
|
const data: (file | directory)[] = await miaoFetchApi.get(this)
|
||||||
|
this.updateContent(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export default VirtualDirectory;
|
export default VirtualDirectory
|
||||||
@@ -89,6 +89,7 @@ defineExpose({ alertTip });
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.miao-message-provider-container {
|
.miao-message-provider-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container" @dragover="handleDragOver" @dragleave="handleDragLeave" @drop="handleDrop">
|
<div
|
||||||
|
class="container"
|
||||||
|
@dragover="handleDragOver"
|
||||||
|
@dragleave="handleDragLeave"
|
||||||
|
@drop="handleDrop">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<miao-mask v-model:show="showMask"></miao-mask>
|
<miao-mask v-model:show="showMask"></miao-mask>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,11 +68,15 @@ const removeDirectory = async (files: File[]) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const check = (event: DragEvent) => [
|
const check = (event: DragEvent) => {
|
||||||
...(event.dataTransfer?.files ?? []),
|
return (
|
||||||
...(dataBus.get('dragData_vFiles') ?? []),
|
[
|
||||||
...(dataBus.get('dragData_vDirectory') ?? [])
|
...(event.dataTransfer?.types?.filter(v=>v === 'Files') ?? []),
|
||||||
].length !== 0
|
...(dataBus.get('dragData_vFiles') ?? []),
|
||||||
|
...(dataBus.get('dragData_vDirectory') ?? [])
|
||||||
|
].length !== 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const handleDragOver = async (event: DragEvent) => {
|
const handleDragOver = async (event: DragEvent) => {
|
||||||
if (props.disable || check(event) === false) {
|
if (props.disable || check(event) === false) {
|
||||||
|
|||||||
@@ -53,7 +53,12 @@ export const renderIcon = (icon: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const sleep = async (timeout: number) => {
|
||||||
|
await new Promise(_=>setTimeout(_, timeout))
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
filePicker,
|
filePicker,
|
||||||
renderIcon
|
renderIcon,
|
||||||
|
sleep
|
||||||
}
|
}
|
||||||
@@ -1,28 +1,49 @@
|
|||||||
<template>
|
<template>
|
||||||
<miao-drop-handler @on-virtual-directory="handleDropVDirectory" @on-files="handleDropFiles"
|
<miao-drop-handler
|
||||||
|
@on-virtual-directory="handleDropVDirectory"
|
||||||
|
@on-files="handleDropFiles"
|
||||||
@on-virtual-files="handleDropVirtualFiles">
|
@on-virtual-files="handleDropVirtualFiles">
|
||||||
<div class="miao-directory-item-container" ref="rootDomRef">
|
<miaoAlertTipProvider ref="miaoAlertTip">
|
||||||
<!-- 顶部面包屑导航和工具栏 -->
|
<div class="miao-directory-item-container" ref="rootDomRef">
|
||||||
<miao-directory-top :color="props.color" :current-directory="currentDirectory" @back="handleBack"
|
<!-- 顶部面包屑导航和工具栏 -->
|
||||||
:open-menu-option="topBarMenuOption" @reload="handleReload" @exit="emit('exit')" :index="index"
|
<miao-directory-top
|
||||||
@set-current-directory="setCurrentDirectory" @search="handleSearch"
|
:color="props.color"
|
||||||
@menu-select="handleTopBarMenuSelect" />
|
:current-directory="currentDirectory"
|
||||||
|
@back="handleBack"
|
||||||
|
:open-menu-option="topBarMenuOption"
|
||||||
|
@reload="handleReload"
|
||||||
|
@exit="emit('exit')"
|
||||||
|
:index="index"
|
||||||
|
@set-current-directory="setCurrentDirectory"
|
||||||
|
@search="handleSearch"
|
||||||
|
@menu-select="handleTopBarMenuSelect" />
|
||||||
|
|
||||||
<!-- 文件和文件夹列表 -->
|
<!-- 文件和文件夹列表 -->
|
||||||
<miao-directory-items ref="miaoDirectoryItemRef" :color="props.color"
|
<miao-directory-items
|
||||||
:showData_directory="showData_directory" :showData_files="showData_files"
|
ref="miaoDirectoryItemRef"
|
||||||
:selected-item="selectedItem.value" :index="index" @item-click="handleItemClick"
|
:color="props.color"
|
||||||
@item-download="handleItemDownload" @item-delete="handleItemDelete"
|
:showData_directory="showData_directory"
|
||||||
@item-drag-start="handleItemDragStart" @item-rename="handleItemRename"
|
:showData_files="showData_files"
|
||||||
@item-select="handleItemSelect" />
|
:selected-item="selectedItem.value"
|
||||||
|
:index="index"
|
||||||
|
@item-click="handleItemClick"
|
||||||
|
@item-download="handleItemDownload"
|
||||||
|
@item-delete="handleItemDelete"
|
||||||
|
@item-drag-start="handleItemDragStart"
|
||||||
|
@item-rename="handleItemRename"
|
||||||
|
@item-select="handleItemSelect" />
|
||||||
|
|
||||||
<!-- 底部工具栏 -->
|
<!-- 底部工具栏 -->
|
||||||
<miao-directory-bottom :index="index" @add-new-item="handleAddNewItem" v-if="false"
|
<miao-directory-bottom
|
||||||
@pick-files-upload="handlePickFilesUpload" />
|
:index="index"
|
||||||
|
@add-new-item="handleAddNewItem"
|
||||||
|
v-if="false"
|
||||||
|
@pick-files-upload="handlePickFilesUpload" />
|
||||||
|
|
||||||
<miao-mask v-model:show="showModel"></miao-mask>
|
<miao-mask v-model:show="showModel"></miao-mask>
|
||||||
<miao-popup-input ref="popupInput"></miao-popup-input>
|
<miao-popup-input ref="popupInput"></miao-popup-input>
|
||||||
</div>
|
</div>
|
||||||
|
</miaoAlertTipProvider>
|
||||||
</miao-drop-handler>
|
</miao-drop-handler>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -37,13 +58,13 @@ import useVirtualPages from '@/hooks/useVirtualPages'
|
|||||||
import { filePicker, renderIcon } from '@/hooks/miaoTools'
|
import { filePicker, renderIcon } from '@/hooks/miaoTools'
|
||||||
import uniq from 'lodash/uniq'
|
import uniq from 'lodash/uniq'
|
||||||
|
|
||||||
// 导入子组件
|
|
||||||
import miaoDirectoryTop from './components/miaoDirectoryTop.vue'
|
import miaoDirectoryTop from './components/miaoDirectoryTop.vue'
|
||||||
import MiaoDirectoryItems from './components/miaoDirectoryItemsContainer.vue'
|
import MiaoDirectoryItems from './components/miaoDirectoryItemsContainer.vue'
|
||||||
import MiaoDirectoryBottom from './components/miaoDirectoryBottom.vue'
|
import MiaoDirectoryBottom from './components/miaoDirectoryBottom.vue'
|
||||||
import MiaoMask from '@/components/miaoMask.vue'
|
import MiaoMask from '@/components/miaoMask.vue'
|
||||||
import MiaoPopupInput from '@/components/miaoPopupInput.vue'
|
import MiaoPopupInput from '@/components/miaoPopupInput.vue'
|
||||||
import MiaoDropHandler from '@/components/miaoDropHandler.vue'
|
import MiaoDropHandler from '@/components/miaoDropHandler.vue'
|
||||||
|
import miaoAlertTipProvider from '@/components/miaoAlertTipProvider.vue'
|
||||||
import {
|
import {
|
||||||
CloseOutline,
|
CloseOutline,
|
||||||
SearchOutline,
|
SearchOutline,
|
||||||
@@ -80,6 +101,7 @@ const searchText = ref<string>('')
|
|||||||
const showDirs = ref<boolean>(true)
|
const showDirs = ref<boolean>(true)
|
||||||
const showFiles = ref<boolean>(true)
|
const showFiles = ref<boolean>(true)
|
||||||
const miaoDirectoryItemRef = ref()
|
const miaoDirectoryItemRef = ref()
|
||||||
|
const miaoAlertTip = ref<InstanceType<typeof miaoAlertTipProvider>>()
|
||||||
|
|
||||||
class SelectedItem {
|
class SelectedItem {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -182,10 +204,10 @@ const topBarMenuOption = computed(() => {
|
|||||||
},
|
},
|
||||||
searchText.value !== ''
|
searchText.value !== ''
|
||||||
? {
|
? {
|
||||||
label: '重置搜索',
|
label: '重置搜索',
|
||||||
key: 'searchReset',
|
key: 'searchReset',
|
||||||
icon: renderIcon(SearchOutline)
|
icon: renderIcon(SearchOutline)
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
// selectedItem.value.length !== 0
|
// selectedItem.value.length !== 0
|
||||||
// ? {
|
// ? {
|
||||||
@@ -227,13 +249,14 @@ const topBarMenuOption = computed(() => {
|
|||||||
label: `反选`,
|
label: `反选`,
|
||||||
key: 'multiSelect:inversion'
|
key: 'multiSelect:inversion'
|
||||||
},
|
},
|
||||||
selectedItem.value.length === 2 ?
|
selectedItem.value.length === 2
|
||||||
{
|
? {
|
||||||
label: `区间内全选`,
|
label: `区间内全选`,
|
||||||
key: 'multiSelect:range'
|
key: 'multiSelect:range'
|
||||||
} : undefined
|
}
|
||||||
|
: undefined
|
||||||
].filter((v) => v !== undefined),
|
].filter((v) => v !== undefined),
|
||||||
icon: renderIcon(CheckmarkDoneOutline),
|
icon: renderIcon(CheckmarkDoneOutline)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '插件',
|
label: '插件',
|
||||||
@@ -259,11 +282,9 @@ const topBarMenuOption = computed(() => {
|
|||||||
|
|
||||||
// 设置显示的dir
|
// 设置显示的dir
|
||||||
const setCurrentDirectory = async (virtualDirectory: VirtualDirectory) => {
|
const setCurrentDirectory = async (virtualDirectory: VirtualDirectory) => {
|
||||||
|
try {
|
||||||
// 若没有缓存数据则同步刷新,有缓存数据则异步刷新
|
// 若没有缓存数据则同步刷新,有缓存数据则异步刷新
|
||||||
if (
|
if (!virtualDirectory.isUpdated) {
|
||||||
virtualDirectory.files === undefined ||
|
|
||||||
virtualDirectory.directories === undefined
|
|
||||||
) {
|
|
||||||
await virtualDirectory.update()
|
await virtualDirectory.update()
|
||||||
} else {
|
} else {
|
||||||
virtualDirectory.update()
|
virtualDirectory.update()
|
||||||
@@ -279,6 +300,12 @@ const setCurrentDirectory = async (virtualDirectory: VirtualDirectory) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
currentDirectories.value[0] = virtualDirectory
|
currentDirectories.value[0] = virtualDirectory
|
||||||
|
} catch(e) {
|
||||||
|
miaoAlertTip.value?.alertTip(`获取文件夹内容出错`, {
|
||||||
|
type: 'error',
|
||||||
|
timeout: 3000
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const reload = () => {
|
const reload = () => {
|
||||||
@@ -315,10 +342,12 @@ const handleTopBarMenuSelect = (key: string) => {
|
|||||||
// selectedItem.clear()
|
// selectedItem.clear()
|
||||||
} else if (key === 'showDirs') {
|
} else if (key === 'showDirs') {
|
||||||
showDirs.value = !showDirs.value
|
showDirs.value = !showDirs.value
|
||||||
showDirs.value === false && selectedItem.clear(v => v.type !== 'directory')
|
showDirs.value === false &&
|
||||||
|
selectedItem.clear((v) => v.type !== 'directory')
|
||||||
} else if (key === 'showFiles') {
|
} else if (key === 'showFiles') {
|
||||||
showFiles.value = !showFiles.value
|
showFiles.value = !showFiles.value
|
||||||
showFiles.value === false && selectedItem.clear(v => v.type !== 'file')
|
showFiles.value === false &&
|
||||||
|
selectedItem.clear((v) => v.type !== 'file')
|
||||||
} else if (key.startsWith('plugin:')) {
|
} else if (key.startsWith('plugin:')) {
|
||||||
const pluginName = key.split(':')[1]
|
const pluginName = key.split(':')[1]
|
||||||
pluginCenter.usePlugin(pluginName, [currentDirectory.value], [])
|
pluginCenter.usePlugin(pluginName, [currentDirectory.value], [])
|
||||||
@@ -326,20 +355,29 @@ const handleTopBarMenuSelect = (key: string) => {
|
|||||||
const opName = key.split(':')[1]
|
const opName = key.split(':')[1]
|
||||||
switch (opName) {
|
switch (opName) {
|
||||||
case 'all':
|
case 'all':
|
||||||
selectedItem.pushArray([...showData_directory.value, ...showData_files.value])
|
selectedItem.pushArray([
|
||||||
break;
|
...showData_directory.value,
|
||||||
|
...showData_files.value
|
||||||
|
])
|
||||||
|
break
|
||||||
case 'reset':
|
case 'reset':
|
||||||
selectedItem.clear()
|
selectedItem.clear()
|
||||||
break
|
break
|
||||||
case 'inversion':
|
case 'inversion':
|
||||||
const sArr = selectedItem.value
|
const sArr = selectedItem.value
|
||||||
const arr = [...showData_directory.value, ...showData_files.value].filter(i => !sArr.includes(i))
|
const arr = [
|
||||||
|
...showData_directory.value,
|
||||||
|
...showData_files.value
|
||||||
|
].filter((i) => !sArr.includes(i))
|
||||||
selectedItem.clear()
|
selectedItem.clear()
|
||||||
selectedItem.pushArray(arr)
|
selectedItem.pushArray(arr)
|
||||||
break
|
break
|
||||||
case "range":
|
case 'range':
|
||||||
const _sArr = selectedItem.value
|
const _sArr = selectedItem.value
|
||||||
const _arr = [...showData_directory.value, ...showData_files.value]
|
const _arr = [
|
||||||
|
...showData_directory.value,
|
||||||
|
...showData_files.value
|
||||||
|
]
|
||||||
const _nArr = []
|
const _nArr = []
|
||||||
let _counter = 0
|
let _counter = 0
|
||||||
for (const i of _arr) {
|
for (const i of _arr) {
|
||||||
@@ -357,7 +395,6 @@ const handleTopBarMenuSelect = (key: string) => {
|
|||||||
selectedItem.pushArray(_nArr)
|
selectedItem.pushArray(_nArr)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +414,7 @@ const handleItemClick = (item: VirtualDirectory | VirtualFile) => {
|
|||||||
} else {
|
} else {
|
||||||
if (item.type === 'file') {
|
if (item.type === 'file') {
|
||||||
const useablePlugins = pluginCenter.getUsablePlugin([], [item])
|
const useablePlugins = pluginCenter.getUsablePlugin([], [item])
|
||||||
if(useablePlugins.length > 0){
|
if (useablePlugins.length > 0) {
|
||||||
pluginCenter.usePlugin(useablePlugins[0].key, [], [item])
|
pluginCenter.usePlugin(useablePlugins[0].key, [], [item])
|
||||||
} else {
|
} else {
|
||||||
openUrl(`${baseUrl}${api.get}${item.path}`)
|
openUrl(`${baseUrl}${api.get}${item.path}`)
|
||||||
@@ -396,7 +433,7 @@ const handleItemDownload = (item: VirtualFile) => {
|
|||||||
|
|
||||||
const handleItemDelete = async (_item: VirtualDirectory | VirtualFile) => {
|
const handleItemDelete = async (_item: VirtualDirectory | VirtualFile) => {
|
||||||
for (let item of uniq([...selectedItem.value, _item])) {
|
for (let item of uniq([...selectedItem.value, _item])) {
|
||||||
; (async () => {
|
;(async () => {
|
||||||
const { response } = miaoFetchApi.delete(item, {
|
const { response } = miaoFetchApi.delete(item, {
|
||||||
retry: 5
|
retry: 5
|
||||||
})
|
})
|
||||||
@@ -485,7 +522,7 @@ const handleDropVDirectory = async (vDirs: VirtualDirectory[]) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let dir of vDirs) {
|
for (let dir of vDirs) {
|
||||||
; (async () => {
|
;(async () => {
|
||||||
const _from = dir.parent
|
const _from = dir.parent
|
||||||
const { response } = miaoFetchApi.cut(dir, currentDirectory.value)
|
const { response } = miaoFetchApi.cut(dir, currentDirectory.value)
|
||||||
const id = (await response).eventId
|
const id = (await response).eventId
|
||||||
@@ -504,7 +541,7 @@ const handleDropVirtualFiles = (files: VirtualFile[]) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for (let file of files) {
|
for (let file of files) {
|
||||||
; (async () => {
|
;(async () => {
|
||||||
const _from = file.parent
|
const _from = file.parent
|
||||||
const { response } = miaoFetchApi.cut(file, currentDirectory.value)
|
const { response } = miaoFetchApi.cut(file, currentDirectory.value)
|
||||||
const id = (await response).eventId
|
const id = (await response).eventId
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const pluginConfig: registerComponentOption = {
|
|||||||
key: 'miaoMusicPlayer',
|
key: 'miaoMusicPlayer',
|
||||||
name: '音乐',
|
name: '音乐',
|
||||||
icon: Disc,
|
icon: Disc,
|
||||||
getComponent: async () =>
|
getComponent: async () =>
|
||||||
(await import('./miaoMusicPlayerDemo.vue')).default,
|
(await import('./miaoMusicPlayerDemo.vue')).default,
|
||||||
filter: (vDirs, vFiles) => {
|
filter: (vDirs, vFiles) => {
|
||||||
if (vDirs.length !== 0) {
|
if (vDirs.length !== 0) {
|
||||||
@@ -17,13 +17,13 @@ const pluginConfig: registerComponentOption = {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for (let i of vFiles) {
|
for (let i of vFiles) {
|
||||||
for (let s of ['mp3', 'flac', 'ogg']) {
|
for (let s of ['mp3', 'flac', 'ogg', 'mp4']) {
|
||||||
if (i.name.endsWith(s)) {
|
if (i.name.endsWith(s)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vFiles[0].name.endsWith('?')
|
return false
|
||||||
},
|
},
|
||||||
disable: false,
|
disable: false,
|
||||||
single: true,
|
single: true,
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { createApp, Reactive } from "vue";
|
import { createApp, Reactive } from "vue";
|
||||||
import aplayerListNew from "../src/aplayerListNew.vue";
|
import aplayerListNew from "../src/aplayerListNew.vue";
|
||||||
import apType from "../types/ap";
|
import apType, { audioType } from "../types/ap";
|
||||||
|
|
||||||
type aplayerMiaoOption = {
|
type aplayerMiaoOption = {
|
||||||
onDragItemStart?: () => void,
|
onDragItemStart?: () => void
|
||||||
onDragItemEnd?: () => void,
|
onDragItemEnd?: () => void
|
||||||
|
onPlayVideo?: (element: audioType) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +39,8 @@ const useAplayerMiao = (ap: Reactive<apType>, options?: aplayerMiaoOption) => {
|
|||||||
const app = createApp(aplayerListNew, { ap, ...(options ?? {}) });
|
const app = createApp(aplayerListNew, { ap, ...(options ?? {}) });
|
||||||
app.mount(new_list_dom);
|
app.mount(new_list_dom);
|
||||||
|
|
||||||
|
// console.log({ap})
|
||||||
|
|
||||||
ap.on("destroy", () => {
|
ap.on("destroy", () => {
|
||||||
app.unmount();
|
app.unmount();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,118 +1,157 @@
|
|||||||
<template>
|
<template>
|
||||||
<miao-drop-handler @on-virtual-files="handleDropVFiles">
|
<miao-drop-handler @on-virtual-files="handleDropVFiles">
|
||||||
<miao-alertTip-provider ref="miaoMessageRef">
|
<miao-alert-tip-provider ref="miaoMessageRef">
|
||||||
<div class="miaoMusic-container">
|
<div class="miaoMusic-container">
|
||||||
<NScrollbar>
|
<NScrollbar>
|
||||||
<div class="miaoMusic-main">
|
<miao-music-main v-if="ap" :ap="ap"></miao-music-main>
|
||||||
</div>
|
|
||||||
</NScrollbar>
|
</NScrollbar>
|
||||||
<div ref="aplayer" />
|
<miao-mask
|
||||||
|
:show="isAPlayerListShow"
|
||||||
|
style="z-index: 5"
|
||||||
|
@click="() => ap?.list.hide()"></miao-mask>
|
||||||
|
<div ref="aplayer" style="z-index: 10" />
|
||||||
</div>
|
</div>
|
||||||
</miao-alertTip-provider>
|
</miao-alert-tip-provider>
|
||||||
</miao-drop-handler>
|
</miao-drop-handler>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import useAplayerMiao from './hooks/aplayerMiao'
|
||||||
|
import { VirtualFile } from '@/class/VirtualDirectory'
|
||||||
|
import { App, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
||||||
|
import { NScrollbar } from 'naive-ui'
|
||||||
|
import './src/APlayer.fix.css'
|
||||||
|
// @ts-ignore
|
||||||
|
import APlayer from 'APlayer'
|
||||||
|
import config from '@/config'
|
||||||
|
import difference from 'lodash/difference'
|
||||||
|
import uniq from 'lodash/uniq'
|
||||||
|
import apType from './types/ap'
|
||||||
import miaoDropHandler from '@/components/miaoDropHandler.vue'
|
import miaoDropHandler from '@/components/miaoDropHandler.vue'
|
||||||
import miaoAlertTipProvider from '@/components/miaoAlertTipProvider.vue'
|
import miaoAlertTipProvider from '@/components/miaoAlertTipProvider.vue'
|
||||||
import useAplayerMiao from './hooks/aplayerMiao';
|
import usePluginCenter from '@/hooks/usePluginCenter'
|
||||||
import { VirtualFile } from '@/class/VirtualDirectory';
|
import VirtualPage from '@/class/VirtualPage'
|
||||||
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue';
|
import miaoMask from '@/components/miaoMask.vue'
|
||||||
import { NScrollbar } from 'naive-ui';
|
import miaoMusicMain from './src/main.vue'
|
||||||
import "./src/APlayer.fix.css"
|
|
||||||
// @ts-ignore
|
const pluginCenter = usePluginCenter()
|
||||||
import APlayer from 'APlayer';
|
let ap = ref<apType>()
|
||||||
import config from '@/config';
|
let vueApp: App<Element>
|
||||||
import difference from 'lodash/difference';
|
|
||||||
import uniq from 'lodash/uniq'
|
|
||||||
import apType from './types/ap';
|
|
||||||
|
|
||||||
const miaoMessageRef = ref<InstanceType<typeof miaoAlertTipProvider>>()
|
const miaoMessageRef = ref<InstanceType<typeof miaoAlertTipProvider>>()
|
||||||
|
const aplayer = ref<any>(null)
|
||||||
|
const isAPlayerListShow = ref(true)
|
||||||
|
|
||||||
const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
|
const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
|
||||||
required: true
|
required: true
|
||||||
});
|
|
||||||
|
|
||||||
watch(() => currentFiles.value, (value, oldValue) => {
|
|
||||||
const diff = difference(value, oldValue)
|
|
||||||
if (diff.length > 0) {
|
|
||||||
const _s = `等${diff.length}个资源`
|
|
||||||
miaoMessageRef.value?.alertTip(`已添加 ${diff[0].name}${diff.length !== 1 ? _s : ''}`, {
|
|
||||||
type: 'success',
|
|
||||||
timeout: 3000
|
|
||||||
})
|
|
||||||
ap.list.add(getMusicList(diff))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const getMusicList = (mp3VFiles: VirtualFile[]) => mp3VFiles.map((v, index) => ({
|
const props = defineProps<{
|
||||||
url: `${config.baseUrl}${v.url}`,
|
view: VirtualPage
|
||||||
name: v.name,
|
}>()
|
||||||
artist: ' ',
|
|
||||||
index
|
watch(
|
||||||
}));
|
() => currentFiles.value,
|
||||||
|
(value, oldValue) => {
|
||||||
|
const diff = difference(value, oldValue)
|
||||||
|
if (diff.length > 0) {
|
||||||
|
const _s = `等${diff.length}个资源`
|
||||||
|
miaoMessageRef.value?.alertTip(
|
||||||
|
`已添加 ${diff[0].name}${diff.length !== 1 ? _s : ''}`,
|
||||||
|
{
|
||||||
|
type: 'success',
|
||||||
|
timeout: 3000
|
||||||
|
}
|
||||||
|
)
|
||||||
|
ap?.value?.list.add(getMusicList(diff))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const getMusicList = (mp3VFiles: VirtualFile[]) =>
|
||||||
|
mp3VFiles.map((v, index) => ({
|
||||||
|
url: `${config.baseUrl}${v.url}`,
|
||||||
|
name: v.name,
|
||||||
|
artist: ' ',
|
||||||
|
index
|
||||||
|
}))
|
||||||
|
|
||||||
const handleDropVFiles = (files: VirtualFile[]) => {
|
const handleDropVFiles = (files: VirtualFile[]) => {
|
||||||
currentFiles.value = uniq([...currentFiles.value, ...files]);
|
currentFiles.value = uniq([...currentFiles.value, ...files])
|
||||||
};
|
}
|
||||||
|
|
||||||
const aplayer = ref<any>(null);
|
const initAPlayerMiao = () => {
|
||||||
|
|
||||||
const disableDropReceiver = ref(false)
|
|
||||||
|
|
||||||
let ap: apType
|
|
||||||
let vueApp: any
|
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
currentFiles.value = [...currentFiles.value.reverse()]
|
|
||||||
const aplayerOption = {
|
const aplayerOption = {
|
||||||
container: aplayer.value,
|
container: aplayer.value,
|
||||||
audio: getMusicList(currentFiles.value),
|
audio: getMusicList(currentFiles.value),
|
||||||
autoplay: true,
|
autoplay: true,
|
||||||
volume: 1,
|
volume: 1,
|
||||||
theme: "#60e8a2"
|
theme: '#60e8a2',
|
||||||
|
listMaxHeight: '500px'
|
||||||
}
|
}
|
||||||
ap = reactive<apType>(new APlayer(aplayerOption))
|
ap.value = reactive<apType>(new APlayer(aplayerOption))
|
||||||
vueApp = useAplayerMiao(ap, {
|
vueApp = useAplayerMiao(ap.value, {
|
||||||
onDragItemStart: () => {
|
onDragItemStart: () => {},
|
||||||
disableDropReceiver.value = true
|
onDragItemEnd: () => {},
|
||||||
},
|
onPlayVideo: (element) => {
|
||||||
onDragItemEnd: () => {
|
pluginCenter.usePlugin(
|
||||||
disableDropReceiver.value = false
|
'miaoVideoPlayer',
|
||||||
},
|
[],
|
||||||
|
[
|
||||||
|
currentFiles.value.find(
|
||||||
|
(v) => v.name === element.name
|
||||||
|
) as VirtualFile
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
ap.on('listremove', (...args: any) => {
|
ap.value.on('listremove', (...args: any) => {
|
||||||
const { index } = args[0] as { index: number }
|
const { index } = args[0] as { index: number }
|
||||||
const _name = ap.list.audios[index].name
|
const _name = ap?.value?.list.audios[index].name
|
||||||
currentFiles.value = currentFiles.value.filter(v => v.name !== _name)
|
currentFiles.value = currentFiles.value.filter((v) => v.name !== _name)
|
||||||
})
|
})
|
||||||
vueApp
|
ap.value.on('play', () => {
|
||||||
});
|
const name = ap.value?.list.audios[ap.value.list.index].name as string
|
||||||
|
props.view.setTitle(name)
|
||||||
|
})
|
||||||
|
ap.value.on('listshow', () => {
|
||||||
|
isAPlayerListShow.value = true
|
||||||
|
})
|
||||||
|
ap.value.on('listhide', () => {
|
||||||
|
isAPlayerListShow.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
currentFiles.value = [...currentFiles.value.reverse()]
|
||||||
|
initAPlayerMiao()
|
||||||
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
ap.destroy()
|
vueApp.unmount()
|
||||||
|
ap?.value?.destroy()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.miaoMusic-container {
|
.miaoMusic-container {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.miaoMusic-main {
|
|
||||||
padding-bottom: 88px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.aplayer {
|
.aplayer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
position: fixed;
|
position: absolute;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
width: -webkit-fill-available;
|
width: -webkit-fill-available;
|
||||||
|
.aplayer-icon-order,
|
||||||
|
.aplayer-icon-loop {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .07), 0 1px 5px 0 rgba(0, 0, 0, .1);
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .07), 0 1px 5px 0 rgba(0, 0, 0, .1);
|
||||||
border-radius: 2px;
|
border-radius: 5px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
@@ -22,10 +22,10 @@
|
|||||||
height: 100%
|
height: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
.aplayer svg circle,
|
/* .aplayer svg circle,
|
||||||
.aplayer svg path {
|
.aplayer svg path {
|
||||||
fill: #fff
|
fill: #fff
|
||||||
}
|
} */
|
||||||
|
|
||||||
.aplayer.aplayer-withlist .aplayer-info {
|
.aplayer.aplayer-withlist .aplayer-info {
|
||||||
border-bottom: 1px solid #e9e9e9
|
border-bottom: 1px solid #e9e9e9
|
||||||
@@ -427,11 +427,11 @@
|
|||||||
fill: #000
|
fill: #000
|
||||||
}
|
}
|
||||||
|
|
||||||
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon.aplayer-icon-menu,
|
/* .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon.aplayer-icon-menu,
|
||||||
.aplayer .aplayer-info .aplayer-controller .aplayer-time.aplayer-time-narrow .aplayer-icon-menu,
|
.aplayer .aplayer-info .aplayer-controller .aplayer-time.aplayer-time-narrow .aplayer-icon-menu,
|
||||||
.aplayer .aplayer-info .aplayer-controller .aplayer-time.aplayer-time-narrow .aplayer-icon-mode {
|
.aplayer .aplayer-info .aplayer-controller .aplayer-time.aplayer-time-narrow .aplayer-icon-mode {
|
||||||
display: none
|
display: none
|
||||||
}
|
} */
|
||||||
|
|
||||||
.aplayer .aplayer-info .aplayer-controller .aplayer-volume-wrap {
|
.aplayer .aplayer-info .aplayer-controller .aplayer-volume-wrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -556,9 +556,9 @@
|
|||||||
|
|
||||||
.aplayer .aplayer-list {
|
.aplayer .aplayer-list {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
transition: all .5s ease;
|
transition: all .35s ease;
|
||||||
will-change: height;
|
will-change: height;
|
||||||
display: none;
|
/* display: none; */
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,9 +604,9 @@
|
|||||||
border-top: none
|
border-top: none
|
||||||
}
|
}
|
||||||
|
|
||||||
.aplayer .aplayer-list ol li:hover {
|
/* .aplayer .aplayer-list ol li:hover {
|
||||||
background: #efefef
|
background: #efefef
|
||||||
}
|
} */
|
||||||
|
|
||||||
.aplayer .aplayer-list ol li.aplayer-list-light {
|
.aplayer .aplayer-list ol li.aplayer-list-light {
|
||||||
background: #e9e9e9
|
background: #e9e9e9
|
||||||
|
|||||||
@@ -1,70 +1,164 @@
|
|||||||
<template>
|
<template>
|
||||||
<ol :style="{ maxHeight: ap.options.listMaxHeight }" :key="refreshKey" ref="ol">
|
<div class="aplayer-list-top">
|
||||||
<VueDraggable v-model="ap.list.audios" @start="onDragStart" @end="onDragEnd" item-key="id"
|
<div @click="loopModeToggle" class="aplayer-list-top-loopMode">
|
||||||
handle=".aplayer-list-control-btn-reorder" ghostClass="iSDragging" :animation="150">
|
<component
|
||||||
<miaoLazyDiv v-for="(element, index) in ap.list.audios" :min-height="'32px'" auto-height>
|
:is="loopModeMap[loopMode].icon"
|
||||||
<li :class="activeAudioIndex == index ? 'aplayer-list-light' : ''" class="aplayer-list-new"
|
class="aplayer-list-top-loopMode-icon"></component>
|
||||||
:key="element.id">
|
<span class="aplayer-list-top-loopMode-name">
|
||||||
<span class="aplayer-list-cur" :style="{ backgroundColor: apTheme }"></span>
|
{{ loopModeMap[loopMode].name }}
|
||||||
<span class="aplayer-list-index">{{ index + 1 }}</span>
|
</span>
|
||||||
<span class="aplayer-list-title">{{ element.name }}</span>
|
</div>
|
||||||
<div class="aplayer-list-control">
|
<div class="aplayer-list-top-buttons">
|
||||||
<div class="aplayer-list-control-btn aplayer-list-control-btn-hover aplayer-list-control-btn-play"
|
<component :is="AddCircleOutline" class="aplayer-list-top-buttons-icon"></component>
|
||||||
@click.stop="switchAudio(index)">
|
</div>
|
||||||
<PlayOutline class="aplayer-list-control-btn-svg" />
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="aplayer-list-control-btn aplayer-list-control-btn-hover"
|
<ol
|
||||||
@click.stop="switchAudio(index)" v-if="false">
|
:style="{ maxHeight: ap.options.listMaxHeight }"
|
||||||
<HeartOutline class="aplayer-list-control-btn-svg" />
|
:class="[
|
||||||
</div>
|
!isDragging ? 'miaoMusic-ol-isDragging' : 'miaoMusic-ol-notDragging'
|
||||||
<div class="aplayer-list-control-btn" @click.stop="listAudioUp(index)" v-if="false">
|
]"
|
||||||
<ChevronUpOutline class="aplayer-list-control-btn-svg" />
|
:key="refreshKey"
|
||||||
</div>
|
ref="ol">
|
||||||
<div class="aplayer-list-control-btn" @click.stop="listAudioDown(index)" v-if="false">
|
<VueDraggable
|
||||||
<ChevronDownOutline class="aplayer-list-control-btn-svg" />
|
v-model="ap.list.audios"
|
||||||
</div>
|
@start="onDragStart"
|
||||||
<div class="aplayer-list-control-btn aplayer-list-control-btn-hover"
|
@end="onDragEnd"
|
||||||
@click.stop="listAudioRemove(index)">
|
item-key="id"
|
||||||
<CloseOutline class="aplayer-list-control-btn-svg" />
|
handle=".aplayer-list-control-btn-reorder"
|
||||||
</div>
|
ghostClass="iSDragging"
|
||||||
<div class="aplayer-list-control-btn aplayer-list-control-btn-reorder">
|
:animation="150">
|
||||||
<ReorderFourOutline class="aplayer-list-control-btn-svg" />
|
<!-- <miaoLazyDiv :min-height="'32px'" auto-height> -->
|
||||||
</div>
|
<li
|
||||||
|
v-for="(element, index) in ap.list.audios"
|
||||||
|
:class="[activeAudioIndex == index ? 'aplayer-list-light' : '']"
|
||||||
|
class="aplayer-list-new"
|
||||||
|
:key="element.id">
|
||||||
|
<span
|
||||||
|
class="aplayer-list-cur"
|
||||||
|
:style="{ backgroundColor: apTheme }"></span>
|
||||||
|
<span class="aplayer-list-index">{{ index + 1 }}</span>
|
||||||
|
<span class="aplayer-list-title">{{ element.name }}</span>
|
||||||
|
<div class="aplayer-list-control">
|
||||||
|
<div
|
||||||
|
v-if="isVideo(element)"
|
||||||
|
class="aplayer-list-control-btn aplayer-list-control-btn-hover aplayer-list-control-btn-play"
|
||||||
|
@click.stop="onPlayVideo(element)">
|
||||||
|
<VideocamOutline class="aplayer-list-control-btn-svg" />
|
||||||
</div>
|
</div>
|
||||||
<span class="aplayer-list-author" v-show="element.artist !== 'Audio artist1'">{{ element.artist
|
<div
|
||||||
}}</span>
|
class="aplayer-list-control-btn aplayer-list-control-btn-hover aplayer-list-control-btn-play"
|
||||||
</li>
|
@click.stop="switchAudio(index)">
|
||||||
</miaoLazyDiv>
|
<component
|
||||||
|
:is="
|
||||||
|
activeAudioIndex == index && !isPaused
|
||||||
|
? PauseOutline
|
||||||
|
: PlayOutline
|
||||||
|
"
|
||||||
|
class="aplayer-list-control-btn-svg"></component>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="aplayer-list-control-btn aplayer-list-control-btn-hover"
|
||||||
|
@click.stop="switchAudio(index)"
|
||||||
|
v-if="false">
|
||||||
|
<HeartOutline class="aplayer-list-control-btn-svg" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="aplayer-list-control-btn"
|
||||||
|
@click.stop="listAudioUp(index)"
|
||||||
|
v-if="false">
|
||||||
|
<ChevronUpOutline
|
||||||
|
class="aplayer-list-control-btn-svg" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="aplayer-list-control-btn"
|
||||||
|
@click.stop="listAudioDown(index)"
|
||||||
|
v-if="false">
|
||||||
|
<ChevronDownOutline
|
||||||
|
class="aplayer-list-control-btn-svg" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="aplayer-list-control-btn aplayer-list-control-btn-hover"
|
||||||
|
@click.stop="listAudioRemove(index)">
|
||||||
|
<CloseOutline class="aplayer-list-control-btn-svg" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="aplayer-list-control-btn aplayer-list-control-btn-reorder">
|
||||||
|
<ReorderFourOutline
|
||||||
|
class="aplayer-list-control-btn-svg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="aplayer-list-author"
|
||||||
|
v-show="element.artist !== 'Audio artist1'">
|
||||||
|
{{ element.artist }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<!-- </miaoLazyDiv> -->
|
||||||
</VueDraggable>
|
</VueDraggable>
|
||||||
</ol>
|
</ol>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, nextTick, onMounted, ref } from 'vue';
|
import { computed, nextTick, onMounted, ref } from 'vue'
|
||||||
import { ChevronUpOutline, ChevronDownOutline, CloseOutline, ReorderFourOutline, PlayOutline, HeartOutline } from '@vicons/ionicons5';
|
import {
|
||||||
|
ChevronUpOutline,
|
||||||
|
ChevronDownOutline,
|
||||||
|
CloseOutline,
|
||||||
|
ReorderFourOutline,
|
||||||
|
PlayOutline,
|
||||||
|
HeartOutline,
|
||||||
|
VideocamOutline,
|
||||||
|
PauseOutline,
|
||||||
|
ListCircleOutline,
|
||||||
|
ListOutline,
|
||||||
|
HeadsetOutline,
|
||||||
|
LogoOctocat,
|
||||||
|
AddCircleOutline
|
||||||
|
} from '@vicons/ionicons5'
|
||||||
|
|
||||||
import { VueDraggable } from 'vue-draggable-plus'
|
import { VueDraggable } from 'vue-draggable-plus'
|
||||||
import miaoLazyDiv from '@/components/miaoLazyDiv.vue';
|
// 与vue-draggable冲突
|
||||||
import apType, { audioType } from '../types/ap';
|
// import miaoLazyDiv from '@/components/miaoLazyDiv.vue';
|
||||||
|
import apType, { audioType } from '../types/ap'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
ap: apType
|
ap: apType
|
||||||
onDragItemStart: () => void,
|
onDragItemStart: () => void
|
||||||
onDragItemEnd: () => void
|
onDragItemEnd: () => void
|
||||||
|
onPlayVideo: (element: audioType) => void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const apRef = ref(props.ap)
|
||||||
|
|
||||||
const ol = ref<HTMLOListElement>()
|
const ol = ref<HTMLOListElement>()
|
||||||
|
|
||||||
const refreshKey = ref(Math.random())
|
const refreshKey = ref(Math.random())
|
||||||
|
|
||||||
const isDragging = ref(false)
|
const isDragging = ref(false)
|
||||||
|
|
||||||
const apTheme = computed(() => props.ap.list.audios[activeAudioIndex.value].theme ?? props.ap.options.theme)
|
const apTheme = computed(
|
||||||
|
() =>
|
||||||
|
props.ap.list.audios[activeAudioIndex.value].theme ??
|
||||||
|
props.ap.options.theme
|
||||||
|
)
|
||||||
|
|
||||||
const activeAudioIndex = computed(() => props.ap.list.index)
|
const activeAudioIndex = computed(() => props.ap.list.index)
|
||||||
|
const isPaused = ref(false)
|
||||||
|
|
||||||
|
props.ap.on('play', () => {
|
||||||
|
nextTick(() => {
|
||||||
|
isPaused.value = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
props.ap.on('pause', () => {
|
||||||
|
isPaused.value = true
|
||||||
|
})
|
||||||
|
|
||||||
props.ap.on('listswitch', (...args: any) => {
|
props.ap.on('listswitch', (...args: any) => {
|
||||||
// 手动触发更新,不然监听不到
|
// 手动触发更新,不然监听不到
|
||||||
props.ap.list.index = args[0].index as number;
|
props.ap.list.index = args[0].index as number
|
||||||
})
|
})
|
||||||
|
|
||||||
const refresh = () => {
|
const refresh = () => {
|
||||||
@@ -72,7 +166,7 @@ const refresh = () => {
|
|||||||
refreshKey.value = Math.random()
|
refreshKey.value = Math.random()
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
ol.value?.scrollTo({
|
ol.value?.scrollTo({
|
||||||
top,
|
top
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -82,6 +176,12 @@ props.ap.on('listadd', refresh)
|
|||||||
|
|
||||||
const switchAudio = (index: number) => {
|
const switchAudio = (index: number) => {
|
||||||
if (index === activeAudioIndex.value) {
|
if (index === activeAudioIndex.value) {
|
||||||
|
if (props.ap.paused) {
|
||||||
|
props.ap.play()
|
||||||
|
} else {
|
||||||
|
props.ap.pause()
|
||||||
|
}
|
||||||
|
props.ap.paused = props.ap.paused
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
props.ap.list.switch(index)
|
props.ap.list.switch(index)
|
||||||
@@ -96,33 +196,33 @@ const listRefreshIndex = (curr: audioType) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const listAudioUp = (index: number) => {
|
const listAudioUp = (index: number) => {
|
||||||
const arr = props.ap.list.audios;
|
const arr = props.ap.list.audios
|
||||||
const len = arr.length
|
const len = arr.length
|
||||||
const curr = props.ap.list.audios[props.ap.list.index]
|
const curr = props.ap.list.audios[props.ap.list.index]
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
const _item = arr.shift();
|
const _item = arr.shift()
|
||||||
_item && arr.push(_item);
|
_item && arr.push(_item)
|
||||||
} else {
|
} else {
|
||||||
const pre: number = (len - 1 + index) % len;
|
const pre: number = (len - 1 + index) % len
|
||||||
const _pre = arr[index];
|
const _pre = arr[index]
|
||||||
arr[index] = arr[pre];
|
arr[index] = arr[pre]
|
||||||
arr[pre] = _pre;
|
arr[pre] = _pre
|
||||||
}
|
}
|
||||||
listRefreshIndex(curr)
|
listRefreshIndex(curr)
|
||||||
};
|
}
|
||||||
|
|
||||||
const listAudioDown = (index: number) => {
|
const listAudioDown = (index: number) => {
|
||||||
const arr = props.ap.list.audios;
|
const arr = props.ap.list.audios
|
||||||
const len = arr.length
|
const len = arr.length
|
||||||
const curr = props.ap.list.audios[props.ap.list.index]
|
const curr = props.ap.list.audios[props.ap.list.index]
|
||||||
if (index === len - 1) {
|
if (index === len - 1) {
|
||||||
const _item = arr.pop();
|
const _item = arr.pop()
|
||||||
_item && arr.unshift(_item);
|
_item && arr.unshift(_item)
|
||||||
} else {
|
} else {
|
||||||
const pre: number = (len + 1 + index) % len;
|
const pre: number = (len + 1 + index) % len
|
||||||
const _pre = arr[index];
|
const _pre = arr[index]
|
||||||
arr[index] = arr[pre];
|
arr[index] = arr[pre]
|
||||||
arr[pre] = _pre;
|
arr[pre] = _pre
|
||||||
}
|
}
|
||||||
listRefreshIndex(curr)
|
listRefreshIndex(curr)
|
||||||
}
|
}
|
||||||
@@ -144,13 +244,61 @@ const { onDragStart, onDragEnd } = (() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
// const onDragEnd = (_e: any) => {
|
|
||||||
// const curr = props.ap.list.audios[props.ap.list.index]
|
const isVideo = (element: audioType) => {
|
||||||
// listRefreshIndex(curr)
|
for (let end of ['mp4']) {
|
||||||
// }
|
if (element.name.endsWith(end)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const loopModeMap = {
|
||||||
|
0: { name: '列表循环', icon: ListCircleOutline },
|
||||||
|
1: { name: '单曲循环', icon: HeadsetOutline },
|
||||||
|
2: { name: '列表播放', icon: ListOutline },
|
||||||
|
3: { name: '随机播放', icon: LogoOctocat }
|
||||||
|
}
|
||||||
|
|
||||||
|
const loopMode = computed(() => {
|
||||||
|
if (apRef.value.options.order === 'list') {
|
||||||
|
switch (apRef.value.options.loop) {
|
||||||
|
case 'all':
|
||||||
|
return 0
|
||||||
|
case 'one':
|
||||||
|
return 1
|
||||||
|
case 'none':
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 3
|
||||||
|
})
|
||||||
|
|
||||||
|
const loopModeToggle = () => {
|
||||||
|
const ops = apRef.value.options
|
||||||
|
if (ops.order === 'random') {
|
||||||
|
ops.order = 'list'
|
||||||
|
} else {
|
||||||
|
switch (ops.loop) {
|
||||||
|
case 'all': {
|
||||||
|
ops.loop = 'one'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'one': {
|
||||||
|
ops.loop = 'none'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'none': {
|
||||||
|
ops.loop = 'all'
|
||||||
|
ops.order = 'random'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// console.log(props.ap)
|
console.log(props.ap)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -188,7 +336,7 @@ onMounted(() => {
|
|||||||
&-svg {
|
&-svg {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
transition: all .1s ease;
|
transition: all 0.1s ease;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +348,60 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aplayer-list-top {
|
||||||
|
height: 30px;
|
||||||
|
// width: auto;
|
||||||
|
// max-width: 100%;
|
||||||
|
position: relative;
|
||||||
|
border-bottom: 1px solid #e9e9e9;
|
||||||
|
display: flex;
|
||||||
|
justify-items: baseline;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
.aplayer-list-top-loopMode {
|
||||||
|
text-align: center;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
float: left;
|
||||||
|
// background-color: #f9f9f9;
|
||||||
|
scale: 1;
|
||||||
|
transition: scale 0.15s ease;
|
||||||
|
&-icon {
|
||||||
|
width: 20px;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
transform: translateY(1px);
|
||||||
|
fill: #000;
|
||||||
|
path {
|
||||||
|
fill: #000 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-name {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
scale: 1.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.aplayer-list-top-buttons {
|
||||||
|
display: inline-flex;
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
scale: 1;
|
||||||
|
transition: scale 0.15s ease;
|
||||||
|
&-icon {
|
||||||
|
width: 20px;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
scale: 1.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@@ -221,11 +423,10 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.aplayer .aplayer-list ol li:hover {
|
.aplayer .aplayer-list .miaoMusic-ol-isDragging li:hover {
|
||||||
background: #efefef !important;
|
background: #efefef !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.miaoMusicDrag-move,
|
.miaoMusicDrag-move,
|
||||||
.miaoMusicDrag-enter-active,
|
.miaoMusicDrag-enter-active,
|
||||||
.miaoMusicDrag-leave-active {
|
.miaoMusicDrag-leave-active {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 29 32">
|
||||||
|
<path
|
||||||
|
d="M9.333 9.333h13.333v4l5.333-5.333-5.333-5.333v4h-16v8h2.667v-5.333zM22.667 22.667h-13.333v-4l-5.333 5.333 5.333 5.333v-4h16v-8h-2.667v5.333z"></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="miaoMusic-main">
|
||||||
|
<div class="fd" v-if="false">
|
||||||
|
{{ fakeData }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import apType from '../types/ap'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
ap: apType
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const fakeData = ref(new Array(10000).fill('我会一直盯着你'))
|
||||||
|
console.log(props.ap)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.miaoMusic-main {
|
||||||
|
padding-bottom: 88px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -9,6 +9,7 @@ export type audioType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type apType = {
|
type apType = {
|
||||||
|
paused: boolean
|
||||||
list: {
|
list: {
|
||||||
audios: audioType[]
|
audios: audioType[]
|
||||||
index: number
|
index: number
|
||||||
@@ -16,25 +17,28 @@ type apType = {
|
|||||||
remove: (index: number) => void
|
remove: (index: number) => void
|
||||||
add: (audios: audioType[]) => void
|
add: (audios: audioType[]) => void
|
||||||
refreshAudioIndex: () => void
|
refreshAudioIndex: () => void
|
||||||
|
hide: () => void
|
||||||
}
|
}
|
||||||
container: HTMLDivElement
|
container: HTMLDivElement
|
||||||
on: (event: string, callback: () => void) => void
|
on: (event: string, callback: () => void) => void
|
||||||
options: {
|
options: {
|
||||||
audio: audioType[],
|
audio: audioType[]
|
||||||
autoplay: boolean,
|
autoplay: boolean
|
||||||
"volume": number,
|
volume: number
|
||||||
"theme": string,
|
theme: string
|
||||||
"mini": boolean,
|
mini: boolean
|
||||||
"fixed": boolean,
|
fixed: boolean
|
||||||
"mutex": boolean,
|
mutex: boolean
|
||||||
"lrcType": number,
|
lrcType: number
|
||||||
"preload": "auto",
|
preload: 'auto'
|
||||||
"loop": "all",
|
loop: 'all' | 'one' | 'none'
|
||||||
"order": "list",
|
order: 'list' | 'random'
|
||||||
"listMaxHeight": string,
|
listMaxHeight: string
|
||||||
"storageName": "aplayer-setting"
|
storageName: 'aplayer-setting'
|
||||||
},
|
}
|
||||||
destroy: () => {}
|
destroy: () => {}
|
||||||
|
pause: () => void
|
||||||
|
play: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default apType
|
export default apType
|
||||||
@@ -15,14 +15,15 @@ const pluginConfig: registerComponentOption = {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for (let i of vFiles) {
|
for (let i of vFiles) {
|
||||||
for (let s of ['mp4', 'mp3']) {
|
for (let s of ['mp4']) {
|
||||||
if (i.name.endsWith(s)) {
|
if (i.name.endsWith(s)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
},
|
||||||
|
priority: 6
|
||||||
}
|
}
|
||||||
|
|
||||||
export default pluginConfig
|
export default pluginConfig
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { VirtualFile } from '@/class/VirtualDirectory'
|
|||||||
import miaoDropHandler from '@/components/miaoDropHandler.vue'
|
import miaoDropHandler from '@/components/miaoDropHandler.vue'
|
||||||
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
import { onBeforeUnmount, onMounted, ref } from 'vue'
|
||||||
import XGPlayer from 'xgplayer'
|
import XGPlayer from 'xgplayer'
|
||||||
import '@/style/xgplayer.scss'
|
import './style/xgplayer.scss'
|
||||||
import TextTrack from 'xgplayer/es/plugins/track'
|
import TextTrack from 'xgplayer/es/plugins/track'
|
||||||
import 'xgplayer/es/plugins/track/index.css'
|
import 'xgplayer/es/plugins/track/index.css'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
@@ -347,4 +347,4 @@ onBeforeUnmount(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: rgb(0, 0, 0);
|
background-color: rgb(0, 0, 0);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
background-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.37), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0.75));
|
background-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.37), rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0.75));
|
||||||
transition: opacity 0.5s ease, visibility 0.5s ease;
|
transition: opacity 0.5s ease, visibility 0.5s ease;
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
.xgplayer .xgplayer-controls.show {
|
.xgplayer .xgplayer-controls.show {
|
||||||
display: block;
|
display: block;
|
||||||
+67
-64
@@ -5,69 +5,72 @@ import { resolve } from "path";
|
|||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
base: "./",
|
base: './',
|
||||||
plugins: [
|
plugins: [
|
||||||
vue()
|
vue()
|
||||||
// viteSingleFile()
|
// viteSingleFile()
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": resolve(__dirname, "src")
|
'@': resolve(__dirname, 'src')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
"/get": {
|
'/get': {
|
||||||
target: "http://127.0.0.1:17705",
|
target: 'http://127.0.0.1:17705',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/get/, "/get")
|
rewrite: (path) => path.replace(/^\/get/, '/get')
|
||||||
},
|
},
|
||||||
|
|
||||||
"/upload": {
|
'/upload': {
|
||||||
target: "http://127.0.0.1:17705",
|
target: 'http://127.0.0.1:17705',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/upload/, "/upload")
|
rewrite: (path) => path.replace(/^\/upload/, '/upload')
|
||||||
},
|
},
|
||||||
|
|
||||||
"/delete": {
|
'/delete': {
|
||||||
target: "http://127.0.0.1:17705",
|
target: 'http://127.0.0.1:17705',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/delete/, "/delete")
|
rewrite: (path) => path.replace(/^\/delete/, '/delete')
|
||||||
},
|
},
|
||||||
"/query": {
|
'/query': {
|
||||||
target: "http://127.0.0.1:17705",
|
target: 'http://127.0.0.1:17705',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/query/, "/query")
|
rewrite: (path) => path.replace(/^\/query/, '/query')
|
||||||
},
|
},
|
||||||
"/rename": {
|
'/rename': {
|
||||||
target: "http://127.0.0.1:17705",
|
target: 'http://127.0.0.1:17705',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/rename/, "/rename")
|
rewrite: (path) => path.replace(/^\/rename/, '/rename')
|
||||||
},
|
},
|
||||||
"/cut": {
|
'/cut': {
|
||||||
target: "http://127.0.0.1:17705",
|
target: 'http://127.0.0.1:17705',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/cut/, "/cut")
|
rewrite: (path) => path.replace(/^\/cut/, '/cut')
|
||||||
},
|
},
|
||||||
"/mkdir": {
|
'/mkdir': {
|
||||||
target: "http://127.0.0.1:17705",
|
target: 'http://127.0.0.1:17705',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: path => path.replace(/^\/mkdir/, "/mkdir")
|
rewrite: (path) => path.replace(/^\/mkdir/, '/mkdir')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: {
|
input: {
|
||||||
main: "index.html"
|
main: 'index.html'
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
manualChunks(id) {
|
entryFileNames: 'assets/[name]-[hash].js',
|
||||||
if (id.includes("export.ts") && id.includes('plugins')) {
|
chunkFileNames: 'assets/chunk-[name]-[hash].js',
|
||||||
return "pluginExports";
|
assetFileNames: 'assets/[name]-[hash][extname]',
|
||||||
}
|
manualChunks(id) {
|
||||||
}
|
if (id.includes('export.ts') && id.includes('plugins')) {
|
||||||
}
|
return 'pluginExports'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in new issue
Block a user