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

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

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


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




        画图不是强项,看得懂就行。
        1、grid在渲染好后就会通过Stroe来取得数据;
        2、Stroe会发送ajax请求至后台服务器,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 = http://www.mamicode.com/"/module")>
        5、在service包中加入ModuleService.java,用来完成查询,新增,删除,修改的功能。
        6、加入ModuleDAO.java ,用来根据模块名称,起始行,终止行,筛选条件等来从数据库中取得数据。这些类太多了,就不一一写明了。




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