到目前为止,我们的整个项目已经完成了三分之一了,之前都是基于环境搭建、配置、以及增删改查的单元测试,几乎无关用户最关心的views部分了,也就是jsp页面的展示,这部分也是很重要的,好的布局和效果,直接影响使用者的心情,当然,后台工程师是不关心前台工程师是怎么来设计页面的,他们只关心,前端请求的url是什么,请求的数据(参数)是什么.......但是,但是,但是我们还是要多少会一点点前端的技术的,起码知道JQuery框架怎么用,js怎么写,css怎么布局,jsp页面标签怎么放.....
这里我还想补充一下,对于上一篇Mybatis逆向映射数据关系到JavaBean(类,接口,对象.....)以及Mapper的XML配置文件,我认识的比较浅,在新环境工作了差不多一周后,发现,JaveBean(表映射的Java类,表字段和类属性的对应,以及各种眼花缭乱的Sql操作条件组合方法的定义)、Mapper接口(增删改查方法的声明)和Mapper配置文件(实现简单的增删改查语句,并将实现的结果映射到对应的JavaBean)远不止逆向工程自动生成的这么简单,我们还可以自己写JavaBean,写Mapper接口,并在Mapper.xml里实现更为复杂的Sql操作行为,实现"自己动手,丰衣足食"。
由于这部分自己还在摸索阶段,暂时说不清其中的门道,可以参考这篇博文【mybatis联合查询之高级映射】,写的很不错,但是缺乏例子测试,自己可以脑补。
回到本篇,我们开始,我们的第一步工作,引入两个JS框架,一个是UI插件集合框架 JQuery EasuUI,另一个是本项目要用到的富文本编辑器Kindeditor
一、在..../WEB_INF/js/目录下面添加这两个框架
(1) 凡是本项目中的涉及到的资源,均存在于我的下载资源里对应的项目中。
(2)我们看到还有一个common.js的资源,从名字上就可以看出来,这个js是全局性的,我们看一下,内容是什么
Date.prototype.format = function(format){ var o = { "M+" : this.getMonth()+1, //month "d+" : this.getDate(), //day "h+" : this.getHours(), //hour "m+" : this.getMinutes(), //minute "s+" : this.getSeconds(), //second "q+" : Math.floor((this.getMonth()+3)/3), //quarter "S" : this.getMilliseconds() //millisecond }; if(/(y+)/.test(format)){ format = format.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); } for(var k in o) { if(new RegExp("("+ k +")").test(format)){ format = format.replace(RegExp.$1, RegExp.$1.length==1 ? o[k] : ("00"+ o[k]).substr((""+ o[k]).length)); } } return format; }; var TT = YuKun = { // 富文本编辑器中的参数,实际上页面的图片上传按钮调用的是富文本编辑器里面的图片上传功能 kingEditorParams : { filePostName : "uploadFile", //表单提交中file组件的名称 uploadJson : '/pic/upload', //上传地址,对应一个Controller dir : "image" //类型 }, // 格式化时间 formatDateTime : function(val,row){ var now = new Date(val); return now.format("yyyy-MM-dd hh:mm:ss"); }, // 格式化连接 formatUrl : function(val,row){ if(val){ return "<a href='"+val+"' target='_blank'>查看</a>"; } return ""; }, init : function(data){ //上来先初始化图片上传组件 this.initPicUpload(data); }, // 初始化图片上传组件 initPicUpload : function(data){ $(".picFileUpload").each(function(i,e){ var _ele = $(e); _ele.siblings("div.pics").remove(); _ele.after('\ <div class="pics">\ <ul></ul>\ </div>'); // 回显图片 if(data && data.pics){ var imgs = data.pics.split(","); //alert(imgs); for(var i in imgs){ if($.trim(imgs[i]).length > 0){ _ele.siblings(".pics").find("ul").append("<li><a href='"+imgs[i]+"' target='_blank'><img src='"+imgs[i]+"' width='80' height='50' /></a></li>"); } } } $(e).unbind('click').click(function(){ //从按钮开始向上查找form,查找最近的一个form对象 var form = $(this).parentsUntil("form").parent("form"); //图片上传参数 KindEditor.editor(TT.kingEditorParams).loadPlugin('multiimage',function(){ var editor = this; editor.plugin.multiImageDialog({ //点击“全部插入”时执行 clickFn : function(urlList) { var imgArray = []; KindEditor.each(urlList, function(i, data) { imgArray.push(data.url); //小图片预览 form.find(".pics ul").append("<li><a href='"+data.url+"' target='_blank'><img src='"+data.url+"' width='80' height='50' /></a></li>"); }); //将url用逗号分隔写入到隐藏域中,注意name的值不要写错 form.find("[name=icon]").val(imgArray.join(",")); editor.hideDialog(); } }); }); }); }); }, createEditor : function(select){ return KindEditor.create(select, TT.kingEditorParams); }, /** * 创建一个窗口,关闭窗口后销毁该窗口对象。 * * 默认: * width : 80% * height : 80% * title : (空字符串) * * 参数: * width : * height : * title : * url : 必填参数 * onLoad : function 加载完窗口内容后执行 * * */ createWindow : function(params){ $("<div>").css({padding:"5px"}).window({ width : params.width?params.width:"80%", height : params.height?params.height:"80%", modal:true, title : params.title?params.title:" ", href : params.url, onClose : function(){ $(this).window("destroy"); }, onLoad : function(){ if(params.onLoad){ params.onLoad.call(this); } } }).window("open"); }, closeCurrentWindow : function(){ $(".panel-tool-close").click(); }, getSelectionsIds : function (select){ var list = $(select); var sels = list.datagrid("getSelections"); var ids = []; for(var i in sels){ ids.push(sels[i].id); } ids = ids.join(","); return ids; }, /** * 初始化单图片上传组件 * 选择器为:.onePicUpload * 上传完成后会设置input内容以及在input后面追加<img> */ initOnePicUpload : function(){ $(".onePicUpload").click(function(){ var _self = $(this); KindEditor.editor(TT.kingEditorParams).loadPlugin('image', function() { this.plugin.imageDialog({ showRemote : false, clickFn : function(url, title, width, height, border, align) { var input = _self.siblings("input"); input.parent().find("img").remove(); input.val(url); input.after("<a href='"+url+"' target='_blank'><img src='"+url+"' width='80' height='50'/></a>"); this.hideDialog(); } }); }); }); } };
其中定义了一些数据的格式化方法,组件的初始化、窗体的创建和销毁....JS当然不是我写出来的,我只是拿来改,没错,是改,
二、在..../WEB_INF/commons/目录下面创建一个全局jsp引用头(外部静态资源引用)
(1)
(2)common-js.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <link rel="stylesheet" type="text/css" href="/js/jquery-easyui-1.4.1/themes/default/easyui.css" /> <link rel="stylesheet" type="text/css" href="/js/jquery-easyui-1.4.1/themes/icon.css" /> <script type="text/javascript" src="/js/jquery-easyui-1.4.1/jquery.min.js"></script> <script type="text/javascript" src="/js/jquery-easyui-1.4.1/jquery.easyui.min.js"></script> <script type="text/javascript" src="/js/jquery-easyui-1.4.1/locale/easyui-lang-zh_CN.js"></script> <script type="text/javascript" src="/js/common.js"></script>
(3)注意外部资源的引用href和src的路径一定要对着的,不是乱写的(主要是easyui的css和js引用)
三、修改views目录下面的index.jsp内容(之前的内容太简陋-->简单+丑陋)
(1)
(2)index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>技能任务单后台管理--Appleyk</title> <jsp:include page="/WEB-INF/commons/common-js.jsp"></jsp:include> <style type="text/css"> .content { padding: 10px 10px 10px 10px; } </style> </head> <body class="easyui-layout"> <div data-options="region:'west',title:'菜单',split:true" style="width:180px;"> <ul id="menu" class="easyui-tree" style="margin-top: 10px;margin-left: 5px;"> <li> <span>插件管理</span> <ul> <li data-options="attributes:{'url':'plugin-add'}">数据插入</li> <li data-options="attributes:{'url':'plugin-list'}">数据显示</li> </ul> </li> <li> <span>用户管理</span> <ul> <li data-options="attributes:{'url':'users-add'}">添加用户</li> <li data-options="attributes:{'url':'users-list'}">用户列表</li> </ul> </li> <li> <span>文件管理</span> <ul> <li data-options="attributes:{'url':'upload/upload'}">文件上传</li> <li data-options="attributes:{'url':'listFile'}">文件下载</li> </ul> </li> </ul> </div> <div data-options="region:'center',title:''"> <div id="tabs" class="easyui-tabs"> <div title="首页" style="padding:20px;"> </div> </div> </div> <script type="text/javascript"> $(function(){ $('#menu').tree({ onClick: function(node){ if($('#menu').tree("isLeaf",node.target)){//判断点击的节点是否为叶子节点 var tabs = $("#tabs"); var tab = tabs.tabs("getTab",node.text); if(tab){ //选中 tabs.tabs("select",node.text); }else{ //新增tab tabs.tabs('add',{ title:node.text, href: node.attributes.url, closable:true, bodyCls:"content" }); } } } }); }); </script> </body> </html>
注意几个地方:
A.common-js.jsp其实只是jsp中的一个资源引用片段,而,index.jsp将其包含进来了
B.
C.easyUI-tree添加tab节点
四、静态资源文件目录结构图
五、运行项目,并访问首页
(1)localhost:8080
至此,入职技能任务单的前台首页布局和展示就已经完成了,接下来,就是针对每个节点设计对应的jsp页面,并全面进入MVC的开发模式了。
下一篇:Java Web后端--入职技能任务单(新增插件信息)八