|
|
@@ -1,21 +1,33 @@
|
|
|
<template>
|
|
|
- <div class="layout-navbars-breadcrumb-station">
|
|
|
+ <div class="layout-navbars-breadcrumb-station"
|
|
|
+ :class="{'is-open': state.open, 'is-empty': !state.loading && state.stationList.length === 0}"
|
|
|
+ title="切换当前查看的站点,页面数据范围会跟随变化">
|
|
|
<el-select-v2
|
|
|
v-model="state.currentStationId"
|
|
|
:options="state.options"
|
|
|
+ :loading="state.loading"
|
|
|
+ :loading-text="'正在加载站点…'"
|
|
|
+ :no-data-text="'没有匹配的站点'"
|
|
|
+ :disabled="!state.loading && state.stationList.length === 0"
|
|
|
+ :placeholder="placeholder"
|
|
|
filterable
|
|
|
- placeholder="选择站点"
|
|
|
+ popper-class="station-select-popper"
|
|
|
class="station-select"
|
|
|
- @change="handleStationChange">
|
|
|
+ @change="handleStationChange"
|
|
|
+ @visible-change="state.open = $event">
|
|
|
<template #prefix>
|
|
|
- <SvgIcon name="ele-Location"></SvgIcon>
|
|
|
+ <SvgIcon name="ele-Location" :size="15"/>
|
|
|
+ </template>
|
|
|
+ <template #header>
|
|
|
+ <span>站点范围</span>
|
|
|
+ <span>共 {{ state.stationList.length }} 个站点</span>
|
|
|
</template>
|
|
|
</el-select-v2>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts" name="layoutBreadcrumbStationSwitcher">
|
|
|
-import {reactive, onMounted} from 'vue';
|
|
|
+import {reactive, computed, onMounted} from 'vue';
|
|
|
import mittBus from '/@/utils/mitt';
|
|
|
import {Session} from '/@/utils/storage';
|
|
|
import {$body} from '/@/utils/request';
|
|
|
@@ -23,7 +35,15 @@ import {$body} from '/@/utils/request';
|
|
|
const state = reactive({
|
|
|
stationList: [] as Array<any>,
|
|
|
currentStationId: null as any,
|
|
|
- options: [] as Array<any>
|
|
|
+ options: [] as Array<any>,
|
|
|
+ loading: true,
|
|
|
+ open: false
|
|
|
+});
|
|
|
+
|
|
|
+const placeholder = computed(() => {
|
|
|
+ if (state.loading) return '加载站点中';
|
|
|
+ if (state.stationList.length === 0) return '暂无站点';
|
|
|
+ return '选择站点';
|
|
|
});
|
|
|
|
|
|
//站点切换
|
|
|
@@ -54,6 +74,8 @@ const loadStationList = () => {
|
|
|
}
|
|
|
}).catch(e => {
|
|
|
//console.error(e)
|
|
|
+ }).finally(() => {
|
|
|
+ state.loading = false;
|
|
|
})
|
|
|
}
|
|
|
|
|
|
@@ -68,23 +90,157 @@ onMounted(() => {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
height: 50px;
|
|
|
- padding: 0 8px;
|
|
|
+ padding: 0 12px 0 4px;
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ //与面包屑之间的分隔:范围(哪个站)与位置(哪个页)是两个语境
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ top: 50%;
|
|
|
+ transform: translateY(-50%);
|
|
|
+ width: 1px;
|
|
|
+ height: 20px;
|
|
|
+ background: var(--el-border-color-lighter);
|
|
|
+ }
|
|
|
|
|
|
.station-select {
|
|
|
- width: 230px;
|
|
|
+ width: 180px;
|
|
|
|
|
|
- :deep(.el-input__wrapper),
|
|
|
+ //去框融入顶栏:静态时无边框无底色,悬停/聚焦时才浮起一层浅底
|
|
|
:deep(.el-select__wrapper) {
|
|
|
- background: var(--el-fill-color-light);
|
|
|
- border-radius: 16px;
|
|
|
- box-shadow: 0 0 0 1px var(--el-border-color-lighter) inset;
|
|
|
+ height: 34px;
|
|
|
+ min-height: 34px;
|
|
|
+ padding: 0 8px;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: transparent;
|
|
|
+ box-shadow: none;
|
|
|
+ transition: background-color .2s cubic-bezier(.4, 0, .2, 1);
|
|
|
+
|
|
|
+ &.is-hovering {
|
|
|
+ background: var(--next-color-user-hover);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.is-focused {
|
|
|
+ background: var(--next-color-user-hover);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.is-disabled {
|
|
|
+ background: transparent;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-select__prefix) {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-right: 6px;
|
|
|
+ color: var(--next-bg-topBarColor);
|
|
|
+ transition: color .2s cubic-bezier(.4, 0, .2, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-select__placeholder),
|
|
|
+ :deep(.el-select__input) {
|
|
|
+ color: var(--next-bg-topBarColor);
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ transition: color .2s cubic-bezier(.4, 0, .2, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ //未选中任何站点时的占位:退一档
|
|
|
+ :deep(.el-select__placeholder.is-transparent) {
|
|
|
+ color: var(--el-text-color-placeholder);
|
|
|
+ font-weight: 400;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-select__caret) {
|
|
|
+ color: var(--next-bg-topBarColor);
|
|
|
+ opacity: 0.6;
|
|
|
+ transform-origin: center;
|
|
|
+ transition: transform .2s cubic-bezier(.4, 0, .2, 1), opacity .2s cubic-bezier(.4, 0, .2, 1), color .2s;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //悬停时文字与图标转为品牌色,呼应 Ghost 按钮规则(禁用态除外)
|
|
|
+ &:not(.is-empty) .station-select:hover {
|
|
|
+ :deep(.el-select__wrapper .el-select__placeholder),
|
|
|
+ :deep(.el-select__wrapper .el-select__input),
|
|
|
+ :deep(.el-select__wrapper .el-select__prefix),
|
|
|
+ :deep(.el-select__wrapper .el-select__caret) {
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ opacity: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //展开时箭头翻转
|
|
|
+ &.is-open .station-select {
|
|
|
+ :deep(.el-select__caret) {
|
|
|
+ transform: rotate(180deg);
|
|
|
+ opacity: 1;
|
|
|
+ color: var(--el-color-primary);
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ //禁用态(无站点可用)
|
|
|
+ &:deep(.el-select__wrapper.is-disabled .el-select__placeholder),
|
|
|
+ &:deep(.el-select__wrapper.is-disabled .el-select__prefix),
|
|
|
+ &:deep(.el-select__wrapper.is-disabled .el-select__caret) {
|
|
|
+ color: var(--el-text-color-disabled);
|
|
|
+ opacity: 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+// 下拉面板(teleported,需全局样式)
|
|
|
+.station-select-popper {
|
|
|
+ .el-select-dropdown {
|
|
|
+ padding: 6px;
|
|
|
+ border: none;
|
|
|
+ border-radius: 12px;
|
|
|
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.06);
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-select-dropdown__header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 4px 10px 6px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: var(--el-text-color-secondary);
|
|
|
|
|
|
- :deep(.el-input__wrapper.is-focus),
|
|
|
- :deep(.el-select__wrapper.is-focused) {
|
|
|
- background: var(--el-bg-color);
|
|
|
- box-shadow: 0 0 0 1px var(--el-color-primary) inset;
|
|
|
+ span:last-child {
|
|
|
+ font-weight: 400;
|
|
|
+ color: var(--el-text-color-placeholder);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ .el-select-dropdown__list {
|
|
|
+ padding: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-select-dropdown__item {
|
|
|
+ height: 34px;
|
|
|
+ margin: 2px 0;
|
|
|
+ padding: 0 10px;
|
|
|
+ border-radius: 8px;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-select-dropdown__item.is-hovering {
|
|
|
+ background: var(--el-fill-color-light);
|
|
|
+ }
|
|
|
+
|
|
|
+ //当前站点:品牌色 + 加粗标记「你在这里」
|
|
|
+ .el-select-dropdown__item.is-selected {
|
|
|
+ color: var(--el-color-primary);
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-select-dropdown__empty {
|
|
|
+ padding: 14px 10px;
|
|
|
+ font-size: 13px;
|
|
|
+ color: var(--el-text-color-placeholder);
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|