mirror of https://gitee.com/godoos/godoos.git
13 changed files with 416 additions and 84 deletions
@ -0,0 +1,239 @@ |
|||||
|
<template> |
||||
|
<div |
||||
|
class="item-group" |
||||
|
v-for="(item, index) in fileList" |
||||
|
:key="item.path + item.isOpen" |
||||
|
> |
||||
|
<div |
||||
|
class="file-item" |
||||
|
:class="{ |
||||
|
chosen: chosenPath === item.path, |
||||
|
// 'no-chosen': !chosenIndexs.includes(index), |
||||
|
'mode-icon': mode === 'icon', |
||||
|
'mode-list': mode === 'list', |
||||
|
}" |
||||
|
:style="{ |
||||
|
'padding-left': level * 12 + 'px', |
||||
|
}" |
||||
|
@click="handleClick(item, index)" |
||||
|
@mousedown.stop |
||||
|
> |
||||
|
<div |
||||
|
class="iconfont" |
||||
|
:class="{ |
||||
|
'open-arrow': item.isOpen, |
||||
|
'hide-arrow': item.isOpen && !item.subFileList?.length, |
||||
|
}" |
||||
|
@click.stop="onOpenArrow(item)" |
||||
|
> |
||||
|
<div class="icon-arrow-down"></div> |
||||
|
</div> |
||||
|
<div class="file-item_img"> |
||||
|
<FileIcon :file="item" /> |
||||
|
</div> |
||||
|
<span class="file-item_title">{{ getName(item) }}</span> |
||||
|
</div> |
||||
|
<div class="sub-tree"> |
||||
|
<ShareFileTree |
||||
|
v-if="item.isOpen" |
||||
|
:level="level + 1" |
||||
|
mode="list" |
||||
|
:chosen-path="chosenPath" |
||||
|
:on-refresh="() => onSubRefresh(item)" |
||||
|
:on-open="onSubOpen" |
||||
|
:file-list="item.subFileList" |
||||
|
> |
||||
|
</ShareFileTree> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script lang="ts" setup> |
||||
|
import { useSystem,OsFileWithoutContent,basename } from '@/system/index.ts'; |
||||
|
import { onMounted, ref } from 'vue'; |
||||
|
import { dealSystemName } from '@/i18n'; |
||||
|
|
||||
|
const sys = useSystem(); |
||||
|
type FileWithOpen = OsFileWithoutContent & { |
||||
|
isOpen?: boolean; |
||||
|
subFileList?: FileWithOpen[]; |
||||
|
}; |
||||
|
const props = defineProps({ |
||||
|
level: { |
||||
|
type: Number, |
||||
|
default: 0, |
||||
|
}, |
||||
|
onOpen: { |
||||
|
type: Function, |
||||
|
default: () => { |
||||
|
// |
||||
|
}, |
||||
|
}, |
||||
|
onRefresh: { |
||||
|
type: Function, |
||||
|
default: () => { |
||||
|
// |
||||
|
}, |
||||
|
}, |
||||
|
chosenPath: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
fileList: { |
||||
|
type: Array<FileWithOpen>, |
||||
|
default: () => [], |
||||
|
}, |
||||
|
|
||||
|
mode: { |
||||
|
type: String, |
||||
|
default: 'icon', |
||||
|
}, |
||||
|
}); |
||||
|
const chosenIndexs = ref<Array<number>>([]); |
||||
|
function handleClick(item: FileWithOpen, index: number) { |
||||
|
chosenIndexs.value = [index]; |
||||
|
props.onOpen(item.path); |
||||
|
} |
||||
|
|
||||
|
function getName(item:any){ |
||||
|
const name = dealSystemName(basename(item.path)) |
||||
|
return name |
||||
|
} |
||||
|
onMounted(() => { |
||||
|
chosenIndexs.value = []; |
||||
|
props.fileList.forEach((item) => { |
||||
|
item.isOpen = false; |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
function onSubOpen(path: string) { |
||||
|
props.onOpen(path); |
||||
|
} |
||||
|
|
||||
|
async function onSubRefresh(item: FileWithOpen) { |
||||
|
item.subFileList = (await sys.fs.sharedir(sys.getConfig('userInfo')?.id, item?.path)).filter((file:any) => { |
||||
|
return file.isDirectory; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
async function onOpenArrow(item: FileWithOpen) { |
||||
|
if (item.isOpen && !item.subFileList?.length) { |
||||
|
return; |
||||
|
} |
||||
|
item.isOpen = !item.isOpen; |
||||
|
item.subFileList = (await sys.fs.sharedir(sys.getConfig('userInfo')?.id, item?.path)).filter((file:any) => { |
||||
|
return file.isDirectory; |
||||
|
}); |
||||
|
} |
||||
|
</script> |
||||
|
<style lang="scss" scoped> |
||||
|
.icon-arrow-down { |
||||
|
display: block; |
||||
|
width: 4px; |
||||
|
height: 4px; |
||||
|
margin: 7px; |
||||
|
transform: translateY(0px) rotate(-45deg); |
||||
|
border: 2px solid rgba(0, 0, 0, 0.465); |
||||
|
border-left: none; |
||||
|
border-top: none; |
||||
|
transition: all 0.1s; |
||||
|
} |
||||
|
.hide-arrow { |
||||
|
border-color: transparent; |
||||
|
} |
||||
|
.open-arrow { |
||||
|
transform: translateY(-2px) translateX(2px) rotate(90deg); |
||||
|
} |
||||
|
.file-item { |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
width: 100%; |
||||
|
color: var(--icon-title-color); |
||||
|
|
||||
|
font-size: var(--ui-font-size); |
||||
|
border: 1px solid transparent; |
||||
|
margin: 2px; |
||||
|
user-select: none; |
||||
|
} |
||||
|
|
||||
|
.file-item:hover { |
||||
|
background-color: #b1f1ff4c; |
||||
|
} |
||||
|
.chosen { |
||||
|
border: 1px dashed #3bdbff3d; |
||||
|
background-color: #9595956b; |
||||
|
.file-item_title { |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
word-break: break-all; |
||||
|
display: -webkit-box; |
||||
|
-webkit-box-orient: vertical; |
||||
|
-webkit-line-clamp: 1; |
||||
|
} |
||||
|
// background-color: var(--theme-color); |
||||
|
} |
||||
|
.chosen:hover { |
||||
|
background-color: #9595956b; |
||||
|
} |
||||
|
.no-chosen { |
||||
|
.file-item_title { |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
word-break: break-all; |
||||
|
display: -webkit-box; |
||||
|
-webkit-box-orient: vertical; |
||||
|
-webkit-line-clamp: 1; |
||||
|
} |
||||
|
} |
||||
|
.mode-icon { |
||||
|
.file-item_img { |
||||
|
width: 60%; |
||||
|
height: calc(0.6 * var(--desk-item-size)); |
||||
|
margin: 0px auto; |
||||
|
user-select: none; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.file-item_title { |
||||
|
// color: var(--color-ui-desk-item-title); |
||||
|
height: calc(0.4 * var(--desk-item-size)); |
||||
|
display: block; |
||||
|
text-align: center; |
||||
|
word-break: break-all; |
||||
|
flex-grow: 0; |
||||
|
} |
||||
|
} |
||||
|
.mode-list { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
justify-content: flex-start; |
||||
|
height: calc(0.8 * var(--menulist-item-height)); |
||||
|
width: 100%; |
||||
|
|
||||
|
.file-item_img { |
||||
|
width: var(--menulist-item-height); |
||||
|
height: calc(0.6 * var(--menulist-item-height)); |
||||
|
// margin: 0px auto; |
||||
|
user-select: none; |
||||
|
flex-shrink: 0; |
||||
|
svg { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
object-fit: contain; |
||||
|
} |
||||
|
} |
||||
|
.file-item_title { |
||||
|
height: min-content; |
||||
|
|
||||
|
word-break: break-all; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
word-break: break-all; |
||||
|
display: -webkit-box; |
||||
|
-webkit-box-orient: vertical; |
||||
|
-webkit-line-clamp: 1; |
||||
|
} |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue