From 9685b6648dadbee5770f590da9c7b75aab1dc19c Mon Sep 17 00:00:00 2001 From: yuanlei <18627959669@163.com> Date: Thu, 17 Jul 2025 14:43:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=B6=88=E6=81=AF=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 3 +- uni_modules/vrapile-im/changelog.md | 4 + uni_modules/vrapile-im/package.json | 2 +- utils/accessLog.js | 43 ++++---- utils/nineTool.js | 194 +++++++++++++++++++----------------- utils/nodeId.js | 11 +- utils/request.js | 175 ++++++++++++++++---------------- 7 files changed, 219 insertions(+), 213 deletions(-) diff --git a/App.vue b/App.vue index 6f9374d..0d3aa03 100644 --- a/App.vue +++ b/App.vue @@ -2,8 +2,7 @@ import store from '@/store' import socketStore from '@/uni_modules/vrapile-im/store' import { getToken } from '@/utils/token' - import { setNodeId, getNodeId } from '@/utils/nodeId' - import { getLongRandom } from '@/utils/nineTool'; + import { getNodeId } from '@/utils/nodeId' export default { globalData: { // appId diff --git a/uni_modules/vrapile-im/changelog.md b/uni_modules/vrapile-im/changelog.md index 2460be6..57f79c1 100644 --- a/uni_modules/vrapile-im/changelog.md +++ b/uni_modules/vrapile-im/changelog.md @@ -1,3 +1,7 @@ +## 1.1.13(2025-07-17) +更新消息排序规则 +## 1.1.12(2025-07-17) +更新消息排序规则 ## 1.1.11(2025-07-14) 更新readme说明文件 ## 1.1.10(2025-04-11) diff --git a/uni_modules/vrapile-im/package.json b/uni_modules/vrapile-im/package.json index 75ee176..5450d5c 100644 --- a/uni_modules/vrapile-im/package.json +++ b/uni_modules/vrapile-im/package.json @@ -1,7 +1,7 @@ { "id": "vrapile-im", "displayName": "im页面组件", - "version": "1.1.11", + "version": "1.1.13", "description": "实现WebSocket连接/好友/群组/新消息/历史消息,都是全局配置并本地化存储,已调试兼容H5/微信小程序/安卓App/PC多端同步通讯", "keywords": [ "IM页面组件,websocket应用" diff --git a/utils/accessLog.js b/utils/accessLog.js index 6074f26..3c7be15 100644 --- a/utils/accessLog.js +++ b/utils/accessLog.js @@ -1,30 +1,23 @@ import store from '@/store' import { diyApi } from '@/utils/queryByDiy'; -import { setNodeId, getNodeId } from '@/utils/nodeId' -import { getLongRandom } from '@/utils/nineTool'; +import { getNodeId } from '@/utils/nodeId'; export function saveAccessLog(to, f) { - // 开发环境不保存日志 - if(import.meta.env.VITE_APP_ENV == 'development'){ - return; - } - // 生成一个nodeId,用于记录日志 - let nodeId = getNodeId(); - if(!nodeId){ - nodeId = getLongRandom(24) - setNodeId(nodeId) - } - let flag = getApp().globalData.terminal + "_" + f; - let data = { - platform: getApp().globalData.appId, - terminal: getApp().globalData.terminal, - nodeId: nodeId, - flag: getApp().globalData.terminal + "_" + f, - fullPath: to.url.split("?")[0], - allPath: to.url, - menuName: to.tabBarText, - userId: store.state.user.userInfo.userId, - userName: store.state.user.userInfo.userName - } - diyApi("/system/log/insSysAccessLog", data); + // 开发环境不保存日志 + if(import.meta.env.VITE_APP_ENV == 'development'){ + return; + } + let flag = getApp().globalData.terminal + "_" + f; + let data = { + platform: getApp().globalData.appId, + terminal: getApp().globalData.terminal, + nodeId: getNodeId(), + flag: getApp().globalData.terminal + "_" + f, + fullPath: to.url.split("?")[0], + allPath: to.url, + menuName: to.tabBarText, + userId: store.state.user.userInfo.userId, + userName: store.state.user.userInfo.userName + } + diyApi("/system/log/insSysAccessLog", data); } diff --git a/utils/nineTool.js b/utils/nineTool.js index b8d13c8..ecd962a 100644 --- a/utils/nineTool.js +++ b/utils/nineTool.js @@ -1,39 +1,39 @@ export function isNull(o) { - if(o === 0 || o === "0"){ - return false; - } - if(o == "undefined" || o == null || o == ""){ - return true; - } - return false; + if(o === 0 || o === "0"){ + return false; + } + if(o == "undefined" || o == null || o == ""){ + return true; + } + return false; } export function isPhone(o) { - if(/^1[23456789]\d{9}$/.test(o)){ - return true; - } - return false; + if(/^1[23456789]\d{9}$/.test(o)){ + return true; + } + return false; } export function isMail(o) { - if(/^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$/.test(o)){ - return true; - } - return false; + if(/^([a-z0-9A-Z]+[-|\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$/.test(o)){ + return true; + } + return false; } export function isNumber(value) { return !isNaN(parseFloat(value)) && isFinite(value) } export function isLetter(o) { - if(/^[A-Za-z]+$/.test(o)){ - return true; - } - return false; + if(/^[A-Za-z]+$/.test(o)){ + return true; + } + return false; } export function isNumberOrLetter(o) { - if(/^[A-Za-z0-9]+$/.test(o)){ - return true; - } - return false; + if(/^[A-Za-z0-9]+$/.test(o)){ + return true; + } + return false; } // 日期格式化 @@ -65,7 +65,7 @@ export function parseTime(time, pattern) { s: date.getSeconds(), a: date.getDay() } - const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + const time_str = format.replace(new RegExp(/{(y|m|d|h|i|s|a)+}/g), (result, key) => { let value = formatObj[key] // Note: getDay() returns 0 on Sunday if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } @@ -83,11 +83,11 @@ export function formatDate(time, option) { } else { time = +time } - - if (option) { - return parseTime(time, option) - } - + + if (option) { + return parseTime(time, option) + } + const d = new Date(time) const now = Date.now() @@ -117,19 +117,19 @@ export function formatDate(time, option) { } if(diff < 3600 * 24 * 365) { return ( - (d.getMonth()*1 + 1) + + (d.getMonth()*1 + 1) + '月' + d.getDate() + '日' ) } else { - return ( - d.getFullYear() + - '年' + - (d.getMonth()*1 + 1) + - '月' - ) - } + return ( + d.getFullYear() + + '年' + + (d.getMonth()*1 + 1) + + '月' + ) + } } export function formatTime(time, option) { @@ -138,29 +138,38 @@ export function formatTime(time, option) { } else { time = +time } - - if (option) { + + if (option) { return parseTime(time, option) } - + const d = new Date(time) const now = Date.now() const diff = (now - d) / 1000 - return ( - d.getFullYear() + - '-' + - ((d.getMonth()*1 + 1) + "").padStart(2,0) + - '-' + - (d.getDate() + '').padStart(2,0) + - ' ' + - (d.getHours() + '').padStart(2,0) + - ':' + - (d.getMinutes() + '').padStart(2,0) + - ':' + - (d.getSeconds() + '').padStart(2,0) - ) + return ( + d.getFullYear() + + '-' + + ((d.getMonth()*1 + 1) + "").padStart(2,0) + + '-' + + (d.getDate() + '').padStart(2,0) + + ' ' + + (d.getHours() + '').padStart(2,0) + + ':' + + (d.getMinutes() + '').padStart(2,0) + + ':' + + (d.getSeconds() + '').padStart(2,0) + ) +} + +export function showRangeTime(date, start=1) { + if(start==1){ + return date.replace(" 00:00:00", "") + } + if(start==2){ + return date.replace(" 23:59:59", "") + } } // number:要格式化的数字, @@ -170,19 +179,19 @@ export function formatTime(time, option) { // tail_add: 小数点后面数据是否添加0补足位数, 默认空字符 // null_default: 如果为空的值, 默认空字符 function numberFormat(number, decimals, tail_add="", thousands_sep, dec_point, null_default="") { - number = (number + '').replace(/[^0-9+-Ee.]/g, ''); - var n = !isFinite(+number) ? 0 : +number, - prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), - sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, - dec = (typeof dec_point === 'undefined') ? '.' : dec_point, - s = '', - toFixedFix = function (n, prec) { - var k = Math.pow(10, prec); - return '' + Math.round(n * k) / k; - }; + number = (number + '').replace(new RegExp(/[^0-9+-Ee.]/g), ''); + let n = !isFinite(+number) ? 0 : +number, + prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), + sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, + dec = (typeof dec_point === 'undefined') ? '.' : dec_point, + s = '', + toFixedFix = function (n, prec) { + let k = Math.pow(10, prec); + return '' + Math.round(n * k) / k; + }; s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.'); - var re = /(-?\d+)(\d{3})/; + let re = new RegExp(/(-?\d+)(\d{3})/g); if(sep.length > 0){ while (re.test(s[0])) { s[0] = s[0].replace(re, "$1" + sep + "$2"); @@ -211,9 +220,10 @@ export function formatNumber(number, decimals, tail_add, thousands_sep, dec_poin } // thousands_sep:千分位符号 默认空字符 export function formatPercent(number, decimals, tail_add, thousands_sep="", dec_point, null_default) { - if(isNull(number) || isNull(String(number).trim().replaceAll(",", ""))){return null_default;} - if(!isNumber(String(number).trim().replaceAll(",", ""))){return number;} - number = String(number).trim().replaceAll(",", ""); + let re = new RegExp(/,/g) + if(isNull(number) || isNull(String(number).trim().replace(re, ""))){return null_default;} + if(!isNumber(String(number).trim().replace(re, ""))){return number;} + number = String(number).trim().replace(re, ""); let value = numberFormat(number*100, decimals, tail_add, thousands_sep, dec_point, null_default); if(value){ return value + "%"; @@ -306,24 +316,24 @@ export function GetOs () { } export function getRandom(len){ - let data = Math.random() + ""; - let index = 2; - while(data[index] == 0){ - index++; - } - return data.substr(index, len); + let data = Math.random() + ""; + let index = 2; + while(data[index] == 0){ + index++; + } + return data.substr(index, len); } export function getLongRandom(len){ - if(len <= 16){ - return getRandom(len) - } - let data = Math.random() + ""; - let index = 2; - while(data[index] == 0){ - index++; - } - return parseTime(Date.now(), '{y}{m}{d}{h}{i}{s}') + "" + data.substr(index, len-16); + if(len <= 16){ + return getRandom(len) + } + let data = Math.random() + ""; + let index = 2; + while(data[index] == 0){ + index++; + } + return parseTime(Date.now(), '{y}{m}{d}{h}{i}{s}') + "" + data.substr(index, len-14); } export function moveInArray(array, fromIndex, toIndex) { @@ -332,17 +342,17 @@ export function moveInArray(array, fromIndex, toIndex) { } export function jsonCharBigInt(s){ - if(typeof s !== 'string'){ - return s - } - let re = /([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/g - return s.replaceAll(re, "$1$2$1$3$1") + if(typeof s !== 'string'){ + return s + } + const re = new RegExp(/([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/gm); + return s.replace(re, "$1$2$1$3$1") } export function jsonParse(s){ - if(typeof s !== 'string'){ - return s - } - let re = /([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/g - return JSON.parse(s.replaceAll(re, "$1$2$1$3$1")) + if(typeof s !== 'string'){ + return s + } + const re = new RegExp(/([\\]?['|"]{1})(\w+[\\]?['|"]{1}[ |\n|r|\t]*:[ |\n|r|\t]*)([-]?\d{15,})/gm); + return JSON.parse(s.replace(re, "$1$2$1$3$1")) } \ No newline at end of file diff --git a/utils/nodeId.js b/utils/nodeId.js index cceab2e..0136636 100644 --- a/utils/nodeId.js +++ b/utils/nodeId.js @@ -1,7 +1,14 @@ +import { getLongRandom } from '@/utils/nineTool'; + const NodeIdKey = 'App-Node-Id' -export function getNodeId() { - return uni.getStorageSync(NodeIdKey) +export function getNodeId(len=18) { + let nodeId = uni.getStorageSync(NodeIdKey); + if(!nodeId){ + nodeId = getLongRandom(len) + uni.setStorageSync(NodeIdKey, nodeId) + } + return nodeId } export function setNodeId(nodeId) { diff --git a/utils/request.js b/utils/request.js index 733c528..f604477 100644 --- a/utils/request.js +++ b/utils/request.js @@ -1,7 +1,6 @@ import store from '@/store' import { getToken } from '@/utils/token' -import { setNodeId, getNodeId } from '@/utils/nodeId' -import { getLongRandom } from '@/utils/nineTool'; +import { getNodeId } from '@/utils/nodeId'; import errorCode from '@/utils/errorCode' import { getSessionCache, setSessionCache } from '@/utils/cache' import { toast, showConfirm, tansParams } from '@/utils/requestTool' @@ -12,22 +11,16 @@ const baseUrl = import.meta.env.VITE_APP_BASE_URL const request = config => { // 是否需要设置 token const isToken = (config.headers || {}).isToken === false - // 是否需要防止数据重复提交 + // 是否需要防止数据重复提交 const isRepeatSubmit = (config.headers || {}).repeatSubmit === false config.header = config.header || {} if (getToken() && !isToken) { config.header['Authorization'] = 'Vrapile ' + getToken() } - // 节点 - let nodeId = getNodeId(); - if(!nodeId){ - nodeId = getLongRandom(24); - setNodeId(nodeId); - } config.header["platform"] = getApp().globalData.appId; config.header["terminal"] = getApp().globalData.terminal; - config.header["nodeId"] = nodeId; + config.header["nodeId"] = getNodeId(); // get请求映射params参数 if (config.params) { @@ -35,89 +28,89 @@ const request = config => { url = url.slice(0, -1) config.url = url } - if (!isRepeatSubmit) { - const requestObj = { - url: config.url, - data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, - time: new Date().getTime() - } - const sessionObj = getSessionCache() - if (sessionObj === undefined || sessionObj === null || sessionObj === '') { - setSessionCache(requestObj) - } else { - const s_url = sessionObj.url; // 请求地址 - const s_data = sessionObj.data; // 请求数据 - const s_time = sessionObj.time; // 请求时间 - const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 - if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { - const message = '数据正在处理,请勿重复提交:' + s_url; - console.warn(`[${s_url}]: ` + message) - return Promise.reject(new Error(message)) - } else { - setSessionCache(requestObj) - } - } - } + if (!isRepeatSubmit) { + const requestObj = { + url: config.url, + data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, + time: new Date().getTime() + } + const sessionObj = getSessionCache() + if (sessionObj === undefined || sessionObj === null || sessionObj === '') { + setSessionCache(requestObj) + } else { + const s_url = sessionObj.url; // 请求地址 + const s_data = sessionObj.data; // 请求数据 + const s_time = sessionObj.time; // 请求时间 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 + if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { + const message = '数据正在处理,请勿重复提交:' + s_url; + console.warn(`[${s_url}]: ` + message) + return Promise.reject(new Error(message)) + } else { + setSessionCache(requestObj) + } + } + } return new Promise((resolve, reject) => { uni.request({ - method: config.method || 'get', - timeout: config.timeout || timeout, - url: config.baseUrl || baseUrl + config.url, - data: config.data, - header: config.header, - dataType: 'json' - }).then(res => { - // let [error, res] = response - const code = res.data.code || res.data.status || 200 - const msg = errorCode[code] || res.data.msg || errorCode['default'] - // if (code != 200) { - // toast('后端接口连接异常') - // reject('后端接口连接异常') - // return - // } - if (code === 401) { - // 密码登录的,实现自动重新登录 - let loginInfo = store.state.user.loginInfo; - if(loginInfo && loginInfo.loginType == 0){ - store.dispatch('Login', { - loginType: loginInfo.loginType, - userName: loginInfo.userName, - password: loginInfo.password, - registerFlag: "N" - }).then(() => { - store.dispatch('GetInfo'); - }) - reject('无效的会话,或者会话已过期,已重新登录。') - }else{ - showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { - if (res.confirm) { - uni.reLaunch({ url: '/pages/user/login' }) - } - }) - reject('无效的会话,或者会话已过期,请重新登录。') - } - } else if (code === 500) { - toast(msg) - reject(res) - } else if (code !== 200) { - toast(msg) - reject(res) - } - resolve(res.data) - }).catch(error => { - let { message } = error - if (message && message === 'Network Error') { - message = '后端接口连接异常' - } else if (message && message.includes('timeout')) { - message = '系统接口请求超时' - } else if (message && message.includes('Request failed with status code')) { - message = '系统接口' + message.substr(message.length - 3) + '异常' - }else{ - message = '系统繁忙' - } - toast(message) - reject(error) - }) + method: config.method || 'get', + timeout: config.timeout || timeout, + url: config.baseUrl || baseUrl + config.url, + data: config.data, + header: config.header, + dataType: 'json' + }).then(res => { + // let [error, res] = response + const code = res.data.code || res.data.status || 200 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + // if (code != 200) { + // toast('后端接口连接异常') + // reject('后端接口连接异常') + // return + // } + if (code === 401) { + // 密码登录的,实现自动重新登录 + let loginInfo = store.state.user.loginInfo; + if(loginInfo && loginInfo.loginType == 0){ + store.dispatch('Login', { + loginType: loginInfo.loginType, + userName: loginInfo.userName, + password: loginInfo.password, + registerFlag: "N" + }).then(() => { + store.dispatch('GetInfo'); + }) + reject('无效的会话,或者会话已过期,已重新登录。') + }else{ + showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => { + if (res.confirm) { + uni.reLaunch({ url: '/pages/user/login' }) + } + }) + reject('无效的会话,或者会话已过期,请重新登录。') + } + } else if (code === 500) { + toast(msg) + reject(res) + } else if (code !== 200) { + toast(msg) + reject(res) + } + resolve(res.data) + }).catch(error => { + let { message } = error + if (message && message === 'Network Error') { + message = '后端接口连接异常' + } else if (message && message.includes('timeout')) { + message = '系统接口请求超时' + } else if (message && message.includes('Request failed with status code')) { + message = '系统接口' + message.substr(message.length - 3) + '异常' + }else{ + message = '系统繁忙' + } + toast(message) + reject(error) + }) }) }