挂载点
// 难点 怎么能够同步更新版本 如果我们自己拉下来之后
import { get, pick } from "lodash-es";
import api from "@/api";
import { MessageBox } from "element-ui";
class OpenAppEventBridge {
constructor() {
this.messageHandler = this.messageHandler.bind(this);
if (window.addEventListener) {
window.addEventListener("message", this.messageHandler);
} else {
window.attachEvent("onmessage", this.messageHandler);
}
this.store = {};
}
messageHandler(e) {
const { data = {}, origin, source } = e;
const { code } = data;
// console.debug(data);
if (!code) {
return;
}
this.broadcast(data);
}
findProxy({ entranceId, appID }) {
return Object.values(this.store).find(
(proxy) =>
proxy && proxy.entranceId === entranceId && proxy.appID === appID
);
}
broadcast(data) {
const { code, event, params, id } = data;
Object.entries(this.store).forEach(([key, proxy]) => {
if (key === code) {
proxy.emit(event, { params, code, id }, this);
}
});
}
/**
* 主要目的就是为了绑定相应的iframe对象
*/
registerApp(params) {
const proxy = new Proxy(params);
this.store[proxy.code] = proxy;
return proxy;
}
updateAppCode(preCode, newCode) {
const appProxy = this.store[preCode];
appProxy.code = newCode;
this.store[newCode] = appProxy;
this.store[preCode] = null;
}
destroyApp(code) {
this.store[code] = null;
}
}
class Proxy {
constructor({
code,
appID,
entranceParams,
iframe,
vm,
workspaceId,
entityId,
entityType,
entranceId,
}) {
this.code = code;
this.iframe = iframe;
this.appID = appID;
this.workspaceId = workspaceId;
this.entranceParams = entranceParams;
this.vm = vm;
this.entityId = entityId;
this.entityType = entityType;
this.entranceId = entranceId;
this.queue = [];
}
on(event, callback) {
this.queue.push({ event, callback });
return this;
}
emit(event, { params, code, id }, controller) {
this.queue.forEach(async (item) => {
if (event === item.event) {
const result = await item.callback.call(
this.vm,
{
params,
proxy: this,
code,
id,
},
controller
);
this.send({
params: result,
id,
});
}
});
}
send({ event = "", params, id }) {
console.log(event, params, id);
const message = {
code: this.code,
event,
params,
id,
};
const { iframe } = this;
iframe.contentWindow.postMessage(message, "*");
}
}
export default function (Vue) {
const controller = new OpenAppEventBridge();
// eslint-disable-next-line no-param-reassign
Vue.prototype.$registerApp = function (params) {
const vm = this;
// register open app proxy and listen common event for vue components
const proxy = controller
.registerApp({
...params,
vm,
})
.on("showFlash", message)
.on("generateCode", refreshToken)
.on("getEntranceData", getEntranceData)
.on("openObjURL", openObjURL)
.on("openBkURL", openBkURLPage)
.on("showConfirm", showConfirm)
.on("handlerInvoke", handlerInvoke)
.on("getUserListByKeyWords", getUserListByKeyWords)
.on("getWorkspaceMemberList", getWorkspaceMemberList)
.on("getAllRelateMember", getAllRelateMember)
.on("syncPageEvent", syncPageEvent)
.on("showDialog", showDialog)
.on("closeConfirm", closeConfirmCallBack);
// remove the proxy when vue components destroyed
vm.$on("hook:beforeDestroy", () => {
controller.destroyApp(proxy.code);
});
return proxy;
};
// Vue.prototype.$listenOpenApp = function () {};
}
/* event handle begin */
function message({ params }) {
const { msg } = params;
const message = msg.trim();
message && this.$message(msg);
}
function closeConfirmCallBack({ params }) {
const msg = get(params, "params.msg", "").trim();
message && this.$message(msg);
}
/**
* @todo 历史原因已经不能够将这个code作为通信凭证的问题解决
* @description 刷新code;
*/
async function refreshToken({ proxy }, controller) {
const vm = this;
const { currentWorkspaceId } = vm;
const refreshCode = await api.open.generateCode({
workspaceId: currentWorkspaceId,
appID: proxy.appID,
});
// 历史代码的兼容,如果用的是JS-sdk不需要
proxy.send({
event: "syncCode",
params: { code: refreshCode },
});
controller.updateAppCode(proxy.code, refreshCode);
return refreshCode;
}
/**
* @description 同一个应用的不同挂载点通信
*/
function syncPageEvent({ params, proxy }, controller) {
const { entranceId, data } = params;
const targetProxy = controller.findProxy({
appID: proxy.appID,
entranceId,
});
if (targetProxy) {
targetProxy.send({
event: "syncPageEvent",
params: {
data,
},
});
}
}
/**
* @description 获取挂在点信息
*/
function getEntranceData({ proxy }) {
return pick(
proxy,
"entityId",
"entityType",
"workspaceId",
"appId",
"code",
"entranceId"
);
}
/**
* @description 打开3大对象页面
*/
function openObjURL({ params, proxy }) {
const { entityType, entityId } = params;
const { workspaceId } = proxy;
let url = "";
// @TODO: 待确认跳转的链接地址
switch (entityType) {
case "story":
url = `/${workspaceId}/prong/stories/view/${entityId}`;
break;
case "bug":
url = `/${workspaceId}/bugtrace/bugs/view?bug_id=${entityId}`;
break;
case "task":
url = `/${workspaceId}/prong/tasks/view/${entityId}`;
break;
}
url && window.open(url, "_blank");
}
/**
* @description 打开 app_for_project 挂载点 跟 应用设置页面
**/
function openBkURLPage({ params: options, proxy: data }) {
const entityId = options.entityId || "app_for_project";
const url = `/${this.workspaceId + entityId + data.appId}#${options.url}`;
if (url) window.open(url, "_blank");
}
async function showConfirm({ params, proxy }) {
return await MessageBox.confirm(params.content, "", {
dangerouslyUseHTMLString: proxy.code === "code_review", // 老旧逻辑的白名单
}).then(() => {
proxy.send({
event: "confirmYes",
params: { data: params.data },
});
});
}
/**
* Api 错误的事件,不公开也不推荐添加 ;
*/
async function getUserListByKeyWords({ params, proxy }) {
const result = await api.open.getUsers({
workspaceId: params.workspace_id,
keyword: params.key_word,
});
const response = {
data: result.data.data,
keyword: params.key_word,
};
proxy.send({
event: "userChooserFetchFinish",
params: response,
});
return response;
}
async function handlerInvoke({ params, proxy }) {
const { workspaceId, appID } = proxy;
const { handler } = params;
const res = await api.open.handleInvoke({
workspaceId,
appID,
handler,
params: params.params,
});
const invokeData = get(res, "data.data");
return invokeData ? invokeData : res;
}
async function getWorkspaceMemberList() {
return {};
}
async function getAllRelateMember({ proxy }) {
proxy.send({ event: "getAllRelateMemberFinish", params: [] });
return {};
}
function showDialog({ params, proxy }) {
this.$openAppDialog({
name: params.title,
url: params.url,
entranceId: "open-app-dialog",
height: params.height,
appID: proxy.appID,
});
}
最后更新于
这有帮助吗?