import { isFunction, isNull, isNotNull, isArray, each, isWidget, extend, init, isEmpty, remove } from "./2.base"; import { OB } from "./3.ob"; import { Widget } from "./4.widget"; const moduleInjection = {}, moduleInjectionMap = { components: {}, constants: {}, stores: {}, services: {}, models: {}, providers: {}, }; export function module(xtype, cls) { if (isNotNull(moduleInjection[xtype])) { _global.console && console.error(`module: [${xtype}] 已经注册过了`); } else { if (isFunction(cls)) { cls = cls(); } for (const k in moduleInjectionMap) { if (cls[k]) { for (const key in cls[k]) { if (!moduleInjectionMap[k]) { continue; } if (!moduleInjectionMap[k][key]) { moduleInjectionMap[k][key] = []; } moduleInjectionMap[k][key].push({ version: cls[k][key], moduleId: xtype, }); } } } moduleInjection[xtype] = cls; } return () => Modules.getModule(xtype); } const constantInjection = {}; export function constant(xtype, cls) { if (isNotNull(constantInjection[xtype])) { _global.console && console.error(`constant: [${xtype}]已经注册过了`); } else { constantInjection[xtype] = cls; } return () => Constants.getConstant(xtype); } const modelInjection = {}; export function model(xtype, cls) { if (isNotNull(modelInjection[xtype])) { _global.console && console.error(`model: [${xtype}] 已经注册过了`); } else { modelInjection[xtype] = cls; } return config => Models.getModel(xtype, config); } const storeInjection = {}; export function store(xtype, cls) { if (isNotNull(storeInjection[xtype])) { _global.console && console.error(`store: [${xtype}] 已经注册过了`); } else { storeInjection[xtype] = cls; } return config => Stores.getStore(xtype, config); } const serviceInjection = {}; export function service(xtype, cls) { if ((serviceInjection[xtype])) { _global.console && console.error(`service: [${xtype}] 已经注册过了`); } serviceInjection[xtype] = cls; return config => Services.getService(xtype, config); } const providerInjection = {}; export function provider(xtype, cls) { if ((providerInjection[xtype])) { _global.console && console.error(`provider: [${xtype}] 已经注册过了`); } else { providerInjection[xtype] = cls; } return config => Providers.getProvider(xtype, config); } const configFunctions = OB.configFunctions = {}; const runConfigFunction = (type, configFn) => { if (!type || !configFunctions[type]) { return false; } let queue = []; if (configFn) { queue = configFunctions[type].filter(conf => conf.fn === configFn); configFunctions[type] = configFunctions[type].filter(conf => conf.fn !== configFn); } else { queue = configFunctions[type]; delete configFunctions[type]; } const dependencies = Providers.getProvider("bi.provider.system").getDependencies(); const modules = moduleInjectionMap.components[type] || moduleInjectionMap.constants[type] || moduleInjectionMap.services[type] || moduleInjectionMap.stores[type] || moduleInjectionMap.models[type] || moduleInjectionMap.providers[type]; for (let i = 0; i < queue.length; i++) { const conf = queue[i]; const version = conf.opt.version; const fn = conf.fn; if (modules && version) { let findVersion = false; let module; for (let j = 0; j < modules.length; j++) { module = modules[j]; if (module && dependencies[module.moduleId] && module.version === version) { const minVersion = dependencies[module.moduleId].minVersion, maxVersion = dependencies[module.moduleId].maxVersion; if (minVersion && (moduleInjection[module.moduleId].version || version) < minVersion) { findVersion = true; break; } if (maxVersion && (moduleInjection[module.moduleId].version || version) > maxVersion) { findVersion = true; break; } } } if (findVersion === true) { _global.console && console.error(`moduleId: [${module.moduleId}] 接口: [${type}] 接口版本: [${version}] 已过期,版本要求为:`, dependencies[module.moduleId], "=>", moduleInjection[module.moduleId]); continue; } } if (constantInjection[type]) { constantInjection[type] = fn(constantInjection[type]); continue; } if (providerInjection[type]) { if (!providers[type]) { providers[type] = new providerInjection[type](); } if (providerInstance[type]) { delete providerInstance[type]; } fn(providers[type]); continue; } BI.Plugin.configWidget(type, fn, conf.opt); } }; export function config(type, configFn, opt) { if (isFunction(type)) { opt = configFn; configFn = type; type = "bi.provider.system"; } opt = opt || {}; // 系统配置直接执行 if ("bi.provider.system" === type) { if (!providers[type]) { providers[type] = new providerInjection[type](); } // 如果config被重新配置的话,需要删除掉之前的实例 if (providerInstance[type]) { delete providerInstance[type]; } return configFn(providers[type]); } if (!configFunctions[type]) { configFunctions[type] = []; } configFunctions[type].push({ fn: configFn, opt, }); if (opt.immediately) { return runConfigFunction(type, configFn); } } export function getReference(type, fn) { return BI.Plugin.registerObject(type, fn); } const actions = {}; const globalAction = []; export function action(type, actionFn) { if (isFunction(type)) { globalAction.push(type); return () => { remove(globalAction, idx => globalAction.indexOf(actionFn) === idx); }; } if (!actions[type]) { actions[type] = []; } actions[type].push(actionFn); return () => { remove(actions[type], idx => actions[type].indexOf(actionFn) === idx); if (actions[type].length === 0) { delete actions[type]; } }; } const points = {}; export function point(type, action, pointFn, after) { if (!points[type]) { points[type] = {}; } if (!points[type][action]) { points[type][action] = {}; } if (!points[type][action][after ? "after" : "before"]) { points[type][action][after ? "after" : "before"] = []; } points[type][action][after ? "after" : "before"].push(pointFn); } export const Modules = { getModule (type) { if (!moduleInjection[type]) { _global.console && console.error(`module: [${type}] 未定义`); } return moduleInjection[type]; }, getAllModules () { return moduleInjection; }, }; export const Constants = { getConstant (type) { if (isNull(constantInjection[type])) { _global.console && console.error(`constant: [${type}] 未定义`); } runConfigFunction(type); return isFunction(constantInjection[type]) ? constantInjection[type]() : constantInjection[type]; }, }; function callPoint(inst, types) { types = isArray(types) ? types : [types]; each(types, (idx, type) => { if (points[type]) { for (const action in points[type]) { const bfns = points[type][action].before; if (bfns) { BI.aspect.before(inst, action, (function (bfns) { return function () { for (let i = 0, len = bfns.length; i < len; i++) { try { bfns[i].apply(inst, arguments); } catch (e) { _global.console && console.error(e); } } }; }(bfns))); } const afns = points[type][action].after; if (afns) { BI.aspect.after(inst, action, (function (afns) { return function () { for (let i = 0, len = afns.length; i < len; i++) { try { afns[i].apply(inst, arguments); } catch (e) { _global.console && console.error(e); } } }; }(afns))); } } } }); } export const Models = { getModel (type, config) { if (!modelInjection[type]) { _global.console && console.error(`model: [${type}] 未定义`); } runConfigFunction(type); const inst = new modelInjection[type](config); inst._constructor && inst._constructor(config); inst.mixins && callPoint(inst, inst.mixins); callPoint(inst, type); return inst; }, }; const stores = {}; export const Stores = { getStore (type, config) { if (!storeInjection[type]) { _global.console && console.error(`store: [${type}] 未定义`); } if (stores[type]) { return stores[type]; } const inst = stores[type] = new storeInjection[type](config); inst._constructor && inst._constructor(config, () => { delete stores[type]; }); callPoint(inst, type); return inst; }, }; const services = {}; export const Services = { getService: (type, config) => { if (!serviceInjection[type]) { _global.console && console.error(`service: [${type}] 未定义`); } if (services[type]) { return services[type]; } services[type] = new serviceInjection[type](config); callPoint(services[type], type); return services[type]; }, }; const providers = {}, providerInstance = {}; export const Providers = { getProvider: (type, config) => { if (!providerInjection[type]) { _global.console && console.error(`provider: [${type}] 未定义`); } runConfigFunction(type); if (!providers[type]) { providers[type] = new providerInjection[type](); } if (!providerInstance[type] && providers[type].$get) { providerInstance[type] = new (providers[type].$get())(config); } return providerInstance[type]; }, }; export const Actions = { runAction (type, event, config) { each(actions[type], (i, act) => { try { act(event, config); } catch (e) { _global.console && console.error(e); } }); }, runGlobalAction () { const args = [].slice.call(arguments); each(globalAction, (i, act) => { try { act(...args); } catch (e) { _global.console && console.error(e); } }); }, }; const kv = {}; export function shortcut(xtype, cls) { if (isNotNull(kv[xtype])) { _global.console && console.error(`组件: [${xtype}] 已经注册过了`); } if (cls) { cls.xtype = xtype; } kv[xtype] = cls; } // 根据配置属性生成widget const createRealWidget = (config, context, lazy) => { const Cls = isFunction(config.type) ? config.type : kv[config.type]; if (!Cls) { throw new Error(`组件: [${config.type}] 未定义`); } let pushed = false; const widget = new Cls(); widget._context = Widget.context || context; if (!Widget.context && context) { pushed = true; Widget.pushContext(context); } callPoint(widget, config.type); widget._initProps(config); widget._initRoot(); widget._constructed(); // if (!lazy || config.element || config.root) { widget._lazyConstructor(); // } pushed && Widget.popContext(); return widget; }; export function createWidget(item, options, context, lazy) { item || (item = {}); if (isWidget(options)) { context = options; options = {}; } else { options || (options = {}); } let el, w; if (item.type || options.type) { el = extend({}, options, item); } else if (item.el && (item.el.type || options.type)) { el = extend({}, options, item.el); } let elType; if (el) { elType = (el.type && el.type.xtype) || el.type; runConfigFunction(elType); } // 先把准备环境准备好 init(); if (isEmpty(item) && isEmpty(options)) { return createWidget({ type: "bi.layout", }); } if (isWidget(item)) { return item; } if (el) { w = BI.Plugin.getWidget(elType, el); const wType = (w.type && w.type.xtype) || w.type; if (wType === elType) { if (BI.Plugin.hasObject(elType)) { if (!w.listeners || isArray(w.listeners)) { w.listeners = (w.listeners || []).concat([{ eventName: BI.Events.MOUNT, action: () => { BI.Plugin.getObject(elType, this); }, }]); } else { w.listeners[BI.Events.MOUNT] = [ () => { BI.Plugin.getObject(elType, this); } ].concat(w.listeners[BI.Events.MOUNT] || []); } } return createRealWidget(w, context, lazy); } return createWidget(w, options, context, lazy); } if (isWidget(item.el)) { return item.el; } throw new Error("组件:无法根据item创建组件", item); } export function _lazyCreateWidget (item, options, context) { return createWidget(item, options, context, true); } export function createElement() { const widget = createWidget.apply(this, arguments); return widget.element; } export function getResource(type, config) { if (isNotNull(constantInjection[type])) { return Constants.getConstant(type); } if (modelInjection[type]) { return Models.getModel(type, config); } if (storeInjection[type]) { return Stores.getStore(type, config); } if (serviceInjection[type]) { return Services.getService(type, config); } if (providerInjection[type]) { return Providers.getProvider(type, config); } throw new Error(`未知类型: [${type}] 未定义`); }