From 3832a82fb79d4cec4cca5e2854e54953f2095ef8 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期五, 06 九月 2024 16:55:08 +0800 Subject: [PATCH] 1. 添加溯源清单功能 2. 修复切换至走航监测界面后,之前正在加载的历史数据依旧展示至地图的问题 3. 添加折线图下载图片功能; 4. 添加数据导出功能; 5. 添加设备管理功能; 6. 添加数据弹框和溯源清单开关功能; 7. 优化3D里面的颜色展示逻辑,底部颜色由原来的因子最小值颜色改为当前量级的上一个量级对应的颜色 --- src/utils/chart/chart-option.js | 31 + src/api/deviceApi.js | 11 src/utils/map/dialog.js | 53 ++ src/model/Factor.js | 9 src/components.d.ts | 5 src/views/HomePage.vue | 5 src/components/CardDialog.vue | 21 src/views/realtimemode/RealtimeMode.vue | 19 src/styles/elementUI.scss | 10 src/components/map/MapToolbox.vue | 33 + src/components/monitor/DataTable.vue | 14 src/api/index.js | 40 + src/constant/device-type.js | 10 src/components/search/OptionType.vue | 19 src/constant/scene-types.js | 2 src/utils/map/util.js | 6 src/utils/factor/data.js | 37 src/components/map/ConfigManage.vue | 46 ++ src/views/LoginPage.vue | 13 src/views/historymode/HistoryMode.vue | 48 - src/assets/border.css | 7 src/components/monitor/DataSummary.vue | 14 src/components/mission/MissionManage.vue | 25 src/components/scene/SceneSearch.vue | 178 ++++++++ src/components/device/DeviceCreate.vue | 85 ++++ src/utils/map/marks.js | 13 /dev/null | 186 --------- src/model/Legend.js | 27 + src/components/device/DeviceManage.vue | 59 ++ src/stores/toolbox.js | 5 src/utils/map/sector.js | 1 src/components/search/OptionDevice.vue | 35 + src/components/search/OptionMission.vue | 7 src/utils/map/3dLayer.js | 7 src/api/sceneInfoApi.js | 23 src/stores/device.js | 12 src/stores/scene.js | 32 + src/utils/map/toolbox.js | 25 + 38 files changed, 816 insertions(+), 357 deletions(-) diff --git a/src/api/deviceApi.js b/src/api/deviceApi.js index b2a8390..06432cb 100644 --- a/src/api/deviceApi.js +++ b/src/api/deviceApi.js @@ -4,18 +4,17 @@ * 璧拌埅璁惧鐩稿叧鎺ュ彛API */ export default { - fethchDevice({ type, page, pageSize }) { - let params = `page=${page}&perPage=${pageSize}`; - params += type ? `&type=${type}` : ''; - return $http.get(`air/device/type?${params}`).then((res) => res.data); + fethchDevice({ type }) { + let params = type ? `?&type=${type}` : ''; + return $http.get(`air/device/type${params}`).then((res) => res.data); }, putNewDevice(device) { - return $http.post(`air/device/create`, device).then((res) => res.data); + return $http.put(`air/device/create`, device).then((res) => res.data); }, deleteDevice(deviceCode) { let params = `deviceCode=${deviceCode}`; - return $http.post(`air/device/delete?${params}`).then((res) => res.data); + return $http.delete(`air/device/delete?${params}`).then((res) => res.data); } }; diff --git a/src/api/index.js b/src/api/index.js index ef5ed5c..c0264f8 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -1,7 +1,7 @@ import axios from 'axios'; import { ElMessage } from 'element-plus'; -const debug = true; +const debug = false; let ip1 = 'http://47.100.191.150:9029/'; // console.log(import.meta.env); @@ -93,4 +93,40 @@ ); }); -export { $http }; +// const $http = { +// get(url) { +// const controller = new AbortController(); +// return { +// con: controller, +// resp: axiosInstance.get(url, { signal: controller.signal }) +// }; +// }, +// put(url, data) { +// const controller = new AbortController(); +// return { +// con: controller, +// resp: axiosInstance.put(url, data, { signal: controller.signal }) +// }; +// }, +// post(url, data) { +// const controller = new AbortController(); +// return { +// con: controller, +// resp: axiosInstance.post(url, data, { signal: controller.signal }) +// }; +// }, +// delete(url) { +// const controller = new AbortController(); +// return { +// con: controller, +// resp: axiosInstance.delete(url, { signal: controller.signal }) +// }; +// } +// }; + +function resToData(res) { + res.resp = res.resp.then((res) => res.data); + return res; +} + +export { $http, resToData }; diff --git a/src/api/sceneInfoApi.js b/src/api/sceneInfoApi.js index 56cbbc6..e412d46 100644 --- a/src/api/sceneInfoApi.js +++ b/src/api/sceneInfoApi.js @@ -1,14 +1,27 @@ import { $http } from './index'; /** - * + * 鍦烘櫙淇℃伅API鎺ュ彛 */ export default { + /** + * 鏌ユ壘琛屾斂鍖哄垝鑼冨洿鍐呯殑鏌愮被鍦烘櫙 + * @param {Object} area + * @returns + */ searchScene(area) { return $http.post(`scene/find`, area).then((res) => res.data); - } + }, - // searchByCoordinate({lng, lat, radius}) { - // return $http.post(`scene/find/radius`, mission).then((res) => res.data); - // }, + /** + * 鏌ユ壘鍗婂緞鑼冨洿鍐呯殑鍦烘櫙 + * @param {Number} lng 缁忓害锛岄珮寰峰湴鍥撅紙鐏槦鍧愭爣绯伙級 + * @param {Number} lat 缁村害锛岄珮寰峰湴鍥撅紙鐏槦鍧愭爣绯伙級 + * @param {Number} radius 鍗婂緞锛屽崟浣嶇背 + * @returns + */ + searchByCoordinate(lng, lat, radius) { + let param = `?lng=${lng}&lat=${lat}&radius=${radius}`; + return $http.post(`scene/find/radius${param}`).then((res) => res.data); + } }; diff --git a/src/assets/border.css b/src/assets/border.css index a45a338..a7fbf40 100644 --- a/src/assets/border.css +++ b/src/assets/border.css @@ -20,8 +20,10 @@ --border-color: #cac8c8ef; --bg-color: #122b54a9; --bg-color-2: #122b54e3; - --select_color: #7dff5d96; - /* --select_color: #23dad0a2; */ + /* --select_color: #7dff5d96; */ + --select_color: #23dad0a2; + /* --select_color: #23dad1; */ + /* --font-color: #221f1fc0; --border-color: #e5f58eef; @@ -213,6 +215,7 @@ .ff-content-medium .ff-border-top { padding: 8px 8px var(--bevel-length-2) 8px; + /* padding: 0px 0px var(--bevel-length-2) 0px; */ -webkit-clip-path: polygon(var(--border-width) var(--border-width), calc(100% - var(--border-width)) var(--border-width), diff --git a/src/components.d.ts b/src/components.d.ts index 890072c..11c6829 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -11,7 +11,7 @@ BaseMap: typeof import('./components/map/BaseMap.vue')['default'] CardButton: typeof import('./components/CardButton.vue')['default'] CardDialog: typeof import('./components/CardDialog.vue')['default'] - copy: typeof import('./components/search/OptionType copy.vue')['default'] + ConfigManage: typeof import('./components/map/ConfigManage.vue')['default'] CoreHeader: typeof import('./components/core/CoreHeader.vue')['default'] CoreMenu: typeof import('./components/core/CoreMenu.vue')['default'] DataSummary: typeof import('./components/monitor/DataSummary.vue')['default'] @@ -60,17 +60,16 @@ MissionImport: typeof import('./components/mission/MissionImport.vue')['default'] MissionManage: typeof import('./components/mission/MissionManage.vue')['default'] OptionDevice: typeof import('./components/search/OptionDevice.vue')['default'] - 'OptionDevice copy': typeof import('./components/search/OptionDevice copy.vue')['default'] OptionLocation: typeof import('./components/search/OptionLocation.vue')['default'] OptionLocation2: typeof import('./components/search/OptionLocation2.vue')['default'] OptionMission: typeof import('./components/search/OptionMission.vue')['default'] OptionTime: typeof import('./components/search/OptionTime.vue')['default'] OptionType: typeof import('./components/search/OptionType.vue')['default'] - 'OptionType copy': typeof import('./components/search/OptionType copy.vue')['default'] ProgressLineChart: typeof import('./components/chart/ProgressLineChart.vue')['default'] RealTimeLineChart: typeof import('./components/chart/RealTimeLineChart.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] + SceneSearch: typeof import('./components/scene/SceneSearch.vue')['default'] SearchBar: typeof import('./components/search/SearchBar.vue')['default'] SliderBar: typeof import('./components/SliderBar.vue')['default'] TrajectoryState: typeof import('./components/animation/TrajectoryState.vue')['default'] diff --git a/src/components/CardDialog.vue b/src/components/CardDialog.vue index 4ce1ea9..7d601c7 100644 --- a/src/components/CardDialog.vue +++ b/src/components/CardDialog.vue @@ -5,8 +5,11 @@ @closed="handleChange(false)" :show-close="false" :destroy-on-close="true" - align-center :width="width" + :draggable="draggable" + :modal="modal" + :close-on-click-modal="modal" + :modal-class="modal ? 'p-events-auto' : ''" > <template #header="{ close, titleId, titleClass }"> <BaseCard direction="top-left" borderless="t"> @@ -38,18 +41,30 @@ <script> export default { props: { - title: String, + // 鏄鹃殣鎺у埗 modelValue: Boolean, + // 鏍囬 + title: String, + // 瀹藉害 width: { type: [String, Number], default: '50%' + }, + // 鍙嫋鎷� + draggable: Boolean, + // 閬僵灞� + modal: { + type: Boolean, + default: true } }, - emits: ['update:modelValue'], + emits: ['update:modelValue', 'changed'], methods: { handleChange(value) { this.$emit('update:modelValue', value); + this.$emit('changed', value); } } }; </script> +<style></style> diff --git a/src/components/device/DeviceCreate.vue b/src/components/device/DeviceCreate.vue index e69de29..df5cf95 100644 --- a/src/components/device/DeviceCreate.vue +++ b/src/components/device/DeviceCreate.vue @@ -0,0 +1,85 @@ +<template> + <el-button + type="primary" + class="el-button-custom" + @click="dialogVisible = !dialogVisible" + > + 鏂板缓璁惧 + </el-button> + <CardDialog v-model="dialogVisible" title="鏂板缓璧拌埅璁惧"> + <el-form + :inline="false" + :model="formObj" + ref="formRef" + :rules="rules" + label-position="right" + label-width="100px" + > + <el-form-item label="璁惧缂栧彿" prop="deviceCode"> + <el-input + size="small" + clearable + v-model="formObj.deviceCode" + placeholder="璁惧缂栧彿" + /> + </el-form-item> + <OptionType :show="true" v-model="formObj.deviceType"></OptionType> + <el-form-item> + <el-button + :disabled="!edit" + type="primary" + @click="onSubmit" + :loading="loading" + >鎻愪氦</el-button + > + <el-button @click="onCancel">鍙栨秷</el-button> + </el-form-item> + </el-form> + </CardDialog> +</template> +<script setup> +import { ref, reactive, computed } from 'vue'; +import deviceApi from '@/api/deviceApi'; +import { useFormConfirm } from '@/composables/formConfirm'; +import { useFetchData } from '@/composables/fetchData'; +import { useDeviceStore } from '@/stores/device'; + +const deviceStore = useDeviceStore(); +const dialogVisible = ref(false); +const { loading, fetchData } = useFetchData(); +const rules = reactive({ + deviceCode: [ + { + required: true, + message: '璁惧缂栧彿涓嶈兘涓虹┖', + trigger: 'blur' + } + ] +}); +const param = computed(() => { + return { + deviceType: formObj.value.deviceType, + deviceCode: formObj.value.deviceCode + }; +}); +// 鍒涘缓璁惧 +function createDevice() { + fetchData(() => { + return deviceApi.putNewDevice(param.value).then(() => { + dialogVisible.value = false; + deviceStore.fetchDevice(); + }); + }); +} +const { formObj, formRef, edit, onSubmit, onCancel } = useFormConfirm({ + submit: { + do: createDevice + }, + cancel: { + do: () => { + dialogVisible.value = false; + } + } +}); +</script> +<style scoped></style> diff --git a/src/components/device/DeviceManage.vue b/src/components/device/DeviceManage.vue index b892027..889e1b8 100644 --- a/src/components/device/DeviceManage.vue +++ b/src/components/device/DeviceManage.vue @@ -1,17 +1,21 @@ <template> - <el-button + <!-- <el-button type="primary" icon="Memo" class="el-button-custom p-events-auto" @click="dialogVisible = !dialogVisible" > 璁惧绠$悊 - </el-button> - <CardDialog v-model="dialogVisible" title="璧拌埅璁惧绠$悊"> - <el-row class="mission-table"> + </el-button> --> + <CardDialog + :model-value="modelValue" + @changed="handleChange" + title="璧拌埅璁惧绠$悊" + > + <el-row class="device-table"> <el-col :span="20"> <el-table - :data="deviceStore.deviceList" + :data="deviceData" table-layout="fixed" size="small" :show-overflow-tooltip="true" @@ -28,7 +32,14 @@ align="center" width="50" /> - <el-table-column prop="deviceType" label="璁惧绫诲瀷" align="center" /> + <el-table-column + prop="deviceType" + label="璁惧绫诲瀷" + align="center" + width="70" + :formatter="deviceFormatter" + /> + <el-table-column prop="deviceName" label="璁惧鍚嶇О" align="center" /> <el-table-column prop="deviceCode" label="璁惧缂栧彿" align="center" /> <el-table-column prop="createTime" @@ -36,7 +47,7 @@ align="center" :formatter="timeFormatter" /> - <el-table-column label="绠$悊" width="140" align="center"> + <el-table-column label="绠$悊" width="70" align="center"> <template #default="{ row }"> <el-button type="primary" @@ -51,7 +62,7 @@ </el-col> <el-col :span="4" class="flex-col"> <div> - <!-- todo 璁惧鍒涘缓 --> + <DeviceCreate></DeviceCreate> </div> </el-col> </el-row> @@ -59,24 +70,27 @@ <MessageBox v-model="msgBoxVisible" :on-confirm="onConfirm" - title="鍒犻櫎璧拌埅浠诲姟" - msg="纭鏄惁鍒犻櫎璇ヨ蛋鑸换鍔�" + title="鍒犻櫎璧拌埅璁惧" + msg="纭鏄惁鍒犻櫎璇ヨ蛋鑸澶�" confirmText="鍒犻櫎" ></MessageBox> </template> <script> import moment from 'moment'; -import deviceApi from '@/api/deviceApi'; import { mapStores } from 'pinia'; import { useDeviceStore } from '@/stores/device'; import { useFetchData } from '@/composables/fetchData'; +import { typeName } from '@/constant/device-type'; export default { setup() { const { loading, fetchData } = useFetchData(); return { loading, fetchData }; }, - props: {}, + props: { + modelValue: Boolean + }, + emits: ['update:modelValue'], data() { return { dialogVisible: false, @@ -85,18 +99,37 @@ }; }, computed: { - ...mapStores(useDeviceStore) + ...mapStores(useDeviceStore), + deviceData() { + return this.deviceStore.getDevice(); + } }, methods: { + handleChange(value) { + this.$emit('update:modelValue', value); + }, deleteDevice(row) { this.onConfirm = () => { this.deviceStore.deleteDevice(row.deviceCode); }; this.msgBoxVisible = true; }, + // eslint-disable-next-line no-unused-vars + deviceFormatter(row, col, cellValue, index) { + return typeName(cellValue); + }, + // eslint-disable-next-line no-unused-vars timeFormatter(row, col, cellValue, index) { return moment(cellValue).format('YYYY-MM-DD HH:mm:ss'); } } }; </script> +<style scoped> +.flex-col { + display: flex; + flex-direction: column; + gap: 4px; + align-items: flex-end; +} +</style> diff --git a/src/components/map/ConfigManage.vue b/src/components/map/ConfigManage.vue new file mode 100644 index 0000000..7c573f8 --- /dev/null +++ b/src/components/map/ConfigManage.vue @@ -0,0 +1,46 @@ +<template> + <el-dropdown class="p-events-auto" trigger="click" size="small"> + <el-button type="primary" class="el-button-custom"> + <el-icon class="el-icon--left"><Setting /></el-icon> + 閰嶇疆绠$悊 + <el-icon class="el-icon--right"><arrow-down /></el-icon> + </el-button> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item> + <el-button + type="info" + icon="Memo" + plain + @click="missionVisible = !missionVisible" + > + 浠诲姟绠$悊 + </el-button> + </el-dropdown-item> + <el-dropdown-item> + <el-button + type="info" + icon="Cellphone" + plain + @click="deviceVisible = !deviceVisible" + > + 璁惧绠$悊 + </el-button> + </el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + <MissionManage v-model="missionVisible"></MissionManage> + <DeviceManage v-model="deviceVisible"></DeviceManage> +</template> +<script> +export default { + data() { + return { + missionVisible: false, + deviceVisible: false + }; + }, + methods: {} +}; +</script> diff --git a/src/components/map/MapToolbox.vue b/src/components/map/MapToolbox.vue index 39f98c7..e2d3c45 100644 --- a/src/components/map/MapToolbox.vue +++ b/src/components/map/MapToolbox.vue @@ -7,7 +7,7 @@ > <el-button type="primary" class="el-button-custom"> <el-icon class="el-icon--left"><TakeawayBox /></el-icon> - 鍦板浘宸ュ叿绠� + 宸ュ叿绠� <el-icon class="el-icon--right"><arrow-down /></el-icon> </el-button> <template #dropdown> @@ -65,14 +65,14 @@ } }, { - icon: 'fa fa-compass', + icon: 'fa fa-crosshairs', label: '鍧愭爣鎷惧彇', value: false, click: function () { this.value = !this.value; toolbox.toggleCoorPicking(this.value); } - } + }, // { // icon: 'fa fa-compass', // label: '鏁版嵁鏍囪', @@ -82,15 +82,24 @@ // // todo 鏁版嵁鏍囪 // } // }, - // { - // icon: 'fa fa-compass', - // label: '鏁版嵁寮规', - // value: true, - // click: function () { - // this.value = !this.value; - // // todo 鏁版嵁寮规 - // } - // } + { + icon: 'fa fa-comment-alt', + label: '鏁版嵁寮规', + value: true, + click: function () { + this.value = !this.value; + toolbox.toggleDataDialogStatus(this.value); + } + }, + { + icon: 'fa fa-comment-alt', + label: '婧簮娓呭崟', + value: true, + click: function () { + this.value = !this.value; + toolbox.toggleSceneSearch(this.value); + } + } ] }; }, diff --git a/src/components/mission/MissionManage.vue b/src/components/mission/MissionManage.vue index 7e67122..1cf433f 100644 --- a/src/components/mission/MissionManage.vue +++ b/src/components/mission/MissionManage.vue @@ -1,13 +1,17 @@ <template> - <el-button + <!-- <el-button type="primary" icon="Memo" class="el-button-custom p-events-auto" @click="dialogVisible = !dialogVisible" > 浠诲姟绠$悊 - </el-button> - <CardDialog v-model="dialogVisible" title="璧拌埅浠诲姟绠$悊"> + </el-button> --> + <CardDialog + :model-value="modelValue" + @changed="handleChange" + title="璧拌埅浠诲姟绠$悊" + > <el-row class="mission-table"> <el-col :span="20"> <el-table @@ -50,14 +54,14 @@ @click="deleteMission(row)" >鍒犻櫎</el-button > - <el-button + <!-- <el-button :loading="row.downloadLoading" type="primary" size="small" class="el-button-custom" @click="downloadReport(row)" >鎶ュ憡</el-button - > + > --> </template> </el-table-column> </el-table> @@ -102,7 +106,10 @@ const { loading, fetchData } = useFetchData(); return { loading, fetchData }; }, - props: {}, + props: { + modelValue: Boolean + }, + emits: ['update:modelValue'], data() { return { dialogVisible: false, @@ -114,6 +121,9 @@ ...mapStores(useMissionStore) }, methods: { + handleChange(value) { + this.$emit('update:modelValue', value); + }, deleteMission(row) { this.onConfirm = () => { this.missionStore.deleteMission(row.missionCode); @@ -126,6 +136,7 @@ .downloadReport(row.missionCode) .finally(() => (row.downloadLoading = false)); }, + // eslint-disable-next-line no-unused-vars timeFormatter(row, col, cellValue, index) { return moment(cellValue).format('YYYY-MM-DD HH:mm:ss'); } @@ -153,6 +164,6 @@ } .mission-table { - height: 60vh; + /* height: 60vh; */ } </style> diff --git a/src/components/monitor/DataSummary.vue b/src/components/monitor/DataSummary.vue index 250cdd7..6733744 100644 --- a/src/components/monitor/DataSummary.vue +++ b/src/components/monitor/DataSummary.vue @@ -20,7 +20,7 @@ size="small" :show-overflow-tooltip="true" border - row-class-name="t-row" + row-class-name="t-row-summary" cell-class-name="t-cell" header-row-class-name="t-header-row" header-cell-class-name="t-header-cell" @@ -136,3 +136,15 @@ } }; </script> +<style> +.t-row-summary { + cursor: auto; + background-color: transparent !important; +} +</style> +<style scoped> +.el-table { + --el-table-row-hover-bg-color: transparent; + --el-table-current-row-bg-color: transparent; +} +</style> diff --git a/src/components/monitor/DataTable.vue b/src/components/monitor/DataTable.vue index b99e67a..6579e51 100644 --- a/src/components/monitor/DataTable.vue +++ b/src/components/monitor/DataTable.vue @@ -56,7 +56,7 @@ </template> <template #footer> - <el-row justify="space-between" class="p-b-2"> + <el-row justify="space-between" class="p-b-2 one-row"> <el-button :loading="downloadLoading" type="primary" @@ -259,11 +259,17 @@ } }; </script> +<style scoped> +.one-row { + /* background-color: red; */ + flex-wrap: nowrap; +} +</style> <style> .el-table { --el-table-bg-color: transparent; - --el-table-row-hover-bg-color: #23dad0a2; - --el-table-current-row-bg-color: #23dad0a2; + --el-table-row-hover-bg-color: var(--select_color); + --el-table-current-row-bg-color: var(--select_color); /* --el-table-current-row-bg-color: #7dff5d96; */ --el-table-text-color: var(--font-color); } @@ -284,7 +290,7 @@ .t-header-cell { background-color: var(--bg-color-2) !important; - text-align: center !important; + /* text-align: center !important; */ color: white !important; } .el-pagination { diff --git a/src/components/scene/SceneSearch.vue b/src/components/scene/SceneSearch.vue new file mode 100644 index 0000000..92d4de0 --- /dev/null +++ b/src/components/scene/SceneSearch.vue @@ -0,0 +1,178 @@ +<template> + <!-- <el-button + type="primary" + icon="Memo" + class="el-button-custom p-events-auto" + @click="dialogVisible = !dialogVisible" + > + 婧簮娓呭崟 + </el-button> --> + <CardDialog + v-model="dialogVisible" + title="婧簮娓呭崟" + draggable + :modal="false" + width="400px" + > + <template #default> + <el-row class="scene-table"> + <!-- <el-col :span="20"> --> + <el-table + :data="sceneStore.sceneList" + table-layout="fixed" + size="small" + :show-overflow-tooltip="true" + border + row-class-name="t-row" + cell-class-name="t-cell" + header-row-class-name="t-header-row" + header-cell-class-name="t-header-cell" + @row-click="handleRowClick" + > + <el-table-column type="index" label="#" width="25" /> + <el-table-column + prop="type" + label="绫诲瀷" + width="55" + :filters="sceneTypeFilter" + :filter-method="filterHandler" + /> + <el-table-column prop="name" label="鍚嶇О" /> + <!-- <el-table-column prop="location" label="鍦板潃" /> --> + <!-- <el-table-column prop="districtName" label="鍖哄幙" align="center" /> --> + <!-- <el-table-column label="绠$悊" width="70" align="center"> + <template #default="{ row }"> + <el-button + type="primary" + size="small" + class="el-button-custom" + @click="deleteDevice(row)" + >鍒犻櫎</el-button + > + </template> + </el-table-column> --> + </el-table> + <!-- </el-col> --> + </el-row> + </template> + <template #footer> + <el-row justify="start" align="middle" class="p-b-2 one-row"> + <el-text size="small" type="warning">鎼滅储鑼冨洿</el-text> + <el-input + class="input-radius m-h-2" + size="small" + v-model="sceneStore.radius" + :min="1" + /> + <el-text size="small" type="warning"> + 鍏噷浠ュ唴锛岀粨鏋渰{ sceneStore.sceneList.length }}鏉�</el-text + > + </el-row> + </template> + </CardDialog> +</template> +<script> +import { sceneTypes, sceneIcon } from '@/constant/scene-types'; +import marks from '@/utils/map/marks'; +import { useFetchData } from '@/composables/fetchData'; +import { mapStores } from 'pinia'; +import { useSceneStore } from '@/stores/scene'; +import { useToolboxStore } from '@/stores/toolbox'; +import MapUtil from '@/utils/map/util'; + +let layer = undefined; + +export default { + setup() { + const { loading, fetchData } = useFetchData(); + return { loading, fetchData }; + }, + props: { + modelValue: Boolean + }, + emits: ['update:modelValue'], + data() { + return { + dialogVisible: false, + onConfirm: undefined + }; + }, + computed: { + ...mapStores(useSceneStore), + ...mapStores(useToolboxStore), + sceneTypeFilter() { + return sceneTypes() + .filter((v) => { + return !v.disabled; + }) + .map((v) => { + return { text: v.label, value: v.label }; + }); + } + }, + watch: { + dialogVisible(nv) { + if (layer) { + if (!nv) { + MapUtil.removeViews(layer); + } else { + MapUtil.addViews(layer); + } + } + }, + 'sceneStore.sceneList': { + handler(nV, oV) { + if (nV != oV) { + this.dialogVisible = true; + this.drawMarks(nV); + } + }, + deep: true + }, + 'toolboxStore.sceneSearchStatus': { + handler(nV) { + if (!nV) { + this.dialogVisible = false; + } + }, + deep: true + } + }, + methods: { + drawMarks(sceneList) { + if (layer != undefined) { + MapUtil.removeViews(layer); + layer = undefined; + } + if (sceneList.length != 0) { + const icons = []; + sceneList.forEach((s) => { + icons.push(sceneIcon(s.typeId)); + }); + layer = marks.createLabelMarks(icons, sceneList, false); + } + }, + handleRowClick(row, col, event) { + MapUtil.setCenter([row.longitude, row.latitude], true); + }, + filterHandler(value, row, column) { + const property = column['property']; + return row[property] === value; + } + } +}; +</script> +<style scoped> +.scene-table { + /* background-color: antiquewhite; */ +} + +.input-radius { + width: 36px; + height: 16px; +} + +/* .ff-content-medium .ff-border-top { + padding: 0px 0px var(--bevel-length-2) 0px; +} */ +</style> diff --git a/src/components/search/OptionDevice copy.vue b/src/components/search/OptionDevice copy.vue deleted file mode 100644 index 6fc1b0a..0000000 --- a/src/components/search/OptionDevice copy.vue +++ /dev/null @@ -1,72 +0,0 @@ -<template> - <el-form-item label="璁惧"> - <el-select - :model-value="modelValue" - @update:model-value="handleChange" - placeholder="璁惧" - size="small" - class="w-120" - > - <el-option - v-for="(s, i) in deviceList" - :key="i" - :label="s.label" - :value="s.value" - /> - </el-select> - </el-form-item> -</template> - -<script> -export default { - props: { - type: String, - modelValue: String - }, - emits: ['update:modelValue'], - data() { - return {}; - }, - computed: { - deviceList() { - const t = this.type ? this.type : '0a'; - return [1, 2, 3].map((v) => { - const label = `${this.getDeviceType(t)}璁惧${v}鍙穈; - const value = `${t}000000000${v}`; - return { - label: label, - value: value - }; - }); - } - }, - watch: { - deviceList(nV, oV) { - if (nV != oV) { - this.handleChange(nV[0].value); - } - } - }, - methods: { - handleChange(value) { - this.$emit('update:modelValue', value); - }, - getDeviceType(t) { - switch (t) { - case '0a': - return '杞﹁浇'; - case '0b': - return '鏃犱汉鏈�'; - case '0c': - return '鏃犱汉鑸�'; - default: - return '杞﹁浇'; - } - } - }, - mounted() { - this.handleChange(this.deviceList[0].value); - } -}; -</script> -<style scoped></style> diff --git a/src/components/search/OptionDevice.vue b/src/components/search/OptionDevice.vue index 2ba1468..d5a4d43 100644 --- a/src/components/search/OptionDevice.vue +++ b/src/components/search/OptionDevice.vue @@ -19,6 +19,8 @@ <script> import { deviceList } from '@/constant/device-type'; +import { mapStores } from 'pinia'; +import { useDeviceStore } from '@/stores/device'; export default { props: { @@ -30,24 +32,51 @@ return {}; }, computed: { + ...mapStores(useDeviceStore), deviceOptions() { - return deviceList(this.type); + return this.deviceStore.getDevice(this.type).map((v) => { + return { + label: v.deviceName, + value: v.deviceCode + }; + }); } }, watch: { + // type(nV, oV) { + // if (nV != oV) { + // this.refreshOptions(); + // } + // } deviceOptions(nV, oV) { if (nV != oV) { - this.handleChange(nV[0].value); + if (nV.length > 0) { + this.handleChange(nV[0].value); + } } } }, methods: { + fetchDevice() { + this.deviceStore.fetchDevice().then((res) => { + if (res.success && res.data.length > 0) { + this.handleChange(this.deviceOptions[0].value); + } + }); + }, + // refreshOptions() { + // this.deviceOptions = + // }, handleChange(value) { this.$emit('update:modelValue', value); } }, mounted() { - this.handleChange(this.deviceOptions[0].value); + if (this.deviceStore.deviceList.length == 0) { + this.fetchDevice(); + } else { + this.handleChange(this.deviceOptions[0].value); + } } }; </script> diff --git a/src/components/search/OptionMission.vue b/src/components/search/OptionMission.vue index f26efe3..f58d98f 100644 --- a/src/components/search/OptionMission.vue +++ b/src/components/search/OptionMission.vue @@ -54,7 +54,12 @@ } }, mounted() { - this.fetchMission(); + if (this.missionStore.missionList.length == 0) { + this.fetchMission(); + } else { + this.index = 0; + this.handleChange(0); + } } }; </script> diff --git a/src/components/search/OptionType copy.vue b/src/components/search/OptionType copy.vue deleted file mode 100644 index b6e4817..0000000 --- a/src/components/search/OptionType copy.vue +++ /dev/null @@ -1,54 +0,0 @@ -<template> - <el-form-item label="绫诲瀷"> - <el-select - :model-value="modelValue" - @update:model-value="handleChange" - placeholder="绫诲瀷" - size="small" - class="w-80" - > - <el-option - v-for="(s, i) in typeList" - :key="i" - :label="s.label" - :value="s.value" - /> - </el-select> - </el-form-item> -</template> - -<script> -export default { - props: { - modelValue: String - }, - emits: ['update:modelValue'], - data() { - return { - typeList: [ - { - label: '杞﹁浇', - value: '0a' - }, - { - label: '鏃犱汉鏈�', - value: '0b' - }, - { - label: '鏃犱汉鑸�', - value: '0c' - } - ] - }; - }, - methods: { - handleChange(value) { - // todo 鏍规嵁璁惧绫诲瀷鍒囨崲鍦板浘杞藉叿鐨勫浘鏍囥�� - this.$emit('update:modelValue', value); - } - }, - mounted() { - this.handleChange(this.typeList[0].value); - } -}; -</script> diff --git a/src/components/search/OptionType.vue b/src/components/search/OptionType.vue index 644898d..c28a189 100644 --- a/src/components/search/OptionType.vue +++ b/src/components/search/OptionType.vue @@ -1,11 +1,12 @@ <template> - <el-form-item v-show="isShow" label="绫诲瀷"> + <el-form-item v-show="show" label="绫诲瀷"> <el-select :model-value="modelValue" @update:model-value="handleChange" placeholder="绫诲瀷" size="small" class="w-80" + :disabled="disabled" > <el-option v-for="(s, i) in typeList" @@ -21,6 +22,14 @@ import { typeList } from '@/constant/device-type'; export default { props: { + disabled: { + type: Boolean, + default: import.meta.env.VITE_DATA_MODE == 'jingan' + }, + show: { + type: Boolean, + default: import.meta.env.VITE_DATA_MODE != 'jingan' + }, modelValue: String }, emits: ['update:modelValue'], @@ -30,6 +39,14 @@ isShow: import.meta.env.VITE_DATA_MODE != 'jingan' }; }, + watch: { + show: { + handler(nV) { + this.isShow = nV; + }, + immediate: true + } + }, methods: { handleChange(value) { // todo 鏍规嵁璁惧绫诲瀷鍒囨崲鍦板浘杞藉叿鐨勫浘鏍囥�� diff --git a/src/constant/device-type.js b/src/constant/device-type.js index 6291f18..6316134 100644 --- a/src/constant/device-type.js +++ b/src/constant/device-type.js @@ -30,6 +30,10 @@ { label: '鏃犱汉鑸�', value: '0c' + }, + { + label: '缃戞牸鍖�', + value: '0d' } ]; } @@ -61,4 +65,8 @@ } } -export { TYPE0, TYPE1, TYPE2, TYPE3, TYPE4, typeList, deviceList }; +function typeName(type) { + return typeList().find((v) => (v.value = type)).label; +} + +export { TYPE0, TYPE1, TYPE2, TYPE3, TYPE4, typeList, typeName, deviceList }; diff --git a/src/constant/scene-types.js b/src/constant/scene-types.js index 30c5590..109c726 100644 --- a/src/constant/scene-types.js +++ b/src/constant/scene-types.js @@ -20,7 +20,7 @@ } function sceneIcon(type) { - switch (type) { + switch (type + '') { case '1': return scene_1; case '4': diff --git a/src/model/Factor.js b/src/model/Factor.js index 1aaa149..3af0452 100644 --- a/src/model/Factor.js +++ b/src/model/Factor.js @@ -51,6 +51,7 @@ this.factorId; this.heights = []; //3d鍦板浘褰撳墠灞曠ず鍧愭爣鐐瑰搴旂殑楂樺害鏁扮粍 this.colors = []; // 3d鍦板浘褰撳墠灞曠ず鍧愭爣鐐瑰搴旂殑棰滆壊鏁扮粍 + this.bottomColors = []; //鏈�灏忓�煎搴旂殑鍥句緥鑹叉暟缁� this.bottomColor; //鏈�灏忓�煎搴旂殑鍥句緥鑹� this.min = -1; // 褰撳墠鏄剧ず鐨勬渶灏忓�� this.max = -1; // 褰撳墠鏄剧ず鐨勬渶澶у�� @@ -72,6 +73,7 @@ this.factorName = options.factorName; this.factorId = options.factorId; this.colors = options.colors; + this.bottomColors = options.bottomColors; this.bottomColor = options.bottomColor; this.standardMin = options.standardMin; this.standardMax = options.standardMax; @@ -125,12 +127,12 @@ this.heights = []; this.colors = []; this.datas.forEach((d) => { - var h = getFactorHeight(d.factorId, d.factorData, [this.min, this.max]); + const h = getFactorHeight(d.factorId, d.factorData, [this.min, this.max]); if (d.factorData == -1) { h = -1; } this.heights.push(h); - var c = Legend.getColor( + const c = Legend.getColor( this.factorName, this.legendType, d.factorData, @@ -138,6 +140,8 @@ this.max ); this.colors.push(c); + const b = Legend.getPreviousColor(this.factorName, this.legendType, c); + this.bottomColors.push(b); // this.heights.push(d.factorData) }); this.bottomColor = Legend.getColor( @@ -182,6 +186,7 @@ originMax: this.originMax, factorName: this.factorName, colors: this.colors, + bottomColors: this.bottomColors, bottomColor: this.bottomColor, standardMin: this.standardMin, standardMax: this.standardMax diff --git a/src/model/Legend.js b/src/model/Legend.js index dffc4e0..cf6d5b3 100644 --- a/src/model/Legend.js +++ b/src/model/Legend.js @@ -181,23 +181,42 @@ }, /** + * 鑾峰彇褰撳墠棰滆壊涓婁竴涓瓑绾х殑棰滆壊 + * @param {*} name + * @param {*} type + * @param {*} color + */ + getPreviousColor(name, type, color) { + let colors; + if (type == this.S_TYPE) { + colors = this._legend_c[name]; + } else { + colors = this._custom; + } + let index = colors.indexOf(color); + index--; + if (index < 0) index = 0; + return colors[index]; + }, + + /** * 鑾峰彇鐩戞祴鍥犲瓙褰撳墠娴撳害瀵瑰簲鐨勯鑹� * @param name 鐩戞祴鍥犲瓙鍚嶇О * @param data 鐩戞祴鍥犲瓙娴撳害 */ getStandardColor: function (name, data) { - var range = this._legend_r[name]; - var colors = this._legend_c[name]; + let range = this._legend_r[name]; + let colors = this._legend_c[name]; if (range == undefined) { range = this._legend_r['PM25']; colors = this._legend_c['PM25']; } // return colors[0] - var selected = undefined; + let selected = undefined; for (let i = 0; i < range.length; i++) { const d = range[i]; - var d1 = d; + let d1 = d; if (name == 'CO') { d1 *= 1000; } diff --git a/src/stores/device.js b/src/stores/device.js index c75f474..f17f37e 100644 --- a/src/stores/device.js +++ b/src/stores/device.js @@ -3,10 +3,18 @@ import deviceApi from '@/api/deviceApi'; import { useFetchData } from '@/composables/fetchData'; -// 璧拌埅浠诲姟 +// 璧拌埅璁惧 export const useDeviceStore = defineStore('device', () => { const deviceList = ref([]); const { loading, fetchData } = useFetchData(); + + function getDevice(deviceType) { + if (deviceType) { + return deviceList.value.filter((v) => v.deviceType == deviceType); + } else { + return deviceList.value; + } + } function fetchDevice(type) { return fetchData((page, pageSize) => { @@ -38,5 +46,5 @@ }); } - return { deviceList, loading, fetchDevice, deleteDevice }; + return { deviceList, loading, getDevice, fetchDevice, deleteDevice }; }); diff --git a/src/stores/scene.js b/src/stores/scene.js new file mode 100644 index 0000000..b590a8d --- /dev/null +++ b/src/stores/scene.js @@ -0,0 +1,32 @@ +import { ref } from 'vue'; +import { defineStore } from 'pinia'; +import { useFetchData } from '@/composables/fetchData'; +import sceneInfoApi from '@/api/sceneInfoApi'; +import { useToolboxStore } from '@/stores/toolbox'; + +const toolboxStore = useToolboxStore(); + +// 璧拌埅璁惧 +export const useSceneStore = defineStore('scene', () => { + // 榛樿鎼滅储鑼冨洿1鍏噷浠ュ唴 + const radius = ref(1); + const sceneList = ref([]); + const { loading, fetchData } = useFetchData(); + + function searchScene(lng, lat) { + if (toolboxStore.sceneSearchStatus) { + return fetchData(() => { + return sceneInfoApi + .searchByCoordinate(lng, lat, radius.value * 1000) + .then((res) => { + sceneList.value = res.data.filter((v) => { + return v.typeId != 19 && v.typeId != 20; + }); + return res; + }); + }); + } + } + + return { radius, sceneList, loading, searchScene }; +}); diff --git a/src/stores/toolbox.js b/src/stores/toolbox.js index 639efcf..93a5cf3 100644 --- a/src/stores/toolbox.js +++ b/src/stores/toolbox.js @@ -14,6 +14,8 @@ const dataMarkerStatus = ref(true); // 寮�鍏虫暟鎹脊妗� const dataDialogStatus = ref(true); + // 寮�鍏虫函婧愭竻鍗� + const sceneSearchStatus = ref(true); return { featuresStatus, @@ -21,6 +23,7 @@ controlbarStatus, coorPickStatus, dataMarkerStatus, - dataDialogStatus + dataDialogStatus, + sceneSearchStatus }; }); diff --git a/src/styles/elementUI.scss b/src/styles/elementUI.scss index 30ea08a..e1d1401 100644 --- a/src/styles/elementUI.scss +++ b/src/styles/elementUI.scss @@ -12,17 +12,19 @@ .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-hover-text-color: var(--select_color); + // --el-button-hover-bg-color: var(--bg-color); + --el-button-hover-bg-color: var(--select_color); --el-button-active-border-color: transparent; } .el-button-custom-light { --el-button-bg-color: var(--font-color); --el-button-text-color: var(--bg-color); - --el-button-hover-text-color: var(--bg-color); - --el-button-hover-bg-color: var(--font-color); + // --el-button-hover-text-color: var(--bg-color); + // --el-button-hover-bg-color: var(--font-color); + --el-button-hover-bg-color: var(--select_color); --el-button-border-color: var(--bg-color); --el-button-active-border-color: transparent; } diff --git a/src/utils/chart/chart-option.js b/src/utils/chart/chart-option.js index 5ce5a26..30995e3 100644 --- a/src/utils/chart/chart-option.js +++ b/src/utils/chart/chart-option.js @@ -22,16 +22,27 @@ animationDelayUpdate: function (idx) { return idx * 5; }, - // toolbox: { - // bottom: 0, - // feature: { - // dataZoom: {}, - // magicType: { - // type: ['line', 'bar'] - // }, - // restore: {} - // } - // }, + toolbox: { + // bottom: 0, + feature: { + // dataZoom: {}, + // magicType: { + // type: ['line', 'bar'] + // }, + // restore: { + // title: '鍒锋柊' + // }, + saveAsImage: { + show: true, + backgroundColor: '#122b54a9', + name: '璧拌埅鐩戞祴鍥�', + title: '淇濆瓨涓哄浘鐗�', + iconStyle: { + borderColor: '#fff' + } + } + } + }, tooltip: { textStyle: { fontSize: fontSize diff --git a/src/utils/factor/data.js b/src/utils/factor/data.js index 74d13c9..80f5e14 100644 --- a/src/utils/factor/data.js +++ b/src/utils/factor/data.js @@ -159,24 +159,25 @@ /** * 鑾峰彇鍘嗗彶鏁版嵁 */ -function fetchHistoryData(params) { - // if (import.meta.env.VITE_DATA_MODE == 'jingan') { - // const _params = { - // compUser: 'user1', - // compPassword: 'User1@jingan', - // mn: params.deviceCode, - // dtFrom: params.startTime - // ? params.startTime - // : moment().subtract(6, 'm').format('YYYY-MM-DD HH:mm:ss'), - // dtTo: params.endTime - // ? params.endTime - // : moment().format('YYYY-MM-DD HH:mm:ss') - // }; - // return fetchThirdPartyData(_params); - // } else { - // return fetchOriginHistoryData(params); - // } - return fetchOriginHistoryData(params); +function fetchHistoryData(params, origin = true) { + if (origin) { + return fetchOriginHistoryData(params); + } else if (import.meta.env.VITE_DATA_MODE == 'jingan') { + const _params = { + compUser: 'user1', + compPassword: 'User1@jingan', + mn: params.deviceCode, + dtFrom: params.startTime + ? params.startTime + : moment().subtract(6, 'm').format('YYYY-MM-DD HH:mm:ss'), + dtTo: params.endTime + ? params.endTime + : moment().format('YYYY-MM-DD HH:mm:ss') + }; + return fetchThirdPartyData(_params); + } else { + return fetchOriginHistoryData(params); + } } var fetchingTask; diff --git a/src/utils/map/3dLayer.js b/src/utils/map/3dLayer.js index 72d0e14..5bf559a 100644 --- a/src/utils/map/3dLayer.js +++ b/src/utils/map/3dLayer.js @@ -97,6 +97,7 @@ const heights = factor.heights; const colors = factor.colors; const bColor = factor.bottomColor; + const bColors = factor.bottomColors; // eslint-disable-next-line no-undef var cylinder = new AMap.Object3D.Mesh(); @@ -133,10 +134,8 @@ } } - // var bColor = bColor - var tColor = colors[i]; - geometry.vertexColors.push.apply(geometry.vertexColors, bColor); //搴曢儴椤剁偣棰滆壊 - geometry.vertexColors.push.apply(geometry.vertexColors, tColor); //椤堕儴椤剁偣棰滆壊 + geometry.vertexColors.push.apply(geometry.vertexColors, bColors[i]); //搴曢儴椤剁偣棰滆壊 + geometry.vertexColors.push.apply(geometry.vertexColors, colors[i]); //椤堕儴椤剁偣棰滆壊 } // 7.鏍规嵁鍚堝苟閫夐」閲嶇疆鎴栨柊澧炲綋鍓嶇紦瀛樻暟鎹� diff --git a/src/utils/map/dialog.js b/src/utils/map/dialog.js index 5c1ada9..c7403eb 100644 --- a/src/utils/map/dialog.js +++ b/src/utils/map/dialog.js @@ -4,17 +4,14 @@ import { windDir } from '@/constant/wind-dir'; import { map } from './index_old'; import { checkboxOptions } from '@/constant/checkbox-options'; +import { useToolboxStore } from '@/stores/toolbox'; + +const toolboxStore = useToolboxStore(); export const DialogUtil = { - show: true, - toggleDataDialog() { - this.show = !this.show; - if (this.show) { - return '鏁版嵁寮规锛氬紑'; - } else { - return '鏁版嵁寮规锛氬叧'; - } - }, + // 褰撳墠鎵撳紑鐨勫脊妗嗗強浣嶇疆鍧愭爣 + marker: undefined, + lnglat: undefined, /** * 鍒涘缓寮瑰嚭妗� * @param {*} factorDatas 鐩戞祴鏁版嵁 @@ -39,7 +36,7 @@ offset: new AMap.Pixel(16, -45), autoMove: false }); - return m.window; + return m; }, /** @@ -243,15 +240,45 @@ return info; }, + /** + * 寮�鍚竴涓柊鐨勬暟鎹脊妗� + * @param {String} deviceType 璁惧绫诲瀷 + * @param {String} deviceCode 璁惧缂栧彿 + * @param {Array} factorDatas 鐩戞祴鏁版嵁 + * @param {Number} i 鏁版嵁绱㈠紩 + * @param {Function} onClose 寮规鍏抽棴鍥炶皟 + * @returns + */ openNewWindow(deviceType, deviceCode, factorDatas, i, onClose) { - if (!this.show) return; - const window = this.createInfoWindow( + if (!toolboxStore.dataDialogStatus) return; + this.marker = this.createInfoWindow( deviceType, deviceCode, factorDatas, i, onClose ); - window.open(map, factorDatas.lnglats_GD[i]); + this.marker.window.open(map, factorDatas.lnglats_GD[i]); + this.lnglat = factorDatas.lnglats_GD[i]; + }, + + /** + * 鎵撳紑缂撳瓨涓殑寮规 + */ + openWindow() { + if (this.marker && this.lnglat) { + // this.marker.close(); + this.marker.window.open(map, this.lnglat); + } + }, + + /** + * 鍏抽棴宸插脊鍑虹殑寮规 + */ + closeWindow() { + if (this.marker) { + // this.marker.close(); + this.marker.window.close(); + } } }; diff --git a/src/utils/map/marks.js b/src/utils/map/marks.js index ba31891..a72dcdf 100644 --- a/src/utils/map/marks.js +++ b/src/utils/map/marks.js @@ -79,13 +79,20 @@ } }, - createLabelMarks(img, dataList) { + /** + * 鍒涘缓鏍囪鐐� + * @param {string | Array} img 鍥炬爣鎴栧浘鏍囨暟缁� + * @param {Array} dataList 鐩戞祴鏁版嵁 + * @param {boolean} collision 鏍囨敞閬胯 + * @returns + */ + createLabelMarks(img, dataList, collision = true) { // eslint-disable-next-line no-undef const layer = new AMap.LabelsLayer({ zooms: [3, 20], zIndex: 1000, // 寮�鍚爣娉ㄩ伩璁╋紝榛樿涓哄紑鍚紝v1.4.15 鏂板灞炴�� - collision: true, + collision: collision, // 寮�鍚爣娉ㄦ贰鍏ュ姩鐢伙紝榛樿涓哄紑鍚紝v1.4.15 鏂板灞炴�� animation: true }); @@ -103,7 +110,7 @@ zIndex: 10, icon: { type: 'image', - image: img, + image: typeof img === 'string' ? img : img[i], // clipOrigin: [14, 92], // clipSize: [50, 68], size: [30, 30], diff --git a/src/utils/map/sector.js b/src/utils/map/sector.js index 32a88e6..25ae2d5 100644 --- a/src/utils/map/sector.js +++ b/src/utils/map/sector.js @@ -241,6 +241,7 @@ object3Dlayer.remove(_sector); } }, + sectorParams: sectorParams, /** * 缁樺埗鎵囧舰 * @param {FactorDatas} fDatas diff --git a/src/utils/map/toolbox.js b/src/utils/map/toolbox.js index aa6fb9e..23c10c5 100644 --- a/src/utils/map/toolbox.js +++ b/src/utils/map/toolbox.js @@ -1,7 +1,7 @@ /* eslint-disable no-undef */ import { map, satellite } from './index_old'; import { useToolboxStore } from '@/stores/toolbox'; -// import '@/lib/jquery-3.5.1.min'; +import { DialogUtil } from '@/utils/map/dialog'; const toolboxStore = useToolboxStore(); @@ -44,7 +44,9 @@ * @param {boolean} value */ toggleFeatures(value) { - value ? map.setFeatures(['bg', 'road', 'point', 'building']) : map.setFeatures(['bg', 'road']); + value + ? map.setFeatures(['bg', 'road', 'point', 'building']) + : map.setFeatures(['bg', 'road']); toolboxStore.featuresStatus = value; }, @@ -81,5 +83,24 @@ _locationText = undefined; } toolboxStore.coorPickStatus = value; + }, + + /** + * 寮�鍏虫暟鎹脊妗� + */ + toggleDataDialogStatus(value) { + toolboxStore.dataDialogStatus = value; + if (value) { + DialogUtil.openWindow(); + } else { + DialogUtil.closeWindow(); + } + }, + + /** + * 寮�鍏虫函婧愭竻鍗� + */ + toggleSceneSearch(value) { + toolboxStore.sceneSearchStatus = value; } }; diff --git a/src/utils/map/util.js b/src/utils/map/util.js index ee73357..e783baf 100644 --- a/src/utils/map/util.js +++ b/src/utils/map/util.js @@ -62,14 +62,14 @@ }; export default { - setCenter(lnglat) { - if (isDragging) { + setCenter(lnglat, ignore = false) { + if (!ignore && isDragging) { return; } var now = new Date(); if ( this.lasttime == undefined || - now.getTime() - this.lasttime.getTime() >= 1000 + now.getTime() - this.lasttime.getTime() >= 200 ) { map.setCenter(lnglat); this.lasttime = now; diff --git a/src/views/HomePage.vue b/src/views/HomePage.vue index 32d7a91..2e68604 100644 --- a/src/views/HomePage.vue +++ b/src/views/HomePage.vue @@ -4,8 +4,10 @@ <CoreHeader></CoreHeader> <el-row class="dropdown-wrap"> <MapToolbox></MapToolbox> - <MissionManage></MissionManage> + <!-- <MissionManage></MissionManage> --> + <ConfigManage></ConfigManage> <!-- <MapLocation></MapLocation> --> + <SceneSearch></SceneSearch> <MapScene></MapScene> </el-row> <CoreMenu></CoreMenu> @@ -30,6 +32,7 @@ } .dropdown-wrap { + /* background-color: aliceblue; */ position: absolute; top: 10px; left: 2px; diff --git a/src/views/LoginPage.vue b/src/views/LoginPage.vue index fa815f7..7ecab70 100644 --- a/src/views/LoginPage.vue +++ b/src/views/LoginPage.vue @@ -42,13 +42,13 @@ </template> <script> -import underwayPng from '@/assets/mipmap/underway-2.png'; +import underwayPng2 from '@/assets/mipmap/underway-2.png'; +import underwayPng from '@/assets/mipmap/underway.png'; import { ElMessage } from 'element-plus'; export default { data() { return { - underwayPng: underwayPng, formObj: {}, rules: { userName: [ @@ -68,6 +68,15 @@ } }; }, + computed: { + underwayPng() { + if (import.meta.env.VITE_DATA_MODE == 'jingan') { + return underwayPng2; + } else { + return underwayPng; + } + } + }, methods: { login() { this.$refs.formRef.validate((valid) => { diff --git a/src/views/historymode/HistoryMode copy.vue b/src/views/historymode/HistoryMode copy.vue deleted file mode 100644 index 9421a94..0000000 --- a/src/views/historymode/HistoryMode copy.vue +++ /dev/null @@ -1,237 +0,0 @@ -<template> - <div class="p-events-none m-t-2"> - <el-row justify="center" align="middle" class="top-wrap"> - <SearchBar - v-show="status == 0" - :search-time="searchTime" - :loading="loading" - @search="fetchHistroyData" - ></SearchBar> - <TrajectoryState v-show="status != 0" :status="status"></TrajectoryState> - </el-row> - <el-row class="m-t-2"> - <FactorRadio - :device-type="deviceType" - @change="(e) => (factorType = e)" - ></FactorRadio> - </el-row> - <el-row class="m-t-2"> - <FactorLegend - class="m-t-2" - :factor="factorDatas.factor[factorType]" - ></FactorLegend> - </el-row> - <el-row class="historical" justify="center"> - <HistoricalTrajectory - :factor-datas="factorDatas" - :factor-type="factorType" - @change="(e) => (status = e)" - @stop="draw" - ></HistoricalTrajectory> - </el-row> - <TrendAnalysis - class="trend-analysis" - :locate-index="locateIndex" - @chart-click="handelIndexChange" - :factor-datas="factorDatas" - :device-type="deviceType" - ></TrendAnalysis> - <DataSheet - class="data-sheet" - :locate-index="locateIndex" - @table-click="handelIndexChange" - :factor-datas="factorDatas" - :device-type="deviceType" - ></DataSheet> - </div> -</template> - -<script> -import Layer from '@/utils/map/3dLayer'; -import marks from '@/utils/map/marks'; -import sector from '@/utils/map/sector'; -import mapUtil from '@/utils/map/util'; -import { DialogUtil } from '@/utils/map/dialog'; -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'; -import TrendAnalysis from './component/TrendAnalysis.vue'; -import DataSheet from './component/DataSheet.vue'; -import { ElMessageBox, ElNotification, ElMessage } from 'element-plus'; - -export default { - components: { TrendAnalysis, DataSheet }, - setup() { - const { loading, fetchData } = useFetchData(10000); - return { loading, fetchData }; - }, - data() { - return { - // 鐩戞祴璁惧绫诲瀷 - deviceType: TYPE0, - // 鐩戞祴鍥犲瓙鐨勭被鍨嬬紪鍙� - factorType: '1', - // 鐩戞祴鏁版嵁 - factorDatas: new FactorDatas(), - // 鍐冲畾缁樺埗3D鍥惧舰鏃舵槸鍚︿笌鍘熷浘鍍忓悎骞� - merge: false, - // 鍐冲畾缁樺埗瀹�3D鍥惧舰鍚庡湴鍥捐瑙掓槸鍚﹁嚜鍔ㄥ洖涓� - setCenter: true, - // 缁樺埗妯″紡锛�0锛氳嚜鍔ㄦā寮忥紝鑷姩璁$畻褰撳墠鏁版嵁鐨勮寖鍥达紝缁樺埗鍚堥�傜殑姣斾緥锛�1锛氭墜鍔ㄦā寮忥紝鏍规嵁椤甸潰璁剧疆鐨勭粯鍥捐寖鍥磋繘琛岀粯鍒� - drawMode: 0, - searchTime: [], - // 褰撳墠閫変腑楂樹寒鐨勬暟鎹偣绱㈠紩 - locateIndex: undefined, - // 杞ㄨ抗鍔ㄧ敾鐘舵�� - status: 0 - }; - }, - watch: { - factorType(nValue, oValue) { - if (nValue != oValue && this.status == 0) { - this.draw(); - } - } - }, - methods: { - // 妫�鏌ユ暟鎹粡绾害鏄惁鍚堟硶 - checkDataIsValid(index) { - const lnglats_GD = this.factorDatas.lnglats_GD[index]; - const time = this.factorDatas.times[index]; - if (lnglats_GD[0] == 0 && lnglats_GD[1] == 0) { - ElMessage({ - message: `${time}鐨勬暟鎹粡绾害鏃犳晥`, - type: 'warning' - }); - return false; - } else { - this.locateIndex = index; - return true; - } - }, - // 鐩戝惉鎶樼嚎鍥惧拰琛ㄦ牸鐨勭偣鍑讳簨浠� - handelIndexChange(index) { - if (this.checkDataIsValid(index)) { - this.drawSector(index); - } - }, - draw() { - // 鍒锋柊鍥句緥 - const factor = this.factorDatas.factor[this.factorType]; - sector.clearSector(); - this.drawRoadMap(factor); - this.drawMassMarks(factor); - }, - // 缁樺埗3D璧拌璺嚎鍥� - drawRoadMap(e) { - this.factorDatas.refreshHeight(this.factorType); - - Layer.drawRoadMap(this.factorDatas, e, this.merge, this.setCenter); - // } - }, - drawMassMarks(e) { - marks.drawMassMarks(this.factorDatas, e, (index) => { - // 鏌ヨ鑼冨洿鍐呯殑鐩戞祴绔欑偣 - // SceneUtil.searchByCoordinate(lnglat[0], lnglat[1], distance); - if (this.checkDataIsValid(index)) { - this.drawSector(index); - } - }); - // 璋冩暣鍦板浘瑙嗚 - mapUtil.setBound(this.factorDatas.lnglats_GD); - }, - drawSector(index) { - // 1. 缁樺埗鏂版墖褰㈠尯鍩� - const pr = sector.drawSector(this.factorDatas, index); - // 璋冩暣瑙嗚灞呬腑鏄剧ず - mapUtil.setFitSector(pr); - // 2. 缁樺埗瀵硅瘽妗� - DialogUtil.openNewWindow(this.factorDatas, index, () => { - // 绉婚櫎鎵囧舰鍖哄煙 - sector.clearSector(); - }); - }, - 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, - page, - perPage: pageSize - }) - .then((res) => this.onFetchData(type, res.data)); - }); - }, - fetchRealTimeData() { - // fixme 2024.5.3 姝ゅ鍒濆鑾峰彇鐨勬暟鎹紝鍙傛暟搴旇鐢眘earchbar鍐冲畾锛屽悗缁慨鏀� - this.fetchData((page) => { - 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.replace(' ', 'T')); - const e = new Date( - res.data[res.data.length - 1].time.replace(' ', 'T') - ); - this.searchTime = [s, e]; - } - this.onFetchData(TYPE0, res.data); - }); - }); - } - }, - mounted() { - this.fetchRealTimeData(); - }, - unmounted() { - mapUtil.clearMap(); - } -}; -</script> -<style scoped> -.top-wrap { - height: 40px; -} - -.trend-analysis { - position: absolute; - left: 0; - bottom: 2px; -} - -.data-sheet { - position: absolute; - right: 0; - top: 0; -} - -.historical { - position: absolute; - bottom: 10px; - left: 0; - right: 0; -} -</style> diff --git a/src/views/historymode/HistoryMode.vue b/src/views/historymode/HistoryMode.vue index cbf22c8..11ba4f6 100644 --- a/src/views/historymode/HistoryMode.vue +++ b/src/views/historymode/HistoryMode.vue @@ -5,7 +5,7 @@ v-show="status == 0" :search-time="searchTime" :loading="loading" - @search="fetchHistroyData" + @search="onSearch" ></SearchBar> <TrajectoryState v-show="status != 0" :status="status"></TrajectoryState> </el-row> @@ -62,10 +62,13 @@ import DataSheet from './component/DataSheet.vue'; import { ElMessage } from 'element-plus'; import { fetchHistoryData } from '@/utils/factor/data'; +import { mapStores } from 'pinia'; +import { useSceneStore } from '@/stores/scene'; export default { components: { TrendAnalysis, DataSheet }, setup() { + // 闄愬畾鍒嗛〉鏁版嵁閲忎负10000 const { loading, fetchData } = useFetchData(10000); return { loading, fetchData }; }, @@ -89,7 +92,9 @@ // 褰撳墠閫変腑楂樹寒鐨勬暟鎹偣绱㈠紩 locateIndex: undefined, // 杞ㄨ抗鍔ㄧ敾鐘舵�� - status: 0 + status: 0, + // 鏄惁椤甸潰宸茶烦杞� + isUnmounted: false }; }, watch: { @@ -98,6 +103,9 @@ this.draw(); } } + }, + computed: { + ...mapStores(useSceneStore) }, methods: { // 妫�鏌ユ暟鎹粡绾害鏄惁鍚堟硶 @@ -118,7 +126,11 @@ // 鐩戝惉鎶樼嚎鍥惧拰琛ㄦ牸鐨勭偣鍑讳簨浠� handelIndexChange(index) { if (this.checkDataIsValid(index)) { + // 缁樺埗婧簮鎵囧舰 this.drawSector(index); + // 鏌ヨ鑼冨洿鍐呯殑鐩戞祴绔欑偣 + const [lng, lat] = this.factorDatas.lnglats_GD[index]; + this.sceneStore.searchScene(lng, lat); } }, draw() { @@ -137,11 +149,7 @@ }, drawMassMarks(e) { marks.drawMassMarks(this.factorDatas, e, (index) => { - // 鏌ヨ鑼冨洿鍐呯殑鐩戞祴绔欑偣 - // SceneUtil.searchByCoordinate(lnglat[0], lnglat[1], distance); - if (this.checkDataIsValid(index)) { - this.drawSector(index); - } + this.handelIndexChange(index); }); // 璋冩暣鍦板浘瑙嗚 mapUtil.setBound(this.factorDatas.lnglats_GD); @@ -165,6 +173,7 @@ ); }, onFetchData(deviceType, data) { + if (this.isUnmounted) return; // todo 鏍规嵁璁惧绫诲瀷鍒囨崲鍦板浘鐩戞祴鍥犲瓙灞曠ず鍗曢�夋銆佹姌绾垮浘澶嶉�夋銆佹暟鎹〃鏍煎閫夋鐨勫洜瀛愮被鍨� this.deviceType = deviceType; this.factorDatas.setData(data, this.drawMode, () => { @@ -172,7 +181,7 @@ this.draw(); }); }, - fetchHistroyData(option) { + onSearch(option) { const { deviceType, deviceCode, timeArray } = option; this.deviceType = deviceType; this.deviceCode = deviceCode; @@ -192,32 +201,13 @@ }).then((res) => this.onFetchData(deviceType, res.data)); }); } - // fetchRealTimeData() { - // // fixme 2024.5.3 姝ゅ鍒濆鑾峰彇鐨勬暟鎹紝鍙傛暟搴旇鐢眘earchbar鍐冲畾锛屽悗缁慨鏀� - // this.fetchData((page) => { - // return fetchHistoryData({ - // deviceCode: '0a0000000001', - // // type: TYPE0, - // page, - // perPage: 100 - // }).then((res) => { - // if (res.data.length > 0) { - // const s = new Date(res.data[0].time.replace(' ', 'T')); - // const e = new Date( - // res.data[res.data.length - 1].time.replace(' ', 'T') - // ); - // this.searchTime = [s, e]; - // } - // this.onFetchData(TYPE0, res.data); - // }); - // }); - // } }, mounted() { - // this.fetchRealTimeData(); + this.isUnmounted = false; }, unmounted() { mapUtil.clearMap(); + this.isUnmounted = true; } }; </script> diff --git a/src/views/realtimemode/RealtimeMode copy.vue b/src/views/realtimemode/RealtimeMode copy.vue deleted file mode 100644 index 9c352f2..0000000 --- a/src/views/realtimemode/RealtimeMode copy.vue +++ /dev/null @@ -1,186 +0,0 @@ -<template> - <div class="p-events-none m-t-2"> - <el-row justify="center" align="middle" class="top-wrap"> - <DeviceChange @change="onDeviceChange"></DeviceChange> - </el-row> - <el-row class="m-t-2"> - <FactorRadio - :device-type="deviceType" - @change="(e) => (factorType = e)" - ></FactorRadio> - </el-row> - <el-row class="m-t-2"> - <FactorLegend - class="m-t-2" - :factor="factorDatas.factor[factorType]" - ></FactorLegend> - </el-row> - <DashBoard class="dash-board" :factor-datas="factorDatas"></DashBoard> - <RealTimeTrend - class="real-time-trend" - :factor-datas="factorDatas" - :device-type="deviceType" - ></RealTimeTrend> - </div> -</template> - -<script> -import { useFetchData } from '@/composables/fetchData'; -import { TYPE0 } from '@/constant/device-type'; -import { FactorDatas } from '@/model/FactorDatas'; -import monitorDataApi from '@/api/monitorDataApi'; -import DashBoard from './component/DashBoard.vue'; -import RealTimeTrend from './component/RealTimeTrend.vue'; -import DeviceChange from './component/DeviceChange.vue'; -import { realTimeMapAnimation } from '@/utils/map/animation'; -import { startLoopFetchRealTimeData } from '@/utils/factor/data'; - -// const mapAnimation = new MapAnimation(); - -export default { - components: { DashBoard, RealTimeTrend, DeviceChange }, - setup() { - const { loading, fetchData } = useFetchData(10000); - return { loading, fetchData }; - }, - data() { - return { - // 鐩戞祴璁惧绫诲瀷 - deviceType: TYPE0, - deviceCode: '0a0000000001', - // 鐩戞祴鍥犲瓙鐨勭被鍨嬬紪鍙� - factorType: '1', - // 鏂拌幏鍙栫殑鐩戞祴鏁版嵁 - factorDatas: new FactorDatas(), - // 鍏ㄩ儴鐩戞祴鏁版嵁 - allFactorDatas: new FactorDatas() - }; - }, - watch: { - factorType(nV, oV) { - if (nV != oV) { - realTimeMapAnimation.setFactorType(nV); - } - } - }, - computed: { - latestTime() { - if (this.factorDatas.times.length == 0) { - return ''; - } else { - return this.factorDatas.times[this.factorDatas.times.length - 1]; - } - } - }, - methods: { - onDeviceChange({ type, deviceCode }) { - this.deviceType = type; - this.deviceCode = deviceCode; - this.clearFetchingTask(); - realTimeMapAnimation.stop(); - this.allFactorDatas.clearData(); - this.factorDatas.clearData(); - this.notFirstFetch = false; - this.fetchRealTimeData(); - }, - onFetchData(data) { - // todo 鏍规嵁璁惧绫诲瀷鍒囨崲鍦板浘鐩戞祴鍥犲瓙灞曠ず鍗曢�夋銆佹姌绾垮浘澶嶉�夋銆佹暟鎹〃鏍煎閫夋鐨勫洜瀛愮被鍨� - // this.deviceType = type; - const fDatas = new FactorDatas(); - fDatas.setData(data, this.drawMode, () => { - fDatas.refreshHeight(this.factorType); - // this.draw(); - this.factorDatas = fDatas; - }); - }, - fetchRealTimeData() { - this.fetchData((page) => { - return monitorDataApi - .fetchHistroyData({ - deviceCode: this.deviceCode, - // startTime: '2021-11-04 09:53:35', - page, - perPage: 100 - }) - .then((res) => { - this.onFetchData(res.data); - this.onMapData(res.data); - this.fetchNextData(); - }); - }); - }, - clearFetchingTask() { - if (this.fetchingTask) { - clearInterval(this.fetchingTask); - this.fetchingTask = undefined; - } - }, - fetchNextData() { - this.clearFetchingTask(); - this.fetchingTask = setInterval(() => { - if (this.isFetching) { - return; - } - - this.isFetching = true; - this.fetchData(() => { - return monitorDataApi - .fetchNextData({ - deviceCode: this.deviceCode, - updateTime: this.latestTime, - perPage: 10 - }) - .then((res) => { - this.onFetchData(res.data); - this.onMapData(res.data); - }) - .finally(() => (this.isFetching = false)); - }); - }, 10000); - }, - onMapData(dataList) { - let startIndex = this.allFactorDatas.length() - 1; - if (!this.notFirstFetch) { - startIndex = dataList.length - 2; - this.notFirstFetch = true; - } - startIndex = startIndex < 0 ? 0 : startIndex; - return new Promise((resolve, reject) => { - this.allFactorDatas.addData(dataList, this.drawMode, () => { - realTimeMapAnimation.moveAnimation( - this.allFactorDatas, - this.factorType, - startIndex - ); - }); - }); - } - }, - mounted() { - this.fetchRealTimeData(); - // startLoopFetchRealTimeData({ - // compUser: 'user1', - // compPassword: 'User1@jingan', - // mn: 'TX105', - // dtFrom: '2024-08-07 10:00:00', - // dtTo: '2024-08-07 10:00:59' - // }); - }, - unmounted() { - this.clearFetchingTask(); - realTimeMapAnimation.stop(); - } -}; -</script> -<style scoped> -.dash-board { - position: absolute; - left: 0; - bottom: 2px; -} -.real-time-trend { - position: absolute; - right: 0; - top: 0; -} -</style> diff --git a/src/views/realtimemode/RealtimeMode.vue b/src/views/realtimemode/RealtimeMode.vue index 5ec6009..e01a9aa 100644 --- a/src/views/realtimemode/RealtimeMode.vue +++ b/src/views/realtimemode/RealtimeMode.vue @@ -103,13 +103,16 @@ }, fetchRealTimeData() { this.fetchData((page) => { - return fetchHistoryData({ - deviceCode: this.deviceCode, - // startTime: '2024-08-20 06:00:00', - // endTime: '2024-08-20 06:02:00', - page, - perPage: 100 - }).then((res) => { + return fetchHistoryData( + { + deviceCode: this.deviceCode, + // startTime: '2024-08-20 06:00:00', + // endTime: '2024-08-20 06:02:00', + page, + perPage: 100 + }, + false + ).then((res) => { this.onFetchData(res.data); this.onMapData(res.data); // if (res.data.length > 0) { @@ -146,7 +149,7 @@ this.notFirstFetch = true; } startIndex = startIndex < 0 ? 0 : startIndex; - return new Promise((resolve, reject) => { + return new Promise(() => { this.allFactorDatas.addData(dataList, this.drawMode, () => { realTimeMapAnimation.moveAnimation( this.allFactorDatas, -- Gitblit v1.9.3