Files
medical-mall/uni_modules/charts/EChartsView.uvue
2026-02-25 11:39:54 +08:00

115 lines
2.7 KiB
Plaintext
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>
<view class="ec-wrap">
<!-- 使用 ref 来获取容器 -->
<view ref="ecCanvas" class="ec-canvas" :style="{ width: '100%', height: '100%' }"></view>
</view>
</template>
<script setup lang="uts">
import { ref, onMounted, onBeforeUnmount, watch, onUnmounted } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
option: { type: Object, default: () => ({}) },
theme: { type: String, default: 'light' }
})
const ecCanvas = ref<UniElement | null>(null)
let chart: any = null
let resizeObserver: any = null
// 加载并注册中国地图
async function loadChinaMap() {
try {
// 检查是否已注册过
if (echarts.getMap('china')) return
// 尝试从 CDN 加载中国地图
const response = await fetch('https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json')
if (response.ok) {
const geoJson = await response.json()
echarts.registerMap('china', geoJson)
console.log('[EChartsView] 中国地图载入并注册成功')
}
} catch (e) {
console.warn('[EChartsView] 地图加载失败,降级处理', e)
}
}
const initChart = async () => {
if (!ecCanvas.value) {
console.warn('[EChartsView] 找不到 canvas 引用')
return
}
// 在 H5 环境下ecCanvas.value 会表现为 HTML 元素
const el = ecCanvas.value as any; // 这里显式作为 any 使用以避开UTS编译器对DOM API的严格限制
if (chart) {
chart.dispose()
chart = null
}
// 计算是否需要地图
const opt = props.option as any;
const needsMap = opt['geo'] != null || (opt['series'] != null && Array.isArray(opt['series']) && (opt['series'] as any[]).some(s => s.type === 'map' && s.map === 'china'))
if (needsMap) {
await loadChinaMap()
}
try {
chart = echarts.init(el, props.theme)
chart.setOption(props.option)
// 监听容器尺寸变化实施自适应
if (typeof ResizeObserver !== 'undefined') {
resizeObserver = new ResizeObserver(() => {
if (chart) chart.resize()
})
resizeObserver.observe(el)
}
} catch (e) {
console.error('[EChartsView] 初始化失败', e)
}
}
onMounted(() => {
// 渲染后延迟初始化以确保容器宽高已经渲染完毕
setTimeout(() => {
initChart()
}, 100)
})
onUnmounted(() => {
if (chart) {
chart.dispose()
chart = null
}
if (resizeObserver) {
resizeObserver.disconnect()
resizeObserver = null
}
})
watch(() => props.option, (newVal) => {
if (chart) {
chart.setOption(newVal)
}
}, { deep: true })
</script>
<style scoped>
.ec-wrap {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.ec-canvas {
width: 100%;
height: 100%;
display: block;
}
</style>