diff --git a/src/tis/index.js b/src/tis/index.js index c076c21..d88d489 100644 --- a/src/tis/index.js +++ b/src/tis/index.js @@ -14,9 +14,21 @@ import screenshotPlugin from "./plugins/screenshotPlugin"; import qtPlugin from "./plugins/qtPlugin"; import workerpool from "workerpool"; import { registerApps } from "./utils/scriptsLoader/index"; -import { getRecvMsg, updateRecvMsg, activeTime, getOMesplug, setManageMode } from "../api/api"; -import { formatDBToMsg, formatMsgToDB, formatSysTime, currentOS } from "./utils/util"; +import { + getRecvMsg, + updateRecvMsg, + activeTime, + getOMesplug, + setManageMode +} from "../api/api"; +import { + formatDBToMsg, + formatMsgToDB, + formatSysTime, + currentOS +} from "./utils/util"; import router from "./router/index"; +import { createBus } from "./utils/bus"; const devLib = process.env.VUE_APP_DEVLIB === "dev"; const devMode = process.env.NODE_ENV === "development" || devLib; @@ -29,57 +41,56 @@ const APPS_SLEEPING_LEN = 5; // Vue.use(ElementUI); Vue.config.productionTip = false; Vue.prototype.$Notifition = Notifition; //可以在任意地方调用, -Vue.prototype.$EsDataMsg = function() { -}; +Vue.prototype.$EsDataMsg = function() {}; const bus = new Vue({ data: { devMode: devMode, //当前运行环境是什么 schema: "", //当前运行项目是什么项目 - alias: {},//避免硬编码id,可配置 - userInfo: {},//用户信息 - openByKt: false,//是否从kt打开 - resource: {},//组件静态资源 - allComponents: [],//所有的组件 + alias: {}, //避免硬编码id,可配置 + userInfo: {}, //用户信息 + openByKt: false, //是否从kt打开 + resource: {}, //组件静态资源 + allComponents: [], //所有的组件 whitelist: [], // 白名单应用id globalState: {}, // 全局变量 appsSleeping: [], // 休眠应用队列 最长暂时为5 apps: [], // 界面显示的所有应用 widgets: [], // 界面显示的所有浮窗 - allApps: [],//所有应用 - allWidgets: [],//所有浮窗 - location: {},//设置经纬度 + allApps: [], //所有应用 + allWidgets: [], //所有浮窗 + location: {}, //设置经纬度 deviceType: currentOS() || "pc", visibleWidgetPanel: false, // 选择浮窗的视图 visibleAppsPanel: false, // 选择浮窗的视图 widgetListViewVisible: false, // 展示所有浮窗的列表视图 - visibleWidgetSysSetting: false,// 展示设置浮窗 + visibleWidgetSysSetting: false, // 展示设置浮窗 controlPanelPadVisible: false, - visibleWidgetLogin: false,//登录窗口 + visibleWidgetLogin: false, //登录窗口 visibleHistoricalNews: false, //是否显示历史消息 visibleNotificationWhole: false, //是否显示右侧全部消息 visibleSearchBox: false, // 搜索框 visibleDialogBox: false, visibleLookAtMsgBox: false, visibleVoiceBox: false, - msgBoxText: "",//查看窗口的文本内容 + msgBoxText: "", //查看窗口的文本内容 isFullScreen: false, messageItem: {}, // 消息面板的信息逻辑 messageBoxList: [], // 收件箱数据面板数据存储,初始化时请求接口, warAndAstrTime: { - astrTime: "----/--/-- --:--:--",//天文时间 - warTime: "----/--/-- --:--:--"//作战时间 + astrTime: "----/--/-- --:--:--", //天文时间 + warTime: "----/--/-- --:--:--" //作战时间 }, footerTimer: null, showFooter: true, alertSettingPageVisible: false, - locationArtificial: false,// 人工定位弹框 - visibleMessageBox: false,//消息 - visibleToListMail: false,//通知校时 - visiblediwd: false,//事件通知 + locationArtificial: false, // 人工定位弹框 + visibleMessageBox: false, //消息 + visibleToListMail: false, //通知校时 + visiblediwd: false, //事件通知 headerVisible: true, theme: document.documentElement.getAttribute("data-theme") || "default", - showMoreContent: false, //底部点击展示更多 - menuVisible: false, // 菜单编辑弹框 + showMoreContent: false, //底部点击展示更多 + menuVisible: false, // 菜单编辑弹框 // pad 应用界面 applicationInterface: { visible: false, @@ -90,16 +101,17 @@ const bus = new Vue({ searchBoxPadVisible: false, // pad搜索组件 SettingSysPadVisible: false, // pad消息设置 messageCenterVisible: false, // pad消息中心 - txlVisiable: false,//pad通讯录 + txlVisiable: false, //pad通讯录 registerVisible: {}, - notificationConfig: { //消息设置 + notificationConfig: { + //消息设置 voiceHint: "无", precise: "模糊", rightHint: true, disturb: false, startTime: "", endTime: "" - },//消息通知的设置 + }, //消息通知的设置 // 消息中心数据 unReadMessageList: [ { @@ -112,7 +124,7 @@ const bus = new Vue({ time: 1619827200, title: "态势感知", - reply: 0 // 是否有回复按钮 + reply: 0 // 是否有回复按钮 }, { id: 1, @@ -123,7 +135,7 @@ const bus = new Vue({ compnent: 1, time: 1622505600000, title: "态势感知", - reply: 1 // 是否有回复按钮 + reply: 1 // 是否有回复按钮 }, { id: 11, @@ -134,7 +146,7 @@ const bus = new Vue({ compnent: 1, time: 1622505600000, title: "态势感知", - reply: 1 // 是否有回复按钮 + reply: 1 // 是否有回复按钮 }, { id: 12, @@ -145,7 +157,7 @@ const bus = new Vue({ compnent: 1, time: 1622505600000, title: "态势感知", - reply: 1 // 是否有回复按钮 + reply: 1 // 是否有回复按钮 }, { id: 13, @@ -156,7 +168,7 @@ const bus = new Vue({ compnent: 1, time: 1622505600000, title: "态势感知", - reply: 1 // 是否有回复按钮 + reply: 1 // 是否有回复按钮 }, { id: 14, @@ -167,7 +179,7 @@ const bus = new Vue({ compnent: 1, time: 1622505600000, title: "态势感知", - reply: 1 // 是否有回复按钮 + reply: 1 // 是否有回复按钮 }, { id: 2, @@ -213,7 +225,7 @@ const bus = new Vue({ appName: "taishiganzhi", text: "态势感知态势感知态势感知态势感知态势感感", type: "态势感知", - level: 3,// 3警报,2告警 1生化 + level: 3, // 3警报,2告警 1生化 compnent: 1, time: "10分钟", title: "态势感知", @@ -224,7 +236,7 @@ const bus = new Vue({ appName: "taishiganzhi", text: "态势感知态势感知态势感知态势感知态势感感", type: "态势感知", - level: 3,// 3警报,2告警 1生化 + level: 3, // 3警报,2告警 1生化 compnent: 1, time: "10分钟", title: "态势感知", @@ -235,7 +247,7 @@ const bus = new Vue({ appName: "taishiganzhi", text: "态势感知态势感知态势感知态势感知态势感感", type: "态势感知", - level: 3,// 3警报,2告警 1生化 + level: 3, // 3警报,2告警 1生化 compnent: 1, time: "10分钟", title: "态势感知", @@ -318,30 +330,36 @@ async function getApp(appId) { async function loadApp(app) { const onMessage = { ref: null }; const onMenu = { ref: null }; - const instance = loadMicroApp({ - name: app.id, - container: "#" + app.containerId, - entry: app.entry, - // activeRule:"/app_demo", - props: { - tis: { - ...tis, - ...createEventBus(app.id), - appId: app.id, - entry: app.entry, - components: app.components, - asserts: app.asserts, - }, - onMessage, - onMenu - } - }, { - sandbox: { - strictStyleIsolation: false, - experimentalStyleIsolation: true + const bus = createBus(app.id); + + const instance = loadMicroApp( + { + name: app.id, + container: "#" + app.containerId, + entry: app.entry, + // activeRule:"/app_demo", + props: { + tis: { + ...tis, + ...createEventBus(app.id), + appId: app.id, + entry: app.entry, + components: app.components, + asserts: app.asserts + }, + bus, + onMessage, + onMenu + } + }, + { + sandbox: { + strictStyleIsolation: false, + experimentalStyleIsolation: true + } } - }); - await instance.bootstrapPromise.catch((err) => { + ); + await instance.bootstrapPromise.catch(err => { console.error(`boostrap: [${app.name} ${app.id}] 出错`, err); throw err; }); @@ -419,7 +437,10 @@ const tis = { return new Promise((resolve, reject) => { el.onload = el.onreadystatechange = function() { let readyState = el.readyState; - if (typeof readyState === "undefined" || /^(loaded|complete)$/.test(readyState)) { + if ( + typeof readyState === "undefined" || + /^(loaded|complete)$/.test(readyState) + ) { resolve(); // 卸载事件和断开dom引用,避免内存泄漏 el.onload = el.onerror = el.onreadystatechange = null; @@ -427,7 +448,10 @@ const tis = { }; el.onerror = function() { let readyState = el.readyState; - if (typeof readyState === "undefined" || /^(loaded|complete)$/.test(readyState)) { + if ( + typeof readyState === "undefined" || + /^(loaded|complete)$/.test(readyState) + ) { console.log("load js resources failed"); reject({ error: "load js resources failed" }); // 卸载事件和断开dom引用,避免内存泄漏 @@ -439,23 +463,28 @@ const tis = { // 加载第三方耗时js eg:地图 loadTimeConsumingResources() { this.onLoaded(document).then(() => { - console.log("<<<<=========基础资源加载完毕,第三方资源加载ing===========>>>>>"); + console.log( + "<<<<=========基础资源加载完毕,第三方资源加载ing===========>>>>>" + ); // 白名单列表中的launcher不加载地图等耗时资源 const whiteList = ["manager", "appStore", "monitor"]; - axios.get(`${baseURL}manifest/library.json`) - .then(async res => { - //是否需要再度延迟,防止用户操作登录下拉框时发生卡顿?可以先观察,未来再处理 - const data = res.data; - const resources = Object.keys(data).filter(d => new RegExp(bus.deviceType, "gi") - .test(data[d].target) && !whiteList.includes(window.currentLauncher)); - //按照顺序加载 - for (let i = 0; i < resources.length; i++) { - let rs = resources[i]; - await registerApps(data[rs], baseURL) - .then(() => console.log(`<<<<=========${rs}资源加载完毕===========>>>>>`)); - } - console.log("<<<<=========第三方资源加载完毕===========>>>>>"); - }); + axios.get(`${baseURL}manifest/library.json`).then(async res => { + //是否需要再度延迟,防止用户操作登录下拉框时发生卡顿?可以先观察,未来再处理 + const data = res.data; + const resources = Object.keys(data).filter( + d => + new RegExp(bus.deviceType, "gi").test(data[d].target) && + !whiteList.includes(window.currentLauncher) + ); + //按照顺序加载 + for (let i = 0; i < resources.length; i++) { + let rs = resources[i]; + await registerApps(data[rs], baseURL).then(() => + console.log(`<<<<=========${rs}资源加载完毕===========>>>>>`) + ); + } + console.log("<<<<=========第三方资源加载完毕===========>>>>>"); + }); }); }, //获取天文、作战时间 @@ -475,21 +504,21 @@ const tis = { }, //登出框架,清空用户信息, 清空界面信息 loginOut() { - bus.userInfo = {};//用户信息 - bus.openByKt = false;//是否从kt打开 + bus.userInfo = {}; //用户信息 + bus.openByKt = false; //是否从kt打开 bus.whitelist = []; // 白名单应用id bus.globalState = {}; // 全局变量 bus.appsSleeping = []; // 休眠应用队列 最长暂时为5 - bus.apps = [];// 界面显示的所有应用 + bus.apps = []; // 界面显示的所有应用 bus.widgets = []; // 界面显示的所有浮窗 - bus.visibleWidgetPanel = false;// 选择浮窗的视图 + bus.visibleWidgetPanel = false; // 选择浮窗的视图 bus.visibleAppsPanel = false; // 选择浮窗的视图 bus.widgetListViewVisible = false; // 展示所有浮窗的列表视图 - bus.visibleWidgetSysSetting = false;// 展示设置浮窗 - bus.visibleWidgetLogin = false;//登录窗口 + bus.visibleWidgetSysSetting = false; // 展示设置浮窗 + bus.visibleWidgetLogin = false; //登录窗口 bus.visibleHistoricalNews = false; //是否显示历史消息 bus.visibleNotificationWhole = false; //是否显示右侧全部消息 - bus.visibleSearchBox = false;// 搜索框 + bus.visibleSearchBox = false; // 搜索框 bus.visibleDialogBox = false; bus.visibleLookAtMsgBox = false; bus.messageItem = {}; // 消息面板的信息逻辑 @@ -500,8 +529,7 @@ const tis = { localStorage.removeItem("USER_INFO"); localStorage.removeItem("SYS_MODE"); this.openWidgetLoginPanel(); - setManageMode({ mode: "0" }).then(res => { - }); + setManageMode({ mode: "0" }).then(() => {}); }, // 底部栏显示隐藏 setFooterShow() { @@ -514,7 +542,10 @@ const tis = { setNotificationConfig(config) { bus.notificationConfig = config; //存入localStorage - window.localStorage.setItem("MESSAGE_CONFIG", JSON.stringify(bus.notificationConfig)); + window.localStorage.setItem( + "MESSAGE_CONFIG", + JSON.stringify(bus.notificationConfig) + ); }, // 获取消息通知配置 getNotificationConfig() { @@ -546,9 +577,9 @@ const tis = { // return {}; // } return bus.userInfo; - }, //控制平板菜单开关 + // eslint-disable-next-line no-unused-vars showControlPanel(name) { bus.registerVisible.alarmMainWineowVisible = false; bus.alarmMainWineowVisible = false; @@ -557,17 +588,13 @@ const tis = { // name: name // }; - bus.controlPanelPadVisible = !bus - .controlPanelPadVisible; - bus.registerVisible.controlPanelPadVisible = !bus - .controlPanelPadVisible; + bus.controlPanelPadVisible = !bus.controlPanelPadVisible; + bus.registerVisible.controlPanelPadVisible = !bus.controlPanelPadVisible; }, switchControlPadVisible() { //关闭菜单 - bus.controlPanelPadVisible = !bus - .controlPanelPadVisible; - bus.registerVisible.controlPanelPadVisible = !bus - .controlPanelPadVisible; + bus.controlPanelPadVisible = !bus.controlPanelPadVisible; + bus.registerVisible.controlPanelPadVisible = !bus.controlPanelPadVisible; }, //获取是否需要登录的标识 openFullScreenAppId() { @@ -598,7 +625,7 @@ const tis = { containerId: "app_" + app.id, opened: false, asserts: bus.resource, - privateBus: {}//私有bus + privateBus: {} //私有bus }; }); bus.apps = [...bus.apps, ...newApss]; @@ -620,7 +647,7 @@ const tis = { // return found || defaultApp || apps[0] }, getRunningApps() { - return bus.apps.filter((a) => { + return bus.apps.filter(a => { return a.instance && a.instance.getStatus() === "MOUNTED"; }); }, @@ -674,9 +701,13 @@ const tis = { if (a !== app && a.opened && a.instance) { a.opened = false; // 休眠队列和白名单里的进行隐藏不卸载 - if (bus.whitelist.includes(a.id) || bus.appsSleeping.indexOf(a.id) !== -1) { + if ( + bus.whitelist.includes(a.id) || + bus.appsSleeping.indexOf(a.id) !== -1 + ) { a.instance.hide(); - } else { // 非白名单的进行卸载 + } else { + // 非白名单的进行卸载 a.instance.unmount(); } } @@ -708,7 +739,10 @@ const tis = { console.log("process.env.VUE_APP_DEVLIB", process.env.VUE_APP_DEVLIB); const domain = devLib ? "http://localhost:9902/" : ""; const base = devMode ? "/" : "/TIS_LIB/"; - styleLink.setAttribute("href", `${domain}${base}tis-ui/theme-chalk/index${dir}.css`); + styleLink.setAttribute( + "href", + `${domain}${base}tis-ui/theme-chalk/index${dir}.css` + ); // 设置localstorage localStorage.setItem("TIS_DESIGN_THEME", theme); }, @@ -731,7 +765,8 @@ const tis = { // 休眠队列和白名单里的进行隐藏不卸载 if (bus.whitelist.includes(a.id) || bus.appsSleeping.indexOf(a.id) !== -1) { a.instance.hide(); - } else { // 非白名单的进行卸载 + } else { + // 非白名单的进行卸载 a.instance.unmount(); } @@ -844,7 +879,6 @@ const tis = { bus.visiblediwd = false; }, - //人工定位弹框 isVisiblelocationArtificial() { return bus.locationArtificial; @@ -938,11 +972,14 @@ const tis = { }, delMessage(id) { //将此消息状态更新为已读,只有存在15位uuid的才执行数据库的更新 - const readedMsg = bus.unReadMessageList.filter(v => v.id == id && id.length > 15).map(m => { - m.isRead = "1"; - return formatMsgToDB(m); - }); - if (readedMsg.length > 0) updateRecvMsg({ Content: readedMsg }).catch(err => console.error(err)); + const readedMsg = bus.unReadMessageList + .filter(v => v.id == id && id.length > 15) + .map(m => { + m.isRead = "1"; + return formatMsgToDB(m); + }); + if (readedMsg.length > 0) + updateRecvMsg({ Content: readedMsg }).catch(err => console.error(err)); bus.unReadMessageList = bus.unReadMessageList.filter(v => v.id !== id); }, // 清空消息 @@ -954,14 +991,13 @@ const tis = { //展现右上角的逻辑。 }, addWidgets(widgets) { - const newWidgets = widgets.map((w) => { + const newWidgets = widgets.map(w => { return { ...w, containerId: "widget_" + w.id, opened: false, asserts: bus.resource - } - ; + }; }); bus.widgets = [...bus.widgets, ...newWidgets]; }, @@ -975,9 +1011,12 @@ const tis = { }, //增加所有组件 addComponents(components) { - bus.allComponents = [...bus.allComponents, ...components.map(c => { - return { ...c, loaded: false }; - })]; + bus.allComponents = [ + ...bus.allComponents, + ...components.map(c => { + return { ...c, loaded: false }; + }) + ]; }, getAllComponents() { return bus.allComponents; @@ -1012,15 +1051,18 @@ const tis = { return bus.widgets.length; }, getOpenedWidgetIds() { - return bus.widgets.filter(w => w.opened).map((w) => w.id); + return bus.widgets.filter(w => w.opened).map(w => w.id); }, _saveOpenedWidgets() { - sessionStorage.setItem("openedWidgets", JSON.stringify(this.getOpenedWidgetIds())); + sessionStorage.setItem( + "openedWidgets", + JSON.stringify(this.getOpenedWidgetIds()) + ); }, restoreWidgetsFromSession() { try { const ids = sessionStorage.getItem("openedWidgets") || JSON.stringify([]); - JSON.parse(ids).forEach((widgetId) => { + JSON.parse(ids).forEach(widgetId => { this.openWidget(widgetId); }); } catch (_) { @@ -1074,9 +1116,11 @@ const tis = { } }); //应用自定义配置的compoonents也得返给应用,不能全部依赖管理员配置 - app.components = defaultApp && defaultApp.components ? [...appComps, ...defaultApp.components] : appComps; + app.components = + defaultApp && defaultApp.components + ? [...appComps, ...defaultApp.components] + : appComps; //返回给应用所有的htmlresource资源目录,后端暂时无法配置组件。这个以后可以再改。 - }); custom_widgets = widgets.map(widget => { let widgetComps = []; @@ -1091,12 +1135,14 @@ const tis = { } }); //合并默认组件配置和管理员的配置 - widget.components = defaultwg && defaultwg.components ? [...defaultwg.components, ...widgetComps] : widgetComps; + widget.components = + defaultwg && defaultwg.components + ? [...defaultwg.components, ...widgetComps] + : widgetComps; //返回给应用所有的htmlresource资源目录,后端暂时无法配置组件。这个以后可以再改。 return { ...widget, ...defaultwg }; }); - if (!test) { //过滤掉kt,兼容 this.addApps(apps.filter(a => a.id !== "TIS_RJJHJCKJ_WEB")); @@ -1104,11 +1150,9 @@ const tis = { //TODO 打开 this.openDefaultApp(); this.restoreWidgetsFromSession(); - this._initUnReadMessageList();//初始化未读消息 + this._initUnReadMessageList(); //初始化未读消息 this.initConfig(); - } - }, getSchema() { return bus.schema; @@ -1117,12 +1161,14 @@ const tis = { initOMFrameView(mode = 0) { // 清空apps再操作 bus.apps = []; - getOMesplug(mode).then(r => { - const { apps = [] } = r; - this.addApps(apps); - this.initConfig(); - this.openDefaultApp(); - }).catch(e => console.error(e)); + getOMesplug(mode) + .then(r => { + const { apps = [] } = r; + this.addApps(apps); + this.initConfig(); + this.openDefaultApp(); + }) + .catch(e => console.error(e)); }, //默认的初始化框架界面函数 initFrameViewByDefault(options = {}) { @@ -1149,13 +1195,13 @@ const tis = { //初始化config配置 initConfig() { const msg_conf = window.localStorage.getItem("MESSAGE_CONFIG"); - msg_conf ? bus.notificationConfig = JSON.parse(msg_conf) : ""; + msg_conf ? (bus.notificationConfig = JSON.parse(msg_conf)) : ""; }, //初始化框架内apps widgets components 等全集 initAlldata(config = {}) { const { apps = [], widgets = [], components = [] } = config; - this.addAllApps(apps);//app的全集,用户登录后拿到其中的某几个app构成的子集 - this.addAllWidgets(widgets);//widgets,用户登录后拿到其中的某几个widgets构成的子集 + this.addAllApps(apps); //app的全集,用户登录后拿到其中的某几个app构成的子集 + this.addAllWidgets(widgets); //widgets,用户登录后拿到其中的某几个widgets构成的子集 this.addComponents(components); this.openAppByIdImmediately(); }, @@ -1205,10 +1251,11 @@ const tis = { getRecvMsg(params).then(d => { const { Content = [], TotalNum = 0 } = d; if (TotalNum > 0) { - const unReadMsgs = Content.filter(c => c.isRead == 0).map(c => formatDBToMsg(c)); + const unReadMsgs = Content.filter(c => c.isRead == 0).map(c => + formatDBToMsg(c) + ); unReadMsgs.forEach(ur => this.addMessageData(ur)); } - }); }, //获取alias中别名对应的真名 @@ -1217,8 +1264,12 @@ const tis = { }, // 加载组件的函数,目前应用的加载组件函数是否需要封装到tis中? async _loadComponent(component) { - let curBaseUrl = process.env.NODE_ENV === "development" ? `http://${document.domain}:8080` : `http://${document.domain}:3806`; - const comp = bus.allComponents.find(arg => arg.component === component) || {}; + let curBaseUrl = + process.env.NODE_ENV === "development" + ? `http://${document.domain}:8080` + : `http://${document.domain}:3806`; + const comp = + bus.allComponents.find(arg => arg.component === component) || {}; let assets = null; let dependencies = []; try { @@ -1230,9 +1281,13 @@ const tis = { } console.log( `框架开始加载${component}组件资源...`, - `所有组件信息`, bus.allComponents, - `匹配到的组件信息`, comp, - "该组件静态资源", assets); + `所有组件信息`, + bus.allComponents, + `匹配到的组件信息`, + comp, + "该组件静态资源", + assets + ); //等待依赖下载完毕 for (const refer of dependencies) { let reference = bus.resource[refer] || null; @@ -1241,33 +1296,36 @@ const tis = { return new Promise((resolve, reject) => { //加载组件资源 console.log("开始加载组件", "组件:" + component, assets); - registerApps(assets, curBaseUrl).then(() => { - let startTime = new Date().getTime(); - const looper = setInterval(() => { - if (Vue.component(`${component}`)) { - resolve(comp); - clearInterval(looper); - } else { - let nowTime = new Date().getTime(); - if (nowTime - startTime > 2000) { - if (!assets) { - reject(`[loading error:${component}]:组件资源加载失败`); - } else { - reject(`[loading error:${component}]:loading component timed out`); - } + registerApps(assets, curBaseUrl) + .then(() => { + let startTime = new Date().getTime(); + const looper = setInterval(() => { + if (Vue.component(`${component}`)) { + resolve(comp); clearInterval(looper); + } else { + let nowTime = new Date().getTime(); + if (nowTime - startTime > 2000) { + if (!assets) { + reject(`[loading error:${component}]:组件资源加载失败`); + } else { + reject( + `[loading error:${component}]:loading component timed out` + ); + } + clearInterval(looper); + } } + }, 300); + }) + .catch(err => { + if (!assets) { + reject(`[loading error:${component}]:组件资源加载失败`); + } else { + reject(`[loading error:${component}]:${err}`); } - }, 300); - }).catch(err => { - if (!assets) { - reject(`[loading error:${component}]:组件资源加载失败`); - } else { - reject(`[loading error:${component}]:${err}`); - } - }); + }); }); - }, worker, @@ -1281,30 +1339,42 @@ const tis = { } }, hiddenAllVisible() { - Object.keys(bus.registerVisible).map((key) => { + Object.keys(bus.registerVisible).map(key => { bus[key] = false; }); bus.applicationInterface.visible = false; }, - initAppBusById(bus,AppId){ - let app = this.getApps().find(app=>app.id === AppId ); + initAppBusById(bus, AppId) { + let app = this.getApps().find(app => app.id === AppId); app.privateBus = bus; - }, - + } }; hotkeysPlugin(tis); voicePlugin(tis); qtPlugin(tis); screenshotPlugin(tis); -Vue.prototype.$tis = new Proxy({ loadApp }, { - get: function(o, k) { - return o[k] || tis[k]; +Vue.prototype.$tis = new Proxy( + { loadApp }, + { + get: function(o, k) { + return o[k] || tis[k]; + } } -}); +); export function setup(options = {}) { - const { layouts = {}, whitelist = [], schema, wsUrl, apps = [], components = [], hotkeys, alias = {}, theme = "default" } = options; + const { + layouts = {}, + whitelist = [], + schema, + wsUrl, + apps = [], + components = [], + hotkeys, + alias = {}, + theme = "default" + } = options; tis.layouts = layouts; bus.whitelist = [...whitelist]; bus.alias = alias; @@ -1340,30 +1410,32 @@ export function setup(options = {}) { tis.bindPlatformHotkeys(hotkeys); //挂载Vue、tis - window.esapp = Object.assign(!window.esapp ? window.esapp = {} : window.esapp, { - Vue: Vue, - vue: new Vue({ - store, - router, - render: h => h(App) - }).$mount("#app"), - add_path: function(route, name, obj) { - store.registerModule(name, obj); - }, - add_store: function(module, data) { - store.commit(module, data); - }, - Vuex: Vuex, - VueRouter: {}, - registerAppAsync: function(source) { - return source; - }, - tis: tis, //新框架核心对象, - flag: tis // - }); - + window.esapp = Object.assign( + !window.esapp ? (window.esapp = {}) : window.esapp, + { + Vue: Vue, + vue: new Vue({ + store, + router, + render: h => h(App) + }).$mount("#app"), + add_path: function(route, name, obj) { + store.registerModule(name, obj); + }, + add_store: function(module, data) { + store.commit(module, data); + }, + Vuex: Vuex, + VueRouter: {}, + registerAppAsync: function(source) { + return source; + }, + tis: tis, //新框架核心对象, + flag: tis // + } + ); return tis; } -export default tis; \ No newline at end of file +export default tis; diff --git a/src/tis/utils/bus.js b/src/tis/utils/bus.js new file mode 100644 index 0000000..ee3831c --- /dev/null +++ b/src/tis/utils/bus.js @@ -0,0 +1,280 @@ +import Vue from "vue"; +import EE from "eventemitter3"; +import axios from "axios"; +import { registerApps } from "./scriptsLoader/index"; + +// temp +let curBaseUrl = ""; +const dev = process.env.NODE_ENV === "development"; +const baseUrl = dev ? process.env.BASE_URL : ""; + +// 数据机制,考虑vuex来实现 +class Bus extends EE { + components = []; // components + asserts = {}; + deviceType = "pc"; + appId = ""; + actives = []; //从菜单中激活的组件, + layouts = []; //由自定义组件和第三方组件组成的布局组件集合 + + getDeviceType() { + return this.deviceType; + } + + getTemplateLayouts() { + return this.layouts; + } + + // 传递当前所处组件的上下文环境 + menuStatusUpdate() { + const onActives = this.getTemplateLayouts() + .filter(l => !l.lazy) + .map(c => c.component.name || c.component); + const appId = ""; + console.log("============>", appId); + // TODO 这里通过event-bus来实现吧,Vue实例获取不到 + this.$emit("TIS_TEMPLATE_MENU_ACTIVE", { + appId, + onActives: onActives, + system: true + }); + } + async loadComponent(component) { + const comp = this.components.find(arg => arg.component === component) || {}; + console.log("所有组件...", this.components); + console.log("所有资源...", this.asserts); + console.log("当前加载组件...", component); + console.log("匹配到的组件...", comp); + let assets = null; + let dependencies = []; + let isLib = false; + try { + const info = comp.segprefix; + assets = this.asserts[info]; + dependencies = comp.dependencies || []; + isLib = comp.lib; + } catch (e) { + console.error(e); + } + + //等待依赖下载完毕 + for (const refer of dependencies) { + let reference = this.asserts[refer] || null; + await registerApps(reference, curBaseUrl); + } + return new Promise((resolve, reject) => { + //加载组件资源 + console.log("开始加载组件资源", assets, curBaseUrl); + registerApps(assets, curBaseUrl) + .then(() => { + if (!isLib) { + //正常组件的加载流程,isLib为true代表纯js lib库的加载 + let startTime = new Date().getTime(); + const looper = setInterval(() => { + if (Vue.component(`${component}`)) { + resolve(comp); + clearInterval(looper); + } else { + let nowTime = new Date().getTime(); + if (nowTime - startTime > 2000) { + if (!assets) { + reject(`[loading error:${component}]:组件资源加载失败`); + } else { + reject( + `[loading error:${component}]:loading component timed out` + ); + } + clearInterval(looper); + } + } + }, 300); + } else { + resolve(comp); + } + }) + .catch(err => { + if (!assets) { + reject(`[loading error:${component}]:组件资源加载失败`); + } else { + reject(`[loading error:${component}]:${err}`); + } + }); + }); + } + //自定义函数,支持开发者按需增加接口 + + openComponentByMenu(components) { + //长度变化才会触发computed? + this.components + .filter(c => { + const component = c.component.name || c.component; + //激活组件命中此组件,更改状态 + const hit = components.includes(component); + if (hit) { + c.lazy = !hit; + return c; + } + }) + .forEach(c => { + if ( + !this.layouts.some( + l => (l.component.name || l.component) === c.component + ) + ) { + this.layouts.push(c); + } else { + //改变状态 + this.layouts.forEach(l => { + if ((l.component.name || l.component) === c.component) { + l.lazy = false; + } + }); + } + + if (!this.actives.some(l => l.component === c.component)) { + //弹窗暂定为同一时间只能打开一个 + if (c.type === "dialog") { + this.actives = [c]; + } else { + this.actives.push(c); + } + } + }); + //有 加入 无 删除? + + console.log("layouts变化状态", this.layouts); + console.log("actives变化状态", this.actives); + this.menuStatusUpdate(); + } + // 关闭组件 + closeComponent(components) { + //修改layout中的状态 + this.layouts.forEach(c => { + const component = c.component.name || c.component; + //激活组件命中此组件,更改状态 + const hit = components.includes(component); + if (hit) { + c.lazy = hit; + } + }); + //active中删除该组件 + console.log("待删除组件", components); + components.forEach(c => { + const index = this.actives.findIndex(b => b.component === c); + console.log("aaaaaa", index); + if (index >= 0) { + this.actives.splice(index, 1); + } + }); + console.log("layouts变化状态", this.layouts); + console.log("actives变化状态", this.actives); + this.menuStatusUpdate(); + } + //initLayouts //layouts 初始化,外部组件 + initLayouts(layouts = []) { + this.layouts.push(...layouts.filter(l => !l.lazy)); + } + + //获取组件 + getWidgetsByType(type) { + //以type 或 position 命中widget,背景板默认lazy=false + return this.layouts + .filter(f => (f.type === type || f.position === type) && !f.lazy) + .map(f => { + //string类型,来自配置文件,需要下载资源才能使用,懒加载组件不加载但是需要加入到数组中、、 + + if (typeof f.component === "string") { + console.log("下载component资源", f.component); + return this.loadComponent(f.component); + } else { + return f; + } + }); + } + + //获取含有当前类型的激活组件 + getActivesByType(type) { + return this.actives.filter(a => a.type === type); + } + + // 初始化配置信息 + async initData(props) { + const dev = process.env.NODE_ENV === "development"; + curBaseUrl = props.tis ? props.tis.entry : baseUrl; + const esData = await axios + .get(`${curBaseUrl}/esplug.json`) + .catch(err => console.error(err)); + const asserts = await axios + .get(`${curBaseUrl}/tisplatform.json`) + .catch(err => console.error(err)); + try { + //运行模式才取用框架返回的数据 + if (props.tis && !dev) { + console.log("框架传入的components:", props.tis.components); + this.components = props.tis.components + ? [...props.tis.components, ...esData.data.components] + : esData.data.components; + this.asserts = + Object.keys(props.tis.asserts).length !== 0 + ? props.tis.asserts + : asserts.data; + this.widgets = props.tis.widgets + ? props.tis.widgets + : esData.data.widgets; + } else { + this.components = esData.data.components; + this.asserts = asserts.data; + this.widgets = esData.data.widgets; + } + //避免不填此属性,默认懒加载 + this.components = this.components.map(c => { + if ( + !Object.prototype.hasOwnProperty.call(c, "lazy") && + c.type !== "background" + ) { + c.lazy = true; + } + return c; + }); + } catch (e) { + console.error(e); + } + } + + $emit(event) { + return this.emit(event); + } + + $on(event, fn) { + return this.on(event, fn); + } + + $off(event, fn) { + return this.off(event, fn); + } + + $once(event, fn) { + return this.once(event, fn); + } +} + +export function createBus(appId) { + const bus = new Bus(); + bus.appId = appId; + + function onSetup(options = {}) { + bus.layouts = options.layout; + } + + async function onMount(props) { + await bus.initData(props); + bus.initLayouts(bus.components); + bus.initLayouts(bus.widgets); + } + + return { + bus, + onSetup, + onMount + }; +}