作为软件开发人员,软件做好后,接下来就是编写文档。我自己也是做软件的,经常有用户询问软件的安装与使用,

我一直很喜欢微软的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

仿MSDN的帮助系统的更多相关文章

  1. Windows XP SP3 Professional 微软(MSDN)官方原版系统

    Windows XP SP3 Professional 微软(MSDN)官方原版系统 Windows XP(版本号:5.1,开发代号:Whistler)是微软公司推出供个人电脑使用的操作系统,其RTM ...

  2. 仿5173游戏交易平台系统SQL注入(可直接脱裤)+Getshell

    最近没事登登好几年前玩过的游戏看看,发现有人喊高价收号,这一看就是骗子,这等骗子还想骗我?我就来看看这逗逼是怎么骗人的,结果发现这人给了一个说是 5173平台交易的网站,叫我直接把号的信息填上去然后填 ...

  3. 最全的微软msdn原版windows系统镜像和office下载地址集锦

    随着windows的发展,越来越多的人都热衷于微软的原版系统下载了,相比之前的版本比如winxp版本,windows vista/win7/win8/win8.1/win10后来的版本在安装方面也比较 ...

  4. win10全系列官方MSDN原版系统安装密钥、版本区别、镜像下载地址与激活教程

    微软发布win10正式版已经过去几天了,相信很多同学都心情高涨的装上了期待已久的win10系统,但也有很多同学面对win10系统的众多版本感到一脸茫然,的确,微软在win10系统版本上的划分确实有点多 ...

  5. 重装系统之制作U盘启动盘

    准备: 1.需要一个大于4G的U盘. 2.一个原版系统. 3.制作U盘启动盘的工具—ultraliso. 一.一个大于4G的U盘 制作启动盘将会格式化U盘,记得做好备份. 二.一个原版系统 至于你要装 ...

  6. Flask:Flask的模板系统和静态文件

    1.Flask模板系统 Django框架有自己独立的模板系统,而Flask是没有的,Flask默认采用jinjia2模板系统,jinjia2是仿写Django模板系统的一个第三方模块,但性能上要比Dj ...

  7. IO操作

    /// <summary> /// 文件读写操作/// </summary> public partial class TestIO : DevComponents.DotNe ...

  8. 【高清未加密】2015传智播客 最新21期c#asp.net 基础到就业班视频和源码

    [.NET]传智播客第[21]期就业班视频(高清无加密)本套2015年21期传智播客C#ASP.NET win10通用mvc+app开发视频教程附源码,是一套非常不错的asp.net自学视频教程,传智 ...

  9. C# 文件与目录的基本操作(System.IO)

    1. 文件操作 /// <summary> /// 文件读写操作 /// 为简化代码供大家学习,暂不考虑捕捉异常 /// </summary> public partial c ...

随机推荐

  1. Leetcode(5)-最长回文子串(包含动态规划以及Manacher算法)

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &quo ...

  2. Python Web Framework All In One

    Python Web Framework All In One Django and Flask are the top Python web frameworks so far. Django ht ...

  3. js GC & stack heap

    js GC & stack heap stack 栈,函数执行形成执行栈帧,变量名,指针 heap 堆,非结构化的数据(Object),分配的内存的存储空间 js 垃圾回收机制 https:/ ...

  4. auto responsive rem

    auto responsive rem 移动端适配 ;(function(win, lib) { var doc = win.document; var docEl = doc.documentEle ...

  5. js 监听ajax请求

    function hookSend(hook) { if (!XMLHttpRequest.prototype._oldSend) XMLHttpRequest.prototype._oldSend ...

  6. JS实现点击加载更多效果

    适用场景:后端直接把所有的文章都给你调出来了,但是领导又让做点击加载更多效果...(宝宝心里苦啊)   点击加载更多效果:         第一个和第二个参数分别是btn和ul的DOM(必填)     ...

  7. pycharm + git+gitlab的可视化界面操作

    前言: 写这篇博​​客,主要为了记录一套经过本人实践,并运行通过的操作gitlab流程. 通过以下步骤,可实现最基本的远程服务器(gitlab)和本地工具(pycharm)的,针对两端文件增删改查的及 ...

  8. C++算法代码——骨牌铺法

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1638 题目描述 输入 输入一个正整数,表示n. 输出 输出一个正整数,表示铺法. 样 ...

  9. HQYJ嵌入式学习笔记——C语言复习day2

    1.计算机的数值表示 数值类型和非数值类型 二进制 0,1 (0b1001) 八进制 0~7   (0146) 十进制 0~9 十六进制 0~f (0x3f) 八进制转二进制-->一位八进制数换 ...

  10. 使用PageHelper进行分页查询

    service层代码: public Result getDataSetList(String dataCode, String dataName, int pageIndex, int length ...