From 6cf16e6806325f4f7d26de900b65a028d96552be Mon Sep 17 00:00:00 2001 From: ZhaoYang <565837861@qq.com> Date: Fri, 10 Apr 2026 20:28:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=AA=8C=E8=AF=81=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chenhai-ui/src/components/visual/scgk.vue | 255 ++++++++++--------- chenhai-ui/src/views/login.vue | 282 ++++++++++------------ 2 files changed, 273 insertions(+), 264 deletions(-) diff --git a/chenhai-ui/src/components/visual/scgk.vue b/chenhai-ui/src/components/visual/scgk.vue index e4a16a8..6908361 100644 --- a/chenhai-ui/src/components/visual/scgk.vue +++ b/chenhai-ui/src/components/visual/scgk.vue @@ -126,23 +126,12 @@ -
- 🎯 产奶目标完成度 + 🐪 泌乳母驼存栏结构
-
- - - - {{ completionPercent }}% - 完成率 - -
- +
+
@@ -154,9 +143,7 @@ import * as echarts from 'echarts'; import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; -// 注意:animate-number 组件需要单独安装或自定义,这里提供一个简单的模拟实现 -// 如果项目中未安装 vue-animate-number,可以自行实现一个简单的数字动画组件 -// 为了代码完整性,我们在 components 中注册一个简单的 animate-number 组件 +// 动画数字组件 const AnimateNumber = { props: { from: Number, @@ -195,8 +182,8 @@ export default { }, data() { return { - // 默认中心坐标(阿拉善左旗吉兰泰镇附近,与地图实际展示匹配) - center: { lng: 105.669, lat: 38.833 }, + // 默认中心坐标 + center: { lng: 104.516843, lat: 40.272114 }, productionStats: { totalMilk: 2845, // 吨 camelCount: 12860, @@ -219,36 +206,39 @@ export default { ], camelChartIns: null, trendChartIns: null, - // 环形进度条参数 - ringCircumference: 2 * Math.PI * 54, // 周长 = 2*pi*r - // 百度地图实例 + lactatingBarChartIns: null, baiduMap: null }; }, computed: { - // 完成百分比(基于年度目标3500吨) - completionPercent() { - let percent = (this.productionStats.totalMilk / 3500) * 100; - percent = Math.min(100, Math.max(0, percent)); - return Math.floor(percent); + lactatingCamels() { + return Math.round(this.productionStats.camelCount * 0.48); + }, + otherCamels() { + return this.productionStats.camelCount - this.lactatingCamels; }, - // 环形进度条偏移量 - ringOffset() { - const percent = this.completionPercent / 100; - return this.ringCircumference * (1 - percent); + barChartData() { + const months = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']; + const lactatingData = []; + const otherData = []; + const baseTotal = this.productionStats.camelCount; + const ratios = [0.47, 0.46, 0.45, 0.46, 0.48, 0.50, 0.52, 0.51, 0.50, 0.49, 0.48, 0.47]; + for (let i = 0; i < months.length; i++) { + const lactating = Math.round(baseTotal * ratios[i]); + lactatingData.push(lactating); + otherData.push(baseTotal - lactating); + } + return { + months, + lactatingData, + otherData + }; } }, mounted() { this.getCurrentDateTime(); this.initAllCharts(); window.addEventListener('resize', this.handleResize); - // 由于百度地图组件 需要等待其初始化完成,但实际原生百度地图GL与Vue组件集成可能有问题 - // 为了保证地图正常显示且与统计指标对齐,我们采用原生方式在 nextTick 中初始化地图,替换原有的 baidu-map 组件标签内容 - // 注意:template 中的 组件可能无法正常工作(需要vue-baidu-map插件),为了可靠性,我们将采用原生方式手动挂载地图 - // 并且移除 template 中的 baidu-map 组件,改为一个普通的 div 容器,由 js 初始化。 - // 为保持代码一致性,我将在 mounted 中重新获取容器并初始化原生百度地图,同时修改 template 中的地图容器为普通 div。 - // 但由于用户代码中使用了 标签,可能已安装对应库,为保险,我同时保留两种方式,但根据错误提示,最好改为原生。 - // 下面将重写地图初始化部分,确保地图正常显示且不超出布局。 this.$nextTick(() => { this.initBaiduMapNative(); }); @@ -257,19 +247,19 @@ export default { window.removeEventListener('resize', this.handleResize); if (this.camelChartIns) this.camelChartIns.dispose(); if (this.trendChartIns) this.trendChartIns.dispose(); + if (this.lactatingBarChartIns) this.lactatingBarChartIns.dispose(); if (this.baiduMap) { - // 清理地图 this.baiduMap.destroy(); } }, methods: { getCurrentDateTime() { - // 这个函数可以移除,因为原代码中查找 #cloudDate 等元素不存在,但保留无影响 - // 为了安全,不报错即可 + // 保留原函数 }, initAllCharts() { this.initCamelStructureChart(); this.initTrendChart(); + this.initLactatingBarChart(); }, initCamelStructureChart() { const chartDom = this.$refs.camelChart; @@ -332,12 +322,80 @@ export default { symbolSize: 8, itemStyle: { color: '#3498db' } }], - grid: { containLabel: true, bottom: 10, top: 20, right: 20, left: 45 } + grid: { containLabel: true, bottom: 0, top: 40, right: 20, left: 10 } + }); + }, + initLactatingBarChart() { + const chartDom = this.$refs.lactatingBarChart; + if (!chartDom) return; + if (this.lactatingBarChartIns) this.lactatingBarChartIns.dispose(); + this.lactatingBarChartIns = echarts.init(chartDom); + const { months, lactatingData, otherData } = this.barChartData; + this.lactatingBarChartIns.setOption({ + tooltip: { + trigger: 'axis', + axisPointer: { type: 'shadow' }, + backgroundColor: 'rgba(0,0,0,0.7)', + borderColor: '#3498db', + textStyle: { color: '#fff' }, + formatter: (params) => { + let res = `${params[0].axisValue}
`; + res += `${params[0].marker} 泌乳母驼: ${params[0].value} 峰
`; + res += `${params[1].marker} 其他骆驼: ${params[1].value} 峰
`; + res += `合计: ${params[0].value + params[1].value} 峰`; + return res; + } + }, + legend: { + data: ['泌乳母驼', '其他骆驼'], + textStyle: { color: '#fff' }, + left: 'left', + itemWidth: 25, + itemHeight: 14 + }, + grid: { + containLabel: true, + bottom: 15, + top: 30, + right: 15, + left: 50 + }, + xAxis: { + type: 'category', + data: months, + axisLabel: { color: '#fff', rotate: 30, interval: 0 }, + axisLine: { lineStyle: { color: '#5dade2' } }, + axisTick: { show: false } + }, + yAxis: { + type: 'value', + nameTextStyle: { color: '#fff' }, + axisLabel: { color: '#fff' }, + splitLine: { lineStyle: { color: 'rgba(93, 173, 226, 0.3)' } }, + axisLine: { lineStyle: { color: '#5dade2' } } + }, + series: [ + { + name: '泌乳母驼', + type: 'bar', + stack: 'total', + data: lactatingData, + itemStyle: { color: '#3498db', borderRadius: [4, 4, 0, 0] }, + label: { show: false } + }, + { + name: '其他骆驼', + type: 'bar', + stack: 'total', + data: otherData, + itemStyle: { color: '#85c1e9', borderRadius: [4, 4, 0, 0] }, + label: { show: false } + } + ], + backgroundColor: 'transparent' }); }, - // 原生百度地图GL初始化 (替换原有组件,确保地图显示且布局对齐) initBaiduMapNative() { - // 检查百度地图API是否加载完成 if (typeof window.BMapGL === 'undefined') { console.error('百度地图API未加载,请检查AK或网络,稍后重试'); setTimeout(() => this.initBaiduMapNative(), 500); @@ -348,23 +406,16 @@ export default { console.error('地图容器未找到'); return; } - // 清空容器可能存在的子元素 mapContainer.innerHTML = ''; - - // 创建地图实例 (阿拉善左旗吉兰泰镇附近坐标) const map = new window.BMapGL.Map(mapContainer); const centerPoint = new window.BMapGL.Point(105.669, 38.833); map.centerAndZoom(centerPoint, 11); map.enableScrollWheelZoom(true); - // 设置深色地图样式 map.setMapStyle({ style: 'midnight' }); - // 添加标记点示例:展示核心牧场位置 const markerPoint = new window.BMapGL.Point(105.669, 38.833); const marker = new window.BMapGL.Marker(markerPoint); map.addOverlay(marker); - - // 添加信息窗口 const infoWindow = new window.BMapGL.InfoWindow( '
吉兰泰骆驼产业园
存栏骆驼: 4200峰
日产奶量: 8.6吨
', { width: 200, offset: new window.BMapGL.Size(0, -30) } @@ -373,7 +424,6 @@ export default { map.openInfoWindow(infoWindow, markerPoint); }); - // 添加区域示意圈 const circlePoint = new window.BMapGL.Point(105.62, 38.81); const circle = new window.BMapGL.Circle(circlePoint, 5000, { strokeColor: "#3498db", @@ -383,7 +433,6 @@ export default { }); map.addOverlay(circle); - // 添加文本标签 const labelOpts = { position: new window.BMapGL.Point(105.69, 38.85), offset: new window.BMapGL.Size(20, 0) }; const label = new window.BMapGL.Label('巴音塔拉嘎查', labelOpts); label.setStyle({ @@ -396,7 +445,6 @@ export default { }); map.addOverlay(label); - // 添加第二个标注点 const markerPoint2 = new window.BMapGL.Point(105.59, 38.79); const marker2 = new window.BMapGL.Marker(markerPoint2); map.addOverlay(marker2); @@ -409,8 +457,6 @@ export default { }); this.baiduMap = map; - - // 强制resize确保地图容器正确渲染 setTimeout(() => { if (this.baiduMap) { this.baiduMap.centerAndZoom(centerPoint, 11); @@ -420,6 +466,7 @@ export default { handleResize() { if (this.camelChartIns) this.camelChartIns.resize(); if (this.trendChartIns) this.trendChartIns.resize(); + if (this.lactatingBarChartIns) this.lactatingBarChartIns.resize(); if (this.baiduMap) { setTimeout(() => { this.baiduMap.centerAndZoom(this.baiduMap.getCenter(), this.baiduMap.getZoom()); @@ -431,7 +478,6 @@ export default { \ No newline at end of file