Files
Docker/WebVue/src/components/basic/Toolbar.vue
T
2026-09-09 16:31:34 +08:00

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>