全部打开/关闭

This commit is contained in:
WindowBird 2025-10-14 17:54:52 +08:00
parent 07459ccd39
commit 8cf6372b6e
2 changed files with 348 additions and 312 deletions

View File

@ -128,6 +128,33 @@ export default {
} }
}, },
//
buildGatewayPayload(command, reason) {
// 使 getCurrentSelection
let selection = this.currentSelection;
if (
this.$refs.floorSelector &&
typeof this.$refs.floorSelector.getCurrentSelection === "function"
) {
selection = this.$refs.floorSelector.getCurrentSelection();
}
const floorId = selection?.floor?.label;
if (!floorId) {
uni.showToast({ title: "请先选择楼层", icon: "none" });
return false;
}
console.log("floodr", floorId);
return {
// floorId regionId
regionId: String(floorId),
command, // open | close
mac: "FFFFFFFFFFFF",
timeout: "11",
reason,
};
},
// //
async promptDurationAndUnit() { async promptDurationAndUnit() {
// 1: 2: 3: 4: // 1: 2: 3: 4:
@ -173,11 +200,20 @@ export default {
}, },
async handleAllOpen() { async handleAllOpen() {
if (!this.ensureUnitSelected()) return; const payload = this.buildGatewayPayload("open", "全开");
await this.performPut( await this.performPut(
`/app/memorial/sendCommandGateway`, `/app/memorial/sendCommandGateway`,
null, payload,
"handleForceOpen", "handleAllOpen",
);
},
async handleAllClose() {
const payload = this.buildGatewayPayload("close", "全关");
await this.performPut(
`/app/memorial/sendCommandGateway`,
payload,
"handleAllClose",
); );
}, },

View File

@ -7,8 +7,8 @@
<view <view
v-for="floor in floors" v-for="floor in floors"
:key="floor.id" :key="floor.id"
class="floor-btn"
:class="{ active: selectedFloor && selectedFloor.id === floor.id }" :class="{ active: selectedFloor && selectedFloor.id === floor.id }"
class="floor-btn"
@click="selectFloor(floor)" @click="selectFloor(floor)"
> >
{{ floor.label }} {{ floor.label }}
@ -25,8 +25,8 @@
<view <view
v-for="area in areas" v-for="area in areas"
:key="area.id" :key="area.id"
class="area-btn"
:class="{ active: selectedArea && selectedArea.id === area.id }" :class="{ active: selectedArea && selectedArea.id === area.id }"
class="area-btn"
@click="selectArea(area)" @click="selectArea(area)"
> >
{{ area.label }} {{ area.label }}
@ -42,8 +42,8 @@
<view <view
v-for="unit in units" v-for="unit in units"
:key="unit.id" :key="unit.id"
class="unit-btn"
:class="{ active: selectedUnit && selectedUnit.id === unit.id }" :class="{ active: selectedUnit && selectedUnit.id === unit.id }"
class="unit-btn"
@click="selectUnit(unit)" @click="selectUnit(unit)"
> >
{{ unit.label }} {{ unit.label }}
@ -55,328 +55,328 @@
</template> </template>
<script> <script>
import { getMemorialTree } from '@/api/memorial/index.js' import { getMemorialTree } from "@/api/memorial/index.js";
export default { export default {
name: 'FloorSelector', name: "FloorSelector",
props: { props: {
// ID // ID
defaultFloorId: { defaultFloorId: {
type: String, type: String,
default: '', default: "",
},
// ID
defaultAreaId: {
type: String,
default: '',
},
// ID
defaultUnitId: {
type: String,
default: '',
},
}, },
data() { // ID
return { defaultAreaId: {
treeData: [], type: String,
selectedFloor: null, default: "",
selectedArea: null,
selectedUnit: null,
loading: false,
}
}, },
computed: { // ID
// defaultUnitId: {
floors() { type: String,
if (!this.treeData.length) return [] default: "",
const memorial = this.treeData[0]
return memorial && memorial.children ? memorial.children : []
},
//
areas() {
if (!this.selectedFloor) return []
return this.selectedFloor.children ? this.selectedFloor.children : []
},
//
units() {
if (!this.selectedArea) return []
return this.selectedArea.children ? this.selectedArea.children : []
},
}, },
watch: { },
// data() {
selectedUnit: { return {
handler(newUnit) { treeData: [],
this.$emit('selection-change', { selectedFloor: null,
floor: this.selectedFloor, selectedArea: null,
area: this.selectedArea, selectedUnit: null,
unit: newUnit, loading: false,
}) };
}, },
deep: true, computed: {
}, //
floors() {
if (!this.treeData.length) return [];
const memorial = this.treeData[0];
return memorial && memorial.children ? memorial.children : [];
}, },
mounted() { //
this.loadTreeData() areas() {
if (!this.selectedFloor) return [];
return this.selectedFloor.children ? this.selectedFloor.children : [];
}, },
methods: { //
// units() {
async loadTreeData() { if (!this.selectedArea) return [];
this.loading = true return this.selectedArea.children ? this.selectedArea.children : [];
try { },
const response = await getMemorialTree() },
console.log('楼层树形数据:', response) watch: {
//
if (response && response.code === 200) { selectedUnit: {
this.treeData = response.data || [] handler(newUnit) {
this.$emit("selection-change", {
//
this.setDefaultSelection()
} else {
console.error('获取楼层数据失败:', response)
uni.showToast({
title: '获取楼层数据失败',
icon: 'none',
})
}
} catch (error) {
console.error('加载楼层数据失败:', error)
uni.showToast({
title: '网络异常,请稍后重试',
icon: 'none',
})
} finally {
this.loading = false
}
},
//
setDefaultSelection() {
//
if (this.defaultFloorId) {
const floor = this.floors.find(f => f.id === this.defaultFloorId)
if (floor) {
this.selectFloor(floor)
}
} else if (this.floors.length > 0) {
//
this.selectFloor(this.floors[0])
}
//
if (this.defaultAreaId && this.selectedFloor) {
const area = this.areas.find(a => a.id === this.defaultAreaId)
if (area) {
this.selectArea(area)
}
} else if (this.areas.length > 0) {
//
this.selectArea(this.areas[0])
}
//
if (this.defaultUnitId && this.selectedArea) {
const unit = this.units.find(u => u.id === this.defaultUnitId)
if (unit) {
this.selectUnit(unit)
}
} else if (this.units.length > 0) {
//
this.selectUnit(this.units[0])
}
},
//
selectFloor(floor) {
this.selectedFloor = floor
this.selectedArea = null
this.selectedUnit = null
//
if (this.areas.length > 0) {
this.selectArea(this.areas[0])
}
},
//
selectArea(area) {
this.selectedArea = area
this.selectedUnit = null
//
if (this.units.length > 0) {
this.selectUnit(this.units[0])
}
},
//
selectUnit(unit) {
this.selectedUnit = unit
},
//
getCurrentSelection() {
return {
floor: this.selectedFloor, floor: this.selectedFloor,
area: this.selectedArea, area: this.selectedArea,
unit: this.selectedUnit, unit: newUnit,
} });
},
//
resetSelection() {
this.selectedFloor = null
this.selectedArea = null
this.selectedUnit = null
this.setDefaultSelection()
}, },
deep: true,
}, },
} },
mounted() {
this.loadTreeData();
},
methods: {
//
async loadTreeData() {
this.loading = true;
try {
const response = await getMemorialTree();
console.log("楼层树形数据:", response);
if (response && response.code === 200) {
this.treeData = response.data || [];
//
this.setDefaultSelection();
} else {
console.error("获取楼层数据失败:", response);
uni.showToast({
title: "获取楼层数据失败",
icon: "none",
});
}
} catch (error) {
console.error("加载楼层数据失败:", error);
uni.showToast({
title: "网络异常,请稍后重试",
icon: "none",
});
} finally {
this.loading = false;
}
},
//
setDefaultSelection() {
//
if (this.defaultFloorId) {
const floor = this.floors.find((f) => f.id === this.defaultFloorId);
if (floor) {
this.selectFloor(floor);
}
} else if (this.floors.length > 0) {
//
this.selectFloor(this.floors[0]);
}
//
if (this.defaultAreaId && this.selectedFloor) {
const area = this.areas.find((a) => a.id === this.defaultAreaId);
if (area) {
this.selectArea(area);
}
} else if (this.areas.length > 0) {
//
this.selectArea(this.areas[0]);
}
//
if (this.defaultUnitId && this.selectedArea) {
const unit = this.units.find((u) => u.id === this.defaultUnitId);
if (unit) {
this.selectUnit(unit);
}
} else if (this.units.length > 0) {
//
this.selectUnit(this.units[0]);
}
},
//
selectFloor(floor) {
this.selectedFloor = floor;
this.selectedArea = null;
this.selectedUnit = null;
//
if (this.areas.length > 0) {
this.selectArea(this.areas[0]);
}
},
//
selectArea(area) {
this.selectedArea = area;
this.selectedUnit = null;
//
if (this.units.length > 0) {
this.selectUnit(this.units[0]);
}
},
//
selectUnit(unit) {
this.selectedUnit = unit;
},
//
getCurrentSelection() {
return {
floor: this.selectedFloor,
area: this.selectedArea,
unit: this.selectedUnit,
};
},
//
resetSelection() {
this.selectedFloor = null;
this.selectedArea = null;
this.selectedUnit = null;
this.setDefaultSelection();
},
},
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.floor-selector { .floor-selector {
padding: 42rpx 44rpx 30rpx 44rpx; padding: 42rpx 44rpx 30rpx 44rpx;
width: 750rpx; width: 750rpx;
background-color: #fffbf5; background-color: #fffbf5;
border-radius: 38rpx; border-radius: 38rpx;
box-sizing: border-box; box-sizing: border-box;
margin-top: 14rpx; margin-top: 14rpx;
}
.floor-section {
display: flex;
align-items: center;
margin-bottom: 26rpx;
//border:1rpx solid #613613;
}
.section-label {
margin-right: 10rpx;
width: 96rpx;
height: 44rpx;
font-weight: 400;
font-size: 32rpx;
color: #3d3d3d;
line-height: 44rpx;
text-align: left;
}
.floor-buttons {
display: flex;
gap: 20rpx;
}
.floor-btn {
padding: 4rpx 49rpx;
color: #a24242;
border-radius: 8rpx;
font-size: 28rpx;
cursor: pointer;
transition: all 0.3s ease;
width: 134rpx;
height: 52rpx;
background: #fff1dd;
border: 1rpx solid #a24242;
&.active {
background-color: #a24242;
color: #fff1dd;
} }
}
.floor-section { .divider {
display: flex; height: 1rpx;
align-items: center; background: repeating-linear-gradient(
margin-bottom: 26rpx; to right,
//border:1rpx solid #613613; #a24242 0,
#a24242 8rpx,
transparent 8rpx,
transparent 16rpx
);
margin: 26rpx 0 0 0;
}
.content-section {
display: flex;
height: calc(100% - 120rpx);
}
.area-section {
margin-top: 30rpx;
width: 180rpx;
display: flex;
flex-direction: column;
gap: 16rpx;
//border: 1rpx solid #f414fb;
}
.area-btn {
padding: 4rpx 40rpx;
color: #a24242;
border-radius: 8rpx;
font-size: 28rpx;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
box-sizing: border-box;
width: 134rpx;
height: 52rpx;
background: #fff1dd;
border: 1rpx solid #a24242;
&.active {
background-color: #a24242;
color: #fff1dd;
} }
}
.section-label { .vertical-divider {
margin-right: 10rpx; width: 1rpx;
width: 96rpx; background: repeating-linear-gradient(
height: 44rpx; to bottom,
font-weight: 400; #a24242 0,
font-size: 32rpx; #a24242 8rpx,
color: #3d3d3d; transparent 8rpx,
line-height: 44rpx; transparent 16rpx
text-align: left; );
} margin: 0 48rpx 0 0;
}
.floor-buttons {
display: flex; .unit-section {
gap: 20rpx; //border: 1rpx solid #f47fef;
} flex: 1;
margin-top: 64rpx;
.floor-btn { }
padding: 4rpx 49rpx;
color: #a24242; .unit-grid {
border-radius: 8rpx; //border: 1rpx solid #f47fef;
font-size: 28rpx; display: grid;
cursor: pointer; grid-template-columns: repeat(3, 1fr);
transition: all 0.3s ease; gap: 16rpx;
width: 134rpx; }
height: 52rpx;
background: #fff1dd; .unit-btn {
border: 1rpx solid #a24242; padding: 16rpx 12rpx;
color: #a24242;
&.active { border-radius: 8rpx;
background-color: #a24242; font-size: 28rpx;
color: #fff1dd; text-align: center;
} cursor: pointer;
} transition: all 0.3s ease;
display: flex;
.divider { align-items: center;
height: 1rpx; justify-content: center;
background: repeating-linear-gradient( width: 134rpx;
to right, height: 52rpx;
#a24242 0, background: #fff1dd;
#a24242 8rpx, border: 1rpx solid #a24242;
transparent 8rpx,
transparent 16rpx &.active {
); background-color: #a24242;
margin: 26rpx 0 0 0; color: #fff1dd;
} border-color: #a24242;
.content-section {
display: flex;
height: calc(100% - 120rpx);
}
.area-section {
margin-top: 30rpx;
width: 180rpx;
display: flex;
flex-direction: column;
gap: 16rpx;
//border: 1rpx solid #f414fb;
}
.area-btn {
padding: 4rpx 40rpx;
color: #a24242;
border-radius: 8rpx;
font-size: 28rpx;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
box-sizing: border-box;
width: 134rpx;
height: 52rpx;
background: #fff1dd;
border: 1rpx solid #a24242;
&.active {
background-color: #a24242;
color: #fff1dd;
}
}
.vertical-divider {
width: 1rpx;
background: repeating-linear-gradient(
to bottom,
#a24242 0,
#a24242 8rpx,
transparent 8rpx,
transparent 16rpx
);
margin: 0 48rpx 0 0;
}
.unit-section {
//border: 1rpx solid #f47fef;
flex: 1;
margin-top: 64rpx;
}
.unit-grid {
//border: 1rpx solid #f47fef;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16rpx;
}
.unit-btn {
padding: 16rpx 12rpx;
color: #a24242;
border-radius: 8rpx;
font-size: 28rpx;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
width: 134rpx;
height: 52rpx;
background: #fff1dd;
border: 1rpx solid #a24242;
&.active {
background-color: #a24242;
color: #fff1dd;
border-color: #a24242;
}
} }
}
</style> </style>