Lmm 1 yıl önce
ebeveyn
işleme
d1add76f10
3 değiştirilmiş dosya ile 601 ekleme ve 143 silme
  1. 442 143
      src/App.vue
  2. 34 0
      src/components/PopMoreTable.vue
  3. 125 0
      src/dataHandler.js

+ 442 - 143
src/App.vue

@@ -1,28 +1,24 @@
 <template>
 	<div>
-		<el-table :data="tableData" size="mini" border :span-method="objectSpanMethod">
+		<el-table :data="tableData" border :span-method="objectSpanMethod">
 			<el-table-column label="序号" width="60" align="center" fixed>
 				<template slot-scope="scope">
-					<span>{{ queryParams.page_index * queryParams.page_size + scope.$index + 1 }}</span>
+					<span>{{ (queryParams.page_index - 1) * queryParams.page_size + scope.$index + 1 }}</span>
 				</template>
 			</el-table-column>
-			<el-table-column prop="projectName" label="项目名称" align="center" width="200" show-overflow-tooltip fixed />
+			<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">
 				<template slot-scope="scope">
-					<span class="el-table-tag" :style="{'background': runStatMap[scope.row.runStatus].color}">
-						{{ runStatMap[scope.row.runStatus].label }}
-					</span>
+					<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">
 				<template slot-scope="scope">
-					<span class="el-table-tag" :style="{'background': runModeMap[scope.row.runMode].color}">
-						{{ runModeMap[scope.row.runMode].label }}
-					</span>
+					<span class="el-table-tag" :style="{ background: runModeMap[scope.row.runMode].color }">{{ runModeMap[scope.row.runMode].label }}</span>
 				</template>
 			</el-table-column>
-			
+
 			<!-- 主机列 Begin -->
 			<el-table-column label="主机控制器" align="center" width="60">
 				<el-table-column prop="host_order" label="编号" align="center" width="60">
@@ -30,60 +26,153 @@
 						<span>{{ scope.row.host_order || '-' }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column prop="host_connect_status" label="通讯状态" align="center" width="80">
+				<el-table-column prop="host_connect_status" label="通讯状态" align="center" width="100">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: connectStatColor(scope.row.host_connect_status) }">{{ connectStatText(scope.row.host_connect_status) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="host_fault" label="故障" align="center" width="90">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: scope.row.host_fault == 1 ? 'yellowgreen' : 'yellow' }">{{ scope.row.host_fault == 1 ? '无' : '有' }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="host_su_temp" label="供水水温(℃)" align="center" width="120">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: hpTempColor(scope.row.runMode, scope.row.host_su_temp) }">{{ fixedVal(scope.row.host_su_temp) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="host_re_temp" label="回水水温(℃)" align="center" width="120">
 					<template slot-scope="scope">
-						<span>{{ connectStatMap[scope.row.host_connect_status] || '-' }}</span>
+						<span class="el-table-tag" :style="{ background: hpTempColor(scope.row.runMode, scope.row.host_re_temp) }">{{ fixedVal(scope.row.host_re_temp) }}</span>
 					</template>
 				</el-table-column>
-				<el-table-column prop="host_fault" label="故障" align="center" width="80" >
+				<el-table-column prop="host_temp_diff" label="温差" align="center" width="100">
 					<template slot-scope="scope">
-						<span>{{ scope.row.host_fault || '-' }}</span>
+						<span class="el-table-tag" :style="{ background: scope.row.host_temp_diff && scope.row.host_temp_diff <= 5 ? 'yellowgreen' : '' }">
+							{{ fixedVal(scope.row.host_temp_diff) }}
+						</span>
 					</template>
 				</el-table-column>
-				<el-table-column prop="host_su_temp" label="供水水温(℃)" align="center" width="100" />
-				<el-table-column prop="host_re_temp" label="回水水温(℃)" align="center" width="100" />
-				<el-table-column prop="host_temp_diff" label="温差" align="center" width="80" />
 			</el-table-column>
 			<!-- 主机列 End -->
-			
+
 			<!-- 新风机列 Begin -->
 			<el-table-column label="新风机控制器" align="center" width="60">
 				<el-table-column prop="nt_order" label="编号" align="center" width="60" />
-				<el-table-column prop="nt_connect_status" label="通讯状态" align="center" width="80" />
-				<el-table-column prop="nt_fault" label="故障" align="center" width="80" />
-				<el-table-column prop="nt_in_temp" label="送风温度(℃)" align="center" width="100" />
-				<el-table-column prop="nt_in_humidity" label="送风湿度(℃)" align="center" width="100" />
-				<el-table-column prop="nt_dew_point" label="露点(℃)" align="center" width="80" />
+				<el-table-column prop="nt_connect_status" label="通讯状态" align="center" width="100">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: connectStatColor(scope.row.nt_connect_status) }">{{ connectStatText(scope.row.nt_connect_status) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="nt_fault" label="故障" align="center" width="90">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: scope.row.nt_fault == 1 ? 'yellowgreen' : 'yellow' }">{{ scope.row.nt_fault == 1 ? '无' : '有' }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="nt_in_temp" label="送风温度(℃)" align="center" width="120">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: dhTempColor(scope.row.runMode, scope.row.nt_in_temp) }">{{ fixedVal(scope.row.nt_in_temp) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="nt_in_humidity" label="送风湿度(%)" align="center" width="120">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: dhHumiColor(scope.row.runMode, scope.row.nt_in_humidity) }">{{ fixedVal(scope.row.nt_in_humidity) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="nt_dew_point" label="露点(℃)" align="center" width="90">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: dhDewPointColor(scope.row.nt_dew_point) }">{{ fixedVal(scope.row.nt_dew_point) }}</span>
+					</template>
+				</el-table-column>
 			</el-table-column>
 			<!-- 新风机列 End -->
-			
+
 			<!-- 换热站列 Begin -->
 			<el-table-column label="换热站控制器" align="center" width="60">
 				<el-table-column prop="hex_order" label="编号" align="center" width="60" />
-				<el-table-column prop="hex_connect_status" label="通讯状态" align="center" width="80" />
-				<el-table-column prop="hex_fault" label="故障" align="center" width="80" />
-				<el-table-column prop="hex_su_temp" label="供水水温(℃)" align="center" width="100" />
-				<el-table-column prop="hex_re_temp" label="回水水温(℃)" align="center" width="100" />
-				<el-table-column prop="hex_temp_diff" label="温差(℃)" align="center" width="80" />
-				<el-table-column prop="hex_pump_status" label="水泵状态" align="center" width="80" />
-				
+				<el-table-column prop="hex_connect_status" label="通讯状态" align="center" width="100">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: connectStatColor(scope.row.hex_connect_status) }">{{ connectStatText(scope.row.hex_connect_status) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="hex_fault" label="故障" align="center" width="90">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: scope.row.hex_fault == 1 ? 'yellowgreen' : 'yellow' }">{{ scope.row.hex_fault == 1 ? '无' : '有' }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="hex_su_temp" label="供水水温(℃)" align="center" width="120">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: hexTempColor(scope.row.runMode, scope.row.hex_su_temp) }">{{ fixedVal(scope.row.hex_su_temp) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="hex_re_temp" label="回水水温(℃)" align="center" width="120">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: hexTempColor(scope.row.runMode, scope.row.hex_re_temp) }">{{ fixedVal(scope.row.hex_re_temp) }}</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="hex_temp_diff" label="温差(℃)" align="center" width="90">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: scope.row.hex_temp_diff && scope.row.hex_temp_diff <= 5 ? 'yellowgreen' : '' }">
+							{{ fixedVal(scope.row.hex_temp_diff) }}
+						</span>
+					</template>
+				</el-table-column>
+				<el-table-column prop="hex_pump_status" label="水泵状态" align="center" width="100">
+					<template slot-scope="scope">
+						<span class="el-table-tag" :style="{ background: scope.row.hex_pump_status == 0 ? 'yellow' : 'yellowgreen' }">
+							{{ scope.row.hex_pump_status == 0 ? '停止' : '运行' }}
+						</span>
+					</template>
+				</el-table-column>
 			</el-table-column>
 			<!-- 换热站列 End -->
-			
+
 			<!-- 末端列 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_exception_num" label="通讯异常数量" align="center" width="120" />
-				<el-table-column prop="end_min_temp" label="最低室内温度(℃)" align="center" width="120" />
-				<el-table-column prop="end_min_humidity" label="最低室内湿度(℃)" align="center" width="120" />
-				<el-table-column prop="end_min_dew_point" label="最低室内露点(℃)" align="center" width="120" />
-				<el-table-column prop="end_max_temp" label="最高室内温度(℃)" align="center" width="120" />
-				<el-table-column prop="end_max_humidity" label="最高室内湿度(℃)" align="center" width="120" />
-				<el-table-column prop="end_max_dew_point" label="最高室内露点(℃)" align="center" width="120" />
+				<el-table-column prop="end_exception_num" label="通讯异常数量" align="center" width="120">
+					<template slot-scope="scope">
+						<span>{{ scope.row.end_exception_num > 0 ? scope.row.end_exception_num : '无' }}</span>
+					</template>
+				</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>
+					</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>
+					</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>
+					</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>
+					</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>
+					</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>
+							<i v-if="scope.row.cbCnt > 1" class="el-icon-caret-bottom ml10" @click.stop="handleClickMore(scope.row, 'end')"></i>
+						</div>
+					</template>
+				</el-table-column>
 			</el-table-column>
 			<!-- 末端列 End -->
 		</el-table>
 		<el-pagination
+			class="mt10"
 			:current-page="queryParams.page_index"
 			:page-sizes="[10, 20, 30, 40]"
 			:page-size="queryParams.page_size"
@@ -93,12 +182,138 @@
 			@size-change="handleSizeChange"
 			@current-change="handleCurrentChange"
 		></el-pagination>
+		<!-- 更多信息对话框 -->
+		<el-dialog :title="dialog.title" :visible.sync="dialog.show" width="76%">
+			<pop-more-table :visible="dialog.show" :tableData="dialog.tableData" :columns="dialog.tableColumns"></pop-more-table>
+		</el-dialog>
 	</div>
 </template>
 
 <script>
 import axios from 'axios';
+import { expandAllNodes, mergeTableRows } from './dataHandler.js';
+import PopMoreTable from './components/PopMoreTable.vue';
 export default {
+	components: {
+		PopMoreTable
+	},
+	computed: {
+		connectStatColor() {
+			return function(state) {
+				if (this.connectStatMap[state]) {
+					return this.connectStatMap[state].color;
+				} else {
+					return '';
+				}
+			};
+		},
+		connectStatText() {
+			return function(state) {
+				if (this.connectStatMap[state]) {
+					return this.connectStatMap[state].label;
+				} else {
+					return '/';
+				}
+			};
+		},
+		// 主机供水温度与回水温度颜色判定
+		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';
+			};
+		},
+		fixedVal() {
+			return function(val) {
+				if (val == 0) return 0;
+				if (!val) return '/';
+				return parseFloat(val).toFixed(1);
+			};
+		}
+	},
 	data() {
 		return {
 			queryParams: {
@@ -109,8 +324,10 @@ export default {
 				online_status: undefined,
 				run_mode: undefined
 			},
-			tableData: [],
 			total: 0,
+			dataSource: [], // 数据源
+			tableData: [],
+			mergeColums: ['projectName', 'boxName', 'runStatus'],
 			runStatMap: {
 				0: { label: '离线', color: 'lightgray' },
 				1: { label: '在线', color: 'yellowgreen' },
@@ -125,9 +342,16 @@ export default {
 				5: { label: '通风', color: 'rgb(182, 174, 227)' }
 			},
 			connectStatMap: {
-				0: '异常',
-				1: '正常',
+				0: { label: '异常', color: 'yellow' },
+				1: { label: '正常', color: 'yellowgreen' }
 			},
+			dialog: {
+				show: false,
+				title: '',
+				tableColumns: [],
+				tableData: [],
+				totalWidth: 0
+			}
 		};
 	},
 	created() {
@@ -136,7 +360,7 @@ export default {
 	methods: {
 		/** 获取项目列表 */
 		getProjects() {
-			var params =  {
+			var params = {
 				page_index: Math.max(0, this.queryParams.page_index - 1),
 				page_size: this.queryParams.page_size,
 				project_id: this.queryParams.project_id,
@@ -150,9 +374,10 @@ export default {
 					let data = resp.data || {};
 					let result = data.result || {};
 					this.total = result.count;
+					this.dataSource = result.data || [];
 					// 展开所有项目下的设备及单机
-					this.tableData = this.expandAllNodes(result.data || []);
-					let dataSolve = this.mergeTableRow(this.tableData,["projectName","boxName","runStatus","",""]);
+					this.tableData = expandAllNodes(this.dataSource);
+					let dataSolve = mergeTableRows(this.tableData, this.mergeColums);
 					this.tableData = dataSolve;
 					console.log('>>> tableData: ', this.tableData);
 				})
@@ -160,45 +385,155 @@ export default {
 					console.log('请求错误: ', err);
 				});
 		},
-		/** 展开属性结构所有数据 */
-		expandAllNodes(projects) {
-			let tableData = [];
-			projects.forEach(p => {
-				if (Array.isArray(p.boxList)) {
-					p.boxList.forEach(b => {
-						// 继续判断有多少单机,主机、新风机、换热站、末端单机数量取最大值
-						let maxCnt = this.calcMaxStandaloneCnt(b);
-						for (let i = 0; i < maxCnt; i++) {
-							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] : {};
-							
-							tableData.push({
-								projectId: p.project_auto_id,
-								projectName: p.projectName,
-								boxName: b.boxName,
-								runStatus: b.runStatus,
-								runMode: b.runMode,
-								...hpStandalone,
-								...dhStandalone,
-								...hexStandalone,
-								...cbStandalone
-							});
-						}
-					});
+		/** 数据行合并 */
+		objectSpanMethod({ row, column, rowIndex, columnIndex }) {
+			if (columnIndex >= 24) {
+				return { rowspan: row.spanRows, colspan: 1 };
+			}
+			const span = column['property'] + '-span';
+			if (row[span]) {
+				return row[span];
+			}
+		},
+		/** 获取对应设备下的末端列表 */
+		getDatasByRow(row, prop) {
+			let project = this.dataSource.find(p => p.project_auto_id === row.projectId);
+			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: '露点(℃)'
 				}
-			});
-			return tableData;
+			];
 		},
-		/** 取最大单机数 */
-		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 cbStandaloneCnt = box.end ? box.end.length : 0;
-			return Math.max(hpStandaloneCnt, dhStandaloneCnt, hexStandaloneCnt, cbStandaloneCnt);
+		/** 拼接换热站更多数据 */
+		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: '最高室内露点(℃)'
+				}
+			];
 		},
+		/** 分页切换 */
 		handleSizeChange(val) {
 			this.queryParams.page_size = val;
 			this.getProjects();
@@ -207,68 +542,25 @@ export default {
 			this.queryParams.page_index = val;
 			this.getProjects();
 		},
-		// 合并表格
-		mergeTableRow(data,merge){
-			if(!merge || merge.length === 0) {
-				return data;
-			}
-			merge.forEach((m) => {
-				const mList = {};
-				let spliceLocation = merge.indexOf(m);
-				data = data.map((v,index) => {
-					const rowVal = v[m];
-					if(mList[rowVal] && mList[rowVal].newIndex === index){
-						let flag = false;
-						let mergeSolve = merge.slice(0, spliceLocation);
-						mergeSolve.slice(0, spliceLocation).forEach(mergeItem => {
-							if (data[index][mergeItem] == data[index - 1][mergeItem]) {
-								flag = true
-							}
-						})
-						if (m == merge[0]) {
-							flag = true;
-						}
-						if (flag) {
-							mList[rowVal]["num"]++;
-							mList[rowVal]["newIndex"]++;
-							data[mList[rowVal]["index"]][m + "-span"].rowspan++;
-							v[m + "-span"] = {
-								rowspan: 0,
-								colspan: 0,
-							};
-						} else {
-							mList[rowVal] = {
-								num: 1,
-								index: index,
-								newIndex: index + 1,
-							};
-							v[m + "-span"] = {
-								rowspan: 1,
-								colspan: 1,
-							};
-						}
-					}else {
-						mList[rowVal] = {
-							num: 1,
-							index: index,
-							newIndex: index + 1,
-						};
-						v[m + "-span"] = {
-							rowspan: 1,
-							colspan: 1,
-						};
-					}
-					return v;
-				});
-			});
-			return data;
-		},
-		
-		objectSpanMethod({ row, column, rowIndex, columnIndex }) {
-			const span = column["property"] + "-span";
-			if(row[span]) {
-				return row[span];
+		handleClickMore(row, category) {
+			if (category === 'host') {
+				this.dialog.tableData = this.getDatasByRow(row, 'hostCtrl');
+				this.dialog.tableColumns = this.packHostColumns();
+				this.dialog.title = '主机控制器';
+			} else if (category === 'newTrend') {
+				this.dialog.tableData = this.getDatasByRow(row, 'newTrendCtrl');
+				this.dialog.tableColumns = this.packNewTrendColumns();
+				this.dialog.title = '新风机控制器';
+			} else if (category === 'heatExchange') {
+				this.dialog.tableData = this.getDatasByRow(row, 'hex');
+				this.dialog.tableColumns = this.packHeatExchangeColumns();
+				this.dialog.title = '换热站控制器';
+			} else if (category === 'end') {
+				this.dialog.tableData = this.getDatasByRow(row, 'end');
+				this.dialog.tableColumns = this.packEndColumns();
+				this.dialog.title = '末端控制器';
 			}
+			this.dialog.show = true;
 		}
 	}
 };
@@ -277,9 +569,16 @@ export default {
 <style>
 .el-table-tag {
 	/* width: 64px; */
-	padding: 4px 14px;
+	padding: 4px 12px;
 	color: #333;
 	/* border-radius: 2px; */
 	font-size: 12px;
 }
+
+.ml10 {
+	margin-left: 10px;
+}
+.mt10 {
+	margin-top: 10px;
+}
 </style>

+ 34 - 0
src/components/PopMoreTable.vue

@@ -0,0 +1,34 @@
+<template>
+	<div>
+		<el-table :data="tableData" size="mini" border>
+			<el-table-column 
+				v-for="(col, index) in columns" 
+				:key="index" 
+				:prop="col.prop" 
+				:label="col.label" 
+				:width="col.width ? col.width : ''" 
+				align="center"
+			></el-table-column>
+		</el-table>
+	</div>
+</template>
+
+<script>
+export default {
+	name: 'PopMoreTable',
+	props: {
+		visible: {
+			type: Boolean,
+			default: false
+		},
+		tableData: {
+			type: Array,
+			default: () => []
+		},
+		columns: {
+			type: Array,
+			default: () => []
+		}
+	}
+};
+</script>

+ 125 - 0
src/dataHandler.js

@@ -0,0 +1,125 @@
+// 展开所有数据
+export function expandAllNodes(projects) {
+	let tableData = []
+	projects.forEach(p => {
+		if (Array.isArray(p.boxList)) {
+			p.boxList.forEach(b => {
+				// 继续判断有多少单机,主机、新风机、换热站、末端单机数量取最大值
+				let maxCnt = _calcMaxStandaloneCnt(b)
+				for (let i = 0; i < maxCnt; i++) {
+					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] : {}
+					tableData.push({
+						projectId: p.project_auto_id,
+						projectName: p.projectName,
+						boxId: b.box_id,
+						boxName: b.boxName,
+						runStatus: b.runStatus,
+						runMode: b.runMode,
+						hpCnt: b.hostCtrl && b.hostCtrl.length,
+						dhCnt: b.newTrendCtrl && b.newTrendCtrl.length,
+						hexCnt: b.hex && b.hex.length,
+						cbCnt: b.end && b.end.length,
+						maxCnt,
+						...hpStandalone,
+						...dhStandalone,
+						...hexStandalone,
+						...cbStandalone
+					})
+				}
+			})
+		}
+	})
+	return _getEndSpanRows(tableData);
+}
+
+// 合并行数据
+export function mergeTableRows(data, merge) {
+	if (!merge || merge.length === 0) {
+		return data
+	}
+	merge.forEach(m => {
+		const mList = {}
+		let spliceLocation = merge.indexOf(m)
+		data = data.map((v, index) => {
+			const rowVal = v[m]
+			if (mList[rowVal] && mList[rowVal].newIndex === index) {
+				let flag = false
+				let mergeSolve = merge.slice(0, spliceLocation)
+				// console.log(">>> mergeSolve: ", mergeSolve)
+				mergeSolve.slice(0, spliceLocation).forEach(mergeItem => {
+					// console.log(">>> mergeItem: ", mergeItem)
+					// console.log(">>> data[index][mergeItem]: ", data[index][mergeItem])
+					// console.log(">>> data[index - 1][mergeItem]: ", data[index - 1][mergeItem])
+					if (data[index][mergeItem] == data[index - 1][mergeItem]) {
+						flag = true
+					}
+				})
+				if (m == merge[0]) {
+					flag = true
+				}
+				if (flag) {
+					mList[rowVal]["num"]++
+					mList[rowVal]["newIndex"]++
+					data[mList[rowVal]["index"]][m + "-span"].rowspan++
+					v[m + "-span"] = {
+						rowspan: 0,
+						colspan: 0,
+					}
+				} else {
+					mList[rowVal] = {
+						num: 1,
+						index: index,
+						newIndex: index + 1,
+					}
+					v[m + "-span"] = {
+						rowspan: 1,
+						colspan: 1,
+					}
+				}
+			} else {
+				mList[rowVal] = {
+					num: 1,
+					index: index,
+					newIndex: index + 1,
+				}
+				v[m + "-span"] = {
+					rowspan: 1,
+					colspan: 1,
+				}
+			}
+			return v
+		})
+	})
+	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 _getEndSpanRows(tableData) {
+	tableData.map((td, index) => {
+		let previous = tableData[index - 1]
+		if (td.maxCnt > 1 && previous.spanRows < 2) {
+			td.spanRows = td.maxCnt
+		} else if (index > 0 && previous.spanRows > 1) {
+			td.spanRows = 0
+		} else {
+			td.spanRows = 1
+		}
+		tableData[index] = td
+		return td
+	})
+	return tableData
+}