Lmm 1 year ago
parent
commit
dd65dd761d
4 changed files with 426 additions and 396 deletions
  1. 71 296
      src/App.vue
  2. 274 71
      src/js/common.js
  3. 34 1
      src/js/export.js
  4. 47 28
      src/js/merge.js

+ 71 - 296
src/App.vue

@@ -42,24 +42,24 @@
 			<el-form-item>
 				<el-button type="primary" size="small" @click="handleQuery">搜索</el-button>
 				<el-button v-if="loading" type="success" size="small" :loding="loading">导出中...</el-button>
-				<el-button v-else type="success" size="small" @click="handleDerive">导出</el-button>
+				<el-button v-else type="success" size="small" :disabled="!selection.length" @click="handleDerive">导出</el-button>
 			</el-form-item>
 		</el-form>
 		<el-table :data="tableData" border :span-method="objectSpanMethod" @selection-change="handleSelectionChange">
 			<el-table-column type="selection" width="60" align="center" fixed />
 			<el-table-column label="序号" width="60" align="center" fixed>
 				<template slot-scope="scope">
-					<span>{{ (queryParams.page_index - 1) * queryParams.page_size + scope.$index + 1 }}</span>
+					<span>{{ (queryParams.page_index - 1) * queryParams.page_size + scope.row.projectId }}</span>
 				</template>
 			</el-table-column>
-			<el-table-column prop="projectName" label="项目名称" align="center" width="220" show-overflow-tooltip fixed />
-			<el-table-column prop="boxName" label="盒子名称" align="center" width="180" show-overflow-tooltip fixed />
-			<el-table-column prop="runStatus" label="在线状态" align="center" width="100">
+			<el-table-column prop="projectName" label="项目名称" align="center" width="180" fixed />
+			<el-table-column prop="boxName" label="盒子名称" align="center" width="180" fixed />
+			<el-table-column prop="runStatus" label="在线状态" align="center" width="100" fixed>
 				<template slot-scope="scope">
 					<span class="el-table-tag" :style="{ background: runStatMap[scope.row.runStatus].color }">{{ runStatMap[scope.row.runStatus].label }}</span>
 				</template>
 			</el-table-column>
-			<el-table-column prop="runMode" label="运行模式" align="center" width="100">
+			<el-table-column prop="runMode" label="运行模式" align="center" width="100" fixed>
 				<template slot-scope="scope">
 					<span class="el-table-tag" :style="{ background: runModeMap[scope.row.runMode].color }">{{ runModeMap[scope.row.runMode].label }}</span>
 				</template>
@@ -98,7 +98,7 @@
 				</el-table-column>
 				<el-table-column prop="host_su_temp" label="供水水温(℃)" align="center" width="120">
 					<template slot-scope="scope">
-						<span v-if="scope.row.host_su_temp" class="el-table-tag" :style="{ background: hpTempColor(scope.row.runMode, scope.row.host_su_temp) }">
+						<span v-if="scope.row.host_su_temp" class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 							{{ fixedVal(scope.row.host_su_temp) }}
 						</span>
 						<span v-else>/</span>
@@ -106,7 +106,7 @@
 				</el-table-column>
 				<el-table-column prop="host_re_temp" label="回水水温(℃)" align="center" width="120">
 					<template slot-scope="scope">
-						<span v-if="scope.row.host_re_temp" class="el-table-tag" :style="{ background: hpTempColor(scope.row.runMode, scope.row.host_re_temp) }">
+						<span v-if="scope.row.host_re_temp" class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 							{{ fixedVal(scope.row.host_re_temp) }}
 						</span>
 						<span v-else>/</span>
@@ -115,7 +115,7 @@
 				<el-table-column prop="host_temp_diff" label="温差" align="center" width="100">
 					<template slot-scope="scope">
 						<div v-if="scope.row.host_temp_diff">
-							<span class="el-table-tag" :style="{ background: scope.row.host_temp_diff && scope.row.host_temp_diff <= 5 ? 'yellowgreen' : '' }">
+							<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 								{{ fixedVal(scope.row.host_temp_diff) }}
 							</span>
 							<i v-if="scope.row.hpCnt > scope.row.maxCnt" class="el-icon-caret-bottom ml10" @click.stop="handleClickMore(scope.row, 'host')"></i>
@@ -159,7 +159,7 @@
 				</el-table-column>
 				<el-table-column prop="nt_in_temp" label="送风温度(℃)" align="center" width="120">
 					<template slot-scope="scope">
-						<span v-if="scope.row.nt_in_temp" class="el-table-tag" :style="{ background: dhTempColor(scope.row.runMode, scope.row.nt_in_temp) }">
+						<span v-if="scope.row.nt_in_temp" class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 							{{ fixedVal(scope.row.nt_in_temp) }}
 						</span>
 						<span v-else>/</span>
@@ -167,7 +167,7 @@
 				</el-table-column>
 				<el-table-column prop="nt_in_humidity" label="送风湿度(%)" align="center" width="120">
 					<template slot-scope="scope">
-						<span v-if="scope.row.nt_in_humidity" class="el-table-tag" :style="{ background: dhHumiColor(scope.row.runMode, scope.row.nt_in_humidity) }">
+						<span v-if="scope.row.nt_in_humidity" class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 							{{ fixedVal(scope.row.nt_in_humidity) }}
 						</span>
 						<span v-else>/</span>
@@ -176,7 +176,7 @@
 				<el-table-column prop="nt_dew_point" label="露点(℃)" align="center" width="120">
 					<template slot-scope="scope">
 						<div v-if="scope.row.nt_dew_point">
-							<span class="el-table-tag" :style="{ background: dhDewPointColor(scope.row.nt_dew_point) }">
+							<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 								{{ fixedVal(scope.row.nt_dew_point) }}
 							</span>
 							<i v-if="scope.row.dhCnt > scope.row.maxCnt" class="el-icon-caret-bottom ml10" @click.stop="handleClickMore(scope.row, 'newTrend')"></i>
@@ -220,7 +220,7 @@
 				</el-table-column>
 				<el-table-column prop="hex_su_temp" label="供水水温(℃)" align="center" width="120">
 					<template slot-scope="scope">
-						<span v-if="scope.row.hex_su_temp" class="el-table-tag" :style="{ background: hexTempColor(scope.row.runMode, scope.row.hex_su_temp) }">
+						<span v-if="scope.row.hex_su_temp" class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 							{{ fixedVal(scope.row.hex_su_temp) }}
 						</span>
 						<span v-else>/</span>
@@ -228,7 +228,7 @@
 				</el-table-column>
 				<el-table-column prop="hex_re_temp" label="回水水温(℃)" align="center" width="120">
 					<template slot-scope="scope">
-						<span v-if="scope.row.hex_re_temp" class="el-table-tag" :style="{ background: hexTempColor(scope.row.runMode, scope.row.hex_re_temp) }">
+						<span v-if="scope.row.hex_re_temp" class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
 							{{ fixedVal(scope.row.hex_re_temp) }}
 						</span>
 						<span v-else>/</span>
@@ -239,7 +239,7 @@
 						<span 
 							v-if="scope.row.hex_temp_diff != undefined && scope.row.hex_temp_diff != null" 
 							class="el-table-tag" 
-							:style="{ background: scope.row.hex_temp_diff <= 5 ? 'yellowgreen' : '' }"
+							:style="{ background: calcArgsColor(scope) }"
 						>
 							{{ fixedVal(scope.row.hex_temp_diff) }}
 						</span>
@@ -262,7 +262,7 @@
 
 			<!-- 末端列 Begin -->
 			<el-table-column label="末端控制器" align="center" width="60">
-				<el-table-column prop="end_order" label="编号" align="center" width="60" />
+				<!-- <el-table-column prop="end_order" label="编号" align="center" width="60" /> -->
 				<el-table-column prop="end_exception_num" label="通讯异常数量" align="center" width="120">
 					<template slot-scope="scope">
 						<span v-if="scope.row.end_exception_num != undefined && scope.row.end_exception_num != null">
@@ -273,33 +273,45 @@
 				</el-table-column>
 				<el-table-column prop="end_min_temp" label="最低室内温度(℃)" align="center" width="140">
 					<template slot-scope="scope">
-						<span class="el-table-tag" :style="{ background: cbMinTempColor(scope.row) }">{{ fixedVal(scope.row.end_min_temp) }}</span>
+						<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
+							{{ fixedVal(scope.row.end_min_temp) }}
+						</span>
 					</template>
 				</el-table-column>
 				<el-table-column prop="end_min_humidity" label="最低室内湿度(%)" align="center" width="140">
 					<template slot-scope="scope">
-						<span class="el-table-tag" :style="{ background: cbMinHumiColor(scope.row) }">{{ fixedVal(scope.row.end_min_humidity) }}</span>
+						<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
+							{{ fixedVal(scope.row.end_min_humidity) }}
+						</span>
 					</template>
 				</el-table-column>
 				<el-table-column prop="end_min_dew_point" label="最低室内露点(℃)" align="center" width="140">
 					<template slot-scope="scope">
-						<span class="el-table-tag" :style="{ background: cbMinDewPointColor(scope.row) }">{{ fixedVal(scope.row.end_min_dew_point) }}</span>
+						<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
+							{{ fixedVal(scope.row.end_min_dew_point) }}
+						</span>
 					</template>
 				</el-table-column>
 				<el-table-column prop="end_max_temp" label="最高室内温度(℃)" align="center" width="140">
 					<template slot-scope="scope">
-						<span class="el-table-tag" :style="{ background: cbMaxTempColor(scope.row) }">{{ fixedVal(scope.row.end_max_temp) }}</span>
+						<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
+							{{ fixedVal(scope.row.end_max_temp) }}
+						</span>
 					</template>
 				</el-table-column>
 				<el-table-column prop="end_max_humidity" label="最高室内湿度(%)" align="center" width="140">
 					<template slot-scope="scope">
-						<span class="el-table-tag" :style="{ background: cbMaxHumiColor(scope.row) }">{{ fixedVal(scope.row.end_max_humidity) }}</span>
+						<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
+							{{ fixedVal(scope.row.end_max_humidity) }}
+						</span>
 					</template>
 				</el-table-column>
 				<el-table-column prop="end_max_dew_point" label="最高室内露点(℃)" align="center" width="140">
 					<template slot-scope="scope">
 						<div>
-							<span class="el-table-tag" :style="{ background: cbMaxDewPointColor(scope.row) }">{{ fixedVal(scope.row.end_max_dew_point) }}</span>
+							<span class="el-table-tag" :style="{ background: calcArgsColor(scope) }">
+								{{ fixedVal(scope.row.end_max_dew_point) }}
+							</span>
 							<i v-if="scope.row.cbCnt > 1" class="el-icon-caret-bottom ml10" @click.stop="handleClickMore(scope.row, 'end')"></i>
 						</div>
 					</template>
@@ -329,7 +341,10 @@
 import { listProjects, listArgs } from './js/api.js';
 import { expandAllNodes, mergeTableRows } from './js/merge.js';
 import { exportToExcel } from './js/export.js';
-import { runStatDict, runModeDict, connectStatDict, faultDict, hexPumpStatDict } from './js/common.js';
+import { runStatDict, runModeDict, connectStatDict, faultDict, hexPumpStatDict, heatExchangeCols } from './js/common.js';
+import { runStatOpts, runModeOpts } from './js/common.js';
+import { hostCols, newTrendCols, heaxExchangeCols, endCols } from './js/common.js';
+import { getArgsColor } from './js/common.js';
 import PopMoreTable from './components/PopMoreTable.vue';
 export default {
 	components: {
@@ -366,112 +381,12 @@ export default {
 				return this.hexPumpStatMap[state] ? this.hexPumpStatMap[state].label : '/'
 			}
 		},
-		// 主机供水温度与回水温度颜色判定
-		hpTempColor() {
-			return function(runMode, temp) {
-				if (!temp) return '';
-				if (runMode == 2 || runMode == 4) {
-					return temp < 30 ? 'yellow' : 'yellowgreen';
-				} else if (runMode == 1 || runMode == 3) {
-					return temp > 25 ? 'yellow' : 'yellowgreen';
-				}
-			};
-		},
-		// 新风机送风温度颜色判定
-		dhTempColor() {
-			return function(runMode, temp) {
-				if (!temp) return '';
-				if (temp <= 5) return 'yellow';
-				if (runMode == 2 || runMode == 4) {
-					return temp < 20 ? 'yellow' : 'yellowgreen';
-				} else if (runMode == 1 || runMode == 3) {
-					return temp > 25 ? 'yellow' : 'yellowgreen';
-				}
-			};
-		},
-		// 新风机送风湿度颜色判定
-		dhHumiColor() {
-			return function(humi) {
-				if (!humi) return '';
-				return humi < 20 || humi > 80 ? 'yellow' : 'yellowgreen';
-			};
-		},
-		// 新风机露点颜色判定
-		dhDewPointColor() {
-			return function(dewPoint) {
-				if (!dewPoint) return '';
-				return dewPoint < 5 || dewPoint > 14 ? 'yellow' : 'yellowgreen';
-			};
-		},
-		// 换热站供水温度与回水温度颜色判定
-		hexTempColor() {
-			return function(runMode, temp) {
-				if (!temp) return '';
-				if (runMode == 2 || runMode == 4) {
-					return temp < 30 ? 'yellow' : 'yellowgreen';
-				} else if (runMode == 1 || runMode == 3) {
-					return temp > 25 ? 'yellow' : 'yellowgreen';
-				}
-			};
-		},
-		// 末端最低室内温度颜色判定
-		cbMinTempColor() {
-			return function(row) {
-				if (!row.end_min_temp) return '';
-				return row.end_min_temp < 18 ? 'yellow' : 'yellowgreen';
-			};
-		},
-		// 末端最低室内湿度颜色判定
-		cbMinHumiColor() {
-			return function(row) {
-				if (!row.end_min_humidity) return '';
-				return row.end_min_humidity < 30 ? 'yellow' : 'yellowgreen';
-			};
-		},
-		// 末端最低室内露点颜色判定
-		cbMinDewPointColor() {
-			return function(row) {
-				if (!row.end_min_dew_point) return '';
-				return row.end_min_dew_point < 7 ? 'yellow' : 'yellowgreen';
-			};
-		},
-		// 末端最高室内温度颜色判定
-		cbMaxTempColor() {
-			return function(row) {
-				if (!row.end_max_temp) return '';
-				return row.end_max_temp > 28 ? 'yellow' : 'yellowgreen';
-			};
-		},
-		// 末端最高室内湿度颜色判定
-		cbMaxHumiColor() {
-			return function(row) {
-				if (!row.end_max_humidity) return '';
-				return row.end_max_humidity > 70 ? 'yellow' : 'yellowgreen';
-			};
-		},
-		// 末端最高室内露点颜色判定
-		cbMaxDewPointColor() {
-			return function(row) {
-				if (!row.end_max_dew_point) return '';
-				return row.end_max_dew_point > 18 ? 'yellow' : 'yellowgreen';
-			};
-		},
 		calcArgsColor() {
-			return function(row, prop) {
-				let items = this.argsList.filter(a => a.En === prop);
-				if (!items) {
-					return '';
-				}
-				if (items.length > 1) {
-					// items.forEach(v => {
-					// 	if (v.RunMode > 0) {
-							
-					// 	} else {
-							
-					// 	}
-					// });
-				} else {
-					return this.getArgsColor(row, prop, items[0].Action, items[0].Threshold);
+			return function(scope) {
+				let property = scope.column.property || '';
+				if (property && property.length) {
+					let argsItems = this.argsList.filter(a => a.En === property);
+					return getArgsColor(argsItems, scope.row.runMode, scope.row[property]);
 				}
 			}
 		},
@@ -497,23 +412,15 @@ export default {
 			dataSource: [], // 数据源
 			tableData: [],
 			argsList: [],
+			selection: [],  // 选中的数据
 			mergeColums: ['projectName', 'boxName', 'runStatus', 'runMode'],
 			runStatMap: runStatDict,
 			runModeMap: runModeDict,
 			connectStatMap: connectStatDict,
 			hexPumpStatMap: hexPumpStatDict,
 			faultMap: faultDict,
-			runStatOptions: [ 
-				{ label:'在线', value:'1' }, 
-				{ label:'离线', value:'0' },
-			],
-			runModeOptions: [
-				{ label:'制冷', value:'1' }, 
-				{ label:'采暖', value:'2' },
-				{ label:'除湿', value:'3' },
-				{ label:'预热', value:'4' },
-				{ label:'通风', value:'5' },
-			],
+			runStatOptions: runStatOpts,
+			runModeOptions: runModeOpts,
 			dialog: {
 				show: false,
 				title: '',
@@ -561,38 +468,25 @@ export default {
 				console.log('[args/list]请求错误: ', err);
 			});
 		},
-		/** 多选 */
-		handleSelectionChange(val) {
-			
-		},
-		/** 计算颜色 */
-		getArgsColor(row, prop, action, threshold) {
-			if (action === ">") {
-				return row[prop] > threshold ? 'yellow' : "yellowgreen";
-			} else if (action === "<") {
-				return row[prop] < threshold ? 'yellow' : "yellowgreen";
-			} else if (action === ">=") {
-				return row[prop] >= threshold ? 'yellow' : "yellowgreen";
-			} else if (action === "<=") {
-				return row[prop] <= threshold ? 'yellow' : "yellowgreen";
-			}
-		},
 		/** 数据行合并 */
 		objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+			if (columnIndex == 0 || columnIndex == 1) {
+				if (row['boxName-span']) return row['boxName-span'];
+			}
 			// 主机合并
-			if (columnIndex >= 5 && columnIndex <= 10) {
+			if (columnIndex >= 6 && columnIndex <= 11) {
 				return { rowspan: row.hpSpanRows, colspan: 1 };
 			}
 			// 新风机
-			if (columnIndex >= 11 && columnIndex <= 16) {
+			if (columnIndex >= 12 && columnIndex <= 17) {
 				return { rowspan: row.dhSpanRows, colspan: 1 };
 			}
 			// 换热站
-			if (columnIndex >= 17 && columnIndex <= 23) {
+			if (columnIndex >= 18 && columnIndex <= 24) {
 				return { rowspan: row.hexSpanRows, colspan: 1 };
 			}
 			// 末端
-			if (columnIndex >= 24) {
+			if (columnIndex >= 25) {
 				return { rowspan: row.cbSpanRows, colspan: 1 };
 			}
 			const span = column['property'] + '-span';
@@ -606,138 +500,6 @@ export default {
 			let box = project.boxList.find(b => b.box_id === row.boxId);
 			return box[prop];
 		},
-		/** 拼接主机更多数据 */
-		packHostColumns(datas) {
-			return [
-				{
-					prop: 'host_order',
-					label: '编号',
-					width: 60
-				},
-				{
-					prop: 'host_connect_status',
-					label: '通讯状态'
-				},
-				{
-					prop: 'host_fault',
-					label: '故障'
-				},
-				{
-					prop: 'host_su_temp',
-					label: '供水水温(℃)'
-				},
-				{
-					prop: 'host_re_temp',
-					label: '回水水温(℃)'
-				},
-				{
-					prop: 'host_temp_diff',
-					label: '温差(℃)'
-				}
-			];
-		},
-		/** 拼接新风机更多数据 */
-		packNewTrendColumns(datas) {
-			return [
-				{
-					prop: 'nt_order',
-					label: '编号',
-					width: 60
-				},
-				{
-					prop: 'nt_connect_status',
-					label: '通讯状态'
-				},
-				{
-					prop: 'nt_fault',
-					label: '故障'
-				},
-				{
-					prop: 'nt_in_temp',
-					label: '送风温度(℃)'
-				},
-				{
-					prop: 'nt_in_humidity',
-					label: '送风湿度(℃)'
-				},
-				{
-					prop: 'nt_dew_point',
-					label: '露点(℃)'
-				}
-			];
-		},
-		/** 拼接换热站更多数据 */
-		packHeatExchangeColumns(datas) {
-			return [
-				{
-					prop: 'hex_order',
-					label: '编号',
-					width: 60
-				},
-				{
-					prop: 'hex_connect_status',
-					label: '通讯状态'
-				},
-				{
-					prop: 'hex_fault',
-					label: '故障'
-				},
-				{
-					prop: 'hex_su_temp',
-					label: '供水水温(℃)'
-				},
-				{
-					prop: 'hex_re_temp',
-					label: '回水水温(℃)'
-				},
-				{
-					prop: 'hex_temp_diff',
-					label: '温差(℃)'
-				},
-				{
-					prop: 'hex_pump_status',
-					label: '水泵状态'
-				}
-			];
-		},
-		/** 拼接末端更多数据 */
-		packEndColumns(datas) {
-			return [
-				{
-					prop: 'end_order',
-					label: '编号',
-					width: 60
-				},
-				{
-					prop: 'end_exception_num',
-					label: '通讯异常数量'
-				},
-				{
-					prop: 'end_min_temp',
-					label: '最低室内温度(℃)'
-				},
-				{
-					prop: 'end_min_humidity',
-					label: '最低室内湿度(%)'
-				},
-				{
-					prop: 'end_min_dew_point',
-					label: '最低室内露点(℃)'
-				},
-				{
-					prop: 'end_max_temp',
-					label: '最高室内温度(℃)'
-				},
-				{
-					prop: 'end_max_humidity',
-					label: '最高室内湿度(%)'
-				},
-				{
-					prop: 'end_max_dew_point',
-					label: '最高室内露点(℃)'
-				}
-			];
-		},
 		/** 搜索 */
 		handleQuery(){
 			this.queryParams.page_index = 1;
@@ -747,10 +509,23 @@ export default {
 		handleDerive() {
 			var that = this;
 			that.loading = true;
-			exportToExcel(function() {
+			exportToExcel(this.selection, function() {
 				that.loading = false;
 			});
 		},
+		/** 多选 */
+		handleSelectionChange(val) {
+			// 根据源数据找到对应的项目列表
+			// 先合并选中的数据中的项目名称,再根据项目名称匹配项目数据
+			let projectNames = val.map(v => v.projectName);
+			let nameset = Array.from(new Set(projectNames));
+			let projList = [];
+			nameset.forEach(name => {
+				let project = this.dataSource.find(d => d.projectName === name);
+				projList.push(project);
+			})
+			this.selection = projList;
+		},
 		/** 分页切换 */
 		handleSizeChange(val) {
 			this.queryParams.page_size = val;
@@ -763,19 +538,19 @@ export default {
 		handleClickMore(row, category) {
 			if (category === 'host') {
 				this.dialog.tableData = this.getDatasByRow(row, 'hostCtrl');
-				this.dialog.tableColumns = this.packHostColumns();
+				this.dialog.tableColumns = hostCols;
 				this.dialog.title = '主机控制器';
 			} else if (category === 'newTrend') {
 				this.dialog.tableData = this.getDatasByRow(row, 'newTrendCtrl');
-				this.dialog.tableColumns = this.packNewTrendColumns();
+				this.dialog.tableColumns = newTrendCols;
 				this.dialog.title = '新风机控制器';
 			} else if (category === 'heatExchange') {
 				this.dialog.tableData = this.getDatasByRow(row, 'hex');
-				this.dialog.tableColumns = this.packHeatExchangeColumns();
+				this.dialog.tableColumns = heatExchangeCols;
 				this.dialog.title = '换热站控制器';
 			} else if (category === 'end') {
 				this.dialog.tableData = this.getDatasByRow(row, 'end');
-				this.dialog.tableColumns = this.packEndColumns();
+				this.dialog.tableColumns = endCols;
 				this.dialog.title = '末端控制器';
 			}
 			this.dialog.show = true;

+ 274 - 71
src/js/common.js

@@ -1,74 +1,277 @@
-export const runStatDict = {
-	2: {
-		label: '离线',
-		color: 'lightgray'
-	},
-	1: {
-		label: '在线',
-		color: 'yellowgreen'
-	},
-	0: {
-		label: '未关联',
-		color: 'lightgray'
+// 定义运行状态字典
+export const runStatDict = {
+	0: {
+		label: '离线',
+		color: 'lightgray'
+	},
+	1: {
+		label: '在线',
+		color: 'yellowgreen'
+	},
+	2: {
+		label: '未关联',
+		color: 'lightgray'
+	}
+}
+
+// 定义运行模式字典
+export const runModeDict = {
+	0: {
+		label: '无',
+		color: 'lightgray'
+	},
+	1: {
+		label: '制冷',
+		color: 'darkgreen'
+	},
+	2: {
+		label: '采暖',
+		color: 'orange'
+	},
+	3: {
+		label: '除湿',
+		color: 'rgb(182, 172, 195)'
+	},
+	4: {
+		label: '预热',
+		color: 'yellow'
+	},
+	5: {
+		label: '通风',
+		color: 'rgb(182, 174, 227)'
+	}
+}
+
+// 定义连接状态字典
+export const connectStatDict = {
+	0: {
+		label: '异常',
+		color: 'yellow'
+	},
+	1: {
+		label: '正常',
+		color: 'yellowgreen'
+	}
+}
+
+// 定义故障字典
+export const faultDict = {
+	0: {
+		label: '无',
+		color: 'yellowgreen'
+	},
+	1: {
+		label: '有',
+		color: 'yellow'
+	}
+}
+
+// 定义换热站水泵状态字典
+export const hexPumpStatDict = {
+	0: {
+		label: '停止',
+		color: 'yellow'
+	},
+	1: {
+		label: '运行',
+		color: 'yellowgreen'
+	}
+}
+
+// 运行状态选项定义
+export const runStatOpts = [{
+		label: '在线',
+		value: '1'
+	},
+	{
+		label: '离线',
+		value: '0'
+	}
+]
+
+// 运行模式选项定义
+export const runModeOpts = [{
+		label: '制冷',
+		value: '1'
+	},
+	{
+		label: '采暖',
+		value: '2'
+	},
+	{
+		label: '除湿',
+		value: '3'
+	},
+	{
+		label: '预热',
+		value: '4'
+	},
+	{
+		label: '通风',
+		value: '5'
+	}
+]
+
+// 定义弹窗的主机列
+export const hostCols = [{
+		prop: 'host_order',
+		label: '编号',
+		width: 60
+	},
+	{
+		prop: 'host_connect_status',
+		label: '通讯状态'
+	},
+	{
+		prop: 'host_fault',
+		label: '故障'
+	},
+	{
+		prop: 'host_su_temp',
+		label: '供水水温(℃)'
+	},
+	{
+		prop: 'host_re_temp',
+		label: '回水水温(℃)'
+	},
+	{
+		prop: 'host_temp_diff',
+		label: '温差(℃)'
+	}
+]
+
+// 新风机列
+export const newTrendCols = [{
+		prop: 'nt_order',
+		label: '编号',
+		width: 60
+	},
+	{
+		prop: 'nt_connect_status',
+		label: '通讯状态'
+	},
+	{
+		prop: 'nt_fault',
+		label: '故障'
+	},
+	{
+		prop: 'nt_in_temp',
+		label: '送风温度(℃)'
+	},
+	{
+		prop: 'nt_in_humidity',
+		label: '送风湿度(℃)'
+	},
+	{
+		prop: 'nt_dew_point',
+		label: '露点(℃)'
+	}
+]
+
+// 换热站列
+export const heatExchangeCols = [{
+		prop: 'hex_order',
+		label: '编号',
+		width: 60
+	},
+	{
+		prop: 'hex_connect_status',
+		label: '通讯状态'
+	},
+	{
+		prop: 'hex_fault',
+		label: '故障'
+	},
+	{
+		prop: 'hex_su_temp',
+		label: '供水水温(℃)'
+	},
+	{
+		prop: 'hex_re_temp',
+		label: '回水水温(℃)'
+	},
+	{
+		prop: 'hex_temp_diff',
+		label: '温差(℃)'
+	},
+	{
+		prop: 'hex_pump_status',
+		label: '水泵状态'
+	}
+]
+
+// 末端列
+export const endCols = [{
+		prop: 'end_order',
+		label: '编号',
+		width: 60
+	},
+	{
+		prop: 'end_exception_num',
+		label: '通讯异常数量'
+	},
+	{
+		prop: 'end_min_temp',
+		label: '最低室内温度(℃)'
+	},
+	{
+		prop: 'end_min_humidity',
+		label: '最低室内湿度(%)'
+	},
+	{
+		prop: 'end_min_dew_point',
+		label: '最低室内露点(℃)'
+	},
+	{
+		prop: 'end_max_temp',
+		label: '最高室内温度(℃)'
+	},
+	{
+		prop: 'end_max_humidity',
+		label: '最高室内湿度(%)'
+	},
+	{
+		prop: 'end_max_dew_point',
+		label: '最高室内露点(℃)'
+	}
+]
+
+/**
+ * 函数:通过数组描述执行表达式,得到变量对应的颜色
+ */
+export function getArgsColor(argsList, runMode, val) {
+	let evalString = ""
+	if (argsList.length <= 0) {
+		return evalString
 	}
-}
-
-export const runModeDict = {
-	0: {
-		label: '无',
-		color: 'lightgray'
-	},
-	1: {
-		label: '制冷',
-		color: 'darkgreen'
-	},
-	2: {
-		label: '采暖',
-		color: 'orange'
-	},
-	3: {
-		label: '除湿',
-		color: 'rgb(182, 172, 195)'
-	},
-	4: {
-		label: '预热',
-		color: 'yellow'
-	},
-	5: {
-		label: '通风',
-		color: 'rgb(182, 174, 227)'
-	}
-}
-
-export const connectStatDict = {
-	0: {
-		label: '异常',
-		color: 'yellow'
-	},
-	1: {
-		label: '正常',
-		color: 'yellowgreen'
-	}
-}
-
-export const faultDict = {
-	0: {
-		label: '无',
-		color: 'yellowgreen'
-	},
-	1: {
-		label: '有',
-		color: 'yellow'
-	}
-}
-
-export const hexPumpStatDict = {
-	0: {
-		label: '停止',
-		color: 'yellow'
-	},
-	1: {
-		label: '运行',
-		color: 'yellowgreen'
+	
+	var color = ''
+	// 先找出条件中有模式的数组跟无模式的数组
+	// 先拼接带有模式的数组, 再组合一下无模式的数组
+	let runModeArgs = argsList.filter(args => args.RunMode > 0)
+	let noneRunModeArgs = argsList.filter(args => args.RunMode <= 0)
+	runModeArgs.forEach(args => {
+		evalString += `if (runMode==${args.RunMode}) {color=val${args.Action}${args.Threshold}?'yellow':'yellowgreen'} else `
+	})
+	if (noneRunModeArgs.length > 0) {
+		let tmp = 'if (';
+		noneRunModeArgs.forEach(args => {
+			tmp += `val${args.Action}${args.Threshold}`
+			tmp += '||'
+		})
+		tmp = tmp.substring(0, tmp.length - 2)
+		tmp += `) {color='yellow'} else {color='yellowgreen'}`
+		evalString += tmp
+	} else {
+		evalString = evalString.substring(0, evalString.length - 5)
 	}
+	
+	// if (argsList[0].En === 'nt_dew_point') {
+	// 	console.log(">>> argsList: ", argsList, runMode, val)
+	// 	console.log(">>> evalString: ", evalString)
+	// }
+	
+	// 执行命令
+	eval(evalString)
+	return color
 }

+ 34 - 1
src/js/export.js

@@ -14,7 +14,8 @@ function reset() {
 	config.load = 0
 }
 
-export function exportToExcel(fn) {
+export function exportToExcel(datas, fn) {
+	/*
 	reset()
 	_listAllProjects(function(finished) {
 		// Excel文件名
@@ -51,6 +52,38 @@ export function exportToExcel(fn) {
 		})
 		fn()
 	})
+	*/
+ 
+	// Excel文件名
+	let defaultFilename = 'LINKSEE-智能报表'
+	// 多级表头
+	const multiHeader = [[
+		'项目名称', '盒子名称', '在线状态', '运行模式',
+		'主机', '', '', '', '', '',
+		'新风机', '', '', '', '', '',
+		'换热站', '', '', '', '', '', '',
+		'末端', '', '', '', '', '', '', ''
+	]]
+	// 二级表头
+	let header = [
+		'项目名称', '盒子名称', '在线状态', '运行模式',
+		'编号', '通讯状态', '故障', '供水水温(℃)', '回水水温(℃)', '温差',
+		'编号', '通讯状态', '故障', '送风温度(℃)', '送风湿度(%)', '露点(℃)',
+		'编号', '通讯状态', '故障', '供水水温(℃)', '回水水温(℃)', '温差', '水泵状态',
+		'编号', '通讯异常数量', '最低室内温度(℃)', '最低室内湿度(%)', '最低室内露点(℃)', '最高室内温度(℃)', '最高室内湿度(%)', '最高室内露点(℃)'
+	]
+	// 合并项
+	const merges = ['A1:A2', 'B1:B2', 'C1:C2', 'D1:D2', 'E1:J1', 'K1:P1', 'Q1:W1', 'X1:AE1']
+	// 数据
+	let data = _transferDataToXlsx(datas);
+	Export2ExcelMerge({
+		multiHeader, 
+		header: header, 
+		data: data, 
+		filename: defaultFilename, 
+		merges
+	})
+	fn()
 }
 
 function _listAllProjects(fn) {

+ 47 - 28
src/js/merge.js

@@ -10,9 +10,10 @@ export function expandAllNodes(projects) {
 					let hpStandalone = b.hostCtrl && i < b.hostCtrl.length ? b.hostCtrl[i] : {}
 					let dhStandalone = b.newTrendCtrl && i < b.newTrendCtrl.length ? b.newTrendCtrl[i] : {}
 					let hexStandalone = b.hex && i < b.hex.length ? b.hex[i] : {}
-					let cbStandalone = b.end && i < b.end.length ? b.end[i] : {}
+					let cbStandalone = _calcEndMinAndMaxValue(b.end || [])
 					tableData.push({
-						projectId: p.project_auto_id,
+						// projectId: p.project_auto_id,
+						projectId: index + 1,
 						projectName: p.projectName,
 						boxId: b.box_id,
 						boxName: b.boxName,
@@ -32,7 +33,8 @@ export function expandAllNodes(projects) {
 			})
 		}
 	})
-	return _getStandaloneSpanRows(tableData);
+	// 合并单机
+	return _getStandaloneSpanRows(tableData)
 }
 
 // 合并行数据
@@ -49,7 +51,9 @@ export function mergeTableRows(data, merge) {
 				let flag = false
 				let mergeSolve = merge.slice(0, spliceLocation)
 				mergeSolve.slice(0, spliceLocation).forEach(mergeItem => {
-					if (data[index][mergeItem] == data[index - 1][mergeItem]) {
+					// 需要以盒子名称的维度来合并
+					if (data[index][mergeItem] == data[index - 1][mergeItem] && 
+						data[index]["boxName"] == data[index - 1]["boxName"]) {
 						flag = true
 					}
 				})
@@ -92,18 +96,7 @@ export function mergeTableRows(data, merge) {
 	return data
 }
 
-// 取最大单机数(最多显示2行)
-function _calcMaxStandaloneCnt(box) {
-	let hpStandaloneCnt = box.hostCtrl ? box.hostCtrl.length : 0
-	let dhStandaloneCnt = box.newTrendCtrl ? box.newTrendCtrl.length : 0
-	let hexStandaloneCnt = box.hex ? box.hex.length : 0
-	// 需求:末端最多显示一行,其他类型设备最多两行。如果其他类型设备超过一行,末端需要合并
-	// 所以就无需考虑末端单机的个数
-	let max = Math.max(hpStandaloneCnt, dhStandaloneCnt, hexStandaloneCnt)
-	return Math.min(2, max)
-}
-
-// 计算每条记录末端所占的行数
+// 计算每个单机所占的行数
 function _getStandaloneSpanRows(tableData) {
 	tableData.map((td, index) => {
 		if (index > 0) {
@@ -111,34 +104,26 @@ function _getStandaloneSpanRows(tableData) {
 			// 主机合并
 			if (td.maxCnt > 1 && td.hpCnt < td.maxCnt && previous.hpSpanRows < 2) {
 				td.hpSpanRows = td.maxCnt
-			} else if (index > 0 && previous.hpSpanRows > 1) {
-				td.hpSpanRows = 0
 			} else {
-				td.hpSpanRows = 1
+				td.hpSpanRows = (index > 0 && previous.hpSpanRows > 1) ? 0 : 1
 			}
 			// 新风机合并
 			if (td.maxCnt > 1 && td.dhCnt < td.maxCnt && previous.dhSpanRows < 2) {
 				td.dhSpanRows = td.maxCnt
-			} else if (index > 0 && previous.dhSpanRows > 1) {
-				td.dhSpanRows = 0
 			} else {
-				td.dhSpanRows = 1
+				td.dhSpanRows = (index > 0 && previous.dhSpanRows > 1) ? 0 : 1
 			}
 			// 换热站合并
 			if (td.maxCnt > 1 && td.hexCnt < td.maxCnt && previous.hexSpanRows < 2) {
 				td.hexSpanRows = td.maxCnt
-			} else if (index > 0 && previous.hexSpanRows > 1) {
-				td.hexSpanRows = 0
 			} else {
-				td.hexSpanRows = 1
+				td.hexSpanRows = (index > 0 && previous.hexSpanRows > 1) ? 0 : 1
 			}
 			// 末端合并
 			if (td.maxCnt > 1 && previous.cbSpanRows < 2) {
 				td.cbSpanRows = td.maxCnt
-			} else if (index > 0 && previous.cbSpanRows > 1) {
-				td.cbSpanRows = 0
 			} else {
-				td.cbSpanRows = 1
+				td.cbSpanRows = (index > 0 && previous.cbSpanRows > 1) ? 0 : 1
 			}
 			tableData[index] = td
 		} else {
@@ -152,3 +137,37 @@ function _getStandaloneSpanRows(tableData) {
 	})
 	return tableData
 }
+
+// 取最大单机数(最多显示2行)
+function _calcMaxStandaloneCnt(box) {
+	let hpStandaloneCnt = box.hostCtrl ? box.hostCtrl.length : 0
+	let dhStandaloneCnt = box.newTrendCtrl ? box.newTrendCtrl.length : 0
+	let hexStandaloneCnt = box.hex ? box.hex.length : 0
+	// 需求:末端最多显示一行,其他类型设备最多两行。如果其他类型设备超过一行,末端需要合并
+	// 所以就无需考虑末端单机的个数
+	let max = Math.max(hpStandaloneCnt, dhStandaloneCnt, hexStandaloneCnt)
+	return Math.min(2, max)
+}
+
+// 计算每个盒子下末端的最大值与最小值
+function _calcEndMinAndMaxValue(standalone) {
+	let tmp = {
+		end_exception_num: 0,
+		end_min_temp: 10000,
+		end_min_humidity: 10000,
+		end_min_dew_point: 10000,
+		end_max_temp: 0,
+		end_max_humidity: 0,
+		end_max_dew_point: 0
+	}
+	standalone.forEach(s => {
+		tmp.end_exception_num += s.end_exception_num
+		tmp.end_min_temp = Math.min(tmp.end_min_temp, s.end_min_temp)
+		tmp.end_min_humidity = Math.min(tmp.end_min_humidity, s.end_min_humidity)
+		tmp.end_min_dew_point = Math.min(tmp.end_min_dew_point, s.end_min_dew_point)
+		tmp.end_max_temp = Math.max(tmp.end_max_temp, s.end_max_temp)
+		tmp.end_max_humidity = Math.max(tmp.end_max_humidity, s.end_max_humidity)
+		tmp.end_max_dew_point = Math.max(tmp.end_max_dew_point, s.end_max_dew_point)
+	})
+	return tmp
+}