Compare commits

2 Commits
Author SHA1 Message Date
539943419 78dac7482c update readme 2024-09-02 00:56:05 +08:00
539943419 9aec221ea3 feat: 重构部分组件,使miaoDirectoryItem更加通用 2024-09-01 14:45:29 +08:00
7 changed files with 139 additions and 113 deletions

No files matched your search

+12
View File
@@ -7,9 +7,21 @@
| 完善PDF插件 | ✅ |
| 完善Code插件 | ✅ |
| 实现miaoDirectory的搜索功能 | ✅ |
| plugin增加些选项,icon之类的 | ❌ |
| 完善miaoDirectory的搜索功能 | ❌ |
| 实现miaoDirectory的排序功能 | ❌ |
| 完善图片浏览插件 | ❌ |
| VirtualDirectory更新时更新文件信息 | ❌ |
| 创建音乐播放器组件(仿QQ音乐移动端吧) | ❌ |
| miaoDirectory的复制文件/文件夹功能 | ❌ |
| 长期计划 |
|---|
| 重构virtualDirectory,使其不用直接拥有父文件夹 |
| 重构virtualDirectory,使其不用直接拥有父文件夹 |
## 碎碎念:
为什么不直接做成类似于windows的风格呢?其实技术实现上问题应该不大,重构也不用重构太多东西(APP.vue改改,插件部分改改这样),但是开学了事情一大堆,实习又没法比较美好地推掉。平时每天到宿舍都精疲力竭还要准备秋招和学校的破事。更何况搞不好还会被两个学分卡得没法毕业,好烦好烦。
不过可能我对插件的价值也是有所高估吧。
+3 -3
View File
@@ -114,7 +114,7 @@ onMounted(() => {
<n-scrollbar x-scrollable>
<div class="tabs-container">
<transition-group name="tab">
<div class="tab" v-for="(view, index) of views._views" :key="view.uid">
<div class="tab" v-for="(view, index) of views._views" :key="view.id">
<span class="tab-title" :title="view.title" @click="handleClickTitle(index)">
{{
view.title.length > 5 && 0
@@ -159,9 +159,9 @@ onMounted(() => {
<div class="view-container">
<transition-group name="page">
<div class="view-container-item" v-for="(view, index) of views._views" v-show="view.visible"
:key="view.uid">
:key="view.id">
<component :is="view.component" v-model:current-directories="view.currentDirectories"
v-model:current-files="view.currentFiles" :id="view.uid" :color="view.color"
v-model:current-files="view.currentFiles" :id="view.id" :color="view.color"
@exit="deleteView(index)"></component>
</div>
</transition-group>
+4 -4
View File
@@ -13,14 +13,14 @@ export class VirtualFile {
this.stats = info.stats;
this.parent = parent;
this.type = "file";
this.uid = generateId();
this.id = generateId();
}
name: string;
type: "file";
size: number;
stats: stats;
parent: VirtualDirectory;
uid: number;
id: number;
get path() {
return `${this.parent.path}${this.name}`;
}
@@ -36,7 +36,7 @@ class VirtualDirectory {
this.type = "directory";
this.stats = info.stats;
this.parent = parent ?? undefined;
this.uid = generateId();
this.id = generateId();
}
// 文件夹名
name: string;
@@ -51,7 +51,7 @@ class VirtualDirectory {
// 父文件夹
parent?: VirtualDirectory;
uid: number;
id: number;
/**
* 获取相对于根目录的路径的层数
+4 -4
View File
@@ -18,7 +18,7 @@ export default class VirtualPage {
this.currentDirectories = initObjects?.directories ?? [];
this.currentFiles = initObjects?.files ?? [];
this.visible = true;
this.uid = generateId();
this.id = generateId();
this.refreshKey = Math.random();
this.color = getRandomWebSafeColor();
}
@@ -31,7 +31,7 @@ export default class VirtualPage {
// 当前正在使用的文件
currentFiles: VirtualFile[];
// 区分每一个页面的唯一id
uid: number;
id: number;
// 当refreshKey改变时需要刷新页面,目前还没接入刷新
refreshKey: number;
// 为了区分,每个虚拟页面都会分配一个color,这个color会体现在tab上
@@ -79,7 +79,7 @@ export class VirtualPages {
*/
getIndex(id: number) {
for (let i in this._views) {
if (this._views[i].uid === id) {
if (this._views[i].id === id) {
return parseInt(i);
}
}
@@ -91,7 +91,7 @@ export class VirtualPages {
*/
getView(id: number) {
for (let v of this._views) {
if (v.uid === id) {
if (v.id === id) {
return v;
}
}
@@ -1,6 +1,6 @@
<template>
<div class="miao-item" draggable="true" ref="itemRef" @dragstart="handleDragStart">
<miaoContextMenu :options="dropDownOptions" :touch-time-out="500" @select="handleDropdownSelect">
<miaoContextMenu :options="dropDownOptions ?? []" :touch-time-out="500" @select="handleDropdownSelect">
<div class="item-main" :class="selected ? 'item-main-selected' : ''" ref="mainRef">
<div class="item-main-front" :style="{ backgroundColor: props.color }"></div>
<Icon class="item-main-icon" v-show="clientWidth > 250"></Icon>
@@ -13,19 +13,12 @@
{{ time }}
</div>
</div>
<!-- 菜单现在通过右键/长按呼出 -->
<!-- <n-dropdown trigger="click" :options="dropDownOptions" @select="handleDropdownSelect">
<div class="item-main-option" @click="(e) => e.stopPropagation()">
<EllipsisVertical class="item-main-option-icon" />
</div>
</n-dropdown> -->
</div>
</miaoContextMenu>
</div>
</template>
<script setup lang="ts">
import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory'
import miaoContextMenu from '../miaoContextMenu.vue'
import {
DocumentText,
@@ -39,33 +32,37 @@ import {
PlayCircle,
Disc
} from '@vicons/ionicons5'
import { computed, onMounted, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import dateFormatter from '@/hooks/dateFormatter'
import { NEllipsis } from 'naive-ui'
import usePluginCenter from '@/hooks/usePluginCenter'
import { DropdownOption } from 'naive-ui/es/dropdown';
// import useMiaoFetchApi from '@/hooks/useMiaoFetchApi'
// const miaoFetchApi = useMiaoFetchApi()
const props = defineProps<{
item: VirtualDirectory | VirtualFile
item: {
name: string,
type: 'directory' | 'file'
stats: {
mtimeMs: number
}
}
name?: string
color: string
selectedItem: (VirtualDirectory | VirtualFile)[]
dropDownOptions?: DropdownOption[]
selected?: boolean
}>()
const emit = defineEmits<{
download: []
delete: []
rename: []
dragStart: [event: DragEvent, item: VirtualDirectory | VirtualFile]
dragStart: [event: DragEvent]
onSelected: []
plugin: [plugin: string]
}>()
const pluginCenter = usePluginCenter()
const itemType = ref<'file' | 'directory'>(props.item.type)
const mainRef = ref<HTMLDivElement>()
// 使用ResizeObserver实现
@@ -73,9 +70,11 @@ const clientWidth = ref<number>(666)
const name = props.name ?? props.item.name
const selected = computed(() => {
return props.selectedItem.includes(props.item)
})
const observer = new ResizeObserver(entries => {
for (let entry of entries) {
clientWidth.value = entry.contentRect.width;
}
});
const time = computed(() => {
return dateFormatter(
@@ -84,59 +83,6 @@ const time = computed(() => {
)
})
const dropDownOptions = computed(() => {
const items = [...props.selectedItem]
if (!selected.value) {
items.push(props.item)
}
const vDirs = items.filter(v => v.type === 'directory')
const vFiles = items.filter(v => v.type === 'file')
const options = [
{
label: '重命名',
key: 'rename'
},
{
label: '删除',
key: 'delete'
},
]
if (itemType.value === 'file') {
options.push(
...[
{
label: '下载',
key: 'download'
}
]
)
}
if (selected.value === false) {
options.push(
...[
{
label: '多选:选择',
key: 'select'
}
]
)
} else {
options.push(
...[
{
label: '多选:取消',
key: 'select'
}
]
)
}
options.push(...pluginCenter.getUsablePlugin(vDirs, vFiles).map(v => ({
label: `插件:${v.name}`,
key: `plugin:${v.key}`
})))
return options
})
// 是不是可以直接在这里面实现?
// 应该将所有事件emit出去才对
const handleDropdownSelect = (key: string) => {
@@ -149,14 +95,8 @@ const handleDropdownSelect = (key: string) => {
} else if (key === 'select') {
emit('onSelected')
} else if (key.startsWith('plugin:')) {
const items = [...props.selectedItem]
if (!selected.value) {
items.push(props.item)
}
const vDirs = items.filter(v => v.type === 'directory')
const vFiles = items.filter(v => v.type === 'file')
const plugin = key.split(':')[1]
pluginCenter.usePlugin(plugin, vDirs, vFiles)
emit('plugin', plugin)
}
}
@@ -218,20 +158,21 @@ const Icon = computed(() => {
const itemRef = ref()
const handleDragStart = (event: DragEvent) => {
emit('dragStart', event, props.item)
emit('dragStart', event)
// dataBus.set('dragData', [props.item])
}
onMounted(() => {
const observer = new ResizeObserver(entries => {
for (let entry of entries) {
clientWidth.value = entry.contentRect.width;
}
});
if (mainRef.value) {
observer.observe(mainRef.value);
}
})
onBeforeUnmount(() => {
if (mainRef.value) {
observer.unobserve(mainRef.value);
}
})
</script>
<style lang="scss" scoped>
@@ -4,16 +4,19 @@
index % 2 === 0 ? '#f8f8f8' : 'rgb(240 240 240)'
}">
<n-scrollbar ref="scrollbarRef" style="max-height: 100%;">
<miao-lazy-div v-for="(dir, index) in showData_directory" :key="dir.uid" min-height="50px">
<miaoDirectoryItem :item="dir" :color="props.color" :selectedItem="selectedItem"
@delete="handleItemDelete(dir)" @click="handleItemClick(dir)" @drag-start="handleItemDragStart"
@rename="handleItemRename(dir)" @on-selected="handleItemSelect(dir)" />
<miao-lazy-div v-for="(dir) in showData_directory" :key="dir.id" min-height="50px">
<miaoDirectoryItem :item="dir" :color="props.color" :selected="selectedItem.includes(dir)"
:drop-down-options="itemDropDownOptions(dir).value" @delete="handleItemDelete(dir)"
@plugin="p => handleItemUsePlugin(dir)(p)" @click="handleItemClick(dir)"
@drag-start="e => handleItemDragStart(dir)(e)" @rename="handleItemRename(dir)"
@on-selected="handleItemSelect(dir)" />
</miao-lazy-div>
<miao-lazy-div v-for="(file) in showData_files" :key="file.uid" min-height="50px">
<miaoDirectoryItem :item="file" :color="props.color" :selectedItem="selectedItem"
@click="handleItemClick(file)" @download="handleItemDownload(file)" @delete="handleItemDelete(file)"
@drag-start="handleItemDragStart" @rename="handleItemRename(file)"
@on-selected="handleItemSelect(file)" />
<miao-lazy-div v-for="(file) in showData_files" :key="file.id" min-height="50px">
<miaoDirectoryItem :item="file" :color="props.color" :selected="selectedItem.includes(file)"
:drop-down-options="itemDropDownOptions(file).value" @click="handleItemClick(file)"
@download="handleItemDownload(file)" @delete="handleItemDelete(file)"
@drag-start="e => handleItemDragStart(file)(e)" @rename="handleItemRename(file)"
@plugin="p => handleItemUsePlugin(file)(p)" @on-selected="handleItemSelect(file)" />
</miao-lazy-div>
</n-scrollbar>
</div>
@@ -24,7 +27,10 @@ import { NScrollbar } from 'naive-ui'
import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory'
import miaoDirectoryItem from '@/components/miaoDirectory/miaoDirectoryItem.vue'
import miaoLazyDiv from '@/components/miaoLazyDiv.vue'
import { ref } from 'vue';
import { computed, ref } from 'vue';
import usePluginCenter from '@/hooks/usePluginCenter';
const pluginCenter = usePluginCenter()
const props = defineProps<{
color: string
@@ -45,7 +51,60 @@ const emit = defineEmits<{
const scrollbarRef = ref()
defineExpose({ scrollTo: (...args: any) => scrollbarRef.value.scrollTo(...args) });
const itemDropDownOptions = (item: VirtualDirectory | VirtualFile) => computed(() => {
const items = [...props.selectedItem]
const selected = props.selectedItem.includes(item)
if (!selected) {
items.push(item)
}
const vDirs = items.filter(v => v.type === 'directory')
const vFiles = items.filter(v => v.type === 'file')
const options = [
{
label: '重命名',
key: 'rename'
},
{
label: '删除',
key: 'delete'
},
]
if (item.type === 'file') {
options.push(
...[
{
label: '下载',
key: 'download'
}
]
)
}
if (selected === false) {
options.push(
...[
{
label: '多选:选择',
key: 'select'
}
]
)
} else {
options.push(
...[
{
label: '多选:取消',
key: 'select'
}
]
)
}
options.push(...pluginCenter.getUsablePlugin(vDirs, vFiles).map(v => ({
label: `插件:${v.name}`,
key: `plugin:${v.key}`
})))
return options
})
const handleItemClick = (item: VirtualDirectory | VirtualFile) => {
emit('item-click', item)
@@ -59,7 +118,7 @@ const handleItemDelete = (item: VirtualDirectory | VirtualFile) => {
emit('item-delete', item)
}
const handleItemDragStart = (_event: DragEvent, item: VirtualDirectory | VirtualFile) => {
const handleItemDragStart = (item: VirtualDirectory | VirtualFile) => (_event: DragEvent) => {
emit('item-drag-start', _event, item)
}
@@ -70,6 +129,20 @@ const handleItemRename = (item: VirtualDirectory | VirtualFile) => {
const handleItemSelect = (item: VirtualDirectory | VirtualFile) => {
emit('item-select', item)
}
const handleItemUsePlugin = (item: VirtualDirectory | VirtualFile) => (plugin: string) => {
const items = [...props.selectedItem]
const selected = props.selectedItem.includes(item)
if (!selected) {
items.push(item)
}
const vDirs = items.filter(v => v.type === 'directory')
const vFiles = items.filter(v => v.type === 'file')
pluginCenter.usePlugin(plugin, vDirs, vFiles)
}
defineExpose({ scrollTo: (...args: any) => scrollbarRef.value.scrollTo(...args) });
</script>
<style scoped lang="scss">
+4 -4
View File
@@ -55,7 +55,7 @@ const { setVideo } = (() => {
// console.log(srtToVtt(response.data))
const url = setUrl(new Blob([srtToVtt(response.data)]))
_list.push({
id: i.uid,
id: i.id,
url,
// 这个language会覆盖id的设置,导致无法切换字幕
// language: 'zh-cn',
@@ -66,7 +66,7 @@ const { setVideo } = (() => {
// console.log(assToVtt(response.data))
const url = setUrl(new Blob([assToVtt(response.data)]))
_list.push({
id: i.uid,
id: i.id,
url,
text: i.name
})
@@ -75,13 +75,13 @@ const { setVideo } = (() => {
// console.log(ssaToVtt(response.data))
const url = setUrl(new Blob([ssaToVtt(response.data)]))
_list.push({
id: i.uid,
id: i.id,
url,
text: i.name
})
} else {
_list.push({
id: i.uid,
id: i.id,
url: i.url,
text: i.name
})