diff --git a/miniprogram/miniprogram/app.js b/miniprogram/miniprogram/app.js
index 7c52faf..5032278 100644
--- a/miniprogram/miniprogram/app.js
+++ b/miniprogram/miniprogram/app.js
@@ -1,5 +1,66 @@
// app.js
+const {
+ init,
+ Result,
+ register
+} = requirePlugin('starCloud')
+
App({
- onLaunch() {
+ globalData: {
+ accountInfo: null,
+ deviceList: [],
+ lock: null // 添加lock属性
+ },
+
+ onLaunch: function() {
+ this.initBluetooth()
+ },
+
+ async initBluetooth() {
+ // 初始化SDK
+ init({
+ clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
+ clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
+ env: 'SKY',
+ isReportLog: true,
+ accounts: []
+ })
+
+ try {
+ // 注册账号
+ const registerResult = await register()
+ if (registerResult.code === Result.Success.code) {
+ this.globalData.accountInfo = registerResult.data
+
+ // 使用注册的账号重新初始化
+ init({
+ clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
+ clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
+ env: 'SKY',
+ isReportLog: true,
+ accounts: [this.globalData.accountInfo]
+ })
+
+ try {
+ // 请求蓝牙权限
+ await wx.authorize({
+ scope: 'scope.bluetooth'
+ })
+
+ } catch (error) {
+ wx.showModal({
+ title: '提示',
+ content: '获取蓝牙权限失败',
+ showCancel: false
+ })
+ }
+ }
+ } catch (error) {
+ wx.showModal({
+ title: '提示',
+ content: '蓝牙初始化失败,请检查蓝牙权限',
+ showCancel: false
+ })
+ }
}
})
diff --git a/miniprogram/miniprogram/app.json b/miniprogram/miniprogram/app.json
index 41147cb..7b20773 100644
--- a/miniprogram/miniprogram/app.json
+++ b/miniprogram/miniprogram/app.json
@@ -1,7 +1,16 @@
{
"pages": [
- "pages/index/index"
+ "pages/index/index",
+ "pages/password/password",
+ "pages/card/card",
+ "pages/fingerprint/fingerprint"
],
+ "window": {
+ "backgroundTextStyle": "light",
+ "navigationBarBackgroundColor": "#fff",
+ "navigationBarTitleText": "门锁管理",
+ "navigationBarTextStyle": "black"
+ },
"plugins": {
"starCloud": {
"version": "dev",
diff --git a/miniprogram/miniprogram/pages/card/card.js b/miniprogram/miniprogram/pages/card/card.js
new file mode 100644
index 0000000..d85bf68
--- /dev/null
+++ b/miniprogram/miniprogram/pages/card/card.js
@@ -0,0 +1,685 @@
+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();
+ }
+ });
+
+ // 初始化时间
+ 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 表示删除操作
+ }
+})
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/card/card.json b/miniprogram/miniprogram/pages/card/card.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/miniprogram/miniprogram/pages/card/card.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/card/card.wxml b/miniprogram/miniprogram/pages/card/card.wxml
new file mode 100644
index 0000000..10feb53
--- /dev/null
+++ b/miniprogram/miniprogram/pages/card/card.wxml
@@ -0,0 +1,171 @@
+
+
+
+ 卡片名称:
+
+
+
+ 卡片类型:
+
+ 永久
+ 期限
+ 循环
+
+
+
+ 管理员:
+
+
+
+ 胁迫模式:
+
+
+
+
+ 期限时间:
+
+ {{startDateDisplay || '请选择开始时间'}}
+
+
+
+
+
+ {{endDateDisplay || '请选择结束时间'}}
+
+
+
+
+
+ 循环周期:
+
+ {{weekdayPatterns[weekdayPatternIndex]}}
+
+
+
+ 自定义:
+
+
+
+
+
+ 生效日期:
+
+ {{startDateDisplay || '请选择开始日期'}}
+
+
+
+ 失效日期:
+
+ {{endDateDisplay || '请选择结束日期'}}
+
+
+
+ 生效时间:
+
+ {{startTime || '请选择'}}
+
+
+
+ 失效时间:
+
+ {{endTime || '请选择'}}
+
+
+
+
+
+
+ 当前操作参数
+
+
+ 卡片类型:
+ {{currentParams.type}}
+
+
+ 操作类型:
+ {{currentParams.operate}}
+
+
+ 管理员权限:
+ {{currentParams.isAdmin}}
+
+
+ 胁迫模式:
+ {{currentParams.isForce}}
+
+
+ 循环模式:
+ {{currentParams.isRound}}
+
+
+
+ 循环周期:
+ {{currentParams.weekDay}}
+
+
+
+
+ 期限时间:
+ {{currentParams.displayTimeRange}}
+
+
+
+
+ 有效期:
+ {{currentParams.startDate}} 至 {{currentParams.endDate}}
+
+
+
+
+ 生效时间:
+ {{currentParams.startTime}} - {{currentParams.endTime}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 名称:{{item.cardName}}
+ 类型:{{item.cardType === 1 ? '永久' : item.cardType === 2 ? '期限' : '循环'}}
+ 管理员:{{item.isAdmin === 1 ? '是' : '否'}}
+ 胁迫:{{item.isForce === 1 ? '是' : '否'}}
+
+
+
+ {{item.startDate}} - {{item.endDate}}
+
+
+ 周期:{{item.weekDayText}}
+
+ {{item.startTime}} - {{item.endTime}}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/card/card.wxss b/miniprogram/miniprogram/pages/card/card.wxss
new file mode 100644
index 0000000..864af64
--- /dev/null
+++ b/miniprogram/miniprogram/pages/card/card.wxss
@@ -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;
+}
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/fingerprint/fingerprint.js b/miniprogram/miniprogram/pages/fingerprint/fingerprint.js
new file mode 100644
index 0000000..245c179
--- /dev/null
+++ b/miniprogram/miniprogram/pages/fingerprint/fingerprint.js
@@ -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
+ });
+ }
+ }
+})
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/fingerprint/fingerprint.json b/miniprogram/miniprogram/pages/fingerprint/fingerprint.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/miniprogram/miniprogram/pages/fingerprint/fingerprint.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/fingerprint/fingerprint.wxml b/miniprogram/miniprogram/pages/fingerprint/fingerprint.wxml
new file mode 100644
index 0000000..18eb88c
--- /dev/null
+++ b/miniprogram/miniprogram/pages/fingerprint/fingerprint.wxml
@@ -0,0 +1,163 @@
+
+
+
+ 指纹名称:
+
+
+
+ 指纹类型:
+
+ 永久
+ 期限
+ 循环
+
+
+
+ 管理员:
+
+
+
+ 胁迫模式:
+
+
+
+
+ 期限时间:
+
+ {{startDateDisplay || '请选择开始时间'}}
+
+
+
+
+
+ {{endDateDisplay || '请选择结束时间'}}
+
+
+
+
+
+ 循环周期:
+
+ {{weekdayPatterns[weekdayPatternIndex]}}
+
+
+
+ 生效日期:
+
+ {{startDateDisplay || '请选择开始日期'}}
+
+
+
+ 失效日期:
+
+ {{endDateDisplay || '请选择结束日期'}}
+
+
+
+ 生效时间:
+
+ {{startTime}}
+
+
+
+ 失效时间:
+
+ {{endTime}}
+
+
+
+
+
+
+ 当前操作参数
+
+
+ 指纹类型:
+ {{currentParams.type}}
+
+
+ 操作类型:
+ {{currentParams.operate}}
+
+
+ 管理员权限:
+ {{currentParams.isAdmin}}
+
+
+ 胁迫模式:
+ {{currentParams.isForce}}
+
+
+ 循环模式:
+ {{currentParams.isRound}}
+
+
+
+ 循环周期:
+ {{currentParams.weekDay}}
+
+
+
+
+ 期限时间:
+ {{currentParams.displayTimeRange}}
+
+
+
+
+
+ 有效期:
+ {{currentParams.startDate}} 至 {{currentParams.endDate}}
+
+
+
+ 生效时间:
+ {{currentParams.startTime}} - {{currentParams.endTime}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 名称:{{item.fingerprintName}}
+ 类型:{{item.fingerprintType === 1 ? '永久' : item.fingerprintType === 2 ? '期限' : '循环'}}
+ 管理员:{{item.isAdmin === 1 ? '是' : '否'}}
+ 胁迫:{{item.isForce === 1 ? '是' : '否'}}
+
+
+
+ {{item.startDateDisplay}} - {{item.endDateDisplay}}
+
+
+ 周期:{{item.weekDayText}}
+
+ {{item.startTime}} - {{item.endTime}}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/fingerprint/fingerprint.wxss b/miniprogram/miniprogram/pages/fingerprint/fingerprint.wxss
new file mode 100644
index 0000000..03910c0
--- /dev/null
+++ b/miniprogram/miniprogram/pages/fingerprint/fingerprint.wxss
@@ -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;
+}
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/index/index.js b/miniprogram/miniprogram/pages/index/index.js
index 0f70640..5755e52 100644
--- a/miniprogram/miniprogram/pages/index/index.js
+++ b/miniprogram/miniprogram/pages/index/index.js
@@ -9,68 +9,114 @@ const {
stopSearchDevice,
selectLock,
getLockSupportFeatures,
- getOfflinePassword,
- registerExtendedProducts,
- starEventOn,
- starEventEmit,
- getFingerprintList,
- getIcCardList,
- customPassword,
updateAdminPassword,
+ updateSupportFunctionsWithParams,
+ remoteUnLock,
+ readSupportFunctions,
} = requirePlugin('starCloud')
+
Page({
data: {
list: [],
accountInfo: {},
lock: null,
- cardId: -1,
- cardNumber: 0,
- fingerprintId: -1,
- fingerprintNumber: 0,
eventChannel: null,
- pwdId: -1,
- pwdNo: 0,
+ isSearching: false,
+ loading: false, // 添加loading状态
+ showPassageMode: false,
+ passageModeForm: {
+ passageMode: '1',
+ startDate: '',
+ endDate: '',
+ isAllDay: '0',
+ cycleType: 'workday', // 添加循环类型:workday/weekend/everyday
+ autoUnlock: '1'
+ },
},
- async onLoad() {
- init({
- clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
- clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
- env: 'SKY',
- isReportLog: true,
- accounts: []
- })
- const result = await register()
- if (result.code === Result.Success.code) {
- this.setData({
- accountInfo: result.data
+
+ startSearching() {
+ if (this.data.isSearching) {
+ wx.showToast({
+ title: '正在搜索中',
+ icon: 'none'
})
- init({
- clientId: 'Tmj4XoB9dkXjD7t7OHKHl564rJdmvPm9',
- clientSecret: 'g1VvSbN0Ya3IqPkA8j9Xn54PE1L8zGiy',
- env: 'SKY',
- isReportLog: true,
- accounts: [this.data.accountInfo]
- })
- console.log('初始化成功:', this.data.accountInfo)
+ return
}
- starEventOn('registerFingerprintConfirm', async (data) => {
- if (data.code === 0) {
- this.data.fingerprintId = data.data.fingerprintId
- this.data.fingerprintNumber = data.data.fingerprintNumber
- console.log('收到指纹确认事件', data, this.fingerprintId, this.fingerprintNumber);
+
+ this.setData({ isSearching: true })
+ searchDevice((result) => {
+ if (result.code === Result.Success.code) {
+ this.setData({
+ list: result.data.list
+ })
+ getApp().globalData.deviceList = result.data.list
}
- });
- starEventOn('registerCardConfirm', async (data) => {
- if (data.code === 0) {
- this.data.cardId = data.data.cardId
- this.data.cardNumber = data.data.cardNumber
- console.log('收到卡片确认事件', data, this.cardId, this.cardNumber);
- }
- });
- starEventOn('registerFingerprintProcess', async (data) => {
- console.log('收到指纹过程事件', data);
- });
+ })
+
+ wx.showToast({
+ title: '开始搜索设备',
+ icon: 'none'
+ })
},
+
+ stopSearching() {
+ if (!this.data.isSearching) return
+
+ stopSearchDevice()
+ this.setData({ isSearching: false })
+ wx.showToast({
+ title: '已停止搜索',
+ icon: 'none'
+ })
+ },
+
+ onHide() {
+ this.stopSearching()
+ },
+
+ onUnload() {
+ this.stopSearching()
+ },
+
+ onLoad() {
+ // 从app.globalData获取数据
+ const app = getApp();
+ // 确保accountInfo包含必要的字段
+ const accountInfo = {
+ ...app.globalData.accountInfo,
+ account: app.globalData.accountInfo.account || '',
+ password: app.globalData.accountInfo.password || '',
+ aesKey: app.globalData.accountInfo.aesKey || '',
+ };
+
+ this.setData({
+ list: app.globalData.deviceList,
+ accountInfo: accountInfo
+ });
+
+ // 打印检查accountInfo结构
+ console.log('Current accountInfo:', accountInfo);
+ },
+
+ async requestBluetoothPermission() {
+ try {
+ const res = await wx.authorize({
+ scope: 'scope.bluetooth'
+ });
+ this.startSearching();
+ } catch (error) {
+ wx.showModal({
+ title: '提示',
+ content: '请授权蓝牙权限以使用设备功能',
+ success: (res) => {
+ if (res.confirm) {
+ wx.openSetting();
+ }
+ }
+ });
+ }
+ },
+
// 搜索设备
searchDevice() {
searchDevice(this.searchDeviceCallback)
@@ -83,7 +129,21 @@ Page({
})
}
},
- // 绑定设备
+
+ // 添加通用的loading处理方法
+ async handleApiCall(apiFunc, loadingText = '处理中...') {
+ this.setData({ loading: true })
+ wx.showLoading({ title: loadingText, mask: true })
+
+ try {
+ await apiFunc()
+ } finally {
+ this.setData({ loading: false })
+ wx.hideLoading()
+ }
+ },
+
+ // 修改绑定设备方法
bindDevice(e) {
const {device} = e.currentTarget.dataset
wx.showModal({
@@ -91,63 +151,87 @@ Page({
content: `确定绑定${device.name}吗?`,
success: async (res) => {
if (res.confirm) {
- const result = await bindDevice({
- accountInfo: this.data.accountInfo,
- name: device.name,
- })
- if (result.code === Result.Success.code) {
- stopSearchDevice()
- this.setData({
- lock: result.data.lock
+ await this.handleApiCall(async () => {
+ const result = await bindDevice({
+ accountInfo: this.data.accountInfo,
+ name: device.name,
})
- wx.showToast({
- title: '绑定成功',
- icon: 'none',
- })
- }
+ if (result.code === Result.Success.code) {
+ // 合并设备信息,确保显示完整信息
+ const lockInfo = {
+ ...device, // 包含搜索时的设备信息(name, mac, uid等)
+ ...result.data.lock // 包含绑定后的信息(lockId, keyId等)
+ }
+ this.setData({
+ lock: lockInfo,
+ list: [] // 清空搜索列表
+ })
+ // 更新app.globalData中的lock
+ getApp().globalData.lock = lockInfo
+ this.stopSearching()
+ wx.showToast({
+ title: '绑定成功',
+ icon: 'success',
+ })
+ }
+ }, '绑定中...')
}
}
})
},
- // 开门
+
+ // 修改开门方法
async openDoor() {
- await 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({
- title: '开门成功',
- icon: 'none',
+ await this.handleApiCall(async () => {
+ await selectLock({
+ accountInfo: this.data.accountInfo,
+ lockId: this.data.lock.lockId
})
- }
+ const result = await openDoor({
+ accountInfo: this.data.accountInfo,
+ disconnect: true,
+ type: 'open'
+ })
+ if (result.code === Result.Success.code) {
+ wx.showToast({
+ title: '开门成功',
+ icon: 'success',
+ })
+ }
+ }, '开门中...')
},
- // 删除锁
+
+ // 修改删除锁方法
async deleteLock() {
- await selectLock({
- accountInfo: this.data.accountInfo,
- lockId: this.data.lock.lockId
+ wx.showModal({
+ title: '提示',
+ content: '确定要删除此设备吗?',
+ success: async (res) => {
+ if (res.confirm) {
+ await this.handleApiCall(async () => {
+ await selectLock({
+ accountInfo: this.data.accountInfo,
+ lockId: this.data.lock.lockId
+ })
+ const result = await deleteLock({
+ accountInfo: this.data.accountInfo,
+ })
+ if (result.code === Result.Success.code) {
+ this.setData({
+ lock: null,
+ list: []
+ })
+ wx.showToast({
+ title: '删除成功',
+ icon: 'success',
+ })
+ }
+ }, '删除中...')
+ }
+ }
})
- 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({
@@ -156,152 +240,284 @@ Page({
})
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) {
- const parms = {
- type: 'card',
- keyId: String(this.data.lock.keyId),
- uid: String(this.data.accountInfo.uid),
- userCountLimit: 0xFFFF,
- operate: operate,
- isAdmin: 0,
- isForce: 0,
- isRound: 0,
- weekDays: [1, 2, 3, 4, 5],
- startDate: 1743991211000,
- endDate: 1745978411000,
- // startTime: '12:00',
- // endTime: '20:00',
- cardId: this.data.cardId,
- cardNumber: this.data.cardNumber,
- cardName: '15161195',
- cardType: 2,
- cardUserNo: 999
- };
- if (operate === 1) {
- parms.cardName = '测试卡片2'
- }
- console.log('parms', parms)
- const registerExtendedProductsResult = await registerExtendedProducts(parms)
- console.log('registerExtendedProductsResult', registerExtendedProductsResult);
+ navigateToCard() {
+ wx.navigateTo({
+ url: '/pages/card/card'
+ })
},
- fingerprintOperate(e) {
+
+ navigateToFingerprint() {
+ wx.navigateTo({
+ url: '/pages/fingerprint/fingerprint'
+ })
+ },
+
+ navigateToPassword() {
+ wx.navigateTo({
+ url: '/pages/password/password',
+ success: (res) => {
+ res.eventChannel.emit('acceptDataFromOpenerPage', {
+ accountInfo: this.data.accountInfo,
+ lock: this.data.lock
+ })
+ }
+ });
+ },
+
+ setAdminPasswordOperate(e) {
const operate = e.currentTarget.dataset.operate;
- this._fingerprintOperate(Number(operate)); // 调用实际的逻辑函数
+ wx.showModal({
+ title: '设置管理员密码',
+ editable: true,
+ placeholderText: '请输入管理员密码',
+ success: (res) => {
+ if (res.confirm && res.content) {
+ this._setAdminPasswordOperate(Number(operate), res.content);
+ }
+ }
+ });
},
- 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 _setAdminPasswordOperate(operate, password) {
+ await this.handleApiCall(async () => {
+ await selectLock({
+ accountInfo: this.data.accountInfo,
+ lockId: this.data.lock.lockId
+ });
+ const params = {
+ accountInfo: this.data.accountInfo,
+ adminPwd: password
+ };
+ const result = await updateAdminPassword(params);
+ if (result.code === Result.Success.code) {
+ wx.showToast({
+ title: '设置成功',
+ icon: 'success'
+ });
+ }
+ console.log('_setAdminPasswordOperate', result);
+ }, '设置中...');
},
- async findAllCard() {
- const result = await getIcCardList({lockId: this.data.lock.lockId})
- console.log('findAllCard', result)
+
+ async updateAutoLock() {
+ wx.showModal({
+ title: '自动闭锁设置',
+ editable: true,
+ showCancel: true,
+ placeholderText: '请输入自动闭锁时间(秒)',
+ success: async (res) => {
+ if (res.confirm) {
+ const value = parseInt(res.content);
+ if (!res.content) {
+ // 用户未输入数值,视为关闭自动闭锁
+ this._updateAutoLockSetting(0);
+ } else if (isNaN(value) || value < 1) {
+ wx.showToast({
+ title: '请输入大于1的整数',
+ icon: 'none'
+ });
+ } else {
+ // 输入合法,更新设置
+ this._updateAutoLockSetting(value);
+ }
+ }
+ }
+ });
},
- async findAllFingerprint() {
- const result = await getFingerprintList({lockId: this.data.lock.lockId})
- console.log('findAllFingerprint', result)
+
+ async _updateAutoLockSetting(seconds) {
+ await this.handleApiCall(async () => {
+ await selectLock({
+ accountInfo: this.data.accountInfo,
+ lockId: this.data.lock.lockId
+ });
+ const params = {
+ accountInfo: this.data.accountInfo,
+ featureBit: 29,
+ data: Number(seconds),
+ withParams: true
+ };
+ const result = await updateSupportFunctionsWithParams(params);
+ if (result.code === Result.Success.code) {
+ wx.showToast({
+ title: seconds === 0 ? '已关闭自动闭锁' : '设置成功',
+ icon: 'success'
+ });
+ }
+ console.log('updateAutoLock', result);
+ }, '设置中...');
},
- customPasswordOperate(e) {
+
+ async updateLockSound() {
+ wx.showActionSheet({
+ itemList: ['关闭', '1档', '2档', '3档', '4档', '5档'],
+ success: (res) => {
+ // res.tapIndex 从0开始,正好对应音量级别
+ this._updateLockSoundSetting(res.tapIndex);
+ }
+ });
+ },
+
+ async _updateLockSoundSetting(volume) {
+ await this.handleApiCall(async () => {
+ await selectLock({
+ accountInfo: this.data.accountInfo,
+ lockId: this.data.lock.lockId
+ });
+ const params = {
+ accountInfo: this.data.accountInfo,
+ featureBit: 33,
+ data: Number(volume),
+ withParams: true
+ };
+ const result = await updateSupportFunctionsWithParams(params);
+ if (result.code === Result.Success.code) {
+ wx.showToast({
+ title: volume === 0 ? '已关闭提示音' : `已设置为${volume}档`,
+ icon: 'success'
+ });
+ }
+ console.log('updateLockSound', result);
+ }, '设置中...');
+ },
+
+ async remoteUnLockRequest() {
+ await selectLock({
+ accountInfo: this.data.accountInfo,
+ lockId: this.data.lock.lockId
+ })
+ console.log('remoteUnLockRequest', await remoteUnLock());
+ },
+ async enableAntiPryAlarm(e) {
const operate = e.currentTarget.dataset.operate;
- this._customPasswordOperate(Number(operate)); // 调用实际的逻辑函数
- },
- async _customPasswordOperate(operate) {
await selectLock({
accountInfo: this.data.accountInfo,
lockId: this.data.lock.lockId
})
const parms = {
accountInfo: this.data.accountInfo,
- password: {
- keyboardPwdName: '测试密码',
- keyboardPwdType: 3,
- keyboardPwd: 123456,
- addType: 2,
- isCoerced: 2,
- startDate: 1743997466000,
- endDate: 1743997646000,
- operate: operate,
- pwdRight: 0,
- lockId: this.data.lock.lockId,
- }
+ featureBit: 30,
+ featureEnable: operate,
+ withParams: false
};
- if (parms.password.operate === 1 || parms.password.operate === 2) {
- parms.password.keyboardPwdId = this.data.pwdId
- parms.password.pwdNo = this.data.pwdNo
- parms.password.keyboardPwd = 112233
- parms.password.keyboardPwdName = '测试密码1'
- }
- const result = await customPassword(parms);
- if (parms.password.operate === 0) {
- this.data.pwdId = result.data.keyboardPwdId
- this.data.pwdNo = result.data.pwdNo
- }
+ const reslut = await updateSupportFunctionsWithParams(parms);
+ console.log('enableAntiPryAlarm', reslut)
+ },
+ async updatePassageMode() {
+ this.setData({
+ showPassageMode: true
+ });
+ },
- console.log('customPassword', result)
+ hidePassageMode() {
+ this.setData({
+ showPassageMode: false
+ });
},
- setAdminPasswordOperate(e) {
- const operate = e.currentTarget.dataset.operate;
- this._setAdminPasswordOperate(Number(operate)); // 调用实际的逻辑函数
+
+ onPassageModeInput(e) {
+ const { field } = e.currentTarget.dataset;
+ const { value } = e.detail;
+ this.setData({
+ [`passageModeForm.${field}`]: value
+ });
},
- async _setAdminPasswordOperate(operate) {
- await selectLock({
- accountInfo: this.data.accountInfo,
- lockId: this.data.lock.lockId
- })
- const parms = {
- accountInfo: this.data.accountInfo,
- uid: String(this.data.accountInfo.uid),
- adminPwd: '11223345'
- };
- const reslut= await updateAdminPassword(parms);
- console.log('_setAdminPasswordOperate', reslut)
+
+ async submitPassageMode() {
+ try {
+ const form = this.data.passageModeForm;
+ const startTime = parseInt(form.startDate);
+ const endTime = parseInt(form.endDate);
+
+ // 验证输入
+ if (!form.startDate || !form.endDate) {
+ throw new Error('请输入开始和结束时间');
+ }
+ if (isNaN(startTime) || startTime < 0 || startTime > 1440 ||
+ isNaN(endTime) || endTime < 0 || endTime > 1440) {
+ throw new Error('时间必须在0-1440分钟之间');
+ }
+ if (endTime <= startTime) {
+ throw new Error('结束时间必须大于开始时间');
+ }
+
+ // 根据循环类型设置weekDay
+ let weekDay;
+ switch (form.cycleType) {
+ case 'workday':
+ weekDay = [1, 2, 3, 4, 5];
+ break;
+ case 'weekend':
+ weekDay = [6, 7];
+ break;
+ case 'everyday':
+ weekDay = [1, 2, 3, 4, 5, 6, 7];
+ break;
+ default:
+ throw new Error('请选择循环类型');
+ }
+
+ const params = {
+ passageMode: parseInt(form.passageMode),
+ startDate: startTime,
+ endDate: endTime,
+ isAllDay: parseInt(form.isAllDay),
+ weekDay,
+ autoUnlock: parseInt(form.autoUnlock)
+ };
+
+ await this._updatePassageModeSetting(params);
+ this.hidePassageMode();
+ } catch (error) {
+ wx.showToast({
+ 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 readSupportFunctionsSet() {
+ await this.handleApiCall(async () => {
+ await selectLock({
+ accountInfo: this.data.accountInfo,
+ lockId: this.data.lock.lockId
+ });
+ const result = await readSupportFunctions({
+ lockId: this.data.lock.lockId
+ });
+ console.log('readSupportFunctionsSet', result);
+ wx.showModal({
+ title: '功能设置',
+ content: JSON.stringify(result.data, null, 2),
+ showCancel: false
+ });
+ }, '读取中...');
}
+
})
diff --git a/miniprogram/miniprogram/pages/index/index.wxml b/miniprogram/miniprogram/pages/index/index.wxml
index ba9e0b0..cb6d639 100644
--- a/miniprogram/miniprogram/pages/index/index.wxml
+++ b/miniprogram/miniprogram/pages/index/index.wxml
@@ -1,26 +1,154 @@
-
-
-
- {{device.name}}
+
+
+
+ 可用设备
+
+
+
+
+
+
+ {{item.name}}
+ 点击绑定
+
+
+
+ {{isSearching ? '正在搜索设备...' : '未找到设备,点击搜索按钮开始搜索'}}
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+ 设备名称:
+ {{lock.lockName || lock.name || '未知'}}
+
+
+ MAC地址:
+ {{lock.mac}}
+
+
+ UID:
+ {{lock.uid}}
+
+
+ 钥匙ID:
+ {{lock.keyId}}
+
+
+ 锁ID:
+ {{lock.lockId}}
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ 管理功能
+
+
+
+
+
+
+
+
+
+ 设置选项
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/miniprogram/miniprogram/pages/index/index.wxss b/miniprogram/miniprogram/pages/index/index.wxss
index e46383b..f8ad8cd 100644
--- a/miniprogram/miniprogram/pages/index/index.wxss
+++ b/miniprogram/miniprogram/pages/index/index.wxss
@@ -1,5 +1,347 @@
-.device {
- padding: 32rpx;
- margin: 32rpx;
- border: #2c405a 1px solid;
+.container {
+ padding: 32rpx;
+ background: #f5f5f5;
}
+
+.device-list {
+ background: white;
+ border-radius: 16rpx;
+ padding: 24rpx;
+ margin-bottom: 32rpx;
+}
+
+.section-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ margin-bottom: 24rpx;
+}
+
+.device {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 24rpx;
+ margin: 16rpx 0;
+ background: #f8f9fa;
+ border-radius: 8rpx;
+}
+
+.device-name {
+ font-size: 28rpx;
+ color: #333;
+}
+
+.device-status {
+ font-size: 24rpx;
+ color: #2c405a;
+}
+
+.action-section {
+ background: white;
+ border-radius: 16rpx;
+ padding: 24rpx;
+}
+
+.main-actions {
+ display: flex;
+ gap: 16rpx;
+ margin-bottom: 32rpx;
+}
+
+.primary-btn {
+ flex: 1;
+ background: #2c405a;
+ color: white;
+}
+
+.management-section,
+.settings-section {
+ margin-bottom: 32rpx;
+}
+
+.grid-buttons {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 16rpx;
+}
+
+.grid-buttons button {
+ margin: 0;
+ background: #f8f9fa;
+ color: #2c405a;
+}
+
+.danger-btn {
+ background: #dc3545;
+ color: white;
+ margin-top: 32rpx;
+}
+
+.password-time-picker {
+ padding: 15px;
+ background: #fff;
+ margin: 10px 0;
+}
+
+.picker-item {
+ display: flex;
+ align-items: center;
+ margin: 10px 0;
+}
+
+.picker-item text {
+ width: 80px;
+}
+
+.picker {
+ flex: 1;
+ padding: 5px 10px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+}
+
+.password-list {
+ margin: 15px;
+ padding: 10px;
+ background: #fff;
+ border-radius: 8px;
+}
+
+.password-list-title {
+ font-size: 16px;
+ font-weight: bold;
+ margin-bottom: 10px;
+ padding-bottom: 5px;
+ border-bottom: 1px solid #eee;
+}
+
+.password-item {
+ padding: 10px;
+ margin: 5px 0;
+ background: #f5f5f5;
+ border-radius: 4px;
+}
+
+.password-item view {
+ margin: 3px 0;
+ font-size: 14px;
+}
+
+.password-time-picker {
+ padding: 15px;
+ background: #fff;
+ margin: 10px;
+ border-radius: 8px;
+}
+
+.time-section {
+ margin-bottom: 15px;
+}
+
+.section-title {
+ font-size: 14px;
+ color: #333;
+ margin-bottom: 8px;
+}
+
+.picker-group {
+ display: flex;
+ gap: 10px;
+}
+
+.picker {
+ flex: 1;
+ padding: 8px 12px;
+ background: #f5f5f5;
+ border-radius: 4px;
+ font-size: 14px;
+ color: #333;
+}
+
+.pwd-type-picker {
+ padding: 15px;
+ background: #fff;
+ margin: 10px;
+ border-radius: 8px;
+}
+
+.section-title {
+ font-size: 14px;
+ color: #333;
+ margin-bottom: 8px;
+}
+
+.picker {
+ padding: 8px 12px;
+ background: #f5f5f5;
+ border-radius: 4px;
+ font-size: 14px;
+ color: #333;
+}
+
+.picker-value {
+ border: 1rpx solid #ddd;
+ border-radius: 8rpx;
+ padding: 20rpx;
+ font-size: 28rpx;
+ background: #f8f9fa;
+ color: #333;
+}
+
+.picker-value:active {
+ background: #eee;
+}
+
+.search-btn {
+ width: 90%;
+ margin: 10px auto;
+ background-color: #007AFF;
+ color: white;
+ border-radius: 8px;
+}
+
+.device-info {
+ background: #f5f5f5;
+ padding: 15px;
+ border-radius: 8px;
+ margin: 10px;
+}
+
+.info-item {
+ display: flex;
+ padding: 5px 0;
+ font-size: 14px;
+}
+
+.info-item .label {
+ color: #666;
+ width: 80px;
+}
+
+.info-item .value {
+ color: #333;
+ flex: 1;
+ word-break: break-all;
+}
+
+.passage-mode-popup {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 1000;
+ display: none;
+}
+
+.passage-mode-popup.show {
+ display: block;
+}
+
+.popup-mask {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.6);
+}
+
+.popup-content {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: #fff;
+ border-radius: 24rpx 24rpx 0 0;
+ max-height: 85vh;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.popup-header {
+ padding: 30rpx;
+ border-bottom: 1rpx solid #eee;
+}
+
+.popup-header .title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+}
+
+.popup-header .close {
+ position: absolute;
+ right: 30rpx;
+ top: 30rpx;
+ font-size: 40rpx;
+ color: #999;
+ line-height: 1;
+}
+
+.popup-body {
+ flex: 1;
+ padding: 30rpx;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.form-item {
+ margin-bottom: 40rpx;
+}
+
+.form-item .label {
+ display: block;
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 20rpx;
+ font-weight: 500;
+}
+
+.form-item .input {
+ border: 1rpx solid #ddd;
+ border-radius: 8rpx;
+ padding: 20rpx;
+ font-size: 28rpx;
+ background: #f8f9fa;
+}
+
+.form-item .hint {
+ display: block;
+ font-size: 24rpx;
+ color: #666;
+ margin-top: 12rpx;
+ line-height: 1.5;
+}
+
+.radio-group {
+ display: flex;
+ gap: 30rpx;
+}
+
+.popup-footer {
+ padding: 30rpx;
+ border-top: 1rpx solid #eee;
+ display: flex;
+ gap: 20rpx;
+}
+
+.popup-footer button {
+ flex: 1;
+ margin: 0;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ border-radius: 8rpx;
+}
+
+.cancel-btn {
+ background: #f5f5f5;
+ color: #333;
+}
+
+.confirm-btn {
+ background: #007aff;
+ color: #fff;
+}
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/password/password.js b/miniprogram/miniprogram/pages/password/password.js
new file mode 100644
index 0000000..86cc339
--- /dev/null
+++ b/miniprogram/miniprogram/pages/password/password.js
@@ -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
+ }
+})
diff --git a/miniprogram/miniprogram/pages/password/password.json b/miniprogram/miniprogram/pages/password/password.json
new file mode 100644
index 0000000..8835af0
--- /dev/null
+++ b/miniprogram/miniprogram/pages/password/password.json
@@ -0,0 +1,3 @@
+{
+ "usingComponents": {}
+}
\ No newline at end of file
diff --git a/miniprogram/miniprogram/pages/password/password.wxml b/miniprogram/miniprogram/pages/password/password.wxml
new file mode 100644
index 0000000..e7f6ab7
--- /dev/null
+++ b/miniprogram/miniprogram/pages/password/password.wxml
@@ -0,0 +1,78 @@
+
+
+
+
+ 管理员
+
+
+
+
+
+ {{pwdTypeList[currentPwdType-1].name}}
+
+
+
+
+
+
+
+
+
+
+ 密码名称
+
+
+
+
+ 密码
+
+
+
+
+ 胁迫密码
+
+
+
+
+ 添加类型
+
+ {{addTypeList[currentAddType-1].name}}
+
+
+
+
+ 密码类型
+
+ {{currentPwdType === 2 ? '永久密码' : '限时密码'}}
+
+
+
+
+
+ 时间设置
+
+
+ {{currentStartDate || '开始日期'}}
+
+
+ {{currentStartTime || '开始时间'}}
+
+
+
+
+ {{currentEndDate || '结束日期'}}
+
+
+ {{currentEndTime || '结束时间'}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/miniprogram/miniprogram/pages/password/password.wxss b/miniprogram/miniprogram/pages/password/password.wxss
new file mode 100644
index 0000000..fbb0006
--- /dev/null
+++ b/miniprogram/miniprogram/pages/password/password.wxss
@@ -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;
+}
diff --git a/package-lock.json b/package-lock.json
index 000eba3..03f31da 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,7 +24,7 @@
"@dcloudio/uni-mp-xhs": "3.0.0-4030620241128001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4030620241128001",
"pinia": "^2.2.8",
- "star-cloud-uni": "^1.0.11",
+ "star-cloud-uni": "^1.0.12",
"vue": "^3.5.13",
"vue-i18n": "^9.1.9"
},
@@ -10046,9 +10046,9 @@
}
},
"node_modules/star-cloud-uni": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/star-cloud-uni/-/star-cloud-uni-1.0.11.tgz",
- "integrity": "sha512-4FrCDxiMka+vCG9ac9yvBJAIxHy3FqTOykdGaIrzzztU3pbWo8W+4ASkrvfP9mIVs35UoKPN94OBsGGUGNN40g==",
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/star-cloud-uni/-/star-cloud-uni-1.0.12.tgz",
+ "integrity": "sha512-QhBsp8kF0aOaveFohaDTVibX6v9zJAczMvC5G1faPH++B48LmgPTmsqihlD0TwEip8nTWuNQDT89xZ84nbWg5g==",
"dependencies": {
"buffer": "^6.0.3",
"crc": "^4.3.2",
diff --git a/package.json b/package.json
index 137cd50..4dc5190 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"@dcloudio/uni-mp-xhs": "3.0.0-4030620241128001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4030620241128001",
"pinia": "^2.2.8",
- "star-cloud-uni": "^1.0.11",
+ "star-cloud-uni": "^1.0.12",
"vue": "^3.5.13",
"vue-i18n": "^9.1.9"
},
diff --git a/src/index.js b/src/index.js
index 05044a2..5c453b1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -19,9 +19,13 @@ import {
updateAdminPassword,
syncOpenDoorRecord,
getServerTime, getLockSupportFeatures,
- Result, registerExtendedProductsCancel
+ Result, registerExtendedProductsCancel,
+ updateSupportFunctionsWithParams,
+ remoteUnLock,
+ readSupportFunctionsSetting,
} from 'star-cloud-uni'
-
+// 用于存储事件监听器的Map
+const eventListeners = new Map();
module.exports = {
Result,
/**
@@ -195,6 +199,16 @@ module.exports = {
return await getRemoteList(params)
},
+
+ async updateSupportFunctionsWithParams(params) {
+ return await updateSupportFunctionsWithParams(params)
+ },
+ async readSupportFunctions(params) {
+ return await readSupportFunctionsSetting(params)
+ },
+
+
+
/**
* 事件触发
* @param eventName 事件昵称
@@ -210,7 +224,6 @@ module.exports = {
uni.$emit(eventName, object)
},
-
/**
* 事件监听
* @param eventName 事件昵称
@@ -224,20 +237,28 @@ module.exports = {
return;
}
- // 使用uni.$on监听事件
+ // 检查是否已经存在该事件的监听器
+ if (eventListeners.has(eventName)) {
+ console.warn(`Event ${eventName} already has a listener registered.`);
+ return;
+ }
+
+ // 创建监听器函数
const listener = async (data) => {
try {
- // 调用外部传入的回调函数
await callBack(data);
} catch (error) {
console.error(`Error executing callback for event ${eventName}:`, error);
}
};
+ // 存储监听器
+ eventListeners.set(eventName, listener);
+
+ // 注册事件监听
uni.$on(eventName, listener);
},
-
/**
* 事件监听但仅触发一次,在第一次触发之后移除该监听器。
* @param eventName 事件昵称
@@ -265,7 +286,7 @@ module.exports = {
},
/**
- * 移除全局自定义事件监听器。
+ * 移除全局自定义事件监听器
* @param eventName
* @param callBack
* @returns {Promise}
@@ -277,15 +298,15 @@ module.exports = {
return;
}
- const listener = async (data) => {
- try {
- // 调用外部传入的回调函数
- await callBack(data);
- } catch (error) {
- console.error(`Error executing callback for event ${eventName}:`, error);
- }
- };
+ // 获取存储的监听器
+ const listener = eventListeners.get(eventName);
+ if (listener) {
+ uni.$off(eventName, listener);
+ eventListeners.delete(eventName);
+ }
+ },
- uni.$off(eventName, listener);
+ async remoteUnLock(){
+ return await remoteUnLock()
}
}