# 数科套红技术说明文档
# 1.业务逻辑说明
# 1.1 快速发文正文套红
快速发文中正文套红代码逻辑如图所示:
# 1.2 待办正文套红
待办中正文套红逻辑如下图所示:
# 1.3 文单套红
文单套红代码逻辑如图所示:
# 2. 接口说明
# 2.1 使用方式
调用officeSDK.taohong(params,callback)方法进行套红,taohong方法是异步方法,如果需要确保套红完成后再做后续的逻辑,可采用一下两种方式: 方法1:
let result = await officeSDK.taohong(params);
if(result){
// 后续处理逻辑
}
方法2:
officeSDK.taohong(params,function(err,result){
if(!err){
// err如果未false,表示套红成功,此处可以做后续处理
}
})
// params:调用套红接口参数
// callback:回调函数,接收套红结果
备注:套红后是否打开文档是在各自插件对应的Adapter文件中控制,文件打开方式由params参数控制,可以在套红之前调用officeSDK.setOptions({})将参数设置进去,打开文件的时候会根据参数控制打开的方式
# 2.2 参数说明
# 1. 套红参数说明
参数 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
allBookMark | List | 是 | 书签对象集合 |
templateType | String | 是 | 模板类型(edoc:正文,script:表单) |
fileType | String | 是 | 文件类型(doc或者docx) |
fileId | String | 是 | 文件ID |
refreshBookMarkText | Boolean | 是 | 刷新数书签值,如果需要刷新书签,次参数传递true |
templateUrl | String | 否 | 模板ID |
extParam | Map | 否 | 扩展参数 |
# 2. 书签对象说明
参数 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
bookmark | String | 是 | 书签名称 |
type | String | 是 | 书签类型(DOCUMENT \ IMAGE \TEXT) |
text | String | 否 | 文本内容 |
imgInfo | ImgInfo | 否 | 图片对象,当type为IMAGE时,必填 |
fileInfo | DocumentInfo | 否 | 文件对象,当type为DOCUMENT时,必填 |
# 3. 图片对象说明
参数 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
imgId | String | 是 | 图片ID |
inputType | String | 是 | 图片类型(image、handwrite、barcode) |
createDate | String | 否 | 创建时间 |
isSignatrue | String | 是 | 是否签章 |
# 4. 文件对象说明
参数 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
fileId | String | 是 | 文件ID |
fileType | String | 是 | 正文类型 |
originalFileId | String | 否 | 原正文ID |
size | Long | 否 | 文件大小 |
# 5.扩展参数说明
参数 | 参数类型 | 是否必填 | 说明 |
---|---|---|---|
useOriginContentTaohong | String | 否 | 是否原正文套红 |
originContentId | String | 否 | 原正文ID |
# 3.套红功能
套红功能支持的插件为数科预览、金山文档中台、WPS加载项,在调用套红功能之前需要将当前插件切换为编辑模式,代码示例如下:
示例1:
await officeSDK.init({
mode: OfficeSDK.ENUM_MODE_TYPE.EDIT
});
示例2:
await officeSDK.switchProvider({
mode: OfficeSDK.ENUM_MODE_TYPE.EDIT
});
# 3.1 数科套红
# 1. 前端代码
同时存在多个可以套红的插件时会优先使用数科的套红功能,因此数科的前端套红方法被封装为OfficeSDK的一个工具方法:
OfficeSDK.utils = {
taohong: function (params, callback) {
.....
}
}
PC代码位置:
apps-office-plugins-front\\desktop-front\\src\\office\\js\\OfficeSDK.js
移动端代码位置:
apps-office-plugins-front\\mplus-front\\src\\office\\js\\OfficeSDK.js
# 2. 后端代码
数科套红采用的是后端接口套红,接口信息如下:
请求方式:POST
请求地址:/rest/suWellTaoHong/taohong
接口入口如下:
@Path("/taohong")
@POST
@ApiOperation(name="套红",scenes = "PC端-套红")
public Response taohong(@RequestBody CommonTaoHongParam commonTaoHongParam){
String configValue= OfficeConfigUtil.getConfigValue(OfficeConfigEnum.ONLINE_PREVIEW_TYPE);
if(commonTaoHongParam == null){
return this.fail("taoHongParams is null");
}
if(!("SUWELL").equals(configValue)){
return this.fail("当前插件不支持套红");
}
try {
DocumentInfo documentInfo = suWellTaoHongManager.taohong(commonTaoHongParam);
return this.success(documentInfo);
} catch (BusinessException e) {
return this.fail(e.getMessage());
}
}
# 3.2 文档通
由于文档同本身没有实现套红功能,套红逻辑采用的是数科的套红功能,因文档通的套红方法是通过调用OfficeSDK.utils.taohong(params,callback)方法进行套红的。
# 1. 前端代码
PC代码位置:apps-office-plugins-front\desktop-front\src\office\js\docWebOffice\wdtAdapter.js
DocWebOfficePlugin.prototype.taohong = function (params, callback) {
var _self = this;
return new Promise((resolve, reject) => {
OfficeSDK.utils.taohong(params, async function (error, result) {
if (error) {
callback && callback(error, result);
reject(error)
} else {
_self.openFile({ fileId: result.fileId }, function (error, result) {
callback && callback(error, result);
resolve(result)
});
}
})
})
}
移动端代码位置:
apps-office-plugins-front\mplus-front\src\webOffice\docWebOffice\wdtAdapter.js
DocWebOfficePlugin.prototype.taohong = function (params, callback) {
var _self = this;
return new Promise((resolve, reject) => {
OfficeSDK.utils.taohong(params, function (error, result) {
callback && callback(error,result);
if (error) {
reject(false)
} else {
resolve(result)
}
})
})
}
# 3.金山文档中台
金山文档中台套红功能首先是调用后台套红接口进行套红,后台套红不支持的功能再经过前端进行套红。
备注:意见区域待图片使用前端套红
# 1. 前端代码
PC代码位置:
apps-office-plugins-front\desktop-front\src\office\js\kingSoftAdapter\kingSoftAdapter.js
KingSoftOfficePlugin.prototype.taohong = async function (params, callback) {
var _self = this;
return new Promise((resolve, reject) => {
OfficeSDK.utils.taohong(params, async function (error, result) {
if (error) {
_self.webOfficeInstance.taohong(params, async (e, res) => {
if (e) {
callback && callback(e, res);
} else {
if (res) {
// 后端套红成功,需要再执行前端套红
// 服务端套红生成的文件需要比对是否替换fileId
if (_self.params.fileId !== res.data.fileId) {
_self.params.fileId = res.data.fileId;
}
// 服务端套红后需要刷新office,但是之前已经存在一个wps实例,会导致展示的内容为原wps内容而不是套红后的内容(这是wps本身缺陷),所以需保证wps实例为最新
await _self.webOfficeInstance.wps.destroy();
// 套红后需要是可以编辑状态
_self.params.canEdit = true;
_self.params.editType = "2,1";
await _self.openFile();
// 前端补套,由于服务端无法执行部分书签的套红(如:书签下同时包含图片和文字两种类型的值)
// 如果是快速发文,不走前端套红的逻辑
await _self.webOfficeInstance.frontTaohong(params.imgArray, params.allBookMark);
var data = {
fileId: _self.params.fileId
}
callback && callback(null, data);
resolve(data)
} else {
callback && callback(false, false);
reject(false)
}
}
});
} else {
//刷新的时候调用强制刷新刷新内容
await _uploadWebofficeEditRefresh(result.fileId);
_self.openFile({fileId: result.fileId},function(error,result){
callback && callback(error,result);
resolve(result)
});
}
})
})
}
PC端金山文档中台套红相关业务代码位置如下:
apps-office-plugins-front\desktop-front\src\office\js\kingSoftAdapter\kingSoftWebOffice.js通过KingSoftAdapter.js对业务代码进行调用。
移动端代码位置:
apps-office-plugins-front\mplus-front\src\webOffice\kingsoft\kingSoftAdapter.js
KingSoftOfficePlugin.prototype.taohong = async function (params, callback) {
var _self = this;
return new Promise((resolve, reject) => {
OfficeSDK.utils.taohong(params, function (error, result) {
if (error) {
_self.webOfficeInstance.taohong(params, async (e, res) => {
callback && callback(e, res);
resolve(res)
});
}else{
callback && callback(error, result);
resolve(result)
}
})
})
}
移动端金山文档中台套红相关业务代码位置如下:
apps-office-plugins-front\mplus-front\src\webOffice\kingSoftWebOffice.js通过KingSoftAdapter.js对业务代码进行调用。
# 2. 后台代码
金山文档中台后端套红代码接口信息如下:
请求方式:POST
请求地址:/rest/webOffice/format/taohong
金山文档中台代码位置:
apps-office-plugins\src\main\java\com\seeyon\ctp\rest\resources\WebOfficeFormatResource.java
代码入口如下:
@Path("/taohong")
@POST
@ApiOperation(name = "套红", scenes = "套红")
public Object taohong(@RequestBody TaoHongParams taoHongParams) throws BusinessException {
// 获取模板
if(taoHongParams == null){
return this.fail("taoHongParams is null");
}
try {
DocumentInfo info = formatControlManager.taohong(taoHongParams);
return this.success(info);
}catch (Exception e){
log.error("后端套红出错",e);
return this.fail(e.getMessage());
}
}
# 4. WPS加载项
# 1. 前端代码
WPS加载项套红采用的是再客户端进行套红,目前暂时不支持移动端套红
PC代码位置:
apps-office-plugins-front\desktop-front\src\office\js\wpsAdapter\wpsAdapter.js
WpsAdapter.prototype.taohong = async function (params={}, callback){
if(!await this.checkOpenState()){
return false;
}
let allBM = {};
params.allBookMark && params.allBookMark.forEach((item) => {
if(item.type=='TEXT'){
allBM[item.bookmark] = item.text;
}else if(item.type === "IMAGE"){
let imgInfo=item.imgInfo;
if(typeof(imgInfo) !="undefined") {
let imgValObj = {inputType: imgInfo.inputType};
imgValObj["value"] = imgInfo.value;
imgValObj["isSignatrue"] = "false";
var imgVal = [["imgsign", imgValObj]];
allBM[item.bookmark] = imgVal;
}
}else{
if(item.bookmark.indexOf("FJ_正文")==0 || (params.extParam.category == "32" && item.type == "DOCUMENT")){
let fileInfo=item.fileInfo;
allBM[item.bookmark]={"FJContent":fileInfo.fileId,"fileName":fileInfo.fileName,"fileType":fileInfo.fileType};
}else {
allBM[item.bookmark] = item;
}
}
});
var wpsTaohongParam ={
fileId:this.options.fileId,
// 执行操作
handleType: params.templateType=="edoc" ? HANDLE_TYPE.BodyInsertRed : HANDLE_TYPE.FormInsertRed,
// 模版id
templateUrl:params.templateUrl,
redFileElement: allBM,
//插入正文对应的元素
bkInsertFile:'Content', //Content
zhInsertFile:'正文', //正文
editType: "1,0",
istaohong:true
}
if (!WpsUtil.isEmptyObject(params.extParam)) {
if (params.extParam["useOriginContentTaohong"] == true) {
// 原正文套红
wpsTaohongParam["useOriginContentTaohong"] = params.extParam["useOriginContentTaohong"];
wpsTaohongParam["originContentId"] = params.extParam["originContentId"];
} else {
// 文单套红,可修改,但不能保存到oa,直接不清稿操作
if(wpsTaohongParam.handleType==HANDLE_TYPE.FormInsertRed){
wpsTaohongParam["wpsFileSaveToServer"] = params.extParam.wpsFileSaveToServer || '';
wpsTaohongParam["isFromDocTaoHong"] = true;//是否来于文单套红
}
}
}
//信息报送-期刊套红
try {
if(params.extParam.category=="32") {
wpsTaohongParam.category = "32";
if (params.extParam.dataList && (params.extParam.dataList.length > 0|| Object.keys(params.extParam.dataList).length > 0)) {
wpsTaohongParam.dataList = params.extParam.dataList;
}
}
} catch(e) {}
await this.active();
await InsertRedHead(wpsTaohongParam);
callback && callback(null,true);
return true;
}