写完第一篇Hello World之后,我就一直在准备着弄弄MVC,整了2天终于弄好了,遇到问题,也只能靠自己.
其实就是用ExtJS5 搭个后台界面:
啥都不说了,上代码。
首先需要一个app.js来定义一个ExtJS的Application,Application里去启动运行ExtJS的程序
App.js
- Ext.QuickTips.init();
- Ext.Loader.setConfig({
- enabled : true
- });
- Ext.Loader.setPath({
- 'Ext.ux' : 'extjs/ux',
- //'Ext.app' : 'extjs/app',
- 'Portal.view' : 'extjs/app',
- 'OA.util' : 'app/util'
- });
- /**
- * 加载ExtJS插件文件
- */
- Ext.require(
- [
- 'Portal.view.Portlet',
- 'Portal.view.PortalColumn',
- 'Portal.view.PortalPanel',
- 'Portal.view.PortalDropZone',
- 'Ext.ux.TabReorderer',
- 'Ext.ux.BoxReorderer',
- 'Ext.ux.TabCloseMenu',
- 'Ext.ux.PageSizePaging',
- 'OA.util.AppUtil'
- ]
- );
- Ext.application({
- requires: ['Ext.container.Viewport','OA.view.Viewport'],
- //项目名称简称
- name: 'OA',
- appFolder: 'app',
- autoCreateViewport: true,
- //控制器注册
- controllers:[
- 'AppController',
- 'user.UserController'
- ],
- launch: function () {
- //Ext.create('OA.view.Viewport');
- }
- });
app.js里有个autoCreateViewport属性,即自动创建Viewport容器,我们知道ExtJS的所有组件都是需要放进这个总容器里的,当然viewport不是必须的哈。在ExtJS4.x的时候,是需要显示的在launch里去create我们的viewport容器,autoCreateViewport可以接收true/false,true的话就会自动到app/view下查找Viewport.js文件,自动帮我们加载并帮我们创建viewport容器,这是5.x后的新特性。当然你手动create还是可行的。此外,autoCreateViewport也可以接收一个Viewport类的全路径,即指定自动加载哪个viewport.举个例子:autoCreateViewport: "OA.view,Viewport",这样,如果你的viewport不在默认app/view路径下时,就可以手动指定要加载的viewport的路径。
Viewport.js
- /*********************全局视图容器类************************/
- Ext.define("OA.view.Viewport",{
- extend:'Ext.container.Viewport',
- requires:['Ext.container.Viewport','OA.view.MainPanel'],
- alias : 'widget.baseviewport',
- alternateClassName: ["OA.Viewport"],
- layout: 'fit',
- loadMask:{msg : '正在加载,请稍候...'},
- items: [
- {
- xtype: 'mainpanel'
- }
- ]
- });
Viewport里就放了一个mainpanel子组件,采用fit布局是为了让他能充满整个屏幕。
MainPanel.js
- Ext.define("OA.view.MainPanel",{
- extend:'Ext.panel.Panel',
- alias : 'widget.mainpanel',
- alternateClassName: ["OA.MainPanel"],
- requires: ['OA.view.TopPanel','OA.view.BottomPanel','OA.view.LeftPanel','OA.view.CenterPanel'],
- layout: 'border',
- border: 0,
- initComponent: function () {
- var me = this;
- me.items = [
- {
- xtype: 'toppanel'
- },
- {
- xtype: 'bottompanel'
- },
- {
- xtype: 'leftpanel'
- },
- {
- xtype: 'centerpanel'
- }
- ];
- me.callParent(arguments);
- }
- });
MainPanel里采用border布局,分别放了4个panel,上下左右,ExtJS的经典布局,你懂的。
上下左右4个panel的代码我直接贴了,代码太多就不一一解释了。
TopPanel.js
- /**********************顶部Panel***********************/
- Ext.define("OA.view.TopPanel",{
- extend:'Ext.panel.Panel',
- requires:["OA.view.ThemeMenu"],
- alias : 'widget.toppanel',
- alternateClassName: ["OA.TopPanel"],
- height: 50,
- split: false,
- border: 0,
- collapsible: false,
- titleCollapse: false,
- region: 'north',
- initComponent : function() {
- var me = this;
- me.items = [
- {
- title: 'OA管理系统',
- xtype: 'panel',
- margins:'0 0 5 0',
- tbar:[
- '->',
- '益达,欢迎您!',
- new Date().format("yyyy年MM月dd日 hh:mm:ss w"),
- {
- text:'修改密码'
- },
- {
- text:'退出'
- },
- {
- text: '换肤',
- //iconCls: 'theme',
- menu: {xtype: 'thememenu'}
- }
- ]
- }
- ];
- me.callParent(arguments);
- }
- });
BottomPanel.js
- /**********************底部Panel***********************/
- Ext.define("OA.view.BottomPanel",{
- extend:'Ext.panel.Panel',
- alias : 'widget.bottompanel',
- alternateClassName: ["OA.BottomPanel"],
- height: 20,
- border: 0,
- split: false,
- collapsible: false,
- titleCollapse: false,
- draggable: false,
- region: 'south',
- initComponent: function () {
- var me = this;
- Ext.apply(me, {
- tbar: ['->','OA by yida']
- });
- me.callParent(arguments);
- }
- });
LeftPanel.js
- /*********************左侧Panel************************/
- Ext.define("OA.view.LeftPanel",{
- extend:'Ext.panel.Panel',
- requires:["OA.view.LeftTreePanel"],
- alias : 'widget.leftpanel',
- alternateClassName: ["OA.LeftPanel"],
- initComponent : function(){
- Ext.apply(this,{
- id : "leftPanel",
- title: '导航菜单',
- width: 200,
- height: "100%",
- border: true,
- collapsed: false,
- collapsible: true,
- animCollapse: true,
- collapseMode: 'mini',
- autoScroll: false,
- containerScroll: true,
- split: true,
- resizable: false,
- region: 'west',
- layout: 'accordion',
- layoutConfig : {
- titleCollapse: false,
- animate : true, //动态切换树空间
- activeOnTop: true,
- multi:false
- }
- });
- this.callParent(arguments);
- }
- });
CenterPanel.js
- /*******************中间Panel**************************/
- Ext.define("OA.view.CenterPanel",{
- extend:'Ext.tab.Panel',
- requires:['Ext.tab.Panel'],
- alias : 'widget.centerpanel',
- alternateClassName: ["OA.CenterPanel"],
- id : "centerPanel",
- width: '100%',
- border: 0,
- enableTabScroll: true,
- autoScroll: true,
- activeItem: 0,
- region: 'center',
- layout: 'fit',
- initComponent : function() {
- var me = this;
- me.callParent(arguments);
- },
- items: [
- {
- //iconCls : 'icon-activity',
- title : '平台首页',
- xtype:'portalpanel',
- layout:'hbox',
- items : [
- {
- xtype : 'portalcolumn',
- columnWidth : 0.7,
- items:[
- {title: '新闻动态',height : 180},
- {title: '最新通知',height : 180},
- {title: '业绩报表',height : 180}
- ]
- },
- {
- xtype : 'portalcolumn',
- columnWidth : 0.3,
- items:[
- {title: '常用功能', height : 180},
- {title: '待办事项',height : 180},
- {title: '邮件列表', height : 180}
- ]
- }
- ]
- }
- ],
- listeners: {
- resize :function(p, width, height,oldWidth,oldHeight, eOpts) {
- p.updateLayout();
- }
- }
- });
最后贴一下AppUtil.js工具类
- /**
- * JavaScript-Date日期类型格式化<br/>
- * 使用示例:
- * var date = new Date();
- * alert(date.format("yyyy-MM-dd hh:mm:ss"));
- * @param {} format
- * @return {}
- */
- Date.prototype.format = function(format){
- var _week = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
- 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毫秒
- "w" : _week[this.getDay()+""] //星期几
- }
- 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;
- }
- /**
- * 在原日期基础上添加或减去指定天(年,月,日,小时,分钟,秒)数<br/>
- * interval参数:
- * y 年
- * q 季度
- * m 月
- * d 日
- * w 周
- * h 小时
- * n 分钟
- * s 秒
- * ms 毫秒
- *
- * number参数:时间间隔,必须为数字,为正数表示获取指定间隔的未来的日期,为负数表示过去的日期
- * @param {} interval
- * @param {} number
- * @return {}
- */
- Date.prototype.dateAdd = function(interval,number)
- {
- var d = this;
- var k={'y':'FullYear', 'q':'Month', 'm':'Month', 'w':'Date', 'd':'Date', 'h':'Hours', 'n':'Minutes', 's':'Seconds', 'ms':'MilliSeconds'};
- var n={'q':3, 'w':7};
- eval('d.set'+k[interval]+'(d.get'+k[interval]+'()+'+((n[interval]||1)*number)+')');
- return d;
- }
- /**
- * 用于计算两个日期之间的时间间隔<br/>
- * 使用此方法还能比较两个日期的大小,如果返回值大于0,表示objDate2比较大,
- * 如果小于0,表示objDate2比较小
- * @param {} interval
- * @param {} objDate2
- * @return 返回相差的毫秒数
- */
- Date.prototype.dateDiff = function(interval,objDate2)
- {
- var d=this, i={}, t=d.getTime(), t2=objDate2.getTime();
- i['y']=objDate2.getFullYear()-d.getFullYear();
- i['q']=i['y']*4+Math.floor(objDate2.getMonth()/4)-Math.floor(d.getMonth()/4);
- i['m']=i['y']*12+objDate2.getMonth()-d.getMonth();
- i['ms']=objDate2.getTime()-d.getTime();
- i['w']=Math.floor((t2+345600000)/(604800000))-Math.floor((t+345600000)/(604800000));
- i['d']=Math.floor(t2/86400000)-Math.floor(t/86400000);
- i['h']=Math.floor(t2/3600000)-Math.floor(t/3600000);
- i['n']=Math.floor(t2/60000)-Math.floor(t/60000);
- i['s']=Math.floor(t2/1000)-Math.floor(t/1000);
- return i[interval];
- }
- /**
- * 获取数组中某元素的索引【索引从零开始计算】
- * @param {} o
- * @return {}
- */
- Array.prototype.indexOf = function(o){
- for(var i = 0,len=this.length; i<len;i++){
- if(this[i] == o){
- return i;
- }
- }
- return -1;
- }
- /**
- * 删除数组中某元素
- * @param {} o
- * @return {}
- */
- Array.prototype.remove = function(o){
- var index = this.indexOf(o);
- if(index != -1){
- this.splice(index,1);
- }
- return this;
- }
- /**
- * 去除数组中重复数据
- * @param {} o
- * @return {}
- */
- function removeDuplicateArray(o){
- var obj={},ret=[],i=0;
- for(var a in o){
- obj[o[a]]=o[a];
- }
- for(ret[i++] in obj);
- return ret;
- }
- /**
- * 去除字符串中重复字符
- * @param {} str
- * @return {}
- */
- function removeDuplicateString(str){
- var obj={},ret="";
- for(var i=0;i<str.length;i++){
- var s=str.slice(i,i+1);
- obj[s]=s;
- }
- for(s in obj){
- ret += obj[s];
- };
- return ret;
- }
- /**
- * 去除数组或字符串中的重复字符
- * @param {} o
- * @return {}
- */
- function removeDuplicate(o){
- return typeof(o)=="object"?removeDuplicateArray(o):removeDuplicateString(o);
- }
- /**
- * 删除字符串中重复字符
- * @param {} o
- * @return {}
- */
- function removeRepeat(o) {
- return o.replace(/([\s\S]{1})(?:\1+)/g,'$1');
- }
- /**
- * 系统工具类[静态常量和静态方法]
- */
- Ext.define("OA.util.AppUtil",{
- alternateClassName: ["OA.AppUtil"],
- requires: ["OA.util.JSLoader"],
- statics: {
- basePath : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/",
- jsBasePath : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/js/",
- imageBasePath : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/images/",
- cssBasePath : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/css/",
- extjsBasePath : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/extjs/",
- extjsThemePath : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/extjs/theme/",
- loginPage : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/login.jsp",
- indexPage : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/index.jsp",
- loginUrl : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/login.do",
- logOutUrl : window.location.protocol + '//' + window.location.host + '/'
- + window.location.pathname.split('/')[1] + "/logout.do",
- firstTreePanelId: 1,
- /**
- * ExtJS ajax封装<br/>
- * 调用示例:
- * ajax({
- * url : "??.do",
- * params : {
- * id : "参数值",
- * name: "参数值"
- * },
- * callback : function(json){}
- * });
- * @param {} config
- */
- ajax : function(config) {
- Ext.Ajax.request( {
- url : config.url,
- params : config.params,
- method : config.method || 'post',
- callback : function(options, success, response) {
- config.callback(Ext.JSON.decode(response.responseText));
- }
- });
- },
- /**
- * 返回星期几的中文形式
- * @param {} date
- * @return {}
- */
- getDayOfWeek : function(date) {
- var week = [ "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" ];
- return week[day.getDay()];
- },
- /**
- * ExtJS组件的命令空间路径转换成组件的实际访问路径<br/>
- * 如:OA.view.user.UserPanel转换后basePath + app/view/user/UserPanel.js
- *
- * @param {} np
- * @return {}
- */
- namespace2Path : function(np) {
- if(!np) {
- return null;
- }
- np = np + "";
- return OA.util.AppUtil.basePath + np.replace(/\./g,"/").replace("OA","app") + ".js";
- },
- /**
- * 用户退出系统
- */
- logout : function() {
- Ext.Msg.confirm('提示', "您确认要退出系统吗?", function(btn) {
- if (btn == "yes") {
- OA.util.AppUtil.ajax({
- url : OA.util.AppUtil.logOutUrl,
- params : {},
- callback : function(json){
- if(json && json.success) {
- window.location = OA.util.AppUtil.loginPage;
- }
- }
- });
- }
- });
- },
- /**
- * 显示当前时间的时钟信息
- * @param {} domId 时钟信息要显示在哪个dom元素上
- * @param {} pattern 日期时间显示格式,如yyyy-MM-dd hh:mm:ss
- */
- showColock : function(domId,pattern) {
- var date = new Date();
- var colockEl = Ext.get(domId);
- if(!colockEl) {
- return;
- }
- colockEl.dom.innerHTML = date.format(pattern || "yyyy年MM月dd日 hh:mm:ss w");
- },
- /**
- * 动态添加Tab页
- * @param {} node
- */
- openPanel: function(node,centerPanelId) {
- var max = 5;
- var id = node.data.component || "_tab0";
- var centerPanel = Ext.getCmp(centerPanelId);
- var grid = centerPanel.getComponent(node.data.id);
- if (!grid) {
- if (this.items && this.items.length >= max) {
- Ext.Msg.alert("错误", "<span style='font-size:14px;font-weight:600;color:red;'>最多能打开5个模块,请先关闭部分不再使用的模块!</span>");
- }
- else {
- var tab = {};
- centerPanel.getEl().mask("正在加载面板,请稍候...");
- //var cla = Ext.decode("{cla:" + id + "}",true).cla;
- if(node.data.type == "url") {
- tab = Ext.create("Ext.panel.Panel",{
- itemId: node.data.id,
- xtype: 'panel',
- title: node.data.text,
- layout: 'fit',
- closable: true,
- autoScroll: true,
- border: true,
- autoDestroy : true,
- closeAction : 'destory',
- html: '<iframe width="100%" height="100%" frameborder="0" src="' + id + '"></iframe>'
- //iconCls: 'modelIcon'
- });
- } else if(node.data.type == "component") {
- tab = Ext.create("Ext.panel.Panel",{
- itemId: node.data.id,
- xtype: 'panel',
- title: node.data.text,
- layout: 'fit',
- closable: true,
- autoScroll: true,
- border: true,
- autoDestroy : true,
- closeAction : 'destory',
- items:[
- {xtype: id}
- ]
- });
- }
- centerPanel.add(tab);
- centerPanel.setActiveTab(tab);
- centerPanel.doLayout();
- centerPanel.getEl().unmask();
- }
- }
- else {
- centerPanel.setActiveTab(tab);
- centerPanel.getEl().unmask();
- }
- },
- /**
- * 动态添加TreePanel
- */
- addTreePanel : function(data,leftPanel) {
- Ext.getBody().unmask();
- for (var i = 0; i < data.length; i++) {
- /*leftPanel.add(Ext.create("OA.view.LeftTreePanel",{
- id: data[i].id,
- title: data[i].text,
- iconCls: data[i].iconCls
- }));*/
- leftPanel.add({
- xtype: "lefttreepanel",
- itemId: data[i].id,
- title: data[i].text,
- iconCls: data[i].iconCls
- });
- }
- leftPanel.doLayout();
- },
- /**
- * 添加手风琴面板
- * @param {} leftPanelId
- */
- addAccordionPanel : function(data,leftPanelId) {
- var leftPanel = Ext.getCmp(leftPanelId);
- Ext.getBody().unmask();
- for (var i = 0; i < data.length; i++) {
- if(i == 0) {
- leftPanel.add({
- xtype: "panel",
- itemId: data[i].id,
- title: data[i].text,
- iconCls: data[i].iconCls,
- layout: 'fit',
- items: [
- {
- xtype: "lefttreepanel",
- root: {
- id: data[i].id,
- expanded: true
- }
- }
- ]
- });
- } else {
- leftPanel.add({
- xtype: "panel",
- itemId: data[i].id,
- title: data[i].text,
- iconCls: data[i].iconCls,
- layout: 'fit'
- });
- }
- }
- leftPanel.updateLayout();
- },
- /**
- * 更换皮肤
- */
- changeTheme: function(itemId, checked) {
- if (checked) {
- var css = OA.util.AppUtil.extjsThemePath;
- cssname = itemId.replace("Skin-", "").toLowerCase();
- css += "ext-theme-" + cssname + "/ext-theme-" + (cssname == "default" ? "classic" : cssname) + "-all.css";
- Ext.util.CSS.swapStyleSheet(null, css);
- var exp = new Date();
- //Cookie保存30天
- exp.setTime(exp.getTime() + 30 * 24 * 60 * 60 * 1000);
- Ext.util.Cookies.set("ThemeCSS", css, exp);
- Ext.util.Cookies.set("ThemeName", itemId, exp);
- }
- }
- }
- });
index.jsp是测试页面
demo里也附带了换肤功能实现
需要源代码的,请加Q-Q群 105098806
转载:http://iamyida.iteye.com/blog/2181805