UNPKG

@hsui/core

Version:

Hundsun frontend runtime core framework

1,565 lines (1,491 loc) 43.5 kB
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties'; import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2'; import _defineProperty from '@babel/runtime/helpers/esm/defineProperty'; import _classCallCheck from '@babel/runtime/helpers/esm/classCallCheck'; import _createClass from '@babel/runtime/helpers/esm/createClass'; import _classPrivateFieldLooseBase from '@babel/runtime/helpers/esm/classPrivateFieldLooseBase'; import _classPrivateFieldLooseKey from '@babel/runtime/helpers/esm/classPrivateFieldLooseKey'; import { ajax, ajaxCancelMap, storage, setConfig } from '@hsui/sdk'; import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray'; import _typeof from '@babel/runtime/helpers/esm/typeof'; import { createLogger } from '@hsui/logger'; import Model from 'vue'; import Router from 'vue-router'; import _regeneratorRuntime from '@babel/runtime/helpers/esm/regeneratorRuntime'; import _asyncToGenerator from '@babel/runtime/helpers/esm/asyncToGenerator'; export * from '@@/huiExports'; /** * Native isArray */ var isArray = Array.isArray; /** * Underscore isFunction */ function isFunction(value) { return Object.prototype.toString.call(value) === '[object Function]'; } /** * Redux isPlainObject */ function isPlainObject(obj) { if (_typeof(obj) !== 'object' || obj === null) return false; var proto = obj; while (Object.getPrototypeOf(proto) !== null) { proto = Object.getPrototypeOf(proto); } return Object.getPrototypeOf(obj) === proto; } /** * Check if powered by HUI Micro App */ function isMicroApp() { return Boolean(window.__POWERED_BY_HUI_MICRO_APP__); } /** * simple generate uuid * 支持 ie10 及以上 * 基于 uuid v4 添加 performance.now 避免重复 */ function uuid() { var d = Date.now(); if (typeof performance !== 'undefined' && typeof performance.now === 'function') { d += performance.now(); //use high-precision timer if available } return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c === 'x' ? r : r & 0x3 | 0x8).toString(16); }); } /** * Underscore uniqueId */ var idCounter = 0; function uniqueId(prefix) { var id = ++idCounter + ''; return prefix ? prefix + id : id; } /** * Native extend */ var extend = Object.assign; /** * Lodash isObject */ function isObject$1(value) { var type = _typeof(value); return value != null && (type == 'object' || type == 'function'); } /** * Underscore clone */ function clone(value) { if (!isObject$1(value)) return value; if (typeof value === 'function') return value; return isArray(value) ? value.slice() : extend({}, value); } /** * DeepClone */ function deepClone(value) { return JSON.parse(JSON.stringify(value)); } var utils = /*#__PURE__*/Object.freeze({ __proto__: null, isArray: isArray, isFunction: isFunction, isPlainObject: isPlainObject, isMicroApp: isMicroApp, uuid: uuid, uniqueId: uniqueId, extend: extend, isObject: isObject$1, clone: clone, deepClone: deepClone }); /** * Lodash isUndefined */ function isUndefined(value) { return value === undefined; } /** * Lodash isObject */ function isObject(value) { var type = _typeof(value); return value != null && (type == 'object' || type == 'function'); } /** * Lodash noop */ function noop() { // No operation performed. } function isNull(value) { return value === null || value === undefined; } function isString(value) { return typeof value === 'string'; } /** * @class - MiddlewareManager * @classdesc - manager of middlewares */ var MiddlewareManager = /*#__PURE__*/function () { function MiddlewareManager(type) { _classCallCheck(this, MiddlewareManager); this.type = type; this.middlewares = []; this.finalHook = noop; } _createClass(MiddlewareManager, [{ key: "final", value: function final(hook) { this.finalHook = hook; } }, { key: "concat", value: function concat(middlewares) { this.middlewares = this.middlewares.concat(middlewares); } }, { key: "push", value: function push(middleware) { this.middlewares.push(middleware); } // just run and return nothing }, { key: "justRun", value: function justRun() { this.args = Array.prototype.slice.call(arguments); var _this = this; var fn = function fn(index) { if (index < this.middlewares.length) { this.middlewares[index].apply(null, [].concat(_toConsumableArray(this.args), [function () { fn.call(_this, ++index); }])); } else { this.finalHook.apply(null, this.args); } }; fn.call(_this, 0); } // run middlewares and return a promise }, { key: "runAndReturn", value: function runAndReturn() { this.args = Array.prototype.slice.call(arguments); var _this = this; return new Promise(function (resolve, reject) { var fn = function fn(index) { if (index < this.middlewares.length) { try { this.middlewares[index].apply(null, [].concat(_toConsumableArray(this.args), [function () { fn.call(_this, ++index); }])); } catch (error) { reject(error); } } else { // final hook should return a promise too this.finalHook.apply(null, this.args).then(resolve).catch(reject); } }; fn.call(_this, 0); }); } }]); return MiddlewareManager; }(); var manager = {}; ['before-route-change', 'after-route-change', 'before-request-send', 'after-request-send', 'before-launch'].forEach(function (type) { manager[type] = new MiddlewareManager(type); }); var beforeRouteChange = manager['before-route-change']; var afterRouteChange = manager['after-route-change']; var beforeRequestSend = manager['before-request-send']; var afterRequestSend = manager['after-request-send']; var beforeLaunch = manager['before-launch']; function registerMiddleware(type, middleware) { if (isFunction(middleware)) { manager[type].push(middleware); } if (isArray(middleware)) { manager[type].concat(middleware); } } var logger = createLogger(); var log = function log() { for (var _len = arguments.length, content = new Array(_len), _key = 0; _key < _len; _key++) { content[_key] = arguments[_key]; } return logger.info.apply(logger, content); }; logger.levels.forEach(function (level) { log[level] = function () { for (var _len2 = arguments.length, content = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { content[_key2] = arguments[_key2]; } return logger[level].apply(logger, content); }; }); function final_(error, response) { if (error) { return Promise.reject(error); } return Promise.resolve(response); } /** * 合并全局配置和实例配置 * @param {Object} defaultConfig 全局配置 * @param {Object} config 实例配置 * @returns 合并后的请求配置 */ function mergeConfig(defaultConfig, config) { var mergedConfig = _objectSpread(_objectSpread({}, defaultConfig), config); if (mergedConfig.shouldMergeHeaders) { var defaultHeaders = defaultConfig.headers; var configHeaders = config.headers; var mergedHeaders = _objectSpread(_objectSpread({}, defaultHeaders), configHeaders); mergedConfig.headers = mergedHeaders; } return mergedConfig; } /** * fetchPromise(调用fetch函数得到) 和 ajaxPromise(调用ajax函数得到) 关联对应 * 其中,key 为 fetchPromise,value 为 ajaxPromise */ var fetchMap = new WeakMap(); var defaultConfig = { method: 'post', data: {}, timeout: 5000, headers: {}, withCredentials: false }; var Fetch = /*#__PURE__*/_createClass(function Fetch() { var _config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; _classCallCheck(this, Fetch); extend(defaultConfig, _config); var ajaxPromise; // 存储 ajax 返回的 promise beforeRequestSend.final(function (config) { return new Promise(function (resolve, reject) { var error, response; ajaxPromise = ajax(config); ajaxPromise.then(function (res) { return response = res; }).catch(function (err) { return error = err; }).finally(function () { afterRequestSend.runAndReturn(error, response).then(resolve).catch(reject); }); }); }); afterRequestSend.final(final_); function fetch(config) { log.debug('Fetch 实例初始化选项', mergeConfig(defaultConfig, config)); var fetchPromise = beforeRequestSend.runAndReturn(mergeConfig(defaultConfig, config)); fetchMap.set(fetchPromise, ajaxPromise); // 建立关联,fetchPromise 和 ajaxPromise return fetchPromise; } fetch.get = function (url, config) { if (config) { extend(config, { url: url, method: 'get' }); } else { config = { url: url, method: 'get' }; } return fetch(config); }; fetch.post = function (url, data, config) { if (config) { extend(config, { url: url, method: 'post', data: data }); } else { config = { url: url, method: 'post', data: data }; } return fetch(config); }; fetch.cancel = function () { for (var _len = arguments.length, fetchPromises = new Array(_len), _key = 0; _key < _len; _key++) { fetchPromises[_key] = arguments[_key]; } fetchPromises.forEach(function (fetchPromise, index) { var ajaxPromise = fetchMap.get(fetchPromise); var cancel = ajaxCancelMap.get(ajaxPromise); cancel ? cancel() : log.debug("\u6CA1\u6709\u627E\u5230\u4E0B\u6807\u4E3A ".concat(index, " \u5BF9\u5E94\u7684 cancel \u51FD\u6570")); }); }; return fetch; }); function initFetch() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$defaultConfig = _ref.defaultConfig, defaultConfig = _ref$defaultConfig === void 0 ? { method: 'post', data: {}, timeout: 5000, headers: {}, withCredentials: false } : _ref$defaultConfig, _ref$beforeRequestSen = _ref.beforeRequestSendMiddlewares, beforeRequestSendMiddlewares = _ref$beforeRequestSen === void 0 ? [] : _ref$beforeRequestSen, _ref$afterRequestSend = _ref.afterRequestSendMiddlewares, afterRequestSendMiddlewares = _ref$afterRequestSend === void 0 ? [] : _ref$afterRequestSend; var beforeRequestSend = new MiddlewareManager('before-request-send'); beforeRequestSend.concat(beforeRequestSendMiddlewares); var afterRequestSend = new MiddlewareManager('after-request-send'); afterRequestSend.concat(afterRequestSendMiddlewares); afterRequestSend.final(final_); var ajaxPromise; // 存储 ajax 函数返回的 promise beforeRequestSend.final(function (config) { return new Promise(function (resolve, reject) { var error, response; ajaxPromise = ajax(config); ajaxPromise.then(function (res) { return response = res; }).catch(function (err) { return error = err; }).finally(function () { afterRequestSend.runAndReturn(error, response).then(resolve).catch(reject); }); }); }); var fetch = function fetch(config) { log.debug('Fetch 实例初始化选项', mergeConfig(defaultConfig, config)); var fetchPromise = beforeRequestSend.runAndReturn(mergeConfig(defaultConfig, config)); fetchMap.set(fetchPromise, ajaxPromise); return fetchPromise; }; fetch.get = function (url, config) { if (config) { extend(config, { url: url, method: 'get' }); } else { config = { url: url, method: 'get' }; } return fetch(config); }; fetch.post = function (url, data, config) { if (config) { extend(config, { url: url, method: 'post', data: data }); } else { config = { url: url, method: 'post', data: data }; } return fetch(config); }; fetch.cancel = function () { for (var _len2 = arguments.length, fetchPromises = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { fetchPromises[_key2] = arguments[_key2]; } fetchPromises.forEach(function (fetchPromise, index) { var ajaxPromise = fetchMap.get(fetchPromise); // 根据传入的 fetchPromise,查找对应的 ajaxPromise var cancel = ajaxCancelMap.get(ajaxPromise); // 根据指定的 ajaxPromise,查找对应的取消函数 cancel ? cancel() : log.debug("\u6CA1\u6709\u627E\u5230\u4E0B\u6807\u4E3A ".concat(index, " \u5BF9\u5E94\u7684 cancel \u51FD\u6570")); }); }; return fetch; } var _require = require('../package.json'), version = _require.version; var isNavigationFailure = Router.isNavigationFailure, NavigationFailureType = Router.NavigationFailureType; var encodeReserveRE = /[!'()*]/g; var encodeReserveReplacer = function encodeReserveReplacer(c) { return '%' + c.charCodeAt(0).toString(16); }; var commaRE = /%2C/g; // fixed encodeURIComponent which is more conformant to RFC3986: // - escapes [!'()*] // - preserve commas var encode = function encode(str) { return encodeURIComponent(str).replace(encodeReserveRE, encodeReserveReplacer).replace(commaRE, ','); }; var decode = decodeURIComponent; var defaultRouterOpts = { scrollBehavior: function scrollBehavior() { return { x: 0, y: 0 }; } }; var router = null; function initRouter$1(routes, opts) { if (router) return router; // 避免在调用 initRouter 之前注册,在 1.0 的场景下,多个子应用都访问 @hsui/core 的情况下会造成冲突 Model.use(Router); // 合并 defaultRouterOpts opts = _objectSpread(_objectSpread({}, defaultRouterOpts), opts); // 保证在 hash 模式下也能从 location.search 中读取查询参数 // TODO - 暂时还没有解决方案,在主子应用同时存在路由参数的情况下,url 会存在多个 search 片段的问题 if (opts.mode === 'hash') { opts = _objectSpread(_objectSpread({}, opts), {}, { parseQuery: function parseQuery(query) { var res = {}; query = query.trim().replace(/^(\?|#|&)/, ''); if (!query) { var _location = location, search = _location.search; search = search.trim().replace(/^(\?|#|&)/, ''); if (!search) { return res; } query = search; } query.split('&').forEach(function (param) { var parts = param.replace(/\+/g, ' ').split('='); var key = decode(parts.shift()); var val = parts.length > 0 ? decode(parts.join('=')) : null; if (res[key] === undefined) { res[key] = val; } else if (Array.isArray(res[key])) { res[key].push(val); } else { res[key] = [res[key], val]; } }); return res; }, stringifyQuery: function stringifyQuery(obj) { var res = obj ? Object.keys(obj).map(function (key) { var val = obj[key]; if (val === undefined) { return ''; } if (val === null) { return encode(key); } if (Array.isArray(val)) { var result = []; val.forEach(function (val2) { if (val2 === undefined) { return; } if (val2 === null) { result.push(encode(key)); } else { result.push(encode(key) + '=' + encode(val2)); } }); return result.join('&'); } return encode(key) + '=' + encode(val); }).filter(function (x) { return x.length > 0; }).join('&') : null; if (res && !location.search.includes(res)) { return "?".concat(res); } return ''; } }); } router = new Router(opts); if (routes) { router.addRoutes(routes); } log.debug('Router 实例', router); log.debug('Router 构建选项', opts); log.debug('Routes 路由记录', router.getRoutes()); router.beforeEach(function (to, from, next) { log.debug('路由跳转前置导航守卫', to, from); next(); }); beforeRouteChange.middlewares.forEach(function (middleware) { return router.beforeEach(middleware); }); router.afterEach(function (to, from) { log.debug('路由跳转后置导航守卫', to, from); afterRouteChange.justRun(to, from); }); return router; } /** * Set default router options * @param {object} opts */ function setRouterOpts(opts) { extend(defaultRouterOpts, opts); } /** * @description jump programmatically * @param {String} path target path * @param {Object} opts options * @param {Boolean} opts.history whether to keep current browser history, perform like pushState or replaceState, default true * @param {Boolean} opts.animation todo * @param {Object} query query params */ function navigate(path, opts, query) { if (!router) return; var defaultOpts = { history: true }; var defaultQuery = {}; if (!_typeof(path) === 'string' || path === '') { log.error('navigate 方法必须指定 path 为字符串类型且不能为空'); return false; } // 只有两个参数,则第二个为 query if (isPlainObject(opts) && isUndefined(query)) { query = opts; opts = defaultOpts; } // path 是必填项 if (isUndefined(opts)) { opts = defaultOpts; query = defaultQuery; } var _opts = opts, history = _opts.history; var onError = function onError(err) { if (isNavigationFailure(err, NavigationFailureType.duplicated) || isNavigationFailure(err, NavigationFailureType.redirected)) { return; } log.error('路由跳转异常', err); throw err; }; if (history) { router.push({ path: path, query: query }).catch(onError); } else { router.replace({ path: path, query: query }).catch(onError); } } /** * @description go forwards or go backwards in the history stack programmatically * @param {Number} n steps to go, setting to 0 perform like reload */ function go(n) { if (!router) return; router.go(n); } /** * https://github.com/developit/mitt */ function mitt(all) { all = all || new Map(); return { on: function on(type, handler) { var handlers = all.get(type); var added = handlers && handlers.push(handler); if (!added) { all.set(type, [handler]); } log.debug('部署事件监听', type); }, off: function off(type, handler) { var handlers = all.get(type); if (handlers) { if (handler) { handlers.splice(handlers.indexOf(handler) >>> 0, 1); } else { all.set(type, []); } } log.debug('取消事件监听', type); }, emit: function emit(type) { log.debug.apply(log, ['触发事件监听'].concat(Array.prototype.slice.call(arguments))); var args = Array.prototype.slice.call(arguments); (all.get(type) || []).slice().map(function (handler) { log.debug('响应事件监听', type, handler); handler.apply(null, args.slice(1)); }); (all.get('*') || []).slice().map(function (handler) { log.debug('响应事件监听', type, handler); handler.apply(null, args); }); } }; } var emitter = mitt(); emitter.once = function (type, handler) { var _handler = function _handler() { handler.apply(null, Array.prototype.slice.call(arguments)); emitter.off(type, _handler); }; emitter.on(type, _handler); }; var on = emitter.on, once = emitter.once, off = emitter.off, emit = emitter.emit, trigger = emitter.emit; /** * Path parser * - Inspired: * Vue.js Path parser */ // actions var APPEND = 0; var PUSH = 1; var INC_SUB_PATH_DEPTH = 2; var PUSH_SUB_PATH = 3; // states var BEFORE_PATH = 0; var IN_PATH = 1; var BEFORE_IDENT = 2; var IN_IDENT = 3; var IN_SUB_PATH = 4; var IN_SINGLE_QUOTE = 5; var IN_DOUBLE_QUOTE = 6; var AFTER_PATH = 7; var ERROR = 8; var pathStateMachine = []; pathStateMachine[BEFORE_PATH] = { ws: [BEFORE_PATH], ident: [IN_IDENT, APPEND], '[': [IN_SUB_PATH], eof: [AFTER_PATH] }; pathStateMachine[IN_PATH] = { ws: [IN_PATH], '.': [BEFORE_IDENT], '[': [IN_SUB_PATH], eof: [AFTER_PATH] }; pathStateMachine[BEFORE_IDENT] = { ws: [BEFORE_IDENT], ident: [IN_IDENT, APPEND], '0': [IN_IDENT, APPEND], number: [IN_IDENT, APPEND] }; pathStateMachine[IN_IDENT] = { ident: [IN_IDENT, APPEND], '0': [IN_IDENT, APPEND], number: [IN_IDENT, APPEND], ws: [IN_PATH, PUSH], '.': [BEFORE_IDENT, PUSH], '[': [IN_SUB_PATH, PUSH], eof: [AFTER_PATH, PUSH] }; pathStateMachine[IN_SUB_PATH] = { "'": [IN_SINGLE_QUOTE, APPEND], '"': [IN_DOUBLE_QUOTE, APPEND], '[': [IN_SUB_PATH, INC_SUB_PATH_DEPTH], ']': [IN_PATH, PUSH_SUB_PATH], eof: ERROR, else: [IN_SUB_PATH, APPEND] }; pathStateMachine[IN_SINGLE_QUOTE] = { "'": [IN_SUB_PATH, APPEND], eof: ERROR, else: [IN_SINGLE_QUOTE, APPEND] }; pathStateMachine[IN_DOUBLE_QUOTE] = { '"': [IN_SUB_PATH, APPEND], eof: ERROR, else: [IN_DOUBLE_QUOTE, APPEND] }; /** * Check if an expression is a literal value. */ var literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/; function isLiteral(exp) { return literalValueRE.test(exp); } /** * Strip quotes from a string */ function stripQuotes(str) { var a = str.charCodeAt(0); var b = str.charCodeAt(str.length - 1); return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str; } /** * Determine the type of a character in a keypath. */ function getPathCharType(ch) { if (ch === undefined || ch === null) { return 'eof'; } var code = ch.charCodeAt(0); switch (code) { case 0x5b: // [ case 0x5d: // ] case 0x2e: // . case 0x22: // " case 0x27: // ' return ch; case 0x5f: // _ case 0x24: // $ case 0x2d: // - return 'ident'; case 0x09: // Tab case 0x0a: // Newline case 0x0d: // Return case 0xa0: // No-break space case 0xfeff: // Byte Order Mark case 0x2028: // Line Separator case 0x2029: // Paragraph Separator return 'ws'; } return 'ident'; } /** * Format a subPath, return its plain form if it is * a literal string or number. Otherwise prepend the * dynamic indicator (*). */ function formatSubPath(path) { var trimmed = path.trim(); // invalid leading 0 if (path.charAt(0) === '0') { return false; } return isLiteral(trimmed) ? stripQuotes(trimmed) : '*' + trimmed; } /** * Parse a string path into an array of segments */ function parse(path) { var keys = []; var index = -1; var mode = BEFORE_PATH; var subPathDepth = 0; var c; var key; var newChar; var type; var transition; var action; var typeMap; var actions = []; actions[PUSH] = function () { if (key !== undefined) { keys.push(key); key = undefined; } }; actions[APPEND] = function () { if (key === undefined) { key = newChar; } else { key += newChar; } }; actions[INC_SUB_PATH_DEPTH] = function () { actions[APPEND](); subPathDepth++; }; actions[PUSH_SUB_PATH] = function () { if (subPathDepth > 0) { subPathDepth--; mode = IN_SUB_PATH; actions[APPEND](); } else { subPathDepth = 0; if (key === undefined) { return false; } key = formatSubPath(key); if (key === false) { return false; } else { actions[PUSH](); } } }; function maybeUnescapeQuote() { var nextChar = path[index + 1]; if (mode === IN_SINGLE_QUOTE && nextChar === "'" || mode === IN_DOUBLE_QUOTE && nextChar === '"') { index++; newChar = '\\' + nextChar; actions[APPEND](); return true; } } while (mode !== null) { index++; c = path[index]; if (c === '\\' && maybeUnescapeQuote()) { continue; } type = getPathCharType(c); typeMap = pathStateMachine[mode]; transition = typeMap[type] || typeMap['else'] || ERROR; if (transition === ERROR) { return; // parse error } mode = transition[0]; action = actions[transition[1]]; if (action) { newChar = transition[2]; newChar = newChar === undefined ? c : newChar; if (action() === false) { return; } } if (mode === AFTER_PATH) { return keys; } } } var I18nPath = /*#__PURE__*/function () { function I18nPath() { _classCallCheck(this, I18nPath); this._cache = void 0; this._cache = Object.create(null); } /** * External parse that check for a cache hit first */ _createClass(I18nPath, [{ key: "parsePath", value: function parsePath(path) { var hit = this._cache[path]; if (!hit) { hit = parse(path); if (hit) { this._cache[path] = hit; } } return hit || []; } /** * Get path value from path string */ }, { key: "getPathValue", value: function getPathValue(obj, path) { if (!isObject(obj)) { return null; } var paths = this.parsePath(path); if (paths.length === 0) { return null; } else { var length = paths.length; var last = obj; var i = 0; while (i < length) { var value = last[paths[i]]; if (value === undefined || value === null) { return null; } last = value; i++; } return last; } } }]); return I18nPath; }(); var i18ns = []; var I18n = /*#__PURE__*/function () { /** * lightweight i18n * @param {object} options * - locale * - messages */ function I18n(options) { _classCallCheck(this, I18n); this.locale = options.locale || 'en-US'; this.messages = options.messages || {}; // window.__hCoreReference var root = window.__hCoreReference__.root; this._root = options.root || root || null; this._path = new I18nPath(); this.watchLocale(); i18ns.push(this); } _createClass(I18n, [{ key: "watchLocale", value: function watchLocale() { // sync with vue-i18n root if (this._root && this._root.$i18n) { // locale watcher var _this = this; this.localeWatcher = this._root.$i18n.vm.$watch('locale', function (val) { _this.locale = val; }, { immediate: true }); } return null; } // string support only }, { key: "_translate", value: function _translate(message, key) { var pathRet = this._path.getPathValue(message, key); if (isArray(pathRet) || isPlainObject(pathRet)) { return pathRet; } var ret; if (isNull(pathRet) && isPlainObject(message)) { ret = message[key]; } else if (isString(pathRet)) { ret = pathRet; } else { return null; } return !isString(ret) ? ret.join('') : ret; } }, { key: "t", value: function t(key) { if (!key) return ''; var message = this.messages[this.locale]; if (message) { return this._translate(message, key); } return ''; } }]); return I18n; }(); var _app = /*#__PURE__*/_classPrivateFieldLooseKey("app"); var _isNavigable = /*#__PURE__*/_classPrivateFieldLooseKey("isNavigable"); var _options = /*#__PURE__*/_classPrivateFieldLooseKey("options"); var _walkOpts = /*#__PURE__*/_classPrivateFieldLooseKey("walkOpts"); var HCore = /*#__PURE__*/function () { function HCore(_opts) { _classCallCheck(this, HCore); Object.defineProperty(this, _walkOpts, { value: _walkOpts2 }); Object.defineProperty(this, _app, { writable: true, value: void 0 }); // enable or disable router system Object.defineProperty(this, _isNavigable, { writable: true, value: true }); // model options Object.defineProperty(this, _options, { writable: true, value: { el: '#app', beforeDestroy: function beforeDestroy() { i18ns.forEach(function (i18n) { if (i18n.localeWatcher) { delete i18n.localeWatcher; i18n = null; } }); } } }); if (!!_classPrivateFieldLooseBase(this, _app)[_app]) { return _classPrivateFieldLooseBase(this, _app)[_app]; } _classPrivateFieldLooseBase(this, _app)[_app] = this; _classPrivateFieldLooseBase(this, _walkOpts)[_walkOpts](_opts); this.Model.prototype.$hCore = _classPrivateFieldLooseBase(this, _app)[_app]; if (!this.ajax) { var fetch = new Fetch(); extend(this, { ajax: fetch, fetch: fetch }); } extend(this, { middleware: registerMiddleware }); extend(this, { on: on, once: once, off: off, emit: emit, trigger: trigger }); extend(this, { log: log, logger: logger }); extend(this, { utils: utils }); extend(this, { storage: storage }); extend(this, { navigate: navigate, go: go }); } _createClass(HCore, [{ key: "Model", get: function get() { return Model; } }, { key: "options", get: function get() { return _classPrivateFieldLooseBase(this, _options)[_options]; } }, { key: "version", get: function get() { return version; } }, { key: "initRouter", value: function initRouter(routes, opts) { if (_classPrivateFieldLooseBase(this, _isNavigable)[_isNavigable]) { var router = initRouter$1(routes, opts); extend(_classPrivateFieldLooseBase(this, _options)[_options], { router: router, template: '<router-view></router-view>' }); extend(this, { router: router }); } } }, { key: "addRoutes", value: function addRoutes(routes) { if (this.router) { this.log.debug('新增 Routes 路由记录', routes); this.router.addRoutes(routes); } else { this.initRouter(routes); } } }, { key: "start", value: function start(cb) { var _this = this; // 在应用前要确保已经完成路由系统的初始化 if (!this.router) { this.initRouter(); } // 这里最好不要有异步逻辑,在微前端框架下可能会出现问题 // 暂时不对外 beforeLaunch.final(function () { // 在微前端框架下应用生命周期被接管 if (!isMicroApp()) { _this.root = new _this.Model(_classPrivateFieldLooseBase(_this, _options)[_options]); _this.root.$nextTick(function () { trigger('app-ready', _this.root); cb && cb(_this.root); }); } else { // 启动的回调函数传递给 singleSpaVue,保持和独立运行一致的处理逻辑 trigger('app-start', cb); } }); beforeLaunch.justRun(this); } }]); return HCore; }(); function _walkOpts2(opts) { var _this2 = this; if (isPlainObject(opts)) { Object.keys(opts).forEach(function (key) { // ajaxConfig === fetchConfig if (key === 'ajaxConfig' || key === 'fetchConfig') { var fetch = new Fetch(opts[key]); extend(_this2, { ajax: fetch, fetch: fetch }); // ajax === fetch } // logLevel if (key === 'logLevel') { logger.setLevel(opts[key]); } // extra vue options if (key === 'extraModelOptions') { var staticModelKey = ['router']; Object.keys(opts[key]).filter(function (modelKey) { return !staticModelKey.includes(modelKey); }).forEach(function (modelKey) { extend(_classPrivateFieldLooseBase(_this2, _options)[_options], _defineProperty({}, modelKey, opts[key][modelKey])); // store if (modelKey === 'store') { extend(_this2, _defineProperty({}, modelKey, opts[key][modelKey])); } }); } // extra router options if (key === 'extraRouterOptions') { if (typeof opts[key]['isNavigable'] !== 'undefined') { _classPrivateFieldLooseBase(_this2, _isNavigable)[_isNavigable] = opts[key]['isNavigable']; } if (_classPrivateFieldLooseBase(_this2, _isNavigable)[_isNavigable]) { _classPrivateFieldLooseBase(_this2, _isNavigable)[_isNavigable] && setRouterOpts(opts[key]); } } }); } } /** * Find which layout the component should render. * If the component is not specified layout name, `default` is used. * Otherwise return undefined. */ function resolveLayoutName(matched) { var defaultName = 'default'; var last = matched[matched.length - 1]; if (!last) { return; } var Component = last.components.default; if (!Component) { return; } var isAsync = typeof Component === 'function' && !Component.options; if (isAsync) { return; } return getLayoutName(Component) || defaultName; } function getLayoutName(Component /* ComponentOptions | VueConstructor */) { var isCtor = typeof Component === 'function' && Component.options; var options = isCtor ? Component.options : Component; if (options.layout) { return options.layout; } else { // Retrieve super component and mixins var mixins = (options.mixins || []).slice().reverse(); var extend = options.extends || []; return mixins.concat(extend).reduce(function (acc, c) { return acc || getLayoutName(c); }, undefined); } } function loadAsyncComponents(route) { var promises = []; route.matched.forEach(function (record) { Object.keys(record.components).forEach(function (key) { var component = record.components[key]; var isAsync = typeof component === 'function' && !component.options; if (isAsync) { promises.push(component().then(function (loaded) { var isEsModule = loaded.__esModule || typeof Symbol !== 'undefined' && loaded[Symbol.toStringTag] === 'Module'; record.components[key] = isEsModule ? loaded.default : loaded; })); } }); }); return Promise.all(promises); } /*! * vue-router-layout v0.1.5 * Lightweight layout resolver for Vue Router. * https://github.com/ktsn/vue-router-layout * * @license * Copyright (c) 2018 katashin * Released under the MIT license * https://github.com/ktsn/vue-router-layout/blob/master/LICENSE */ function initRouterLayout(resolve) { Model.use(Router); Model.mixin({ inject: { $_routerLayout_notifyRouteUpdate: { default: null } }, beforeRouteUpdate: function beforeRouteUpdate(to, _from, next) { var _this = this; return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() { var notify; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: notify = _this.$_routerLayout_notifyRouteUpdate; if (!notify) { _context.next = 4; break; } _context.next = 4; return notify(to); case 4: next(); case 5: case "end": return _context.stop(); } }, _callee); }))(); } }); return Model.extend({ name: 'RouterLayout', data: function data() { return { layoutName: undefined, layouts: Object.create(null) }; }, watch: { layoutName: function layoutName(name) { if (!this.layouts[name]) { this.$set(this.layouts, name, function () { return resolve(name); }); } } }, provide: function provide() { var _this2 = this; return { $_routerLayout_notifyRouteUpdate: function () { var _$_routerLayout_notifyRouteUpdate = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(to) { return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return loadAsyncComponents(to); case 2: _this2.layoutName = resolveLayoutName(to.matched) || _this2.layoutName; case 3: case "end": return _context2.stop(); } }, _callee2); })); function $_routerLayout_notifyRouteUpdate(_x) { return _$_routerLayout_notifyRouteUpdate.apply(this, arguments); } return $_routerLayout_notifyRouteUpdate; }() }; }, /** * Somehow, app can't be rendered when navigate back under micro app framework without this hook */ mounted: function mounted() { var _this3 = this; return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() { return _regeneratorRuntime().wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: if (!_this3.$router) { _context3.next = 4; break; } _context3.next = 3; return loadAsyncComponents(_this3.$route); case 3: _this3.layoutName = resolveLayoutName(_this3.$route.matched) || _this3.layoutName; case 4: case "end": return _context3.stop(); } }, _callee3); }))(); }, beforeRouteEnter: function beforeRouteEnter(to, _from, next) { return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() { return _regeneratorRuntime().wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: _context4.next = 2; return loadAsyncComponents(to); case 2: next(function (vm) { vm.layoutName = resolveLayoutName(to.matched) || vm.layoutName; }); case 3: case "end": return _context4.stop(); } }, _callee4); }))(); }, beforeRouteUpdate: function beforeRouteUpdate(to, _from, next) { var _this4 = this; return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() { return _regeneratorRuntime().wrap(function _callee5$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: _context5.next = 2; return loadAsyncComponents(to); case 2: _this4.layoutName = resolveLayoutName(to.matched) || _this4.layoutName; next(); case 4: case "end": return _context5.stop(); } }, _callee5); }))(); }, render: function render(h) { var layout = this.layoutName && this.layouts[this.layoutName]; if (!layout) { return h(); } return h(layout, { key: this.layoutName }); } }); } var _excluded = ["meta"]; /** * 整个应用框架接口应该有且仅有三种调用方式: * * 1. 通过应用实例调用,这应该是首选的调用方式,适合在应用入口或者 vue 文件中,具体如下: * const app = hCore(); * app.ajax 或者 this.$hCore.ajax * * 2. 通过 hCore 函数对象调用,这应该可以覆盖非 vue 实例的场景,比如在一个普通的 js 文件中调用,具体如下: * hCore.ajax * * 3. 通过 @hsui/core 暴露的接口调用,这样的接口应该是有限的,目前包括: * - hCoreReference * - initFetch * - initRouter * - initRouterLayout * * 4. 通过 @@/huiExports 动态扩展 @hsui/core */ var hCoreReference; var hCoreOpts = { meta: { versions: { '@hsui/core': version, vue: Model.version, 'vue-router': Router.version } } }; function hCore(opts) { if (isPlainObject(opts)) { // 设置日志级别 logger.setLevel(opts.logLevel || 'info'); // 本地日志容量控制配置 logger.setConfig && logger.setConfig(opts.logConfig || {}); // 合并元数据信息 if (opts.meta) { for (var key in opts.meta) { if (Object.hasOwnProperty.call(opts.meta, key)) { if (key === 'versions') { hCoreOpts.meta.versions = _objectSpread(_objectSpread({}, hCoreOpts.meta.versions), opts.meta.versions); } else { hCoreOpts.meta[key] = opts.meta[key]; } } } } opts.meta; var extra = _objectWithoutProperties(opts, _excluded); hCoreOpts = _objectSpread(_objectSpread({}, hCoreOpts), extra); } window.__hCoreReference__ = hCoreReference = new HCore(hCoreOpts); log.debug('应用元数据信息', hCoreOpts.meta); log.debug('hCore 实例', hCoreReference); log.debug('hCore 构建选项', hCoreOpts); return hCoreReference; } setConfig({ logger: logger }); // 支持扩展 HCore 的原型方法 extend(hCore, { extend: function extend(opts) { // Handle case when target is a string or something (possible in deep copy) if (!isPlainObject(opts)) return false; // Extend the base object for (var name in opts) { if (Object.hasOwnProperty.call(opts, name)) { var copy = opts[name]; // Prevent Object.prototype pollution // Prevent never-ending loop if (name === '__proto__' || opts === copy) { continue; } // Recurse if we're merging plain objects or arrays if (copy && (isPlainObject(copy) || isArray(copy))) { // Handle a deep copy situation HCore.prototype[name] = deepClone(copy); // Don't bring in undefined values } else if (copy !== undefined) { HCore.prototype[name] = copy; } } } } }); extend(hCore, { middleware: registerMiddleware }); extend(hCore, { log: log, logger: logger }); extend(hCore, { navigate: navigate, go: go }); extend(hCore, { on: on, once: once, off: off, emit: emit, trigger: trigger }); extend(hCore, { storage: storage }); extend(hCore, { utils: utils }); if (hCoreOpts['ajaxConfig'] || hCoreOpts['fetchConfig']) { var fetch = new Fetch(hCoreOpts['ajaxConfig'] || hCoreOpts['fetchConfig']); extend(hCore, { ajax: fetch, fetch: fetch }); } else { var _fetch = new Fetch(); extend(hCore, { ajax: _fetch, fetch: _fetch }); } /** Legacy for bundler <= 1.3.4 */ var initRouter = function initRouter(routes, opts) { return setRouterOpts(extend(opts, { routes: routes })); }; export default hCore; export { I18n, hCoreReference, initFetch, initRouter, initRouterLayout, setRouterOpts as initRouterOptions };