Merge branch 'temp' of http://123.60.103.97:3000/xuziqiang/SaaS-lib into temp
This commit is contained in:
Binary file not shown.
Binary file not shown.
10
hx-ai-intelligent/src/api/coldAndHeatSources.ts
Normal file
10
hx-ai-intelligent/src/api/coldAndHeatSources.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { BASE_URL } from './index';
|
||||
|
||||
export enum coldAndHeatSourcesApi {
|
||||
getUserWaterPumpState = `${BASE_URL}/api/tempSysCtrl/getUserWaterPumpState`, // 用户水泵查询最新状态
|
||||
getLandWaterPumpState = `${BASE_URL}/api/tempSysCtrl/getLandWaterPumpState`, // 地源水泵查询最新状态
|
||||
getLandHeatPumpState = `${BASE_URL}/api/tempSysCtrl/getLandHeatPumpState`, //螺旋式地源热泵 - 查询最新状态
|
||||
getEnergyTankState = `${BASE_URL}/api/tempSysCtrl/getEnergyTankState`, //冷热水双蓄储能罐 - 查询最新状态
|
||||
getCoolPumpState = `${BASE_URL}/api/tempSysCtrl/getCoolPumpState`, //释冷泵 - 查询最新状态
|
||||
getAirHeatPumpState = `${BASE_URL}/api/tempSysCtrl/getAirHeatPumpState`, //空气源热泵 - 查询最新状态
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
const prefix = '/carbon-smart/api';
|
||||
// 通风系统相关接口
|
||||
export enum waterSys {
|
||||
// 首页 ====================================================
|
||||
|
||||
// 获得污水池状态
|
||||
getPool1 = prefix + '/waterSysCtrl/getSewagePoolState',
|
||||
// 获得阀门状态
|
||||
@@ -10,4 +12,15 @@ export enum waterSys {
|
||||
getPool2 = prefix + '/waterSysCtrl/getCollectPoolState',
|
||||
// 获得水泵状态
|
||||
getPump = prefix + '/waterSysCtrl/getPumpState',
|
||||
// 提交场景模式修改
|
||||
submitList = prefix + '/waterSysCtrl/changeToSceneMode',
|
||||
|
||||
// 计划 tab1 ===============================================
|
||||
submitTableData = prefix + '/waterSysCtrl/refreshPlanStatus',
|
||||
|
||||
// 日志 tab2 ===============================================
|
||||
// 获得设备日志
|
||||
getLog = prefix + '/waterSysInfo/pageAbleLog',
|
||||
// 获得日志详情
|
||||
getLogDetail = prefix + '/waterSysInfo/fullLog',
|
||||
}
|
||||
|
||||
@@ -119,25 +119,25 @@ const equipmentControl = {
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// path: 'waterSystem',
|
||||
// name: 'waterSystem',
|
||||
// meta: { title: '给排水系统', hideChildren: true, icon: 'shebeiqunkong' },
|
||||
// component: Base,
|
||||
// redirect: { name: 'waternControlSystemIndex' },
|
||||
// children: [
|
||||
// {
|
||||
// path: 'index',
|
||||
// name: 'waternControlSystemIndex',
|
||||
// component: () => import('/@/view/equipmentControl/waterSystem/index.vue'),
|
||||
// meta: {
|
||||
// title: '给排水系统',
|
||||
// keepAlive: false,
|
||||
// // backApi: [],
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
path: 'waterSystem',
|
||||
name: 'waterSystem',
|
||||
meta: { title: '给排水系统', hideChildren: true, icon: 'shebeiqunkong' },
|
||||
component: Base,
|
||||
redirect: { name: 'waternControlSystemIndex' },
|
||||
children: [
|
||||
{
|
||||
path: 'index',
|
||||
name: 'waternControlSystemIndex',
|
||||
component: () => import('/@/view/equipmentControl/waterSystem/index.vue'),
|
||||
meta: {
|
||||
title: '给排水系统',
|
||||
keepAlive: false,
|
||||
// backApi: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'planToAdd',
|
||||
name: 'planToAdd',
|
||||
|
||||
@@ -10,10 +10,43 @@ import FileSaver from 'file-saver';
|
||||
// export default exportExcel;
|
||||
|
||||
// 导出excel文件
|
||||
export function exportExcel (tableColumns,data,fillName,isMerge,start,end) {
|
||||
/**
|
||||
*
|
||||
* @param {*} tableColumns 表头
|
||||
* @param {*} data 数据
|
||||
* @param {*} fillName 文件名
|
||||
* @param {*} isMerge 是否合并单元格
|
||||
* @param {*} firstKey 第一个字段的key,用来判断序号列是否合并
|
||||
* @param {*} start 合并单元格开始列
|
||||
* @param {*} end 合并单元格结束列
|
||||
* @returns
|
||||
*/
|
||||
export function exportExcel (tableColumns,data,fillName,isMerge = false, firstKey = '',start = 0, end = 0) {
|
||||
debugger
|
||||
if (!data || data.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (isMerge) {
|
||||
// 需要合并序号
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
// 自定义单元格内容,这里返回序号
|
||||
if (i == 0) {
|
||||
data[i].index = 1;
|
||||
// return 1;
|
||||
} else if (data[i - 1][firstKey] == data[i][firstKey]) {
|
||||
data[i].index = data[i - 1].index;
|
||||
// return data.value[index].index;
|
||||
} else {
|
||||
data[i].index = data[i - 1].index + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 不需要合并序号
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
data[i].index = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建工作簿
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
// 添加工作表,名为sheet1
|
||||
@@ -33,27 +66,22 @@ export function exportExcel (tableColumns,data,fillName,isMerge,start,end) {
|
||||
columns.push({
|
||||
header: tableColumns[i].title,
|
||||
key: tableColumns[i].dataIndex,
|
||||
width: tableColumns[i].width / 5,
|
||||
width: tableColumns[i].width ? tableColumns[i].width / 5 : 20,
|
||||
});
|
||||
}
|
||||
}
|
||||
//传入的数据
|
||||
const list = data;
|
||||
|
||||
//格式化数据
|
||||
const datas = formatJson(filterVal, list);
|
||||
|
||||
// // 导出数据列表
|
||||
// const data = [
|
||||
// { 姓名: '张三', 年龄: 18, 身高: 175, 体重: 74 },
|
||||
// { 姓名: '李四', 年龄: 22, 身高: 177, 体重: 84 },
|
||||
// { 姓名: '王五', 年龄: 53, 身高: 155, 体重: 64 },
|
||||
// ];
|
||||
// 获取表头所有键
|
||||
// const headers = Object.keys(data[0]);
|
||||
|
||||
// 获取表头
|
||||
sheet1.columns = columns;
|
||||
// // 将标题写入第一行
|
||||
// sheet1.addRow(tHeader);
|
||||
|
||||
// 将数据写入工作表
|
||||
datas.forEach((row) => {
|
||||
// const values = Object.values(row);
|
||||
@@ -62,80 +90,30 @@ export function exportExcel (tableColumns,data,fillName,isMerge,start,end) {
|
||||
|
||||
// 判断是否合并单元格
|
||||
if (isMerge) {
|
||||
debugger
|
||||
// 遍历列,从第一列到 end 列
|
||||
// 遍历列,从 start 列到 end 列
|
||||
for (let col = start; col <= end; col++) {
|
||||
// let mergeStartRow = 2; // 每次新列开始时,重置起始行
|
||||
for (let row = 3; row <= datas.length + 1; row++) {
|
||||
const currentCellValue = sheet1.getCell(row, col).value;
|
||||
const previousCellValue = sheet1.getCell(row - 1, col).value;
|
||||
|
||||
let currentCellValue_1 = ''
|
||||
let previousCellValue_1 = ''
|
||||
// 从第二列开始就要看前一列是否已经合并
|
||||
let isMerged = true
|
||||
if (col > 1) {
|
||||
currentCellValue_1 = sheet1.getCell(row, col-1).value;
|
||||
previousCellValue_1 = sheet1.getCell(row - 1, col-1).value;
|
||||
isMerged = ifMerged(sheet1,row - 1, col-1,row, col-1)
|
||||
}
|
||||
|
||||
if (currentCellValue === previousCellValue && currentCellValue_1 === previousCellValue_1) {
|
||||
// 当前列有变化,检查是否需要合并前面的单元格
|
||||
// if (mergeStartRow < row - 1) {
|
||||
// 只有在前面的行有超过1个时才合并
|
||||
sheet1.mergeCells(row, col, row - 1, col);
|
||||
// }
|
||||
// 更新起始行
|
||||
// mergeStartRow = row;
|
||||
if (currentCellValue === previousCellValue && isMerged) {
|
||||
// 检查是上边需要合并的单元格是否已经合并
|
||||
const mergeInfo = getMergeInfo(sheet1, row - 1, col)
|
||||
if ( mergeInfo.isMerged ) {
|
||||
sheet1.unMergeCells( mergeInfo.startRow, col, row - 1, col);
|
||||
sheet1.mergeCells(mergeInfo.startRow, col, row, col);
|
||||
} else {
|
||||
sheet1.mergeCells(row, col, row - 1, col);
|
||||
}
|
||||
}
|
||||
|
||||
// // 如果是最后一行,检查是否需要合并
|
||||
// if (row === datas.length + 1 && mergeStartRow < row) {
|
||||
// sheet1.mergeCells(mergeStartRow, col, row, col);
|
||||
// }
|
||||
}
|
||||
}
|
||||
// 从第一列开始逐列检查,前提是前面的列已合并
|
||||
// for (let col = start; col <= end; col++) {
|
||||
// let startRow = 2; // 从数据开始的第二行开始检查
|
||||
// let endRow = 2;
|
||||
|
||||
// while (endRow <= sheet1.rowCount) {
|
||||
// let currentValue = sheet1.getCell(endRow, col).value;
|
||||
// let prevValue = sheet1.getCell(endRow - 1, col).value;
|
||||
|
||||
// // 如果当前值等于前一个值,且前面的列是合并的,则继续合并
|
||||
// if (currentValue === prevValue) {
|
||||
// let mergeAllowed = true;
|
||||
// for (let prevCol = 1; prevCol < col; prevCol++) {
|
||||
// let range = sheet1.getCell(endRow - 1, prevCol).master;
|
||||
// if (range && range.row !== startRow) {
|
||||
// mergeAllowed = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (mergeAllowed) {
|
||||
// endRow++;
|
||||
// } else {
|
||||
// // 不允许合并,直接移动起始行到当前行
|
||||
// startRow = endRow;
|
||||
// endRow++;
|
||||
// }
|
||||
// } else {
|
||||
// // 当前值不等于前一个值或合并不允许,进行合并操作
|
||||
// if (startRow < endRow - 1) {
|
||||
// sheet1.mergeCells(startRow, col, endRow - 1, col);
|
||||
// }
|
||||
// startRow = endRow;
|
||||
// endRow++;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 处理最后一段相同的单元格
|
||||
// if (startRow < endRow - 1) {
|
||||
// sheet1.mergeCells(startRow, col, endRow - 1, col);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -208,3 +186,43 @@ function formatJson (filterVal, jsonData) {
|
||||
return jsonData.map((v) => filterVal.map((j) => v[j]));
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取给定行和列的单元格是否为合并单元格,并返回合并起始行
|
||||
* @param {Worksheet} worksheet - ExcelJS 工作表对象
|
||||
* @param {number} row - 单元格的行号 (从 1 开始)
|
||||
* @param {number} col - 单元格的列号 (从 1 开始)
|
||||
* @returns {Object} - 返回一个对象,包含 isMerged 和 startRow 属性
|
||||
*/
|
||||
function getMergeInfo(worksheet, row, col) {
|
||||
// 遍历所有的合并范围
|
||||
for (const mergeRange in worksheet._merges) {
|
||||
if (worksheet._merges.hasOwnProperty(mergeRange)) {
|
||||
const { top, left, bottom, right } = worksheet._merges[mergeRange];
|
||||
|
||||
// 检查行列是否在当前合并范围内
|
||||
if (row >= top && row <= bottom && col >= left && col <= right) {
|
||||
return { isMerged: true, startRow: top }; // 找到合并范围,返回合并信息
|
||||
}
|
||||
}
|
||||
}
|
||||
return { isMerged: false, startRow: null }; // 单元格不在任何合并范围内
|
||||
}
|
||||
|
||||
|
||||
// 函数:检查两个单元格是否属于同一个合并区域
|
||||
function ifMerged(worksheet, row1, col1, row2, col2) {
|
||||
const merges = worksheet._merges; // 获取所有的合并区域
|
||||
for (let mergeAddress in merges) {
|
||||
const mergeRange = merges[mergeAddress];
|
||||
const { top, left, bottom, right } = mergeRange;
|
||||
|
||||
const isCell1InRange = (row1 >= top && row1 <= bottom && col1 >= left && col1 <= right);
|
||||
const isCell2InRange = (row2 >= top && row2 <= bottom && col2 >= left && col2 <= right);
|
||||
|
||||
if (isCell1InRange && isCell2InRange) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</a-form>
|
||||
</a-card>
|
||||
</div>
|
||||
<div style="display: flex; margin-top: 20px; height: calc(84% - 20px)">
|
||||
<div style="display: flex; margin-top: 20px; height: calc(85% - 20px)">
|
||||
<div class="detailTable">
|
||||
<ns-view-list-table v-bind="tableConfig" :model="data" ref="mainRef" :scroll="{ x: 1280 }">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
@@ -523,6 +523,7 @@
|
||||
{
|
||||
title: '更新时间',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
dataIndex: 'updateTime',
|
||||
},
|
||||
],
|
||||
@@ -826,7 +827,7 @@
|
||||
padding: 16px;
|
||||
}
|
||||
.search {
|
||||
height: 16%;
|
||||
height: 15%;
|
||||
}
|
||||
.detailTable {
|
||||
width: 70%;
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
<a-button type="primary" ghost style="margin-left: 6px" @click="reset">重置</a-button>
|
||||
</span>
|
||||
</template>
|
||||
<template #bodyCell="{ column, text }">
|
||||
<span>{{ text || '-' }}</span>
|
||||
</template>
|
||||
</a-table>
|
||||
<!-- <a-pagination
|
||||
:current="queryParams.pageNum"
|
||||
|
||||
@@ -146,7 +146,7 @@ export const drawerColumns = [
|
||||
dataIndex: 'dataSources',
|
||||
},
|
||||
];
|
||||
export const setFactorConfig = (orgId) => {
|
||||
export const setFactorConfig = (orgId, treeId, tableId) => {
|
||||
return ref({
|
||||
api: carbonEmissionFactorLibrary.getTableList,
|
||||
params: { orgId, pageNum: 1, pageSize: 9999, emissionList: [0] },
|
||||
@@ -155,7 +155,8 @@ export const setFactorConfig = (orgId) => {
|
||||
icon: 'deviceType',
|
||||
title: '排放分类',
|
||||
},
|
||||
params: { orgId},
|
||||
selectedKeys: treeId,
|
||||
params: { orgId },
|
||||
dynamicParams: { emissionList: 'id[]' },
|
||||
defaultExpandAll: true,
|
||||
// checkable:true,
|
||||
@@ -175,7 +176,10 @@ export const setFactorConfig = (orgId) => {
|
||||
],
|
||||
},
|
||||
},
|
||||
rowSelection: { type: 'radio' },
|
||||
rowSelection: {
|
||||
type: 'radio',
|
||||
selectedRowKeys: tableId,
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
title: '序号',
|
||||
|
||||
@@ -297,9 +297,7 @@
|
||||
indexName: '能源种类', // 匹配类型字段
|
||||
message: [
|
||||
{ label: '1、若必填项未填写,则不能进行导入操作' },
|
||||
{ label: `2、当重复时,则更新数据。` },
|
||||
{ label: '3、数据将从模版的第五行进行导入。' },
|
||||
{ label: '4、文件导入勿超过5MB。' },
|
||||
{ label: '2、文件导入勿超过5MB。' },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -21,20 +21,22 @@
|
||||
:auto-expand-parent="autoExpandParent"
|
||||
:selectedKeys="selectedKeys"
|
||||
:tree-data="gData"
|
||||
:show-line="{ showLeafIcon: false }"
|
||||
show-line
|
||||
@expand="onExpand"
|
||||
@select="onSelect"
|
||||
style="padding: 0 16px !important">
|
||||
<template #title="data">
|
||||
<span
|
||||
<!-- <span
|
||||
v-if="data.energyType && searchValue && data.energyType.indexOf(searchValue) > -1">
|
||||
{{ data.energyType.substring(0, data.energyType.indexOf(searchValue)) }}
|
||||
<span style="color: #f50">{{ searchValue }}</span>
|
||||
{{
|
||||
data.energyType.substring(data.energyType.indexOf(searchValue) + searchValue.length)
|
||||
}}
|
||||
</span>
|
||||
<span v-else>{{ data.energyType }}</span>
|
||||
</span> -->
|
||||
<span v-if="data.code">{{ truncatedName(data.energyType + data.code) }}</span>
|
||||
<span v-else>{{ truncatedName(data.energyType) }}</span>
|
||||
</template>
|
||||
</a-tree>
|
||||
</div>
|
||||
@@ -130,8 +132,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch, toRaw, defineExpose } from 'vue';
|
||||
import type { TreeProps } from 'ant-design-vue';
|
||||
import { ref, watch, toRaw, defineExpose, nextTick } from 'vue';
|
||||
import { message, TreeProps } from 'ant-design-vue';
|
||||
import { Pagination, Modal } from 'ant-design-vue';
|
||||
import { columns, drawerColumns } from '../config';
|
||||
import { http } from '/nerv-lib/util/http';
|
||||
@@ -225,6 +227,12 @@
|
||||
expandedKeys.value = keys;
|
||||
autoExpandParent.value = false;
|
||||
};
|
||||
const truncatedName = (name) => {
|
||||
if (name.length > 8) {
|
||||
return name.substring(0, 8) + '...';
|
||||
}
|
||||
return name;
|
||||
};
|
||||
// 被选中的树节点
|
||||
const energyType = ref();
|
||||
const onSelect = (selectedKey: string[], info: any) => {
|
||||
@@ -245,16 +253,22 @@
|
||||
return null;
|
||||
})
|
||||
.filter((item, i, self) => item && self.indexOf(item) === i);
|
||||
expandedKeys.value = expanded;
|
||||
// expandedKeys.value = expanded;
|
||||
searchValue.value = value;
|
||||
autoExpandParent.value = true;
|
||||
});
|
||||
// 查询因子分类树数据
|
||||
const onSearchTreeData = () => {};
|
||||
const getTreeQuery = ref({
|
||||
orgId: orgId.value,
|
||||
});
|
||||
const onSearchTreeData = () => {
|
||||
getTreeQuery.value.energyType = searchValue.value;
|
||||
getTreeData();
|
||||
};
|
||||
const statsId = ref();
|
||||
// 获取因子分类树数据
|
||||
const getTreeData = () => {
|
||||
fetch(quickCalculation.carbonQuickTree, { orgId: orgId.value }).then((res) => {
|
||||
fetch(quickCalculation.carbonQuickTree, getTreeQuery.value).then((res) => {
|
||||
gData.value = res.data;
|
||||
energyType.value = gData.value[0].children[0].id;
|
||||
statsId.value = gData.value[0].children[0].id;
|
||||
@@ -271,9 +285,12 @@
|
||||
});
|
||||
const tableData = ref([]);
|
||||
const emissionSources = ref();
|
||||
const treeId = ref([]);
|
||||
const tableId = ref([]);
|
||||
const tableConfig = ref({
|
||||
title: '排放因子库',
|
||||
api: quickCalculation.queryCarbonEmissionPage,
|
||||
rowSelection: null,
|
||||
params: {
|
||||
orgId,
|
||||
energyType,
|
||||
@@ -306,12 +323,6 @@
|
||||
className: 'carbonEmissionSuffix',
|
||||
dataIndex: 'carbonEmissionSuffix',
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
className: 'updateTime',
|
||||
dataIndex: 'updateTime',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '启用时间',
|
||||
className: 'startTime',
|
||||
@@ -327,6 +338,12 @@
|
||||
className: 'dataSources',
|
||||
dataIndex: 'dataSources',
|
||||
},
|
||||
{
|
||||
title: '更新时间',
|
||||
className: 'updateTime',
|
||||
dataIndex: 'updateTime',
|
||||
ellipsis: true,
|
||||
},
|
||||
],
|
||||
columnActions: {
|
||||
title: '操作',
|
||||
@@ -342,8 +359,10 @@
|
||||
formState.value.factorId = record.factorId;
|
||||
text.value = '编辑';
|
||||
visible.value = true;
|
||||
emissionSources.value = record.factorId; //todo
|
||||
queryData.value.factorId = emissionSources.value; //todo
|
||||
emissionSources.value = record.factorId;
|
||||
queryData.value.factorId = emissionSources.value;
|
||||
treeId.value = [record.treeId];
|
||||
tableId.value = [record.factorId];
|
||||
getNewTable();
|
||||
},
|
||||
},
|
||||
@@ -450,6 +469,7 @@
|
||||
selectedRowKeys.value = [];
|
||||
formState.value = {};
|
||||
formRef.value.resetFields();
|
||||
message.success('操作成功!');
|
||||
mainRef.value?.nsTableRef.reload();
|
||||
});
|
||||
} else {
|
||||
@@ -458,6 +478,7 @@
|
||||
selectedRowKeys.value = [];
|
||||
formState.value = {};
|
||||
formRef.value.resetFields();
|
||||
message.success('操作成功!');
|
||||
mainRef.value?.nsTableRef.reload();
|
||||
});
|
||||
}
|
||||
@@ -487,9 +508,15 @@
|
||||
};
|
||||
const openVisible = ref(false);
|
||||
const setFactorRef = ref();
|
||||
const config = setFactorConfig(orgId.value);
|
||||
const config = setFactorConfig(orgId.value, treeId.value, tableId.value);
|
||||
const selectFactor = () => {
|
||||
openVisible.value = true;
|
||||
nextTick(() => {
|
||||
setFactorRef.value.nsTableRef.params.emissionList = treeId.value;
|
||||
setFactorRef.value.nsTableRef.treeElRef.selectedKeys = treeId.value;
|
||||
setFactorRef.value.nsTableRef.rowSelection.selectedRowKeys = tableId.value;
|
||||
setFactorRef.value.nsTableRef.reload();
|
||||
});
|
||||
};
|
||||
const btnClick = () => {
|
||||
let selectRowKeys = setFactorRef.value?.nsTableRef.tableState.selectedRowKeys;
|
||||
@@ -624,6 +651,25 @@
|
||||
:deep(.ant-modal-footer) {
|
||||
border-top: 10px solid #f0f0f0 !important;
|
||||
}
|
||||
:deep(.ns-table-container) {
|
||||
background: white;
|
||||
}
|
||||
:deep(.ns-part-tree) {
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0px 2px 20px rgb(69 123 234 / 20%);
|
||||
}
|
||||
:deep(.ns-table-search) {
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0px 2px 20px rgb(69 123 234 / 20%);
|
||||
}
|
||||
:deep(.ns-table-main) {
|
||||
margin-top: 20px !important;
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0px 2px 20px rgb(69 123 234 / 20%);
|
||||
}
|
||||
</style>
|
||||
<style scoped>
|
||||
th.column-money,
|
||||
|
||||
@@ -1193,11 +1193,11 @@
|
||||
return regex.test(filename);
|
||||
};
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
const filename = file.name;
|
||||
if (!isValidFileName(filename)) {
|
||||
message.error('文件名不符合规则');
|
||||
return Upload.LIST_IGNORE; // 阻止文件上传
|
||||
}
|
||||
// const filename = file.name;
|
||||
// if (!isValidFileName(filename)) {
|
||||
// message.error('文件名不符合规则');
|
||||
// return Upload.LIST_IGNORE; // 阻止文件上传
|
||||
// }
|
||||
return false;
|
||||
};
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
@@ -1284,14 +1284,16 @@
|
||||
NsMessage.warn('请选择因子');
|
||||
return;
|
||||
} else {
|
||||
if (newTableData.value.emissionFactorUnits === carbonEmission.value) {
|
||||
if (newTableData.value[0].emissionFactorUnits === carbonEmission.value) {
|
||||
newTableData.value = setFactorRef.value?.nsTableRef.tableState.selectedRows;
|
||||
selectedRowKeysEdit.value = setFactorRef.value?.nsTableRef.tableState.selectedRowKeys;
|
||||
editFormState.value.emissionFactors = newTableData.value[0].emissionFactors;
|
||||
editFormState.value.factorId = selectedRowKeysEdit.value[0];
|
||||
openVisible.value = false;
|
||||
} else {
|
||||
NsMessage.warn('因子值单位不统一,请重新选择!');
|
||||
NsMessage.warn(
|
||||
'因子值单位与当前因子值单位(' + carbonEmission.value + ')不统一,请重新选择!',
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,11 +39,7 @@
|
||||
placeholder="请输入报告名称" />
|
||||
</a-form-item>
|
||||
<a-form-item ref="name" label="报告年度" name="reportYear">
|
||||
<a-date-picker
|
||||
v-model:value="formState.reportYear"
|
||||
@openChange="openChange"
|
||||
picker="year"
|
||||
valueFormat="YYYY" />
|
||||
<a-date-picker v-model:value="formState.reportYear" picker="year" valueFormat="YYYY" />
|
||||
</a-form-item>
|
||||
<a-form-item ref="name" label="适用标准" name="genericStandard">
|
||||
<a-input
|
||||
@@ -64,7 +60,6 @@
|
||||
<a-form-item ref="name" label="报告范围" name="reportScope">
|
||||
<a-range-picker
|
||||
v-model:value="formState.reportScope"
|
||||
:defaultPickerValue="defaultPickerValue"
|
||||
picker="month"
|
||||
:disabledDate="disabledDate"
|
||||
valueFormat="YYYY-MM" />
|
||||
@@ -111,20 +106,22 @@
|
||||
const selectChange = (value) => {
|
||||
formState.value.reportScope = '';
|
||||
};
|
||||
const defaultPickerValue = ref([
|
||||
dayjs('2020'), // 默认开始日期
|
||||
dayjs('2020'), // 默认结束日期
|
||||
]);
|
||||
const openChange = (status) => {
|
||||
if (status === false) {
|
||||
if (formState.value.reportYear) {
|
||||
defaultPickerValue.value = [
|
||||
dayjs(formState.value.reportYear),
|
||||
dayjs(formState.value.reportYear),
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
// const defaultPickerValue = ref([]);
|
||||
// const open = ref(false);
|
||||
// const openChange = (status) => {
|
||||
// debugger;
|
||||
// open.value = status;
|
||||
// if (formState.value.reportYear) {
|
||||
// defaultPickerValue.value = [
|
||||
// dayjs(formState.value.reportYear),
|
||||
// dayjs(formState.value.reportYear),
|
||||
// ];
|
||||
// open.value = false;
|
||||
// nextTick(() => {
|
||||
// open.value = status; // 重新打开日期选择框
|
||||
// });
|
||||
// }
|
||||
// };
|
||||
// 定义form表单的必填
|
||||
const rules: Record<string, Rule[]> = {
|
||||
reportName: [{ required: true, message: '请输入报告名称', trigger: 'change' }],
|
||||
|
||||
@@ -417,7 +417,6 @@
|
||||
const editData = (record) => {
|
||||
open.value = true;
|
||||
if (record.isLastYear !== undefined) {
|
||||
formState.value.ids = [record.id];
|
||||
if (record.lastYear === '是') {
|
||||
formState.value.isLastYear = 1;
|
||||
disabled.value = false;
|
||||
@@ -425,10 +424,12 @@
|
||||
formState.value.isLastYear = 0;
|
||||
disabled.value = true;
|
||||
}
|
||||
formState.value.conversionRate = record.conversionRate;
|
||||
formState.value.lastYearList = [record.lastYearActualUsage];
|
||||
formState.value.budget = record.budget;
|
||||
}
|
||||
formState.value.ids = [record.id];
|
||||
formState.value.conversionRate = record.conversionRate;
|
||||
formState.value.lastYearList = [record.lastYearActualUsage];
|
||||
formState.value.ids = [record.id];
|
||||
formState.value.budget = record.budget;
|
||||
};
|
||||
const disabled = ref(true);
|
||||
const selectChange = (value) => {
|
||||
@@ -995,6 +996,9 @@
|
||||
:deep(.ant-card-bordered) {
|
||||
border: unset;
|
||||
}
|
||||
:deep(.ant-input-number-handler-wrap){
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<style scoped>
|
||||
.editable-row-operations a {
|
||||
|
||||
@@ -674,7 +674,7 @@
|
||||
}
|
||||
.contant {
|
||||
width: 100%;
|
||||
height: calc(94% - 5vh);
|
||||
height: calc(94% - 5vh - 24px);
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
.chartsPart {
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
v-model:pageSize="pagination.pageSize"
|
||||
show-size-changer
|
||||
:total="pagination.total"
|
||||
show-less-items
|
||||
@change="getTable(true)" />
|
||||
<div style="width: 100%; height: 40px"></div>
|
||||
|
||||
|
||||
@@ -16,17 +16,41 @@
|
||||
<div style="width: 100%; height: 20px; color: rgb(128, 255, 255)">
|
||||
{{ item.deviceInfoName }}
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
模式: <span style="color: #fff">{{ item.type }}</span>
|
||||
<div v-if="item.autoStatus" style="width: 100%; height: 20px">
|
||||
模式: <span style="color: #fff">{{ item.autoStatus.label }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
设定温度: <span style="color: #fff">{{ item.number }}</span>
|
||||
<div v-if="item.temp" style="width: 100%; height: 20px">
|
||||
设定温度: <span style="color: #fff">{{ item.temp }} {{ item.tempUnit }}</span>
|
||||
</div>
|
||||
<img
|
||||
style="position: absolute; width: 135px; height: 130px; left: -20px; top: 40px"
|
||||
:src="item.url" />
|
||||
</div>
|
||||
</template>
|
||||
<!-- 空气源 - 传感器 -->
|
||||
<template v-for="(item, index) in airSourceSensor" :key="index">
|
||||
<div
|
||||
style="
|
||||
width: 135px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
color: #ffff80;
|
||||
z-index: 2;
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<div style="width: 100%; height: 20px">
|
||||
出水温度: <span style="color: #fff">{{ item.temp }} {{ item.tempUnit }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
流量: <span style="color: #fff">{{ item.traffic }} {{ item.trafficUnit }}</span>
|
||||
</div>
|
||||
<img
|
||||
style="position: absolute; width: 28px; height: 28px; left: -20px; top: 40px"
|
||||
:src="item.url" />
|
||||
</div>
|
||||
</template>
|
||||
<!-- 水泵 -->
|
||||
<div
|
||||
style="
|
||||
@@ -37,7 +61,7 @@
|
||||
bottom: 50%;
|
||||
position: absolute;
|
||||
">
|
||||
<a-switch
|
||||
<!-- <a-switch
|
||||
:checked="selectAllCheckbox === 1 ? true : false"
|
||||
size="small"
|
||||
:disabled="true"
|
||||
@@ -46,10 +70,34 @@
|
||||
'blue-background': selectAllCheckbox === 1 ? true : false,
|
||||
'grey-background': selectAllCheckbox === 1 ? false : true,
|
||||
}"
|
||||
@change="toggleAllSelection" />
|
||||
@change="toggleAllSelection" /> -->
|
||||
<img style="display: flex; width: 111px; height: 100px" :src="waterPumpSrc" />
|
||||
<div style="width: 100%; height: 20px; color: rgb(128, 255, 255)"> 水泵 </div>
|
||||
</div>
|
||||
<!-- 水泵 传感器 -->
|
||||
<template v-for="(item, index) in waterSensor" :key="index">
|
||||
<div
|
||||
style="
|
||||
width: 135px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
color: #ffff80;
|
||||
z-index: 2;
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<div style="width: 100%; height: 20px">
|
||||
温度: <span style="color: #fff">{{ item.temp }} {{ item.tempUnit }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
流量: <span style="color: #fff">{{ item.traffic }} {{ item.trafficUnit }}</span>
|
||||
</div>
|
||||
<img
|
||||
style="position: absolute; width: 28px; height: 28px; left: -20px; top: 40px"
|
||||
:src="item.url" />
|
||||
</div>
|
||||
</template>
|
||||
<!-- 螺杆式地源热泵 -->
|
||||
<template v-for="(item, index) in screwGeothermalHeatPump" :key="index">
|
||||
<div
|
||||
@@ -69,11 +117,11 @@
|
||||
<div style="width: 100%; height: 20px; color: rgb(128, 255, 255); z-index: 2">
|
||||
{{ item.deviceInfoName }}
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
模式: <span style="color: #fff">{{ item.type }}</span>
|
||||
<div v-if="item.autoStatus" style="width: 100%; height: 20px">
|
||||
模式: <span style="color: #fff">{{ item.autoStatus.label }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
设定温度: <span style="color: #fff">{{ item.number }}</span>
|
||||
<div v-if="item.temp" style="width: 100%; height: 20px">
|
||||
设定温度: <span style="color: #fff">{{ item.temp }} {{ item.tempUnit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -90,15 +138,17 @@
|
||||
z-index: 2;
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<div style="width: 100%; height: 20px; color: rgb(128, 255, 255)">
|
||||
<div
|
||||
style="
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
color: rgb(128, 255, 255);
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 5px;
|
||||
">
|
||||
{{ item.deviceInfoName }}
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
出水温度: <span style="color: #fff">{{ item.number }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
流量: <span style="color: #fff">{{ item.lNumber }}</span>
|
||||
</div>
|
||||
<img
|
||||
style="position: absolute; width: 117.42px; height: 106.31px; left: -20px; top: 60px"
|
||||
:src="item.url" />
|
||||
@@ -117,17 +167,14 @@
|
||||
z-index: 2;
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<div style="width: 100%; height: 20px; color: rgb(128, 255, 255)">
|
||||
<div style="width: 100%; height: 20px; color: rgb(128, 255, 255); margin-top: 20px">
|
||||
{{ item.deviceInfoName }}
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
出水温度: <span style="color: #fff">{{ item.number }}</span>
|
||||
<div v-if="item.temp" style="width: 100%; height: 20px">
|
||||
出水温度: <span style="color: #fff">{{ item.temp }} {{ item.tempUnit }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
容量: <span style="color: #fff">{{ item.rNumber }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
流量: <span style="color: #fff">{{ item.lNumber }}</span>
|
||||
<div v-if="item.temp" style="width: 100%; height: 20px">
|
||||
容量: <span style="color: #fff">{{ item.vol }} {{ item.volUnit }}</span>
|
||||
</div>
|
||||
<img
|
||||
style="position: absolute; width: 110px; height: 110px; left: -20px; top: 80px"
|
||||
@@ -146,13 +193,14 @@
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<a-switch
|
||||
:checked="item.user === 1 ? true : false"
|
||||
v-if="item.switchStatus"
|
||||
:checked="item?.switchStatus?.value === 1 ? true : false"
|
||||
size="small"
|
||||
:disabled="true"
|
||||
style="position: absolute; left: 30px; bottom: 0px; z-index: 2"
|
||||
:class="{
|
||||
'blue-background': item.user === 1 ? true : false,
|
||||
'grey-background': item.user === 1 ? false : true,
|
||||
'blue-background': item?.switchStatus?.value === 1 ? true : false,
|
||||
'grey-background': item?.switchStatus?.value === 1 ? false : true,
|
||||
}" />
|
||||
<img
|
||||
style="
|
||||
@@ -168,7 +216,7 @@
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
left: -40px;
|
||||
top: 30px;
|
||||
top: 40px;
|
||||
transform: rotateZ(-24deg);
|
||||
"
|
||||
>{{ item.deviceInfoName }}</div
|
||||
@@ -192,21 +240,43 @@
|
||||
style="width: 226.19px; height: 176.19px; transform: rotateY(13deg)"
|
||||
:src="manifoldSrc" />
|
||||
</div>
|
||||
<!-- 集水器 传感器 -->
|
||||
<template v-for="(item, index) in manifoldSensor" :key="index">
|
||||
<div
|
||||
style="
|
||||
width: 135px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
color: #ffff80;
|
||||
z-index: 2;
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<div style="width: 100%; height: 20px">
|
||||
回水温度: <span style="color: #fff">{{ item.temp }} {{ item.tempUnit }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
流量: <span style="color: #fff">{{ item.traffic }} {{ item.trafficUnit }}</span>
|
||||
</div>
|
||||
<img
|
||||
style="
|
||||
position: absolute;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
left: -20px;
|
||||
top: 40px;
|
||||
transform: rotateX(-4deg) rotateY(180deg) rotateZ(1deg);
|
||||
"
|
||||
:src="item.url" />
|
||||
</div>
|
||||
</template>
|
||||
<!-- 定压补水装置 -->
|
||||
<template v-for="(item, index) in pressureWater" :key="index">
|
||||
<div
|
||||
style="width: 137px; height: 137px; position: relative; position: absolute; z-index: 2"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<img style="width: 137px; height: 127px; transform: rotateY(157deg)" :src="item.url" />
|
||||
<a-switch
|
||||
:checked="item.user === 1 ? true : false"
|
||||
size="small"
|
||||
:disabled="true"
|
||||
style="position: absolute; left: 40px; bottom: 0px"
|
||||
:class="{
|
||||
'blue-background': item.user === 1 ? true : false,
|
||||
'grey-background': item.user === 1 ? false : true,
|
||||
}" />
|
||||
<div
|
||||
style="
|
||||
width: 100%;
|
||||
@@ -217,9 +287,6 @@
|
||||
font-size: 12px;
|
||||
">
|
||||
<div> {{ item.deviceInfoName }}</div>
|
||||
<div style="width: 100%; height: 20px; color: #ffff80">
|
||||
压差: <span style="color: #fff">{{ item.yc }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -294,13 +361,14 @@
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<a-switch
|
||||
:checked="item.user === 1 ? true : false"
|
||||
v-if="item.switchStatus"
|
||||
:checked="item.switchStatus.value === 1 ? true : false"
|
||||
size="small"
|
||||
:disabled="true"
|
||||
style="position: absolute; left: 30px; bottom: 0px; z-index: 2"
|
||||
:class="{
|
||||
'blue-background': item.user === 1 ? true : false,
|
||||
'grey-background': item.user === 1 ? false : true,
|
||||
'blue-background': item.switchStatus.value === 1 ? true : false,
|
||||
'grey-background': item.switchStatus.value === 1 ? false : true,
|
||||
}" />
|
||||
<img
|
||||
style="
|
||||
@@ -356,6 +424,30 @@
|
||||
>
|
||||
<img style="width: 290.75px; height: 215.29px" :src="soilCouplerSrc" />
|
||||
</div>
|
||||
<!-- 土壤 传感器 -->
|
||||
<template v-for="(item, index) in soilCouplerSensor" :key="index">
|
||||
<div
|
||||
style="
|
||||
width: 135px;
|
||||
height: 80px;
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
color: #ffff80;
|
||||
z-index: 2;
|
||||
"
|
||||
:style="{ left: item.style.mLeft, bottom: item.style.mBottom }">
|
||||
<div style="width: 100%; height: 20px">
|
||||
供水温度: <span style="color: #fff">{{ item.temp }} {{ item.tempUnit }}</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 20px">
|
||||
流量: <span style="color: #fff">{{ item.traffic }} {{ item.trafficUnit }}</span>
|
||||
</div>
|
||||
<img
|
||||
style="position: absolute; width: 28px; height: 28px; left: -20px; top: 40px"
|
||||
:src="item.url" />
|
||||
</div>
|
||||
</template>
|
||||
<!-- 线 -->
|
||||
<template v-for="(item, index) in line" :key="index">
|
||||
<div
|
||||
@@ -370,11 +462,27 @@
|
||||
}">
|
||||
</div>
|
||||
</template>
|
||||
<!-- 箭头 -->
|
||||
<template v-for="(item, index) in arrow" :key="index">
|
||||
<div
|
||||
style="width: 50px; height: 20px; position: absolute"
|
||||
:style="{
|
||||
left: item.style.mLeft,
|
||||
bottom: item.style.mBottom,
|
||||
transform: item.style.transform,
|
||||
}">
|
||||
<img style="width: 50px; height: 20px" :src="item.url" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { http } from '/nerv-lib/util';
|
||||
import { coldAndHeatSourcesApi } from '/@/api/coldAndHeatSources';
|
||||
import { ventilating } from '/@/api/ventilatingSystem';
|
||||
|
||||
//图片资源
|
||||
import airSourceThermalCollapseSrc from '../image/coldAndHeatSources/airSourceThermalCollapse.png';
|
||||
import waterPumpSrc from '../image/coldAndHeatSources/waterPump.png';
|
||||
@@ -386,10 +494,24 @@
|
||||
import softenedWaterTankSrc from '../image/coldAndHeatSources/softenedWaterTank.png';
|
||||
import waterProcessorSrc from '../image/coldAndHeatSources/waterProcessor.png';
|
||||
import soilCouplerSrc from '../image/coldAndHeatSources/soilCoupler.png';
|
||||
import sensorSrc from '../image/coldAndHeatSources/sensor.png';
|
||||
import blueGif from '../image/coldAndHeatSources/blue.gif';
|
||||
import bluePng from '../image/coldAndHeatSources/blue.png';
|
||||
import greenGif from '../image/coldAndHeatSources/green.gif';
|
||||
import greenPng from '../image/coldAndHeatSources/green.png';
|
||||
import arrowSrc from '../image/coldAndHeatSources/arrow.svg';
|
||||
// 定位数据
|
||||
import {
|
||||
userWaterPumpPosition,
|
||||
waterPumpPosition,
|
||||
airSourceThermalCollapsePosition,
|
||||
screwGeothermalHeatPumpPosition,
|
||||
airSourceSensorPosition,
|
||||
} from './position';
|
||||
// 全局变量
|
||||
import { items } from '/@/store/item';
|
||||
// 全局变量
|
||||
const state = items();
|
||||
const line = ref([
|
||||
//水泵线-热泵
|
||||
{
|
||||
@@ -759,9 +881,6 @@
|
||||
]);
|
||||
const airSourceThermalCollapse = ref([
|
||||
{
|
||||
deviceInfoName: '1#空气源热泵',
|
||||
type: '制热',
|
||||
number: '40℃',
|
||||
style: {
|
||||
mLeft: '17%',
|
||||
mBottom: '54%',
|
||||
@@ -769,9 +888,6 @@
|
||||
url: airSourceThermalCollapseSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '2#空气源热泵',
|
||||
type: '制热',
|
||||
number: '40℃',
|
||||
style: {
|
||||
mLeft: '24%',
|
||||
mBottom: '59%',
|
||||
@@ -779,9 +895,6 @@
|
||||
url: airSourceThermalCollapseSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '3#空气源热泵',
|
||||
type: '制热',
|
||||
number: '40℃',
|
||||
style: {
|
||||
mLeft: '31%',
|
||||
mBottom: '66%',
|
||||
@@ -789,9 +902,6 @@
|
||||
url: airSourceThermalCollapseSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '4#空气源热泵',
|
||||
type: '制热',
|
||||
number: '40℃',
|
||||
style: {
|
||||
mLeft: '38%',
|
||||
mBottom: '73%',
|
||||
@@ -802,9 +912,6 @@
|
||||
//螺杆式地源热泵
|
||||
const screwGeothermalHeatPump = ref([
|
||||
{
|
||||
deviceInfoName: '1#螺杆式地源热泵',
|
||||
type: '制热',
|
||||
number: '40℃',
|
||||
style: {
|
||||
mLeft: '9.5%',
|
||||
mBottom: '22.5%',
|
||||
@@ -812,9 +919,6 @@
|
||||
url: screwGeothermalHeatPumpSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '2#螺杆式地源热泵',
|
||||
type: '制热',
|
||||
number: '40℃',
|
||||
style: {
|
||||
mLeft: '18.5%',
|
||||
mBottom: '31.5%',
|
||||
@@ -826,8 +930,6 @@
|
||||
const diluteCoolingPump = ref([
|
||||
{
|
||||
deviceInfoName: '稀冷泵',
|
||||
number: '40℃',
|
||||
lNumber: '139 m3/h',
|
||||
style: {
|
||||
mLeft: '30%',
|
||||
mBottom: '29%',
|
||||
@@ -838,56 +940,40 @@
|
||||
//冷热水双蓄储能罐
|
||||
const coldWater = ref([
|
||||
{
|
||||
deviceInfoName: '冷热水双蓄储能罐',
|
||||
number: '40℃',
|
||||
lNumber: '139 m3/h',
|
||||
rNumber: '135L',
|
||||
url: coldWaterSrc,
|
||||
style: {
|
||||
mLeft: '36%',
|
||||
mBottom: '39%',
|
||||
},
|
||||
url: coldWaterSrc,
|
||||
},
|
||||
]);
|
||||
//用户水泵
|
||||
const userWaterPump = ref([
|
||||
{
|
||||
deviceInfoName: '1#用户水泵',
|
||||
number: '40℃',
|
||||
user: 1,
|
||||
url: waterPumpSrc,
|
||||
style: {
|
||||
mLeft: '50%',
|
||||
mBottom: '55.5%',
|
||||
},
|
||||
url: waterPumpSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '2#用户水泵',
|
||||
number: '40℃',
|
||||
user: 1,
|
||||
url: waterPumpSrc,
|
||||
style: {
|
||||
mLeft: '55%',
|
||||
mBottom: '51%',
|
||||
},
|
||||
url: waterPumpSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '3#用户水泵',
|
||||
number: '40℃',
|
||||
user: 1,
|
||||
url: waterPumpSrc,
|
||||
style: {
|
||||
mLeft: '59%',
|
||||
mBottom: '47%',
|
||||
},
|
||||
url: waterPumpSrc,
|
||||
},
|
||||
]);
|
||||
//地源水泵
|
||||
const waterPump = ref([
|
||||
{
|
||||
deviceInfoName: '1#地源水泵',
|
||||
number: '40℃',
|
||||
user: 1,
|
||||
style: {
|
||||
mLeft: '65%',
|
||||
mBottom: '41%',
|
||||
@@ -895,9 +981,6 @@
|
||||
url: waterPumpSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '2#地源水泵',
|
||||
number: '40℃',
|
||||
user: 1,
|
||||
style: {
|
||||
mLeft: '70%',
|
||||
mBottom: '36%',
|
||||
@@ -905,9 +988,6 @@
|
||||
url: waterPumpSrc,
|
||||
},
|
||||
{
|
||||
deviceInfoName: '3#地源水泵',
|
||||
number: '40℃',
|
||||
user: 1,
|
||||
style: {
|
||||
mLeft: '75%',
|
||||
mBottom: '31%',
|
||||
@@ -928,9 +1008,287 @@
|
||||
url: pressureWaterSrc,
|
||||
},
|
||||
]);
|
||||
const selectAllCheckbox = ref(1);
|
||||
onMounted(() => {});
|
||||
onUnmounted(() => {});
|
||||
//水泵 - 螺杆式 传感器
|
||||
const waterSensor = ref([
|
||||
{
|
||||
url: sensorSrc,
|
||||
style: {
|
||||
mLeft: '9%',
|
||||
mBottom: '27%',
|
||||
},
|
||||
},
|
||||
]);
|
||||
//集水器 传感器
|
||||
const manifoldSensor = ref([
|
||||
{
|
||||
url: sensorSrc,
|
||||
style: {
|
||||
mLeft: '81%',
|
||||
mBottom: '51%',
|
||||
},
|
||||
},
|
||||
]);
|
||||
//土壤 传感器
|
||||
const soilCouplerSensor = ref([
|
||||
{
|
||||
url: sensorSrc,
|
||||
style: {
|
||||
mLeft: '79%',
|
||||
mBottom: '13%',
|
||||
},
|
||||
},
|
||||
]);
|
||||
//空气源 - 传感器
|
||||
const airSourceSensor = ref([
|
||||
{
|
||||
style: {
|
||||
mLeft: '26.5%',
|
||||
mBottom: '34%',
|
||||
},
|
||||
url: sensorSrc,
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '32.5%',
|
||||
mBottom: '39%',
|
||||
},
|
||||
url: sensorSrc,
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '38.5%',
|
||||
mBottom: '44.5%',
|
||||
},
|
||||
url: sensorSrc,
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '47.5%',
|
||||
mBottom: '52.5%',
|
||||
},
|
||||
url: sensorSrc,
|
||||
},
|
||||
]);
|
||||
//箭头
|
||||
const arrow = ref([
|
||||
{
|
||||
url: arrowSrc,
|
||||
style: {
|
||||
mLeft: '6%',
|
||||
mBottom: '42.5%',
|
||||
transform: 'rotateZ(36deg)',
|
||||
},
|
||||
},
|
||||
{
|
||||
url: arrowSrc,
|
||||
style: {
|
||||
mLeft: '25%',
|
||||
mBottom: '18%',
|
||||
transform: 'rotateZ(36deg)',
|
||||
},
|
||||
},
|
||||
{
|
||||
url: arrowSrc,
|
||||
style: {
|
||||
mLeft: '76%',
|
||||
mBottom: '13%',
|
||||
transform: 'rotateZ(37deg)',
|
||||
},
|
||||
},
|
||||
{
|
||||
url: arrowSrc,
|
||||
style: {
|
||||
mLeft: '78%',
|
||||
mBottom: '72%',
|
||||
transform: 'rotateZ(149deg)',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
//获取用户水泵数据
|
||||
const getUserWaterPump = () => {
|
||||
http
|
||||
.get(coldAndHeatSourcesApi.getUserWaterPumpState, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
floor: 1,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
res.data.forEach((item: any, index: any) => {
|
||||
userWaterPump.value[index] = {
|
||||
deviceInfoName: item.deviceInfoName,
|
||||
...item.record,
|
||||
url: waterPumpSrc,
|
||||
style: userWaterPumpPosition[index].style,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
//获取地源水泵数据
|
||||
const getLandWaterPumpState = () => {
|
||||
http
|
||||
.get(coldAndHeatSourcesApi.getLandWaterPumpState, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
floor: 1,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
res.data.forEach((item: any, index: any) => {
|
||||
waterPump.value[index] = {
|
||||
deviceInfoName: item.deviceInfoName,
|
||||
...item.record,
|
||||
url: waterPumpSrc,
|
||||
style: waterPumpPosition[index].style,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//获取空气源热泵
|
||||
const getAirHeatPumpState = () => {
|
||||
http
|
||||
.get(coldAndHeatSourcesApi.getAirHeatPumpState, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
floor: 1,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
res.data.forEach((item: any, index: any) => {
|
||||
airSourceThermalCollapse.value[index] = {
|
||||
deviceInfoName: item.deviceInfoName,
|
||||
...item.record,
|
||||
url: airSourceThermalCollapseSrc,
|
||||
style: airSourceThermalCollapsePosition[index].style,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
//获取螺杆式地源热泵
|
||||
const getLandHeatPumpState = () => {
|
||||
http
|
||||
.get(coldAndHeatSourcesApi.getLandHeatPumpState, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
floor: 1,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
res.data.forEach((item: any, index: any) => {
|
||||
screwGeothermalHeatPump.value[index] = {
|
||||
deviceInfoName: item.deviceInfoName,
|
||||
...item.record,
|
||||
url: screwGeothermalHeatPumpSrc,
|
||||
style: screwGeothermalHeatPumpPosition[index].style,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
//冷热水双蓄储能罐
|
||||
const getEnergyTankState = () => {
|
||||
http
|
||||
.get(coldAndHeatSourcesApi.getEnergyTankState, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
floor: 1,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
res.data.forEach((item: any) => {
|
||||
coldWater.value[0] = {
|
||||
deviceInfoName: item.deviceInfoName,
|
||||
...item.record,
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
//获取多功能传感器
|
||||
const getSensorData = () => {
|
||||
http
|
||||
.get(ventilating.getSensorData, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
floor: 1,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.msg === 'success') {
|
||||
res.data.forEach((item: any, index: any) => {
|
||||
if (index < 4) {
|
||||
airSourceSensor.value[index] = {
|
||||
deviceInfoName: item.deviceInfoName,
|
||||
...item.record,
|
||||
url: sensorSrc,
|
||||
style: airSourceSensorPosition[index].style,
|
||||
};
|
||||
}
|
||||
});
|
||||
// 水泵传感器
|
||||
let data = res.data[Math.floor(Math.random() * res.data.length)];
|
||||
waterSensor.value[0] = {
|
||||
deviceInfoName: data.deviceInfoName,
|
||||
...data.record,
|
||||
url: sensorSrc,
|
||||
style: {
|
||||
mLeft: '9%',
|
||||
mBottom: '27%',
|
||||
},
|
||||
};
|
||||
// 集水器 -传感器
|
||||
data = res.data[Math.floor(Math.random() * res.data.length)];
|
||||
manifoldSensor.value[0] = {
|
||||
deviceInfoName: data.deviceInfoName,
|
||||
...data.record,
|
||||
url: sensorSrc,
|
||||
style: {
|
||||
mLeft: '81%',
|
||||
mBottom: '51%',
|
||||
},
|
||||
};
|
||||
// 土壤 -传感器
|
||||
data = res.data[Math.floor(Math.random() * res.data.length)];
|
||||
soilCouplerSensor.value[0] = {
|
||||
deviceInfoName: data.deviceInfoName,
|
||||
...data.record,
|
||||
url: sensorSrc,
|
||||
style: {
|
||||
mLeft: '79%',
|
||||
mBottom: '13%',
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
//获取地源水泵设备
|
||||
const getData = () => {
|
||||
//获取用户水泵数据
|
||||
getUserWaterPump();
|
||||
//获取地源水泵数据
|
||||
getLandWaterPumpState();
|
||||
//获取空气源热泵数据
|
||||
getAirHeatPumpState();
|
||||
//螺杆式地源热泵
|
||||
getLandHeatPumpState();
|
||||
//冷热水双蓄储能罐
|
||||
getEnergyTankState();
|
||||
//获取多功能传感器
|
||||
getSensorData();
|
||||
};
|
||||
//定时
|
||||
// const intervalId = setInterval(getList, 60000);
|
||||
onMounted(() => {
|
||||
getData();
|
||||
});
|
||||
onUnmounted(() => {
|
||||
// 这里写销毁时需要执行的逻辑
|
||||
// clearInterval(intervalId);
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.box-cold {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
//用户水泵位置
|
||||
export const userWaterPumpPosition = [
|
||||
{
|
||||
style: {
|
||||
mLeft: '50%',
|
||||
mBottom: '55.5%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '55%',
|
||||
mBottom: '51%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '59%',
|
||||
mBottom: '47%',
|
||||
},
|
||||
},
|
||||
];
|
||||
//地源水泵位置
|
||||
export const waterPumpPosition = [
|
||||
{
|
||||
style: {
|
||||
mLeft: '65%',
|
||||
mBottom: '41%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '70%',
|
||||
mBottom: '36%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '75%',
|
||||
mBottom: '31%',
|
||||
},
|
||||
},
|
||||
];
|
||||
//空气源热泵
|
||||
export const airSourceThermalCollapsePosition = [
|
||||
{
|
||||
style: {
|
||||
mLeft: '17%',
|
||||
mBottom: '54%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '24%',
|
||||
mBottom: '59%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '31%',
|
||||
mBottom: '66%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '38%',
|
||||
mBottom: '73%',
|
||||
},
|
||||
},
|
||||
];
|
||||
//获取螺杆式地源热泵
|
||||
export const screwGeothermalHeatPumpPosition = [
|
||||
{
|
||||
style: {
|
||||
mLeft: '9.5%',
|
||||
mBottom: '22.5%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '18.5%',
|
||||
mBottom: '31.5%',
|
||||
},
|
||||
},
|
||||
];
|
||||
// 空气源 - 传感器
|
||||
export const airSourceSensorPosition = [
|
||||
{
|
||||
style: {
|
||||
mLeft: '26.5%',
|
||||
mBottom: '34%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '32.5%',
|
||||
mBottom: '39%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '38.5%',
|
||||
mBottom: '44.5%',
|
||||
},
|
||||
},
|
||||
{
|
||||
style: {
|
||||
mLeft: '47.5%',
|
||||
mBottom: '52.5%',
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="50px" height="22px" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1 0 0 1 -1191 -569 )">
|
||||
<path d="M 49.73958333333333 7.581274382314695 C 49.91319444444444 7.752925877763329 50 7.972258344169916 50 8.239271781534459 L 50 13.732119635890768 C 50 13.999133073255308 49.91319444444444 14.2184655396619 49.73958333333333 14.390117035110533 C 49.56597222222222 14.561768530559167 49.34413580246914 14.647594278283485 49.074074074074076 14.647594278283485 L 12.962962962962962 14.647594278283485 L 12.962962962962962 21.055916775032507 C 12.962962962962962 21.456436931079324 12.779706790123457 21.732986562635453 12.413194444444445 21.88556566970091 C 12.046682098765434 22.038144776766362 11.709104938271606 21.99046380580841 11.400462962962964 21.742522756827046 L 0.28935185185185186 11.729518855656698 C 0.09645061728395089 11.538794971824878 0 11.31946250541829 0 11.071521456436932 C 0 10.804508019072387 0.09645061728395089 10.575639358474207 0.28935185185185186 10.384915474642392 L 11.400462962962964 0.2574772431729524 C 11.709104938271606 -0.009536194191596348 12.046682098765434 -0.06675335934114024 12.413194444444445 0.08582574772431828 C 12.779706790123457 0.2574772431729524 12.962962962962962 0.5340268747290853 12.962962962962962 0.9154746423927169 L 12.962962962962962 7.3237971391417425 L 49.074074074074076 7.3237971391417425 C 49.34413580246914 7.3237971391417425 49.56597222222222 7.409622886866061 49.73958333333333 7.581274382314695 Z " fill-rule="nonzero" fill="#ffff80" stroke="none" transform="matrix(1 0 0 1 1191 569 )" />
|
||||
</g>
|
||||
</svg>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@@ -30,6 +30,7 @@
|
||||
v-model:pageSize="pagination.pageSize"
|
||||
show-size-changer
|
||||
:total="pagination.total"
|
||||
show-less-items
|
||||
@change="getTable(true)" />
|
||||
<div style="width: 100%; height: 40px"></div>
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
<div
|
||||
:style="{
|
||||
color: {
|
||||
'0': '#ccc',
|
||||
'1': 'rgba(255, 165, 0, 1)',
|
||||
'2': 'rgb(57, 215, 187)',
|
||||
'3': 'rgb(255, 0, 0)',
|
||||
'4': '#ccc',
|
||||
}[record.executeStatus.value],
|
||||
}">
|
||||
{{ record.executeStatus.label }}</div
|
||||
@@ -36,7 +36,7 @@
|
||||
import { NsMessage } from '/nerv-lib/component';
|
||||
import { getEnum } from '/@/api';
|
||||
import { http } from '/nerv-lib/util';
|
||||
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
//页面 创建
|
||||
const orgId = ref('');
|
||||
const projectId = ref('');
|
||||
@@ -46,6 +46,7 @@
|
||||
projectId.value = results.projectId;
|
||||
const mainRef = ref(null);
|
||||
const modalFormRef = ref(null);
|
||||
|
||||
const addPlan = () => {
|
||||
if (mainRef.value.nsTableRef.treeElRef.selectedRow.node.planLib) {
|
||||
http
|
||||
@@ -69,6 +70,10 @@
|
||||
? record.startTime.substring(0, 10) + ' - ' + record.endTime.substring(0, 10)
|
||||
: '未配置时间';
|
||||
};
|
||||
const disabledDate = (current: Dayjs) => {
|
||||
// Can not select days before today and today
|
||||
return current && current < dayjs().endOf('day');
|
||||
};
|
||||
const nsModalFormConfig = ref({
|
||||
api: planToAddApi.updPlan,
|
||||
data: {},
|
||||
@@ -92,6 +97,7 @@
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD hh:mm:ss',
|
||||
placeholder: ['开始日期', '结束日期'],
|
||||
disabledDate: disabledDate,
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
|
||||
@@ -85,9 +85,9 @@
|
||||
:class="{ btn: true, selected: button.selected }"
|
||||
class="zmhlbtn"
|
||||
@click="changeLine(button)">
|
||||
<div v-if="button.lockStatus" class="btn-back">
|
||||
<!-- <div v-if="button.lockStatus" class="btn-back">
|
||||
<stop-outlined />
|
||||
</div>
|
||||
</div> -->
|
||||
{{ button.name }}
|
||||
</button>
|
||||
<div style="margin-top: 10px">
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
v-model:pageSize="pagination.pageSize"
|
||||
show-size-changer
|
||||
:total="pagination.total"
|
||||
show-less-items
|
||||
@change="getTable(true)" />
|
||||
<div style="width: 100%; height: 40px"></div>
|
||||
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
<template>
|
||||
<table class="custom-table table1">
|
||||
<thead>
|
||||
<tr :style="{ background: 'rgba(35,45,69)' }">
|
||||
<th>序号</th>
|
||||
<th>执行时间</th>
|
||||
<th>操作内容</th>
|
||||
<th>操作人</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
:style="{ color: row.ctrlResult == 1 ? 'red' : 'white' }"
|
||||
v-for="(row, index) in dataSource"
|
||||
:key="index"
|
||||
@click="handleRowClick(row.id, index)"
|
||||
:class="index === trIndex ? 'isTrIndex' : ''">
|
||||
<td>{{ index + 1 }}</td>
|
||||
<td>{{ row.startTime }}</td>
|
||||
<td>{{ row.operationContent }}</td>
|
||||
<td>{{ row.createUser }}</td>
|
||||
<td>{{ row.ctrlResult ? '失败' : '成功' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<a-pagination
|
||||
style="margin-top: 10px; text-align: right"
|
||||
v-model:current="pagination.pageNum"
|
||||
v-model:pageSize="pagination.pageSize"
|
||||
show-size-changer
|
||||
:total="pagination.total"
|
||||
@change="getTable(true)" />
|
||||
<div style="width: 100%; height: 40px"></div>
|
||||
|
||||
<div class="out-dialog" :class="{ showDialog: logModalVisible }" v-if="logModalVisible">
|
||||
<div class="content">
|
||||
<div>
|
||||
<div class="div-operation"></div>
|
||||
<span class="text-operation">变更内容 </span>
|
||||
</div>
|
||||
<div>
|
||||
<button :class="{ btn: true, selected: activeButton == 1 }" @click="changeBtn(1)"
|
||||
>阀门</button
|
||||
>
|
||||
<button :class="{ btn: true, selected: activeButton == 2 }" @click="changeBtn(2)"
|
||||
>水泵</button
|
||||
>
|
||||
</div>
|
||||
<div class="device-list" v-if="activeButton == 1">
|
||||
<div class="device-list-item" v-for="(item, index) in valveLogList" :key="index">
|
||||
<div class="list-item-title">
|
||||
<div class="item-title">
|
||||
<img src="../images/device1.png" alt="" />
|
||||
<span>{{ item.deviceGroupName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item-main">
|
||||
<div>
|
||||
<div class="info">开度</div>
|
||||
<div class="text">
|
||||
<span>{{ item.openPercentBefore + '%' }}</span>
|
||||
<img src="/asset/image/bulbLogo/22406.png" alt="" />
|
||||
<span>{{ item.openPercentAfter + '%' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
<a-empty style="margin-top: 100px" v-if="valveLogList.length == 0">
|
||||
<template #description> <span style="color: white">暂无数据</span></template>
|
||||
</a-empty>
|
||||
</div>
|
||||
<div class="device-list" v-if="activeButton == 2">
|
||||
<div class="device-list-item" v-for="(item, index) in pumpLogList" :key="index">
|
||||
<div class="list-item-title">
|
||||
<div class="item-title">
|
||||
<img src="../images/device2.png" alt="" />
|
||||
<span>{{ item.deviceGroupName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item-main">
|
||||
<div>
|
||||
<div class="info">频率</div>
|
||||
<div class="text">
|
||||
<span>{{ item.frequencyBefore + 'MHz' }}</span>
|
||||
<img src="/asset/image/bulbLogo/22406.png" alt="" />
|
||||
<span>{{ item.frequencyAfter + 'MHz' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="info">开关</div>
|
||||
<div class="text">
|
||||
<span>{{ item.switchStatusBefore.label }}</span>
|
||||
<img src="/asset/image/bulbLogo/22406.png" alt="" />
|
||||
<span>{{ item.switchStatusAfter.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-empty style="margin-top: 100px" v-if="pumpLogList.length == 0">
|
||||
<template #description> <span style="color: white">暂无数据</span></template>
|
||||
</a-empty>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100%; height: 160px"></div>
|
||||
<div class="button-box">
|
||||
<button class="cancel" @click="logModalVisible = false">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-add">
|
||||
<button class="add" @click="reset">刷新</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { Pagination } from 'ant-design-vue';
|
||||
import { http } from '/nerv-lib/util/http';
|
||||
import { waterSys } from '/@/api/waterSystem';
|
||||
// 全局变量
|
||||
import { items } from '/@/store/item';
|
||||
|
||||
// 初始化 =======================================================
|
||||
|
||||
// 组件
|
||||
defineOptions({
|
||||
components: {
|
||||
'a-pagination': Pagination,
|
||||
},
|
||||
});
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
getTable();
|
||||
});
|
||||
|
||||
// 全局变量
|
||||
const state = items();
|
||||
|
||||
// 日志业务 ======================================================
|
||||
|
||||
// 分页设置
|
||||
const pagination = ref({
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
total: 0,
|
||||
});
|
||||
// 表格数据
|
||||
const dataSource = ref([]);
|
||||
// 当前选中表格行
|
||||
let trIndex = ref(-1);
|
||||
// 获得表格数据
|
||||
const getTable = (changePage = false) => {
|
||||
state.setLoading(true);
|
||||
// 如果是切换页面,则清除当前序列、关闭弹窗
|
||||
if (changePage) {
|
||||
trIndex.value = -1;
|
||||
logModalVisible.value = false;
|
||||
pumpLogList.value.length = 0;
|
||||
valveLogList.value.length = 0;
|
||||
}
|
||||
http
|
||||
.get(waterSys.getLog, {
|
||||
pageSize: pagination.value.pageSize,
|
||||
pageNum: pagination.value.pageNum,
|
||||
})
|
||||
.then((res) => {
|
||||
state.setLoading(false);
|
||||
let data = res.data;
|
||||
dataSource.value = data.records;
|
||||
pagination.value.total = data.total;
|
||||
})
|
||||
.catch(() => {
|
||||
state.setLoading(false);
|
||||
});
|
||||
};
|
||||
// 刷新功能(右下角)
|
||||
const reset = () => {
|
||||
trIndex.value = -1;
|
||||
logModalVisible.value = false;
|
||||
pagination.value = {
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
total: 0,
|
||||
};
|
||||
getTable();
|
||||
};
|
||||
// 点击日志行事件
|
||||
const handleRowClick = (id: any, index: any) => {
|
||||
trIndex.value = index;
|
||||
getLogDetail(id);
|
||||
};
|
||||
|
||||
// 日志详情业务 ==================================================
|
||||
|
||||
// 日志详情显隐
|
||||
const logModalVisible = ref(false);
|
||||
const getLogDetail = (id: any) => {
|
||||
state.setLoading(true);
|
||||
http
|
||||
.get(waterSys.getLogDetail, { logId: id })
|
||||
.then((res) => {
|
||||
state.setLoading(false);
|
||||
const data = res.data;
|
||||
if (data.pumpLogList.length || data.valveLogList.length) {
|
||||
// 显示模态框
|
||||
logModalVisible.value = true;
|
||||
pumpLogList.value = data.pumpLogList;
|
||||
valveLogList.value = data.valveLogList;
|
||||
} else {
|
||||
return message.info('返回值无效');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
state.setLoading(false);
|
||||
});
|
||||
};
|
||||
// 当前选中的设备类型 阀门=1/水泵=2
|
||||
const activeButton = ref(1);
|
||||
// 切换设备类型
|
||||
const changeBtn = (key: number) => {
|
||||
activeButton.value = key;
|
||||
};
|
||||
// 水泵数据
|
||||
const pumpLogList = ref<any>([]);
|
||||
// 水阀数据
|
||||
const valveLogList = ref<any>([]);
|
||||
|
||||
// 向外暴露方法
|
||||
defineExpose({
|
||||
reset,
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import '../../style/dialogStyle.less';
|
||||
|
||||
// 右下角添加按钮
|
||||
.div-add {
|
||||
height: 64px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin-right: 20px;
|
||||
.add {
|
||||
width: 74px;
|
||||
height: 40px;
|
||||
opacity: 1;
|
||||
border-radius: 4px;
|
||||
background: rgba(67, 136, 251, 1);
|
||||
border: rgba(67, 136, 251, 1);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// 表格
|
||||
.custom-table {
|
||||
border-collapse: collapse;
|
||||
width: 416px;
|
||||
min-height: 60px;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
cursor: pointer;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
.custom-table th,
|
||||
.custom-table td {
|
||||
border: 1px solid rgba(163, 192, 243, 1);
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table1 {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
border: 1px solid rgba(255, 255, 255);
|
||||
border-radius: 5px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
|
||||
.tabReboot,
|
||||
.tabDelete {
|
||||
border: none;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
line-height: 20px;
|
||||
color: rgba(67, 136, 251, 1);
|
||||
}
|
||||
|
||||
.tabReboot {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.isTrIndex {
|
||||
background: rgba(67, 136, 251, 1);
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.ant-transfer) {
|
||||
// 屏蔽自带的hover效果
|
||||
.ant-transfer-list-content-item:hover {
|
||||
background: black;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 92px;
|
||||
height: 40px;
|
||||
border-radius: 4px;
|
||||
opacity: 1;
|
||||
margin-top: 10px;
|
||||
margin-left: 15px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
opacity: 1;
|
||||
border: 1px solid rgba(207, 212, 219, 1);
|
||||
line-height: 20.27px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.selected {
|
||||
background: linear-gradient(180deg, rgba(201, 245, 255, 1) 0%, rgba(138, 215, 255, 1) 100%);
|
||||
color: rgba(0, 61, 90, 1);
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: rgba(207, 212, 219, 1);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
background-color: rgba(102, 102, 102, 1);
|
||||
color: white;
|
||||
}
|
||||
.device-list {
|
||||
margin-left: 15px;
|
||||
margin-top: 15px;
|
||||
width: calc(100% - 15px);
|
||||
font-size: 13px;
|
||||
height: auto;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
flex-direction: column;
|
||||
.device-list-item {
|
||||
width: calc(100% - 15px);
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
border: 2px solid #03407e;
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 177, 255, 0.2);
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-direction: column;
|
||||
.list-item-title {
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.item-title {
|
||||
img {
|
||||
width: 25px;
|
||||
}
|
||||
span {
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.revoke {
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 5px 15px;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 187, 0, 1) 0%,
|
||||
rgba(255, 112, 3, 1) 91.21%,
|
||||
rgba(255, 129, 3, 1) 100%
|
||||
);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.list-item-main {
|
||||
display: flex;
|
||||
> div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
> .info {
|
||||
text-align: center;
|
||||
width: 6em;
|
||||
height: 2.5em;
|
||||
line-height: 2.5em;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(86, 221, 253, 1) 0%,
|
||||
rgba(25, 176, 255, 1) 100%
|
||||
);
|
||||
}
|
||||
> .text {
|
||||
:first-child {
|
||||
color: white;
|
||||
line-height: 2.5em;
|
||||
}
|
||||
img {
|
||||
padding: 0 5px;
|
||||
}
|
||||
:last-child {
|
||||
line-height: 2.5em;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,381 @@
|
||||
<template>
|
||||
<div class="div-add">
|
||||
<button class="add" @click="addModal">添加</button>
|
||||
<a-popconfirm
|
||||
title="是否提交以上修改?"
|
||||
placement="bottomLeft"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="sendTable">
|
||||
<button class="add" style="margin-left: 20px">执行</button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<span style="color: red; padding-top: 20px">*以下修改需执行后生效</span>
|
||||
<div class="plans">
|
||||
<button class="plan enabled" style="margin-right: 10px" @click="togglePlan(1)">
|
||||
计划启用
|
||||
</button>
|
||||
<button class="plan disabled" @click="togglePlan(3)"> 计划禁用 </button>
|
||||
</div>
|
||||
</div>
|
||||
<table class="custom-table table1">
|
||||
<thead>
|
||||
<tr :style="{ background: 'rgba(35,45,69)' }">
|
||||
<th>序号</th>
|
||||
<th>执行时间</th>
|
||||
<th>计划名称</th>
|
||||
<th>状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(row, index) in dataSource" v-show="row.executeStatus.value != 0" :key="index">
|
||||
<td>{{ index + 1 }}</td>
|
||||
<td>{{ row.startTime }}</td>
|
||||
<td>{{ row.planName }}</td>
|
||||
<td>
|
||||
<button
|
||||
:style="{
|
||||
'font-size': '12px',
|
||||
width: '5em',
|
||||
background: 'rgb(47, 47, 47)',
|
||||
color: setStateColor(row.executeStatus.value),
|
||||
border: '1px solid',
|
||||
}">
|
||||
{{ setStateText(row.executeStatus.value) }}
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<div class="tabReboot" @click="startPlan(row)">启用</div>
|
||||
<a-popconfirm
|
||||
title="此操作将移除该数据"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
placement="topRight"
|
||||
@confirm="deletePlan(row)">
|
||||
<div class="tabDelete">删除</div>
|
||||
</a-popconfirm>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="out-dialog" v-if="addVisible">
|
||||
<div class="content">
|
||||
<div class="div-operation"></div>
|
||||
<span class="text-operation">计划库</span>
|
||||
</div>
|
||||
<div style="margin-top: 20px">
|
||||
<a-transfer
|
||||
v-model:target-keys="targetKeys"
|
||||
:data-source="transferData"
|
||||
show-search
|
||||
:filter-option="filterOption"
|
||||
:render="(item: any) => item.title"
|
||||
@change="handleChange"
|
||||
:style="{ color: 'rgba(255,255,255,1)' }"
|
||||
@search="handleSearch"
|
||||
:listStyle="{ border: '2px solid rgba(25,74,125,1)', height: 'calc(100vh - 200px)' }" />
|
||||
</div>
|
||||
<div style="width: 100%; height: 60px"></div>
|
||||
<div class="button-box">
|
||||
<button class="cancel" @click="addVisible = false">取消</button>
|
||||
<button class="execute" @click="sendPlan">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
// 请求
|
||||
import { http } from '/nerv-lib/util/http';
|
||||
import { planManage } from '/@/api/planManage';
|
||||
import { waterSys } from '/@/api/waterSystem';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { getEnum } from '/@/api';
|
||||
// 全局变量
|
||||
import { items } from '/@/store/item';
|
||||
|
||||
// 初始化 ===========================================================
|
||||
|
||||
onMounted(() => {
|
||||
// 获得枚举
|
||||
getStateEnum();
|
||||
// 获得穿梭框 与 表格数据
|
||||
reset();
|
||||
});
|
||||
// 全局变量
|
||||
const state = items();
|
||||
// 获得任务状态枚举
|
||||
const getStateEnum = async () => {
|
||||
let enumData = await getEnum({ params: { enumType: 'PlanExecuteStatus' } });
|
||||
stateList.value = enumData.data;
|
||||
};
|
||||
/**
|
||||
* @method resetAll 刷新3个tab中的全部数据(修改计划,会影响tab1数据信息,生成tab3日志)
|
||||
*/
|
||||
const emit = defineEmits(['resetAll']);
|
||||
|
||||
// tab页部分 ========================================================
|
||||
|
||||
// 状态枚举
|
||||
const stateList = ref([]);
|
||||
// 设置枚举的颜色 与 文本
|
||||
const setStateColor = (state: number) => {
|
||||
if (state == 0) {
|
||||
return '#ccc';
|
||||
} else if (state == 1) {
|
||||
return 'orange';
|
||||
} else if (state == 2) {
|
||||
return 'rgb(57, 215, 187)';
|
||||
} else if (state == 3) {
|
||||
return 'rgb(255, 0, 0)';
|
||||
}
|
||||
};
|
||||
// 设置枚举的文本
|
||||
const setStateText = (state: number) => {
|
||||
const res = stateList.value.find((item) => {
|
||||
return item.value == state;
|
||||
});
|
||||
return res.label;
|
||||
};
|
||||
// 计划启用/禁用事件
|
||||
const togglePlan = (state: number) => {
|
||||
dataSource.value.forEach((item: any) => {
|
||||
// 执行中 无法修改为待执行
|
||||
if (state == 1) {
|
||||
if (item.executeStatus.value != 2) {
|
||||
item.executeStatus.value = state;
|
||||
}
|
||||
// 任何状态都可以修改为 暂停
|
||||
} else {
|
||||
item.executeStatus.value = state;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 表格数据
|
||||
const dataSource = ref([]);
|
||||
// 获得表格数据
|
||||
const getTable = () => {
|
||||
http
|
||||
.get(planManage.getTableData, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
// 设备类型(1照明,2空调,3排风扇,4风幕机,5电动窗,6给排水)
|
||||
ctrlType: 6,
|
||||
})
|
||||
.then((res) => {
|
||||
dataSource.value = res.data;
|
||||
});
|
||||
};
|
||||
// 删除表格中的计划(将当前任意状态,修改为未启用 =0)
|
||||
const deletePlan = (row: any) => {
|
||||
row.executeStatus.value = 0;
|
||||
};
|
||||
// 重启表格中的计划(将当前任意状态,修改为待执行 = 1)
|
||||
const startPlan = (row: any) => {
|
||||
if (row.executeStatus.value == 1) {
|
||||
return message.info('该数据已是待执行状态,无需再次修改');
|
||||
}
|
||||
if (row.executeStatus.value == 2) {
|
||||
return message.info('执行中的状态已被启用,无需修改');
|
||||
}
|
||||
row.executeStatus.value = 1;
|
||||
};
|
||||
// 将对表格的修改统一发送
|
||||
const sendTable = () => {
|
||||
if (!dataSource.value.length) {
|
||||
return message.info('没有任何数据可以提交');
|
||||
}
|
||||
state.setLoading(true);
|
||||
http
|
||||
.post(
|
||||
waterSys.submitTableData +
|
||||
`?projectId=${state.projectId}${state.siteId ? `&siteId=${state.siteId}` : ''}`,
|
||||
dataSource.value,
|
||||
)
|
||||
.then((res) => {
|
||||
state.setLoading(false);
|
||||
if (res.retcode == 0) {
|
||||
message.success('操作成功');
|
||||
// 刷新数据
|
||||
emit('resetAll');
|
||||
} else {
|
||||
message.info(res.msg);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
state.setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
// 计划表格
|
||||
getTable();
|
||||
// 穿梭框原始数据
|
||||
getLeftPlan();
|
||||
};
|
||||
|
||||
// tab页弹窗部分 ====================================================
|
||||
|
||||
// 添加弹窗控制变量
|
||||
const addVisible = ref(false);
|
||||
// 打开弹窗
|
||||
const addModal = () => {
|
||||
addVisible.value = true;
|
||||
};
|
||||
|
||||
// 穿梭框部分 =======================================================
|
||||
|
||||
// 穿梭框数据
|
||||
const transferData = ref([]) as any;
|
||||
// 获得穿梭框原始数据
|
||||
const getLeftPlan = () => {
|
||||
http
|
||||
.get(planManage.getTransData, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
// 设备类型(1照明,2空调,3排风扇,4风幕机,5电动窗,6给排水)
|
||||
ctrlType: 6,
|
||||
})
|
||||
.then((res) => {
|
||||
let arr: Array<Object> = [];
|
||||
res.data.forEach((item: any) => {
|
||||
arr.push({
|
||||
key: item.id,
|
||||
title: item.planName,
|
||||
});
|
||||
});
|
||||
transferData.value = arr;
|
||||
});
|
||||
};
|
||||
|
||||
const handleChange = (keys: string[], direction: string, moveKeys: string[]) => {
|
||||
console.log(keys, direction, moveKeys);
|
||||
};
|
||||
const handleSearch = (dir: string, value: string) => {
|
||||
console.log('search:', dir, value);
|
||||
};
|
||||
// 穿梭框选中数据
|
||||
const targetKeys = ref<string[]>([]);
|
||||
// 将穿梭框选中的计划提交
|
||||
const sendPlan = () => {
|
||||
if (targetKeys.value.length < 1) {
|
||||
return message.info('没有选择任何计划');
|
||||
}
|
||||
http.post(planManage.submitTransData, targetKeys.value).then(() => {
|
||||
message.success('添加成功');
|
||||
// 如果发送成功,则刷新表格
|
||||
reset();
|
||||
});
|
||||
};
|
||||
|
||||
const filterOption = (inputValue: string, option: any) => {
|
||||
return option.description.indexOf(inputValue) > -1;
|
||||
};
|
||||
|
||||
// 向外暴露方法
|
||||
defineExpose({
|
||||
reset,
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import '../../style/dialogStyle.less';
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.plan {
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
border-radius: 5px;
|
||||
width: 88px;
|
||||
height: 32px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
margin: 15px 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.plan.enabled {
|
||||
background: linear-gradient(180deg, rgba(103, 222, 0, 1) 0%, rgba(0, 181, 6, 1) 100%);
|
||||
}
|
||||
.plan.disabled {
|
||||
background-color: red;
|
||||
}
|
||||
.plan:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
// 右下角添加按钮
|
||||
.div-add {
|
||||
height: 64px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin-right: 10px;
|
||||
.add {
|
||||
width: 74px;
|
||||
height: 40px;
|
||||
opacity: 1;
|
||||
border-radius: 4px;
|
||||
background: rgba(67, 136, 251, 1);
|
||||
border: rgba(67, 136, 251, 1);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
// 表格
|
||||
.custom-table {
|
||||
border-collapse: collapse;
|
||||
width: 416px;
|
||||
height: 40px;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
.custom-table th,
|
||||
.custom-table td {
|
||||
border: 1px solid rgba(163, 192, 243, 1);
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
.table1 {
|
||||
width: 100%;
|
||||
border: 1px solid rgba(255, 255, 255);
|
||||
border-radius: 5px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
// 表格中的操作按钮
|
||||
.tabReboot,
|
||||
.tabDelete {
|
||||
border: none;
|
||||
display: inline-block;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
line-height: 20px;
|
||||
color: rgba(67, 136, 251, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
.tabReboot {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.tabReboot::active {
|
||||
color: white !important;
|
||||
}
|
||||
.tabDelete::active {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
::v-deep(.ant-transfer) {
|
||||
// 屏蔽自带的hover效果
|
||||
.ant-transfer-list-content-item:hover {
|
||||
background: black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,282 @@
|
||||
import { ref } from 'vue';
|
||||
// 流动线条样式与定位
|
||||
export const linePosition = [
|
||||
// 雨水池 - 控制阀
|
||||
{
|
||||
left: '4%',
|
||||
top: '44%',
|
||||
transform: 'rotateZ(-30deg)',
|
||||
transformOrigin: 'left',
|
||||
zIndex: '6',
|
||||
width: '6%',
|
||||
},
|
||||
{
|
||||
left: '4%',
|
||||
top: '84%',
|
||||
transform: 'rotateZ(-30deg)',
|
||||
transformOrigin: 'left',
|
||||
zIndex: '6',
|
||||
width: '6%',
|
||||
},
|
||||
// 控制阀 - 进水阀
|
||||
{ left: '12%', top: '34%', width: '10%' },
|
||||
{ left: '12%', top: '74%', width: '10%' },
|
||||
// 进水阀 - 集水池
|
||||
{ left: '23%', top: '34%', width: '8%' },
|
||||
{ left: '23%', top: '74%', width: '8%' },
|
||||
// 集水池 - 排水泵 - 横线
|
||||
{ left: '35%', top: '34%', width: '4%' },
|
||||
{ left: '35%', top: '74%', width: '4%' },
|
||||
// 上半集水池右侧分线
|
||||
{ left: '39%', top: '34%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '4%' },
|
||||
{ left: '39%', top: '34%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '4%' },
|
||||
// 下半集水池右侧分线
|
||||
{ left: '39%', top: '74%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '4%' },
|
||||
{ left: '39%', top: '74%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '4%' },
|
||||
// 上半-左侧水泵分线
|
||||
{ left: '39%', top: '25%', width: '8%' },
|
||||
{ left: '39%', top: '43%', width: '8%' },
|
||||
// 下半-左侧水泵分线
|
||||
{ left: '39%', top: '65%', width: '8%' },
|
||||
{ left: '39%', top: '83%', width: '8%' },
|
||||
// 水泵右侧合线 下半
|
||||
{ left: '47%', top: '83%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '14%' },
|
||||
// 水泵右侧合线 上半
|
||||
{ left: '47%', top: '25%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '12%' },
|
||||
// 汇入总闸连线
|
||||
{ left: '47%', top: '52%', width: '4%' },
|
||||
// 汇入总集水池
|
||||
{ left: '51%', top: '52%', transform: 'rotateZ(-25deg)', transformOrigin: 'left', width: '7%' },
|
||||
// 汇入总排水闸
|
||||
{ left: '58%', top: '45%', width: '9%' },
|
||||
// 汇入市政管道 - 途径水泵2
|
||||
{ left: '68%', top: '45%', width: '28%' },
|
||||
// 总排水闸 - 总排水泵1 上半
|
||||
{ left: '75%', top: '45%', transform: 'rotateZ(-90deg)', transformOrigin: 'left', width: '10%' },
|
||||
{ left: '75%', top: '23%', width: '11%' },
|
||||
{ left: '86%', top: '22.5%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '10%' },
|
||||
// 总排水闸 - 总排水泵3 下半
|
||||
{ left: '75%', top: '45%', transform: 'rotateZ(90deg)', transformOrigin: 'left', width: '9%' },
|
||||
{ left: '75%', top: '65%', width: '11%' },
|
||||
{
|
||||
left: '86%',
|
||||
top: '65%',
|
||||
transform: 'rotateZ(-90deg)',
|
||||
transformOrigin: 'left',
|
||||
width: '9%',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 1. 设备数量是固定的
|
||||
* 2. 设备顺序是固定的
|
||||
* 3. 此处数据用于渲染设备图标,后端返回数据后,将依次插入
|
||||
* @param icon 决定调用的设备图标:污水池=1/集水池=2/控制阀=3//进水阀=4//排水泵=5
|
||||
* @param type 设备类型:污水池=1/阀门=2/集水池=3/水泵=4
|
||||
* @param open 水泵的开关状态 开=true/关=false
|
||||
* @param control 是否可以被操作(是否显示顶部按钮,水池为false)
|
||||
* @param edited 是否已经被编辑(决定显示编辑 或 撤销)
|
||||
*/
|
||||
// 污水池
|
||||
export const device1 = ref([
|
||||
{
|
||||
control: false,
|
||||
type: 1,
|
||||
icon: 1,
|
||||
styleObject: {
|
||||
left: '1%',
|
||||
top: '40%',
|
||||
zIndex: '9',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: false,
|
||||
type: 1,
|
||||
icon: 1,
|
||||
styleObject: {
|
||||
left: '1%',
|
||||
top: '80%',
|
||||
zIndex: '9',
|
||||
},
|
||||
},
|
||||
]);
|
||||
// 阀门
|
||||
export const device2 = ref([
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 2,
|
||||
icon: 3,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '8%',
|
||||
top: '28%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: false,
|
||||
type: 2,
|
||||
icon: 3,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '8%',
|
||||
top: '68%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 2,
|
||||
icon: 4,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '20%',
|
||||
top: '28%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 2,
|
||||
icon: 4,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '20%',
|
||||
top: '68%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 2,
|
||||
icon: 3,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '48%',
|
||||
top: '46%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 2,
|
||||
icon: 3,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '65%',
|
||||
top: '38%',
|
||||
},
|
||||
},
|
||||
]);
|
||||
// 集水池
|
||||
export const device3 = ref([
|
||||
{
|
||||
control: false,
|
||||
type: 3,
|
||||
icon: 2,
|
||||
styleObject: {
|
||||
left: '30%',
|
||||
top: '68%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: false,
|
||||
type: 3,
|
||||
icon: 2,
|
||||
styleObject: {
|
||||
left: '30%',
|
||||
top: '28%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: false,
|
||||
type: 3,
|
||||
icon: 2,
|
||||
styleObject: {
|
||||
left: '56%',
|
||||
top: '40%',
|
||||
},
|
||||
},
|
||||
]);
|
||||
// 水泵
|
||||
export const device4 = ref([
|
||||
{
|
||||
control: true,
|
||||
open: false,
|
||||
type: 4,
|
||||
icon: 5,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '40%',
|
||||
top: '20%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 4,
|
||||
icon: 5,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '40%',
|
||||
top: '40%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 4,
|
||||
icon: 5,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '40%',
|
||||
top: '60%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 4,
|
||||
icon: 5,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '40%',
|
||||
top: '80%',
|
||||
},
|
||||
},
|
||||
// 右上3水泵
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 4,
|
||||
icon: 5,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '78%',
|
||||
top: '20%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 4,
|
||||
icon: 5,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '78%',
|
||||
top: '40%',
|
||||
},
|
||||
},
|
||||
{
|
||||
control: true,
|
||||
open: true,
|
||||
type: 4,
|
||||
icon: 5,
|
||||
edited: false,
|
||||
styleObject: {
|
||||
left: '78%',
|
||||
top: '60%',
|
||||
},
|
||||
},
|
||||
]);
|
||||
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<div class="left-top">
|
||||
<div class="info">
|
||||
<div class="title-item">
|
||||
<div class="title-back">设备状态</div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div v-for="(item, index) in deviceState" :key="index">
|
||||
<img v-if="item.type == props.state" :src="item.icon" alt="" />
|
||||
<img v-else :src="item.default" alt="" />
|
||||
<div class="mode-item-text">{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mode">
|
||||
<div class="title-item">
|
||||
<div class="title-back">控制模式</div>
|
||||
<div class="title-button">计划启用</div>
|
||||
</div>
|
||||
<div class="mode-item"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
// 全局变量
|
||||
import { items } from '/@/store/item';
|
||||
// 图像资源引入
|
||||
import type1 from './images/type1.png';
|
||||
import type2 from './images/type2.png';
|
||||
import type3 from './images/type3.png';
|
||||
import type1off from './images/type1off.png';
|
||||
import type2off from './images/type2off.png';
|
||||
import type3off from './images/type3off.png';
|
||||
// 传入的值
|
||||
const props = defineProps({
|
||||
// 设备状态
|
||||
state: {
|
||||
type: Number,
|
||||
},
|
||||
});
|
||||
const deviceState = [
|
||||
{
|
||||
icon: type1,
|
||||
default: type1off,
|
||||
name: '运行',
|
||||
type: 1,
|
||||
},
|
||||
{
|
||||
icon: type2,
|
||||
default: type2off,
|
||||
name: '故障',
|
||||
type: 2,
|
||||
},
|
||||
{
|
||||
icon: type3,
|
||||
default: type3off,
|
||||
name: '强排',
|
||||
type: 3,
|
||||
},
|
||||
];
|
||||
//页面 创建
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.left-top {
|
||||
--pad: 12px;
|
||||
position: absolute;
|
||||
left: var(--pad);
|
||||
top: var(--pad);
|
||||
width: auto;
|
||||
height: 110px;
|
||||
display: flex;
|
||||
z-index: 99;
|
||||
gap: var(--pad);
|
||||
> div {
|
||||
background: black;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
.title-item {
|
||||
padding: 5px;
|
||||
position: relative;
|
||||
.title-back {
|
||||
margin-left: 10px;
|
||||
padding-left: 5px;
|
||||
background: linear-gradient(to right, #1aaefb, transparent);
|
||||
width: 7em;
|
||||
color: white;
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.title-back::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
display: block;
|
||||
width: 5px;
|
||||
height: 100%;
|
||||
left: -12px;
|
||||
background: #1aaefb;
|
||||
}
|
||||
.title-button {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
padding: 3px 8px;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(180deg, rgba(103, 222, 0, 1) 0%, rgba(0, 181, 6, 1) 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设备状态
|
||||
.info {
|
||||
width: 230px;
|
||||
.info-item {
|
||||
display: flex;
|
||||
padding-top: 3px;
|
||||
div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
.mode-item-text {
|
||||
color: white;
|
||||
user-select: none;
|
||||
}
|
||||
img {
|
||||
width: 23px;
|
||||
display: block;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 控制模式
|
||||
.mode {
|
||||
width: 200px;
|
||||
.mode-item {
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<div class="deviceItem" :style="info.styleObject">
|
||||
<!-- 点击编辑弹出框 -->
|
||||
<a-popover
|
||||
color="rgba(0, 0, 0, 0.8)"
|
||||
placement="right"
|
||||
v-model:visible="visible"
|
||||
trigger="click">
|
||||
<template #content>
|
||||
<div class="item-box">
|
||||
<div class="item-box-title">
|
||||
<img v-if="info.type == 2" src="./images/device1.png" alt="" />
|
||||
<img v-if="info.type == 4" src="./images/device2.png" alt="" />
|
||||
<span>{{ info.name }}</span>
|
||||
</div>
|
||||
<!-- 开关 -->
|
||||
<div v-if="info.type == 4" class="item-box-switch">
|
||||
<div>开关</div>
|
||||
<a-switch style="margin-top: 3px" size="small" v-model:checked="info.open" />
|
||||
</div>
|
||||
<div v-if="info.type == 2" class="item-box-range">
|
||||
<div>开度</div>
|
||||
<!-- <a-slider v-model:value="info.value" :tooltip-visible="true" :marks="range" :step="1"> -->
|
||||
<a-slider v-model:value="info.value" :marks="range" :step="1">
|
||||
<template #mark="{ label, point }">
|
||||
<template v-if="point === 100">
|
||||
<strong>{{ label }}</strong>
|
||||
</template>
|
||||
<template v-else>{{ label }}</template>
|
||||
</template>
|
||||
</a-slider>
|
||||
</div>
|
||||
<div v-if="info.type == 4" class="item-box-range">
|
||||
<div>频率</div>
|
||||
<a-slider v-model:value="info.value" :marks="range" :step="1">
|
||||
<template #mark="{ label, point }">
|
||||
<template v-if="point === 100">
|
||||
<strong>{{ label }}</strong>
|
||||
</template>
|
||||
<template v-else>{{ label }}</template>
|
||||
</template>
|
||||
</a-slider>
|
||||
</div>
|
||||
<div class="item-box-button">
|
||||
<a-button class="item-btn" @click="refresh">刷新</a-button>
|
||||
<a-popconfirm
|
||||
title="此操作只保存修改,需右下角按钮提交"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="editDevice">
|
||||
<a-button class="item-btn" type="primary">执行</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="!info.edited && info.control" class="device-button-back">
|
||||
<img src="./images/edit.png" alt="" />
|
||||
编辑</div
|
||||
>
|
||||
</a-popover>
|
||||
|
||||
<a-popconfirm
|
||||
title="撤销将移除已保存的修改"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
@confirm="backConfirm">
|
||||
<div v-if="info.edited && info.control" class="device-button">
|
||||
<img src="./images/back.png" alt="" />
|
||||
撤销</div
|
||||
>
|
||||
</a-popconfirm>
|
||||
<!-- 设备图标 - 当前共5种单位 -->
|
||||
<img v-if="info.icon == 1" src="./images/pond1.png" alt="" />
|
||||
<img v-if="info.icon == 2" src="./images/pond2.png" alt="" />
|
||||
<img v-if="info.icon == 3" src="./images/valve1.png" alt="" />
|
||||
<img v-if="info.icon == 4" src="./images/valve2.png" alt="" />
|
||||
<img v-if="info.icon == 5" style="width: 70px; height: 70px" src="./images/pump.png" alt="" />
|
||||
<div class="info-name">
|
||||
<span>{{ info.name }}</span>
|
||||
<div class="img-box">
|
||||
<img
|
||||
v-if="(info.type == 2 || info.type == 4) && info.state == 0"
|
||||
src="./images/alarm1.png"
|
||||
alt="" />
|
||||
<img
|
||||
v-if="(info.type == 2 || info.type == 4) && info.state > 0"
|
||||
src="./images/alarm2.png"
|
||||
alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 只有水池会显示容量 -->
|
||||
<div class="info-value" v-if="info.type == 1 || info.type == 3">
|
||||
容量 : {{ info.value + info.unit }}</div
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
// 图像资源引入
|
||||
|
||||
// 初始化 ===============================================================
|
||||
|
||||
//页面 创建
|
||||
onMounted(() => {});
|
||||
// 传入的值
|
||||
const props = defineProps({
|
||||
// 设备类型
|
||||
info: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
// 父组件传递的数据
|
||||
const info = computed(() => props.info);
|
||||
|
||||
// 组件交互 =============================================================
|
||||
|
||||
// 用于控制弹窗的显示状态
|
||||
const visible = ref(false);
|
||||
// 滑动条显示规则
|
||||
const range = ref({
|
||||
0: {
|
||||
style: {
|
||||
color: '#0DFFFF',
|
||||
},
|
||||
label: 'min',
|
||||
},
|
||||
100: {
|
||||
style: {
|
||||
color: '#0DFFFF',
|
||||
},
|
||||
label: 'max',
|
||||
},
|
||||
});
|
||||
// 刷新事件
|
||||
const refresh = () => {
|
||||
info.value.value = info.value.oldVal;
|
||||
};
|
||||
// 撤销事件
|
||||
const backConfirm = () => {
|
||||
info.value.value = info.value.oldVal;
|
||||
info.value.edited = false;
|
||||
// 如果为水泵
|
||||
if (info.value.type == 4) {
|
||||
console.log(info.value);
|
||||
info.value.open = info.value.opened;
|
||||
}
|
||||
};
|
||||
// 编辑-执行事件
|
||||
const editDevice = () => {
|
||||
// 未产生修改
|
||||
if (info.value.value == info.value.oldVal && info.value.open === info.value.opened) {
|
||||
return message.info('未产生任何修改');
|
||||
}
|
||||
// 产生修改
|
||||
visible.value = false;
|
||||
info.value.edited = true;
|
||||
message.success('保存成功');
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
// 设备的图像
|
||||
.deviceItem {
|
||||
--size: 90px;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
text-align: center;
|
||||
// 默认使用3
|
||||
z-index: 3;
|
||||
> img {
|
||||
user-select: none;
|
||||
}
|
||||
// 设备名
|
||||
.info-name {
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
> span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.img-box {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
margin-left: 8px;
|
||||
width: 22px;
|
||||
> img {
|
||||
width: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 设备容量(仅水池)
|
||||
.info-value {
|
||||
text-align: center;
|
||||
color: #23fdab;
|
||||
font-size: 13px;
|
||||
}
|
||||
// 撤销按钮
|
||||
.device-button {
|
||||
position: absolute;
|
||||
top: -35px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 5em;
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(#ffd700, #ffa403);
|
||||
color: #674330;
|
||||
user-select: none;
|
||||
> img {
|
||||
width: 13px;
|
||||
}
|
||||
}
|
||||
// 编辑按钮
|
||||
.device-button-back {
|
||||
position: absolute;
|
||||
top: -35px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 5em;
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
border-radius: 4px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(#00f92c, #00fe9f);
|
||||
color: #003d5a;
|
||||
user-select: none;
|
||||
> img {
|
||||
width: 13px;
|
||||
}
|
||||
}
|
||||
> img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
// 弹出框样式
|
||||
.ant-popover-inner {
|
||||
// 弹出框内部容器
|
||||
.item-box {
|
||||
width: 250px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
color: white;
|
||||
img {
|
||||
width: 20px;
|
||||
margin-right: 10px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
// 开关控件
|
||||
.item-box-switch {
|
||||
padding: 10px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-radius: 4px;
|
||||
background: rgba(67, 136, 251, 0.3);
|
||||
.ant-switch-checked {
|
||||
background: linear-gradient(180deg, rgba(1, 206, 255, 1) 0%, rgba(0, 150, 229, 1) 100%);
|
||||
}
|
||||
}
|
||||
// 滑动条控件
|
||||
.item-box-range {
|
||||
padding: 10px 15px 10px 15px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
background: rgba(67, 136, 251, 0.3);
|
||||
.ant-slider-handle {
|
||||
border: 2px solid red !important;
|
||||
}
|
||||
}
|
||||
// 底部按钮区
|
||||
.item-box-button {
|
||||
text-align: right;
|
||||
.item-btn {
|
||||
text-align: center;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="line-item" :style="position"></div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
// 传入的值
|
||||
const props = defineProps({
|
||||
// 线条
|
||||
position: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
const position = computed(() => {
|
||||
return props.position;
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.line-item {
|
||||
position: absolute;
|
||||
height: 10px;
|
||||
width: 250px;
|
||||
z-index: 1;
|
||||
background-image: url(./images/back.gif);
|
||||
background-color: rgba(13, 255, 164, 0.3);
|
||||
background-size: 200px 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,663 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<!-- 左上角设备信息面板 -->
|
||||
<deviceInfo :state="deviceState" />
|
||||
<!-- 示意图 -->
|
||||
<div class="map">
|
||||
<!-- 污水池图标 -->
|
||||
<deviceItem v-for="(item, index) in device1" :key="index" :info="item" />
|
||||
<!-- 阀门图标 -->
|
||||
<deviceItem v-for="(item, index) in device2" :key="index" :info="item" />
|
||||
<!-- 集水池图标 -->
|
||||
<deviceItem v-for="(item, index) in device3" :key="index" :info="item" />
|
||||
<!-- 排水泵图标 -->
|
||||
<deviceItem v-for="(item, index) in device4" :key="index" :info="item" />
|
||||
<!-- 市政管道图标 -->
|
||||
<div class="pipe">
|
||||
<div>市政管道</div>
|
||||
<img src="./images/pipe.png" alt="" />
|
||||
</div>
|
||||
<!-- 设备图标底部连线 -->
|
||||
<deviceLine v-for="(item, index) in linePosition" :key="index" :position="item" />
|
||||
</div>
|
||||
<!-- 右下角按钮 -->
|
||||
<div class="buttons">
|
||||
<a-button type="primary" @click="openDrawer1">执行</a-button>
|
||||
<a-button type="primary" @click="resetAll">全部撤销</a-button>
|
||||
</div>
|
||||
<!-- 页面右侧抽屉开关 -->
|
||||
<div class="right-button">
|
||||
<div>计划与日志</div>
|
||||
<img @click="visible = true" src="./images/open.png" alt="" />
|
||||
</div>
|
||||
<!-- 右侧 计划日志抽屉 -->
|
||||
<a-drawer
|
||||
v-model:visible="visible"
|
||||
class="drawer-item"
|
||||
width="496"
|
||||
placement="right"
|
||||
:body-style="{ background: 'rgba(0, 0, 0)', opacity: 0.8 }"
|
||||
:closable="false"
|
||||
id="drawer"
|
||||
:maskStyle="{ 'background-color': 'rgba(0, 0, 0, 0)' }">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="计划列表" force-render>
|
||||
<planTab ref="tabs1Ref" @reset-all="resetDrawer" />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="日志">
|
||||
<logTab ref="tabs2Ref" @reset-all="resetDrawer" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-drawer>
|
||||
<!-- 右侧 操作队列 -->
|
||||
<a-drawer
|
||||
v-model:visible="visible1"
|
||||
class="drawer-item"
|
||||
width="496"
|
||||
placement="right"
|
||||
:body-style="{ background: 'rgba(0, 0, 0)', opacity: 0.8 }"
|
||||
:closable="false"
|
||||
id="drawer"
|
||||
:maskStyle="{ 'background-color': 'rgba(0, 0, 0, 0)' }">
|
||||
<a-tabs v-model:activeKey="activeKey1">
|
||||
<a-tab-pane key="1" tab="操作队列" force-render>
|
||||
<div>
|
||||
<a-badge :offset="[-5, 12]" :count="valveList.length">
|
||||
<button :class="{ btn: true, selected: activeButton == 1 }" @click="changeBtn(1)"
|
||||
>阀门</button
|
||||
>
|
||||
</a-badge>
|
||||
<a-badge :offset="[-5, 12]" :count="pumpList.length">
|
||||
<button :class="{ btn: true, selected: activeButton == 2 }" @click="changeBtn(2)"
|
||||
>水泵</button
|
||||
>
|
||||
</a-badge>
|
||||
</div>
|
||||
<div class="device-list" v-if="activeButton == 1">
|
||||
<div class="device-list-item" v-for="(item, index) in valveList" :key="index">
|
||||
<div class="list-item-title">
|
||||
<div class="item-title">
|
||||
<img src="./images/device1.png" alt="" />
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="revoke" @click="revoke(item.id, index, 1)">撤销</div>
|
||||
</div>
|
||||
<div class="list-item-main">
|
||||
<div>
|
||||
<div class="info">开度</div>
|
||||
<div class="text">
|
||||
<span>{{ item.oldVal + item.unit }}</span>
|
||||
<img src="/asset/image/bulbLogo/22406.png" alt="" />
|
||||
<span>{{ item.value + item.unit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
<a-empty style="margin-top: 100px" v-if="valveList.length == 0">
|
||||
<template #description> <span style="color: white">暂无数据</span></template>
|
||||
</a-empty>
|
||||
</div>
|
||||
<div class="device-list" v-if="activeButton == 2">
|
||||
<div class="device-list-item" v-for="(item, index) in pumpList" :key="index">
|
||||
<div class="list-item-title">
|
||||
<div class="item-title">
|
||||
<img src="./images/device2.png" alt="" />
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="revoke" @click="revoke(item.id, index, 2)">撤销</div>
|
||||
</div>
|
||||
<div class="list-item-main">
|
||||
<div>
|
||||
<div class="info">频率</div>
|
||||
<div class="text">
|
||||
<span>{{ item.oldVal + item.unit }}</span>
|
||||
<img src="/asset/image/bulbLogo/22406.png" alt="" />
|
||||
<span>{{ item.value + item.unit }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="info">开关</div>
|
||||
<div class="text">
|
||||
<span>{{ item.opened ? '开' : '关' }}</span>
|
||||
<img src="/asset/image/bulbLogo/22406.png" alt="" />
|
||||
<span>{{ item.open == 1 ? '开' : '关' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-empty style="margin-top: 100px" v-if="pumpList.length == 0">
|
||||
<template #description> <span style="color: white">暂无数据</span></template>
|
||||
</a-empty>
|
||||
</div>
|
||||
<div style="width: 100%; height: 100px"></div>
|
||||
<div class="button-box">
|
||||
<button class="cancel" @click="visible1 = false">取消</button>
|
||||
<a-popconfirm
|
||||
title="此操作将提交以上修改内容"
|
||||
ok-text="确定"
|
||||
cancel-text="取消"
|
||||
placement="bottomRight"
|
||||
@confirm="submitChange">
|
||||
<button class="execute">执行</button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-drawer>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { Modal, message } from 'ant-design-vue';
|
||||
|
||||
import deviceInfo from './deviceInfo.vue';
|
||||
import deviceLine from './deviceLine.vue';
|
||||
import deviceItem from './deviceItem.vue';
|
||||
import planTab from './component/planTab.vue';
|
||||
import logTab from './component/logTab.vue';
|
||||
import { linePosition, device1, device2, device3, device4 } from './device';
|
||||
// 网络请求
|
||||
import { http } from '/nerv-lib/util/http';
|
||||
import { waterSys } from '/@/api/waterSystem';
|
||||
// 全局变量
|
||||
import { items } from '/@/store/item';
|
||||
|
||||
// 初始化 ===========================================================================================
|
||||
|
||||
const state = items();
|
||||
onMounted(() => {
|
||||
// 获得所有设备状态
|
||||
getAllDevice();
|
||||
});
|
||||
const deviceState = 1;
|
||||
|
||||
// 计划与日志 抽屉业务 =========================================================================================
|
||||
|
||||
// 计划与日志
|
||||
const visible = ref(false);
|
||||
// 当前选中的tab
|
||||
const activeKey = ref('1');
|
||||
|
||||
// 执行 抽屉业务 =========================================================================================
|
||||
|
||||
// 执行
|
||||
const visible1 = ref(false);
|
||||
// 当前选中的tab
|
||||
const activeKey1 = '1';
|
||||
// 当前选中的设备类型 阀门=1/水泵=2
|
||||
const activeButton = ref(1);
|
||||
// 切换设备类型
|
||||
const changeBtn = (key: number) => {
|
||||
activeButton.value = key;
|
||||
};
|
||||
// 当前修改的水泵数据
|
||||
const pumpList = ref<any>([]);
|
||||
// 当前修改的水阀数据
|
||||
const valveList = ref<any>([]);
|
||||
|
||||
// 打开右侧抽屉
|
||||
const openDrawer1 = () => {
|
||||
valveList.value = device2.value.filter((item: any) => {
|
||||
return item.edited;
|
||||
});
|
||||
pumpList.value = device4.value.filter((item: any) => {
|
||||
return item.edited;
|
||||
});
|
||||
if (valveList.value.length || pumpList.value.length) {
|
||||
visible1.value = true;
|
||||
} else {
|
||||
message.info('未产生任何修改');
|
||||
}
|
||||
};
|
||||
// 右侧抽屉 - 撤回
|
||||
const revoke = (id: any, index: number, type: number) => {
|
||||
if (type == 1) {
|
||||
valveList.value.splice(index, 1);
|
||||
device2.value.forEach((item: any) => {
|
||||
if (item.id == id) {
|
||||
item.value = item.oldVal;
|
||||
item.edited = false;
|
||||
}
|
||||
});
|
||||
} else if (type == 2) {
|
||||
pumpList.value.splice(index, 1);
|
||||
device4.value.forEach((item: any) => {
|
||||
if (item.id == id) {
|
||||
item.value = item.oldVal;
|
||||
item.open = item.opened;
|
||||
item.edited = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
const submitChange = () => {
|
||||
let valveList = [];
|
||||
device2.value.forEach((item: any) => {
|
||||
if (item.edited) {
|
||||
valveList.push({
|
||||
deviceGroup: item.id,
|
||||
openPercent: item.value,
|
||||
});
|
||||
}
|
||||
});
|
||||
let pumpList = [];
|
||||
device4.value.forEach((item: any) => {
|
||||
if (item.edited) {
|
||||
pumpList.push({
|
||||
deviceGroup: item.id,
|
||||
frequency: item.value,
|
||||
switchStatus: +item.open,
|
||||
});
|
||||
}
|
||||
});
|
||||
state.setLoading(true);
|
||||
http
|
||||
.post(waterSys.submitList, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
valveList,
|
||||
pumpList,
|
||||
})
|
||||
.then((res) => {
|
||||
let data = res.data;
|
||||
state.setLoading(false);
|
||||
// 修改请求发送了,但操作时产生了失败结果
|
||||
if (res.retcode != 0) {
|
||||
// 直接提示并跳出
|
||||
return message.warning(res.msg);
|
||||
}
|
||||
// 所有修改均生效
|
||||
if (data.allSucceed) {
|
||||
message.success('修改完成');
|
||||
// allSucceed不为true,则至少有一条数据修改失败
|
||||
} else {
|
||||
message.info(`${data.successList.length}条修改成功,${data.failList.length}条修改失败`);
|
||||
}
|
||||
// 将所有已修改状态的数据还原
|
||||
resetEdit();
|
||||
visible1.value = false;
|
||||
getAllDevice();
|
||||
});
|
||||
};
|
||||
|
||||
const resetEdit = () => {
|
||||
device2.value.forEach((item) => {
|
||||
item.edited = false;
|
||||
});
|
||||
device4.value.forEach((item) => {
|
||||
item.edited = false;
|
||||
});
|
||||
};
|
||||
|
||||
// 设备数据业务 ==========================================================================================
|
||||
|
||||
// 当其中一个tab产生了数据修改,可以调用该方法重置所有tab
|
||||
const resetDrawer = () => {
|
||||
try {
|
||||
// tab1重置
|
||||
tabs1Ref.value.reset();
|
||||
} catch {}
|
||||
try {
|
||||
// tab2重置
|
||||
tabs2Ref.value.reset();
|
||||
} catch {}
|
||||
};
|
||||
// 抽屉tab1组件的引用
|
||||
const tabs1Ref = ref();
|
||||
// 抽屉tab2组件的引用
|
||||
const tabs2Ref = ref();
|
||||
// 撤销所有修改
|
||||
const resetAll = () => {
|
||||
Modal.confirm({
|
||||
title: '提示信息',
|
||||
content: '该操作将还原已编辑内容',
|
||||
onOk() {
|
||||
// 水阀
|
||||
device2.value.forEach((item: any) => {
|
||||
if (item.edited) {
|
||||
item.value = item.oldVal;
|
||||
item.edited = false;
|
||||
}
|
||||
});
|
||||
// 水泵 水泵包含
|
||||
device4.value.forEach((item: any) => {
|
||||
if (item.edited) {
|
||||
item.value = item.oldVal;
|
||||
item.open = item.opened;
|
||||
item.edited = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel() {},
|
||||
});
|
||||
};
|
||||
// 获得所有设备状态
|
||||
const getAllDevice = () => {
|
||||
getDevice(1);
|
||||
getDevice(2);
|
||||
getDevice(3);
|
||||
getDevice(4);
|
||||
};
|
||||
/**
|
||||
* 获取一个设备类型的数据
|
||||
* @param type 污水池=1/阀门=2/集水池=3/水泵=4
|
||||
*/
|
||||
const getDevice = (type: number) => {
|
||||
// 请求地址
|
||||
let url = '';
|
||||
if (type == 1) {
|
||||
url = waterSys.getPool1;
|
||||
} else if (type == 2) {
|
||||
url = waterSys.getValve;
|
||||
} else if (type == 3) {
|
||||
url = waterSys.getPool2;
|
||||
} else if (type == 4) {
|
||||
url = waterSys.getPump;
|
||||
}
|
||||
http
|
||||
.get(url, {
|
||||
projectId: state.projectId,
|
||||
siteId: state.siteId,
|
||||
})
|
||||
.then((res) => {
|
||||
let data = res.data;
|
||||
// 污水池数据
|
||||
if (type == 1) {
|
||||
device1.value.forEach((item: any, index: number) => {
|
||||
let result = data[index];
|
||||
// 污水池名称
|
||||
item.name = result.deviceInfoName;
|
||||
// 污水池容量
|
||||
item.value = result.record.capacity ? result.record.capacity : '--';
|
||||
// 单位
|
||||
item.unit = result.record.capacityUnit ? result.record.capacityUnit : '';
|
||||
});
|
||||
}
|
||||
// 阀门数据
|
||||
if (type == 2) {
|
||||
device2.value.forEach((item: any, index: number) => {
|
||||
let result = data[index];
|
||||
// 阀门名称
|
||||
item.name = result.deviceGroupName;
|
||||
// 阀门ID
|
||||
item.id = result.deviceGroup;
|
||||
// 编辑状态重置
|
||||
item.edited = false;
|
||||
// 设备状态(是否正常)
|
||||
item.state = result.record.runStatus.value != null ? result.record.runStatus.value : -1;
|
||||
// 开度-新值
|
||||
item.value = result.record.openPercent ? result.record.openPercent : 0;
|
||||
// 开度-旧值(用于判断旧值是否被修改)
|
||||
item.oldVal = result.record.openPercent ? result.record.openPercent : null;
|
||||
// 单位
|
||||
item.unit = result.record.openPercentUnit ? result.record.openPercentUnit : '';
|
||||
});
|
||||
}
|
||||
// 集水池数据
|
||||
if (type == 3) {
|
||||
device3.value.forEach((item: any, index: number) => {
|
||||
let result = data[index];
|
||||
// 集水池名称
|
||||
item.name = result.deviceInfoName;
|
||||
// 集水池容量
|
||||
item.value = result.record.capacity ? result.record.capacity : '--';
|
||||
// 单位
|
||||
item.unit = result.record.capacityUnit ? result.record.capacityUnit : '';
|
||||
});
|
||||
}
|
||||
// 水泵数据
|
||||
if (type == 4) {
|
||||
device4.value.forEach((item: any, index: number) => {
|
||||
let result = data[index];
|
||||
// 水泵名称
|
||||
item.name = result.deviceGroupName;
|
||||
// 水泵ID
|
||||
item.id = result.deviceGroup;
|
||||
// 编辑状态重置
|
||||
item.edited = false;
|
||||
// 水泵的开启状态-新值
|
||||
item.open = result.record.switchStatus.value == 1 ? true : false;
|
||||
// 水泵的开启状态-旧值(用于判断是否被修改)
|
||||
item.opened = result.record.switchStatus.value == 1 ? true : false;
|
||||
// 设备状态(是否正常)
|
||||
item.state = result.record.runStatus.value != null ? result.record.runStatus.value : -1;
|
||||
// 频率-新值
|
||||
item.value = result.record.frequency ? result.record.frequency : 0;
|
||||
// 频率-旧值(用于判断是否被修改)
|
||||
item.oldVal = result.record.frequency ? result.record.frequency : null;
|
||||
// 单位
|
||||
item.unit = result.record.frequencyUnit ? result.record.frequencyUnit : '';
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background: linear-gradient(to bottom, rgb(35, 102, 165), rgb(1, 19, 81));
|
||||
// 图例区域
|
||||
.map {
|
||||
width: 85vw;
|
||||
height: 38vw;
|
||||
position: relative;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
// 右侧 市政管道
|
||||
.pipe {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 92%;
|
||||
top: 40%;
|
||||
z-index: 3;
|
||||
transform: translateY(-60px);
|
||||
img {
|
||||
height: 100%;
|
||||
}
|
||||
div {
|
||||
width: inherit;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: -1.5em;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 右下角按钮
|
||||
.buttons {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
bottom: 15px;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
height: 40px;
|
||||
> button {
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
.right-button {
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 10px;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
z-index: 99;
|
||||
gap: 10px;
|
||||
color: #0dffff;
|
||||
> img {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 2px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
.drawer-item {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border: 2px solid red;
|
||||
}
|
||||
}
|
||||
// 抽屉顶部tab按钮样式
|
||||
:deep(.ant-tabs-tab-btn) {
|
||||
color: white;
|
||||
}
|
||||
.btn {
|
||||
width: 92px;
|
||||
height: 40px;
|
||||
border-radius: 4px;
|
||||
opacity: 1;
|
||||
margin-top: 10px;
|
||||
margin-left: 15px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
opacity: 1;
|
||||
border: 1px solid rgba(207, 212, 219, 1);
|
||||
line-height: 20.27px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.selected {
|
||||
background: linear-gradient(180deg, rgba(201, 245, 255, 1) 0%, rgba(138, 215, 255, 1) 100%);
|
||||
color: rgba(0, 61, 90, 1);
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: rgba(207, 212, 219, 1);
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
background-color: rgba(102, 102, 102, 1);
|
||||
color: white;
|
||||
}
|
||||
.device-list {
|
||||
margin-left: 15px;
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
flex-direction: column;
|
||||
.device-list-item {
|
||||
width: calc(100% - 15px);
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
border: 2px solid #03407e;
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 177, 255, 0.2);
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-direction: column;
|
||||
.list-item-title {
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.item-title {
|
||||
img {
|
||||
width: 25px;
|
||||
}
|
||||
span {
|
||||
margin-left: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
.revoke {
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 5px 15px;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(255, 187, 0, 1) 0%,
|
||||
rgba(255, 112, 3, 1) 91.21%,
|
||||
rgba(255, 129, 3, 1) 100%
|
||||
);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.list-item-main {
|
||||
display: flex;
|
||||
font-size: 13px;
|
||||
> div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
> .info {
|
||||
text-align: center;
|
||||
width: 6em;
|
||||
height: 2.5em;
|
||||
line-height: 2.5em;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(86, 221, 253, 1) 0%,
|
||||
rgba(25, 176, 255, 1) 100%
|
||||
);
|
||||
}
|
||||
> .text {
|
||||
:first-child {
|
||||
color: white;
|
||||
line-height: 2.5em;
|
||||
}
|
||||
img {
|
||||
padding: 0 5px;
|
||||
}
|
||||
:last-child {
|
||||
line-height: 2.5em;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-box {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
height: 60px;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
text-align: right;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
.execute,
|
||||
.cancel {
|
||||
margin-right: 10px;
|
||||
width: 74px;
|
||||
height: 40px;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
border: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.execute {
|
||||
background: rgb(67, 136, 251);
|
||||
color: white;
|
||||
}
|
||||
.cancel {
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -52,6 +52,10 @@
|
||||
if (graphRef.value) {
|
||||
graphRef.value.downloadChart();
|
||||
}
|
||||
} else {
|
||||
if (tableRef.value) {
|
||||
tableRef.value.export1();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { exportExcel } from '/@/util/ExcelUtil.js';
|
||||
import { defineComponent, watch, ref, onMounted } from 'vue';
|
||||
import type { TableColumnType } from 'ant-design-vue';
|
||||
import { Pagination } from 'ant-design-vue';
|
||||
@@ -245,6 +246,9 @@
|
||||
columns.value = columnA;
|
||||
total.value = dataList.value.length;
|
||||
onChange(1, 10);
|
||||
}; // 导出excel文件
|
||||
const export1 = () => {
|
||||
exportExcel(columns.value, dataList.value, '历史数据导出', true, 'deviceName', 1, 4);
|
||||
};
|
||||
onMounted(() => {
|
||||
init();
|
||||
@@ -257,6 +261,7 @@
|
||||
total,
|
||||
onChange,
|
||||
x,
|
||||
export1,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
:tree-data="treeData1"
|
||||
@change="changeDeviceType" />
|
||||
|
||||
<a-spin :spinning="treeLoading">
|
||||
<a-tree
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
:show-line="{ showLeafIcon: false }"
|
||||
checkable
|
||||
:height="560"
|
||||
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
|
||||
:tree-data="treeData2" />
|
||||
</a-spin>
|
||||
<!-- <a-spin :spinning="treeLoading"> -->
|
||||
<a-tree
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
:show-line="{ showLeafIcon: false }"
|
||||
checkable
|
||||
:height="560"
|
||||
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
|
||||
:tree-data="treeData2" />
|
||||
<!-- </a-spin> -->
|
||||
|
||||
<!-- <div class="fixed-bottom"> -->
|
||||
<div>
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import ExcelJS from 'exceljs';
|
||||
import FileSaver from 'file-saver';
|
||||
import { defineComponent, ref, inject, watch, onMounted } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
@@ -130,6 +132,153 @@
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
// 导出excel文件
|
||||
// 因为有多级表头,特殊处理,没有用公共方法
|
||||
const export1 = () => {
|
||||
if (!data.value || data.value.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 不需要合并序号
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
data.value[i].index = i + 1;
|
||||
}
|
||||
|
||||
// 创建工作簿
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
// 添加工作表,名为sheet1
|
||||
const sheet1 = workbook.addWorksheet('sheet1');
|
||||
|
||||
// 字段名
|
||||
let filterVal = [
|
||||
'name',
|
||||
'value',
|
||||
'yoyDiff',
|
||||
'yoyRate',
|
||||
'momDiff',
|
||||
'momRate',
|
||||
'zongxiangDiff',
|
||||
'zongxiangRate',
|
||||
];
|
||||
// 表格columns
|
||||
// 添加多行表头
|
||||
sheet1.addRows([
|
||||
['设备/节点', '统计值', '同比', '', '环比', '', '纵向对比', ''],
|
||||
['', '', '△差值', '增长率', '△差值', '增长率', '△差值', '增长率'],
|
||||
]);
|
||||
|
||||
// 合并单元格来实现多行表头
|
||||
sheet1.mergeCells('A1:A2'); // 合并 '设备/节点' 单元格
|
||||
sheet1.mergeCells('B1:B2'); // 合并 '统计值' 单元格
|
||||
sheet1.mergeCells('C1:D1'); // 合并 '同比' 单元格
|
||||
sheet1.mergeCells('E1:F1'); // 合并 '环比' 单元格
|
||||
sheet1.mergeCells('G1:H1'); // 合并 '纵向对比' 单元格
|
||||
//传入的数据
|
||||
const list = data.value;
|
||||
|
||||
//格式化数据
|
||||
const datas = formatJson(filterVal, list);
|
||||
|
||||
// 将数据写入工作表
|
||||
datas.forEach((row: any) => {
|
||||
// const values = Object.values(row);
|
||||
sheet1.addRow(row);
|
||||
});
|
||||
|
||||
let column = sheet1.columns;
|
||||
for (let i = 0; i < column.length; i++) {
|
||||
column[i].width = 20;
|
||||
}
|
||||
|
||||
// 修改所有单元格样式
|
||||
// 遍历每一行
|
||||
sheet1.eachRow((row) => {
|
||||
// 遍历每个单元格
|
||||
row.eachCell((cell) => {
|
||||
// 设置边框样式
|
||||
cell.border = {
|
||||
top: { style: 'thin' },
|
||||
left: { style: 'thin' },
|
||||
bottom: { style: 'thin' },
|
||||
right: { style: 'thin' },
|
||||
};
|
||||
// 设置居中对齐
|
||||
cell.alignment = {
|
||||
vertical: 'middle',
|
||||
horizontal: 'center',
|
||||
};
|
||||
});
|
||||
});
|
||||
// 获取标题行数据
|
||||
const titleCell1 = sheet1.getRow(1);
|
||||
// 设置行高为30
|
||||
titleCell1.height = 30;
|
||||
// 设置标题行单元格样式
|
||||
titleCell1.eachCell((cell) => {
|
||||
// 设置标题行背景颜色为黄色
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFFFFF' },
|
||||
};
|
||||
// 设置标题行字体
|
||||
cell.font = {
|
||||
// color: { argb: 'FF0000' }, //颜色为红色
|
||||
bold: true, // 字体粗体
|
||||
size: 18, // 设置字体大小为18
|
||||
};
|
||||
});
|
||||
const titleCell2 = sheet1.getRow(2);
|
||||
// 设置行高为30
|
||||
titleCell2.height = 30;
|
||||
// 设置标题行单元格样式
|
||||
titleCell2.eachCell((cell) => {
|
||||
// 设置标题行背景颜色为黄色
|
||||
cell.fill = {
|
||||
type: 'pattern',
|
||||
pattern: 'solid',
|
||||
fgColor: { argb: 'FFFFFF' },
|
||||
};
|
||||
// 设置标题行字体
|
||||
cell.font = {
|
||||
// color: { argb: 'FF0000' }, //颜色为红色
|
||||
bold: true, // 字体粗体
|
||||
size: 18, // 设置字体大小为18
|
||||
};
|
||||
});
|
||||
// 获取第二行到最后一行的内容数据
|
||||
const bodyRows = sheet1.getRows(3, sheet1.rowCount);
|
||||
if (bodyRows) {
|
||||
// 处理内容行的数据
|
||||
bodyRows.forEach((bodyRow) => {
|
||||
// 设置行高为20
|
||||
bodyRow.height = 20;
|
||||
bodyRow.eachCell((cell) => {
|
||||
cell.font = {
|
||||
size: 16, // 设置内容行字体大小为16
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 导出表格文件
|
||||
workbook.xlsx
|
||||
.writeBuffer()
|
||||
.then((buffer) => {
|
||||
let file = new Blob([buffer], { type: 'application/octet-stream' });
|
||||
FileSaver.saveAs(file, '分析数据导出.xlsx');
|
||||
})
|
||||
.catch((error) => console.log('Error writing excel export', error));
|
||||
};
|
||||
/**
|
||||
* 格式化表格数据
|
||||
* @filterVal 格式头
|
||||
* @jsonData 用来格式化的表格数据
|
||||
*/
|
||||
function formatJson(filterVal: any, jsonData: any) {
|
||||
return jsonData.map((v: any) => filterVal.map((j: any) => v[j]));
|
||||
}
|
||||
onMounted(() => {
|
||||
// 深度拷贝
|
||||
data.value = JSON.parse(JSON.stringify(pageData.analysisTableList));
|
||||
@@ -165,6 +314,7 @@
|
||||
rowSelection,
|
||||
selectedKey,
|
||||
setStandard,
|
||||
export1,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { exportExcel } from '/@/util/ExcelUtil.js';
|
||||
import { defineComponent, watch, inject, ref, onMounted } from 'vue';
|
||||
import type { TableColumnType } from 'ant-design-vue';
|
||||
import { Pagination } from 'ant-design-vue';
|
||||
@@ -152,6 +153,9 @@
|
||||
columns.value = columnA;
|
||||
total.value = dataList.value.length;
|
||||
onChange(1, 10);
|
||||
}; // 导出excel文件
|
||||
const export1 = () => {
|
||||
exportExcel(columns.value, dataList.value, '图表数据导出');
|
||||
};
|
||||
onMounted(() => {
|
||||
init();
|
||||
@@ -167,6 +171,7 @@
|
||||
columns,
|
||||
total,
|
||||
onChange,
|
||||
export1,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</template> -->
|
||||
</a-tabs>
|
||||
<div class="button">
|
||||
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="downloadChart" />
|
||||
<ns-icon name="xiazai" size="18" style="margin-right: 10px" @click="download" />
|
||||
<ns-icon :name="iconName" size="18" style="margin-right: 10px" @click="change" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,14 +74,26 @@
|
||||
name: 'EnvironmentMonitorIndex', // 与页面路由name一致缓存才可生效
|
||||
});
|
||||
|
||||
const downloadChart = () => {
|
||||
if (activeKey.value == '1' && isGraph) {
|
||||
if (graphRef.value) {
|
||||
graphRef.value.downloadChart();
|
||||
const download = () => {
|
||||
if (activeKey.value == '1') {
|
||||
if (isGraph.value) {
|
||||
if (graphRef.value) {
|
||||
graphRef.value.downloadChart();
|
||||
}
|
||||
} else {
|
||||
if (tableRef.value) {
|
||||
tableRef.value.export1();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (analysisGraphRef.value) {
|
||||
analysisGraphRef.value.downloadChart();
|
||||
if (isGraph.value) {
|
||||
if (analysisGraphRef.value) {
|
||||
analysisGraphRef.value.downloadChart();
|
||||
}
|
||||
} else {
|
||||
if (analysisTableRef.value) {
|
||||
analysisTableRef.value.export1();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,17 +35,17 @@
|
||||
v-if="mode == '0'"
|
||||
@change="changeMode" />
|
||||
<a-input v-model:value="pointName" placeholder="请输入节点名称" v-else @change="changeMode" />
|
||||
<a-spin :spinning="treeLoading">
|
||||
<a-tree
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
:show-line="{ showLeafIcon: false }"
|
||||
checkable
|
||||
:height="600"
|
||||
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
|
||||
:tree-data="treeData2">
|
||||
<!-- <template #title="{ title }">
|
||||
<!-- <a-spin :spinning="treeLoading"> -->
|
||||
<a-tree
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
v-model:checkedKeys="checkedKeys"
|
||||
:show-line="{ showLeafIcon: false }"
|
||||
checkable
|
||||
:height="500"
|
||||
style="width: 100%; overflow-y: auto; margin-bottom: 10px; margin-top: 10px"
|
||||
:tree-data="treeData2">
|
||||
<!-- <template #title="{ title }">
|
||||
<span v-if="title.indexOf(mode == '0' ? deviceName : pointName) > -1">
|
||||
{{ title.substr(0, title.indexOf(mode == '0' ? deviceName : pointName)) }}
|
||||
<span style="color: #f50">{{ mode == '0' ? deviceName : pointName }}</span>
|
||||
@@ -58,8 +58,8 @@
|
||||
</span>
|
||||
<span v-else>{{ title }}</span>
|
||||
</template> -->
|
||||
</a-tree>
|
||||
</a-spin>
|
||||
</a-tree>
|
||||
<!-- </a-spin> -->
|
||||
|
||||
<!-- <div class="fixed-bottom"> -->
|
||||
<div>
|
||||
|
||||
@@ -206,10 +206,7 @@
|
||||
};
|
||||
// 导出excel文件
|
||||
const export1 = () => {
|
||||
for (let i = 0; i < data.value.length; i++) {
|
||||
data.value[i].index = i + 1;
|
||||
}
|
||||
exportExcel(tableColumns.value, data.value, '平均数据导出', false);
|
||||
exportExcel(tableColumns.value, data.value, '平均数据导出');
|
||||
};
|
||||
onMounted(async () => {
|
||||
// 获取频率
|
||||
|
||||
@@ -288,6 +288,10 @@
|
||||
// 获取表格数据
|
||||
const getTableList = () => {
|
||||
loading.value = true;
|
||||
tableColumns.value = [];
|
||||
data.value = [];
|
||||
total.value = 0;
|
||||
pageData.value = [];
|
||||
let environmentType = '';
|
||||
for (let i = 0; i < typeList.value.length; i++) {
|
||||
if (typeList.value[i].value == typeValue.value) {
|
||||
@@ -353,7 +357,7 @@
|
||||
};
|
||||
// 导出excel文件
|
||||
const export1 = () => {
|
||||
exportExcel(tableColumns.value, data.value, '历史数据导出', true, 1, 3);
|
||||
exportExcel(tableColumns.value, data.value, '历史数据导出', true, 'location', 1, 3);
|
||||
};
|
||||
onMounted(async () => {
|
||||
// 获取频率
|
||||
|
||||
@@ -120,9 +120,9 @@
|
||||
})
|
||||
.then((res) => {
|
||||
treeData.value = transform(get(res, resultField));
|
||||
//默认选择第一个 并刷新列表
|
||||
selectedKeys.value = [];
|
||||
if (formConfig.value.callList && formConfig.value.defaultSelection) {
|
||||
//默认选择第一个 并刷新列表
|
||||
selectedKeys.value = [];
|
||||
handleSelect([treeData.value[0].id], {
|
||||
selected: true,
|
||||
event: 'select',
|
||||
|
||||
@@ -129,11 +129,13 @@ export const importFile = (
|
||||
headers: { token: Cookies.get(`${import.meta.env.VITE_PUBLIC_PATH}-nervsid`) },
|
||||
})
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
if (res.data.data) {
|
||||
NsMessage.success('导入成功', 1, () => {
|
||||
reload && reload();
|
||||
successBack && successBack(res);
|
||||
});
|
||||
} else {
|
||||
NsMessage.error(res.data.msg || '导入失败');
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
Reference in New Issue
Block a user