feat: 重新组织代码结构

This commit is contained in:
539943419 committed 2024-09-04 11:47:14 +08:00
commit 4d2bd3867f
23 files changed
+240 -187

No files matched your search

@@ -1,77 +0,0 @@
<template>
<div class="miao-directory-container-bottom" :style="{
backgroundColor:
index % 2 === 1 ? 'rgb(61 61 61)' : 'rgb(162 162 162)'
}">
<div class="container-bottom-item">
<div class="container-bottom-item-icon">
<add-outline :style="{
color:
index % 2 === 0
? 'rgb(0 0 0)'
: 'rgb(255 255 255)'
}" @click="emit('add-new-item')" />
</div>
</div>
<div class="container-bottom-item">
<div class="container-bottom-item-icon">
<cloud-upload-outline :style="{
color:
index % 2 === 0
? 'rgb(0 0 0)'
: 'rgb(255 255 255)'
}" @click="emit('pick-files-upload')" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { AddOutline, CloudUploadOutline } from '@vicons/ionicons5'
defineProps<{
index: number
}>()
const emit = defineEmits<{
'add-new-item': []
'pick-files-upload': []
}>()
</script>
<style scoped lang="scss">
.miao-directory-container-bottom {
height: 60px;
background-color: bisque;
display: flex;
justify-content: space-around;
align-items: center;
user-select: none;
box-shadow: 0px 1px 10px #888888;
z-index: 2;
.container-bottom-item {
height: 40px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
.container-bottom-item-icon {
svg {
width: 30px;
height: 30px;
transition: width 0.3s ease;
transition: height 0.3s ease;
cursor: pointer;
}
&:hover {
svg {
width: 40px;
height: 40px;
}
}
}
}
}
</style>
@@ -1,289 +0,0 @@
<template>
<div class="miao-item" draggable="true" ref="itemRef" @dragstart="handleDragStart">
<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>
<div class="item-main-info">
<div class="item-main-info-name">
<Icon class="item-main-info-name-icon" v-if="clientWidth <= 250"></Icon>
<n-ellipsis :style="{ maxWidth: clientWidth > 250 ? '80%' : '75%' }">{{ name }}</n-ellipsis>
</div>
<div class="item-main-info-date" v-if="time">
{{ time }}
</div>
</div>
</div>
</miaoContextMenu>
</div>
</template>
<script setup lang="ts">
import miaoContextMenu from '../miaoContextMenu.vue'
import {
DocumentText,
FileTray,
Help,
Image,
LogoChrome,
LogoCss3,
LogoJavascript,
LogoVue,
PlayCircle,
Disc
} from '@vicons/ionicons5'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import dateFormatter from '@/hooks/dateFormatter'
import { NEllipsis } from 'naive-ui'
import { DropdownOption } from 'naive-ui/es/dropdown';
// import useMiaoFetchApi from '@/hooks/useMiaoFetchApi'
// const miaoFetchApi = useMiaoFetchApi()
const props = defineProps<{
item: {
name: string,
type: 'directory' | 'file'
stats: {
mtimeMs: number
}
}
name?: string
color: string
dropDownOptions?: DropdownOption[]
selected?: boolean
}>()
const emit = defineEmits<{
download: []
delete: []
rename: []
dragStart: [event: DragEvent]
onSelected: []
plugin: [plugin: string]
}>()
const mainRef = ref<HTMLDivElement>()
// 使用ResizeObserver实现
const clientWidth = ref<number>(666)
const name = props.name ?? props.item.name
const observer = new ResizeObserver(entries => {
for (let entry of entries) {
clientWidth.value = entry.contentRect.width;
}
});
const time = computed(() => {
return dateFormatter(
new Date(props.item.stats.mtimeMs),
'yyyy-MM-dd hh:mm:ss'
)
})
// 是不是可以直接在这里面实现?
// 应该将所有事件emit出去才对
const handleDropdownSelect = (key: string) => {
if (key === 'rename') {
emit('rename')
} else if (key === 'download') {
emit('download')
} else if (key === 'delete') {
emit('delete')
} else if (key === 'select') {
emit('onSelected')
} else if (key.startsWith('plugin:')) {
const plugin = key.split(':')[1]
emit('plugin', plugin)
}
}
const Icon = computed(() => {
try {
if (props.item.type === 'directory') {
return FileTray
} else if (props.item.type === 'file') {
const aft = props.item.name.split('.').at(-1)?.toLowerCase()
if (!aft) {
throw 1
} else if (
['txt', 'doc', 'docs', 'docx', 'xls', 'xlsx'].includes(aft)
) {
return DocumentText
} else if (
['mp3', 'wav', 'ape', 'acc', 'ogg', 'flac'].includes(aft)
) {
return Disc
} else if (
[
'xbm',
'tif',
'pjp',
'svgz',
'jpg',
'jpeg',
'ico',
'tiff',
'gif',
'svg',
'jfif',
'webp',
'png',
'bmp',
'pjpeg',
'avif'
].includes(aft)
) {
return Image
} else if (['mp4', 'm2v', 'mkv'].includes(aft)) {
return PlayCircle
} else if (['js', 'jsx', 'ts', 'tsx'].includes(aft)) {
return LogoJavascript
} else if (['html'].includes(aft)) {
return LogoChrome
} else if (['css', 'scss', 'less'].includes(aft)) {
return LogoCss3
} else if (['vue'].includes(aft)) {
return LogoVue
}
return DocumentText
}
} catch {
return Help
}
})
const itemRef = ref()
const handleDragStart = (event: DragEvent) => {
emit('dragStart', event)
// dataBus.set('dragData', [props.item])
}
onMounted(() => {
if (mainRef.value) {
observer.observe(mainRef.value);
}
})
onBeforeUnmount(() => {
if (mainRef.value) {
observer.unobserve(mainRef.value);
}
})
</script>
<style lang="scss" scoped>
.miao-item {
cursor: pointer;
width: calc(100% - 20px);
// min-width: 170px;
// aspect-ratio: 66/9;
height: 50px;
position: relative;
display: flex;
justify-content: center;
align-items: center;
margin: 10px 10px;
.item-main {
position: relative;
width: 100%;
height: 95%;
background-color: rgb(255, 255, 255);
border-radius: 7px;
display: flex;
align-items: center;
transition: background-color 0.3s ease;
.item-main-front {
height: 100%;
min-width: 10px;
border-radius: 7px 0 0 7px;
background-color: rgb(0, 0, 0);
}
.item-main-icon {
min-width: 30px;
margin-left: 10px;
height: 30px;
width: 30px;
color: #00403e;
transition: color 0.15s ease-out;
}
.item-main-info {
margin-left: 10px;
height: 100%;
width: calc(100% - 10px);
display: flex;
flex-direction: column;
&-name {
position: relative;
user-select: none;
display: flex;
align-items: center;
margin-top: 3px;
&-icon {
color: #00403e;
width: 20px;
margin-right: 5px;
transition: color 0.15s ease-out;
}
}
&-date {
user-select: none;
font-size: small;
}
}
.item-main-option {
height: 100%;
width: 20px;
position: absolute;
right: 0;
border-radius: 0 7px 7px 0;
background-color: rgba(0, 0, 0, 0);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: background-color 0.3s;
.item-main-option-icon {
color: #000;
transition: color 0.15s;
}
&:hover,
&:active {
background-color: #8b8b8b;
.item-main-option-icon {
color: #fff;
}
}
}
&:hover,
&:active {
background-color: #d2d2d2;
}
}
.item-main-selected {
background-color: rgba(0, 128, 207, 0.32);
&:hover {
background-color: rgba(0, 128, 207, 0.64);
;
}
}
}
</style>
@@ -1,181 +0,0 @@
<template>
<div
class="miao-directory-container-items"
:style="{
backgroundColor: index % 2 === 0 ? '#f8f8f8' : 'rgb(240 240 240)'
}">
<n-scrollbar ref="scrollbarRef" style="max-height: 100%">
<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.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>
</template>
<script setup lang="ts">
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 { computed, ref } from 'vue'
import usePluginCenter from '@/hooks/usePluginCenter'
import { renderIcon } from '@/hooks/miaoTools'
const pluginCenter = usePluginCenter()
const props = defineProps<{
color: string
index: number
showData_directory: VirtualDirectory[]
showData_files: VirtualFile[]
selectedItem: (VirtualFile | VirtualDirectory)[]
}>()
const emit = defineEmits<{
'item-click': [item: VirtualDirectory | VirtualFile]
'item-download': [item: VirtualFile]
'item-delete': [item: VirtualDirectory | VirtualFile]
'item-drag-start': [_event: DragEvent, item: VirtualDirectory | VirtualFile]
'item-rename': [item: VirtualDirectory | VirtualFile]
'item-select': [item: VirtualDirectory | VirtualFile]
}>()
const scrollbarRef = ref()
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}`,
icon: v.icon ? renderIcon(v.icon) : undefined
}))
)
return options
})
const handleItemClick = (item: VirtualDirectory | VirtualFile) => {
emit('item-click', item)
}
const handleItemDownload = (item: VirtualFile) => {
emit('item-download', item)
}
const handleItemDelete = (item: VirtualDirectory | VirtualFile) => {
emit('item-delete', item)
}
const handleItemDragStart =
(item: VirtualDirectory | VirtualFile) => (_event: DragEvent) => {
emit('item-drag-start', _event, item)
}
const handleItemRename = (item: VirtualDirectory | VirtualFile) => {
emit('item-rename', item)
}
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">
.miao-directory-container-items {
width: 100%;
flex: 1;
min-height: 0;
}
</style>
@@ -1,152 +0,0 @@
<template>
<div class="miao-directory-container-top" :style="{
backgroundColor:
index % 2 === 0 ? '#f8f8f8' : 'rgb(240 240 240)'
}">
<div class="container-top-colorfulBar" :style="{ backgroundColor: props.color }"></div>
<div class="container-top-breadcrumb">
<div class="container-top-breadcrumb-container">
<n-breadcrumb separator=">" style="margin-left: 5px">
<n-breadcrumb-item :clickable="false">
<n-icon size="18">
<CloudOutline />
</n-icon>
</n-breadcrumb-item>
<n-breadcrumb-item v-for="dir in currentDirectory?.getParents"
@click="handleClickBreadcrumbItem(dir)" :clickable="true">
<div>{{ dir.name }}</div>
</n-breadcrumb-item>
</n-breadcrumb>
</div>
</div>
<div class="container-top-tools">
<n-icon class="container-top-tools-item" size="15" @click="$emit('back')">
<ChevronBackOutline />
</n-icon>
<n-icon class="container-top-tools-item" size="14" @click="$emit('reload')">
<ReloadOutline class="container-top-tools-item-reload" />
</n-icon>
<n-dropdown trigger="click" :options="openMenuOption" @select="(key: string) => emit('menuSelect', key)">
<n-icon class="container-top-tools-item" size="14">
<EllipsisVertical />
</n-icon>
</n-dropdown>
</div>
</div>
</template>
<script setup lang="ts">
import { NBreadcrumbItem, NBreadcrumb, NIcon, NDropdown } from 'naive-ui'
import {
CloudOutline,
ChevronBackOutline,
ReloadOutline,
EllipsisVertical,
} from '@vicons/ionicons5'
import VirtualDirectory from '@/class/VirtualDirectory'
const props = defineProps<{
color: string;
index: number
currentDirectory: VirtualDirectory | undefined;
openMenuOption: {
key: string,
label: string,
[key: string]: any,
}[]
}>()
const emit = defineEmits<{
back: [],
reload: [],
menuSelect: [key: string]
'set-current-directory': [virtualDirectory: VirtualDirectory]
}>()
const handleClickBreadcrumbItem = (virtualDirectory: VirtualDirectory) => {
emit('set-current-directory', virtualDirectory)
}
</script>
<style scoped lang="scss">
.miao-directory-container-top {
height: 30px;
width: 100%;
user-select: none;
position: relative;
display: flex;
align-items: center;
overflow: hidden;
background-color: #f1f1f1;
.container-top-colorfulBar {
height: 70%;
width: 5px;
margin-left: 10px;
border-radius: 3px 0 0 3px;
}
.container-top-breadcrumb {
position: relative;
height: 70%;
width: calc(100% - 95px);
display: flex;
justify-content: flex-start;
align-items: center;
// overflow: hidden;
overflow-y: hidden;
overflow-x: hidden;
background-color: #ffffff;
padding: 0 5px;
border-radius: 0 3px 3px 0;
.container-top-breadcrumb-container {
position: absolute;
height: 100%;
right: 0;
top: 0;
min-width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
}
}
.container-top-tools {
position: relative;
height: 100%;
// width: 70px;
padding: 0 5px;
display: flex;
justify-content: space-around;
align-items: center;
.container-top-tools-item {
width: 20px;
height: 20px;
margin: 0 1px;
display: flex;
justify-content: center;
align-items: center;
background-color: #ffffff00;
border-radius: 5px;
transition: background-color 0.3s;
cursor: pointer;
.container-top-tools-item-reload {
transition: transform 0.6s ease-in-out;
}
&:hover {
background-color: rgba(128, 128, 128, 0.4);
}
&:active .container-top-tools-item-reload {
transform: rotate(360deg);
}
}
}
}
</style>