目录

服务端交互

  前面章节介绍了DocEditor编辑器的前端集成,以及核心功能,要在系统中完整集成DocEditor,还需要后端服务来实现编辑器数据,历史修订痕迹的保存与获取和手写签批的保存、提交和获取。DocEditor是纯前端编辑器组件,不含后端服务,所有保存数据、获取数据的服务需要集成方实现。需要实现5个后端交互服务,分别是:获取编辑器数据、保存编辑器数据、获取历史修订痕迹列表、获取单条历史修订痕迹数据,保存单条历史修订痕迹数据。如果需要使用到手写签批功能,还需要用到7个后端交互服务,分别是:获取手写签批记录列表,获取当前人编辑的手写数据,获取图片地址,保存手写签批数据,带背景提交手写签批,不带背景提交手写签批,html转图片

  需要重载DocEditor的service对象来调用以上12个服务,其中基础服务2个,痕迹相关服务3个,手写签批相关服务有7个。服务调用过程如下:

重载service对象的方法

要实现这12个方法,需要重载service对象,可以使用以下代码来实现:

const service = new DocEditor.Service();

//获取历史痕迹列表
service.listHistory = function(docid){
  const res = fetch("restful请求路径");	//发起http请求获取历史痕迹列表
  return res.json();										//返回一个resvole了json对象的Promise
};

//获取历史痕迹数据
service.getHistory = function(id){
  const res = fetch("restful请求路径/id");	//发起http请求获取单条历史修订痕迹数据
  return res.json();										//返回一个resvole了json对象的Promise
};

//保存历史痕迹数据
service.saveHistory = function(data){
    return fetch("restful请求路径", {				//发起http请求保存单条历史修订痕迹数据
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
};

//获取编辑器数据
service.getData = function(docid){
  const res = fetch("restful请求路径");	//发起http请求获取编辑器数据
  return res.json();										//返回一个resvole了json对象的Promise
};

//保存编辑器数据
service.saveData = function(data){
    return fetch("restful请求路径", {				//发起http请求保存编辑器数据
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
};

//返回当前文档的手写签批记录(已提交的)列表,返回一个数组列表
service.listHandwritingLog = function(docid){
  const res = fetch("restful请求路径");	//发起http请求获取当前文档的手写签批记录
  return res.json();										//返回一个resvole了json对象的Promise
}

//根据图片id获取图片地址或者是图片base64编码后的数据
service.getHandwritingImage = function(imageId){
	const await res = fetch("restful请求路径");	//发起http请求获取图片src
  return res.json().src;								//返回图片地址或者是图片base64编码后的数据
}

//实现获取当前处理人编辑的手写数据
service.getEditedHandwriting = function(options){
  const res = fetch("restful请求路径");	//发起http请求获取当前处理人编辑的手写数据
  return res.json();										//返回一个resvole了json对象的Promise
}

//保存手写签批数据
service.saveHandwriting = function(data){
    return fetch("restful请求路径", {				//发起http请求保存手写签批数据
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}

//带正文背景提交手写签批
service.submitHandwritingWithDoc = function(data){
    return fetch("restful请求路径", {				//发起http请求提交带正文背景提交手写签批
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}

//不带正文背景提交手写签批
service.submitHandwritingWithoutDoc = function(data){
    return fetch("restful请求路径", {				//发起http请求提交不带正文背景提交手写签批
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}

//html转图片, 获取图片地址
service.htmlToImage = function(data){
    return fetch("restful请求路径", {				//html转图片, 获取图片地址
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}

当然,也可以继承DocEditor.Service类,来创建自己的Service类:

class MyService extends DocEditor.Service {
    async listHistory(id) {
       //实现获取历史痕迹列表,返回一个数组列表\
       //...
    }
    async getHistory(id){
        //实现获取历史痕迹数据
        //...
    }
    async saveHistory(data){
        //实现保存历史痕迹数据
        //...
    }
    async getData(id){
        //实现获取编辑器数据
        //...
    }
    async saveData(data){
        //实现保存编辑器数据
        //...
    }
    async listHandwritingLog(docid){
       //返回当前文档的手写签批记录(已提交的)列表,返回一个数组列表
        //...
   }
   async getHandwritingImage(imageId){
       //根据图片id获取图片地址或者是图片base64编码后的数据
        //...
   }
   async getEditedHandwriting(options){
       //实现获取当前处理人编辑的手写数据
        //...
   }
   async saveHandwriting(data){
       //保存手写签批数据
        //...
   }
   async submitHandwritingWithDoc(data){
       //带正文背景提交手写签批
        //...
   }
   async submitHandwritingWithoutDoc(data){
       //不带正文背景提交手写签批
        //...
   }
   async htmlToImage(data){
       //html转图片, 获取图片地址
        //...
   }
}
const service = new MyService();

完成service对象后,在初始化编辑器时,传入service:

const editor = DocEditor.createEditor(div, {
  //我们在打包配置中将public目录输出到了 doceditor/public,
  //所以此处需要配置为'./doceditor/' 或 'doceditor/'
  base: './doceditor/',
}, service);
editor.load();

getData获取编辑器数据

  service.getData用于在编辑器加载时,从服务端获取之前被保存过的编辑器数据。返回一个promise,resvole编辑器数据的json对象,或直接返回json对象。json格式参考options中的defaultValue。

  getData方法接收一个参数id,一般情况下,这是一个文档实例的id,由编辑器初始化时的配置项docId传入。

  项目中集成DocEditor的常规过程应该是这样的:

当打开一个现有的文档时:

1、根据现有文档的id获取文档相关信息。

2、获取到当前用户信息。

3、如果是流程,则获取到当前流程和当前流程步骤的信息。

4、将流程id传入到编辑器的docId配置项

5、将当前用户信息传入到编辑器的user配置项

6、将当前流程步骤的信息传入到编辑器的activity配置项

7、将当前流程信息传入到编辑器的processInfo配置项

8、编辑器初始化时,触发service.getData方法,实现getData方法,根据传入的id获取编辑器数据并返回。

9、编辑器正常加载数据。

可能的代码结构如下:

//当打开文档时,必然可以获取到当前文档的唯一标识,如id
const id = 'xxxxxxxxx'; //已知的id

//通过id获取到文档的数据信息
const docData = getDataById(id);

//获取到当前用户信息
const user = getCurrentUser();

//获取到当前流程和当前流程步骤的信息
const process = getCurrentProcess(id);
const activity = getCurrentActivity(id);

//实现DocEditor.Service
const service = new DocEditor.Service();
//获取编辑器数据
service.getData = function(docid){
  cosnst res = fetch("restful请求路径");	//发起http请求获取编辑器数据
  return res.json();										//返回一个resvole了json对象的Promise
};
//其他service方法实现
//...

//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  //我们在打包配置中将public目录输出到了 doceditor/public,
  //所以此处需要配置为'./doceditor/' 或 'doceditor/'
  base: './doceditor/',
  
  docId: id,
  user: {
    name: user.name
    //name 是必须的,在记录修改痕迹时需要使用到
  },
  activity: {
    name: activity.name
    //name 是必须的,在记录修改痕迹时需要使用到
  },
  processInfo: process
}, service);
editor.load();

  service.getData方法,根据id参数获取编辑数据,当我们是新建文档时,则不需要传入docId,此时,getData方法返回null即可。

save保存编辑器数据

  在你保存文档时,需要调用编辑器的save方法,此方法会计算本次正文内容修改的痕迹,并触发service.saveData和service.saveHistory方法。

如果启用了手写签批,save方法可以传入参数表示保存或提交手写签批。如下:

  参数1,表示保存手写签批数据,触发service.saveHandwriting方法;

  参数2,表示不带背景提交数据,触发service.submitHandwritingWithoutDoc方法,如果用户之前保存了签批,本次编辑未打开签批,会提示用户打开签批以便提交。且save方法返回false,且不保存正文数据和痕迹数据;

  参数3,表示带背景提交数据,触发service.submitHandwritingWithDoc方法,如果用户之前保存了签批,本次编辑未打开签批,会提示用户打开签批以便提交。且save方法返回false,且不保存正文数据和痕迹数据。

//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
}, service);
editor.load();
editor.save(); //保存正文、痕迹数据
editor.save(1); //保存正文、痕迹、手写签批
if( editor.save(2) === false ){ //保存正文、痕迹、不带背景提交手写签批,并判断
  //do someting
}; 
if( editor.save(3) === false ){ //保存正文、痕迹、带背景提交数据手写签批,并判断
   //do someting
}; 

  service.saveData方法接收一个参数data,这是编辑器数据的json格式,并有一个docId成员,存储了当前文档的id,这是由编辑器初始化时的配置项docId传入的。data参数格式如下:

//data为要保存的数据,格式如下:
{
  "docId": "xxxxxxx"  //文档的唯一标识
  "copies": "",
  "secret": "",
  "priority": "",
  "redHeader": "文件红头",
  "fileno": "[文号]",
  "signerTitle": "签发人:",
  "signer": "[签发人]",
  "subject": "[文件标题]",
  "mainSend": "[主送单位:]",
  "filetext": "[请在此处编辑正文内容]",
  "attachmentTitle": "附件:",
  "attachment": "",
  "issuanceUnit": "[发文机关]",
  "issuanceDate": "[成文日期]",
  "annotation": "",
  "copytoTitle": "抄送:",
  "copyto": "[抄送]",
  "copyto2Title": "发:",
  "copyto2": "[发]",
  "editionUnit": "[印发机关]",
  "editionDate": "[印发日期]",
  "meetingAttendTitle": "出席:",
  "meetingLeaveTitle": "请假:",
  "meetingSitTitle": "列席:",
  "meetingAttend": "",
  "meetingLeave": "",
  "meetingSit": "",
  "meetingRecord": "",
  //其他自定义扩展字段, 就是配置项processInfo中的内容
}

  在保存编辑器数据时,可能会有两种情况:

  一是编辑器数据是和文档的其他数据一起存储的,那只需要一个请求就可以实现文档的完整保存,这种情况下,其实不实现service.saveData也是可以的,请看下面的模拟代码:

//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  //我们在打包配置中将public目录输出到了 doceditor/public,
  //所以此处需要配置为'./doceditor/' 或 'doceditor/'
  base: './doceditor/',
  
  docId: id,
  user: {
    name: user.name
    //name 是必须的,在记录修改痕迹时需要使用到
  },
  activity: {
    name: activity.name
    //name 是必须的,在记录修改痕迹时需要使用到
  },
  processInfo: process
}, service);
editor.load();

function saveDocument(){
  //获取文档的数据
  const docData = getDocData();
  //获取到编辑器数据
  const editorData = editor.getData();
  
  //发起一个请求,保存文档数据和编辑器数据
  sendRequestSaveData(docData, editorData);
  
  //此处还是要调用编辑器的save方法,以便编辑器计算并保存修改痕迹数据
  editor.save();
}

//保存按钮绑定事件
saveButton.addEventListener('click', ()=>{
  saveDocument();
})

  另一种情况是方式是文档数据和编辑器数据分别由两个请求存储,那就实现service.saveData,用于保存编辑器数据。请看下面的模拟代码:

//实现DocEditor.Service
const service = new DocEditor.Service();
//保存编辑器数据
service.saveData = function(data){
    return fetch("restful请求路径", {				//发起http请求保存编辑器数据
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
};
//其他service方法实现
//...

//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  //我们在打包配置中将public目录输出到了 doceditor/public,
  //所以此处需要配置为'./doceditor/' 或 'doceditor/'
  base: './doceditor/',
  
  docId: id,
  user: {
    name: user.name
    //name 是必须的,在记录修改痕迹时需要使用到
  },
  activity: {
    name: activity.name
    //name 是必须的,在记录修改痕迹时需要使用到
  },
  processInfo: process
}, service);
editor.load();

function saveDocument(){
  //获取文档的数据
  const docData = getDocData();
  //获取到编辑器数据
  const editorData = editor.getData();
  
  //发起一个请求,保存文档数据
  sendRequestSaveDocData(docData).then((id)=>{
    //保存文档数据后,得到文档id,并传入编辑器配置项
    //因为如果是新文档的话,在编辑器初始化的时候,是没有传入docId的
    editor.options.docId = id;
    //调用save方法,以便编辑器触发saveData和保存修改痕迹数据
    editor.save();
  });
}

//保存按钮绑定事件
saveButton.addEventListener('click', ()=>{
  saveDocument();
})

获取历史痕迹

  当点击“查看痕迹”按钮时,会触发service.listHistory方法,在点击历史痕迹列表时,会触发service.getHistory获取历史痕迹的具体信息。

  service.listHistory方法接收一个参数id,这是一个文档实例的id,由编辑器初始化时的配置项docId传入。需要返回一个promise,resvole历史痕迹列表数据的json对象数组,或直接返回json对象数组。格式如下:

[
  {
    "id": "xxxxxxxxxxxxx",         			  //痕迹内容唯一标识,用于获取具体的痕迹数据,由服务器生成
    "person": "huqi@huqi@P",              //痕迹修订的用户
    "category": "documenteditor",         //编辑id号,由创建编辑器时的options中id字段提供
    "activityName": "拟稿",               //产生痕迹的步骤
    "createTime": "2022-03-14 10:16:05",  //保存时由服务器自动生成
    "updateTime": "2022-03-14 10:16:05"   //保存时由服务器自动生成
    ...                                   //其他数据由创建编辑器时的options中的processInfo对象提供
  },
  ...
]

  service.getHistory方法接收一个参数id,这是由listHistory方法获取到的每一个成员的id,需要返回一个promise,resvole历史痕迹数据的json对象,或直接返回json对象。json格式如下:

{
  "id": "xxxxxxxxxxxxx",            //痕迹内容唯一标识,用于获取具体的痕迹数据,由服务器生成
  "person": "某某",                 //痕迹修订的用户 创建编辑器时的options中的user.name
  "category": "documenteditor",     //编辑id号,由创建编辑器时的options中id字段提供
  "data": "...",                        //修订痕迹数据,保存时的data
  "json": {}                            //将data中的文本转换为json对象(JSON.parse)
  "activityName": "拟稿",               //产生痕迹的步骤 创建编辑器时的options中的activity.name
  "createTime": "2022-03-12 17:23:40",  //保存时由服务器自动生成
  "updateTime": "2022-03-12 17:23:40"   //保存时由服务器自动生成
}

  这里需要注意的是有一个名为“json”的成员,它其实就是对“data”成员进行JSON.parse后的结果。在保存历史痕迹时,是没有“json”这个成员的,所以一般情况下,我们会在getHistory方法中对data进行JSON.parse:

//获取历史痕迹数据
service.getHistory = async function(id){
  cosnst res = fetch("restful请求路径/id");	//发起http请求获取单条历史修订痕迹数据
  const historyData = await res.json();
  const patchs = JSON.parse(historyData.data);
  historyData.json = patchs;
  return historyData;
};

保存历史痕迹

  在你保存文档时,需要调用编辑器的save方法,此方法会计算本次正文内容修改的痕迹,并触发service.saveData和service.saveHistory方法。

  service.saveHistory方法接收一个参数data,这是历史痕迹数据的json格式,并有一个docId成员,存储了当前文档的id,这是由编辑器初始化时的配置项docId传入的。data参数格式如下:

//data为要保存的数据,格式如下:
{
  "docId": "xxxx"                 //当前文档的唯一标识,创建编辑器时的options中的docId
  "category": "documenteditor",   //编辑id号,由创建编辑器时的options中id字段提供
  "data": "...",                  //修订痕迹数据
  "person": "测试",                //修订用户 创建编辑器时的options中的user.name
  "activityName": "核稿"            //修订时的活动状态 创建编辑器时的options中的activity.name
  ...                            //其他数据由创建编辑器时的options中的processInfo对象提供
}



获取正编辑的手写签批数据

  当点击“手写签批”按钮时,会触发service.getEditedHandwriting方法。

  由于获取手写签批数据除了当前的docId,还有其他的可能参数,比如当前人或者待办id,因此在触发service.getEditedHandwriting的时候,会传入编辑器初始化的配置项。service.getEditedHandwriting方法接收一个参数options,这是编辑器初始化时的配置项。

const service = new DocEditor.Service();
//实现获取当前处理人编辑的手写数据
//options为编辑器初始化的配置项
service.getEditedHandwriting = function(options){
  const url = "http://abc.com/handwirting/task/"+options.taskId; //业务中可能是根据taskId获取
  const res = fetch(url);	//发起http请求获取当前处理人编辑的手写数据
  return res.json();										//返回一个resvole了json对象的Promise
}
//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
  taskId: "" //业务中可能是待办的id
  ...
}, service);
editor.load();

service.getEditedHandwriting服务需要返回一个promise,resvole手写签批数据的json对象数组,或直接返回json对象数组。

如果返回的数据使用图片id,会触发service.getHandwritingImage获取根据图片id获取图片地址或者是图片base64编码后的数据;如果返回的数据返回src,则不触发service.getHandwritingImage。

格式如下:

{
   "id": "bfc6cc5b-e171-4f1a-83a0-78a40cf6a581", //正在编辑的手写签批id
   "activityName": "确认",                       //手写签批的步骤  创建编辑器时的options中的activity.name
   "person": "张三@zhangsan@P",                  //签批的用户
   "status": 1,                                  //签批类型,1表示正在编辑中,还未提交(提交后不允许编辑)
   "inputList": [                                //用输入法输入的文本框
       {
           "coordinates":{ //用输入法输入的文本框的位置,top\left\right\bottom是相对于编辑器正文内容的位置
               "left":10,
               "top":30,
               "width":200,
               "height":100,
               "right":700,
               "bottom":900
           },
           "styles":{ //用输入法输入的文本的样式
               "color":"#4bacc6",
               "font-size":"32px"
           },
           "html":"手写输入内容" ////用输入法输入的内容
       }
     ],
   "imageList": [                            //用笔画画出的图片列表
      {
           "id": "4b6f4164-2856-44c8-bd0a-4c43f6b34ff8", //签批图片的id, 和src二选一,如果使用id,需要实现 service.getHandwritingImage 方法
           "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAA...", //签批图片的base64编码或图片地址, 和id二选一,src优先
           "width":"793.6875",                                                 //图片宽度
           "height":"1000"                                                     //图片高度
       },
       {
           "src": "",                                  //src为空及id为空(或无src及id),表示无该页无签批内容
           "width": "793.671875",                                              //占位宽度
           "height":"215"                                                      //占位高度
       }
     ]
 }

  

获取已提交的手写签批数据列表

   当编辑器的选项中开启了allowHandwritingLog,平台会触发 service.listHandwritingLog(docId) 来查询本docId对应的所有已提交的手写签批数据列表。如果有数据会显示按钮及数量:

const service = new DocEditor.Service();
//返回当前文档的手写签批记录(已提交的)列表,返回一个数组列表
//docId为文档id
service.listHandwritingLog = function(docId){
  const res = fetch("restful请求路径");	//发起http请求获取当前文档的手写签批记录
  return res.json();										//返回一个resvole了json对象的Promise
}
//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
  docId: "" //文档id
  ...
}, service);
editor.load();

service.listHandwritingLog服务需要返回一个promise,resvole提交的手写签批列表数据的json对象数组,或直接返回json对象数组。

返回单个手写签批对象中需要包含status为2或者3,2表示不带背景保存的记录,3表示带正文背景保存的记录。

如果service.listHandwritingLog返回的数据使用图片id,会触发service.getHandwritingImage获取根据图片id获取图片地址或者是图片base64编码后的数据;如果返回的数据返回src,则不触发service.getHandwritingImage。

格式如下:

[
     //带正文背景保存的记录
     {
         "status": 3,                   //签批记录的类别,3表示带正文背景保存的记录
         "image": {                                        //带正文保存的签批图片
             "id": "4b6f4164-2856-44c8-bd0a-4c43f6b34ff8",       //签批图片的id, 和src二选一,如果使用id,需要实现 service.getHandwritingImage 方法
             "src": "data:image/png;base64,iVBORw0KGgoAAAA..." //签批图片的base64编码或图片地址, 和id二选一,src优先
         },
         "id": "0d35a43e-8cb5-4af8-ac6a-da681221c350",           //签批记录id,由服务器生成
         "activityName": "核稿",                                 //产生签批的步骤
         "person": "张三@zhangsan@P",                            //签批的用户
         "createTime": "2022-05-30 15:19:13",                    //保存时由服务器自动生成
         "updateTime": "2022-05-30 15:19:13",                    //保存时由服务器自动生成
         ...     //其他自定义的数据
     },
     //不带正文背景保存的记录
     {
         "status": 2,                  //签批记录的类别,2表示不带背景保存的记录
         "id": "dc3bc8d1-0d2a-43e6-a44e-9036c058cf70",           //签批记录id,由服务器生成
         "activityName": "办理",                                 //产生签批的步骤
         "person": "李四@lisi@P",                                //签批的用户
         "createTime": "2022-05-30 15:20:43",                    //保存时由服务器自动生成
         "updateTime": "2022-05-30 15:20:43",                    //保存时由服务器自动生成
         "imageList": [                                    //不带正文保存的签批图片信息
             {
                 "id": "4b6f4164-2856-44c8-bd0a-4c43f6b34ff8", //签批图片的id, 和src二选一,如果使用id,需要实现 service.getHandwritingImage 方法
                 "src": "data:image/png;base64,iVBORw0KGgoAAAA...", //签批图片的base64编码或图片地址, 和id二选一
                 "type": "image",                                 //表示这是一张图片
                 "width": "793.671875",                           //所占宽度
                 "height": "1000",                                //所占高度
                 ... //其他自定义的数据
             },
             {
                 "type": "placeholder",                           //表示这个位置没有图片,只占一个位置
                 "width": "793.671875",                           //所占宽度
                 "height": "701",                                 //所占高度
                 ... //其他自定义的数据
             }
         ]
     }
 ]

  

获取手写签批图片

获取正在编辑的手写签批数据(service.getEditedHandwriting)、获取历史手写签批记录列表(service.listHandwriting)都可能有包含图片。这两个服务可以直接返回图片的src字段,src字段可以是url地址,也可以是经过位编码的图片数据。这两个服务也可以返回图片的id,然后再调用service.getHandwritingImage服务来获取图片的地址。

service.getHandwritingImage有两个参数,第一个参数是图片的id,第二个参数是图片的类型,为数字,获取图片的类型,1表示正在编辑的手写签批图片,2表示签批历史记录里不带正文背景的图片,3表示历史记录里带正文背景的图片。

我们需要service.getHandwritingImage返回一个promise,resvole图片的src数据,或直接返回src字符串。

如:

const service = new DocEditor.Service();
//imageId 根据getEditedHandwriting或listHandwritingLog方法返回的数据中包含的图片id
//status 获取图片的类型
service.getHandwritingImage = function(imageId, status){
  switch (status) {
      case 1: //1表示正在编辑的手写签批图片
          return "http://www.aaa.net/handwriting/edting/"+imageId;
      case 2: //2表示签批历史记录里不带正文背景的图片
          return "http://www.aaa.net/handwriting/without/"+imageId;
      case 3: //3表示历史记录里带正文背景的图片
          return "http://www.aaa.net/handwriting/with/"+imageId;
  }
}
//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
    ...
}, service);
editor.load();

保存或提交手写签批数据

当用户点击了“手写签批”按钮,并且进行写画,或者输入了文字。当文档保存的时候需要同时保存手写签批数据到后台。

手写签批数据的保存/提交一共有三种方式:

1、只保存数据,当用户重新打开文档的时候需要获取上次保存的手写数据重新进行编辑。系统中对应状态1。

2、提交签批数据,形成签批记录,重新打开文档不能编辑提交过的数据了,只能查看记录。而且签批提交后,需要对正文进行编辑如发文。系统中对应状态2。

3、提交签批数据,形成签批记录,重新打开文档不能编辑提交过的数据了,只能查看记录。而且签批提交后,需要对正文进行编辑如收文。系统中对应状态3。

对于这三种情况,我们分别调用不同的服务来保存/提交数据。

保存

我们可以通过editor.save(1)在保存编辑器正文数据的同时保存手写签批数据。

也可以调用editor.saveHandwriting()来单独保存手写签批数据。

保存手写签批数据需调用方法 service.saveHandwriting(data)进行和服务端的交互。

const service = new DocEditor.Service();
//保存手写签批数据服务
service.saveHandwriting = function(data){
  return fetch("restful请求路径", {				//发起http请求保存手写签批数据
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}
//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
  taskId: "" //业务中可能是待办的id
    ...
}, service);
editor.load();
 
editor.save(1);  //保存编辑器正文数据的同时保存手写签批数据
//或者
editor.saveHandwriting() //单独保存手写签批数据
{
  "docId": "aaaaa",                 //当前文档的唯一标识,创建编辑器时的options中的docId
  "id": "bbbbbbbb",                 //当前签批的唯一标识,依赖于getEditedHandwriting获取的数据是否包含id。如果没有,表示新建。
  "activityName": "确认",                       //手写签批的步骤  创建编辑器时的options中的activity.name
  "person": "张三@zhangsan@P",                  //签批的用户
  "status": 1,                                  //签批类型,1表示正在编辑中,还未提交(提交后不允许编辑)
  "inputList": [                                //用输入法输入的文本框
    {
      "coordinates":{ //用输入法输入的文本框的位置,top\left\right\bottom是相对于编辑器正文内容的位置
        "left":10,
        "top":30,
        "width":200,
        "height":100,
        "right":700,
        "bottom":900
      },
      "styles":{ //用输入法输入的文本的样式
        "color":"#4bacc6",
        "font-size":"32px"
      },
      "html":"手写输入内容" ////用输入法输入的内容
    }
  ],
  "imageList": [                            //用笔画画出的图片列表
    {
      "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAA...", //签批图片base64编码,
      "width":"793.6875",                                                 //图片宽度
      "height":"1000"                                                     //图片高度
    },
    {
      "src": "",                                                          //src为空表示无该页无签批内容
      "width": "793.671875",                                              //占位宽度
      "height":"215"                                                      //占位高度
    }
  ]
}

不带正文背景提交

我们可以通过editor.save(2)在保存编辑器正文数据的同时不带背景提交。如果当前用户保存过手写签批数据但是没有提交,系统会根据编辑器配置里的hangwrting.notice的设置来弹出对话框提醒用户打开手写签批再提交,同时返回false且不保存正文数据和痕迹数据;这个时候应该检查返回结果判断后续代码的执行。

也可以调用editor.submitHandwriting(false)来单独保存手写签批数据。有3种返回值:

1、用户进行了手写签批,保存成功,返回service.submitHandwritingWithoutDoc(data)返回的数据。

2、用户没有进行手写签批,返回 true

3、用户保存过手写签批数据但是没有提交,系统会根据编辑器配置里的handwriting.notice的设置来弹出对话框提醒用户打开手写签批再提交,返回false

保存手写签批数据需调用方法 service.submitHandwritingWithoutDoc(data)进行和服务端的交互。

const service = new DocEditor.Service();
//保存手写签批数据服务
service.submitHandwritingWithoutDoc = function(data){
  return fetch("restful请求路径", {				//发起http请求提交手写签批数据
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}
//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
  taskId: "", //业务中可能是待办的id
  handwriting: {
  	notice: true //是否提示
  }
    ...
}, service);
editor.load();
 
if( editor.save(2) === false ){  //保存正文、痕迹、不带背景提交手写签批,并判断
    //do someting
}; 
//或者
const result = editor.submitHandwriting(false) //单独不带背景提交手写签批
//result 可能是 或后台返回的数据,true,flase
{
      "docId": "aaaaa",                 //当前文档的唯一标识,创建编辑器时的options中的docId
      "id": "bbbbbbbb",                //当前签批的唯一标识,依赖于getEditedHandwriting获取的数据是否包含id。如果没有,表示新建。
      "activityName": "确认",                       //手写签批的步骤  创建编辑器时的options中的activity.name
      "person": "张三@zhangsan@P",                  //签批的用户
      "status": 2,                                  //签批类型,2表示不带背景提交
      "imageList": [                            //用笔画画出的图片列表
         {
           "src": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAA...", //签批图片base64编码,
           "width":"793.6875",                                                 //图片宽度
           "height":"1000"                                                     //图片高度
         },
         {
           "src": "",                                                          //src为空表示无该页无签批内容
           "width": "793.671875",                                              //占位宽度
           "height":"215"                                                      //占位高度
         }
     ]
 }

带正文背景提交

我们可以通过editor.save(3)在保存编辑器正文数据的同时带背景提交。如果当前用户保存过手写签批数据但是没有提交,系统会根据编辑器配置里的hangwrting.notice的设置来弹出对话框提醒用户打开手写签批再提交,同时返回false且不保存正文数据和痕迹数据;这个时候应该检查返回结果判断后续代码的执行。

也可以调用editor.submitHandwriting(true)来单独保存手写签批数据。有3种返回值:

1、用户进行了手写签批,保存成功,返回service.submitHandwritingWithDoc(data)返回的数据。

2、用户没有进行手写签批,返回 true

3、用户保存过手写签批数据但是没有提交,系统会根据编辑器配置里的handwriting.notice的设置来弹出对话框提醒用户打开手写签批再提交,返回false

保存手写签批数据需调用方法 service.submitHandwritingWithDoc(data)进行和服务端的交互。

const service = new DocEditor.Service();
//保存手写签批数据服务
service.submitHandwritingWithDoc = function(data){
  return fetch("restful请求路径", {				//发起http请求提交手写签批数据
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}
//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
  taskId: "", //业务中可能是待办的id
  handwriting: {
  	notice: true //是否提示
  }
    ...
}, service);
editor.load();
 
if( editor.save(3) === false ){  //保存正文、痕迹、带背景提交手写签批,并判断
    //do someting
}; 
//或者
const result = editor.submitHandwriting(true) //单独带背景提交手写签批
//result 可能是 或后台返回的数据,true,flase
{
  "docId": "aaaaa",                 //当前文档的唯一标识,创建编辑器时的options中的docId
  "id": "bbbbbbbb",                 //当前签批的唯一标识,依赖于getEditedHandwriting获取的数据是否包含id。如果没有,表示新建。
  "activityName": "确认",                       //手写签批的步骤  创建编辑器时的options中的activity.name
  "person": "张三@zhangsan@P",                  //签批的用户
  "status": 3,                                  //签批类型,3表示带正文背景提交
  "htmlContent": "<div>....</div>",              //包含正文和手写签批图片的html内容,需要后台
  "htmlWidth": "793.671875",                     //html内容的宽度
  "htmlHeight": "1000"                           //html内容的高度
 }

html内容转图片

如果编辑器选项开启了手写签批的输入法设置 handwriting.inputEnable为true。手写签批中允许用户输入文字内容,如下图:

在我们进行手写签批的提交时,需要将用户输入的html内容转换成图片,再将图片内容插入到canvas中。这个时候需要调用到service.htmlToImage(data)方法同服务器进行交互,并获取图片地址。

const service = new DocEditor.Service();
//html转图片, 获取图片地址
service.htmlToImage = function(data){
    return fetch("restful请求路径", {				//html转图片, 获取图片地址
      "method": "post",
      "body": data,
      "headers": {
        "Content-Type": 'application/json'
      }
    });	
}
//初始化编辑器,并传入相关参数
const editor = DocEditor.createEditor(div, {
  base: './doceditor/',
  taskId: "", //业务中可能是待办的id
  handwriting: {
  	notice: true //是否提示
  }
    ...
}, service);
editor.load();

//下面的4个执行有可能会触发service.htmlToImage(data)
editor.save(2)
//或者
editor.submitHandwriting(false) //单独带背景提交手写签批
//或者
editor.save(3)
//或者
editor.submitHandwriting(true) //单独带背景提交手写签批
{
      workHtml: "<div>...</div>",
      htmlWidth: 200, //html正文宽度,允许为空.
      htmlHeight: 300, //html正文高度,允许为空.
      startX: 10,    //html的X轴开始位置,允许为空.
      startY: 20,    //html的Y轴开始位置,允许为空.
      omitBackground: true //背景是否透明
}