fastbee/yack-mini/miniprogram/pages/device/command/command.js

362 lines
7.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 命令发送页面
*/
const { commandManager } = require('../../../services/command-manager.js');
const { gateway } = require('../../../services/gateway.js');
const storage = require('../../../utils/storage.js');
const app = getApp();
Page({
data: {
device: null,
activeTab: 0,
tabs: ['预设命令', '自定义', '发送历史'],
// 预设命令
commands: [],
// 自定义输入
customHex: '',
customName: '',
// 发送历史
history: [],
// BLE连接状态
bleConnected: false,
// 编辑弹窗
showEditModal: false,
editMode: 'add', // 'add' 或 'edit'
editCommand: null,
editName: '',
editHex: '',
},
onLoad(options) {
const sn = options.sn;
if (!sn) {
wx.showToast({ title: '设备信息缺失', icon: 'none' });
setTimeout(() => wx.navigateBack(), 500);
return;
}
// 获取设备信息
let device = storage.getDevice(sn);
if (!device) {
wx.showToast({ title: '设备不存在', icon: 'none' });
setTimeout(() => wx.navigateBack(), 500);
return;
}
this.setData({ device });
this.loadCommands();
this.loadHistory();
this.checkConnectionStatus();
},
onShow() {
// 订阅网关状态
if (!this._unsub) {
this._unsub = gateway.subscribe(() => this.checkConnectionStatus());
}
this.checkConnectionStatus();
},
onHide() {
if (this._unsub) {
this._unsub();
this._unsub = null;
}
},
/**
* 加载预设命令
*/
loadCommands() {
const commands = commandManager.getCommands(this.data.device.serialNumber);
this.setData({ commands });
},
/**
* 加载发送历史
*/
loadHistory() {
const history = commandManager.getHistory(this.data.device.serialNumber);
// 格式化时间
const formattedHistory = history.map(item => ({
...item,
sendTime: this._formatTime(item.sendTime),
}));
this.setData({ history: formattedHistory });
},
/**
* 检查连接状态
*/
checkConnectionStatus() {
const snap = gateway.getSnapshot();
const isActive = snap.device && snap.device.serialNumber === this.data.device.serialNumber;
this.setData({
bleConnected: isActive && snap.bleConnected,
});
},
/**
* 切换 Tab
*/
switchTab(e) {
const index = e.currentTarget.dataset.index;
this.setData({ activeTab: index });
// 切换到历史 tab 时重新加载
if (index === 2) {
this.loadHistory();
}
},
/**
* 输入自定义命令
*/
onCustomHexInput(e) {
this.setData({ customHex: e.detail.value.toUpperCase() });
},
/**
* 输入命令名称
*/
onCustomNameInput(e) {
this.setData({ customName: e.detail.value });
},
/**
* 发送自定义命令
*/
async handleSendCustom() {
const { customHex, customName, device } = this.data;
if (!customHex) {
wx.showToast({ title: '请输入命令', icon: 'none' });
return;
}
await this._sendCommand(customHex, customName || '自定义命令');
},
/**
* 选择预设命令
*/
async handleSelectCommand(e) {
const index = e.currentTarget.dataset.index;
const command = this.data.commands[index];
if (!command) return;
await this._sendCommand(command.hex, command.name, command.id);
},
/**
* 发送命令(核心方法,固定使用BLE)
*/
async _sendCommand(hex, name, commandId) {
const { device, bleConnected } = this.data;
// 检查BLE连接状态
if (!bleConnected) {
wx.showToast({ title: 'BLE 未连接,请先连接设备', icon: 'none' });
return;
}
wx.showLoading({ title: '发送中...', mask: true });
try {
// 固定使用BLE方式发送
await commandManager.sendCommand(hex, 'BLE', device, { name });
// 更新命令使用次数
if (commandId) {
commandManager.incrementUseCount(commandId);
}
wx.hideLoading();
wx.showToast({ title: '发送成功', icon: 'success' });
// 刷新历史
this.loadHistory();
} catch (err) {
wx.hideLoading();
wx.showToast({
title: err.message || '发送失败',
icon: 'none',
});
}
},
/**
* 显示添加命令弹窗
*/
handleAddCommand() {
this.setData({
showEditModal: true,
editMode: 'add',
editCommand: null,
editName: '',
editHex: '',
});
},
/**
* 编辑命令
*/
handleEditCommand(e) {
const index = e.currentTarget.dataset.index;
const command = this.data.commands[index];
if (!command) return;
this.setData({
showEditModal: true,
editMode: 'edit',
editCommand: command,
editName: command.name,
editHex: command.hex,
});
},
/**
* 取消编辑
*/
handleCancelEdit() {
this.setData({
showEditModal: false,
editCommand: null,
editName: '',
editHex: '',
});
},
/**
* 阻止事件冒泡(空方法)
*/
stopPropagation() {
// 阻止事件冒泡,什么都不做
},
/**
* 编辑命令输入
*/
onEditNameInput(e) {
this.setData({ editName: e.detail.value });
},
onEditHexInput(e) {
this.setData({ editHex: e.detail.value.toUpperCase() });
},
/**
* 删除命令
*/
handleSaveCommand() {
const { editMode, editName, editHex, device, editCommand } = this.data;
if (!editName || editName.trim() === '') {
wx.showToast({ title: '请输入命令名称', icon: 'none' });
return;
}
if (!editHex || editHex.trim() === '') {
wx.showToast({ title: '请输入命令', icon: 'none' });
return;
}
// 验证命令格式
const hex = editHex.replace(/\s+/g, '').toUpperCase();
if (!/^[0-9A-F]+$/.test(hex) || hex.length % 2 !== 0) {
wx.showToast({ title: '命令格式错误', icon: 'none' });
return;
}
const command = {
name: editName.trim(),
hex: hex,
deviceId: device.serialNumber,
};
if (editMode === 'add') {
const success = commandManager.addCommand(command);
if (!success) {
wx.showToast({ title: '命令名称已存在', icon: 'none' });
return;
}
wx.showToast({ title: '添加成功', icon: 'success' });
} else {
// 编辑模式
if (!editCommand || !editCommand.id) {
wx.showToast({ title: '编辑失败', icon: 'none' });
return;
}
command.id = editCommand.id;
commandManager.updateCommand(command);
wx.showToast({ title: '修改成功', icon: 'success' });
}
this.setData({
showEditModal: false,
editCommand: null,
editName: '',
editHex: '',
});
this.loadCommands();
},
/**
* 删除命令
*/
handleDeleteCommand(e) {
const index = e.currentTarget.dataset.index;
const command = this.data.commands[index];
if (!command) return;
wx.showModal({
title: '删除命令',
content: `确定删除命令 "${command.name}" 吗?`,
confirmColor: '#ff4d4f',
success: (res) => {
if (res.confirm) {
commandManager.removeCommand(command.id);
this.loadCommands();
wx.showToast({ title: '已删除', icon: 'success' });
}
},
});
},
/**
* 清空发送历史
*/
handleClearHistory() {
wx.showModal({
title: '清空历史',
content: '确定清空今天的发送历史吗?',
confirmColor: '#ff4d4f',
success: (res) => {
if (res.confirm) {
commandManager.clearHistory();
this.loadHistory();
wx.showToast({ title: '已清空', icon: 'success' });
}
},
});
},
/**
* 格式化时间
*/
_formatTime(timestamp) {
const date = new Date(timestamp);
const h = date.getHours().toString().padStart(2, '0');
const m = date.getMinutes().toString().padStart(2, '0');
const s = date.getSeconds().toString().padStart(2, '0');
return `${h}:${m}:${s}`;
},
});