作為軟體開發人員,軟體做好後,接下來就是編寫文件。我自己也是做軟體的,經常有使用者詢問軟體的安裝與使用,
我一直很喜歡微軟的MSDN幫助系統,簡介、大氣,使用方便。
網上也找了很久,感覺一直沒有合適的,
所以,花了一週時間寫了一個仿MSDN的系統 kbase(演示見 http://demo.dotnetcms.org/kbase)。
這篇文章來分析在製作這個系統遇到的幾個問題以及總結。
如果分析微軟MSDN,不難發現,他的左邊是一個導航樹,中間是正文,右邊是正文的快速連結。
(1)樹導航
在選擇導航樹時,我最初考慮的是bootstrap-treeview,
不管從介面還是功能上,他和MSDN的幫助系統導航樹都很像。
但是,如果我們仔細觀察MSDN,他的導航樹裡,當點選父節點時是展開子節點,
只有點選“子節點”才能才會開啟正文(參考下圖)。
但是,這個功能bootstrap treeview控制的並不是很好。
bootstrap treeview點選父節點是開啟文字,只有點選父節點前面的“+”才會展開子節點。
所以,最終選擇了zTree,在zTree官方給的Demo裡,有一個Outlook風格的模板,簡直就是MSDN的原型。
同時,ztree提供的介面和功能遠遠比bootstrap-treeview強大,所以很快我就選中了她。
要使用zTree,首先定義zTree的配置seeting,然後在程式碼裡,重新了onClick事件。
在onClick事件裡,判斷使用者點選的節點有沒有子節點,
如果有子節點,就展開子節點,
如果沒有子節點,就開啟網址。
var setting = { view: { showLine: false, showIcon: false, selectedMulti: false, dblClickExpand: false, addDiyDom: addDiyDom }, data: { simpleData: { enable: true } }, callback: { onClick: onClick } }; function onClick(e, treeId, treeNode) { if (treeNode.children != null) { var zTree = $.fn.zTree.getZTreeObj("treeNav"); zTree.expandNode(treeNode); } else { if (treeNode.id > 0) { } else { window.location = "default.aspx?id=" + treeNode.id+"&title="+treeNode.name; } } } function addDiyDom(treeId, treeNode) { var spaceWidth = 5; var switchObj = $("#" + treeNode.tId + "_switch"), icoObj = $("#" + treeNode.tId + "_ico"); switchObj.remove(); icoObj.before(switchObj); if (treeNode.level >= 1) { var spaceStr = "<span style='display: inline-block;width:" + (spaceWidth * treeNode.level) + "px'></span>"; switchObj.before(spaceStr); } }
(2)導航樹的子節點是類別還是標題
但是,這樣又遇到第二個問題:
左邊導航樹裡的內容,到底是按照“分類”處理還是按照“新聞標題”處理。
開發過CMS(內容管理系統)的朋友都知道,一般CMS系統都是:
建立一個catetory分類,然後新聞會有一個標題title,和一個分類catID和分類表關聯。
那MSDN左邊導航樹,使用者點選的具體內容到底算“類別”還是“新聞標題”呢?
我最初的想法是算類別,左邊設想的是一張表,裡面儲存所有的導航樹“節點”,但是你能想象出來,
如果文章內容越來越多,構建導航樹維護是比較困難。
最終,我決定,MSDN導航樹,父節點都是“類別”,而葉節點才是新聞的標題,
系統實現裡,建了兩張表,這兩張表通過 SQL的union all 關鍵字進行合併,然後作為資料來源提供給zTree
select id, pId, catname as name, orderid from kb_cat union all select id, catid as pId, title as name, orderid from kb_news
(3)編輯器選擇
在一開始,我就定位了後臺編輯器必須使用Markdown(MD)編輯器,
原因很簡單,這個仿MSDN的系統更偏向知識的傳遞,注重的是內容而不是介面,
而傳統的HTML編寫幫助文件,會產生大量的“垃圾程式碼”,這不是我想要的。
因此,接下來就是開始尋找MD編輯器。
我最先想到的是部落格園後臺有markdown編輯器,所以看看部落格園怎麼做的吧
但是很快放棄使用部落格園的MD了,原因有2點:
(1)他的編寫和預覽是分開的,這不是我想要的,我希望左邊是錄入頁面,右邊是實時預覽。
(2)View Source頁面,天,部落格園的原始碼是全壓縮的JS, 完全看不到他引用了哪些JS。
算了,放棄把
接下來就是痛苦的尋找過程。
包括 幾款主流好用的markdown編輯器介紹 等,但是,都感覺差了那麼點意思,不是我想要的。
最終,皇天不負有心人,無意中點到了“葉子島”(叛道)網站,
然後看到了一個“ipandao(愛叛道)”的MD編輯器。
(題外話,這個編輯器名字太難記了,所以,軟體開發還是要取一個容易記憶的名字。)
點進去看看 https://pandao.github.io/editor.md/ 介面美觀,大方,左右佈局,提供實時預覽,提供自定義擴充套件,
而且內建和codemirror整合,支援程式碼高亮顯示,而且還開源,原始碼的JS裡也沒有使用太複雜的技術。
這正是我想要的,這真的是太好了。
很快,我就把這個系統整合到仿MSDN的系統裡。同時,自定義了工具欄,移除了沒用的,只保留10來個按鈕。
下面是程式碼的實現
<script type="text/javascript"> var testEditor; $(function () { testEditor = editormd("test-editormd", { width: "100%", height:520, placeholder: "", lineNumbers:true, path: "../javascript/pandao-markdown/lib/", toolbarIcons: function () { return ["bold", "quote", "|", "h3", "h4", "h5", "h6", "list-ul", "list-ol", "|", "link", "image", "|", "code", "code-block", "table"] }, imageUpload: true, imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"], imageUploadURL: "save_img.aspx", saveHTMLToTextarea : true }); }); </script>
(4)新聞內容的儲存
在上一步使用了ipandao的md後,他提供了2個方法用來獲取錄入的內容:
testEditor.getMarkdown(); // 獲取 Markdown 原始碼 testEditor.getHTML(); // 獲取 Textarea 儲存的 HTML 原始碼
接下來一個問題,使用者寫好的MD以怎麼的格式儲存到MSSQL裡?
如果直接儲存HTML,那麼後期使用者將無法編輯文章,因為MD無法直接載入HTML,他識別不了HTML。
如果直接儲存MD,那麼瀏覽器並不能識別MD,這就要使用者訪問幫助文件時,每次都JS解析MD,可能使用者感覺速度會沒那麼快。
如果同時儲存HTML和MD,前端瀏覽器顯示用HTML,後臺,使用者更新時用MD,通過程式儲存資料同步,這會佔用資料庫空間。
總之,基本上沒有完美的解決方法。
在我的做法裡,是直接儲存MD原始碼,然後前端使用者訪問時,利用MD提供的markdownToHTML方法,轉換為HTML進行渲染。
我看了MSDN,猜測他應該是MD和HTML同時儲存。
testEditor.markdownToHTML("contents");
(5)右邊快速預覽
右邊快速預覽其實是從MD裡提取<h3>標題實現的。
$(function () { editormd.markdownToHTML("contents"); let menu = "<h5>本頁內容</h4>"; $("#contents h3").each( function () { menu += "<a class='quick_a' href='#" + $(this).text() + "'>" + $(this).text() + "</a>"; } ); $("#rightmenu").html(menu); $("#rightmenu").pin({ minWidth: 800, padding: { top: 50 } }); });
在上面,還是用了一個外掛:jquery.pin()。
他的作用但是:當頁面過長,往下滾動時,他會把右邊導航“釘”在右上角。
這樣,一個仿MSDN核心功能介紹完了,剩下的就是普通的資料庫增刪讀寫了。
本系統演示見 http://demo.dotnetcms.org/kbase 使用者名稱 admin,密碼123456