重构第一版 智控助手小程序

This commit is contained in:
2025-12-30 15:21:19 +08:00
parent c25e282398
commit 3852e6ac20
32 changed files with 3584 additions and 123 deletions

View File

@@ -0,0 +1,629 @@
// pages/FacialDeviceBinding/FacialDeviceBinding.js
// 人脸设备绑定页面逻辑
const app = getApp()
// 导入请求中心
import {
GetHostsInfo,
GetFaceSN,
GetFaceCode,
CheckFaceSNAutho,
CheckFaceSN,
OpenDoorTest
} from '../../../lib/RequestingCenter';
Page({
data: {
autho:null,
RoomIndex: 0, // 当前选中房间索引
Hotelinfo: null, // 酒店信息
HostsData: null, // 原始设备数据
HostsDataFilters: [], // 过滤后的设备数据
onlineFaceDevices: 0, // 在线人脸设备数量
inputValue: "", // 搜索输入值
scrollHeight: 0, // 滚动区域高度
toView: '', // 滚动位置
modal: '', // 弹窗状态
selHosts: null, // 当前选中的房间
faceSNCode: '', // 人脸设备SN输入
bdHosts: [], // 已绑定的主机列表
Help: false, // 帮助状态
islogs: false, // 操作记录状态
showinfo: 0, // 显示信息类型
faceAddress: '', // 人脸设备地址
input: 0, // 输入类型
ISLoopDebugging: 0, // 回路调试状态
message: [], // 弹窗信息
},
/**
* 页面的初始数据
*/
onLoad:async function(options) {
if (!options.HotelId || app.globalData.autho == null) {
app.toast(2, "无酒店信息~")
return;
}
this.setData({
autho: app.globalData.autho ,
HotelId:options.HotelId
})
try {
this.data.autho.forEach((element, index) => {
element.Hotels.forEach((elements, indexs) => {
if (elements.HotelId == options.HotelId) {
this.setData({
Hotelinfo: elements
})
throw new Error();
}
})
});
} catch (error) {
console.log("已经找到,无需循环~")
}
// 计算滚动区域高度
this.calcScrollHeight();
// 获取人脸设备数据
this.GetHostsInfo();
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
// 页面显示时重新获取数据
this.GetHostsInfo();
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
this.GetHostsInfo();
wx.stopPullDownRefresh();
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
// 返回上一页
back: function () {
wx.navigateBack({
delta: 1
});
},
// 计算滚动区域高度
calcScrollHeight: function () {
// 1. 拿到屏幕可用高度px
const sys = wx.getSystemInfoSync();
const screenHeight = sys.windowHeight; // px
// 2. 拿到 scroll-view 的 toppx
wx.createSelectorQuery()
.in(this)
.select('#myScroll')
.boundingClientRect(rect => {
if (rect) {
const topPx = rect.top; // px
const bottomPx = 10 / 2; // 10rpx → 5px2倍屏
const heightPx = screenHeight - topPx - bottomPx;
// 3. 转 rpx 并写入
this.setData({
scrollHeight: heightPx * 2 // px→rpx
});
}
})
.exec();
},
// 获取人脸设备数据
GetHostsInfo: function () {
const that = this;
// 显示加载提示
wx.showLoading({
title: '加载中...',
});
// 调用获取主机信息接口
GetHostsInfo({
HotelID: that.data.HotelId
}).then(res => {
// 隐藏加载提示
wx.hideLoading();
if (res.Status == 200) {
// 处理数据
const HostsData = res.Data;
const HostsDataFilters = HostsData;
// 统计在线人脸设备数量
let onlineFaceDevices = 0;
for (let i = 0; i < HostsDataFilters.length; i++) {
if (HostsDataFilters[i].FaceStatus) {
onlineFaceDevices++;
}
}
// 更新数据
that.setData({
HostsData: HostsData,
HostsDataFilters: HostsDataFilters,
onlineFaceDevices: onlineFaceDevices,
RoomIndex: 0
});
// 获取位置信息
that.GetLOC();
} else {
wx.showToast({
title: '获取数据失败',
icon: 'none'
});
}
}).catch(err => {
wx.hideLoading();
wx.showToast({
title: '网络异常',
icon: 'none'
});
console.error('获取主机信息失败:', err);
});
},
// 获取位置信息
GetLOC: function () {
const that = this;
// 调用微信获取位置接口
wx.getFuzzyLocation({
type: 'wgs84',
success(res) {
const latitude = res.latitude;
const longitude = res.longitude;
const address = `${latitude},${longitude}`;
that.setData({
faceAddress: address
});
},
fail(err) {
console.error('获取位置信息失败:', err);
// 位置信息获取失败不影响主流程
}
});
},
// 搜索输入
inputSearchForHotels: function (e) {
this.setData({
inputValue: e.detail.value
});
},
// 搜索房间
SearchForHotels: function () {
const that = this;
const inputValue = that.data.inputValue;
const HostsData = that.data.HostsData;
if (inputValue === '') {
// 搜索条件为空,显示所有数据
that.setData({
HostsDataFilters: HostsData
});
return;
}
// 根据房号搜索
const filters = HostsData.filter(item => {
return item.RoomNumber.indexOf(inputValue) !== -1;
});
that.setData({
HostsDataFilters: filters
});
},
// 刷新房间数据
RefreshTheRoom: function () {
this.GetHostsInfo();
},
// 跳转到人脸设备详情或直接扫码绑定
goFaceDetail: function (e) {
const index = e.currentTarget.id.split('-')[1];
const HostsDataFilters = this.data.HostsDataFilters;
const selHosts = HostsDataFilters[index];
selHosts.index = index;
this.setData({
RoomIndex: index,
selHosts: selHosts
});
// 判断条件:离线且未绑定
if (!selHosts.FaceStatus && (!selHosts.FaceSN || selHosts.FaceSN === '')) {
// 直接调用摄像头扫码绑定
this.GetFaceCode();
} else {
// 设置消息数据
this.setData({
message: [selHosts.FaceSN, selHosts.RoomNumber],
// 显示设备详情
modal: -1
});
}
},
// 关闭弹窗
GetHide: function () {
this.setData({
modal: ''
});
},
// 反馈错误
ErrorInfo: function () {
wx.showToast({
title: '反馈功能开发中',
icon: 'none'
});
},
// 人脸设备解绑
JbSn: function (params) {
let jbjd = null;
let faceSN = null;
let that = this;
let index = -1;
// 检查是否从SN已绑定弹窗点击解绑按钮
if (typeof params.currentTarget.dataset['index'] != 'undefined') {
faceSN = this.data.faceSNCode;
index = params.currentTarget.dataset['index'];
// 解绑的房间
jbjd = this.data.bdHosts[index];
} else {
jbjd = this.data.selHosts;
faceSN = this.data.selHosts.FaceSN;
}
wx.showModal({
title: '解绑确认',
content: `确定要解除${jbjd.RoomNumber}房间的人脸设备绑定吗?`,
success(res) {
if (res.confirm) {
// 调用解绑接口
GetFaceSN({
faceSN: faceSN,
roomID: jbjd.Id,
roomNumber: jbjd.RoomNumber,
faceAddress: that.data.faceAddress,
HotelID: jbjd.HotelID,
isjb: true
}).then(res => {
if (res.Status == 200) {
wx.showToast({
title: '解绑成功',
icon: 'success'
});
// 如果是从SN已绑定弹窗解绑需要更新bdHosts数据
if (index > -1) {
let databdHosts = that.data.bdHosts;
databdHosts.splice(index, 1);
that.setData({
bdHosts: databdHosts
});
// 如果bdHosts为空继续执行绑定
if (databdHosts.length <= 0) {
that.GetFaceSNend();
}
}
// 重新获取数据
that.GetHostsInfo();
// 关闭弹窗
that.GetHide();
} else {
wx.showToast({
title: '解绑失败',
icon: 'none'
});
}
}).catch(err => {
wx.showToast({
title: '网络异常',
icon: 'none'
});
console.error('解绑失败:', err);
});
}
}
});
},
// 扫码绑定人脸设备
GetFaceCode: function () {
const that = this;
// 检查权限
if (!that.CheckFaceSNAutho()) {
wx.showToast({
title: '您没有权限绑定人脸设备',
icon: 'none'
});
return;
}
// 调用微信扫码接口
wx.scanCode({
success: (res) => {
const code = res.result;
that.setData({
faceSNCode: code
});
debugger
that.GetFaceSNOK();
},
fail: (err) => {
console.error('扫码失败:', err);
wx.showToast({
title: '扫码失败',
icon: 'none'
});
}
});
},
// 手动输入人脸设备SN
ShowInputsn: function () {
// 检查权限
if (!this.CheckFaceSNAutho()) {
wx.showToast({
title: '您没有权限绑定人脸设备',
icon: 'none'
});
return;
}
this.setData({
modal: 'showBindConfirm'
});
},
GetFaceSNOK:function(){
let that = this;
if (!this.CheckFaceMAC(that.data.faceSNCode)) {
this.setData({
modal: 520
})
return;
};
if (that.data.selHosts.FaceSN == that.data.faceSNCode) {
app.toast(2, "条码一致,无需更改~")
return;
}
this.CheckFaceMACWL()
},
CheckFaceMACWL(){
let that = this;
CheckFaceSN({faceSN:this.data.faceSNCode}).then(
res => {
if (res.Status == 200) {
if(res.Data<=0){
that.setData({
modal:-521,
})
}else{
let remove = [];
let bdHosts = res.Data;
try {
//记录已经分配酒店但是未分配房间 且酒店是当前酒店 那就判断为没有绑定
that.data.autho.forEach((element, index) => {
element.Hotels.forEach((elements, indexs) => {
for (let index = 0; index < bdHosts.length; index++) {
if (elements.HotelId == bdHosts[index].HotelID) {
if(bdHosts[index].HotelID == that.data.Hotelinfo.HotelId && bdHosts[index].Id==0){
remove.push(index);
}
elements.Auth.forEach (Auth=>{
if(Auth.AuthorityId == 21 && Auth.AuthotypeId == 3){
//有权限
bdHosts[index].qx = 0;
}
})
}
}
})
});
} catch (error) {
console.log(error)
}
remove.forEach (x=>{
bdHosts.splice(x, 1);
})
let modalval = -200;
if(bdHosts.length<=0){
modalval = -521;
}
that.setData({
modal:modalval,
bdHosts:bdHosts
})
// app.toast(2, "已经被绑定")
}
}else{
app.toast(2, "网络繁忙")
}
},
err => {
console.log(err)
app.toast(2, "网络繁忙")
}).catch(err => {
console.log(err)
app.toast(2, "网络繁忙")
});
},
CheckFaceMAC:function(vlues){
return true;
console.log(vlues.length != 16)
return vlues.length == 16;
},
// 完成人脸设备绑定
GetFaceSNend: function () {
const that = this;
const selHosts = that.data.selHosts;
const faceSNCode = that.data.faceSNCode;
// 显示加载提示
wx.showLoading({
title: '绑定中...',
});
// 调用绑定接口
GetFaceSN({
faceSN: faceSNCode,
roomID: selHosts.Id,
roomNumber: selHosts.RoomNumber,
faceAddress: that.data.faceAddress,
HotelID: selHosts.HotelID,
isjb: false
}).then(res => {
// 隐藏加载提示
wx.hideLoading();
if (res.Status == 200) {
wx.showToast({
title: '绑定成功',
icon: 'success'
});
// 重新获取数据
that.GetHostsInfo();
// 关闭弹窗
that.GetHide();
} else if (res.Status == 400) {
// 设备已被绑定
that.setData({
bdHosts: res.Data,
code: faceSNCode,
modal: -200
});
} else {
wx.showToast({
title: '绑定失败',
icon: 'none'
});
}
}).catch(err => {
// 隐藏加载提示
wx.hideLoading();
wx.showToast({
title: '网络异常',
icon: 'none'
});
console.error('绑定失败:', err);
});
},
// 检查人脸设备绑定权限
CheckFaceSNAutho: function () {
let res = false;
this.data.Hotelinfo.Auth.forEach(x => {
if (x.AuthorityId == 21 && x.AuthotypeId == 3) {
res = true;
}
});
return res;
},
// 设置操作
testinfo: function (e) {
var jbjd = this.data.selHosts;
wx.navigateTo({
url: '/pages/test/test?Hotelinfo=' + e.currentTarget.id + '&RoomID=' + jbjd.Id + '&faceadd=' + this.data.faceAddress
});
},
// 开门操作
OpenDoor: function (e) {
const sn = e.currentTarget.id.split('_');
OpenDoorTest({faceSN:sn[2],isjb:true}).then(
res=>{
if (res.Status == 200) {
wx.showToast({
title: res.Message,
icon: 'none'
})
}else{
wx.showToast({
title: res.Message,
icon: 'none'
})
}
},rej=>{
wx.showToast({
title: "网络繁忙",
icon: 'none'
})
}
);
},
// 切换显示信息
GetshowinfoClick: function (e) {
const index = e.currentTarget.dataset.index;
this.setData({
showinfo: index
});
},
// 切换显示信息(刷新)
GetshowinfoClick1: function () {
this.GetHostsInfo();
},
})

View File

@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "人脸设备绑定",
"usingComponents": {
"cu-custom": "/colorui/components/cu-custom"
}
}

View File

@@ -0,0 +1,144 @@
<cu-custom bgColor="bg-gradual-blue"
isBack="true">
<block bindtap="back" slot="backText" >返回</block>
<view slot="content">{{Hotelinfo.HotelName}}({{Hotelinfo.Code}})</view>
</cu-custom>
<view class=" solids bg-white" style="height:70px ;width: 100%;font-weight: bold; ">
<view class="flex text-xl" style=" height:45% ;width: 100%;">
<view class="solids" wx:if="{{RoomIndex>=0}}" style="height:100% ;width: 50%;">
<text class="text-black">房号:{{HostsDataFilters[RoomIndex].RoomNumber}}</text>
</view>
<view class="solids" wx:if="{{RoomIndex>=0}}" style="height:100% ;width: 50%;">
<text class="text-black">人脸设备在线:</text>
<text class="text-blue">{{onlineFaceDevices}}/</text>
<text class="text-black">{{HostsDataFilters.length}} </text>
</view>
</view>
<view class="cu-bar1 bg-white " style="height:50% ;width: 100%;" >
<view class="solids" style="width: 60%;">
<input class="solids cu-btn1" focus="true" bindinput="inputSearchForHotels" confirm-type="search" style="width: 100%;" placeholder="请输入房号搜索房间"/>
</view>
<view class="flex"style="width: 40%;">
<button class="cu-btn1 line-green margin-left " style="width: 100%; margin:5rpx;" bindtap="SearchForHotels">搜索</button>
<button class="cu-btn1 line-green margin-left " style="width: 100%; margin:5rpx;" bindtap="RefreshTheRoom">刷新</button>
</view>
</view>
</view>
<scroll-view scroll-y scroll-into-view="{{toView}}" id="myScroll" style="height:{{scrollHeight}}rpx;" >
<view class='nav-list1 bg-white' style="margin-top: 20rpx;">
<view bindtap="goFaceDetail" data-room="{{item.RoomNumber}}" data-hotel="{{Hotelinfo.HotelName}}"
data-status="{{item.FaceStatus}}" data-faceSN="{{item.FaceSN}}" hover-class="navigator-hover" class="nav-li4 bg-{{item.FaceStatus===true? 'cyan':'gray'}}" wx:for="{{HostsDataFilters}}" id="msg-{{index}}" wx:key="index">
<view style="font-size: 28rpx;justify-content:start" >{{item.RoomNumber}}</view>
<view style="font-size: 18rpx;justify-content:start;color:{{item.FaceSN && !item.FaceStatus ? 'red' : 'gray'}}" >{{item.FaceSN || '未绑定'}}</view>
</view>
</view>
</scroll-view>
<!-- 房间已经绑定人脸机弹窗提示 -->
<view class="cu-modal {{modal==-1?'show':''}}">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">{{selHosts.RoomNumber}}已经绑定人脸机</view>
<view class="action" bindtap="GetHide" >
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-lg flex flex-wrap " >
<view class="basis-sm text-right">酒店:</view><view class="text-left basis-lg">{{Hotelinfo.HotelName}}</view>
<view class="basis-sm text-right">房间:</view><view class="basis-lg text-left">{{message[1]}}</view>
<view class="basis-sm text-right">人脸机SN</view><view class="basis-lg text-left">{{message[0]}}</view>
<view class=" text-left flex-sub text-sm text-gray">房间已经绑定人脸机,点击继续将执行扫描绑定;点击取消,将不会执行任何操作~</view>
</view>
<view class="cu-bar bg-white">
<!-- <view class="action margin-0 flex-sub " data-type="0" bindtap="ErrorInfo">反馈错误</view>text-red -->
<view id="{{Hotelinfo.HotelName}}_{{message[1]}}_{{message[0]}}_{{Hotelinfo.Code}}_{{Hotelinfo.HotelId}}" class="action margin-0 flex-sub text-green solid-left" style="font-weight: 600;" bindtap="testinfo" >设置</view>
<view id="{{Hotelinfo.HotelName}}_{{message[1]}}_{{message[0]}}_{{Hotelinfo.Code}}" class="action margin-0 flex-sub text-green solid-left" style="font-weight: 600;" bindtap="OpenDoor" >开门</view>
<!-- <view class="action margin-0 flex-sub {{selHosts.FaceSN!=''?'show':''}} text-red solid-left" bindtap="JbSn" >解绑</view> -->
<!-- <view class="action margin-0 flex-sub solid-left" bindtap="GetHide" >取消</view> -->
<!-- <view class="action margin-0 flex-sub text-green solid-left" bindtap="{{FaceSNinput == 0?'GetFaceCode':'ShowInputsn'}}" >继续</view> -->
</view>
</view>
</view>
<!-- 绑定确认弹窗 -->
<view class="cu-modal {{modal=='-521'?'show':''}}">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">绑定人脸设备</view>
<view class="action" bindtap="GetHide" >
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-lg flex flex-wrap " >
<view class="basis-sm text-right">酒店:</view><view class="text-left basis-lg">{{Hotelinfo.HotelName}}</view>
<view class="basis-sm text-right">房间:</view><view class="basis-lg text-left">{{selHosts.RoomNumber}}</view>
<view class="basis-sm text-right">人脸设备SN</view>
<view class="basis-lg text-left">
<textarea placeholder="请输入人脸设备SN" model:value="{{faceSNCode}}" name="input" style="width: 100%; height: 100rpx; border: 1rpx solid #ccc; border-radius: 4rpx; padding: 10rpx;" placeholder-style="color: #999;"></textarea>
</view>
<view class=" text-left flex-sub text-sm text-gray">确定为该房间绑定人脸设备SN点击继续将执行绑定操作点击取消将不会执行任何操作~</view>
</view>
<view class="cu-bar bg-white">
<view class="action margin-0 flex-sub text-green solid-left" bindtap="GetHide" >取消</view>
<view class="action margin-0 flex-sub solid-left" bindtap="GetFaceSNend" >继续</view>
</view>
</view>
</view>
<!-- SN已经被绑定弹窗提示 -->
<view class="cu-modal {{modal==-200?'show':''}}">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">{{code}}已经被绑定
</view>
<view class="action" bindtap="GetHide" >
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view class="padding-xs flex flex-wrap justify-center " >
<view class="basis-xl text-sm" wx:for="{{bdHosts}}" >
<text class=" text-right ">酒店:</text><text class="text-left text-red">{{item.HotelName}}</text>
<text class="padding-left-xs text-right " >房间:</text><text class="text-left text-red">{{item.RoomNumber}}</text>
<button class="cu-btn margin-left-xs sm bg-red" wx:if="{{item.qx == 0}}" data-index="{{index}}" type="" bindtap="JbSn" >解绑</button>
<button class="cu-btn margin-left-xs sm bg-red" wx:if="{{item.qx != 0}}" disabled >解绑</button>
</view>
<view class="basis-xl">SN<text class="text-left">{{faceSNCode}}</text></view>
<view class="basis-xl text-left text-sm text-gray">SN已经被其他房间绑定点击解绑将取消原有绑定执行新的绑定点击取消将不会执行任何操作~</view>
</view>
<view class="cu-bar bg-white">
<view class="action margin-0 flex-sub text-green solid-left" bindtap="GetHide" >取消</view>
<view wx:if="{{bdHosts.length<=0}}" class="action margin-0 flex-sub solid-left" data-type="false" bindtap="GetFaceSNend" >继续</view>
</view>
</view>
</view>

View File

@@ -0,0 +1,364 @@
/* pages/FacialDeviceBinding/FacialDeviceBinding.wxss */
/* 人脸设备绑定页面样式 */
/* 滚动区域样式 */
#scroll {
height: 100%;
}
/* 房间列表样式 */
.nav-list1 {
display: flex;
flex-wrap: wrap;
padding: 0 10rpx;
}
/* 房间项样式 */
.nav-li4 {
width: 31.33%;
margin: 1%;
padding: 15rpx;
border-radius: 8rpx;
text-align: center;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
transition: all 0.3s;
}
.nav-li4:active {
transform: scale(0.95);
}
/* 在线状态样式 */
.bg-green {
background-color: #4CD964;
color: white;
}
/* 青色在线状态样式 */
.bg-cyan {
background-color: #00BCD4;
color: white;
}
/* 离线状态样式 */
.bg-gray {
background-color: #E5E5EA;
color: #8E8E93;
}
/* 搜索框样式 */
.cu-btn1 {
position: relative;
border: 0rpx;
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
padding: 0 5rpx;
font-size: 26rpx;
height: 64rpx;
line-height: 1;
text-align: center;
text-decoration: none;
overflow: visible;
margin-left: initial;
transform: translate(0rpx, 0rpx);
margin-right: initial;
}
/* 按钮样式 */
.margin-left {
margin-left: 10rpx;
}
/* 顶部操作栏样式 */
.cu-bar1 {
display: flex;
align-items: center;
justify-content: space-between;
}
/* 弹性换行样式 */
.flex-wrap {
display: flex;
}
/* 固体样式 */
.solids {
display: block;
}
/* 顶部信息栏样式 */
.text-xl {
font-size: 36rpx;
font-weight: bold;
}
.text-blue {
color: #007AFF;
}
.text-black {
color: #000000;
}
/* 弹窗样式 */
.cu-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s;
}
.cu-modal.show {
opacity: 1;
}
.cu-dialog {
background: white;
border-radius: 10rpx;
width: 80%;
max-width: 500rpx;
overflow: hidden;
transform: scale(0.8);
transition: transform 0.3s;
}
.cu-modal.show .cu-dialog {
transform: scale(1);
}
.cu-bar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
border-bottom: 1px solid #E5E5EA;
}
.cu-bar .content {
font-size: 36rpx;
font-weight: bold;
}
.cu-bar.bg-gradual-blue .action {
color: white;
}
.cu-bar.bg-gradual-blue .action text {
color: white;
}
.cu-bar .action {
color: #007AFF;
font-size: 32rpx;
}
/* 内容区样式 */
.padding-lg {
padding: 30rpx;
}
.flex {
display: flex;
}
.flex-wrap {
flex-wrap: wrap;
}
.basis-sm {
width: 30%;
text-align: right;
padding-right: 20rpx;
}
.basis-lg {
width: 70%;
text-align: left;
}
.text-red {
color: #FF3B30;
}
.text-green {
color: #4CD964;
}
/* 输入框样式 */
input {
border: 1px solid #E5E5EA;
border-radius: 5rpx;
padding: 15rpx;
width: 100%;
font-size: 32rpx;
box-sizing: border-box;
}
/* 底部按钮栏样式 */
.cu-bar.bg-white {
border-top: 1px solid #E5E5EA;
border-bottom: none;
}
.cu-bar .action {
padding: 10rpx 20rpx;
}
.solid-left {
border-left: 1px solid #E5E5EA;
}
/* 酒店信息样式 */
.text-df {
font-size: 28rpx;
}
/* 设备信息样式 */
.text-sm {
font-size: 24rpx;
}
/* 分隔线样式 */
.ControlLine {
height: 2rpx;
background-color: #E5E5EA;
margin: 20rpx 0;
}
/* 轻量级文本样式 */
.light {
opacity: 0.7;
}
/* 禁用状态样式 */
button:disabled {
opacity: 0.5;
}
/* 加载提示样式 */
.loading {
display: flex;
justify-content: center;
align-items: center;
padding: 50rpx;
}
.loading text {
margin-left: 10rpx;
font-size: 32rpx;
color: #8E8E93;
}
/* 空数据提示样式 */
.empty {
text-align: center;
padding: 100rpx;
color: #8E8E93;
font-size: 32rpx;
}
/* 帮助区域样式 */
.cu-card {
margin: 20rpx;
background: white;
border-radius: 10rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.cu-item {
padding: 30rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
margin-bottom: 20rpx;
}
.content {
font-size: 32rpx;
line-height: 1.6;
}
.desc {
margin-bottom: 20rpx;
}
.text-content {
font-size: 30rpx;
line-height: 1.8;
}
/* 酒店信息样式 */
.hotel-info {
padding: 20rpx;
background: white;
border-bottom: 1px solid #E5E5EA;
}
.hotel-name {
font-size: 36rpx;
font-weight: bold;
color: #000000;
}
.hotel-code {
font-size: 30rpx;
color: #8E8E93;
margin-top: 10rpx;
}
/* 状态统计样式 */
.status-stats {
display: flex;
justify-content: space-around;
padding: 20rpx;
background: white;
border-bottom: 1px solid #E5E5EA;
}
.stat-item {
text-align: center;
}
.stat-label {
font-size: 30rpx;
color: #8E8E93;
}
.stat-value {
font-size: 40rpx;
font-weight: bold;
color: #007AFF;
}
/* 操作按钮样式 */
.operation-buttons {
display: flex;
justify-content: space-around;
padding: 20rpx;
background: white;
border-bottom: 1px solid #E5E5EA;
}
.operation-button {
flex: 1;
margin: 0 10rpx;
padding: 20rpx;
background: #007AFF;
color: white;
border-radius: 50rpx;
text-align: center;
font-size: 32rpx;
}
.operation-button:active {
opacity: 0.8;
}