# 金格外部中间件JSAPI实现逻辑
# ⅠPDF实现逻辑
# 控件加载要求
页面加载的时候需要初始化一个id为officeEditorFrame的ifram标签,并且加载basePdf.js,basePdf.js需要和iframe在同一个页面
示例:
<iframe id="officeEditorFrame" name="officeEditorFrame"
frameborder="0" height="100%" width="100%" scrolling="no" marginheight="0" marginwidth="0"></iframe>
<script src="./basePdf.js"></script>
# 代码加载顺序
basePdf.js>pdf_kinggrid_brower.js
basePdf.js中通过懒加载的方式引入对应插件所需要的js
# 加载流程
# 各文件的作用
1、pdf.html:控件挂载点
2、pdfBrowser.css:样式文件
3、basePdf.js:调用pdf控件的基础js,提供了业务方法的调用
4、pdf.js:用于postMessage通信,根据插件类型懒加载对应插件所需的js,并返回加载消息给basePdf.js
5、enum.js:不同控件需要的js枚举
6、utils.js:实现一些内部所需要的工具方法
7、pdf_kinggrid_browse.js:金格pdf控件jsapi原型对象js
8、pdf_invoke.js:金格pdf控件jsapi双向通信封装的方法
9、tgPdf.js:金格控件jsapi插件端执行的js
# 实现逻辑
1、方法入口为basePdf.js中的initPdf()方法
/**
* 初始化控件
* @param {*} params
*/
initPdf: async function (params, callBack) {
//老控件需求
PdfUtils.setEditorFrameOptions(params);
// callback执行顺序 1: parasm.callback 2:第二个参数callback
const data = await this.showPdfDiv(params.fileType, params.isFullSize, params.callback, params);
if (typeof callBack == 'function') {
callBack(data);
}
return data;
}
2、initPdf()调用basePdf.js文件的showPdfDiv()方法
1).判断插件类型,根据环境判断当前插件是否可用(jsapi支持谷歌内核107以上,不支持mac环境、windows环境火狐浏览器不支持)
2).判断是否立即加载控件
3).调用loadHtmlForPlugin()加载pdf.html页面,懒加载js(basePdf.js与pdf.html中的pdf.js通过postMessage进行通信)pdf.html加载完成后basePdf.js会通过postMessage与pdf.js进行通信
关键代码:
basePdf.js
if (iframeDom.attachEvent) {
iframeDom.attachEvent("onload", async () => {
var targetWindow = iframeDom.contentWindow;
await this.emitMessage(param, targetWindow);
resolve(targetWindow.PDFOffice);
})
} else {
iframeDom.onload = async () => {
var targetWindow = iframeDom.contentWindow;
await this.emitMessage(param, targetWindow);
resolve(targetWindow.PDFOffice);
}
}
以上代码标识pdf.html页面加载完成后向pdf.js发送消息,pdf.js会监听postMessage发送过来的消息,然后左响应的js加载
pdf.js
/**
* 懒加载js文件
* @returns
*/
function lazyLoadJS(params, callback) {
return new Promise((resolve, reject) => {
const {
pluginType,
webRoot
} = params;
let urls = JsFilesEnums[pluginType];
// 文件接口拼接
urls = urls.map(item => {
if (item.needWebRoot) {
return webRoot + item.jsUrl;
} else {
return item.jsUrl;
}
})
loadJS(urls, () => {
if (typeof callback == 'function') {
callback();
}
resolve(true);
});
});
}
这里的控件类型是“kingsoft_pdf_jsapi”,因此会加载enum.js文件中JsFilesEnums对象中kingsoft_pdf_ppapi对应的js文件
4).实例化PDFOffice对象
5).调用PDFOffice对象的initPdf()初始化控件(pdf_kinggrid_browser.js对应的initPdf方法)
6).调用basePdf.js中的doShowPdfDiv()打开PDF控件,加载文档
3、doShowPdfDiv()调用basePdf.js中的loadPdf()加载文件
1).在每个插件对应的js中检查控件是否可用
2).设置记录文件打开值isLoadPdfFile
3).调用插件对应的loadPdf()加载pdf正文(pdf_kinggrid_browser.js文件中的loadPdf())
4、调用pdf_kinggrid_brower.js文件中的loadPdf()方法
1).获取令牌,设置令牌
2).验证控件是否可用
// 获取证书
const verification = KGPdfUtils.getVerification();
// 验证PDF控件是否可用
// 第一步检测金格中间件应用 第二步检测iwebpdf是否安装
if (!this.isOfficeAvailable() || !await this.checkOfficeStatus(params)) {
this.dialog();
this.isLoading = false;
return false;
}
3).如果控件可用,会调用唤起App,然后打开文件
const res = await KGBrowserPdfUtils.StartApp(params);
if(res){
data = await KGBrowserPdfUtils.openFile(params); //data就代表文档是否打开成功,如果不用打开或不用保存,则返回true
setIsLoadPdfFile(data);
}else{
setIsLoadPdfFile(false);
}
备注:这里的打开文件并不是真的打开,是调用pdf_invoke.js的openFile方法是发送了一个消息给tgPdf.js执行tgPdf.js中的openFile方法,发送消息见pdf_invoke.js如下:
/**
* 金格JSAPI统一发送消息的方法
* @param { String } func 需要执行的方法名称
* @param { Object } params 参数信息
*/
function _KgInvoke(func, params = {}) {
const { reqType = 'post' } = params;
// 金格sdk中获取的方法
return new Promise(function (resolve, reject) {
if(KgPdfApp) {
KgPdfApp.invoke({
method: func.method,
reqType: reqType,
params: params,
success: function (data) {
resolve(data);
},
error: function (err) {
reject(err);
}
});
} else {
reject(false);
}
});
}
4).调用initOcxMenu()进行菜单初始化
/**
* 初始化菜单
*/
PDFOffice.prototype.initOcxMenu = function () {
var pdfFun = document.getElementById("WebPDF").iWebPDFFun;
pdfFun.AppendTools("101", KGPdfUtils.getPdfLanguage("menu_57"), 7);
}
5).调用adjustMenu()调整菜单显示
/**
* 调整菜单显示
*/
PDFOffice.prototype.adjustMenu = function () {
try {
//修改正文
var pdfObj = document.getElementById("WebPDF").iWebPDFFun;
pdfObj.Zoom = 100;
var menuStr = "";
var _canOpen = true;
var hideMenuStr = "";
var signMenu = "";
if (parent.editType == "0,0" || parent.editType == "4,0") { //查看只读文档状态,不能打开文档,保存文档
menuStr = "menu_1,menu_10,menu_89,menu_90";
hideMenuStr = "menu_118";
_canOpen = false;
signMenu = ",menu_102,menu_103";
try {
pdfObj.AllowMoveAnnot = false;
} catch (e) {}
} else if (parent.editType == "1,0") { // 新建文档状态,可以打开文档,保存文档
_canOpen = true;
}
/*************************************隐藏菜单开始***********************************************/
for (var i = 2; i < 118; i++) {
if (_canOpen) {
if (i == 8 || i == 10 || i == 12 || i == 57 || i == 88 || i == 89 || i == 91 || i == 92 || i == 93 || i == 94 || i == 95 || i == 96 || i == 102 || i == 103 || i == 104 || i == 105 || i == 106 || i == 107 || i == 108) {
continue;
}
if(menuStr == ""){
menuStr = menuStr + "menu_" + i;
}else{
menuStr = menuStr + ",menu_" + i;
}
} else {
if (i == 8 || i == 10 || i == 12 || i == 51 || i == 52 || i == 57 || i == 88 || i == 91 || i == 92 || i == 93 || i == 94 || i == 95 || i == 96 || i == 102 || i == 103 || i == 104 || i == 105 || i == 106 || i == 107 || i == 108) {
continue;
}
if(menuStr == ""){
menuStr = menuStr + "menu_" + i;
}else{
menuStr = menuStr + ",menu_" + i;
}
}
}
/*************************************隐藏菜单结束***********************************************/
//-----------------------------
var canSaveLocal = parent.contentSaveLocal && parent.contentSaveLocal == "true";
canSaveLocal = canSaveLocal || parent.officecanSaveLocal && parent.officecanSaveLocal == "true";
canSaveLocal = canSaveLocal || parent.parent.officecanSaveLocal && parent.parent.officecanSaveLocal == "true";
//如果是快速发文,默认有下载权限
if (parent.parent && parent.parent.isQuickSend === "true") {
canSaveLocal = true;
}
//要禁用的菜单 本地另存为按钮 只有在没权限保存的时候禁用
if (!canSaveLocal) {
menuStr = menuStr + ",menu_8";
}
menuStr += signMenu;
//-----------------------------
//打印
menuStr = this.setToolsPrintState(menuStr);
menuStr = KGPdfUtils.getPdfLanguage(menuStr).replace(/,/g, ";");
hideMenuStr = this.setToolsPrintState(hideMenuStr);
hideMenuStr = KGPdfUtils.getPdfLanguage(hideMenuStr).replace(/,/g, ";");
pdfObj.EnableTools(menuStr, 0);
pdfObj.EnableTools(hideMenuStr, 2);
pdfObj.EnableTools(KGPdfUtils.getPdfLanguage("menu_51,menu_52").replace(/,/g, ";"), 1);
//文字选择按钮,控制复制粘特
this.isAuthorityToCopy(pdfObj);
} catch (e) {
window.console && console.log(e);
}
}
# Ⅱ Word、WPS实现逻辑
# 控件加载要求
页面加载的时候需要初始化一个id为officeEditorFrame的ifram标签,并且加载baseOffice.js,baseOffice.js需要和iframe在同一个页面
示例:
<iframe id="officeEditorFrame" name="officeEditorFrame"
frameborder="0" height="100%" width="100%" scrolling="no" marginheight="0" marginwidth="0"></iframe>
<script src="./baseOffice.js"></script>
# 各文件的作用
officeBrowse.html:挂载点
officeBrower.css:样式文件
baseOffice.js:调用pdf控件的基础js,提供了业务方法的调用
kinggirdBaseOffice.js:金格office控件jsapi原型对象js
kinggirdInvoke.js:金格office控件jsapi双向通信封装的方法
tgOffice.js:金格控件jsapi插件端执行的js
# 实现逻辑
1、方法入口为baseOffice.js中的initOffice()方法
initOffice: async function(params) {
await this.buildOfficePlugin(params);
}
2、调用buildOfficePlugin()方法
1).获取webOffice在线编辑的类型
2).获取是否启用了webOffice配置
3).如果是wps类型需要判断webOffice是否可用
4).如果webOffice不可用,并且客户端混网,没有购买国标office插件,就走金格
5).如果是非混网,或者pdf被wps打开了
3、调用baseOffice.js的setKinggriddPlugin()方法设置参数
1)、获取谷歌内核版本,如果是高于107版本就使用金格jsapi
2)、实例化金格插件对象,设置相关参数
4、调用kinggridBaseOffice.js的loadOffice()方法加载office
1).判断插件是否可用
2).调用_loadKGBrowerHtml()设置正文挂载点
3).设置一下最新的参数
4).判断金格app是否安装,控件未加载成功后续逻辑不再执行
5).调用checkOfficeStatus()检查控件即当前状态
6).调用kinggridOffice.js的StartApp()方法,备注:kinggridOffice.js的startApp()并不是打开控件,而是调用kinggridinvoke.js的StartApp()方法打开控件
7).调用kinggridOffice.closeDocumentByAll()关闭金格控件,这个方法会调用kinggridinvoke.js的closeDocumentByAll()方法,向tgOffice.js发送关闭文档的指令。备注:tgOffice.js是在金格外部中间件的浏览器中加载,OA不能直接调用,所有交互都是采用消息发送。
8).判断是否立即加载,如果需要立即加载再次调用startApp打开控件
7、打开金格外部中间件
调用kinggridOffice.js的StartApp()方法即可打开控件
