| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import UrlParser from 'url-parse'; |
| |
| const Utils = { |
| UrlParser: UrlParser, |
| _typeof (obj) { |
| return Object.prototype.toString |
| .call(obj) |
| .slice(8, -1) |
| .toLowerCase(); |
| }, |
| isPlainObject (obj) { |
| return Utils._typeof(obj) === 'object'; |
| }, |
| isString (obj) { |
| return typeof obj === 'string'; |
| }, |
| isNonEmptyArray (obj = []) { |
| return obj && obj.length > 0 && Array.isArray(obj) && typeof obj !== 'undefined'; |
| }, |
| isObject (item) { |
| return item && typeof item === 'object' && !Array.isArray(item); |
| }, |
| isEmptyObject (obj) { |
| return Object.keys(obj).length === 0 && obj.constructor === Object; |
| }, |
| decodeIconFont (text) { |
| // 正则匹配 图标和文字混排 eg: 我去上学校,天天不迟到 |
| const regExp = /&#x[a-z|0-9]{4,5};?/g; |
| if (regExp.test(text)) { |
| return text.replace(new RegExp(regExp, 'g'), function (iconText) { |
| const replace = iconText.replace(/&#x/, '0x').replace(/;$/, ''); |
| return String.fromCharCode(replace); |
| }); |
| } else { |
| return text; |
| } |
| }, |
| mergeDeep (target, ...sources) { |
| if (!sources.length) return target; |
| const source = sources.shift(); |
| if (Utils.isObject(target) && Utils.isObject(source)) { |
| for (const key in source) { |
| if (Utils.isObject(source[key])) { |
| if (!target[key]) { |
| Object.assign(target, { |
| [key]: {} |
| }); |
| } |
| Utils.mergeDeep(target[key], source[key]); |
| } else { |
| Object.assign(target, { [key]: source[key] }); |
| } |
| } |
| } |
| return Utils.mergeDeep(target, ...sources); |
| }, |
| appendProtocol (url) { |
| if (/^\/\//.test(url)) { |
| const { bundleUrl } = weex.config; |
| return `http${/^https:/.test(bundleUrl) ? 's' : ''}:${url}`; |
| } |
| return url; |
| }, |
| encodeURLParams (url) { |
| const parsedUrl = new UrlParser(url, true); |
| return parsedUrl.toString(); |
| }, |
| goToH5Page (jumpUrl, animated = false, callback = null) { |
| const Navigator = weex.requireModule('navigator'); |
| const jumpUrlObj = new Utils.UrlParser(jumpUrl, true); |
| const url = Utils.appendProtocol(jumpUrlObj.toString()); |
| Navigator.push( |
| { |
| url: Utils.encodeURLParams(url), |
| animated: animated.toString() |
| }, |
| callback |
| ); |
| }, |
| env: { |
| isTaobao () { |
| const { appName } = weex.config.env; |
| return /(tb|taobao|淘宝)/i.test(appName); |
| }, |
| isTrip () { |
| const { appName } = weex.config.env; |
| return appName === 'LX'; |
| }, |
| isBoat () { |
| const { appName } = weex.config.env; |
| return appName === 'Boat' || appName === 'BoatPlayground'; |
| }, |
| isWeb () { |
| const { platform } = weex.config.env; |
| return typeof window === 'object' && platform.toLowerCase() === 'web'; |
| }, |
| isIOS () { |
| const { platform } = weex.config.env; |
| return platform.toLowerCase() === 'ios'; |
| }, |
| /** |
| * 是否为 iPhone X or iPhoneXS or iPhoneXR or iPhoneXS Max |
| * @returns {boolean} |
| */ |
| isIPhoneX () { |
| const { deviceHeight } = weex.config.env; |
| if (Utils.env.isWeb()) { |
| return ( |
| typeof window !== undefined && |
| window.screen && |
| window.screen.width && |
| window.screen.height && |
| ((parseInt(window.screen.width, 10) === 375 && parseInt(window.screen.height, 10) === 812) || |
| (parseInt(window.screen.width, 10) === 414 && parseInt(window.screen.height, 10) === 896)) |
| ); |
| } |
| return ( |
| Utils.env.isIOS() && |
| (deviceHeight === 2436 || deviceHeight === 2688 || deviceHeight === 1792 || deviceHeight === 1624) |
| ); |
| }, |
| isAndroid () { |
| const { platform } = weex.config.env; |
| return platform.toLowerCase() === 'android'; |
| }, |
| isTmall () { |
| const { appName } = weex.config.env; |
| return /(tm|tmall|天猫)/i.test(appName); |
| }, |
| isAliWeex () { |
| return Utils.env.isTmall() || Utils.env.isTrip() || Utils.env.isTaobao(); |
| }, |
| /** |
| * 获取weex屏幕真实的设置高度,需要减去导航栏高度 |
| * @returns {Number} |
| */ |
| getPageHeight () { |
| const { env } = weex.config; |
| const navHeight = Utils.env.isWeb() ? 0 : Utils.env.isIPhoneX() ? 176 : 132; |
| return (env.deviceHeight / env.deviceWidth) * 750 - navHeight; |
| }, |
| /** |
| * 获取weex屏幕真实的设置高度 |
| * @returns {Number} |
| */ |
| getScreenHeight () { |
| const { env } = weex.config; |
| return (env.deviceHeight / env.deviceWidth) * 750; |
| } |
| }, |
| |
| /** |
| * 版本号比较 |
| * @memberOf Utils |
| * @param currVer {string} |
| * @param promoteVer {string} |
| * @returns {boolean} |
| * @example |
| * |
| * const { Utils } = require('@ali/wx-bridge'); |
| * const { compareVersion } = Utils; |
| * console.log(compareVersion('0.1.100', '0.1.11')); // 'true' |
| */ |
| compareVersion (currVer = '0.0.0', promoteVer = '0.0.0') { |
| if (currVer === promoteVer) return true; |
| const currVerArr = currVer.split('.'); |
| const promoteVerArr = promoteVer.split('.'); |
| const len = Math.max(currVerArr.length, promoteVerArr.length); |
| for (let i = 0; i < len; i++) { |
| const proVal = ~~promoteVerArr[i]; |
| const curVal = ~~currVerArr[i]; |
| if (proVal < curVal) { |
| return true; |
| } else if (proVal > curVal) { |
| return false; |
| } |
| } |
| return false; |
| }, |
| /** |
| * 分割数组 |
| * @param arr 被分割数组 |
| * @param size 分割数组的长度 |
| * @returns {Array} |
| */ |
| arrayChunk (arr = [], size = 4) { |
| let groups = []; |
| if (arr && arr.length > 0) { |
| groups = arr |
| .map((e, i) => { |
| return i % size === 0 ? arr.slice(i, i + size) : null; |
| }) |
| .filter(e => { |
| return e; |
| }); |
| } |
| return groups; |
| }, |
| /* |
| * 截断字符串 |
| * @param str 传入字符串 |
| * @param len 截断长度 |
| * @param hasDot 末尾是否... |
| * @returns {String} |
| */ |
| truncateString (str, len, hasDot = true) { |
| let newLength = 0; |
| let newStr = ''; |
| let singleChar = ''; |
| const chineseRegex = /[^\x00-\xff]/g; |
| const strLength = str.replace(chineseRegex, '**').length; |
| for (let i = 0; i < strLength; i++) { |
| singleChar = str.charAt(i).toString(); |
| if (singleChar.match(chineseRegex) !== null) { |
| newLength += 2; |
| } else { |
| newLength++; |
| } |
| if (newLength > len) { |
| break; |
| } |
| newStr += singleChar; |
| } |
| |
| if (hasDot && strLength > len) { |
| newStr += '...'; |
| } |
| return newStr; |
| }, |
| /* |
| * 转换 obj 为 url params参数 |
| * @param obj 传入字符串 |
| * @returns {String} |
| */ |
| objToParams (obj) { |
| let str = ''; |
| for (const key in obj) { |
| if (str !== '') { |
| str += '&'; |
| } |
| str += key + '=' + encodeURIComponent(obj[key]); |
| } |
| return str; |
| }, |
| /* |
| * 转换 url params参数为obj |
| * @param str 传入url参数字符串 |
| * @returns {Object} |
| */ |
| paramsToObj (str) { |
| let obj = {}; |
| try { |
| obj = JSON.parse( |
| '{"' + |
| decodeURI(str) |
| .replace(/"/g, '\\"') |
| .replace(/&/g, '","') |
| .replace(/=/g, '":"') + |
| '"}' |
| ); |
| } catch (e) { |
| console.log(e); |
| } |
| return obj; |
| }, |
| animation: { |
| /** |
| * 返回定义页面转场动画起初的位置 |
| * @param ref |
| * @param transform 运动类型 |
| * @param status |
| * @param callback 回调函数 |
| */ |
| pageTransitionAnimation (ref, transform, status, callback) { |
| const animation = weex.requireModule('animation'); |
| animation.transition( |
| ref, |
| { |
| styles: { |
| transform: transform |
| }, |
| duration: status ? 250 : 300, // ms |
| timingFunction: status ? 'ease-in' : 'ease-out', |
| delay: 0 // ms |
| }, |
| function () { |
| callback && callback(); |
| } |
| ); |
| } |
| }, |
| uiStyle: { |
| /** |
| * 返回定义页面转场动画起初的位置 |
| * @param animationType 页面转场动画的类型 push,model |
| * @param size 分割数组的长度 |
| * @returns {} |
| */ |
| pageTransitionAnimationStyle (animationType) { |
| if (animationType === 'push') { |
| return { |
| left: '750px', |
| top: '0px', |
| height: (weex.config.env.deviceHeight / weex.config.env.deviceWidth) * 750 + 'px' |
| }; |
| } else if (animationType === 'model') { |
| return { |
| top: (weex.config.env.deviceHeight / weex.config.env.deviceWidth) * 750 + 'px', |
| left: '0px', |
| height: (weex.config.env.deviceHeight / weex.config.env.deviceWidth) * 750 + 'px' |
| }; |
| } |
| return {}; |
| } |
| } |
| }; |
| |
| export default Utils; |