Browse Source

2022-11-22

1. 调整excel组件的激活样式
2. 调整tag的最大宽度为动态
3. 调整main.js中的重复点击控制逻辑
4. 功率曲线拟合页 新增区域划分功能.
5. 新增拟合完成后默认展示图表及数据功能
moccus 2 years ago
parent
commit
744d6c98f6

+ 1 - 1
src/components/Tags.vue

@@ -147,7 +147,7 @@ watch(
 
 .tags-li-title {
 	float: left;
-	max-width: 80px;
+	/* max-width: 80px; */
 	overflow: hidden;
 	white-space: nowrap;
 	text-overflow: ellipsis;

+ 3 - 3
src/components/excel.vue

@@ -30,15 +30,15 @@ const funCheckChange = (checkArr) => {
 		:style="{ height: typeof props.height === 'string' ? props.height : props.height + 'px' }">
 		<el-empty v-if="!props.data.length" description="暂无数据" />
 		<el-checkbox-group size="small" v-model="excelCheckIds" v-if="props.showCheckbox" @change="funCheckChange">
-			<el-checkbox :class="{'bg-[rgb(236,245,255)]': currentId === item.id}" size="small" class="!mr-0 mb-[6px]" :label="item.id" v-for="item in props.data" :key="item.name">
+			<el-checkbox :class="{'!bg-[rgb(236,245,255)]': currentId === item.id}" size="small" class="hover:bg-[rgb(245,247,250)] !mr-0 py-[3px]" :label="item.id" v-for="item in props.data" :key="item.name">
 				<span class="whitespace-nowrap cursor-pointer text-[12px] align-middle inline-flex items-center"
 					@click.stop="funExcelChange(item)"><el-icon class="mr-[4px] !text-[rgb(71,179,71)]"><Document /></el-icon>{{ item.name }}</span>
 			</el-checkbox>
 		</el-checkbox-group>
 		<div v-else>
 			<div
-				class="whitespace-nowrap text-[#606266] px-[8px] w-full cursor-pointer leading-[10px] inline-flex items-center h-[24px] text-[12px]"
-				v-for="item in props.data" :key="item.name" :class="{'bg-[rgb(236,245,255)]': currentId === item.id}" @click="funExcelChange(item)"><el-icon class="mr-[4px] !text-[rgb(71,179,71)]"><Document /></el-icon>{{ item.name }}</div>
+				class="hover:bg-[rgb(245,247,250)] whitespace-nowrap text-[#606266] px-[8px] py-[3px] w-full cursor-pointer leading-[10px] inline-flex items-center h-[24px] text-[12px]"
+				v-for="item in props.data" :key="item.name" :class="{'!bg-[rgb(236,245,255)]': currentId === item.id}" @click="funExcelChange(item)"><el-icon class="mr-[4px] !text-[rgb(71,179,71)]"><Document /></el-icon>{{ item.name }}</div>
 		</div>
 	</div>
 </template>

+ 8 - 2
src/main.js

@@ -53,16 +53,22 @@ const VUE = createApp(App);
 for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
     VUE.component(key, component)
 }
+
+const messageToast = () => { //作为eventListener时, 必须使用外部定义函数
+    ElMessage.error('5秒内请勿重复点击')
+}
 /**阻止多次重复点击指令  延时暂定5秒 示例 v-prevdbclick:arg='func' */
 const funListener = (el, binding) => {
     let time = null
-    el.addEventListener('click', ()=> {
+    el.removeEventListener('click', messageToast)
+    el.addEventListener('click', () => {
         binding.value()
+        el.addEventListener('click', messageToast, false)
         time = setTimeout(() => {
             clearTimeout(time)
             funListener(el, binding)
         }, Number(binding.arg) || 5000)
-    },{
+    }, {
         once: true
     })
 }

+ 94 - 0
src/pages/curveDeviation/rateAnalysis/components/search.vue

@@ -0,0 +1,94 @@
+<script lang="ts" setup name="search">
+import { onMounted, reactive, ref } from 'vue'
+import request from '@/api/axios.js'
+
+const queryForm = reactive({
+	station: '',
+	wtIds: [],
+	st: Date.now() - 30 * 24 * 60 * 60 * 1000,
+	et: Date.now(),
+	interval: 3
+})
+/**场站 */
+const stationList = ref([])
+const funGetStation = async () => {
+	const res = await request.get("/base/station")
+	stationList.value = res.data
+	if (stationList.value.length) {
+		queryForm.station = stationList.value[0].id
+		funGetWind(queryForm.station)
+	}
+}
+const funStationChange = (stationId?: string) => {
+	if (stationId) {
+		funGetWind(stationId)
+	} else {
+		windList.value = []
+	}
+}
+/**风机 */
+const windList = ref<{id:string, name: string}[]>([])
+const funGetWind = async (stationId: string) => {
+	const res = await request.get("/base/windturbine", {params: { stationId }})
+	windList.value = res.data
+	queryForm.wtIds = res.data.map(o => o.id)
+}
+/**导出 */
+const emits = defineEmits(['submit'])
+const funSubmit = async () => {
+	const query = {
+		station: queryForm.station,
+		wtIds: queryForm.wtIds.join(),
+		st: new Date(queryForm.st).getTime(),
+		et: new Date(queryForm.et).getTime(),
+		interval: queryForm.interval
+	}
+	switch (queryForm.interval) {
+		case 2:
+			query.interval = 60
+			break;
+		case 3:
+			query.interval = 600
+			break;
+		case 4:
+			query.interval = 900
+			break;
+	}
+	emits('submit', query)
+}
+/**created */
+funGetStation()
+</script>
+<template>
+	<div class="overflow-x-auto pl-[10px] pt-[10px]">
+		<el-form class="whitespace-nowrap" :inline="true" :model="queryForm">
+			<el-form-item label="场站">
+				<el-select v-model="queryForm.station" class="w-[150px]" @change="funStationChange">
+					<el-option v-for="item in stationList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+				</el-select>
+			</el-form-item>
+			<el-form-item label="风机">
+				<el-select multiple class="w-[150px]" clearable v-model="queryForm.wtIds" collapse-tags>
+					<el-option v-for="item in windList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+				</el-select>
+			</el-form-item>
+			<el-form-item label="开始时间">
+				<el-date-picker class="!w-[150px]" type="date" v-model="queryForm.st"></el-date-picker>
+			</el-form-item>
+			<el-form-item label="结束时间">
+				<el-date-picker class="!w-[150px]" type="date" v-model="queryForm.et"></el-date-picker>
+			</el-form-item>
+			<el-form-item label="等间隔">
+				<el-radio-group v-model="queryForm.interval">
+					<el-radio :label="1">一秒钟</el-radio>
+					<el-radio :label="2">一分钟</el-radio>
+					<el-radio :label="3">十分钟</el-radio>
+					<el-radio :label="4">十五分钟</el-radio>
+				</el-radio-group>
+			</el-form-item>
+			<el-form-item>
+				<el-button type="primary" v-prevdbclick:5000="funSubmit">执行</el-button>
+			</el-form-item>
+		</el-form>
+	</div>
+</template>

+ 41 - 0
src/pages/curveDeviation/rateAnalysis/components/table.vue

@@ -0,0 +1,41 @@
+<script lang="ts" setup name="table">
+import {ref, computed} from 'vue'
+const props = withDefaults(defineProps<{
+  height?: string | number,
+  data: any,
+  column: any,
+  tableId: string,
+  tableName: string,
+  loading?: boolean
+}>(), {
+  height: '800px',
+  data: [],
+  column: [],
+  tableName: '',
+  tableId: '',
+  loading: false
+})
+const emits = defineEmits(['export'])
+const funExport = () => {
+  emits('export')
+}
+const tableRef = ref('')
+const tableHeight =  computed(() => {
+  return tableRef.value.offsetHeight? tableRef.value.offsetHeight - 46 : 661
+})
+</script>
+<template>
+  <div ref="tableRef" class="p-[10px] shadow rounded-[6px] shadow-blue-500"
+    :style="{ height: typeof props.height === 'string' ? props.height : props.height + 'px' }">
+    <div class="flex justify-between items-center pb-[10px] border-b-[1px]">
+      <h3>{{props.tableName}}</h3>
+      <!-- <el-button type="primary" @click="funExport" :disabled="!props.tableId">数据导出</el-button> -->
+    </div>
+    <el-table border :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>

+ 136 - 0
src/pages/curveDeviation/rateAnalysis/index.vue

@@ -0,0 +1,136 @@
+<script lang="ts" setup name="prepare">
+import searchCop from './components/search.vue'
+import excelCop from '@/components/excel.vue'
+import treeCop from '@/components/tree.vue'
+import tableCop from './components/table.vue'
+import { ElMessage } from 'element-plus';
+import { onMounted, ref, onActivated } from 'vue'
+import request from "@/api/axios.js"
+import config from '@/api/config.js'
+/**配置参数 */
+const treeHeight = '81vh' //tree高度
+const excelHeight = '81vh' //excel高度
+const tableHeight = '81vh'
+/**excel 开始 */
+const excelList = ref<{ id: string, name: string }[]>([])
+const funExcelChange = async (obj: any) => { //点击excel项时
+	tableShowId.value = obj.id
+	tableName.value = obj.name
+	tableLoading.value = true
+	const res = await request.get('/power/prepare/show', { params: { id: obj.id } })
+	tableColumn.value = res.data.title.map(o => {
+		return {
+			prop: o.key,
+			label: o.des,
+		}
+	})
+	tableData.value = res.data.data
+	tableLoading.value = false
+}
+/**tree 开始 */
+const treeData = ref([])
+const funRepeatMap = (arr: any) => {
+	return arr.map(o => {
+		if (o.children) {
+			const findIndex = o.children.findIndex(p => !!p.type)
+			if (findIndex !== -1) {
+				o.childs = o.children
+				o.children = []
+			}
+		}
+		return {
+			...o,
+			children: o.children?.length ? funRepeatMap(o.children) : []
+		}
+	})
+}
+const funGetTree = async () => {
+	const res = await request.get("/power/prepare/tree")
+	treeData.value = funRepeatMap(res.data)
+}
+const funCurrentChange = ({ current, currentNode }) => {
+	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 = []
+	}
+}
+/**table 开始 */
+const tableShowId = ref('')
+const tableName = ref('')
+const tableColumn = ref([])
+const tableLoading = ref(false)
+const tableData = ref([])
+const funExport = async () => {
+	const a = document.createElement('a')
+	a.href = config.baseURL + '/power/prepare/download?id=' + tableShowId.value
+	a.download = ''
+	a.click()
+}
+/**submit */
+const progress = ref(0)
+const funWebSocket = () => {
+	const webSocket = new WebSocket(`${config.socketURL}/ws/powerfitting/admin`)
+	webSocket.onerror = () => setTimeout(() => { funWebSocket() }, 2000)
+
+	webSocket.onmessage = (event) => {
+		const message = JSON.parse(event.data)
+		if (message.code === 200) {
+			progress.value = Number(message.data) * 100
+			if (progress.value === 100) {
+				ElMessage.success('数据加载完成')
+				funGetTree()
+				progress.value = 0
+			}
+		}
+	}
+}
+const funSubmit = async (params) => {
+	const res = await request.get('/power/prepare/data', { params: params })
+	if (res.code === 200) {
+		ElMessage.success(res.msg)
+
+	}
+}
+/**created */
+funGetTree()
+funWebSocket()
+/**activated */
+onActivated(() => {
+	funGetTree()
+})
+</script>
+<template>
+	<div class="bg-white pb-[10px] relative">
+		<search-cop @submit="funSubmit"></search-cop>
+		<el-row :gutter="10">
+			<el-col :span="5">
+				<tree-cop :data="treeData" :height="treeHeight" @currentChange="funCurrentChange" @refresh="funGetTree">
+				</tree-cop>
+			</el-col>
+			<el-col :span="3">
+				<excel-cop :data="excelList" :height="excelHeight" @excelChange="funExcelChange"></excel-cop>
+			</el-col>
+			<el-col :span="16">
+				<div>
+					<table-cop :data="tableData" :column="tableColumn" :loading="tableLoading" :height="tableHeight"
+						:tableId="tableShowId" :tableName="tableName" @export="funExport"></table-cop>
+				</div>
+			</el-col>
+		</el-row>
+		<el-progress :percentage="progress" class="!absolute top-0 right-0 left-0" :indeterminate="false" color="rgb(19,206,102)"
+			:stroke-width="4" :show-text="false" />
+	</div>
+</template>

+ 27 - 12
src/pages/dataFilter/combine/components/current-scatter-chart.vue

@@ -84,7 +84,6 @@ export default {
       const that = this;
       echarts.registerTheme('chartTheme', chartTheme)
       let myChart = echarts.init(document.getElementById(this.id), 'chartTheme');
-
       //指定图表的配置项和数据
       const option = {
         //标题
@@ -103,7 +102,7 @@ export default {
         toolbox: {
           show: true,
           x: "right",
-          position: [10, 10],
+          position: [0, 0],
           backgroundColor:
             that.theme === "dark"
               ? "rgba(0,0,0,0.4)"
@@ -145,9 +144,9 @@ export default {
             color: that.theme === "dark" ? "#fff" : "#000",
           },
           formatter(params) {
-            return params.name
-              ? `${params.seriesName}<br />风速:${params.name}m/s<br />功率:${params.value}kW`
-              : `${params.seriesName}<br />风速:${params.value.x}m/s<br />功率:${params.value.y}kW`;
+            return params.value?.x
+              ? `${params.seriesName}<br />风速:${params.value.x}m/s<br />功率:${params.value.y}kW`
+              : `${params.name}`;
           },
         },
         brush: {
@@ -206,7 +205,7 @@ export default {
           },
         },
         grid: {
-          top: 32,
+          top: 42,
           left: 40,
           right: 40,
           bottom: 24,
@@ -245,7 +244,7 @@ export default {
           position: 'right',
           min: 0,
         }],
-        animation: false,
+        animation: true,
         dataset: that.dataSet.length? JSON.parse(that.dataSet) : [],
         //数据-data是最终要显示的数据
         series: that.seriesData,
@@ -258,12 +257,7 @@ export default {
       window.addEventListener("resize", that.resize);
 
       myChart.setOption(option);
-
       if (that.brushSelected) {
-        myChart.off("brushSelected");
-        myChart.on("brushSelected", (params) => {
-          that.$emit("getSelected", params.batch || []);
-        });
         myChart.dispatchAction({
           type: "takeGlobalCursor",
           // 如果想变为“可刷选状态”,必须设置。不设置则会关闭“可刷选状态”。
@@ -285,6 +279,26 @@ export default {
           },
         });
       }
+      myChart.off("brushSelected");
+      myChart.on("brushSelected", (params) => {
+        that.$emit("getSelected", params.batch || []);
+      });
+      myChart.off('click')
+      myChart.on('click', params => {
+          console.log(params)
+          if(params.componentType === 'markArea'){
+            myChart.dispatchAction({
+              type: 'brush',
+              areas: [
+                {
+                  xAxisIndex: 0,
+                  brushType: 'lineX',
+                  coordRange: [params.data.coord[0][0], params.data.coord[1][0]]
+                },
+              ]
+            });
+          }
+        })
     },
   },
   created() {
@@ -298,6 +312,7 @@ export default {
     // });
   },
   updated() {
+    console.log('update')
     let myChart = echarts.init(document.getElementById(this.id));
     myChart.dispose();
     this.$nextTick(() => {

+ 140 - 28
src/pages/dataFilter/combine/index.vue

@@ -6,6 +6,7 @@ import tableCop from './components/table.vue'
 import { ref, nextTick, onActivated } from 'vue'
 import request from '@/api/axios.js'
 import { ElMessage } from 'element-plus'
+import util from "@tools/util";
 import CurrentScatterChart from './components/current-scatter-chart.vue'
 /**配置参数 */
 const treeHeight = '40vh' //tree高度
@@ -18,6 +19,7 @@ const excelCheckIds = ref<string[]>([])
 const excelList = ref<{ id: string, name: string }[]>([])
 const funExcelChange = async (obj: any) => { //点击excel项时
 	activeTab.value = '1'
+	isChartArea.value = false
 	tableShowId.value = obj.id
 	tableName.value = obj.name
 	excelType.value = obj.type // 接收excel的type 用于控制右侧tab展示
@@ -85,7 +87,7 @@ const funExcelChange = async (obj: any) => { //点击excel项时
 				showEffectOn: "emphasis",
 				name: '无用点',
 				symbolSize: (data) => {
-					return data.s? data.s>10 ? 10 : data.s : 4
+					return data.s ? data.s > 10 ? 10 : data.s : 4
 				},
 				datasetIndex: 0,
 				encode: {
@@ -101,7 +103,7 @@ const funExcelChange = async (obj: any) => { //点击excel项时
 				showEffectOn: "emphasis",
 				name: '有用点',
 				symbolSize: (data) => {
-					return data.s? data.s>10 ? 10 : data.s : 4
+					return data.s ? data.s > 10 ? 10 : data.s : 4
 				},
 				datasetIndex: 1,
 				animation: false,
@@ -123,7 +125,6 @@ const funExcelChange = async (obj: any) => { //点击excel项时
 				yAxisIndex: 1,
 			},
 		]
-
 	}
 }
 const funExcelCheckChange = ({ checkArr, data }) => {   //bug 
@@ -234,11 +235,21 @@ const funSubmit = async (query) => {
 	if (res.code === 200) {
 		ElMessage.success(res.msg)
 		funGetProcessTree()
+		const excelInfo = res.data
+
+		/**拟合完成后 显示右侧图表及数据 */
+		funExcelChange({
+			id: excelInfo.id,
+			name: excelInfo.path.substring(excelInfo.path.indexOf(excelInfo.station + '_') + (excelInfo.station + '_').length),
+			type: 'fitting'
+		})
 	}
 }
 /**chart Data */
 const xAxisData = ref([])
-const seriesData = ref([])
+const chartRef = ref() //chart 的ref
+const seriesData = ref<any>([])
+const isChartArea = ref(false) // 用来控制图表是否区域划分
 const dataSet = ref('')
 const funChartSelect = async (batch) => {
 	const wDataArr = []
@@ -262,39 +273,138 @@ const funChartSelect = async (batch) => {
 					yDataArr.push(dataSetObj[1].source[scatterIndex].k)
 				}
 			}
-			const wtRes = await request.get('/power/fitting/filter', {params: {yk: yDataArr.join(','), wk: wDataArr.join(',')}})
-			if(wtRes.code === 200){
+			const wtRes = await request.get('/power/fitting/filter', { params: { yk: yDataArr.join(','), wk: wDataArr.join(',') } })
+			if (wtRes.code === 200) {
 				let id = 1
 				const tempArr = [] //用于以风机id 聚合dataArr
-				if(wtRes.data?.length){
-					for(const data of wtRes.data){
-					if(tempArr.length){
-						const findIndex = tempArr.findIndex(o => o.wtId === data.wtId)
-						if(findIndex !== -1){
-							if(!tempArr[findIndex].children){
-								tempArr[findIndex].children = []
+				if (wtRes.data?.length) {
+					for (const data of wtRes.data) {
+						if (tempArr.length) {
+							const findIndex = tempArr.findIndex(o => o.wtId === data.wtId)
+							if (findIndex !== -1) {
+								if (!tempArr[findIndex].children) {
+									tempArr[findIndex].children = []
+								}
+								tempArr[findIndex].children.push({ ...data, id: id, filter: data.filter === 0 ? '是' : '否' })
+								id++
+							} else {
+								tempArr.push({ ...data, id: id, filter: data.filter === 0 ? '是' : '否' })
+								id++
 							}
-							tempArr[findIndex].children.push({...data, id: id, filter: data.filter === 0? '是': '否'})
-							id++
-						}else{
-							tempArr.push({...data, id: id, filter: data.filter === 0? '是': '否'})
+						} else {
+							tempArr.push({ ...data, id: id, filter: data.filter === 0 ? '是' : '否' })
 							id++
 						}
-					}else{
-						tempArr.push({...data, id: id, filter: data.filter === 0? '是': '否'})
-						id++
 					}
-				}
-				wtDialog.value = true
-				nextTick(() => {
-					wtTab.value = 'table'
-					wtData.value = tempArr
-				})
+					wtDialog.value = true
+					nextTick(() => {
+						wtTab.value = 'table'
+						wtData.value = tempArr
+					})
 				}
 			}
 		}
 	}
 }
+const funChartArea = () => {
+	if (seriesData.value?.length) {
+		if (!isChartArea.value) {
+			seriesData.value[0] = {
+					...seriesData.value[0],
+					markLine: {
+						symbol: 'none',
+						label: {
+							show: false
+						},
+						lineStyle: {
+							color: 'rgba(96,174,255, 1)'
+						},
+						data: [
+							{
+								xAxis: 3,
+								valueIndex: 0,
+							},
+							{
+								xAxis: 5,
+								valueIndex: 0
+							},
+							{
+								xAxis: 10,
+								valueIndex: 0
+							},
+							{
+								xAxis: 12,
+								valueIndex: 0
+							},
+							{
+								xAxis: 25,
+								valueIndex: 0
+							},
+						]
+					},
+					markArea: {
+						label: {
+							fontSize: util.vh(12),
+						},
+						itemStyle: {
+							color: 'rgba(236,245,255, 0)'
+						},
+						emphasis: {
+							itemStyle: {
+								color: 'rgba(96,174,255, 0.5)'
+							}
+						},
+						data: [
+							[
+								{
+									name: '3~5m/s',
+									xAxis: 3,
+								},
+								{
+									xAxis: 5,
+								}
+							],
+							[
+								{
+									name: '5~10m/s',
+									xAxis: 5,
+								},
+								{
+									xAxis: 10,
+								}
+							],
+							[
+								{
+									name: '10~12m/s',
+									xAxis: 10,
+								},
+								{
+									xAxis: 12,
+								}
+							],
+							[
+								{
+									name: '12~25m/s',
+									xAxis: 12,
+								},
+								{
+									xAxis: 25,
+								}
+							],
+						]
+					}
+				}
+			isChartArea.value = true
+		} else {
+			seriesData.value[0] = {
+					...seriesData.value[0],
+					markLine: null,
+					markArea: null
+				}
+			isChartArea.value = false
+		}
+	}
+}
 /**dialog 数据 */
 const wtDialog = ref(false)
 const wtData = ref([])
@@ -348,6 +458,8 @@ onActivated(() => {
 			</el-col>
 			<el-col :span="16">
 				<div class="px-[10px] shadow rounded-[6px] shadow-blue-500">
+					<el-button class="absolute right-[16px] top-[4px] z-10" type="primary"
+						v-if="activeTab === '2' && excelType === 'fitting'" @click="funChartArea">区域划分</el-button>
 					<el-tabs v-model="activeTab">
 						<el-tab-pane label="表格数据" name="1">
 						</el-tab-pane>
@@ -357,9 +469,9 @@ onActivated(() => {
 							:height="tableHeight" :tableId="tableShowId" :tableName="tableName"></table-cop>
 						<div v-show="activeTab === '2'"
 							:style="{ height: typeof tableHeight === 'string' ? tableHeight : tableHeight + 'px' }" class="p-[10px]">
-							<CurrentScatterChart width="100%" height="100%" chartTitle="风速功率曲线图" :xAxisData="xAxisData"
+							<CurrentScatterChart ref="chartRef" width="100%" height="100%" chartTitle="风速功率曲线图" :xAxisData="xAxisData"
 								:yAxisData="{ splitLine: { show: false } }" :seriesData="seriesData" :showLegend="true"
-								:brushSelected="true" :dataSet="dataSet" @getSelected="funChartSelect" />
+								:brushSelected="!isChartArea" :dataSet="dataSet" @getSelected="funChartSelect" />
 						</div>
 					</el-tabs>
 				</div>

+ 1 - 1
src/pages/dataFilter/process/components/search.vue

@@ -13,7 +13,7 @@ const queryForm = reactive({
 	isbw: true,
 	istj: true,
 	isglpc: true,
-	isqfh: true,
+	isqfh: false,
 	qfhdj: 2
 })
 /**导出 */

+ 27 - 0
src/router/index.js

@@ -61,6 +61,33 @@ const routes = [{
                 },
             ]
         },
+        {
+            icon: 'iconfont iconbaojingpeizhi',
+            path: '/curveDeviation',
+            name: 'curveDeviation',
+            redirect: '/curveDeviation/rateAnalysis',
+            meta: {
+                title: '曲线偏差率分析',
+            },
+            component: () =>
+                import(
+                    '../pages/routerViewss.vue'
+                ),
+            children: [
+                {
+                    icon: 'el-icon-s-home',
+                    path: '/curveDeviation/rateAnalysis',
+                    name: 'curveDeviationRateAnalysis',
+                    meta: {
+                        title: '曲线偏差率分析',
+                    },
+                    component: () =>
+                        import(
+                            '../pages/curveDeviation/rateAnalysis/index.vue'
+                        ),
+                },
+            ]
+        },
     ],
 },