mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
修复搜索结果卡片视图筛选可视性,优化季集显示位置,重构nodatafound情形ui,重构文件管理器ui并增加文件树功能,优化侧边栏高度规避竖向滑动条
This commit is contained in:
@@ -112,86 +112,279 @@ const sortIcon = computed(() => {
|
||||
if (sort.value === 'time') return 'mdi-sort-clock-ascending-outline'
|
||||
else return 'mdi-sort-alphabetical-ascending'
|
||||
})
|
||||
|
||||
// 保存路径片段引用
|
||||
const pathSegmentRef = ref<HTMLElement | null>(null)
|
||||
|
||||
// 检查文本是否被截断
|
||||
function checkTextTruncated(event: MouseEvent) {
|
||||
const target = event.target as HTMLElement
|
||||
if (!target) return
|
||||
|
||||
// 动态设置tooltip是否禁用
|
||||
const isTextOverflowing = target.offsetWidth < target.scrollWidth
|
||||
|
||||
// 找到最近的tooltip组件并设置disabled属性
|
||||
const tooltipEl = target.closest('.v-tooltip')
|
||||
if (tooltipEl) {
|
||||
const tooltipComponent = (tooltipEl as any).__vue__
|
||||
if (tooltipComponent && tooltipComponent.isActive !== undefined) {
|
||||
tooltipComponent.isActive = isTextOverflowing
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VToolbar flat dense>
|
||||
<VToolbarItems class="overflow-hidden">
|
||||
<VMenu v-if="inProps.storages?.length || 0 > 1" offset-y>
|
||||
<template #activator="{ props }">
|
||||
<VBtn v-bind="props">
|
||||
<VIcon icon="mdi-arrow-down-drop-circle-outline" />
|
||||
<VToolbar flat dense class="file-toolbar">
|
||||
<VToolbarItems class="overflow-hidden w-100">
|
||||
<VBtn
|
||||
variant="text"
|
||||
:input-value="inProps.item?.path === '/'"
|
||||
color="primary"
|
||||
class="px-1 path-button home-button"
|
||||
@click="changePath(inProps.itemstack[0])"
|
||||
>
|
||||
<VIcon icon="mdi-home" class="me-2" />
|
||||
<span class="text-truncate">根目录</span>
|
||||
</VBtn>
|
||||
|
||||
<div class="breadcrumb">
|
||||
<template v-for="(segment, index) in pathSegments" :key="index">
|
||||
<VBtn
|
||||
v-if="display.mdAndUp.value"
|
||||
variant="text"
|
||||
color="primary"
|
||||
density="comfortable"
|
||||
:input-value="index === pathSegments.length - 1"
|
||||
:class="['px-1', 'path-button', {'current-path': index === pathSegments.length - 1}]"
|
||||
@click="changePath(inProps.itemstack[index + 1])"
|
||||
>
|
||||
<VIcon icon="mdi-chevron-right" size="small" />
|
||||
<VTooltip>
|
||||
<template #activator="{ props }">
|
||||
<span
|
||||
class="path-segment"
|
||||
v-bind="props"
|
||||
ref="pathSegmentRef"
|
||||
@mouseover="checkTextTruncated"
|
||||
>
|
||||
{{ segment.name }}
|
||||
</span>
|
||||
</template>
|
||||
{{ segment.name }}
|
||||
</VTooltip>
|
||||
</VBtn>
|
||||
</template>
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, index) in storages"
|
||||
:key="index"
|
||||
:disabled="item.value === storageObject?.value"
|
||||
@click="changeStorage(item.value)"
|
||||
>
|
||||
<template #prepend>
|
||||
<Icon :icon="item.icon" />
|
||||
</div>
|
||||
|
||||
<VSpacer />
|
||||
|
||||
<div class="file-actions">
|
||||
<VTooltip text="调整排序">
|
||||
<template #activator="{ props }">
|
||||
<VBtn
|
||||
v-bind="props"
|
||||
@click="changeSort"
|
||||
icon
|
||||
variant="text"
|
||||
color="primary"
|
||||
class="action-button"
|
||||
>
|
||||
<VIcon :icon="sortIcon" />
|
||||
</VBtn>
|
||||
</template>
|
||||
</VTooltip>
|
||||
|
||||
<VTooltip text="返回上一级" v-if="pathSegments.length > 0">
|
||||
<template #activator="{ props }">
|
||||
<VBtn
|
||||
v-bind="props"
|
||||
@click="goUp"
|
||||
icon
|
||||
variant="text"
|
||||
color="primary"
|
||||
class="action-button"
|
||||
>
|
||||
<VIcon icon="mdi-arrow-up" />
|
||||
</VBtn>
|
||||
</template>
|
||||
</VTooltip>
|
||||
|
||||
<VDialog v-model="newFolderPopper" max-width="40rem" class="mkdir-dialog">
|
||||
<template #activator="{ props }">
|
||||
<VBtn
|
||||
v-bind="props"
|
||||
icon
|
||||
variant="text"
|
||||
color="primary"
|
||||
class="action-button"
|
||||
>
|
||||
<VTooltip text="新建文件夹">
|
||||
<template #activator="{ props: _props }">
|
||||
<VIcon v-bind="_props" icon="mdi-folder-plus" />
|
||||
</template>
|
||||
</VTooltip>
|
||||
</VBtn>
|
||||
</template>
|
||||
<VCard title="新建文件夹" class="pa-2">
|
||||
<template #title>
|
||||
<div class="d-flex align-center px-4 pt-4">
|
||||
<VIcon icon="mdi-folder-plus" color="primary" class="me-2" />
|
||||
<span class="text-h6">新建文件夹</span>
|
||||
</div>
|
||||
</template>
|
||||
<VListItemTitle>{{ item.title }}</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
<VBtn variant="text" :input-value="item.path === '/'" class="px-1" @click="changePath(inProps.itemstack[0])">
|
||||
<VIcon :icon="storageObject?.icon" class="mr-2" />
|
||||
{{ storageObject?.title }}
|
||||
</VBtn>
|
||||
<template v-for="(segment, index) in pathSegments" :key="index">
|
||||
<VBtn
|
||||
v-if="display.mdAndUp.value"
|
||||
variant="text"
|
||||
:input-value="index === pathSegments.length - 1"
|
||||
class="px-1"
|
||||
@click="changePath(inProps.itemstack[index + 1])"
|
||||
>
|
||||
<VIcon icon=" mdi-chevron-right" />
|
||||
{{ segment.name }}
|
||||
</VBtn>
|
||||
</template>
|
||||
<DialogCloseBtn @click="newFolderPopper = false" />
|
||||
<VDivider class="mt-3" />
|
||||
<VCardText>
|
||||
<VTextField
|
||||
v-model="newFolderName"
|
||||
label="文件夹名称"
|
||||
placeholder="请输入文件夹名称"
|
||||
variant="outlined"
|
||||
hide-details="auto"
|
||||
autofocus
|
||||
@keyup.enter="mkdir"
|
||||
/>
|
||||
</VCardText>
|
||||
<VCardActions class="pa-4 pt-0">
|
||||
<VSpacer />
|
||||
<VBtn color="grey" variant="text" @click="newFolderPopper = false">取消</VBtn>
|
||||
<VBtn
|
||||
:disabled="!newFolderName"
|
||||
color="primary"
|
||||
variant="elevated"
|
||||
@click="mkdir"
|
||||
class="ms-2"
|
||||
>
|
||||
创建
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</div>
|
||||
</VToolbarItems>
|
||||
<div class="flex-grow-1" />
|
||||
<VTooltip text="调整排序">
|
||||
<template #activator="{ props }">
|
||||
<IconBtn v-bind="props" @click="changeSort">
|
||||
<VIcon :icon="sortIcon" />
|
||||
</IconBtn>
|
||||
</template>
|
||||
</VTooltip>
|
||||
<VTooltip text="返回上一级" v-if="pathSegments.length > 0">
|
||||
<template #activator="{ props }">
|
||||
<IconBtn v-bind="props" @click="goUp">
|
||||
<VIcon icon="mdi-arrow-up-bold-outline" />
|
||||
</IconBtn>
|
||||
</template>
|
||||
</VTooltip>
|
||||
<VDialog v-model="newFolderPopper" max-width="50rem">
|
||||
<template #activator="{ props }">
|
||||
<IconBtn v-bind="props">
|
||||
<VTooltip text="新建文件夹">
|
||||
<template #activator="{ props: _props }">
|
||||
<VIcon v-bind="_props" icon="mdi-folder-plus-outline" />
|
||||
</template>
|
||||
</VTooltip>
|
||||
</IconBtn>
|
||||
</template>
|
||||
<VCard title="新建文件夹">
|
||||
<DialogCloseBtn @click="newFolderPopper = false" />
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<VTextField v-model="newFolderName" label="名称" />
|
||||
</VCardText>
|
||||
<VCardActions>
|
||||
<div class="flex-grow-1" />
|
||||
<VBtn :disabled="!newFolderName" variant="elevated" @click="mkdir" prepend-icon="mdi-check" class="px-5 me-3">
|
||||
新建
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</VToolbar>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.file-toolbar {
|
||||
background-color: var(--v-theme-surface);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.home-button {
|
||||
min-width: 50px;
|
||||
flex-shrink: 0;
|
||||
|
||||
@media (min-width: 960px) {
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
@media (max-width: 959px) {
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// 确保当面包屑宽度超出容器时,最后一个元素可见
|
||||
&:hover {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
// 允许在触摸设备上滚动
|
||||
touch-action: pan-x;
|
||||
}
|
||||
|
||||
.path-button {
|
||||
padding: 0 4px;
|
||||
min-width: auto;
|
||||
height: 36px;
|
||||
font-weight: normal;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:not(.current-path) {
|
||||
@media (max-width: 959px) {
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
&.current-path {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.path-segment {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
|
||||
.path-button:not(.current-path) & {
|
||||
@media (min-width: 1200px) {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) and (max-width: 1199px) {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) and (max-width: 959px) {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
@media (max-width: 599px) {
|
||||
max-width: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
.current-path & {
|
||||
@media (min-width: 960px) {
|
||||
max-width: unset;
|
||||
}
|
||||
|
||||
@media (max-width: 959px) {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
@media (max-width: 599px) {
|
||||
max-width: 120px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-button {
|
||||
margin: 0 2px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(var(--v-theme-primary), 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
.mkdir-dialog {
|
||||
.v-card {
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.file-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user