From 71e116f52ca9d543f096bad9bc12cc789a5f78e7 Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Thu, 24 Jun 2021 21:22:59 +0800 Subject: [PATCH] wip(app): uni-app-plus --- packages/shims-uni-app.d.ts | 10 +- .../uni-app-plus/dist/uni-app-service.es.js | 284 +++++++++++++++++- .../uni-app-plus/dist/uni-app-view.umd.js | 48 +-- .../src/service/framework/page/index.ts | 45 +++ .../framework/page/initRouteOptions.ts | 21 ++ .../service/framework/page/webview/index.ts | 20 ++ .../service/framework/page/webview/nvue.ts | 32 ++ .../page/webview/style/backgroundColor.ts | 20 ++ .../framework/page/webview/style/index.ts | 55 ++++ .../framework/page/webview/style/nvue.ts | 13 + .../page/webview/style/popGesture.ts | 16 + .../page/webview/style/pullToRefresh.ts | 34 +++ .../page/webview/style/titleNView.ts | 61 ++++ .../framework/page/webview/style/utils.ts | 4 + .../service/framework/page/webview/utils.ts | 28 ++ packages/uni-app-plus/src/service/index.ts | 3 +- packages/uni-cli-shared/src/json/pages.ts | 54 +++- .../src/components/swiper/index.tsx | 19 +- packages/uni-core/src/helpers/page.ts | 19 ++ packages/uni-core/src/helpers/util.ts | 25 +- packages/uni-h5/dist/uni-h5.cjs.js | 62 ++-- packages/uni-h5/dist/uni-h5.es.js | 69 +++-- .../src/framework/setup/provide/page.ts | 19 +- packages/uni-shared/dist/uni-shared.cjs.js | 4 +- packages/uni-shared/dist/uni-shared.d.ts | 2 + packages/uni-shared/dist/uni-shared.es.js | 5 +- packages/uni-shared/src/constants.ts | 3 +- yarn.lock | 6 +- 28 files changed, 829 insertions(+), 152 deletions(-) create mode 100644 packages/uni-app-plus/src/service/framework/page/index.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/initRouteOptions.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/index.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/nvue.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/style/backgroundColor.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/style/index.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/style/nvue.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/style/popGesture.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/style/pullToRefresh.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/style/titleNView.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/style/utils.ts create mode 100644 packages/uni-app-plus/src/service/framework/page/webview/utils.ts diff --git a/packages/shims-uni-app.d.ts b/packages/shims-uni-app.d.ts index 46164f7226..7f46dc78cf 100644 --- a/packages/shims-uni-app.d.ts +++ b/packages/shims-uni-app.d.ts @@ -104,17 +104,20 @@ declare namespace UniApp { } interface PageNavigationBar { - type?: 'default' | 'transparent' | 'float' | 'none' + type?: 'default' | 'transparent' | 'float' titleSize?: string titleText?: string titleImage?: string - titleColor?: '#000' | '#fff' + titleColor?: '#000000' | '#ffffff' timingFunc?: string duration?: string backgroundColor?: string titlePenetrate?: 'YES' | 'NO' shadowColorType?: 'grey' | 'blue' | 'green' | 'orange' | 'red' | 'yellow' - backButton?: boolean + backButton?: Omit< + PageNavigationBarButton, + 'type' | 'float' | 'fontSrc' | 'fontFamily' | 'select' | 'text' | 'width' + > buttons?: PageNavigationBarButton[] searchInput?: PageNavigationBarSearchInput style?: 'default' | 'custom' @@ -149,6 +152,7 @@ declare namespace UniApp { refreshOptions?: PageRefreshOptions onReachBottomDistance?: number pageOrientation?: 'auto' | 'portrait' | 'landscape' + backgroundColor?: string } interface PageRouteMeta extends PagesJsonPageStyle { id?: number diff --git a/packages/uni-app-plus/dist/uni-app-service.es.js b/packages/uni-app-plus/dist/uni-app-service.es.js index 71dde91dba..492d8c0dba 100644 --- a/packages/uni-app-plus/dist/uni-app-service.es.js +++ b/packages/uni-app-plus/dist/uni-app-service.es.js @@ -21,7 +21,11 @@ var serviceContext = (function () { : {}; (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : []; const extend = Object.assign; - const isString = (val) => typeof val === 'string'; + const isArray = Array.isArray; + const isString = (val) => typeof val === 'string'; + const objectToString = Object.prototype.toString; + const toTypeString = (value) => objectToString.call(value); + const isPlainObject = (val) => toTypeString(val) === '[object Object]'; let isInitEntryPage = false; function initEntry() { @@ -82,11 +86,45 @@ var serviceContext = (function () { } return ret; }; + + const encode$1 = encodeURIComponent; + function stringifyQuery(obj, encodeStr = encode$1) { + const res = obj + ? Object.keys(obj) + .map((key) => { + let val = obj[key]; + if (typeof val === undefined || val === null) { + val = ''; + } + else if (isPlainObject(val)) { + val = JSON.stringify(val); + } + return encodeStr(key) + '=' + encodeStr(val); + }) + .filter((x) => x.length > 0) + .join('&') + : null; + return res ? `?${res}` : ''; + } const TABBAR_HEIGHT = 50; + const BACKGROUND_COLOR = '#f7f7f7'; // 背景色,如标题栏默认背景色 const SCHEME_RE = /^([a-z-]+:)?\/\//i; const DATA_RE = /^data:.*,.*/; const WEB_INVOKE_APPSERVICE = 'WEB_INVOKE_APPSERVICE'; + const PAGE_META_KEYS = ['navigationBar', 'refreshOptions']; + function initGlobalStyle() { + return JSON.parse(JSON.stringify(__uniConfig.globalStyle || {})); + } + function mergePageMeta(id, pageMeta) { + const globalStyle = initGlobalStyle(); + const res = extend({ id }, globalStyle, pageMeta); + PAGE_META_KEYS.forEach((name) => { + res[name] = extend({}, globalStyle[name], pageMeta[name]); + }); + return res; + } + function getRealRoute(fromRoute, toRoute) { if (toRoute.indexOf('/') === 0) { return toRoute; @@ -483,8 +521,252 @@ var serviceContext = (function () { initGlobalEvent(); } + function initRouteOptions(path, openType) { + // 需要序列化一遍 + const routeOptions = JSON.parse(JSON.stringify(__uniRoutes.find((route) => route.path === path))); + if (openType === 'reLaunch' || + (!__uniConfig.realEntryPagePath && getCurrentPages().length === 0) // redirectTo + ) { + routeOptions.meta.isQuit = true; + } + else if (!routeOptions.meta.isTabBar) { + routeOptions.meta.isQuit = false; + } + // TODO + // if (routeOptions.meta.isTabBar) { + // routeOptions.meta.visible = true + // } + return routeOptions; + } + + function initNVue(webviewStyle, routeMeta, path) { + if (path && routeMeta.isNVue) { + webviewStyle.uniNView = { + path, + defaultFontSize: __uniConfig.defaultFontSize, + viewport: __uniConfig.viewport, + }; + } + } + + const colorRE = /^#[a-z0-9]{6}$/i; + function isColor(color) { + return color && (colorRE.test(color) || color === 'transparent'); + } + + function initBackgroundColor(webviewStyle, routeMeta) { + const { backgroundColor } = routeMeta; + if (!backgroundColor) { + return; + } + if (!isColor(backgroundColor)) { + return; + } + if (!webviewStyle.background) { + webviewStyle.background = backgroundColor; + } + if (!webviewStyle.backgroundColorTop) { + webviewStyle.backgroundColorTop = backgroundColor; + } + } + + function initPopGesture(webviewStyle, routeMeta) { + // 不支持 hide + if (webviewStyle.popGesture === 'hide') { + delete webviewStyle.popGesture; + } + // 似乎没用了吧?记得是之前流应用时,需要 appback 的逻辑 + if (routeMeta.isQuit) { + webviewStyle.popGesture = (plus.os.name === 'iOS' ? 'appback' : 'none'); + } + } + + function initPullToRefresh(webviewStyle, routeMeta) { + if (!routeMeta.enablePullDownRefresh) { + return; + } + webviewStyle.pullToRefresh = extend({}, plus.os.name === 'Android' + ? defaultAndroidPullToRefresh + : defaultPullToRefresh, routeMeta.refreshOptions); + } + const defaultAndroidPullToRefresh = { support: true, style: 'circle' }; + const defaultPullToRefresh = { + support: true, + style: 'default', + height: '50px', + range: '200px', + contentdown: { + caption: '', + }, + contentover: { + caption: '', + }, + contentrefresh: { + caption: '', + }, + }; + + function initTitleNView(webviewStyle, routeMeta) { + const { navigationBar } = routeMeta; + if (navigationBar.style === 'custom') { + return false; + } + let autoBackButton = true; + if (routeMeta.isQuit) { + autoBackButton = false; + } + const titleNView = { + autoBackButton, + }; + Object.keys(navigationBar).forEach((name) => { + const value = navigationBar[name]; + if (name === 'backgroundColor') { + titleNView.backgroundColor = isColor(value) + ? value + : BACKGROUND_COLOR; + } + else if (name === 'titleImage' && value) { + titleNView.tags = createTitleImageTags(value); + } + else if (name === 'buttons' && isArray(value)) { + titleNView.buttons = value.map((button, index) => { + button.onclick = createTitleNViewBtnClick(index); + return button; + }); + } + }); + webviewStyle.titleNView = titleNView; + } + function createTitleImageTags(titleImage) { + return [ + { + tag: 'img', + src: titleImage, + position: { + left: 'auto', + top: 'auto', + width: 'auto', + height: '26px', + }, + }, + ]; + } + function createTitleNViewBtnClick(index) { + return function onClick(btn) { + btn.index = index; + invokeHook('onNavigationBarButtonTap', btn); + }; + } + + function parseWebviewStyle(id, path, routeOptions) { + const webviewStyle = { + bounce: 'vertical', + }; + const routeMeta = mergePageMeta(id, routeOptions.meta); + Object.keys(routeMeta).forEach((name) => { + if (WEBVIEW_STYLE_BLACKLIST.indexOf(name) === -1) { + webviewStyle[name] = + routeMeta[name]; + } + }); + initNVue(webviewStyle, routeMeta, path); + initPopGesture(webviewStyle, routeMeta); + initBackgroundColor(webviewStyle, routeMeta); + initTitleNView(webviewStyle, routeMeta); + initPullToRefresh(webviewStyle, routeMeta); + return webviewStyle; + } + const WEBVIEW_STYLE_BLACKLIST = [ + 'id', + 'route', + 'isNVue', + 'isQuit', + 'isEntry', + 'isTabBar', + 'tabBarIndex', + 'windowTop', + 'topWindow', + 'leftWindow', + 'rightWindow', + 'maxWidth', + 'usingComponents', + 'disableScroll', + 'enablePullDownRefresh', + 'navigationBar', + 'refreshOptions', + 'onReachBottomDistance', + 'pageOrientation', + 'backgroundColor', + ]; + + let id = 2; + let preloadWebview; + function getWebviewId() { + return id; + } + function genWebviewId() { + return id++; + } + function getPreloadWebview() { + return preloadWebview; + } + function encode(val) { + return val; + } + function initUniPageUrl(path, query) { + const queryString = query ? stringifyQuery(query, encode) : ''; + return { + path: path.substr(1), + query: queryString ? queryString.substr(1) : queryString, + }; + } + + function createNVueWebview({ path, query, routeOptions, webviewStyle, }) { + const curWebviewId = genWebviewId(); + const curWebviewStyle = parseWebviewStyle(curWebviewId, path, routeOptions); + curWebviewStyle.uniPageUrl = initUniPageUrl(path, query); + if ((process.env.NODE_ENV !== 'production')) { + console.log('[uni-app] createWebview', curWebviewId, path, curWebviewStyle); + } + curWebviewStyle.isTab = !!routeOptions.meta.isTabBar; + return plus.webview.create('', String(curWebviewId), curWebviewStyle, extend({ + nvue: true, + }, webviewStyle)); + } + + function createWebview(options) { + if (options.routeOptions.meta.isNVue) { + return createNVueWebview(options); + } + if (getWebviewId() === 2) { + // 如果首页非 nvue,则直接返回 Launch Webview + return plus.webview.getLaunchWebview(); + } + return getPreloadWebview(); + } + + function registerPage({ path, query, openType, webview, }) { + // fast 模式,nvue 首页时,会在nvue中主动调用registerPage并传入首页webview,此时初始化一下首页(因为此时可能还未调用registerApp) + if (webview) { + initEntry(); + } + // TODO preloadWebview + const routeOptions = initRouteOptions(path, openType); + if (!webview) { + webview = createWebview({ path, routeOptions, query }); + } + else { + webview = plus.webview.getWebviewById(webview.id); + webview.nvue = routeOptions.meta.isNVue; + } + if ((process.env.NODE_ENV !== 'production')) { + console.log(`[uni-app] registerPage(${path},${webview.id})`); + } + } + var index = { __registerApp: registerApp, + __registerPage: registerPage, }; return index; diff --git a/packages/uni-app-plus/dist/uni-app-view.umd.js b/packages/uni-app-plus/dist/uni-app-view.umd.js index cde367a1cb..3e95926fb2 100644 --- a/packages/uni-app-plus/dist/uni-app-view.umd.js +++ b/packages/uni-app-plus/dist/uni-app-view.umd.js @@ -625,16 +625,30 @@ function PolySymbol(name) { return Symbol("[uni-app]: " + name); } - function rpx2px(str) { + function hasRpx(str) { + return str.indexOf("rpx") !== -1 || str.indexOf("upx") !== -1; + } + function rpx2px(str, replace = false) { + if (replace) { + return rpx2pxWithReplace(str); + } if (typeof str === "string") { const res = parseInt(str) || 0; - if (str.indexOf("rpx") !== -1 || str.indexOf("upx") !== -1) { + if (hasRpx(str)) { return uni.upx2px(res); } return res; } return str; } + function rpx2pxWithReplace(str) { + if (!hasRpx(str)) { + return str; + } + return str.replace(/(\d+(\.\d+)?)[ru]px/g, (_a, b) => { + return uni.upx2px(parseFloat(b)) + "px"; + }); + } const ICON_PATH_CANCEL = "M20.928 10.176l-4.928 4.928-4.928-4.928-0.896 0.896 4.928 4.928-4.928 4.928 0.896 0.896 4.928-4.928 4.928 4.928 0.896-0.896-4.928-4.928 4.928-4.928-0.896-0.896zM16 2.080q-3.776 0-7.040 1.888-3.136 1.856-4.992 4.992-1.888 3.264-1.888 7.040t1.888 7.040q1.856 3.136 4.992 4.992 3.264 1.888 7.040 1.888t7.040-1.888q3.136-1.856 4.992-4.992 1.888-3.264 1.888-7.040t-1.888-7.040q-1.856-3.136-4.992-4.992-3.264-1.888-7.040-1.888zM16 28.64q-3.424 0-6.4-1.728-2.848-1.664-4.512-4.512-1.728-2.976-1.728-6.4t1.728-6.4q1.664-2.848 4.512-4.512 2.976-1.728 6.4-1.728t6.4 1.728q2.848 1.664 4.512 4.512 1.728 2.976 1.728 6.4t-1.728 6.4q-1.664 2.848-4.512 4.512-2.976 1.728-6.4 1.728z"; const ICON_PATH_CLEAR = "M16 0q-4.352 0-8.064 2.176-3.616 2.144-5.76 5.76-2.176 3.712-2.176 8.064t2.176 8.064q2.144 3.616 5.76 5.76 3.712 2.176 8.064 2.176t8.064-2.176q3.616-2.144 5.76-5.76 2.176-3.712 2.176-8.064t-2.176-8.064q-2.144-3.616-5.76-5.76-3.712-2.176-8.064-2.176zM22.688 21.408q0.32 0.32 0.304 0.752t-0.336 0.736-0.752 0.304-0.752-0.32l-5.184-5.376-5.376 5.184q-0.32 0.32-0.752 0.304t-0.736-0.336-0.304-0.752 0.32-0.752l5.376-5.184-5.184-5.376q-0.32-0.32-0.304-0.752t0.336-0.752 0.752-0.304 0.752 0.336l5.184 5.376 5.376-5.184q0.32-0.32 0.752-0.304t0.752 0.336 0.304 0.752-0.336 0.752l-5.376 5.184 5.184 5.376z"; const ICON_PATH_DOWNLOAD = "M15.808 1.696q-3.776 0-7.072 1.984-3.2 1.888-5.088 5.152-1.952 3.392-1.952 7.36 0 3.776 1.952 7.072 1.888 3.2 5.088 5.088 3.296 1.952 7.072 1.952 3.968 0 7.36-1.952 3.264-1.888 5.152-5.088 1.984-3.296 1.984-7.072 0-4-1.984-7.36-1.888-3.264-5.152-5.152-3.36-1.984-7.36-1.984zM20.864 18.592l-3.776 4.928q-0.448 0.576-1.088 0.576t-1.088-0.576l-3.776-4.928q-0.448-0.576-0.24-0.992t0.944-0.416h2.976v-8.928q0-0.256 0.176-0.432t0.4-0.176h1.216q0.224 0 0.4 0.176t0.176 0.432v8.928h2.976q0.736 0 0.944 0.416t-0.24 0.992z"; @@ -677,34 +691,6 @@ fromRouteArray.splice(fromRouteArray.length - i - 1, i + 1); return "/" + fromRouteArray.concat(toRouteArray).join("/"); } - const callbacks = {}; - function createCallbacks(namespace) { - let scopedCallbacks = callbacks[namespace]; - if (!scopedCallbacks) { - scopedCallbacks = { - id: 1, - callbacks: Object.create(null) - }; - callbacks[namespace] = scopedCallbacks; - } - return { - get(id) { - return scopedCallbacks.callbacks[id]; - }, - pop(id) { - const callback = scopedCallbacks.callbacks[id]; - if (callback) { - delete scopedCallbacks.callbacks[id]; - } - return callback; - }, - push(callback) { - const id = scopedCallbacks.id++; - scopedCallbacks.callbacks[id] = callback; - return id; - } - }; - } /* @__PURE__ */ extend(initBridge("service"), { invokeOnCallback(name, res) { return UniServiceJSBridge.emit("api." + name, res); @@ -1489,8 +1475,6 @@ resetSize }; } - createCallbacks("canvasEvent"); - createCallbacks("getSelectedTextRangeEvent"); function _isSlot(s) { return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !vue.isVNode(s); } diff --git a/packages/uni-app-plus/src/service/framework/page/index.ts b/packages/uni-app-plus/src/service/framework/page/index.ts new file mode 100644 index 0000000000..d166c616d6 --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/index.ts @@ -0,0 +1,45 @@ +import { initEntry } from '../app/initEntry' +import { initRouteOptions } from './initRouteOptions' +import { createWebview } from './webview' + +export type OpenType = + | 'navigateTo' + | 'redirectTo' + | 'reLaunch' + | 'switchTab' + | 'navigateBack' + | 'preloadPage' + +interface RegisterPageOptions { + url: string + path: string + query: Record + openType: OpenType + webview?: PlusWebviewWebviewObject + eventChannel: unknown +} + +export function registerPage({ + path, + query, + openType, + webview, +}: RegisterPageOptions) { + // fast 模式,nvue 首页时,会在nvue中主动调用registerPage并传入首页webview,此时初始化一下首页(因为此时可能还未调用registerApp) + if (webview) { + initEntry() + } + // TODO preloadWebview + + const routeOptions = initRouteOptions(path, openType) + + if (!webview) { + webview = createWebview({ path, routeOptions, query }) + } else { + webview = plus.webview.getWebviewById(webview.id) + ;(webview as any).nvue = routeOptions.meta.isNVue + } + if (__DEV__) { + console.log(`[uni-app] registerPage(${path},${webview.id})`) + } +} diff --git a/packages/uni-app-plus/src/service/framework/page/initRouteOptions.ts b/packages/uni-app-plus/src/service/framework/page/initRouteOptions.ts new file mode 100644 index 0000000000..78d701276c --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/initRouteOptions.ts @@ -0,0 +1,21 @@ +import { OpenType } from '.' + +export function initRouteOptions(path: string, openType: OpenType) { + // 需要序列化一遍 + const routeOptions = JSON.parse( + JSON.stringify(__uniRoutes.find((route) => route.path === path)) + ) as UniApp.UniRoute + if ( + openType === 'reLaunch' || + (!__uniConfig.realEntryPagePath && getCurrentPages().length === 0) // redirectTo + ) { + routeOptions.meta.isQuit = true + } else if (!routeOptions.meta.isTabBar) { + routeOptions.meta.isQuit = false + } + // TODO + // if (routeOptions.meta.isTabBar) { + // routeOptions.meta.visible = true + // } + return routeOptions +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/index.ts b/packages/uni-app-plus/src/service/framework/page/webview/index.ts new file mode 100644 index 0000000000..ae7ed8a9ab --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/index.ts @@ -0,0 +1,20 @@ +import { createNVueWebview } from './nvue' +import { getPreloadWebview, getWebviewId } from './utils' + +export interface CreateWebviewOptions { + path: string + query: Record + routeOptions: UniApp.UniRoute + webviewStyle?: Record +} + +export function createWebview(options: CreateWebviewOptions) { + if (options.routeOptions.meta.isNVue) { + return createNVueWebview(options) + } + if (getWebviewId() === 2) { + // 如果首页非 nvue,则直接返回 Launch Webview + return plus.webview.getLaunchWebview() + } + return getPreloadWebview() +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/nvue.ts b/packages/uni-app-plus/src/service/framework/page/webview/nvue.ts new file mode 100644 index 0000000000..3f21bf8959 --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/nvue.ts @@ -0,0 +1,32 @@ +import { extend } from '@vue/shared' + +import { CreateWebviewOptions } from '.' +import { parseWebviewStyle } from './style' +import { genWebviewId, initUniPageUrl } from './utils' + +export function createNVueWebview({ + path, + query, + routeOptions, + webviewStyle, +}: CreateWebviewOptions) { + const curWebviewId = genWebviewId() + const curWebviewStyle = parseWebviewStyle(curWebviewId, path, routeOptions) + ;(curWebviewStyle as any).uniPageUrl = initUniPageUrl(path, query) + if (__DEV__) { + console.log('[uni-app] createWebview', curWebviewId, path, curWebviewStyle) + } + // android 需要使用 + ;(curWebviewStyle as any).isTab = !!routeOptions.meta.isTabBar + return plus.webview.create( + '', + String(curWebviewId), + curWebviewStyle, + extend( + { + nvue: true, + }, + webviewStyle + ) + ) +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/style/backgroundColor.ts b/packages/uni-app-plus/src/service/framework/page/webview/style/backgroundColor.ts new file mode 100644 index 0000000000..e55af7693c --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/style/backgroundColor.ts @@ -0,0 +1,20 @@ +import { isColor } from './utils' + +export function initBackgroundColor( + webviewStyle: PlusWebviewWebviewStyles, + routeMeta: UniApp.PageRouteMeta +) { + const { backgroundColor } = routeMeta + if (!backgroundColor) { + return + } + if (!isColor(backgroundColor)) { + return + } + if (!webviewStyle.background) { + webviewStyle.background = backgroundColor + } + if (!webviewStyle.backgroundColorTop) { + webviewStyle.backgroundColorTop = backgroundColor + } +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/style/index.ts b/packages/uni-app-plus/src/service/framework/page/webview/style/index.ts new file mode 100644 index 0000000000..1eb39ce8de --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/style/index.ts @@ -0,0 +1,55 @@ +import { mergePageMeta } from '@dcloudio/uni-core' +import { initNVue } from './nvue' +import { initBackgroundColor } from './backgroundColor' +import { initPopGesture } from './popGesture' +import { initPullToRefresh } from './pullToRefresh' +import { initTitleNView } from './titleNView' + +export function parseWebviewStyle( + id: number, + path: string, + routeOptions: UniApp.UniRoute +): PlusWebviewWebviewStyles { + const webviewStyle: PlusWebviewWebviewStyles = { + bounce: 'vertical', + } + const routeMeta = mergePageMeta(id, routeOptions.meta) + + Object.keys(routeMeta).forEach((name) => { + if (WEBVIEW_STYLE_BLACKLIST.indexOf(name) === -1) { + webviewStyle[name as keyof PlusWebviewWebviewStyles] = + routeMeta[name as keyof UniApp.PageRouteMeta] + } + }) + + initNVue(webviewStyle, routeMeta, path) + initPopGesture(webviewStyle, routeMeta) + initBackgroundColor(webviewStyle, routeMeta) + initTitleNView(webviewStyle, routeMeta) + initPullToRefresh(webviewStyle, routeMeta) + + return webviewStyle +} + +const WEBVIEW_STYLE_BLACKLIST = [ + 'id', + 'route', + 'isNVue', + 'isQuit', + 'isEntry', + 'isTabBar', + 'tabBarIndex', + 'windowTop', + 'topWindow', + 'leftWindow', + 'rightWindow', + 'maxWidth', + 'usingComponents', + 'disableScroll', + 'enablePullDownRefresh', + 'navigationBar', + 'refreshOptions', + 'onReachBottomDistance', + 'pageOrientation', + 'backgroundColor', +] diff --git a/packages/uni-app-plus/src/service/framework/page/webview/style/nvue.ts b/packages/uni-app-plus/src/service/framework/page/webview/style/nvue.ts new file mode 100644 index 0000000000..158ffd58ba --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/style/nvue.ts @@ -0,0 +1,13 @@ +export function initNVue( + webviewStyle: PlusWebviewWebviewStyles, + routeMeta: UniApp.PageRouteMeta, + path: string +) { + if (path && routeMeta.isNVue) { + ;(webviewStyle as any).uniNView = { + path, + defaultFontSize: (__uniConfig as any).defaultFontSize, + viewport: (__uniConfig as any).viewport, + } + } +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/style/popGesture.ts b/packages/uni-app-plus/src/service/framework/page/webview/style/popGesture.ts new file mode 100644 index 0000000000..9f60bb02c1 --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/style/popGesture.ts @@ -0,0 +1,16 @@ +export function initPopGesture( + webviewStyle: PlusWebviewWebviewStyles, + routeMeta: UniApp.PageRouteMeta +) { + // 不支持 hide + if (webviewStyle.popGesture === 'hide') { + delete webviewStyle.popGesture + } + + // 似乎没用了吧?记得是之前流应用时,需要 appback 的逻辑 + if (routeMeta.isQuit) { + webviewStyle.popGesture = ( + plus.os.name === 'iOS' ? 'appback' : 'none' + ) as PlusWebviewWebviewStyles['popGesture'] + } +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/style/pullToRefresh.ts b/packages/uni-app-plus/src/service/framework/page/webview/style/pullToRefresh.ts new file mode 100644 index 0000000000..e5e390605b --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/style/pullToRefresh.ts @@ -0,0 +1,34 @@ +import { extend } from '@vue/shared' + +export function initPullToRefresh( + webviewStyle: PlusWebviewWebviewStyles, + routeMeta: UniApp.PageRouteMeta +) { + if (!routeMeta.enablePullDownRefresh) { + return + } + webviewStyle.pullToRefresh = extend( + {}, + plus.os.name === 'Android' + ? defaultAndroidPullToRefresh + : defaultPullToRefresh, + routeMeta.refreshOptions + ) as unknown as PlusWebviewWebviewPullToRefreshStyles +} + +const defaultAndroidPullToRefresh = { support: true, style: 'circle' } +const defaultPullToRefresh = { + support: true, + style: 'default', + height: '50px', + range: '200px', + contentdown: { + caption: '', + }, + contentover: { + caption: '', + }, + contentrefresh: { + caption: '', + }, +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/style/titleNView.ts b/packages/uni-app-plus/src/service/framework/page/webview/style/titleNView.ts new file mode 100644 index 0000000000..09324d9079 --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/style/titleNView.ts @@ -0,0 +1,61 @@ +import { isArray } from '@vue/shared' +import { BACKGROUND_COLOR } from '@dcloudio/uni-shared' +import { isColor } from './utils' +import { invokeHook } from '@dcloudio/uni-core' +export function initTitleNView( + webviewStyle: PlusWebviewWebviewStyles, + routeMeta: UniApp.PageRouteMeta +) { + const { navigationBar } = routeMeta + if (navigationBar.style === 'custom') { + return false + } + let autoBackButton = true + if (routeMeta.isQuit) { + autoBackButton = false + } + const titleNView: PlusWebviewWebviewTitleNViewStyles = { + autoBackButton, + } + Object.keys(navigationBar).forEach((name) => { + const value = navigationBar[name as keyof UniApp.PageNavigationBar] + if (name === 'backgroundColor') { + titleNView.backgroundColor = isColor(value as string) + ? (value as string) + : BACKGROUND_COLOR + } else if (name === 'titleImage' && value) { + titleNView.tags = createTitleImageTags(value as string) + } else if (name === 'buttons' && isArray(value)) { + titleNView.buttons = (value as UniApp.PageNavigationBar['buttons'])!.map( + (button, index) => { + ;(button as any).onclick = createTitleNViewBtnClick(index) + return button + } + ) + } + }) + + webviewStyle.titleNView = titleNView +} + +function createTitleImageTags(titleImage: string) { + return [ + { + tag: 'img', + src: titleImage, + position: { + left: 'auto', + top: 'auto', + width: 'auto', + height: '26px', + }, + }, + ] +} + +function createTitleNViewBtnClick(index: number) { + return function onClick(btn: UniApp.PageNavigationBarButton) { + ;(btn as any).index = index + invokeHook('onNavigationBarButtonTap', btn) + } +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/style/utils.ts b/packages/uni-app-plus/src/service/framework/page/webview/style/utils.ts new file mode 100644 index 0000000000..91d5afb7df --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/style/utils.ts @@ -0,0 +1,4 @@ +const colorRE = /^#[a-z0-9]{6}$/i +export function isColor(color?: string) { + return color && (colorRE.test(color) || color === 'transparent') +} diff --git a/packages/uni-app-plus/src/service/framework/page/webview/utils.ts b/packages/uni-app-plus/src/service/framework/page/webview/utils.ts new file mode 100644 index 0000000000..e0984fbe40 --- /dev/null +++ b/packages/uni-app-plus/src/service/framework/page/webview/utils.ts @@ -0,0 +1,28 @@ +import { stringifyQuery } from '@dcloudio/uni-shared' + +let id = 2 +let preloadWebview: PlusWebviewWebviewObject + +export function getWebviewId() { + return id +} + +export function genWebviewId() { + return id++ +} + +export function getPreloadWebview() { + return preloadWebview +} + +function encode(val: Parameters[0]) { + return val as string +} + +export function initUniPageUrl(path: string, query: Record) { + const queryString = query ? stringifyQuery(query, encode) : '' + return { + path: path.substr(1), + query: queryString ? queryString.substr(1) : queryString, + } +} diff --git a/packages/uni-app-plus/src/service/index.ts b/packages/uni-app-plus/src/service/index.ts index 8aeabb5f89..a330dcd8b4 100644 --- a/packages/uni-app-plus/src/service/index.ts +++ b/packages/uni-app-plus/src/service/index.ts @@ -1,5 +1,6 @@ import { registerApp as __registerApp } from './framework/app' - +import { registerPage as __registerPage } from './framework/page' export default { __registerApp, + __registerPage, } diff --git a/packages/uni-cli-shared/src/json/pages.ts b/packages/uni-cli-shared/src/json/pages.ts index 6191260b8c..d3a562e5af 100644 --- a/packages/uni-cli-shared/src/json/pages.ts +++ b/packages/uni-cli-shared/src/json/pages.ts @@ -58,11 +58,10 @@ export function normalizePagesJson(jsonStr: string, platform: UniApp.PLATFORM) { function validatePages(pagesJson: Record, jsonStr: string) { if (!Array.isArray(pagesJson.pages)) { pagesJson.pages = [] - console.error(`[uni-app] Error: pages.json->pages parse failed.\n`, jsonStr) + throw new Error(`[uni-app] Error: pages.json->pages parse failed.`) } else if (!pagesJson.pages.length) { - console.error( - `[uni-app] Error: pages.json->pages must contain at least 1 page.\n`, - jsonStr + throw new Error( + `[uni-app] Error: pages.json->pages must contain at least 1 page.` ) } } @@ -105,6 +104,10 @@ function normalizePageStyle( extend(pageStyle, pageStyle[platform] || {}) if (['h5', 'app'].includes(platform)) { pageStyle.navigationBar = normalizeNavigationBar(pageStyle) + if (isEnablePullDownRefresh(pageStyle)) { + pageStyle.enablePullDownRefresh = true + pageStyle.refreshOptions = normalizePullToRefresh(pageStyle) + } } return removePlatformStyle(pageStyle) } @@ -127,8 +130,8 @@ function normalizeNavigationBar( Object.keys(navigationBarMaps).forEach((name) => { if (hasOwn(pageStyle, name)) { - // @ts-ignore - navigationBar[navigationBarMaps[name]] = pageStyle[name] + navigationBar[navigationBarMaps[name] as keyof UniApp.PageNavigationBar] = + pageStyle[name] delete pageStyle[name] } }) @@ -137,10 +140,33 @@ function normalizeNavigationBar( if (isPlainObject(titleNView)) { extend(navigationBar, titleNView) delete pageStyle.titleNView + } else if (titleNView === false) { + navigationBar.style = 'custom' + } + + if (hasOwn(navigationBar, 'transparentTitle')) { + const transparentTitle = (navigationBar as any).transparentTitle as + | 'none' + | 'auto' + | 'always' + if (transparentTitle === 'always') { + navigationBar.style = 'custom' + navigationBar.type = 'float' + } else if (transparentTitle === 'auto') { + navigationBar.type = 'transparent' + } else { + navigationBar.type = 'default' + } + delete (navigationBar as any).transparentTitle + } + + if (navigationBar.titleImage && navigationBar.titleText) { + delete navigationBar.titleText } + if (!navigationBar.titleColor && hasOwn(navigationBar, 'textStyle')) { navigationBar.titleColor = - (navigationBar as any).textStyle === 'black' ? '#000' : '#fff' + (navigationBar as any).textStyle === 'black' ? '#000000' : '#ffffff' delete (navigationBar as any).textStyle } @@ -175,9 +201,9 @@ function normalizeNavigationBar( function normalizeNavigationBarButton( btn: UniApp.PageNavigationBarButton, type: UniApp.PageNavigationBar['type'], - titleColor: '#000' | '#fff' + titleColor: UniApp.PageNavigationBar['titleColor'] ) { - btn.color = type === 'transparent' ? '#fff' : btn.color || titleColor + btn.color = type === 'transparent' ? '#ffffff' : btn.color || titleColor! if (!btn.fontSize) { btn.fontSize = type === 'transparent' || (btn.text && /\\u/.test(btn.text)) @@ -315,3 +341,13 @@ export function normalizePagesRoute( } }) } + +function isEnablePullDownRefresh(pageStyle: Record) { + return pageStyle.enablePullDownRefresh || pageStyle.pullToRefresh?.support +} + +function normalizePullToRefresh( + pageStyle: Record +): UniApp.PageRefreshOptions | undefined { + return pageStyle.pullToRefresh +} diff --git a/packages/uni-components/src/components/swiper/index.tsx b/packages/uni-components/src/components/swiper/index.tsx index fb87f689a7..52de7f6069 100644 --- a/packages/uni-components/src/components/swiper/index.tsx +++ b/packages/uni-components/src/components/swiper/index.tsx @@ -12,11 +12,11 @@ import { markRaw, SetupContext, } from 'vue' -import { upx2px } from '@dcloudio/uni-api' import { defineBuiltInComponent } from '../../helpers/component' import { useCustomEvent, CustomEventTrigger } from '../../helpers/useEvent' import { useTouchtrack } from '../../helpers/useTouchtrack' import { flatVNode } from '../../helpers/flatVNode' +import { rpx2px } from '@dcloudio/uni-core' const props = { indicatorDots: { @@ -92,15 +92,6 @@ export interface SwiperContext { export type AddSwiperContext = (context: SwiperContext) => void export type RemoveSwiperContext = (context: SwiperContext) => void -function upx2pxStr(val: string): string { - if (/\d+[ur]px$/i.test(val)) { - val.replace(/\d+[ur]px$/i, (text) => { - return `${upx2px(parseFloat(text))}px` - }) - } - return val || '' -} - interface State { interval: number duration: number @@ -633,14 +624,14 @@ export default /*#__PURE__*/ defineBuiltInComponent({ ? { left: 0, right: 0, - top: upx2pxStr(props.previousMargin), - bottom: upx2pxStr(props.nextMargin), + top: rpx2px(props.previousMargin, true), + bottom: rpx2px(props.nextMargin, true), } : { top: 0, bottom: 0, - left: upx2pxStr(props.previousMargin), - right: upx2pxStr(props.nextMargin), + left: rpx2px(props.previousMargin, true), + right: rpx2px(props.nextMargin, true), } } return style diff --git a/packages/uni-core/src/helpers/page.ts b/packages/uni-core/src/helpers/page.ts index fc6a56e5a6..63af8d0b2d 100644 --- a/packages/uni-core/src/helpers/page.ts +++ b/packages/uni-core/src/helpers/page.ts @@ -1,3 +1,4 @@ +import { extend } from '@vue/shared' import { ComponentPublicInstance, getCurrentInstance } from 'vue' export function useCurrentPageId() { @@ -13,3 +14,21 @@ export function getPageIdByVm(vm: ComponentPublicInstance) { return rootProxy.$page.id } } + +const PAGE_META_KEYS = ['navigationBar', 'refreshOptions'] as const + +function initGlobalStyle() { + return JSON.parse(JSON.stringify(__uniConfig.globalStyle || {})) +} + +export function mergePageMeta( + id: number, + pageMeta: UniApp.PageRouteMeta +): UniApp.PageRouteMeta { + const globalStyle = initGlobalStyle() + const res = extend({ id }, globalStyle, pageMeta) + PAGE_META_KEYS.forEach((name) => { + ;(res as any)[name] = extend({}, globalStyle[name], pageMeta[name]) + }) + return res +} diff --git a/packages/uni-core/src/helpers/util.ts b/packages/uni-core/src/helpers/util.ts index 30badbb6c9..08e9a3cb74 100644 --- a/packages/uni-core/src/helpers/util.ts +++ b/packages/uni-core/src/helpers/util.ts @@ -2,16 +2,37 @@ export function PolySymbol(name: string) { return Symbol(__DEV__ ? '[uni-app]: ' + name : name) } -export function rpx2px(str: string | number) { +function hasRpx(str: string) { + return str.indexOf('rpx') !== -1 || str.indexOf('upx') !== -1 +} + +export function rpx2px(str: string | number): number +export function rpx2px(str: string, replace: true): string +export function rpx2px(str: string | number, replace = false) { + if (replace) { + return rpx2pxWithReplace(str as string) + } if (__NODE_JS__) { return parseInt(str + '') } if (typeof str === 'string') { const res = parseInt(str) || 0 - if (str.indexOf('rpx') !== -1 || str.indexOf('upx') !== -1) { + if (hasRpx(str)) { return uni.upx2px(res) } return res } return str } + +function rpx2pxWithReplace(str: string) { + if (__NODE_JS__) { + return str + } + if (!hasRpx(str)) { + return str + } + return str.replace(/(\d+(\.\d+)?)[ru]px/g, (_a, b) => { + return uni.upx2px(parseFloat(b)) + 'px' + }) +} diff --git a/packages/uni-h5/dist/uni-h5.cjs.js b/packages/uni-h5/dist/uni-h5.cjs.js index 697ed63e72..78b06b666b 100644 --- a/packages/uni-h5/dist/uni-h5.cjs.js +++ b/packages/uni-h5/dist/uni-h5.cjs.js @@ -387,11 +387,19 @@ function updatePageCssVar(cssVars) { function PolySymbol(name) { return Symbol(process.env.NODE_ENV !== "production" ? "[uni-app]: " + name : name); } -function rpx2px(str) { +function rpx2px(str, replace = false) { + if (replace) { + return rpx2pxWithReplace(str); + } { return parseInt(str + ""); } } +function rpx2pxWithReplace(str) { + { + return str; + } +} const ICON_PATH_CANCEL = "M20.928 10.176l-4.928 4.928-4.928-4.928-0.896 0.896 4.928 4.928-4.928 4.928 0.896 0.896 4.928-4.928 4.928 4.928 0.896-0.896-4.928-4.928 4.928-4.928-0.896-0.896zM16 2.080q-3.776 0-7.040 1.888-3.136 1.856-4.992 4.992-1.888 3.264-1.888 7.040t1.888 7.040q1.856 3.136 4.992 4.992 3.264 1.888 7.040 1.888t7.040-1.888q3.136-1.856 4.992-4.992 1.888-3.264 1.888-7.040t-1.888-7.040q-1.856-3.136-4.992-4.992-3.264-1.888-7.040-1.888zM16 28.64q-3.424 0-6.4-1.728-2.848-1.664-4.512-4.512-1.728-2.976-1.728-6.4t1.728-6.4q1.664-2.848 4.512-4.512 2.976-1.728 6.4-1.728t6.4 1.728q2.848 1.664 4.512 4.512 1.728 2.976 1.728 6.4t-1.728 6.4q-1.664 2.848-4.512 4.512-2.976 1.728-6.4 1.728z"; const ICON_PATH_CLEAR = "M16 0q-4.352 0-8.064 2.176-3.616 2.144-5.76 5.76-2.176 3.712-2.176 8.064t2.176 8.064q2.144 3.616 5.76 5.76 3.712 2.176 8.064 2.176t8.064-2.176q3.616-2.144 5.76-5.76 2.176-3.712 2.176-8.064t-2.176-8.064q-2.144-3.616-5.76-5.76-3.712-2.176-8.064-2.176zM22.688 21.408q0.32 0.32 0.304 0.752t-0.336 0.736-0.752 0.304-0.752-0.32l-5.184-5.376-5.376 5.184q-0.32 0.32-0.752 0.304t-0.736-0.336-0.304-0.752 0.32-0.752l5.376-5.184-5.184-5.376q-0.32-0.32-0.304-0.752t0.336-0.752 0.752-0.304 0.752 0.336l5.184 5.376 5.376-5.184q0.32-0.32 0.752-0.304t0.752 0.336 0.304 0.752-0.336 0.752l-5.376 5.184 5.184 5.376z"; const ICON_PATH_DOWNLOAD = "M15.808 1.696q-3.776 0-7.072 1.984-3.2 1.888-5.088 5.152-1.952 3.392-1.952 7.36 0 3.776 1.952 7.072 1.888 3.2 5.088 5.088 3.296 1.952 7.072 1.952 3.968 0 7.36-1.952 3.264-1.888 5.152-5.088 1.984-3.296 1.984-7.072 0-4-1.984-7.36-1.888-3.264-5.152-5.152-3.36-1.984-7.36-1.984zM20.864 18.592l-3.776 4.928q-0.448 0.576-1.088 0.576t-1.088-0.576l-3.776-4.928q-0.448-0.576-0.24-0.992t0.944-0.416h2.976v-8.928q0-0.256 0.176-0.432t0.4-0.176h1.216q0.224 0 0.4 0.176t0.176 0.432v8.928h2.976q0.736 0 0.944 0.416t-0.24 0.992z"; @@ -418,6 +426,18 @@ function createSvgIconVNode(path, color = "#000", size = 27) { function useCurrentPageId() { return vue.getCurrentInstance().root.proxy.$page.id; } +const PAGE_META_KEYS = ["navigationBar", "refreshOptions"]; +function initGlobalStyle() { + return JSON.parse(JSON.stringify(__uniConfig.globalStyle || {})); +} +function mergePageMeta(id, pageMeta) { + const globalStyle = initGlobalStyle(); + const res = shared.extend({ id }, globalStyle, pageMeta); + PAGE_META_KEYS.forEach((name) => { + res[name] = shared.extend({}, globalStyle[name], pageMeta[name]); + }); + return res; +} function getRealRoute(fromRoute, toRoute) { if (toRoute.indexOf("/") === 0) { return toRoute; @@ -1297,19 +1317,6 @@ function defineSyncApi(name, fn, protocol, options) { function defineAsyncApi(name, fn, protocol, options) { return promisify(wrapperAsyncApi(name, fn, process.env.NODE_ENV !== "production" ? protocol : void 0, options)); } -const API_UPX2PX = "upx2px"; -const Upx2pxProtocol = [ - { - name: "upx", - type: [Number, String], - required: true - } -]; -const upx2px = /* @__PURE__ */ defineSyncApi(API_UPX2PX, (number, newDeviceWidth) => { - { - return number; - } -}, Upx2pxProtocol); createCallbacks("canvasEvent"); const API_ON_TAB_BAR_MID_BUTTON_TAP = "onTabBarMidButtonTap"; createCallbacks("getSelectedTextRangeEvent"); @@ -5678,14 +5685,6 @@ const props$c = { default: false } }; -function upx2pxStr(val) { - if (/\d+[ur]px$/i.test(val)) { - val.replace(/\d+[ur]px$/i, (text) => { - return `${upx2px(parseFloat(text))}px`; - }); - } - return val || ""; -} function useState$1(props2) { const interval = vue.computed(() => { const interval2 = Number(props2.interval); @@ -6016,13 +6015,13 @@ var index$g = /* @__PURE__ */ defineBuiltInComponent({ style = props2.vertical ? { left: 0, right: 0, - top: upx2pxStr(props2.previousMargin), - bottom: upx2pxStr(props2.nextMargin) + top: rpx2px(props2.previousMargin, true), + bottom: rpx2px(props2.nextMargin, true) } : { top: 0, bottom: 0, - left: upx2pxStr(props2.previousMargin), - right: upx2pxStr(props2.nextMargin) + left: rpx2px(props2.previousMargin, true), + right: rpx2px(props2.nextMargin, true) }; } return style; @@ -6544,17 +6543,6 @@ function initPageMeta(id) { } return vue.reactive(normalizePageMeta(JSON.parse(JSON.stringify(mergePageMeta(id, __uniRoutes[0].meta))))); } -const PAGE_META_KEYS = [ - "navigationBar", - "refreshOptions" -]; -function mergePageMeta(id, pageMeta) { - const res = shared.extend({ id }, __uniConfig.globalStyle, pageMeta); - PAGE_META_KEYS.forEach((name) => { - res[name] = shared.extend({}, __uniConfig.globalStyle[name], pageMeta[name]); - }); - return res; -} function normalizePageMeta(pageMeta) { if (__UNI_FEATURE_PULL_DOWN_REFRESH__) { const { enablePullDownRefresh, navigationBar } = pageMeta; diff --git a/packages/uni-h5/dist/uni-h5.es.js b/packages/uni-h5/dist/uni-h5.es.js index d6948a543e..5b2cec3711 100644 --- a/packages/uni-h5/dist/uni-h5.es.js +++ b/packages/uni-h5/dist/uni-h5.es.js @@ -753,16 +753,30 @@ function removeStyle(id2) { function PolySymbol(name) { return Symbol(process.env.NODE_ENV !== "production" ? "[uni-app]: " + name : name); } -function rpx2px(str) { +function hasRpx(str) { + return str.indexOf("rpx") !== -1 || str.indexOf("upx") !== -1; +} +function rpx2px(str, replace = false) { + if (replace) { + return rpx2pxWithReplace(str); + } if (typeof str === "string") { const res = parseInt(str) || 0; - if (str.indexOf("rpx") !== -1 || str.indexOf("upx") !== -1) { + if (hasRpx(str)) { return uni.upx2px(res); } return res; } return str; } +function rpx2pxWithReplace(str) { + if (!hasRpx(str)) { + return str; + } + return str.replace(/(\d+(\.\d+)?)[ru]px/g, (_a, b) => { + return uni.upx2px(parseFloat(b)) + "px"; + }); +} const ICON_PATH_CANCEL = "M20.928 10.176l-4.928 4.928-4.928-4.928-0.896 0.896 4.928 4.928-4.928 4.928 0.896 0.896 4.928-4.928 4.928 4.928 0.896-0.896-4.928-4.928 4.928-4.928-0.896-0.896zM16 2.080q-3.776 0-7.040 1.888-3.136 1.856-4.992 4.992-1.888 3.264-1.888 7.040t1.888 7.040q1.856 3.136 4.992 4.992 3.264 1.888 7.040 1.888t7.040-1.888q3.136-1.856 4.992-4.992 1.888-3.264 1.888-7.040t-1.888-7.040q-1.856-3.136-4.992-4.992-3.264-1.888-7.040-1.888zM16 28.64q-3.424 0-6.4-1.728-2.848-1.664-4.512-4.512-1.728-2.976-1.728-6.4t1.728-6.4q1.664-2.848 4.512-4.512 2.976-1.728 6.4-1.728t6.4 1.728q2.848 1.664 4.512 4.512 1.728 2.976 1.728 6.4t-1.728 6.4q-1.664 2.848-4.512 4.512-2.976 1.728-6.4 1.728z"; const ICON_PATH_CLEAR = "M16 0q-4.352 0-8.064 2.176-3.616 2.144-5.76 5.76-2.176 3.712-2.176 8.064t2.176 8.064q2.144 3.616 5.76 5.76 3.712 2.176 8.064 2.176t8.064-2.176q3.616-2.144 5.76-5.76 2.176-3.712 2.176-8.064t-2.176-8.064q-2.144-3.616-5.76-5.76-3.712-2.176-8.064-2.176zM22.688 21.408q0.32 0.32 0.304 0.752t-0.336 0.736-0.752 0.304-0.752-0.32l-5.184-5.376-5.376 5.184q-0.32 0.32-0.752 0.304t-0.736-0.336-0.304-0.752 0.32-0.752l5.376-5.184-5.184-5.376q-0.32-0.32-0.304-0.752t0.336-0.752 0.752-0.304 0.752 0.336l5.184 5.376 5.376-5.184q0.32-0.32 0.752-0.304t0.752 0.336 0.304 0.752-0.336 0.752l-5.376 5.184 5.184 5.376z"; const ICON_PATH_DOWNLOAD = "M15.808 1.696q-3.776 0-7.072 1.984-3.2 1.888-5.088 5.152-1.952 3.392-1.952 7.36 0 3.776 1.952 7.072 1.888 3.2 5.088 5.088 3.296 1.952 7.072 1.952 3.968 0 7.36-1.952 3.264-1.888 5.152-5.088 1.984-3.296 1.984-7.072 0-4-1.984-7.36-1.888-3.264-5.152-5.152-3.36-1.984-7.36-1.984zM20.864 18.592l-3.776 4.928q-0.448 0.576-1.088 0.576t-1.088-0.576l-3.776-4.928q-0.448-0.576-0.24-0.992t0.944-0.416h2.976v-8.928q0-0.256 0.176-0.432t0.4-0.176h1.216q0.224 0 0.4 0.176t0.176 0.432v8.928h2.976q0.736 0 0.944 0.416t-0.24 0.992z"; @@ -799,6 +813,18 @@ function getPageIdByVm(vm) { return rootProxy.$page.id; } } +const PAGE_META_KEYS = ["navigationBar", "refreshOptions"]; +function initGlobalStyle() { + return JSON.parse(JSON.stringify(__uniConfig.globalStyle || {})); +} +function mergePageMeta(id2, pageMeta) { + const globalStyle = initGlobalStyle(); + const res = extend({ id: id2 }, globalStyle, pageMeta); + PAGE_META_KEYS.forEach((name) => { + res[name] = extend({}, globalStyle[name], pageMeta[name]); + }); + return res; +} function disableScrollListener(evt) { evt.preventDefault(); } @@ -4810,6 +4836,7 @@ const ShowActionSheetProtocol = { required: true }, title: String, + alertText: String, itemColor: String, popover: Object }; @@ -11928,14 +11955,6 @@ const props$j = { default: false } }; -function upx2pxStr(val) { - if (/\d+[ur]px$/i.test(val)) { - val.replace(/\d+[ur]px$/i, (text2) => { - return `${upx2px(parseFloat(text2))}px`; - }); - } - return val || ""; -} function useState$2(props2) { const interval = computed(() => { const interval2 = Number(props2.interval); @@ -12372,13 +12391,13 @@ var Swiper = /* @__PURE__ */ defineBuiltInComponent({ style = props2.vertical ? { left: 0, right: 0, - top: upx2pxStr(props2.previousMargin), - bottom: upx2pxStr(props2.nextMargin) + top: rpx2px(props2.previousMargin, true), + bottom: rpx2px(props2.nextMargin, true) } : { top: 0, bottom: 0, - left: upx2pxStr(props2.previousMargin), - right: upx2pxStr(props2.nextMargin) + left: rpx2px(props2.previousMargin, true), + right: rpx2px(props2.nextMargin, true) }; } return style; @@ -12998,17 +13017,6 @@ function initPageMeta(id2) { } return reactive(normalizePageMeta(JSON.parse(JSON.stringify(mergePageMeta(id2, __uniRoutes[0].meta))))); } -const PAGE_META_KEYS = [ - "navigationBar", - "refreshOptions" -]; -function mergePageMeta(id2, pageMeta) { - const res = extend({ id: id2 }, __uniConfig.globalStyle, pageMeta); - PAGE_META_KEYS.forEach((name) => { - res[name] = extend({}, __uniConfig.globalStyle[name], pageMeta[name]); - }); - return res; -} function normalizePageMeta(pageMeta) { if (__UNI_FEATURE_PULL_DOWN_REFRESH__) { const { enablePullDownRefresh, navigationBar } = pageMeta; @@ -17634,6 +17642,10 @@ const props$3 = { type: String, default: "" }, + alertText: { + type: String, + default: "" + }, itemList: { type: Array, default() { @@ -17720,9 +17732,10 @@ var actionSheet = /* @__PURE__ */ defineComponent({ } $event.preventDefault(); } + const fixTitle = computed(() => props2.title || props2.alertText); watch(() => props2.visible, () => { nextTick(() => { - if (props2.title) { + if (fixTitle.value) { titleHeight.value = document.querySelector(".uni-actionsheet__title").offsetHeight; } scroller.update(); @@ -17753,14 +17766,14 @@ var actionSheet = /* @__PURE__ */ defineComponent({ "ref": main, "class": "uni-actionsheet__menu", "onWheel": _handleWheel - }, [props2.title ? createVNode(Fragment, null, [createVNode("div", { + }, [fixTitle.value ? createVNode(Fragment, null, [createVNode("div", { "class": "uni-actionsheet__cell", "style": { height: `${titleHeight.value}px` } }, null), createVNode("div", { "class": "uni-actionsheet__title" - }, [props2.title])]) : "", createVNode("div", { + }, [fixTitle.value])]) : "", createVNode("div", { "style": { maxHeight: `${HEIGHT.value}px`, overflow: "hidden" diff --git a/packages/uni-h5/src/framework/setup/provide/page.ts b/packages/uni-h5/src/framework/setup/provide/page.ts index a21afde827..9f84936675 100644 --- a/packages/uni-h5/src/framework/setup/provide/page.ts +++ b/packages/uni-h5/src/framework/setup/provide/page.ts @@ -3,7 +3,7 @@ import { reactive, provide, inject } from 'vue' import { useRoute } from 'vue-router' import { NAVBAR_HEIGHT, parseQuery } from '@dcloudio/uni-shared' -import { PolySymbol, rpx2px } from '@dcloudio/uni-core' +import { mergePageMeta, PolySymbol, rpx2px } from '@dcloudio/uni-core' import safeAreaInsets from 'safe-area-insets' @@ -60,23 +60,6 @@ function initPageMeta(id: number) { ) } -const PAGE_META_KEYS: ['navigationBar', 'refreshOptions'] = [ - 'navigationBar', - 'refreshOptions', -] - -function mergePageMeta(id: number, pageMeta: UniApp.PageRouteMeta) { - const res = extend({ id }, __uniConfig.globalStyle, pageMeta) - PAGE_META_KEYS.forEach((name) => { - ;(res as any)[name] = extend( - {}, - __uniConfig.globalStyle[name], - pageMeta[name] - ) - }) - return res -} - function normalizePageMeta(pageMeta: UniApp.PageRouteMeta) { if (__UNI_FEATURE_PULL_DOWN_REFRESH__) { const { enablePullDownRefresh, navigationBar } = pageMeta diff --git a/packages/uni-shared/dist/uni-shared.cjs.js b/packages/uni-shared/dist/uni-shared.cjs.js index 3abc97280b..d985ffdb25 100644 --- a/packages/uni-shared/dist/uni-shared.cjs.js +++ b/packages/uni-shared/dist/uni-shared.cjs.js @@ -866,7 +866,8 @@ const ON_REACH_BOTTOM_DISTANCE = 50; const RESPONSIVE_MIN_WIDTH = 768; const COMPONENT_NAME_PREFIX = 'VUni'; const PRIMARY_COLOR = '#007aff'; -const SELECTED_COLOR = '#0062cc'; +const SELECTED_COLOR = '#0062cc'; // 选中的颜色,如选项卡默认的选中颜色 +const BACKGROUND_COLOR = '#f7f7f7'; // 背景色,如标题栏默认背景色 const UNI_SSR = '__uniSSR'; const UNI_SSR_TITLE = 'title'; const UNI_SSR_STORE = 'store'; @@ -882,6 +883,7 @@ function getEnvLocale() { return (lang && lang.replace(/[.:].*/, '')) || 'en'; } +exports.BACKGROUND_COLOR = BACKGROUND_COLOR; exports.BUILT_IN_TAGS = BUILT_IN_TAGS; exports.COMPONENT_NAME_PREFIX = COMPONENT_NAME_PREFIX; exports.COMPONENT_PREFIX = COMPONENT_PREFIX; diff --git a/packages/uni-shared/dist/uni-shared.d.ts b/packages/uni-shared/dist/uni-shared.d.ts index c20ef2588a..a381e62460 100644 --- a/packages/uni-shared/dist/uni-shared.d.ts +++ b/packages/uni-shared/dist/uni-shared.d.ts @@ -2,6 +2,8 @@ import { FontFaceDescriptors } from 'css-font-loading-module'; export declare function addFont(family: string, source: string, desc?: FontFaceDescriptors): Promise; +export declare const BACKGROUND_COLOR = "#f7f7f7"; + export declare const BUILT_IN_TAGS: string[]; export declare const cacheStringFunction: string>(fn: T) => T; diff --git a/packages/uni-shared/dist/uni-shared.es.js b/packages/uni-shared/dist/uni-shared.es.js index c22bbd2d08..5b2a031668 100644 --- a/packages/uni-shared/dist/uni-shared.es.js +++ b/packages/uni-shared/dist/uni-shared.es.js @@ -862,7 +862,8 @@ const ON_REACH_BOTTOM_DISTANCE = 50; const RESPONSIVE_MIN_WIDTH = 768; const COMPONENT_NAME_PREFIX = 'VUni'; const PRIMARY_COLOR = '#007aff'; -const SELECTED_COLOR = '#0062cc'; +const SELECTED_COLOR = '#0062cc'; // 选中的颜色,如选项卡默认的选中颜色 +const BACKGROUND_COLOR = '#f7f7f7'; // 背景色,如标题栏默认背景色 const UNI_SSR = '__uniSSR'; const UNI_SSR_TITLE = 'title'; const UNI_SSR_STORE = 'store'; @@ -878,4 +879,4 @@ function getEnvLocale() { return (lang && lang.replace(/[.:].*/, '')) || 'en'; } -export { BUILT_IN_TAGS, COMPONENT_NAME_PREFIX, COMPONENT_PREFIX, COMPONENT_SELECTOR_PREFIX, DATA_RE, NAVBAR_HEIGHT, NODE_TYPE_COMMENT, NODE_TYPE_ELEMENT, NODE_TYPE_PAGE, NODE_TYPE_TEXT, ON_REACH_BOTTOM_DISTANCE, PLUS_RE, PRIMARY_COLOR, RESPONSIVE_MIN_WIDTH, SCHEME_RE, SELECTED_COLOR, TABBAR_HEIGHT, TAGS, UNI_SSR, UNI_SSR_DATA, UNI_SSR_GLOBAL_DATA, UNI_SSR_STORE, UNI_SSR_TITLE, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniNode, UniTextAreaElement, UniTextNode, WEB_INVOKE_APPSERVICE, addFont, cacheStringFunction, callOptions, createRpx2Unit, debounce, decode, decodeAttr, decodeTag, decodedQuery, defaultRpx2Unit, encodeAttr, encodeTag, formatDateTime, getCustomDataset, getEnvLocale, getLen, initCustomDataset, invokeArrayFns, isBuiltInComponent, isCustomElement, isNativeTag, isServiceCustomElement, isServiceNativeTag, normalizeDataset, normalizeTarget, once, parseQuery, passive, plusReady, removeLeadingSlash, sanitise, scrollTo, stringifyQuery, updateElementStyle }; +export { BACKGROUND_COLOR, BUILT_IN_TAGS, COMPONENT_NAME_PREFIX, COMPONENT_PREFIX, COMPONENT_SELECTOR_PREFIX, DATA_RE, NAVBAR_HEIGHT, NODE_TYPE_COMMENT, NODE_TYPE_ELEMENT, NODE_TYPE_PAGE, NODE_TYPE_TEXT, ON_REACH_BOTTOM_DISTANCE, PLUS_RE, PRIMARY_COLOR, RESPONSIVE_MIN_WIDTH, SCHEME_RE, SELECTED_COLOR, TABBAR_HEIGHT, TAGS, UNI_SSR, UNI_SSR_DATA, UNI_SSR_GLOBAL_DATA, UNI_SSR_STORE, UNI_SSR_TITLE, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniNode, UniTextAreaElement, UniTextNode, WEB_INVOKE_APPSERVICE, addFont, cacheStringFunction, callOptions, createRpx2Unit, debounce, decode, decodeAttr, decodeTag, decodedQuery, defaultRpx2Unit, encodeAttr, encodeTag, formatDateTime, getCustomDataset, getEnvLocale, getLen, initCustomDataset, invokeArrayFns, isBuiltInComponent, isCustomElement, isNativeTag, isServiceCustomElement, isServiceNativeTag, normalizeDataset, normalizeTarget, once, parseQuery, passive, plusReady, removeLeadingSlash, sanitise, scrollTo, stringifyQuery, updateElementStyle }; diff --git a/packages/uni-shared/src/constants.ts b/packages/uni-shared/src/constants.ts index be939211a8..887ae181c7 100644 --- a/packages/uni-shared/src/constants.ts +++ b/packages/uni-shared/src/constants.ts @@ -6,7 +6,8 @@ export const RESPONSIVE_MIN_WIDTH = 768 export const COMPONENT_NAME_PREFIX = 'VUni' export const PRIMARY_COLOR = '#007aff' -export const SELECTED_COLOR = '#0062cc' +export const SELECTED_COLOR = '#0062cc' // 选中的颜色,如选项卡默认的选中颜色 +export const BACKGROUND_COLOR = '#f7f7f7' // 背景色,如标题栏默认背景色 export const UNI_SSR = '__uniSSR' export const UNI_SSR_TITLE = 'title' diff --git a/yarn.lock b/yarn.lock index 8be75f2b0e..744e07f123 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2116,9 +2116,9 @@ acorn@^7.1.1, acorn@^7.4.0: integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.2.4: - version "8.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.0.tgz#af53266e698d7cffa416714b503066a82221be60" - integrity sha512-ULr0LDaEqQrMFGyQ3bhJkLsbtrQ8QibAseGZeaSUiT/6zb9IvIkomWHJIvgvwad+hinRAgsI51JcWk2yvwyL+w== + version "8.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c" + integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA== add-stream@^1.0.0: version "1.0.0" -- GitLab