Files
SaaS-lib/hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs1.vue
2024-08-09 09:09:57 +08:00

823 lines
26 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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="取消"
@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>手动</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>自动</span>
</div>
</div>
<div class="btn-item">
<div class="left"> 亮度 </div>
<div class="right">
<!-- 数字0也会被判为false故只判断undefined null -->
<span>{{
item?.stateBefore?.brightness != undefined ? item.stateBefore.brightness : '--'
}}</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>{{
item?.stateAfter?.brightness != undefined ? item.stateAfter.brightness : '--'
}}</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?.color != undefined ? item.stateBefore.color : '--'
}}</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>
{{ item?.stateAfter?.color != undefined ? item.stateAfter.color : '--' }}
</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 { lightingManage } from '/@/api/IlluminationInfo';
import { airConditionControl } from '/@/api/airConditionControlSystem';
// 全局变量
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 用于刷新一次页面
*/
const emit = defineEmits(['changeArea', 'reset', 'reload']);
// 照明区域业务 =======================================================================
// 按钮区展开与收起状态
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 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);
});
}
changeList.value = [];
if (!reload) {
lockList.value.forEach((item: any) => {
resetLockList(item);
});
}
lockList.value = [];
// 默认选择第一个楼层
let data = props.treeData[0];
// 默认选中
data.selected = true;
// 默认选中 1-1 分区 回路
buttons2.value = data.childList;
// 将选中线路重置
resetMode();
};
// 将已修改的禁用/启用状态改回
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) {
return message.info('未产生任何修改');
}
http
.post(airConditionControl.getChangeList, {
sceneList: changeList.value,
lockList: lockList.value,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
if (res.msg === 'success') {
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(() => {
emit('reload');
refresh(true);
});
};
// 其他业务 ========================================================================
// 将当前选择的回路置空
const resetMode = () => {
thisButton2.value = {
dataCode: '',
name: '',
treePid: '',
childList: [],
};
};
// 向外暴露方法
defineExpose({
// 分区切换
changeArea,
// 回路切换
changeLine,
});
</script>
<style lang="less" scoped>
@import './dialogStyle.less';
@import './tabs1.less';
</style>