今天重新做了一下实验项目的LookUp的页面和流程设计,感触颇多啊
关于LookUp:lookup页面就是提供给其他的实体的某个实体的列表展示,例如,实验课程要关联实验项目,首先有一个页面是该实验课程已经关联了的实验项目,然后在这个页面中可以点击“添加”,这就打开了那个LookUp页面,里面的实验项目是前面的实验课程所没有包含的,管理员可以选中某一些,然后点击“添加”,LookUp页面就返回一个选中了项组成的一个String,然后原来的页面就可以根据这个String来添加item,需要注意的是,在打开lookup页面时前一个页面要给它一个查询条件where(String)用于筛选出可以选择的实验项目
需要注意的是:任何的lookup都是只有一个!不管它是提供给哪个实体查看,都是用那一个页面,这就提高了项目开发的难度,并提高了代码的可重用性,如果以后还要添加一个lookup,那么代码添加和修改就很方便了,而不用另外的添加太多的其他的页面和代码
下面我就实际的操作一遍:以实验课程关联实验项目为例
1.添加“关联实验项目”
实验课程管理的页面主要是一个DateGrid,给这个DateGrid添加一个附加操作列
newcol = CourseDBGrid.addCol(); newcol.setTitleString("关联实验项目"); newcol.setColType(Const.BS_CRL_COL_ADDDATAOPERATE); newcol.setColControlType(Const.BS_CRL_LINK); newcol.setCellFun("doCourseItemR()");
该列点击了就会调用JS方法
function doCourseItemR() {//打开实验课程关联的实验项目 var fromObj = {}; fromObj.id = CourseDBGrid.doGetCellValue(0); //alert(fromObj.id); p.openParentDlg("LOOKUP_ITEMFORCOURSE", "关联实验项目", 690, 420, fromObj, "ITEM", "CourseItemIni", "&in_courseid=" + fromObj.id, window, true, true, "", ""); }
调用了这个JS方法会得到选中的那个实验课程id,然后打开一个新的Dialog,并执行BSID=”ITEM”(对应的JavaBean是BSItem)的do_CourseItemIni方法
同时给后台传了一个参数 in_courseid,同时注意fromObj传给了下一个页面,也就是说下一个页面也可以得到选中了的课程ID,这个很重要,要注意这里的ID是如何传递的
2.编写 do_CourseItemIni方法
/** * <p> * 方法名:do_CourseItemIni * </p> * <p> * 方法描述:实验课程关联的实验项目页面 * </p> * <p> * 输入参数:BSObject m_bs:BS框架业务对象 * </p> * <p> * 输出参数:BSObject:BS框架业务对象 * </p> */ public BSObject do_CourseItemIni(BSObject m_bs) throws Exception { m_bs.setCurPage("system/course/courseitem.jsp"); String courseId = (String) m_bs.getPrivateMap().get("in_courseid"); m_bs.setPrivateValue("lookup_coursename", WDLabStatic.courseMap.get(courseId).getName()); SqlExecute sqlHelper = new SqlExecute(); try { BSItemDBMang itemDB=new BSItemDBMang(sqlHelper, m_bs); //sql="select t.item_id,t.item_name,t.item_state,t.item_type,t.item_desc from T_EXP_ITEM t where t.item_id is not null and t.item_state='1' and t.item_id in //(select t2.item_id from t_course_item_r t2 where t.item_id = t2.item_id and t2.course_id='5D8026C12E9D5C4E009AA4C3CC75A629' ) order by t.item_id" String where=" and t.item_id in (select t2.item_id from t_course_item_r t2 where t.item_id = t2.item_id and t2.course_id='" +courseId+"') "; ArrayList<ItemPojo> list=itemDB.getItemList(where); this._setCourseItemDataGrid(m_bs, list); //sql="select t.item_id,t.item_name,t.item_state,t.item_type,t.item_desc from T_EXP_ITEM t where t.item_id is not null and t.item_state='1' and t.item_id not //in (select t2.item_id from t_course_item_r t2 where t.item_id = t2.item_id and t2.course_id='5D8026C12E9D5C4E009AA4C3CC75A629' ) order by t.item_id" String itemwhere=" and t.item_id not in (select t2.item_id from t_course_item_r t2 where t.item_id = t2.item_id and t2.course_id='" +courseId+"') "; m_bs.setPrivateValue("itemwhere", itemwhere); } catch (Exception ep) { ep.printStackTrace(); throw ep; } finally { sqlHelper.close(); } return m_bs; }
这个方法首先得到传过来的参数courseid,也就是选中的课程Id,这个很重要,根据这个ID,我们可以在WDLabStatic中的courseMap中得到对应的course的名称,而不用查询数据库
其次,根据这个courseId可以得到两个where查询条件:一个是根据这个courseid得到和这个course关联的实验项目,另一个就是根据这个courseid得到没有和它相互关联的实验项目
其中,后者是很重要的,它首先不会去执行查询,只有到了要打开lookup时才会传递过去并执行,这个过程是这样的:
当前的页面时courseitem.jsp:就是显示一个实验课程关联的实验项目的页面,页面中有一个“新增”按钮,显示效果:
该页面中有一个隐藏的text:<BS:text type="hidden" name="itemwhere" />
它保存的就是前面说的第二个where查询条件,由于数据量比较大,所以不能使用get方法传递,只能是post
添加JS方法,就是点击了“新增”之后触发的事件
var fObj = thisDlg.inObj;
function addItem(){ var tObj = {}; tObj.itemwhere = $("itemwhere").value; tObj.id=fObj.id; //alert(tObj.id); //alert(tObj.itemwhere); doItemLookup(tObj.itemwhere,tObj.id,"addItemRet"); }
注意第一句话:var fObj = thisDlg.inObj; 这里的fObj就是刚才的 fromObj,里面包含了一个id,就是 选中的 courseId!
这个JS方法就是得到那个where,同时得到一个id,后面将会介绍这个id的传递过程,然后就会调用另一个JS方法 doItemLookup
我定义在 WDLookUp.js 中,这个方法单独拿出来就是为了提高代码的可重用性,降低耦合
function doItemLookup(where, id, retFun) { var fromObj = {}; fromObj.where = where; fromObj.id=id; p.openParentDlg("WDLOOKUP_ITEM", "实验项目选择", 700, 420, fromObj, "ITEM", "ItemLookUpIni", "" , window, true,false, retFun); }
这个JS的执行:首先得到参数where和id,放到一个新的对象fromObj中,同时打开一个新的Dialog,这个新的页面就是LookUp页面
注意一个东西,就是第三个方法,那个是 回调函数,也就是说当那个窗体关闭后执行的方法
3.编写方法 ItemLookUpIni
/** * <p> * 方法名:do_ItemLookUpIni * </p> * <p> * 方法描述:关联实验项目页面初始化 * </p> * <p> * 输入参数:BSObject m_bs:BS框架业务对象 * </p> * <p> * 输出参数:BSObject:BS框架业务对象 * </p> */ public BSObject do_ItemLookUpIni(BSObject m_bs) throws Exception { m_bs.setCurPage("labbase/item/lookup.jsp");// 注意设置路径时是从根目录开始的 SqlExecute sqlHelper = new SqlExecute(); try { String where = (String)m_bs.getPrivateMap().get("itemwhere"); BSItemDBMang itemDB = new BSItemDBMang(sqlHelper, m_bs); ArrayList<ItemPojo> itemList = itemDB.getItemList(where); this._setLookUpDataGrid(m_bs, itemList); //设置lookup页面的实验项目列表 } catch (Exception e) { e.printStackTrace(); throw e; } finally { sqlHelper.close(); } return m_bs; }
这个方法首先得到前面的 String where = (String)m_bs.getPrivateMap().get("itemwhere"); 这个就是筛选的条件,根据这个筛选得到没有关联的其他的实验项目
然后查询,得到一个ItemList,最后把这个list放到DateGrid中就可以了!
选中了几个之后,就可以得到选中的项组成的String,调用的是LookUp中的一个JS方法
function addItems() { var keyStr=ItemLookUpDataGrid.getSelectKey(); if(keyStr==""&&keyStr==null){ keyStr="T"; } var tObj = {}; tObj.keyStr = keyStr; tObj.id=fObj.id; //alert(tObj.id); alert(tObj.keyStr); thisDlg.returnObj = tObj; thisDlg.closeDlg(); }
第一句就是得到那个String,需要注意的是,这个String可能为空或者为null,如果不处理就直接返回给原来的窗体中,就会在查询时报空指针异常了
接着得到 fObj.id,和前面一样,fObj就是上一个页面传递过来的id,还是那个选中的courseId
将keyStr和id设置到了一个对象tObj上之后就可以将它作为返回对象返回了 thisDlg.returnObj = tObj;
最后就是关闭lookup页面
4.回调方法
前面说过有一个回调方法,就是关闭lookup页面之后调用的方法,这里是一个JS方法
function addItemRet(r_obj, i_obj){ var keyStr = r_obj.keyStr; var courseId=r_obj.id; if(keyStr!=""&&keyStr!=null){ //doRefresh("CLASSMANG","addItem",true,"","&in_keyStr="+keyStr,"showItemRet"); } }
它是定义在 courseitem.jsp 中的,这里就是整个流程的结尾了,r_obj就是上面的lookup页面的返回对象,其中保存了String(选中的项)和id,就是最开始选中的实验课程
现在又返回过来了,然后就是一个判断了,如果那个String是合法的,那么就可以调用零刷新的方法进行零刷新了,刷新之后就是原来关联的加上后来添加的了
总结:
这个过程经过总结之后就清晰了很多,这么做的原因就是要保证任何 lookup页面都是只有一个!这才是真正的项目开发!