zoukankan      html  css  js  c++  java
  • 跟我一起学extjs5(37--单个模块的设计[5取得模块列表数据])

    跟我一起学extjs5(37--单个模块的设计[5取得模块列表数据])


            写了几个月,总算有点盼头了,最终要从后台取得数据了。后台的spring mvc 和 service 仅仅能简单的说说了,里面加了几十个类。有兴趣的下载了源代码自己看。以下画张通用的模块列表取数据的流程,这个流程是适用于全部的模块。我这个后台处理程序也是对全部的模块进行统一处理,包含数据查找,新增,改动,删除都是同样的。





            绘图不是强项。看得懂即可。
            1、grid在渲染好后就会通过Stroe来取得数据;
            2、Stroe会发送ajax请求至后台server,spring mvc 会依据请求找到 ModuleController 中的对应取得数据的函数;
            3、控制器中调用ModuleService中的函数取得数据。
            4、Service再调用 ModuleDAO的函数从数据库中取得数据,然后一级级的返回到Store中。再显示在Grid之中。


            如今我们先做extjs5端的改动。原来的Store使用的是本地数据,如今要改成远程调用的数据,

    1、先改动model的生成函数ModelFactory.js。这个函数依据传入的module的定义来生成model,主要生成的有fields属性和proxy。另一些以后要用到的函数。比方推断此条记录能否改动、删除等的函数。

    另一个是取得本条记录的标志字段的函数。

    /**
     * 依据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,用来完毕查询,新增,删除。改动的功能。

            6、增加ModuleDAO.java ,用来依据模块名称。起始行,终止行,筛选条件等来从数据库中取得数据。这些类太多了,就不一一写明了。




  • 相关阅读:
    SubString函数总结
    button按钮居中
    2019 面试题
    linux(centos)搭建SVN服务器
    svn 设置钩子将代码同步到web目录下面
    sql 语句总结
    php 多维数组转换
    php 两个数组是否相同,并且输出全面的数据,相同的加一个字段标示
    PHP错误类型及屏蔽方法
    设置div中文字超出时自动换行
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5077518.html
Copyright © 2011-2022 走看看