调整控制显示面板

This commit is contained in:
wzy-warehouse
2026-05-04 21:46:36 +08:00
parent 8917b38339
commit 8e365e980e
9 changed files with 208 additions and 262 deletions
@@ -4,18 +4,49 @@
v-show="useStatusStore().uiComponents.controlPanel.show"
>
<div class="title-box">
<header>控制显示</header>
<header>图例与控制</header>
</div>
<div class="control-show-list">
<div v-for="(item, index) in constrolShowList" :key="index">
<el-checkbox
v-model="item.statusStore[item.statusKey].show"
:label="item.name"
@change="
changeStatus(item.statusStore[item.statusKey].show, item.callback)
"
/>
<!-- 按分类显示 -->
<div
v-for="(category, categoryIndex) in categorizedList"
:key="categoryIndex"
class="category-section"
>
<!-- 分类标题 -->
<div class="category-title">{{ category.title }}</div>
<!-- 分类下的项目 -->
<div
v-for="(item, index) in category.items"
:key="index"
class="control-item"
>
<el-checkbox
v-model="item.statusStore[item.statusKey].show"
@change="
changeStatus(item.statusStore[item.statusKey].show, item.callback)
"
/>
<!-- 图例部分 -->
<div class="legend-content">
<!-- 支持图片链接 -->
<img
v-if="item.link"
:src="item.link"
:alt="item.name"
class="legend-item-img"
/>
<!-- 支持HTML+CSS样式 -->
<div
v-else-if="item.html"
v-html="item.html"
class="legend-item-html"
></div>
</div>
<!-- 描述文字 -->
<span class="item-description">{{ item.name }}</span>
</div>
</div>
</div>
</div>
@@ -24,16 +55,41 @@
<script lang="ts" setup>
import { useLoadingInformationStore } from '@/stores/useLoadingInformation.ts';
import { useStatusStore } from '@/stores/useStatusStore';
import { computed } from 'vue';
defineProps<{
const props = defineProps<{
constrolShowList: {
name: string;
statusStore: Record<string, { show: boolean; loading: boolean }>;
statusKey: string;
callback: (...args: unknown[]) => unknown;
link?: string; // 图例图片链接
html?: string; // 图例HTML内容
category?: string; // 分类名称
}[];
}>();
// 按分类组织的数据
const categorizedList = computed(() => {
const categories: Record<
string,
{ title: string; items: typeof props.constrolShowList }
> = {};
props.constrolShowList.forEach((item) => {
const categoryName = item.category || '其他';
if (!categories[categoryName]) {
categories[categoryName] = {
title: categoryName,
items: [],
};
}
categories[categoryName].items.push(item);
});
return Object.values(categories);
});
// 状态改变执行
const changeStatus = (
status: boolean,
@@ -50,19 +106,20 @@
<style scoped>
.control-show-panel-box {
position: absolute;
top: 75px;
right: 0px;
bottom: 20px;
right: 20px;
border-radius: 2px;
z-index: 1000;
width: 160px;
width: 200px;
overflow: auto;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
color: white;
border: 1px solid rgb(0, 225, 255);
max-height: 650px;
}
.title-box {
font-weight: bold;
font-size: 12px;
font-size: 16px;
background: linear-gradient(
180deg,
rgb(86, 204, 242) 0%,
@@ -76,12 +133,65 @@
padding: 8px;
display: flex;
flex-direction: column;
font-size: 12px;
font-size: 14px;
gap: 6px;
max-height: 60vh;
overflow-y: auto;
}
.category-section {
margin-bottom: 8px;
}
.category-title {
font-weight: bold;
font-size: 14px;
color: #00e1ff;
padding: 4px 0;
margin-bottom: 4px;
border-bottom: 1px solid rgba(0, 225, 255, 0.3);
}
.control-item {
display: flex;
align-items: center;
gap: 8px;
padding: 2px 0;
}
.legend-content {
display: flex;
align-items: center;
justify-content: center;
min-width: 20px;
}
.legend-item-img {
width: 18px;
height: 18px;
flex-shrink: 0;
object-fit: contain;
}
.legend-item-html {
width: 18px;
height: 18px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
}
.legend-item-html :deep(*) {
width: 100%;
height: 100%;
}
.item-description {
flex: 1;
text-align: justify;
text-justify: inter-ideograph;
font-size: 14px;
line-height: 1.5;
letter-spacing: 0.5px;
word-break: break-all;
}
:deep(.el-checkbox) {
height: auto;
color: #fff;
margin-right: 0;
}
:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
color: #fff;
@@ -1,163 +0,0 @@
<!-- 图例组件 -->
<template>
<!-- 控制按钮 -->
<div
class="control-box"
:style="{
bottom: `${useStatusStore().uiComponents.legendShow.show ? 248 : 25}px`,
}"
>
<el-button
@click="changeStatus"
circle
:title="`${useStatusStore().uiComponents.legendShow.show ? '关闭' : '打开'}图例`"
>{{
useStatusStore().uiComponents.legendShow.show ? '-' : '+'
}}</el-button
>
</div>
<div
class="legend-box"
v-show="useStatusStore().uiComponents.legendShow.show"
>
<div class="title-box">
<header>图例</header>
</div>
<div class="legend-list-box">
<el-row
v-for="(list, index1) in finalLegendList"
:key="index1"
class="legend-row"
>
<el-col
:span="24 / colsNum"
v-for="(item, index2) in list"
:key="`${index1}_${index2}`"
>
<div class="legend-item">
<!-- 支持图片链接 -->
<img v-if="item.link" :src="item.link" :alt="item.name" class="legend-item-img" />
<!-- 支持HTML+CSS样式 -->
<div v-else-if="item.html" v-html="item.html" class="legend-item-html"></div>
<span class="legend-item-text">{{ item.name }}</span>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<script setup lang="ts">
import { useStatusStore } from '@/stores/useStatusStore';
import { Utils } from '@/utils/utils';
import { onMounted, ref, type Ref } from 'vue';
// 接收父组件传递的属性
const props = defineProps<{
legendList: { name: string; link?: string; html?: string }[];
colsNum: 1 | 2 | 3 | 4 | 6 | 8 | 12 | 24;
}>();
// 处理后图例列表
const finalLegendList: Ref<{ name: string; link?: string; html?: string }[][]> = ref([]);
// 切换图例显示状态
const changeStatus = () => {
useStatusStore().uiComponents.legendShow.show =
!useStatusStore().uiComponents.legendShow.show;
};
onMounted(() => {
finalLegendList.value = Utils.chunkArray(props.legendList, props.colsNum);
});
</script>
<style scoped>
.legend-box {
position: absolute;
bottom: 20px;
right: 15px;
z-index: 1000;
width: 310px;
height: 265px;
overflow-y: auto;
box-shadow: inset 0px 0px 9px rgba(62, 136, 210, 1);
color: white;
font-family: Arial, sans-serif;
border: 1px solid rgba(0, 225, 255, 1);
}
.control-box {
position: absolute;
right: 30px;
z-index: 1001;
}
.title-box {
background: linear-gradient(
180deg,
rgba(86, 204, 242, 1) 0%,
rgba(47, 128, 237, 1) 100%
);
height: 25px;
padding: 10px;
text-align: center;
font-weight: bold;
flex-shrink: 0;
}
.legend-list-box {
background: rgba(14, 52, 98, 0.8);
padding: 10px;
height: calc(100% - 45px);
box-sizing: border-box;
}
.legend-row {
margin-bottom: 2px;
}
.legend-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 8px;
margin: 0;
min-height: 20px;
border-radius: 3px;
transition: background-color 0.2s ease;
}
.legend-item-img {
width: 18px;
height: 18px;
flex-shrink: 0;
object-fit: contain;
margin-right: 8px;
}
.legend-item-html {
width: 18px;
height: 18px;
flex-shrink: 0;
margin-right: 8px;
display: flex;
align-items: center;
justify-content: center;
}
.legend-item-html :deep(*) {
width: 100%;
height: 100%;
}
.legend-item-text {
flex: 1;
text-align: justify;
text-justify: inter-ideograph;
font-size: 14px;
line-height: 1.5;
letter-spacing: 0.5px;
word-break: break-all;
}
</style>
@@ -79,7 +79,7 @@
width: 180px;
position: absolute;
top: 45px;
right: 200px;
right: 40px;
z-index: 1000;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0);