/**
* 公文编辑器。符合《党政机关公文格式》国家标准(GB/T 9704-2012)
* @class DocEditor
* @param {Element} el 要装载编辑器的Element对象
* @param {options} [options] 公文编辑配置数据数据
* @param {Service} [service] 公文编辑请求对象,需要调用者实现。
*
* @example
* //通过script标签引用
* //将build后的dist目录部署到服务器web目录,dist可更改名称,然后通过script标签引入
*<html>
<head>
<title>docEditor</title>
<script src="./dist/docEditor.js"></script>
</head>
<body>
<div></div>
<script>
DocEditor.createEditor("div", {
//此处配置所需要的参数
}).load()
</script>
</body>
</html>
*
* @example
* //使用 ES Module 模块引用
* //1、将源码包放到项目目录中。
* //2、使用 npm install <doceditor路径> 进行安装
* //3、打包配置,需要将doceditor下的public目录部署到输出目录,如果您使用webpack,在config中使用CopyPlugin插件:
* plugins: [
new CopyPlugin({
patterns: [
{ from: "doceditor/public", to: "doceditor/public" }
],
})
]
*
* //4、在代码中使用。
* import DocEditor from '@o2oa/doceditor'
* var div = document.createElement("div");
document.body.appendChild(div)
const editor = DocEditor.createEditor(div, {
'base': './doceditor/' //我们在打包配置中将public目录输出到了 doceditor/public,所以此处需要配置为'./doceditor/' 或 'doceditor/'
//此处配置其他所需要的参数
});
editor.load().then(()=>{
//编辑器加载完成
});
*
* @example
* //使用 CommandJS 模块引用
* //与 ES Module 模块基本相同,只是通过require函数引入DocEditor
*
* const DocEditor = require('@o2oa/doceditor');
* //后面与 ES Module 模块相同
*/
class DocEditor{
/**
* 编辑器配置参数
* @typedef {Object} options
* @example
* {
* "base": "", //编辑器引用的基础路径。如果使用<script>标签引用,一般情况下,会自动计算引用路径,此处保持为空,就可以。
* //当使用模块化ESModule 或 CommonJS引用时, 需要将base设置为 doceditor/public目录的部署路径。
* "id": "documenteditor", //编辑器标识
* "name": "", //编辑器名称
* "readonly": false, //是否只读
* "lp": "zh-cn", //语言,目前只有zh-cn 和 en
* "mobile": false, //是否时移动端展现,
* "zIndex": {
* "toolbar": 2000, //操作条的z-inde值
* "histroy": 20000, //痕迹记录容器的z-inde值
* "fullScreen": 1000000 //全屏模式的基础z-index值
* },
* "defaultValue": { //编辑器数据默认值
"copies": "", //份数
"secret": "", //密级
"priority": "", //紧急度
"redHeader": "文件红头", //文件红头,允许html
"fileno": "[文号]", //文号
"signerTitle": "签发人:", //签发人标题
"signer": "[签发人]", //签发人,允许文本数组
"subject": "[文件标题]", //文件标题
"mainSend": "[主送单位:]", //主送单位
"filetext": "[请在此处编辑正文内容]", //正文
"attachmentTitle": "附件:", //附件说明标题
"attachment": "", //附件说明列表,允许数组
"issuanceUnit": "[发文机关]", //发文机关
"issuanceDate": "[成文日期]", //成文日期
"annotation": "", //附注
"copytoTitle": "抄送:", //抄送标题
"copyto": "[抄送]", //抄送
"copyto2Title": "发:",
"copyto2": "[发]",
"editionUnit": "[印发机关]", //印发机关
"editionDate": "[印发日期]", //印发日期
"meetingAttendTitle": "出席:",
"meetingLeaveTitle": "请假:",
"meetingSitTitle": "列席:",
"meetingAttend": "", //会议出席
"meetingLeave": "", //会议请假
"meetingSit": "", //会议列席
"meetingRecord": "" //会议记录
},
"documentTempleteType": "sys", //公文模板类型,取值 "sys"或 "cus"; sys 标识系统内置模板,documentTempleteName字段生效; cus 表示自定义模板,documentTempleteUrl字段生效
"documentTempleteName": "standard", //内置模板名称,见 src/editor/templete.json, 模板取值:
//standard (标准公文类); meeting (纪要通报类); party-meeting (党委纪要类); letter (函类); command (命令类); party(党委纪委类); combine(联合发文类); empty (空模板(仅正文))
"documentTempleteUrl" : "", //自定义模板url路径
"allowEdit": "y", //是否允许编辑 "y" 或 "n" 或 "s" 表示根据脚本确定
"allowPrint": "y", //是否允许打印 "y" 或 "n" 或 "s" 表示根据脚本确定
"allowHistory": "y", //是否允许查看痕迹 "y" 或 "n" 或 "s" 表示根据脚本确定
"allowHandwriting": "y", //是否允许查看手写签批 "y" 或 "n" 或 "s" 表示根据脚本确定
"allowHandwritingLog": "y", //有手写签批记录的情况下,是否允许查看手写签批记录, "y" 或 "n" 或 "s" 表示根据脚本确定
"allowEditScript": null, //判断是否允许编辑的脚本(allowEdit为"s"时有效),一个返回boolean型的function,或者是 {"code": "return true"},这样的代码片段
"allowPrintScript": null, //判断是否允许打印的脚本(allowPrint"s"时有效),一个返回boolean型的function,或者是 {"code": "return true"},这样的代码片段
"historyMode": "task", //痕迹保留模式:"task"或者"save"。"save"模式:每次保存文档时记录痕迹;"task"模式:每个task只记录最后一次提交的痕迹
"historyCollapse": "n", //显示痕迹时是否默认折叠修改项
"resetPasteTable": "y", //当有外部表格被粘贴时,是否重建表格
"allowHistoryScript": null, //判断是否允许查看痕迹的脚本(allowHistory"s"时有效),一个返回boolean型的function,或者是 {"code": "return true"},这样的代码片段
"allowHandwritingScript": null, //判断是否允许查看痕迹的脚本(allowHandwriting"s"时有效),一个返回boolean型的function,或者是 {"code": "return true"},这样的代码片段
"allowHandwritingLogScript": null, //是否允许查看手写签批记录,判断是否允许查看痕迹的脚本(allowHandwritingLog"s"时有效),一个返回boolean型的function,或者是 {"code": "return true"},这样的代码片段
"canScale": true, //是否允许缩放 true 或 false
"fullWidth": true, //自动将半角空格转换为全角 true 或 false
"textIndent": true, //段落首行自动缩进 true 或 false
"canFullScreen": true, //是否允许全屏 true 或 false
"toWordSeal": true, //转换word时,是否显示图片章 true 或 false
"firstPageNumber": true, //转换word,第一页是否显示页码 true 或 false
"wordConversionEncryption": false, //转换word,是否启用文档保护 true 或 false
"copiesSecretPriorityShow": "y", //份号、密级、紧急度是否显示 "y" 或 "n"
"copiesShow": "a", //份号是否显示 "y":显示; "n":不显示; "a":自动(有值就显示,否则隐藏); "s": 根据脚本确定(脚本返回true显示,否则隐藏)
"copiesShowScript": null, //通过脚本判断份号是否显示(copiesShow为"s"时有效),一个返回boolean型的function,或者是 {"code": "return true"},这样的代码片段
"copiesValueType": "data", //份号数据绑定类型,"data":绑定表单上的一个可输入字段(copiesValueData); "script":通过脚本绑定值(redHeaderValueScript)
"copiesValueData": "", //份号数据绑定的表单字段选择器,如"#subject",表示id为subject的dom元素。
"copiesValueScript": null, //通过脚本绑定数据,copiesValueType为“script”时生效。一个function,或者是 {"code": "return '数据'"},这样的代码片段
... //所有公文元素都有这五个字段,他们的含义都是一样的,可以看src/editor/options.json文件
"subjectEdit" : "y", //份号是否允许编辑 "y"、"n" 或 "s": 根据脚本确定(脚本返回true可编辑,否则不可编辑)
"subjectEditScript": null, //通过脚本判断标题是否可编辑(subjectEdit"s"时有效),一个返回boolean型的function,或者是 {"code": "return true"},这样的代码片段
"subjectFontFamily": "方正小标宋简体", //标题字体
"customFields": { //模板中自定义元素数据绑定,这个样例的意思是将自定义元素layout_opinions与表单字段#opinions的只绑定
"layout_opinions" : "#opinions" //模板元素设置class为“doc_layout”,并增加属性“data-doc-layout='xxxx'”就是一个名为xxxx的自定义元素
}, //这个例子中,模板中应该有一个类似 <div class='doc_layout' data-doc-layout='layout_opinions'></div> 这样的元素
"ckeditConfigOptions" //ckeditor编辑器配置参数,一个返回Object类型的function,或者是 {"code": "return {}"},这样的代码片段
"recordScale": false, //是否记录用户设置的缩放比例,下次打开时以这个比例显示
"autoScale": "auto", //是否自动调整比例。当屏幕足够大,显示100%,当屏幕不足以显示100%比例时,自动将宽度缩小到展现文档内容
"fullScreenDom": null, //全屏时参照的dom对象,为空时就是document.body
"user": { //当前用户名称
"name": "测试"
},
"activity": { //当前活动名称
"name": "核稿"
},
"processInfo": {}, //文档或流程相关的扩展信息
"docId": "", //当前文档的唯一标识,一般情况下是流程实例的id
"taskId": "" //当前文档的任务唯一标识,一般情况下是当前待办的id,在痕迹保留模式(historyMode)为"task"时,必须提供
"handwriting": { //手写签批参数
"notice": true, //如果提交手写签批的时候,用户当前未打开手写签批,且系统中存在该用户的未提交签批内容,系统是否提示用户打开手写签批
"lineWidth" : 1, //画笔初始粗细,px
"color" : "#000000", //画笔初始颜色值
"eraserRadiusSize": 20, //橡皮初始粗细,px
"fontSize": "16", //输入法初始字体大小, px
"fontSizeList": ["10", "12", "14", "16", "18", "24", "32", "48"], //字体大小可选值
"pageHeight": 1000, //每页canvas高度,最后1页取实际高度,需要注意的是不同浏览器对canvas的尺寸都是有不同限制的
"inputEnable": true, //是否启用输入法功能
"eraserEnable": true, //是否启用橡皮功能
"tools": [ //操作条位置和启用操作,|表示分隔线
"|"
"undo", //撤销
"redo", "|", //重做
"eraser", //橡皮
"input", //输入法
"pen", "|", //笔画
"eraserRadius", //橡皮尺寸
"size", //笔画粗细
"color", //笔画颜色和输入法颜色
"fontSize", "|", //输入法尺寸
"reset" //撤销
]
},
"handwritingLog": { //手写历史记录界面
"colorList": [ //不带背景签批记录展现的颜色值列表,当签批记录超过该列表长度,系统会产生随机颜色
"#00b050","#4f81bd","#BAE637", "#36CFC9",
"#5C0011", "#1890FF","#135200", "#906EDB",
"#391085", "#FF85C0","#FA8C16","#061178",
"#9E1068","#D4380D","#FFD300", "#333333"
]
}
* }
*/
options;
/**
* 编辑器加载前触发。
* @event DocEditor#beforeLoad
*/
/**
* 编辑器加载前触发。
* @event DocEditor#queryLoad
*/
/**
* 编辑器加载后触发。
* @event DocEditor#postLoad
*/
/**
* 编辑器加载后触发。
* @event DocEditor#load
*/
/**
* 公文页面被重画后触发。
* @event DocEditor#loadPage
*/
/**
* 正文中粘贴内容时触发
* @event DocEditor#paste
*/
/**
* 正文改变后触发。
* @event DocEditor#change
*/
/**
* 正文编辑器获得焦点时触发。
* @event DocEditor#focus
*/
/**
* 正文编辑器失去焦点时触发。
* @event DocEditor#blur
*/
/**
* 正文编辑器加载完成时触发。
* @event DocEditor#loaded
*/
/**
* 正文中粘贴内容后触发。
* @event DocEditor#afterPaste
*/
/**
* 全屏展示时触发。
* @event DocEditor#fullScreen
*/
/**
* 显示痕迹时触发。
* @event DocEditor#showHistory
*/
/**
* 保存痕迹之前触发。
* @event DocEditor#beforeSaveHistory
*/
/**
* 保存痕迹之后触发。
* @event DocEditor#afterSaveHistory
*/
/**
* 保存编辑器数据之前触发。
* @event DocEditor#beforeSave
*/
/**
* 保存编辑器数据之后触发。
* @event DocEditor#afterSave
*/
/**
* 保存手写签批数据之前触发。
* @event DocEditor#beforeSaveHandwriting
*/
/**
* 保存手写签批数据之后触发。
* @event DocEditor#afterSaveHandwriting
*/
/**
* 提交不带正文背景的手写签批数据之前触发。
* @event DocEditor#beforSubmitHandwritingWithoutDoc
*/
/**
* 提交不带正文背景的手写签批数据之后触发。
* @event DocEditor#afterSubmitHandwritingWithoutDoc
*/
/**
* 提交带正文背景的手写签批数据之前触发。
* @event DocEditor#beforSubmitHandwritingWithDoc
*/
/**
* 提交带正文背景的手写签批数据之后触发。
* @event DocEditor#afterSubmitHandwritingWithDoc
*/
/**
* 打开手写签批界面前触发。
* @event DocEditor#beforeHandWrite
*/
/**
* 打开手写签批界面后触发。
* @event DocEditor#afterHandWrite
*/
/**
* 退出手写签批界面前触发。
* @event DocEditor#beforeExitHandWrite
*/
/**
* 退出手写签批界面后触发。
* @event DocEditor#afterExitHandWrite
*/
/**
* 打开手写签批历史记录弹出层前触发。
* @event DocEditor#beforeShowHandWriteLog
*/
/**
* 打开手写签批历史记录弹出层后触发。
* @event DocEditor#afterShowHandWriteLog
*/
#eventList = {
'beforeLoad': [],
'queryLoad': [],
'postLoad': [],
'load': [],
'loadPage': [],
'paste': [],
'change': [],
'focus': [],
'blur': [],
'loaded': [],
'afterPaste': [],
'fullScreen': [],
'showHistory': [],
'beforeSaveHistory': [],
'afterSaveHistory': [],
'beforeSave': [],
'afterSave': []
};
/**
* @summary 创建编辑器
* @param {Element} el 要装载编辑器的Element对象
* @param {options} options 公文编辑配置数据数据
* @param {Service} service 公文编辑请求对象,需要调用者实现。
* @example
* const editor = DocEditor.createEditor(node);
* editor.load().then(()=>{
* //...
* });
*/
constructor(el, options, service){}
/**
* @summary 载入公文编辑器
* @param {Object} data 公文编辑数据
* @example
* const editor = DocEditor.createEditor(node);
* editor.load().then(()=>{
* //...
* });
*/
async load(data){};
/**
* @summary 重新载入公文编辑器
* @param {Object} options 公文编辑配置数据数据
* @param {Object} data 公文编辑数据
* @example
* const editor = DocEditor.createEditor(node);
* editor.reload().then(()=>{
* //...
* });
*/
async reload(options, data){};
/**
* @summary 销毁公文编辑器
* @example
* editor.destroy();
*/
destroy(){};
/**
* @summary 重新计算公文要素显示
* @example
* editor.redisplay();
*/
redisplay(){}
/**对正文进行模拟盖章(模板中必须有class为“doc_layout_seal”的img对象)
* @summary 对正文进行模拟盖章,此方法只是进行模拟盖章,通过图片显示,并非专业盖章,不具备法律效应。
* @param src{String} 盖章图片的url.
* @param position{integer} 要盖章的位置, 默认为0.
* @example
* editor.seal("../custom/img/seal.png", 0); //在第一个盖章位置进行模拟盖章
*/
seal(src, position){};
/**
* @summary 设置公文编辑器数据
* @param {Object} data 公文编辑数据
* @example
* const data = editor.getData();
* data.filetext = "测试内容";
* editor.setData(data);
*/
setData(data){};
/**
* @summary 获取公文编辑器数据
* @return {Object} 公文编辑器的数据
* @example
* const data = editor.getData();
*/
getData(){};
/**
* @summary 重新设置公文编辑器数据和展现
* @example
* const data = editor.resetData();
*/
resetData(){};
/**
* @summary 公文编辑器放大显示 5%(0.05)
* @example
* editor.zoomIn();
*/
zoomIn(){};
/**
* @summary 公文编辑器缩小显示 5%(0.05)
* @example
* editor.zoomOut();
*/
zoomOut(){};
/**设公文编辑器缩放
* @param {number} scale 缩放比例(0.5 - 2)
* @param {boolean} temporary 可选 是否是临时缩放(默认false)
* @example
* editor.zoom(1.3);
*/
zoom(scale, temporary){};
/**
* @summary 根据屏幕自动缩放正文大小
* @param {boolean} temporary 可选 是否是临时缩放(默认false)
* @example
* editor.autoZoom();
*/
autoZoom(temporary){};
/**
* @summary 进入阅读状态,正文不能编辑
* @example
* editor.readFiletext();
*/
readFiletext(){};
/**
* @summary 进入编辑状态,正文可编辑
* @example
* editor.editFiletext();
*/
editFiletext(){};
/**
* @summary 保存正文数据 (需要实现service.saveData方法来完成与服务器的交互)
* @param {Number} [handwritingStatus] 手写签批的处理,1表示保存手写签批数据(需实现service.saveHandwriting);
* 2表示不带背景提交数据(需实现service.submitHandwritingWithoutDoc),如果用户之前保存了签批,本次编辑未打开签批,会提示用户打开签批以便提交。且本方法返回false;
* 3表示带背景提交数据(需实现service.submitHandwritingWithDoc),如果用户之前保存了签批,本次编辑未打开签批,会提示用户打开签批以便提交。且本方法返回false;
* 没有该参数不处理手写签批。
* @return {Boolean} 见参数handwritingStatus
* @example
* editor.save(); //保存正文、历史
* editor.save(1); //保存正文、历史、手写签批
* editor.save(2); //保存正文、历史、不带背景提交手写签批
* editor.save(3); //保存正文、历史、带背景提交数据手写签批
*/
async save(handwritingStatus){};
/**
* @summary 保存修订痕迹数据。会计算正文内容与上一次保存或第一次打开时的差异,生成修订痕迹,并请求保存。(需要实现service.saveHistory方法来完成与服务器的交互)
* @example
* editor.saveHistory();
*/
saveHistory(){}
/**
* @summary 保存手写签批内容(数据的status为1)。保存后再次打开,允许编辑。(需要实现service.saveHandwriting方法来完成与服务器的交互)
* @example
* editor.saveHandwriting();
*/
async saveHandwriting(){}
/**
* @summary 提交手写签批内容
* @param {Boolean} [withDoc] 提交签批的处理方式,
* false 表示不带背景提交数据,数据的 status为2(需实现service.submitHandwritingWithoutDoc);
* true 表示带背景提交数据,数据的 status为3(需实现service.submitHandwritingWithDoc);
* @return {Object|Boolean}
* 如果用户当前打开了手写签批,为service.submitHandwritingWithoutDoc或service.submitHandwritingWithDoc返回的数据。
* 如果用户当前未打开手写签批,且系统中存在该用户的未提交签批内容(service.getEditedHandwriting()无数据或数据长度为空),本方法访问true。
* 如果用户当前未打开手写签批,且系统中存在该用户的未提交签批内容,系统提示用户打开手写签批,本方法返回false。
* @example
* editor.submitHandwriting(); //不带背景提交数据
* editor.submitHandwriting(false); //不带背景提交数据
* editor.submitHandwriting(true); //带背景提交数据
* @example
* var flag = editor.submitHandwriting(false); //不带背景提交数据
* if( flag === false )return false; //之前编辑过,本次未打开手写签批
*/
async submitHandwriting(withDoc){}
/**
* @summary 全屏显示
* @example
* editor.fullScreen();
*/
fullScreen(){};
/**将公文编辑器内容以html形式输出
* @return {String}
* @example
* var html = editor.getDocumentHtml();
*/
getDocumentHtml(){};
/**
* @summary 将公文转换为word
* @return {Promise} revole了word文件的Blob数据。
* @example
* editor.toWord();
*/
toWord(){};
/**
* @summary 将公文编辑转换为word文件,并下载
* @example
* editor.printDoc();
*/
async printDoc(e){};
/**
* @summary 进入痕迹查看状态
* @example
* editor.historyDoc();
*/
historyDoc(){};
/**
* @summary 退出痕迹查看状态
* @example
* editor.exitHistoryDoc();
*/
exitHistoryDoc(){};
/**
* @summary 为编辑器注入service对象,用于请求编辑器数据和保存数据等服务,
* @param {Object} obj 要注入到编辑器的对象
* @example
* import DocEditor from '@o2oa/doceditor';
* const node = document.querySelector('div');
* const editor = DocEditor.createEditor(node);
*
* class MyService extends DocEditor.Service{
* async listHistory() {
* //获取正文痕迹列表
* }
* async getHistory(id){
* //获取指定的正文痕迹比较数据
* }
* async saveHistory(data){
* //保存正文痕迹比较数据
* }
* async getData(){
* //获取编辑器数据
* }
* async saveData(data){
* //保存编辑器数据
* }
* async listHandwritingLog(docid){
* //返回当前文档的手写签批记录(已提交的)列表,返回一个数组列表
* }
* async getHandwritingImage(imageId, status){
* //根据图片id获取图片地址或者是图片base64编码后的数据
* //stauts为数字,获取图片的类型,1表示正在编辑的手写签批图片,2表示签批历史记录里不带正文背景的图片,3表示历史记录里带正文背景的图片
* }
* async getEditedHandwriting(options){
* //实现获取当前处理人编辑的手写数据
* }
* async saveHandwriting(data){
* //保存手写签批数据
* }
* async submitHandwritingWithDoc(data){
* //带正文背景提交手写签批
* }
* async submitHandwritingWithoutDoc(data){
* //不带正文背景提交手写签批
* }
* async htmlToImage(data){
* //html转图片, 获取图片地址
* }
* }
* const service = new MyService();
*
* editor.provide({service});
*
* editor.load().then(()=>{
* //...
* });
*/
provide(service){};
/**
* @summary 监听编辑器事件,
* @param {String} type 编辑器事件名称,可以是dom原生事件,这会将事件绑定到editorNode上
* @param {Functioin} listener 事件出发时执行函数
* @example
* editor.on('loadPage', (e)=>{
* //e.editor 编辑器对象
* });
*/
on(type, listener){};
/**
* @summary 删除编辑器事件监听
* @param {String} type 编辑器事件名称
* @param {Functioin} listener 需要从目标事件移除的 listener 函数。
* @example
* const listener = (e)=>{
* //e.editor 编辑器对象
* }
* editor.on('loadPage', listener); //监听编辑器事件
* editor.off('loadPage', listener); //删除编辑器事件监听
*/
off(type, listener){};
/**
* @summary 进入手写签批模式
* @param {Event} [ev] 鼠标事件,用于提示框的相关位置,如果没有ev,提示框居中显示。
* @example
* editor.handWrite();
*/
handWrite(ev){};
/**
* @summary 从手写签批模式退出
* @example
* editor.exitHandWrite();
*/
exitHandWrite(){};
/**
* @summary 如果有手写签批历史,显示手写签批历史弹出层
* @example
* editor.showHandWriteLog();
*/
showHandWriteLog(){};
/**
* @summary 如果显示了手写签批历史弹出层,隐藏它,并且隐藏所有的签批展现界面
* @example
* editor.hideHandWriteLog();
*/
hideHandWriteLog(){}
/**
* @summary 如果显示了手写签批历史弹出层,隐藏它
* @example
* editor.hideHandWriteLogTooltip();
*/
hideHandWriteLogTooltip(){}
}
export default DocEditor;