218 lines
7.0 KiB
Vue
218 lines
7.0 KiB
Vue
<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> |