刮刮前端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

3514 lines
85 KiB

import { initVueI18n } from '@dcloudio/uni-i18n';
import Vue from 'vue';
let realAtob;
const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const b64re = /^(?:[A-Za-z\d+/]{4})*?(?:[A-Za-z\d+/]{2}(?:==)?|[A-Za-z\d+/]{3}=?)?$/;
if (typeof atob !== 'function') {
realAtob = function (str) {
str = String(str).replace(/[\t\n\f\r ]+/g, '');
if (!b64re.test(str)) { throw new Error("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.") }
// Adding the padding if missing, for semplicity
str += '=='.slice(2 - (str.length & 3));
var bitmap; var result = ''; var r1; var r2; var i = 0;
for (; i < str.length;) {
bitmap = b64.indexOf(str.charAt(i++)) << 18 | b64.indexOf(str.charAt(i++)) << 12 |
(r1 = b64.indexOf(str.charAt(i++))) << 6 | (r2 = b64.indexOf(str.charAt(i++)));
result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255)
: r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255)
: String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
}
return result
};
} else {
// 注意atob只能在全局对象上调用,例如:`const Base64 = {atob};Base64.atob('xxxx')`是错误的用法
realAtob = atob;
}
function b64DecodeUnicode (str) {
return decodeURIComponent(realAtob(str).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
}).join(''))
}
function getCurrentUserInfo () {
const token = ( my).getStorageSync('uni_id_token') || '';
const tokenArr = token.split('.');
if (!token || tokenArr.length !== 3) {
return {
uid: null,
role: [],
permission: [],
tokenExpired: 0
}
}
let userInfo;
try {
userInfo = JSON.parse(b64DecodeUnicode(tokenArr[1]));
} catch (error) {
throw new Error('获取当前用户信息出错,详细错误信息为:' + error.message)
}
userInfo.tokenExpired = userInfo.exp * 1000;
delete userInfo.exp;
delete userInfo.iat;
return userInfo
}
function uniIdMixin (Vue) {
Vue.prototype.uniIDHasRole = function (roleId) {
const {
role
} = getCurrentUserInfo();
return role.indexOf(roleId) > -1
};
Vue.prototype.uniIDHasPermission = function (permissionId) {
const {
permission
} = getCurrentUserInfo();
return this.uniIDHasRole('admin') || permission.indexOf(permissionId) > -1
};
Vue.prototype.uniIDTokenValid = function () {
const {
tokenExpired
} = getCurrentUserInfo();
return tokenExpired > Date.now()
};
}
const _toString = Object.prototype.toString;
const hasOwnProperty = Object.prototype.hasOwnProperty;
function isFn (fn) {
return typeof fn === 'function'
}
function isStr (str) {
return typeof str === 'string'
}
function isObject (obj) {
return obj !== null && typeof obj === 'object'
}
function isPlainObject (obj) {
return _toString.call(obj) === '[object Object]'
}
function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}
function noop () {}
/**
* Create a cached version of a pure function.
*/
function cached (fn) {
const cache = Object.create(null);
return function cachedFn (str) {
const hit = cache[str];
return hit || (cache[str] = fn(str))
}
}
/**
* Camelize a hyphen-delimited string.
*/
const camelizeRE = /-(\w)/g;
const camelize = cached((str) => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
});
const HOOKS = [
'invoke',
'success',
'fail',
'complete',
'returnValue'
];
const globalInterceptors = {};
const scopedInterceptors = {};
function mergeHook (parentVal, childVal) {
const res = childVal
? parentVal
? parentVal.concat(childVal)
: Array.isArray(childVal)
? childVal : [childVal]
: parentVal;
return res
? dedupeHooks(res)
: res
}
function dedupeHooks (hooks) {
const res = [];
for (let i = 0; i < hooks.length; i++) {
if (res.indexOf(hooks[i]) === -1) {
res.push(hooks[i]);
}
}
return res
}
function removeHook (hooks, hook) {
const index = hooks.indexOf(hook);
if (index !== -1) {
hooks.splice(index, 1);
}
}
function mergeInterceptorHook (interceptor, option) {
Object.keys(option).forEach(hook => {
if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) {
interceptor[hook] = mergeHook(interceptor[hook], option[hook]);
}
});
}
function removeInterceptorHook (interceptor, option) {
if (!interceptor || !option) {
return
}
Object.keys(option).forEach(hook => {
if (HOOKS.indexOf(hook) !== -1 && isFn(option[hook])) {
removeHook(interceptor[hook], option[hook]);
}
});
}
function addInterceptor (method, option) {
if (typeof method === 'string' && isPlainObject(option)) {
mergeInterceptorHook(scopedInterceptors[method] || (scopedInterceptors[method] = {}), option);
} else if (isPlainObject(method)) {
mergeInterceptorHook(globalInterceptors, method);
}
}
function removeInterceptor (method, option) {
if (typeof method === 'string') {
if (isPlainObject(option)) {
removeInterceptorHook(scopedInterceptors[method], option);
} else {
delete scopedInterceptors[method];
}
} else if (isPlainObject(method)) {
removeInterceptorHook(globalInterceptors, method);
}
}
function wrapperHook (hook, params) {
return function (data) {
return hook(data, params) || data
}
}
function isPromise (obj) {
return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'
}
function queue (hooks, data, params) {
let promise = false;
for (let i = 0; i < hooks.length; i++) {
const hook = hooks[i];
if (promise) {
promise = Promise.resolve(wrapperHook(hook, params));
} else {
const res = hook(data, params);
if (isPromise(res)) {
promise = Promise.resolve(res);
}
if (res === false) {
return {
then () { }
}
}
}
}
return promise || {
then (callback) {
return callback(data)
}
}
}
function wrapperOptions (interceptor, options = {}) {
['success', 'fail', 'complete'].forEach(name => {
if (Array.isArray(interceptor[name])) {
const oldCallback = options[name];
options[name] = function callbackInterceptor (res) {
queue(interceptor[name], res, options).then((res) => {
/* eslint-disable no-mixed-operators */
return isFn(oldCallback) && oldCallback(res) || res
});
};
}
});
return options
}
function wrapperReturnValue (method, returnValue) {
const returnValueHooks = [];
if (Array.isArray(globalInterceptors.returnValue)) {
returnValueHooks.push(...globalInterceptors.returnValue);
}
const interceptor = scopedInterceptors[method];
if (interceptor && Array.isArray(interceptor.returnValue)) {
returnValueHooks.push(...interceptor.returnValue);
}
returnValueHooks.forEach(hook => {
returnValue = hook(returnValue) || returnValue;
});
return returnValue
}
function getApiInterceptorHooks (method) {
const interceptor = Object.create(null);
Object.keys(globalInterceptors).forEach(hook => {
if (hook !== 'returnValue') {
interceptor[hook] = globalInterceptors[hook].slice();
}
});
const scopedInterceptor = scopedInterceptors[method];
if (scopedInterceptor) {
Object.keys(scopedInterceptor).forEach(hook => {
if (hook !== 'returnValue') {
interceptor[hook] = (interceptor[hook] || []).concat(scopedInterceptor[hook]);
}
});
}
return interceptor
}
function invokeApi (method, api, options, ...params) {
const interceptor = getApiInterceptorHooks(method);
if (interceptor && Object.keys(interceptor).length) {
if (Array.isArray(interceptor.invoke)) {
const res = queue(interceptor.invoke, options);
return res.then((options) => {
// 重新访问 getApiInterceptorHooks, 允许 invoke 中再次调用 addInterceptor,removeInterceptor
return api(
wrapperOptions(getApiInterceptorHooks(method), options),
...params
)
})
} else {
return api(wrapperOptions(interceptor, options), ...params)
}
}
return api(options, ...params)
}
const promiseInterceptor = {
returnValue (res) {
if (!isPromise(res)) {
return res
}
return new Promise((resolve, reject) => {
res.then(res => {
if (res[0]) {
reject(res[0]);
} else {
resolve(res[1]);
}
});
})
}
};
const SYNC_API_RE =
/^\$|Window$|WindowStyle$|sendHostEvent|sendNativeEvent|restoreGlobal|requireGlobal|getCurrentSubNVue|getMenuButtonBoundingClientRect|^report|interceptors|Interceptor$|getSubNVueById|requireNativePlugin|upx2px|hideKeyboard|canIUse|^create|Sync$|Manager$|base64ToArrayBuffer|arrayBufferToBase64|getLocale|setLocale|invokePushCallback|getWindowInfo|getDeviceInfo|getAppBaseInfo|getSystemSetting|getAppAuthorizeSetting|initUTS|requireUTS|registerUTS/;
const CONTEXT_API_RE = /^create|Manager$/;
// Context例外情况
const CONTEXT_API_RE_EXC = ['createBLEConnection'];
// 同步例外情况
const ASYNC_API = ['createBLEConnection', 'createPushMessage'];
const CALLBACK_API_RE = /^on|^off/;
function isContextApi (name) {
return CONTEXT_API_RE.test(name) && CONTEXT_API_RE_EXC.indexOf(name) === -1
}
function isSyncApi (name) {
return SYNC_API_RE.test(name) && ASYNC_API.indexOf(name) === -1
}
function isCallbackApi (name) {
return CALLBACK_API_RE.test(name) && name !== 'onPush'
}
function handlePromise (promise) {
return promise.then(data => {
return [null, data]
})
.catch(err => [err])
}
function shouldPromise (name) {
if (
isContextApi(name) ||
isSyncApi(name) ||
isCallbackApi(name)
) {
return false
}
return true
}
/* eslint-disable no-extend-native */
if (!Promise.prototype.finally) {
Promise.prototype.finally = function (callback) {
const promise = this.constructor;
return this.then(
value => promise.resolve(callback()).then(() => value),
reason => promise.resolve(callback()).then(() => {
throw reason
})
)
};
}
function promisify (name, api) {
if (!shouldPromise(name) || !isFn(api)) {
return api
}
return function promiseApi (options = {}, ...params) {
if (isFn(options.success) || isFn(options.fail) || isFn(options.complete)) {
return wrapperReturnValue(name, invokeApi(name, api, options, ...params))
}
return wrapperReturnValue(name, handlePromise(new Promise((resolve, reject) => {
invokeApi(name, api, Object.assign({}, options, {
success: resolve,
fail: reject
}), ...params);
})))
}
}
const EPS = 1e-4;
const BASE_DEVICE_WIDTH = 750;
let isIOS = false;
let deviceWidth = 0;
let deviceDPR = 0;
function checkDeviceWidth () {
const {
platform,
pixelRatio,
windowWidth
} = my.getSystemInfoSync(); // uni=>my runtime 编译目标是 uni 对象,内部不允许直接使用 uni
deviceWidth = windowWidth;
deviceDPR = pixelRatio;
isIOS = platform === 'ios';
}
function upx2px (number, newDeviceWidth) {
if (deviceWidth === 0) {
checkDeviceWidth();
}
number = Number(number);
if (number === 0) {
return 0
}
let result = (number / BASE_DEVICE_WIDTH) * (newDeviceWidth || deviceWidth);
if (result < 0) {
result = -result;
}
result = Math.floor(result + EPS);
if (result === 0) {
if (deviceDPR === 1 || !isIOS) {
result = 1;
} else {
result = 0.5;
}
}
return number < 0 ? -result : result
}
const LOCALE_ZH_HANS = 'zh-Hans';
const LOCALE_ZH_HANT = 'zh-Hant';
const LOCALE_EN = 'en';
const LOCALE_FR = 'fr';
const LOCALE_ES = 'es';
const messages = {};
let locale;
{
locale = normalizeLocale(my.getSystemInfoSync().language) || LOCALE_EN;
}
function initI18nMessages () {
if (!isEnableLocale()) {
return
}
const localeKeys = Object.keys(__uniConfig.locales);
if (localeKeys.length) {
localeKeys.forEach((locale) => {
const curMessages = messages[locale];
const userMessages = __uniConfig.locales[locale];
if (curMessages) {
Object.assign(curMessages, userMessages);
} else {
messages[locale] = userMessages;
}
});
}
}
initI18nMessages();
const i18n = initVueI18n(
locale,
{}
);
const t = i18n.t;
const i18nMixin = (i18n.mixin = {
beforeCreate () {
const unwatch = i18n.i18n.watchLocale(() => {
this.$forceUpdate();
});
this.$once('hook:beforeDestroy', function () {
unwatch();
});
},
methods: {
$$t (key, values) {
return t(key, values)
}
}
});
const setLocale = i18n.setLocale;
const getLocale = i18n.getLocale;
function initAppLocale (Vue, appVm, locale) {
const state = Vue.observable({
locale: locale || i18n.getLocale()
});
const localeWatchers = [];
appVm.$watchLocale = fn => {
localeWatchers.push(fn);
};
Object.defineProperty(appVm, '$locale', {
get () {
return state.locale
},
set (v) {
state.locale = v;
localeWatchers.forEach(watch => watch(v));
}
});
}
function isEnableLocale () {
return typeof __uniConfig !== 'undefined' && __uniConfig.locales && !!Object.keys(__uniConfig.locales).length
}
function include (str, parts) {
return !!parts.find((part) => str.indexOf(part) !== -1)
}
function startsWith (str, parts) {
return parts.find((part) => str.indexOf(part) === 0)
}
function normalizeLocale (locale, messages) {
if (!locale) {
return
}
locale = locale.trim().replace(/_/g, '-');
if (messages && messages[locale]) {
return locale
}
locale = locale.toLowerCase();
if (locale === 'chinese') {
// 支付宝
return LOCALE_ZH_HANS
}
if (locale.indexOf('zh') === 0) {
if (locale.indexOf('-hans') > -1) {
return LOCALE_ZH_HANS
}
if (locale.indexOf('-hant') > -1) {
return LOCALE_ZH_HANT
}
if (include(locale, ['-tw', '-hk', '-mo', '-cht'])) {
return LOCALE_ZH_HANT
}
return LOCALE_ZH_HANS
}
const lang = startsWith(locale, [LOCALE_EN, LOCALE_FR, LOCALE_ES]);
if (lang) {
return lang
}
}
// export function initI18n() {
// const localeKeys = Object.keys(__uniConfig.locales || {})
// if (localeKeys.length) {
// localeKeys.forEach((locale) =>
// i18n.add(locale, __uniConfig.locales[locale])
// )
// }
// }
function getLocale$1 () {
// 优先使用 $locale
if (isFn(getApp)) {
const app = getApp({
allowDefault: true
});
if (app && app.$vm) {
return app.$vm.$locale
}
}
return normalizeLocale(my.getSystemInfoSync().language) || LOCALE_EN
}
function setLocale$1 (locale) {
const app = isFn(getApp) ? getApp() : false;
if (!app) {
return false
}
const oldLocale = app.$vm.$locale;
if (oldLocale !== locale) {
app.$vm.$locale = locale;
onLocaleChangeCallbacks.forEach((fn) => fn({
locale
}));
return true
}
return false
}
const onLocaleChangeCallbacks = [];
function onLocaleChange (fn) {
if (onLocaleChangeCallbacks.indexOf(fn) === -1) {
onLocaleChangeCallbacks.push(fn);
}
}
if (typeof global !== 'undefined') {
global.getLocale = getLocale$1;
}
const interceptors = {
promiseInterceptor
};
var baseApi = /*#__PURE__*/Object.freeze({
__proto__: null,
upx2px: upx2px,
getLocale: getLocale$1,
setLocale: setLocale$1,
onLocaleChange: onLocaleChange,
addInterceptor: addInterceptor,
removeInterceptor: removeInterceptor,
interceptors: interceptors
});
class EventChannel {
constructor (id, events) {
this.id = id;
this.listener = {};
this.emitCache = {};
if (events) {
Object.keys(events).forEach(name => {
this.on(name, events[name]);
});
}
}
emit (eventName, ...args) {
const fns = this.listener[eventName];
if (!fns) {
return (this.emitCache[eventName] || (this.emitCache[eventName] = [])).push(args)
}
fns.forEach(opt => {
opt.fn.apply(opt.fn, args);
});
this.listener[eventName] = fns.filter(opt => opt.type !== 'once');
}
on (eventName, fn) {
this._addListener(eventName, 'on', fn);
this._clearCache(eventName);
}
once (eventName, fn) {
this._addListener(eventName, 'once', fn);
this._clearCache(eventName);
}
off (eventName, fn) {
const fns = this.listener[eventName];
if (!fns) {
return
}
if (fn) {
for (let i = 0; i < fns.length;) {
if (fns[i].fn === fn) {
fns.splice(i, 1);
i--;
}
i++;
}
} else {
delete this.listener[eventName];
}
}
_clearCache (eventName) {
const cacheArgs = this.emitCache[eventName];
if (cacheArgs) {
for (; cacheArgs.length > 0;) {
this.emit.apply(this, [eventName].concat(cacheArgs.shift()));
}
}
}
_addListener (eventName, type, fn) {
(this.listener[eventName] || (this.listener[eventName] = [])).push({
fn,
type
});
}
}
const eventChannels = {};
const eventChannelStack = [];
let id = 0;
function initEventChannel (events, cache = true) {
id++;
const eventChannel = new EventChannel(id, events);
if (cache) {
eventChannels[id] = eventChannel;
eventChannelStack.push(eventChannel);
}
return eventChannel
}
function getEventChannel (id) {
if (id) {
const eventChannel = eventChannels[id];
delete eventChannels[id];
return eventChannel
}
return eventChannelStack.shift()
}
var navigateTo = {
args (fromArgs, toArgs) {
const id = initEventChannel(fromArgs.events).id;
if (fromArgs.url) {
fromArgs.url = fromArgs.url + (fromArgs.url.indexOf('?') === -1 ? '?' : '&') + '__id__=' + id;
}
},
returnValue (fromRes, toRes) {
fromRes.eventChannel = getEventChannel();
}
};
function findExistsPageIndex (url) {
const pages = getCurrentPages();
let len = pages.length;
while (len--) {
const page = pages[len];
if (page.$page && page.$page.fullPath === url) {
return len
}
}
return -1
}
var redirectTo = {
name (fromArgs) {
if (fromArgs.exists === 'back' && fromArgs.delta) {
return 'navigateBack'
}
return 'redirectTo'
},
args (fromArgs) {
if (fromArgs.exists === 'back' && fromArgs.url) {
const existsPageIndex = findExistsPageIndex(fromArgs.url);
if (existsPageIndex !== -1) {
const delta = getCurrentPages().length - 1 - existsPageIndex;
if (delta > 0) {
fromArgs.delta = delta;
}
}
}
}
};
function setStorageSync (key, data) {
return my.setStorageSync({
key,
data
})
}
function getStorageSync (key) {
const result = my.getStorageSync({
key
});
// 支付宝平台会返回一个 success 值,但是目前测试的结果这个始终是 true。当没有存储数据的时候,其它平台会返回空字符串。
return result.data !== null ? result.data : ''
}
function removeStorageSync (key) {
return my.removeStorageSync({
key
})
}
function addSafeAreaInsets (result) {
if (result.safeArea) {
const safeArea = result.safeArea;
result.safeAreaInsets = {
top: safeArea.top,
left: safeArea.left,
right: result.windowWidth - safeArea.right,
bottom: result.screenHeight - safeArea.bottom
};
}
}
function populateParameters (result) {
const {
brand = '', model = '', system = '',
language = '', theme, version,
platform, fontSizeSetting,
SDKVersion, pixelRatio, deviceOrientation
} = result;
// const isQuickApp = "mp-alipay".indexOf('quickapp-webview') !== -1
const extraParam = {};
// osName osVersion
let osName = '';
let osVersion = '';
{
my.canIUse('isIDE') && my.isIDE && (extraParam.platform = 'devtools');
osName = platform;
osVersion = system;
}
let hostVersion = version;
// deviceType
const deviceType = getGetDeviceType(result, model);
// deviceModel
const deviceBrand = getDeviceBrand(brand);
// hostName
const _hostName = getHostName(result);
// deviceOrientation
let _deviceOrientation = deviceOrientation; // 仅 微信 百度 支持
// devicePixelRatio
let _devicePixelRatio = pixelRatio;
// SDKVersion
let _SDKVersion = SDKVersion;
{ _SDKVersion = my.SDKVersion; }
// hostLanguage
const hostLanguage = language.replace(/_/g, '-');
// wx.getAccountInfoSync
const parameters = {
appId: process.env.UNI_APP_ID,
appName: process.env.UNI_APP_NAME,
appVersion: process.env.UNI_APP_VERSION_NAME,
appVersionCode: process.env.UNI_APP_VERSION_CODE,
appLanguage: getAppLanguage(hostLanguage),
uniCompileVersion: process.env.UNI_COMPILER_VERSION,
uniRuntimeVersion: process.env.UNI_COMPILER_VERSION,
uniPlatform: process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM,
deviceBrand,
deviceModel: model,
deviceType,
devicePixelRatio: _devicePixelRatio,
deviceOrientation: _deviceOrientation,
osName: osName.toLocaleLowerCase(),
osVersion,
hostTheme: theme,
hostVersion,
hostLanguage,
hostName: _hostName,
hostSDKVersion: _SDKVersion,
hostFontSizeSetting: fontSizeSetting,
windowTop: 0,
windowBottom: 0,
// TODO
osLanguage: undefined,
osTheme: undefined,
ua: undefined,
hostPackageName: undefined,
browserName: undefined,
browserVersion: undefined
};
Object.assign(result, parameters, extraParam);
}
function getGetDeviceType (result, model) {
let deviceType = result.deviceType || 'phone';
{
const deviceTypeMaps = {
ipad: 'pad',
windows: 'pc',
mac: 'pc'
};
const deviceTypeMapsKeys = Object.keys(deviceTypeMaps);
const _model = model.toLocaleLowerCase();
for (let index = 0; index < deviceTypeMapsKeys.length; index++) {
const _m = deviceTypeMapsKeys[index];
if (_model.indexOf(_m) !== -1) {
deviceType = deviceTypeMaps[_m];
break
}
}
}
return deviceType
}
function getDeviceBrand (brand) {
let deviceBrand = brand;
if (deviceBrand) {
deviceBrand = brand.toLocaleLowerCase();
}
return deviceBrand
}
function getAppLanguage (defaultLanguage) {
return getLocale$1
? getLocale$1()
: defaultLanguage
}
function getHostName (result) {
const _platform = "mp-alipay".split('-')[1];
let _hostName = result.hostName || _platform; // mp-jd
_hostName = result.app;
return _hostName
}
const UUID_KEY = '__DC_STAT_UUID';
let deviceId;
function addUuid (result) {
deviceId = deviceId || getStorageSync(UUID_KEY);
if (!deviceId) {
deviceId = Date.now() + '' + Math.floor(Math.random() * 1e7);
my.setStorage({
key: UUID_KEY,
data: deviceId
});
}
result.deviceId = deviceId;
}
function normalizePlatform (result) {
let platform = result.platform ? result.platform.toLowerCase() : 'devtools';
if (!~['android', 'ios'].indexOf(platform)) {
platform = 'devtools';
}
result.platform = platform;
}
var getSystemInfo = {
returnValue: function (result) {
addUuid(result);
addSafeAreaInsets(result);
normalizePlatform(result);
populateParameters(result);
}
};
// 不支持的 API 列表
const todos = [
'preloadPage',
'unPreloadPage',
'loadSubPackage'
// 'getRecorderManager',
// 'getBackgroundAudioManager',
// 'createInnerAudioContext',
// 'createCameraContext',
// 'createLivePlayerContext',
// 'startAccelerometer',
// 'startCompass',
// 'authorize',
// 'chooseInvoiceTitle',
// 'addTemplate',
// 'deleteTemplate',
// 'getTemplateLibraryById',
// 'getTemplateLibraryList',
// 'getTemplateList',
// 'sendTemplateMessage',
// 'setEnableDebug',
// 'getExtConfig',
// 'getExtConfigSync',
// 'onWindowResize',
// 'offWindowResize'
];
// 存在兼容性的 API 列表
const canIUses = [
'startPullDownRefresh',
'setTabBarItem',
'setTabBarStyle',
'hideTabBar',
'showTabBar',
'setTabBarBadge',
'removeTabBarBadge',
'showTabBarRedDot',
'hideTabBarRedDot',
'openSetting',
'getSetting',
'createIntersectionObserver',
'getUpdateManager',
'setBackgroundColor',
'setBackgroundTextStyle',
'checkIsSupportSoterAuthentication',
'startSoterAuthentication',
'checkIsSoterEnrolledInDevice',
'openDocument',
'createVideoContext',
'onMemoryWarning',
'addPhoneContact'
];
function _handleNetworkInfo (result) {
switch (result.networkType) {
case 'NOTREACHABLE':
result.networkType = 'none';
break
case 'WWAN':
// TODO ?
result.networkType = '3g';
break
default:
result.networkType = result.networkType.toLowerCase();
break
}
return {}
}
const protocols = { // 需要做转换的 API 列表
navigateTo,
redirectTo,
returnValue (methodName, res = {}) { // 通用 returnValue 解析
if (res.error || res.errorMessage) {
res.errMsg = `${methodName}:fail ${res.errorMessage || res.error}`;
delete res.error;
delete res.errorMessage;
} else {
res.errMsg = `${methodName}:ok`;
}
return res
},
request: {
name: my.canIUse('request') ? 'request' : 'httpRequest',
args (fromArgs) {
const method = fromArgs.method || 'GET';
if (!fromArgs.header) { // 默认增加 header 参数,方便格式化 content-type
fromArgs.header = {};
}
const headers = {
'content-type': 'application/json'
};
Object.keys(fromArgs.header).forEach(key => {
headers[key.toLocaleLowerCase()] = fromArgs.header[key];
});
return {
header (header = {}, toArgs) {
return {
name: 'headers',
value: headers
}
},
data (data) {
// 钉钉小程序在content-type为application/json时需上传字符串形式data,使用my.dd在真机运行钉钉小程序时不能正确判断
if (my.canIUse('saveFileToDingTalk') && method.toUpperCase() === 'POST' && headers['content-type'].indexOf(
'application/json') === 0 && isPlainObject(data)) {
return {
name: 'data',
value: JSON.stringify(data)
}
}
return {
name: 'data',
value: data
}
},
method: 'method', // TODO 支付宝小程序仅支持 get,post
responseType: false
}
},
returnValue: {
status: 'statusCode',
headers: 'header'
}
},
setNavigationBarColor: {
name: 'setNavigationBar',
args: {
frontColor: false,
animation: false
}
},
setNavigationBarTitle: {
name: 'setNavigationBar'
},
showModal ({
showCancel = true
} = {}) {
if (showCancel) {
return {
name: 'confirm',
args: {
cancelColor: false,
confirmColor: false,
cancelText: 'cancelButtonText',
confirmText: 'confirmButtonText'
},
returnValue (fromRes, toRes) {
toRes.confirm = fromRes.confirm;
toRes.cancel = !fromRes.confirm;
}
}
}
return {
name: 'alert',
args: {
confirmColor: false,
confirmText: 'buttonText'
},
returnValue (fromRes, toRes) {
toRes.confirm = true;
toRes.cancel = false;
}
}
},
showToast ({
icon = 'success'
} = {}) {
const args = {
title: 'content',
icon: 'type',
image: false,
mask: false
};
if (icon === 'loading') {
return {
name: 'showLoading',
args
}
}
return {
name: 'showToast',
args
}
},
showActionSheet: {
name: 'showActionSheet',
args: {
itemList: 'items',
itemColor: false
},
returnValue: {
index: 'tapIndex'
}
},
showLoading: {
args: {
title: 'content'
}
},
uploadFile: {
args: {
name: 'fileName'
}
// 从测试结果看,是有返回对象的,文档上没有说明。
},
downloadFile: {
returnValue: {
apFilePath: 'tempFilePath'
}
},
getFileInfo: {
args: {
filePath: 'apFilePath'
}
},
compressImage: {
args (fromArgs) {
fromArgs.compressLevel = 4;
if (fromArgs && fromArgs.quality) {
fromArgs.compressLevel = Math.floor(fromArgs.quality / 26);
}
fromArgs.apFilePaths = [fromArgs.src];
},
returnValue (result) {
if (result.apFilePaths && result.apFilePaths.length) {
result.tempFilePath = result.apFilePaths[0];
}
}
},
chooseVideo: {
// 支付宝小程序文档中未找到(仅在getSetting处提及),但实际可用
returnValue: {
apFilePath: 'tempFilePath'
}
},
connectSocket: {
args: {
method: false,
protocols: false
}
// TODO 有没有返回值还需要测试下
},
chooseImage: {
returnValue (result) {
const hasTempFilePaths = hasOwn(result, 'tempFilePaths') && result.tempFilePaths;
if (hasOwn(result, 'apFilePaths') && !hasTempFilePaths) {
result.tempFilePaths = result.apFilePaths;
delete result.apFilePaths;
}
if (!hasOwn(result, 'tempFiles') && hasTempFilePaths) {
result.tempFiles = [];
result.tempFilePaths.forEach(tempFilePath => result.tempFiles.push({ path: tempFilePath }));
}
return {}
}
},
previewImage: {
args (fromArgs) {
// 支付宝小程序的 current 是索引值,而非图片地址。
const currentIndex = Number(fromArgs.current);
if (isNaN(currentIndex)) {
if (fromArgs.current && Array.isArray(fromArgs.urls)) {
const index = fromArgs.urls.indexOf(fromArgs.current);
fromArgs.current = ~index ? index : 0;
}
} else {
fromArgs.current = currentIndex;
}
return {
indicator: false,
loop: false
}
}
},
saveFile: {
args: {
tempFilePath: 'apFilePath'
},
returnValue: {
apFilePath: 'savedFilePath'
}
},
getSavedFileInfo: {
args: {
filePath: 'apFilePath'
}
},
getSavedFileList: {
returnValue (result) {
if (result.fileList && result.fileList.length) {
result.fileList.forEach(file => {
file.filePath = file.apFilePath;
delete file.apFilePath;
});
}
return {}
}
},
removeSavedFile: {
args: {
filePath: 'apFilePath'
}
},
getLocation: {
args: {
type: false,
altitude: false
}
},
openLocation: {
args: {
// TODO address 参数在阿里上是必传的
}
},
getNetworkType: {
returnValue: _handleNetworkInfo
},
onNetworkStatusChange: {
returnValue: _handleNetworkInfo
},
stopAccelerometer: {
name: 'offAccelerometerChange'
},
stopCompass: {
name: 'offCompassChange'
},
scanCode: {
name: 'scan',
args (fromArgs) {
if (fromArgs.scanType) {
switch (fromArgs.scanType[0]) {
case 'qrCode':
fromArgs.type = 'qr';
break
case 'barCode':
fromArgs.type = 'bar';
break
}
}
return {
onlyFromCamera: 'hideAlbum'
}
},
returnValue: {
code: 'result'
}
},
setClipboardData: {
name: 'setClipboard',
args: {
data: 'text'
}
},
getClipboardData: {
name: 'getClipboard',
returnValue: {
text: 'data'
}
},
login: {
name: 'getAuthCode',
returnValue (result) {
result.code = result.authCode;
}
},
getUserInfo: {
name: my.canIUse('getOpenUserInfo') ? 'getOpenUserInfo' : 'getAuthUserInfo',
returnValue (result) {
if (my.canIUse('getOpenUserInfo')) {
let response = {};
try {
response = JSON.parse(result.response).response;
} catch (e) {}
result.nickName = response.nickName;
result.avatar = response.avatar;
}
result.userInfo = {
nickName: result.nickName,
avatarUrl: result.avatar
};
}
},
getUserProfile: {
name: my.canIUse('getOpenUserInfo') ? 'getOpenUserInfo' : 'getAuthUserInfo',
returnValue (result) {
if (my.canIUse('getOpenUserInfo')) {
let response = {};
try {
response = JSON.parse(result.response).response;
} catch (e) {}
result.nickName = response.nickName;
result.avatar = response.avatar;
}
result.userInfo = {
nickName: result.nickName,
avatarUrl: result.avatar
};
}
},
requestPayment: {
name: 'tradePay',
args: {
orderInfo: 'tradeNO'
}
},
getBLEDeviceServices: {
returnValue (result) {
result.services.forEach((item) => {
item.uuid = item.serviceId;
});
}
},
createBLEConnection: {
name: 'connectBLEDevice',
args: {
timeout: false
}
},
closeBLEConnection: {
name: 'disconnectBLEDevice'
},
onBLEConnectionStateChange: {
name: 'onBLEConnectionStateChanged'
},
makePhoneCall: {
args: {
phoneNumber: 'number'
}
},
stopGyroscope: {
name: 'offGyroscopeChange'
},
getSystemInfo: getSystemInfo,
getSystemInfoSync: getSystemInfo,
// 文档没提到,但是实测可用。
canvasToTempFilePath: {
returnValue (result) {
// 真机的情况下会有 tempFilePath 这个值,因此需要主动修改。
result.tempFilePath = result.apFilePath;
}
},
setScreenBrightness: {
args: {
value: 'brightness'
}
},
getScreenBrightness: {
returnValue: {
brightness: 'value'
}
},
showShareMenu: {
name: 'showSharePanel'
},
hideHomeButton: {
name: 'hideBackHome'
},
saveVideoToPhotosAlbum: {
args: {
filePath: 'src'
}
},
chooseAddress: {
name: 'getAddress',
returnValue (result) {
const info = result.result || {};
result.userName = info.fullname;
result.provinceName = info.prov;
result.cityName = info.city;
result.countyName = info.area;
result.detailInfo = info.address;
result.telNumber = info.mobilePhone;
result.errMsg = result.resultStatus;
}
}
};
// 钉钉小程序处理
if (!my.canIUse('saveImageToPhotosAlbum')) {
protocols.saveImageToPhotosAlbum = {
name: 'saveImage',
args: {
filePath: 'url'
}
};
}
const CALLBACKS = ['success', 'fail', 'cancel', 'complete'];
function processCallback (methodName, method, returnValue) {
return function (res) {
return method(processReturnValue(methodName, res, returnValue))
}
}
function processArgs (methodName, fromArgs, argsOption = {}, returnValue = {}, keepFromArgs = false) {
if (isPlainObject(fromArgs)) { // 一般 api 的参数解析
const toArgs = keepFromArgs === true ? fromArgs : {}; // returnValue 为 false 时,说明是格式化返回值,直接在返回值对象上修改赋值
if (isFn(argsOption)) {
argsOption = argsOption(fromArgs, toArgs) || {};
}
for (const key in fromArgs) {
if (hasOwn(argsOption, key)) {
let keyOption = argsOption[key];
if (isFn(keyOption)) {
keyOption = keyOption(fromArgs[key], fromArgs, toArgs);
}
if (!keyOption) { // 不支持的参数
console.warn(`The '${methodName}' method of platform '支付宝小程序' does not support option '${key}'`);
} else if (isStr(keyOption)) { // 重写参数 key
toArgs[keyOption] = fromArgs[key];
} else if (isPlainObject(keyOption)) { // {name:newName,value:value}可重新指定参数 key:value
toArgs[keyOption.name ? keyOption.name : key] = keyOption.value;
}
} else if (CALLBACKS.indexOf(key) !== -1) {
if (isFn(fromArgs[key])) {
toArgs[key] = processCallback(methodName, fromArgs[key], returnValue);
}
} else {
if (!keepFromArgs) {
toArgs[key] = fromArgs[key];
}
}
}
return toArgs
} else if (isFn(fromArgs)) {
fromArgs = processCallback(methodName, fromArgs, returnValue);
}
return fromArgs
}
function processReturnValue (methodName, res, returnValue, keepReturnValue = false) {
if (isFn(protocols.returnValue)) { // 处理通用 returnValue
res = protocols.returnValue(methodName, res);
}
return processArgs(methodName, res, returnValue, {}, keepReturnValue)
}
function wrapper (methodName, method) {
if (hasOwn(protocols, methodName)) {
const protocol = protocols[methodName];
if (!protocol) { // 暂不支持的 api
return function () {
console.error(`Platform '支付宝小程序' does not support '${methodName}'.`);
}
}
return function (arg1, arg2) { // 目前 api 最多两个参数
let options = protocol;
if (isFn(protocol)) {
options = protocol(arg1);
}
arg1 = processArgs(methodName, arg1, options.args, options.returnValue);
const args = [arg1];
if (typeof arg2 !== 'undefined') {
args.push(arg2);
}
if (isFn(options.name)) {
methodName = options.name(arg1);
} else if (isStr(options.name)) {
methodName = options.name;
}
const returnValue = my[methodName].apply(my, args);
if (isSyncApi(methodName)) { // 同步 api
return processReturnValue(methodName, returnValue, options.returnValue, isContextApi(methodName))
}
return returnValue
}
}
return method
}
const todoApis = Object.create(null);
const TODOS = [
'onTabBarMidButtonTap',
'subscribePush',
'unsubscribePush',
'onPush',
'offPush',
'share'
];
function createTodoApi (name) {
return function todoApi ({
fail,
complete
}) {
const res = {
errMsg: `${name}:fail method '${name}' not supported`
};
isFn(fail) && fail(res);
isFn(complete) && complete(res);
}
}
TODOS.forEach(function (name) {
todoApis[name] = createTodoApi(name);
});
var providers = {
oauth: ['alipay'],
share: ['alipay'],
payment: ['alipay'],
push: ['alipay']
};
function getProvider ({
service,
success,
fail,
complete
}) {
let res = false;
if (providers[service]) {
res = {
errMsg: 'getProvider:ok',
service,
provider: providers[service]
};
isFn(success) && success(res);
} else {
res = {
errMsg: 'getProvider:fail service not found'
};
isFn(fail) && fail(res);
}
isFn(complete) && complete(res);
}
var extraApi = /*#__PURE__*/Object.freeze({
__proto__: null,
getProvider: getProvider
});
const getEmitter = (function () {
let Emitter;
return function getUniEmitter () {
if (!Emitter) {
Emitter = new Vue();
}
return Emitter
}
})();
function apply (ctx, method, args) {
return ctx[method].apply(ctx, args)
}
function $on () {
return apply(getEmitter(), '$on', [...arguments])
}
function $off () {
return apply(getEmitter(), '$off', [...arguments])
}
function $once () {
return apply(getEmitter(), '$once', [...arguments])
}
function $emit () {
return apply(getEmitter(), '$emit', [...arguments])
}
var eventApi = /*#__PURE__*/Object.freeze({
__proto__: null,
$on: $on,
$off: $off,
$once: $once,
$emit: $emit
});
function createMediaQueryObserver () {
const mediaQueryObserver = {};
const {
windowWidth,
windowHeight
} = my.getSystemInfoSync();
const orientation = windowWidth < windowHeight ? 'portrait' : 'landscape';
mediaQueryObserver.observe = (options, callback) => {
let matches = true;
for (const item in options) {
const itemValue = item === 'orientation' ? options[item] : Number(options[item]);
if (options[item] !== '') {
if (item === 'width') {
if (itemValue === windowWidth) {
matches = true;
} else {
matches = false;
callback(matches);
return matches
}
}
if (item === 'minWidth') {
if (windowWidth >= itemValue) {
matches = true;
} else {
matches = false;
callback(matches);
return matches
}
}
if (item === 'maxWidth') {
if (windowWidth <= itemValue) {
matches = true;
} else {
matches = false;
callback(matches);
return matches
}
}
if (item === 'height') {
if (itemValue === windowHeight) {
matches = true;
} else {
matches = false;
callback(matches);
return matches
}
}
if (item === 'minHeight') {
if (windowHeight >= itemValue) {
matches = true;
} else {
matches = false;
callback(matches);
return matches
}
}
if (item === 'maxHeight') {
if (windowHeight <= itemValue) {
matches = true;
} else {
matches = false;
callback(matches);
return matches
}
}
if (item === 'orientation') {
if (options[item] === orientation) {
matches = true;
} else {
matches = false;
callback(matches);
return matches
}
}
}
}
callback(matches);
return matches
};
mediaQueryObserver.disconnect = () => {
};
return mediaQueryObserver
}
/**
* 框架内 try-catch
*/
/**
* 开发者 try-catch
*/
function tryCatch (fn) {
return function () {
try {
return fn.apply(fn, arguments)
} catch (e) {
// TODO
console.error(e);
}
}
}
function getApiCallbacks (params) {
const apiCallbacks = {};
for (const name in params) {
const param = params[name];
if (isFn(param)) {
apiCallbacks[name] = tryCatch(param);
delete params[name];
}
}
return apiCallbacks
}
let cid;
let cidErrMsg;
let enabled;
function normalizePushMessage (message) {
try {
return JSON.parse(message)
} catch (e) {}
return message
}
function invokePushCallback (
args
) {
if (args.type === 'enabled') {
enabled = true;
} else if (args.type === 'clientId') {
cid = args.cid;
cidErrMsg = args.errMsg;
invokeGetPushCidCallbacks(cid, args.errMsg);
} else if (args.type === 'pushMsg') {
const message = {
type: 'receive',
data: normalizePushMessage(args.message)
};
for (let i = 0; i < onPushMessageCallbacks.length; i++) {
const callback = onPushMessageCallbacks[i];
callback(message);
// 该消息已被阻止
if (message.stopped) {
break
}
}
} else if (args.type === 'click') {
onPushMessageCallbacks.forEach((callback) => {
callback({
type: 'click',
data: normalizePushMessage(args.message)
});
});
}
}
const getPushCidCallbacks = [];
function invokeGetPushCidCallbacks (cid, errMsg) {
getPushCidCallbacks.forEach((callback) => {
callback(cid, errMsg);
});
getPushCidCallbacks.length = 0;
}
function getPushClientId (args) {
if (!isPlainObject(args)) {
args = {};
}
const {
success,
fail,
complete
} = getApiCallbacks(args);
const hasSuccess = isFn(success);
const hasFail = isFn(fail);
const hasComplete = isFn(complete);
Promise.resolve().then(() => {
if (typeof enabled === 'undefined') {
enabled = false;
cid = '';
cidErrMsg = 'uniPush is not enabled';
}
getPushCidCallbacks.push((cid, errMsg) => {
let res;
if (cid) {
res = {
errMsg: 'getPushClientId:ok',
cid
};
hasSuccess && success(res);
} else {
res = {
errMsg: 'getPushClientId:fail' + (errMsg ? ' ' + errMsg : '')
};
hasFail && fail(res);
}
hasComplete && complete(res);
});
if (typeof cid !== 'undefined') {
invokeGetPushCidCallbacks(cid, cidErrMsg);
}
});
}
const onPushMessageCallbacks = [];
// 不使用 defineOnApi 实现,是因为 defineOnApi 依赖 UniServiceJSBridge ,该对象目前在小程序上未提供,故简单实现
const onPushMessage = (fn) => {
if (onPushMessageCallbacks.indexOf(fn) === -1) {
onPushMessageCallbacks.push(fn);
}
};
const offPushMessage = (fn) => {
if (!fn) {
onPushMessageCallbacks.length = 0;
} else {
const index = onPushMessageCallbacks.indexOf(fn);
if (index > -1) {
onPushMessageCallbacks.splice(index, 1);
}
}
};
let onKeyboardHeightChangeCallback;
function startGyroscope (params) {
if (hasOwn(params, 'interval')) {
console.warn('支付宝小程序 startGyroscope暂不支持interval');
}
params.success && params.success({
errMsg: 'startGyroscope:ok'
});
params.complete && params.complete({
errMsg: 'startGyroscope:ok'
});
}
function createExecCallback (execCallback) {
return function wrapperExecCallback (res) {
this.actions.forEach((action, index) => {
(action._$callbacks || []).forEach(callback => {
callback(res[index]);
});
});
if (isFn(execCallback)) {
execCallback(res);
}
}
}
function addCallback (callback) {
if (isFn(callback)) {
const action = this.actions[this.actions.length - 1];
if (action) {
(action._$callbacks || (action._$callbacks = [])).push(callback);
}
}
}
function createSelectorQuery () {
const query = my.createSelectorQuery();
const oldExec = query.exec;
const oldScrollOffset = query.scrollOffset;
const oldBoundingClientRect = query.boundingClientRect;
query.exec = function exec (callback) {
return oldExec.call(this, createExecCallback(callback).bind(this))
};
query.scrollOffset = function scrollOffset (callback) {
const ret = oldScrollOffset.call(this);
addCallback.call(this, callback);
return ret
};
query.boundingClientRect = function boundingClientRect (callback) {
const ret = oldBoundingClientRect.call(this);
addCallback.call(this, callback);
return ret
};
if (!query.fields) {
query.fields = function ({
rect,
size,
scrollOffset
} = {}, callback) {
if (rect || size) {
this.boundingClientRect();
}
if (scrollOffset) {
this.scrollOffset();
}
addCallback.call(this, callback);
return this
};
}
if (!query.in) {
query.in = function () {
return this
};
}
return query
}
function createIntersectionObserver (component, options) {
if (options && options.observeAll) {
options.selectAll = options.observeAll;
delete options.observeAll;
}
return my.createIntersectionObserver(options)
}
function onKeyboardHeightChange (callback) {
// 与微信小程序一致仅保留最后一次监听
if (onKeyboardHeightChangeCallback) {
$off('uni:keyboardHeightChange', onKeyboardHeightChangeCallback);
}
onKeyboardHeightChangeCallback = callback;
$on('uni:keyboardHeightChange', onKeyboardHeightChangeCallback);
}
function offKeyboardHeightChange () {
// 与微信小程序一致移除最后一次监听
$off('uni:keyboardHeightChange', onKeyboardHeightChangeCallback);
onKeyboardHeightChangeCallback = null;
}
var api = /*#__PURE__*/Object.freeze({
__proto__: null,
startGyroscope: startGyroscope,
createSelectorQuery: createSelectorQuery,
createIntersectionObserver: createIntersectionObserver,
onKeyboardHeightChange: onKeyboardHeightChange,
offKeyboardHeightChange: offKeyboardHeightChange,
createMediaQueryObserver: createMediaQueryObserver,
setStorageSync: setStorageSync,
getStorageSync: getStorageSync,
removeStorageSync: removeStorageSync,
getPushClientId: getPushClientId,
onPushMessage: onPushMessage,
offPushMessage: offPushMessage,
invokePushCallback: invokePushCallback
});
function findVmByVueId (vm, vuePid) {
const $children = vm.$children;
// 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200)
for (let i = $children.length - 1; i >= 0; i--) {
const childVm = $children[i];
if (childVm.$scope._$vueId === vuePid) {
return childVm
}
}
// 反向递归查找
let parentVm;
for (let i = $children.length - 1; i >= 0; i--) {
parentVm = findVmByVueId($children[i], vuePid);
if (parentVm) {
return parentVm
}
}
}
function handleLink (event) {
const {
vuePid,
vueOptions
} = event.detail || event.value; // detail 是微信,value 是百度(dipatch)
let parentVm;
if (vuePid) {
parentVm = findVmByVueId(this.$vm, vuePid);
}
if (!parentVm) {
parentVm = this.$vm;
}
vueOptions.parent = parentVm;
}
function markMPComponent (component) {
// 在 Vue 中标记为小程序组件
const IS_MP = '__v_isMPComponent';
Object.defineProperty(component, IS_MP, {
configurable: true,
enumerable: false,
value: true
});
return component
}
function toSkip (obj) {
const OB = '__ob__';
const SKIP = '__v_skip';
if (isObject(obj) && Object.isExtensible(obj)) {
// 避免被 @vue/composition-api 观测
Object.defineProperty(obj, OB, {
configurable: true,
enumerable: false,
value: {
[SKIP]: true
}
});
}
return obj
}
const isArray = Array.isArray;
const keyList = Object.keys;
function equal (a, b) {
if (a === b) return true
if (a && b && typeof a === 'object' && typeof b === 'object') {
const arrA = isArray(a);
const arrB = isArray(b);
let i, length, key;
if (arrA && arrB) {
length = a.length;
if (length !== b.length) return false
for (i = length; i-- !== 0;) {
if (!equal(a[i], b[i])) return false
}
return true
}
if (arrA !== arrB) return false
const dateA = a instanceof Date;
const dateB = b instanceof Date;
if (dateA !== dateB) return false
if (dateA && dateB) return a.getTime() === b.getTime()
const regexpA = a instanceof RegExp;
const regexpB = b instanceof RegExp;
if (regexpA !== regexpB) return false
if (regexpA && regexpB) return a.toString() === b.toString()
const keys = keyList(a);
length = keys.length;
if (length !== keyList(b).length) {
return false
}
for (i = length; i-- !== 0;) {
if (!hasOwn.call(b, keys[i])) return false
}
for (i = length; i-- !== 0;) {
key = keys[i];
if (!equal(a[key], b[key])) return false
}
return true
}
return false
}
const customizeRE = /:/g;
const customize = cached((str) => {
return camelize(str.replace(customizeRE, '-'))
});
const isComponent2 = my.canIUse('component2');
const mocks = ['$id'];
function initRefs () {
}
function initRelation (detail) {
this.props.onVueInit(detail);
}
function initSpecialMethods (mpInstance) {
if (!mpInstance.$vm) {
return
}
let path = mpInstance.is || mpInstance.route;
if (!path) {
return
}
if (path.indexOf('/') === 0) {
path = path.substr(1);
}
const specialMethods = my.specialMethods && my.specialMethods[path];
if (specialMethods) {
specialMethods.forEach(method => {
if (isFn(mpInstance.$vm[method])) {
mpInstance[method] = function (event) {
if (hasOwn(event, 'markerId')) {
event.detail = typeof event.detail === 'object' ? event.detail : {};
event.detail.markerId = event.markerId;
}
// TODO normalizeEvent
mpInstance.$vm[method](event);
};
}
});
}
}
function initChildVues (mpInstance) {
// 此时需保证当前 mpInstance 已经存在 $vm
if (!mpInstance.$vm) {
return
}
mpInstance._$childVues && mpInstance._$childVues.forEach(({
vuePid,
vueOptions,
VueComponent,
mpInstance: childMPInstance
}) => {
// 父子关系
handleLink.call(mpInstance, {
detail: {
vuePid,
vueOptions
}
});
childMPInstance.$vm = new VueComponent(vueOptions);
initSpecialMethods(childMPInstance);
handleRef.call(vueOptions.parent.$scope, childMPInstance);
childMPInstance.$vm.$mount();
initChildVues(childMPInstance);
childMPInstance.$vm._isMounted = true;
childMPInstance.$vm.__call_hook('mounted');
childMPInstance.$vm.__call_hook('onReady');
});
delete mpInstance._$childVues;
}
function handleProps (ref) {
const eventProps = {};
let refProps = ref.props;
const eventList = (refProps['data-event-list'] || '').split(',');
// 初始化支付宝小程序组件事件
eventList.forEach(key => {
const handler = refProps[key];
const res = key.match(/^on([A-Z])(\S*)/);
const event = res && (res[1].toLowerCase() + res[2]);
refProps[key] = eventProps[key] = function () {
const props = Object.assign({}, refProps);
props[key] = handler;
// 由于支付宝事件可能包含多个参数,不使用微信小程序事件格式
delete props['data-com-type'];
triggerEvent.bind({ props })(event, {
__args__: [...arguments]
});
};
});
// 处理 props 重写
Object.defineProperty(ref, 'props', {
get () {
return refProps
},
set (value) {
refProps = Object.assign(value, eventProps);
}
});
}
function handleRef (ref) {
if (!(ref && this.$vm)) {
return
}
const refName = ref.props['data-ref'];
const refInForName = ref.props['data-ref-in-for'];
if (refName) {
this.$vm.$refs[refName] = ref.$vm || toSkip(ref);
} else if (refInForName) {
(this.$vm.$refs[refInForName] || (this.$vm.$refs[refInForName] = [])).push(ref.$vm || toSkip(ref));
}
}
function triggerEvent (type, detail, options) {
const handler = this.props && this.props[customize('on-' + type)];
if (!handler) {
return
}
const eventOpts = this.props['data-event-opts'];
const eventParams = this.props['data-event-params'];
const comType = this.props['data-com-type'];
const target = {
dataset: {
eventOpts,
eventParams,
comType
}
};
handler({
type: customize(type),
target,
currentTarget: target,
detail
});
}
const IGNORES = ['$slots', '$scopedSlots'];
function createObserver (isDidUpdate) {
return function observe (props) {
const prevProps = isDidUpdate ? props : this.props;
const nextProps = isDidUpdate ? this.props : props;
if (equal(prevProps, nextProps)) {
return
}
Object.keys(prevProps).forEach(name => {
if (IGNORES.indexOf(name) === -1) {
const prevValue = prevProps[name];
const nextValue = nextProps[name];
if (!isFn(prevValue) && !isFn(nextValue) && !equal(prevValue, nextValue)) {
this.$vm[name] = nextProps[name];
}
}
});
}
}
const handleLink$1 = (function () {
if (isComponent2) {
return function handleLink$1 (detail) {
return handleLink.call(this, {
detail
})
}
}
return function handleLink$1 (detail) {
if (this.$vm && this.$vm._isMounted) { // 父已初始化
return handleLink.call(this, {
detail: {
vuePid: detail.vuePid,
vueOptions: detail.vueOptions
}
})
}
// 支付宝通过 didMount 来实现,先子后父,故等父 ready 之后,统一初始化
(this._$childVues || (this._$childVues = [])).unshift(detail);
}
})();
const handleWrap = function (mp, destory) {
const vueId = mp.props.vueId;
const list = (mp.props['data-event-list'] || '').split(',');
list.forEach(eventName => {
const key = `${eventName}${vueId}`;
if (destory) {
delete this[key];
} else {
this[key] = function () {
mp.props[eventName].apply(this, arguments);
};
}
});
if (!destory) {
handleProps(mp);
}
};
const MPComponent = Component;
function initHook (name, options) {
const oldHook = options[name];
options[name] = function (...args) {
markMPComponent(this);
const props = this.props;
if (props && props['data-com-type'] === 'wx') {
handleProps(this);
}
if (oldHook) {
return oldHook.apply(this, args)
}
};
}
if (!MPComponent.__$wrappered) {
MPComponent.__$wrappered = true;
Component = function (options = {}) {
initHook('onInit', options);
return MPComponent(options)
};
}
const PAGE_EVENT_HOOKS = [
'onPullDownRefresh',
'onReachBottom',
'onAddToFavorites',
'onShareTimeline',
'onShareAppMessage',
'onPageScroll',
'onResize',
'onTabItemTap'
];
function initMocks (vm, mocks) {
const mpInstance = vm.$mp[vm.mpType];
mocks.forEach(mock => {
if (hasOwn(mpInstance, mock)) {
vm[mock] = mpInstance[mock];
}
});
}
function hasHook (hook, vueOptions) {
if (!vueOptions) {
return true
}
if (Vue.options && Array.isArray(Vue.options[hook])) {
return true
}
vueOptions = vueOptions.default || vueOptions;
if (isFn(vueOptions)) {
if (isFn(vueOptions.extendOptions[hook])) {
return true
}
if (vueOptions.super &&
vueOptions.super.options &&
Array.isArray(vueOptions.super.options[hook])) {
return true
}
return false
}
if (isFn(vueOptions[hook]) || Array.isArray(vueOptions[hook])) {
return true
}
const mixins = vueOptions.mixins;
if (Array.isArray(mixins)) {
return !!mixins.find(mixin => hasHook(hook, mixin))
}
}
function initHooks (mpOptions, hooks, vueOptions) {
hooks.forEach(hook => {
if (hasHook(hook, vueOptions)) {
mpOptions[hook] = function (args) {
return this.$vm && this.$vm.__call_hook(hook, args)
};
}
});
}
function initUnknownHooks (mpOptions, vueOptions, excludes = []) {
findHooks(vueOptions).forEach((hook) => initHook$1(mpOptions, hook, excludes));
}
function findHooks (vueOptions, hooks = []) {
if (vueOptions) {
Object.keys(vueOptions).forEach((name) => {
if (name.indexOf('on') === 0 && isFn(vueOptions[name])) {
hooks.push(name);
}
});
}
return hooks
}
function initHook$1 (mpOptions, hook, excludes) {
if (excludes.indexOf(hook) === -1 && !hasOwn(mpOptions, hook)) {
mpOptions[hook] = function (args) {
return this.$vm && this.$vm.__call_hook(hook, args)
};
}
}
function initVueComponent (Vue, vueOptions) {
vueOptions = vueOptions.default || vueOptions;
let VueComponent;
if (isFn(vueOptions)) {
VueComponent = vueOptions;
} else {
VueComponent = Vue.extend(vueOptions);
}
vueOptions = VueComponent.options;
return [VueComponent, vueOptions]
}
function initVueIds (vueIds, mpInstance) {
vueIds = (vueIds || '').split(',');
const len = vueIds.length;
if (len === 1) {
mpInstance._$vueId = vueIds[0];
} else if (len === 2) {
mpInstance._$vueId = vueIds[0];
mpInstance._$vuePid = vueIds[1];
}
}
function initData (vueOptions, context) {
let data = vueOptions.data || {};
const methods = vueOptions.methods || {};
if (typeof data === 'function') {
try {
data = data.call(context); // 支持 Vue.prototype 上挂的数据
} catch (e) {
if (process.env.VUE_APP_DEBUG) {
console.warn('根据 Vue 的 data 函数初始化小程序 data 失败,请尽量确保 data 函数中不访问 vm 对象,否则可能影响首次数据渲染速度。', data);
}
}
} else {
try {
// 对 data 格式化
data = JSON.parse(JSON.stringify(data));
} catch (e) { }
}
if (!isPlainObject(data)) {
data = {};
}
Object.keys(methods).forEach(methodName => {
if (context.__lifecycle_hooks__.indexOf(methodName) === -1 && !hasOwn(data, methodName)) {
data[methodName] = methods[methodName];
}
});
return data
}
const PROP_TYPES = [String, Number, Boolean, Object, Array, null];
function createObserver$1 (name) {
return function observer (newVal, oldVal) {
if (this.$vm) {
this.$vm[name] = newVal; // 为了触发其他非 render watcher
}
}
}
function initBehaviors (vueOptions, initBehavior) {
const vueBehaviors = vueOptions.behaviors;
const vueExtends = vueOptions.extends;
const vueMixins = vueOptions.mixins;
let vueProps = vueOptions.props;
if (!vueProps) {
vueOptions.props = vueProps = [];
}
const behaviors = [];
if (Array.isArray(vueBehaviors)) {
vueBehaviors.forEach(behavior => {
behaviors.push(behavior.replace('uni://', `${"my"}://`));
if (behavior === 'uni://form-field') {
if (Array.isArray(vueProps)) {
vueProps.push('name');
vueProps.push('value');
} else {
vueProps.name = {
type: String,
default: ''
};
vueProps.value = {
type: [String, Number, Boolean, Array, Object, Date],
default: ''
};
}
}
});
}
{ // alipay 重复定义props会报错,下边的代码对于其他平台也没有意义,保险起见,仅对alipay做处理
return
}
}
function parsePropType (key, type, defaultValue, file) {
// [String]=>String
if (Array.isArray(type) && type.length === 1) {
return type[0]
}
return type
}
function initProperties (props, isBehavior = false, file = '', options) {
const properties = {};
if (!isBehavior) {
properties.vueId = {
type: String,
value: ''
};
{
{
properties.virtualHostStyle = {
type: null,
value: ''
};
properties.virtualHostClass = {
type: null,
value: ''
};
}
}
// scopedSlotsCompiler auto
properties.scopedSlotsCompiler = {
type: String,
value: ''
};
properties.vueSlots = { // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
type: null,
value: [],
observer: function (newVal, oldVal) {
const $slots = Object.create(null);
newVal.forEach(slotName => {
$slots[slotName] = true;
});
this.setData({
$slots
});
}
};
}
if (Array.isArray(props)) { // ['title']
props.forEach(key => {
properties[key] = {
type: null,
observer: createObserver$1(key)
};
});
} else if (isPlainObject(props)) { // {title:{type:String,default:''},content:String}
Object.keys(props).forEach(key => {
const opts = props[key];
if (isPlainObject(opts)) { // title:{type:String,default:''}
let value = opts.default;
if (isFn(value)) {
value = value();
}
opts.type = parsePropType(key, opts.type);
properties[key] = {
type: PROP_TYPES.indexOf(opts.type) !== -1 ? opts.type : null,
value,
observer: createObserver$1(key)
};
} else { // content:String
const type = parsePropType(key, opts);
properties[key] = {
type: PROP_TYPES.indexOf(type) !== -1 ? type : null,
observer: createObserver$1(key)
};
}
});
}
return properties
}
function wrapper$1 (event) {
// TODO 又得兼容 mpvue 的 mp 对象
try {
event.mp = JSON.parse(JSON.stringify(event));
} catch (e) { }
event.stopPropagation = noop;
event.preventDefault = noop;
event.target = event.target || {};
if (!hasOwn(event, 'detail')) {
event.detail = {};
}
if (hasOwn(event, 'markerId')) {
event.detail = typeof event.detail === 'object' ? event.detail : {};
event.detail.markerId = event.markerId;
}
if (isPlainObject(event.detail)) {
event.target = Object.assign({}, event.target, event.detail);
}
return event
}
function getExtraValue (vm, dataPathsArray) {
let context = vm;
dataPathsArray.forEach(dataPathArray => {
const dataPath = dataPathArray[0];
const value = dataPathArray[2];
if (dataPath || typeof value !== 'undefined') { // ['','',index,'disable']
const propPath = dataPathArray[1];
const valuePath = dataPathArray[3];
let vFor;
if (Number.isInteger(dataPath)) {
vFor = dataPath;
} else if (!dataPath) {
vFor = context;
} else if (typeof dataPath === 'string' && dataPath) {
if (dataPath.indexOf('#s#') === 0) {
vFor = dataPath.substr(3);
} else {
vFor = vm.__get_value(dataPath, context);
}
}
if (Number.isInteger(vFor)) {
context = value;
} else if (!propPath) {
context = vFor[value];
} else {
if (Array.isArray(vFor)) {
context = vFor.find(vForItem => {
return vm.__get_value(propPath, vForItem) === value
});
} else if (isPlainObject(vFor)) {
context = Object.keys(vFor).find(vForKey => {
return vm.__get_value(propPath, vFor[vForKey]) === value
});
} else {
console.error('v-for 暂不支持循环数据:', vFor);
}
}
if (valuePath) {
context = vm.__get_value(valuePath, context);
}
}
});
return context
}
function processEventExtra (vm, extra, event, __args__) {
const extraObj = {};
if (Array.isArray(extra) && extra.length) {
/**
*[
* ['data.items', 'data.id', item.data.id],
* ['metas', 'id', meta.id]
*],
*[
* ['data.items', 'data.id', item.data.id],
* ['metas', 'id', meta.id]
*],
*'test'
*/
extra.forEach((dataPath, index) => {
if (typeof dataPath === 'string') {
if (!dataPath) { // model,prop.sync
extraObj['$' + index] = vm;
} else {
if (dataPath === '$event') { // $event
extraObj['$' + index] = event;
} else if (dataPath === 'arguments') {
extraObj['$' + index] = event.detail ? event.detail.__args__ || __args__ : __args__;
} else if (dataPath.indexOf('$event.') === 0) { // $event.target.value
extraObj['$' + index] = vm.__get_value(dataPath.replace('$event.', ''), event);
} else {
extraObj['$' + index] = vm.__get_value(dataPath);
}
}
} else {
extraObj['$' + index] = getExtraValue(vm, dataPath);
}
});
}
return extraObj
}
function getObjByArray (arr) {
const obj = {};
for (let i = 1; i < arr.length; i++) {
const element = arr[i];
obj[element[0]] = element[1];
}
return obj
}
function processEventArgs (vm, event, args = [], extra = [], isCustom, methodName) {
let isCustomMPEvent = false; // wxcomponent 组件,传递原始 event 对象
// fixed 用户直接触发 mpInstance.triggerEvent
const __args__ = isPlainObject(event.detail)
? event.detail.__args__ || [event.detail]
: [event.detail];
if (isCustom) { // 自定义事件
isCustomMPEvent = event.currentTarget &&
event.currentTarget.dataset &&
event.currentTarget.dataset.comType === 'wx';
if (!args.length) { // 无参数,直接传入 event 或 detail 数组
if (isCustomMPEvent) {
return [event]
}
return __args__
}
}
const extraObj = processEventExtra(vm, extra, event, __args__);
const ret = [];
args.forEach(arg => {
if (arg === '$event') {
if (methodName === '__set_model' && !isCustom) { // input v-model value
ret.push(event.target.value);
} else {
if (isCustom && !isCustomMPEvent) {
ret.push(__args__[0]);
} else { // wxcomponent 组件或内置组件
ret.push(event);
}
}
} else {
if (Array.isArray(arg) && arg[0] === 'o') {
ret.push(getObjByArray(arg));
} else if (typeof arg === 'string' && hasOwn(extraObj, arg)) {
ret.push(extraObj[arg]);
} else {
ret.push(arg);
}
}
});
return ret
}
const ONCE = '~';
const CUSTOM = '^';
function isMatchEventType (eventType, optType) {
return (eventType === optType) ||
(
optType === 'regionchange' &&
(
eventType === 'begin' ||
eventType === 'end'
)
)
}
function getContextVm (vm) {
let $parent = vm.$parent;
// 父组件是 scoped slots 或者其他自定义组件时继续查找
while ($parent && $parent.$parent && ($parent.$options.generic || $parent.$parent.$options.generic || $parent.$scope._$vuePid)) {
$parent = $parent.$parent;
}
return $parent && $parent.$parent
}
function handleEvent (event) {
event = wrapper$1(event);
// [['tap',[['handle',[1,2,a]],['handle1',[1,2,a]]]]]
const dataset = (event.currentTarget || event.target).dataset;
if (!dataset) {
return console.warn('事件信息不存在')
}
const eventOpts = dataset.eventOpts || dataset['event-opts']; // 支付宝 web-view 组件 dataset 非驼峰
if (!eventOpts) {
return console.warn('事件信息不存在')
}
// [['handle',[1,2,a]],['handle1',[1,2,a]]]
const eventType = event.type;
const ret = [];
eventOpts.forEach(eventOpt => {
let type = eventOpt[0];
const eventsArray = eventOpt[1];
const isCustom = type.charAt(0) === CUSTOM;
type = isCustom ? type.slice(1) : type;
const isOnce = type.charAt(0) === ONCE;
type = isOnce ? type.slice(1) : type;
if (eventsArray && isMatchEventType(eventType, type)) {
eventsArray.forEach(eventArray => {
const methodName = eventArray[0];
if (methodName) {
let handlerCtx = this.$vm;
if (handlerCtx.$options.generic) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = getContextVm(handlerCtx) || handlerCtx;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
const type = this.$vm.mpType === 'page' ? 'Page' : 'Component';
const path = this.route || this.is;
throw new Error(`${type} "${path}" does not have a method "${methodName}"`)
}
if (isOnce) {
if (handler.once) {
return
}
handler.once = true;
}
let params = processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
);
params = Array.isArray(params) ? params : [];
// 参数尾部增加原始事件对象用于复杂表达式内获取额外数据
if (/=\s*\S+\.eventParams\s*\|\|\s*\S+\[['"]event-params['"]\]/.test(handler.toString())) {
// eslint-disable-next-line no-sparse-arrays
params = params.concat([, , , , , , , , , , event]);
}
ret.push(handler.apply(handlerCtx, params));
}
});
}
});
if (
eventType === 'input' &&
ret.length === 1 &&
typeof ret[0] !== 'undefined'
) {
return ret[0]
}
}
const hooks = [
'onShow',
'onHide',
'onError',
'onPageNotFound',
'onThemeChange',
'onUnhandledRejection'
];
function initEventChannel$1 () {
Vue.prototype.getOpenerEventChannel = function () {
if (!this.__eventChannel__) {
this.__eventChannel__ = new EventChannel();
}
return this.__eventChannel__
};
const callHook = Vue.prototype.__call_hook;
Vue.prototype.__call_hook = function (hook, args) {
if (hook === 'onLoad' && args && args.__id__) {
this.__eventChannel__ = getEventChannel(args.__id__);
delete args.__id__;
}
return callHook.call(this, hook, args)
};
}
function initScopedSlotsParams () {
const center = {};
const parents = {};
function currentId (fn) {
const vueIds = this.$options.propsData.vueId;
if (vueIds) {
const vueId = vueIds.split(',')[0];
fn(vueId);
}
}
Vue.prototype.$hasSSP = function (vueId) {
const slot = center[vueId];
if (!slot) {
parents[vueId] = this;
this.$on('hook:destroyed', () => {
delete parents[vueId];
});
}
return slot
};
Vue.prototype.$getSSP = function (vueId, name, needAll) {
const slot = center[vueId];
if (slot) {
const params = slot[name] || [];
if (needAll) {
return params
}
return params[0]
}
};
Vue.prototype.$setSSP = function (name, value) {
let index = 0;
currentId.call(this, vueId => {
const slot = center[vueId];
const params = slot[name] = slot[name] || [];
params.push(value);
index = params.length - 1;
});
return index
};
Vue.prototype.$initSSP = function () {
currentId.call(this, vueId => {
center[vueId] = {};
});
};
Vue.prototype.$callSSP = function () {
currentId.call(this, vueId => {
if (parents[vueId]) {
parents[vueId].$forceUpdate();
}
});
};
Vue.mixin({
destroyed () {
const propsData = this.$options.propsData;
const vueId = propsData && propsData.vueId;
if (vueId) {
delete center[vueId];
delete parents[vueId];
}
}
});
}
function parseBaseApp (vm, {
mocks,
initRefs
}) {
initEventChannel$1();
{
initScopedSlotsParams();
}
if (vm.$options.store) {
Vue.prototype.$store = vm.$options.store;
}
uniIdMixin(Vue);
Vue.prototype.mpHost = "mp-alipay";
Vue.mixin({
beforeCreate () {
if (!this.$options.mpType) {
return
}
this.mpType = this.$options.mpType;
this.$mp = {
data: {},
[this.mpType]: this.$options.mpInstance
};
this.$scope = this.$options.mpInstance;
delete this.$options.mpType;
delete this.$options.mpInstance;
if (this.mpType === 'page' && typeof getApp === 'function') { // hack vue-i18n
const app = getApp();
if (app.$vm && app.$vm.$i18n) {
this._i18n = app.$vm.$i18n;
}
}
if (this.mpType !== 'app') {
initRefs(this);
initMocks(this, mocks);
}
}
});
const appOptions = {
onLaunch (args) {
if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
return
}
this.$vm = vm;
this.$vm.$mp = {
app: this
};
this.$vm.$scope = this;
// vm 上也挂载 globalData
this.$vm.globalData = this.globalData;
this.$vm._isMounted = true;
this.$vm.__call_hook('mounted', args);
this.$vm.__call_hook('onLaunch', args);
}
};
// 兼容旧版本 globalData
appOptions.globalData = vm.$options.globalData || {};
// 将 methods 中的方法挂在 getApp() 中
const methods = vm.$options.methods;
if (methods) {
Object.keys(methods).forEach(name => {
appOptions[name] = methods[name];
});
}
initAppLocale(Vue, vm, normalizeLocale(my.getSystemInfoSync().language) || LOCALE_EN);
initHooks(appOptions, hooks);
initUnknownHooks(appOptions, vm.$options);
return appOptions
}
function parseApp (vm) {
Vue.prototype.$onAliGetAuthorize = function onAliGetAuthorize (method, $event) {
my.getPhoneNumber({
success: (res) => {
$event.type = 'getphonenumber';
const response = JSON.parse(res.response);
$event.detail.errMsg = 'getPhoneNumber:ok';
$event.detail.encryptedData = response.response;
$event.detail.sign = response.sign;
this[method]($event);
},
fail: (res) => {
$event.type = 'getphonenumber';
$event.detail.errMsg = 'getPhoneNumber:fail Error: ' + JSON.stringify(res);
this[method]($event);
}
});
};
Vue.prototype.$onAliAuthError = function $onAliAuthError (method, $event) {
$event.type = 'getphonenumber';
$event.detail.errMsg = 'getPhoneNumber:fail Error: ' + $event.detail.errorMessage;
this[method]($event);
};
return parseBaseApp(vm, {
mocks,
initRefs
})
}
function createApp (vm) {
App(parseApp(vm));
return vm
}
const encodeReserveRE = /[!'()*]/g;
const encodeReserveReplacer = c => '%' + c.charCodeAt(0).toString(16);
const commaRE = /%2C/g;
// fixed encodeURIComponent which is more conformant to RFC3986:
// - escapes [!'()*]
// - preserve commas
const encode = str => encodeURIComponent(str)
.replace(encodeReserveRE, encodeReserveReplacer)
.replace(commaRE, ',');
function stringifyQuery (obj, encodeStr = encode) {
const res = obj ? Object.keys(obj).map(key => {
const val = obj[key];
if (val === undefined) {
return ''
}
if (val === null) {
return encodeStr(key)
}
if (Array.isArray(val)) {
const result = [];
val.forEach(val2 => {
if (val2 === undefined) {
return
}
if (val2 === null) {
result.push(encodeStr(key));
} else {
result.push(encodeStr(key) + '=' + encodeStr(val2));
}
});
return result.join('&')
}
return encodeStr(key) + '=' + encodeStr(val)
}).filter(x => x.length > 0).join('&') : null;
return res ? `?${res}` : ''
}
const hooks$1 = [
'onShow',
'onHide',
// mp-alipay 特有
'onTitleClick',
'onOptionMenuClick',
'onPopMenuClick',
'onPullIntercept'
];
hooks$1.push(...PAGE_EVENT_HOOKS);
function parsePage (vuePageOptions) {
const [VueComponent, vueOptions] = initVueComponent(Vue, vuePageOptions);
const pageOptions = {
mixins: initBehaviors(vueOptions),
data: initData(vueOptions, Vue.prototype),
onLoad (query) {
const properties = this.props;
const options = {
mpType: 'page',
mpInstance: this,
propsData: properties
};
// 初始化 vue 实例
this.$vm = new VueComponent(options);
initSpecialMethods(this);
// 触发首次 setData
this.$vm.$mount();
const copyQuery = Object.assign({}, query);
delete copyQuery.__id__;
this.$page = {
fullPath: '/' + this.route + stringifyQuery(copyQuery)
};
this.options = query;
this.$vm.$mp.query = query; // 兼容 mpvue
this.$vm.__call_hook('onLoad', query);
},
onReady () {
initChildVues(this);
this.$vm._isMounted = true;
this.$vm.__call_hook('mounted');
this.$vm.__call_hook('onReady');
},
onUnload () {
this.$vm.__call_hook('onUnload');
this.$vm.$destroy();
},
events: {
// 支付宝小程序有些页面事件只能放在events下
onBack () {
this.$vm.__call_hook('onBackPress');
},
onKeyboardHeight (res) {
$emit('uni:keyboardHeightChange', res);
}
},
__r: handleRef,
__e: handleEvent,
__l: handleLink$1,
__w: handleWrap,
triggerEvent
};
Object.assign(pageOptions.events, vueOptions.events || {});
initHooks(pageOptions, hooks$1, vueOptions);
initUnknownHooks(pageOptions, vueOptions, ['onReady']);
if (Array.isArray(vueOptions.wxsCallMethods)) {
vueOptions.wxsCallMethods.forEach(callMethod => {
pageOptions[callMethod] = function (args) {
return this.$vm[callMethod](args)
};
});
}
return pageOptions
}
function createPage (vuePageOptions) {
{
return Page(parsePage(vuePageOptions))
}
}
function initSlots (vm, vueSlots) {
const $slots = Object.create(null);
// 未启用小程序基础库 2.0 时,组件实例支持支持访问 $slots、$scopedSlots
Object.defineProperty(vm, '$slots', {
get () {
const $scope = this.$scope;
return ($scope && $scope.props.$slots) || ($scope && $scope.props.$scopedSlots ? {} : $slots)
}
});
Object.defineProperty(vm, '$scopedSlots', {
get () {
const $scope = this.$scope;
return ($scope && $scope.props.$scopedSlots) || ($scope && $scope.props.$slots ? {} : $slots)
}
});
// 处理$slots,$scopedSlots(暂不支持动态变化$slots)
if (Array.isArray(vueSlots) && vueSlots.length) {
vueSlots.forEach(slotName => {
$slots[slotName] = true;
});
}
}
function initVm (VueComponent) {
if (this.$vm) {
return
}
const properties = this.props;
const options = {
mpType: 'component',
mpInstance: this,
propsData: properties
};
initVueIds(properties.vueId, this);
if (isComponent2) {
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
vueOptions: options
});
// 初始化 vue 实例
this.$vm = new VueComponent(options);
initSlots(this.$vm, properties.vueSlots);
// 触发首次 setData
this.$vm.$mount();
} else {
// 处理父子关系
initRelation.call(this, {
vuePid: this._$vuePid,
vueOptions: options,
VueComponent,
mpInstance: this
});
if (options.parent) { // 父组件已经初始化,直接初始化子,否则放到父组件的 didMount 中处理
// 初始化 vue 实例
this.$vm = new VueComponent(options);
handleRef.call(options.parent.$scope, this);
initSlots(this.$vm, properties.vueSlots);
// 触发首次 setData
this.$vm.$mount();
initChildVues(this);
this.$vm._isMounted = true;
this.$vm.__call_hook('mounted');
this.$vm.__call_hook('onReady');
}
}
}
function parseComponent (vueComponentOptions, needVueOptions) {
const [VueComponent, vueOptions] = initVueComponent(Vue, vueComponentOptions);
const properties = initProperties(vueOptions.props, false, vueOptions.__file);
const props = {
onVueInit: function () {}
};
Object.keys(properties).forEach(key => {
props[key] = properties[key].value;
});
const componentOptions = {
mixins: initBehaviors(vueOptions),
data: initData(vueOptions, Vue.prototype),
props,
didMount () {
if (my.dd) { // 钉钉小程序底层基础库有 bug,组件嵌套使用时,在 didMount 中无法及时调用 props 中的方法
setTimeout(() => {
initVm.call(this, VueComponent);
}, 4);
} else {
initVm.call(this, VueComponent);
}
initSpecialMethods(this);
if (isComponent2) {
this.$vm._isMounted = true;
this.$vm.__call_hook('mounted');
this.$vm.__call_hook('onReady');
}
},
didUnmount () {
this.$vm && this.$vm.$destroy();
},
methods: {
__r: handleRef,
__e: handleEvent,
__l: handleLink$1,
__w: handleWrap,
triggerEvent
}
};
if (isComponent2) {
componentOptions.onInit = function onInit () {
initVm.call(this, VueComponent);
};
componentOptions.deriveDataFromProps = createObserver();
} else {
componentOptions.didUpdate = createObserver(true);
}
if (Array.isArray(vueOptions.wxsCallMethods)) {
vueOptions.wxsCallMethods.forEach(callMethod => {
componentOptions.methods[callMethod] = function (args) {
return this.$vm[callMethod](args)
};
});
}
return needVueOptions ? [componentOptions, vueOptions] : componentOptions
}
function createComponent (vueOptions) {
{
return my.defineComponent(parseComponent(vueOptions))
}
}
function createSubpackageApp (vm) {
const appOptions = parseApp(vm);
const app = getApp({
allowDefault: true
});
vm.$scope = app;
const globalData = app.globalData;
if (globalData) {
Object.keys(appOptions.globalData).forEach(name => {
if (!hasOwn(globalData, name)) {
globalData[name] = appOptions.globalData[name];
}
});
}
Object.keys(appOptions).forEach(name => {
if (!hasOwn(app, name)) {
app[name] = appOptions[name];
}
});
if (isFn(appOptions.onShow) && my.onAppShow) {
my.onAppShow((...args) => {
vm.__call_hook('onShow', args);
});
}
if (isFn(appOptions.onHide) && my.onAppHide) {
my.onAppHide((...args) => {
vm.__call_hook('onHide', args);
});
}
if (isFn(appOptions.onLaunch)) {
const args = my.getLaunchOptionsSync && my.getLaunchOptionsSync();
vm.__call_hook('onLaunch', args);
}
return vm
}
function createPlugin (vm) {
const appOptions = parseApp(vm);
if (isFn(appOptions.onShow) && my.onAppShow) {
my.onAppShow((...args) => {
vm.__call_hook('onShow', args);
});
}
if (isFn(appOptions.onHide) && my.onAppHide) {
my.onAppHide((...args) => {
vm.__call_hook('onHide', args);
});
}
if (isFn(appOptions.onLaunch)) {
const args = my.getLaunchOptionsSync && my.getLaunchOptionsSync();
vm.__call_hook('onLaunch', args);
}
return vm
}
todos.forEach(todoApi => {
protocols[todoApi] = false;
});
canIUses.forEach(canIUseApi => {
const apiName = protocols[canIUseApi] && protocols[canIUseApi].name ? protocols[canIUseApi].name
: canIUseApi;
if (!my.canIUse(apiName)) {
protocols[canIUseApi] = false;
}
});
let uni = {};
if (typeof Proxy !== 'undefined' && "mp-alipay" !== 'app-plus') {
uni = new Proxy({}, {
get (target, name) {
if (hasOwn(target, name)) {
return target[name]
}
if (baseApi[name]) {
return baseApi[name]
}
if (api[name]) {
return promisify(name, api[name])
}
{
if (extraApi[name]) {
return promisify(name, extraApi[name])
}
if (todoApis[name]) {
return promisify(name, todoApis[name])
}
}
if (eventApi[name]) {
return eventApi[name]
}
return promisify(name, wrapper(name, my[name]))
},
set (target, name, value) {
target[name] = value;
return true
}
});
} else {
Object.keys(baseApi).forEach(name => {
uni[name] = baseApi[name];
});
{
Object.keys(todoApis).forEach(name => {
uni[name] = promisify(name, todoApis[name]);
});
Object.keys(extraApi).forEach(name => {
uni[name] = promisify(name, todoApis[name]);
});
}
Object.keys(eventApi).forEach(name => {
uni[name] = eventApi[name];
});
Object.keys(api).forEach(name => {
uni[name] = promisify(name, api[name]);
});
Object.keys(my).forEach(name => {
if (hasOwn(my, name) || hasOwn(protocols, name)) {
uni[name] = promisify(name, wrapper(name, my[name]));
}
});
}
my.createApp = createApp;
my.createPage = createPage;
my.createComponent = createComponent;
my.createSubpackageApp = createSubpackageApp;
my.createPlugin = createPlugin;
var uni$1 = uni;
export default uni$1;
export { createApp, createComponent, createPage, createPlugin, createSubpackageApp };