From 46a0a22722e34558ed8c29b5336793cdc9140f54 Mon Sep 17 00:00:00 2001 From: jia <1451658316@qq.com> Date: Sat, 18 Nov 2023 11:05:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .hbuilderx/launch.json | 26 ++++ manifest.json | 6 +- utils/aa.js | 127 +++++++++++++++++++ utils/base64.js | 164 ++++++++++++++++++++++++ utils/cache.js | 140 +++++++++++++++++++++ utils/encrypt.js | 66 ++++++++++ utils/http.js | 89 +++++++++++++ utils/jpush.js | 276 +++++++++++++++++++++++++++++++++++++++++ utils/logistics.js | 118 ++++++++++++++++++ utils/oahttp.js | 134 ++++++++++++++++++++ utils/request.js | 77 ++++++++++++ utils/time.js | 34 +++++ utils/websocket.js | 85 +++++++++++++ 13 files changed, 1339 insertions(+), 3 deletions(-) create mode 100644 .hbuilderx/launch.json create mode 100644 utils/aa.js create mode 100644 utils/base64.js create mode 100644 utils/cache.js create mode 100644 utils/encrypt.js create mode 100644 utils/http.js create mode 100644 utils/jpush.js create mode 100644 utils/logistics.js create mode 100644 utils/oahttp.js create mode 100644 utils/request.js create mode 100644 utils/time.js create mode 100644 utils/websocket.js diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json new file mode 100644 index 0000000..3ba3864 --- /dev/null +++ b/.hbuilderx/launch.json @@ -0,0 +1,26 @@ +{ + // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ + // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 + "version" : "0.0", + "configurations" : [ + { + "app-plus" : { + "launchtype" : "local" + }, + "default" : { + "launchtype" : "local" + }, + "type" : "uniCloud" + }, + { + "openVueDevtools" : false, + "playground" : "custom", + "type" : "uni-app:app-android" + }, + { + "openVueDevtools" : false, + "playground" : "standard", + "type" : "uni-app:app-ios" + } + ] +} diff --git a/manifest.json b/manifest.json index 796228d..dd2078c 100644 --- a/manifest.json +++ b/manifest.json @@ -250,14 +250,14 @@ }, "TT-AMapNavi" : { "__plugin_info__" : { - "name" : "tongtong-高德导航原生插件 - [试用版,仅用于自定义调试基座]", + "name" : "tongtong-高德导航原生插件", "description" : "高德导航原生插件", "platforms" : "Android,iOS", "url" : "https://ext.dcloud.net.cn/plugin?id=8072", - "android_package_name" : "", + "android_package_name" : "uni.UNI5A081C6", "ios_bundle_id" : "", "isCloud" : true, - "bought" : 0, + "bought" : 1, "pid" : "8072", "parameters" : {} } diff --git a/utils/aa.js b/utils/aa.js new file mode 100644 index 0000000..ce76829 --- /dev/null +++ b/utils/aa.js @@ -0,0 +1,127 @@ +import { + HTTP_REQUEST_URL_THREE, + HEADER, + TOKENNAME, +} from '@/config/app'; +import { + Toast +} from '../libs/uniApi'; +// import { checkLogin } from '../libs/login'; +import store from '../store'; + +function toLogin() { + uni.showToast({ + title: '请先登录', + icon: 'none', + duration: 1000 + }); +} + +function baseRequestTwo(url, method, data, { + noAuth = false, + noVerify = false, + onReLogin = false +}) { + let Url = HTTP_REQUEST_URL_THREE, + header = HEADER; + if (!noAuth) { + // 已经未登录了,禁止请求 + if (!store.state.config.request) return Promise.reject({ + msg: '未登录' + }); + //登录过期自动登录 + if (!store.state.app.token) { + toLogin(); + store.commit("SET_REQUEST", false); + return Promise.reject({ + msg: '未登录' + }); + } + } + + // if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token; + if (store.state.app.token) header[TOKENNAME] = store.state.app.token; + + // header[TOKENNAME] = 'Bearer sdjflidshjgfkbdasgjmasbgvhauuiavhkesvndkaesbvkjsdbv'; + return new Promise((reslove, reject) => { + // uni.showLoading({ + // title: '加载中' + // }) + uni.request({ + // url: Url + '/api/v1' + url, + url: Url + url, + method: method || 'GET', + header: { + ...header + }, + data: method != 'GET' ? data || {} : {}, + params: method == 'GET' ? data : {}, + success: (res) => { + if (noVerify) + reslove(res.data); + else if (res.data.code == -1) { + if(onReLogin) { + store.commit('LOGOUT'); + return reject(); + } + // 如果登录超时,自动重新登录并且继续发送请求 + store.dispatch("RE_LOGIN", { + url: url, + method: method, + data: data, + opt: { + noAuth, + noVerify + } + }).then((e)=>{ + reslove(e); + }).catch((err)=>{ + reject(res.data); + }) + // store.commit("SET_REQUEST", false); + } else if (res.data.code == 0) { + if (res.data.msg != '无登录信息') { + uni.showToast({ + title: res.data.msg || '请检查网络', + icon: 'none', + }) + } + reject(res.data); + } else if (res.data.code == 1) { + store.commit("SET_REQUEST"); + reslove(res.data); + } else if (res.data.code == 200) { + store.commit("SET_REQUEST"); + reslove(res.data.data); + } else if ([410000, 410001, 410002, 40000].indexOf(res.data.code) !== -1) { + toLogin(); + reject(res.data); + } else if (res.data.code == 501) { + reject(res.data); + } else { + uni.showToast({ + title: res.data.msg || '请检查网络', + icon: 'none' + }) + reject(res.data.msg || '请检查网络'); + } + }, + fail: (message) => { + // uni.hideLoading() + uni.showToast({ + title: '网络错误', + icon: 'none' + }) + reject('请求失败'); + } + }) + }); +} + +const oahttp = {}; + +['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => { + oahttp[method] = (api, data, opt) => baseRequestTwo(api, method, data, opt || {}) +}); + +export default oahttp; \ No newline at end of file diff --git a/utils/base64.js b/utils/base64.js new file mode 100644 index 0000000..0b335e5 --- /dev/null +++ b/utils/base64.js @@ -0,0 +1,164 @@ +/*! https://mths.be/base64 v1.0.0 by @mathias | MIT license */ +;(function(root) { + + // Detect free variables `exports`. + var freeExports = typeof exports == 'object' && exports; + + // Detect free variable `module`. + var freeModule = typeof module == 'object' && module && + module.exports == freeExports && module; + + // Detect free variable `global`, from Node.js or Browserified code, and use + // it as `root`. + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { + root = freeGlobal; + } + + /*--------------------------------------------------------------------------*/ + + var InvalidCharacterError = function(message) { + this.message = message; + }; + InvalidCharacterError.prototype = new Error; + InvalidCharacterError.prototype.name = 'InvalidCharacterError'; + + var error = function(message) { + // Note: the error messages used throughout this file match those used by + // the native `atob`/`btoa` implementation in Chromium. + throw new InvalidCharacterError(message); + }; + + var TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + // http://whatwg.org/html/common-microsyntaxes.html#space-character + var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g; + + // `decode` is designed to be fully compatible with `atob` as described in the + // HTML Standard. http://whatwg.org/html/webappapis.html#dom-windowbase64-atob + // The optimized base64-decoding algorithm used is based on @atk’s excellent + // implementation. https://gist.github.com/atk/1020396 + var decode = function(input) { + input = String(input) + .replace(REGEX_SPACE_CHARACTERS, ''); + var length = input.length; + if (length % 4 == 0) { + input = input.replace(/==?$/, ''); + length = input.length; + } + if ( + length % 4 == 1 || + // http://whatwg.org/C#alphanumeric-ascii-characters + /[^+a-zA-Z0-9/]/.test(input) + ) { + error( + 'Invalid character: the string to be decoded is not correctly encoded.' + ); + } + var bitCounter = 0; + var bitStorage; + var buffer; + var output = ''; + var position = -1; + while (++position < length) { + buffer = TABLE.indexOf(input.charAt(position)); + bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer; + // Unless this is the first of a group of 4 characters… + if (bitCounter++ % 4) { + // …convert the first 8 bits to a single ASCII character. + output += String.fromCharCode( + 0xFF & bitStorage >> (-2 * bitCounter & 6) + ); + } + } + return output; + }; + + // `encode` is designed to be fully compatible with `btoa` as described in the + // HTML Standard: http://whatwg.org/html/webappapis.html#dom-windowbase64-btoa + var encode = function(input) { + input = String(input); + if (/[^\0-\xFF]/.test(input)) { + // Note: no need to special-case astral symbols here, as surrogates are + // matched, and the input is supposed to only contain ASCII anyway. + error( + 'The string to be encoded contains characters outside of the ' + + 'Latin1 range.' + ); + } + var padding = input.length % 3; + var output = ''; + var position = -1; + var a; + var b; + var c; + var buffer; + // Make sure any padding is handled outside of the loop. + var length = input.length - padding; + + while (++position < length) { + // Read three bytes, i.e. 24 bits. + a = input.charCodeAt(position) << 16; + b = input.charCodeAt(++position) << 8; + c = input.charCodeAt(++position); + buffer = a + b + c; + // Turn the 24 bits into four chunks of 6 bits each, and append the + // matching character for each of them to the output. + output += ( + TABLE.charAt(buffer >> 18 & 0x3F) + + TABLE.charAt(buffer >> 12 & 0x3F) + + TABLE.charAt(buffer >> 6 & 0x3F) + + TABLE.charAt(buffer & 0x3F) + ); + } + + if (padding == 2) { + a = input.charCodeAt(position) << 8; + b = input.charCodeAt(++position); + buffer = a + b; + output += ( + TABLE.charAt(buffer >> 10) + + TABLE.charAt((buffer >> 4) & 0x3F) + + TABLE.charAt((buffer << 2) & 0x3F) + + '=' + ); + } else if (padding == 1) { + buffer = input.charCodeAt(position); + output += ( + TABLE.charAt(buffer >> 2) + + TABLE.charAt((buffer << 4) & 0x3F) + + '==' + ); + } + + return output; + }; + + var base64 = { + 'encode': encode, + 'decode': decode, + 'version': '1.0.0' + }; + + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define(function() { + return base64; + }); + } else if (freeExports && !freeExports.nodeType) { + if (freeModule) { // in Node.js or RingoJS v0.8.0+ + freeModule.exports = base64; + } else { // in Narwhal or RingoJS v0.7.0- + for (var key in base64) { + base64.hasOwnProperty(key) && (freeExports[key] = base64[key]); + } + } + } else { // in Rhino or a web browser + root.base64 = base64; + } + +}(this)); diff --git a/utils/cache.js b/utils/cache.js new file mode 100644 index 0000000..d9f337e --- /dev/null +++ b/utils/cache.js @@ -0,0 +1,140 @@ +import { EXPIRE } from '@/config/app'; + +class Cache { + + constructor(handler) { + this.cacheSetHandler = uni.setStorageSync; + this.cacheGetHandler = uni.getStorageSync; + this.cacheClearHandler = uni.removeStorageSync; + this.cacheExpire = '_expire_2019_12_17_18_44'; + } + + /** + * 获取当前时间戳 + */ + time() { + return Math.round(new Date() / 1000); + } + + /** + * 设置过期时间缓存 + * @param {Object} key + * @param {Object} expire + */ + setExpireCahe(key, expire) { + expire = expire !== undefined ? expire : EXPIRE; + if (expire) { + this.cacheSetHandler(key + this.cacheExpire, this.time() + expire) + } + } + + /** + * 缓存是否过期,过期自动删除 + * @param {Object} key + * @param {Object} $bool true = 删除,false = 不删除 + */ + getExpireCahe(key, $bool) { + try { + let time = this.cacheGetHandler(key + this.cacheExpire); + if (time) { + let newTime = parseInt(time); + if (time && time < this.time() && !Number.isNaN(newTime)) { + if ($bool === undefined || $bool === true) { + this.cacheClearHandler(key); + this.cacheClearHandler(key + this.cacheExpire); + } + return false; + } else + return true; + } else { + return !!this.cacheGetHandler(key); + } + } catch (e) { + return false; + } + } + + /** + * 设置缓存 + * @param {Object} key + * @param {Object} data + */ + set(key, data, expire) { + if (typeof data === 'object') + data = JSON.stringify(data); + try { + this.setExpireCahe(key, expire); + return this.cacheSetHandler(key, data); + } catch (e) { + return false; + } + } + + /** + * 检测缓存是否存在 + * @param {Object} key + */ + has(key) { + return this.getExpireCahe(key); + } + + /** + * 获取缓存 + * @param {Object} key + * @param {Object} $default + * @param {Object} expire + */ + get(key, $default, expire) { + try { + let isBe = this.getExpireCahe(key); + let data = this.cacheGetHandler(key); + if (data && isBe) { + if (typeof $default === 'boolean') + return JSON.parse(data); + else + return data; + } else { + if (typeof $default === 'function') { + let value = $default(); + this.set(key, value, expire); + return value; + } else { + this.set(key, $default, expire); + return $default; + } + } + } catch (e) { + return null; + } + } + + /** + * 删除缓存 + * @param {Object} key + */ + clear(key) { + try { + let cahceValue = this.cacheGetHandler(key + this.cacheExpire); + if (cahceValue) + this.cacheClearHandler(key + this.cacheExpire); + return this.cacheClearHandler(key); + } catch (e) { + return false; + } + } + + /** + * 清除过期缓存 + */ + clearOverdue() { + // let cacheList = uni.getStorageInfoSync(),that = this; + // if (typeof cacheList.keys === 'object'){ + // cacheList.keys.forEach(item=>{ + // that.getExpireCahe(item); + // }) + // } + } +} + + +export default new Cache; diff --git a/utils/encrypt.js b/utils/encrypt.js new file mode 100644 index 0000000..3312974 --- /dev/null +++ b/utils/encrypt.js @@ -0,0 +1,66 @@ +import Base64 from "@/utils/base64.js" +import cryptoJS from "@/node_modules/crypto-js" + +const key_code = 'gxzhptxiaochengxu_1'; + +// 加密 +const encode = (key, data='')=>{ + try{ + let str; + typeof data == 'object'? str = JSON.stringify(data) : str = data; + str = cryptoJS.AES.encrypt(str, key_code).toString(); + uni.setStorageSync(key, str) + return true; + }catch(e){ + console.log(e); + return false; + } +} + +// 解密 +const decode = (key)=>{ + try{ + let str = uni.getStorageSync(key); + str = cryptoJS.AES.decrypt(str, key_code).toString(cryptoJS.enc.Utf8); + isJSON(str) ? str = JSON.parse(str) : null; + return str; + }catch(e){ + console.log(e); + return undefined; + } +} + +const isJSON = (str)=>{ + try{ + JSON.parse(str) + return true; + }catch(e){ + return false; + } +} + + +const LOGIN = ()=>{ + return new Promise((reslove, reject) => { + uni.request({ + url: Url + '/api' + url, + method: 'POST', + data: data, + success: (res) => { + + }, + fail: (message) => { + uni.showToast({ + title: '网络错误', + icon: 'none' + }) + reject('请求失败'); + } + }) + }); +} + +export default { + encode, + decode +} \ No newline at end of file diff --git a/utils/http.js b/utils/http.js new file mode 100644 index 0000000..fc983f3 --- /dev/null +++ b/utils/http.js @@ -0,0 +1,89 @@ +import { + HTTP_REQUEST_URL, + HTTP_REQUEST_URL_TWO, + HTTP_REQUEST_URL_THREE, + HEADER, + TOKENNAME, +} from '@/config/app'; +import { + checkLogin +} from '../libs/login'; +import { Toast } from '../libs/uniApi'; +import store from '../store'; + +function toLogin() { + store.commit("LOGOUT"); + uni.showToast({ + title: '请登录', + icon: 'none', + duration: 1000 + }); +} + +function baseRequestTwo(url, method, data, { + noAuth = false, + noVerify = false +}) { + let Url = HTTP_REQUEST_URL_TWO, + header = HEADER; + + if (!noAuth) { + //登录过期自动登录 + if (!store.state.app.token && !checkLogin()) { + toLogin(); + return Promise.reject({ + msg: '未登录' + }); + } + } + + if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token; + + return new Promise((reslove, reject) => { + uni.request({ + url: Url + '/api' + url, + method: method || 'GET', + header: header, + data: data || {}, + success: (res) => { + // #ifdef APP-PLUS + console.log('app', Url + '/api/' + url, res.data); + // #endif + if (noVerify) + // reslove(res.data, res); + reslove(res.data); + else if (res.data.status == 200) + reslove(res.data, res); + else if (res.data.code == 1) { + reslove(res.data.data); + } else if (res.data.code == 0) { + reslove(res.data, res); + } else if ([410000, 410001, 410002, 40000].indexOf(res.data.status) !== -1) { + toLogin(); + reject(res.data); + } else if (res.data.status == 501) { + uni.reLaunch({ + url: '/pages/error/index' + }) + reject(res.data); + } else if (res.statusCode === 500) + Toast("请检查网络") + else + reject(res.data.message || '请检查网络'); + + }, + fail: (message) => { + console.log('message', message); + reject('请求失败'); + } + }) + }); +} + +const http = {}; + +['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => { + http[method] = (api, data, opt) => baseRequestTwo(api, method, data, opt || {}) +}); + +export default http; diff --git a/utils/jpush.js b/utils/jpush.js new file mode 100644 index 0000000..42266d4 --- /dev/null +++ b/utils/jpush.js @@ -0,0 +1,276 @@ +// 引用方式 +var jpushModule = uni.requireNativePlugin("JG-JPush"); +// console.log('【sk】【引用方式】【jpushModule】【requireNativePlugin】') + +// 开启 debug 模式,默认是关闭 +function openDebug() { + jpushModule.setLoggerEnable(true); +} + +// 关闭 debug 模式,默认是关闭 +function closeDebug() { + jpushModule.setLoggerEnable(false); +} + +// 获取 RegistrationID,只有当应用程序成功注册到 JPush 的服务器时才返回对应的值,否则返回空字符串 +function getRegistrationID(skBack) { + jpushModule.getRegistrationID(result => { + // code number 状态码 0 - 成功, 1011 - iOS模拟器调用会报此错误 + // registerID string 返回的 registrationID + console.log('【sk】获取 RegistrationID=>', result) + skBack(result.registerID) + }) +} + +// 跳转至系统设置页面,0 - 成功 1 - 失败 +function openSettingsForNotification() { + jpushModule.openSettingsForNotification((result) => { + // code number 0 - 成功 1 - 失败 + console.log('【sk】跳转至系统设置页面result=>', result.code) + }) +} + +// 初始化SDK iOS 说明:如果在mainfest.json里 将JPUSH_DEFAULTINITJPUSH_IOS值配置为"true",插件内部将默认初始化JPush,用户则不需要调用该初始化方法。 +function initJPushService() { + console.log(jpushModule) + jpushModule.initJPushService() +} + +// 连接状态回调,true - 已连接, false - 未连接 +function addConnectEventListener(skBack) { + jpushModule.addConnectEventListener(result => { + // connectEnable boolean true - 已连接, false - 未连接 + console.log('【sk】连接状态回调=>', result.connectEnable) + skBack(result.connectEnable); + }) +} + +// 通知事件回调 +function addNotificationListener(skBack) { + jpushModule.addNotificationListener(result => { + // messageID string 唯一标识通知消息的 ID + // title string 对应 Portal 推送通知界面上的“通知标题”字段 + // content string 对应 Portal 推送通知界面上的“通知内容”字段 + // badge string 对应 Portal 推送通知界面上的可选设置里面的“badge”字段 (ios only) + // ring string 推送通知界面上的可选设置里面的“sound”字段 (ios only) + // extras dictionary 对应 Portal 推送消息界面上的“可选设置”里的附加字段 + // iOS dictionary 对应原生返回的通知内容,如需要更多字段请查看该字段内容 + // android dictionary 对应原生返回的通知内容,如需要更多字段请查看该字段内容 + // notificationEventType string 分为notificationArrived和notificationOpened两种 + console.log('【sk】通知事件回调result=>', result) + skBack(result); + }) +} + +// 自定义消息事件回调 +function addCustomMessageListener(skBack) { + jpushModule.addCustomMessageListener(result => { + // messageID string 唯一标识通知消息的 ID + // content string 对应 Portal 推送通知界面上的“通知内容”字段 + // extras dictionary 对应 Portal 推送消息界面上的“可选设置”里的附加字段 + console.log('【sk】自定义消息事件回调result=>', result) + skBack(result); + }) +} + +// 应用内消息回调 +function addInMessageListener(skBack) { + jpushModule.addInMessageListener(result => { + // eventType string show - 应用内消息展示 disappear - 应用内消息已消失 click - 应用内消息点击 + // messageType string 消息类型, eventType 不为 disappear时返回, inMessageNoti - 通知类型的inMessage + // content dictionary 应用内消息内容, eventType 不为 disappear 时返回 + console.log('【sk】应用内消息回调result=>', result) + skBack(result); + }) +} + +// 本地通知事件回调 +function addLocalNotificationListener(skBack) { + jpushModule.addLocalNotificationListener(result => { + // messageID string 唯一标识通知消息的ID + // title string 对应“通知标题”字段 + // content string 对应“通知内容”字段 + // extras dictionary 对应“附加内容”字段 + console.log('【sk】本地通知事件回调result=>', result) + skBack(result); + }) +} + +// 添加一个本地通知 +function addLocalNotification(e) { + jpushModule.addLocalNotification({ + messageID: e.messageID ? e.messageID : '', // 唯一标识通知消息的ID + title: e.title ? e.title : '', // 对应“通知标题”字段 + content: e.content ? e.content : '', // 对应“通知内容”字段 + extras: e.extras ? e.extras : { + name: '', + age: '' + } // 对应“附加内容”字段 + }) +} + +// 移除指定的本地通知 +function removeLocalNotification(e) { + jpushModule.removeLocalNotification({ + messageID: e.messageID ? e.messageID : '' // 唯一标识通知消息的ID + }) +} + +// 移除所有的本地通知 +function clearLocalNotifications() { + jpushModule.clearLocalNotifications() +} + +// 标签别名事件回调 +function addTagAliasListener(skBack) { + jpushModule.addTagAliasListener(result => { + // code number 请求状态码 0 - 成功 + // sequence number 请求时传入的序列号,会在回调时原样返回 + // tags StringArray 执行tag数组操作时返回 + // tag string 执行查询指定tag(queryTag)操作时会返回 + // tagEnable boolean 执行查询指定tag(queryTag)操作时会返回是否可用 + // alias string 对alias进行操作时返回 + console.log('【sk】标签别名事件回调result=>', result) + skBack(result); + }) +} + +// 新增标签 +function addTags(e) { + jpushModule.addTags({ + 'tags': e.tags ? e.tags : [], // StringArray string类型的数组 + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 覆盖标签 +function updateTags(e) { + jpushModule.updateTags({ + 'tags': e.tags ? e.tags : [], // StringArray string类型的数组 + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 删除指定标签 +function deleteTags(e) { + jpushModule.deleteTags({ + 'tags': e.tags ? e.tags : [], // StringArray string类型的数组 + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 清除所有标签 +function cleanTags(e) { + jpushModule.cleanTags({ + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 查询指定 tag 与当前用户绑定的状态 +function queryTag(e) { + jpushModule.queryTag({ + 'tag': e.tag ? e.tag : '', // string 需要查询的标签 + 'sequence': e.sequence ? sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 查询所有标签 +function getAllTags(e) { + jpushModule.getAllTags({ + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 设置别名 +function setAlias(e) { + console.log('设置别名', e) + jpushModule.setAlias({ + 'alias': e.alias ? e.alias : '', // string 有效的别名组成:字母(区分大小写)、数字、下划线、汉字、特殊字符@!#$&*+=.| + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 删除别名 +function deleteAlias(e) { + jpushModule.deleteAlias({ + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 查询别名 +function queryAlias(e) { + jpushModule.queryAlias({ + 'sequence': e.sequence ? e.sequence : 1 // number 请求时传入的序列号,会在回调时原样返回 + }) +} + +// 开启 CrashLog 上报 +function initCrashHandler() { + jpushModule.initCrashHandler() +} + +// 设置地理围栏的最大个数 +function setMaxGeofenceNumber(e) { + jpushModule.setMaxGeofenceNumber(e.geofenceNumber ? e.geofenceNumber : 10) // 默认值为 10 ,iOS系统默认地理围栏最大个数为20 +} + +// 删除指定id的地理围栏 +function deleteGeofence(e) { + jpushModule.deleteGeofence(e.geofence ? e.geofence : '') // 删除指定id的地理围栏 +} + +// 设置 Badge +function setBadge(e) { + jpushModule.setBadge(e.badge ? e.badge : 0) // number +} + +// 设置手机号码 +function setMobileNumber(e) { + jpushModule.setMobileNumber({ + sequence: e.sequence ? e.sequence : 1, // number 请求时传入的序列号,会在回调时原样返回 + mobileNumber: e.mobileNumber ? e.mobileNumber : '' // string 手机号码 会与用户信息一一对应。可为空,为空则清除号码。 + }) +} + +// 设置手机号码回调 +function addMobileNumberListener(skBack) { + jpushModule.addMobileNumberListener(result => { + // code number 状态码 0 - 成功 + // sequence number 请求时传入的序列号,会在回调时原样返回 + console.log('【sk】设置手机号码回调result=>', result) + skBack(result); + }) +} + + +module.exports = { + openDebug: openDebug, + closeDebug: closeDebug, + getRegistrationID: getRegistrationID, + openSettingsForNotification: openSettingsForNotification, + initJPushService: initJPushService, + addConnectEventListener: addConnectEventListener, + addNotificationListener: addNotificationListener, + addCustomMessageListener: addCustomMessageListener, + addInMessageListener: addInMessageListener, + addLocalNotificationListener: addLocalNotificationListener, + addLocalNotification: addLocalNotification, + removeLocalNotification: removeLocalNotification, + clearLocalNotifications: clearLocalNotifications, + addTagAliasListener: addTagAliasListener, + addTags: addTags, + updateTags: updateTags, + deleteTags: deleteTags, + cleanTags: cleanTags, + queryTag: queryTag, + getAllTags: getAllTags, + setAlias: setAlias, + deleteAlias: deleteAlias, + queryAlias: queryAlias, + initCrashHandler: initCrashHandler, + setMaxGeofenceNumber: setMaxGeofenceNumber, + deleteGeofence: deleteGeofence, + setBadge: setBadge, + setMobileNumber: setMobileNumber, + addMobileNumberListener: addMobileNumberListener +} \ No newline at end of file diff --git a/utils/logistics.js b/utils/logistics.js new file mode 100644 index 0000000..e94a501 --- /dev/null +++ b/utils/logistics.js @@ -0,0 +1,118 @@ +import { + HTTP_REQUEST_URL_TWO, + HEADER, + TOKENNAME, +} from '@/config/app'; +import { + Toast +} from '../libs/uniApi'; +// import { checkLogin } from '../libs/login'; +import store from '../store'; + +function toLogin() { + uni.showToast({ + title: '请先登录', + icon: 'none', + duration: 1000 + }); +} + +function baseRequestTwo(url, method, data, { + noAuth = false, + noVerify = false +}) { + let Url = HTTP_REQUEST_URL_TWO, + header = HEADER; + if (!noAuth) { + // 已经未登录了,禁止请求 + if (!store.state.config.request) return Promise.reject({ + msg: '未登录' + }); + //登录过期自动登录 + if (!store.state.app.token) { + toLogin(); + store.commit("SET_REQUEST", false); + return Promise.reject({ + msg: '未登录' + }); + } + } + + // if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token; + if (store.state.app.token) header[TOKENNAME] = store.state.app.token; + + // header[TOKENNAME] = 'Bearer sdjflidshjgfkbdasgjmasbgvhauuiavhkesvndkaesbvkjsdbv'; + return new Promise((reslove, reject) => { + // uni.showLoading({ + // title: '加载中' + // }) + uni.request({ + // url: Url + '/api/v1' + url, + url: Url + '/api' + url, + method: method || 'GET', + header: { + ...header + + }, + data: method != 'GET' ? data || {} : {}, + params: method == 'GET' ? data : {}, + success: (res) => { + // uni.hideLoading() + if (noVerify) + // reslove(res.data, res); + reslove(res.data); + else if (res.data.code == -1) { + store.commit("LOGOUT"); + store.commit("SET_REQUEST", false); + reject(res.data); + } else if (res.data.code == 0) { + // uni.hideLoading(); + if (res.data.show != 1 && res.data.msg != '无登录信息') { + uni.showToast({ + title: res.data.msg || '请检查网络', + icon: 'none', + }) + } + reject(res.data); + } else if (res.data.code == 1) { + store.commit("SET_REQUEST"); + reslove(res.data); + } else if (res.data.code == 200) { + store.commit("SET_REQUEST"); + reslove(res.data.data); + } else if ([410000, 410001, 410002, 40000].indexOf(res.data.code) !== -1) { + toLogin(); + reject(res.data); + } else if (res.data.code == 501) { + // uni.reLaunch({ + // url: '/pages/error/index' + // }) + reject(res.data); + } else { + // uni.hideLoading(); + uni.showToast({ + title: res.data.msg || '请检查网络', + icon: 'none' + }) + reject(res.data.msg || '请检查网络'); + } + }, + fail: (message) => { + // uni.hideLoading() + uni.showToast({ + title: '网络错误', + icon: 'none' + }) + reject('请求失败'); + } + }) + }); +} + +const oahttp = {}; + +['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => { + oahttp[method] = (api, data, opt) => baseRequestTwo(api, method, data, opt || {}) +}); + +export default oahttp; \ No newline at end of file diff --git a/utils/oahttp.js b/utils/oahttp.js new file mode 100644 index 0000000..dc919ec --- /dev/null +++ b/utils/oahttp.js @@ -0,0 +1,134 @@ +import { + HTTP_REQUEST_URL_THREE, + HEADER, + TOKENNAME, +} from '@/config/app'; +import { + Toast +} from '../libs/uniApi'; +// import { checkLogin } from '../libs/login'; +import store from '../store'; + +function toLogin() { + uni.showToast({ + title: '请先登录', + icon: 'none', + duration: 1000 + }); +} + +function baseRequestTwo(url, method, data, { + noAuth = false, + noVerify = false, + onReLogin = false +}) { + let Url = HTTP_REQUEST_URL_THREE, + header = HEADER; + if (!noAuth) { + // 已经未登录了,禁止请求 + if (!store.state.config.request) return Promise.reject({ + msg: '未登录' + }); + //登录过期自动登录 + if (!store.state.app.token) { + toLogin(); + store.commit("SET_REQUEST", false); + return Promise.reject({ + msg: '未登录' + }); + } + } + + // if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token; + if (store.state.app.token) header[TOKENNAME] = store.state.app.token; + + // header[TOKENNAME] = 'Bearer sdjflidshjgfkbdasgjmasbgvhauuiavhkesvndkaesbvkjsdbv'; + return new Promise((reslove, reject) => { + // uni.showLoading({ + // title: '加载中' + // }) + uni.request({ + // url: Url + '/api/v1' + url, + url: Url + '/api' + url, + method: method || 'GET', + header: { + ...header + }, + data: method != 'GET' ? data || {} : {}, + params: method == 'GET' ? data : {}, + success: (res) => { + + if (noVerify) + reslove(res.data); + else if (res.data.code == -1) { + if (onReLogin) { + store.commit('LOGOUT'); + return reject(); + } + + // 如果登录超时,自动重新登录并且继续发送请求 + store.dispatch("RE_LOGIN", { + url: url, + method: method, + data: data, + opt: { + noAuth, + noVerify + } + }).then((e) => { + reslove(e); + }).catch((err) => { + reject(res.data); + }) + // store.commit("SET_REQUEST", false); + } else if (res.data.code == 0) { + + if (res.data.msg != '无登录信息') { + uni.showToast({ + title: res.data.msg || '请检查网络', + icon: 'none', + }) + } + // reject(res.data); + reslove(res.data); + } else if (res.data.code == 1) { + + reslove(res.data); + + } else if (res.data.code == 200) { + store.commit("SET_REQUEST"); + reslove(res.data.data); + + } else if ([410000, 410001, 410002, 40000].indexOf(res.data.code) !== -1) { + toLogin(); + reject(res.data); + } else if (res.data.code == 501) { + reject(res.data); + } else { + uni.showToast({ + title: res.data.msg || '请检查网络', + icon: 'none' + }) + reject(res.data.msg || '请检查网络'); + } + }, + fail: (message) => { + console.log(message) + // uni.hideLoading() + uni.showToast({ + title: '网络错误', + icon: 'none' + }) + reject('请求失败'); + } + }) + }); +} + +const oahttp = {}; + +['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => { + oahttp[method] = (api, data, opt) => baseRequestTwo(api, method, data, opt || {}) +}); + +export default oahttp; \ No newline at end of file diff --git a/utils/request.js b/utils/request.js new file mode 100644 index 0000000..dc49f11 --- /dev/null +++ b/utils/request.js @@ -0,0 +1,77 @@ +import { HTTP_REQUEST_URL, HEADER, TOKENNAME, } from '@/config/app'; +// import { checkLogin } from '../libs/login'; +import store from '../store'; +import props from '../uni_modules/uview-ui/libs/config/props'; + + +function toLogin() { + store.commit("LOGOUT"); + uni.showToast({ + title: '请登录', + icon: 'none', + duration: 1000 + }); +} + +/** + * 发送请求 + */ +function baseRequest(url, method, data, { + noAuth = false, + noVerify = false +}) { + console.log('当前环境', process.env.NODE_ENV); + let Url = HTTP_REQUEST_URL, + header = HEADER; + + if (!noAuth) { + //登录过期自动登录 + // if (!store.state.app.token && !checkLogin()) { + if (!store.state.app.token) { + toLogin(); + return Promise.reject({ + msg: '未登录' + }); + } + } + + if (store.state.app.token) header[TOKENNAME] = 'Bearer ' + store.state.app.token; + + return new Promise((reslove, reject) => { + uni.request({ + url: Url + '/api/' + url, + method: method || 'GET', + header: header, + data: data || {}, + success: (res) => { + // #ifdef APP-PLUS + console.log('app', Url + '/api/' + url, res.data); + // #endif + if (noVerify) + reslove(res.data, res); + else if (res.data.status == 200) + reslove(res.data, res); + else if ([410000, 410001, 410002, 40000].indexOf(res.data.status) !== -1) { + toLogin(); + reject(res.data); + } else if (res.data.status == 501) { + uni.reLaunch({ + url: '/pages/error/index' + }) + reject(res.data); + } else + reject(res.data.message || '系统错误'); + }, + fail: (message) => { + reject('请求失败'); + } + }) + }); +} + +const request = {}; +['options', 'get', 'post', 'put', 'head', 'delete', 'trace', 'connect'].forEach((method) => { + request[method] = (api, data, opt) => baseRequest(api, method, data, opt || {}) +}); + +export default request; diff --git a/utils/time.js b/utils/time.js new file mode 100644 index 0000000..24d6f2e --- /dev/null +++ b/utils/time.js @@ -0,0 +1,34 @@ + +// 格式化:50分钟前,1小时前.20天前 +export const getTimeAgo = (timestamp) => { + const now = Date.now(); + const diff = now - new Date(timestamp); + + // 计算时间差的毫秒数 + const milliseconds = Math.abs(diff); + + // 定义时间单位与对应的毫秒数 + const timeUnits = [ + { unit: '年', ms: 1000 * 60 * 60 * 24 * 365 }, + { unit: '个月', ms: 1000 * 60 * 60 * 24 * 30 }, + { unit: '周', ms: 1000 * 60 * 60 * 24 * 7 }, + { unit: '天', ms: 1000 * 60 * 60 * 24 }, + { unit: '小时', ms: 1000 * 60 * 60 }, + { unit: '分钟', ms: 1000 * 60 }, + ]; + + let str = '' + + // 循环遍历时间单位,并计算时间差所对应的单位 + for (let i = 0; i < timeUnits.length; i++) { + const { unit, ms } = timeUnits[i]; + if (milliseconds >= ms) { + const count = Math.floor(milliseconds / ms); + str = `${count}${unit}前`; + break; + } + } + + // 如果时间差过小,可以自定义返回结果 + return str||'刚刚'; +} diff --git a/utils/websocket.js b/utils/websocket.js new file mode 100644 index 0000000..ffc0426 --- /dev/null +++ b/utils/websocket.js @@ -0,0 +1,85 @@ +let socket = null; +const HEARTBEAT_INTERVAL = 5000; +let heartbeatTimer = null; + +// // 连接到后端 WebSocket,并开始心跳 +// function connect() { +// WebSocket.connect('ws://your-backend-url'); +// startHeartbeat(); +// } + +// 开始发送心跳消息 +function startHeartbeat() { + heartbeatTimer = setInterval(() => { + WebSocket.send('heartbeat'); + }, HEARTBEAT_INTERVAL); +} + +// 停止发送心跳消息 +function stopHeartbeat() { + clearInterval(heartbeatTimer); +} + +// 监听收到的消息 +WebSocket.onMessage((event) => { + if (event.data === 'heartbeat') { + // 收到心跳响应,重置定时器 + resetHeartbeatTimer(); + } else { + // 处理其他消息 + } +}); + +// 重置心跳定时器 +function resetHeartbeatTimer() { + clearInterval(heartbeatTimer); + startHeartbeat(); +} + +// 在页面关闭或组件销毁时,关闭 WebSocket 连接并停止心跳 +uni.onUnload(() => { + WebSocket.close(); + stopHeartbeat(); +}); + + +function connect(url) { + socket = uni.connectSocket({ + url: url + }); + + socket.onOpen(() => { + console.log('WebSocket 连接已打开'); + }); + + socket.onError((error) => { + console.error('WebSocket 连接发生错误', error); + }); + + socket.onClose((e) => { + console.log('WebSocket 连接已关闭', e); + }); + + socket.onMessage((event) => { + console.log('收到服务器消息', event.data); + // 处理收到的消息 + }); +} + +function send(message) { + socket.send({ + data: message + }); +} + +function close() { + if (socket) { + socket.close(); + } +} + +export default { + connect, + send, + close +}; \ No newline at end of file