feat: 按钮
This commit is contained in:
parent
5cf56739c0
commit
2842fdd0ac
@ -118,7 +118,7 @@ export class BarOption {
|
||||
|
||||
const finalColor = item.color ?? defaultColorSet.color;
|
||||
const finalWfColor = item.wfColor ?? defaultColorSet.wfColor;
|
||||
|
||||
console.log(`Location: ${opts.location || 'Unknown'}, Item index: ${index}, Final color: ${finalColor}`);
|
||||
// 3. 创建一个新的 BarItem 实例,包含所有信息
|
||||
return new BarItem({
|
||||
...item,
|
||||
|
@ -1,13 +1,25 @@
|
||||
<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, watchEffect } from 'vue'; // 1. 引入 watchEffect
|
||||
import { PropType, toRefs, ref, onMounted, computed, watch } from 'vue';
|
||||
import dataJson from './data.json'
|
||||
import { option } from 'keymaster';
|
||||
|
||||
const iframeRef = ref<HTMLIFrameElement | null>(null);
|
||||
const isIframeReady = ref(false); // 2. 创建一个状态来跟踪 iframe 是否已加载
|
||||
@ -22,52 +34,105 @@ const props = defineProps({
|
||||
|
||||
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: BarOption[] = [];
|
||||
if (buttonId === 1) {
|
||||
dataToRender = await fetchData('/space');
|
||||
} else if (buttonId === 2) {
|
||||
dataToRender = await fetchData('/day');
|
||||
} else {
|
||||
console.warn(`未知的按钮ID: ${buttonId},将使用默认数据。`);
|
||||
}
|
||||
// 更新 chartConfig 中的数据,这将触发 BarOptionsData computed 和 watch
|
||||
props.chartConfig.option.dataset.barOptions = dataToRender;
|
||||
console.log(`已为按钮 ${buttonId} 加载 ${dataToRender.length} 条数据。`);
|
||||
};
|
||||
const fetchData = async (url: string) => {
|
||||
try {
|
||||
const response = await axios.get(url);
|
||||
if (response.data.state === true && response.data.value && response.data.value.length > 0) {
|
||||
return response.data.value; // 返回原始数据
|
||||
} else {
|
||||
console.warn('API调用失败或返回空数据,将使用静态数据。');
|
||||
return dataJson.barOptions;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取图表数据失败将使用静态数据:', error);
|
||||
return dataJson.barOptions;
|
||||
}
|
||||
};
|
||||
|
||||
const BarOptionsData = computed(() => {
|
||||
return dataJson.barOptions.map(item =>
|
||||
return props.chartConfig.option.dataset.barOptions.map((item: unknown) =>
|
||||
new BarOption(item as unknown as Partial<BarOption>)
|
||||
);
|
||||
});
|
||||
console.log(BarOptionsData)
|
||||
|
||||
onMounted(() => {
|
||||
const iframe = iframeRef.value;
|
||||
if (iframe) {
|
||||
iframe.onload = () => {
|
||||
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('/map');
|
||||
props.chartConfig.option.dataset.barOptions = data;
|
||||
|
||||
} else {
|
||||
console.error("无法访问 iframe 内的 g.active3d 对象。");
|
||||
}
|
||||
};
|
||||
// 禁止聚焦,免得柱图消失
|
||||
setTimeout(() => {
|
||||
BarOptionsData.value.forEach((barConfig: any) => {
|
||||
callIframeMethod("setProvinceFocusable", false)
|
||||
}, 3000)
|
||||
}
|
||||
});
|
||||
|
||||
// 4. 使用 watchEffect 来处理所有绘图逻辑
|
||||
// index.vue
|
||||
|
||||
watchEffect(() => {
|
||||
if (isIframeReady.value && BarOptionsData.value && iframeApi) {
|
||||
// console.log(" Drawing chart with new options...");
|
||||
|
||||
// 增加延迟,确保iframe内方法准备就绪
|
||||
setTimeout(() => {
|
||||
|
||||
BarOptionsData.value.forEach(barConfig => {
|
||||
// console.log(" Drawing bar with config:", barConfig);
|
||||
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 内部方法的通用函数
|
||||
@ -83,10 +148,130 @@ function callIframeMethod(methodName: string, ...args: any[]) {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.go-iframe-container {
|
||||
// width: 1300px;
|
||||
// height: 900px;
|
||||
overflow: hidden;
|
||||
// border: 1px solid #ccc;
|
||||
position: relative; // 为内部的绝对定位元素提供定位上下文
|
||||
--inactive-border-color: #337ab7;
|
||||
--inactive-text-color: #a0c0e0;
|
||||
--inactive-bg-color: rgba(10, 25, 40, 0.7);
|
||||
--active-border-color: #f7b731;
|
||||
--active-text-color: #f7b731;
|
||||
--active-text-shadow: 0 0 8px rgba(247, 183, 49, 0.7);
|
||||
/* 边框(L型括号)的尺寸参数 */
|
||||
--bracket-thickness: 3px;
|
||||
/* 括号线条粗细 */
|
||||
--bracket-arm-length: 8px;
|
||||
/* 括号横向臂长 */
|
||||
--vertical-segment-height: 8px;
|
||||
/* 括号垂直部分顶部和底部的长度,中间留空 */
|
||||
}
|
||||
|
||||
.button-container-wrapper {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
width: fit-content;
|
||||
padding: 0;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.button {
|
||||
position: relative;
|
||||
padding: 12px 30px;
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
/* 平滑过渡效果 */
|
||||
overflow: hidden;
|
||||
|
||||
--_current-border-color: var(--inactive-border-color);
|
||||
--_current-text-color: var(--inactive-text-color);
|
||||
--_current-text-shadow: none;
|
||||
background-color: var(--inactive-bg-color);
|
||||
/* 按钮背景色 */
|
||||
color: var(--_current-text-color);
|
||||
text-shadow: var(--_current-text-shadow);
|
||||
/* 按钮本体的细线边框:顶部、底部、右侧 */
|
||||
border-top: 1px solid var(--_current-border-color);
|
||||
border-bottom: 1px solid var(--_current-border-color);
|
||||
border-right: 1px solid var(--_current-border-color);
|
||||
border-left: none;
|
||||
/* 左侧边框由伪元素绘制 */
|
||||
}
|
||||
|
||||
/* 激活状态的样式 */
|
||||
.button.active {
|
||||
--_current-border-color: var(--active-border-color);
|
||||
--_current-text-color: var(--active-text-color);
|
||||
--_current-text-shadow: var(--active-text-shadow);
|
||||
color: var(--_current-text-color);
|
||||
text-shadow: var(--_current-text-shadow);
|
||||
border-top-color: var(--_current-border-color);
|
||||
border-bottom-color: var(--_current-border-color);
|
||||
border-right-color: var(--_current-border-color);
|
||||
}
|
||||
|
||||
.button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
width: var(--bracket-arm-length);
|
||||
height: calc(100% + 2px);
|
||||
border-color: var(--_current-border-color);
|
||||
border-style: solid;
|
||||
/* border-width: top right bottom left */
|
||||
border-width: var(--bracket-thickness) 0 var(--bracket-thickness) var(--bracket-thickness);
|
||||
|
||||
/* 使用线性渐变背景来创建左侧垂直部分的断开效果 */
|
||||
background: linear-gradient(to bottom,
|
||||
var(--_current-border-color) 0%,
|
||||
var(--_current-border-color) var(--vertical-segment-height),
|
||||
transparent var(--vertical-segment-height),
|
||||
transparent calc(100% - var(--vertical-segment-height)),
|
||||
var(--_current-border-color) calc(100% - var(--vertical-segment-height)),
|
||||
var(--_current-border-color) 100%) no-repeat left center / var(--bracket-thickness) 100%;
|
||||
|
||||
transition: border-color 0.3s ease, background 0.3s ease;
|
||||
/* 过渡颜色变化 */
|
||||
}
|
||||
|
||||
.button::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
right: -1px;
|
||||
/* 向右偏移1px,与父元素的右边缘对齐 */
|
||||
width: var(--bracket-arm-length);
|
||||
height: calc(100% + 2px);
|
||||
border-color: var(--_current-border-color);
|
||||
border-style: solid;
|
||||
/* 伪元素的边框用于绘制 L 型括号的水平部分和右侧垂直部分的厚度 */
|
||||
/* border-width: top right bottom left */
|
||||
border-width: var(--bracket-thickness) var(--bracket-thickness) var(--bracket-thickness) 0;
|
||||
/* 使用线性渐变背景来创建右侧垂直部分的断开效果 */
|
||||
background: linear-gradient(to bottom,
|
||||
var(--_current-border-color) 0%,
|
||||
var(--_current-border-color) var(--vertical-segment-height),
|
||||
transparent var(--vertical-segment-height),
|
||||
transparent calc(100% - var(--vertical-segment-height)),
|
||||
var(--_current-border-color) calc(100% - var(--vertical-segment-height)),
|
||||
var(--_current-border-color) 100%) no-repeat right center / var(--bracket-thickness) 100%;
|
||||
transition: border-color 0.3s ease, background 0.3s ease;
|
||||
}
|
||||
|
||||
/* 非激活状态按钮的悬停效果 */
|
||||
.button:not(.active):hover {
|
||||
filter: brightness(1.1);
|
||||
/* 略微提高亮度 */
|
||||
}
|
||||
|
||||
.iframe-content {
|
||||
|
@ -3,7 +3,7 @@
|
||||
"message": "Success",
|
||||
"value": [
|
||||
{
|
||||
"label": "中国中车集团有限公司",
|
||||
"label": "中国中车集团有限公司sss",
|
||||
"key": "1674696717063430144",
|
||||
"grade": "org",
|
||||
"parentId": "0",
|
||||
|
@ -536,8 +536,8 @@ const fetchCameraTree = async () => {
|
||||
return [];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取摄像头树失败:', error);
|
||||
return [];
|
||||
console.error('获取摄像头树失败使用静态数据:', error);
|
||||
return props.chartConfig.option.dataset.list;
|
||||
}
|
||||
};
|
||||
onMounted(async () => {
|
||||
@ -616,6 +616,10 @@ const { vChartRef } = useChartDataFetch(props.chartConfig, useChartEditStore, (n
|
||||
background-image: url('data:image/png;base64,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');
|
||||
}
|
||||
|
||||
.title_text {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: #1E5676;
|
||||
border: 1px solid #2E6E89;
|
||||
|
Loading…
Reference in New Issue
Block a user