go-viee-fetch-Demo/src/packages/components/Charts/ConfinedSpace/Map/index.vue

218 lines
7.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="go-iframe-container" :style="{ width: w + 'px', height: h + 'px' }">
<!-- 按钮容器绝对定位在右上角 -->
<div class="button-container-wrapper">
<div class="button-container">
<div v-for="btn in buttons" :key="btn.id" :class="['button', { active: btn.id === activeButtonId }]"
@click="selectButton(btn.id)">
<span>{{ btn.label }}</span>
</div>
</div>
</div>
<iframe ref="iframeRef" class="iframe-content" src="/static/index.html"></iframe>
</div>
</template>
<script setup lang="ts">
import axios from 'axios';
import config, { BarOption } from './config';
import { PropType, toRefs, ref, onMounted, computed, watch } from 'vue';
import dataJson from './data.json'
import axiosInstance from '@/api/axios';
const iframeRef = ref<HTMLIFrameElement | null>(null);
const isIframeReady = ref(false); // 2. 创建一个状态来跟踪 iframe 是否已加载
let iframeApi: any = null;
const props = defineProps({
chartConfig: {
type: Object as PropType<config>,
required: true
}
})
const { w, h } = toRefs(props.chartConfig.attr)
const buttons = ref([
{ id: 1, label: '场所分布情况' },
{ id: 2, label: '当日作业情况' }
]);
const activeButtonId = ref(buttons.value[0].id);
// 按钮点击事件
const selectButton = (id: number) => {
activeButtonId.value = id; // 更新激活状态的 ID
console.log(`按钮 ${id} 被选中`);
updateChartData(id);
};
/**
* 根据按钮ID更新图表数据
* @param buttonId 当前激活的按钮ID
*/
const updateChartData = async (buttonId: number) => {
let dataToRender: any = [];
if (buttonId === 1) {
dataToRender = await fetchData('/spaceMapMock');
} else if (buttonId === 2) {
dataToRender = await fetchData('/dayMapMock');
} else {
console.warn(`未知的按钮ID: ${buttonId}`);
}
props.chartConfig.option.dataset.barOptions = dataToRender;
console.log(`已为按钮 ${buttonId} 加载 ${dataToRender.length} 条数据。`);
};
const fetchData = async (url: string) => {
if (url == '/spaceMapMock') {
return dataJson.barOptions;
} else {
return [{ "location": "四川省.成都市", "items": [{ "tall": 120, "color": "#ff4757" }, { "tall": 50, "color": "#3A86FF" }] }, { "location": "广东省.深圳市", "items": [{ "tall": 90, "color": "#5352ed" }, { "tall": 40, "color": "#5352ed" }] }, { "location": "浙江省.杭州市", "items": [{ "tall": 150, "color": "#ff4757" }, { "tall": 70, "color": "#4ECDC4" }] }, { "location": "江苏省.南京市", "items": [{ "tall": 100, "color": "#ff4757" }, { "tall": 45, "color": "#FFD166" }] }, { "location": "湖北省.武汉市", "items": [{ "tall": 110, "color": "#ff4757" }, { "tall": 52, "color": "#6A0572" }] }, { "location": "陕西省.西安市", "items": [{ "tall": 85, "color": "#ff4757" }, { "tall": 38, "color": "#1A535C" }] }, { "location": "山东省.青岛市", "items": [{ "tall": 130, "color": "#ff4757" }, { "tall": 60, "color": "#FF8C42" }] }, { "location": "河南省.郑州市", "items": [{ "tall": 95, "color": "#ff4757" }, { "tall": 43, "color": "#7209B7" }] }, { "location": "福建省.厦门市", "items": [{ "tall": 140, "color": "#ff4757" }, { "tall": 65, "color": "#06D6A0" }] }, { "location": "辽宁省.大连市", "items": [{ "tall": 88, "color": "#ff4757" }, { "tall": 41, "color": "#118AB2" }] }]
}
// try {
// // 无后端接口, 此为预留
// const response: any = await axiosInstance.get(`/dev${url}`, { baseURL: '' });
// if (response.state === true && response.value && response.value.length > 0) {
// return response.value; // 返回原始数据
// } else {
// console.warn('API调用失败或返回空数据将使用静态数据。');
// return dataJson.barOptions;
// }
// } catch (error) {
// console.error('获取图表数据失败将使用静态数据:', error);
// return dataJson.barOptions;
// }
};
const BarOptionsData = computed(() => {
return props.chartConfig.option.dataset.barOptions.map((item: unknown) =>
new BarOption(item as unknown as Partial<BarOption>)
);
});
onMounted(() => {
const iframe = iframeRef.value;
if (iframe) {
iframe.onload = async () => {
console.log(" Iframe content has loaded!");
if (iframe.contentWindow && (iframe.contentWindow as any).g) {
iframeApi = (iframe.contentWindow as any).g.active3d;
isIframeReady.value = true;
const data = await fetchData('/spaceMapMock');
props.chartConfig.option.dataset.barOptions = data;
} else {
console.error("无法访问 iframe 内的 g.active3d 对象。");
}
setTimeout(() => {
BarOptionsData.value.forEach((barConfig: any) => {
callIframeMethod("setProvinceFocusable", false)
// console.log(" Drawing bar with config:", barConfig);
callIframeMethod("createBar", barConfig);
});
}, 500); // 500ms延迟可根据实际情况调整
};
}
});
watch(
BarOptionsData,
(newBarOptionsData) => {
if (!isIframeReady.value) {
console.warn("Iframe API not ready, skipping bar rendering in watch.");
return;
}
console.log("Watch triggered with newBarOptionsData:", newBarOptionsData);
setTimeout(() => {
callIframeMethod("clearAllBars");
newBarOptionsData.forEach((barConfig: BarOption) => {
console.log(" Re-drawing bar with config:", barConfig);
callIframeMethod("createBar", barConfig);
});
}, 500);
},
{
immediate: true,
deep: false
}
);
/**
* 调用 iframe 内部方法的通用函数
*/
function callIframeMethod(methodName: string, ...args: any[]) {
if (iframeApi && typeof iframeApi[methodName] === 'function') {
iframeApi[methodName].apply(iframeApi, args);
} else if (isIframeReady.value) {
console.error(`方法 ${methodName} 在 iframe API 上不存在。`);
}
}
</script>
<style lang="scss" scoped>
.go-iframe-container {
overflow: hidden;
position: relative; // 为内部的绝对定位元素提供定位上下文
}
.button-container-wrapper {
position: absolute;
top: 20px;
right: 20px;
z-index: 10;
}
.button-container {
display: flex;
flex-direction: row;
// gap: 10px;
// width: 400px;
height: 50px;
padding: 0;
}
.button {
position: relative;
margin: 1px;
display: flex;
align-items: center;
justify-content: center;
padding: 12px 0px;
width: 200px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
/* 平滑过渡效果 */
overflow: hidden;
background-image: url('./assets/unselect.png');
background-size: 100% 100%;
background-repeat: no-repeat;
color: rgb(193, 193, 193);
// background-color: bisque;
}
/* 激活状态的样式 */
.button.active {
background-image: url('./assets/selected.png');
color: #eee;
}
/* 非激活状态按钮的悬停效果 */
.button:not(.active):hover {
filter: brightness(1.1);
}
.iframe-content {
width: 100%;
height: 100%;
border: none;
}
.button:nth-child(1) {
transform: translateX(30px); // 将第二个按钮向左移动
}
</style>