| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- <template>
- <div class="land-use-legend yes-events">
- <div
- v-for="(category, index) in legendData"
- :key="index"
- class="legend-category"
- >
- <!-- 父级:可勾选 -->
- <div class="category-header" @click="toggleExpand(category)">
- <el-icon class="expand-icon" :class="{ expanded: category.expanded }"><CaretRight /></el-icon>
- <el-checkbox
- v-model="category.checked"
- @change="handleCategoryChange(category)"
- @click.stop
- class="category-checkbox"
- />
- <span class="category-name">{{ category.name }}</span>
- </div>
- <!-- 子级:仅显示 -->
- <div v-show="category.expanded" class="category-children">
- <div
- v-for="(child, childIndex) in category.children"
- :key="childIndex"
- class="child-item"
- >
- <span class="color-dot" :style="{ backgroundColor: child.color }"></span>
- <span class="child-name">{{ child.name }}</span>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted } from "vue";
- import eventBus from "@/api/eventBus";
- const props = defineProps({
- data: {
- type: Array,
- default: () => [],
- },
- });
- const emit = defineEmits(["change"]);
- // 默认数据(示例数据,可根据实际需求修改)
- const defaultData = [
- {
- name: "作物类",
- checked: true,
- expanded: true,
- children: [
- { name: "小麦", color: "#2199F8" },
- { name: "油菜", color: "#FFA500" },
- ],
- },
- {
- name: "非农化非粮化类",
- checked: false,
- expanded: true,
- children: [
- { name: "撂荒", color: "#00CED1" },
- { name: "林木", color: "#FF69B4" },
- { name: "果树", color: "#90EE90" },
- { name: "坑塘", color: "#008080" },
- { name: "建设用地", color: "#FFA500" },
- ],
- },
- {
- name: "耕地类",
- checked: false,
- expanded: false,
- children: [
- { name: "水田", color: "#4169E1" },
- { name: "旱地", color: "#8B4513" },
- { name: "水浇地", color: "#228B22" },
- ],
- },
- ];
- const legendData = ref([]);
- // 初始化数据
- const initData = () => {
- if (props.data && props.data.length > 0) {
- legendData.value = props.data.map((item) => ({
- ...item,
- expanded: item.expanded !== undefined ? item.expanded : false,
- checked: item.checked !== undefined ? item.checked : false,
- }));
- } else {
- legendData.value = defaultData.map((item) => ({ ...item }));
- }
- };
- const fetchLandUseTypes = () => {
- VE_API.warning.fetchLandUseTypes().then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 处理接口返回的数据,确保格式正确
- // 默认第一个勾选,全部展开
- let processedData = res.data.map((item, index) => ({
- ...item,
- // 第一个默认勾选,其他不勾选
- checked: index === 0,
- // 全部默认展开
- expanded: true,
- }));
-
- legendData.value = processedData;
-
- // 如果第一个默认勾选,触发 change 事件
- if (processedData.length > 0 && processedData[0].checked) {
- const firstCategory = processedData[0];
- emit("change", {
- category: firstCategory.name,
- checked: true,
- children: firstCategory.children || [],
- nonGrain: firstCategory.id || firstCategory.nonGrain || null,
- });
- // 通知地图更新
- eventBus.emit("chartList:updateMap", {
- statType: firstCategory.id || firstCategory.nonGrain || null,
- });
- }
- } else {
- // 如果接口返回失败,使用默认数据
- // 默认第一个勾选,全部展开
- const defaultProcessed = defaultData.map((item, index) => ({
- ...item,
- checked: index === 0,
- expanded: true,
- }));
- legendData.value = defaultProcessed;
-
- // 如果第一个默认勾选,触发 change 事件
- if (defaultProcessed.length > 0 && defaultProcessed[0].checked) {
- const firstCategory = defaultProcessed[0];
- emit("change", {
- category: firstCategory.name,
- checked: true,
- children: firstCategory.children || [],
- nonGrain: firstCategory.id || firstCategory.nonGrain || null,
- });
- // 通知地图更新
- eventBus.emit("chartList:updateMap", {
- statType: firstCategory.id || firstCategory.nonGrain || null,
- });
- }
- }
- }).catch((error) => {
- console.error("获取土地利用类型失败:", error);
- // 接口失败时使用默认数据
- // 默认第一个勾选,全部展开
- const defaultProcessed = defaultData.map((item, index) => ({
- ...item,
- checked: index === 0,
- expanded: true,
- }));
- legendData.value = defaultProcessed;
-
- // 如果第一个默认勾选,触发 change 事件
- if (defaultProcessed.length > 0 && defaultProcessed[0].checked) {
- const firstCategory = defaultProcessed[0];
- emit("change", {
- category: firstCategory.name,
- checked: true,
- children: firstCategory.children || [],
- nonGrain: firstCategory.id || firstCategory.nonGrain || null,
- });
- // 通知地图更新
- eventBus.emit("chartList:updateMap", {
- statType: firstCategory.id || firstCategory.nonGrain || null,
- });
- }
- });
- };
- onMounted(() => {
- fetchLandUseTypes();
- });
- // 切换展开/折叠
- const toggleExpand = (category) => {
- category.expanded = !category.expanded;
- };
- // 处理父级勾选变化(单选逻辑)
- const handleCategoryChange = (category) => {
- // 计算当前有多少个被选中的项(由于 v-model 已经更新了 category.checked,需要检查其他项)
- const otherCheckedCount = legendData.value.filter((item) => item !== category && item.checked).length;
-
- // 如果用户尝试取消,且没有其他项被选中,阻止这个操作(确保至少有一个被选中)
- if (!category.checked && otherCheckedCount === 0) {
- // 阻止取消,保持选中状态
- category.checked = true;
- return;
- }
-
- // 如果当前类别被选中,取消其他所有类别的选中状态
- if (category.checked) {
- legendData.value.forEach((item) => {
- if (item !== category) {
- item.checked = false;
- }
- });
- }
-
- const nonGrainValue = category.id || category.nonGrain || null;
-
- emit("change", {
- category: category.name,
- checked: category.checked,
- children: category.children,
- nonGrain: nonGrainValue, // 传递 nonGrain
- });
-
- // 通知地图更新,传递 statType 参数
- if (category.checked) {
- eventBus.emit("chartList:updateMap", {
- statType: nonGrainValue,
- });
- }
- };
- </script>
- <style lang="scss" scoped>
- .land-use-legend {
- position: fixed;
- right: 420px;
- top: 90px;
- background: rgba(29, 29, 29, 0.86);
- border: 1px solid rgba(255, 212, 137, 0.3);
- border-radius: 8px;
- padding: 16px;
- min-width: 170px;
- max-height: 80vh;
- z-index: 10;
- color: #fff;
- .legend-category {
- margin-bottom: 6px;
- &:last-child {
- margin-bottom: 0;
- }
- }
- .category-header {
- display: flex;
- align-items: center;
- cursor: pointer;
- .category-checkbox {
- margin-right: 8px;
- ::v-deep {
- .el-checkbox__inner {
- background-color: rgba(255, 212, 137, 0.3);
- border-color: rgba(255, 212, 137, 0.6);
- width: 16px;
- height: 16px;
- }
- .el-checkbox__input.is-checked .el-checkbox__inner {
- background-color: #f7be5a;
- border-color: #f7be5a;
- &::after {
- border-color: #000;
- border-width: 2px;
- left: 5px;
- top: 1px;
- transform: rotate(45deg) scaleY(1);
- }
- }
- }
- }
- .expand-icon {
- margin-right: 8px;
- display: inline-block;
- transition: transform 0.3s;
- color: rgba(255, 212, 137, 0.6);
- font-size: 18px;
- text-align: center;
- line-height: 1;
- &.expanded {
- transform: rotate(90deg);
- }
- }
- .category-name {
- font-size: 14px;
- color: rgba(255, 212, 137, 0.9);
- }
- }
- .category-children {
- margin-left: 47px;
- padding-left: 0;
- .child-item {
- display: flex;
- align-items: center;
- padding: 5px 0;
- font-size: 14px;
- color: rgba(255, 255, 255, 0.8);
- .color-dot {
- width: 12px;
- height: 12px;
- margin-right: 6px;
- border-radius: 2px;
- }
- }
- }
- }
- </style>
|