经过前面几篇文章的介绍,一个基本的MVC结构应该是具备了。而且上一篇文章中,也已经实现了一个基本的用户管理列表页面。接着上一篇,完善用户管理,实现增删改。为了用户体验,增加和修改用户信息的表单,都放在弹窗中进行。避免跳转页面。
定义用户增加窗口:app/luter/view/sys/user/UserAdd.js
Ext.define('luter.view.sys.user.UserAdd', { extend: 'Ext.window.Window',//扩展window组件 alias: 'widget.useraddview', requires: [], constrain: true,//约束窗体弹出,别出浏览器可视范围 modal: true,//模态 maximizable: true,//可以最大化 iconCls: baseConfig.appicon.add,//图标 layout: "fit",//自适应布局 width: 700, autoHeight: true,//自适应高度 viewModel: { data: { title: '' } }, bind: { title: '新增用户: ' + '{title}'//绑定这个空间的title属性上 }, initComponent: function () { var me = this; //加入一个表单,表单内元素通过loadView方法添加 me.items = [{ xtype: 'form', width: 700, autoHeight: true, fieldDefaults: { labelAlign: 'right', labelStyle: 'font-weight:bold;' }, border: false }] //操作按钮直接加载window上 me.buttons = ['->', { text: '新增', cls: 'green-btn', iconCls: baseConfig.appicon.add, handler: function () { var form = this.down('form'); if (form.isValid()) { form.submit({ url: 'sys/user/add', method: 'POST', waitTitle: "提示", waitMsg: '正在提交数据,请稍后 ……', success: function (form, action) {//添加成功后提示消息,并且刷新用户列表数据 me.close(); DealAjaxResponse(action.response); Ext.data.StoreManager.lookup('UserStore').load(); }, failure: function (form, action) { DealAjaxResponse(action.response); } }); } else { toast({ msg: '表单填写错误,请确认' }) } }, scope: this }, '-', { text: '放弃', cls: 'red-btn', iconCls: baseConfig.appicon.undo, handler: function () { me.close(); }, scope: this }] me.callParent(arguments); }, //form表单的渲染在这里完成,目的是可以通过创建操作传入参数 loadView: function (config) { var formCmp = this.getComponent(0); formCmp.add([{ columnWidth: 1, layout: "form", items: [{ xtype: "textfield", fieldLabel: baseConfig.model.user.username, name: 'username', maxLength: 250, maxLengthText: '请输入{0}个字以内', emptyText: '登录用的用户名', bind: '{title}',//mvvm数据绑定,输入的时候同步就显示在win的title上了 allowBlank: false, flex: 1 }, { xtype: "textfield", fieldLabel: baseConfig.model.user.real_name, name: 'real_name', maxLength: 10, maxLengthText: '请输入{0}个字以内', emptyText: '真实姓名', allowBlank: false, flex: 1 } ] }]); }});
添加用户的触发动作是在用户列表页面的添加按钮,所以,还需要修改一下用户列表页面里对应位置,加入触发动作,如下:
。。。。。 me.dockedItems = [{ xtype: 'toolbar', items: [{ text: '添加', iconCls: baseConfig.appicon.add, tooltip: '添加', handler: function () { //create的时候,js会动态加载进来。 var win = Ext.create('luter.view.sys.user.UserAdd', { animateTarget: this//以这个按钮为锚点动画打开win }); win.loadView();//给form加入元素,可以在这里传入一些参数给将要打开的添加页面 win.show();//显示这个窗体 } }] }]。。。。。。
定义用户信息修改窗口:app/luter/view/sys/user/UserEdit.js
Ext.define('luter.view.sys.user.UserEdit', { extend: 'Ext.window.Window',//扩展window组件 alias: 'widget.usereditview', requires: [], constrain: true,//约束窗体弹出,别出浏览器可视范围 modal: true,//模态 maximizable: true,//可以最大化 iconCls: baseConfig.appicon.update,//图标 layout: "fit",//自适应布局 width: 700, autoHeight: true,//自适应高度 initComponent: function () { var me = this; //加入一个表单,表单内元素通过loadView方法添加 me.items = [{ xtype: 'form', width: 700, autoHeight: true, fieldDefaults: { labelAlign: 'right', labelStyle: 'font-weight:bold;' }, border: false }] //操作按钮直接加载window上 me.buttons = ['->', { text: '新增', cls: 'green-btn', iconCls: baseConfig.appicon.add, handler: function () { var form = this.down('form'); if (form.isValid()) { form.submit({ url: 'sys/user/update', method: 'POST', waitTitle: "提示", waitMsg: '正在提交数据,请稍后 ……', success: function (form, action) {//添加成功后提示消息,并且刷新用户列表数据 me.close(); DealAjaxResponse(action.response); Ext.data.StoreManager.lookup('UserStore').load(); }, failure: function (form, action) { DealAjaxResponse(action.response); } }); } else { toast({ msg: '表单填写错误,请确认' }) } }, scope: this }, '-', { text: '放弃', cls: 'red-btn', iconCls: baseConfig.appicon.undo, handler: function () { me.close(); }, scope: this }] me.callParent(arguments); }, loadView: function (config) { var formCmp = this.getComponent(0); formCmp.add([{ columnWidth: 1, layout: "form", items: [{ xtype: "hidden",//这里放一个隐藏控件,因为是修改记录,所以必须提交ID name: 'id' }, { xtype: "textfield", fieldLabel: baseConfig.model.user.username, name: 'username', maxLength: 250, maxLengthText: '请输入{0}个字以内', emptyText: '登录用的用户名', allowBlank: false, flex: 1 }, { xtype: "textfield", fieldLabel: baseConfig.model.user.real_name, name: 'real_name', maxLength: 10, maxLengthText: '请输入{0}个字以内', emptyText: '真实姓名', allowBlank: false, flex: 1 } ] }]); }});
我们希望在双击用户列表中的某一条记录(某个用户)的时候,弹出用户修改对话框,所以,修改用户列表页面代码,添加列表行双击事件的监听,如下:
。。。。。。me.listeners = { 'itemdblclick': function (table, record, html, row, event, opt) { if (record) { var id = record.get('id'); var view = Ext.create('luter.view.sys.user.UserEdit', {title: '编辑数据', animateTarget: this}); view.loadView(); //为了保证数据完整性,拿到这条数据的ID后,需要从后台获取当前这条数据,然后再修改 //对于后台而言,最好对数据设置@version功能,确保数据一致性。 loadFormDataFromDb(view, 'app/testdata/user.json'); } else { showFailMesg({ msg: '加载信息失败,请确认。' }) } } }。。。。。。
添加记录删除操作
在用户列表中,设置action列,实现删除操作,如下:
....... me.columns = [{ xtype: 'rownumberer', text: '序号', width: 60 }, { header: "操作", xtype: "actioncolumn", width: 60, sortable: false, items: [{ text: "删除", iconCls: 'icon-delete', tooltip: "删除这条记录", handler: function (grid, rowIndex, colIndex) { var record = grid.getStore().getAt(rowIndex); if (!record) { toast({ msg: '请选中一条要删除的记录' }) } else { showConfirmMesg({ message: '确定删除这条记录?', fn: function (btn) { if (btn === 'yes') { showToastMessage('啥意思?');//测试一下而已,实际情况是执行ajax删除,如下。 // Ext.Ajax.request({ // url: 'sys/user/delete', // method: 'POST', // params: { // id: record.get('id') // }, // success: function (response, options) { // DealAjaxResponse(response); // Ext.data.StoreManager.lookup('UserStore').load(); // }, // failure: function (response, options) { // DealAjaxResponse(response); // } // }); } else { Ext.toast({ title:'看...', width:200, html: '不删了.....' }); return false; } } }) } } }] }, { header: baseConfig.model.user.id, dataIndex: 'id', hidden: false, flex: 1 }, { header: baseConfig.model.user.username, dataIndex: 'username', flex: 1 }, { header: baseConfig.model.user.real_name, dataIndex: 'real_name', flex: 1 } ].......
extjs样式覆盖app/resource/css/admin.css
主要覆盖了左侧导航菜单treelist和中间tabpanel的部分风格样式,
记得在app.html中extjs样式之后引入覆盖样式.x-treelist-navigation { background-color: #32404e; background-position: 44px 0%; padding: 0 0 0 0}.x-big .x-treelist-navigation { background-position: 0%}.x-treelist-navigation .x-treelist-toolstrip { background-color: #32404e}.x-treelist-navigation .x-treelist-item-selected.x-treelist-item-tool { background-color: #475360}.x-treelist-navigation .x-treelist-item-selected.x-treelist-item-tool:after { height: 50px; position: absolute; top: 0; left: 0; content: " "; width: 5px; background-color: #35baf6}.x-treelist-navigation .x-treelist-item-selected > .x-treelist-row { background-color: #475360}.x-treelist-navigation .x-treelist-item-tool { padding-left: 10px; padding-right: 10px}.x-treelist-navigation .x-treelist-item-tool-floated:after { height: 50px; position: absolute; top: 0; left: 0; content: " "; width: 5px; background-color: #35baf6}.x-treelist-navigation .x-treelist-item-icon:before, .x-treelist-navigation .x-treelist-item-tool:before, .x-treelist-navigation .x-treelist-item-expander { line-height: 50px}.x-treelist-navigation .x-treelist-item-icon, .x-treelist-navigation .x-treelist-item-tool, .x-treelist-navigation .x-treelist-item-expander { text-align: center; background-repeat: no-repeat; background-position: 0 center}.x-treelist-navigation .x-treelist-item-icon, .x-treelist-navigation .x-treelist-item-tool { color: #adb3b8; font-size: 18px; width: 44px}.x-treelist-navigation .x-treelist-item-tool { width: 50px}.x-treelist-navigation .x-treelist-item-expander { color: #fff; font-size: 16px; width: 24px}.x-treelist-navigation .x-treelist-item-text { color: #adb3b8; margin-left: 50px; margin-right: 24px; font-size: 14px; font-weight: 900; line-height: 50px}.x-treelist-navigation .x-treelist-row { padding-left: 10px; padding-right: 10px}.x-treelist-navigation .x-treelist-row-over:before, .x-treelist-navigation .x-treelist-item-selected > .x-treelist-row:before { content: " "; position: absolute; display: block; left: 0; top: 0; width: 5px; height: 100%}.x-treelist-navigation .x-treelist-row-over:before { background-color: transparent}.x-treelist-navigation .x-treelist-item-selected > .x-treelist-row-over:before { background-color: #57c6f8}.x-treelist-navigation .x-treelist-item-selected > .x-treelist-row:before { background-color: #35baf6}.x-treelist-navigation .x-treelist-item-floated .x-treelist-container { width: auto}.x-treelist-navigation .x-treelist-item-floated > .x-treelist-row { background-color: #32404e}.x-treelist-navigation .x-treelist-item-floated > .x-treelist-container { margin-left: -44px}.x-big .x-treelist-navigation .x-treelist-item-floated > .x-treelist-container { margin-left: 0}.x-treelist-navigation .x-treelist-item-floated > * > * > .x-treelist-item-text { margin-left: 0}.x-treelist-navigation .x-treelist-item-floated > * .x-treelist-row { padding-left: 0}.x-treelist-navigation .x-treelist-item-floated .x-treelist-row:before { width: 0}.x-treelist-navigation .x-treelist-item-floated > .x-treelist-row-over { background-color: #32404e}.x-treelist-navigation .x-treelist-item-floated > .x-treelist-row-over > * > .x-treelist-item-text { color: #adb3b8}.x-treelist-navigation .x-treelist-item-expanded { background-color: #2c3845}.x-treelist-navigation.x-treelist-highlight-path .x-treelist-item-over > * > .x-treelist-item-icon { color: #fff}.x-treelist-navigation.x-treelist-highlight-path .x-treelist-item-over > * > .x-treelist-item-text { color: #d6d9dc}.x-treelist-navigation.x-treelist-highlight-path .x-treelist-item-over > * > .x-treelist-item-expander { color: #fff}.x-treelist-navigation .x-treelist-row-over { background-color: #3c4a57}.x-treelist-navigation .x-treelist-row-over > * > .x-treelist-item-icon { color: #fff}.x-treelist-navigation .x-treelist-row-over > * > .x-treelist-item-text { color: #d6d9dc}.x-treelist-navigation .x-treelist-row-over > * > .x-treelist-item-expander { color: #fff}.x-treelist-navigation .x-treelist-expander-first .x-treelist-item-icon { left: 24px}.x-treelist-navigation .x-treelist-expander-first .x-treelist-item-text { margin-left: 74px; margin-right: 0}.x-treelist-navigation .x-treelist-expander-first .x-treelist-item-hide-icon > * > * > .x-treelist-item-text { margin-left: 30px}.x-treelist-navigation .x-treelist-item-hide-icon > * > * > .x-treelist-item-text { margin-left: 6px}.x-tab-bar-default{ height: 40px; /*background-color: #0e2349;*/}.x-tab-default-top { -webkit-border-radius: 0; -moz-border-radius: 0; -ms-border-radius: 0; border-radius: 0; padding: 8px 10px 7px 10px; border-width: 0; border-style: solid; background-color: transparent}.x-tab-bar-default-top > .x-tab-bar-body-default{ padding:0}.x-nbr .x-tab-default-top { padding: 0 !important; border-width: 0 !important; -webkit-border-radius: 0px; -moz-border-radius: 0px; -ms-border-radius: 0px; border-radius: 0px; background-color: transparent !important; box-shadow: none !important}.x-tab-default { border-color: transparent; cursor: pointer}.x-tab-default-top { margin: 0 4px 0 0}.x-tab-default-top.x-tab-rotate-left { margin: 0 0 0 4px}.x-tab-default-top.x-tab-focus { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none}.x-tab-default-top.x-tab-focus.x-tab-over { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none}.x-tab-default-top.x-tab-focus.x-tab-active { -webkit-box-shadow: none; -moz-box-shadow: none; box-shadow: none; background-color: #1d9ce5;}.x-tab-button-default { padding-top: 5px; height: 20px}.x-tab-inner-default { font: 500 13px/20px 'Open Sans', 'Helvetica Neue', helvetica, arial, verdana, sans-serif; /*color: #f0f0f0;*/ max-width: 100%}.x-tab-bar-plain .x-tab-inner-default { color: #606060}.x-tab-icon-right>.x-tab-inner-default,.x-tab-icon-left>.x-tab-inner-default { max-width: calc(100% - 20px)}.x-tab-icon-el-default { min-height: 20px; background-position: center center; font-size: 20px; line-height: 20px; color: #f0f0f0}.x-tab-icon-left>.x-tab-icon-el-default,.x-tab-icon-right>.x-tab-icon-el-default { width: 20px}.x-tab-icon-top>.x-tab-icon-el-default,.x-tab-icon-bottom>.x-tab-icon-el-default { min-width: 20px}.x-tab-bar-plain .x-tab-icon-el-default { color: #606060}.x-tab-icon-el-default.x-tab-glyph { opacity: 0.7}.x-tab-text.x-tab-icon-left>.x-tab-icon-el-default { margin-right: 6px}.x-tab-text.x-tab-icon-right>.x-tab-icon-el-default { margin-left: 6px}.x-tab-text.x-tab-icon-top>.x-tab-icon-el-default { margin-bottom: 6px}.x-tab-text.x-tab-icon-bottom>.x-tab-icon-el-default { margin-top: 6px}.x-tab-focus.x-tab-default { border-color: transparent; background-color: transparent; outline: 1px solid #35baf6; outline-offset: -3px}.x-ie .x-tab-focus.x-tab-default,.x-ie10p .x-tab-focus.x-tab-default,.x-edge .x-tab-focus.x-tab-default { outline: none}.x-ie .x-tab-focus.x-tab-default:after,.x-ie10p .x-tab-focus.x-tab-default:after,.x-edge .x-tab-focus.x-tab-default:after { position: absolute; content: ' '; top: 2px; right: 2px; bottom: 2px; left: 2px; border: 1px solid #35baf6; pointer-events: none}.x-tab-bar-plain .x-tab-focus.x-tab-default .x-tab-inner-default { color: #606060}.x-tab-bar-plain .x-tab-focus.x-tab-default .x-tab-icon-el { color: #606060}.x-tab-over.x-tab-default { border-color: #000; background-image: none; background-color: rgba(0, 0, 0, 0.08)}.x-ie8 .x-tab-over.x-tab-default { -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#14000000, endColorstr=#14000000)"; zoom: 1}.x-ie8 .x-tab-over.x-tab-default.x-tab-rotate-left { -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"}.x-ie8 .x-tab-over.x-tab-default.x-tab-rotate-right { -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"}.x-tab-bar-plain .x-tab-over.x-tab-default .x-tab-inner-default { color: #606060}.x-tab-bar-plain .x-tab-over.x-tab-default .x-tab-icon-el { color: #606060}.x-tab-focus.x-tab-over.x-tab-default { border-color: #000; background-image: none; background-color: rgba(0, 0, 0, 0.08)}.x-ie8 .x-tab-focus.x-tab-over.x-tab-default { -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#14000000, endColorstr=#14000000)"; zoom: 1}.x-ie8 .x-tab-focus.x-tab-over.x-tab-default.x-tab-rotate-left { -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"}.x-ie8 .x-tab-focus.x-tab-over.x-tab-default.x-tab-rotate-right { -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"}.x-tab-bar-plain .x-tab-focus.x-tab-over.x-tab-default .x-tab-inner-default { color: #606060}.x-tab-bar-plain .x-tab-focus.x-tab-over.x-tab-default .x-tab-icon-el { color: #606060}.x-tab.x-tab-active.x-tab-default { border-color: #fff; background-color: #fff}.x-tab.x-tab-active.x-tab-default .x-tab-inner-default { color: #105bf3}.x-tab-bar-plain .x-tab.x-tab-active.x-tab-default .x-tab-inner-default { color: #404040}.x-tab.x-tab-active.x-tab-default .x-tab-icon-el { color: #105bf3}.x-ie8 .x-tab.x-tab-active.x-tab-default .x-tab-icon-el { color: #6ab5d6}.x-tab-bar-plain .x-tab.x-tab-active.x-tab-default .x-tab-icon-el { color: #404040}.x-tab-focus.x-tab-active.x-tab-default { border-color: #fff; background-color: #fff}.x-tab-bar-plain .x-tab-focus.x-tab-active.x-tab-default .x-tab-inner-default { color: #404040}.x-tab-bar-plain .x-tab-focus.x-tab-active.x-tab-default .x-tab-icon-el { color: #404040}.x-tab.x-tab-disabled.x-tab-default { border-color: transparent; background-color: transparent; cursor: default}.x-tab.x-tab-disabled.x-tab-default .x-tab-inner-default { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)"; opacity: 0.3}.x-tab-bar-plain .x-tab.x-tab-disabled.x-tab-default .x-tab-inner-default { color: #606060}.x-tab.x-tab-disabled.x-tab-default .x-tab-icon-el-default { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; opacity: 0.5}.x-tab.x-tab-disabled.x-tab-default .x-tab-icon-el { color: #f0f0f0; opacity: 0.3; filter: none}.x-tab-bar-plain .x-tab.x-tab-disabled.x-tab-default .x-tab-icon-el { color: #606060}.x-nbr .x-tab-default { background-image: none}.x-tab-default .x-tab-close-btn:before { content: "\f00d"}.x-tab-default .x-tab-close-btn { top: 0; right: 0; width: 12px; height: 12px; font: 12px/1 FontAwesome; color: red}.x-tab-default.x-tab-active .x-tab-close-btn { color: red}.x-tab-default .x-tab-close-btn-over { background-position: -12px 0; color: red}
至此,应该能看到基本的界面的样子了:)