markdown.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. $(function () {
  2. window.addDocumentModalFormHtml = $(this).find("form").html();
  3. window.editor = editormd("docEditor", {
  4. width : "100%",
  5. height : "100%",
  6. path : "/static/editor.md/lib/",
  7. toolbar : true,
  8. placeholder: "本编辑器支持Markdown编辑,左边编写,右边预览",
  9. imageUpload: true,
  10. imageFormats: ["jpg", "jpeg", "gif", "png", "JPG", "JPEG", "GIF", "PNG"],
  11. imageUploadURL: window.imageUploadURL ,
  12. toolbarModes : "full",
  13. fileUpload: true,
  14. fileUploadURL : window.fileUploadURL,
  15. taskList : true,
  16. flowChart : true,
  17. htmlDecode : "style,script,iframe,title,onmouseover,onmouseout,style",
  18. lineNumbers : false,
  19. tocStartLevel : 1,
  20. tocm : true,
  21. saveHTMLToTextarea : true,
  22. onload : function() {
  23. this.hideToolbar();
  24. var keyMap = {
  25. "Ctrl-S": function(cm) {
  26. saveDocument(false);
  27. },
  28. "Cmd-S" : function(cm){
  29. saveDocument(false);
  30. },
  31. "Ctrl-A": function(cm) {
  32. cm.execCommand("selectAll");
  33. }
  34. };
  35. this.addKeyMap(keyMap);
  36. var $select_node_id = window.treeCatalog.get_selected();
  37. if($select_node_id) {
  38. var $select_node = window.treeCatalog.get_node($select_node_id[0])
  39. if ($select_node) {
  40. $select_node.node = {
  41. id: $select_node.id
  42. };
  43. loadDocument($select_node);
  44. }
  45. }
  46. uploadImage("docEditor",function ($state, $res) {
  47. if($state === "before"){
  48. return layer.load(1, {
  49. shade: [0.1,'#fff'] //0.1透明度的白色背景
  50. });
  51. }else if($state === "success"){
  52. if($res.errcode === 0) {
  53. var value = '![](' + $res.url + ')';
  54. window.editor.insertValue(value);
  55. }
  56. }
  57. });
  58. },
  59. onchange : function () {
  60. resetEditorChanged(true);
  61. }
  62. });
  63. /**
  64. * 实现标题栏操作
  65. */
  66. $("#editormd-tools").on("click","a[class!='disabled']",function () {
  67. var name = $(this).find("i").attr("name");
  68. if(name === "attachment"){
  69. $("#uploadAttachModal").modal("show");
  70. }else if(name === "history"){
  71. window.documentHistory();
  72. }else if(name === "save"){
  73. saveDocument(false);
  74. }else if(name === "template"){
  75. $("#documentTemplateModal").modal("show");
  76. }else if(name === "sidebar"){
  77. $("#manualCategory").toggle(0,"swing",function () {
  78. var $then = $("#manualEditorContainer");
  79. var left = parseInt($then.css("left"));
  80. if(left > 0){
  81. window.editorContainerLeft = left;
  82. $then.css("left","0");
  83. }else{
  84. $then.css("left",window.editorContainerLeft + "px");
  85. }
  86. window.editor.resize();
  87. });
  88. }else if(name === "release"){
  89. if(Object.prototype.toString.call(window.documentCategory) === '[object Array]' && window.documentCategory.length > 0){
  90. $.ajax({
  91. url : window.releaseURL,
  92. data :{"identify" : window.book.identify },
  93. type : "post",
  94. dataType : "json",
  95. success : function (res) {
  96. if(res.errcode === 0){
  97. layer.msg("发布任务已推送到任务队列,稍后将在后台执行。");
  98. }else{
  99. layer.msg(res.message);
  100. }
  101. }
  102. });
  103. }else{
  104. layer.msg("没有需要发布的文档")
  105. }
  106. }else if(name === "tasks") {
  107. //插入GFM任务列表
  108. var cm = window.editor.cm;
  109. var selection = cm.getSelection();
  110. if (selection === "") {
  111. cm.replaceSelection("- [x] " + selection);
  112. }
  113. else {
  114. var selectionText = selection.split("\n");
  115. for (var i = 0, len = selectionText.length; i < len; i++) {
  116. selectionText[i] = (selectionText[i] === "") ? "" : "- [x] " + selectionText[i];
  117. }
  118. cm.replaceSelection(selectionText.join("\n"));
  119. }
  120. }else {
  121. var action = window.editor.toolbarHandlers[name];
  122. if (action !== "undefined") {
  123. $.proxy(action, window.editor)();
  124. window.editor.focus();
  125. }
  126. }
  127. }) ;
  128. /***
  129. * 加载指定的文档到编辑器中
  130. * @param $node
  131. */
  132. window.loadDocument = function($node) {
  133. var index = layer.load(1, {
  134. shade: [0.1,'#fff'] //0.1透明度的白色背景
  135. });
  136. $.get(window.editURL + $node.node.id ).done(function (res) {
  137. layer.close(index);
  138. resetEditor();
  139. if(res.errcode === 0){
  140. window.isLoad = true;
  141. window.editor.clear();
  142. window.editor.insertValue(res.data.markdown);
  143. window.editor.setCursor({line:0, ch:0});
  144. var node = { "id" : res.data.doc_id,'parent' : res.data.parent_id === 0 ? '#' : res.data.parent_id ,"text" : res.data.doc_name,"identify" : res.data.identify,"version" : res.data.version};
  145. pushDocumentCategory(node);
  146. window.selectNode = node;
  147. pushVueLists(res.data.attach);
  148. }else{
  149. layer.msg("文档加载失败");
  150. }
  151. }).fail(function () {
  152. layer.close(index);
  153. layer.msg("文档加载失败");
  154. });
  155. };
  156. /**
  157. * 保存文档到服务器
  158. * @param $is_cover 是否强制覆盖
  159. */
  160. function saveDocument($is_cover,callback) {
  161. var index = null;
  162. var node = window.selectNode;
  163. var content = window.editor.getMarkdown();
  164. var html = window.editor.getPreviewedHTML();
  165. var version = "";
  166. if(!node){
  167. layer.msg("获取当前文档信息失败");
  168. return;
  169. }
  170. var doc_id = parseInt(node.id);
  171. for(var i in window.documentCategory){
  172. var item = window.documentCategory[i];
  173. if(item.id === doc_id){
  174. version = item.version;
  175. break;
  176. }
  177. }
  178. $.ajax({
  179. beforeSend : function () {
  180. index = layer.load(1, {shade: [0.1,'#fff'] });
  181. },
  182. url : window.editURL,
  183. data : {"identify" : window.book.identify,"doc_id" : doc_id,"markdown" : content,"html" : html,"cover" : $is_cover ? "yes":"no","version": version},
  184. type :"post",
  185. dataType :"json",
  186. success : function (res) {
  187. layer.close(index);
  188. if(res.errcode === 0){
  189. resetEditorChanged(false);
  190. for(var i in window.documentCategory){
  191. var item = window.documentCategory[i];
  192. if(item.id === doc_id){
  193. window.documentCategory[i].version = res.data.version;
  194. break;
  195. }
  196. }
  197. if(typeof callback === "function"){
  198. callback();
  199. }
  200. }else if(res.errcode === 6005){
  201. var confirmIndex = layer.confirm('文档已被其他人修改确定覆盖已存在的文档吗?', {
  202. btn: ['确定','取消'] //按钮
  203. }, function(){
  204. layer.close(confirmIndex);
  205. saveDocument(true,callback);
  206. });
  207. }else{
  208. layer.msg(res.message);
  209. }
  210. }
  211. });
  212. }
  213. function resetEditor($node) {
  214. }
  215. /**
  216. * 设置编辑器变更状态
  217. * @param $is_change
  218. */
  219. function resetEditorChanged($is_change) {
  220. if($is_change && !window.isLoad ){
  221. $("#markdown-save").removeClass('disabled').addClass('change');
  222. }else{
  223. $("#markdown-save").removeClass('change').addClass('disabled');
  224. }
  225. window.isLoad = false;
  226. }
  227. /**
  228. * 添加顶级文档
  229. */
  230. $("#addDocumentForm").ajaxForm({
  231. beforeSubmit : function () {
  232. var doc_name = $.trim($("#documentName").val());
  233. if (doc_name === ""){
  234. return showError("目录名称不能为空","#add-error-message")
  235. }
  236. $("#btnSaveDocument").button("loading");
  237. return true;
  238. },
  239. success : function (res) {
  240. if(res.errcode === 0){
  241. var data = { "id" : res.data.doc_id,'parent' : res.data.parent_id === 0 ? '#' : res.data.parent_id ,"text" : res.data.doc_name,"identify" : res.data.identify,"version" : res.data.version};
  242. var node = window.treeCatalog.get_node(data.id);
  243. if(node){
  244. window.treeCatalog.rename_node({"id":data.id},data.text);
  245. }else {
  246. window.treeCatalog.create_node(data.parent, data);
  247. window.treeCatalog.deselect_all();
  248. window.treeCatalog.select_node(data);
  249. }
  250. pushDocumentCategory(data);
  251. $("#markdown-save").removeClass('change').addClass('disabled');
  252. $("#addDocumentModal").modal('hide');
  253. }else{
  254. showError(res.message,"#add-error-message")
  255. }
  256. $("#btnSaveDocument").button("reset");
  257. }
  258. });
  259. /**
  260. * 文档目录树
  261. */
  262. $("#sidebar").jstree({
  263. 'plugins': ["wholerow", "types", 'dnd', 'contextmenu'],
  264. "types": {
  265. "default": {
  266. "icon": false // 删除默认图标
  267. }
  268. },
  269. 'core': {
  270. 'check_callback': true,
  271. "multiple": false,
  272. 'animation': 0,
  273. "data": window.documentCategory
  274. },
  275. "contextmenu": {
  276. show_at_node: false,
  277. select_node: false,
  278. "items": {
  279. "添加文档": {
  280. "separator_before": false,
  281. "separator_after": true,
  282. "_disabled": false,
  283. "label": "添加文档",
  284. "icon": "fa fa-plus",
  285. "action": function (data) {
  286. var inst = $.jstree.reference(data.reference),
  287. node = inst.get_node(data.reference);
  288. openCreateCatalogDialog(node);
  289. }
  290. },
  291. "编辑": {
  292. "separator_before": false,
  293. "separator_after": true,
  294. "_disabled": false,
  295. "label": "编辑",
  296. "icon": "fa fa-edit",
  297. "action": function (data) {
  298. var inst = $.jstree.reference(data.reference);
  299. var node = inst.get_node(data.reference);
  300. openEditCatalogDialog(node);
  301. }
  302. },
  303. "删除": {
  304. "separator_before": false,
  305. "separator_after": true,
  306. "_disabled": false,
  307. "label": "删除",
  308. "icon": "fa fa-trash-o",
  309. "action": function (data) {
  310. var inst = $.jstree.reference(data.reference);
  311. var node = inst.get_node(data.reference);
  312. openDeleteDocumentDialog(node);
  313. }
  314. }
  315. }
  316. }
  317. }).on('loaded.jstree', function () {
  318. window.treeCatalog = $(this).jstree();
  319. }).on('select_node.jstree', function (node, selected, event) {
  320. if($("#markdown-save").hasClass('change')) {
  321. if(confirm("编辑内容未保存,需要保存吗?")){
  322. saveDocument(false,function () {
  323. loadDocument(selected);
  324. });
  325. return true;
  326. }
  327. }
  328. loadDocument(selected);
  329. }).on("move_node.jstree",jstree_save);
  330. $("#documentTemplateModal").on("click",".section>a[data-type]",function () {
  331. var $this = $(this).attr("data-type");
  332. var body = $("#template-" + $this).html();
  333. if (body) {
  334. window.isLoad = true;
  335. window.editor.clear();
  336. window.editor.insertValue(body);
  337. window.editor.setCursor({line: 0, ch: 0});
  338. resetEditorChanged(true);
  339. }
  340. $("#documentTemplateModal").modal('hide');
  341. });
  342. });