diff --git a/packages/uni-app-plus/dist/index.v3.js b/packages/uni-app-plus/dist/index.v3.js index 0bb18dbc6bdc75e3cf2f3e1f3a423dfdc42945f3..fe4c661db8a51e1632007da2c4d8629c44ce8711 100644 --- a/packages/uni-app-plus/dist/index.v3.js +++ b/packages/uni-app-plus/dist/index.v3.js @@ -425,6 +425,18 @@ var serviceContext = (function () { return encodeStr(key) + '=' + encodeStr(val) }).filter(x => x.length > 0).join('&') : null; return res ? `?${res}` : '' + } + + function decodedQuery (query = {}) { + const decodedQuery = {}; + Object.keys(query).forEach(name => { + try { + decodedQuery[name] = decode(query[name]); + } catch (e) { + decodedQuery[name] = query[name]; + } + }); + return decodedQuery } let id = 0; @@ -1659,7 +1671,11 @@ var serviceContext = (function () { } // switchTab不允许传递参数,reLaunch到一个tabBar页面是可以的 - if (type === 'switchTab' && routeOptions.meta.isTabBar) { + if ( + type === 'switchTab' && + routeOptions.meta.isTabBar && + params.openType !== 'appLaunch' + ) { url = pagePath; } @@ -1670,12 +1686,12 @@ var serviceContext = (function () { // 参数格式化 params.url = encodeQueryString(url); - + // 主要拦截目标为用户快速点击时触发的多次跳转,该情况,通常前后 url 是一样的 if (navigatorLock === url) { return `${navigatorLock} locked` } - // 至少 onLaunch 之后,再启用lock逻辑(onLaunch之前可能开发者手动调用路由API,来提前跳转) + // 至少 onLaunch 之后,再启用lock逻辑(onLaunch之前可能开发者手动调用路由API,来提前跳转) // enableNavigatorLock 临时开关(不对外开放),避免该功能上线后,有部分情况异常,可以让开发者临时关闭 lock 功能 if (__uniConfig.ready && __uniConfig.enableNavigatorLock !== false) { navigatorLock = url; @@ -2058,6 +2074,17 @@ var serviceContext = (function () { backgroundColor: { type: String }, + backgroundImage: { + type: String, + validator (backgroundImage, params) { + if (backgroundImage && !(/^(linear|radial)-gradient\(.+?\);?$/.test(backgroundImage))) { + params.backgroundImage = getRealPath(backgroundImage); + } + } + }, + backgroundRepeat: { + type: String + }, borderStyle: { type: String, validator (borderStyle, params) { @@ -8554,7 +8581,8 @@ var serviceContext = (function () { function _switchTab ({ url, - path, + path, + query, from }, callbackId) { tabBar$1.switchTab(path.slice(1)); @@ -8564,7 +8592,7 @@ var serviceContext = (function () { let callOnHide = false; let callOnShow = false; - + let currentPage; if (len >= 1) { // 前一个页面是非 tabBar 页面 currentPage = pages[len - 1]; @@ -8624,7 +8652,7 @@ var serviceContext = (function () { return showWebview(registerPage({ url, path, - query: {}, + query, openType: 'switchTab' }), 'none', 0, () => { setStatusBarStyle(); @@ -8645,11 +8673,15 @@ var serviceContext = (function () { from, openType }, callbackId) { - const path = url.split('?')[0]; + // 直达时,允许 tabBar 带参数 + const urls = url.split('?'); + const path = urls[0]; + const query = parseQuery(urls[1] || ''); navigate(path, function () { _switchTab({ url, - path, + path, + query, from }, callbackId); }, openType === 'appLaunch'); @@ -8665,9 +8697,16 @@ var serviceContext = (function () { const type = object.type; if (types.indexOf(type) >= 0) { const keys = Object.keys(object); - // eslint-disable-next-line valid-typeof - if (keys.length === 2 && 'data' in object && typeof object.data === type) { - return object.data + if (keys.length === 2 && 'data' in object) { + // eslint-disable-next-line valid-typeof + if (typeof object.data === type) { + return object.data + } + // eslint-disable-next-line no-useless-escape + if (type === 'object' && /^\d{4}-\d{2}-\d{2}T\d{2}\:\d{2}\:\d{2}\.\d{3}Z$/.test(object.data)) { + // ISO 8601 格式返回 Date + return new Date(object.data) + } } else if (keys.length === 1) { return '' } @@ -8739,8 +8778,12 @@ var serviceContext = (function () { data = object; if (typeof object === 'string') { object = JSON.parse(object); - // eslint-disable-next-line valid-typeof - data = typeof object === (type === 'null' ? 'object' : type) ? object : data; + const objectType = typeof object; + if (objectType === 'number' && type === 'date') { + data = new Date(object); + } else if (objectType === (['null', 'array'].indexOf(type) < 0 ? type : 'object')) { + data = object; + } } } } catch (error) {} @@ -9182,36 +9225,19 @@ var serviceContext = (function () { } } - function setTabBarStyle$2 ({ - color, - selectedColor, - backgroundColor, - borderStyle - }) { + function setTabBarStyle$2 (style = {}) { if (!isTabBarPage()) { return { errMsg: 'setTabBarStyle:fail not TabBar page' } } - const style = {}; const borderStyles = { black: 'rgba(0,0,0,0.4)', white: 'rgba(255,255,255,0.4)' }; - if (color) { - style.color = color; - } - if (selectedColor) { - style.selectedColor = selectedColor; - } - if (backgroundColor) { - style.backgroundColor = backgroundColor; - } + const borderStyle = style.borderStyle; if (borderStyle in borderStyles) { - borderStyle = borderStyles[borderStyle]; - } - if (borderStyle) { - style.borderStyle = borderStyle; + style.borderStyle = borderStyles[borderStyle]; } tabBar$1.setTabBarStyle(style); return { @@ -13741,7 +13767,8 @@ var serviceContext = (function () { }, created () { if (this.mpType === 'page') { - callPageHook(this.$scope, 'onLoad', this.$options.pageQuery); + // 理论上应该从最开始的 parseQuery 的地方直接 decode 两次,为了减少影响范围,先仅处理 onLoad 参数 + callPageHook(this.$scope, 'onLoad', decodedQuery(this.$options.pageQuery)); callPageHook(this.$scope, 'onShow'); } }, diff --git a/src/core/helpers/protocol/route/route.js b/src/core/helpers/protocol/route/route.js index 534c4559772f2331f388d44dc7fcbf55153eb59c..1e469deb4d03787159c91bb36b3ff6ff88aaceff 100644 --- a/src/core/helpers/protocol/route/route.js +++ b/src/core/helpers/protocol/route/route.js @@ -61,7 +61,11 @@ function createValidator (type) { } // switchTab不允许传递参数,reLaunch到一个tabBar页面是可以的 - if (type === 'switchTab' && routeOptions.meta.isTabBar) { + if ( + type === 'switchTab' && + routeOptions.meta.isTabBar && + params.openType !== 'appLaunch' + ) { url = pagePath } @@ -72,12 +76,12 @@ function createValidator (type) { // 参数格式化 params.url = encodeQueryString(url) - + // 主要拦截目标为用户快速点击时触发的多次跳转,该情况,通常前后 url 是一样的 if (navigatorLock === url) { return `${navigatorLock} locked` } - // 至少 onLaunch 之后,再启用lock逻辑(onLaunch之前可能开发者手动调用路由API,来提前跳转) + // 至少 onLaunch 之后,再启用lock逻辑(onLaunch之前可能开发者手动调用路由API,来提前跳转) // enableNavigatorLock 临时开关(不对外开放),避免该功能上线后,有部分情况异常,可以让开发者临时关闭 lock 功能 if (__uniConfig.ready && __uniConfig.enableNavigatorLock !== false) { navigatorLock = url diff --git a/src/platforms/app-plus/service/api/route/switch-tab.js b/src/platforms/app-plus/service/api/route/switch-tab.js index d1c1b9336472299275b9a824c391480061d5164b..800d25126235fbbbc0f5e4435d2410c113c418cb 100644 --- a/src/platforms/app-plus/service/api/route/switch-tab.js +++ b/src/platforms/app-plus/service/api/route/switch-tab.js @@ -1,3 +1,7 @@ +import { + parseQuery +} from 'uni-shared' + import { ANI_CLOSE, ANI_DURATION @@ -24,7 +28,8 @@ import tabBar from '../../framework/tab-bar' function _switchTab ({ url, - path, + path, + query, from }, callbackId) { tabBar.switchTab(path.slice(1)) @@ -34,7 +39,7 @@ function _switchTab ({ let callOnHide = false let callOnShow = false - + let currentPage if (len >= 1) { // 前一个页面是非 tabBar 页面 currentPage = pages[len - 1] @@ -94,7 +99,7 @@ function _switchTab ({ return showWebview(registerPage({ url, path, - query: {}, + query, openType: 'switchTab' }), 'none', 0, () => { setStatusBarStyle() @@ -115,11 +120,15 @@ export function switchTab ({ from, openType }, callbackId) { - const path = url.split('?')[0] + // 直达时,允许 tabBar 带参数 + const urls = url.split('?') + const path = urls[0] + const query = parseQuery(urls[1] || '') navigate(path, function () { _switchTab({ url, - path, + path, + query, from }, callbackId) }, openType === 'appLaunch')