From 9e0df95ffda0ef9f2339f7caf413b357640aea28 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期一, 06 五月 2024 08:45:14 +0800 Subject: [PATCH] 完成历史轨迹展示 --- src/views/historymode/HistoryMode.vue | 87 ++++ package-lock.json | 14 src/model/FactorDatas.js | 168 ++++++++ src/model/Factor.js | 222 +++++++++++ src/components/search/SearchBar.vue | 27 + src/utils/map/calculate.js | 57 +++ src/components/search/OptionTime.vue | 1 src/styles/elementUI.scss | 12 src/assets/3dmap.css | 11 src/components/map/MapToolbox.vue | 10 src/model/Legend.js | 294 +++++++++++++++ src/components/monitor/FactorRadio.vue | 24 + src/assets/base.css | 2 src/api/monitorDataApi.js | 23 + index.html | 2 package.json | 2 src/constant/device-type.js | 12 src/components/search/OptionMission.vue | 4 src/components/search/OptionType.vue | 2 vite.config.js | 1 src/constant/radio-options.js | 156 ++++--- 21 files changed, 1,012 insertions(+), 119 deletions(-) diff --git a/index.html b/index.html index 0c69b21..fc727ed 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ <meta charset="UTF-8" /> <link rel="icon" href="/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>Vite App</title> + <title>椋炵窘澶ф皵鐜鏅鸿兘璧拌埅鐩戞祴绯荤粺</title> </head> <body> <div id="app"></div> diff --git a/package-lock.json b/package-lock.json index 34e52f7..e5db76b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "eslint-plugin-vue": "^9.17.0", "jsdom": "^24.0.0", "prettier": "^3.0.3", - "sass": "^1.72.0", + "sass": "^1.76.0", "vite": "^5.1.6", "vitest": "^1.4.0" } @@ -3514,9 +3514,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.72.0", - "resolved": "https://registry.npmmirror.com/sass/-/sass-1.72.0.tgz", - "integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==", + "version": "1.76.0", + "resolved": "https://registry.npmmirror.com/sass/-/sass-1.76.0.tgz", + "integrity": "sha512-nc3LeqvF2FNW5xGF1zxZifdW3ffIz5aBb7I7tSvOoNu7z1RQ6pFt9MBuiPtjgaI62YWrM/txjWlOCFiGtf2xpw==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -6966,9 +6966,9 @@ "dev": true }, "sass": { - "version": "1.72.0", - "resolved": "https://registry.npmmirror.com/sass/-/sass-1.72.0.tgz", - "integrity": "sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==", + "version": "1.76.0", + "resolved": "https://registry.npmmirror.com/sass/-/sass-1.76.0.tgz", + "integrity": "sha512-nc3LeqvF2FNW5xGF1zxZifdW3ffIz5aBb7I7tSvOoNu7z1RQ6pFt9MBuiPtjgaI62YWrM/txjWlOCFiGtf2xpw==", "dev": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", diff --git a/package.json b/package.json index b023b5e..cac16c5 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "eslint-plugin-vue": "^9.17.0", "jsdom": "^24.0.0", "prettier": "^3.0.3", - "sass": "^1.72.0", + "sass": "^1.76.0", "vite": "^5.1.6", "vitest": "^1.4.0" } diff --git a/src/api/monitorDataApi.js b/src/api/monitorDataApi.js index 0b9970f..60130ec 100644 --- a/src/api/monitorDataApi.js +++ b/src/api/monitorDataApi.js @@ -1,11 +1,26 @@ import { $http } from './index'; /** - * + * 璧拌埅鐩戞祴鏁版嵁鐩稿叧API */ export default { - fethcRealtimeData(deviceCode, type, page, perPage) { - const params = `deviceCode=${deviceCode}&type=${type}&page=${page}&perPage=${perPage}`; - $http.get(`air/realtime/sec?${params}`); + /** + * 鑾峰彇鏈�鏂版暟鎹� + * @returns + */ + fethcRealtimeData({ deviceCode, type, page, perPage }) { + return this.fetchHistroyData({ deviceCode, type, page, perPage }); + }, + + /** + * 鑾峰彇鍘嗗彶鏁版嵁 + * @returns + */ + fetchHistroyData({ deviceCode, startTime, endTime, type, page, perPage }) { + let params = `deviceCode=${deviceCode}&page=${page}&perPage=${perPage}`; + params += type ? `&type=${type}` : ''; + params += startTime ? `&startTime=${startTime}` : ''; + params += endTime ? `&type=${endTime}` : ''; + return $http.get(`air/realtime/sec?${params}`).then((res) => res.data); } }; diff --git a/src/assets/3dmap.css b/src/assets/3dmap.css index 0ddf6ed..489d0bf 100644 --- a/src/assets/3dmap.css +++ b/src/assets/3dmap.css @@ -68,7 +68,7 @@ .map-factor-selector { position: absolute; left: 1px; - top: 64px; + top: 41px; z-index: 100px; } @@ -96,12 +96,11 @@ } .map-date-selector { - position: absolute; + position: relative; left: 0; right: 0; - top: 70px; - padding: 0 4px; - /* background-color: #ffffffb0; */ + top: 0px; + /* padding: 0 4px; */ /* color: ffffffbd; */ } @@ -165,7 +164,7 @@ .map-mode-change { position: absolute; left: 10px; - top: 80px; + top: 104px; z-index: 1000px; padding: 1px; font-size: 1rem; diff --git a/src/assets/base.css b/src/assets/base.css index b87ba0d..12df2d2 100644 --- a/src/assets/base.css +++ b/src/assets/base.css @@ -12,7 +12,7 @@ } body { - --screen-min-width: 1200px; + --screen-min-width: 1440px; --screen-min-height: 600px; min-height: var(--screen-min-height); min-width: var(--screen-min-width); diff --git a/src/components/map/MapToolbox.vue b/src/components/map/MapToolbox.vue index 0ad54f6..ba324db 100644 --- a/src/components/map/MapToolbox.vue +++ b/src/components/map/MapToolbox.vue @@ -101,17 +101,7 @@ left: 2px; } -.el-button-custom { - --el-button-bg-color: var(--bg-color); - --el-button-hover-text-color: var(--select_color); - --el-button-hover-bg-color: var(--bg-color); - --el-button-border-color: var(--font-color); - --el-button-active-border-color: transparent; -} -.el-button-custom:focus-visible { - outline: 0px solid var(--el-button-outline-color); -} .el-button { margin: initial !important; diff --git a/src/components/monitor/FactorRadio.vue b/src/components/monitor/FactorRadio.vue index 8d8d1c6..5282125 100644 --- a/src/components/monitor/FactorRadio.vue +++ b/src/components/monitor/FactorRadio.vue @@ -13,14 +13,34 @@ <script> // 鐩戞祴鍥犲瓙鍗曢�夋 import { radioOptions } from '@/constant/radio-options'; +import { TYPE0 } from '@/constant/device-type'; + export default { + props: { + deviceType: { + type: String, + // type0: 杞﹁浇鎴栨棤浜烘満; type1:鏃犱汉鑸� + default: TYPE0 + } + }, emits: ['change'], data() { return { - radio: radioOptions.type0[0].value, - options: radioOptions.type0 + radio: radioOptions(TYPE0)[0].value }; }, + computed: { + options() { + return radioOptions(this.deviceType); + } + }, + watch: { + deviceType(nV, oV) { + if (nV != oV) { + this.radio = this.options[0].value; + } + } + }, method: { handleChange(value) { this.$emit('change', value); diff --git a/src/components/search/OptionMission.vue b/src/components/search/OptionMission.vue index 8e200aa..195e3d2 100644 --- a/src/components/search/OptionMission.vue +++ b/src/components/search/OptionMission.vue @@ -18,7 +18,7 @@ </template> <script> -import missionApi from '../../api/missionApi'; +import missionApi from '@/api/missionApi'; import { useFetchData } from '@/composables/fetchData'; export default { @@ -64,7 +64,7 @@ } }; </script> -<style scoped> +<style> /* :deep() .el-form-item__label { color: red !important; } */ diff --git a/src/components/search/OptionTime.vue b/src/components/search/OptionTime.vue index 0f352f7..24a1d9f 100644 --- a/src/components/search/OptionTime.vue +++ b/src/components/search/OptionTime.vue @@ -37,4 +37,3 @@ } }; </script> -<style scoped></style> diff --git a/src/components/search/OptionType.vue b/src/components/search/OptionType.vue index 5b9334f..5ed124c 100644 --- a/src/components/search/OptionType.vue +++ b/src/components/search/OptionType.vue @@ -43,6 +43,7 @@ }, methods: { handleChange(value) { + // todo 鏍规嵁璁惧绫诲瀷鍒囨崲鍦板浘杞藉叿鐨勫浘鏍囥�� this.$emit('update:modelValue', value); } }, @@ -51,4 +52,3 @@ } }; </script> -<style scoped></style> diff --git a/src/components/search/SearchBar.vue b/src/components/search/SearchBar.vue index 03e4082..003c1a0 100644 --- a/src/components/search/SearchBar.vue +++ b/src/components/search/SearchBar.vue @@ -1,5 +1,5 @@ <template> - <BaseCard class="map-date-selector"> + <BaseCard class="map-date-selector flexbox-col align-items"> <template #content> <el-form :inline="true"> <OptionMission v-model="formSearch.missionCode"></OptionMission> @@ -9,6 +9,9 @@ v-model="formSearch.deviceCode" ></OptionDevice> <OptionTime v-model="formSearch.timeArray"></OptionTime> + <el-button type="primary" class="el-button-custom" @click="handleClick"> + 鍒嗘瀽 + </el-button> </el-form> </template> </BaseCard> @@ -17,6 +20,9 @@ <script> // 鎼滅储妗� export default { + props: { + searchTime: Array + }, data() { return { formSearch: { @@ -27,7 +33,22 @@ } }; }, - method: {} + emits: ['search'], + watch: { + searchTime(nV, oV) { + if (nV != oV) { + this.timeArray = this.searchTime; + } + } + }, + method: { + handleClick() { + this.$emit('search', this.formSearch); + } + } }; </script> -<style scoped></style> +<style lang="scss"> +.fy-container { +} +</style> diff --git a/src/constant/device-type.js b/src/constant/device-type.js new file mode 100644 index 0000000..8d163f8 --- /dev/null +++ b/src/constant/device-type.js @@ -0,0 +1,12 @@ +// 杞﹁浇 +const TYPE0 = '0a'; +// 鏃犱汉鏈� +const TYPE1 = '0b'; +// 鏃犱汉鑸� +const TYPE2 = '0c'; +// 瀹氱偣鐩戞祴 +const TYPE3 = '0d'; +// 鐢ㄧ數閲� +const TYPE4 = '31'; + +export { TYPE0, TYPE1, TYPE2, TYPE3, TYPE4 }; diff --git a/src/constant/radio-options.js b/src/constant/radio-options.js index 3e5b2d8..28df36d 100644 --- a/src/constant/radio-options.js +++ b/src/constant/radio-options.js @@ -1,74 +1,84 @@ +import { TYPE0, TYPE1, TYPE2 } from '@/constant/device-type'; + // 鐩戞祴鍥犲瓙鍗曢�夋閫夐」 -export const radioOptions = { - type0: [ - //鏃犱汉鏈� - { - label: 'NO2', - name: 'NO2', - value: '1' - }, - { - label: 'CO', - name: 'CO', - value: '2' - }, - { - label: 'H2S', - name: 'H2S', - value: '3' - }, - { - label: 'SO2', - name: 'SO2', - value: '4' - }, - { - label: 'O3', - name: 'NO2', - value: '5' - }, - { - label: 'PM2.5', - name: 'PM25', - value: '6' - }, - { - label: 'PM10', - name: 'PM10', - value: '7' - }, - { - label: 'TVOC', - name: 'VOC', - value: '10' - } - ], - type1: [ - //鏃犱汉鑸� - { - label: '娓╁害', - name: '娓╁害', - value: '1' - }, - { - label: '鐢靛鐜�', - name: '鐢靛鐜�', - value: '2' - }, - { - label: '娴婂害', - name: '娴婂害', - value: '3' - }, - { - label: '婧惰В姘�', - name: '婧惰В姘�', - value: '4' - }, - { - label: 'PH', - name: 'PH', - value: '5' - } - ] -}; +function radioOptions(deviceType) { + if ([TYPE0, TYPE1].includes(deviceType)) { + return option1; + } else if (deviceType == TYPE2) { + return option2; + } else { + return []; + } +} + +const option1 = [ + { + label: 'NO2', + name: 'NO2', + value: '1' + }, + { + label: 'CO', + name: 'CO', + value: '2' + }, + { + label: 'H2S', + name: 'H2S', + value: '3' + }, + { + label: 'SO2', + name: 'SO2', + value: '4' + }, + { + label: 'O3', + name: 'NO2', + value: '5' + }, + { + label: 'PM2.5', + name: 'PM25', + value: '6' + }, + { + label: 'PM10', + name: 'PM10', + value: '7' + }, + { + label: 'TVOC', + name: 'VOC', + value: '10' + } +]; + +const option2 = [ + { + label: '娓╁害', + name: '娓╁害', + value: '1' + }, + { + label: '鐢靛鐜�', + name: '鐢靛鐜�', + value: '2' + }, + { + label: '娴婂害', + name: '娴婂害', + value: '3' + }, + { + label: '婧惰В姘�', + name: '婧惰В姘�', + value: '4' + }, + { + label: 'PH', + name: 'PH', + value: '5' + } +]; +export { radioOptions }; diff --git a/src/model/Factor.js b/src/model/Factor.js new file mode 100644 index 0000000..47730e4 --- /dev/null +++ b/src/model/Factor.js @@ -0,0 +1,222 @@ +import { Legend } from './Legend'; + +const _hMap = { + 1: [0, 1000], //NO2 + 2: [0, 2000], //CO + 3: [0, 1000], //H2S + 4: [0, 1000], //SO2 + 5: [0, 1000], //O3 + 6: [0, 1000], //PM2.5 + 7: [0, 1000], //PM10 + 8: [0, 100], //TEMPERATURE + 9: [0, 100], //HUMIDITY + 10: [0, 500], //VOC + 11: [0, 1000] //NOI +}; +const _hRange = [0, 1000]; + +function getFactorHeight(type, data, _range) { + var range = _range == undefined ? _hMap.get(type) : _range; + var min = range[0]; + var max = range[1]; + var scale = max - min == 0 ? 0 : (_hRange[1] - _hRange[0]) / (max - min); + var offset = min; + // console.log("height:" + (data - offset) * scale * 10); + if (data < range[0]) { + return (range[0] - offset) * scale * 10; + } else if (data > range[1]) { + return (range[1] - offset) * scale * 10; + } else { + return (data - offset) * scale * 10; + } +} + +/** + * 鐩戞祴鍥犲瓙绫� + * 瀛樺偍鏌愪竴绫诲瀷鐨勭洃娴嬪洜瀛愭暟鎹紝鎻愪緵3d鍦板浘缁樺埗楂樺害鎹㈢畻锛岀粯鍥捐寖鍥磋瀹氱瓑鍔熻兘 + * 鐢ㄤ簬3d鍦板浘缁樺埗 + */ +function Factor(options) { + /** + * {factorData: 43.209 + factorId: "1" + factorName: "NO2" + physicalQuantity: 211.1 + sensorId: null + statusList: null} + */ + this.datas = []; // 鍘熷鏁版嵁 + // this.lnglats = [] //3d鍦板浘褰撳墠灞曠ず鍧愭爣鐐规暟缁� + this.factorName; + this.factorId; + this.heights = []; //3d鍦板浘褰撳墠灞曠ず鍧愭爣鐐瑰搴旂殑楂樺害鏁扮粍 + this.colors = []; // 3d鍦板浘褰撳墠灞曠ず鍧愭爣鐐瑰搴旂殑棰滆壊鏁扮粍 + this.bottomColor; //鏈�灏忓�煎搴旂殑鍥句緥鑹� + this.min = -1; // 褰撳墠鏄剧ず鐨勬渶灏忓�� + this.max = -1; // 褰撳墠鏄剧ず鐨勬渶澶у�� + this.originMin = -1; // 鍘熷鏁版嵁涓殑鏈�灏忓�� + this.originMax = -1; // 鍘熷鏁版嵁涓殑鏈�澶у�� + this.standardMin = -1; //鐩戞祴鍥犲瓙绫诲瀷瀵瑰簲鐨勬爣鍑嗘渶灏忓�� + this.standardMax = -1; //鐩戞祴鍥犲瓙绫诲瀷瀵瑰簲鐨勬爣鍑嗘渶澶у�� + + this.legendType = Legend.S_TYPE; //鍥句緥妯″紡 + + if (options != undefined) { + this.datas = options.datas; + this.heights = options.heights; + this.min = options.min; + this.max = options.max; + this.originMin = options.originMin; + this.originMax = options.originMax; + + this.factorName = options.factorName; + this.factorId = options.factorId; + this.colors = options.colors; + this.bottomColor = options.bottomColor; + this.standardMin = options.standardMin; + this.standardMax = options.standardMax; + } +} + +Factor.prototype = { + // drawMode: 缁樺埗妯″紡锛�0锛氳嚜鍔ㄦā寮忥紝鑷姩璁$畻褰撳墠鏁版嵁鐨勮寖鍥达紝缁樺埗鍚堥�傜殑姣斾緥锛�1锛氭墜鍔ㄦā寮忥紝鏍规嵁椤甸潰璁剧疆鐨勭粯鍥捐寖鍥磋繘琛岀粯鍒� + pushData: function (data, drawMode) { + if (this.factorName == undefined) { + this.factorName = data.factorName; + this.factorId = data.factorId; + } else { + if (this.factorName != data.factorName) { + console.log( + '閿欒: Factor涓彃鍏ョ殑鏁版嵁鍓嶅悗鍚嶇О涓嶄竴鑷达紝鍘熷洜瀛愶細' + + this.factorName + + '锛屾柊鍥犲瓙锛�' + + data.factorName + ); + } + } + this.datas.push(data); + this.getRange(data, drawMode); + + if (this.standardMin == -1) { + var range = Legend.getStandardRange(this.factorName); + this.standardMin = range[0]; + this.standardMax = range[1]; + } + }, + getRange: function (data, drawMode) { + if (this.min == -1) { + this.min = data.factorData; + this.max = data.factorData; + } + if (this.originMin == -1) { + this.originMin = data.factorData; + this.originMax = data.factorData; + } + if (drawMode == 0) { + this.min = Math.min(this.min, data.factorData); + this.max = Math.max(this.max, data.factorData); + // this.min = this.standardMin + // this.max = this.standardMax + } + this.originMin = Math.min(this.originMin, data.factorData); + this.originMax = Math.max(this.originMax, data.factorData); + }, + getHeight: function () { + this.heights = []; + this.colors = []; + this.datas.forEach((d) => { + var h = getFactorHeight(d.factorId, d.factorData, [this.min, this.max]); + if (d.factorData == -1) { + h = -1; + } + this.heights.push(h); + var c = Legend.getColor( + this.factorName, + this.legendType, + d.factorData, + this.min, + this.max + ); + this.colors.push(c); + // this.heights.push(d.factorData) + }); + this.bottomColor = Legend.getColor( + this.factorName, + this.legendType, + this.standardMin, + this.min, + this.max + ); + // console.log(this.factorName + ':' + this.bottomColor); + }, + setRange: function (range) { + this.min = range[0]; + this.max = range[1]; + this.legendType = Legend.C_TYPE; + this.getHeight(); + }, + clearRange: function () { + this.min = this.originMin; + this.max = this.originMax; + this.legendType = Legend.D_TYPE; + this.getHeight(); + }, + standardRange: function () { + this.min = this.originMin; + this.max = this.originMax; + // this.min = this.standardMin + // this.max = this.standardMax + this.legendType = Legend.S_TYPE; + this.getHeight(); + }, + // 鏍规嵁寮�濮嬪拰缁撴潫涓嬫爣鑾峰彇瀵瑰簲浣嶇疆鏁版嵁闆� + getByIndex: function (s, e) { + var d = this.datas.slice(s, e); + var h = this.heights.slice(s, e); + return new Factor({ + datas: d, + heights: h, + min: this.min, + max: this.max, + originMin: this.originMin, + originMax: this.originMax, + factorName: this.factorName, + colors: this.colors, + bottomColor: this.bottomColor, + standardMin: this.standardMin, + standardMax: this.standardMax + }); + }, + // 鏂板鏁版嵁鍚屾椂鎻掑抚 + insertFrame: function (factor, count, isDraw) { + var d1 = this.datas[this.datas.length - 1]; + var d2 = factor.datas[0]; + if (d1 == undefined || d2 == undefined) { + return; + } + // 鍗曞抚鏁版嵁鍊肩殑宸�� + var dValue = { + factorData: (d2.factorData - d1.factorData) / count, + physicalQuantity: (d2.physicalQuantity - d2.physicalQuantity) / count + }; + for (let i = 0; i < count - 1; i++) { + var _data = { + factorData: d1.factorData + dValue.factorData * (i + 1), + factorId: d1.factorId, + factorName: d1.factorName, + physicalQuantity: + d1.physicalQuantity + dValue.physicalQuantity * (i + 1), + sensorId: d1.sensorId, + statusList: d1.statusList + }; + if (!isDraw) { + _data.factorData = -1; + _data.physicalQuantity = -1; + } + this.datas.push(_data); + } + // this.datas.push(d2) + } +}; + +export { Factor }; diff --git a/src/model/FactorDatas.js b/src/model/FactorDatas.js new file mode 100644 index 0000000..b6b1d30 --- /dev/null +++ b/src/model/FactorDatas.js @@ -0,0 +1,168 @@ +import { Factor } from "./Factor"; +import calculate from "@/utils/map/calculate"; + +/** + * + */ +function FactorDatas(options) { + // 鏃堕棿 + this.times = []; + // 鍘熷缁忕含搴︼紙GPS锛� + this.lnglats_GPS = []; + // 楂樺痉缁忕含搴� + this.lnglats_GD = []; + // 锛堥珮寰峰湴鍥撅級杞崲鍚庣殑3d鍦板浘缁樺埗鍧愭爣 + this.coors_GD = []; + // 鐩戞祴鍥犲瓙鏁版嵁锛孧ap<String, Factor> + this.factor = new Map(); + + if (options != undefined) { + this.times = options.times; + this.lnglats_GPS = options.lnglats_GPS; + this.lnglats_GD = options.lnglats_GD; + this.coors_GD = options.coors_GD; + this.factor = options.factor; + } +} + +FactorDatas.prototype = { + /** + * @param drawMode 缁樺埗妯″紡锛�0锛氳嚜鍔ㄦā寮忥紝鑷姩璁$畻褰撳墠鏁版嵁鐨勮寖鍥达紝缁樺埗鍚堥�傜殑姣斾緥锛�1锛氭墜鍔ㄦā寮忥紝鏍规嵁椤甸潰璁剧疆鐨勭粯鍥捐寖鍥磋繘琛岀粯鍒� + * @param dataList 缁撴瀯濡備笅 + * [{ + "time": "2021-04-21 21:11:59", + "deviceCode": "0a", + "lng": 121.229385, + "lat": 30.828487 + "values": [ + { + "factorId": "1", + "factorName": "NO2", + "sensorId": null, + "factorData": 65.4, + "physicalQuantity": 215.39, + "statusList": null + }, + ], + }] + */ + setData: function (dataList, drawMode, callback) { + this.clearData(); + + dataList.forEach((d) => { + this.times.push(d.time); + this.lnglats_GPS.push([d.lng, d.lat]); + d.values.forEach((v) => { + var f = this.factor[v.factorId]; + if (f == undefined) { + f = new Factor(); + this.factor[v.factorId] = f; + } + f.pushData(v, drawMode == undefined ? 0 : drawMode); + }); + }); + + + + this.convertGPS(this.lnglats_GPS, callback); + }, + + // 鏂板涓�涓柊鏁版嵁 + addData: function (dataList, drawMode, callback) { + var newGps = []; + dataList.forEach((data) => { + this.times.push(data.time); + this.lnglats_GPS.push([data.lng, data.lat]); + newGps.push([data.lng, data.lat]); + // this.coors_GD锛� 3d鍦板浘鐨勫潗鏍囬�氳繃绗竴娆$粯鍒朵箣鍚庤幏寰� + data.values.forEach((d) => { + var f = this.factor[d.factorId]; + if (f == undefined) { + f = new Factor(); + this.factor[d.factorId] = f; + } + f.pushData(d, drawMode == undefined ? 0 : drawMode); + }); + }); + this.convertGPS(newGps, callback); + }, + + convertGPS: function (gpsList, callback) { + var that = this; + calculate.convertFromGPS(gpsList, function (result) { + var gd = that.lnglats_GD; + gd.push.apply(gd, result); + + var coor_GD = calculate.lngLatToGeodeticCoord(result); + var coor = that.coors_GD; + coor.push.apply(coor, coor_GD); + + if (typeof callback === 'function') { + callback(); + } + }); + }, + + clearData: function () { + this.times = []; + this.lnglats_GPS = []; + this.lnglats_GD = []; + this.coors_GD = []; + this.factor = new Map(); + }, + + // 璁剧疆缁樺浘鑼冨洿 + setRange: function (key, range) { + this.factor[key].setRange(range); + }, + + // 閲嶇疆缁樺浘鑼冨洿 + resetRange: function (key) { + this.factor[key].clearRange(); + }, + + // 璁剧疆涓烘爣鍑嗙粯鍥捐寖鍥� + standardRange: function (key) { + this.factor[key].standardRange(); + }, + + // 鏍规嵁褰撳墠缁樺浘鑼冨洿閲嶆柊璁$畻缁樺浘楂樺害 + refreshHeight: function (key) { + if (key != undefined) { + this.factor[key].getHeight(); + } else { + for (const k in this.factor) { + this.factor[k].getHeight(); + } + } + }, + + // 鏍规嵁寮�濮嬪拰缁撴潫涓嬫爣鑾峰彇瀵瑰簲浣嶇疆鏁版嵁闆� + getByIndex: function (s, e) { + var t = this.times.slice(s, e); + var l = this.lnglats_GPS.slice(s, e); + var l_GD = this.lnglats_GD.slice(s, e); + var c = this.coors_GD.slice(s, e); + var f = new Map(); + for (const key in this.factor) { + if (Object.hasOwnProperty.call(this.factor, key)) { + const element = this.factor[key]; + f[key] = element.getByIndex(s, e); + } + } + return new FactorDatas({ + times: t, + lnglats_GPS: l, + lnglats_GD: l_GD, + coors_GD: c, + factor: f + }); + }, + + // 鑾峰彇鏁版嵁闀垮害 + length: function () { + return this.lnglats_GD.length; + }, +}; + +export { FactorDatas }; diff --git a/src/model/Legend.js b/src/model/Legend.js new file mode 100644 index 0000000..054ad4b --- /dev/null +++ b/src/model/Legend.js @@ -0,0 +1,294 @@ +/** + * 鐩戞祴鍥犲瓙鍥句緥 + */ +const Legend = { + S_TYPE: 0, //鏍囧噯鍥句緥 + D_TYPE: 1, //鍔ㄦ�佸浘渚� + C_TYPE: 2, //鑷畾涔夎寖鍥村浘渚� + + //鍚勭洃娴嬪洜瀛愭暟鎹垎绾э紙鏍囧噯锛� + _legend_r: { + NO2: [0, 100, 200, 700, 1200, 2340], + CO: [0, 5, 10, 35, 60, 90], + H2S: [0, 150, 500, 650, 800, 1600], + SO2: [0, 150, 500, 650, 800, 1600], + O3: [0, 160, 200, 300, 400, 800], + PM25: [0, 35, 75, 115, 150, 250], + PM10: [0, 50, 150, 250, 350, 420], + VOC: [0, 200, 400, 600, 1000, 2000, 4000], + TMP: [-10, 0, 10, 20, 30, 40], + spC: [0, 200, 400, 600, 800, 1000], + tur: [0, 50, 100, 150, 200, 250], + DO: [0, 3, 5, 7, 9, 11], + PH: [1, 3, 5, 7, 9, 11, 13] + }, + + //鍚勭洃娴嬪洜瀛愭暟鎹垎绾э紙鏍囧噯锛夊搴旈鑹� + _legend_c: { + NO2: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + CO: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + H2S: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + SO2: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + O3: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + PM25: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + PM10: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + VOC: [ + [0, 0.89, 0, 0.75], + [0, 0.7, 0, 0.75], + [0.8, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.4, 0, 0.3, 0.75], + [0.6, 0, 0.3, 0.75] + ], + TMP: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + spC: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + tur: [ + [0, 0.89, 0, 0.75], + [1, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.6, 0, 0.3, 0.75], + [0.49, 0, 0.14, 0.75] + ], + DO: [ + [0.49, 0, 0.14, 0.75], + [0.6, 0, 0.3, 0.75], + [1, 0, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 1, 0, 0.75], + [0, 0.89, 0, 0.75] + ], + PH: [ + [0, 0.89, 0, 0.75], + [0, 0.7, 0, 0.75], + [0.8, 1, 0, 0.75], + [1, 0.49, 0, 0.75], + [1, 0, 0, 0.75], + [0.4, 0, 0.3, 0.75], + [0.6, 0, 0.3, 0.75] + ] + }, + + _custom: [ + [0.05, 0.9, 0.03, 0.75], + [0.3, 0.65, 0.02, 0.75], + [0.87, 0.92, 0.03, 0.75], + [0.8, 0.67, 0.04, 0.75], + [0.92, 0.28, 0.07, 0.75], + [0.6, 0.05, 0.05, 0.75] + ], + + getStandardRange: function (name) { + var range = this._legend_r[name]; + if (range == undefined) { + range = this._legend_r['PM25']; + } + var min = range[0]; + var max = range[range.length - 1]; + // for (const key in range) { + // if (min == undefined) { + // min = parseInt(key) + // } + // max = parseInt(key) + // } + if (name == 'CO') { + min *= 1000; + max *= 1000; + } + + return [min, max]; + }, + + getColor: function (name, type, data, min, max) { + if (type == this.S_TYPE) { + return this.getStandardColor(name, data); + } else { + return this.getCustomColor(data, min, max); + } + }, + + /** + * 鑾峰彇鐩戞祴鍥犲瓙褰撳墠娴撳害瀵瑰簲鐨勯鑹� + * @param name 鐩戞祴鍥犲瓙鍚嶇О + * @param data 鐩戞祴鍥犲瓙娴撳害 + */ + getStandardColor: function (name, data) { + var range = this._legend_r[name]; + var colors = this._legend_c[name]; + if (range == undefined) { + range = this._legend_r['PM25']; + colors = this._legend_c['PM25']; + } + // return colors[0] + + var selected = undefined; + for (let i = 0; i < range.length; i++) { + const d = range[i]; + var d1 = d; + if (name == 'CO') { + d1 *= 1000; + } + if (data >= d1) { + selected = i; + } else { + break; + } + } + + // 閬垮厤涓嬫爣瓒婄晫 + if (selected >= colors.length) { + selected = colors.length - 1; + } + + // console.log(name + ': ' + selected); + return colors[selected]; + }, + + getCustomColor: function (data, min, max) { + var per = (max - min) / this._custom.length; + var i = parseInt(data / per); + if (i >= this._custom.length) { + i = this._custom.length - 1; + } + return this._custom[i]; + }, + + /** + * 鑾峰彇鍒嗘瀽鍥句緥 + */ + refreshLegend: function (eId, name, animation, type, min, max) { + var legend = $('#' + eId); + legend.empty(); + + var r = this._legend_r[name]; + var c = this._legend_c[name]; + // 娌℃湁鎵惧埌鏍囧噯鍥句緥鐨勫洜瀛愶紝榛樿浣跨敤鑷畾涔夎寖鍥村浘渚� + if (r == undefined) { + type = this.C_TYPE; + } + var range = []; + if (type != this.S_TYPE && min != undefined && max != undefined) { + var count = this._custom.length; + var per = (max - min) / count; + for (let i = 0; i < count; i++) { + range.push([(min + per * i).toFixed(1), this._custom[i]]); + } + } else { + for (let i = 0; i < r.length; i++) { + range.push([r[i], c[i]]); + } + } + + for (let i = 0; i < range.length; i++) { + const r = range[i]; + const nextR = range[i + 1]; + var div1 = $('<div></div>'); + div1.addClass('flexbox align-items margin-top'); + var div2 = $('<div></div>'); + div2.addClass('rectangle'); + + var color = r[1]; + var bgcolor = + 'rgba(' + + color[0] * 255 + + ', ' + + color[1] * 255 + + ', ' + + color[2] * 255 + + ', ' + + color[3] + + ')'; + div2.css('background-color', bgcolor); + var div3 = $('<div></div>'); + var d; + if (nextR != undefined) { + d = r[0] + ' ~' + nextR[0] + ' ' + Util.factorUnit2[name]; + } else { + d = + ' > ' + + r[0] + + ' ' + + Util.factorUnit2[name]; + } + div3.append(d); + div1.append(div2); + div1.append(div3); + legend.append(div1); + } + + if (animation == false) { + return; + } + legend.hide('fast', function () { + setTimeout(() => { + legend.show('fast'); + }, 500); + }); + } +}; + +export { Legend }; diff --git a/src/styles/elementUI.scss b/src/styles/elementUI.scss index 281d6e2..813ba05 100644 --- a/src/styles/elementUI.scss +++ b/src/styles/elementUI.scss @@ -13,3 +13,15 @@ // .el-radio { // --el-radio-text-color: white; // } + +.el-button-custom { + --el-button-bg-color: var(--bg-color); + --el-button-hover-text-color: var(--select_color); + --el-button-hover-bg-color: var(--bg-color); + --el-button-border-color: var(--font-color); + --el-button-active-border-color: transparent; +} + +.el-button-custom:focus-visible { + outline: 0px solid var(--el-button-outline-color); +} \ No newline at end of file diff --git a/src/utils/map/calculate.js b/src/utils/map/calculate.js index 058531f..505d082 100644 --- a/src/utils/map/calculate.js +++ b/src/utils/map/calculate.js @@ -4,6 +4,52 @@ import { map } from './index_old'; +function _prepare4convert(lnglats) { + var coor = []; + var maxLength = 1000; + var start = 0; + var end = start + maxLength; + while (end <= lnglats.length) { + coor.push(lnglats.slice(start, end)); + start += maxLength; + end += maxLength; + } + if (start < lnglats.length) { + coor.push(lnglats.slice(start)); + } + return coor; +} + +function parse2LngLat(lnglats) { + // 鍒涘缓鍖呭惈4涓妭鐐圭殑鎶樼嚎鍙婃枃瀛楁爣娉� + var path = []; + lnglats.forEach(function (value) { + // eslint-disable-next-line no-undef + path.push(new AMap.LngLat(value[0], value[1])); + }); + return path; +} + +/** + * 灏唃ps缁忕含搴﹁浆鎹负楂樺痉鍦板浘缁忕含搴� + * @param {*} lnglats + * @param {*} callback + */ +function _convertLatlng(index, coor, lnglats, callback) { + if (index < coor.length) { + var path = parse2LngLat(coor[index]); + // eslint-disable-next-line no-undef + AMap.convertFrom(path, 'gps', function (status, result) { + if (result.info === 'ok') { + lnglats.push.apply(lnglats, result.locations); + _convertLatlng(index + 1, coor, lnglats, callback); + } + }); + } else { + callback(lnglats); + } +} + export default { /** * 鏍规嵁鍧愭爣鐐广�佽窛绂诲拰瑙掑害锛屽緱鍒板彟涓�涓潗鏍囩偣 @@ -55,5 +101,16 @@ coors_GD.push(p); } return coors_GD; + }, + + convertFromGPS: function (gps, callback) { + var coor = _prepare4convert(gps); + _convertLatlng(0, coor, [], function (result) { + var gd = []; + result.forEach((r) => { + gd.push([r.lng, r.lat]); + }); + callback(gd); + }); } }; diff --git a/src/views/historymode/HistoryMode.vue b/src/views/historymode/HistoryMode.vue index 1c71387..50dc1f0 100644 --- a/src/views/historymode/HistoryMode.vue +++ b/src/views/historymode/HistoryMode.vue @@ -1,22 +1,44 @@ <template> <div class="fy-container"> - <FactorRadio @change="(e) => (factorType = e)"></FactorRadio> - <SearchBar></SearchBar> + <el-row justify="center"> + <SearchBar search-time="" @search="fetchHistroyData"></SearchBar> + </el-row> + <FactorRadio + :device-type="deviceType" + @change="(e) => (factorType = e)" + ></FactorRadio> </div> </template> <script> import Layer from '@/utils/map/3dLayer'; import marks from '@/utils/map/marks'; +import monitorDataApi from '@/api/monitorDataApi'; +import { useFetchData } from '@/composables/fetchData'; +import moment from 'moment'; +import { TYPE0 } from '@/constant/device-type'; +import { FactorDatas } from '@/model/FactorDatas'; export default { - name: 'HistoryPage', + setup() { + const { loading, fetchData } = useFetchData(10000); + return { loading, fetchData }; + }, data() { return { - factorType: '', - factorDatas: [], + // 鐩戞祴璁惧绫诲瀷 + deviceType: TYPE0, + // 鐩戞祴鍥犲瓙鐨勭被鍨嬬紪鍙� + factorType: '1', + // 鐩戞祴鏁版嵁 + factorDatas: new FactorDatas(), + // 鍐冲畾缁樺埗3D鍥惧舰鏃舵槸鍚︿笌鍘熷浘鍍忓悎骞� merge: false, - setCenter: true + // 鍐冲畾缁樺埗瀹�3D鍥惧舰鍚庡湴鍥捐瑙掓槸鍚﹁嚜鍔ㄥ洖涓� + setCenter: true, + // 缁樺埗妯″紡锛�0锛氳嚜鍔ㄦā寮忥紝鑷姩璁$畻褰撳墠鏁版嵁鐨勮寖鍥达紝缁樺埗鍚堥�傜殑姣斾緥锛�1锛氭墜鍔ㄦā寮忥紝鏍规嵁椤甸潰璁剧疆鐨勭粯鍥捐寖鍥磋繘琛岀粯鍒� + drawMode: 0, + searchTime: [] }; }, watch: { @@ -28,6 +50,7 @@ }, methods: { draw() { + // todo 鍒锋柊鍥句緥 const factor = this.factorDatas.factor[this.factorType]; this.drawRoadMap(factor); this.drawMassMarks(factor); @@ -54,12 +77,62 @@ // 4. 琛ㄦ牸鏁版嵁璺宠浆瀹氫綅 // Table.locate(i); }); + }, + onFetchData(type, data) { + // todo 鏍规嵁璁惧绫诲瀷鍒囨崲鍦板浘鐩戞祴鍥犲瓙灞曠ず鍗曢�夋銆佹姌绾垮浘澶嶉�夋銆佹暟鎹〃鏍煎閫夋鐨勫洜瀛愮被鍨� + this.deviceType = type; + this.factorDatas.setData(data, this.drawMode, () => { + this.factorDatas.refreshHeight(this.factorType); + this.draw(); + }); + }, + fetchHistroyData(option) { + const { deviceCode, type, timeArray } = option; + let startTime, endTime; + if (timeArray && timeArray.length == 2) { + startTime = moment(timeArray[0]).format('YYYY-MM-DD HH:mm:ss'); + endTime = moment(timeArray[1]).format('YYYY-MM-DD HH:mm:ss'); + } + this.fetchData((page, pageSize) => { + return monitorDataApi + .fetchHistroyData({ + deviceCode, + startTime, + endTime, + type, + page, + perPage: pageSize + }) + .then((res) => this.onFetchData(type, res.data)); + }); + }, + fetchRealTimeData() { + // fixme 2024.5.3 姝ゅ鍒濆鑾峰彇鐨勬暟鎹紝鍙傛暟搴旇鐢眘earchbar鍐冲畾锛屽悗缁慨鏀� + this.fetchData((page, pageSize) => { + return monitorDataApi + .fetchHistroyData({ + deviceCode: '0a0000000001', + // type: TYPE0, + page, + perPage: 100 + }) + .then((res) => { + if (res.data.length > 0) { + const s = new Date(res.data[0].time); + const e = new Date(res.data[res.data.length - 1].time); + this.searchTime = [s, e]; + } + this.onFetchData(TYPE0, res.data); + }); + }); } + }, + mounted() { + this.fetchRealTimeData(); } }; </script> <style scoped> .fy-container { - background-color: antiquewhite; } </style> diff --git a/vite.config.js b/vite.config.js index 3487c29..ae49381 100644 --- a/vite.config.js +++ b/vite.config.js @@ -34,6 +34,7 @@ preprocessorOptions: { scss: { additionalData: `@use "@/styles/index.scss" as *;` + // additionalData: '@import "@/styles/index.scss";' } } }, -- Gitblit v1.9.3