Browse Source

add:空调系统群控-对接新接口以及逻辑修改

temp
chenpingsen 4 months ago
parent
commit
bb9be7b4e0
  1. 20
      hx-ai-intelligent/src/api/IlluminationInfo.ts
  2. 28
      hx-ai-intelligent/src/api/airConditionControlSystem.ts
  3. 19
      hx-ai-intelligent/src/router/equipmentControl.ts
  4. 157
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/dialogStyle.less
  5. 149
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/index.less
  6. 323
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/index.vue
  7. 149
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/light.vue
  8. 3
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/lightPosition.ts
  9. 403
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs1.less
  10. 754
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs1.vue
  11. 318
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs2.vue
  12. 251
      hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs3.vue
  13. 4
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs.vue
  14. 71
      hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs1.vue

20
hx-ai-intelligent/src/api/IlluminationInfo.ts

@ -3,29 +3,29 @@ export enum lightingManage {
// 主页 ========================================================
// 获得分区与线路
getArea = '/carbon-smart/IlluminationInfo/region',
getTree = '/carbon-smart/api/illuminationCtrl/getCtrlPanelTree',
// 修改线路的可用/禁用状态
setDisable = '/carbon-smart/IlluminationInfo/changePanelStatus',
setDisable = '/carbon-smart/api/illuminationCtrl/changePanelStatus',
// 获得设备 - 小灯泡
getBulbs = '/carbon-smart/IlluminationInfo/getLightState',
getBulbs = '/carbon-smart/api/illuminationCtrl/getLightState',
// 控制面板tab页 ================================================
// 获取当前修改的内容对比数据
getChangeList = '/carbon-smart/IlluminationInfo/getLightSceneChangeInfo',
getChangeList = '/carbon-smart/api/illuminationCtrl/getLightSceneChangeInfo',
// 提交当前修改
submitChangeList = '/carbon-smart/IlluminationInfo/changeLightScene',
submitChangeList = '/carbon-smart/api/illuminationCtrl/changeLightScene',
// 计划列表tab页 ================================================
// 获得计划列表tab页的表格数据
getPlanTable = '/carbon-smart/IlluminationPlan/selectPanelPlan',
getPlanTable = '/carbon-smart/api/illuminationInfo/selectPanelPlan',
// 获得计划列表tab页的穿梭框左侧数据
getLeftPlan = '/carbon-smart/IlluminationPlan/getPlan',
getLeftPlan = '/carbon-smart/api/illuminationInfo/getPlan',
// 提交穿梭框被选择的数据
submitLeftPlan = '/carbon-smart/IlluminationPlan/joinPlan',
submitLeftPlan = '/carbon-smart/api/illuminationInfo/joinPlan',
// 删除表格中的计划
deletePlan = '/carbon-smart/IlluminationPlan/deletePlan',
deletePlan = '/carbon-smart/api/illuminationInfo/deletePlan',
// 重启表格计划
restartPlan = '/carbon-smart/IlluminationPlan/enable',
restartPlan = '/carbon-smart/api/illuminationInfo/enable',
}

28
hx-ai-intelligent/src/api/airConditionControlSystem.ts

@ -0,0 +1,28 @@
const prefix = '/carbon-smart';
// 空调系统及相关接口
export enum airConditionControl {
// 主页 ======================================================
// 主页分区结构
getTree = prefix + '/airConditioningCtrl/getCtrlPanelTree',
// 主页小灯泡
getDeviceList = prefix + '/airConditioningCtrl/getDeviceState',
// 主页 > 抽屉 > 控制面板 =======================================
// 获得修改的比对列表
getChangeList = prefix + '/airConditioningCtrl/getSceneChangeInfo',
// 提交修改结果
submitChangeList = prefix + '/airConditioningCtrl/changeToSceneMode',
// 主页 > 抽屉 > 计划列表 =======================================
// 穿梭框来源数据
getTransData = prefix + '/airConditioningInfo/getDeActivatedPlanList',
// 右侧表格数据
getTableData = prefix + '/airConditioningInfo/getActivatedPlanList',
// 穿梭框结果数据提交
submitTransData = prefix + '/airConditioningInfo/activePlanByIdList',
// 右侧表格修改数据提交
submitTableData = prefix + '/airConditioningCtrl/refreshPlanStatus',
}

19
hx-ai-intelligent/src/router/equipmentControl.ts

@ -100,6 +100,25 @@ const equipmentControl = {
// },
// ],
// },
{
path: 'airConditionControlSystem',
name: 'airConditionControlSystem',
meta: { title: '空调系统群控', hideChildren: true, icon: 'shebeiqunkong' },
component: Base,
redirect: { name: 'airConditionControlSystemIndex' },
children: [
{
path: 'index',
name: 'airConditionControlSystemIndex',
component: () => import('/@/view/equipmentControl/airConditionControlSystem/index.vue'),
meta: {
title: '空调系统群控',
keepAlive: false,
// backApi: [],
},
},
],
},
],
};
export default equipmentControl;

157
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/dialogStyle.less

@ -0,0 +1,157 @@
.out-dialog {
position: fixed;
right: 496px;
width: 500px;
height: 100%;
z-index: 0;
top: 0;
bottom: 0;
margin: auto;
box-sizing: border-box;
color: rgb(255, 83, 0);
background: black;
display: flex;
padding: 25px;
flex-direction: column;
transition: all ease 0.5s;
.content {
overflow-y: scroll;
.div-operation {
display: inline-block;
width: 3px;
height: 13px;
opacity: 1;
border-radius: 1px;
background: rgba(67, 136, 251, 1);
}
.text-operation {
display: inline-block;
color: rgba(255, 255, 255, 1);
font-size: 16px;
font-weight: 700;
margin-left: 5px;
}
.j-box {
background-color: #000;
opacity: 1;
z-index: 99999;
overflow-y: scroll;
.journal {
padding: 1% 3%;
width: 100%;
height: 150px;
background-color: rgba(0, 0, 0);
border-radius: 12px;
border: 2px solid transparent;
border-image: linear-gradient(to bottom, #0077ff, #00f6ff, #000000) 1;
.title-img {
padding-top: 6px;
}
}
.imgText {
display: flex;
align-items: center;
justify-content: space-between;
.ztzm {
display: flex;
align-items: center;
}
.cxbtn {
color: rgba(255, 255, 255, 1);
border: none;
border-radius: 6px;
width: 59.79px;
height: 32px;
opacity: 1;
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;
}
}
.btn-box {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-row-gap: 15px;
.btn-item {
text-align: center;
display: flex;
align-content: space-between;
.left {
width: 70px;
height: 35px;
line-height: 35px;
border-radius: 4px;
background: linear-gradient(
180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%
);
color: rgba(255, 255, 255, 1);
font-size: 14px;
font-weight: 400;
}
.right {
width: 140px;
height: 35px;
line-height: 35px;
:first-child {
color: white;
}
span {
vertical-align: middle;
}
img {
padding: 0 5px;
}
}
}
}
}
}
.button-box {
width: 100%;
box-sizing: border-box;
padding: 10px;
height: 60px;
position: absolute;
background-color: transparent;
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;
}
}
}
.fade-enter-active, .fade-leave-active {
transform: translateX(0px);
}
.fade-enter-from, .fade-leave-to {
transform: translateX(496px);
}

149
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/index.less

@ -0,0 +1,149 @@
// 页面容器
.lighting-box {
position: relative;
width: 100%;
height: 100%;
// background: linear-gradient(#badaff, #8cabeb, #7095de);
// 照明设备功能总容器
.lighting-img-box {
position: relative;
width: 1280px;
height: 720px;
user-select: none;
background-image: url(../image/bg.jpg);
// 由于背景是俯视图,会产生有交点的透视效果,故使用透视属性
perspective: 1000px;
perspective-origin: 850px -160px;
// 左上角区域切换功能
.btn-box {
width: 120px;
position: sticky;
top: 10px;
left: 10px;
display: flex;
flex-direction: column;
gap: 8px;
.btn-item {
cursor: pointer;
width: 100%;
height: 40px;
border-radius: 4px;
background: rgba(39, 120, 255, 1);
border: 1px solid rgba(51, 199, 255, 1);
box-shadow: 0px 10px 15px rgba(0, 54, 136, 0.3);
font-size: 18px;
color: white;
}
.btn-item:hover {
color: black;
}
}
// 大区分区
.area{
position: absolute;
bottom: 170px;
left: 240px;
width: 780px;
height: 240px;
transform: rotateX(79deg) rotateZ(-22deg) skew(29deg);
display: flex;
gap: 5px;
.area1 {
width: 65px;
background: rgba(0, 251, 91, 0.3);
border: 2px solid rgb(0, 251, 91);
display: flex;
}
.area2 {
width: 100px;
background: rgba(255, 165, 0, 0.3);
border: 2px solid rgb(255, 165, 0);
display: flex;
}
.area3 {
width: 220px;
background: rgba(255, 0, 0, 0.3);
border: 2px solid rgb(255, 0, 0);
display: flex;
}
.area4 {
width: 70px;
background: rgba(80, 236, 244, 0.3);
border: 2px solid rgb(80, 236, 244);
display: flex;
}
.area5 {
flex: 210px;
background: rgba(0, 251, 91, 0.3);
border: 2px solid rgb(0, 251, 91);
display: flex;
}
.area6 {
flex: 1;
background: rgba(255, 165, 0, 0.3);
border: 2px solid rgb(255, 165, 0);
display: flex;
}
.area-item:hover {
transform: scale(1.05);
}
.area-item {
cursor: pointer;
transition: all ease 0.2s;
>.light-group {
height: 100%;
flex: 1;
display:flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
padding: 10px;
// border: 2px solid red;
.shadow-box {
width: 30px;
height: 200px;
border-radius: 20px;
background: rgba(0, 0, 0, 0.2);
}
}
}
}
}
}
// 总容器与抽屉按钮
.ns-content-main {
position: relative;
// 抽屉打开按钮
.drawer-box-in {
width: 30px;
height: 40px;
border-radius: 2px;
position: fixed;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background: rgba(0, 0 ,0 ,0.5);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
// 抽屉关闭按钮
.drawer-box-out {
width: 30px;
height: 40px;
border-radius: 2px;
position: fixed;
right: 496px;
top: 0;
bottom: 0;
margin: auto;
background: rgba(0, 0 ,0 ,0.5);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
}

323
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/index.vue

@ -0,0 +1,323 @@
<template>
<div class="lighting-box">
<div class="lighting-img-box">
<!-- 左上角区域切换 -->
<div class="btn-box">
<button
v-for="(item, index) in floorData"
:key="index"
class="btn-item"
:style="{ color: item.dataCode == thisFloor ? 'black' : 'white' }"
@click="changeFloor(item.childList, item.dataCode)"
>{{ item.name }}</button
>
</div>
<!-- 楼层区域 -->
<div class="area">
<div
v-for="(item, index) in treeData"
:class="computedClass(item.id)"
@click="changeThisArea([item])"
:key="index">
<div v-for="(v, i) in item.childList" :key="i" class="light-group">
<div class="group-shadow" @click.stop="changeThisArea([item, v])">
<div :class="computedClass(v.id)" class="shadow-box"></div>
</div>
</div>
</div>
</div>
<!-- 照明设备 -->
<div class="lights">
<light
v-for="(item, index) in bulbs"
:key="index"
:styleObject="item.styleText"
:type="item.type"
:visible="item.visible" />
</div>
</div>
<!-- 右侧抽屉的触发按钮 -->
<div class="drawer-box-in" v-if="!visible" @click="toggleDrawer">
<double-left-outlined class="drawer-icon" style="color: white" />
</div>
<!-- 左侧抽屉的关闭按钮 -->
<div class="drawer-box-out" v-if="visible" @click="toggleDrawer">
<double-right-outlined class="drawer-icon" style="color: white" />
</div>
<!-- 右侧抽屉 -->
<a-drawer
v-model:visible="visible"
class="drawer-item"
width="496"
:forceRender="preload"
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="控制面板">
<tabs1
ref="tabs1Ref"
@changeArea="changeArea"
@reset="reset"
@reload="reload"
:treeData="treeData" />
</a-tab-pane>
<a-tab-pane key="2" tab="计划列表" force-render>
<tabs2 />
</a-tab-pane>
<a-tab-pane key="3" tab="日志">
<tabs3 />
</a-tab-pane>
</a-tabs>
</a-drawer>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
//
import light from './light.vue';
import tabs1 from './tabs1.vue';
import tabs2 from './tabs2.vue';
import tabs3 from './tabs3.vue';
//
import { http } from '/nerv-lib/util/http';
import { airConditionControl } from '/@/api/airConditionControlSystem';
// ICON
import { DoubleLeftOutlined, DoubleRightOutlined } from '@ant-design/icons-vue';
//
import { items } from '/@/store/item';
// =======================================================
onMounted(() => {
// 线
getAllArea();
//
getBulbs();
});
//
const state = items();
// flagref
const preload = ref(false);
// =====================================================
//
const floorData = ref([]);
//
const thisFloor = ref('1');
//
const changeFloor = (area: any, floor: string) => {
thisFloor.value = floor;
//
reset();
//
changeArea(['1']);
//
treeData.value = area;
//
treeData.value[0].selected = true;
};
// =====================================================
//
const treeData = ref([]);
// -
const area = ref(['1']);
// 线 -
const bulbs = ref([
{
styleText: { left: '180px', bottom: '200px' },
area: 1,
type: 1,
visible: true,
},
{
styleText: { left: '230px', bottom: '125px' },
area: 1,
type: 2,
visible: true,
},
{
styleText: { left: '320px', bottom: '140px' },
area: 1,
type: 3,
visible: true,
},
{
styleText: { left: '245px', bottom: '230px' },
area: 1,
type: 3,
visible: true,
},
{
styleText: { left: '405px', bottom: '230px' },
area: 2,
type: 3,
visible: true,
},
{
styleText: { left: '460px', bottom: '180px' },
area: 2,
type: 3,
visible: true,
},
{
styleText: { left: '360px', bottom: '275px' },
area: 2,
type: 3,
visible: true,
},
{
styleText: { left: '715px', bottom: '320px' },
area: 3,
type: 1,
visible: true,
},
]);
// 线
const changeArea = (result: any) => {
console.log(result, 'changeArea');
//
if (Array.isArray(result)) {
area.value = result;
//
} else {
area.value.length = 0;
area.value[0] = String(result);
}
};
//
const changeThisArea = (result: any) => {
console.log(result, 'changeThisArea');
//
reset();
let level1 = result[0];
area.value.length = 0;
//
if (result.length === 1) {
result[0].selected = true;
area.value.push(result[0].id);
//
tabs1Ref.value.changeArea(result[0]);
// + 线
} else if (result.length === 2) {
//
if (!level1) {
level1 = treeData.value[0];
}
// true
level1.selected = result[1].selected = true;
area.value.splice(0, 0, level1.id, result[1].id);
//
tabs1Ref.value.changeArea(result[0]);
tabs1Ref.value.changeLine(result[1]);
}
};
//
const reset = () => {
treeData.value.forEach((item: any) => {
item.selected = false;
item.childList.forEach((v: any) => {
v.selected = false;
});
});
};
//
const computedClass = (string: string) => {
if (area.value.indexOf(string) != -1) {
return `isActive area-item area${string}`;
} else {
return `area-item area${string}`;
}
};
//
const getAllArea = (realod = false) => {
http.get(airConditionControl.getTree, { projectId: state.projectId }).then((res) => {
const data = res.data;
floorData.value = data;
/** 使
* @param id 用于判断样式和层级的前端属性
* @param selected 用于表示是否选中的前端属性
*/
// 1
data.forEach((floor: any) => {
// 2
floor.childList.forEach((item: any, index: number) => {
if (index == 0) {
item.selected = true;
} else {
item.selected = false;
}
item.id = String(index + 1);
// 3
item.childList.forEach((v: any, i: number) => {
v.selected = false;
v.id = index + 1 + '-' + (i + 1);
});
});
});
// 线 1-1,使thisFloor
let index = 0;
if (realod) {
data.find((item: any, i: number) => {
if (item.dataCode == thisFloor.value) {
return (index = i);
}
});
}
treeData.value = data[index].childList;
//
preload.value = true;
});
};
const reload = () => {
getAllArea(true);
};
// ==============================================
const getBulbs = () => {
http
.get(airConditionControl.getDeviceList, {
floor: thisFloor.value,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
console.log(res);
});
};
// =====================================================
// - tab
let activeKey = ref('1');
// -
let visible = ref(false);
// -
const toggleDrawer = () => {
visible.value = !visible.value;
};
// tab1
const tabs1Ref = ref();
</script>
<style lang="less" scoped>
@import './index.less';
//
.isActive {
border: 3px solid white !important;
}
// tab
:deep(.ant-tabs-tab-btn) {
color: white;
}
</style>

149
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/light.vue

@ -0,0 +1,149 @@
<template>
<a-popover color="rgba(0, 0, 0, 0.8)">
<template #content>
<div class="light-tag">
<div class="light-tag-tit">
<div>
<img src="/asset/image//bulbLogo/21962.png" alt="" />
<span class="tag-text">{{ result.name }}</span>
</div>
<button class="right-button">{{ type == 1 ? '正常' : '关闭' }}</button>
</div>
<div class="light-tag-box">
<div class="tag-box-item">
<img src="/asset/image//bulbLogo/22496.png" alt="" />
<span class="title">控制模式</span>
<span class="result">自动</span>
</div>
<div class="tag-box-item">
<img src="/asset/image//bulbLogo/22496.png" alt="" />
<span class="title">亮度</span>
<span class="result">{{ result.brightness }}</span>
</div>
<div class="tag-box-item">
<img src="/asset/image//bulbLogo/22496.png" alt="" />
<span class="title">控制场景</span>
<span class="result">{{ result.automatic2 }}</span>
</div>
<div class="tag-box-item">
<img src="/asset/image//bulbLogo/22496.png" alt="" />
<span class="title">色温</span>
<span class="result">{{ result.brightness3 }}</span>
</div>
</div>
</div>
</template>
<div class="icon-box" :style="styleObject" v-show="visible">
<img v-if="type == 1" class="icon-item" src="/asset/image/bulbLogo/22394.png" alt="" />
<img v-if="type == 2" class="icon-item" src="/asset/image/bulbLogo/22396.png" alt="" />
<img v-if="type == 3" class="icon-item" src="/asset/image/bulbLogo/22400.png" alt="" />
</div>
</a-popover>
</template>
<script setup lang="ts">
import { ref } from 'vue';
defineProps({
styleObject: Object,
type: Number,
visible: {
type: Boolean,
default: false,
},
});
const result = ref({
id: '1',
name: '站厅照明 1区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '舒适',
brightness3: '4000k',
brightness4: '3800k',
});
</script>
<style lang="less" scoped>
.icon-box {
width: 25px;
height: 25px;
position: absolute;
.icon-item {
width: 25px;
cursor: pointer;
transition: all ease 0.1s;
}
.icon-item:active {
transform: scale(1.2);
}
}
//
.light-tag {
display: flex;
flex-direction: column;
gap: 10px;
//
.light-tag-tit {
display: flex;
justify-content: space-between;
vertical-align: middle;
height: 30px;
.tag-text {
font-size: 16px;
font-weight: 700;
color: white;
padding-left: 10px;
}
.right-button {
width: 50px;
height: 26px;
background: rgba(57, 215, 187, 0.1);
border: 1px solid rgba(57, 215, 187, 1);
font-size: 12px;
color: rgba(57, 215, 187, 1);
}
}
}
// 4
.light-tag-box {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-gap: 10px;
.tag-box-item {
position: relative;
display: flex;
justify-content: space-between;
img {
width: 120px;
vertical-align: middle;
}
.title {
position: absolute;
left: 60px;
top: 13px;
color: rgba(64, 255, 252, 1);
}
.result {
line-height: 50px;
font-size: 16px;
font-weight: 700;
color: white;
}
}
}
</style>

3
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/lightPosition.ts

@ -0,0 +1,3 @@
// 此文件只定义light(即俯视图小灯泡)的位置信息
// 与显示状态和分组信息无关
export const lightPosition = [];

403
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs1.less

@ -0,0 +1,403 @@
// 抽屉
.drawer-item {
.light-area,
.circuit-area,
.control-area,
.control-scene-area,
.light-parameters-area {
width: 100%;
margin-top: 20px;
display: flex;
align-items: center;
}
.light-area-tab,
.circuit-tab,
.control-tab,
.control-scene-tab,
.light-parameters-tab {
width: 5px;
height: 23px;
opacity: 1;
background: rgba(26, 174, 251, 1);
margin-right: 4px;
}
.light-area-text,
.circuit-text,
.control-text,
.control-scene-text,
.light-parameters-text {
font-size: 14px;
color: white;
padding-left: 5px;
line-height: 23px;
width: 110px;
height: 23px;
background: linear-gradient(270deg, rgba(86, 221, 253, 0) 0%, rgba(25, 176, 255, 1) 100%);
user-select: none;
}
.light-area-tab,
.light-area-text {
display: inline-block;
justify-content: center;
}
.openPlan {
cursor: pointer;
border: none;
font-size: 14px;
font-weight: 400;
border-radius: 5px;
color: white;
vertical-align: top;
width: 88px;
height: 32px;
}
.openPlan.enabled2 {
background: linear-gradient(180deg, rgba(103, 222, 0, 1) 0%, rgba(0, 181, 6, 1) 100%);
}
.openPlan.disabled2 {
background-color: red;
}
.openPlan:disabled {
cursor: not-allowed;
}
.btn2 {
display: flex;
align-items: center;
margin-left: 80px;
}
.openzm {
cursor: pointer;
color: rgba(34, 183, 255, 1);
margin-left: 20px;
font-size: 14px;
}
.custom-checkbox {
width: 13px;
height: 13px;
}
.both {
width: 59.79px;
height: 32px;
opacity: 1;
background: linear-gradient(180deg,
rgba(255, 187, 0, 1) 0%,
rgba(255, 112, 3, 1) 91.21%,
rgba(255, 129, 3, 1) 100%);
margin-left: 8px;
font-size: 12px;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.btn2 {
button {
margin: 0 5px;
}
}
.allBtn {
border: 0;
width: 40px;
color: white;
background-color: transparent;
}
.blue-background.ant-switch-checked {
background-color: linear-gradient(180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%) !important;
}
.grey-background.ant-switch {
background-color: grey !important;
}
.blue-background.ant-switch-checked .ant-switch-handle {
background-color: linear-gradient(180deg,
rgba(1, 206, 255, 1) 0%,
rgba(0, 150, 229, 1) 100%) !important;
}
.grey-background.ant-switch .ant-switch-handle {
background-color: grey !important;
}
p {
color: white;
}
.area,
.btnArea,
.control-mode-btn-area,
.control-scene-btn-area {
margin-left: -17px;
button {
width: 21%;
padding: 0 2%;
}
}
.btn {
width: 92px;
height: 40px;
border-radius: 4px;
opacity: 1;
margin-top: 10px;
margin-left: 17px;
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;
}
.circuit-area,
.control-scene-area,
.light-parameters-area {
left: 51px;
width: 100%;
margin-top: 20px;
}
.circuit-tab,
.circuit-text {
display: inline-block;
}
.batch {
width: 60px;
height: 32px;
opacity: 1;
border: 1px solid rgba(67, 136, 251, 1);
color: rgba(67, 136, 251, 1);
border-radius: 5px;
background-color: white;
margin-left: 11px;
}
.control-area {
left: 51px;
width: 100%;
margin-top: 20px;
}
.control-tab,
.control-text {
display: inline-block;
}
:deep(.cell) {
text-align: center;
}
:deep(#pane-first) {
height: 100%;
}
.control-scene-tab,
.control-scene-text {
display: inline-block;
}
.light-parameters-tab,
.light-parameters-text {
display: inline-block;
}
.light-parameters-textarea>p {
height: 100%;
display: flex;
border: 1px solid rgba(236, 239, 245, 1);
justify-content: center;
align-items: center;
}
.bottom {
width: 100%;
height: 64px;
display: flex;
justify-content: flex-end;
align-items: center;
position: fixed;
bottom: 0;
right: 0;
}
.execute {
margin-right: 20px;
width: 74px;
height: 40px;
opacity: 1;
cursor: pointer;
border-radius: 4px;
background: rgba(67, 136, 251, 1);
font-size: 14px;
font-weight: 400;
color: white;
border: 0;
margin: 0 10px;
}
.flushed {
width: 74px;
height: 40px;
cursor: pointer;
opacity: 1;
border-radius: 4px;
font-size: 14px;
font-weight: 400;
color: rgba(102, 102, 102, 1);
background: white;
border: 1px solid rgba(193, 197, 204, 1);
margin: 0 10px;
}
:deep(.ant-table-pagination) {
visibility: hidden;
}
.drawer-content {
margin-left: 20px;
}
.arrow-indicator {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
z-index: 1;
}
.drawer-title1 {
position: fixed;
width: 33px;
height: 33px;
top: 0;
bottom: 0;
right: 20px;
margin: auto;
z-index: 99999;
}
.drawer-title2 {
position: fixed;
width: 33px;
height: 33px;
top: 0;
bottom: 0;
right: 495px;
margin: auto;
z-index: 99999;
}
.arrowbtn {
display: flex;
justify-content: center;
align-items: center;
width: 28px;
height: 28px;
background: rgba(0, 0, 0, 1);
opacity: 0.5;
border: none;
}
:deep(.ant-tabs-tab-btn) {
color: white;
}
:deep(.ant-table) {
background-color: transparent;
}
:deep(.ant-table-bordered) {
background-color: transparent;
}
:deep(.ant-table-thead) {
background-color: transparent;
}
:deep(.ant-table-cell) {
background-color: transparent;
color: #fff;
}
.custom-table {
border-collapse: collapse;
width: 416px;
height: 60px;
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%;
cellspacing: 0;
cellpadding: 0;
border: 1px solid rgba(255, 255, 255);
border-radius: 5px;
background: rgba(255, 255, 255, 0.1);
}
.light-area,
.circuit-area,
.control-area,
.control-scene-area,
.light-parameters-area {
width: 100%;
margin-top: 20px;
display: flex;
align-items: center;
}
.zmhlbtn {
position: relative;
}
// 禁用图标
.anticon-stop {
position: absolute;
right: 3px;
bottom: 3px;
}
}

754
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs1.vue

@ -0,0 +1,754 @@
<template>
<a-spin :spinning="isLoading">
<!-- 照明区域 -->
<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">
<button
class="openPlan"
:class="{ enabled2: isPlanEnabled2, disabled2: !isPlanEnabled2 }"
@click="togglePlan2">
{{ isPlanEnabled2 ? '启用开关' : '禁用开关' }}
</button>
<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)">
<stop-outlined v-if="button.ctrlStatus" />
{{ 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)">
<stop-outlined v-if="button.ctrlStatus" />
{{ 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"
@cancel="changeCancel">
<button class="flushed">刷新</button>
</a-popconfirm>
</a-badge>
<a-spin :spinning="buttonLoading">
<button class="execute" @click="showModal">执行</button>
</a-spin>
</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>
</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="取消"
@click="submitChangeList"
@cancel="changeCancel">
<button class="execute">执行</button>
</a-popconfirm>
</div>
</div>
</a-spin>
</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();
// -
handleButton.value = '';
};
// 8
const limitedButtons1 = computed(() => props.treeData.slice(0, 8));
// ======================================================================
// id
const handleButton = ref('');
// /
const isPlanEnabled2 = ref(true);
// /
const togglePlan2 = () => {
//
if (handleButton.value == '') {
return message.info('请选择照明回路');
}
//
const btn: any = buttons2.value.find((button: any) => button.id === handleButton.value);
let panel = +!btn.ctrlStatus;
isLoading.value = true;
http
.get(lightingManage.setDisable, {
deviceGroup: btn.dataCode,
panel,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
if (res.msg === 'success') {
// - - - loading
isPlanEnabled2.value = !isPlanEnabled2.value;
btn.ctrlStatus = panel;
isLoading.value = false;
} else {
isLoading.value = false;
}
})
.catch(() => {
isLoading.value = false;
});
};
//
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) => {
console.log(button, 'button2mmmm');
// ID/
handleButton.value = button.id;
// /
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 {
alert(v.treePid + '---' + before + '---' + after);
changed += 1;
resetScene(item.childList);
changeScene(v1, before, after);
v1.executeStatus.value = 1;
}
}
});
}
});
}
});
alert(`共修改${sum}条,${checked}条无需修改,${nofind}条不具有该选项,${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 当前回路场景的初始值撤回时需使用
*/
const changeScene = (button: any, before: string | undefined, after: string) => {
console.log(changeList.value, 'vvvvvvvvvvvvvv-----', button, 'bbbbbbbb---------');
// ID
const result = changeList.value.find((item: any, index: number) => {
item.index = index;
return item.deviceGroup == button.treePid.split('_')[0];
});
console.log(result, 'rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr');
//
if (result) {
//
if (after == result.before) {
changeList.value.splice(result.index, 1);
//
} else {
result.scene = after;
// flag
delete result.index;
}
//
} else {
changeList.value.push({
//
deviceGroup: thisButton2.value.dataCode,
deviceGroupName: thisButton2.value.name,
//
region: thisButton2.value.treePid,
regionName: '',
//
before,
scene: after,
});
}
button.executeStatus.value = 1;
};
// ======================================================================
const isLoading = ref(false);
// loading
const buttonLoading = ref(false);
//
const refresh = () => {
//
executeVisible.value = false;
//
selectedButton.value = '1';
//
emit('changeArea', ['1']);
emit('reset');
//
changeList.value.forEach((item: any) => {
resetChangeList(item);
});
changeList.value = [];
//
let data = props.treeData[0];
//
data.selected = true;
// 1-1
buttons2.value = data.childList;
// 线
resetMode();
};
//
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 == v3.dataCode) {
v3.executeStatus.value = 1;
}
});
}
});
}
});
}
});
};
//
const showModal = () => {
if (!changeList.value.length) {
return message.info('未产生任何修改');
}
buttonLoading.value = true;
http
.post(airConditionControl.getChangeList, {
sceneList: changeList.value,
lockList: [],
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
if (res.msg === 'success') {
diffList.value = res.data;
executeVisible.value = true;
} else {
message.warning('获取修改内容失败');
}
buttonLoading.value = false;
})
.catch(() => {
buttonLoading.value = false;
});
};
//
const changeCancel = () => {};
// ========================================================================
//
const executeVisible = ref<boolean>(false);
//
const changeList: any = ref([]);
//
const diffList = ref([]);
//
const delBtn = (obj: any) => {
// treeData
obj.scene = obj.stateAfter.scene.value;
obj.before = obj.stateBefore.scene.value;
resetChangeList(obj);
// changeList diffList ()
changeList.value = changeList.value.filter((item: any) => {
return item.deviceGroup !== obj.deviceGroup;
});
diffList.value = diffList.value.filter((item: any) => {
return item.deviceGroup !== obj.deviceGroup;
});
console.log(changeList, 'changeList');
console.log(diffList, 'diffList');
//
if (changeList.value.length == 0) {
executeVisible.value = false;
}
};
//
const submitChangeList = () => {
http
.post(airConditionControl.submitChangeList, {
sceneList: changeList.value,
lockList: [],
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
emit('reload');
refresh();
});
};
// ========================================================================
//
const resetMode = () => {
thisButton2.value = {
dataCode: '',
name: '',
treePid: '',
childList: [],
};
};
//
defineExpose({
//
changeArea,
//
changeLine,
});
</script>
<style lang="less" scoped>
@import './dialogStyle.less';
@import './tabs1.less';
</style>

318
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs2.vue

@ -0,0 +1,318 @@
<template>
<div class="div-add">
<button class="add" @click="addModal">添加</button>
<button class="add" style="margin-left: 20px" @click="sendTable">执行</button>
</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" :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="取消"
@confirm="deletePlan(row)">
<div class="tabDelete">删除</div>
</a-popconfirm>
</td>
</tr>
</tbody>
</table>
<div class="out-dialog" v-if="addVisible">
<div class="content" v-if="addVisible">
<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 { airConditionControl } from '/@/api/airConditionControlSystem';
import { message } from 'ant-design-vue';
import { getEnum } from '/@/api';
//
import { items } from '/@/store/item';
// ===========================================================
onMounted(() => {
getStateEnum();
//
getTable();
// 穿
getLeftPlan();
});
//
const state = items();
const getStateEnum = async () => {
let enumData = await getEnum({ params: { enumType: 'PlanExecuteStatus' } });
stateList.value = enumData.data;
};
// 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) => {
item.executeStatus.value = state;
});
};
//
const dataSource = ref([]);
//
const getTable = () => {
http
.get(airConditionControl.getTableData, { projectId: state.projectId, siteId: state.siteId })
.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('该数据已是待执行状态,无需再次修改');
}
row.executeStatus.value = 1;
};
//
const sendTable = () => {
http.post(airConditionControl.submitTableData, dataSource.value).then((res) => {
message.success('操作成功');
getTable();
getLeftPlan();
});
};
// tab ====================================================
//
const addVisible = ref(false);
//
const addModal = () => {
addVisible.value = true;
};
// 穿 =======================================================
// 穿
const transferData = ref([]) as any;
// 穿
const getLeftPlan = () => {
http
.get(airConditionControl.getTransData, { projectId: state.projectId, siteId: state.siteId })
.then((res) => {
let arr = [];
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(airConditionControl.submitTransData, targetKeys.value).then(() => {
message.success('添加成功');
//
getTable();
getLeftPlan();
});
};
const filterOption = (inputValue: string, option: any) => {
return option.description.indexOf(inputValue) > -1;
};
</script>
<style lang="less" scoped>
@import './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>

251
hx-ai-intelligent/src/view/equipmentControl/airConditionControlSystem/tabs3.vue

@ -0,0 +1,251 @@
<template>
<table class="custom-table table1">
<thead>
<tr :style="{ background: 'rgba(35,45,69)' }">
<th>序号</th>
<th>执行时间</th>
<th>操作内容</th>
<th>操作人</th>
</tr>
</thead>
<tbody>
<tr
v-for="(row, index) in dataSource1"
:key="index"
@click="handleRowClick(row.key)"
:class="row.key === trIndex ? 'isTrIndex' : ''">
<td>{{ row.key }}</td>
<td>{{ row.data }}</td>
<td>{{ row.planName }}</td>
<td>{{ row.status }}</td>
</tr>
</tbody>
</table>
<div class="out-dialog" :class="{ showDialog: logModalVisible }" v-if="logModalVisible">
<div class="content" v-if="logModalVisible">
<div>
<div class="div-operation"></div>
<span class="text-operation">操作日志 </span>
</div>
<div class="j-box" v-for="item in cxList" :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.name }}</span
>
</div>
</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">
<span>100lux</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>30lux</span>
</div>
</div>
<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">
<span>4000k</span>
<img src="/asset/image/bulbLogo/22406.png" alt="" />
<span>3800k</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div style="height: 60px"></div>
<div class="button-box">
<button class="cancel" @click="logModalVisible = false">取消</button>
</div>
</div>
<div class="div-add">
<button class="add">刷新</button>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
//
onMounted(() => {});
// ===================================================================
const props = defineProps({
// >
treeData: {
type: Array,
},
});
const emit = defineEmits(['changeArea']);
//
const dataSource1 = ref([
{
key: '1',
data: '2024-05-01',
planName: '计划再开',
status: '张三111',
},
{
key: '2',
data: '2024-05-01',
planName: '检修模式',
status: '李四12',
},
{
key: '3',
data: '2024-05-01',
planName: '设备变更',
status: '王五33',
},
]);
const cxList = ref([
{
id: '1',
name: '站厅照明 1区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
{
id: '2',
name: '站厅照明 2区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
{
id: '3',
name: '站厅照明 3区',
manual: '手动',
automatic: '自动',
brightness: '100lux',
brightness2: '30lux',
manual2: '手动',
automatic2: '自动',
brightness3: '4000k',
brightness4: '3800k',
},
]);
let trIndex = ref('-1');
const logModalVisible = ref(false);
const handleRowClick = (index: any) => {
trIndex.value = index;
if (index === trIndex.value) {
console.log('tri');
}
//
logModalVisible.value = true;
};
</script>
<style lang="less" scoped>
@import './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;
height: 60px;
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;
}
}
</style>

4
hx-ai-intelligent/src/view/equipmentControl/lightingManage/indexs.vue

@ -7,7 +7,7 @@
v-for="(item, index) in floorData"
:key="index"
class="btn-item"
@click="changeFloor(item.childList, item.code)"
@click="changeFloor(item.childList, item.dataCode)"
>{{ item.name }}</button
>
</div>
@ -233,7 +233,7 @@
//
const getAllArea = () => {
http.get(lightingManage.getArea, { projectId: state.projectId }).then((res) => {
http.get(lightingManage.getTree, { projectId: state.projectId }).then((res) => {
const data = res.data;
floorData.value = data;
/** 使

71
hx-ai-intelligent/src/view/equipmentControl/lightingManage/tabs1.vue

@ -98,27 +98,26 @@
</div>
</div>
<!-- 控制模式部分 -->
<div>
<div class="control-area" v-show="thisButton2.code">
<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" v-show="thisButton2.code">
<div class="control-mode-btn-area">
<button
v-for="(button3, index) in controlMode"
v-for="(button3, index) in thisButton2.childList"
:key="index"
class="btn"
:disabled="button3.value != 3"
:class="{ selected: thisButton2.mode.value == button3.value }"
:class="{ selected: button3.selectAble }"
@click="selectButton3(button3)">
{{ button3.label }}
{{ button3.name }}
</button>
</div>
</div>
<!-- 控制场景部分 -->
<div>
<div class="control-scene-area" v-show="thisButton2.mode.value == 3">
<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"
@ -126,13 +125,13 @@
>
</div>
<!-- 控制场景按钮部分 -->
<div class="control-scene-btn-area" v-show="thisButton2.mode.value == 3">
<div class="control-scene-btn-area">
<button
v-for="(button4, index) in controlScene"
v-for="(button4, index) in thisButton3.childList"
:key="index"
:class="{ btn: true, selected: thisButton2.scene.value == button4.value }"
:class="{ btn: true, selected: button4.executeStatus.value != 0 }"
@click="selectButton4(button4)">
{{ button4.label }}
{{ button4.name }}
</button>
</div>
</div>
@ -156,7 +155,7 @@
<!-- 点击执行时的弹出框 -->
<div class="out-dialog" v-if="executeVisible">
<div class="content" v-if="executeVisible">
<div class="content">
<div>
<div class="div-operation"></div>
<span class="text-operation">变更内容 </span>
@ -247,7 +246,6 @@
//
import { http } from '/nerv-lib/util/http';
import { lightingManage } from '/@/api/IlluminationInfo';
import { getAllEnum } from '/@/api/index';
//
import { items } from '/@/store/item';
@ -256,19 +254,7 @@
onMounted(() => {
//
setArea();
//
getEnum(['IlluminationMode', 'IlluminationScene']);
});
//
const getEnum = (arr: any) => {
getAllEnum({ params: arr }).then((res) => {
const data = res.data;
//
controlMode.value = data.IlluminationMode;
//
controlScene.value = data.IlluminationScene;
});
};
// 1-1
const setArea = () => {
const data = props.treeData[0];
@ -346,7 +332,7 @@
isLoading.value = true;
http
.get(lightingManage.setDisable, {
deviceGroup: btn.code,
deviceGroup: btn.dataCode,
panel,
projectId: state.projectId,
siteId: state.siteId,
@ -419,6 +405,7 @@
scene: {
value: -1,
},
childList: [],
});
//
const changeLine = (button: any) => {
@ -455,6 +442,12 @@
if (button.selected) {
//
thisButton2.value = button;
//
thisButton3.value = button.childList.find((item: any) => {
if (item.selectAble) {
return item.childList ? item.childList : [];
}
});
} else {
//
resetMode();
@ -471,23 +464,20 @@
// ====================================================================
const thisButton3 = ref({
childList: [],
});
// -
const selectButton3 = (button3: any) => {
let checked = thisButton2.value.mode;
console.log(button3.value, '---', checked.value);
//
if (checked.value === button3.value) {
return;
console.log(button3);
if (!button3.selectAble) {
return message.warning(`${button3.name} 暂不支持`);
}
checked.value = button3.value;
thisButton3.value = button3;
};
// =====================================================================
//
const controlMode = ref([]);
//
const controlScene = ref([]);
// -
const selectButton4 = (button4) => {
//
@ -527,7 +517,7 @@
//
const result = changeList.value.find((item: any, index: number) => {
item.index = index;
return item.deviceGroup == button.code;
return item.deviceGroup == button.dataCode;
});
//
if (result) {
@ -544,7 +534,7 @@
} else {
changeList.value.push({
//
deviceGroup: button.code,
deviceGroup: button.dataCode,
deviceGroupName: button.name,
//
region: button.pcode,
@ -659,6 +649,7 @@
scene: {
value: -1,
},
childList: [],
};
};

Loading…
Cancel
Save