fix:调整demo测试页面
This commit is contained in:
parent
891ba072d0
commit
690849af88
@ -5,60 +5,61 @@ const {
|
|||||||
register
|
register
|
||||||
} = requirePlugin('starCloud')
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
// 添加硬编码的账户信息
|
||||||
|
const MOCK_ACCOUNT = {
|
||||||
|
username: 'nhueg_3MWghkBljd8WoDUmeBm',
|
||||||
|
password: '91936ff7ede730fb7befc33dc749543d',
|
||||||
|
uid: 17162
|
||||||
|
};
|
||||||
|
|
||||||
App({
|
App({
|
||||||
globalData: {
|
globalData: {
|
||||||
accountInfo: null,
|
accountInfo: MOCK_ACCOUNT, // 直接使用硬编码的账户信息
|
||||||
deviceList: [],
|
deviceList: [],
|
||||||
lock: null // 添加lock属性
|
lock: null, // 确保初始化为 null
|
||||||
|
currentLockId: null // 可选:添加当前选中的锁ID
|
||||||
},
|
},
|
||||||
|
|
||||||
onLaunch: function() {
|
// 可以添加一个更新锁信息的方法
|
||||||
this.initBluetooth()
|
updateLockInfo(lock) {
|
||||||
|
if (lock && lock.lockId) {
|
||||||
|
this.globalData.lock = lock;
|
||||||
|
this.globalData.currentLockId = lock.lockId;
|
||||||
|
console.log('全局锁信息已更新:', lock);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onLaunch: async function() {
|
||||||
|
await this.initBluetooth()
|
||||||
},
|
},
|
||||||
|
|
||||||
async initBluetooth() {
|
async initBluetooth() {
|
||||||
// 初始化SDK
|
|
||||||
init({
|
|
||||||
clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
|
|
||||||
clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
|
|
||||||
env: 'SKY',
|
|
||||||
isReportLog: true,
|
|
||||||
accounts: []
|
|
||||||
})
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 注册账号
|
wx.showLoading({
|
||||||
const registerResult = await register()
|
title: '初始化中...',
|
||||||
if (registerResult.code === Result.Success.code) {
|
mask: true
|
||||||
this.globalData.accountInfo = registerResult.data
|
});
|
||||||
|
|
||||||
// 使用注册的账号重新初始化
|
// 使用硬编码的账户初始化SDK
|
||||||
init({
|
init({
|
||||||
clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
|
clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
|
||||||
clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
|
clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
|
||||||
env: 'SKY',
|
env: 'SKY',
|
||||||
isReportLog: true,
|
isReportLog: true,
|
||||||
accounts: [this.globalData.accountInfo]
|
accounts: [MOCK_ACCOUNT] // 使用硬编码的账户
|
||||||
})
|
});
|
||||||
|
|
||||||
try {
|
// 跳过注册流程,直接请求蓝牙权限
|
||||||
// 请求蓝牙权限
|
await wx.authorize({ scope: 'scope.bluetooth' });
|
||||||
await wx.authorize({
|
wx.hideLoading();
|
||||||
scope: 'scope.bluetooth'
|
console.log('初始化完成,使用硬编码账户:', this.globalData.accountInfo);
|
||||||
})
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
wx.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '获取蓝牙权限失败',
|
|
||||||
showCancel: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.error('初始化失败:', error)
|
||||||
|
wx.hideLoading()
|
||||||
wx.showModal({
|
wx.showModal({
|
||||||
title: '提示',
|
title: '初始化失败',
|
||||||
content: '蓝牙初始化失败,请检查蓝牙权限',
|
content: '请检查网络连接和蓝牙权限后重试',
|
||||||
showCancel: false
|
showCancel: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
{
|
{
|
||||||
"pages": [
|
"pages": [
|
||||||
"pages/index/index",
|
"pages/index/index",
|
||||||
"pages/password/password",
|
"pages/lock/lock",
|
||||||
|
"pages/lockDetail/lockDetail",
|
||||||
"pages/card/card",
|
"pages/card/card",
|
||||||
"pages/fingerprint/fingerprint"
|
"pages/fingerprint/fingerprint",
|
||||||
|
"pages/password/password"
|
||||||
],
|
],
|
||||||
"window": {
|
"window": {
|
||||||
"backgroundTextStyle": "light",
|
"backgroundTextStyle": "light",
|
||||||
|
|||||||
@ -13,511 +13,107 @@ const {
|
|||||||
updateSupportFunctionsWithParams,
|
updateSupportFunctionsWithParams,
|
||||||
remoteUnLock,
|
remoteUnLock,
|
||||||
readSupportFunctions,
|
readSupportFunctions,
|
||||||
|
getLockList,
|
||||||
} = requirePlugin('starCloud')
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
Page({
|
Page({
|
||||||
data: {
|
data: {
|
||||||
list: [],
|
|
||||||
accountInfo: {},
|
accountInfo: {},
|
||||||
lock: null,
|
deviceType: 'lock', // 默认选择锁
|
||||||
eventChannel: null,
|
retryCount: 0,
|
||||||
isSearching: false,
|
maxRetries: 3
|
||||||
loading: false, // 添加loading状态
|
|
||||||
showPassageMode: false,
|
|
||||||
passageModeForm: {
|
|
||||||
passageMode: '1',
|
|
||||||
startDate: '',
|
|
||||||
endDate: '',
|
|
||||||
isAllDay: '0',
|
|
||||||
cycleType: 'workday', // 添加循环类型:workday/weekend/everyday
|
|
||||||
autoUnlock: '1'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
startSearching() {
|
|
||||||
if (this.data.isSearching) {
|
|
||||||
wx.showToast({
|
|
||||||
title: '正在搜索中',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setData({isSearching: true})
|
|
||||||
searchDevice((result) => {
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
this.setData({
|
|
||||||
list: result.data.list
|
|
||||||
})
|
|
||||||
getApp().globalData.deviceList = result.data.list
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
wx.showToast({
|
|
||||||
title: '开始搜索设备',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
stopSearching() {
|
|
||||||
if (!this.data.isSearching) return
|
|
||||||
|
|
||||||
stopSearchDevice()
|
|
||||||
this.setData({isSearching: false})
|
|
||||||
wx.showToast({
|
|
||||||
title: '已停止搜索',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
onHide() {
|
|
||||||
this.stopSearching()
|
|
||||||
},
|
|
||||||
|
|
||||||
onUnload() {
|
|
||||||
this.stopSearching()
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
// 从app.globalData获取数据
|
this.checkAccountInfo();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检查账户信息
|
||||||
|
checkAccountInfo() {
|
||||||
const app = getApp();
|
const app = getApp();
|
||||||
// 确保accountInfo包含必要的字段
|
console.log('检查账户信息:', app.globalData.accountInfo);
|
||||||
const accountInfo = {
|
|
||||||
...app.globalData.accountInfo,
|
|
||||||
account: app.globalData.accountInfo.account || '',
|
|
||||||
password: app.globalData.accountInfo.password || '',
|
|
||||||
aesKey: app.globalData.accountInfo.aesKey || '',
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setData({
|
// 修正字段检查
|
||||||
list: app.globalData.deviceList,
|
if (app.globalData.accountInfo && app.globalData.accountInfo.username) {
|
||||||
accountInfo: accountInfo
|
const accountInfo = {
|
||||||
});
|
username: app.globalData.accountInfo.username,
|
||||||
|
password: app.globalData.accountInfo.password,
|
||||||
|
uid: app.globalData.accountInfo.uid
|
||||||
|
};
|
||||||
|
|
||||||
// 打印检查accountInfo结构
|
this.setData({ accountInfo });
|
||||||
console.log('Current accountInfo:', accountInfo);
|
console.log('设置账户信息成功:', this.data.accountInfo);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if (this.data.retryCount < this.data.maxRetries) {
|
||||||
|
wx.showLoading({
|
||||||
|
title: '正在初始化...'
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setData({
|
||||||
|
retryCount: this.data.retryCount + 1
|
||||||
|
});
|
||||||
|
wx.hideLoading();
|
||||||
|
this.checkAccountInfo();
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
wx.hideLoading();
|
||||||
|
wx.showModal({
|
||||||
|
title: '初始化失败',
|
||||||
|
content: '账户信息获取失败,请重启小程序',
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async requestBluetoothPermission() {
|
// 切换设备类型
|
||||||
try {
|
onTypeChange(e) {
|
||||||
const res = await wx.authorize({
|
this.setData({
|
||||||
scope: 'scope.bluetooth'
|
deviceType: e.detail.value
|
||||||
});
|
});
|
||||||
this.startSearching();
|
},
|
||||||
} catch (error) {
|
|
||||||
wx.showModal({
|
// 进入设备页面
|
||||||
title: '提示',
|
enterDevice() {
|
||||||
content: '请授权蓝牙权限以使用设备功能',
|
console.log('当前账户信息:', this.data.accountInfo);
|
||||||
|
if (!this.data.accountInfo || !this.data.accountInfo.username) {
|
||||||
|
// 再次尝试获取账户信息
|
||||||
|
if (this.checkAccountInfo()) {
|
||||||
|
this.navigateToDevicePage();
|
||||||
|
} else {
|
||||||
|
wx.showToast({
|
||||||
|
title: '账户信息未准备好',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.navigateToDevicePage();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 添加导航方法
|
||||||
|
navigateToDevicePage() {
|
||||||
|
if (this.data.deviceType === 'lock') {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/lock/lock',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.confirm) {
|
// 确保传递完整的账户信息
|
||||||
wx.openSetting();
|
res.eventChannel.emit('acceptDataFromOpenerPage', {
|
||||||
}
|
accountInfo: this.data.accountInfo
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
},
|
|
||||||
|
|
||||||
// 搜索设备
|
|
||||||
searchDevice() {
|
|
||||||
searchDevice(this.searchDeviceCallback)
|
|
||||||
},
|
|
||||||
// 搜索设备回调
|
|
||||||
searchDeviceCallback(result) {
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
this.setData({
|
|
||||||
list: result.data.list
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 添加通用的loading处理方法
|
|
||||||
async handleApiCall(apiFunc, loadingText = '处理中...') {
|
|
||||||
this.setData({loading: true})
|
|
||||||
wx.showLoading({title: loadingText, mask: true})
|
|
||||||
|
|
||||||
try {
|
|
||||||
await apiFunc()
|
|
||||||
} finally {
|
|
||||||
this.setData({loading: false})
|
|
||||||
wx.hideLoading()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 修改绑定设备方法
|
|
||||||
bindDevice(e) {
|
|
||||||
const {device} = e.currentTarget.dataset
|
|
||||||
wx.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: `确定绑定${device.name}吗?`,
|
|
||||||
success: async (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
const result = await bindDevice({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
name: device.name,
|
|
||||||
})
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
// 合并设备信息,确保显示完整信息
|
|
||||||
const lockInfo = {
|
|
||||||
...device, // 包含搜索时的设备信息(name, mac, uid等)
|
|
||||||
...result.data.lock // 包含绑定后的信息(lockId, keyId等)
|
|
||||||
}
|
|
||||||
this.setData({
|
|
||||||
lock: lockInfo,
|
|
||||||
list: [] // 清空搜索列表
|
|
||||||
})
|
|
||||||
// 更新app.globalData中的lock
|
|
||||||
getApp().globalData.lock = lockInfo
|
|
||||||
this.stopSearching()
|
|
||||||
wx.showToast({
|
|
||||||
title: '绑定成功',
|
|
||||||
icon: 'success',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, '绑定中...')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 修改开门方法
|
|
||||||
async openDoor() {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
})
|
|
||||||
const result = await openDoor({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
disconnect: true,
|
|
||||||
type: 'open'
|
|
||||||
})
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
wx.showToast({
|
|
||||||
title: '开门成功',
|
|
||||||
icon: 'success',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, '开门中...')
|
|
||||||
},
|
|
||||||
|
|
||||||
// 修改删除锁方法
|
|
||||||
async deleteLock() {
|
|
||||||
wx.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '确定要删除此设备吗?',
|
|
||||||
success: async (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
})
|
|
||||||
const result = await deleteLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
})
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
this.setData({
|
|
||||||
lock: null,
|
|
||||||
list: []
|
|
||||||
})
|
|
||||||
wx.showToast({
|
|
||||||
title: '删除成功',
|
|
||||||
icon: 'success',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, '删除中...')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取锁支持项
|
|
||||||
async getLockSupportFeatures() {
|
|
||||||
const result = await getLockSupportFeatures({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
})
|
|
||||||
console.log('锁支持项', result)
|
|
||||||
},
|
|
||||||
|
|
||||||
navigateToCard() {
|
|
||||||
wx.navigateTo({
|
|
||||||
url: '/pages/card/card'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
navigateToFingerprint() {
|
|
||||||
wx.navigateTo({
|
|
||||||
url: '/pages/fingerprint/fingerprint'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
navigateToPassword() {
|
|
||||||
wx.navigateTo({
|
|
||||||
url: '/pages/password/password',
|
|
||||||
success: (res) => {
|
|
||||||
res.eventChannel.emit('acceptDataFromOpenerPage', {
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lock: this.data.lock
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setAdminPasswordOperate(e) {
|
|
||||||
const operate = e.currentTarget.dataset.operate;
|
|
||||||
wx.showModal({
|
|
||||||
title: '设置管理员密码',
|
|
||||||
editable: true,
|
|
||||||
placeholderText: '请输入管理员密码',
|
|
||||||
success: (res) => {
|
|
||||||
if (res.confirm && res.content) {
|
|
||||||
this._setAdminPasswordOperate(Number(operate), res.content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async _setAdminPasswordOperate(operate, password) {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
});
|
|
||||||
const params = {
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
adminPwd: password
|
|
||||||
};
|
|
||||||
const result = await updateAdminPassword(params);
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
wx.showToast({
|
|
||||||
title: '设置成功',
|
|
||||||
icon: 'success'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log('_setAdminPasswordOperate', result);
|
|
||||||
}, '设置中...');
|
|
||||||
},
|
|
||||||
|
|
||||||
async updateAutoLock() {
|
|
||||||
wx.showModal({
|
|
||||||
title: '自动闭锁设置',
|
|
||||||
editable: true,
|
|
||||||
showCancel: true,
|
|
||||||
placeholderText: '请输入自动闭锁时间(秒)',
|
|
||||||
success: async (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
const value = parseInt(res.content);
|
|
||||||
if (!res.content) {
|
|
||||||
// 用户未输入数值,视为关闭自动闭锁
|
|
||||||
this._updateAutoLockSetting(0);
|
|
||||||
} else if (isNaN(value) || value < 1) {
|
|
||||||
wx.showToast({
|
|
||||||
title: '请输入大于1的整数',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 输入合法,更新设置
|
|
||||||
this._updateAutoLockSetting(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async _updateAutoLockSetting(seconds) {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
});
|
|
||||||
const params = {
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
featureBit: 29,
|
|
||||||
data: Number(seconds),
|
|
||||||
withParams: true
|
|
||||||
};
|
|
||||||
const result = await updateSupportFunctionsWithParams(params);
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
wx.showToast({
|
|
||||||
title: seconds === 0 ? '已关闭自动闭锁' : '设置成功',
|
|
||||||
icon: 'success'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log('updateAutoLock', result);
|
|
||||||
}, '设置中...');
|
|
||||||
},
|
|
||||||
|
|
||||||
async updateLockSound() {
|
|
||||||
wx.showActionSheet({
|
|
||||||
itemList: ['关闭', '1档', '2档', '3档', '4档', '5档'],
|
|
||||||
success: (res) => {
|
|
||||||
// res.tapIndex 从0开始,正好对应音量级别
|
|
||||||
this._updateLockSoundSetting(res.tapIndex);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async _updateLockSoundSetting(volume) {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
});
|
|
||||||
const params = {
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
featureBit: 33,
|
|
||||||
data: Number(volume),
|
|
||||||
withParams: true
|
|
||||||
};
|
|
||||||
const result = await updateSupportFunctionsWithParams(params);
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
wx.showToast({
|
|
||||||
title: volume === 0 ? '已关闭提示音' : `已设置为${volume}档`,
|
|
||||||
icon: 'success'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
console.log('updateLockSound', result);
|
|
||||||
}, '设置中...');
|
|
||||||
},
|
|
||||||
|
|
||||||
async remoteUnLockRequest() {
|
|
||||||
|
|
||||||
console.log('remoteUnLockRequest', await remoteUnLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
async enableAntiPryAlarm(e) {
|
|
||||||
const operate = e.currentTarget.dataset.operate;
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
})
|
|
||||||
const parms = {
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
featureBit: 30,
|
|
||||||
featureEnable: operate,
|
|
||||||
withParams: false
|
|
||||||
};
|
|
||||||
const reslut = await updateSupportFunctionsWithParams(parms);
|
|
||||||
console.log('enableAntiPryAlarm', reslut)
|
|
||||||
},
|
|
||||||
async updatePassageMode() {
|
|
||||||
this.setData({
|
|
||||||
showPassageMode: true
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
hidePassageMode() {
|
|
||||||
this.setData({
|
|
||||||
showPassageMode: false
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onPassageModeInput(e) {
|
|
||||||
const {field} = e.currentTarget.dataset;
|
|
||||||
const {value} = e.detail;
|
|
||||||
this.setData({
|
|
||||||
[`passageModeForm.${field}`]: value
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
async submitPassageMode() {
|
|
||||||
try {
|
|
||||||
const form = this.data.passageModeForm;
|
|
||||||
const startTime = parseInt(form.startDate);
|
|
||||||
const endTime = parseInt(form.endDate);
|
|
||||||
|
|
||||||
// 验证输入
|
|
||||||
if (!form.startDate || !form.endDate) {
|
|
||||||
throw new Error('请输入开始和结束时间');
|
|
||||||
}
|
|
||||||
if (isNaN(startTime) || startTime < 0 || startTime > 1440 ||
|
|
||||||
isNaN(endTime) || endTime < 0 || endTime > 1440) {
|
|
||||||
throw new Error('时间必须在0-1440分钟之间');
|
|
||||||
}
|
|
||||||
if (endTime <= startTime) {
|
|
||||||
throw new Error('结束时间必须大于开始时间');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据循环类型设置weekDay
|
|
||||||
let weekDay;
|
|
||||||
switch (form.cycleType) {
|
|
||||||
case 'workday':
|
|
||||||
weekDay = [1, 2, 3, 4, 5];
|
|
||||||
break;
|
|
||||||
case 'weekend':
|
|
||||||
weekDay = [6, 7];
|
|
||||||
break;
|
|
||||||
case 'everyday':
|
|
||||||
weekDay = [1, 2, 3, 4, 5, 6, 7];
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error('请选择循环类型');
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
passageMode: parseInt(form.passageMode),
|
|
||||||
startDate: startTime,
|
|
||||||
endDate: endTime,
|
|
||||||
isAllDay: parseInt(form.isAllDay),
|
|
||||||
weekDay,
|
|
||||||
autoUnlock: parseInt(form.autoUnlock)
|
|
||||||
};
|
|
||||||
|
|
||||||
await this._updatePassageModeSetting(params);
|
|
||||||
this.hidePassageMode();
|
|
||||||
} catch (error) {
|
|
||||||
wx.showToast({
|
wx.showToast({
|
||||||
title: error.message,
|
title: '网关功能开发中',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
async _updatePassageModeSetting(params) {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = await updateSupportFunctionsWithParams({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
featureBit: 50,
|
|
||||||
data: params,
|
|
||||||
withParams: true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
wx.showToast({
|
|
||||||
title: '设置成功',
|
|
||||||
icon: 'success'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw new Error(result.msg || '设置失败');
|
|
||||||
}
|
|
||||||
}, '设置中...');
|
|
||||||
},
|
|
||||||
|
|
||||||
async readSupportFunctionsSet() {
|
|
||||||
await this.handleApiCall(async () => {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
});
|
|
||||||
const result = await readSupportFunctions({
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
});
|
|
||||||
console.log('readSupportFunctionsSet', result);
|
|
||||||
wx.showModal({
|
|
||||||
title: '功能设置',
|
|
||||||
content: JSON.stringify(result.data, null, 2),
|
|
||||||
showCancel: false
|
|
||||||
});
|
|
||||||
}, '读取中...');
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
|
||||||
|
|||||||
@ -1,154 +1,25 @@
|
|||||||
<view class="container">
|
<view class="container">
|
||||||
<!-- 未绑定设备时显示搜索界面 -->
|
<view class="form-card">
|
||||||
<view class="device-list" wx:if="{{!lock}}">
|
<view class="card-title">选择设备类型</view>
|
||||||
<view class="section-title">可用设备</view>
|
|
||||||
<view class="search-section">
|
|
||||||
<button class="search-btn {{isSearching ? 'searching' : ''}}"
|
|
||||||
bind:tap="startSearching"
|
|
||||||
disabled="{{loading}}">
|
|
||||||
{{isSearching ? '正在搜索...' : '搜索设备'}}
|
|
||||||
</button>
|
|
||||||
<button wx:if="{{isSearching}}"
|
|
||||||
class="stop-btn"
|
|
||||||
bind:tap="stopSearching"
|
|
||||||
disabled="{{loading}}">停止搜索</button>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view wx:for="{{list}}"
|
<radio-group class="device-types" bind:change="onTypeChange">
|
||||||
wx:key="name"
|
<label class="type-item {{deviceType === 'lock' ? 'active' : ''}}">
|
||||||
class="device"
|
<radio value="lock" checked="{{deviceType === 'lock'}}"/>
|
||||||
bind:tap="bindDevice"
|
<view class="type-content">
|
||||||
data-device="{{item}}">
|
<text class="type-name">智能门锁</text>
|
||||||
<view class="device-name">{{item.name}}</view>
|
<text class="type-desc">管理您的智能门锁设备</text>
|
||||||
<view class="device-status">点击绑定</view>
|
</view>
|
||||||
</view>
|
</label>
|
||||||
|
|
||||||
<view wx:if="{{list.length === 0}}" class="empty-tip">
|
<label class="type-item {{deviceType === 'gateway' ? 'active' : ''}}">
|
||||||
{{isSearching ? '正在搜索设备...' : '未找到设备,点击搜索按钮开始搜索'}}
|
<radio value="gateway" checked="{{deviceType === 'gateway'}}"/>
|
||||||
</view>
|
<view class="type-content">
|
||||||
</view>
|
<text class="type-name">智能网关</text>
|
||||||
|
<text class="type-desc">管理您的智能网关设备</text>
|
||||||
|
</view>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
|
||||||
<!-- 已绑定设备时显示操作界面 -->
|
<button class="submit-btn" bind:tap="enterDevice">进入设备管理</button>
|
||||||
<view class="action-section" wx:else>
|
|
||||||
<view class="device-info">
|
|
||||||
<view class="info-item">
|
|
||||||
<text class="label">设备名称:</text>
|
|
||||||
<text class="value">{{lock.lockName || lock.name || '未知'}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-item" wx:if="{{lock.mac}}">
|
|
||||||
<text class="label">MAC地址:</text>
|
|
||||||
<text class="value">{{lock.mac}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-item" wx:if="{{lock.uid}}">
|
|
||||||
<text class="label">UID:</text>
|
|
||||||
<text class="value">{{lock.uid}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-item" wx:if="{{lock.keyId}}">
|
|
||||||
<text class="label">钥匙ID:</text>
|
|
||||||
<text class="value">{{lock.keyId}}</text>
|
|
||||||
</view>
|
|
||||||
<view class="info-item" wx:if="{{lock.lockId}}">
|
|
||||||
<text class="label">锁ID:</text>
|
|
||||||
<text class="value">{{lock.lockId}}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="main-actions">
|
|
||||||
<button class="primary-btn" bind:tap="openDoor">开门</button>
|
|
||||||
<button class="primary-btn" bind:tap="remoteUnLockRequest">远程开锁</button>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="management-section">
|
|
||||||
<view class="section-title">管理功能</view>
|
|
||||||
<view class="grid-buttons">
|
|
||||||
<button bind:tap="navigateToCard">卡片管理</button>
|
|
||||||
<button bind:tap="navigateToFingerprint">指纹管理</button>
|
|
||||||
<button bind:tap="navigateToPassword">密码管理</button>
|
|
||||||
<button bind:tap="setAdminPasswordOperate" data-operate="0">设置管理员密码</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="settings-section">
|
|
||||||
<view class="section-title">设置选项</view>
|
|
||||||
<view class="grid-buttons">
|
|
||||||
<button bind:tap="updateAutoLock">自动闭锁设置</button>
|
|
||||||
<button bind:tap="updateLockSound">提示音量</button>
|
|
||||||
<button bind:tap="updatePassageMode">常开模式</button>
|
|
||||||
<button bind:tap="readSupportFunctionsSet">读取功能设置</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<button class="danger-btn" bind:tap="deleteLock">删除设备</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 常开模式设置弹出层 -->
|
|
||||||
<view class="passage-mode-popup {{showPassageMode ? 'show' : ''}}">
|
|
||||||
<view class="popup-mask" catch:tap="hidePassageMode"></view>
|
|
||||||
<view class="popup-content">
|
|
||||||
<view class="popup-header">
|
|
||||||
<text class="title">常开模式设置</text>
|
|
||||||
<text class="close" bind:tap="hidePassageMode">×</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<scroll-view class="popup-body" scroll-y>
|
|
||||||
<view class="form-item">
|
|
||||||
<text class="label">常开模式状态</text>
|
|
||||||
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="passageMode">
|
|
||||||
<radio value="1" checked="{{passageModeForm.passageMode === '1'}}">开启</radio>
|
|
||||||
<radio value="0" checked="{{passageModeForm.passageMode === '0'}}">关闭</radio>
|
|
||||||
</radio-group>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="form-item">
|
|
||||||
<text class="label">是否全天</text>
|
|
||||||
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="isAllDay">
|
|
||||||
<radio value="1" checked="{{passageModeForm.isAllDay === '1'}}">是</radio>
|
|
||||||
<radio value="0" checked="{{passageModeForm.isAllDay === '0'}}">否</radio>
|
|
||||||
</radio-group>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="form-item" wx:if="{{passageModeForm.isAllDay === '0'}}">
|
|
||||||
<text class="label">开始时间(分钟)</text>
|
|
||||||
<input type="number" class="input"
|
|
||||||
value="{{passageModeForm.startDate}}"
|
|
||||||
bind:input="onPassageModeInput"
|
|
||||||
data-field="startDate"
|
|
||||||
placeholder="输入0-1440之间的数字"/>
|
|
||||||
<text class="hint">例如:\n480 = 08:00\n720 = 12:00\n1080 = 18:00</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="form-item" wx:if="{{passageModeForm.isAllDay === '0'}}">
|
|
||||||
<text class="label">结束时间(分钟)</text>
|
|
||||||
<input type="number" class="input"
|
|
||||||
value="{{passageModeForm.endDate}}"
|
|
||||||
bind:input="onPassageModeInput"
|
|
||||||
data-field="endDate"
|
|
||||||
placeholder="输入0-1440之间的数字"/>
|
|
||||||
<text class="hint">注意:结束时间必须大于开始时间</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="form-item">
|
|
||||||
<text class="label">循环方式</text>
|
|
||||||
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="cycleType">
|
|
||||||
<radio value="workday" checked="{{passageModeForm.cycleType === 'workday'}}">工作日循环</radio>
|
|
||||||
<radio value="weekend" checked="{{passageModeForm.cycleType === 'weekend'}}">周末循环</radio>
|
|
||||||
<radio value="everyday" checked="{{passageModeForm.cycleType === 'everyday'}}">每天循环</radio>
|
|
||||||
</radio-group>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="form-item">
|
|
||||||
<text class="label">自动开锁</text>
|
|
||||||
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="autoUnlock">
|
|
||||||
<radio value="1" checked="{{passageModeForm.autoUnlock === '1'}}">开启</radio>
|
|
||||||
<radio value="0" checked="{{passageModeForm.autoUnlock === '0'}}">关闭</radio>
|
|
||||||
</radio-group>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
|
|
||||||
<view class="popup-footer">
|
|
||||||
<button class="cancel-btn" bind:tap="hidePassageMode">取消</button>
|
|
||||||
<button class="confirm-btn" bind:tap="submitPassageMode">确定</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@ -1,347 +1,85 @@
|
|||||||
.container {
|
.container {
|
||||||
padding: 32rpx;
|
padding: 32rpx;
|
||||||
background: #f5f5f5;
|
background: #f7f7f7;
|
||||||
}
|
min-height: 100vh;
|
||||||
|
|
||||||
.device-list {
|
|
||||||
background: white;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
padding: 24rpx;
|
|
||||||
margin-bottom: 32rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 24rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 24rpx;
|
|
||||||
margin: 16rpx 0;
|
|
||||||
background: #f8f9fa;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-name {
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-status {
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: #2c405a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-section {
|
|
||||||
background: white;
|
|
||||||
border-radius: 16rpx;
|
|
||||||
padding: 24rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 16rpx;
|
|
||||||
margin-bottom: 32rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary-btn {
|
|
||||||
flex: 1;
|
|
||||||
background: #2c405a;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.management-section,
|
|
||||||
.settings-section {
|
|
||||||
margin-bottom: 32rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-buttons {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 16rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-buttons button {
|
|
||||||
margin: 0;
|
|
||||||
background: #f8f9fa;
|
|
||||||
color: #2c405a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.danger-btn {
|
|
||||||
background: #dc3545;
|
|
||||||
color: white;
|
|
||||||
margin-top: 32rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-time-picker {
|
|
||||||
padding: 15px;
|
|
||||||
background: #fff;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-item {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 10px 0;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-item text {
|
.form-card {
|
||||||
width: 80px;
|
width: 100%;
|
||||||
|
background: white;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 40rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker {
|
.card-title {
|
||||||
flex: 1;
|
font-size: 36rpx;
|
||||||
padding: 5px 10px;
|
font-weight: 600;
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-list {
|
|
||||||
margin: 15px;
|
|
||||||
padding: 10px;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-list-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-item {
|
|
||||||
padding: 10px;
|
|
||||||
margin: 5px 0;
|
|
||||||
background: #f5f5f5;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-item view {
|
|
||||||
margin: 3px 0;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.password-time-picker {
|
|
||||||
padding: 15px;
|
|
||||||
background: #fff;
|
|
||||||
margin: 10px;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.time-section {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #333;
|
color: #333;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 40rpx;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-group {
|
.device-types {
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker {
|
|
||||||
flex: 1;
|
|
||||||
padding: 8px 12px;
|
|
||||||
background: #f5f5f5;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pwd-type-picker {
|
|
||||||
padding: 15px;
|
|
||||||
background: #fff;
|
|
||||||
margin: 10px;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker {
|
|
||||||
padding: 8px 12px;
|
|
||||||
background: #f5f5f5;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-value {
|
|
||||||
border: 1rpx solid #ddd;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
padding: 20rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
background: #f8f9fa;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-value:active {
|
|
||||||
background: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-btn {
|
|
||||||
width: 90%;
|
|
||||||
margin: 10px auto;
|
|
||||||
background-color: #007AFF;
|
|
||||||
color: white;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-info {
|
|
||||||
background: #f5f5f5;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-item {
|
|
||||||
display: flex;
|
|
||||||
padding: 5px 0;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-item .label {
|
|
||||||
color: #666;
|
|
||||||
width: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-item .value {
|
|
||||||
color: #333;
|
|
||||||
flex: 1;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.passage-mode-popup {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.passage-mode-popup.show {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-mask {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-content {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 24rpx 24rpx 0 0;
|
|
||||||
max-height: 85vh;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
gap: 24rpx;
|
||||||
|
margin-bottom: 48rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-header {
|
.type-item {
|
||||||
padding: 30rpx;
|
display: flex;
|
||||||
border-bottom: 1rpx solid #eee;
|
align-items: center;
|
||||||
}
|
padding: 24rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
.popup-header .title {
|
|
||||||
font-size: 32rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-header .close {
|
|
||||||
position: absolute;
|
|
||||||
right: 30rpx;
|
|
||||||
top: 30rpx;
|
|
||||||
font-size: 40rpx;
|
|
||||||
color: #999;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-body {
|
|
||||||
flex: 1;
|
|
||||||
padding: 30rpx;
|
|
||||||
overflow-y: auto;
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-item {
|
|
||||||
margin-bottom: 40rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-item .label {
|
|
||||||
display: block;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 20rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-item .input {
|
|
||||||
border: 1rpx solid #ddd;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
padding: 20rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-item .hint {
|
.type-item.active {
|
||||||
|
background: rgba(0,122,255,0.1);
|
||||||
|
border: 2rpx solid #007AFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-item radio {
|
||||||
|
transform: scale(0.8);
|
||||||
|
margin-right: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-name {
|
||||||
display: block;
|
display: block;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-desc {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #666;
|
color: #666;
|
||||||
margin-top: 12rpx;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio-group {
|
.submit-btn {
|
||||||
display: flex;
|
width: 100%;
|
||||||
gap: 30rpx;
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
background: linear-gradient(135deg, #007AFF, #40a9ff);
|
||||||
|
color: white;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(0,122,255,0.2);
|
||||||
|
transition: all 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-footer {
|
.submit-btn:active {
|
||||||
padding: 30rpx;
|
transform: scale(0.98);
|
||||||
border-top: 1rpx solid #eee;
|
box-shadow: 0 2rpx 6rpx rgba(0,122,255,0.2);
|
||||||
display: flex;
|
|
||||||
gap: 20rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-footer button {
|
|
||||||
flex: 1;
|
|
||||||
margin: 0;
|
|
||||||
height: 80rpx;
|
|
||||||
line-height: 80rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cancel-btn {
|
|
||||||
background: #f5f5f5;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.confirm-btn {
|
|
||||||
background: #007aff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
165
miniprogram/miniprogram/pages/lock/lock.js
Normal file
165
miniprogram/miniprogram/pages/lock/lock.js
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
const {
|
||||||
|
searchDevice,
|
||||||
|
bindDevice,
|
||||||
|
getLockList,
|
||||||
|
stopSearchDevice,
|
||||||
|
Result
|
||||||
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
searchList: [], // 搜索到的设备列表
|
||||||
|
boundList: [], // 已绑定的设备列表
|
||||||
|
accountInfo: {},
|
||||||
|
isSearching: false,
|
||||||
|
loading: false,
|
||||||
|
needRefresh: false, // 添加needRefresh标记
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
// 页面加载时就获取账户信息并请求设备列表
|
||||||
|
const app = getApp();
|
||||||
|
if (!app.globalData.accountInfo) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '账户信息未准备好',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取正确的账户信息字段
|
||||||
|
const accountInfo = {
|
||||||
|
username: app.globalData.accountInfo.username,
|
||||||
|
password: app.globalData.accountInfo.password,
|
||||||
|
uid: app.globalData.accountInfo.uid
|
||||||
|
};
|
||||||
|
|
||||||
|
// 设置accountInfo并立即获取设备列表
|
||||||
|
this.setData({ accountInfo }, () => {
|
||||||
|
this.getBoundDevices();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onShow() {
|
||||||
|
// 简化判断,避免使用可选链
|
||||||
|
if (this.data.accountInfo && this.data.accountInfo.username) {
|
||||||
|
this.getBoundDevices();
|
||||||
|
// 重置刷新标记
|
||||||
|
this.setData({ needRefresh: false });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取已绑定设备列表
|
||||||
|
async getBoundDevices() {
|
||||||
|
try {
|
||||||
|
wx.showLoading({
|
||||||
|
title: '获取设备列表...'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 确保使用正确的账户信息字段
|
||||||
|
if (!this.data.accountInfo || !this.data.accountInfo.username) {
|
||||||
|
throw new Error('账户信息未准备好');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await getLockList({
|
||||||
|
accountInfo: this.data.accountInfo
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
this.setData({
|
||||||
|
boundList: result.data.groupList[0].lockList || []
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(result.msg || '获取设备列表失败');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
wx.showToast({
|
||||||
|
title: error.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
startSearching() {
|
||||||
|
if (this.data.isSearching) return;
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
isSearching: true,
|
||||||
|
searchList: []
|
||||||
|
});
|
||||||
|
|
||||||
|
searchDevice((result) => {
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
const boundMacs = this.data.boundList.map(item => item.mac);
|
||||||
|
const newDevices = result.data.list.filter(item => !boundMacs.includes(item.mac));
|
||||||
|
this.setData({ searchList: newDevices });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
stopSearching() {
|
||||||
|
if (!this.data.isSearching) return;
|
||||||
|
stopSearchDevice();
|
||||||
|
this.setData({ isSearching: false });
|
||||||
|
},
|
||||||
|
|
||||||
|
bindDevice(e) {
|
||||||
|
const { device } = e.currentTarget.dataset;
|
||||||
|
wx.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: `确定绑定${device.name}吗?`,
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
wx.showLoading({ title: '绑定中...', mask: true });
|
||||||
|
try {
|
||||||
|
// 使用正确的账户信息字段
|
||||||
|
const result = await bindDevice({
|
||||||
|
accountInfo: {
|
||||||
|
username: this.data.accountInfo.username,
|
||||||
|
password: this.data.accountInfo.password,
|
||||||
|
uid: this.data.accountInfo.uid
|
||||||
|
},
|
||||||
|
name: device.name,
|
||||||
|
});
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
await this.getBoundDevices();
|
||||||
|
wx.showToast({
|
||||||
|
title: '绑定成功',
|
||||||
|
icon: 'success',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '绑定失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
selectLock(e) {
|
||||||
|
const { lock } = e.currentTarget.dataset;
|
||||||
|
// 直接更新全局数据
|
||||||
|
const app = getApp();
|
||||||
|
app.globalData.lock = lock;
|
||||||
|
|
||||||
|
// 简化跳转
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/lockDetail/lockDetail'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onHide() {
|
||||||
|
this.stopSearching();
|
||||||
|
},
|
||||||
|
|
||||||
|
onUnload() {
|
||||||
|
this.stopSearching();
|
||||||
|
}
|
||||||
|
})
|
||||||
3
miniprogram/miniprogram/pages/lock/lock.json
Normal file
3
miniprogram/miniprogram/pages/lock/lock.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
39
miniprogram/miniprogram/pages/lock/lock.wxml
Normal file
39
miniprogram/miniprogram/pages/lock/lock.wxml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<view class="container">
|
||||||
|
<!-- 已绑定设备列表 -->
|
||||||
|
<view class="bound-list">
|
||||||
|
<view class="section-title">已绑定设备</view>
|
||||||
|
<view wx:for="{{boundList}}"
|
||||||
|
wx:key="lockId"
|
||||||
|
class="device"
|
||||||
|
bind:tap="selectLock"
|
||||||
|
data-lock="{{item}}">
|
||||||
|
<view class="device-name">{{item.lockName || item.name}}</view>
|
||||||
|
<view class="device-status">点击选择</view>
|
||||||
|
</view>
|
||||||
|
<view wx:if="{{boundList.length === 0}}" class="empty-tip">
|
||||||
|
暂无绑定设备
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 搜索新设备 -->
|
||||||
|
<view class="search-section">
|
||||||
|
<view class="section-title">搜索新设备</view>
|
||||||
|
<button class="search-btn {{isSearching ? 'searching' : ''}}"
|
||||||
|
bind:tap="startSearching"
|
||||||
|
disabled="{{loading}}">
|
||||||
|
{{isSearching ? '正在搜索...' : '搜索设备'}}
|
||||||
|
</button>
|
||||||
|
<button wx:if="{{isSearching}}"
|
||||||
|
class="stop-btn"
|
||||||
|
bind:tap="stopSearching">停止搜索</button>
|
||||||
|
|
||||||
|
<view wx:for="{{searchList}}"
|
||||||
|
wx:key="mac"
|
||||||
|
class="device"
|
||||||
|
bind:tap="bindDevice"
|
||||||
|
data-device="{{item}}">
|
||||||
|
<view class="device-name">{{item.name}}</view>
|
||||||
|
<view class="device-status">点击绑定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
87
miniprogram/miniprogram/pages/lock/lock.wxss
Normal file
87
miniprogram/miniprogram/pages/lock/lock.wxss
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
.container {
|
||||||
|
padding: 32rpx;
|
||||||
|
background: #f7f7f7;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bound-list, .search-section {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
padding-left: 16rpx;
|
||||||
|
border-left: 8rpx solid #007AFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin: 16rpx 0;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device:active {
|
||||||
|
background: #eef0f2;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-status {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #007AFF;
|
||||||
|
background: rgba(0,122,255,0.1);
|
||||||
|
padding: 8rpx 16rpx;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
background: #007AFF;
|
||||||
|
color: white;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
margin: 20rpx 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn.searching {
|
||||||
|
background: #40a9ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stop-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #666;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin: 20rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-tip {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding: 48rpx 0;
|
||||||
|
}
|
||||||
405
miniprogram/miniprogram/pages/lockDetail/lockDetail.js
Normal file
405
miniprogram/miniprogram/pages/lockDetail/lockDetail.js
Normal file
@ -0,0 +1,405 @@
|
|||||||
|
const {
|
||||||
|
Result,
|
||||||
|
openDoor,
|
||||||
|
deleteLock,
|
||||||
|
selectLock,
|
||||||
|
updateAdminPassword,
|
||||||
|
updateSupportFunctionsWithParams,
|
||||||
|
remoteUnLock,
|
||||||
|
readSupportFunctions,
|
||||||
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
lock: null, // 当前选中的锁
|
||||||
|
accountInfo: {},
|
||||||
|
loading: false,
|
||||||
|
showPassageMode: false,
|
||||||
|
passageModeForm: {
|
||||||
|
passageMode: '1',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
isAllDay: '0',
|
||||||
|
cycleType: 'workday',
|
||||||
|
autoUnlock: '1'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad(options) {
|
||||||
|
const app = getApp();
|
||||||
|
|
||||||
|
// 尝试获取全局数据
|
||||||
|
const lock = app.globalData.lock;
|
||||||
|
const accountInfo = app.globalData.accountInfo;
|
||||||
|
|
||||||
|
console.log('lockDetail onLoad:', { lock, accountInfo });
|
||||||
|
|
||||||
|
if (!lock || !accountInfo) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '获取设备信息失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
wx.navigateBack();
|
||||||
|
}, 1500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置数据到页面
|
||||||
|
this.setData({
|
||||||
|
lock,
|
||||||
|
accountInfo
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导航到卡片管理
|
||||||
|
navigateToCard() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/card/card'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导航到指纹管理
|
||||||
|
navigateToFingerprint() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/fingerprint/fingerprint'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导航到密码管理
|
||||||
|
navigateToPassword() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/password/password'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 设置管理员密码
|
||||||
|
setAdminPasswordOperate(e) {
|
||||||
|
wx.showModal({
|
||||||
|
title: '设置管理员密码',
|
||||||
|
editable: true,
|
||||||
|
placeholderText: '请输入管理员密码',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm && res.content) {
|
||||||
|
this._setAdminPasswordOperate(res.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新自动闭锁设置
|
||||||
|
async updateAutoLock() {
|
||||||
|
wx.showModal({
|
||||||
|
title: '自动闭锁设置',
|
||||||
|
editable: true,
|
||||||
|
showCancel: true,
|
||||||
|
placeholderText: '请输入自动闭锁时间(秒)',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
const value = parseInt(res.content);
|
||||||
|
if (!res.content) {
|
||||||
|
this._updateAutoLockSetting(0);
|
||||||
|
} else if (isNaN(value) || value < 1) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请输入大于1的整数',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._updateAutoLockSetting(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新声音设置
|
||||||
|
async updateLockSound() {
|
||||||
|
wx.showActionSheet({
|
||||||
|
itemList: ['关闭', '1档', '2档', '3档', '4档', '5档'],
|
||||||
|
success: (res) => {
|
||||||
|
this._updateLockSoundSetting(res.tapIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 远程开锁
|
||||||
|
async remoteUnLockRequest() {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
console.log('remoteUnLockRequest', await remoteUnLock());
|
||||||
|
},
|
||||||
|
|
||||||
|
// 读取锁设置
|
||||||
|
async readSupportFunctionsSet() {
|
||||||
|
await this.handleApiCall(async () => {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
const result = await readSupportFunctions({
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
wx.showModal({
|
||||||
|
title: '功能设置',
|
||||||
|
content: JSON.stringify(result.data, null, 2),
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 开门操作
|
||||||
|
async openDoor() {
|
||||||
|
await this.handleApiCall(async () => {
|
||||||
|
const app = getApp();
|
||||||
|
// 确保使用最新的锁信息
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: app.globalData.lock.lockId
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await openDoor({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
disconnect: true,
|
||||||
|
type: 'open'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '开门成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, '开门中...');
|
||||||
|
},
|
||||||
|
|
||||||
|
// 常开模式设置
|
||||||
|
async updatePassageMode() {
|
||||||
|
this.setData({
|
||||||
|
showPassageMode: true,
|
||||||
|
passageModeForm: {
|
||||||
|
passageMode: '1',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
isAllDay: '0',
|
||||||
|
cycleType: 'workday',
|
||||||
|
autoUnlock: '1'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
hidePassageMode() {
|
||||||
|
this.setData({
|
||||||
|
showPassageMode: false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onPassageModeInput(e) {
|
||||||
|
const { field } = e.currentTarget.dataset;
|
||||||
|
const { value } = e.detail;
|
||||||
|
this.setData({
|
||||||
|
[`passageModeForm.${field}`]: value
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async submitPassageMode() {
|
||||||
|
try {
|
||||||
|
const form = this.data.passageModeForm;
|
||||||
|
const startTime = parseInt(form.startDate);
|
||||||
|
const endTime = parseInt(form.endDate);
|
||||||
|
|
||||||
|
// 验证输入
|
||||||
|
if (!form.startDate || !form.endDate) {
|
||||||
|
throw new Error('请输入开始和结束时间');
|
||||||
|
}
|
||||||
|
if (isNaN(startTime) || startTime < 0 || startTime > 1440 ||
|
||||||
|
isNaN(endTime) || endTime < 0 || endTime > 1440) {
|
||||||
|
throw new Error('时间必须在0-1440分钟之间');
|
||||||
|
}
|
||||||
|
if (endTime <= startTime) {
|
||||||
|
throw new Error('结束时间必须大于开始时间');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据循环类型设置weekDay
|
||||||
|
let weekDay;
|
||||||
|
switch (form.cycleType) {
|
||||||
|
case 'workday':
|
||||||
|
weekDay = [1, 2, 3, 4, 5];
|
||||||
|
break;
|
||||||
|
case 'weekend':
|
||||||
|
weekDay = [6, 7];
|
||||||
|
break;
|
||||||
|
case 'everyday':
|
||||||
|
weekDay = [1, 2, 3, 4, 5, 6, 7];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('请选择循环类型');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this._updatePassageModeSetting({
|
||||||
|
passageMode: parseInt(form.passageMode),
|
||||||
|
startDate: startTime,
|
||||||
|
endDate: endTime,
|
||||||
|
isAllDay: parseInt(form.isAllDay),
|
||||||
|
weekDay,
|
||||||
|
autoUnlock: parseInt(form.autoUnlock)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.hidePassageMode();
|
||||||
|
} catch (error) {
|
||||||
|
wx.showToast({
|
||||||
|
title: error.message,
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async _updatePassageModeSetting(params) {
|
||||||
|
await this.handleApiCall(async () => {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await updateSupportFunctionsWithParams({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
featureBit: 50,
|
||||||
|
data: params,
|
||||||
|
withParams: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '设置成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(result.msg || '设置失败');
|
||||||
|
}
|
||||||
|
}, '设置中...');
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除设备
|
||||||
|
async deleteLock() {
|
||||||
|
wx.showModal({
|
||||||
|
title: '删除设备',
|
||||||
|
content: '确定要删除此设备吗?此操作不可恢复。',
|
||||||
|
success: async (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
await this.handleApiCall(async () => {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await deleteLock({
|
||||||
|
accountInfo: this.data.accountInfo
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
|
||||||
|
const app = getApp();
|
||||||
|
app.globalData.lock = null;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
wx.navigateBack();
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
throw new Error(result.msg || '删除失败');
|
||||||
|
}
|
||||||
|
}, '删除中...');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 通用的API调用方法
|
||||||
|
async handleApiCall(apiFunc, loadingText = '处理中...') {
|
||||||
|
const app = getApp();
|
||||||
|
this.setData({ loading: true });
|
||||||
|
wx.showLoading({ title: loadingText, mask: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 检查锁信息是否存在
|
||||||
|
if (!app.globalData.lock || !app.globalData.lock.lockId) {
|
||||||
|
throw new Error('锁信息不存在');
|
||||||
|
}
|
||||||
|
await apiFunc();
|
||||||
|
} catch (error) {
|
||||||
|
wx.showToast({
|
||||||
|
title: error.message || '操作失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
this.setData({ loading: false });
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 具体的设置实现方法
|
||||||
|
async _setAdminPasswordOperate(password) {
|
||||||
|
await this.handleApiCall(async () => {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
const result = await updateAdminPassword({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
adminPwd: password
|
||||||
|
});
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '设置成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async _updateAutoLockSetting(seconds) {
|
||||||
|
await this.handleApiCall(async () => {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
const result = await updateSupportFunctionsWithParams({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
featureBit: 29,
|
||||||
|
data: Number(seconds),
|
||||||
|
withParams: true
|
||||||
|
});
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
wx.showToast({
|
||||||
|
title: seconds === 0 ? '已关闭自动闭锁' : '设置成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async _updateLockSoundSetting(volume) {
|
||||||
|
await this.handleApiCall(async () => {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
const result = await updateSupportFunctionsWithParams({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
featureBit: 33,
|
||||||
|
data: Number(volume),
|
||||||
|
withParams: true
|
||||||
|
});
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
wx.showToast({
|
||||||
|
title: volume === 0 ? '已关闭提示音' : `已设置为${volume}档`,
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
3
miniprogram/miniprogram/pages/lockDetail/lockDetail.json
Normal file
3
miniprogram/miniprogram/pages/lockDetail/lockDetail.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
135
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxml
Normal file
135
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxml
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<view class="container">
|
||||||
|
<view class="form-card">
|
||||||
|
<view class="device-info">
|
||||||
|
<view class="info-item">
|
||||||
|
<text class="label">设备名称:</text>
|
||||||
|
<text class="value">{{lock.lockName || lock.name || '未知'}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item" wx:if="{{lock.mac}}">
|
||||||
|
<text class="label">MAC地址:</text>
|
||||||
|
<text class="value">{{lock.mac}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-item" wx:if="{{lock.lockId}}">
|
||||||
|
<text class="label">锁ID:</text>
|
||||||
|
<text class="value">{{lock.lockId}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="section-title">快捷操作</view>
|
||||||
|
<view class="action-buttons">
|
||||||
|
<button class="main-btn primary" bind:tap="openDoor">开门</button>
|
||||||
|
<button class="main-btn primary" bind:tap="remoteUnLockRequest">远程开锁</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="section-title">管理功能</view>
|
||||||
|
<view class="grid-buttons">
|
||||||
|
<button class="feature-btn" bind:tap="navigateToCard">
|
||||||
|
<view class="feature-icon card-icon"></view>
|
||||||
|
<text class="feature-name">卡片管理</text>
|
||||||
|
<text class="feature-desc">IC卡添加与删除</text>
|
||||||
|
</button>
|
||||||
|
<button class="feature-btn" bind:tap="navigateToFingerprint">
|
||||||
|
<view class="feature-icon fingerprint-icon"></view>
|
||||||
|
<text class="feature-name">指纹管理</text>
|
||||||
|
<text class="feature-desc">指纹录入与删除</text>
|
||||||
|
</button>
|
||||||
|
<button class="feature-btn" bind:tap="navigateToPassword">
|
||||||
|
<view class="feature-icon password-icon"></view>
|
||||||
|
<text class="feature-name">密码管理</text>
|
||||||
|
<text class="feature-desc">密码设置与更改</text>
|
||||||
|
</button>
|
||||||
|
<button class="feature-btn" bind:tap="setAdminPasswordOperate">
|
||||||
|
<view class="feature-icon admin-icon"></view>
|
||||||
|
<text class="feature-name">管理员密码</text>
|
||||||
|
<text class="feature-desc">设置管理员权限</text>
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="section-title">设置选项</view>
|
||||||
|
<view class="grid-buttons">
|
||||||
|
<button class="feature-btn" bind:tap="updateAutoLock">
|
||||||
|
<view class="feature-icon autolock-icon"></view>
|
||||||
|
<text class="feature-name">自动闭锁</text>
|
||||||
|
<text class="feature-desc">自动上锁时间</text>
|
||||||
|
</button>
|
||||||
|
<button class="feature-btn" bind:tap="updateLockSound">
|
||||||
|
<view class="feature-icon sound-icon"></view>
|
||||||
|
<text class="feature-name">提示音量</text>
|
||||||
|
<text class="feature-desc">调节锁具音量</text>
|
||||||
|
</button>
|
||||||
|
<button class="feature-btn" bind:tap="updatePassageMode">
|
||||||
|
<view class="feature-icon passage-icon"></view>
|
||||||
|
<text class="feature-name">常开模式</text>
|
||||||
|
<text class="feature-desc">设置通行时段</text>
|
||||||
|
</button>
|
||||||
|
<button class="feature-btn" bind:tap="readSupportFunctionsSet">
|
||||||
|
<view class="feature-icon settings-icon"></view>
|
||||||
|
<text class="feature-name">功能设置</text>
|
||||||
|
<text class="feature-desc">查看所有配置</text>
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<button class="main-btn danger" bind:tap="deleteLock">删除设备</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 常开模式设置弹出层 -->
|
||||||
|
<view class="popup-mask" wx:if="{{showPassageMode}}" bind:tap="hidePassageMode"></view>
|
||||||
|
<view class="popup-content" wx:if="{{showPassageMode}}">
|
||||||
|
<view class="popup-header">
|
||||||
|
<text class="title">常开模式设置</text>
|
||||||
|
<text class="close" bind:tap="hidePassageMode">×</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<scroll-view class="popup-body" scroll-y>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">常开模式状态</text>
|
||||||
|
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="passageMode">
|
||||||
|
<radio value="1" checked="{{passageModeForm.passageMode === '1'}}">开启</radio>
|
||||||
|
<radio value="0" checked="{{passageModeForm.passageMode === '0'}}">关闭</radio>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">是否全天</text>
|
||||||
|
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="isAllDay">
|
||||||
|
<radio value="1" checked="{{passageModeForm.isAllDay === '1'}}">是</radio>
|
||||||
|
<radio value="0" checked="{{passageModeForm.isAllDay === '0'}}">否</radio>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">循环方式</text>
|
||||||
|
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="cycleType">
|
||||||
|
<radio value="workday" checked="{{passageModeForm.cycleType === 'workday'}}">工作日循环</radio>
|
||||||
|
<radio value="weekend" checked="{{passageModeForm.cycleType === 'weekend'}}">周末循环</radio>
|
||||||
|
<radio value="everyday" checked="{{passageModeForm.cycleType === 'everyday'}}">每天循环</radio>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<block wx:if="{{passageModeForm.isAllDay === '0'}}">
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">开始时间(分钟)</text>
|
||||||
|
<input type="number" class="input" bind:input="onPassageModeInput" data-field="startDate" placeholder="输入0-1440之间的数字"/>
|
||||||
|
<text class="hint">例如:480 = 08:00, 720 = 12:00</text>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">结束时间(分钟)</text>
|
||||||
|
<input type="number" class="input" bind:input="onPassageModeInput" data-field="endDate" placeholder="输入0-1440之间的数字"/>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">自动开锁</text>
|
||||||
|
<radio-group class="radio-group" bind:change="onPassageModeInput" data-field="autoUnlock">
|
||||||
|
<radio value="1" checked="{{passageModeForm.autoUnlock === '1'}}">开启</radio>
|
||||||
|
<radio value="0" checked="{{passageModeForm.autoUnlock === '0'}}">关闭</radio>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view class="popup-footer">
|
||||||
|
<button class="cancel-btn" bind:tap="hidePassageMode">取消</button>
|
||||||
|
<button class="confirm-btn" bind:tap="submitPassageMode">确定</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
280
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxss
Normal file
280
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxss
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
.container {
|
||||||
|
padding: 32rpx;
|
||||||
|
background: #f7f7f7;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 40rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-info {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
padding: 12rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item .label {
|
||||||
|
width: 160rpx;
|
||||||
|
color: #666;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item .value {
|
||||||
|
flex: 1;
|
||||||
|
color: #333;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin: 40rpx 0 24rpx;
|
||||||
|
padding-left: 16rpx;
|
||||||
|
border-left: 8rpx solid #007AFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-btn.primary {
|
||||||
|
flex: 1;
|
||||||
|
background: linear-gradient(135deg, #007AFF, #40a9ff);
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 4rpx 12rpx rgba(0,122,255,0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-btn.danger {
|
||||||
|
background: #ff4d4f;
|
||||||
|
color: white;
|
||||||
|
margin-top: 48rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-btn:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-buttons {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 24rpx;
|
||||||
|
padding: 0 0 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-btn {
|
||||||
|
height: 180rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
transition: all 0.3s;
|
||||||
|
position: relative;
|
||||||
|
border: 2rpx solid #f0f0f0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-btn::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-btn:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
background: #f8f9fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon {
|
||||||
|
width: 64rpx;
|
||||||
|
height: 64rpx;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-desc {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 功能图标 */
|
||||||
|
.card-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M844.8 115.2H179.2c-38.4 0-64 25.6-64 64v665.6c0 38.4 25.6 64 64 64h665.6c38.4 0 64-25.6 64-64V179.2c0-38.4-25.6-64-64-64z m-384 512H256v-204.8h204.8V627.2z m320-204.8h-256v-64h256v64z m0 128h-256v-64h256v64z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M512 928c-229.76 0-416-186.24-416-416S282.24 96 512 96s416 186.24 416 416-186.24 416-416 416z m0-64c194.4 0 352-157.6 352-352S706.4 160 512 160 160 317.6 160 512s157.6 352 352 352z m128-352c0-70.4-57.6-128-128-128s-128 57.6-128 128h-64c0-105.6 86.4-192 192-192s192 86.4 192 192h-64z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M768 384h-64V256c0-105.6-86.4-192-192-192s-192 86.4-192 192v128h-64V256c0-140.8 115.2-256 256-256s256 115.2 256 256v128z m64 64H192c-38.4 0-64 25.6-64 64v384c0 38.4 25.6 64 64 64h640c38.4 0 64-25.6 64-64V512c0-38.4-25.6-64-64-64z m-320 256c-38.4 0-64-25.6-64-64s25.6-64 64-64 64 25.6 64 64-25.6 64-64 64z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M512 512c-105.6 0-192-86.4-192-192s86.4-192 192-192 192 86.4 192 192-86.4 192-192 192z m0-320c-70.4 0-128 57.6-128 128s57.6 128 128 128 128-57.6 128-128-57.6-128-128-128z m320 704H192c-38.4 0-64-25.6-64-64V704c0-140.8 115.2-256 256-256h256c140.8 0 256 115.2 256 256v128c0 38.4-25.6 64-64 64z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.autolock-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M512 928c-229.76 0-416-186.24-416-416S282.24 96 512 96s416 186.24 416 416-186.24 416-416 416z m32-416V320h-64v192h192v-64H544z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.sound-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M512 928c-229.76 0-416-186.24-416-416S282.24 96 512 96s416 186.24 416 416-186.24 416-416 416z m128-544c-19.2-19.2-51.2-19.2-70.4 0-19.2 19.2-19.2 51.2 0 70.4 19.2 19.2 19.2 51.2 0 70.4-19.2 19.2-51.2 19.2-70.4 0-19.2-19.2-19.2-51.2 0-70.4 19.2-19.2 19.2-51.2 0-70.4-19.2-19.2-51.2-19.2-70.4 0-19.2 19.2-19.2 51.2 0 70.4 57.6 57.6 57.6 150.4 0 208-19.2 19.2-19.2 51.2 0 70.4 19.2 19.2 51.2 19.2 70.4 0 96-96 96-252.8 0-348.8z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.passage-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M768 384H640V256c0-70.4-57.6-128-128-128s-128 57.6-128 128v128H256V256c0-140.8 115.2-256 256-256s256 115.2 256 256v128z m64 64H192c-38.4 0-64 25.6-64 64v384c0 38.4 25.6 64 64 64h640c38.4 0 64-25.6 64-64V512c0-38.4-25.6-64-64-64z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1677721600000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M512 640c-70.4 0-128-57.6-128-128s57.6-128 128-128 128 57.6 128 128-57.6 128-128 128z m0-192c-35.2 0-64 28.8-64 64s28.8 64 64 64 64-28.8 64-64-28.8-64-64-64z m384 352H128c-38.4 0-64-25.6-64-64V288c0-38.4 25.6-64 64-64h768c38.4 0 64 25.6 64 64v448c0 38.4-25.6 64-64 64z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 弹出层样式 */
|
||||||
|
.popup-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-content {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: white;
|
||||||
|
border-radius: 24rpx 24rpx 0 0;
|
||||||
|
z-index: 1001;
|
||||||
|
max-height: 80vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-header {
|
||||||
|
padding: 32rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-header .title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-header .close {
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #999;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body {
|
||||||
|
flex: 1;
|
||||||
|
padding: 32rpx;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body .form-item {
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body .label {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body .radio-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body .input {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
border: 2rpx solid #eee;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 0 24rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-body .hint {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-footer {
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
border-top: 1rpx solid #eee;
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-footer button {
|
||||||
|
flex: 1;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
border-radius: 44rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-footer .cancel-btn {
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-footer .confirm-btn {
|
||||||
|
background: linear-gradient(135deg, #007AFF, #40a9ff);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-footer button:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
8
package-lock.json
generated
8
package-lock.json
generated
@ -24,7 +24,7 @@
|
|||||||
"@dcloudio/uni-mp-xhs": "3.0.0-4030620241128001",
|
"@dcloudio/uni-mp-xhs": "3.0.0-4030620241128001",
|
||||||
"@dcloudio/uni-quickapp-webview": "3.0.0-4030620241128001",
|
"@dcloudio/uni-quickapp-webview": "3.0.0-4030620241128001",
|
||||||
"pinia": "^2.2.8",
|
"pinia": "^2.2.8",
|
||||||
"star-cloud-uni": "^1.0.13",
|
"star-cloud-uni": "^1.0.14",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^9.1.9"
|
"vue-i18n": "^9.1.9"
|
||||||
},
|
},
|
||||||
@ -10046,9 +10046,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/star-cloud-uni": {
|
"node_modules/star-cloud-uni": {
|
||||||
"version": "1.0.13",
|
"version": "1.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/star-cloud-uni/-/star-cloud-uni-1.0.13.tgz",
|
"resolved": "https://registry.npmjs.org/star-cloud-uni/-/star-cloud-uni-1.0.14.tgz",
|
||||||
"integrity": "sha512-F1LLDwcEAqMkbUDwnbyvqYAbMMhiAJG3rQbduxkOdzdHT3lpxPOxqep6XVi4AfbRbRwbuWXChle81iBLZiK6vw==",
|
"integrity": "sha512-8KnuxvqiyvDcodaue0t0ofYuMNYqXv2HLw5P1HglEWZqiQyMCMwB8dcx9UxV4X1mdRlgj0/JbxdT5vE/eRT4Og==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"crc": "^4.3.2",
|
"crc": "^4.3.2",
|
||||||
|
|||||||
@ -52,7 +52,7 @@
|
|||||||
"@dcloudio/uni-mp-xhs": "3.0.0-4030620241128001",
|
"@dcloudio/uni-mp-xhs": "3.0.0-4030620241128001",
|
||||||
"@dcloudio/uni-quickapp-webview": "3.0.0-4030620241128001",
|
"@dcloudio/uni-quickapp-webview": "3.0.0-4030620241128001",
|
||||||
"pinia": "^2.2.8",
|
"pinia": "^2.2.8",
|
||||||
"star-cloud-uni": "^1.0.13",
|
"star-cloud-uni": "^1.0.14",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^9.1.9"
|
"vue-i18n": "^9.1.9"
|
||||||
},
|
},
|
||||||
|
|||||||
10
src/index.js
10
src/index.js
@ -23,6 +23,7 @@ import {
|
|||||||
updateSupportFunctionsWithParams,
|
updateSupportFunctionsWithParams,
|
||||||
remoteUnLock,
|
remoteUnLock,
|
||||||
readSupportFunctionsSetting,
|
readSupportFunctionsSetting,
|
||||||
|
getLockList,
|
||||||
} from 'star-cloud-uni'
|
} from 'star-cloud-uni'
|
||||||
// 用于存储事件监听器的Map
|
// 用于存储事件监听器的Map
|
||||||
const eventListeners = new Map();
|
const eventListeners = new Map();
|
||||||
@ -318,5 +319,14 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
async remoteUnLock(params){
|
async remoteUnLock(params){
|
||||||
return await remoteUnLock(params)
|
return await remoteUnLock(params)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取锁列表
|
||||||
|
* @param params
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
async getLockList(params){
|
||||||
|
return await getLockList(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user