This commit is contained in:
zhaohy
2024-07-30 14:37:41 +08:00
11 changed files with 330 additions and 171 deletions

View File

@@ -1,13 +1,13 @@
// 照明系统及相关接口 // 照明系统及相关接口
export enum lightingManage { export enum lightingManage {
// 主页 ======================================================== // 主页 ========================================================
// 获得分区与线路 // 获得分区与线路
getArea = '/carbon-smart/IlluminationInfo/region', getArea = '/carbon-smart/IlluminationInfo/region',
// 修改线路的可用/禁用状态 // 修改线路的可用/禁用状态
setDisable = '/carbon-smart/IlluminationInfo/revisePanel', setDisable = '/carbon-smart/IlluminationInfo/changePanelStatus',
// 获得设备 - 小灯泡
getBulbs = '/carbon-smart/IlluminationInfo/getLightState',
// 控制面板tab页 ================================================ // 控制面板tab页 ================================================

View File

@@ -3,7 +3,14 @@ import { defineStore } from 'pinia';
export const items = defineStore({ export const items = defineStore({
id: 'items', id: 'items',
state() { state() {
return { list: [], count: 10 }; return {
list: [],
count: 10,
// 当前项目ID
projectId: 'HLlmTZp8',
// 站点ID
siteId: undefined,
};
}, },
getters: { getters: {
double: (state: any) => state.count * 2, double: (state: any) => state.count * 2,

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="map-box"> <div class="map-box">
<div class="map"> <div class="map">
<liftInfo /> <liftInfo v-for="(item, index) in liftBox" :key="index" :liftInfo="item" />
</div> </div>
</div> </div>
</template> </template>
@@ -16,14 +16,30 @@
onMounted(() => {}); onMounted(() => {});
// tab页部分 ======================================================== // tab页部分 ========================================================
const liftBox = ref([
// 表格数据 {
const dataSource = ref([]); name: '办公区域扶梯A',
workState: 1,
faultState: 2,
direction: 1,
type: 2,
isLeft: true,
styleText: { left: '245px', bottom: '230px' },
},
{
name: '办公区域扶梯B',
workState: 0,
faultState: 3,
direction: 0,
type: 1,
isLeft: false,
styleText: { left: '700px', bottom: '360px' },
},
]);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.map-box { .map-box {
// 颜色变量,用于区别颜色 // 颜色变量,用于区别颜色
// 正常 - 开启 - 上行 -下行 // 正常 - 开启 - 上行 -下行
--on: #0dffa4; --on: #0dffa4;
// 关闭 // 关闭
@@ -36,6 +52,8 @@
--fault: #ff7636; --fault: #ff7636;
// 未知 // 未知
--unknown: #a742ff; --unknown: #a742ff;
// 触发图标大小
--size: 40px;
width: 100%; width: 100%;
height: 100%; height: 100%;
.map { .map {

View File

@@ -1,49 +1,61 @@
<template> <template>
<div class="info-box"> <div class="icon-box" :style="info.styleText">
<div class="box-title"> <img v-if="info.type == 1" src="../image/liftState/lift/lift1.png" alt="" />
<div class="dot"></div> <img v-else-if="info.type == 2" src="../image/liftState/lift/lift2.png" alt="" />
<span>办公区域扶梯A</span> <div class="tab" :class="[info.isLeft ? 'left' : 'right']">
</div> <div v-if="info.isLeft" class="line"></div>
<div class="box-inner"> <div class="info-box">
<!-- 是否开启 --> <div class="box-title">
<div class="item"> <div class="dot"></div>
<div class="item-box"> <span>{{ info.name }}</span>
<div class="icon"> </div>
<div class="icon-item"> <div class="box-inner">
<img src="../image/liftState/lift-normal.svg" alt="" /> <!-- 是否开启 -->
<div class="item">
<div class="item-box">
<div class="icon">
<div class="icon-item">
<img v-if="info.workState" src="../image/liftState/switch-on.svg" alt="" />
<img v-else src="../image/liftState/switch-off.svg" alt="" />
</div>
</div>
</div>
<div class="item-text">
<span v-if="info.workState" style="color: var(--on)">开启</span>
<span v-else style="color: var(--off)">关闭</span>
</div> </div>
</div> </div>
</div> <!-- 是否故障 -->
<div class="item-text">开启</div> <div class="item">
</div> <div class="item-box">
<!-- 是否故障 --> <div class="icon">
<div class="item"> <div class="icon-item">
<div class="item-box"> <img src="../image/liftState/lift-normal.svg" alt="" />
<div class="icon"> </div>
<div class="icon-item"> </div>
<img src="../image/liftState/lift-normal.svg" alt="" />
</div> </div>
<div class="item-text">开启</div>
</div>
<!-- 如何运行 -->
<div class="item">
<div class="item-box">
<div class="icon">
<div class="icon-item">
<img src="../image/liftState/lift-normal.svg" alt="" />
</div>
</div>
</div>
<div class="item-text">开启</div>
</div> </div>
</div> </div>
<div class="item-text">开启</div>
</div>
<!-- 如何运行 -->
<div class="item">
<div class="item-box">
<div class="icon">
<div class="icon-item">
<img src="../image/liftState/lift-normal.svg" alt="" />
</div>
</div>
</div>
<div class="item-text">开启</div>
</div> </div>
<div v-if="!info.isLeft" class="line1"></div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, computed, onMounted } from 'vue';
// 请求 // 请求
@@ -51,96 +63,151 @@
onMounted(() => {}); onMounted(() => {});
// tab页部分 ======================================================== const props = defineProps({
// 分区结构(照明区域 > 照明回路)
liftInfo: {
type: Object,
default: () => {},
},
});
// 运行状态 const info = computed(() => {
const runState = ref('1'); return props.liftInfo;
// 电梯状态 });
const liftState = ref('2');
// tab页部分 ========================================================
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
// 面板 .icon-box:hover {
.info-box { }
// 字体颜色变量 .icon-box {
--text: rgb(20, 255, 255); width: var(--size);
height: var(--size);
width: 240px; position: absolute;
height: 130px; transition: all ease 0.2s;
display: flex; > img {
gap: 5px; width: 100%;
flex-direction: column; height: 100%;
background: rgb(17, 44, 86, 0.9); cursor: pointer;
border-radius: 8px; user-select: none;
box-sizing: border-box; position: relative;
padding: 8px; z-index: 9;
border: 3px solid var(--text);
// 面板标题
.box-title {
height: auto;
color: var(--text);
// 标题前小方块
.dot {
display: inline-block;
width: 2px;
height: 16px;
vertical-align: middle;
background: var(--text);
}
// 标题
span {
padding-left: 8px;
}
} }
// 下半部分 .tab {
.box-inner { position: absolute;
flex: 1; bottom: -20px;
display: flex; display: flex;
padding: 0 10px; .line {
// 单个盒子3盒子 position: relative;
.item { z-index: 1;
flex: 1; width: 40px;
height: 75px;
background-image: url(../image/liftState/lift/line.png);
background-size: 100% 100%;
}
.line1 {
position: relative;
z-index: 1;
width: 40px;
height: 75px;
transform: rotateY(180deg);
background-image: url(../image/liftState/lift/line.png);
background-size: 100% 100%;
}
// 面板
.info-box {
// 字体颜色变量
--text: rgb(20, 255, 255);
width: 250px;
height: 130px;
display: flex; display: flex;
gap: 5px;
flex-direction: column; flex-direction: column;
// 盒子中放置图片的容器 background: rgb(17, 44, 86, 0.9);
.item-box { border-radius: 8px;
box-sizing: border-box;
padding: 8px;
border: 2px solid var(--text);
transform: translateY(-50%);
cursor: pointer;
// 面板标题
.box-title {
height: auto;
color: var(--text);
// 标题前小方块
.dot {
display: inline-block;
width: 2px;
height: 16px;
vertical-align: middle;
background: var(--text);
}
// 标题
span {
padding-left: 8px;
}
}
// 下半部分
.box-inner {
flex: 1; flex: 1;
display: flex; display: flex;
align-items: center; padding: 0 5px;
justify-content: center; // 单个盒子3盒子
// border: 1px solid red; .item {
.icon { flex: 1;
width: 55px; display: flex;
height: 55px; flex-direction: column;
background-image: url(../image/box.svg); // 盒子中放置图片的容器
background-size: 130% 130%; .item-box {
background-repeat: no-repeat; flex: 1;
background-position: left -8px top -8px; display: flex;
// border: 1px solid red; align-items: center;
position: relative; justify-content: center;
.icon-item { // border: 1px solid red;
position: absolute; .icon {
width: 20px; width: 55px;
height: 20px; height: 55px;
left: 0; background-image: url(../image/box.svg);
right: 0; background-size: 130% 130%;
bottom: 0; background-repeat: no-repeat;
top: 0; background-position: left -8px top -8px;
margin: auto; // border: 1px solid red;
img { position: relative;
width: 100%; .icon-item {
height: 100%; position: absolute;
width: 20px;
height: 20px;
left: 0;
right: 0;
bottom: 0;
top: 0;
margin: auto;
img {
width: 100%;
height: 100%;
}
}
} }
} }
.item-text {
height: 20px;
text-align: center;
font-size: 12px;
color: white;
user-select: none;
}
} }
} }
.item-text {
height: 20px;
text-align: center;
font-size: 12px;
color: white;
user-select: none;
}
} }
.info-box:hover {
border: 2px solid white;
}
}
.right {
right: calc(var(--size) / 2);
}
.left {
left: calc(var(--size) / 2);
} }
} }
</style> </style>

View File

@@ -0,0 +1,3 @@
// 此文件只定义lift即电梯的位置信息
// 与显示状态和分组信息无关
export const liftPosition = [];

View File

@@ -3,9 +3,13 @@
<div class="lighting-img-box"> <div class="lighting-img-box">
<!-- 左上角区域切换 --> <!-- 左上角区域切换 -->
<div class="btn-box"> <div class="btn-box">
<button v-for="item in floorData" class="btn-item" @click="changeFloor(item.childList)">{{ <button
item.name v-for="(item, index) in floorData"
}}</button> :key="index"
class="btn-item"
@click="changeFloor(item.childList, item.code)"
>{{ item.name }}</button
>
</div> </div>
<!-- 楼层区域 --> <!-- 楼层区域 -->
<div class="area"> <div class="area">
@@ -77,14 +81,20 @@
import { lightingManage } from '/@/api/IlluminationInfo'; import { lightingManage } from '/@/api/IlluminationInfo';
// ICON // ICON
import { DoubleLeftOutlined, DoubleRightOutlined } from '@ant-design/icons-vue'; import { DoubleLeftOutlined, DoubleRightOutlined } from '@ant-design/icons-vue';
// 全局变量
import { items } from '/@/store/item';
// 初始化 ======================================================= // 初始化 =======================================================
onMounted(() => { onMounted(() => {
// 获得分区与线路的结构 // 获得分区与线路的结构
getAllArea(); getAllArea();
// 获得俯视图中的小灯泡
getBulbs();
}); });
// 获得全局变量
const state = items();
// 预加载flag获得分区数据后预加载抽屉防止获取ref报错 // 预加载flag获得分区数据后预加载抽屉防止获取ref报错
const preload = ref(false); const preload = ref(false);
@@ -92,8 +102,11 @@
// 所有楼层的数据 // 所有楼层的数据
const floorData = ref([]); const floorData = ref([]);
// 当前选择的楼层
const thisFloor = ref(1);
// 左上角分层切换 // 左上角分层切换
const changeFloor = (area: any) => { const changeFloor = (area: any, floor: number) => {
thisFloor.value = floor;
// 重置数据 // 重置数据
reset(); reset();
// 重置视图 // 重置视图
@@ -220,7 +233,7 @@
// 获得所有分区 // 获得所有分区
const getAllArea = () => { const getAllArea = () => {
http.get(lightingManage.getArea, { projectId: 'HLlmTZp8' }).then((res) => { http.get(lightingManage.getArea, { projectId: state.projectId }).then((res) => {
const data = res.data; const data = res.data;
floorData.value = data; floorData.value = data;
/** 只在前端使用的变量 /** 只在前端使用的变量
@@ -248,6 +261,20 @@
}); });
}; };
// 设备业务 小灯泡 ==============================================
const getBulbs = () => {
http
.get(lightingManage.getBulbs, {
floor: thisFloor.value,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => {
console.log(res);
});
};
// 抽屉业务 ===================================================== // 抽屉业务 =====================================================
// 抽屉 - 当前选择的tab // 抽屉 - 当前选择的tab

View File

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

View File

@@ -50,7 +50,7 @@
class="openPlan" class="openPlan"
:class="{ enabled2: isPlanEnabled2, disabled2: !isPlanEnabled2 }" :class="{ enabled2: isPlanEnabled2, disabled2: !isPlanEnabled2 }"
@click="togglePlan2"> @click="togglePlan2">
{{ isPlanEnabled2 ? '启用面板' : '禁用面板' }} {{ isPlanEnabled2 ? '启用开关' : '禁用开关' }}
</button> </button>
<a-switch <a-switch
v-model:checked="selectAllCheckbox" v-model:checked="selectAllCheckbox"
@@ -248,11 +248,13 @@
import { http } from '/nerv-lib/util/http'; import { http } from '/nerv-lib/util/http';
import { lightingManage } from '/@/api/IlluminationInfo'; import { lightingManage } from '/@/api/IlluminationInfo';
import { getAllEnum } from '/@/api/index'; import { getAllEnum } from '/@/api/index';
// 全局变量
import { items } from '/@/store/item';
// 初始化 ========================================================================= // 初始化 =========================================================================
onMounted(() => { onMounted(() => {
// 默认选项 // 分区初始化
setArea(); setArea();
// 获得枚举 // 获得枚举
getEnum(['IlluminationMode', 'IlluminationScene']); getEnum(['IlluminationMode', 'IlluminationScene']);
@@ -267,11 +269,13 @@
controlScene.value = data.IlluminationScene; controlScene.value = data.IlluminationScene;
}); });
}; };
// 以 1-1 作为默认回路 // 分区初始化,以 1-1 作为默认回路
const setArea = () => { const setArea = () => {
const data = props.treeData[0]; const data = props.treeData[0];
buttons2.value = data.childList; buttons2.value = data.childList;
}; };
// 全局变量
const state = items();
// 与父组件的交互 =================================================================== // 与父组件的交互 ===================================================================
@@ -279,11 +283,12 @@
// 分区结构(照明区域 > 照明回路) // 分区结构(照明区域 > 照明回路)
treeData: { treeData: {
type: Array, type: Array,
default: [], default: () => {
[];
},
}, },
}); });
// 向上传递修改选择样式 /** 向上传递方法
/**
* @method changeArea 用于控制俯视图的选中状态 * @method changeArea 用于控制俯视图的选中状态
* @method reset 用于重置按钮区 * @method reset 用于重置按钮区
*/ */
@@ -327,9 +332,9 @@
// 最近交互过的按钮id用于禁用和启用 // 最近交互过的按钮id用于禁用和启用
const handleButton = ref(''); const handleButton = ref('');
// 面板启用/禁用状态 // 开关启用/禁用状态
const isPlanEnabled2 = ref(true); const isPlanEnabled2 = ref(true);
// 面板启用/禁用切换事件 // 开关启用/禁用切换事件
const togglePlan2 = () => { const togglePlan2 = () => {
// 如果未交互任何按钮 // 如果未交互任何按钮
if (handleButton.value == '') { if (handleButton.value == '') {
@@ -340,7 +345,12 @@
let panel = +!btn.ctrlStatus; let panel = +!btn.ctrlStatus;
isLoading.value = true; isLoading.value = true;
http http
.get(lightingManage.setDisable, { deviceGroup: btn.code, panel }) .get(lightingManage.setDisable, {
deviceGroup: btn.code,
panel,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => { .then((res) => {
if (res.msg === 'success') { if (res.msg === 'success') {
// 确认成功后 - 按钮文本取反 - 按钮布尔值修改 - 关闭loading // 确认成功后 - 按钮文本取反 - 按钮布尔值修改 - 关闭loading
@@ -392,7 +402,7 @@
buttons2.value.forEach((item: any) => { buttons2.value.forEach((item: any) => {
item.selected = false; item.selected = false;
}); });
// 全不选时,隐藏模式-场景按钮 // 全不选时,隐藏 模式场景 按钮
resetMode(); resetMode();
} }
emit('changeArea', arr); emit('changeArea', arr);
@@ -423,7 +433,7 @@
// 选择时反控俯视图 // 选择时反控俯视图
let level1 = selectedButton.value; let level1 = selectedButton.value;
let level2 = button.id; let level2 = button.id;
// 单选模式,需将所有其他按钮设为false // 单选模式,需将所有其他回路设为false
if (singleSelection.value) { if (singleSelection.value) {
buttons2.value.forEach((item: any) => { buttons2.value.forEach((item: any) => {
item.selected = false; item.selected = false;
@@ -486,44 +496,64 @@
let before = data.scene.value; let before = data.scene.value;
// 修改后的数据 // 修改后的数据
let after = button4.value; let after = button4.value;
// 如果没有产生实质性的修改(修改前后相同,则跳出) // 如果是多选模式
if (before === after) { if (!singleSelection.value) {
return message.info('未产生实际修改'); buttons2.value.forEach((item: any) => {
// 产生了修改 // 查看当前回路,哪些被选中
} else { if (item.selected) {
thisButton2.value.scene.value = after; changeScene(item, item.scene.value, after);
// 查询之前是否修改过 item.scene.value = after;
const result = changeList.value.find((item: any, index: number) => {
item.index = index;
return item.deviceGroup == data.code;
});
// 如果已产生过修改
if (result) {
// 改回了原有的值,则从数组中移除
if (after == result.before) {
changeList.value.splice(result.index, 1);
// 修改为新值则只修改after
} else {
result.scene = after;
// 临时flag用后移除
delete result.index;
} }
// 如果未产生过修改 });
thisButton2.value.scene.value = after;
return message.info('已修改X项');
// 如果是单选模式
} else {
// 如果没有产生实质性的修改(修改前后相同,则跳出)
if (before === after) {
return message.info('未产生实际修改');
// 产生了修改
} else { } else {
changeList.value.push({ changeScene(data, before, after);
// 回路
deviceGroup: data.code,
deviceGroupName: data.name,
// 分区
region: data.pcode,
regionName: '',
// 修改前
before: before,
// 修改后
scene: after,
});
} }
console.log(changeList.value, 'changeList'); }
};
/** 控制场景 - 按钮切换通用方法(单选 & 多选)
* @param button 当前被选中的回路(单选 & 多选)
* @param before 回路场景的初始值(撤回时需使用)
* @param after 回路场景被修改后的值
*/
const changeScene = (button: any, before: number, after: number) => {
// 查询之前是否修改过
const result = changeList.value.find((item: any, index: number) => {
item.index = index;
return item.deviceGroup == button.code;
});
// 如果已产生过修改
if (result) {
// 改回了原有的值,则从数组中移除
if (after == result.before) {
changeList.value.splice(result.index, 1);
// 修改为新值则只修改after
} else {
result.scene = after;
// 临时flag用后移除
delete result.index;
}
// 如果未产生过修改
} else {
changeList.value.push({
// 回路
deviceGroup: button.code,
deviceGroupName: button.name,
// 分区
region: button.pcode,
regionName: '',
// 修改前
before: before,
// 修改后
scene: after,
});
} }
thisButton2.value.scene.value = after; thisButton2.value.scene.value = after;
}; };
@@ -559,7 +589,11 @@
} }
buttonLoading.value = true; buttonLoading.value = true;
http http
.post(lightingManage.getChangeList, { infoList: changeList.value, projectId: 'HLlmTZp8' }) .post(lightingManage.getChangeList, {
infoList: changeList.value,
projectId: state.projectId,
siteId: state.siteId,
})
.then((res) => { .then((res) => {
if (res.msg === 'success') { if (res.msg === 'success') {
diffList.value = res.data; diffList.value = res.data;