From 4f62525ce303e942ad9b37b4ab234301a191c575 Mon Sep 17 00:00:00 2001 From: wally <18603454788@163.com> Date: Fri, 26 Nov 2021 17:28:59 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=BC=E5=90=88=E6=9B=B2=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/workspace.xml | 19 +- components/Common/Map.vue | 8 +- components/Common/Monitor.vue | 34 +++ components/DataCenter/Address.vue | 30 +++ components/DataCenter/ComplexChart.vue | 63 +++++- components/DataCenter/MapContainer.vue | 18 +- components/DataCenter/Right.vue | 5 +- components/DataCenter/YieldChart.vue | 50 ++++- config/layout/dataCenterBody.js | 2 +- package.json | 3 +- server/api/datas.ts | 6 + server/mocks/datas.js | 290 +++++++++++++++++++++++++ utils/complexChart.js | 177 +++++++++++++++ utils/complexConfig.js | 202 +++++++++++++++++ utils/map.js | 9 +- yarn.lock | 5 + 16 files changed, 886 insertions(+), 35 deletions(-) create mode 100644 components/Common/Monitor.vue create mode 100644 components/DataCenter/Address.vue create mode 100644 server/api/datas.ts create mode 100644 server/mocks/datas.js create mode 100644 utils/complexChart.js create mode 100644 utils/complexConfig.js diff --git a/.idea/workspace.xml b/.idea/workspace.xml index e9bb0d7..efb4d4a 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -6,12 +6,14 @@ - - - + + + + + - + @@ -22,8 +24,8 @@ - + @@ -61,7 +63,7 @@ - + @@ -89,7 +91,10 @@ - + + + + diff --git a/components/Common/Map.vue b/components/Common/Map.vue index 18b846c..f09b0d4 100644 --- a/components/Common/Map.vue +++ b/components/Common/Map.vue @@ -7,16 +7,10 @@ import { initOptions } from '@/utils/map'; import { onMounted } from 'vue'; import ShanXiMap from 'config/map/shanxi'; -console.log('ShanXiMap: ', ShanXiMap); - -// onMounted(() => { - // console.log(111); const chartDom = document.getElementById('map'); - console.log('chartDom: ', chartDom); const myChart = echarts.init(chartDom); - // console.log('myChart: ', myChart); - // + echarts.registerMap('shanxi', ShanXiMap); // myChart.setOption(initOptions()); diff --git a/components/Common/Monitor.vue b/components/Common/Monitor.vue new file mode 100644 index 0000000..922a966 --- /dev/null +++ b/components/Common/Monitor.vue @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/components/DataCenter/Address.vue b/components/DataCenter/Address.vue new file mode 100644 index 0000000..3e6aaef --- /dev/null +++ b/components/DataCenter/Address.vue @@ -0,0 +1,30 @@ + + + + 我的位置:山西省 > 太原市 > 晋祠农场 + + + + + + diff --git a/components/DataCenter/ComplexChart.vue b/components/DataCenter/ComplexChart.vue index 512cd39..4ef9404 100644 --- a/components/DataCenter/ComplexChart.vue +++ b/components/DataCenter/ComplexChart.vue @@ -1,5 +1,62 @@ -综合曲线 + + + - + + + diff --git a/components/DataCenter/MapContainer.vue b/components/DataCenter/MapContainer.vue index 82b04ef..e5d0f01 100644 --- a/components/DataCenter/MapContainer.vue +++ b/components/DataCenter/MapContainer.vue @@ -1,7 +1,21 @@ - + + + + + + + + + - + diff --git a/components/DataCenter/Right.vue b/components/DataCenter/Right.vue index f754cf6..152b328 100644 --- a/components/DataCenter/Right.vue +++ b/components/DataCenter/Right.vue @@ -29,8 +29,7 @@ import { body } from '@/config/layout/dataCenterBody'; background-position: left top; background-size: 100% 100%; background-repeat: no-repeat; -} -.title { - font-weight: bold; + display: flex; + flex-direction: column; } diff --git a/components/DataCenter/YieldChart.vue b/components/DataCenter/YieldChart.vue index 4c73609..8dd37a0 100644 --- a/components/DataCenter/YieldChart.vue +++ b/components/DataCenter/YieldChart.vue @@ -1,9 +1,47 @@ -产量对比 + + + - - + diff --git a/config/layout/dataCenterBody.js b/config/layout/dataCenterBody.js index 6a1113f..bac5a4e 100644 --- a/config/layout/dataCenterBody.js +++ b/config/layout/dataCenterBody.js @@ -62,7 +62,7 @@ export const body = { align: 'center', height: '40rem', }, - component: 'ComplexChart', + component: 'DataCenterComplexChart', }, ], }, diff --git a/package.json b/package.json index 9d36bae..2aaf451 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "axios": "^0.24.0", "dayjs": "^1.10.7", "echarts": "^5.2.2", - "echarts-gl": "^2.0.8" + "echarts-gl": "^2.0.8", + "lodash": "^4.17.21" } } diff --git a/server/api/datas.ts b/server/api/datas.ts new file mode 100644 index 0000000..bce1f69 --- /dev/null +++ b/server/api/datas.ts @@ -0,0 +1,6 @@ +import type { IncomingMessage, ServerResponse } from 'http'; +import { datas } from '../mocks/datas'; + +export default async (req: IncomingMessage, res: ServerResponse) => { + return { code: 200, msg: 'ok', data: datas }; +}; diff --git a/server/mocks/datas.js b/server/mocks/datas.js new file mode 100644 index 0000000..0dd5876 --- /dev/null +++ b/server/mocks/datas.js @@ -0,0 +1,290 @@ +export const datas = [ + { + time: '00:00', + roomT: 19, + roomH: 60, + outT: '-5', + outH: 60, + soilT: 6, + soilH: 40, + windSpeed: 0, + co2: '0.01 ', + light: 3, + }, + { + time: '01:00', + roomT: 19, + roomH: 70, + outT: '-6', + outH: 70, + soilT: 7, + soilH: 50, + windSpeed: 2, + co2: '0.02 ', + light: 2, + }, + { + time: '02:00', + roomT: 19, + roomH: 80, + outT: '-7', + outH: 80, + soilT: 7, + soilH: 60, + windSpeed: 3, + co2: '0.03 ', + light: 1, + }, + { + time: '03:00', + roomT: 19, + roomH: 90, + outT: '-8', + outH: 90, + soilT: 7, + soilH: 70, + windSpeed: 7, + co2: '0.04 ', + light: 1, + }, + { + time: '04:00', + roomT: 18, + roomH: 100, + outT: '-9', + outH: 100, + soilT: 5, + soilH: 80, + windSpeed: 9, + co2: '0.05 ', + light: 4, + }, + { + time: '05:00', + roomT: 18, + roomH: 95, + outT: '-10', + outH: 95, + soilT: 5, + soilH: 75, + windSpeed: 14, + co2: '0.06 ', + light: 8, + }, + { + time: '06:00', + roomT: 19, + roomH: 90, + outT: '-5', + outH: 90, + soilT: 7, + soilH: 70, + windSpeed: 12, + co2: '0.07 ', + light: 10, + }, + { + time: '07:00', + roomT: 19, + roomH: 85, + outT: '-1', + outH: 85, + soilT: 7, + soilH: 65, + windSpeed: 15, + co2: '0.08 ', + light: 20, + }, + { + time: '08:00', + roomT: 20, + roomH: 80, + outT: 0, + outH: 80, + soilT: 10, + soilH: 60, + windSpeed: 13, + co2: '0.09 ', + light: 26, + }, + { + time: '09:00', + roomT: 20, + roomH: 75, + outT: 1, + outH: 75, + soilT: 12, + soilH: 55, + windSpeed: 14, + co2: '0.09 ', + light: 35, + }, + { + time: '10:00', + roomT: 21, + roomH: 70, + outT: 2, + outH: 70, + soilT: 14, + soilH: 50, + windSpeed: 9, + co2: '0.12 ', + light: 45, + }, + { + time: '11:00', + roomT: 21, + roomH: 65, + outT: 3, + outH: 65, + soilT: 16, + soilH: 45, + windSpeed: 5, + co2: '0.14 ', + light: 50, + }, + { + time: '12:00', + roomT: 23, + roomH: 60, + outT: 4, + outH: 60, + soilT: 19, + soilH: 40, + windSpeed: 8, + co2: '0.16 ', + light: 55, + }, + { + time: '13:00', + roomT: 24, + roomH: 55, + outT: 5, + outH: 55, + soilT: 22, + soilH: 35, + windSpeed: 7, + co2: '0.18 ', + light: 65, + }, + { + time: '14:00', + roomT: 28, + roomH: 50, + outT: 6, + outH: 50, + soilT: 23, + soilH: 30, + windSpeed: 6, + co2: '0.20 ', + light: 80, + }, + { + time: '15:00', + roomT: 28, + roomH: 45, + outT: 6, + outH: 45, + soilT: 23, + soilH: 25, + windSpeed: 4, + co2: '0.19 ', + light: 70, + }, + { + time: '16:00', + roomT: 26, + roomH: 40, + outT: 7, + outH: 40, + soilT: 20, + soilH: 20, + windSpeed: 11, + co2: '0.18 ', + light: 65, + }, + { + time: '17:00', + roomT: 25, + roomH: 45, + outT: 5, + outH: 45, + soilT: 17, + soilH: 25, + windSpeed: 8, + co2: '0.17 ', + light: 55, + }, + { + time: '18:00', + roomT: 24, + roomH: 50, + outT: 5, + outH: 50, + soilT: 14, + soilH: 30, + windSpeed: 5, + co2: '0.16 ', + light: 40, + }, + { + time: '19:00', + roomT: 23, + roomH: 55, + outT: 1, + outH: 55, + soilT: 11, + soilH: 35, + windSpeed: 1, + co2: '0.15 ', + light: 35, + }, + { + time: '20:00', + roomT: 22, + roomH: 60, + outT: 0, + outH: 60, + soilT: 8, + soilH: 40, + windSpeed: 5, + co2: '0.14 ', + light: 25, + }, + { + time: '21:00', + roomT: 21, + roomH: 65, + outT: 0, + outH: 65, + soilT: 7, + soilH: 45, + windSpeed: 4, + co2: '0.13 ', + light: 6, + }, + { + time: '22:00', + roomT: 20, + roomH: 70, + outT: '-3', + outH: 70, + soilT: 6, + soilH: 50, + windSpeed: 6, + co2: '0.12 ', + light: 5, + }, + { + time: '23:00', + roomT: 20, + roomH: 75, + outT: '-4', + outH: 75, + soilT: 5, + soilH: 55, + windSpeed: 7, + co2: '0.11 ', + light: 4, + }, +]; diff --git a/utils/complexChart.js b/utils/complexChart.js new file mode 100644 index 0000000..ee46e16 --- /dev/null +++ b/utils/complexChart.js @@ -0,0 +1,177 @@ +/* eslint-disable max-len,object-curly-newline */ +import max from 'lodash/max'; +import { + colors, + generateDefaultSeries, + itemColor, + legendData, + yAxisData, +} from './complexConfig'; + +/** + * 生成chart所需参数 + * @param {Object[]} data 服务端返回数据 + * @returns {{environmentTemperature: *[], corrosionXIN: *[], corrosionGANG: *[], corrosionTONG: *[], so2: *[], corrosionLV: *[], time: *[], saltT: *[], saltR: *[], environmentHumidity: *[]}} + */ +function generateParams(data) { + const result = { + time: [], + roomT: [], + roomH: [], + outT: [], + outH: [], + soilT: [], + soilH: [], + windSpeed: [], + co2: [], + light: [], + }; + data.forEach(item => { + result.time.push(item.time); + result.roomT.push(+item.roomT); + result.roomH.push(+item.roomH); + result.outT.push(+item.outT); + result.outH.push(+item.outH); + result.soilT.push(+item.soilT); + result.soilH.push(+item.soilH); + result.windSpeed.push(+item.windSpeed); + result.co2.push(+item.co2); + result.light.push(+item.light); + }); + return result; +} + +/** + * 计算Y轴的显示 + * @param {string} yName Y轴的name + * @param {Object} selectedLegend legends + * @returns {boolean} + */ +export function computeYAxisShow(yName, selectedLegend) { + // eslint-disable-next-line guard-for-in,no-restricted-syntax + for (const key in selectedLegend) { + if (key.includes(yName) && selectedLegend[key]) { + return true; + } + } + return false; +} + +/** + * 生产y轴内容 + * @param {Object} selectedLegend + * @returns {({axisLabel: {formatter: string}, axisLine: {lineStyle: {color: string}, show: boolean}, name: string, position: string, type: string}|{axisLabel: {formatter: string}, offset: number, axisLine: {lineStyle: {color: string}, show: boolean}, name: string, position: string, type: string}|{axisLabel: {formatter: string}, offset: number, axisLine: {lineStyle: {color: string}, show: boolean}, name: string, position: string, type: string}|{axisLabel: {formatter: string}, offset: number, axisLine: {lineStyle: {color: string}, show: boolean}, name: string, position: string, type: string}|{axisLabel: {formatter: string}, axisLine: {lineStyle: {color: string}, show: boolean}, name: string, position: string, type: string})[]} + */ +export function generateYAxis(selectedLegend) { + let leftIndex = 0; + let rightIndex = 0; + yAxisData.forEach(item => { + item.show = computeYAxisShow(item.name, selectedLegend); + if (item.show) { + if (item.position === 'left') { + item.offset = 40 * leftIndex; + leftIndex += 1; + } else { + item.offset = 40 * rightIndex; + rightIndex += 1; + } + } + }); + return yAxisData; +} + +/** + * 生成series数据 + * @param {Object} data + * @param {Object[]} yAxis + * @returns {({data: ([]|number|string|*), name: string, type: string}|{data: ([]|number|BufferSource|string|*), name: string, type: string, yAxisIndex: number}|{data: ([]|string|*), name: string, type: string, yAxisIndex: number}|{data: ([]|string|*), name: string, type: string, yAxisIndex: number}|{data: [], name: string, type: string, yAxisIndex: number})[]|*[]} + */ +function generateSeries(data, yAxis) { + const seriesArr = generateDefaultSeries(data); + const showArr = seriesArr.filter(item => + yAxis.find(y => y.name === item.name), + ); + const hideArr = seriesArr.filter( + item => !yAxis.find(y => y.name === item.name), + ); + const result = [...showArr, ...hideArr]; + result.forEach(item => { + item.itemStyle = { color: itemColor[item.name] }; + if (item.name.includes('温度')) { + item.yAxisIndex = 0; + } else if (item.name.includes('湿度')) { + item.yAxisIndex = 1; + } else if (item.name.includes('风速')) { + item.yAxisIndex = 2; + } else if (item.name.includes('CO2')) { + item.yAxisIndex = 3; + } else if (item.name.includes('光照')) { + item.yAxisIndex = 4; + } + }); + return result || []; +} + +/** + * 计算图表grid left right值 + * @param {Object[]} yAxis + * @returns {{left: number, right: number}} + */ +function generateGrid(yAxis) { + const left = []; + const right = []; + yAxis.forEach(item => { + if (item.show) { + if (item.position === 'left') { + left.push(item.offset || 0); + } else { + right.push(item.offset || 0); + } + } + }); + return { + left: max(left) + 40, + right: max(right) + 40, + bottom: 20, + }; +} + +/** + * 生成chart参数 + * @param {Object[]} rawData 返回段返回的data数据 + * @param {Object} selected 选中的legend + * @returns {{yAxis: ({axisLabel: {formatter: string}, axisLine: {lineStyle: {color: string}, show: boolean}, name: string, position: string, type: string}|{axisLabel: {formatter: string}, offset: number, axisLine: {lineStyle: {color: string}, show: boolean}, name: string, position: string, type: string})[], xAxis: [{data: *[], axisTick: {alignWithLabel: boolean}, type: string}], color: [string,string,string,string,string,string,string,string,string], grid: {left: number, right: number}, legend: {data: [string,string,string,string,string,string,string,string,string], type: string, selected}, series: (({data: ([]|number|string|*), name: string, type: string}|{data: ([]|number|BufferSource|string|*), name: string, type: string, yAxisIndex: number}|{data: ([]|string|*), name: string, type: string, yAxisIndex: number}|{data: [], name: string, type: string, yAxisIndex: number})[]|*[]), tooltip: {axisPointer: {type: string, snap: boolean}, trigger: string}, dataZoom: [{type: string},{type: string}]}} + */ +export function generateChartOption(rawData, selected) { + const data = generateParams(rawData); + const yAxis = generateYAxis(selected); + const series = generateSeries(data, yAxis); + const grid = generateGrid(yAxis); + const option = { + color: colors, + darkMode: true, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross', + snap: true, + }, + }, + grid, + legend: { + type: 'scroll', + selected, + data: legendData, + }, + xAxis: [ + { + type: 'category', + axisTick: { alignWithLabel: true }, + data: data.time, + }, + ], + yAxis, + series, + }; + return option; +} diff --git a/utils/complexConfig.js b/utils/complexConfig.js new file mode 100644 index 0000000..5970042 --- /dev/null +++ b/utils/complexConfig.js @@ -0,0 +1,202 @@ +/* eslint-disable max-len */ +export const colors = [ + '#EAB308', + '#F97316', + '#EC4899', + '#F43F5E', + '#D946EF', + '#06B6D4', + '#B45309', + '#1E40AF', + '#166534', +]; + +export const itemColor = { + '室内温度(℃)': colors[5], + '室外温度(℃)': colors[6], + '土壤温度(℃)': colors[7], + '室内湿度(RH%)': colors[8], + '室外湿度(RH%)': colors[0], + '土壤湿度(RH%)': colors[1], + '风速(m/s)': colors[2], + 'CO2(%)': colors[3], + '光照(klux)': colors[4], +}; + +export const legendData = [ + { + name: '室外湿度(RH%)', + itemStyle: { color: colors[0] }, + listStyle: { color: colors[0] }, + }, + { + name: '土壤湿度(RH%)', + itemStyle: { color: colors[1] }, + listStyle: { color: colors[1] }, + }, + { + name: '风速(m/s)', + itemStyle: { color: colors[2] }, + listStyle: { color: colors[2] }, + }, + { + name: 'CO2(%)', + itemStyle: { color: colors[3] }, + listStyle: { color: colors[3] }, + }, + { + name: '光照(klux)', + itemStyle: { color: colors[4] }, + listStyle: { color: colors[4] }, + }, + { + name: '室内温度(℃)', + itemStyle: { color: colors[5] }, + listStyle: { color: colors[5] }, + }, + { + name: '室外温度(℃)', + itemStyle: { color: colors[6] }, + listStyle: { color: colors[6] }, + }, + { + name: '土壤温度(℃)', + itemStyle: { color: colors[7] }, + listStyle: { color: colors[7] }, + }, + { + name: '室内湿度(RH%)', + itemStyle: { color: colors[8] }, + listStyle: { color: colors[8] }, + }, +]; + +// y轴定义 +export const yAxisData = [ + { + type: 'value', + name: '温度', + offset: 0, + position: 'left', + axisLine: { + show: true, + lineStyle: { color: colors[7] }, + }, + axisLabel: { formatter: '{value}' }, + axisPointer: { show: false }, + }, + { + type: 'value', + name: '湿度', + offset: 70, + position: 'left', + axisLine: { + show: true, + lineStyle: { color: colors[1] }, + }, + axisLabel: { formatter: '{value}' }, + axisPointer: { show: false }, + }, + { + type: 'value', + name: '风速', + offset: 0, + position: 'right', + axisLine: { + show: true, + lineStyle: { color: colors[2] }, + }, + axisLabel: { formatter: '{value}' }, + axisPointer: { show: false }, + }, + { + type: 'value', + name: 'CO2', + position: 'right', + show: false, + offset: 80, + axisLine: { + show: true, + lineStyle: { color: colors[3] }, + }, + axisLabel: { formatter: '{value}' }, + axisPointer: { show: false }, + }, + { + type: 'value', + name: '光照', + show: false, + position: 'right', + offset: 160, + axisLine: { + show: true, + lineStyle: { color: colors[4] }, + }, + axisLabel: { formatter: '{value}' }, + axisPointer: { show: false }, + }, +]; + +/** + * 生成默认数据 + * @param {Object} data + * @returns {[{data: (number|[]|string|*), name: string, type: string},{data: (number|[]|BufferSource|string|*), name: string, type: string, yAxisIndex: number},{data: ([]|string|*), name: string, type: string, yAxisIndex: number},{data: ([]|string|*), name: string, type: string, yAxisIndex: number},{data: [], name: string, type: string, yAxisIndex: number},null,null,null]} + */ +export function generateDefaultSeries(data) { + return [ + { + name: '室内温度(℃)', + type: 'line', + yAxisIndex: 0, + data: data.roomT, + }, + { + name: '室外温度(℃)', + type: 'line', + yAxisIndex: 0, + data: data.outT, + }, + { + name: '土壤温度(℃)', + type: 'line', + yAxisIndex: 0, + data: data.soilT, + }, + { + name: '室内湿度(RH%)', + type: 'line', + yAxisIndex: 0, + data: data.roomH, + }, + { + name: 'CO2(%)', + type: 'line', + yAxisIndex: 1, + data: data.co2, + }, + { + name: '风速(m/s)', + type: 'line', + yAxisIndex: 1, + data: data.windSpeed, + }, + { + name: '光照(klux)', + type: 'line', + yAxisIndex: 2, + data: data.light, + }, + { + name: '室外湿度(RH%)', + type: 'line', + yAxisIndex: 3, + data: data.outH, + }, + { + name: '土壤湿度(RH%)', + type: 'line', + yAxisIndex: 4, + data: data.soilH, + }, + ]; +} diff --git a/utils/map.js b/utils/map.js index 229f12e..d33f2f0 100644 --- a/utils/map.js +++ b/utils/map.js @@ -35,8 +35,7 @@ function initValues() { export function initOptions() { return { - zoom: 0.4, - + backgroundColor: 'transparent', visualMap: { show: true, min: 0, @@ -74,15 +73,15 @@ export function initOptions() { [ { offset: 0, - color: '#00aa32', // 天空颜色 + color: '#0c2771', // 天空颜色 }, { offset: 0.7, - color: '#998866', // 地面颜色 + color: '#026fab', // 地面颜色 }, { offset: 1, - color: '#000', // 地面颜色 + color: '#01285c', // 地面颜色 }, ], false, diff --git a/yarn.lock b/yarn.lock index e8d9731..4398de6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3274,6 +3274,11 @@ lodash@^4.17.20: resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw= +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.nlark.com/lodash/download/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw= + log-symbols@^5.0.0: version "5.0.0" resolved "https://registry.nlark.com/log-symbols/download/log-symbols-5.0.0.tgz#7720d3c6a56c365e1f658916069ba18d941092ca"