Compare commits
10 Commits
b55d0b857c
...
8c3a83497a
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c3a83497a | |||
| 32378c2aef | |||
| 39a70a768d | |||
| 81bc00e03e | |||
| d2071f2e88 | |||
| 690849af88 | |||
| 891ba072d0 | |||
| 2911b32664 | |||
| 150a002560 | |||
| 675c6337da |
@ -1,5 +1,67 @@
|
|||||||
// app.js
|
// app.js
|
||||||
|
const {
|
||||||
|
init,
|
||||||
|
Result,
|
||||||
|
register
|
||||||
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
// 添加硬编码的账户信息
|
||||||
|
const MOCK_ACCOUNT = {
|
||||||
|
username: 'nhueg_3MWghkBljd8WoDUmeBm',
|
||||||
|
password: '91936ff7ede730fb7befc33dc749543d',
|
||||||
|
uid: 17162
|
||||||
|
};
|
||||||
|
|
||||||
App({
|
App({
|
||||||
onLaunch() {
|
globalData: {
|
||||||
|
accountInfo: MOCK_ACCOUNT, // 直接使用硬编码的账户信息
|
||||||
|
deviceList: [],
|
||||||
|
lock: null, // 确保初始化为 null
|
||||||
|
currentLockId: null // 可选:添加当前选中的锁ID
|
||||||
|
},
|
||||||
|
|
||||||
|
// 可以添加一个更新锁信息的方法
|
||||||
|
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() {
|
||||||
|
try {
|
||||||
|
wx.showLoading({
|
||||||
|
title: '初始化中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用硬编码的账户初始化SDK
|
||||||
|
init({
|
||||||
|
clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
|
||||||
|
clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
|
||||||
|
env: 'SKY',
|
||||||
|
isReportLog: true,
|
||||||
|
accounts: [MOCK_ACCOUNT] // 使用硬编码的账户
|
||||||
|
});
|
||||||
|
|
||||||
|
// 跳过注册流程,直接请求蓝牙权限
|
||||||
|
await wx.authorize({ scope: 'scope.bluetooth' });
|
||||||
|
wx.hideLoading();
|
||||||
|
console.log('初始化完成,使用硬编码账户:', this.globalData.accountInfo);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化失败:', error)
|
||||||
|
wx.hideLoading()
|
||||||
|
wx.showModal({
|
||||||
|
title: '初始化失败',
|
||||||
|
content: '请检查网络连接和蓝牙权限后重试',
|
||||||
|
showCancel: false
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,7 +1,19 @@
|
|||||||
{
|
{
|
||||||
"pages": [
|
"pages": [
|
||||||
"pages/index/index"
|
"pages/index/index",
|
||||||
|
"pages/lock/lock",
|
||||||
|
"pages/lockDetail/lockDetail",
|
||||||
|
"pages/card/card",
|
||||||
|
"pages/fingerprint/fingerprint",
|
||||||
|
"pages/password/password",
|
||||||
|
"pages/configNetwork/configNetwork"
|
||||||
],
|
],
|
||||||
|
"window": {
|
||||||
|
"backgroundTextStyle": "light",
|
||||||
|
"navigationBarBackgroundColor": "#fff",
|
||||||
|
"navigationBarTitleText": "门锁管理",
|
||||||
|
"navigationBarTextStyle": "black"
|
||||||
|
},
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"starCloud": {
|
"starCloud": {
|
||||||
"version": "dev",
|
"version": "dev",
|
||||||
|
|||||||
687
miniprogram/miniprogram/pages/card/card.js
Normal file
687
miniprogram/miniprogram/pages/card/card.js
Normal file
@ -0,0 +1,687 @@
|
|||||||
|
const {
|
||||||
|
registerExtendedProducts,
|
||||||
|
starEventOn,
|
||||||
|
getIcCardList,
|
||||||
|
selectLock
|
||||||
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
cardId: -1,
|
||||||
|
cardNumber: 0,
|
||||||
|
cardName: '',
|
||||||
|
cardType: 1,
|
||||||
|
isAdmin: 1,
|
||||||
|
isForce: 0,
|
||||||
|
isRound: 0,
|
||||||
|
weekDayInput: '', // 新增输入框的值
|
||||||
|
weekDay: [], // 修改为空数组,不再使用 0/1 数组
|
||||||
|
weekdayPattern: 'workday', // 添加周期模式选择
|
||||||
|
weekdayPatterns: ['工作日循环(星期一到星期五)', '周末循环(星期六日)', '每天循环'],
|
||||||
|
weekdayPatternIndex: 0,
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
startDateDisplay: '', // 添加用于显示的日期字符串
|
||||||
|
endDateDisplay: '', // 添加用于显示的日期字符串
|
||||||
|
startTime: '00:00',
|
||||||
|
endTime: '00:00',
|
||||||
|
cardList: [],
|
||||||
|
currentParams: null,
|
||||||
|
editMode: false,
|
||||||
|
selectedCard: null,
|
||||||
|
dateTimeArray: [], // 日期时间选择器的数据
|
||||||
|
startDateTimeArray: [0, 0, 0, 0, 0], // 开始时间选择器的当前值
|
||||||
|
endDateTimeArray: [0, 0, 0, 0, 0] // 结束时间选择器的当前值
|
||||||
|
},
|
||||||
|
|
||||||
|
observers: {
|
||||||
|
'weekDayInput': function (val) {
|
||||||
|
if (!val) {
|
||||||
|
this.setData({
|
||||||
|
weekDay: [],
|
||||||
|
isRound: 0
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const weekDay = val.split(',')
|
||||||
|
.map(item => item.trim())
|
||||||
|
.filter(item => /^[0-6]$/.test(item))
|
||||||
|
.filter((item, index, self) => self.indexOf(item) === index)
|
||||||
|
.sort((a, b) => Number(a) - Number(b));
|
||||||
|
|
||||||
|
console.log('Observer - Input:', val);
|
||||||
|
console.log('Observer - Processed weekDay:', weekDay);
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
weekDay,
|
||||||
|
isRound: weekDay.length > 0 ? 1 : 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
starEventOn('registerCardConfirm', async (data) => {
|
||||||
|
if (data.code === 0) {
|
||||||
|
this.setData({
|
||||||
|
cardId: data.data.cardId,
|
||||||
|
cardNumber: data.data.cardNumber
|
||||||
|
})
|
||||||
|
console.log('收到卡片确认事件', data, this.data.cardId, this.data.cardNumber);
|
||||||
|
// 添加成功后自动刷新列表
|
||||||
|
await this.findAllCard();
|
||||||
|
} else {
|
||||||
|
console.log('收到卡片确认事件', data, this.data.cardId, this.data.cardNumber);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化时间
|
||||||
|
const now = new Date();
|
||||||
|
const nextHour = new Date(now.getTime() + 60 * 60 * 1000);
|
||||||
|
const nowArr = [
|
||||||
|
now.getFullYear(),
|
||||||
|
now.getMonth(),
|
||||||
|
now.getDate(),
|
||||||
|
now.getHours(),
|
||||||
|
now.getMinutes()
|
||||||
|
];
|
||||||
|
const nextArr = [
|
||||||
|
nextHour.getFullYear(),
|
||||||
|
nextHour.getMonth(),
|
||||||
|
nextHour.getDate(),
|
||||||
|
nextHour.getHours(),
|
||||||
|
nextHour.getMinutes()
|
||||||
|
];
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
startTime: now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0'),
|
||||||
|
endTime: nextHour.getHours().toString().padStart(2, '0') + ':' + nextHour.getMinutes().toString().padStart(2, '0'),
|
||||||
|
startDateTimeArray: nowArr,
|
||||||
|
endDateTimeArray: nextArr,
|
||||||
|
startDate: now.getTime(),
|
||||||
|
endDate: nextHour.getTime(),
|
||||||
|
startDateDisplay: this.formatDateTime(now),
|
||||||
|
endDateDisplay: this.formatDateTime(nextHour)
|
||||||
|
});
|
||||||
|
|
||||||
|
// 页面加载时获取卡片列表
|
||||||
|
this.findAllCard();
|
||||||
|
|
||||||
|
// 初始化日期时间选择器数据
|
||||||
|
this.initDateTimeArray();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改格式化日期时间的方法,增加更多格式化选项
|
||||||
|
formatDateTime(date, format = 'display') {
|
||||||
|
if (!date || !(date instanceof Date)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (format === 'display') {
|
||||||
|
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
} else if (format === 'params') {
|
||||||
|
return `${date.getFullYear()}年${(date.getMonth() + 1).toString().padStart(2, '0')}月${date.getDate().toString().padStart(2, '0')}日${date.getHours().toString().padStart(2, '0')}时${date.getMinutes().toString().padStart(2, '0')}分`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 初始化日期时间选择器数据
|
||||||
|
initDateTimeArray() {
|
||||||
|
const date = new Date();
|
||||||
|
const years = [];
|
||||||
|
const months = [];
|
||||||
|
const days = [];
|
||||||
|
const hours = [];
|
||||||
|
const minutes = [];
|
||||||
|
|
||||||
|
// 生成年份选项(当前年份往后5年)
|
||||||
|
for (let i = date.getFullYear(); i <= date.getFullYear() + 5; i++) {
|
||||||
|
years.push(i + '年');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成月份选项 - 显示1-12月
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
months.push(i.toString().padStart(2, '0') + '月');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成天数选项(默认31天)
|
||||||
|
for (let i = 1; i <= 31; i++) {
|
||||||
|
days.push(i.toString().padStart(2, '0') + '日');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成小时选项
|
||||||
|
for (let i = 0; i < 24; i++) {
|
||||||
|
hours.push(i.toString().padStart(2, '0') + '时');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成分钟选项
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
minutes.push(i.toString().padStart(2, '0') + '分');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
dateTimeArray: [years, months, days, hours, minutes]
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onStartDateTimeChange(e) {
|
||||||
|
const val = e.detail.value;
|
||||||
|
const dateTimeArray = this.data.dateTimeArray;
|
||||||
|
|
||||||
|
const yearStr = dateTimeArray[0][val[0]];
|
||||||
|
const year = parseInt(yearStr);
|
||||||
|
const month = parseInt(dateTimeArray[1][val[1]]) - 1; // 转换为0-11的月份
|
||||||
|
const day = parseInt(dateTimeArray[2][val[2]]);
|
||||||
|
const hour = parseInt(dateTimeArray[3][val[3]]);
|
||||||
|
const minute = parseInt(dateTimeArray[4][val[4]]);
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(year);
|
||||||
|
date.setMonth(month); // 使用0-11的月份
|
||||||
|
date.setDate(day);
|
||||||
|
date.setHours(hour);
|
||||||
|
date.setMinutes(minute);
|
||||||
|
date.setSeconds(0);
|
||||||
|
date.setMilliseconds(0);
|
||||||
|
|
||||||
|
const timestamp = date.getTime();
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
startDateTimeArray: val,
|
||||||
|
startDate: timestamp,
|
||||||
|
startDateDisplay: this.formatDateTime(date)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndDateTimeChange(e) {
|
||||||
|
const val = e.detail.value;
|
||||||
|
const dateTimeArray = this.data.dateTimeArray;
|
||||||
|
|
||||||
|
const yearStr = dateTimeArray[0][val[0]];
|
||||||
|
const year = parseInt(yearStr);
|
||||||
|
const month = parseInt(dateTimeArray[1][val[1]]) - 1; // 转换为0-11的月份
|
||||||
|
const day = parseInt(dateTimeArray[2][val[2]]);
|
||||||
|
const hour = parseInt(dateTimeArray[3][val[3]]);
|
||||||
|
const minute = parseInt(dateTimeArray[4][val[4]]);
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(year);
|
||||||
|
date.setMonth(month); // 使用0-11的月份
|
||||||
|
date.setDate(day);
|
||||||
|
date.setHours(hour);
|
||||||
|
date.setMinutes(minute);
|
||||||
|
date.setSeconds(59);
|
||||||
|
date.setMilliseconds(999);
|
||||||
|
|
||||||
|
const timestamp = date.getTime();
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
endDateTimeArray: val,
|
||||||
|
endDate: timestamp,
|
||||||
|
endDateDisplay: this.formatDateTime(date)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理日期时间选择器列变化
|
||||||
|
onStartDateTimeColumnChange(e) {
|
||||||
|
// 处理月份天数联动
|
||||||
|
if (e.detail.column === 1) {
|
||||||
|
this.updateDays('startDateTimeArray', e.detail.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndDateTimeColumnChange(e) {
|
||||||
|
if (e.detail.column === 1) {
|
||||||
|
this.updateDays('endDateTimeArray', e.detail.value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新天数
|
||||||
|
updateDays(arrayName, monthIndex) {
|
||||||
|
const year = this.data.dateTimeArray[0][this.data[arrayName][0]];
|
||||||
|
const month = monthIndex + 1;
|
||||||
|
const days = new Date(parseInt(year), month, 0).getDate();
|
||||||
|
|
||||||
|
const newDays = [];
|
||||||
|
for (let i = 1; i <= days; i++) {
|
||||||
|
newDays.push(i.toString().padStart(2, '0') + '日');
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateTimeArray = this.data.dateTimeArray;
|
||||||
|
dateTimeArray[2] = newDays;
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
dateTimeArray: dateTimeArray
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async icCardOperate(e) {
|
||||||
|
const operate = e.currentTarget.dataset.operate;
|
||||||
|
const cardData = e.currentTarget.dataset.card;
|
||||||
|
if (cardData) {
|
||||||
|
this.setData({
|
||||||
|
cardId: cardData.cardId,
|
||||||
|
cardNumber: cardData.cardNumber,
|
||||||
|
cardName: cardData.cardName,
|
||||||
|
cardType: cardData.cardType,
|
||||||
|
isAdmin: cardData.isAdmin,
|
||||||
|
isForce: cardData.isForce,
|
||||||
|
isRound: cardData.isRound,
|
||||||
|
weekDay: cardData.weekDay || [],
|
||||||
|
startDate: cardData.startDate || 0,
|
||||||
|
endDate: cardData.endDate || 0,
|
||||||
|
startDateDisplay: cardData.startDate ? new Date(cardData.startDate).toISOString().split('T')[0] : '',
|
||||||
|
endDateDisplay: cardData.endDate ? new Date(cardData.endDate).toISOString().split('T')[0] : '',
|
||||||
|
startTime: cardData.startTime || '00:00',
|
||||||
|
endTime: cardData.endTime || '00:00'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await this._icCardOperate(Number(operate));
|
||||||
|
},
|
||||||
|
|
||||||
|
async _icCardOperate(operate) {
|
||||||
|
// 如果是修改操作,需要验证 cardNumber
|
||||||
|
if (operate === 1) {
|
||||||
|
if (!this.data.cardNumber || this.data.cardNumber === '0' || this.data.cardNumber === 0) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '卡号无效',
|
||||||
|
icon: 'error',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增:验证循环卡的周期设置
|
||||||
|
if (this.data.cardType === 4) {
|
||||||
|
if (!this.data.weekDay || !this.data.weekDay.length) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请设置循环周期',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wx.showLoading({
|
||||||
|
title: '处理中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const app = getApp();
|
||||||
|
const {accountInfo} = app.globalData;
|
||||||
|
const {lock} = app.globalData;
|
||||||
|
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: accountInfo,
|
||||||
|
lockId: lock.lockId
|
||||||
|
});
|
||||||
|
|
||||||
|
let finalStartDate = this.data.startDate;
|
||||||
|
let finalEndDate = this.data.endDate;
|
||||||
|
|
||||||
|
// 处理循环卡的时间戳
|
||||||
|
if (this.data.cardType === 4) {
|
||||||
|
if (!this.data.weekDay || !this.data.weekDay.length) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请输入循环周期',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将时间部分应用到日期时间戳中
|
||||||
|
if (this.data.startDate && this.data.startTime) {
|
||||||
|
const [startHours, startMinutes] = this.data.startTime.split(':');
|
||||||
|
const startDate = new Date(this.data.startDate);
|
||||||
|
startDate.setHours(parseInt(startHours), parseInt(startMinutes), 0, 0);
|
||||||
|
finalStartDate = startDate.getTime();
|
||||||
|
}
|
||||||
|
if (this.data.endDate && this.data.endTime) {
|
||||||
|
const [endHours, endMinutes] = this.data.endTime.split(':');
|
||||||
|
const endDate = new Date(this.data.endDate);
|
||||||
|
endDate.setHours(parseInt(endHours), parseInt(endMinutes), 59, 999);
|
||||||
|
finalEndDate = endDate.getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('发送请求前的 weekDay:', this.data.weekDay);
|
||||||
|
|
||||||
|
// 转换 weekDay 为数字数组
|
||||||
|
const weekDayNumbers = this.data.weekDay.map(Number);
|
||||||
|
console.log('转换后的 weekDayNumbers:', weekDayNumbers);
|
||||||
|
|
||||||
|
const parms = {
|
||||||
|
type: 'card',
|
||||||
|
keyId: String(lock.keyId),
|
||||||
|
uid: String(accountInfo.uid),
|
||||||
|
userCountLimit: 0xFFFF,
|
||||||
|
operate: operate,
|
||||||
|
isAdmin: this.data.isAdmin,
|
||||||
|
isForce: this.data.isForce,
|
||||||
|
isRound: this.data.isRound,
|
||||||
|
weekDay: weekDayNumbers,
|
||||||
|
cardId: this.data.cardId,
|
||||||
|
cardNumber: Number(this.data.cardNumber), // 确保 cardNumber 是数字类型
|
||||||
|
cardName: this.data.cardName,
|
||||||
|
cardType: this.data.cardType,
|
||||||
|
cardUserNo: 999,
|
||||||
|
startDate: finalStartDate,
|
||||||
|
endDate: finalEndDate,
|
||||||
|
startTime: this.data.cardType === 4 ? this.data.startTime : undefined,
|
||||||
|
endTime: this.data.cardType === 4 ? this.data.endTime : undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新参数显示,添加格式化的时间显示
|
||||||
|
if (this.data.cardType === 2) {
|
||||||
|
const startDateTime = new Date(this.data.startDate);
|
||||||
|
const endDateTime = new Date(this.data.endDate);
|
||||||
|
parms.displayTimeRange = `${this.formatDateTime(startDateTime, 'params')}-${this.formatDateTime(endDateTime, 'params')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
currentParams: parms
|
||||||
|
});
|
||||||
|
|
||||||
|
const registerExtendedProductsResult = await registerExtendedProducts(parms)
|
||||||
|
console.log('registerExtendedProductsResult', registerExtendedProductsResult);
|
||||||
|
|
||||||
|
if (registerExtendedProductsResult.code === 0) {
|
||||||
|
// 操作成功后清空表单
|
||||||
|
this.setData({
|
||||||
|
cardName: '',
|
||||||
|
cardType: 1,
|
||||||
|
isAdmin: 1,
|
||||||
|
isForce: 0,
|
||||||
|
isRound: 0,
|
||||||
|
weekDayInput: '',
|
||||||
|
weekDay: [],
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
startDateDisplay: '',
|
||||||
|
endDateDisplay: '',
|
||||||
|
startTime: '00:00',
|
||||||
|
endTime: '00:00'
|
||||||
|
});
|
||||||
|
// 刷新列表
|
||||||
|
await this.findAllCard();
|
||||||
|
wx.showToast({
|
||||||
|
title: '操作成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
wx.showToast({
|
||||||
|
title: '操作失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('操作失败:', error);
|
||||||
|
wx.showToast({
|
||||||
|
title: '操作失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async findAllCard() {
|
||||||
|
const app = getApp();
|
||||||
|
const {lock} = app.globalData;
|
||||||
|
const result = await getIcCardList({lockId: lock.lockId})
|
||||||
|
console.log('findAllCard', result)
|
||||||
|
|
||||||
|
// 处理返回的卡片列表数据
|
||||||
|
const processedList = (result.data.list || []).map(card => {
|
||||||
|
// 将周期数字转换为周几文本
|
||||||
|
const weekDayText = card.weekDay ? card.weekDay.map(day => {
|
||||||
|
if (day === 7) return '周日';
|
||||||
|
return `周${['一', '二', '三', '四', '五', '六'][day - 1]}`;
|
||||||
|
}).join(', ') : '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
...card,
|
||||||
|
isAdmin: card.cardRight === 1 ? 1 : 0,
|
||||||
|
isForce: card.isCoerced === 1 ? 1 : 0,
|
||||||
|
isRound: (card.weekDay && card.weekDay.length > 0) ? 1 : 0,
|
||||||
|
weekDayText // 添加文本形式的周期显示
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
cardList: processedList
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onCardTypeChange(e) {
|
||||||
|
const type = Number(e.detail.value);
|
||||||
|
this.setData({
|
||||||
|
cardType: type,
|
||||||
|
// 当选择永久类型时,重置时间
|
||||||
|
startTime: type === 1 ? '00:00' : this.data.startTime,
|
||||||
|
endTime: type === 1 ? '00:00' : this.data.endTime
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdminChange(e) {
|
||||||
|
this.setData({
|
||||||
|
isAdmin: e.detail.value ? 1 : 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onForceChange(e) {
|
||||||
|
this.setData({
|
||||||
|
isForce: e.detail.value ? 1 : 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onStartDateChange(e) {
|
||||||
|
const dateStr = e.detail.value;
|
||||||
|
const timestamp = new Date(dateStr).getTime();
|
||||||
|
this.setData({
|
||||||
|
startDate: timestamp,
|
||||||
|
startDateDisplay: dateStr
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndDateChange(e) {
|
||||||
|
const dateStr = e.detail.value;
|
||||||
|
const timestamp = new Date(dateStr).getTime();
|
||||||
|
this.setData({
|
||||||
|
endDate: timestamp,
|
||||||
|
endDateDisplay: dateStr
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onStartTimeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
startTime: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndTimeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
endTime: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改周期模式切换处理方法
|
||||||
|
onWeekdayPatternChange(e) {
|
||||||
|
const index = e.detail.value;
|
||||||
|
let weekDay = [];
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case '0': // 工作日循环
|
||||||
|
weekDay = [2, 3, 4, 5, 6]; // 星期一到星期五
|
||||||
|
break;
|
||||||
|
case '1': // 周末循环
|
||||||
|
weekDay = [1, 7]; // 星期日和星期六
|
||||||
|
break;
|
||||||
|
case '2': // 每天循环
|
||||||
|
weekDay = [1, 2, 3, 4, 5, 6, 7]; // 所有天
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
weekdayPatternIndex: index,
|
||||||
|
weekDay,
|
||||||
|
isRound: weekDay.length > 0 ? 1 : 0
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('周期模式变更:', this.data.weekdayPatterns[index], weekDay);
|
||||||
|
},
|
||||||
|
|
||||||
|
onWeekDayChange(e) {
|
||||||
|
const selectedDays = e.detail.value.map(Number);
|
||||||
|
// 创建一个长度为7的数组,初始值都是0
|
||||||
|
const weekDay = selectedDays.sort((a, b) => a - b);
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
weekDay,
|
||||||
|
isRound: weekDay.length > 0 ? 1 : 0
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('自定义周期变更:', weekDay);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改选择卡片方法中的处理
|
||||||
|
selectCard(e) {
|
||||||
|
const cardData = e.currentTarget.dataset.card;
|
||||||
|
|
||||||
|
// 处理循环数据
|
||||||
|
let weekDay = [];
|
||||||
|
let weekdayPatternIndex = 0;
|
||||||
|
|
||||||
|
if (cardData.weekDay && Array.isArray(cardData.weekDay)) {
|
||||||
|
weekDay = cardData.weekDay;
|
||||||
|
weekDay.sort((a, b) => a - b); // 确保顺序一致
|
||||||
|
|
||||||
|
// 判断是否符合预设模式
|
||||||
|
const weekDayStr = weekDay.join(',');
|
||||||
|
if (weekDayStr === '2,3,4,5,6') {
|
||||||
|
weekdayPatternIndex = 0; // 工作日
|
||||||
|
} else if (weekDayStr === '1,7') {
|
||||||
|
weekdayPatternIndex = 1; // 周末
|
||||||
|
} else if (weekDayStr === '1,2,3,4,5,6,7') {
|
||||||
|
weekdayPatternIndex = 2; // 每天
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理时间戳转换
|
||||||
|
const startDateTime = new Date(Number(cardData.startDate) || 0);
|
||||||
|
const endDateTime = new Date(Number(cardData.endDate) || 0);
|
||||||
|
|
||||||
|
// 提取时间部分
|
||||||
|
const startTime = cardData.startTime ||
|
||||||
|
`${startDateTime.getHours().toString().padStart(2, '0')}:${startDateTime.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
const endTime = cardData.endTime ||
|
||||||
|
`${endDateTime.getHours().toString().padStart(2, '0')}:${endDateTime.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
|
||||||
|
// 格式化日期显示
|
||||||
|
const startDateDisplay = this.formatDateTime(startDateTime).split(' ')[0];
|
||||||
|
const endDateDisplay = this.formatDateTime(endDateTime).split(' ')[0];
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
cardId: cardData.cardId,
|
||||||
|
cardNumber: this.data.cardNumber || cardData.cardNumber || 0,
|
||||||
|
cardName: cardData.cardName,
|
||||||
|
cardType: cardData.cardType,
|
||||||
|
isAdmin: cardData.isAdmin || (cardData.cardRight === 1 ? 1 : 0),
|
||||||
|
isForce: cardData.isForce || (cardData.isCoerced === 1 ? 1 : 0),
|
||||||
|
isRound: weekDay.length > 0 ? 1 : 0,
|
||||||
|
weekDay,
|
||||||
|
weekdayPatternIndex,
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
startDateDisplay,
|
||||||
|
endDateDisplay,
|
||||||
|
startDate: cardData.startDate || 0,
|
||||||
|
endDate: cardData.endDate || 0,
|
||||||
|
editMode: true,
|
||||||
|
selectedCard: cardData
|
||||||
|
}, () => {
|
||||||
|
// 强制触发一次视图更新
|
||||||
|
this.setData({_forceUpdate: Date.now()});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 添加辅助方法,计算年份索引
|
||||||
|
getYearIndex(year) {
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
return year - currentYear;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改确认编辑方法,直接使用时间戳
|
||||||
|
async confirmEdit() {
|
||||||
|
// 验证 cardNumber
|
||||||
|
if (!this.data.cardNumber || this.data.cardNumber === '0' || this.data.cardNumber === 0) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '卡号无效',
|
||||||
|
icon: 'error',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接使用当前的时间戳,不再重新构造
|
||||||
|
const formData = {
|
||||||
|
cardId: this.data.cardId,
|
||||||
|
cardNumber: this.data.cardNumber,
|
||||||
|
cardName: this.data.cardName,
|
||||||
|
cardType: this.data.cardType,
|
||||||
|
isAdmin: this.data.isAdmin,
|
||||||
|
isForce: this.data.isForce,
|
||||||
|
isRound: this.data.isRound,
|
||||||
|
weekDay: this.data.weekDay,
|
||||||
|
startDate: this.data.startDate,
|
||||||
|
endDate: this.data.endDate
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新当前数据
|
||||||
|
this.setData(formData);
|
||||||
|
|
||||||
|
// 执行修改操作
|
||||||
|
await this._icCardOperate(1);
|
||||||
|
|
||||||
|
// 修改完成后,退出编辑模式
|
||||||
|
if (this.data.editMode) {
|
||||||
|
this.cancelEdit();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 修改取消编辑方法
|
||||||
|
cancelEdit() {
|
||||||
|
this.setData({
|
||||||
|
editMode: false,
|
||||||
|
selectedCard: null,
|
||||||
|
cardId: -1,
|
||||||
|
cardNumber: 0,
|
||||||
|
cardName: '',
|
||||||
|
cardType: 1,
|
||||||
|
isAdmin: 1,
|
||||||
|
isForce: 0,
|
||||||
|
isRound: 0,
|
||||||
|
weekDayInput: '',
|
||||||
|
weekdayPatternIndex: 0,
|
||||||
|
weekDay: [], // 默认为空数组
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
startDateDisplay: '',
|
||||||
|
endDateDisplay: '',
|
||||||
|
startTime: '00:00',
|
||||||
|
endTime: '00:00'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除单个卡片
|
||||||
|
async deleteCard(e) {
|
||||||
|
const cardData = e.currentTarget.dataset.card;
|
||||||
|
this.setData({
|
||||||
|
cardId: cardData.cardId,
|
||||||
|
cardNumber: cardData.cardNumber
|
||||||
|
});
|
||||||
|
await this._icCardOperate(2); // 2 表示删除操作
|
||||||
|
}
|
||||||
|
})
|
||||||
3
miniprogram/miniprogram/pages/card/card.json
Normal file
3
miniprogram/miniprogram/pages/card/card.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
171
miniprogram/miniprogram/pages/card/card.wxml
Normal file
171
miniprogram/miniprogram/pages/card/card.wxml
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
<view class="card-page">
|
||||||
|
<view class="card-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text>卡片名称:</text>
|
||||||
|
<input type="text" model:value="{{cardName}}" placeholder="请输入卡片名称"/>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>卡片类型:</text>
|
||||||
|
<radio-group bindchange="onCardTypeChange">
|
||||||
|
<radio value="1" checked="{{cardType === 1}}">永久</radio>
|
||||||
|
<radio value="2" checked="{{cardType === 2}}">期限</radio>
|
||||||
|
<radio value="4" checked="{{cardType === 4}}">循环</radio>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>管理员:</text>
|
||||||
|
<switch checked="{{isAdmin === 1}}" bindchange="onAdminChange"/>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>胁迫模式:</text>
|
||||||
|
<switch checked="{{isForce === 1}}" bindchange="onForceChange"/>
|
||||||
|
</view>
|
||||||
|
<block wx:if="{{cardType === 2}}">
|
||||||
|
<view class="form-item">
|
||||||
|
<text>期限时间:</text>
|
||||||
|
<picker mode="multiSelector" value="{{startDateTimeArray}}" bindchange="onStartDateTimeChange" bindcolumnchange="onStartDateTimeColumnChange" range="{{dateTimeArray}}">
|
||||||
|
<view>{{startDateDisplay || '请选择开始时间'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text> </text>
|
||||||
|
<picker mode="multiSelector" value="{{endDateTimeArray}}" bindchange="onEndDateTimeChange" bindcolumnchange="onEndDateTimeColumnChange" range="{{dateTimeArray}}">
|
||||||
|
<view>{{endDateDisplay || '请选择结束时间'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{cardType === 4}}">
|
||||||
|
<view class="form-item">
|
||||||
|
<text>循环周期:</text>
|
||||||
|
<picker bindchange="onWeekdayPatternChange" range="{{weekdayPatterns}}" value="{{weekdayPatternIndex}}">
|
||||||
|
<view class="picker-view">{{weekdayPatterns[weekdayPatternIndex]}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item" wx:if="{{weekdayPattern === 'custom'}}">
|
||||||
|
<text>自定义:</text>
|
||||||
|
<checkbox-group bindchange="onWeekDayChange" class="weekday-group">
|
||||||
|
<label wx:for="{{['周一', '周二', '周三', '周四', '周五', '周六', '周日']}}" wx:key="index" class="weekday-item">
|
||||||
|
<checkbox value="{{index + 1}}" checked="{{weekDay[index + 1] === 1}}">{{item}}</checkbox>
|
||||||
|
</label>
|
||||||
|
</checkbox-group>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>生效日期:</text>
|
||||||
|
<picker mode="date" value="{{startDateDisplay}}" bindchange="onStartDateChange">
|
||||||
|
<view>{{startDateDisplay || '请选择开始日期'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>失效日期:</text>
|
||||||
|
<picker mode="date" value="{{endDateDisplay}}" bindchange="onEndDateChange">
|
||||||
|
<view>{{endDateDisplay || '请选择结束日期'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>生效时间:</text>
|
||||||
|
<picker mode="time" value="{{startTime}}" bindchange="onStartTimeChange">
|
||||||
|
<view>{{startTime || '请选择'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>失效时间:</text>
|
||||||
|
<picker mode="time" value="{{endTime}}" bindchange="onEndTimeChange">
|
||||||
|
<view>{{endTime || '请选择'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="params-display" wx:if="{{currentParams}}">
|
||||||
|
<view class="params-title">当前操作参数</view>
|
||||||
|
<view class="params-content">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">卡片类型:</text>
|
||||||
|
<text>{{currentParams.type}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">操作类型:</text>
|
||||||
|
<text>{{currentParams.operate}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">管理员权限:</text>
|
||||||
|
<text>{{currentParams.isAdmin}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">胁迫模式:</text>
|
||||||
|
<text>{{currentParams.isForce}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">循环模式:</text>
|
||||||
|
<text>{{currentParams.isRound}}</text>
|
||||||
|
</view>
|
||||||
|
<block wx:if="{{currentParams.weekDay && currentParams.weekDay.length}}">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">循环周期:</text>
|
||||||
|
<text>{{currentParams.weekDay}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{cardType === 2 && currentParams.displayTimeRange}}">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">期限时间:</text>
|
||||||
|
<text>{{currentParams.displayTimeRange}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{currentParams.startDate && cardType !== 1}}">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">有效期:</text>
|
||||||
|
<text>{{currentParams.startDate}} 至 {{currentParams.endDate}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{cardType !== 1}}">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">生效时间:</text>
|
||||||
|
<text>{{currentParams.startTime}} - {{currentParams.endTime}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="button-group">
|
||||||
|
<block wx:if="{{editMode}}">
|
||||||
|
<button type="primary" bind:tap="confirmEdit">确认修改</button>
|
||||||
|
<button bind:tap="cancelEdit">取消</button>
|
||||||
|
</block>
|
||||||
|
<block wx:else>
|
||||||
|
<button type="primary" bind:tap="icCardOperate" data-operate="0">添加卡片</button>
|
||||||
|
<button bind:tap="icCardOperate" data-operate="3">删除全部卡片</button>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="card-list">
|
||||||
|
<view class="list-header">
|
||||||
|
<text>卡片列表</text>
|
||||||
|
<button bind:tap="findAllCard" size="mini">刷新</button>
|
||||||
|
</view>
|
||||||
|
<view class="list-content">
|
||||||
|
<block wx:for="{{cardList}}" wx:key="cardId">
|
||||||
|
<view class="card-item {{selectedCard.cardId === item.cardId ? 'selected' : ''}}"
|
||||||
|
bind:tap="selectCard" data-card="{{item}}">
|
||||||
|
<view class="card-info">
|
||||||
|
<text>名称:{{item.cardName}}</text>
|
||||||
|
<text>类型:{{item.cardType === 1 ? '永久' : item.cardType === 2 ? '期限' : '循环'}}</text>
|
||||||
|
<text>管理员:{{item.isAdmin === 1 ? '是' : '否'}}</text>
|
||||||
|
<text>胁迫:{{item.isForce === 1 ? '是' : '否'}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-time">
|
||||||
|
<block wx:if="{{item.cardType === 2}}">
|
||||||
|
<text>{{item.startDate}} - {{item.endDate}}</text>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{item.cardType === 4}}">
|
||||||
|
<text>周期:{{item.weekDayText}}</text>
|
||||||
|
</block>
|
||||||
|
<text>{{item.startTime}} - {{item.endTime}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-actions">
|
||||||
|
<button size="mini" type="warn" bind:tap="deleteCard" data-card="{{item}}">删除</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
208
miniprogram/miniprogram/pages/card/card.wxss
Normal file
208
miniprogram/miniprogram/pages/card/card.wxss
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
.card-page {
|
||||||
|
padding: 20rpx;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-form {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item text {
|
||||||
|
width: 180rpx;
|
||||||
|
color: #333;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item input {
|
||||||
|
flex: 1;
|
||||||
|
height: 70rpx;
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item .tips {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item radio-group,
|
||||||
|
.form-item checkbox-group {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item picker {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item picker view {
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-view {
|
||||||
|
flex: 1;
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item.week-tips {
|
||||||
|
margin-top: -10rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item.week-tips text:first-child {
|
||||||
|
width: 180rpx;
|
||||||
|
color: #666;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item.week-tips .tips {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
width: auto;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pattern-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pattern-group radio {
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday-item {
|
||||||
|
margin-right: 20rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday-item checkbox {
|
||||||
|
margin-right: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #007aff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button:nth-child(2) {
|
||||||
|
background-color: #28cd41;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button:nth-child(3) {
|
||||||
|
background-color: #ff3b30;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button:nth-child(4) {
|
||||||
|
background-color: #ff9500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-list {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-item {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-item.selected {
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
border: 1px solid #1aad19;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-info {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 10rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-info text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-time {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
139
miniprogram/miniprogram/pages/configNetwork/configNetwork.js
Normal file
139
miniprogram/miniprogram/pages/configNetwork/configNetwork.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
const {
|
||||||
|
Result,
|
||||||
|
startSearchWiFi,
|
||||||
|
selectLock,
|
||||||
|
starEventOn,
|
||||||
|
connectWiFi,
|
||||||
|
starEventOff,
|
||||||
|
getLockNetworkInfo,
|
||||||
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
lock: null, // 当前选中的锁
|
||||||
|
accountInfo: {},
|
||||||
|
loading: false,
|
||||||
|
wifiList: [],
|
||||||
|
showConnectDialog: false,
|
||||||
|
connectSsid: '',
|
||||||
|
connectPassword: '',
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
starEventOn('searchWiFiResult', async (data) => {
|
||||||
|
if (data.code === 0) {
|
||||||
|
console.log("收到wifi搜索列表的事件回调", data)
|
||||||
|
this.setData({wifiList: data.wifiList || [], loading: false});
|
||||||
|
}
|
||||||
|
this.setData({loading: false});
|
||||||
|
wx.hideLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
this.searchWifi();
|
||||||
|
},
|
||||||
|
async searchWifi() {
|
||||||
|
console.log('启动搜索WiFi...');
|
||||||
|
this.setData({loading: true});
|
||||||
|
wx.showLoading({title: '正在搜索WiFi...', mask: true});
|
||||||
|
try {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
const result = await startSearchWiFi({
|
||||||
|
disconnect: false
|
||||||
|
});
|
||||||
|
console.log('searchWifi result', result);
|
||||||
|
if (result.code === 0) {
|
||||||
|
// 已经开始搜索,loading状态保持,等待事件回调结束loading
|
||||||
|
} else {
|
||||||
|
this.setData({loading: false});
|
||||||
|
wx.hideLoading();
|
||||||
|
wx.showModal({
|
||||||
|
title: '搜索失败',
|
||||||
|
content: result.message || '启动WiFi搜索失败',
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.setData({loading: false});
|
||||||
|
wx.hideLoading();
|
||||||
|
wx.showModal({
|
||||||
|
title: '异常',
|
||||||
|
content: error.message || 'WiFi搜索异常',
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onWifiItemTap(e) {
|
||||||
|
const ssid = e.currentTarget.dataset.ssid;
|
||||||
|
this.setData({
|
||||||
|
showConnectDialog: true,
|
||||||
|
connectSsid: ssid,
|
||||||
|
connectPassword: ''
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onInputSsid(e) {
|
||||||
|
this.setData({connectSsid: e.detail.value});
|
||||||
|
},
|
||||||
|
onInputPassword(e) {
|
||||||
|
this.setData({connectPassword: e.detail.value});
|
||||||
|
},
|
||||||
|
onDialogCancel() {
|
||||||
|
this.setData({showConnectDialog: false});
|
||||||
|
},
|
||||||
|
async onDialogConfirm() {
|
||||||
|
const ssid = this.data.connectSsid;
|
||||||
|
const password = this.data.connectPassword;
|
||||||
|
this.setData({loading: true});
|
||||||
|
wx.showLoading({title: '正在连接WiFi...', mask: true});
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
});
|
||||||
|
// 这里可以进行连接WiFi的逻辑
|
||||||
|
const result = await connectWiFi({
|
||||||
|
ssid: ssid,
|
||||||
|
password: password,
|
||||||
|
});
|
||||||
|
console.log('connectWiFi result', result);
|
||||||
|
if (result.code === 0) {
|
||||||
|
const networkInfo = await getLockNetworkInfo({
|
||||||
|
uid: this.data.accountInfo.uid,
|
||||||
|
deviceMac: this.data.lock.mac,
|
||||||
|
})
|
||||||
|
console.log('networkInfo', networkInfo)
|
||||||
|
}
|
||||||
|
this.setData({loading: false, showConnectDialog: false});
|
||||||
|
wx.hideLoading();
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
if (typeof starEventOff === 'function') {
|
||||||
|
starEventOff('searchWiFiResult');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"navigationBarTitleText": "配置网络"
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<view class="container">
|
||||||
|
<view class="header">配置网络</view>
|
||||||
|
<view class="content">
|
||||||
|
<view class="tip-text">
|
||||||
|
<text>• 确保搜索WiFi时锁板处于亮屏状态</text>
|
||||||
|
<text>\n</text>
|
||||||
|
<text>• 确保连接的WiFi是2.4GHz的WiFi</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="wifi-list" wx:if="{{wifiList.length}}">
|
||||||
|
<view class="wifi-item" wx:for="{{wifiList}}" wx:key="ssid" data-ssid="{{item.ssid}}" bindtap="onWifiItemTap">
|
||||||
|
<text class="ssid">{{item.ssid}}</text>
|
||||||
|
<text class="rssi">信号: {{item.rssi}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view wx:if="{{showConnectDialog}}" class="dialog-mask">
|
||||||
|
<view class="dialog-box">
|
||||||
|
<view class="dialog-title">连接WiFi</view>
|
||||||
|
<view class="dialog-content">
|
||||||
|
<input class="dialog-input" placeholder="WiFi昵称" value="{{connectSsid}}" disabled />
|
||||||
|
<input class="dialog-input" placeholder="WiFi密码" password value="{{connectPassword}}" bindinput="onInputPassword" />
|
||||||
|
</view>
|
||||||
|
<view class="dialog-actions">
|
||||||
|
<button class="dialog-btn cancel" bindtap="onDialogCancel">取消</button>
|
||||||
|
<button class="dialog-btn confirm" bindtap="onDialogConfirm">确定</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
111
miniprogram/miniprogram/pages/configNetwork/configNetwork.wxss
Normal file
111
miniprogram/miniprogram/pages/configNetwork/configNetwork.wxss
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
.container {
|
||||||
|
padding: 32rpx;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
color: #007AFF;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.wifi-list {
|
||||||
|
margin-top: 32rpx;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
}
|
||||||
|
.wifi-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16rpx 0;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
.wifi-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.ssid {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.rssi {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.loading-bar {
|
||||||
|
margin: 24rpx 0;
|
||||||
|
padding: 20rpx;
|
||||||
|
background: #fffbe6;
|
||||||
|
color: #faad14;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.dialog-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
|
background: rgba(0,0,0,0.4);
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.dialog-box {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
width: 80vw;
|
||||||
|
max-width: 600rpx;
|
||||||
|
padding: 40rpx 32rpx 24rpx 32rpx;
|
||||||
|
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.15);
|
||||||
|
}
|
||||||
|
.dialog-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.dialog-content {
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
.dialog-input {
|
||||||
|
width: 100%;
|
||||||
|
height: 80rpx;
|
||||||
|
border: 2rpx solid #eee;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.dialog-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 24rpx;
|
||||||
|
}
|
||||||
|
.dialog-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 36rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.dialog-btn.cancel {
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.dialog-btn.confirm {
|
||||||
|
background: linear-gradient(135deg, #007AFF, #40a9ff);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.tip-text {
|
||||||
|
color: #faad14;
|
||||||
|
font-size: 26rpx;
|
||||||
|
line-height: 1.8;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
628
miniprogram/miniprogram/pages/fingerprint/fingerprint.js
Normal file
628
miniprogram/miniprogram/pages/fingerprint/fingerprint.js
Normal file
@ -0,0 +1,628 @@
|
|||||||
|
const {
|
||||||
|
registerExtendedProducts,
|
||||||
|
starEventOn,
|
||||||
|
getFingerprintList,
|
||||||
|
selectLock
|
||||||
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
fingerprintId: -1,
|
||||||
|
fingerprintNumber: 0,
|
||||||
|
fingerprintName: '',
|
||||||
|
fingerprintType: 1,
|
||||||
|
isAdmin: 1,
|
||||||
|
isForce: 0,
|
||||||
|
isRound: 0,
|
||||||
|
weekDay: [], // 确保初始化为空数组
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
startTime: '00:00',
|
||||||
|
endTime: '00:00',
|
||||||
|
fingerprintList: [],
|
||||||
|
currentParams: null,
|
||||||
|
dateTimeArray: [], // 日期时间选择器数据
|
||||||
|
startDateTimeArray: [], // 开始时间数组
|
||||||
|
endDateTimeArray: [], // 结束时间数组
|
||||||
|
startDateDisplay: '', // 显示用的开始日期
|
||||||
|
endDateDisplay: '', // 显示用的结束日期
|
||||||
|
weekdayPatterns: ['工作日循环(星期一到星期五)', '周末循环(星期六日)', '每天循环'],
|
||||||
|
weekdayPatternIndex: 0,
|
||||||
|
selectedFingerprint: null, // 当前选中的指纹
|
||||||
|
editMode: false // 编辑模式标识
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
starEventOn('registerFingerprintConfirm', async (data) => {
|
||||||
|
if (data.code === 0) {
|
||||||
|
this.setData({
|
||||||
|
fingerprintId: data.data.fingerprintId,
|
||||||
|
fingerprintNumber: data.data.fingerprintNumber
|
||||||
|
})
|
||||||
|
console.log('收到指纹确认事件', data, this.data.fingerprintId, this.data.fingerprintNumber);
|
||||||
|
// 添加成功后自动刷新列表
|
||||||
|
await this.findAllFingerprint();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化时间
|
||||||
|
const now = new Date();
|
||||||
|
const nextHour = new Date(now.getTime() + 60 * 60 * 1000);
|
||||||
|
const nowArr = [
|
||||||
|
now.getFullYear(),
|
||||||
|
now.getMonth(),
|
||||||
|
now.getDate(),
|
||||||
|
now.getHours(),
|
||||||
|
now.getMinutes()
|
||||||
|
];
|
||||||
|
const nextArr = [
|
||||||
|
nextHour.getFullYear(),
|
||||||
|
nextHour.getMonth(),
|
||||||
|
nextHour.getDate(),
|
||||||
|
nextHour.getHours(),
|
||||||
|
nextHour.getMinutes()
|
||||||
|
];
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
startTime: now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0'),
|
||||||
|
endTime: nextHour.getHours().toString().padStart(2, '0') + ':' + nextHour.getMinutes().toString().padStart(2, '0'),
|
||||||
|
startDateTimeArray: nowArr,
|
||||||
|
endDateTimeArray: nextArr,
|
||||||
|
startDate: now.getTime(),
|
||||||
|
endDate: nextHour.getTime(),
|
||||||
|
startDateDisplay: this.formatDateTime(now),
|
||||||
|
endDateDisplay: this.formatDateTime(nextHour)
|
||||||
|
});
|
||||||
|
|
||||||
|
starEventOn('registerFingerprintProcess', async (data) => {
|
||||||
|
console.log('收到指纹过程事件', data);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.initDateTimeArray();
|
||||||
|
},
|
||||||
|
|
||||||
|
async fingerprintOperate(e) {
|
||||||
|
const operate = e.currentTarget.dataset.operate;
|
||||||
|
const fingerprintData = e.currentTarget.dataset.fingerprint;
|
||||||
|
|
||||||
|
if (operate === 'edit') {
|
||||||
|
// 点击修改按钮,将数据同步到表单
|
||||||
|
if (fingerprintData) {
|
||||||
|
const weekDay = Array.isArray(fingerprintData.weekDay) ? fingerprintData.weekDay : [];
|
||||||
|
// 判断周期模式
|
||||||
|
let weekdayPatternIndex = 0;
|
||||||
|
if (weekDay.length > 0) {
|
||||||
|
const weekDayStr = weekDay.sort().join(',');
|
||||||
|
if (weekDayStr === '1,2,3,4,5') {
|
||||||
|
weekdayPatternIndex = 0; // 工作日
|
||||||
|
} else if (weekDayStr === '0,6') {
|
||||||
|
weekdayPatternIndex = 1; // 周末
|
||||||
|
} else if (weekDayStr === '0,1,2,3,4,5,6') {
|
||||||
|
weekdayPatternIndex = 2; // 每天
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理日期和时间显示
|
||||||
|
const startDate = fingerprintData.startDate ? new Date(fingerprintData.startDate) : null;
|
||||||
|
const endDate = fingerprintData.endDate ? new Date(fingerprintData.endDate) : null;
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
editMode: true, // 使用 editMode 替代 isEditing
|
||||||
|
fingerprintId: fingerprintData.fingerprintId,
|
||||||
|
fingerprintNumber: fingerprintData.fingerprintNumber,
|
||||||
|
fingerprintName: fingerprintData.fingerprintName,
|
||||||
|
fingerprintType: fingerprintData.fingerprintType,
|
||||||
|
isAdmin: fingerprintData.fingerRight,
|
||||||
|
isForce: fingerprintData.isCoerced,
|
||||||
|
isRound: weekDay.length > 0 ? 1 : 0,
|
||||||
|
weekDay: weekDay,
|
||||||
|
weekdayPatternIndex: weekdayPatternIndex,
|
||||||
|
startDate: fingerprintData.startDate || 0,
|
||||||
|
endDate: fingerprintData.endDate || 0,
|
||||||
|
startDateDisplay: startDate ? this.formatDateTime(startDate) : '',
|
||||||
|
endDateDisplay: endDate ? this.formatDateTime(endDate) : '',
|
||||||
|
startTime: fingerprintData.startTime || '00:00',
|
||||||
|
endTime: fingerprintData.endTime || '00:00'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行实际的操作
|
||||||
|
await this._fingerprintOperate(Number(operate));
|
||||||
|
},
|
||||||
|
|
||||||
|
async _fingerprintOperate(operate) {
|
||||||
|
// 修改验证逻辑,移除单次类型相关的判断
|
||||||
|
if (this.data.fingerprintType === 2) {
|
||||||
|
if (!this.data.startDateDisplay || !this.data.endDateDisplay) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请选择期限时间',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 添加时间范围验证
|
||||||
|
if (this.data.startDate >= this.data.endDate) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '结束时间必须大于开始时间',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.data.fingerprintType === 4) {
|
||||||
|
if (!this.data.weekDay || !this.data.weekDay.length) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请选择循环周期',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.data.startDate || !this.data.endDate) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请选择日期范围',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.data.startTime || !this.data.endTime) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请选择时间范围',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wx.showLoading({
|
||||||
|
title: '处理中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const app = getApp();
|
||||||
|
const { accountInfo } = app.globalData;
|
||||||
|
const { lock } = app.globalData;
|
||||||
|
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: accountInfo,
|
||||||
|
lockId: lock.lockId
|
||||||
|
});
|
||||||
|
|
||||||
|
let finalStartDate = this.data.startDate;
|
||||||
|
let finalEndDate = this.data.endDate;
|
||||||
|
|
||||||
|
// 处理循环指纹的时间戳
|
||||||
|
if (this.data.fingerprintType === 4) {
|
||||||
|
if (this.data.startDate && this.data.startTime) {
|
||||||
|
const [startHours, startMinutes] = this.data.startTime.split(':');
|
||||||
|
const startDate = new Date(this.data.startDate);
|
||||||
|
startDate.setHours(parseInt(startHours), parseInt(startMinutes), 0, 0);
|
||||||
|
finalStartDate = startDate.getTime();
|
||||||
|
}
|
||||||
|
if (this.data.endDate && this.data.endTime) {
|
||||||
|
const [endHours, endMinutes] = this.data.endTime.split(':');
|
||||||
|
const endDate = new Date(this.data.endDate);
|
||||||
|
endDate.setHours(parseInt(endHours), parseInt(endMinutes), 59, 999);
|
||||||
|
finalEndDate = endDate.getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据不同类型构造不同的参数
|
||||||
|
const baseParams = {
|
||||||
|
type: 'fingerprint',
|
||||||
|
keyId: String(lock.keyId),
|
||||||
|
uid: String(accountInfo.uid),
|
||||||
|
userCountLimit: 0xFFFF,
|
||||||
|
operate: operate,
|
||||||
|
isAdmin: this.data.isAdmin,
|
||||||
|
isForce: this.data.isForce,
|
||||||
|
fingerprintId: this.data.fingerprintId,
|
||||||
|
fingerprintNumber: this.data.fingerprintNumber,
|
||||||
|
fingerprintName: this.data.fingerprintName,
|
||||||
|
fingerprintType: this.data.fingerprintType,
|
||||||
|
fingerprintUserNo: 999
|
||||||
|
};
|
||||||
|
|
||||||
|
let timeParams = {};
|
||||||
|
if (this.data.fingerprintType === 1) {
|
||||||
|
// 永久类型不需要时间参数
|
||||||
|
timeParams = {
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
isRound: 0,
|
||||||
|
weekDay: []
|
||||||
|
};
|
||||||
|
} else if (this.data.fingerprintType === 2) {
|
||||||
|
// 期限类型
|
||||||
|
timeParams = {
|
||||||
|
startDate: this.data.startDate,
|
||||||
|
endDate: this.data.endDate,
|
||||||
|
isRound: 0,
|
||||||
|
weekDay: []
|
||||||
|
};
|
||||||
|
// 添加显示用的时间范围
|
||||||
|
const startDateTime = new Date(this.data.startDate);
|
||||||
|
const endDateTime = new Date(this.data.endDate);
|
||||||
|
timeParams.displayTimeRange = `${this.formatDateTime(startDateTime, 'params')}-${this.formatDateTime(endDateTime, 'params')}`;
|
||||||
|
} else if (this.data.fingerprintType === 4) {
|
||||||
|
// 循环类型
|
||||||
|
timeParams = {
|
||||||
|
startDate: finalStartDate,
|
||||||
|
endDate: finalEndDate,
|
||||||
|
startTime: this.data.startTime,
|
||||||
|
endTime: this.data.endTime,
|
||||||
|
isRound: this.data.isRound,
|
||||||
|
weekDay: this.data.weekDay
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const parms = {
|
||||||
|
...baseParams,
|
||||||
|
...timeParams
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
currentParams: parms
|
||||||
|
});
|
||||||
|
|
||||||
|
const registerExtendedProductsResult = await registerExtendedProducts(parms)
|
||||||
|
console.log('registerExtendedProductsResult', registerExtendedProductsResult);
|
||||||
|
|
||||||
|
if (registerExtendedProductsResult.code === 0) {
|
||||||
|
// 操作成功后清空表单
|
||||||
|
this.setData({
|
||||||
|
editMode: false, // 使用 editMode 替代 isEditing
|
||||||
|
fingerprintName: '',
|
||||||
|
fingerprintType: 1,
|
||||||
|
isAdmin: 1,
|
||||||
|
isForce: 0,
|
||||||
|
isRound: 0,
|
||||||
|
weekDay: [],
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
startTime: '00:00',
|
||||||
|
endTime: '00:00'
|
||||||
|
});
|
||||||
|
// 刷新列表
|
||||||
|
await this.findAllFingerprint();
|
||||||
|
wx.showToast({
|
||||||
|
title: '操作成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
wx.showToast({
|
||||||
|
title: '操作失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('操作失败:', error);
|
||||||
|
wx.showToast({
|
||||||
|
title: '操作失败',
|
||||||
|
icon: 'error'
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async findAllFingerprint() {
|
||||||
|
const app = getApp();
|
||||||
|
const { lock } = app.globalData;
|
||||||
|
const result = await getFingerprintList({lockId: lock.lockId})
|
||||||
|
console.log('findAllFingerprint', result)
|
||||||
|
|
||||||
|
const processedList = (result.data.list || []).map(fingerprint => {
|
||||||
|
// 转换周期显示,与卡片保持一致
|
||||||
|
const weekDayText = fingerprint.weekDay ? fingerprint.weekDay.map(day => {
|
||||||
|
if (day === 7 || day === 0) return '周日';
|
||||||
|
return `周${['一','二','三','四','五','六'][day - 1]}`;
|
||||||
|
}).join(', ') : '';
|
||||||
|
|
||||||
|
// 处理时间显示
|
||||||
|
const startDate = new Date(Number(fingerprint.startDate));
|
||||||
|
const endDate = new Date(Number(fingerprint.endDate));
|
||||||
|
const startDateDisplay = this.formatDateTime(startDate);
|
||||||
|
const endDateDisplay = this.formatDateTime(endDate);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...fingerprint,
|
||||||
|
isAdmin: fingerprint.fingerRight === 1 ? 1 : 0,
|
||||||
|
isForce: fingerprint.isCoerced === 1 ? 1 : 0,
|
||||||
|
isRound: (fingerprint.weekDay && fingerprint.weekDay.length > 0) ? 1 : 0,
|
||||||
|
weekDayText,
|
||||||
|
startDateDisplay,
|
||||||
|
endDateDisplay
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
fingerprintList: processedList
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onFingerprintTypeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
fingerprintType: Number(e.detail.value)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdminChange(e) {
|
||||||
|
this.setData({
|
||||||
|
isAdmin: e.detail.value ? 1 : 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onForceChange(e) {
|
||||||
|
this.setData({
|
||||||
|
isForce: e.detail.value ? 1 : 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onStartDateChange(e) {
|
||||||
|
const dateStr = e.detail.value; // 格式为 "YYYY-MM-DD"
|
||||||
|
const date = new Date(dateStr);
|
||||||
|
this.setData({
|
||||||
|
startDate: date.getTime(),
|
||||||
|
startDateDisplay: dateStr // 直接使用选择器返回的日期字符串
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndDateChange(e) {
|
||||||
|
const dateStr = e.detail.value; // 格式为 "YYYY-MM-DD"
|
||||||
|
const date = new Date(dateStr);
|
||||||
|
this.setData({
|
||||||
|
endDate: date.getTime(),
|
||||||
|
endDateDisplay: dateStr // 直接使用选择器返回的日期字符串
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onWeekDayChange(e) {
|
||||||
|
const selectedDays = e.detail.value;
|
||||||
|
this.setData({
|
||||||
|
weekDay: selectedDays.map(Number),
|
||||||
|
isRound: selectedDays.length > 0 ? 1 : 0
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onWeekdayPatternChange(e) {
|
||||||
|
const index = Number(e.detail.value);
|
||||||
|
let weekDay = [];
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case 0: // 工作日循环
|
||||||
|
weekDay = [2, 3, 4, 5, 6]; // 修改为与卡片一致的周期值
|
||||||
|
break;
|
||||||
|
case 1: // 周末循环
|
||||||
|
weekDay = [1, 7]; // 修改为与卡片一致的周期值
|
||||||
|
break;
|
||||||
|
case 2: // 每天循环
|
||||||
|
weekDay = [1, 2, 3, 4, 5, 6, 7]; // 修改为与卡片一致的周期值
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
weekdayPatternIndex: index,
|
||||||
|
weekDay,
|
||||||
|
isRound: 1
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onStartTimeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
startTime: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndTimeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
endTime: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 初始化日期时间选择器数据
|
||||||
|
initDateTimeArray() {
|
||||||
|
const date = new Date();
|
||||||
|
const years = [];
|
||||||
|
const months = [];
|
||||||
|
const days = [];
|
||||||
|
const hours = [];
|
||||||
|
const minutes = [];
|
||||||
|
|
||||||
|
for (let i = date.getFullYear(); i <= date.getFullYear() + 10; i++) {
|
||||||
|
years.push(i + '年');
|
||||||
|
}
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
months.push(i + '月');
|
||||||
|
}
|
||||||
|
for (let i = 1; i <= 31; i++) {
|
||||||
|
days.push(i + '日');
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 24; i++) {
|
||||||
|
hours.push(i + '时');
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
minutes.push(i + '分');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
dateTimeArray: [years, months, days, hours, minutes]
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 日期时间选择器列变化
|
||||||
|
onStartDateTimeColumnChange(e) {
|
||||||
|
const { column, value } = e.detail;
|
||||||
|
const data = {
|
||||||
|
dateTimeArray: this.data.dateTimeArray,
|
||||||
|
startDateTimeArray: this.data.startDateTimeArray
|
||||||
|
};
|
||||||
|
data.startDateTimeArray[column] = value;
|
||||||
|
this.setData(data);
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndDateTimeColumnChange(e) {
|
||||||
|
const { column, value } = e.detail;
|
||||||
|
const data = {
|
||||||
|
dateTimeArray: this.data.dateTimeArray,
|
||||||
|
endDateTimeArray: this.data.endDateTimeArray
|
||||||
|
};
|
||||||
|
data.endDateTimeArray[column] = value;
|
||||||
|
this.setData(data);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 日期时间确认选择
|
||||||
|
onStartDateTimeChange(e) {
|
||||||
|
const val = e.detail.value;
|
||||||
|
const dateTimeArray = this.data.dateTimeArray;
|
||||||
|
|
||||||
|
const year = parseInt(dateTimeArray[0][val[0]]);
|
||||||
|
const month = parseInt(dateTimeArray[1][val[1]]) - 1;
|
||||||
|
const day = parseInt(dateTimeArray[2][val[2]]);
|
||||||
|
const hour = parseInt(dateTimeArray[3][val[3]]);
|
||||||
|
const minute = parseInt(dateTimeArray[4][val[4]]);
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(year);
|
||||||
|
date.setMonth(month);
|
||||||
|
date.setDate(day);
|
||||||
|
date.setHours(hour);
|
||||||
|
date.setMinutes(minute);
|
||||||
|
date.setSeconds(0);
|
||||||
|
date.setMilliseconds(0);
|
||||||
|
|
||||||
|
const startDate = date.getTime();
|
||||||
|
const startDateDisplay = this.formatDateTime(date);
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
startDate,
|
||||||
|
startDateDisplay,
|
||||||
|
startDateTimeArray: val
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onEndDateTimeChange(e) {
|
||||||
|
const val = e.detail.value;
|
||||||
|
const dateTimeArray = this.data.dateTimeArray;
|
||||||
|
|
||||||
|
const year = parseInt(dateTimeArray[0][val[0]]);
|
||||||
|
const month = parseInt(dateTimeArray[1][val[1]]) - 1;
|
||||||
|
const day = parseInt(dateTimeArray[2][val[2]]);
|
||||||
|
const hour = parseInt(dateTimeArray[3][val[3]]);
|
||||||
|
const minute = parseInt(dateTimeArray[4][val[4]]);
|
||||||
|
|
||||||
|
const date = new Date();
|
||||||
|
date.setFullYear(year);
|
||||||
|
date.setMonth(month);
|
||||||
|
date.setDate(day);
|
||||||
|
date.setHours(hour);
|
||||||
|
date.setMinutes(minute);
|
||||||
|
date.setSeconds(59);
|
||||||
|
date.setMilliseconds(999);
|
||||||
|
|
||||||
|
const endDate = date.getTime();
|
||||||
|
const endDateDisplay = this.formatDateTime(date);
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
endDate,
|
||||||
|
endDateDisplay,
|
||||||
|
endDateTimeArray: val
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 取消编辑
|
||||||
|
cancelEdit() {
|
||||||
|
this.setData({
|
||||||
|
editMode: false,
|
||||||
|
selectedFingerprint: null,
|
||||||
|
fingerprintName: '',
|
||||||
|
fingerprintType: 1,
|
||||||
|
isAdmin: 1,
|
||||||
|
isForce: 0,
|
||||||
|
isRound: 0,
|
||||||
|
weekDay: [],
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
startTime: '00:00',
|
||||||
|
endTime: '00:00'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 确认编辑
|
||||||
|
async confirmEdit() {
|
||||||
|
await this._fingerprintOperate(1); // 1 表示修改操作
|
||||||
|
},
|
||||||
|
|
||||||
|
formatDateTime(date) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||||
|
const day = date.getDate().toString().padStart(2, '0');
|
||||||
|
const hour = date.getHours().toString().padStart(2, '0');
|
||||||
|
const minute = date.getMinutes().toString().padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day} ${hour}:${minute}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 选择指纹记录
|
||||||
|
selectFingerprint(e) {
|
||||||
|
const fingerprintData = e.currentTarget.dataset.fingerprint;
|
||||||
|
if (fingerprintData) {
|
||||||
|
let weekDay = [];
|
||||||
|
let weekdayPatternIndex = 0;
|
||||||
|
|
||||||
|
if (fingerprintData.weekDay && Array.isArray(fingerprintData.weekDay)) {
|
||||||
|
weekDay = fingerprintData.weekDay.map(day => day === 7 ? 7 : day); // 确保周日使用7
|
||||||
|
weekDay.sort((a, b) => a - b);
|
||||||
|
|
||||||
|
const weekDayStr = weekDay.join(',');
|
||||||
|
if (weekDayStr === '2,3,4,5,6') {
|
||||||
|
weekdayPatternIndex = 0; // 工作日
|
||||||
|
} else if (weekDayStr === '1,7') {
|
||||||
|
weekdayPatternIndex = 1; // 周末
|
||||||
|
} else if (weekDayStr === '1,2,3,4,5,6,7') {
|
||||||
|
weekdayPatternIndex = 2; // 每天
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理时间戳和显示
|
||||||
|
const startDateTime = new Date(Number(fingerprintData.startDate) || 0);
|
||||||
|
const endDateTime = new Date(Number(fingerprintData.endDate) || 0);
|
||||||
|
|
||||||
|
// 日期和时间分开处理
|
||||||
|
let startDate = startDateTime;
|
||||||
|
let endDate = endDateTime;
|
||||||
|
let startTime = '00:00';
|
||||||
|
let endTime = '00:00';
|
||||||
|
|
||||||
|
if (fingerprintData.fingerprintType === 4) {
|
||||||
|
startTime = `${startDateTime.getHours().toString().padStart(2, '0')}:${startDateTime.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
endTime = `${endDateTime.getHours().toString().padStart(2, '0')}:${endDateTime.getMinutes().toString().padStart(2, '0')}`;
|
||||||
|
// 重置日期部分的时间为0点
|
||||||
|
startDate.setHours(0, 0, 0, 0);
|
||||||
|
endDate.setHours(23, 59, 59, 999);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setData({
|
||||||
|
fingerprintId: fingerprintData.fingerprintId,
|
||||||
|
fingerprintNumber: fingerprintData.fingerprintNumber || 0,
|
||||||
|
fingerprintName: fingerprintData.fingerprintName,
|
||||||
|
fingerprintType: fingerprintData.fingerprintType,
|
||||||
|
isAdmin: fingerprintData.isAdmin || (fingerprintData.fingerRight === 1 ? 1 : 0),
|
||||||
|
isForce: fingerprintData.isForce || (fingerprintData.isCoerced === 1 ? 1 : 0),
|
||||||
|
isRound: weekDay.length > 0 ? 1 : 0,
|
||||||
|
weekDay,
|
||||||
|
weekdayPatternIndex,
|
||||||
|
startDate: startDate.getTime(),
|
||||||
|
endDate: endDate.getTime(),
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
startDateDisplay: this.formatDateTime(startDateTime),
|
||||||
|
endDateDisplay: this.formatDateTime(endDateTime),
|
||||||
|
editMode: true,
|
||||||
|
selectedFingerprint: fingerprintData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
163
miniprogram/miniprogram/pages/fingerprint/fingerprint.wxml
Normal file
163
miniprogram/miniprogram/pages/fingerprint/fingerprint.wxml
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
<view class="fingerprint-page">
|
||||||
|
<view class="fingerprint-form">
|
||||||
|
<view class="form-item">
|
||||||
|
<text>指纹名称:</text>
|
||||||
|
<input type="text" model:value="{{fingerprintName}}" placeholder="请输入指纹名称"/>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>指纹类型:</text>
|
||||||
|
<radio-group bindchange="onFingerprintTypeChange">
|
||||||
|
<radio value="1" checked="{{fingerprintType === 1}}">永久</radio>
|
||||||
|
<radio value="2" checked="{{fingerprintType === 2}}">期限</radio>
|
||||||
|
<radio value="4" checked="{{fingerprintType === 4}}">循环</radio>
|
||||||
|
</radio-group>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>管理员:</text>
|
||||||
|
<switch checked="{{isAdmin === 1}}" bindchange="onAdminChange"/>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>胁迫模式:</text>
|
||||||
|
<switch checked="{{isForce === 1}}" bindchange="onForceChange"/>
|
||||||
|
</view>
|
||||||
|
<block wx:if="{{fingerprintType === 2}}">
|
||||||
|
<view class="form-item">
|
||||||
|
<text>期限时间:</text>
|
||||||
|
<picker mode="multiSelector" value="{{startDateTimeArray}}" bindchange="onStartDateTimeChange" bindcolumnchange="onStartDateTimeColumnChange" range="{{dateTimeArray}}">
|
||||||
|
<view>{{startDateDisplay || '请选择开始时间'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text> </text>
|
||||||
|
<picker mode="multiSelector" value="{{endDateTimeArray}}" bindchange="onEndDateTimeChange" bindcolumnchange="onEndDateTimeColumnChange" range="{{dateTimeArray}}">
|
||||||
|
<view>{{endDateDisplay || '请选择结束时间'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{fingerprintType === 4}}">
|
||||||
|
<view class="form-item">
|
||||||
|
<text>循环周期:</text>
|
||||||
|
<picker bindchange="onWeekdayPatternChange" range="{{weekdayPatterns}}" value="{{weekdayPatternIndex}}">
|
||||||
|
<view class="picker-view">{{weekdayPatterns[weekdayPatternIndex]}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>生效日期:</text>
|
||||||
|
<picker mode="date" value="{{startDateDisplay}}" bindchange="onStartDateChange">
|
||||||
|
<view>{{startDateDisplay || '请选择开始日期'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>失效日期:</text>
|
||||||
|
<picker mode="date" value="{{endDateDisplay}}" bindchange="onEndDateChange">
|
||||||
|
<view>{{endDateDisplay || '请选择结束日期'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>生效时间:</text>
|
||||||
|
<picker mode="time" value="{{startTime}}" bindchange="onStartTimeChange">
|
||||||
|
<view>{{startTime}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text>失效时间:</text>
|
||||||
|
<picker mode="time" value="{{endTime}}" bindchange="onEndTimeChange">
|
||||||
|
<view>{{endTime}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="params-display" wx:if="{{currentParams}}">
|
||||||
|
<view class="params-title">当前操作参数</view>
|
||||||
|
<view class="params-content">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">指纹类型:</text>
|
||||||
|
<text>{{currentParams.type}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">操作类型:</text>
|
||||||
|
<text>{{currentParams.operate}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">管理员权限:</text>
|
||||||
|
<text>{{currentParams.isAdmin}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">胁迫模式:</text>
|
||||||
|
<text>{{currentParams.isForce}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">循环模式:</text>
|
||||||
|
<text>{{currentParams.isRound}}</text>
|
||||||
|
</view>
|
||||||
|
<block wx:if="{{currentParams.weekDay && currentParams.weekDay.length}}">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">循环周期:</text>
|
||||||
|
<text>{{currentParams.weekDay}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{fingerprintType === 2 && currentParams.displayTimeRange}}">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">期限时间:</text>
|
||||||
|
<text>{{currentParams.displayTimeRange}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{fingerprintType !== 1}}">
|
||||||
|
<block wx:if="{{currentParams.startDate}}">
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">有效期:</text>
|
||||||
|
<text>{{currentParams.startDate}} 至 {{currentParams.endDate}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<view class="param-item">
|
||||||
|
<text class="param-label">生效时间:</text>
|
||||||
|
<text>{{currentParams.startTime}} - {{currentParams.endTime}}</text>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="button-group">
|
||||||
|
<block wx:if="{{!editMode}}">
|
||||||
|
<button bind:tap="fingerprintOperate" data-operate="0">添加指纹</button>
|
||||||
|
<button bind:tap="fingerprintOperate" data-operate="3">删除全部指纹</button>
|
||||||
|
</block>
|
||||||
|
<block wx:else>
|
||||||
|
<button bind:tap="fingerprintOperate" data-operate="1">确认修改</button>
|
||||||
|
<button bind:tap="cancelEdit">取消修改</button>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="fingerprint-list">
|
||||||
|
<view class="list-header">
|
||||||
|
<text>指纹列表</text>
|
||||||
|
<button bind:tap="findAllFingerprint" size="mini">刷新</button>
|
||||||
|
</view>
|
||||||
|
<view class="list-content">
|
||||||
|
<block wx:for="{{fingerprintList}}" wx:key="fingerprintId">
|
||||||
|
<view class="fingerprint-item {{selectedFingerprint.fingerprintId === item.fingerprintId ? 'selected' : ''}}"
|
||||||
|
bind:tap="selectFingerprint" data-fingerprint="{{item}}">
|
||||||
|
<view class="fingerprint-info">
|
||||||
|
<text>名称:{{item.fingerprintName}}</text>
|
||||||
|
<text>类型:{{item.fingerprintType === 1 ? '永久' : item.fingerprintType === 2 ? '期限' : '循环'}}</text>
|
||||||
|
<text>管理员:{{item.isAdmin === 1 ? '是' : '否'}}</text>
|
||||||
|
<text>胁迫:{{item.isForce === 1 ? '是' : '否'}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="fingerprint-time">
|
||||||
|
<block wx:if="{{item.fingerprintType === 2}}">
|
||||||
|
<text>{{item.startDateDisplay}} - {{item.endDateDisplay}}</text>
|
||||||
|
</block>
|
||||||
|
<block wx:if="{{item.fingerprintType === 4}}">
|
||||||
|
<text>周期:{{item.weekDayText}}</text>
|
||||||
|
</block>
|
||||||
|
<text>{{item.startTime}} - {{item.endTime}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="fingerprint-actions">
|
||||||
|
<button size="mini" bind:tap="fingerprintOperate" data-operate="2" data-fingerprint="{{item}}">删除</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
156
miniprogram/miniprogram/pages/fingerprint/fingerprint.wxss
Normal file
156
miniprogram/miniprogram/pages/fingerprint/fingerprint.wxss
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
.fingerprint-page {
|
||||||
|
padding: 20rpx;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-form {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item text {
|
||||||
|
width: 180rpx;
|
||||||
|
color: #333;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item input {
|
||||||
|
flex: 1;
|
||||||
|
height: 70rpx;
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item radio-group,
|
||||||
|
.form-item checkbox-group {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item picker {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item picker view {
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-view {
|
||||||
|
flex: 1;
|
||||||
|
height: 70rpx;
|
||||||
|
line-height: 70rpx;
|
||||||
|
border: 1rpx solid #ddd;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weekday-item {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 20rpx;
|
||||||
|
margin: 30rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button {
|
||||||
|
margin: 0;
|
||||||
|
background-color: #007aff;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button:nth-child(2) {
|
||||||
|
background-color: #28cd41;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button:nth-child(3) {
|
||||||
|
background-color: #ff3b30;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group button:nth-child(4) {
|
||||||
|
background-color: #ff9500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-list {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
border-bottom: 1rpx solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-header text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-item {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-item.selected {
|
||||||
|
background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
border: 1px solid #1aad19;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-info {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 10rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-info text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fingerprint-time {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
@ -9,239 +9,111 @@ const {
|
|||||||
stopSearchDevice,
|
stopSearchDevice,
|
||||||
selectLock,
|
selectLock,
|
||||||
getLockSupportFeatures,
|
getLockSupportFeatures,
|
||||||
getOfflinePassword,
|
updateAdminPassword,
|
||||||
registerExtendedProducts,
|
updateSupportFunctionsWithParams,
|
||||||
starEventOn,
|
remoteUnLock,
|
||||||
starEventEmit,
|
readSupportFunctions,
|
||||||
getFingerprintList,
|
getLockList,
|
||||||
getIcCardList
|
|
||||||
} = requirePlugin('starCloud')
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
Page({
|
Page({
|
||||||
data: {
|
data: {
|
||||||
list: [],
|
|
||||||
accountInfo: {},
|
accountInfo: {},
|
||||||
lock: null,
|
deviceType: 'lock', // 默认选择锁
|
||||||
cardId: -1,
|
retryCount: 0,
|
||||||
cardNumber: 0,
|
maxRetries: 3
|
||||||
fingerprintId: -1,
|
|
||||||
fingerprintNumber: 0,
|
|
||||||
eventChannel: null
|
|
||||||
},
|
},
|
||||||
async onLoad() {
|
|
||||||
init({
|
onLoad() {
|
||||||
clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
|
this.checkAccountInfo();
|
||||||
clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
|
},
|
||||||
env: 'SKY',
|
|
||||||
isReportLog: true,
|
// 检查账户信息
|
||||||
accounts: []
|
checkAccountInfo() {
|
||||||
})
|
const app = getApp();
|
||||||
const result = await register()
|
console.log('检查账户信息:', app.globalData.accountInfo);
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
this.setData({
|
// 修正字段检查
|
||||||
accountInfo: result.data
|
if (app.globalData.accountInfo && app.globalData.accountInfo.username) {
|
||||||
})
|
const accountInfo = {
|
||||||
init({
|
username: app.globalData.accountInfo.username,
|
||||||
clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
|
password: app.globalData.accountInfo.password,
|
||||||
clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
|
uid: app.globalData.accountInfo.uid
|
||||||
env: 'SKY',
|
};
|
||||||
isReportLog: true,
|
|
||||||
accounts: [this.data.accountInfo]
|
this.setData({ accountInfo });
|
||||||
})
|
console.log('设置账户信息成功:', this.data.accountInfo);
|
||||||
console.log('初始化成功:', this.data.accountInfo)
|
return true;
|
||||||
}
|
} else {
|
||||||
starEventOn('registerFingerprintConfirm', async (data) => {
|
if (this.data.retryCount < this.data.maxRetries) {
|
||||||
if (data.code === 0) {
|
wx.showLoading({
|
||||||
this.fingerprintId = data.data.fingerprintId
|
title: '正在初始化...'
|
||||||
this.fingerprintNumber = data.data.fingerprintNumber
|
});
|
||||||
console.log('收到指纹确认事件', data, this.fingerprintId, this.fingerprintNumber);
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
starEventOn('registerCardConfirm', async (data) => {
|
|
||||||
if (data.code === 0) {
|
|
||||||
this.cardId = data.data.cardId
|
|
||||||
this.cardNumber = data.data.cardNumber
|
|
||||||
console.log('收到卡片确认事件', data, this.cardId, this.cardNumber);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
starEventOn('registerFingerprintProcess', async (data) => {
|
|
||||||
console.log('收到指纹过程事件', data);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 搜索设备
|
|
||||||
searchDevice() {
|
|
||||||
searchDevice(this.searchDeviceCallback)
|
|
||||||
},
|
|
||||||
// 搜索设备回调
|
|
||||||
searchDeviceCallback(result) {
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
this.setData({
|
|
||||||
list: result.data.list
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 绑定设备
|
|
||||||
bindDevice(e) {
|
// 切换设备类型
|
||||||
const {device} = e.currentTarget.dataset
|
onTypeChange(e) {
|
||||||
wx.showModal({
|
this.setData({
|
||||||
title: '提示',
|
deviceType: e.detail.value
|
||||||
content: `确定绑定${device.name}吗?`,
|
});
|
||||||
success: async (res) => {
|
},
|
||||||
if (res.confirm) {
|
|
||||||
const result = await bindDevice({
|
// 进入设备页面
|
||||||
accountInfo: this.data.accountInfo,
|
enterDevice() {
|
||||||
name: device.name,
|
console.log('当前账户信息:', this.data.accountInfo);
|
||||||
})
|
if (!this.data.accountInfo || !this.data.accountInfo.username) {
|
||||||
if (result.code === Result.Success.code) {
|
// 再次尝试获取账户信息
|
||||||
stopSearchDevice()
|
if (this.checkAccountInfo()) {
|
||||||
this.setData({
|
this.navigateToDevicePage();
|
||||||
lock: result.data.lock
|
} else {
|
||||||
})
|
wx.showToast({
|
||||||
wx.showToast({
|
title: '账户信息未准备好',
|
||||||
title: '绑定成功',
|
icon: 'none'
|
||||||
icon: 'none',
|
});
|
||||||
})
|
}
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.navigateToDevicePage();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 添加导航方法
|
||||||
|
navigateToDevicePage() {
|
||||||
|
if (this.data.deviceType === 'lock') {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/lock/lock',
|
||||||
|
success: (res) => {
|
||||||
|
// 确保传递完整的账户信息
|
||||||
|
res.eventChannel.emit('acceptDataFromOpenerPage', {
|
||||||
|
accountInfo: this.data.accountInfo
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
})
|
} else {
|
||||||
},
|
|
||||||
// 开门
|
|
||||||
async openDoor() {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
})
|
|
||||||
const result = await openDoor({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
disconnect: true,
|
|
||||||
type: 'open'
|
|
||||||
})
|
|
||||||
console.log('开门结果', result)
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
wx.showToast({
|
wx.showToast({
|
||||||
title: '开门成功',
|
title: '网关功能开发中',
|
||||||
icon: 'none',
|
icon: 'none'
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
// 删除锁
|
|
||||||
async deleteLock() {
|
|
||||||
await selectLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
})
|
|
||||||
const result = await deleteLock({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
})
|
|
||||||
console.log('删除结果', result)
|
|
||||||
if (result.code === Result.Success.code) {
|
|
||||||
this.setData({
|
|
||||||
lock: null
|
|
||||||
})
|
|
||||||
wx.showToast({
|
|
||||||
title: '删除成功',
|
|
||||||
icon: 'none',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 获取锁支持项
|
|
||||||
async getLockSupportFeatures() {
|
|
||||||
const result = await getLockSupportFeatures({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
lockId: this.data.lock.lockId
|
|
||||||
})
|
|
||||||
console.log('锁支持项', result)
|
|
||||||
},
|
|
||||||
// 获取锁离线密码
|
|
||||||
async getOfflinePassword() {
|
|
||||||
const result = await getOfflinePassword({
|
|
||||||
accountInfo: this.data.accountInfo,
|
|
||||||
password: {
|
|
||||||
lockId: this.data.lock.lockId,
|
|
||||||
keyboardPwdName: `单次密码${new Date().getTime()}`,
|
|
||||||
keyboardPwdType: 1,
|
|
||||||
isCoerced: 2,
|
|
||||||
startDate: 0,
|
|
||||||
endDate: 0,
|
|
||||||
hoursStart: 0,
|
|
||||||
hoursEnd: 0,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
console.log('锁离线密码', result)
|
|
||||||
},
|
|
||||||
// ...其他代码
|
|
||||||
icCardOperate(e) {
|
|
||||||
const operate = e.currentTarget.dataset.operate;
|
|
||||||
this._icCardOperate(Number(operate)); // 调用实际的逻辑函数
|
|
||||||
},
|
|
||||||
async _icCardOperate(operate) {
|
|
||||||
console.log('this.data', this.data)
|
|
||||||
const parms = {
|
|
||||||
type: 'card',
|
|
||||||
keyId: String(this.data.lock.keyId),
|
|
||||||
uid: String(this.data.accountInfo.uid),
|
|
||||||
userCountLimit: 0xFFFF,
|
|
||||||
operate: operate,
|
|
||||||
isAdmin: 1,
|
|
||||||
isForce: 0,
|
|
||||||
isRound: 0,
|
|
||||||
weekDays: [],
|
|
||||||
startDate: 0,
|
|
||||||
endDate: 0,
|
|
||||||
startTime: '00:00',
|
|
||||||
endTime: '00:00',
|
|
||||||
cardId: this.data.cardId,
|
|
||||||
cardNumber: this.data.cardNumber,
|
|
||||||
cardName: '测试卡片1',
|
|
||||||
cardType: 1,
|
|
||||||
cardUserNo: 999
|
|
||||||
};
|
|
||||||
if (operate === 1) {
|
|
||||||
parms.cardName = '测试卡片2'
|
|
||||||
}
|
|
||||||
const registerExtendedProductsResult = await registerExtendedProducts(parms)
|
|
||||||
console.log('registerExtendedProductsResult', registerExtendedProductsResult);
|
|
||||||
},
|
|
||||||
fingerprintOperate(e) {
|
|
||||||
const operate = e.currentTarget.dataset.operate;
|
|
||||||
this._fingerprintOperate(Number(operate)); // 调用实际的逻辑函数
|
|
||||||
},
|
|
||||||
async _fingerprintOperate(operate) {
|
|
||||||
console.log('this.data', this.data)
|
|
||||||
const parms = {
|
|
||||||
type: 'fingerprint',
|
|
||||||
keyId: String(this.data.lock.keyId),
|
|
||||||
uid: String(this.data.accountInfo.uid),
|
|
||||||
userCountLimit: 0xFFFF,
|
|
||||||
operate: operate,
|
|
||||||
isAdmin: 1,
|
|
||||||
isForce: 0,
|
|
||||||
isRound: 0,
|
|
||||||
weekDays: [],
|
|
||||||
startDate: 0,
|
|
||||||
endDate: 0,
|
|
||||||
startTime: '00:00',
|
|
||||||
endTime: '00:00',
|
|
||||||
fingerprintId: this.data.fingerprintId,
|
|
||||||
fingerprintNumber: this.data.fingerprintNumber,
|
|
||||||
fingerprintName: '测试指纹1',
|
|
||||||
fingerprintType: 1,
|
|
||||||
fingerprintUserNo: 999,
|
|
||||||
deleteType: 1
|
|
||||||
};
|
|
||||||
if (operate === 1) {
|
|
||||||
parms.fingerprintName = '测试指纹2'
|
|
||||||
}
|
|
||||||
console.log('parms', parms)
|
|
||||||
const registerExtendedProductsResult = await registerExtendedProducts(parms)
|
|
||||||
console.log('registerExtendedProductsResult', registerExtendedProductsResult);
|
|
||||||
},
|
|
||||||
async findAllCard() {
|
|
||||||
const result = await getIcCardList({lockId: this.lock.lockId})
|
|
||||||
console.log('findAllCard', result)
|
|
||||||
},
|
|
||||||
async findAllFingerprint() {
|
|
||||||
const result = await getFingerprintList({lockId: this.lock.lockId})
|
|
||||||
console.log('findAllFingerprint', result)
|
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|||||||
@ -1,22 +1,25 @@
|
|||||||
<view>
|
<view class="container">
|
||||||
<button bind:tap="searchDevice">搜索设备</button>
|
<view class="form-card">
|
||||||
<view wx:for="{{list}}" wx:for-item="device" class="device" bind:tap="bindDevice" data-device="{{device}}">
|
<view class="card-title">选择设备类型</view>
|
||||||
{{device.name}}
|
|
||||||
|
<radio-group class="device-types" bind:change="onTypeChange">
|
||||||
|
<label class="type-item {{deviceType === 'lock' ? 'active' : ''}}">
|
||||||
|
<radio value="lock" checked="{{deviceType === 'lock'}}"/>
|
||||||
|
<view class="type-content">
|
||||||
|
<text class="type-name">智能门锁</text>
|
||||||
|
<text class="type-desc">管理您的智能门锁设备</text>
|
||||||
|
</view>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="type-item {{deviceType === 'gateway' ? 'active' : ''}}">
|
||||||
|
<radio value="gateway" checked="{{deviceType === 'gateway'}}"/>
|
||||||
|
<view class="type-content">
|
||||||
|
<text class="type-name">智能网关</text>
|
||||||
|
<text class="type-desc">管理您的智能网关设备</text>
|
||||||
|
</view>
|
||||||
|
</label>
|
||||||
|
</radio-group>
|
||||||
|
|
||||||
|
<button class="submit-btn" bind:tap="enterDevice">进入设备管理</button>
|
||||||
</view>
|
</view>
|
||||||
<button wx:if="{{lock}}" bind:tap="openDoor">开门</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="deleteLock">删除设备</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="getLockSupportFeatures">获取锁支持项</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="getOfflinePassword">获取锁离线密码</button>
|
|
||||||
|
|
||||||
<button wx:if="{{lock}}" bind:tap="icCardOperate" data-operate="0">添加卡片</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="icCardOperate" data-operate="1">修改卡片</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="icCardOperate" data-operate="2">删除卡片</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="icCardOperate" data-operate="3">删除全部卡片</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="findAllCard" >查询卡片列表</button>
|
|
||||||
|
|
||||||
<button wx:if="{{lock}}" bind:tap="fingerprintOperate" data-operate="0">添加指纹</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="fingerprintOperate" data-operate="1">修改指纹</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="fingerprintOperate" data-operate="2">删除指纹</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="fingerprintOperate" data-operate="3">删除全部指纹</button>
|
|
||||||
<button wx:if="{{lock}}" bind:tap="findAllFingerprint" >查询卡片列表</button>
|
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@ -1,5 +1,85 @@
|
|||||||
.device {
|
.container {
|
||||||
padding: 32rpx;
|
padding: 32rpx;
|
||||||
margin: 32rpx;
|
background: #f7f7f7;
|
||||||
border: #2c405a 1px solid;
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-card {
|
||||||
|
width: 100%;
|
||||||
|
background: white;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 40rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-types {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-bottom: 48rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
background: #f8f9fa;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-desc {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
width: 100%;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
box-shadow: 0 2rpx 6rpx rgba(0,122,255,0.2);
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
}
|
||||||
433
miniprogram/miniprogram/pages/lockDetail/lockDetail.js
Normal file
433
miniprogram/miniprogram/pages/lockDetail/lockDetail.js
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
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 this.handleApiCall(async () => {
|
||||||
|
const app = getApp();
|
||||||
|
// 确保使用最新的锁信息
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: app.globalData.lock.lockId
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await remoteUnLock({
|
||||||
|
lockId: this.data.lock.lockId,
|
||||||
|
uid: this.data.accountInfo.uid,
|
||||||
|
})
|
||||||
|
console.log('result', result)
|
||||||
|
|
||||||
|
if (result.code === Result.Success.code) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '开门成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
wx.showToast({
|
||||||
|
title: result.message,
|
||||||
|
icon: 'fail'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, '开门中...');
|
||||||
|
},
|
||||||
|
|
||||||
|
// 读取锁设置
|
||||||
|
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'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 配置网络
|
||||||
|
configNetwork() {
|
||||||
|
wx.navigateTo({
|
||||||
|
url: '/pages/configNetwork/configNetwork'
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
3
miniprogram/miniprogram/pages/lockDetail/lockDetail.json
Normal file
3
miniprogram/miniprogram/pages/lockDetail/lockDetail.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
140
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxml
Normal file
140
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxml
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
<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>
|
||||||
|
<button class="feature-btn" bind:tap="configNetwork">
|
||||||
|
<view class="feature-icon network-icon"></view>
|
||||||
|
<text class="feature-name">配置网络</text>
|
||||||
|
<text class="feature-desc">WiFi网络设置</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>
|
||||||
284
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxss
Normal file
284
miniprogram/miniprogram/pages/lockDetail/lockDetail.wxss
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-icon {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg t='1710000000000' class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M512 832a64 64 0 1 0 0-128 64 64 0 0 0 0 128zm0-704C300.3 128 128 300.3 128 512h64c0-176.7 143.3-320 320-320s320 143.3 320 320h64c0-211.7-172.3-384-384-384zm0 192c-123.7 0-224 100.3-224 224h64c0-88.2 71.8-160 160-160s160 71.8 160 160h64c0-123.7-100.3-224-224-224z' fill='%23007AFF'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
264
miniprogram/miniprogram/pages/password/password.js
Normal file
264
miniprogram/miniprogram/pages/password/password.js
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
const {
|
||||||
|
selectLock,
|
||||||
|
getOfflinePassword,
|
||||||
|
customPassword
|
||||||
|
} = requirePlugin('starCloud')
|
||||||
|
|
||||||
|
Page({
|
||||||
|
data: {
|
||||||
|
accountInfo: null,
|
||||||
|
lock: null,
|
||||||
|
pwdId: -1,
|
||||||
|
pwdNo: 0,
|
||||||
|
currentStartDate: '',
|
||||||
|
currentStartTime: '',
|
||||||
|
currentEndDate: '',
|
||||||
|
currentEndTime: '',
|
||||||
|
pwdTypeList: [
|
||||||
|
{id: 1, name: '单次密码'},
|
||||||
|
{id: 2, name: '永久密码'},
|
||||||
|
{id: 3, name: '限时密码'},
|
||||||
|
{id: 4, name: '删除密码'},
|
||||||
|
{id: 5, name: '周末循环'},
|
||||||
|
{id: 6, name: '每日循环'},
|
||||||
|
{id: 7, name: '工作日循环'},
|
||||||
|
{id: 8, name: '周一循环'},
|
||||||
|
{id: 9, name: '周二循环'},
|
||||||
|
{id: 10, name: '周三循环'},
|
||||||
|
{id: 11, name: '周四循环'},
|
||||||
|
{id: 12, name: '周五循环'},
|
||||||
|
{id: 13, name: '周六循环'},
|
||||||
|
{id: 14, name: '周日循环'}
|
||||||
|
],
|
||||||
|
currentPwdType: 3, // 默认为限时密码
|
||||||
|
passwordName: '', // 密码名称
|
||||||
|
password: '', // 密码
|
||||||
|
isCoerced: false, // 是否胁迫密码
|
||||||
|
addTypeList: [
|
||||||
|
{id: 1, name: '管理员添加'},
|
||||||
|
{id: 2, name: '用户添加'}
|
||||||
|
],
|
||||||
|
currentAddType: 1,
|
||||||
|
isAdmin: false // 是否管理员
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad(options) {
|
||||||
|
const eventChannel = this.getOpenerEventChannel()
|
||||||
|
eventChannel.on('acceptDataFromOpenerPage', data => {
|
||||||
|
this.setData({
|
||||||
|
accountInfo: data.accountInfo,
|
||||||
|
lock: data.lock
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
bindPwdTypeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
currentPwdType: Number(e.detail.value) + 1
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
bindCustomPwdTypeChange(e) {
|
||||||
|
const index = Number(e.detail.value);
|
||||||
|
// 因为只提供永久和限时两种选择,所以index为0时是永久(2),为1时是限时(3)
|
||||||
|
this.setData({
|
||||||
|
currentPwdType: index === 0 ? 2 : 3
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
bindStartDateChange(e) {
|
||||||
|
this.setData({
|
||||||
|
currentStartDate: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
bindStartTimeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
currentStartTime: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
bindEndDateChange(e) {
|
||||||
|
this.setData({
|
||||||
|
currentEndDate: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
bindEndTimeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
currentEndTime: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
bindAddTypeChange(e) {
|
||||||
|
this.setData({
|
||||||
|
currentAddType: Number(e.detail.value) + 1
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onCoercedChange(e) {
|
||||||
|
this.setData({
|
||||||
|
isCoerced: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdminChange(e) {
|
||||||
|
this.setData({
|
||||||
|
isAdmin: e.detail.value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
_convertToTimestamp(date, time) {
|
||||||
|
if (!date || !time) return 0;
|
||||||
|
const dateTimeStr = `${date} ${time}:00`;
|
||||||
|
return new Date(dateTimeStr).getTime();
|
||||||
|
},
|
||||||
|
|
||||||
|
_getDefaultTimeRange() {
|
||||||
|
const now = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
const end = new Date();
|
||||||
|
end.setHours(now.getHours() + 1, 0, 0, 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
hoursStart: now.getHours(),
|
||||||
|
hoursEnd: end.getHours(),
|
||||||
|
startDate: start.getTime(),
|
||||||
|
endDate: end.getTime()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
async getOfflinePassword() {
|
||||||
|
wx.showLoading({
|
||||||
|
title: '处理中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
let params = {
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
password: {
|
||||||
|
lockId: this.data.lock.lockId,
|
||||||
|
keyboardPwdName: `密码${new Date().getTime()}`,
|
||||||
|
keyboardPwdType: this.data.currentPwdType,
|
||||||
|
isCoerced: 2,
|
||||||
|
startDate: 0,
|
||||||
|
endDate: 0,
|
||||||
|
hoursStart: 0,
|
||||||
|
hoursEnd: 0,
|
||||||
|
isAdmin: this.data.isAdmin ? 1 : 0, // 添加管理员标识
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理限时密码
|
||||||
|
if (this.data.currentPwdType === 3) {
|
||||||
|
params.password.startDate = this._convertToTimestamp(this.data.currentStartDate, this.data.currentStartTime);
|
||||||
|
params.password.endDate = this._convertToTimestamp(this.data.currentEndDate, this.data.currentEndTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理循环密码(周末、每日、工作日、周一到周日循环)
|
||||||
|
if (params.password.keyboardPwdType >= 5) {
|
||||||
|
if (this.data.currentStartTime && this.data.currentEndTime) {
|
||||||
|
params.password.hoursStart = parseInt(this.data.currentStartTime.split(':')[0]);
|
||||||
|
params.password.hoursEnd = parseInt(this.data.currentEndTime.split(':')[0]);
|
||||||
|
|
||||||
|
const startDate = this.data.currentStartDate ? new Date(this.data.currentStartDate) : new Date();
|
||||||
|
const endDate = this.data.currentEndDate ? new Date(this.data.currentEndDate) : new Date();
|
||||||
|
params.password.startDate = startDate.getTime();
|
||||||
|
params.password.endDate = endDate.getTime();
|
||||||
|
} else {
|
||||||
|
// 使用默认时间范围
|
||||||
|
const defaultTime = this._getDefaultTimeRange();
|
||||||
|
params.password.hoursStart = defaultTime.hoursStart;
|
||||||
|
params.password.hoursEnd = defaultTime.hoursEnd;
|
||||||
|
params.password.startDate = defaultTime.startDate;
|
||||||
|
params.password.endDate = defaultTime.endDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await getOfflinePassword(params)
|
||||||
|
if (result.code === 0) {
|
||||||
|
wx.showModal({
|
||||||
|
title: '离线密码',
|
||||||
|
content: result.data.keyboardPwd,
|
||||||
|
showCancel: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
customPasswordOperate(e) {
|
||||||
|
const operate = e.currentTarget.dataset.operate;
|
||||||
|
this._customPasswordOperate(Number(operate));
|
||||||
|
},
|
||||||
|
|
||||||
|
async _customPasswordOperate(operate) {
|
||||||
|
if (!this.validateInput()) return;
|
||||||
|
|
||||||
|
wx.showLoading({
|
||||||
|
title: '处理中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await selectLock({
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
lockId: this.data.lock.lockId
|
||||||
|
})
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
accountInfo: this.data.accountInfo,
|
||||||
|
password: {
|
||||||
|
keyboardPwdName: this.data.passwordName,
|
||||||
|
keyboardPwdType: this.data.currentPwdType, // 使用选择的密码类型
|
||||||
|
keyboardPwd: Number(this.data.password),
|
||||||
|
addType: this.data.currentAddType,
|
||||||
|
isCoerced: this.data.isCoerced ? 1 : 2,
|
||||||
|
startDate: this._convertToTimestamp(this.data.currentStartDate, this.data.currentStartTime),
|
||||||
|
endDate: this._convertToTimestamp(this.data.currentEndDate, this.data.currentEndTime),
|
||||||
|
operate: operate,
|
||||||
|
pwdRight: 0,
|
||||||
|
lockId: this.data.lock.lockId,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (params.password.operate === 1 || params.password.operate === 2) {
|
||||||
|
params.password.keyboardPwdId = this.data.pwdId
|
||||||
|
params.password.pwdNo = this.data.pwdNo
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await customPassword(params);
|
||||||
|
if (operate === 0 && result.code === 0) {
|
||||||
|
this.setData({
|
||||||
|
pwdId: result.data.keyboardPwdId,
|
||||||
|
pwdNo: result.data.pwdNo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
wx.showToast({
|
||||||
|
title: ['添加', '修改', '删除'][operate] + (result.code === 0 ? '成功' : '失败'),
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
wx.hideLoading();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
validateInput() {
|
||||||
|
if (!this.data.passwordName) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请输入密码名称',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!this.data.password || !/^\d{6,12}$/.test(this.data.password)) {
|
||||||
|
wx.showToast({
|
||||||
|
title: '请输入6-12位数字密码',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
3
miniprogram/miniprogram/pages/password/password.json
Normal file
3
miniprogram/miniprogram/pages/password/password.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
||||||
78
miniprogram/miniprogram/pages/password/password.wxml
Normal file
78
miniprogram/miniprogram/pages/password/password.wxml
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<view class="container">
|
||||||
|
<view class="password-section">
|
||||||
|
<view class="section-header">离线密码</view>
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">管理员</text>
|
||||||
|
<switch checked="{{isAdmin}}" bindchange="onAdminChange"/>
|
||||||
|
</view>
|
||||||
|
<view class="pwd-type-picker">
|
||||||
|
<picker range="{{pwdTypeList}}" range-key="name" bindchange="bindPwdTypeChange">
|
||||||
|
<view class="picker">
|
||||||
|
{{pwdTypeList[currentPwdType-1].name}}
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
<button class="action-button" bind:tap="getOfflinePassword">获取离线密码</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="password-section">
|
||||||
|
<view class="section-header">自定义密码</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">密码名称</text>
|
||||||
|
<input class="input" model:value="{{passwordName}}" placeholder="请输入密码名称"/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">密码</text>
|
||||||
|
<input class="input" type="number" model:value="{{password}}" placeholder="请输入6-12位数字密码"/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">胁迫密码</text>
|
||||||
|
<switch checked="{{isCoerced}}" bindchange="onCoercedChange"/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">添加类型</text>
|
||||||
|
<picker range="{{addTypeList}}" range-key="name" bindchange="bindAddTypeChange">
|
||||||
|
<view class="picker">{{addTypeList[currentAddType-1].name}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<text class="label">密码类型</text>
|
||||||
|
<picker range="{{[pwdTypeList[1], pwdTypeList[2]]}}" range-key="name" bindchange="bindCustomPwdTypeChange">
|
||||||
|
<view class="picker">{{currentPwdType === 2 ? '永久密码' : '限时密码'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="password-time-picker" wx:if="{{currentPwdType === 3}}">
|
||||||
|
<view class="time-section">
|
||||||
|
<view class="section-title">时间设置</view>
|
||||||
|
<view class="picker-group">
|
||||||
|
<picker mode="date" value="{{currentStartDate}}" start="2024-01-01" end="2025-12-31" bindchange="bindStartDateChange">
|
||||||
|
<view class="picker">{{currentStartDate || '开始日期'}}</view>
|
||||||
|
</picker>
|
||||||
|
<picker mode="time" value="{{currentStartTime}}" bindchange="bindStartTimeChange">
|
||||||
|
<view class="picker">{{currentStartTime || '开始时间'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
<view class="picker-group">
|
||||||
|
<picker mode="date" value="{{currentEndDate}}" start="2024-01-01" end="2025-12-31" bindchange="bindEndDateChange">
|
||||||
|
<view class="picker">{{currentEndDate || '结束日期'}}</view>
|
||||||
|
</picker>
|
||||||
|
<picker mode="time" value="{{currentEndTime}}" bindchange="bindEndTimeChange">
|
||||||
|
<view class="picker">{{currentEndTime || '结束时间'}}</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="button-group">
|
||||||
|
<button class="action-button" bind:tap="customPasswordOperate" data-operate="0">添加</button>
|
||||||
|
<button class="action-button" bind:tap="customPasswordOperate" data-operate="1">修改</button>
|
||||||
|
<button class="action-button" bind:tap="customPasswordOperate" data-operate="2">删除</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
104
miniprogram/miniprogram/pages/password/password.wxss
Normal file
104
miniprogram/miniprogram/pages/password/password.wxss
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
.container {
|
||||||
|
padding: 24rpx;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-section {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
border-bottom: 2rpx solid #eef0f5;
|
||||||
|
color: #2c405a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pwd-type-picker {
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker {
|
||||||
|
background: #f8f9fc;
|
||||||
|
padding: 24rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
flex: 1;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
border: 2rpx solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-section {
|
||||||
|
margin: 32rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #2c405a;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 24rpx;
|
||||||
|
margin-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-button {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0;
|
||||||
|
background: #2c405a;
|
||||||
|
color: white;
|
||||||
|
font-size: 30rpx;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-button:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 28rpx 0;
|
||||||
|
border-bottom: 2rpx solid #eef0f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 180rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #2c405a;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 30rpx;
|
||||||
|
padding: 16rpx 24rpx;
|
||||||
|
background: #f8f9fc;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
border: 2rpx solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:focus {
|
||||||
|
border-color: #2c405a;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
@ -4,22 +4,30 @@
|
|||||||
"compileType": "plugin",
|
"compileType": "plugin",
|
||||||
"libVersion": "latest",
|
"libVersion": "latest",
|
||||||
"srcMiniprogramRoot": "miniprogram/",
|
"srcMiniprogramRoot": "miniprogram/",
|
||||||
"appid": "wxf2c491f734bbf82f",
|
|
||||||
"pluginAppid": "wxf2c491f734bbf82f",
|
|
||||||
"packOptions": {
|
|
||||||
"ignore": [],
|
|
||||||
"include": []
|
|
||||||
},
|
|
||||||
"setting": {
|
"setting": {
|
||||||
"babelSetting": {
|
"babelSetting": {
|
||||||
"ignore": [],
|
"ignore": [],
|
||||||
"disablePlugins": [],
|
"disablePlugins": [],
|
||||||
"outputPath": ""
|
"outputPath": ""
|
||||||
}
|
},
|
||||||
|
"coverView": false,
|
||||||
|
"postcss": false,
|
||||||
|
"minified": false,
|
||||||
|
"enhance": false,
|
||||||
|
"showShadowRootInWxmlPanel": false,
|
||||||
|
"packNpmRelationList": [],
|
||||||
|
"ignoreUploadUnusedFiles": true
|
||||||
},
|
},
|
||||||
"condition": {},
|
"condition": {},
|
||||||
"editorSetting": {
|
"editorSetting": {
|
||||||
"tabIndent": "insertSpaces",
|
"tabIndent": "insertSpaces",
|
||||||
"tabSize": 2
|
"tabSize": 2
|
||||||
}
|
},
|
||||||
|
"simulatorPluginLibVersion": {},
|
||||||
|
"packOptions": {
|
||||||
|
"ignore": [],
|
||||||
|
"include": []
|
||||||
|
},
|
||||||
|
"appid": "wxf2c491f734bbf82f",
|
||||||
|
"pluginAppid": "wxf2c491f734bbf82f"
|
||||||
}
|
}
|
||||||
80
package-lock.json
generated
80
package-lock.json
generated
@ -23,11 +23,8 @@
|
|||||||
"@dcloudio/uni-mp-weixin": "3.0.0-4030620241128001",
|
"@dcloudio/uni-mp-weixin": "3.0.0-4030620241128001",
|
||||||
"@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",
|
||||||
"buffer": "^6.0.3",
|
|
||||||
"crc": "^4.3.2",
|
|
||||||
"js-md5": "^0.8.3",
|
|
||||||
"pinia": "^2.2.8",
|
"pinia": "^2.2.8",
|
||||||
"sm-crypto": "^0.3.13",
|
"star-cloud-uni": "^1.0.23",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^9.1.9"
|
"vue-i18n": "^9.1.9"
|
||||||
},
|
},
|
||||||
@ -9018,9 +9015,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pinia": {
|
"node_modules/pinia": {
|
||||||
"version": "2.2.8",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz",
|
||||||
"integrity": "sha512-NRTYy2g+kju5tBRe0oNlriZIbMNvma8ZJrpHsp3qudyiMEA8jMmPPKQ2QMHg0Oc4BkUyQYWagACabrwriCK9HQ==",
|
"integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/devtools-api": "^6.6.3",
|
"@vue/devtools-api": "^6.6.3",
|
||||||
@ -9030,45 +9027,15 @@
|
|||||||
"url": "https://github.com/sponsors/posva"
|
"url": "https://github.com/sponsors/posva"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@vue/composition-api": "^1.4.0",
|
|
||||||
"typescript": ">=4.4.4",
|
"typescript": ">=4.4.4",
|
||||||
"vue": "^2.6.14 || ^3.5.11"
|
"vue": "^2.7.0 || ^3.5.11"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@vue/composition-api": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pinia/node_modules/vue-demi": {
|
|
||||||
"version": "0.14.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
|
|
||||||
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"vue-demi-fix": "bin/vue-demi-fix.js",
|
|
||||||
"vue-demi-switch": "bin/vue-demi-switch.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/antfu"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@vue/composition-api": "^1.0.0-rc.1",
|
|
||||||
"vue": "^3.0.0-0 || ^2.6.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"@vue/composition-api": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pirates": {
|
"node_modules/pirates": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
||||||
@ -10078,6 +10045,17 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/star-cloud-uni": {
|
||||||
|
"version": "1.0.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/star-cloud-uni/-/star-cloud-uni-1.0.23.tgz",
|
||||||
|
"integrity": "sha512-LlYwyMv2BD3Nqpy/HfusDHQNBzwIUGVTtuSk6iT0gqGoYYpnbIxVRdu8ZtY8s0qok/diVP2JzWriKOWEnxnD/A==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"crc": "^4.3.2",
|
||||||
|
"js-md5": "^0.8.3",
|
||||||
|
"sm-crypto": "^0.3.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/statuses": {
|
"node_modules/statuses": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||||
@ -10856,6 +10834,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-demi": {
|
||||||
|
"version": "0.14.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
|
||||||
|
"integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vue-i18n": {
|
"node_modules/vue-i18n": {
|
||||||
"version": "9.14.2",
|
"version": "9.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.2.tgz",
|
||||||
|
|||||||
@ -51,8 +51,8 @@
|
|||||||
"@dcloudio/uni-mp-weixin": "3.0.0-4030620241128001",
|
"@dcloudio/uni-mp-weixin": "3.0.0-4030620241128001",
|
||||||
"@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",
|
||||||
"star-cloud-uni": "^1.0.7",
|
|
||||||
"pinia": "^2.2.8",
|
"pinia": "^2.2.8",
|
||||||
|
"star-cloud-uni": "^1.0.23",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-i18n": "^9.1.9"
|
"vue-i18n": "^9.1.9"
|
||||||
},
|
},
|
||||||
|
|||||||
96
src/index.js
96
src/index.js
@ -19,9 +19,18 @@ import {
|
|||||||
updateAdminPassword,
|
updateAdminPassword,
|
||||||
syncOpenDoorRecord,
|
syncOpenDoorRecord,
|
||||||
getServerTime, getLockSupportFeatures,
|
getServerTime, getLockSupportFeatures,
|
||||||
Result, registerExtendedProductsCancel
|
Result, registerExtendedProductsCancel,
|
||||||
|
updateSupportFunctionsWithParams,
|
||||||
|
remoteUnLock,
|
||||||
|
readSupportFunctionsSetting,
|
||||||
|
getLockList,
|
||||||
|
startSearchWiFi,
|
||||||
|
connectWiFi,
|
||||||
|
getLockNetworkInfo,
|
||||||
} from 'star-cloud-uni'
|
} from 'star-cloud-uni'
|
||||||
|
|
||||||
|
// 用于存储事件监听器的Map
|
||||||
|
const eventListeners = new Map();
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Result,
|
Result,
|
||||||
/**
|
/**
|
||||||
@ -194,7 +203,22 @@ module.exports = {
|
|||||||
async getRemoteList(params) {
|
async getRemoteList(params) {
|
||||||
return await getRemoteList(params)
|
return await getRemoteList(params)
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 更新锁支持项目
|
||||||
|
* @param params
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
async updateSupportFunctionsWithParams(params) {
|
||||||
|
return await updateSupportFunctionsWithParams(params)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 读取锁设置
|
||||||
|
* @param params
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
async readSupportFunctions(params) {
|
||||||
|
return await readSupportFunctionsSetting(params)
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 事件触发
|
* 事件触发
|
||||||
* @param eventName 事件昵称
|
* @param eventName 事件昵称
|
||||||
@ -210,7 +234,6 @@ module.exports = {
|
|||||||
uni.$emit(eventName, object)
|
uni.$emit(eventName, object)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 事件监听
|
* 事件监听
|
||||||
* @param eventName 事件昵称
|
* @param eventName 事件昵称
|
||||||
@ -224,20 +247,28 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用uni.$on监听事件
|
// 检查是否已经存在该事件的监听器
|
||||||
|
if (eventListeners.has(eventName)) {
|
||||||
|
console.warn(`Event ${eventName} already has a listener registered.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建监听器函数
|
||||||
const listener = async (data) => {
|
const listener = async (data) => {
|
||||||
try {
|
try {
|
||||||
// 调用外部传入的回调函数
|
|
||||||
await callBack(data);
|
await callBack(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error executing callback for event ${eventName}:`, error);
|
console.error(`Error executing callback for event ${eventName}:`, error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 存储监听器
|
||||||
|
eventListeners.set(eventName, listener);
|
||||||
|
|
||||||
|
// 注册事件监听
|
||||||
uni.$on(eventName, listener);
|
uni.$on(eventName, listener);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 事件监听但仅触发一次,在第一次触发之后移除该监听器。
|
* 事件监听但仅触发一次,在第一次触发之后移除该监听器。
|
||||||
* @param eventName 事件昵称
|
* @param eventName 事件昵称
|
||||||
@ -265,7 +296,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除全局自定义事件监听器。
|
* 移除全局自定义事件监听器
|
||||||
* @param eventName
|
* @param eventName
|
||||||
* @param callBack
|
* @param callBack
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
@ -277,15 +308,48 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const listener = async (data) => {
|
// 获取存储的监听器
|
||||||
try {
|
const listener = eventListeners.get(eventName);
|
||||||
// 调用外部传入的回调函数
|
if (listener) {
|
||||||
await callBack(data);
|
uni.$off(eventName, listener);
|
||||||
} catch (error) {
|
eventListeners.delete(eventName);
|
||||||
console.error(`Error executing callback for event ${eventName}:`, error);
|
}
|
||||||
}
|
},
|
||||||
};
|
|
||||||
|
|
||||||
uni.$off(eventName, listener);
|
/**
|
||||||
|
* 远程开锁
|
||||||
|
* @param params
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
async remoteUnLock(params) {
|
||||||
|
return await remoteUnLock(params)
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取锁列表
|
||||||
|
* @param params
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
async getLockList(params) {
|
||||||
|
return await getLockList(params);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动搜索wifi
|
||||||
|
* @param params
|
||||||
|
* @returns {Promise<*>}
|
||||||
|
*/
|
||||||
|
async startSearchWiFi(params) {
|
||||||
|
return await startSearchWiFi(params);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
async connectWiFi(params){
|
||||||
|
return await connectWiFi(params);
|
||||||
|
},
|
||||||
|
|
||||||
|
async getLockNetworkInfo(params){
|
||||||
|
return await getLockNetworkInfo(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user