123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- <template>
- <div class="realtime-container">
- <div ref="chart" class="chart" :style="{height: '500px', width: '100%'}" />
- </div>
- </template>
- <script>
- import * as echarts from "echarts";
- require('echarts/theme/macarons') // echarts theme
- import resize from '@/utils/resize'
- import { getConfig } from '@/api/site/site'
- import { getSiteSection } from '@/api/site/berthing'
- import { getCarLocation, getWaterLevel } from '@/api/analysis/achievement'
- import CarSvg from '@/assets/images/car.svg'
- import BarSvg from '@/assets/images/bar.svg'
- export default {
- mixins: [resize],
- props: {
- siteId: Number | String,
- },
- data() {
- return {
- sections: [],
- config: {},
- location: 0,
- waterlevel: 0,
- }
- },
- mounted() {
- this.loadSection();
- this.loadSiteConfig();
- this.loadCarLocation();
- this.timer1 = setInterval(() => this.loadCarLocation(), 5e3)
- this.loadWaterLevel();
- this.timer2 = setInterval(() => this.loadWaterLevel(), 5e3)
- this.$nextTick(() => {
- this.chart = echarts.init(this.$refs.chart, 'macarons');
- })
- },
- beforeDestroy() {
- if (this.timer1) clearTimeout(this.timer1);
- if (this.timer2) clearTimeout(this.timer2);
- if (this.chart) {
- this.chart.dispose()
- this.chart = null
- }
- },
- methods: {
- loadCarLocation() {
- getCarLocation(this.siteId).then((res) => {
- this.location = res.data?.position || 0;
- this.setOptions();
- })
- },
- loadSection() {
- getSiteSection(this.siteId).then((res) => {
- this.sections = JSON.parse(res.data.positions) || [];
- this.setOptions();
- })
- },
- loadWaterLevel() {
- getWaterLevel(this.siteId).then((res) => {
- this.waterlevel = res.data.waterlevel || 0;
- this.setOptions();
- })
- },
- loadSiteConfig() {
- getConfig(this.siteId).then((res) => {
- this.config = res.data || {};
- this.setOptions();
- })
- },
- setOptions() {
- if (!this.chart || !this.config || this.sections.length === 0) {
- return;
- }
- const carWidth = 50; // 小车宽度
- const carHeight = 32; // 小车高度
- const gap = carWidth / 2; // 断面左右留的边距,方便绘制立柱
- const barWidth = 18; // 立柱宽度
- const waterlevel = this.waterlevel;
- const start = this.config.offset;
- const location = this.location;
- const sections = [
- [this.sections[0].x - gap, this.sections[0].y],
- ...this.sections.map(({x, y}) => [x, y]),
- [this.sections[this.sections.length - 1].x + gap, this.sections[this.sections.length - 1].y],
- ];
- const x = sections.map(([x]) => x);
- const maxX = Math.max(...x);
- const minX = Math.min(...x);
- const bar1X = start - (carWidth - barWidth) / 2; // 左侧立柱x坐标
- const bar2X = maxX - (start - minX) + (carWidth - barWidth) / 2; // 右侧立柱x坐标
- const boxWidth = (carWidth - barWidth) * 2; // 小车充电盒子宽度
- const y = sections.map(([,y]) => y);
- const maxY = Math.max(...y);
- const minY = Math.min(...y);
- const disY = maxY - minY;
- const barY = maxY + disY * 1.2;
- const lineY = maxY + disY * 0.8;
- const options = {
- grid: {
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- show: false,
- },
- xAxis: {
- type: 'value',
- min: minX,
- max: maxX,
- show: false,
- },
- yAxis: {
- min: minY - disY * 0.1,
- max: maxY + disY * 1.5,
- type: 'value',
- show: false,
- },
- series: [
- {
- data: sections,
- type: 'line',
- // symbol: 'none',
- animation: false,
- z: 10,
- lineStyle: {
- width: 1,
- color: '#FF8500',
- },
- areaStyle: {
- opacity: 1,
- color: '#ffc27f',
- }
- },
- {
- data: [[minX, waterlevel],[maxX, waterlevel]],
- type: 'line',
- symbol: 'none',
- z: 0,
- lineStyle: {
- width: 0,
- },
- areaStyle: {
- opacity: 1,
- color: '#a5cdf7',
- }
- },
- {
- data: [[bar1X, lineY],[bar2X, lineY]],
- type: 'line',
- symbol: 'none',
- z: 2,
- lineStyle: {
- width: 2,
- color: '#54606C',
- },
- },
- {
- data: [[bar1X, barY],[bar2X, barY]],
- type: 'bar',
- barWidth: barWidth,
- z: 3,
- itemStyle: {
- color: '#A6B7C7'
- }
- },
- {
- data: [[location, lineY]],
- type: 'scatter',
- symbol: `image://${CarSvg}`,
- symbolSize: [carWidth, carHeight],
- symbolOffset: [0, -6],
- silent: true,
- z: 3,
- itemStyle: {
- opacity: 1
- }
- },
- {
- data: [[start, lineY]],
- type: 'scatter',
- symbol: 'rect',
- symbolSize: [boxWidth, 30],
- symbolOffset: [0, '-50%'],
- silent: true,
- z: 4,
- itemStyle: {
- color: '#778CB2',
- opacity: 0.5
- }
- },
- ]
- };
- this.chart.setOption(options);
- },
- }
- }
- </script>
- <style scoped>
- .realtime-container {
- height: 500px;
- background: linear-gradient(0, #FFFFFF 57%, #D1E8FF 100%);
- border-radius: 4px;
- }
- </style>
|