网上有些免费的在线HTML编辑器,有的功能实在是过于强大但显得臃肿不堪;有的外表轻松紧凑但又没有直接的源码提供。根据163、sina、sohu等门户网站邮箱里的编辑器样式,个人改造了一个功能简单的Editor:

编辑器一般包括二个部分: 工具条和文本区,文本区又可以通过按钮进行源码方式和文本方式的切换即存在文本域与源码域。

首先是采用一个标准的样式表来规范编辑器的页面,有以下基于图形toolbar.gif的文件editor.css:

toolbar.gif如下:

editor.css如下:
#dvPanel {...}{ position:relative;width:600px;height:240px; }

#dvToobar{...}{ padding-left:3px;padding-top:2px;background-color: #EEEEEE; border-top:1px solid #AAAAAA;border-right:1px solid #AAAAAA;border-left:1px solid #AAAAAA; height:26px; }
#divEditor{...}{background-color:#EEEEEE;border-top:1px solid #AAAAAA;border-right:1px solid #AAAAAA; border-left:1px solid #AAAAAA;border-bottom:1px solid #AAAAAA;height:224px;}

#dvToobar a {...}{background-repeat:no-repeat;display:block;float:left;margin-right:3px;border:1px solid #dfdfdf;border-top:1px solid #E2E3E2;border-bottom:1px solid #E2E3E2; background-image:url(toolbar.gif);height:20px; font-size:0px;}
#dvToobar a:hover{...}{border-top:1px solid #CCC;border-right:1px solid #999;border-bottom:1px solid #999;border-left:1px solid #CCC;background-color:#FFF}
#dvToobar a.icoCut{...}{background-position:-1px -3px;width:22px; }
#dvToobar a.icoCpy{...}{background-position:-28px -3px; width:24px; }
#dvToobar a.icoPse{...}{background-position:-57px -3px; width:52px}
#dvToobar a.icoWgt{...}{background-position:-108px -3px; width:24px}
#dvToobar a.icoIta{...}{background-position:-136px -3px; width:22px}
#dvToobar a.icoUln{...}{background-position:-164px -3px; width:24px}
#dvToobar a.icoAgn{...}{background-position:-192px -3px; width:24px;}
#dvToobar a.icoLst{...}{background-position:-220px -3px; width:24px;}
#dvToobar a.icoOdt{...}{background-position:-248px -3px; width:26px;}
#dvToobar a.icoFcl{...}{background-position:-332px -1px; width:24px;}
#dvToobar a.icoUrl{...}{background-position:-360px -3px; width:24px;}
#dvToobar a.icoImg{...}{background-position:-388px -1px; width:24px;}
#dvToobar a.icoMfc{...}{background-position:-416px -3px; width:24px;}
#dvToobar a.icoHtm{...}{background-position:-442px -3px; width:44px;}

#dvAlign {...}{ background:#FFFFFF;border:1px solid #838383;padding:1px; width:60px;height:60px;}
#dvAlign a{...}{font-size:12px; height:16px;line-height:16px; display:block;padding:2px;color:#000000;text-decoration:none;position:relative}
#dvAlign a:hover{...}{ background:#E5E5E5}

#dvOrder {...}{ background:#FFFFFF;border:1px solid #838383;padding:1px; width:60px;height:40px;}
#dvOrder a{...}{font-size:12px; height:16px;line-height:16px; display:block;padding:2px;color:#000000;text-decoration:none;position:relative}
#dvOrder a:hover{...}{ background:#E5E5E5}

#dvDent {...}{ background:#FFFFFF;border:1px solid #838383;padding:1px; width:60px;height:40px;}
#dvDent a{...}{font-size:12px; height:16px;line-height:16px; display:block;padding:2px;color:#000000;text-decoration:none;position:relative}
#dvDent a:hover{...}{ background:#E5E5E5}

#dvForeColor {...}{ position:relative;left:50px;background:#FFFFFF;border:1px solid #838383;width:90px;}

#dvForeColor a{...}{font-size:12px;height:16px;line-height:16px;display:block;padding:2px;color:#000000;text-decoration:none;position:relative}
#dvForeColor a:hover{...}{ background:#E5E5E5}
#dvForeColor span{...}{position:absolute;left:19px;top:0px;cursor:hand!important;cursor:pointer;color:#333}
#dvForeColor b{...}{font-size:0;display:block;width:10px;height:8px;position:relative;left:4px;top:1px;cursor:hand!important;cursor:pointer}

.fontfamily {...}{ position: relative;width:100px;height:22px;font-size:12px;float:left;margin-right:5px;}
.fontsize {...}{ position: relative;width: 50px;height:22px;font-size:12px;float:left;margin-right:5px;}

.HtmlEditor {...}{ width:100%; height:100%; }

.sourceEditor{...}{
height:100%;
width:100%;
border:0px;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;

}

在初始化函数中我们必须先加载这一样式单:
loadcss:function () ...{

var links= document.createElement("Link");
links.setAttribute("type","text/css");
links.setAttribute("rel","stylesheet");
links.setAttribute("href","editor.css");
document.getElementsByTagName("head")[0].appendChild(links);
}

这样就可以准备装载工具条了:
工具条包括了字体字号、粘贴复制、粗体倾斜下划链接等,其中对齐编号缩进颜色包括多项这里我也采用了浮层菜单的方式。对工具条的加载包括三个部分:

1.对象或者对象元素数组的的初始化(代码部分就不解释了)
var EditorKit=...{
mode: 1, //change the appearence between HTML and SOURCE

FontColors:...{ "0":["暗红色","#800000"],"1":["紫色","#800080"],"2":["红色","#F00000"],"3":["鲜粉色","#F000F0"],"4":["深蓝色","#000080"],"5":["蓝色","#0000F0"],"6":["湖蓝色","#00F0F0"],"7":["蓝绿色","#008080"],"8":["绿色","#008000"],"9":["橄榄色","#808000"],"10":["浅绿色","#00F000"],"11":["橙黄色","#F0C000"],"12":["黑色","#000000"],"13":["灰色","#808080"],"14":["银色","#C0C0C0"],"15":["白色","#FFFFFF"] },

fonts:["字体","宋体","黑体","楷体_GB2312","隶书","幼圆","Arial","Arial Narrow","Arial Black","Comic Sans MS","Courier","System","Times New Roman"],
sizes:["字号","1","2","3","4","5","6","7"],

aligns:...{"0":["Justifyleft","左对齐"],"1":["Justifycenter","居中对齐"],"2":["Justifyright","右对齐"]},
orders:...{"0":["Insertorderedlist","数字列表"],"1":["Insertunorderedlist","符号列表"]},
dents :...{"0":["Indent","增加缩进"],"1":["Outdent","减少缩进"]},
divs:["dvAlign","dvOrder","dvDent","dvForeColor","dvImgFace"],

//including the following methods;
}

2.工具对应的功能函数
format:function(type, para)...{
var f = window.frames["HtmlEditor"];
f.focus();
if(!para) f.document.execCommand(type);
else f.document.execCommand(type,false,para);
f.focus();
},

changeMode:function ()...{ var sourceEditor =document.getElementById("sourceEditor");
var HtmlEditor =document.getElementById("HtmlEditor");
var divEditor = document.getElementById("divEditor");
var f = window.frames["HtmlEditor"];
var body = f.document.getElementsByTagName("BODY")[0];
if(this.mode)...{
sourceEditor.style.display = "";
HtmlEditor.style.display = "none";
sourceEditor.value = body.innerHTML;

}else...{
sourceEditor.style.display = "none";
HtmlEditor.style.display = "";
body.innerHTML = sourceEditor.value;

}
this.mode=1-this.mode;

},

//隐藏所有已打开的菜单浮动层

hideAllMenu:function () ...{

for (each in this.divs)
...{
if(document.getElementById(this.divs[each])) document.getElementById(this.divs[each]).style.display="none";
}

},

//加载对齐下拉浮动菜单层;首次点击时进行
loadAlign: function () ...{

var aligndiv=document.createElement("div");
aligndiv.style.display="none";
aligndiv.setAttribute("id","dvAlign");
aligndiv.style.position="absolute";

//计算偏移位置,在单击按钮align正下方24px处;
var e=document.getElementById("alignbtn");
var x=e.offsetLeft;
var y=e.offsetTop;
while(e=e.offsetParent)...{ x+=e.offsetLeft; y+=e.offsetTop; }
y+=24;

aligndiv.style.left= x+"px";
aligndiv.style.top = y+"px";

var aligna;
for(each in this.aligns) ...{
aligna=document.createElement("A");
aligna.setAttribute("href","javascript:EditorKit.setAlign('"+this.aligns[each][0]+"')");
aligna.appendChild(document.createTextNode(this.aligns[each][1]));
aligndiv.appendChild(aligna);
}

document.getElementsByTagName("body")[0].appendChild(aligndiv);
},

showAlign:function () ...{

if(!document.getElementById("dvAlign")) this.loadAlign();
var aligndiv=document.getElementById("dvAlign");

this.hideAllMenu();

aligndiv.style.display="";
},

setAlign:function(type) ...{

this.format(type);
document.getElementById("dvAlign").style.display="none";

},

loadOrder:function() ...{

var orderdiv=document.createElement("div");
orderdiv.style.display="none";
orderdiv.setAttribute("id","dvOrder");
orderdiv.style.position="absolute";

//计算偏移位置,在单击按钮align正下方24px处;
var e=document.getElementById("orderbtn");
var x=e.offsetLeft;
var y=e.offsetTop;
while(e=e.offsetParent)...{ x+=e.offsetLeft; y+=e.offsetTop; }
y+=24;

orderdiv.style.left= x+"px";
orderdiv.style.top = y+"px";

var ordera;
for(each in this.orders) ...{
ordera=document.createElement("A");
ordera.setAttribute("href","javascript:EditorKit.setOrder('"+this.orders[each][0]+"')");
ordera.appendChild(document.createTextNode(this.orders[each][1]));
orderdiv.appendChild(ordera);
}

document.getElementsByTagName("body")[0].appendChild(orderdiv);
},

showOrder:function() ...{

if(!document.getElementById("dvOrder")) this.loadOrder();
var orderdiv=document.getElementById("dvOrder");
this.hideAllMenu();

orderdiv.style.display="";
},

setOrder:function(type) ...{

this.format(type);
document.getElementById("dvOrder").style.display="none";
},

loadDent:function() ...{

var dentdiv=document.createElement("div");
dentdiv.style.display="none";
dentdiv.setAttribute("id","dvDent");
dentdiv.style.position="absolute";

//计算偏移位置,在单击按钮align正下方24px处;
var e=document.getElementById("dentbtn");
var x=e.offsetLeft;
var y=e.offsetTop;
while(e=e.offsetParent)...{ x+=e.offsetLeft; y+=e.offsetTop; }
y+=24;

dentdiv.style.left= x+"px";
dentdiv.style.top = y+"px";

var denta;
for(each in this.dents) ...{
denta=document.createElement("A");
denta.setAttribute("href","javascript:EditorKit.setDent('"+this.dents[each][0]+"')");
denta.appendChild(document.createTextNode(this.dents[each][1]));
dentdiv.appendChild(denta);
}

document.getElementsByTagName("body")[0].appendChild(dentdiv);
},

showDent:function() ...{

if(!document.getElementById("dvDent")) this.loadDent();
var dentdiv=document.getElementById("dvDent");
this.hideAllMenu();

dentdiv.style.display="";
},

setDent:function(type) ...{

this.format(type);
document.getElementById("dvDent").style.display="none";
},

loadForeColor:function() ...{

var colordiv=document.createElement("div");
colordiv.setAttribute("id","dvForeColor");
colordiv.style.display="none";
colordiv.style.position="absolute";

var e=document.getElementById("foreColorbtn");
var x=e.offsetLeft;
var y=e.offsetTop;
while(e=e.offsetParent)...{ x+=e.offsetLeft; y+=e.offsetTop; }
y+=24;

colordiv.style.left= x+"px";
colordiv.style.top = y+"px";

var newcolor;
var block;
var stext;

for(each in this.FontColors) ...{

newcolor=document.createElement("A");
newcolor.setAttribute("href","javascript:EditorKit.setForeColor('"+this.FontColors[each][1]+"')");
block=document.createElement("B");
block.style.backgroundColor =this.FontColors[each][1];

stext=document.createElement("span");
stext.appendChild(document.createTextNode(this.FontColors[each][0]));

newcolor.appendChild(stext);
newcolor.insertBefore(block,stext);

colordiv.appendChild(newcolor);
}
document.getElementsByTagName("body")[0].appendChild(colordiv);

},

showForeColor:function() ...{

if(!document.getElementById("dvForeColor")) this.loadForeColor();
var foreColordiv=document.getElementById("dvForeColor");
this.hideAllMenu();

foreColordiv.style.display="";
},

setForeColor:function(para) ...{

this.format("forecolor",para);
document.getElementById("dvForeColor").style.display="none";
},

setFontname:function () ...{

var index=document.getElementById("fontfamily").selectedIndex;
if(index!=0) ...{
EditorKit.format("fontname",EditorKit.fonts[index]);
}
},

setFontsize:function () ...{

var index=document.getElementById("fontsize").selectedIndex;
if(index!=0) ...{
EditorKit.format("fontsize",EditorKit.sizes[index]);
}
},

showToolbar:function () ...{

document.getElementById("dvToobar").style.display="";
},

createLink: function () ...{
var sURL=window.prompt("请输入链接 (如:http://www.163.com/):", "http://");
if ((sURL!=null) && (sURL!="http://")) ...{ this.format("CreateLink", sURL); }
},

insertimgInit:function() ...{

var file=document.createElement("input");
file.style.display="none";
file.setAttribute("type","file");
file.setAttribute("id","imgname");
document.getElementsByTagName("body")[0].appendChild(file);
},

insertImg:function ()...{

if(!document.getElementById("imgname")) this.insertimgInit();
document.getElementById("imgname").click();
document.getElementById("imgname").onChange=document.getElementById("imgname").value!=""?this.format("InsertImage",document.getElementById("imgname").value):null;

}

在加载浮层菜单时候用到了元素绝对地址的计算,方法也很简单。

3.在初始化函数中添加这些元素
//加载工具条
var dvToobar=document.createElement("div");
dvToobar.setAttribute("id","dvToobar");
dvToobar.style.display="none";
//1.加载字体类型
var family=document.createElement("select");
family.className="fontfamily";
family.setAttribute("id","fontfamily");
family.attachEvent("onchange",EditorKit.setFontname);

var newfont;

for(each in this.fonts) ...{
newfont=document.createElement("option");
newfont.value=this.fonts[each];
newfont.appendChild(document.createTextNode(this.fonts[each]));

family.appendChild(newfont);
}

dvToobar.appendChild(family);

//2.加载字体大小
var fontsizes=document.createElement("select");
fontsizes.className="fontsize";
fontsizes.setAttribute("id","fontsize");
fontsizes.attachEvent("onchange",EditorKit.setFontsize);

var newsize;
for(each in this.sizes) ...{
newsize=document.createElement("option");
newsize.appendChild(document.createTextNode(this.sizes[each]));

fontsizes.appendChild(newsize);
}
dvToobar.appendChild(fontsizes);

//3.加载一些小按钮
//剪切
var cutBtn=document.createElement("A");
cutBtn.className="icoCut";
cutBtn.setAttribute("href","javascript:EditorKit.format('Cut')");
cutBtn.setAttribute("title","剪切");
dvToobar.appendChild(cutBtn);

//复制
var cpyBtn=document.createElement("A");
cpyBtn.className="icoCpy";
cpyBtn.setAttribute("href","javascript:EditorKit.format('Copy')");
cpyBtn.setAttribute("title","复制");
dvToobar.appendChild(cpyBtn);

//粘贴
var pseBtn=document.createElement("A");
pseBtn.className="icoPse";
pseBtn.setAttribute("href","javascript:EditorKit.format('Paste')");
pseBtn.setAttribute("title","粘贴");
dvToobar.appendChild(pseBtn);

//加粗
var bldBtn=document.createElement("A");
bldBtn.className="icoWgt";
bldBtn.setAttribute("href","javascript:EditorKit.format('Bold')");
bldBtn.setAttribute("title","加粗");
dvToobar.appendChild(bldBtn);

//斜体
var itaBtn=document.createElement("A");
itaBtn.className="icoIta";
itaBtn.setAttribute("href","javascript:EditorKit.format('Italic')");
itaBtn.setAttribute("title","斜体");
dvToobar.appendChild(itaBtn);

//下划线
var ulnBtn=document.createElement("A");
ulnBtn.className="icoUln";
ulnBtn.setAttribute("href","javascript:EditorKit.format('Underline')");
ulnBtn.setAttribute("title","下划线");
dvToobar.appendChild(ulnBtn);

//对齐
var agnBtn=document.createElement("A");
agnBtn.className="icoAgn";
agnBtn.setAttribute("href","javascript:EditorKit.showAlign()");
agnBtn.setAttribute("id","alignbtn");
agnBtn.setAttribute("title","对齐");
dvToobar.appendChild(agnBtn);

//编号
var lstBtn=document.createElement("A");
lstBtn.className="icoLst";
lstBtn.setAttribute("href","javascript:EditorKit.showOrder()");
lstBtn.setAttribute("id","orderbtn");
lstBtn.setAttribute("title","编号");
dvToobar.appendChild(lstBtn);

//缩进
var odtBtn=document.createElement("A");
odtBtn.className="icoOdt";
odtBtn.setAttribute("href","javascript:EditorKit.showDent()");
odtBtn.setAttribute("id","dentbtn");
odtBtn.setAttribute("title","缩进");
dvToobar.appendChild(odtBtn);

//字体颜色
var fclBtn=document.createElement("A");
fclBtn.className="icoFcl";
fclBtn.setAttribute("href","javascript:EditorKit.showForeColor()");
fclBtn.setAttribute("id","foreColorbtn");
fclBtn.setAttribute("title","字体颜色");
dvToobar.appendChild(fclBtn);

//超链接
var urlBtn=document.createElement("A");
urlBtn.className="icoUrl";
urlBtn.setAttribute("href","javascript:EditorKit.createLink()");
urlBtn.setAttribute("title","超链接");
dvToobar.appendChild(urlBtn);

//增加图片
var imgBtn=document.createElement("A");
imgBtn.className="icoImg";
imgBtn.setAttribute("href","javascript:EditorKit.insertImg()");
imgBtn.setAttribute("title","增加图片");
dvToobar.appendChild(imgBtn);

//魔法表情
var mfcBtn=document.createElement("A");
mfcBtn.className="icoMfc";
mfcBtn.setAttribute("href","javascript:loadimgface()");
mfcBtn.setAttribute("title","魔法表情");
dvToobar.appendChild(mfcBtn);

//模式切换
var htmBtn=document.createElement("A");
htmBtn.className="icoHtm";
htmBtn.setAttribute("href","javascript:EditorKit.changeMode()");
htmBtn.setAttribute("title","模式切换");
dvToobar.appendChild(htmBtn);

根据前面的分析,文本区的加载自然包括二个部分:
//文本面板: 包括一个框架和一个文本域
var txtpanel=document.createElement("div");
txtpanel.setAttribute("id","divEditor");

//一个框架,可以进行正常的编辑面板
var HtmlEditor=document.createElement("iframe");
HtmlEditor.frameBorder =0;
HtmlEditor.marginHeight=0;
HtmlEditor.marginWidth =0;
HtmlEditor.src="about:blank";
HtmlEditor.setAttribute("id","HtmlEditor");
HtmlEditor.className="HtmlEditor";
HtmlEditor.attachEvent("onfocus",EditorKit.showToolbar);
txtpanel.appendChild(HtmlEditor);

var sourceEditor=document.createElement("textarea");
sourceEditor.className="sourceEditor";
sourceEditor.setAttribute("id","sourceEditor");

txtpanel.appendChild(sourceEditor);
var dvpanel=document.createElement("div");
dvpanel.setAttribute("id","dvPanel");
dvpanel.appendChild(dvToobar);
dvpanel.appendChild(txtpanel);
document.getElementsByTagName("body")[0].appendChild(dvpanel);

这里我已经绑定了点击后就弹出隐藏的工具栏函数,参见前面的代码。

最后是激活这个编辑器控件:
aliveEditor:function () ...{

var f = window.frames["HtmlEditor"];
var html = '<HEAD></HEAD><BODY><div></div></BODY>';
f.document.open("text/html","replace");
f.document.write(html);
f.document.close();
f.document.designMode="on";
var sourceEditor =document.getElementById("sourceEditor");
sourceEditor.style.display = "none";
}

其实更好的方法是仅仅提供一个工具条的接口给页面使用,在实际中应努力做好需要时再加载且之加载一次,
而不再去关联实际需要的文本区,进而免去对文本区不必要的束缚。

仿网易163的在线HTML编辑器及其轻量化结构相关推荐

  1. 仿网易163邮箱界面模板

    链接:http://pan.baidu.com/s/1i57bVzn 密码:qzpg 转载于:https://www.cnblogs.com/wordblog/p/6790861.html

  2. 使用 Arya 在线 Markdown 编辑器

    使用 Arya 在线 Markdown 编辑器 Arya,是一款基于 Vue.Vditor,为未来而构建的在线 Markdown 编辑器:轻量且强大:内置粘贴 HTML 自动转换为 Markdown, ...

  3. ionic2入门教程(三)高仿网易公开课(1)

    Ionic2系列之高仿网易公开课(1) 0.登录界面实现截图和官方图片对比 我的 官方 1.新建一个blank项目 打开cmd,输入ionic start Ionic-NetEaseOpenCours ...

  4. 07 仿网易严选微信小程序商城

    仿网易严选微信小程序商城 一.代码 一.代码 github,国外最大的开源项目中心,https://www.oschina.net/ 码云,https://gitee.com/?from=osc-in ...

  5. css+js校验 实现仿网易邮箱注册界面 和 校验 功能

    css+js校验 实现仿网易邮箱注册界面 和 校验 功能 先来看看最终的效果图吧ヾ(≧▽≦*)o 代码如下: <!DOCTYPE html> <html lang="en& ...

  6. 仿网易邮箱5.0(三):panel.js

    今天我们首先来接触第一个用到的插件--Neter.Panel(登录框),在这个插件中,主要的操作有:添加一个标签,更新标签,删除标签. 还是先上代码: View Code 1 /** 2 * 面板插件 ...

  7. CodeMirror 5.26.0 发布,在线代码编辑器

    CodeMirror 5.26.0 已发布,CodeMirror 是一款"Online Source Editor",基于 Javascript,短小精悍,实时在线代码高亮显示,它 ...

  8. Codemirror-开源在线代码编辑器

    Codemirror是一款"Online Source Editor",基于Javascript,短小精悍,实时在线代码高亮显示,他不是某个富文本编辑器的附属产品,他是许多大名鼎鼎 ...

  9. CentOS 5.6 修改国内网易163高速源

    今天在VM7.X中安装了CentOS5.6,安装完成后想修改国内网易163高速源,以下是网络上找到的修改方法,不过任有报错,报错信息在最后,以下是源文件的修改: cd /etc/yum.repos.d ...

最新文章

  1. MapGuide应用开发系列(四)---- 如何运行第一个.net实例代码
  2. Port Forwarding Port Triggering
  3. 关于获取客户端Mac地址
  4. 反射型XSS漏洞的条件+类型+危害+解决
  5. mysql 5.6.37 winx64_Mysql 5.6.37 winx64安装双版本mysql笔记记录
  6. 【dfs】年会小游戏
  7. [react] 如何更新组件的状态?
  8. pycharm变量存_pycharm不为人知的功能们
  9. bat批处理执行python_通过批处理来运行python程序
  10. mysql nn_mysql workbench建表时PK,NN,UQ,BIN,UN,ZF,AI含义说明
  11. Azkaban 进程和任务监控(任务状态从MySQL同步到SqlServer)
  12. java中的List排序[转]
  13. openCV播放视频的程序
  14. html5拼音显示,HTML5:给汉字加拼音?收起展开组件?
  15. 8.MIL中相机标定(Calibration)
  16. Radware荣获ICSA实验室“卓越信息安全测试奖”
  17. 猿创征文|项目中使用Git,解决一些项目开发中常见的Git问题
  18. c语言函数参数的含义,C语言函数的含义
  19. “笨办法”学Python3,Zed A. Shaw, 习题13
  20. ByteCTF2021安全范儿高校挑战赛线上Misc-《HearingNotBelieving》

热门文章

  1. liunx oracle 12505,ORA-12505 错误解决
  2. 什么是催眠?人机融合智能可以催眠吗?
  3. Jquery 中 ajaxSubmit使用讲解
  4. 华为 2017 实习生招聘笔试题
  5. 解读|TARS开源项目发布Go语言版本
  6. ebs各模块名称及英文缩写
  7. 如何进行旅游app开发定制
  8. 逻辑回归模型logistic原理详解
  9. Mac安装软件时提示“文件已损坏,您应该将它移到废纸篓”解决办法(亲测有效)
  10. 武汉大学计算机学院李明,第一届CSIG全国SLAM技术论坛成功举办