You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

895 lines
29 KiB

<template>
<!-- 空调区域 -->
<div>
<div class="light-area">
<div class="light-area-tab"></div>
<span class="light-area-text">空调区域</span>
</div>
<!-- 空调区域按钮部分 -->
<div class="area">
<template v-if="!showAllButtonsArea">
<button
v-for="(button, index) in limitedButtons1"
:key="index"
:class="{ btn: true, selected: button.selected }"
@click="changeArea(button)">
{{ button.name }}
</button>
<div style="margin-top: 10px">
<span @click="showAllButtonsArea = true" class="openzm"><down-outlined /> 展开</span>
</div>
</template>
<template v-else>
<button
v-for="(button, index) in props.treeData"
:key="index"
:class="{ btn: true, selected: button.selected }"
@click="changeArea(button)">
{{ button.name }}
</button>
<div style="margin-top: 10px">
<span @click="showAllButtonsArea = false" class="openzm"><up-outlined /> 回缩</span>
</div>
</template>
</div>
</div>
<!-- 空调分组部分 -->
<div>
<div class="circuit-area">
<div class="circuit-tab"></div>
<span class="circuit-text">空调分组</span>
<div class="btn2">
<a-badge :offset="[-10, 2]" :count="lockList.length">
<button
class="openPlan"
:class="{ enabled2: isPlanEnabled2, disabled2: !isPlanEnabled2 }"
@click="togglePlan2">
{{ isPlanEnabled2 ? '启用开关' : '禁用开关' }}
</button>
</a-badge>
<a-switch
v-model:checked="selectAllCheckbox"
:disabled="singleSelection"
:class="{
'blue-background': selectAllCheckbox,
'grey-background': !selectAllCheckbox,
}"
@change="toggleAllSelection" />
<button class="allBtn">全选</button>
<button class="both" @click="selectAll">
{{ singleSelection ? '多选' : '单选' }}
</button>
</div>
</div>
<div class="btnArea">
<template v-if="!showAllButtons">
<button
v-for="(button, index) in limitedButtons2"
:key="index"
:class="{ btn: true, selected: button.selected }"
class="zmhlbtn"
@click="changeLine(button)">
<div v-if="button.lockStatus" class="btn-back">
<stop-outlined />
</div>
{{ button.name }}
</button>
<div style="margin-top: 10px">
<span @click="showAllButtons = true" class="openzm"><down-outlined /> 展开</span>
</div>
</template>
<template v-else>
<button
v-for="(button, index) in buttons2"
:key="index"
:class="{ btn: true, selected: button.selected }"
class="zmhlbtn"
@click="changeLine(button)">
<div v-if="button.lockStatus" class="btn-back">
<stop-outlined />
</div>
{{ button.name }}
</button>
<div style="margin-top: 10px">
<span @click="showAllButtons = false" class="openzm"><up-outlined /> 回缩</span>
</div>
</template>
</div>
</div>
<!-- 控制模式部分 -->
<div v-show="thisButton2.dataCode">
<div class="control-area">
<div class="control-tab"></div>
<span class="control-text">控制模式</span>
</div>
<!-- 控制模式按钮部分 -->
<div class="control-mode-btn-area">
<button
v-for="(button3, index) in thisButton2.childList"
:key="index"
class="btn"
:class="{ selected: button3.selectAble }"
@click="selectButton3(button3)">
{{ button3.name }}
</button>
</div>
</div>
<!-- 控制场景部分 -->
<div v-show="thisButton2.dataCode">
<div class="control-scene-area">
<div class="control-scene-tab"></div>
<span class="control-scene-text">启动模式</span>
<div v-if="!singleSelection" style="flex: 1; color: red; text-align: right"
>多选模式下会修改当前选中的所有回路</div
>
</div>
<!-- 控制场景按钮部分 -->
<div class="control-scene-btn-area">
<button
v-for="(button4, index) in thisButton3.childList"
:key="index"
:class="{ btn: true, selected: button4.executeStatus.value != 0 }"
@click="selectButton4(button4)">
{{ button4.name }}
</button>
</div>
</div>
<!-- 底部按钮区 -->
<div class="bottom">
<a-badge :offset="[-10, 2]" :count="changeList.length">
<a-popconfirm
title="刷新将会取消已作出的修改"
ok-text="确定"
cancel-text="取消"
@confirm="refresh(false)"
@cancel="changeCancel">
<button class="flushed">刷新</button>
</a-popconfirm>
</a-badge>
<button class="execute" @click="showModal">执行</button>
</div>
<!-- 点击执行时的弹出框 -->
<div class="out-dialog" v-if="executeVisible">
<div class="content">
<div>
<div class="div-operation"></div>
<span class="text-operation">变更内容 </span>
</div>
<div class="j-box" v-for="item in diffList" :key="item.id">
<div class="journal" style="margin-top: 20px">
<div class="imgText">
<div class="zjzm">
<img class="title-img" src="/asset/image//bulbLogo/21961.png" alt="" />&nbsp;
<span
class="title-text"
style="font-size: 20px; font-weight: 500; color: rgba(255, 255, 255, 1)"
>{{ item.regionName + ' > ' + item.deviceGroupName }}</span
>
</div>
<a-popconfirm
title="此操作将会撤销修改"
ok-text="确定"
cancel-text="取消"
placement="bottomRight"
@confirm="delBtn(item)"
@cancel="changeCancel">
<button class="cxbtn">撤销</button>
</a-popconfirm>
</div>
<div class="btn-box">
<div class="btn-item">
<div class="left">控制模式</div>
<div class="right">
<span>{{ item.stateBefore.autoStatus.label.replace('模式', '') }}</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>{{ item.stateAfter.autoStatus.label.replace('模式', '') }}</span>
</div>
</div>
<div class="btn-item">
<div class="left"> 温度 </div>
<div class="right">
<!-- 数字0也会被判为false,故只判断undefined 和 null -->
<span>{{
item.stateBefore.temperature != null ? item.stateBefore.temperature + '℃' : '--'
}}</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>
{{
item.stateAfter.temperature != null ? item.stateAfter.temperature + '℃' : '--'
}}
</span>
</div>
</div>
<div class="btn-item">
<div class="left"> 控制场景 </div>
<div class="right">
<span>{{
item?.stateBefore?.scene?.label ? item.stateBefore.scene.label : '--'
}}</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>{{
item?.stateAfter?.scene?.label ? item.stateAfter.scene.label : '--'
}}</span>
</div>
</div>
<div class="btn-item">
<div class="left"> 风速 </div>
<div class="right">
<span>{{
item.stateBefore.windSpeed != null ? item.stateBefore.windSpeed + 'm/s' : '--'
}}</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>
{{ item.stateAfter.windSpeed != null ? item.stateAfter.windSpeed + 'm/s' : '--' }}
</span>
</div>
</div>
<div class="btn-item">
<div class="left"> 启用状态 </div>
<div class="right">
<span>{{
item?.stateBefore?.lockStatus != undefined
? item.stateBefore.lockStatus
? '禁用'
: '启用'
: '--'
}}</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>
{{
item?.stateAfter?.lockStatus != undefined
? item.stateAfter.lockStatus
? '禁用'
: '启用'
: '--'
}}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="width: 100%; height: 60px"></div>
<div class="button-box">
<button class="cancel" @click="executeVisible = false">取消</button>
<a-popconfirm
title="此操作将提交以上修改内容"
ok-text="确定"
cancel-text="取消"
@confirm="submitChangeList"
@cancel="changeCancel">
<button class="execute">执行</button>
</a-popconfirm>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import { DownOutlined, UpOutlined, StopOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
// 请求
import { http } from '/nerv-lib/util/http';
import { airConditionControl } from '/@/api/airConditionControlSystem';
import { planManage } from '/@/api/planManage';
// 全局变量
import { items } from '/@/store/item';
// 初始化 =========================================================================
onMounted(() => {
// 分区初始化
setArea();
});
// 分区初始化,以 1-1 作为默认回路
const setArea = () => {
const data = props.treeData[0];
buttons2.value = data.childList;
};
// 全局变量
const state = items();
// 与父组件的交互 ===================================================================
const props = defineProps({
// 分区结构(照明区域 > 照明回路)
treeData: {
type: Array,
default: () => {
[];
},
},
});
/** 向上传递方法
* @method changeArea 用于控制俯视图的选中状态
* @method reset 用于重置按钮区
* @method reload 用于刷新一次页面
* @method resetAll 刷新所有tab,对计划进行修改时,需刷新tab2与tab3
*/
const emit = defineEmits(['changeArea', 'reset', 'reload', 'resetAll']);
// 照明区域业务 =======================================================================
// 按钮区展开与收起状态
const showAllButtonsArea = ref(false);
// 被选中的分区 默认为1 用于选中样式渲染
const selectedButton = ref<string | undefined>('1');
// 分区切换
const changeArea = (button: any) => {
// 当前选中按钮
selectedButton.value = button.id;
// 设置当前选中的回路
buttons2.value = button.childList;
// 重置按钮状态
emit('reset');
// 设置选中按钮状态
button.selected = true;
// 改变俯视图样式
emit('changeArea', button.id);
// 当前选中回路 - 置空
resetMode();
};
// 默认最多展示8个按钮
const limitedButtons1 = computed(() => props.treeData.slice(0, 8));
// 照明回路业务 ======================================================================
// 开关启用/禁用状态
const isPlanEnabled2 = ref(false);
// 开关修改保存数组
const lockList = ref<any>([]);
// 开关启用/禁用切换事件
const togglePlan2 = () => {
// 获取选中线路
let valid = buttons2.value.filter((item: any) => {
return item.selected;
});
// 未选中线路
if (valid.length == 0) {
return message.info('请先选择线路');
// 选中线路
} else {
// 按钮切换
isPlanEnabled2.value = !isPlanEnabled2.value;
// 禁用状态原值
let after = +isPlanEnabled2.value;
// 当前修改线路
valid.forEach((item: any) => {
// 按钮与需修改的值一致,无效
if (item.lockStatus == after) {
return;
}
// 查看是否已经产生过修改
const same = lockList.value.find((v: any) => {
return v.deviceGroup == item.dataCode;
});
// 如果发生过修改
if (same) {
// 改回原值,则移除
if (same.before == after) {
lockList.value.forEach((v1: any, index: number) => {
if (same.deviceGroup == v1.deviceGroup) {
lockList.value.splice(index, 1);
}
});
// 只有true 和 false 的切换,无需继续判断
}
// 初次修改
} else {
lockList.value.push({
deviceGroup: item.dataCode,
deviceGroupName: item.name,
region: item.treePid,
regionName: '',
before: item.lockStatus,
lockStatus: after,
});
}
// 修改
item.lockStatus = after;
});
}
};
// 是否单选,状态
let singleSelection = ref(true);
// 多选与单选切换事件
const selectAll = () => {
selectAllCheckbox.value = false;
// 切换时清空当前所有选项
buttons2.value.forEach((button: any) => {
button.selected = false;
});
singleSelection.value = !singleSelection.value;
// 当前选中回路 - 置空
resetMode();
// 改变俯视图样式
emit('changeArea', [selectedButton.value]);
};
// 全选状态
const selectAllCheckbox = ref(false);
// 全选切换事件(switch)
const toggleAllSelection = () => {
let arr = [selectedButton.value];
// 全选
if (selectAllCheckbox.value) {
buttons2.value.forEach((item: any, index: number) => {
// 全选时,默认展示第一条回路的模式-场景按钮
if (index == 0) {
thisButton2.value = item;
}
item.selected = true;
arr.push(item.id);
});
// 全不选
} else {
buttons2.value.forEach((item: any) => {
item.selected = false;
});
// 全不选时,隐藏 模式 与 场景 按钮
resetMode();
}
emit('changeArea', arr);
};
// 储存当前选中的回路
const thisButton2 = ref({
dataCode: '',
name: '',
treePid: '',
childList: [],
});
// 依托父组件传值,重置回路
const setButtons2 = (data: any) => {
buttons2.value = data;
};
// 照明回路的按钮切换
const changeLine = (button: any) => {
// 根据按钮状态,展示禁用/启用按钮文本
if (button.ctrlStatus) {
isPlanEnabled2.value = true;
} else {
isPlanEnabled2.value = false;
}
// 选择时反控俯视图
let level1 = selectedButton.value;
let level2 = button.id;
// 单选模式,需将所有其他回路设为false
if (singleSelection.value) {
buttons2.value.forEach((item: any) => {
item.selected = false;
});
button.selected = !button.selected;
emit('changeArea', [level1, level2]);
} else {
// 多选模式传值
button.selected = !button.selected;
const arr = [level1];
buttons2.value.forEach((item: any) => {
if (item.selected) {
arr.push(item.id);
}
});
emit('changeArea', arr);
}
// 用于展示控制模式
if (button.selected) {
// 发生了选中事件
thisButton2.value = button;
// 获得启动模式
if (button.childList) {
thisButton3.value = button.childList.find((item: any) => {
if (item.selectAble) {
return item.childList ? item.childList : [];
}
});
} else {
thisButton3.value = { childList: [] };
}
} else {
// 未发生选中 或 多选的其中一个按钮被取消
resetMode();
}
console.log(thisButton2, 'button');
};
// 空调分组所有按钮
const buttons2 = ref([]);
// 按钮区展开与收起状态
const showAllButtons = ref(false);
// 默认最多展示8个按钮
const limitedButtons2 = computed(() => buttons2.value.slice(0, 8));
// 控制模式业务 ====================================================================
const thisButton3 = ref({
childList: [],
});
// 控制模式 - 按钮切换
const selectButton3 = (button3: any) => {
console.log(button3);
if (!button3.selectAble) {
return message.warning(`${button3.name} 暂不支持`);
}
thisButton3.value = button3;
};
// 控制场景业务 =====================================================================
// 控制场景 - 按钮切换
const selectButton4 = (button4: any) => {
const after = button4.dataCode;
let before = '';
// 如果是多选模式
if (!singleSelection.value) {
// 操作线路总数
let sum = 0;
// 没有这个选项的线路
// let nofind = 0;
// 修改无效的数量
let checked = 0;
// 可修改的数量
let changed = 0;
buttons2.value.forEach((item: any) => {
// 取出当前选中的值 before
if (item.childList) {
let mode = item.childList.find((lv3: any) => {
return lv3.selectAble;
});
if (mode.childList) {
mode.childList.forEach((mode: any) => {
// 取出当前选中的模式
if (mode.executeStatus.value == 1) {
before = mode.dataCode;
}
});
}
}
// 查看当前回路,哪些被选中
if (item.selected) {
item.childList.forEach((v: any) => {
if (v.childList) {
v.childList.forEach((v1: any) => {
// 查看是否包含当前要修改的值
if (v1.dataCode == after) {
sum += 1;
// 已经被选中,无需修改的内容
if (before == after) {
return (checked += 1);
// 修改
} else {
changed += 1;
changeScene(v1, before, after, item);
v1.executeStatus.value = 1;
}
// 不符合条件的全部重置
} else {
v1.executeStatus.value = 0;
}
});
}
});
}
});
message.info(`共修改${sum}条数据,其中${checked}条无需修改,${changed}条修改有效`);
// 如果是单选模式
} else {
// 如果按钮已经被选择
if (button4.executeStatus.value == 1) {
return message.info('未产生实际修改');
} else {
// 获得线路当前的场景
let before;
thisButton2.value.childList.find((item: any) => {
if (item.childList) {
item.childList.forEach((i: any) => {
if (i.executeStatus.value == 1) {
return (before = i.dataCode);
}
});
}
});
// 移除选中场景
resetScene(thisButton2.value.childList);
changeScene(button4, before, after);
}
}
};
// 切换场景前,需要把其他场景移除
const resetScene = (list: any) => {
list.forEach((item: any) => {
if (item.childList) {
item.childList.forEach((i: any) => {
i.executeStatus.value = 0;
});
}
});
};
/** 控制场景 - 按钮切换通用方法(单选 & 多选)
* @param button 当前被选中的场景(单选 & 多选)
* @param before 当前回路场景的初始值(撤回时需使用)
* @param after 修改后的值(修改时使用)
* @param anyButton 多选时使用
*/
const changeScene = (button: any, before: string | undefined, after: string, line = null) => {
// 通过分组ID,查询之前是否修改过
const result = changeList.value.find((item: any, index: number) => {
item.index = index;
return item.deviceGroup == button.treePid.split('_')[0];
});
// 如果已产生过修改
if (result) {
// 改回了原有的值,则从数组中移除
if (after == result.before) {
changeList.value.splice(result.index, 1);
// 修改为新值,则只修改场景
} else {
result.scene = after;
// 临时flag,用后移除
delete result.index;
}
// 如果未产生过修改
} else {
let nowButton;
// 多选,则使用第四个参数
if (line) {
nowButton = line;
// 如果是单选,则使用thisbotton2
} else {
nowButton = thisButton2.value;
}
changeList.value.push({
// 回路
deviceGroup: nowButton.dataCode,
deviceGroupName: nowButton.name,
// 分区
region: nowButton.treePid,
regionName: '',
// 修改前
before,
scene: after,
});
}
button.executeStatus.value = 1;
};
// 底部按钮区 ======================================================================
// 刷新
const refresh = (reload = false) => {
// 关闭执行弹窗
executeVisible.value = false;
// 设置当前选中的序列
selectedButton.value = '1';
// 重置选中样式 和 按钮选中状态
emit('changeArea', ['1']);
emit('reset');
// 如果是中途刷新(对应提交后刷新),需要将所有修改改回
if (!reload) {
changeList.value.forEach((item: any) => {
resetChangeList(item);
});
lockList.value.forEach((item: any) => {
resetLockList(item);
});
// 默认选择第一个楼层
let data = props.treeData[0];
// 默认选中
data.selected = true;
// 默认选中 1-1 分区 回路
buttons2.value = data.childList;
// 将选中线路重置
resetMode();
}
changeList.value = [];
lockList.value = [];
};
// 将已修改的禁用/启用状态改回
const resetLockList = (item: any) => {
props.treeData.find((v: any) => {
if (item.region == v.dataCode) {
v.childList.find((v1: any) => {
if (item.deviceGroup == v1.dataCode) {
v1.lockStatus = item.before;
}
});
}
});
};
// 刷新时,将已修改的值改回
const resetChangeList = (item: any) => {
props.treeData.find((v: any) => {
if (item.region == v.dataCode) {
v.childList.find((v1: any) => {
// 找到被修改过的线路
if (item.deviceGroup == v1.dataCode) {
v1.childList.forEach((v2: any) => {
if (v2.childList) {
v2.childList.forEach((v3: any) => {
// 将新值移除
if (item.scene == v3.dataCode) {
v3.executeStatus.value = 0;
}
if (!item.before) {
console.log(item, '没有这个选项');
v3.executeStatus.value = 0;
}
// 旧值选中
if (item.before == v3.dataCode) {
v3.executeStatus.value = 1;
}
});
}
});
}
});
}
});
};
// 右下角的执行事件
const showModal = () => {
if (!changeList.value.length && !lockList.value.length) {
return message.info('未产生任何修改');
}
http
.get(planManage.getRunningPlan, {
deviceType: 2,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
// 如果有计划正在执行
if (res.data && res.data.length) {
// 此处框架本身存在问题,弹出层在本地环境无法关闭,暂时使用浏览器自带的confirm方法
// Modal.confirm({
// title: '提示信息',
// content: '有计划正在执行,点击"确定"将暂停当前计划',
// onOk() {
// return new Promise((resolve, reject) => {
// });
// },
// onCancel() { },
// });
let flag = window.confirm('有计划正在执行,点击"确定"将暂停当前计划');
if (flag) {
// 如果点击了确定,将先终止所有进行中的计划
http
.post(airConditionControl.submitChangeList, {
projectId: state.projectId,
siteId: state.siteId,
lockList: [],
sceneList: [],
})
.then((res) => {
console.log(res, '成功');
// 如果重置成功,则获取修改前后对比数据
if (res.retcode == 0) {
sendChangeList();
// 未成功提示
} else {
message.error('关闭进行中的任务操作失败,请重新尝试');
}
});
}
// 没有计划正在执行,则直接请求
} else {
sendChangeList();
}
});
};
// 提交控制场景 与 禁用/启用 修改
const sendChangeList = () => {
http
.post(airConditionControl.getChangeList, {
sceneList: changeList.value,
lockList: lockList.value,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
if (res.retcode == 0) {
diffList.value = res.data;
executeVisible.value = true;
} else {
message.warning('获取修改内容失败');
}
})
.catch(() => {});
};
// 通用取消
const changeCancel = () => {};
// 内侧弹窗 ========================================================================
// 内侧弹窗显隐
const executeVisible = ref<boolean>(false);
// 修改模式 需要向后端提交的内容
const changeList: any = ref([]);
// 展示修改前后差异的内容
const diffList = ref([]);
//撤销
const delBtn = (obj: any) => {
console.log(obj, '当前选择的修改内容');
// 将treeData对应回路的数据改回,数据以后端为准
obj.scene = obj.stateAfter.scene.value;
obj.before = obj.stateBefore.scene.value;
resetChangeList(obj);
resetLockList(obj);
// 将 changeList 与 diffList 中记录的修改移除 (排除极端情况)
changeList.value = changeList.value.filter((item: any) => {
return item.deviceGroup !== obj.deviceGroup;
});
lockList.value = lockList.value.filter((item: any) => {
return item.deviceGroup !== obj.deviceGroup;
});
diffList.value = diffList.value.filter((item: any) => {
return item.deviceGroup !== obj.deviceGroup;
});
// 如果移除后不再有修改内容,则隐藏弹出框
if (changeList.value.length == 0 && lockList.value.length == 0) {
executeVisible.value = false;
}
};
// 提交本次修改
const submitChangeList = () => {
http
.post(airConditionControl.submitChangeList, {
sceneList: changeList.value,
lockList: lockList.value,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
let data = res.data;
// 修改请求发送了,但操作时产生了失败结果
if (res.retcode != 0) {
// 直接提示并跳出
return message.warning(data.msg);
}
// 所有修改均生效
if (data.allSucceed) {
message.success('修改完成');
// allSucceed不为true,则至少有一条数据修改失败
} else {
message.info(`${data.successList.length}条修改成功,${data.failList.length}条修改失败`);
}
refresh(true);
emit('resetAll');
})
.catch(() => {});
};
// 其他业务 ========================================================================
// 将当前选择的回路置空
const resetMode = () => {
thisButton2.value = {
dataCode: '',
name: '',
treePid: '',
childList: [],
};
};
// 向外暴露方法
defineExpose({
// 分区切换
changeArea,
// 回路切换
changeLine,
// 重置当前选择
refresh,
// 由父组件反向刷新当前选中的回路
setButtons2,
});
</script>
<style lang="less" scoped>
@import '../style/dialogStyle.less';
@import './tabs1.less';
</style>