Просмотр исходного кода

2023-03-08 update

1. 新增posAnalysis
2. 增加posChart 调用高德地图卫星地图 展示风机位置信息
moccus 1 год назад
Родитель
Сommit
a4f76092b5

+ 11 - 0
package-lock.json

@@ -8,6 +8,7 @@
       "name": "intelligent-early-warning",
       "version": "1.0.0",
       "dependencies": {
+        "@amap/amap-jsapi-loader": "^1.0.1",
         "@element-plus/icons-vue": "^2.0.10",
         "@stomp/stompjs": "^6.1.2",
         "@vue/runtime-core": "^3.2.33",
@@ -54,6 +55,11 @@
         "windicss": "^3.5.6"
       }
     },
+    "node_modules/@amap/amap-jsapi-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
+    },
     "node_modules/@antfu/utils": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.6.3.tgz",
@@ -5817,6 +5823,11 @@
     }
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
+    },
     "@antfu/utils": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.6.3.tgz",

+ 1 - 0
package.json

@@ -8,6 +8,7 @@
     "serve": "vite preview"
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
     "@element-plus/icons-vue": "^2.0.10",
     "@stomp/stompjs": "^6.1.2",
     "@vue/runtime-core": "^3.2.33",

+ 142 - 0
src/pages/dataAnalysis/posAnalysis/components/posChart.vue

@@ -0,0 +1,142 @@
+<script setup name="posChart">
+import { onMounted, ref, shallowRef, defineProps, watch } from 'vue'
+import AMapLoader from '@amap/amap-jsapi-loader';
+import { ElMessage } from 'element-plus';
+import request from '@/api/axios.js'
+// import stationPosRes from './stationPos.json'
+const map = shallowRef(null);
+const aMap = ref(null)
+const container = ref()
+const funMapSet = (callback = (flag) => {}) => {
+	AMapLoader.load({
+		key:"	540080009cfdae95b6b5a4f47af24f90",             // 申请好的Web端开发者Key,首次调用 load 时必填
+		version:"2.0",      // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+		plugins:[''],       // 需要使用的的插件列表,如比例尺'AMap.Scale'等
+	}).then((AMap)=>{
+			aMap.value = AMap;
+			map.value = new AMap.Map(container.value,{  //设置地图容器id
+					viewMode:"3D",    //是否为3D地图模式
+					zoom:9,           //初始化地图级别
+					center:[106.065974,37.428168], //初始化地图中心点位置
+					layers: [
+						// 卫星
+						new AMap.TileLayer.Satellite(),
+						// 路网
+						new AMap.TileLayer.RoadNet()
+					]
+			});
+			callback(true)
+	}).catch(e=>{
+			console.error(e);
+			callback(false)
+	})
+}
+const funStationPos = async () => {
+	const res = await request.get('/base/station', {params: {}})
+	// const res = stationPosRes
+	if(res.code === 200){
+		if(res.data && res.data.length){
+			map.value.clearMap()
+			res.data.forEach(item => {
+				const marker = new aMap.value.Marker({
+					icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_r.png",
+					position: [Number(item.longitude), Number(item.latitude)],
+					anchor:'bottom-center'
+				});
+				map.value.add(marker)
+				// marker.setTitle(item.name);
+				// 设置label标签
+				// label默认蓝框白底左上角显示,样式className为:amap-marker-label
+				marker.setLabel({
+					direction:'right',
+					offset: new aMap.value.Pixel(10, 0),  //设置文本标注偏移量
+					content: `${item.name}`, //设置文本标注内容
+				});
+			})
+			map.value.setFitView()
+		}
+	}
+}
+
+const props = defineProps({
+	windList: {
+		type: Array,
+		default: () => []
+	},
+	height: {
+		type: String,
+		default: '100%'
+	}
+})
+
+watch(() => props.windList, (val) => {
+	if(val && val.length){
+		map.value.clearMap()
+		val.forEach(item => {
+			const marker = new aMap.value.Marker({
+				icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_r.png",
+				position: [Number(item.longitude), Number(item.latitude)],
+				anchor:'bottom-center'
+			});
+			//创建右键菜单
+			const contextMenu = new aMap.value.ContextMenu();
+
+			//右键1
+			contextMenu.addItem("功率曲线拟合",  (e) => {
+				console.log(e)
+					
+			}, 0);
+
+			//右键2
+			contextMenu.addItem("对风偏差分析", () => {
+					
+			}, 1);
+
+			//右键2
+			contextMenu.addItem("曲线偏差率分析", () => {
+					
+			}, 2);
+
+			//绑定鼠标右击事件——弹出右键菜单
+			marker.on('rightclick', function (e) {
+					contextMenu.open(map, e);
+			});
+			map.value.add(marker)
+			// marker.setTitle(item.name);
+			// 设置label标签
+			// label默认蓝框白底左上角显示,样式className为:amap-marker-label
+			marker.setLabel({
+				direction:'right',
+				offset: new aMap.value.Pixel(10, 0),  //设置文本标注偏移量
+				content: `${item.name}`, //设置文本标注内容
+			});
+		})
+		map.value.setFitView()
+		setTimeout(() => {
+			let zoom = map.value.getZoom()
+			if(zoom > 15){
+				zoom = 15
+				map.value.setZoom(zoom)
+			}
+		},1000)
+	}else{
+		funStationPos()
+	}
+})
+//created
+funMapSet(mapStatus => {
+	if(!mapStatus){
+		ElMessage.error('地图未加载成功, 请刷新重试或检查网络!')
+		return false
+	}
+	funStationPos()
+})
+</script>
+<template>
+	<div :style="{height: props.height}">
+		<div class="h-full" ref="container">
+			<el-empty description="地图未加载成功, 请刷新重试或检查网络!"></el-empty>
+		</div>
+	</div>
+</template>
+<style scoped></style>

+ 52 - 0
src/pages/dataAnalysis/posAnalysis/components/table.vue

@@ -0,0 +1,52 @@
+<script setup name="table">
+import { computed, ref } from 'vue';
+
+const props = defineProps({
+  height: {
+    type: String,
+    default: '800px'
+  },
+  data: {
+    type: Array,
+    default: () => ([]),
+  },
+  column: {
+    type: Array,
+    default: () => ([]),
+  },
+  tableName: {
+    type: String,
+    default: '',
+  },
+  tableId: {
+    type: String,
+    default: '',
+  },
+  loading: {
+    type: Boolean,
+    default: false,
+  }
+})
+const emits = defineEmits(['export'])
+const funExport = () => {
+  emits('export')
+}
+const tableRef = ref('')
+const tableHeight =  computed(() => {
+  return tableRef.value.offsetHeight? tableRef.value.offsetHeight - 46 : 739
+})
+</script>
+<template>
+  <div ref="tableRef" class=""
+    :style="{ height: typeof props.height === 'string' ? props.height : props.height + 'px' }">
+    <div class="flex justify-between items-center pb-[10px]">
+      <h3>{{ props.tableName }}</h3>
+      <!-- <el-button size="small" type="primary" @click="funExport" :disabled="!props.tableId">数据导出</el-button> -->
+    </div>
+    <el-table stripe :data="props.data" size="small" v-loading="props.loading" :max-height="tableHeight"
+      :style="{ width: '100%' }">
+      <el-table-column align="center" show-overflow-tooltip v-for="item in props.column" :prop="item.prop"
+        :label="item.label" sortable resizable :min-width="item.width ? item.width : 80" />
+    </el-table>
+  </div>
+</template>

+ 200 - 0
src/pages/dataAnalysis/posAnalysis/index.vue

@@ -0,0 +1,200 @@
+<script setup name="prepare">
+import excelCop from '@/components/excel.vue'
+import treeCop from '@/components/tree.vue'
+import { ref, nextTick, onActivated, onMounted, reactive } from 'vue'
+import request from '@/api/axios.js'
+import { ElMessage } from 'element-plus'
+import posChart from './components/posChart.vue'
+/**配置参数 */
+const treeHeight = ref(window.innerHeight - 160 + 'px') //tree高度
+const excelHeight = ref(window.innerHeight - 160 + 'px') //excel高度
+const tableHeight = ref(window.innerHeight - 160 + 'px')
+/**excel 开始 */
+const excelCheckboxShow = ref(false)
+const excelCheckIds = ref([])
+const excelList = ref([])
+const funExcelChange = async (obj) => { //点击excel项时
+	return false
+}
+const funExcelCheckChange = ({ checkArr, data }) => {   //bug 
+	excelCheckIds.value = checkArr
+	funSubmit()
+}
+/**prepare tree 开始 */
+const treeData = ref([])
+const treeCopRef = ref()  //treeCop ref
+const actTreeNode = ref(null) //当前激活的treeNode
+const funRepeatMap = (arr, type='fitting') => {
+	return arr.map(o => {
+		if (o.children) {
+			const findIndex = o.children.findIndex(p => !!p.type)
+			if (findIndex !== -1) {
+				o.childs = o.children
+				o.children = []
+				if(!actTreeNode.value && type === 'fitting'){ //判断当且仅有process获取tree时 赋值
+					actTreeNode.value = o
+				}
+			}
+		}
+		return {
+			...o,
+			children: o.children ? funRepeatMap(o.children, type) : []
+		}
+	})
+}
+const funGetTree = async () => {
+	actTreeNode.value = null
+	const res = await request.get("/power/fitting/tree")
+	treeData.value = funRepeatMap(res.data)
+	excelList.value = []
+	if(actTreeNode.value){
+		funCurrentChange({current: actTreeNode.value, currentNode: null})
+		if(treeCopRef.value){
+			treeCopRef.value.setCheckedKeys([actTreeNode.value.id])
+			excelCheckIds.value = actTreeNode.value.childs.map(o => o.id)
+			funSubmit()
+		}
+	}
+}
+const funCurrentChange = ({ current, currentNode }) => {
+	excelCheckboxShow.value = true
+	if (current.childs) {
+		excelList.value = current.childs.map(o => {
+			return {
+				id: o.id,
+				interval: o.interval,
+				path: o.path,
+				prepareid: o.prepareid,
+				station: o.station,
+				time: o.time,
+				type: o.type,
+				windturbine: o.windturbine,
+				name: o.path.substring(o.path.indexOf(o.station + '_') + (o.station + '_').length)
+			}
+		})
+	} else {
+		excelList.value = []
+	}
+}
+const funTreeCheckChange = ({ current, checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys }) => {  //tree change  -> excel change
+	funCurrentChange({ current, currentNode: '' })
+	const checkIds = []
+	if (checkedNodes.length) {
+		for (const node of checkedNodes) {
+			if (node.childs && node.childs.length) {
+				for (const child of node.childs) {
+					checkIds.push(child.id)
+				}
+			}
+		}
+	}else{
+		windList.value = []
+	}
+	excelCheckIds.value = checkIds
+	funSubmit()
+}
+
+/**search 开始 */
+const funSubmit = async () => {
+	// if (!excelCheckIds.value.length) {
+	// 	ElMessage.error('请勾选要执行的项')
+	// 	return false
+	// }
+	const params = {
+		ids: excelCheckIds.value.join(',')
+	}
+	const res = await request.get('/base/location', { params: params })
+	if (res.code === 200) {
+		windList.value = res.data.filter(o => {
+			return !!o.longitude && !!o.latitude
+		})
+	}
+}
+
+/**posChart */
+const windList = ref([])
+
+/**mounted */
+onMounted(() => {
+	tableHeight.value = window.innerHeight - 160 + 'px'
+	excelHeight.value = window.innerHeight - 160 + 'px'
+	treeHeight.value = window.innerHeight - 160 + 'px'
+	window.addEventListener('resize', () => {
+		tableHeight.value = window.innerHeight - 160 + 'px'
+		excelHeight.value = window.innerHeight - 160 + 'px'
+		treeHeight.value = window.innerHeight - 160 + 'px'
+	})
+	/**test */
+	// funExcelChange({
+	// 	id: 1,
+	// 	name: 'excel',
+	// 	type: 'fitting',
+	// })
+})
+/**activated */
+onActivated(() => {
+	funGetTree()
+})
+</script>
+<template>
+  <div class="bg-white py-[10px] px-[10px] s-dialog-body">
+    <div
+      class="
+        relative
+        shadow
+        rounded-[6px]
+        shadow-blue-500
+        px-[10px]
+        pt-[20px]
+        pb-[10px]
+      "
+    >
+      <div class="text-[14px] absolute top-[-7px] text-[#838383] left-[20px]">
+        数据展示
+      </div>
+      <el-row :gutter="10">
+        <el-col :span="5">
+          <tree-cop
+						ref="treeCopRef" 
+            :data="treeData"
+            @checkChange="funTreeCheckChange"
+            :show-checkbox="true"
+            :height="treeHeight"
+            @currentChange="funCurrentChange"
+            @refresh="funGetTree"
+          ></tree-cop>
+        </el-col>
+        <el-col :span="3">
+          <excel-cop
+            :checkIds="excelCheckIds"
+            :showCheckbox="excelCheckboxShow"
+            :data="excelList"
+            :height="excelHeight"
+            @excelChange="funExcelChange"
+            @checkChange="funExcelCheckChange"
+          ></excel-cop>
+        </el-col>
+        <el-col :span="16">
+          <div class="shadow rounded-[6px] shadow-blue-500 overflow-hidden">
+            <div
+              :style="{
+                height:
+                  typeof tableHeight === 'string'
+                    ? tableHeight
+                    : tableHeight + 'px',
+								overflow: 'hidden'
+              }"
+            >
+							<posChart :height="typeof tableHeight === 'string' ? `calc(${tableHeight})` : tableHeight + 'px'" :windList="windList"></posChart>
+            </div>
+          </div>
+        </el-col>
+      </el-row>
+    </div>
+  </div>
+</template>
+<style scoped>
+.s-dialog-body /deep/ .el-dialog__body{
+	padding: 0px 20px;
+}
+</style>

+ 12 - 0
src/router/index.js

@@ -158,6 +158,18 @@ const routes = [{
                             '../pages/dataAnalysis/windAnalysis/index.vue'
                         ),
                 },
+                {
+                    icon: 'el-icon-s-home',
+                    path: '/dataAnalysis/posAnalysis',
+                    name: 'dataAnalysisPosAnalysis',
+                    meta: {
+                        title: '微观选址分析',
+                    },
+                    component: () =>
+                        import(
+                            '../pages/dataAnalysis/posAnalysis/index.vue'
+                        ),
+                },
             ]
         },
         {

Разница между файлами не показана из-за своего большого размера
+ 3244 - 3241
yarn.lock