254 lines
6.4 KiB
Vue
254 lines
6.4 KiB
Vue
<template>
|
|
<a-row :wrap="false">
|
|
<a-col flex="auto">
|
|
<a-row>
|
|
<a-col flex="100px">
|
|
<a-row justify="start">
|
|
<a-col :span="8"
|
|
><a-tooltip title="返回顶层">
|
|
<a-button
|
|
type="text"
|
|
class="nav-btn"
|
|
:disabled="!canGoTop"
|
|
@click="$emit('go-top')"
|
|
>
|
|
<HomeOutlined />
|
|
</a-button> </a-tooltip
|
|
></a-col>
|
|
<a-col :span="8"
|
|
><a-tooltip title="返回上层">
|
|
<a-button
|
|
type="text"
|
|
class="nav-btn"
|
|
:disabled="!canGoBack"
|
|
@click="$emit('go-back')"
|
|
>
|
|
<ArrowLeftOutlined />
|
|
</a-button> </a-tooltip
|
|
></a-col>
|
|
<a-col :span="8"
|
|
><a-tooltip title="刷新">
|
|
<a-button
|
|
type="text"
|
|
class="nav-btn"
|
|
:loading="loading"
|
|
@click="onBreadcrumbClick(breadcrumbItems[0], 0)"
|
|
>
|
|
<ReloadOutlined />
|
|
</a-button> </a-tooltip
|
|
></a-col>
|
|
</a-row>
|
|
</a-col>
|
|
<a-col :xs="0" :sm="0" :lg="20" flex="auto">
|
|
<div
|
|
class="toolbar-center"
|
|
style="margin-top: 5px; margin-left: 10px"
|
|
>
|
|
<a-breadcrumb class="breadcrumb">
|
|
<a-breadcrumb-item
|
|
v-for="(item, index) in breadcrumbItems"
|
|
:key="index"
|
|
@click="onBreadcrumbClick(item, index)"
|
|
:class="{ clickable: index < breadcrumbItems.length - 1 }"
|
|
>
|
|
<template v-if="index === 0">
|
|
<LaptopOutlined style="margin-right: 4px" />
|
|
</template>
|
|
<template v-else>
|
|
<FolderOutlined style="margin-right: 4px" />
|
|
</template>
|
|
<span
|
|
:style="{
|
|
cursor:
|
|
index < breadcrumbItems.length - 1
|
|
? 'pointer'
|
|
: 'default',
|
|
color: index < breadcrumbItems.length - 1 ? '#1677ff' : '',
|
|
}"
|
|
>{{ item.displayName }}</span
|
|
>
|
|
</a-breadcrumb-item>
|
|
</a-breadcrumb>
|
|
</div>
|
|
</a-col>
|
|
<a-col :xs="10" :sm="10" :lg="0" flex="auto">
|
|
<div
|
|
v-if="viewMode == 'list'"
|
|
style="
|
|
margin-top: 8px;
|
|
margin-left: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
"
|
|
>
|
|
<FolderOutlined style="margin-right: 4px" />
|
|
<span class="breadcrumb-text">{{
|
|
breadcrumbItems.length > 0
|
|
? breadcrumbItems[breadcrumbItems.length - 1].displayName
|
|
: ""
|
|
}}</span>
|
|
</div>
|
|
<div
|
|
style="
|
|
max-width: 260px;
|
|
min-width: 220px;
|
|
margin-left: 20px;
|
|
margin-top: -2px;
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
"
|
|
v-else
|
|
>
|
|
<a-input-search
|
|
v-model:value="searchKeyword"
|
|
placeholder="搜索文件名称"
|
|
allow-clear
|
|
@search="onSearch"
|
|
@pressEnter="onSearch"
|
|
>
|
|
</a-input-search>
|
|
<a-button size="small" type="default" @click="viewMode = 'list'" style="height: 32px;">
|
|
<cust-icon-font size="16" type="icon-gongcheng" />
|
|
</a-button>
|
|
</div>
|
|
</a-col> </a-row
|
|
></a-col>
|
|
<a-col :xs="0" :sm="0" :lg="10" flex="none">
|
|
<div style="margin-bottom: 8px; margin-right: 8px">
|
|
<a-input-search
|
|
v-model:value="searchKeyword"
|
|
placeholder="搜索文件名称"
|
|
allow-clear
|
|
@search="onSearch"
|
|
@pressEnter="onSearch"
|
|
>
|
|
</a-input-search>
|
|
</div>
|
|
</a-col>
|
|
<a-col :xs="4" :sm="4" :lg="0" flex="none">
|
|
<div
|
|
v-if="viewMode == 'list'"
|
|
style="
|
|
margin-right: 20px;
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 4px;
|
|
"
|
|
>
|
|
<a-button size="small" type="default" @click="viewMode = 'search'">
|
|
<cust-icon-font size="14" type="icon-sousuo" />
|
|
</a-button>
|
|
<a-button size="small" type="default" @click="">
|
|
<cust-icon-font size="14" type="icon-help" />
|
|
</a-button>
|
|
</div>
|
|
</a-col>
|
|
</a-row>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, watch } from "vue";
|
|
import {
|
|
HomeOutlined,
|
|
ArrowLeftOutlined,
|
|
ReloadOutlined,
|
|
LaptopOutlined,
|
|
FolderOutlined,
|
|
SearchOutlined,
|
|
} from "@ant-design/icons-vue";
|
|
|
|
interface BreadcrumbItem {
|
|
value: string;
|
|
displayName: string;
|
|
}
|
|
|
|
const props = defineProps<{
|
|
pathStack: BreadcrumbItem[];
|
|
rootPath: string;
|
|
loading: boolean;
|
|
}>();
|
|
|
|
const emit = defineEmits([
|
|
"go-top",
|
|
"go-back",
|
|
"refresh",
|
|
"search",
|
|
"breadcrumb-click",
|
|
]);
|
|
|
|
const searchKeyword = ref("");
|
|
|
|
const viewMode = ref<"search" | "list">("list");
|
|
|
|
const canGoTop = computed(() => {
|
|
return props.pathStack.length > 1;
|
|
});
|
|
|
|
const canGoBack = computed(() => {
|
|
return props.pathStack.length > 1;
|
|
});
|
|
|
|
const breadcrumbItems = computed(() => {
|
|
return props.pathStack;
|
|
});
|
|
|
|
const onSearch = () => {
|
|
emit("search", searchKeyword.value);
|
|
};
|
|
|
|
const onBreadcrumbClick = (item: BreadcrumbItem, index: number) => {
|
|
emit("breadcrumb-click", item, index);
|
|
};
|
|
</script>
|
|
|
|
<style lang="less">
|
|
.nav-btn {
|
|
width: 36px;
|
|
height: 32px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.nav-btn:hover:not(:disabled) {
|
|
background: #e6f4ff;
|
|
color: #1677ff;
|
|
}
|
|
|
|
.nav-btn:disabled {
|
|
color: #bfbfbf;
|
|
}
|
|
|
|
.toolbar-center {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.breadcrumb {
|
|
margin: 0;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.breadcrumb-item.clickable {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.breadcrumb-item.clickable:hover {
|
|
color: #1677ff;
|
|
}
|
|
|
|
.toolbar-right {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.breadcrumb-text {
|
|
display: inline-block;
|
|
max-width: 16ch; /* 6个字符宽度,ch 按字符计算 */
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
</style>
|