diff --git a/common/api/request.js b/common/api/request.js index 003fdeb..5bb1c82 100644 --- a/common/api/request.js +++ b/common/api/request.js @@ -4,6 +4,7 @@ export default (params) => { let data = params.data || {}; let type = params.type || 1; let toast = params.toast || true; + let userInfo=uni.cache.get('userInfo')||{id:''} let header = { version: uni.conf.version, type: uni.getSystemInfoSync().platform, @@ -20,9 +21,9 @@ export default (params) => { platformType: 'ALI', // #endif token: uni.cache.get('token') || '', - id: uni.cache.get('userInfo').id || '', + id: userInfo.id , shopId: uni.cache.get('shopId') || '', - userId: uni.cache.get('userInfo').id || '', + userId:userInfo.id } if (toast) { uni.showLoading({ diff --git a/common/js/websocket - 副本.js b/common/js/websocket - 副本.js new file mode 100644 index 0000000..a4138e0 --- /dev/null +++ b/common/js/websocket - 副本.js @@ -0,0 +1,350 @@ +import { + ref, + onMounted, + onBeforeUnmount +} from 'vue'; + +const useWebSocket = (options = {}) => { + const { + heartbeatInterval = 10000, //心跳是10秒一次 + reconnectInterval = 3000, //重新连接间隔时间的一个参数 + maxReconnectAttempts = 3, //最大重连接次数 + initialReconnectInterval = 3000, // 初始重连间隔 + initMessage, + initMessageRetryCount = 3, // 新增:初始化消息发送重试次数 + initMessageRetryInterval = 2000, // 新增:初始化消息重试间隔 + maxReconnectDuration = Infinity + } = options; + + const autoReconnect = ref(true); //是否自动重新连接 + const socketTask = ref(null); + const isConnected = ref(false); //表示是否已连接上。 + const heartbeatTimer = ref(null); //心跳定时器 + const reconnectTimer = ref(null); //重连定时器 + const reconnectAttempts = ref(0); //重连的尝试次数 + const isNetworkConnected = ref(true); //监听当前网络连接状态 + const isManuallyClosed = ref(false); //是否是被手动关闭的 + const receivedMessages = ref(); //储从 WebSocket 服务器接收到的消息 + const initMessageSendAttempts = ref(0); //初始化连接多少次 + const reconnectStartTime = ref(0); //新增:记录重连开始时间 + const isPongReceived = ref(false) + const allowReconnect = ref(true); // 新增:控制是否允许重连 + // 关闭现有连接并清理资源 + const closeExistingConnection = () => { + if (socketTask.value) { + // 关闭 WebSocket 连接 + socketTask.value.close({ + success: () => { + console.log('WebSocket 连接已关闭'); + }, + fail: (err) => { + console.error('关闭 WebSocket 连接失败:', err); + } + }); + + // 清除心跳定时器 + clearInterval(heartbeatTimer.value); + heartbeatTimer.value = null; + + // 清除重连定时器 + clearTimeout(reconnectTimer.value); + reconnectTimer.value = null; + + // 标记连接已断开 + isConnected.value = false; + } + }; + + // 连接 WebSocket + const connect = () => { + if (!isNetworkConnected.value) { + uni.showToast({ + title: '网络未连接...', + icon: 'none' + }) + setTimeout(() => { + uni.pro.switchTab('index/index') + }, 1000) + console.log('网络未连接,暂不尝试连接 WebSocket'); + return; + } + + // 关闭现有连接并清理资源 + closeExistingConnection(); + + socketTask.value = uni.connectSocket({ + url: uni.conf.baseUrlwws, + success: (res) => { + isConnected.value = true; + // 监听初始化成功在开启心跳 + startHeartbeat(); + }, + fail: () => { + console.error('WebSocket 连接失败,尝试重连'); + if (autoReconnect.value && allowReconnect.value) { + handleReconnect(); + } + } + }); + + if (socketTask.value) { + socketTask.value.onOpen(() => { + // 初始化 初始购物车 + sendMessage(initMessage) + }); + socketTask.value.onMessage((res) => { + receivedMessages.value = JSON.parse(res.data) + // receivedMessages.value.push(list); + if (receivedMessages.value == 'ok' || receivedMessages.value.operate_type == 'init') { + console.log('初始化正常,心跳响应正常'); + // 清除重连定时器 + clearTimeout(reconnectTimer.value); + allowReconnect.value = false + reconnectTimer.value = null; + } + + }); + + socketTask.value.onClose((res) => { + console.log(res, 'WebSocket 连接已关闭,尝试重连'); + isConnected.value = false; + clearInterval(heartbeatTimer.value); // 停止心跳定时器 + clearTimeout(reconnectTimer.value); // 清除重连定时器 + if (res.code == '1006' && !allowReconnect.value) { + uni.showToast({ + title: '网络异常,请重新扫码', + icon: 'none' + }); + autoReconnect.value = false; + setTimeout(() => { + uni.pro.switchTab('index/index'); + }, 1000) + return false; + } + if (autoReconnect.value && !isManuallyClosed.value) { + handleReconnect(); + } + }); + + socketTask.value.onError((err) => { + console.error('WebSocket 连接发生错误:', err); + isConnected.value = false; + clearInterval(heartbeatTimer.value); + if (autoReconnect.value && !isManuallyClosed.value) { + handleReconnect(); + } + }); + } else { + console.error('socketTask 未正确初始化'); + } + }; + + // 启动心跳机制 + const startHeartbeat = () => { + if (!isNetworkConnected.value) { + console.log('网络未连接,暂停心跳'); + uni.showToast({ + title: '网络未连接...', + icon: 'none' + }); + setTimeout(() => { + uni.pro.switchTab('index/index'); + }, 1000); + return; + } + heartbeatTimer.value = setInterval(() => { + if (isConnected.value) { + console.log('发送心跳消息'); + isPongReceived.value = false; // 每次发送心跳消息前重置标记 + socketTask.value.send({ + data: JSON.stringify({ + type: 'ping_interval', + set: 'shopping' + }), + success: () => { + console.log('心跳消息发送成功'); + const pongTimer = setTimeout(() => { + if (!isPongReceived.value) { + console.error('心跳超时,未收到响应,尝试重连'); + clearInterval(heartbeatTimer.value); + if (autoReconnect.value && reconnectAttempts.value < + maxReconnectAttempts && allowReconnect.value) { + handleReconnect(); + } else { + console.error('重连次数达到上限,停止重连和心跳'); + clearInterval(heartbeatTimer.value); + autoReconnect.value = false; + uni.pro.switchTab('index/index'); + } + } + }, heartbeatInterval * 1.2); + + const handlePong = (res) => { + try { + let data = JSON.parse(res.data); + if (data.operate_type == "init" || (data.msg === 'ok' && + data.msg_id == + 'ping_interval')) { + isPongReceived.value = true; + console.log('收到心跳响应,清除超时定时器'); + clearTimeout(pongTimer); + } + } catch (error) { + console.error('解析心跳响应数据时出错:', error); + } + }; + socketTask.value.onMessage(handlePong); + }, + fail: () => { + console.error('心跳消息发送失败,尝试重连'); + clearInterval(heartbeatTimer.value); + if (autoReconnect.value && reconnectAttempts.value < + maxReconnectAttempts && allowReconnect.value) { + handleReconnect(); + } else { + console.error('重连次数达到上限,停止重连和心跳'); + clearInterval(heartbeatTimer.value); + autoReconnect.value = false; + uni.pro.switchTab('index/index'); + } + } + }); + } + }, heartbeatInterval); + }; + + + // 手动关闭连接 + const closeSocket = () => { + isManuallyClosed.value = true; + closeExistingConnection(); + }; + + // 发送消息 + const sendMessage = async (data) => { + if (isConnected.value) { + await socketTask.value.send({ + data: JSON.stringify(data), + success: () => { + // console.log('消息发送成功'); + }, + fail: () => { + // console.error('消息发送失败'); + } + }); + } else { + console.error('WebSocket 未连接,无法发送消息'); + } + }; + + // 处理重连逻辑 + const handleReconnect = () => { + if (!isNetworkConnected.value) { + console.log('网络未连接,暂停重连'); + return; + } + if (isManuallyClosed.value) { + console.log('手动关闭连接,不进行重连'); + return; + } + + if (!allowReconnect.value) { + console.log('重连功能已关闭,不进行重连'); + return; + } + + if (reconnectAttempts.value < maxReconnectAttempts) { + reconnectAttempts.value++; + const reconnectInterval = initialReconnectInterval * Math.pow(2, reconnectAttempts.value - 1); + const randomizedInterval = reconnectInterval + Math.floor(Math.random() * 1000); + uni.showLoading({ + title: `正在努力连接..`, + mask: true + }) + console.log(`尝试第 ${reconnectAttempts.value} 次重连,重连间隔: ${randomizedInterval}ms...`); + + reconnectTimer.value = setTimeout(() => { + connect(); + }, randomizedInterval); + } else { + console.error('重连次数达到上限,停止重连'); + uni.showToast({ + title: '重连次数达到上限,停止重连', + icon: 'none' + }); + clearInterval(heartbeatTimer.value); + autoReconnect.value = false; + setTimeout(() => { + uni.hideLoading(); + uni.pro.switchTab('index/index'); + }, 1000) + } + }; + + + // / 网络状态监听 + const initNetworkListener = () => { + uni.getSystemInfo({ + success: (res) => { + if (res.platform !== 'devtools') { + uni.onNetworkStatusChange((statusRes) => { + isNetworkConnected.value = statusRes.isConnected; + if (statusRes.isConnected && !isManuallyClosed.value) { + console.log('网络已连接,尝试重新连接 WebSocket'); + if (!isConnected.value && autoReconnect.value) { + connect(); + } + } else if (!statusRes.isConnected) { + console.log('网络已断开,暂停 WebSocket 操作'); + clearInterval(heartbeatTimer.value); + clearTimeout(reconnectTimer.value); + if (socketTask.value) { + socketTask.value.close(); + isConnected.value = false; + } + } + }); + } + }, + fail: (err) => { + console.error('获取系统信息失败:', err); + } + }); + + uni.getNetworkType({ + success: (res) => { + isNetworkConnected.value = res.networkType !== 'none'; + if (!isNetworkConnected.value) { + console.log('初始网络未连接,暂不尝试连接 WebSocket'); + } + } + }); + }; + + // 页面显示,尝试连接 WebSocket + const onShowconnect = () => { + if (autoReconnect.value) { + uni.showLoading({ + title: `尝试再次连接`, + mask: true + }) + connect(); + } + } + + onBeforeUnmount(() => { + closeSocket(); + }); + + return { + isConnected, + sendMessage, + closeSocket, + receivedMessages, + closeExistingConnection, + onShowconnect, + initNetworkListener + }; +}; + +export default useWebSocket; \ No newline at end of file diff --git a/common/js/websocket.js b/common/js/websocket.js index a4138e0..a9d057e 100644 --- a/common/js/websocket.js +++ b/common/js/websocket.js @@ -31,6 +31,18 @@ const useWebSocket = (options = {}) => { const allowReconnect = ref(true); // 新增:控制是否允许重连 // 关闭现有连接并清理资源 const closeExistingConnection = () => { + // 清除心跳定时器 + clearInterval(heartbeatTimer.value); + heartbeatTimer.value = null; + + // 清除重连定时器 + clearTimeout(reconnectTimer.value); + reconnectTimer.value = null; + + // 标记连接已断开 + isConnected.value = false; + + uni.closeSocket() if (socketTask.value) { // 关闭 WebSocket 连接 socketTask.value.close({ @@ -72,7 +84,7 @@ const useWebSocket = (options = {}) => { // 关闭现有连接并清理资源 closeExistingConnection(); - socketTask.value = uni.connectSocket({ + uni.connectSocket({ url: uni.conf.baseUrlwws, success: (res) => { isConnected.value = true; @@ -87,6 +99,63 @@ const useWebSocket = (options = {}) => { } }); + uni.onSocketOpen(function(res) { + console.log('WebSocket连接已打开!'); + sendMessage(initMessage) + }); + + function sendSocketMessage(msg) { + if (isConnected.value) { + uni.sendSocketMessage({ + data: msg + }); + } else { + socketMsgQueue.push(msg); + } + } + uni.onSocketError(function(res) { + console.log('WebSocket连接打开失败,请检查!'); + console.error('WebSocket 连接发生错误:', err); + isConnected.value = false; + clearInterval(heartbeatTimer.value); + if (autoReconnect.value && !isManuallyClosed.value) { + handleReconnect(); + } + }); + uni.onSocketMessage(function(res) { + console.log('收到服务器内容:' + res.data); + receivedMessages.value = JSON.parse(res.data) + // receivedMessages.value.push(list); + if (receivedMessages.value == 'ok' || receivedMessages.value.operate_type == 'init') { + console.log('初始化正常,心跳响应正常'); + // 清除重连定时器 + clearTimeout(reconnectTimer.value); + allowReconnect.value = false + reconnectTimer.value = null; + } + }); + uni.onSocketClose(function(res) { + console.log('WebSocket 已关闭!'); + console.log(res, 'WebSocket 连接已关闭,尝试重连'); + isConnected.value = false; + clearInterval(heartbeatTimer.value); // 停止心跳定时器 + clearTimeout(reconnectTimer.value); // 清除重连定时器 + if (res.code == '1006' && !allowReconnect.value) { + uni.showToast({ + title: '网络异常,请重新扫码', + icon: 'none' + }); + autoReconnect.value = false; + setTimeout(() => { + uni.pro.switchTab('index/index'); + }, 1000) + return false; + } + if (autoReconnect.value && !isManuallyClosed.value) { + handleReconnect(); + } + }); + if (socketTask.value) { socketTask.value.onOpen(() => { // 初始化 初始购物车 @@ -223,8 +292,8 @@ const useWebSocket = (options = {}) => { // 发送消息 const sendMessage = async (data) => { if (isConnected.value) { - await socketTask.value.send({ - data: JSON.stringify(data), + uni.sendSocketMessage({ + data:JSON.stringify(data), success: () => { // console.log('消息发送成功'); }, @@ -232,6 +301,15 @@ const useWebSocket = (options = {}) => { // console.error('消息发送失败'); } }); + // await socketTask.value.send({ + // data: JSON.stringify(data), + // success: () => { + // // console.log('消息发送成功'); + // }, + // fail: () => { + // // console.error('消息发送失败'); + // } + // }); } else { console.error('WebSocket 未连接,无法发送消息'); } @@ -252,7 +330,7 @@ const useWebSocket = (options = {}) => { console.log('重连功能已关闭,不进行重连'); return; } - + if (reconnectAttempts.value < maxReconnectAttempts) { reconnectAttempts.value++; const reconnectInterval = initialReconnectInterval * Math.pow(2, reconnectAttempts.value - 1); diff --git a/components/payPassword.vue b/components/payPassword.vue index 0bde54c..1d04f76 100644 --- a/components/payPassword.vue +++ b/components/payPassword.vue @@ -56,7 +56,7 @@ // 关闭模态框 const closeModal = () => { emits('close'); - password = ''; + password.value = ''; }; // 将方法暴露给父组件 defineExpose({ diff --git a/manifest.json b/manifest.json index d216445..ee58fec 100644 --- a/manifest.json +++ b/manifest.json @@ -1,93 +1,93 @@ { - "name": "wepp", - "appid": "__UNI__9EC799C", - "description": "", - "versionName": "1.0.0", - "versionCode": "100", - "transformPx": false, - /* 5+App特有相关 */ - "app-plus": { - "usingComponents": true, - "nvueStyleCompiler": "uni-app", - "compilerVersion": 3, - "splashscreen": { - "alwaysShowBeforeRender": true, - "waiting": true, - "autoclose": true, - "delay": 0 - }, - /* 模块配置 */ - "modules": {}, - /* 应用发布信息 */ - "distribute": { - /* android打包配置 */ - "android": { - "permissions": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "" - ] - }, - /* ios打包配置 */ - "ios": {}, - /* SDK配置 */ - "sdkConfigs": {} - } - }, - /* 快应用特有相关 */ - "quickapp": {}, - /* 小程序特有相关 */ - "mp-weixin": { - "appid": "wxd88fffa983758a30", - "setting": { - "urlCheck": false, - "minified": true, - "es6": true, - "postcss": true - }, - "usingComponents": true, - "libVersion": "latest", - "permission": { - "scope.userLocation": { - "desc": "你的位置信息将用于小程序位置接口的效果展示" - } - }, - "requiredPrivateInfos": ["getLocation", "onLocationChange", "chooseLocation", "chooseAddress"], - "optimization": { - "filterUnused": false - } - }, - "h5": {}, - "mp-alipay": { - "usingComponents": true, - "appid": "2021004145625815", - "devServer": { - "autoOpen": true // 设置为true自动打开支付宝小程序 - }, - "unipush": { - "enable": false - } - }, - "mp-baidu": { - "usingComponents": true - }, - "mp-toutiao": { - "usingComponents": true - }, - "uniStatistics": { - "enable": false - }, - "vueVersion": "3" -} \ No newline at end of file + "name" : "wepp", + "appid" : "__UNI__9EC799C", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : {}, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "wxd88fffa983758a30", + "setting" : { + "urlCheck" : false, + "minified" : true, + "es6" : true, + "postcss" : true + }, + "usingComponents" : true, + "libVersion" : "latest", + "permission" : { + "scope.userLocation" : { + "desc" : "你的位置信息将用于小程序位置接口的效果展示" + } + }, + "requiredPrivateInfos" : [ "getLocation", "onLocationChange", "chooseLocation", "chooseAddress" ], + "optimization" : { + "filterUnused" : false + } + }, + "h5" : {}, + "mp-alipay" : { + "usingComponents" : true, + "appid" : "2021004145625815", + "devServer" : { + "autoOpen" : true // 设置为true自动打开支付宝小程序 + }, + "unipush" : { + "enable" : false + } + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "3" +}