[置顶] 常规功能和模块自定义系统 (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;
  }
}

  经过以上代码的协同工作,我们可以打开人员的设置权限的窗口来进行权限设置了。 [置顶] 常规功能和模块自定义系统 (cfcmms)—030开发日志(创建ManyToMany的column5)_第1张图片


  修改一些用户操作角色,然后保存。
[置顶] 常规功能和模块自定义系统 (cfcmms)—030开发日志(创建ManyToMany的column5)_第2张图片

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

  对于操作角色来说,用户也是一个ManyToMany字段,同样也适用于这样操作。
[置顶] 常规功能和模块自定义系统 (cfcmms)—030开发日志(创建ManyToMany的column5)_第3张图片

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


  进阶设想:

  对于选择tree的改进。在我现在的系统里,在用户模块中,有一个设置权限的按钮,其实就是完成了ManyToMany字段的选择与保存,有了这个字段功能之后,这个设置权限的按钮就可以不要了。但是有一点是不一样的,看看下面的截图:
[置顶] 常规功能和模块自定义系统 (cfcmms)—030开发日志(创建ManyToMany的column5)_第4张图片
  在上图的选择角色的窗口的tree中,角色是按照角色分组来进行分类的,这样在选择的时候可以更直观。以后的ManyToMany字段的选择树也要做成可以配置成这样的结构。这里我大体先写一下思路:
  1、在模块配置中新增一个配置字段:ManyToMany选择时候的树形模块路径;
  2、在某个模块被当作ManyToMany字段来选择的时候,读取其模块路径,然后把当前模块的值都加在相应的节点之下。
  比如对于角色来选择人员来说,可以把部门作为人员的模块路径,这样在选择树中,先是部门的值,然后人员会挂在相应的部门之下来进行选择。
  (这个功能以后有时间再做了)


你可能感兴趣的:(ExtJs6,常规功能和模块自定义系统,cfcmms)