常规功能和模块自定义系统 (cfcmms)—030开发日志(创建ManyToMany的column5)

030开发日志(创建ManyToMany的column5)

  现在对于这个字段来说,还剩最后一个功能了,那就是可以修改ManyToMany的值了。在grid的inline操作里面,是可以直接删除已有值,但是如果要新增的话,就必须要有一个新的界面了。下面来看看开发修改ManyToMany字段所需要的步骤。

  1、创建一个修改窗口,在里面创建一个可check的树;

  2?到后台请求数据,读取当前记录的所有的ManyToMany的可选项,并把已经选中的打勾;

  3?根据读取到的数据更新树;

  4?用户操作check 和 uncheck;

  5?保存修改,使用ajax 将修改过后的ManyToMany中打勾的选项发送到后台,执行保存功能;

  6?刷新当前记录,显示正确的ManyToMany值。

在以上的步骤中可以看出,对于所有的ManyToMany字段的修改都是用这一个办法。上面步骤中比较难的就是如何根据前台的请求生成模块该记录的ManyToMany的所有选项并把已经选中的打勾,以及保存修改过后的值。对于本系统而言,所有的方法尽量都是通用的,因此有些功能的开发比较困难。

  在进行第2步操作时,前台应传给后台的参数应该有:当前模块名称,当前记录id,ManyToMany的模块名称,中间模块的名称。

  同样在进行第5步操作的时候,也要传给后台第2步的参数,并加上当前所有选中ManyToMany的值。

  接着前一节的ManyToManyColumn.js,来修改一下当用户单击修改按钮的时候要进行的操作。

					processEvent : function(type, view, cell, recordIndex, cellIndex, e,
							record, row) {
						var me = this;
						if (type === 'click') {
							var module = this.up('modulegrid').module;
							if (e.getTarget().className === 'manyToManyContext') {
								app.modules.showModuleRecord(this.manyToManyModuleName, e
										.getTarget().getAttribute('_id'));
							} else if (Ext.String.startsWith(e.getTarget().className,
									'manyToManyContextClose')) {
								// 点击了删除按钮,先找到前面一个节点,里面包含了要删除的信息
								var target = e.getTarget().previousElementSibling;
								var text = module.tf_title + ' ' + record.getTitleTpl() + ' 的 '
										+ this.manyToManyModuleTitle + '【' + target.innerHTML + '】';
								Ext.MessageBox.confirm('确定删除', '确定要删除' + text + '吗?', function(
										btn) {
									if (btn == 'yes') {
										// 使用module里面批量删除的ajax
										Ext.Ajax.request({
											url : 'rest/module/removerecords.do',
											params : {
												moduleName : me.fieldDefine.tf_joinTable,
												ids : target.getAttribute('_joinid'),
												titles : target.innerHTML
											},
											success : function(response) {
												var info = Ext.decode(response.responseText, true);
												if (info.resultCode == 0) {
													Ext.toastInfo(text + ' 已成功被删除。');
													// 删除记录后,刷新当前记录
													me.up('modulegrid').refreshSelectedRecord();
												} else {
													Ext.MessageBox.show({
														title : '删除结果',
														msg : text + '删除失败:<br/><br/>'
																+ info.errorMessageList,
														buttons : Ext.MessageBox.OK,
														icon : Ext.MessageBox.ERROR
													});

												}
											},
											failure : function() {
												window.alert('删除时,服务器返回返回错误');
											}
										})
									}
								});
							} else if (Ext.String.startsWith(e.getTarget().className,
									'manyToManyEdit')) {
								//编辑当前记录的manyToMany字段;
								Ext.widget(
										'manytomanyeditwindow',
										{
											grid : me.up('modulegrid'),
											title : module.tf_title + '【' + record.getTitleTpl()
													+ '】的' + this.manyToManyModuleTitle,
											moduleName : module.tf_moduleName,
											idvalue : record.getIdValue(),
											manyToManyModuleName : me.manyToManyModuleName,
											linkModuleName : me.fieldDefine.tf_joinTable
										}).show();
							}
						}
					}

  在上面的代码中可以看出,如果单击了修改按钮,会去创建一个manytomanyeditwindow。在这个window中完成上面的6步操作。

/**
 * 修改记录的manyToMany字段的窗口,在窗口中完成选择操作,并可保存。
 */

Ext.define('app.module.widget.window.ManyToManyEditWindow', {

	extend : 'Ext.window.Window',
	alias : 'widget.manytomanyeditwindow',
	requires : [ 'app.lib.CheckTreePanel' ],
	width : 450,
	height : 600,
	modal : true,
	maximizable : true,
	layout : 'fit',

	buttons : [ '->', {
		text : '保存',
		iconCls : 'fa fa-save',
		handler : function(button) {
			var window = button.up('window');
			var tree = window.down('treepanel');
			var selected = []
			tree.getRootNode().cascadeBy(function(node) {
				// 所有选中的 ManyToMany 的值
				if (node.data.checked == true && node.data.leaf == true) {
					selected.push(node.data.fieldvalue);
				}
			});
			// 提交ajax请求后台修改
			Ext.Ajax.request({
				url : 'modulemanytomany/setmanytomanydetail.do',
				params : {
					moduleName : window.moduleName,
					id : window.idvalue,
					manyToManyModuleName : window.manyToManyModuleName,
					linkModuleName : window.linkModuleName,
					selected : selected.join(',')
				},
				success : function(response) {
					var info = Ext.decode(response.responseText, true);
					if (info.success) {
						Ext.toastInfo(window.titlemess + ' 已保存。');
						window.grid.refreshSelectedRecord();
						window.close();
					} else
						Ext.toastError(window.titlemess + ' 保存失败。<br>' + '原因:' + info.msg);
				}
			})
		}
	}, {
		text : '关闭',
		iconCls : 'fa fa-close',
		handler : function(button) {
			button.up('window').close();
		}
	}, '->' ],

	initComponent : function() {
		var me = this;
		this.titlemess = this.title;
		this.title = '设置 ' + this.titlemess;
		this.items = [ {
			xtype : 'checktreepanel',
			autoLoad : false,
			rootVisible : false,
			root : {},
			store : Ext.create('Ext.data.TreeStore', {
				proxy : {
					type : 'ajax',
					url : 'modulemanytomany/getmanytomanydetail.do',
					extraParams : {
						moduleName : me.moduleName,
						id : me.idvalue,
						manyToManyModuleName : me.manyToManyModuleName,
						linkModuleName : me.linkModuleName
					}
				}
			})
		} ];
		this.callParent(arguments);
	}

})

  这是前台的界面操作的代码,那么后台要处理上面所述的第2,第5步。需要新增一个Controller类来接收ajax请求。下面这个是控制类:

package com.jfok.cfcmms.controller;

import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.jfok.cfcmms.service.ModuleManyToManyService;
import com.jfok.cfcmms.share.TreeNodeRecordChecked;
import com.jfok.cfcmms.util.ActionResult;

/**
 * 用来管理模块的ManyToMany数据的读取和修改的保存
 *
 * @author jiangfeng
 *
 *         2016-01-11
 *
 */
@Controller
@RequestMapping("/modulemanytomany")
public class ModuleManyToManyController {

  @Resource
  private ModuleManyToManyService moduleManyToManyService;

  /**
   *
   * @param request
   * @param moduleName
   *          当前模块名称
   * @param id
   *          当前记录id
   * @param manyToManyModuleName
   *          manyToMany的模块名称
   * @param linkModuleName
   *          中间模块名称
   * @return 返回所有manyToManyModuleName的记录数据,并把当前记录已有的manyToMany值的checked置为true
   */
  @RequestMapping("/getmanytomanydetail.do")
  public @ResponseBody List<TreeNodeRecordChecked> genManyToManyDetail(HttpServletRequest request,
      String moduleName, String id, String manyToManyModuleName, String linkModuleName) {
    return moduleManyToManyService.getManyToManyDetail(request, moduleName, id,
        manyToManyModuleName, linkModuleName);

  }

  /**
   *
   * @param request
   * @param moduleName
   *          当前模块名称
   * @param id
   *          当前记录id
   * @param manyToManyModuleName
   *          manyToMany的模块名称
   * @param linkModuleName
   *          中间模块名称
   * @param selected
   *          所有选中的值,以逗号分隔
   * @return 返回所有manyToManyModuleName的记录数据,并把当前记录已有的manyToMany值的checked置为true
   */

  @RequestMapping("/setmanytomanydetail.do")
  public @ResponseBody ActionResult setManyToManyDetail(HttpServletRequest request,
      String moduleName, String id, String manyToManyModuleName, String linkModuleName,
      String selected) {
    return moduleManyToManyService.setManyToManyDetail(request, moduleName, id,
        manyToManyModuleName, linkModuleName, selected.split(","));

  }

}

  最后一个就是用来处理请求的Service类了,这个类也是这个功能的关键。由他来完成系统中所有的类似的ManyToMany字段读取和修改的操作。

package com.jfok.cfcmms.service;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.jfok.cfcmms.DAO.ModuleDAO;
import com.jfok.cfcmms.DAO.SystemBaseDAO;
import com.jfok.cfcmms.core.module.SqlGenerator;
import com.jfok.cfcmms.core.module.SqlModuleFilter;
import com.jfok.cfcmms.hibernate.system.module._Module;
import com.jfok.cfcmms.share.TreeNodeRecord;
import com.jfok.cfcmms.share.TreeNodeRecordChecked;
import com.jfok.cfcmms.share.ValueText;
import com.jfok.cfcmms.util.ActionResult;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

@Service
public class ModuleManyToManyService {

  @Resource
  private SystemBaseDAO systemBaseDAO;

  @Resource
  private ModuleDAO moduleDAO;

  @Resource
  private ModuleService moduleService;

  /**
   *
   * @param request
   * @param moduleName
   *          当前模块名称
   * @param id
   *          当前记录id
   * @param manyToManyModuleName
   *          manyToMany的模块名称
   * @param linkModuleName
   *          中间模块名称
   * @return 返回所有manyToManyModuleName的记录数据,并把当前记录已有的manyToMany值的checked置为true
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
  public List<TreeNodeRecordChecked> getManyToManyDetail(HttpServletRequest request,
      String moduleName, String id, String manyToManyModuleName, String linkModuleName) {
    _Module module = SystemAndLoginInfoService.getModuleWithName(moduleName);
    _Module manyToManyModule = SystemAndLoginInfoService.getModuleWithName(manyToManyModuleName);

    List<TreeNodeRecord> result = new ArrayList<TreeNodeRecord>();

    // 首先读取manyToManyModuleName中的所有权限可视范围之内的数据
    List<ValueText> allTreeItems = moduleDAO.getModuleWithComboDataWithQuery(manyToManyModuleName,
        null, request);
    for (ValueText vt : allTreeItems) {
      TreeNodeRecordChecked record = new TreeNodeRecordChecked();
      record.setFieldvalue(vt.getValue());
      record.setText(vt.getText());
      record.setLeaf(true);
      result.add(record);
    }
    // 在linkModuleName中读取当前id的manyToMany的值,在数据可视涠之内
    List<SqlModuleFilter> filters = new ArrayList<SqlModuleFilter>();

    SqlModuleFilter moduleIdFilter = new SqlModuleFilter();
    moduleIdFilter.setModuleName(module.getTf_moduleName());
    moduleIdFilter.setTableAsName(module.getTableAsName());
    moduleIdFilter.setPrimarykey(module.getTf_primaryKey());
    moduleIdFilter.setEqualsValue(id);
    filters.add(moduleIdFilter);

    SqlGenerator generator = new SqlGenerator(linkModuleName, request);
    generator.setModuleFilters(filters);
    JSONArray dataArray = moduleDAO.getData(generator, -1, 0);

    // 生成TreeNodeRecordChecked,并加入checked标志
    for (int i = 0; i < dataArray.size(); i++) {
      String manytomanyid = dataArray.getJSONObject(i).getString(
          manyToManyModule.getTableAsName() + "___" + manyToManyModule.getTf_primaryKey());
      for (TreeNodeRecord record : result) {
        if (record.getFieldvalue().equals(manytomanyid))
          ((TreeNodeRecordChecked) record).setChecked(true);
      }

    }

    // 返回结果

    List<TreeNodeRecordChecked> root = new ArrayList<TreeNodeRecordChecked>();
    TreeNodeRecordChecked rootrecord = new TreeNodeRecordChecked();
    rootrecord.setText(manyToManyModule.getTf_title());
    rootrecord.setChildren(result);
    rootrecord.setExpanded(true);
    root.add(rootrecord);
    return root;
  }

  public ActionResult setManyToManyDetail(HttpServletRequest request, String moduleName, String id,
      String manyToManyModuleName, String linkModuleName, String[] selected) {

    _Module module = SystemAndLoginInfoService.getModuleWithName(moduleName);
    _Module manyToManyModule = SystemAndLoginInfoService.getModuleWithName(manyToManyModuleName);
    _Module linkedModule = SystemAndLoginInfoService.getModuleWithName(linkModuleName);
    // 在linkModuleName中读取当前id的manyToMany的值,在数据可视涠之内
    List<SqlModuleFilter> filters = new ArrayList<SqlModuleFilter>();

    SqlModuleFilter moduleIdFilter = new SqlModuleFilter();
    moduleIdFilter.setModuleName(module.getTf_moduleName());
    moduleIdFilter.setTableAsName(module.getTableAsName());
    moduleIdFilter.setPrimarykey(module.getTf_primaryKey());
    moduleIdFilter.setEqualsValue(id);
    filters.add(moduleIdFilter);
    SqlGenerator generator = new SqlGenerator(linkModuleName, request);
    generator.setModuleFilters(filters);
    JSONArray dataArray = moduleDAO.getData(generator, -1, 0);

    // 如果原来有,现在selected里面没有了,那么就要删除了
    for (int i = 0; i < dataArray.size(); i++) {
      String manytomanyid = dataArray.getJSONObject(i).getString(
          manyToManyModule.getTableAsName() + "___" + manyToManyModule.getTf_primaryKey());
      boolean isfound = false;
      for (String selectedid : selected) {
        if (manytomanyid.equals(selectedid)) {
          isfound = true;
          break;
        }
      }
      if (!isfound) {
        // 需要删除这个manyTomany,调用系统Service的remove,会判断能否删除的逻辑,会记入日志
        // 尚未做出错处理
        moduleService.remove(linkModuleName,
            dataArray.getJSONObject(i).getString(linkedModule.getTf_primaryKey()), request);
      }
    }
    // 如果原来没有,现在selected里面有了,那么就要增加进去
    for (String selectedid : selected) {
      if (selectedid.length() > 0) {
        boolean isfound = false;
        for (int i = 0; i < dataArray.size(); i++) {
          String manytomanyid = dataArray.getJSONObject(i).getString(
              manyToManyModule.getTableAsName() + "___" + manyToManyModule.getTf_primaryKey());
          if (manytomanyid.equals(selectedid)) {
            isfound = true;
            break;
          }
        }
        if (!isfound) {
          JSONObject object = new JSONObject();
          object.put(
              manyToManyModule.getTableAsName() + "___" + manyToManyModule.getTf_primaryKey(),
              selectedid);
          object.put(module.getTableAsName() + "___" + module.getTf_primaryKey(), id);
          // 需要新增这个manyTomany,调用系统Service的add ,会判断是否能新增等逻辑,会记入日志
          // 尚未做出错处理
          moduleService.add(linkModuleName, object.toString(), request);
        }
      }
    }
    ActionResult result = new ActionResult();
    return result;
  }
}

  经过以上代码的协同工作,我们可以打开人员的设置权限的窗口来进行权限设置了。

  修改一些用户操作角色,然后保存。

  至此用户的ManyToMany字段操作角色的修改即可完成。

  对于操作角色来说,用户也是一个ManyToMany字段,同样也适用于这样操作。

  至此ManyToMany字段的定义、显示、操作都基本完成。

  进阶设想:

  对于选择tree的改进。在我现在的系统里,在用户模块中,有一个设置权限的按钮,其实就是完成了ManyToMany字段的选择与保存,有了这个字段功能之后,这个设置权限的按钮就可以不要了。但是有一点是不一样的,看看下面的截图:

  在上图的选择角色的窗口的tree中,角色是按照角色分组来进行分类的,这样在选择的时候可以更直观。以后的ManyToMany字段的选择树也要做成可以配置成这样的结构。这里我大体先写一下思路:

  1?在模块配置中新增一个配置字段:ManyToMany选择时候的树形模块路径;

  2?在某个模块被当作ManyToMany字段来选择的时候,读取其模块路径,然后把当前模块的值都加在相应的节点之下。

  比如对于角色来选择人员来说,可以把部门作为人员的模块路径,这样在选择树中,先是部门的值,然后人员会挂在相应的部门之下来进行选择。

  (这个功能以后有时间再做了)

时间: 2024-10-14 05:37:49

常规功能和模块自定义系统 (cfcmms)—030开发日志(创建ManyToMany的column5)的相关文章

常规功能和模块自定义系统 (cfcmms)—029开发日志(创建ManyToMany的column4)

029开发日志(创建ManyToMany的column4) 根据以上几节的准备,在这一节中可以加入ManyToManyColumn.js了.先来看看做好的样子如下图: 单击文字链接可以显示该条记录的情况.按下删除按钮则会显示一个提示窗口,询问是否删除此项. 下面即为ManyToManyColumn.js的代码. /** * * ManyToMany记录的管理,将根据权限设置来显示修改或删除按钮 * * 蒋锋 2015.12.31 * */ Ext .define( 'app.module.wid

常规功能和模块自定义系统 (cfcmms)—032开发日志(用GoJS来绘制模块关系图)

032开发日志(用GoJS来绘制模块关系图) 本系统现在尚没有流程和图表的功能,现在感觉在操作模块的各种功能的时候如果有一个模块关系图,那么就会更直观.网上找了一些绘制图表的库,看了一下GoJS也不错,入门也比较容易.经过一些工作,对业务模块作了一个简单的关系图. GoJS的基础知识请看官网的介绍,在上面的模块图中,有模块节点和连线二种信息需要定义.用户业务模块数据都是由后台组织好后发送到前台的. 整个绘制流程图的界面模块是一个Panel,在render的时候从后台加载数据,然后绘制.js类如下

常规功能和模块自定义系统 (cfcmms)—007Extjs的配置文件和自定义ui

常规功能和模块自定义系统 (cfcmms)-007Extjs的配置文件和自定义ui 一.在自动生成的项目中,文件 app.json 是整个前台系统的配置文件,可以在里面增加或修改配置参数来完成相应的功能.该文件的部分参数如下: { "name": "cfcmms", //项目命名空间 "version": "1.0.0.0", //项目版本号 "indexHtmlPath": "index.htm

常规功能和模块自定义系统 (cfcmms)—018自定义grid方案(2)

常规功能和模块自定义系统 (cfcmms)-018自定义grid方案(2) 下面来看看在系统中如何定义一个grid方案.当前定义grid方案也是采用对记录模块操作的方式,并没有采用所见即所得得的设计方式,以后有时间将会修改成所见即所得得方式. 上图中可以看到在进入了"模块列表方案"后,会显示所有的模块的列表方案,在导航里选择了"省份"这后,会只显示省份的2个列表方案.每个方案都有若干个字段组,选中一条记录以后,按"列表字段分组"可以看到当前方案的

常规功能和模块自定义系统 (cfcmms)—015模块自定义概述(2权限)

常规功能和模块自定义系统 (cfcmms)-015模块自定义概述(2权限) 模块的权限的自定义也是这个系统的重要部分.在本系统中现在模块的权限有三大类:模块操作权限.记录可视范围限定.附加操作权限. 模块操作权限:可以对模块进行浏览.新增.修改.删除.审核.审批等的设置.可以通过生成和隐藏相应的按钮来具体控制权限的设置.如某人无删除权限,则在该模块的操作界面上没有删除按钮.对于一般的管理系统而言这些功能基本上是够用了. 记录可视范围限定:可以在任意模块加上可视范围的限定.在某个父模块上加上可视范

常规功能和模块自定义系统 (cfcmms)—009主界面和菜单的展示和控制(1)

常规功能和模块自定义系统 (cfcmms)-009主界面和菜单的展示和控制(1) 先从主界面和菜单.主tab标签以及一些附加的设置说起. 一个比较传统的管理软件中,一般会包括一个顶部区域.底部区域.菜单条(树状菜单)和主操作区域.本系统亦是如此,只是增加了一点灵活控制的地方.首先来看看本系统中的界面布局和extjs的类之间的对应关系,extjs中的面象对象的功能已经比较完善了,现在开发b/s程序就和我以前用组件开发delphi系统差不多,建好一个个组件类,然后直接使用即可. 和主界面.菜单相关的

常规功能和模块自定义系统 (cfcmms)—008测试试用版(6.0.0)下载及使用

常规功能和模块自定义系统 (cfcmms)-008测试试用版(6.0.0)下载及使用 在经过了一些调试和优化后,现在可以下载和测试试用版(6.0.0).在这个版中本主界面和菜单改用了mvvm方式来显示和控制. 程序和数据下载地址:http://pan.baidu.com/s/1c0sIGPq 所用到的java包下载地址:http://pan.baidu.com/s/1kTF5cIN 安装说明: 程序和数据下载好后解压缩,在eclipse中导入即可.数据库采用mysql,先用命令 CREATE S

常规功能和模块自定义系统(cfcmms)—004可自定义的项目

常规功能和模块自定义系统(cfcmms)-004可自定义的项目 可以在前台浏览器里可进行的配置项目如下图: 版权声明:本文为博主原创文章,未经博主允许不得转载.

常规功能和模块自定义系统 (cfcmms)—019自定义grid方案(3)

常规功能和模块自定义系统 (cfcmms)-019自定义grid方案(3) 这一节开始进入自定义的内部,来看看第一个自定义的功能是如何实现的. 1?在系统登录的时候,将所有的登录用户有权限的模块定义信息全部发送到前端.这段代码在app/view/main/MainModel.js中.在MainModel创建的时候,通过会发送一个同步的ajax请求来获取数据.取得数据后将所有的module信息放到MainView的data中. Ext.Ajax .request({ url : 'applicat