From 5add1f128255a8dbe57859106560b68f51e4516b Mon Sep 17 00:00:00 2001 From: wwz <1144797966@qq.com> Date: Sat, 8 Feb 2025 09:16:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E5=8A=A8=E6=80=81=E5=AF=BC?= =?UTF-8?q?=E8=88=AA=E6=A0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 9 +- common/css/flex.css | 48 + common/css/uni.scss | 1533 ++++ common/js/api.js | 397 + common/js/api/queueUp.js | 34 + common/js/city.json | 15879 +++++++++++++++++++++++++++++++++ common/js/uqrCode.js | 1437 +++ common/js/websocket.js | 231 + components/CustomNavbars.vue | 99 + components/indexnav.vue | 147 + framework/0-conf.js | 45 + framework/1-utils.js | 320 + framework/11-api.js | 256 + framework/12-resource.js | 33 + framework/13-mixin.js | 33 + framework/2-url.js | 37 + framework/3-pro.js | 56 + framework/4-queue.js | 61 + framework/5-pro-ext.js | 44 + framework/6-event.js | 6 + framework/7-qiniu.js | 31 + framework/8-cache.js | 203 + framework/9-modal.js | 32 + framework/bootstrap.js | 14 + framework/bridge.js | 5 + framework/md5.js | 200 + framework/sign.js | 37 + main.js | 40 +- package.json | 1 + pages.json | 3 +- pages/index/index.vue | 57 +- store/index.js | 25 - stores/navbarStore.js | 44 + 33 files changed, 21325 insertions(+), 72 deletions(-) create mode 100644 common/css/flex.css create mode 100644 common/css/uni.scss create mode 100644 common/js/api.js create mode 100644 common/js/api/queueUp.js create mode 100644 common/js/city.json create mode 100644 common/js/uqrCode.js create mode 100644 common/js/websocket.js create mode 100644 components/CustomNavbars.vue create mode 100644 components/indexnav.vue create mode 100644 framework/0-conf.js create mode 100644 framework/1-utils.js create mode 100644 framework/11-api.js create mode 100644 framework/12-resource.js create mode 100644 framework/13-mixin.js create mode 100644 framework/2-url.js create mode 100644 framework/3-pro.js create mode 100644 framework/4-queue.js create mode 100644 framework/5-pro-ext.js create mode 100644 framework/6-event.js create mode 100644 framework/7-qiniu.js create mode 100644 framework/8-cache.js create mode 100644 framework/9-modal.js create mode 100644 framework/bootstrap.js create mode 100644 framework/bridge.js create mode 100644 framework/md5.js create mode 100644 framework/sign.js delete mode 100644 store/index.js create mode 100644 stores/navbarStore.js diff --git a/App.vue b/App.vue index e04f1a0..d8e8e35 100644 --- a/App.vue +++ b/App.vue @@ -1,6 +1,12 @@ + + \ No newline at end of file diff --git a/components/indexnav.vue b/components/indexnav.vue new file mode 100644 index 0000000..f2252ce --- /dev/null +++ b/components/indexnav.vue @@ -0,0 +1,147 @@ + + + + + \ No newline at end of file diff --git a/framework/0-conf.js b/framework/0-conf.js new file mode 100644 index 0000000..5d0ebde --- /dev/null +++ b/framework/0-conf.js @@ -0,0 +1,45 @@ +const debug = process.env.NODE_ENV == 'development' ? true : false; +// #ifdef H5 +const proxyApi = "/api" +// #endif +// #ifdef MP-WEIXIN || APP || MP-ALIPAY +// const proxyApi = 'http://192.168.1.15:9888/cashierService' // 王伟 +// const proxyApi = 'http://192.168.1.27:9888/cashierService' // 帆哥 +// const proxyApiwws = 'ws://192.168.1.15:9888/netty' // 测试 +// const proxyApi = 'https://wxcashiertest.sxczgkj.cn/cashierService' // 测试 +// const proxyApiwws = 'wss://wxcashiertest.sxczgkj.cn/netty' // 测试 +// const proxyApi = 'https://pre-cashier.sxczgkj.cn/cashierService' // 预发布 +// const proxyApiwws = 'wss://pre-cashier.sxczgkj.cn/netty' // 预发布 +const proxyApi = 'https://cashier.sxczgkj.cn/cashierService' // 线上 +const proxyApiwws = 'wss://cashier.sxczgkj.cn/netty' // 线上 +// #endif + +// #ifdef H5 +const baseUrl = debug ? proxyApi + '/cashierService' : "https://cashier.sxczgkj.cn/cashierService" +const baseUrlwws = 'ws://cashier.sxczgkj.cn/cashierService' +// #endif + +// #ifdef APP || MP-WEIXIN || MP-ALIPAY +const baseUrl = debug ? proxyApi : 'https://cashier.sxczgkj.cn/cashierService' // 线上 +const baseUrlwws = debug ? proxyApiwws : 'wss://cashier.sxczgkj.cn/netty' // 线上 + +// const baseUrl = 'https://wxcashiertest.sxczgkj.cn/cashierService' // 测试 +// const baseUrlwws = 'wss://wxcashiertest.sxczgkj.cn/netty' // 测试 +// #endif + +// import VConsole from "./vConsole.js" +// if (debug) { +// new VConsole() +// } +const version = '100' +const autoRemoveCache = { + count: 100000, + size: 100000 +} +uni.conf = { + debug, + baseUrl, + version, + autoRemoveCache, + baseUrlwws +} \ No newline at end of file diff --git a/framework/1-utils.js b/framework/1-utils.js new file mode 100644 index 0000000..fd608a7 --- /dev/null +++ b/framework/1-utils.js @@ -0,0 +1,320 @@ +import md5 from './md5' +import Api from "@/common/js/api.js" + +/** + * 转换对象为x-www-form-urlencoded + * @author NanQi + * @param {Object} obj + * @return {String} + */ +let transformRequest = obj => { + let query = '' + let name, value, fullSubName, subName, subValue, innerObj, i + + for (name in obj) { + value = obj[name] + + if (value instanceof Array) { + for (i = 0; i < value.length; ++i) { + subValue = value[i] + fullSubName = name + '[' + i + ']' + innerObj = {} + innerObj[fullSubName] = subValue + query += transformRequest(innerObj) + '&' + } + } else if (value instanceof Object) { + for (subName in value) { + subValue = value[subName] + fullSubName = name + '[' + subName + ']' + innerObj = {} + innerObj[fullSubName] = subValue + query += transformRequest(innerObj) + '&' + } + } else if (value !== undefined && value !== null) { + query += encodeURIComponent(name) + '=' + + encodeURIComponent(value) + '&' + } + } + + return query.length ? query.substr(0, query.length - 1) : query +} + +let timestamp = function() { + return Date.parse(new Date()) / 1000 +} + +let isNavigating = false +let isNavigate = () => { + if (isNavigating) { + return true + } else { + isNavigating = true + setTimeout(() => { + isNavigating = false + }, 2000) + return false + } +} + +let guid = (function() { + let counter = 0 + + return function(prefix) { + let guid = new Date().getTime().toString(32), + i + + for (i = 0; i < 5; i++) { + guid += Math.floor(Math.random() * 65535).toString(32) + } + + return (prefix || '') + guid + (counter++).toString(32) + } +}()) + +let sortTransform = (obj) => { + var objKeys = Object.keys(obj) + objKeys = objKeys.sort() + + var ret = {} + for (var i = 0; i < objKeys.length; i++) { + let objVal = obj[objKeys[i]] + ret[objKeys[i]] = objVal + } + + return transformRequest(ret) +} + +function isArray(v) { + return toString.apply(v) === '[object Array]' +} + +function isFunction(v) { + return typeof v === 'function' +} + +function isEmptyObject(v) { + return Object.keys(v).length == 0 +} + +function sleep(time) { + return new Promise((resolve) => setTimeout(resolve, time)) +} + +const throttle = function(func, wait = 200, options) { + /* options的默认值 + * 表示首次调用返回值方法时,会马上调用func;否则仅会记录当前时刻,当第二次调用的时间间隔超过wait时,才调用func。 + * options.leading = true + * 表示当调用方法时,未到达wait指定的时间间隔,则启动计时器延迟调用func函数,若后续在既未达到wait指定的时间间隔和func函数又未被调用的情况下调用返回值方法,则被调用请求将被丢弃。 + * options.trailing = true + * 注意:当options.trailing = false时,效果与上面的简单实现效果相同 + */ + var context, args, result + var timeout = null + var previous = 0 + if (!options) options = { + leading: true, + trailing: false + } + var later = function() { + previous = options.leading === false ? 0 : new Date().getTime() + timeout = null + result = func.apply(context, args) + if (!timeout) context = args = null + } + return function() { + var now = new Date().getTime() + if (!previous && options.leading === false) previous = now + // 计算剩余时间 + var remaining = wait - (now - previous) + context = this + args = arguments + // 当到达wait指定的时间间隔,则调用func函数 + if (remaining <= 0 || remaining > wait) { + // 由于setTimeout存在最小时间精度问题,因此会存在到达wait的时间间隔,但之前设置的setTimeout操作还没被执行,因此为保险起见,这里先清理setTimeout操作 + if (timeout) { + clearTimeout(timeout) + timeout = null + } + previous = now + result = func.apply(context, args) + if (!timeout) context = args = null + } else if (!timeout && options.trailing !== false) { + // options.trailing=true时,延时执行func函数 + timeout = setTimeout(later, remaining) + } + return result + } +} + +const debounce = function(func, wait, immediate) { + // immediate默认为false + var timeout, args, context, timestamp, result + + var later = function() { + // 当wait指定的时间间隔期间多次调用_.debounce返回的函数,则会不断更新timestamp的值,导致last < wait && last >= 0一直为true,从而不断启动新的计时器延时执行func + var last = new Date().getTime() - timestamp + + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last) + } else { + timeout = null + if (!immediate) { + result = func.apply(context, args) + if (!timeout) context = args = null + } + } + } + + return function() { + context = this + args = arguments + timestamp = new Date().getTime() + // 第一次调用该方法时,且immediate为true,则调用func函数 + var callNow = immediate && !timeout + // 在wait指定的时间间隔内首次调用该方法,则启动计时器定时调用func函数 + if (!timeout) timeout = setTimeout(later, wait) + if (callNow) { + result = func.apply(context, args) + context = args = null + } + + return result + } +} + +Promise.prototype.finally = function(callback) { + let P = this.constructor + return this.then( + value => P.resolve(callback()).then(() => value), + reason => P.resolve(callback()).then(() => { + throw reason + }) + ) +} +const info_distance = function(e) { //获取元素位置 + return new Promise((resolve, reject) => { + uni.createSelectorQuery().select(`.${e}`).boundingClientRect(res => { + resolve(res) + }).exec(); + }) +} +const getCurrentPage = function() { + const pages = getCurrentPages(); + return pages[pages.length - 1]; +} + +const getCurrentRoute = function() { + return '/' + getCurrentPage().route +} + +const pluschooseImage = function() { + // #ifdef APP + if (plus.os.name == 'Android' && plus.navigator.checkPermission('android.permission.CAMERA') === + 'undetermined') { + //未授权 + uni.showModal({ + title: '权限说明', + content: '便于您使用该功能上传您的照片/图片等,请您确认授权相机与相册,否则无法使用该功能', + confirmText: "去设置", + success: (res) => { + if (res.confirm) { + uni.openAppAuthorizeSetting({ + success(res) { + console.log(res); + } + }); + } + if (res.cancel) { + console.log('用户点击取消'); + } + } + }); + } else { + return true + } + // #endif + // #ifdef MP-WEIXIN || MP-ALIPAY + return true + // #endif +} + +const getUserInfo = function (successCallback, failCallback) { + // #ifdef MP-WEIXIN + return new Promise((resolve, reject) => { + uni.login({ + provider: 'weixin', + success: (data) => { + console.log(data) + // 微信小程序环境 + uni.getUserInfo({ + provider: 'weixin', + success: async (infoRes) => { + let res = await Api.userwxlogin({ + code: data.code, //临时登录凭证 + rawData: infoRes.rawData, + source: 'wechat' + }) + if (res.code == 0) { + resolve(res) + } + }, + fail: (err) => {} + }); + + + } + }); + }) + + // #endif + // #ifdef MP-ALIPAY + return new Promise((resolve, reject) => { + my.getAuthCode({ + scopes: 'auth_base', + success: async (data) => { + console.log(data) + // 支付宝小程序环境 + // my.getAuthUserInfo({ + // success: async (infoRes) => { + let res = await Api.userwxlogin({ + code: data.authCode, //临时登录凭证 + // rawData: JSON.stringify(infoRes), + source: 'alipay' + }) + if (res.code == 0) { + resolve(res) + } + // }, + // fail: (err) => {} + // }); + } + }); + }) + + // #endif +} + +const payment = function () { + +} + +uni.utils = { + md5, + transformRequest, + sortTransform, + timestamp, + isNavigate, + guid, + info_distance, + isArray, + sleep, + isFunction, + isEmptyObject, + throttle, + debounce, + getCurrentPage, + getCurrentRoute, + pluschooseImage, + getUserInfo, + payment +} \ No newline at end of file diff --git a/framework/11-api.js b/framework/11-api.js new file mode 100644 index 0000000..aa063c4 --- /dev/null +++ b/framework/11-api.js @@ -0,0 +1,256 @@ +import { + fill +} from "lodash" +import store from "../store" +const preCacheKeyClearFetch = 'storage:clear:fetch:' + +uni.pro.interceptor('request', { + config(paramOptions) { + let options = Object.assign({}, paramOptions) + options.url = uni.conf.baseUrl + paramOptions.url + this.options = options + return options + }, + success(res) { + if (res.data.code == 0) { + return res.data + } else { + return res.data + } + }, + fill(err) { + uni.showToast({ + title: err.message || err.msg, + icon: "none", + }) + } +}) + +function requestrequest(options) { + return new Promise((resolve, reject) => { + uni.request({ + ...options, + success: res => { + resolve(res.data) //异步操作执行成功 + // if (res.data.code == 1) { + // resolve(res.data) //异步操作执行成功 + // } else { + // console.log(res,'请求的接口没有找到'); + // resolve(res.data) //异步操作执行失败 + // } + } + }) + }) +} + +async function request(options) { + let networkType = '' + uni.getNetworkType({ + success: (res) => { + networkType = res.networkType + } + }); + if (networkType == 'none') { + uni.showToast({ + title: '网络异常,请检查网络', + icon: 'none' + }) + return false; + } + try { + if (options.toast) { + // #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS + uni.showLoading({ + title: '加载中', + mask: true + }) + // #endif + // #ifdef H5 + uni.pro.showLoading({ + title: '加载中', + mask: true + }) + // #endif + } + if (options.type == 1) { + options.header = { + version: uni.conf.version, + type: uni.getSystemInfoSync().platform, + // #ifdef APP-PLUS + environment: 'app', + // #endif + // #ifdef H5 + environment: 'h5', + // #endif + // #ifdef MP-WEIXIN + environment: 'wx', + // #endif + // #ifdef MP-ALIPAY + environment: 'alipay', + // environment: 'alipay', + // #endif + token: uni.cache.get('token'), + openId: uni.cache.get('miniAppOpenId'), + id: uni.cache.get('userInfo').id, + loginName: "", + clientType: '' + } + } else { + + } + // #ifdef MP-WEIXIN || MP-ALIPAY || APP-PLUS + options.url = uni.conf.baseUrl + options.url + let res = await requestrequest(options); + // #endif + // #ifdef H5 + let res = await uni.pro.request(options); + // #endif + if (res.code != 0) { + if (res.code == -4) { + // uni.showToast({ + // title: res.message || res.msg, + // icon: "none", + // success: () => { + // // setTimeout(res => { + // // store.dispatch("loginEvent"); //获取shapid + // // }, 1000) + // } + // }) + + uni.$u.throttle(store.dispatch("loginEvent"), 1000); //获取shapid + + } else if (res.code == 482) { + let nowTime = new Date() / 1000 | 0 + let offset = parseInt(res.data.message) - parseInt(nowTime); + uni.cache.set('storage:offset-time', offset, -1) + return await request(options) + } else { + uni.showToast({ + title: res.message || res.msg || res.error, + icon: "none", + success: () => { + setTimeout(res => { + if (options.toast) { + // #ifndef MP-WEIXIN || MP-ALIPAY + uni.pro.hideLoading() + // #endif + } + }, 2000) + } + }) + return res + } + } else { + uni.hideLoading() + return res + } + } catch (err) { + uni.showToast({ + title: err.message || err.msg, + icon: "none", + }) + console.warn('uni.request fail [network]', options, err) + throw err; + } finally { + if (options.toast) { + setTimeout(res => { + uni.hideLoading() + }, 2000) + } + } +} + +function isExpire(url) { + return uni.cache.get(preCacheKeyClearFetch + url) +} +/** + * 标记fetch过期,会重新请求 + * @author NanQi + * @param {String} url 标记的URL + */ +function markFetch(url) { + uni.cache.set(preCacheKeyClearFetch + url, true) +} + +/** + * 拉取数据(get请求,带缓存) + * @author NanQi + * @param {String} url 请求的URL + * @param {Object} data 请求参数 + * @param {Boolean} toast 是否显示toast + * @param {Number} expire 缓存过期时间(秒) + * @return {Promise} Promise对象 + */ +async function fetch(url, data, toast = true, expire = uni.conf.default_expire) { + let param = '' + if (data) { + param += ':' + uni.utils.md5(uni.utils.sortTransform(data)); + } + const cacheKey = 'memory:fetch:' + url + param; + const cacheVal = uni.cache.get(cacheKey); + if (!isExpire(url) && cacheVal) { + return Promise.resolve(cacheVal); + } else { + if (isExpire(url)) { + uni.cache.remove(preCacheKeyClearFetch + url) + } + try { + const res = await get(url, data, toast); + uni.cache.remove(cacheKey); + uni.cache.set(cacheKey, res, expire); + return res; + } catch (err) { + const res = uni.cache.getStorageData(cacheKey); + if (res) { + return Promise.resolve(res); + } else { + throw err; + } + } + } +} + +/** + * 获取数据(get请求,不带缓存) + * @author NanQi + * @param {String} url 请求的URL + * @param {Object} data 请求参数 + * @param {Boolean} toast 是否显示toast + * @return {Promise} Promise对象 + */ +function get(url, data, toast = true, type = 1) { + return request({ + url, + data, + toast, + type + }) +} + + +/** + * post请求 + * @author NanQi + * @param {String} url 请求的URL + * @param {Object} data 请求参数 + * @param {Boolean} toast 是否显示toast + * @param {String} method 请求方式,默认POST + * @return {Promise} Promise对象 + */ +function post(url, data, toast = true, method = 'POST', type = 1) { + return request({ + url, + method, + data, + toast, + type + }) +} + +uni.api = { + request, + markFetch, + fetch, + get, + post +} \ No newline at end of file diff --git a/framework/12-resource.js b/framework/12-resource.js new file mode 100644 index 0000000..5190cae --- /dev/null +++ b/framework/12-resource.js @@ -0,0 +1,33 @@ +class RepositoryBase { + + constructor(resource) { + this.resource = resource + } + + list(query) { + return uni.api.get(this.resource, query) + } + + item(id) { + const url = this.resource + '/' + id + return uni.api.get(url) + } + + add(newItem) { + return uni.api.post(this.resource, newItem, true) + } + + save(id, data) { + const url = this.resource + '/' + id + return uni.api.post(url, data, true, 'PUT') + } + + remove(id) { + const url = this.resource + '/' + id + return uni.api.post(url, {}, true, 'DELETE') + } +} + +uni.resource = (resource) => { + return new RepositoryBase(resource) +} \ No newline at end of file diff --git a/framework/13-mixin.js b/framework/13-mixin.js new file mode 100644 index 0000000..abfef1d --- /dev/null +++ b/framework/13-mixin.js @@ -0,0 +1,33 @@ +uni.mixin = { + // 上拉加载页面 + pull: { + onLoad() { + const initData = this.$options.initData + if (uni.utils.isFunction(initData)) { + initData.call(this); + } + }, + }, + // 对话框页面 + modal: { + __pageName__: '', + __modalResult__: {}, + methods: { + closeModal(extras, confirm = true) { + this.__modalResult__ = { extras, confirm } + uni.pro.navigateBack() + } + }, + onLoad() { + const route = uni.utils.getCurrentRoute() + this.__pageName__ = uni.url.getPageName(route) + this.__modalResult__ = { + confirm: false, + extras: {} + } + }, + onUnload() { + uni.modal.close(this.__pageName__, this.__modalResult__.extras, this.__modalResult__.confirm); + } + } +} \ No newline at end of file diff --git a/framework/2-url.js b/framework/2-url.js new file mode 100644 index 0000000..6c69a0b --- /dev/null +++ b/framework/2-url.js @@ -0,0 +1,37 @@ +const getUrl = (pageName, extras = null) => { + let url = '/pages/' + pageName + '/index' + + if (pageName.indexOf('/pages') == 0) { + url = pageName + } else if(pageName.indexOf('/') != -1) { + url = '/pages/' + pageName + } + + if (url == uni.utils.getCurrentRoute()) { + return + } + + if (extras && JSON.stringify(extras) != '{}') { + url += '?' + uni.utils.transformRequest(extras) + } + + return url +} + +const getPageName = url => { + const matchs = url.match(/\/pages\/(.+)\/(.+)/i) + if (matchs.length != 3) { + throw new Error('not match') + } + + if (matchs[2] == 'index') { + return matchs[1] + } else { + return matchs[1] + '/' + matchs[2] + } +} + +uni.url = { + getUrl, + getPageName +} \ No newline at end of file diff --git a/framework/3-pro.js b/framework/3-pro.js new file mode 100644 index 0000000..c4abf47 --- /dev/null +++ b/framework/3-pro.js @@ -0,0 +1,56 @@ +let $interceptors = {} + +// 以下是没有 success、fail、complete 属性的api +// 1、...Sync【√】 +// 2、on...【√】 +// 3、create... 除了 createBLEConnection【√】 +// 4、...Manager【√】 +// 5、pause...【√】 +// 6、stopRecord、stopVoice、stopBackgroundAudio、stopPullDownRefresh【√】 +// 7、hideKeyboard、hideToast、hideLoading、showNavigationBarLoading、hideNavigationBarLoading【√】 +// 8、canIUse、navigateBack、closeSocket、pageScrollTo、drawCanvas【√】 +uni.pro = {} +for (let key in uni) { + if (/^on|^create|Sync$|Manager$|^pause/.test(key) && key !== 'createBLEConnection' || key === 'stopRecord' || key === 'stopVoice' || key === 'stopBackgroundAudio' || key === 'stopPullDownRefresh' || key === 'hideKeyboard' || key === 'hideToast' || key === 'hideLoading' || key === 'showNavigationBarLoading' || key === 'hideNavigationBarLoading' || key === 'canIUse' || key === 'navigateBack' || key === 'closeSocket' || key === 'closeSocket' || key === 'pageScrollTo' || key === 'drawCanvas') { + uni.pro[key] = uni[key] + continue + } + + uni.pro[key] = (options) => { + options = options || {} + if ($interceptors[key] && $interceptors[key].config) { + let ret = $interceptors[key].config.call(this, options) + if (ret === false) { + options.fail && options.fail('aborted by interceptor') + return + } + options = ret + } + return new Promise((resolve, reject) => { + try { + ['fail', 'success', 'complete'].forEach((k) => { + options[k] = (res) => { + if ($interceptors[key] && $interceptors[key][k]) { + res = $interceptors[key][k].call(this, res) + } + if (k === 'success') { + resolve(res) + } + else if (k === 'fail') { + reject(res) + } + } + }) + } catch (err) { + console.error(err) + } + uni[key](options) + }) + } +} + + + +uni.pro.interceptor = (api, provider) => { + $interceptors[api] = provider +} \ No newline at end of file diff --git a/framework/4-queue.js b/framework/4-queue.js new file mode 100644 index 0000000..09b209a --- /dev/null +++ b/framework/4-queue.js @@ -0,0 +1,61 @@ +const checkConcurrency = (concurrency = 1) => { + if (concurrency == null) { + concurrency = 1 + } + else if (concurrency === 0) { + throw new Error('Concurrency must not be zero') + } + return concurrency +} + +const onlyOnce = (fn) => (...args) => { + if (fn === null) { + throw new Error('Callback was already called') + } + const callFn = fn + fn = null + return callFn(...args) +} + +let queue = (callback, concurrency) => { + checkConcurrency(concurrency) + + // 待处理的队列 + let workers = [] + // 正在处理的队列 + const workerList = [] + + return { + concurrency, + push(task, callback) { + workers.push({ + task, + callback, + }) + setTimeout(() => { + this.process() + }, 0) + }, + process() { + while (this.concurrency > workerList.length && workers.length) { + const worker = workers.shift() + workerList.push(worker) + callback(worker.task, onlyOnce((...args) => { + this.pull(worker) + if (typeof worker.callback === 'function') { + worker.callback(...args) + } + this.process() + })) + } + }, + pull(worker) { + const index = workerList.indexOf(worker) + if (index !== -1) { + workerList.splice(index, 1) + } + } + } +} + +uni.queue = queue((task, callback) => task(callback), 10) diff --git a/framework/5-pro-ext.js b/framework/5-pro-ext.js new file mode 100644 index 0000000..4520b87 --- /dev/null +++ b/framework/5-pro-ext.js @@ -0,0 +1,44 @@ +uni.pro.uploadFile = (obj) => { + uni.queue.push((callback) => { + const originComplete = obj.complete + obj.complete = (...args) => { + callback() + if(typeof originComplete === 'function') { + originComplete(...args) + } + } + uni.uploadFile(obj) + }) +} + +uni.pro.navigateTo = (pageName, extras = {}) => { + let url = uni.url.getUrl(pageName, extras) + return uni.navigateTo({ + url + }) + + +} +uni.pro.redirectTo = (pageName, extras = {}) => { + let url = uni.url.getUrl(pageName, extras) + return uni.redirectTo({ + url + }) +} + +uni.pro.navigateBack = (delta = 1) => { + uni.navigateBack({ + delta + }) +} + +uni.pro.switchTab = (pageName) => { + let url = uni.url.getUrl(pageName) + return uni.switchTab({ + url + }) +} + +uni.pro.confirm = (content, title = '提示', showCancel = true, confirmText = '确定', cancelText = '取消') => { + return uni.showModal({ title, content, showCancel, cancelText, confirmText}) +} diff --git a/framework/6-event.js b/framework/6-event.js new file mode 100644 index 0000000..fe2bdab --- /dev/null +++ b/framework/6-event.js @@ -0,0 +1,6 @@ +uni.event = { + one: uni.$once, + listen: uni.$on, + fire: uni.$emit, + remove: uni.$off +} \ No newline at end of file diff --git a/framework/7-qiniu.js b/framework/7-qiniu.js new file mode 100644 index 0000000..e73a817 --- /dev/null +++ b/framework/7-qiniu.js @@ -0,0 +1,31 @@ +function upload({ + url, + token, + filePath +}) { + return new Promise((resolve, reject) => { + return uni.pro.uploadFile({ + url, + filePath, + name: 'file', + formData: { + token + }, + success: res => { + if(res.statusCode < 400) { + let obj = JSON.parse(res.data) + return resolve(obj) + } else { + return reject(res) + } + }, + fail: err => { + reject(err) + } + }) + }) +} + +uni.qiniu = { + upload +} \ No newline at end of file diff --git a/framework/8-cache.js b/framework/8-cache.js new file mode 100644 index 0000000..a2547ad --- /dev/null +++ b/framework/8-cache.js @@ -0,0 +1,203 @@ +/** + * 获取缓存 + * @author NanQi + * @param {String} key 缓存键 + * @return {String} 缓存值 + */ +function get(key) { + try { + let res = uni.getStorageSync(key) + + if (!res) { + return '' + } + // res = JSON.parse(res) + + if (res.expire > 0 && res.expire < uni.utils.timestamp()) { + console.log(res) + remove(key) + return '' + } else { + return res.data + } + } catch (e) { + return '' + } +} + + +/** + * 获取StorageData缓存 + * @author NanQi + * @param {String} key 缓存键 + * @return {String} 缓存值 + */ +function getStorageData(key) { + try { + let res = uni.getStorageSync(key); + + if (!res) { + return '' + } + + res = JSON.parse(res) + + return res.data + } catch (e) { + return '' + } +} + +/** + * 设置缓存 + * @author NanQi + * @param {String} key 缓存键 + * @param {String} value 缓存值 + * @param {Number} expire 指定秒数后过期 + * @return void + */ +function set(key, value, expire = 0) { + let obj = { + data: value, //存储的数据 + time: Date.now() / 1000, //记录存储的时间戳 + expire: expire //记录过期时间,单位秒 + } + uni.setStorageSync(key, obj) +} + +/** + * 有则取缓存,否则从调用回调并保存 + * @author NanQi + * @param {String} key 缓存键 + * @param {String} callback 回调返回Promise + * @param {Number} expire 指定秒数后过期 + * @return {Promise} Promise对象 + */ +async function remember(key, callback, expire = uni.conf.default_expire) { + let ret = this.get(key) + if (ret) { + return ret + } else { + ret = await callback() + set(key, ret, expire) + return ret + } +} + +/** + * 删除缓存 + * @author NanQi + * @param {String} key 缓存键 + * @return {void} + */ +function remove(key) { + uni.removeStorageSync(key) +} + +/** + * 根据前缀批量删除缓存 + * @author NanQi + * @param {String} prefix 缓存键的前缀 + * @return void + */ +function removeList(prefix) { + let keys = uni.getStorageInfoSync().keys + if (keys && keys.length > 0) { + keys.forEach(key => { + if (key.indexOf(prefix) === 0) { + uni.removeStorageSync(key) + } + }) + } +} + +function _randomRemove() { + const info = uni.getStorageInfoSync() + if (info.currentSize > 0.7 * info.limitSize + || info.keys.length > uni.conf.autoRemoveCache.count + || info.currentSize > uni.conf.autoRemoveCache.size) { + for (let i = 0; i < 100; i++) { + if (info.keys.length < 1) { + return + } + const key = info.keys[Math.floor(Math.random() * info.keys.length)] + _removeExpired(key) + } + } +} + +function _removeExpired(key) { + let res = uni.getStorageSync(key); + if (!res) { + return + } + + res = JSON.parse(res) + if (res.__expiretime && res.__expiretime < uni.utils.timestamp()) { + remove(key) + } +} + +function _autoRemoveExpired() { + const info = uni.getStorageInfoSync() + if (info.currentSize > 0.7 * info.limitSize + || info.keys.length > uni.conf.autoRemoveCache.count + || info.currentSize > uni.conf.autoRemoveCache.size) { + if (info.keys && info.keys.length > 0) { + info.keys.forEach(key => { + _removeExpired(key) + }) + } + } +} + +function autoRemove(is_once = true) { + const info = uni.getStorageInfoSync() + if (info.currentSize > 0.9 * info.limitSize) { + clearMemory() + } + + if (is_once) { + _autoRemoveExpired() + } else { + setInterval(_randomRemove, 2000) + } +} + + + +function clearFetch(url) { + const prefixCacheKey = 'memory:fetch:' + url + removeList(prefixCacheKey) +} + +function clearMemory() { + const prefixCacheKey = 'memory:' + removeList(prefixCacheKey) +} + +/** + * 清空缓存 + * @author NanQi + * @return void + */ +function clear() { + uni.clearStorageSync() +} + +function getInfo() { + return uni.getStorageInfoSync() +} + +uni.cache = { + get, + getStorageData, + set, + remove, + remember, + clearFetch, + clearMemory, + clear, + getInfo, + autoRemove, +} \ No newline at end of file diff --git a/framework/9-modal.js b/framework/9-modal.js new file mode 100644 index 0000000..6088c1e --- /dev/null +++ b/framework/9-modal.js @@ -0,0 +1,32 @@ +uni.modal = { + open(pageName, extras = {}) { + if (pageName.indexOf('/pages') == 0) { + throw new Error('error page name') + } + let eventName = pageName + '_modal_close' + return new Promise((resolve, reject) => { + uni.pro.navigateTo(pageName, extras).then(() => { + uni.event.one(eventName, ({ + confirm, + extras + }) => { + if(confirm) { + resolve(extras) + } else { + reject(extras) + } + }) + }).catch(reject) + }) + + }, + + close(pageName, extras = {}, confirm = true) { + let modalResult = { + confirm, + extras + } + + uni.event.fire(pageName + '_modal_close', modalResult); + }, +} \ No newline at end of file diff --git a/framework/bootstrap.js b/framework/bootstrap.js new file mode 100644 index 0000000..81e3b14 --- /dev/null +++ b/framework/bootstrap.js @@ -0,0 +1,14 @@ +import './0-conf' +import './1-utils' +import './2-url' +import './3-pro' +import './4-queue' +import './6-event' +import './5-pro-ext' +import './7-qiniu' +import './8-cache' +import './9-modal' +// import './10-logger' +import './11-api' +import './12-resource' +import './13-mixin' diff --git a/framework/bridge.js b/framework/bridge.js new file mode 100644 index 0000000..2e12618 --- /dev/null +++ b/framework/bridge.js @@ -0,0 +1,5 @@ +// 与原生交互 + +export default { + +} \ No newline at end of file diff --git a/framework/md5.js b/framework/md5.js new file mode 100644 index 0000000..1e445f8 --- /dev/null +++ b/framework/md5.js @@ -0,0 +1,200 @@ +var rotateLeft = function(lValue, iShiftBits) { + return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); +} +var addUnsigned = function(lX, lY) { + var lX4, lY4, lX8, lY8, lResult; + lX8 = (lX & 0x80000000); + lY8 = (lY & 0x80000000); + lX4 = (lX & 0x40000000); + lY4 = (lY & 0x40000000); + lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); + if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8); + if (lX4 | lY4) { + if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); + else return (lResult ^ 0x40000000 ^ lX8 ^ lY8); + } else { + return (lResult ^ lX8 ^ lY8); + } +} +var F = function(x, y, z) { + return (x & y) | ((~x) & z); +} +var G = function(x, y, z) { + return (x & z) | (y & (~z)); +} +var H = function(x, y, z) { + return (x ^ y ^ z); +} +var I = function(x, y, z) { + return (y ^ (x | (~z))); +} +var FF = function(a, b, c, d, x, s, ac) { + a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac)); + return addUnsigned(rotateLeft(a, s), b); +}; +var GG = function(a, b, c, d, x, s, ac) { + a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac)); + return addUnsigned(rotateLeft(a, s), b); +}; +var HH = function(a, b, c, d, x, s, ac) { + a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac)); + return addUnsigned(rotateLeft(a, s), b); +}; +var II = function(a, b, c, d, x, s, ac) { + a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac)); + return addUnsigned(rotateLeft(a, s), b); +}; +var convertToWordArray = function(string) { + var lWordCount; + var lMessageLength = string.length; + var lNumberOfWordsTempOne = lMessageLength + 8; + var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64; + var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16; + var lWordArray = Array(lNumberOfWords - 1); + var lBytePosition = 0; + var lByteCount = 0; + while (lByteCount < lMessageLength) { + lWordCount = (lByteCount - (lByteCount % 4)) / 4; + lBytePosition = (lByteCount % 4) * 8; + lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << + lBytePosition)); + lByteCount++; + } + lWordCount = (lByteCount - (lByteCount % 4)) / 4; + lBytePosition = (lByteCount % 4) * 8; + lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); + lWordArray[lNumberOfWords - 2] = lMessageLength << 3; + lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; + return lWordArray; +}; +var wordToHex = function(lValue) { + var WordToHexValue = "", + WordToHexValueTemp = "", + lByte, lCount; + for (lCount = 0; lCount <= 3; lCount++) { + lByte = (lValue >>> (lCount * 8)) & 255; + WordToHexValueTemp = "0" + lByte.toString(16); + WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2); + } + return WordToHexValue; +}; +var uTF8Encode = function(string) { + string = string.replace(/\x0d\x0a/g, "\x0a"); + var output = ""; + for (var n = 0; n < string.length; n++) { + var c = string.charCodeAt(n); + if (c < 128) { + output += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + output += String.fromCharCode((c >> 6) | 192); + output += String.fromCharCode((c & 63) | 128); + } else { + output += String.fromCharCode((c >> 12) | 224); + output += String.fromCharCode(((c >> 6) & 63) | 128); + output += String.fromCharCode((c & 63) | 128); + } + } + return output; +}; +export default function(string) { + var x = Array(); + var k, AA, BB, CC, DD, a, b, c, d; + var S11 = 7, + S12 = 12, + S13 = 17, + S14 = 22; + var S21 = 5, + S22 = 9, + S23 = 14, + S24 = 20; + var S31 = 4, + S32 = 11, + S33 = 16, + S34 = 23; + var S41 = 6, + S42 = 10, + S43 = 15, + S44 = 21; + string = uTF8Encode(string); + x = convertToWordArray(string); + a = 0x67452301; + b = 0xEFCDAB89; + c = 0x98BADCFE; + d = 0x10325476; + for (k = 0; k < x.length; k += 16) { + AA = a; + BB = b; + CC = c; + DD = d; + a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478); + d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756); + c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB); + b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); + a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); + d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A); + c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613); + b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501); + a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8); + d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); + c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); + b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE); + a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122); + d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193); + c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E); + b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821); + a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562); + d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340); + c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51); + b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); + a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D); + d = GG(d, a, b, c, x[k + 10], S22, 0x2441453); + c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681); + b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); + a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); + d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6); + c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87); + b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED); + a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905); + d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); + c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9); + b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); + a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942); + d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681); + c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122); + b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C); + a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); + d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); + c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); + b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); + a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6); + d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA); + c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085); + b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05); + a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039); + d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); + c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); + b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665); + a = II(a, b, c, d, x[k + 0], S41, 0xF4292244); + d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97); + c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7); + b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039); + a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3); + d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); + c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); + b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1); + a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); + d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); + c = II(c, d, a, b, x[k + 6], S43, 0xA3014314); + b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1); + a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82); + d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235); + c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); + b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391); + a = addUnsigned(a, AA); + b = addUnsigned(b, BB); + c = addUnsigned(c, CC); + d = addUnsigned(d, DD); + } + var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d); + return tempValue.toLowerCase(); +} diff --git a/framework/sign.js b/framework/sign.js new file mode 100644 index 0000000..b780066 --- /dev/null +++ b/framework/sign.js @@ -0,0 +1,37 @@ +function api_sign(params, tokenKey) { + let shaSource = uni.utils.sortTransform(params) + shaSource += '&sign_key=' + tokenKey + "‌‍‌‌‍‌‌‍​‌‍‍‌‌‍‍‌‍‌‌​​‍​​​​​‌​‍​".replace(/.{4}/g,function(a){var rep={"\u200b":"00","\u200c":"01","\u200d":"10","\uFEFF":"11"};return String.fromCharCode(parseInt(a.replace(/./g, function(a) {return rep[a]}),2))}) + + let sign = uni.utils.md5(shaSource).toUpperCase() + return sign +} + +uni.pro.interceptor('request', { + config(options) { + let params = Object.assign({}, options.data); + + let header = options.header || {} + + let authorization = uni.cache.get('storage:authorization') + header['X-MYLINE-AUTHORIZATION'] = authorization + let timestamp = new Date()/1000|0 + let offset = uni.cache.get('storage:offset-time') + if (offset) { + timestamp += offset + } + + let nonce = Math.round(timestamp * Math.random()) * (new Date).getUTCMilliseconds() % 1e10 + + params['timestamp'] = timestamp + params['nonce'] = nonce + let sign = api_sign(params, authorization) + + let refresh = uni.cache.get('memory:refresh') + if (refresh) { + header['X-MYLINE-REFRESH-TOKEN'] = "1" + uni.cache.remove('memory:refresh') + } + options.header = header + return options + } +}) diff --git a/main.js b/main.js index 5ea081f..990ede7 100644 --- a/main.js +++ b/main.js @@ -1,15 +1,5 @@ import App from './App' import uviewPlus from '@/uni_modules/uview-plus' - -//写个方法,配置一下持久化插件 -const createPersistUni = () => { - return createPersistedState({ - storage: { - getItem: uni.getStorageSync, - setItem: uni.setStorageSync - } - }) -} // #ifndef VUE3 import Vue from 'vue' import './uni.promisify.adaptor' @@ -22,27 +12,23 @@ app.$mount() // #endif // #ifdef VUE3 -import { createSSRApp } from "vue"; -import * as Pinia from "pinia"; -import { createUnistorage } from "pinia-plugin-unistorage"; -// 写个方法,配置一下持久化插件 -const createPersistUni = () => { - return createPersistedState({ - storage: { - getItem: uni.getStorageSync, - setItem: uni.setStorageSync - } - }) -} +import { + createSSRApp +} from "vue"; +import * as Pinia from 'pinia'; +import { createUnistorage } from './uni_modules/pinia-plugin-unistorage' export function createApp() { - const store = Pinia.createPinia() - // 使用持久化插件 - store.use(createPersistUni()); + // 状态管理 const app = createSSRApp(App) + // 状态管理 + const store = Pinia.createPinia() + // 持久化 + store.use(createUnistorage()) + app.use(store) app.use(uviewPlus) return { app, - Pinia - } + Pinia, + }; } // #endif \ No newline at end of file diff --git a/package.json b/package.json index 0b01ed4..59eca92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "dependencies": { "dayjs": "^1.11.13", + "pinia": "^2.3.1", "pinia-plugin-persistedstate": "^4.2.0" } } diff --git a/pages.json b/pages.json index 0163499..b5b1f5e 100644 --- a/pages.json +++ b/pages.json @@ -11,7 +11,8 @@ { "path": "pages/index/index", "style": { - "navigationBarTitleText": "uni-app" + "navigationBarTitleText": "", + "navigationStyle": "custom" } } ], diff --git a/pages/index/index.vue b/pages/index/index.vue index ec06a23..c57f92f 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -1,29 +1,50 @@ \ No newline at end of file diff --git a/store/index.js b/store/index.js deleted file mode 100644 index b920103..0000000 --- a/store/index.js +++ /dev/null @@ -1,25 +0,0 @@ -// user.js -import { defineStore } from 'pinia'; -export const useAppStore = defineStore('user', { - state: () => { - return { - userInfo: {}, - isLogin: false, - } - }, - getters: { - app_userInfo: (state) => state.userInfo, - app_isLogin: (state) => state.isLogin - }, - - actions: { - // 设置数据 - async setData(key,data){ - this[key] = data - }, - // 获取数据 - getData(key){ - return this[key] - }, - } -}); diff --git a/stores/navbarStore.js b/stores/navbarStore.js new file mode 100644 index 0000000..85700ba --- /dev/null +++ b/stores/navbarStore.js @@ -0,0 +1,44 @@ +import { defineStore } from 'pinia'; + +export const useNavbarStore = defineStore('navbar', { + state: () => ({ + showBack: true, + rightText: '', + showSearch: false, + title: '', + isTransparent: false, + height: 0, + hasPlaceholder: true + }), + actions: { + updateNavbarConfig(config) { + Object.assign(this, config); + }, + initNavbarHeight() { + uni.getSystemInfo({ + success: (res) => { + const statusBarHeight = res.statusBarHeight; + let navBarHeight; + + // 微信小程序的特殊处理 + if (res.platform === 'weapp') { + const menuButtonInfo = uni.getMenuButtonBoundingClientRect(); + const topGap = menuButtonInfo.top - statusBarHeight; + const bottomGap = statusBarHeight + menuButtonInfo.height + topGap * 2 - (menuButtonInfo.top + menuButtonInfo.height); + navBarHeight = menuButtonInfo.height + topGap + bottomGap; + } else if (uni.getSystemInfoSync().platform === 'ios') { + navBarHeight = 44; + } else { + navBarHeight = 48; + } + + this.height = statusBarHeight + navBarHeight; + }, + fail: (err) => { + console.error('获取系统信息失败:', err); + this.height = 64; // 失败时设置一个默认高度 + } + }); + } + } +}); \ No newline at end of file