引言:

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

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

第一种方案是后台挂接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. fiddler学习资源

    小坦克   fiddler教程:http://www.cnblogs.com/TankXiao/archive/2012/04/25/2349049.htmlps:另外博主其他测试文章也值得一看 涂根 ...

  2. 学习笔记 intent属性

    Android开发学习笔记:Intent的简介以及属性的详解 2011-08-08 17:20:48 标签:Intent 移动开发 Android 休闲 详解 原创作品,允许转载,转载时请务必以超链接 ...

  3. 紧跟腾讯大王卡:B站2233卡“基友号”即将上线

    来自B站官方的消息显示,B站在近期也将推出"基友号"功能,功能的内容是通话免费,考虑到这类互联网套餐都是中国联通在运营,因此在内容上可能也会效仿腾讯大王卡实现免费通话. 目前,B站 ...

  4. JavaScript 语言精粹读书笔记

    最近在看 赵泽欣 / 鄢学鹍 翻译的 蝴蝶书, 把一些读后感言记录在这里. 主要是把作者的建议跟 ES5/ES5.1/ES6 新添加的功能进行了对比 涉及到的一些定义 IIFE: Immediatel ...

  5. 万能日志数据收集器 Fluentd - 每天5分钟玩转 Docker 容器技术(91)

    前面的 ELK 中我们是用 Filebeat 收集 Docker 容器的日志,利用的是 Docker 默认的 logging driver json-file,本节我们将使用 fluentd 来收集容 ...

  6. SQL Server 通过SQL脚本启动Broker并设置兼容性

    SQL Server数据库中通过SQL启用Broker 并建立相关队列和服务 兼容代码使其可以在2000库中执行不报错 针对的是2008版本, 如果是其他版本可以改相关版本号和兼容性标记 /***** ...

  7. 关于c# SESSION丢失问题解决办法

    我们在用C#开发程序的时候经常会遇到Session很不稳定,老是数据丢失.下面就是Session数据丢失的解决办法希望对您有好处.1.在WEB.CONFIG文件中修改SESSION状态保存模式,如:& ...

  8. C#对注册表的操作

    C#中提供的与注册表相关的最主要的是两个类: Registry 和 RegistryKey,这两个类属于Microsoft.Win32命名空间 Registry类包含5个公共的静态域,分别代表5个基本 ...

  9. [转载] Hive结构

    转载自http://www.csdn.net/article/2010-11-28/282616 Hive 体系结构 Hive 的结构如图所示 主要分为以下几个部分: 用户接口,包括 CLI,Clie ...

  10. CLR类型设计之方法与构造器

    无论学习那门语言都要学习函数体,C#,JAVA,PHP,都会涉及到函数体,而C#的函数体成员并不少,方法和构造器就是函数体成员之一,函数体成员还包括但不限于:方法,属性,构造器,终结器,运算符及索引器 ...