feat:新增地图组件

This commit is contained in:
Free-sss 2025-08-25 20:27:25 +08:00
parent 69284d0c0e
commit a624a3247e
8 changed files with 277 additions and 1 deletions

View File

@ -0,0 +1,145 @@
import { echartOptionProfixHandle, PublicConfigClass } from '@/packages/public'
import { MapConfig } from './index'
import { chartInitConfig } from '@/settings/designSetting'
import { CreateComponentType } from '@/packages/index.d'
import cloneDeep from 'lodash/cloneDeep'
export const includes = []
const BAR_ITEM_DEFAULT_COLORS = [
{ color: "#00CF28", wfColor: "#03D61A" },
{ color: "#AF380E", wfColor: "#BD1408" },
{ color: "#047DB0", wfColor: "#02BBD1" },
{ color: "#01E5A9", wfColor: "#01C97F" },
];
/**
*
*/
class BarItem {
/**
*
* @default 10
*/
tall: number = 10;
/**
* ()
*/
color?: string;
/**
* 线 ()
*/
wfColor?: string;
constructor(options?: Partial<BarItem>) {
if (options) {
Object.assign(this, options);
}
}
}
/**
*
*/
export class BarOption {
/**
* 线
* @default "湖北省"
*/
location: string = "湖北省";
/**
*
* @default 15
*/
width: number = 15;
/**
*
* @default -45
*/
rotation: number = -45;
/**
* X方向偏移
* @default 5
*/
offsetX: number = 5;
/**
* Y方向偏移
* @default 0
*/
offsetY: number = 0;
/**
* Z方向偏移()
* @default 0
*/
offsetZ: number = 0;
/**
*
*/
onClick: (node: any, item: BarItem) => void = (node, item) => {
console.log("click ->", node, item);
};
/**
*
*/
onEnter: (node: any, item: BarItem) => void = (node, item) => {
console.log("enter ->", node, item);
};
/**
*
*/
onLeave: (node: any, item: BarItem) => void = (node, item) => {
console.log("leave ->", node, item);
};
/**
*
* @default []
*/
items: BarItem[] = [];
/**
*
* @param options Partial<BarOption>
*/
constructor(options?: Partial<BarOption>) {
const opts = { ...options };
if (opts.items) {
this.items = opts.items.map((item, index) => {
const defaultColorSet = BAR_ITEM_DEFAULT_COLORS[index % BAR_ITEM_DEFAULT_COLORS.length];
const finalColor = item.color ?? defaultColorSet.color;
const finalWfColor = item.wfColor ?? defaultColorSet.wfColor;
// 3. 创建一个新的 BarItem 实例,包含所有信息
return new BarItem({
...item,
color: finalColor,
wfColor: finalWfColor,
});
});
delete opts.items;
}
Object.assign(this, opts);
}
}
const option = {
}
export const MapDefaultConfig = { ...option }
export default class Config extends PublicConfigClass implements CreateComponentType {
public key: string = MapConfig.key
public attr = { ...chartInitConfig, w: 1300, h: 900, zIndex: -1 }
public chartConfig = cloneDeep(MapConfig)
public option = echartOptionProfixHandle(option, includes)
// public option = option
}

View File

@ -0,0 +1,9 @@
<template>
<div>
</div>
</template>
<script setup lang="ts">
</script>

View File

@ -0,0 +1,7 @@
{
"barOptions": [
{"location": "湖北省", "items":[{"tall":60},{"tall":40},{"tall":20},{"tall":10}]},
{"location": "湖南省", "items":[{"tall":60},{"tall":40},{"tall":20},{"tall":10}]},
{"location": "北京市", "items":[{"tall":60},{"tall":40},{"tall":20},{"tall":10}]}
]
}

View File

@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const MapConfig: ConfigType = {
key: 'Map',
chartKey: 'VMap',
conKey: 'VCMap',
title: '无无敌大地图',
category: 'ConfinedSpace',
categoryName: '有限空间',
package: PackagesCategoryEnum.CHARTS,
chartFrame: ChartFrameEnum.COMMON,
image: 'map1.png'
}

View File

@ -0,0 +1,92 @@
<template>
<div class="go-iframe-container" :style="{ width: w + 'px', height: h + 'px' }">
<iframe ref="iframeRef" class="iframe-content" src="/public/static/index.html"></iframe>
</div>
</template>
<script setup lang="ts">
import config, { BarOption } from './config';
import { PropType, toRefs, ref, onMounted, computed, watchEffect } from 'vue'; // 1. watchEffect
import dataJson from './data.json'
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 BarOptionsData = computed(() => {
return dataJson.barOptions.map(item =>
new BarOption(item as unknown as Partial<BarOption>)
);
});
console.log(BarOptionsData)
onMounted(() => {
const iframe = iframeRef.value;
if (iframe) {
iframe.onload = () => {
console.log(" Iframe content has loaded!");
if (iframe.contentWindow && (iframe.contentWindow as any).g) {
iframeApi = (iframe.contentWindow as any).g.active3d;
isIframeReady.value = true;
} else {
console.error("无法访问 iframe 内的 g.active3d 对象。");
}
};
}
});
// 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);
callIframeMethod("createBar", barConfig);
});
}, 500); // 500ms
}
});
/**
* 调用 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 {
// width: 1300px;
// height: 900px;
overflow: hidden;
// border: 1px solid #ccc;
}
.iframe-content {
width: 100%;
height: 100%;
border: none;
}
</style>

View File

@ -0,0 +1,4 @@
import {MapConfig} from './Map'
export default [MapConfig]

View File

@ -6,6 +6,7 @@ export enum ChatCategoryEnum {
SCATTER = 'Scatters', SCATTER = 'Scatters',
MAP = 'Maps', MAP = 'Maps',
MyComponets='MyComponets', MyComponets='MyComponets',
ConfinedSpace='ConfinedSpace',
MORE = 'Mores' MORE = 'Mores'
} }
@ -16,6 +17,7 @@ export enum ChatCategoryEnumName {
SCATTER = '散点图', SCATTER = '散点图',
MAP = '地图', MAP = '地图',
MyComponets='我的混合组件', MyComponets='我的混合组件',
ConfinedSpace='有限空间',
COMBINATION = '组合图', COMBINATION = '组合图',
MORE = '更多' MORE = '更多'
} }

View File

@ -5,6 +5,9 @@ import Scatters from './Scatters'
import Mores from './Mores' import Mores from './Mores'
import Maps from './Maps' import Maps from './Maps'
import MyComponets from './MyComponents' import MyComponets from './MyComponents'
import ConfinedSpace from './ConfinedSpace'
export const ChartList = [...Bars, ...Lines, ...Pies, ...Scatters, ...Maps, ...Mores, ...MyComponets] export const ChartList = [...Bars, ...Lines, ...Pies, ...Scatters, ...Maps, ...Mores, ...MyComponets
, ...ConfinedSpace
]