跟我一起学extjs5(37--单个模块的设计[5取得模块列表数据])
跟我一起学extjs5(37--单个模块的设计[5取得模块列表数据])
另一个是取得本条记录的标志字段的函数。
/** * 依据module的数据来生成模块的model */ Ext.define('app.view.module.factory.ModelFactory', { statics : { getModelByModule : function(module) { var model = Ext.define('app.model.' + module.tf_moduleName, { extend : 'Ext.data.Model', module : module, idProperty : module.tf_primaryKey, nameFields : module.tf_nameFields, titleTpl : module.tf_titleTpl, titleTemplate : null, fields : this.getFields(module), proxy : { type : 'rest', batchActions : true, extraParams : { moduleName : module.tf_moduleName }, api : { // 在这里加rest/是由于在web.xml中 // <url-pattern>/rest/*</url-pattern>这一句。spring会依据rest // 后面的參数去进行匹配 read : 'rest/module/fetchdata.do', update : 'rest/module/update.do', create : 'rest/module/create.do', destroy : 'rest/module/remove.do' }, actionMethods : { create : 'POST', read : 'GET', update : 'PUT', destroy : 'DELETE' }, reader : { type : 'json', root : 'records', totalProperty : 'totalCount' }, writer : { type : 'json', writeRecordId : true, writeAllFields : false // 没有改动过的字段不增加到update和delete的json中去 }, listeners : { exception : function(proxy, response, operation) { // 将出错信息加到proxy中去,传递到store的sync中显示出错信息。显示后将此属性删除 proxy.errorInfo = Ext.decode(response.responseText, true); // 假设出错信息解析出错,则增加一个缺省的 if (!proxy.errorInfo) proxy.errorInfo = { resultCode : -1, errorMessage : '未知原因:' + response.responseText } } } }, getTitleTpl : function() { if (!this.titleTemplate) { if (this.titleTpl) this.titleTemplate = new Ext.Template(this.titleTpl); else this.titleTemplate = new Ext.Template('{' + this.nameFields + '}'); } return this.titleTemplate.apply(this.getData()) }, // 此条记录能否够改动 canEdit : function() { if (this.module.tf_hasAuditing && this.get('tf_auditinged')) return false; if (this.module.tf_hasApprove && this.get('tf_shNowCount') > 0) return false; return true; }, // 此条记录能否够进行操作 canOperate : function() { if (this.module.tf_hasAuditing && this.get('tf_auditinged')) return false; return true; }, // 此条记录能否够删除 canDelete : function() { if (this.module.tf_hasAuditing && this.get('tf_auditinged')) return { canDelete : false, message : '【' + this.getTitleTpl() + '】已进行过审核,不同意进行删除操作!' }; if (this.module.tf_hasApprove && this.get('tf_shNowCount') > 0) return { canDelete : false, message : '【' + this.getTitleTpl() + '】正在审批或已经审批完毕,不同意进行删除操作!' }; return true; }, // 取得主键值 getIdValue : function() { return this.get(this.idProperty); }, // 取得当前记录的名字字段 getNameValue : function() { if (this.nameFields) return this.get(this.nameFields); else return null; } }); return model; }, // String("String"), Boolean("Boolean"), Integer("Integer"), // Date("Date"), Double("Double"), Float("Float"); Percent getFields : function(module) { var fields = []; for (var i in module.moduleFields) { var fd = module.moduleFields[i]; var field = { name : fd.tf_fieldName, title : fd.tf_title, type : this.getTypeByStr(fd.tf_fieldType) }; if (field.type == 'string') { field.useNull = true; field.serialize = this.convertToNull; } if (fd.tf_fieldType == 'Date') { field.dateWriteFormat = 'Y-m-d'; field.dateReadFormat = 'Y-m-d'; } if (fd.tf_fieldType == 'Datetime') field.dateReadFormat = 'Y-m-d H:i:s'; field.tf_haveAttachment = fd.tf_haveAttachment; fields.push(field); } return fields; }, getTypeByStr : function(str) { console.log(str); switch (str) { case 'String' : return 'string'; case 'Boolean' : return 'boolean'; case 'Integer' : return 'int'; case 'Date' : return 'date'; case 'Datetime' : return 'date'; case 'Double' : case 'Float' : case 'Percent' : return 'float'; default : return 'string'; } }, // 假设是空字符串,返回null convertToNull : function(v) { return v ?v : null; } } });
2、在app.store的文件夹下生成文件GridStore.js。这是grid的Store的类的定义。
Ext.define('app.store.GridStore', { extend : 'Ext.data.Store', modulePanel : null, remoteSort : true, autoLoad : true, autoSync : true, leadingBufferZone : 100, buffered : false, // buffered=true能够无限下拉。可是删除和新增,reload都有问题,临时不用 config : { extraParams : {}, navigates : [] // 导航属性选中的情况 }, constructor : function(param) { var me = this; this.pageSize = 20; this.extraParams = {}; this.navigates = []; // 有创建时加进来的导航约束 if (param.modulePanel.param) { var dnv = param.modulePanel.param.defaultNavigateValues; this.setDefaultNavigates(dnv); } // /////////// this.callParent(arguments); }, listeners : { // 调用proxy进行ajax的时候。将參数加进 store.proxy中,在调用完毕后。删除掉全部的extraParams參数 // 这样model.proxy就能够多store,互相不干扰了 beforeprefetch : function(store) { for (var i in store.extraParams) store.proxy.extraParams[i] = store.extraParams[i]; }, // buffered = true ,运行的是 prefetch prefetch : function(store, records, successful) { for (var i in store.extraParams) delete store.proxy.extraParams[i]; }, // buffered = false ,运行的是 load beforeload : function(store) { // console.log(store); for (var i in store.extraParams) store.proxy.extraParams[i] = store.extraParams[i]; }, load : function(store) { for (var i in store.extraParams) delete store.proxy.extraParams[i]; } } });
3、改动app.view.module.Module类。把store 和 model的生成方式都改一下。
initComponent : function() { console.log(this.moduleName + ' 正在创建'); // 从MainModel中取得当前模块的定义数据。包含字段和各种设置的信息 var mainmodel = this.up('app-main').getViewModel(); this.module = mainmodel.getModuleDefine(this.moduleName); var viewmodel = new Ext.create('app.view.module.ModuleModel', { // 将该模块的定义信息传递给本模块的viewModel module : this.module }); this.setViewModel(viewmodel); this.glyph = this.getViewModel().get('tf_glyph'); // 因为上面的glyph的bind无效,因此须要在这里增加glyph的设置 this.model = app.view.module.factory.ModelFactory.getModelByModule(this.module); this.store = Ext.create('app.store.GridStore', { module : this.module, model : this.model, modulePanel : this }); this.items = [{ xtype : 'navigate', // 导航区域 region : 'west',
4、后台服务器端在com.jfok.server.controller下增加ModuleController.java,这是spring mvc 的控制类。
package com.jfok.server.controller; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.exception.ConstraintViolationException; import org.springframework.dao.DataAccessException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import com.jfok.server.DAO.SystemBaseDAO; import com.jfok.server.DAO.module.ModuleDAO; import com.jfok.server.DAO.module.SqlModuleFilter; import com.jfok.server.common.ModuleServiceFunction; import com.jfok.server.hibernate.system._Module; import com.jfok.server.service.ApplicationService; import com.jfok.server.service.ModuleService; import com.jfok.shared.module.DataDeleteResponseInfo; import com.jfok.shared.module.DataFetchResponseInfo; import com.jfok.shared.module.DataInsertResponseInfo; import com.jfok.shared.module.DataUpdateResponseInfo; @Controller @RequestMapping(value = "/module") /** * 所有模块的的CRUD都是调用这个类的函数来完毕的Controller里面完毕的 * * @author jiangfeng * */ public class ModuleController { @Resource private SystemBaseDAO systemBaseDAO; @Resource private ModuleService moduleService; @Resource private ModuleDAO moduleDAO; private static final Log log = LogFactory.getLog(ModuleController.class); /** * 依据前台的请求取得数据 */ @RequestMapping(value = "/fetchdata.do", method = RequestMethod.GET) public @ResponseBody Map<String, Object> fetchData(String moduleName, Integer start, Integer limit, String sort, String query, String columns, String navigates, String parentFilter, HttpServletRequest request) { DataFetchResponseInfo response = moduleService.fetchDataInner(moduleName, start, limit, sort, query, columns, navigates, parentFilter, (SqlModuleFilter) null, request); Map<String, Object> result = new HashMap<String, Object>(); result.put("records", response.getMatchingObjects()); result.put("totalCount", response.getTotalRows()); return result; } /** * 新增记录的时候,在后台取得缺省值 * * @param moduleName * @param parentFilter * @param navigates * @param request * @return */ @RequestMapping(value = "/getnewdefault.do", method = RequestMethod.POST) public @ResponseBody Object getRecordNewDefault(String moduleName, String parentFilter, String navigates, HttpServletRequest request) { return moduleService.getRecordNewDefault(moduleName, parentFilter, navigates, request); } @RequestMapping(value = "/fetchdata.do/{id}", method = RequestMethod.GET) public @ResponseBody Object getRecordById(String moduleName, @PathVariable("id") String id, HttpServletRequest request) { log.debug("依据主键取得模块的一条记录:" + moduleName + "," + id); Map<String, Object> result = new HashMap<String, Object>(); result.put("totalCount", 1); List<Object> records = new ArrayList<Object>(); try { records.add(moduleDAO.getModuleRecord(moduleName, id, request).toString()); } catch (Exception e) { e.printStackTrace(); } result.put("records", records); log.debug("getRecordById返回值:" + result.toString()); return result; } /** * 创建一条记录 * * @param moduleName * @param inserted * @param request * @return */ @RequestMapping(value = "/create.do", method = RequestMethod.POST) public @ResponseBody DataInsertResponseInfo addWithNoPrimaryKey(String moduleName, @RequestBody String inserted, HttpServletRequest request) { return add(moduleName, inserted, request); } @RequestMapping(value = "/create.do/{id}", method = RequestMethod.POST) public @ResponseBody DataInsertResponseInfo add(String moduleName, @RequestBody String inserted, HttpServletRequest request) { DataInsertResponseInfo result = null; try { result = moduleService.add(moduleName, inserted, request); if (result.getKey() != null) // 假设是空的话,那么就没有保存,错误原因已经在errorMessage里了 result.getRecords().add( moduleDAO.getModuleRecord(moduleName, result.getKey(), request).toString()); } catch (DataAccessException e) { e.printStackTrace(); if (result == null) result = new DataInsertResponseInfo(); result.setResultCode(ModuleService.STATUS_VALIDATION_ERROR); } catch (Exception e) { e.printStackTrace(); if (result == null) result = new DataInsertResponseInfo(); result.getErrorMessage().put("error", e.getMessage()); result.setResultCode(ModuleService.STATUS_FAILURE); } return result; } /** * 改动记录 * * @param moduleName * @param id * @param oldid * @param operType * @param updated * @param request * @return */ @RequestMapping(value = "/update.do/{id}", method = RequestMethod.PUT) public @ResponseBody DataUpdateResponseInfo update(String moduleName, @PathVariable("id") String id, String oldid, String operType, @RequestBody String updated, HttpServletRequest request) { DataUpdateResponseInfo result = null; _Module module = ApplicationService.getModuleWithName(moduleName); // 假设主键值改动了,那么先进行主键的改动 if (oldid != null && (!oldid.equals(id))) { try { result = moduleService.changeRecordId(moduleName, id, oldid); } catch (ConstraintViolationException e) { e.printStackTrace(); result = new DataUpdateResponseInfo(); if (e.getCause().toString().toLowerCase().indexOf("primary key") >= 0) result.getErrorMessage().put(module.getTf_primaryKey(), "改动过后的主键与原有的主键值反复!"); else result.getErrorMessage().put(module.getTf_primaryKey(), "当前主键与子模块有约束关系。不能够改动!"); result.setResultCode(ModuleService.STATUS_VALIDATION_ERROR); } if (!result.getResultCode().equals(0)) return result; } // 改动记录 try { result = moduleService.update(moduleName, id, operType, updated, request); result.getRecords().add(moduleDAO.getModuleRecord(moduleName, id, request).toString()); } catch (DataAccessException e) { result = new DataUpdateResponseInfo(); result.setResultCode(ModuleService.STATUS_VALIDATION_ERROR); } catch (Exception e) { e.printStackTrace(); result = new DataUpdateResponseInfo(); result.getErrorMessage().put("error", e.getMessage()); result.setResultCode(ModuleService.STATUS_FAILURE); } return result; } /** * 删除记录 * * @param moduleName * @param id * @param request * @return */ @RequestMapping(value = "/remove.do/{id}", method = RequestMethod.DELETE) public @ResponseBody DataDeleteResponseInfo remove(String moduleName, @PathVariable String id, HttpServletRequest request) { DataDeleteResponseInfo result = null; try { result = moduleService.remove(moduleName, id, request); } catch (DataAccessException e) { result = new DataDeleteResponseInfo(); String errormessage = ModuleServiceFunction.addPK_ConstraintMessage(e, moduleName); result.setResultMessage(-1, errormessage != null ? errormessage : "请检查与本记录相关联的其它数据是否所有清空!<br/>"); } catch (Exception e) { result = new DataDeleteResponseInfo(); result.setResultMessage(-1, e.getMessage()); } return result; } @RequestMapping(value = "/removerecords.do") public @ResponseBody DataDeleteResponseInfo removeRecords(String moduleName, String ids, String titles, HttpServletRequest request) { DataDeleteResponseInfo result = null; String[] idarray = ids.split(","); String[] titlearray = titles.split("~~"); result = new DataDeleteResponseInfo(); for (int i = 0; i < idarray.length; i++) { try { DataDeleteResponseInfo recordDeleteResult = moduleService.remove(moduleName, idarray[i], request); if (recordDeleteResult.getResultCode() == 0) result.getOkMessageList().add(titlearray[i]); else { if (recordDeleteResult.getErrorMessageList().size() > 0) result.getErrorMessageList().add( "【" + titlearray[i] + "】" + recordDeleteResult.getErrorMessageList().get(0)); else result.getErrorMessageList().add("【" + titlearray[i] + "】" + "未知错误!"); } } catch (DataAccessException e) { String errormessage = ModuleServiceFunction.addPK_ConstraintMessage(e, moduleName); result.getErrorMessageList().add( "【" + titlearray[i] + "】" + (errormessage != null ?
errormessage : "关联的数据未清空!")); } catch (Exception e) { result.getErrorMessageList().add("【" + titlearray[i] + "】" + e.getMessage()); } } result.setResultCode(result.getErrorMessageList().size()); return result; } }
5、在service包中增加ModuleService.java,用来完毕查询,新增,删除。改动的功能。