个人案例
小微智能体
扣子Coze智能体转微信小程序工具
小微智能体:AI智能体秒变小程序解决方案扫码体验
图片太大会自动压缩
公众号图片不清晰[图片]为什么微信公众号导入的图片不高清 [图片]
02-26当前小程序异常和官方没关系
小程序打不开?北京警务,无犯罪记录结果,课件打不开,急需处理。 [图片]
02-26你的weixin-js-sdk包引用了吗?
微信小程序加载h5页面,h5页面中跳转小程序页面,模拟器可以跳转,真机上不能跳转?我在h5页面中使用了: wx.miniProgram.navigateTo({ url: `../detail/detail`, }) 跳转到小程序中的detail页面;在模拟器上调试的时候可以正常跳转,在真机上点击跳转不跳转,这是为什么?
02-26不是本地网络就是服务器问题
小程序运行出现问题?2月5日,上午。登录小程序时发现,小程序不显示图片,不显示文本、不能登录,(有两个关联的小程序,都是这样) 做的一个相关的后台网站也无法登录(要输入验证码,但验证码不显示)(通过这个网站给小程序上图,修改文档。) 检查后服务器,域名,ssl等没有过期。但到了中午,发现小程序又自动恢复正常了。 这是什么问题,有谁知道能回答下吗,谢谢。
02-26不支持,走H5吧
2025年了,wx.chooseMessageFile() 现在支持PC端使用了吗?wx.chooseMessageFile() 现在支持PC端使用了吗?
02-26ID错误
微信小程序模板消息发送报错invalid template_id rid,错误原因是什么?template_id: 'Y254_oUy19b0XdL3rAW9TcyOTqaW_EBRtw3NXCBzE7M' appid: 'wxfee8004e46043d94' [图片]
02-26找下人工客服
小程序,无法备案,无法变更主体,无法注销。形成死锁,怎么解决?我的小程序是用个体户注册的,可是我的个体户之前已经注销了。 [图片] 我昨天上架完小程序,就去备案。 备案的时候,被退回,退回理由,让我更换主体,所以无法进行备案。 [图片] 我就去更换主体,在倒数第二步的时候,要微信扫码验证之前的法人,结果扫完还是提示个体已注销,无法验证,所以也没有办法更换主体了。 最后,我就想,直接注销吧,最后一步也是让验证,小额打款也不行,所以怎么解决? [图片] 官方能不能给直接注销?我这是注也注销不了,也无法更换主体,备案更不行。所有方法都试了! 原始ID:gh_dfe3db43ca54
02-26这个代码片段格式没有人能看得懂呀
原生小程序 TS 切换到后台,再切回来所有和websocket+ mqtt相关操作都失效原生小程序 TS 现在切屏就重新连接 websocket mqtt ,设置五分钟延迟断连保活也没生效。 // mqtt-client.ts const mqtt = require("../utils/mqtt.min.js"); import { Encrypt, Decrypt } from '../utils/crypto'; // MQTT 消息接口定义 interface MqttMessage { id: string; code: number; msg: string; type: string; ts: number; expired: number; data: { houseId?: string; // 房屋ID houseName?: string; // 房屋名称 role?: number; // 用户角色 deviceCode?: string; online?: boolean; lockStatus?: number; userId?: string; success?: boolean; errorCode?: string; errorMsg?: string; keyType?: string; hijack?: string; password?: string; imgUrl?: string; platform?: string; serialNo?: string; opTime?: number; leaveHouseId?: string; // 被移出的房屋ID }; } interface MqttClient { connected?: boolean; on(event: 'connect' | 'message' | 'error' | 'reconnect' | 'offline' | 'close', callback: (...args: any[]) => void): void; removeListener(event: 'connect' | 'message' | 'error' | 'reconnect' | 'offline' | 'close', callback: (...args: any[]) => void): void; removeAllListeners(event?: 'connect' | 'message' | 'error' | 'reconnect' | 'offline' | 'close'): void; subscribe(topic: string | string[], opts?: any, callback?: (err: Error, granted: any) => void): void; unsubscribe(topic: string | string[], opts?: any, callback?: (err: Error) => void): void; publish(topic: string, message: string): void; end(force?: boolean, opts?: any, cb?: () => void): void; } interface MqttClientConfig { userId: string; familyId: string; deviceCode: string; } interface IClientOptions { clientId: string; username: string; password: string; reconnectPeriod: number; connectTimeout: number; protocol: string; protocolVersion: number; clean: boolean; rejectUnauthorized: boolean; keepalive: number; path: string; will?: { topic: string; payload: string; qos: number; retain: boolean; }; } interface EventEmitter { on(event: string, listener: Function): void; emit(event: string, ...args: any[]): void; off(event: string, listener: Function): void; removeAllListeners?(): void; } // 设备状态接口 interface DeviceStatus { deviceCode: string; online: boolean; lockStatus?: number; lastUpdateTime: number; } // 简单事件发射器实现 class SimpleEventEmitter implements EventEmitter { private listeners: { [event: string]: Function[] } = {}; on(event: string, listener: Function): void { if (!this.listeners[event]) { this.listeners[event] = []; } this.listeners[event].push(listener); } emit(event: string, ...args: any[]): void { if (this.listeners[event]) { this.listeners[event].forEach((listener) => { try { listener(...args); } catch (error) { console.error(`[EventEmitter] Error in listener for event ${event}:`, error); } }); } } off(event: string, listener: Function): void { if (this.listeners[event]) { this.listeners[event] = this.listeners[event].filter(l => l !== listener); } } removeAllListeners(): void { this.listeners = {}; } } // 全局单例实例 let globalClient: SmartDoorMQTTClient | null = null; class SmartDoorMQTTClient { private client: MqttClient | null = null; private config: MqttClientConfig; private eventEmitter: EventEmitter; private deviceStatuses: Map<string, DeviceStatus> = new Map(); private reconnectAttempts: number = 0; private readonly MAX_RECONNECT_ATTEMPTS: number = 15; private isConnecting: boolean = false; private connectionTimer: any = null; private reconnectTimer: any = null; private readonly MQTT_URL = 'wss://iot-door.lloong.com:30013'; private readonly RECONNECT_DELAY = 1000; // 3秒重连延迟 // 新增:记录后台切换前的连接状态 private wasConnectedBeforeBackground: boolean = false; // 新增:消息队列,存储待发送的消息 private messageQueue: Array<{ topic: string, type: string, data: any }> = []; // 新增:连接状态 private _connectingPromise: Promise<void> | null = null; // 新增:重连提示弹窗 private reconnectModal: any = null; private constructor(config: MqttClientConfig) { this.config = config; this.eventEmitter = new SimpleEventEmitter(); this.initDeviceStatus(); // 新增:注册小程序前后台切换事件 this.registerAppEvents(); } // 单例获取方法 public static getInstance(config?: MqttClientConfig): SmartDoorMQTTClient { if (!globalClient && config) { globalClient = new SmartDoorMQTTClient(config); } else if (globalClient && config) { // 更新现有实例的配置 globalClient.updateConfig(config); } return globalClient as SmartDoorMQTTClient; } private updateConfig(config: MqttClientConfig): void { this.config = config; } // 新增:注册小程序前后台切换事件 private registerAppEvents(): void { let backgroundTimer: number; wx.onAppHide(() => { const app = getApp<IAppOption>(); // 优先检查全局导航标记 if (app.globalData.__pageNavigating) { console.log('[MQTT] 页面导航中,保持连接'); return; } // 检查全局标记,判断是否是页面导航 // @ts-ignore - 访问自定义属性 if (getApp() && getApp().__pageNavigating === true) { console.log('[MQTT] 检测到页面导航,不断开连接'); return; } this.wasConnectedBeforeBackground = this.isConnected(); this.closeConnection(1000, "App entering background"); backgroundTimer = setTimeout(() => { this.cleanup(); this.messageQueue = []; }, 5000) as unknown as number; }); wx.onAppShow(() => { const app = getApp<IAppOption>(); // 清除导航标记 if (app.globalData.__pageNavigating) { console.log('[MQTT] 页面导航返回,保持连接'); app.globalData.__pageNavigating = false; return; } // 检查全局标记,判断是否是页面导航 // @ts-ignore - 访问自定义属性 if (getApp() && getApp().__pageNavigating === true) { console.log('[MQTT] 检测到页面导航返回,不触发重连'); // @ts-ignore getApp().__pageNavigating = false; return; } clearTimeout(backgroundTimer); if (this.reconnectTimer) clearTimeout(this.reconnectTimer); this.reconnectTimer = setTimeout(() => { this.handleForegroundReconnect(); }, 300) as unknown as number; }); } // 新增前台重连处理方法 private handleForegroundReconnect(): void { if (!this.wasConnectedBeforeBackground) return; this.showReconnectModal(); this.connect() .then(() => { this.hideReconnectModal(); this.processQueuedMessages(); }) .catch(error => { console.error('[MQTT][AppShow] Failed to reconnect:', error); this.hideReconnectModal(); if (this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) { this.scheduleReconnect(); // 继续按策略重连 } }); } // 新增:显示重连提示弹窗 private showReconnectModal(): void { if (this.reconnectModal) { return; // 已存在弹窗,不重复显示 } try { this.reconnectModal = wx.showLoading({ title: '正在重新连接...', mask: true }); } catch (error) { console.error('[MQTT][ShowReconnectModal] Failed to show modal:', error); } } // 新增:隐藏重连提示弹窗 private hideReconnectModal(): void { if (this.reconnectModal) { try { wx.hideLoading(); this.reconnectModal = null; } catch (error) { console.error('[MQTT][HideReconnectModal] Failed to hide modal:', error); } } } // 新增:手动关闭WebSocket连接方法 private closeConnection(code: number = 1000, reason: string = "Normal closure"): void { try { // 发送静默下线通知(不触发重连) const silentClose = code === 1000 && reason.includes("background"); if (!silentClose) { this.publishServerOffline(); } if (this.client?.connected) { // 发送下线通知 this.publishServerOffline(); // 取消订阅 if (this.config.userId && this.config.familyId) { const userTopic = `mquser-to-${this.config.userId}`; const familyTopic = `mquser-to-${this.config.familyId}`; this.client.unsubscribe([userTopic, familyTopic], {}, () => { this.cleanup(); }); } else { this.cleanup(); } } else { this.cleanup(); } } catch (error) { console.error('[MQTT][CloseConnection] Error closing connection:', error); this.cleanup(); } } // 新增:处理队列中的消息 private processQueuedMessages(): void { if (this.messageQueue.length === 0) return; if (this.isConnected()) { // 处理队列中的所有消息 const messages = [...this.messageQueue]; this.messageQueue = []; messages.forEach(msg => { try { this.publishMessage(msg.topic, msg.type, msg.data); } catch (error) { console.error('[MQTT][ProcessQueue] Failed to publish queued message:', error); } }); } else { console.warn('[MQTT][ProcessQueue] Client not connected, messages remain queued'); } } // 初始化设备状态 private initDeviceStatus(): void { try { const storedStatuses = wx.getStorageSync('deviceStatuses'); if (storedStatuses) { this.deviceStatuses = new Map(JSON.parse(storedStatuses)); console.log('[MQTT][InitDeviceStatus] Loaded stored statuses:', Array.from(this.deviceStatuses.entries())); } } catch (error) { console.error('[MQTT][InitDeviceStatus] Error loading stored statuses:', error); } } // 保存设备状态 private saveDeviceStatuses(): void { try { const statusesArray = Array.from(this.deviceStatuses.entries()); wx.setStorageSync('deviceStatuses', JSON.stringify(statusesArray)); } catch (error) { console.error('[MQTT][SaveDeviceStatuses] Error saving statuses:', error); } } // 连接状态检查 public isConnected(): boolean { return this.client?.connected || false; } // 连接方法,修改为返回 Promise public connect(): Promise<void> { // 如果已有连接进程在进行,返回现有 Promise // 增加状态检查 if (this.isConnected()) { return Promise.resolve(); } // 增加网络状态检查 wx.getNetworkType({ success: res => { if (res.networkType === 'none') { throw new Error('No network connection'); } } }); if (this._connectingPromise) { return this._connectingPromise; } if (this.isConnecting) { this._connectingPromise = new Promise((resolve, reject) => { const checkInterval = setInterval(() => { if (this.isConnected()) { clearInterval(checkInterval); resolve(); } }, 500); // 设置超时 setTimeout(() => { clearInterval(checkInterval); reject(new Error('Connection timeout while waiting for existing connection')); }, 2000); }); return this._connectingPromise; } // 创建新的连接 Promise this._connectingPromise = new Promise((resolve, reject) => { try { this.isConnecting = true; // 清理现有连接 if (this.client) { this.cleanup(); } const clientId = `mquser-xcx-cid-${this.config.userId}-${Date.now()}`; const willMessage: MqttMessage = { id: Math.random().toString(16).substr(2, 16), code: 0, msg: "success", type: "server/offline", ts: Date.now(), expired: Date.now() + 86400000, data: { userId: this.config.userId, platform: "wechat" } }; const willTopic = "mqsvr-to-iot-door-user"; const encryptedWillMessage = Encrypt(JSON.stringify(willMessage)); const options: IClientOptions = { clientId: clientId, username: "xcxtest", password: "xcxtest", reconnectPeriod: 1000, connectTimeout: 1000, protocol: 'wxs', protocolVersion: 4, clean: true, rejectUnauthorized: false, keepalive: 10, path: '/mqtt', will: { topic: willTopic, payload: encryptedWillMessage, qos: 1, retain: false } }; // 设置连接超时处理 this.connectionTimer = setTimeout(() => { if (this.isConnecting) { this.cleanup(); this.scheduleReconnect(); this.eventEmitter.emit('connectionTimeout'); reject(new Error('Connection timeout')); this._connectingPromise = null; } }, options.connectTimeout); this.client = mqtt.connect(this.MQTT_URL, options); if (!this.client) { throw new Error('Failed to create MQTT client instance'); } // 修改事件监听器,添加Promise处理 this.client.on('connect', () => { this.isConnecting = false; this.reconnectAttempts = 0; if (this.connectionTimer) { clearTimeout(this.connectionTimer); this.connectionTimer = null; } this.handleConnect(); resolve(); // 解决Promise this._connectingPromise = null; }); this.setupEventListeners(() => { // 在出错时reject Promise reject(new Error('Connection failed or was closed')); this._connectingPromise = null; }); } catch (error) { console.error('[MQTT][Connect] Setup failed:', error); this.cleanup(); this.scheduleReconnect(); reject(error); this._connectingPromise = null; } }); return this._connectingPromise; } // 修改 scheduleReconnect 方法 private scheduleReconnect(): void { if (this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) { this.eventEmitter.emit('maxReconnectAttemptsReached'); this.showReconnectFailedToast(); return; } // 使用固定延迟,不再使用指数退避策略 const delay = this.RECONNECT_DELAY; this.reconnectTimer = setTimeout(() => { this.connect().catch(console.error); }, delay); this.reconnectAttempts++; } // 新增重连失败提示 private showReconnectFailedToast(): void { wx.showToast({ title: '连接断开,请检查网络', icon: 'none', duration: 2000 }); } private cleanup(): void { this.reconnectAttempts = 0; // 新增 // 清除所有定时器 [this.connectionTimer, this.reconnectTimer].forEach(timer => { if (timer) { clearTimeout(timer); timer = null; } }); // 强制关闭连接 if (this.client) { try { this.client.removeAllListeners(); this.client.end(true); } catch (error) { console.error('[MQTT][Cleanup] Error during cleanup:', error); } this.client = null; } // 重置状态 this.isConnecting = false; this._connectingPromise = null; this.reconnectAttempts = 0; // 重置重试次数 } private setupEventListeners(onError?: () => void): void { if (!this.client) { if (onError) onError(); return; } this.client.on('message', (topic: string, payload: string | ArrayBuffer) => { this.handleMessage(topic, payload); }); this.client.on('error', (error: Error) => { this.handleError(error); if (onError) onError(); }); this.client.on('offline', () => { this.handleOffline(); }); this.client.on('close', () => { this.scheduleReconnect(); if (onError) onError(); }); this.client.on('reconnect', () => { this.reconnectAttempts++; if (this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) { console.error('[MQTT][Event:Reconnect] Max reconnection attempts reached'); this.cleanup(); this.eventEmitter.emit('maxReconnectAttemptsReached'); if (onError) onError(); } }); } private handleConnect(): void { if (!this.client) { console.error('[MQTT][HandleConnect] Cannot handle connect - client is null'); return; } const userTopic = `mquser-to-${this.config.userId}`; const familyTopic = `mquser-to-${this.config.familyId}`; this.client.subscribe([userTopic, familyTopic], { qos: 1 }, (err, granted) => { if (err) { console.error('[MQTT][HandleConnect] Subscribe error:', err); return; } console.log('[MQTT][HandleConnect] Subscribe success:', granted); this.publishUserOnline(); }); } private decodeMessage(payload: string | ArrayBuffer): string { if (typeof payload === 'string') { return payload; } return typeof TextDecoder !== 'undefined' ? new TextDecoder().decode(payload) : this.arrayBufferToString(payload); } private arrayBufferToString(buffer: ArrayBuffer): string { const uint8Array = new Uint8Array(buffer); let result = ''; for (let i = 0; i < uint8Array.length; i++) { result += String.fromCharCode(uint8Array[i]); } return result; } private handleUserJoinHouse(message: MqttMessage): void { try { wx.setStorageSync('has_new_house', true); } catch (e) { console.error('[MQTT] Failed to set refresh flag:', e); } // 仍然触发事件以保持兼容性 this.eventEmitter.emit('userJoinHouse'); } private handleMessage(topic: string, payload: string | ArrayBuffer): void { try { console.log('[MQTT][HandleMessage] 收到消息 - 主题:', topic); const message = this.decodeMessage(payload); const parsedMessage = JSON.parse(Decrypt(message)) as MqttMessage; console.log('[MQTT][HandleMessage] 解密消息 - 类型:', parsedMessage.type, 'ID:', parsedMessage.id); switch (parsedMessage.type) { case 'family/user_online': console.log('[MQTT][HandleMessage] 处理家庭用户上线消息'); this.handleFamilyUserOnline(parsedMessage); break; case 'server/offline': console.log('[MQTT][HandleMessage] 处理服务器离线消息'); this.handleServerOffline(parsedMessage); break; case 'user/door_status': console.log('[MQTT][HandleMessage] 处理用户门锁状态消息'); this.handleUserDoorStatus(parsedMessage); break; case 'family/door_status': console.log('[MQTT][HandleMessage] 处理家庭门锁状态消息'); this.handleDoorStatus(parsedMessage); break; case 'user/online_status': console.log('[MQTT][HandleMessage] 处理用户在线状态消息'); this.handleUserOnlineStatus(parsedMessage); break; case 'user/add_key_success': console.log('[MQTT][HandleMessage] 处理添加密钥成功消息'); this.handleAddKeySuccess(parsedMessage); break; case 'door/lock_status': console.log('[MQTT][HandleMessage] 处理门锁状态消息'); this.handleDoorLockStatus(parsedMessage); break; case 'door/open_door_result': console.log('[MQTT][HandleMessage] 处理开门结果消息'); this.handleOpenDoorResult(parsedMessage); break; case 'door/delete_key_result': console.log('[MQTT][HandleMessage] 处理删除密钥结果消息'); this.handleDeleteKeyResult(parsedMessage); break; case 'door/add_key_result': console.log('[MQTT][HandleMessage] 处理添加密钥结果消息'); this.handleAddKeyResult(parsedMessage); break; case 'door/wallpaper_result': console.log('[MQTT][HandleMessage] 处理壁纸结果消息'); this.handleWallpaperResult(parsedMessage); break; case 'user/reset_device': console.log('[MQTT][HandleMessage] 处理重置设备消息'); this.handleResetDevice(parsedMessage); break; case 'user/join_house': console.log('[MQTT][HandleMessage] 处理加入房屋消息'); this.handleUserJoinHouse(parsedMessage); break; case 'user/leave_house': console.log('[MQTT][HandleMessage] 处理离开房屋消息'); this.handleUserLeaveHouse(parsedMessage); break; case 'user/house_user_role': console.log('[MQTT][HandleMessage] 处理房屋用户角色消息'); this.handleHouseUserRole(parsedMessage); break; default: console.log('[MQTT][HandleMessage] 未知消息类型:', parsedMessage.type); break; } } catch (error) { console.error('[MQTT][HandleMessage] Processing error:', error); } } private handleHouseUserRole(message: MqttMessage): void { const { houseId } = message.data; if (!houseId) return; // 触发权限变更事件,传递房屋ID this.eventEmitter.emit('houseUserRole', { houseId }); } private handleUserLeaveHouse(message: MqttMessage): void { // 触发事件,由页面处理刷新逻辑 this.eventEmitter.emit('userLeaveHouse'); } private handleResetDevice(message: MqttMessage): void { const { serialNo, opTime } = message.data; if (!serialNo) return; this.eventEmitter.emit('deviceReset', { serialNo, opTime }); Array.from(this.deviceStatuses.keys()).forEach(deviceCode => { this.deviceStatuses.delete(deviceCode); }); this.saveDeviceStatuses(); } private handleFamilyUserOnline(message: MqttMessage): void { const { userId } = message.data; if (!userId) return; this.eventEmitter.emit('familyUserOnline', { userId }); } private handleUserDoorStatus(message: MqttMessage): void { const { deviceCode, online, lockStatus } = message.data; if (!deviceCode) return; this.updateDeviceStatus(deviceCode, { online: online ?? true, lockStatus }); this.eventEmitter.emit('doorLockStatusChanged', { deviceCode, online, lockStatus }); } private handleServerOffline(message: MqttMessage): void { const { userId, platform } = message.data; if (!userId || !platform) return; this.eventEmitter.emit('serverOffline', { userId, platform }); } private handleUserOnlineStatus(message: MqttMessage): void { const { deviceCode, online } = message.data; if (!deviceCode || online === undefined) return; this.updateDeviceStatus(deviceCode, { online }); } private handleDoorStatus(message: MqttMessage): void { const { deviceCode, online, lockStatus } = message.data; if (!deviceCode) return; this.updateDeviceStatus(deviceCode, { online, lockStatus }); if (online) { this.publishDoorOnlineStatus(deviceCode); } } private handleDoorLockStatus(message: MqttMessage): void { const { deviceCode, lockStatus } = message.data; console.log('[MQTT][HandleDoorLockStatus] 收到门锁状态更新 - 设备码:', deviceCode, '状态:', lockStatus); if (!deviceCode || lockStatus === undefined) { console.warn('[MQTT][HandleDoorLockStatus] 收到无效的门锁状态消息'); return; } // 更新设备状态并触发事件 this.updateDeviceStatus(deviceCode, { lockStatus }); console.log('[MQTT][HandleDoorLockStatus] 更新设备状态并触发事件'); this.eventEmitter.emit('doorLockStatusChanged', { deviceCode, lockStatus }); } private handleAddKeySuccess(message: MqttMessage): void { this.eventEmitter.emit('addKeySuccess', message); } private handleOpenDoorResult(message: MqttMessage): void { const { deviceCode, success, errorCode, errorMsg } = message.data; console.log('[MQTT][HandleOpenDoorResult] 收到开门结果 - 设备码:', deviceCode, '成功:', success, '错误码:', errorCode || 'N/A', '错误信息:', errorMsg || 'N/A'); if (!deviceCode || success === undefined) { console.warn('[MQTT][HandleOpenDoorResult] 收到无效的开门结果消息'); return; } this.eventEmitter.emit('openDoorResult', { deviceCode, success, errorCode, errorMsg }); if (!success) { // 只有在开门失败时才立即更新状态 console.log('[MQTT][HandleOpenDoorResult] 开门失败,更新锁状态为已上锁'); this.updateDeviceStatus(deviceCode, { lockStatus: 2 }); this.eventEmitter.emit('openDoorFailed', { deviceCode, errorCode, errorMsg }); } } private handleDeleteKeyResult(message: MqttMessage): void { const { deviceCode, success, errorCode, errorMsg } = message.data; if (!deviceCode || success === undefined) return; this.eventEmitter.emit('deleteKeyResult', { deviceCode, success, errorCode, errorMsg }); } private handleAddKeyResult(message: MqttMessage): void { const { deviceCode, success, errorCode, errorMsg } = message.data; if (!deviceCode || success === undefined) return; this.eventEmitter.emit('addKeyResult', { deviceCode, success, errorCode, errorMsg }); } private handleWallpaperResult(message: MqttMessage): void { const { deviceCode, success, errorCode, errorMsg } = message.data; if (!deviceCode || success === undefined) return; this.eventEmitter.emit('wallpaperResult', { deviceCode, success, errorCode, errorMsg }); } private handleError(error: Error): void { this.eventEmitter.emit('error', error); } private handleOffline(): void { this.eventEmitter.emit('offline'); } private updateDeviceStatus(deviceCode: string, updates: Partial<DeviceStatus>): void { const currentStatus = this.deviceStatuses.get(deviceCode) || { deviceCode, online: false, lastUpdateTime: Date.now() }; const newStatus = { ...currentStatus, ...updates, lastUpdateTime: Date.now() }; this.deviceStatuses.set(deviceCode, newStatus); this.saveDeviceStatuses(); this.eventEmitter.emit('deviceStatusChanged', newStatus); if (updates.online !== undefined) { this.eventEmitter.emit('deviceOnlineStatusChanged', { deviceCode, online: updates.online }); } } // 公共方法 public getDeviceStatus(deviceCode: string): DeviceStatus | null { return this.deviceStatuses.get(deviceCode) || null; } public getLockStatusText(status?: number): string { switch (status) { case 0: return '开锁中'; case 1: return '已开门'; case 2: return '已上锁'; default: return '未知状态'; } } public updateDeviceCode(deviceCode: string): void { this.config.deviceCode = deviceCode; } public on(event: string, listener: Function): void { this.eventEmitter.on(event, listener); } public off(event: string, listener: Function): void { this.eventEmitter.off(event, listener); } public removeAllListeners(): void { if (this.eventEmitter.removeAllListeners) { this.eventEmitter.removeAllListeners(); } } // 修改消息发布方法,添加连接状态检查和消息队列 private publishMessage(topic: string, type: string, data: any): void { console.log('[MQTT][PublishMessage] 准备发布消息 - 主题:', topic, '类型:', type, '数据:', JSON.stringify(data)); if (!this.isConnected()) { console.log('[MQTT][PublishMessage] MQTT未连接,将消息加入队列'); // 将消息添加到队列 this.messageQueue.push({ topic, type, data }); // 如果没有连接,尝试重新连接 if (!this.isConnecting && !this._connectingPromise) { console.log('[MQTT][PublishMessage] 尝试重新连接'); this.showReconnectModal(); this.connect().then(() => { this.hideReconnectModal(); console.log('[MQTT][PublishMessage] 重连成功,处理队列消息'); this.processQueuedMessages(); }).catch(error => { console.error('[MQTT][PublishMessage] Failed to reconnect:', error); this.hideReconnectModal(); // 显示发送失败提示 wx.showToast({ title: '消息发送失败,请重试', icon: 'none', duration: 2000 }); }); } return; } if (!this.client) { console.error('[MQTT][PublishMessage] 客户端为空,无法发送消息'); throw new Error('Cannot publish - client is null'); } try { const message: MqttMessage = { id: Math.random().toString(16).substr(2, 16), code: 0, msg: "success", type, ts: Date.now(), expired: Date.now() + 86400000, data }; console.log('[MQTT][PublishMessage] 发送消息ID:', message.id); const messageString = JSON.stringify(message); const encryptedMessage = Encrypt(messageString); this.client.publish(topic, encryptedMessage); console.log('[MQTT][PublishMessage] 消息发送成功 - 主题:', topic); } catch (error) { console.error('[MQTT][PublishMessage] Failed to publish:', error); throw error; } } public publishUserOnline(): void { const message = { userId: this.config.userId, platform: "wechat" }; this.publishMessage(`mqdev-to-${this.config.familyId}`, 'family/user_online', message); } // 修改后的 publishServerOffline 方法 public publishServerOffline(): void { try { // 检查客户端连接状态 if (!this.client || !this.client.connected) { return; } const message = { userId: this.config.userId, platform: "wechat" }; // 直接使用 MQTT 客户端发送消息,确保消息能立即发送 try { const mqttMessage: MqttMessage = { id: Math.random().toString(16).substr(2, 16), code: 0, msg: "success", type: "server/offline", ts: Date.now(), expired: Date.now() + 86400000, data: message }; const messageString = JSON.stringify(mqttMessage); const encryptedMessage = Encrypt(messageString); // 修改:使用新的 topic const topic = "mqsvr-to-iot-door-user"; // 修正:只传递两个参数 - 主题和消息内容 this.client.publish(topic, encryptedMessage); } catch (error) { console.error('[MQTT][PublishServerOffline] 直接发送消息失败:', error); // 如果直接发送失败,尝试使用队列方式发送(也使用新的 topic) this.publishMessage("mqsvr-to-iot-door-user", 'server/offline', message); } } catch (error) { console.error('[MQTT][PublishServerOffline] 发送离线消息失败:', error); } } // 修改后的 handleLogout 方法 public handleLogout(): void { try { // 先发送离线消息,确保消息发送 if (this.client && this.client.connected) { try { // 直接使用 MQTT 客户端发送消息 const message = { userId: this.config.userId, platform: "wechat", online: false }; const mqttMessage: MqttMessage = { id: Math.random().toString(16).substr(2, 16), code: 0, msg: "success", type: "server/offline", ts: Date.now(), expired: Date.now() + 86400000, data: message }; const messageString = JSON.stringify(mqttMessage); const encryptedMessage = Encrypt(messageString); // 修改:使用新的 topic const topic = "mqsvr-to-iot-door-user"; // 修正:只传递两个参数 - 主题和消息内容 this.client.publish(topic, encryptedMessage); } catch (error) { } // 延迟一点时间确保消息能发送出去 setTimeout(() => { this.cleanup(); globalClient = null; }, 300); } else { this.cleanup(); globalClient = null; } // 清理设备状态和消息队列 this.deviceStatuses.clear(); this.saveDeviceStatuses(); this.messageQueue = []; } catch (error) { this.cleanup(); globalClient = null; } } public publishDoorOnlineStatus(deviceCode: string): void { const message = { deviceCode: deviceCode, online: true }; this.publishMessage(`mqdev-to-${deviceCode}`, 'door/online_status', message); } // 修改开门方法,添加连接状态检查 public publishOpenDoor(deviceCode: string): void { console.log('[MQTT][PublishOpenDoor] 准备发送开门指令 - 设备码:', deviceCode); if (!this.isConnected()) { console.log('[MQTT][PublishOpenDoor] MQTT未连接,取消操作'); wx.showToast({ title: '正在连接,请稍后重试', icon: 'none', duration: 2000 }); return; } const message = { userId: this.config.userId }; console.log('[MQTT][PublishOpenDoor] 发送开门消息 - 用户ID:', this.config.userId); this.publishMessage(`mqdev-to-${deviceCode}`, 'door/open_door', message); } public publishAddKey(deviceCode: string, keyType: string, password?: string, hijack: string = 'false'): void { const data: MqttMessage['data'] = { userId: this.config.userId, keyType, hijack }; if (password) { data.password = password; } this.publishMessage(`mqdev-to-${deviceCode}`, 'door/start_add_key', data); } public publishDeleteKey(deviceCode: string, key: any): void { this.publishMessage(`mqdev-to-${deviceCode}`, 'door/delete_key', key); } public publishResetDevice(deviceCode: string): void { const message = { deviceCode, userId: this.config.userId }; this.publishMessage(`mqdev-to-${deviceCode}`, 'door/reset_device', message); } public publishAddHouseUser(deviceCode: string): void { this.publishMessage(`mqdev-to-${deviceCode}`, 'door/house_user_add', {}); } public publishUpdateWallpaper(deviceCode: string, imgUrl: string): void { const message = { imgUrl }; this.publishMessage(`mqdev-to-${deviceCode}`, 'door/wallpaper', message); } } export default SmartDoorMQTTClient;
02-26搜索算法是动态变化的
小程序在微信搜一搜下服务的关键词突然无法搜索到?在2025年2月5日之前,小程序通过微信搜一搜的服务关键词可以正常搜索到,展示和流量均无异常。 然而,自2025年2月5日起,搜索服务关键词时,小程序不再展示在前端,需下拉至底部才能找到,且小程序前端未显示服务标签。此时,小程序后台的服务关键词状态显示为在线,站内信没收到任何违规信息,然展示和流量全部丢失,新增用户直接变为0。 经核查,发现小程序后台的【小程序评测】于2025年2月5日突然变为【审核中】状态,推测这可能影响了服务关键词的展示。至2025年2月15日,审核通过,综合评测结果显示已达标。尽管如此,小程序的服务关键词仍无法通过搜索展示,导致搜一搜流量降至零。 [图片] 奇怪的是,微信搜一搜的昨日运营数据的引流人数,但是实际新增人数为0 [图片] 在此期间,曾多次联系微信搜一搜公众号客服寻求帮助。目前问题仍未解决,服务关键词搜索展示功能持续失效,对小程序流量和用户体验造成了较大影响。 希望微信小程序团队能够尽快帮我司定位问题原因。 [图片] AppID(小程序ID): wxf261ca909029b83f
02-26已体验👍,以下为体验的教程《3行代码搞定微信小程序接入DeepSeek满血版!》
有奖体验 | 微信云开发支持扩展调用AI大模型,你体验了没?伴随 AI 的高速发展,有越来越多的小程序开发者也想将自己的小程序接入AI大模型,实现智能对话、文本生成等功能,近期微信云开发的更新了扩展调用的AI大模型能力,各位开发者可参考如下教程进行体验: 针对小程序开发,云开发准备了三种「快连」方式——SDK 直连、智能体对话、AI对话组件一键接入 ,适配不同场景 1.非对话类的通用场景,如文本生成、智能补全、智能翻译等。 2.AI 对话场景,支持配置欢迎语、提示词、知识库等对话中需要的能力。 3.快速在小程序中植入 AI 对话能力,更快速友好。 方式一:SDK 直连大模型,最少仅需3行代码直接使用小程序端的代码调用模型 [图片] 方式二:创建一个智能体使用自定义创建或者模板创建(两者任选)的方式,创建智能体,接入后可调用体验云开发SDK ,支持调用整套AI扩展能力的 API 接口,实现基础对话、对话历史保存、对话反馈收集、次轮问题推荐。 自定义创建 [图片] 模板创建 [图片] 方式三:在现有小程序、公众号服务号、小程序客服、微信客服调用对话组件使用云开发AI对话的小程序集成到现有小程序。 [图片] 同时,云开发团队准备了完整的接入文档和代码示例,开发者们可以参考以下文档和代码仓库进行开发 - 小程序接入云开发 AI 能力文档: https://docs.cloudbase.net/ai/miniprogram-using - 云开发 AI 能力示例仓库: Gitee:https://gitee.com/TencentCloudBase/cloudbase-ai-example Github:https://github.com/TencentCloudBase/cloudbase-ai-example 目前以上能力已经全面公测,欢迎各位开发者朋友们前往体验,未来我们也计划推出更多的 AI 能力,如 Tool Calling(工具调用)、多 Agent 串联、工作流编排等,敬请期待,也欢迎大家在评论区中提出建议。 即日起3月18日,欢迎大家在下方评论区分享使用微信云开发扩展调用AI大模型以及使用场景(听说有图有真相,效果更加棒 ʕ•͡ᴥ•ʔ),精选评论的用户将获得周边礼品 1 份。🎁 [图片] 准备工作● 注册一个微信小程序账号,并且创建本地小程序工程项目 ● 小程序基础库需要在 3.7.1 及以上版本,具备 wx.cloud.extend.AI 对象 ● 小程序需要开通「云开发」,可在小程序开发工具中点击工具栏里的「云开发」按钮进行开通,并创建环境(PS:对于首次使用云开发的用户,第一个月套餐免费): [图片]
02-20