引言:

本人所属施工单位,在建项目较多,通讯录是以项目为单位挂接在公司内部网站通讯录板块,以静态页面展示。一直以来都是项目部办公室通过电话、邮件等方式通知总部信息部门变更通讯录,日常维护的工作量较大。最近受领导委托设计一款能让项目部自助维护通讯录的软件,一二级部门标题要加以区分,要方便排序,方便维护,还要统一风格显示。

↑公司现有通讯录效果展示

第一种方案是后台挂接Excel表格,前台展示,这种显示效果一般,不符合要求。

↑Excel通讯录效果展示

第二种方案是后台单条录入,前台用表格(XXGrid,Repeater)展示,这种维护方便,但是不太方便排版。

↑第三方表格通讯录效果展示

第三种方案是后台编辑HTML表格,前台使用css样式调整显示风格。这种方案符合预期,但是让非技术人员编辑HTML表格,而且要统一风格,难度有点大。于是构思怎样简化用户操作,想到了用在线编辑器固定Table样式,然后通过自定义按钮实现简单的文字调整。

↑预期效果展示

其实技术实现并不难,主要是细节问题处理和调试工作繁琐,本人花费两天时间研究并实现了这个功能,下面详细展开说一下。

我这里使用的是KindEditor,最新版可以到官网下载。

首先新建一个空白页面,引用以下脚本文件:

<script src="Script/jquery-1.8.2.min.js"></script>
<script src="Script/kindeditor/kindeditor-all-min.js"></script>
<script src="Script/kindeditor/lang/zh-CN.js"></script>

然后自己设计或从网上找一些漂亮的table样式,比如我在百度找了一段css样式(版权归原作者啊):

 * {
margin: 0;
padding: 0;
} body {
padding: 40px 50px;
} .demo {
width: 600px;
margin: 40px auto;
font-family: 'trebuchet MS', 'Lucida sans', Arial;
font-size: 14px;
color: #444;
}
.header {
text-align:center;
background-color:#dfefff;
height:90px;
width:100%;
}
.footer {
text-align:center;
background-color:#dfefff;
height:30px;
width:100%;
position:fixed;
bottom:0;
}
table {
*border-collapse: collapse; /* IE7 and lower */
border-spacing: 0;
width: 100%;
border: solid #ccc 1px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius: 6px;
-webkit-box-shadow: 0 1px 1px #ccc;
-moz-box-shadow: 0 1px 1px #ccc;
box-shadow: 0 1px 1px #ccc;
} table tr {
-o-transition: all 0.1s ease-in-out;
-webkit-transition: all 0.1s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-ms-transition: all 0.1s ease-in-out;
transition: all 0.1s ease-in-out;
} table .highlight,
table tr:hover {
background: #fbf8e9;
} table td,
table th {
border-left: 1px solid #ccc;
border-top: 1px solid #ccc;
padding: 10px;
text-align: left;
} table th {
background-color: #dce9f9;
-ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#ebf3fc, endColorstr=#dce9f9)";
-webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset;
-moz-box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset;
box-shadow: 0 1px 0 rgba(255, 255, 255, .8) inset;
text-shadow: 0 1px 0 rgba(255, 255, 255, .5);
background-image: linear-gradient(top, #ebf3fc, #dce9f9);
border-top-style: none;
border-top-color: inherit;
border-top-width: medium;
} table td:first-child,
table th:first-child {
border-left: none;
} table th:first-child {
-moz-border-radius: 6px 0 0 0;
-webkit-border-radius: 6px 0 0 0;
border-radius: 6px 0 0 0;
} table th:last-child {
-moz-border-radius: 0 6px 0 0;
-webkit-border-radius: 0 6px 0 0;
border-radius: 0 6px 0 0;
} table tr:last-child td:first-child {
-moz-border-radius: 0 0 0 6px;
-webkit-border-radius: 0 0 0 6px;
border-radius: 0 0 0 6px;
} table tr:last-child td:last-child {
-moz-border-radius: 0 0 6px 0;
-webkit-border-radius: 0 0 6px 0;
border-radius: 0 0 6px 0;
}
/*----------------------*/
.zebra td,
.zebra th {
padding: 10px;
border-bottom: 1px solid #f2f2f2;
} .zebra .alternate,
.zebra tbody tr:nth-child(even) {
background: #f5f5f5;
-webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
-moz-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
} .zebra th {
text-align: left;
text-shadow: 0 1px 0 rgba(255,255,255,.5);
border-bottom: 1px solid #ccc;
background-color: #eee;
-ms-filter: "progid:DXImageTransform.Microsoft.gradient (GradientType=0, startColorstr=#f5f5f5, endColorstr=#eeeeee)";
background-image: linear-gradient(top, #f5f5f5, #eee);
} .zebra th:first-child {
-moz-border-radius: 6px 0 0 0;
-webkit-border-radius: 6px 0 0 0;
border-radius: 6px 0 0 0;
} .zebra th:last-child {
-moz-border-radius: 0 6px 0 0;
-webkit-border-radius: 0 6px 0 0;
border-radius: 0 6px 0 0;
} .zebra tfoot td {
border-bottom: 0;
border-top: 1px solid #fff;
background-color: #f1f1f1;
} .zebra tfoot td:first-child {
-moz-border-radius: 0 0 0 6px;
-webkit-border-radius: 0 0 0 6px;
border-radius: 0 0 0 6px;
} .zebra tfoot td:last-child {
-moz-border-radius: 0 0 6px 0;
-webkit-border-radius: 0 0 6px 0;
border-radius: 0 0 6px 0;
}

第三步需要找一些自定义按钮图标,添加到页面的Body里,为啥不能放到Head里呢,我也有点郁闷,放到Head里自定义按钮都不显示了,为此还调试了老半天。

/*----------编辑器上的自定义按钮图标------------*/

    .ke-icon-settfirst {
background-image:url(/Resource/first.gif);
width: 16px;
height: 16px;
}
.ke-icon-settsecond {
background-image:url(/Resource/second.gif);
width: 16px;
height: 16px;
}
.ke-icon-cancelthead {
background-image:url(/Resource/cancel.gif);
width: 16px;
height: 16px;
}
.ke-icon-moveup {
background-image:url(/Resource/moveup.gif);
width: 16px;
height: 16px;
}
.ke-icon-movedown {
background-image:url(/Resource/movedown.gif);
width: 16px;
height: 16px;
}

第四步在Body里添加textarea元素

<div>
<textarea id="editor_id" name="content" style="width:700px;height:300px;">
</textarea>
</div>

第五步是编写KindEditor脚本,也是难度最大的部分,主要实现的功能就是设置标题,上下左右移动和保存。闲话不说,具体看代码吧。

// 自定义插件
KindEditor.lang({
settfirst: '设置为一级标题',
settsecond: '设置为二级标题',
cancelthead: '取消标题',
moveup: '向上移动',
movedown: '向下移动',
moveleft: '向左移动',
moveright: '向右移动',
savedata: '保存'
});
KindEditor.plugin('settfirst', function (K) {
var self = this, name = 'settfirst';
self.clickToolbar(name, function () {
table = self.plugin.getSelectedTable();
if (table) {
var cell = self.plugin.getSelectedCell();
if (cell == null) return;
cell[0].style.cssText = '';
cell[0].outerHTML = cell[0].outerHTML.replace(/td/g, "th"); }
});
});
KindEditor.plugin('settsecond', function (K) {
var self = this, name = 'settsecond';
self.clickToolbar(name, function () {
table = self.plugin.getSelectedTable();
if (table) {
var cell = self.plugin.getSelectedCell();
if (cell == null) return;
cell[0].style.cssText = 'font-color:#0000ff;font-size:10px;font-name:隶书';
cell[0].outerHTML = cell[0].outerHTML.replace(/td/g, "th"); }
});
});
KindEditor.plugin('cancelthead', function (K) {
var self = this, name = 'cancelthead';
self.clickToolbar(name, function () {
table = self.plugin.getSelectedTable();
if (table) {
var cell = self.plugin.getSelectedThead();
if (cell == null) return;
cell[0].style.cssText = '';
cell[0].outerHTML = cell[0].outerHTML.replace(/th/g, "td"); }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('moveup', function (K) {
var self = this, name = 'moveup';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
preRowIndex = rowIndex - 1;
// 第一行不能移动
if (preRowIndex <= 0) {
return;
}
var prevCell = table[0].rows[preRowIndex].cells[cellIndex];
if (prevCell.innerHTML != "" && prevCell.innerHTML != "&nbsp;") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
prevCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('movedown', function (K) {
var self = this, name = 'movedown';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
nextRowIndex = rowIndex + 1;
// 最后一行不能移动
if (nextRowIndex >= table[0].rows.length) {
return;
}
var nextCell = table[0].rows[nextRowIndex].cells[cellIndex];
if (nextCell.innerHTML != "" && nextCell.innerHTML != "&nbsp;") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
nextCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('moveleft', function (K) {
var self = this, name = 'moveleft';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
prevCellIndex = cellIndex - 1;
// 最左一列不能移动
if (prevCellIndex < 0) {
return;
}
var prevCell = table[0].rows[rowIndex].cells[prevCellIndex];
if (prevCell.innerHTML != "" && prevCell.innerHTML != "&nbsp;") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
prevCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('moveright', function (K) {
var self = this, name = 'moveright';
self.clickToolbar(name, function () {
var table = self.plugin.getSelectedTable();
if (table) {
var row = self.plugin.getSelectedRow()[0]; var cells = self.plugin.getSelectedCell();
if (cells == null)
cells = self.plugin.getSelectedThead();
var cell = cells[0]; var rowIndex = row.rowIndex,
cellIndex = cell.cellIndex,
nextCellIndex = cellIndex + 1;
// 最右一列不能移动
if (nextCellIndex >= table[0].rows[rowIndex].cells.length) {
return;
}
var nextCell = table[0].rows[rowIndex].cells[nextCellIndex];
if (nextCell.innerHTML != "" && nextCell.innerHTML != "&nbsp;") {
if (confirm('目标单元格不为空,是否替换?')) { }
else {
return;
}
}
nextCell.innerHTML = cell.innerHTML;
cell.innerHTML = ""; }
});
self.plugin.getSelectedThead = function () {
return self.cmd.commonAncestor('th');
};
});
KindEditor.plugin('savedata', function (K) {
var self = this, name = 'savedata';
self.clickToolbar(name, function () { SaveData(); });
});
KindEditor.ready(function (K) {
window.editor = K.create('#editor_id', {
cssPath: 'Style/table.css',
items: ['source', 'settfirst', 'settsecond', 'cancelthead', 'moveup', 'movedown', 'moveleft', 'moveright', '|', 'savedata'],
fullscreenMode: true
}); });

需要说明的是KindEditor可以引用外部样式,我就是用 cssPath: 'Style/table.css'来把表格样式固定的,也就是说,在外部定义好Table的css样式,在KindEditor里只需要考虑<tr><td>元素的创建合并,不需要考虑样式问题。

表格的保存按钮实现也很简单,我这里是用Ajax实现的保存功能,代码如下:

function SaveData() {

            var postData = { mode: "0", data: encodeURIComponent(window.editor.html()) };

            $.ajax({
type: 'post',
dataType: "text",
url: RootPath() + "/DataHandler.ashx",//请求保存的服务器目录
data: postData,
cache: false,
async: false,
success: function (data) {
if (data == "ok") {
location.href = "ShowPhone.html";
}
},
error: function (data) {
alert("error:" + JSON.stringify(data));
}
});
}

其中window.editor.html()是表格的内容,最好用encodeURIComponent函数对内容进行编码,不然到后台接收的时候可能会出现乱码或被拒绝的情况,后台接收到然后在解码即可。我这里用的C#语言,用Uri.UnescapeDataString 方法可实现解码。

展示页在这里就不介绍了,先引用table的样式文件,再从数据库提取到Table代码,加载到Body里即可。以下是编辑器显示效果。

利用KindEditor实现公司通讯录的维护的更多相关文章

  1. 利用KindEditor的uploadbutton实现异步上传图片

    利用KindEditor的uploadbutton实现异步上传图片 异步上传图片最经常使用的方法就是图片在iframe中上传.这样仅仅须要刷新iframe.而不用刷新整个页面.     KindEdi ...

  2. .net mvc4 利用 kindeditor 上传本地图片

    http://blog.csdn.net/ycwol/article/details/41824371?utm_source=tuicool&utm_medium=referral 最近在用k ...

  3. 利用本地SQL Server维护计划来维护SQL Database

    On-Premise的SQL Server提供了维护计划来定期.定时的维护SQL Server.一般的做法是:定义SQL Server Agent Jobs,而后维护计划帮助我们定期.定时执行SQL ...

  4. [gj]来公司停电了-维护机器

    停电出现的问题 一早来机房跳闸了. 很多vm手动起来后有些服务不太正常了. 机房锁坏了.不知道谁进去干啥了.导致跳闸 闸门不知道在哪里.导致所有机器停电了 牵扯到的技术点: 1,nexus启动. ng ...

  5. 利用Powershell获取公司内部机器的资源信息,作为企业兴许资产管理的基本途径!

    今天一个哥们问我是否用Powershell 实现.我好久没有写脚本,脚本的协作和调试还是费了一些时间,兴许调试了下.运作没有问题,大家能够參考以下的脚本来丰富您企业须要做的一些事情,脚本代码例如以下: ...

  6. 利用Ossim系统进行主机漏洞扫描

    利用Ossim系统进行主机漏洞扫描 企业中查找漏洞要付出很大的努力,不能简单的在服务器上安装一个漏洞扫描软件那么简单,那样起不了多大作用.这并不是因为企业中拥有大量服务器和主机设备,这些服务器和设备又 ...

  7. 如何利用Flink实现超大规模用户行为分析

    如何利用Flink实现超大规模用户行为分析   各位晚上好,首先感谢大家参与我的这次主题分享,同时也感谢 InfoQ AI 前线组织这次瀚思科技主题月! 瀚思科技成立于 2014 年,按行业划分我们是 ...

  8. 杂项-公司:Apple

    ylbtech-杂项-公司:Apple 苹果公司(Apple Inc. )是美国的一家高科技公司.由史蒂夫·乔布斯.斯蒂夫·沃兹尼亚克和罗·韦恩(Ron Wayne)等人于1976年4月1日创立,并命 ...

  9. 利用KMeans聚类进行航空公司客户价值分析

    准确的客户分类的结果是企业优化营销资源的重要依据,本文利用了航空公司的部分数据,利用Kmeans聚类方法,对航空公司的客户进行了分类,来识别出不同的客户群体,从来发现有用的客户,从而对不同价值的客户类 ...

随机推荐

  1. 10大H5前端框架,让你开发不愁

    ![](http://upload-images.jianshu.io/upload_images/8373224-7903a1466f7b9722?imageMogr2/auto-orient/st ...

  2. 使用JS实现图片轮播滚动跑马灯效果

    我的第一篇文章.哈哈.有点小鸡冻.  之前在百度搜索"图片轮播"."图片滚动",结果都是那种可以左右切换的.也是我们最常见的那种.可能是搜索 关键字的问题吧. ...

  3. mysql服务处理流程

    先把错误日志定位 就是找的错误日志 然后必要的时候 重新启动服务器 排除其他的干扰 把错误日志 挪到旧文件 清空错误日志 然后试着启动 看干净的错误日志 然后 问题就解决了

  4. windows 系统下C++实现的多线程

    摘抄http://blog.csdn.net/huyiyang2010/article/details/5809919 Thread.h #ifndef __THREAD_H__ #define __ ...

  5. D - MUH and Cube Walls

    D. MUH and Cube Walls   Polar bears Menshykov and Uslada from the zoo of St. Petersburg and elephant ...

  6. Python面向对象篇之元类,附Django Model核心原理

    关于元类,我写过一篇,如果你只是了解元类,看下面这一篇就足够了. Python面向对象之类的方法和属性 本篇是深度解剖,如果你觉得元类用不到,呵呵,那是因为你不了解Django. 在Python中有一 ...

  7. Azkaban 2.5.0 搭建和一些小问题

    安装环境: 系统环境: ubuntu-12.04.2-server-amd64 安装目录: /usr/local/ae/ankaban JDK 安装目录: export JAVA_HOME=/usr/ ...

  8. 逻辑卷lvm创建、扩展、缩小

    系统环境:CentOS Linux release 7.3.1611 (Core) 3.10.0-514.el7.x86_64 CentOS6与7配置方法大同小异.通常是在系统安装的时候创建lvm,然 ...

  9. MSSQL 备份数据库还原

    -- 完整还原RESTORE DATABASE XXXX FROM DISK = 'd:\XXXX.bak' WITH MOVE 'XXXX' TO 'D:\MSSQL\Data\XXXX.mdf', ...

  10. 三、VueJs 填坑日记之项目文件认识

    上一篇博文,我们搭建了一套基础的vuejs的环境,首先安装node.js,然后利用npm包管理器,安装vue-cli,设置淘宝镜像,初始化项目,安装依赖,运行.在这一篇,我们将认识vuejs项目里的各 ...