在这里会简述及展现,部分表单控件如何应用以及后端数据如何处理和应用。html
框架使用Spring封装的一系列表单标签。前端
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
涉及方法:java
<!-- DictUtils --> <function> <description>获取字典标签</description> <name>getDictLabel</name> <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class> <function-signature>java.lang.String getDictLabel(java.lang.String, java.lang.String, java.lang.String)</function-signature> <example>${fns:getDictLabel(value, type, defaultValue)}</example> </function> <function> <description>获取字典标签(多个)</description> <name>getDictLabels</name> <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class> <function-signature>java.lang.String getDictLabels(java.lang.String, java.lang.String, java.lang.String)</function-signature> <example>${fns:getDictLabels(values, type, defaultValue)}</example> </function> <function> <description>获取字典值</description> <name>getDictValue</name> <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class> <function-signature>java.lang.String getDictValue(java.lang.String, java.lang.String, java.lang.String)</function-signature> <example>${fns:getDictValue(label, type, defaultValue)}</example> </function> <function> <description>获取字典对象列表</description> <name>getDictList</name> <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class> <function-signature>java.util.List getDictList(java.lang.String)</function-signature> <example>${fns:getDictList(type)}</example> </function> <function> <description>获取字典对象列表</description> <name>getDictListJson</name> <function-class>com.thinkgem.jeesite.modules.sys.utils.DictUtils</function-class> <function-signature>java.lang.String getDictListJson(java.lang.String)</function-signature> <example>${fns:getDictListJson(type)}</example> </function>
文件位置:com.thinkgem.jeesite.modules.sys.utils.DictUtils.javagit
/** * Copyright © 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved. */ package com.thinkgem.jeesite.modules.sys.utils; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.thinkgem.jeesite.common.mapper.JsonMapper; import com.thinkgem.jeesite.common.utils.CacheUtils; import com.thinkgem.jeesite.common.utils.SpringContextHolder; import com.thinkgem.jeesite.modules.sys.dao.DictDao; import com.thinkgem.jeesite.modules.sys.entity.Dict; /** * 字典工具类 * @author ThinkGem * @version 2013-5-29 */ public class DictUtils { private static DictDao dictDao = SpringContextHolder.getBean(DictDao.class); public static final String CACHE_DICT_MAP = "dictMap"; public static String getDictLabel(String value, String type, String defaultValue){ if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(value)){ for (Dict dict : getDictList(type)){ if (type.equals(dict.getType()) && value.equals(dict.getValue())){ return dict.getLabel(); } } } return defaultValue; } public static String getDictLabels(String values, String type, String defaultValue){ if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(values)){ List<String> valueList = Lists.newArrayList(); for (String value : StringUtils.split(values, ",")){ valueList.add(getDictLabel(value, type, defaultValue)); } return StringUtils.join(valueList, ","); } return defaultValue; } public static String getDictValue(String label, String type, String defaultLabel){ if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(label)){ for (Dict dict : getDictList(type)){ if (type.equals(dict.getType()) && label.equals(dict.getLabel())){ return dict.getValue(); } } } return defaultLabel; } public static List<Dict> getDictList(String type){ @SuppressWarnings("unchecked") Map<String, List<Dict>> dictMap = (Map<String, List<Dict>>)CacheUtils.get(CACHE_DICT_MAP); if (dictMap==null){ dictMap = Maps.newHashMap(); for (Dict dict : dictDao.findAllList(new Dict())){ List<Dict> dictList = dictMap.get(dict.getType()); if (dictList != null){ dictList.add(dict); }else{ dictMap.put(dict.getType(), Lists.newArrayList(dict)); } } CacheUtils.put(CACHE_DICT_MAP, dictMap); } List<Dict> dictList = dictMap.get(type); if (dictList == null){ dictList = Lists.newArrayList(); } return dictList; } /** * 返回字典列表(JSON) * @param type * @return */ public static String getDictListJson(String type){ return JsonMapper.toJsonString(getDictList(type)); } }
页面数据编辑和回显:github
单选按钮(单选): <form:radiobuttons path="check" items="${fns:getDictList('yes_no')}" itemLabel="label" itemValue="value" htmlEscape="false"/> 下拉框(单选): <form:select path="check" class="input-xlarge "> <form:option value="" label=""/> <form:options items="${fns:getDictList('yes_no')}" itemLabel="label" itemValue="value" htmlEscape="false"/> </form:select> 复选框(多选): <form:checkboxes path="goodsTypeFormatDictList" items="${fns:getDictList('map_goods_format')}" itemLabel="label" itemValue="value" htmlEscape="false"/>
页面数据显示:spring
单选按钮和单选下拉框: ${fns:getDictLabel(对象.属性, 'yes_no', '')} 复选框: ${fns:getDictLabels(对象.属性, 'map_goods_format', '')}
控件属性说明sql
Radio和Select比较简单,由于存储的都是单一值,在数据编辑方面并无须要注意的地方,只须要稍微注意一下所封装的数据类型对应调整就能够了。数据库
CheckBox在数据回显和提交时须要特别注意一下,由于封装的形式和提交的方式稍微会有所调整,在此我从新以自定义对象举例说明:apache
一共有3张表,TravelRout,旅游路线表;ScenicArea,景区信息表;TravelRouteScenicArea,旅游路线和景区信息关联表,多对多的关系;后端
实体模型TravelRoute类中,须要ScenicArea属性标识,用于封装传递的多选数值:
private List<String> scenicAreaIdList = Lists.newArrayList(); //拥有的景区ID集合,用于数据回显 private List<ScenicArea> scenicAreaList = Lists.newArrayList(); //拥有的景区源数据集合 public List<ScenicArea> getScenicAreaList() { return scenicAreaList; } public void setScenicAreaList(List<ScenicArea> scenicAreaList) { this.scenicAreaList = scenicAreaList; } @JsonIgnore public List<String> getScenicAreaIdList(){ List<String> scenicAreaIdList = Lists.newArrayList(); for(ScenicArea scenicArea : scenicAreaList){ scenicAreaIdList.add(scenicArea.getId()); } return scenicAreaIdList; } public void setScenicAreaIdList(List<String> scenicAreaIdList){ scenicAreaList = Lists.newArrayList(); for(String scenicAreaId : scenicAreaIdList){ ScenicArea scenicArea = new ScenicArea(); scenicArea.setId(scenicAreaId); scenicAreaList.add(scenicArea); } }
TravelRouteService类中,get方法须要获取scenicAreaList集合进行数据填充,该数据源是利用scenicAreaId查询TravelRouteScenicArea获得的集合,注意:
public TravelRoute get(String id) { TravelRoute travelRoute = travelRouteDao.get(id); List<ScenicArea> list = travelRouteDao.findTravelRouteScenicAreaByTR(id); travelRoute.setScenicAreaList(list); return travelRoute; }
TravelRouteController类中,还须要针对前端所有景区数据列表作一个属性回显,allScenicAreas,即查询所有景区信息列表:
@RequiresPermissions("hnly:travelRoute:view") @RequestMapping(value = "form") public String form(TravelRoute travelRoute, Model model) { model.addAttribute("travelRoute", travelRoute); model.addAttribute("allScenicAreas", scenicAreaService.findList(null)); return "modules/hnly/travelRouteForm"; }
前端JSP:
<div class="control-group"> <label class="control-label">途径景区:</label> <div class="controls"> <form:checkboxes path="scenicAreaIdList" items="${allScenicAreas}" itemLabel="name" itemValue="id" htmlEscape="false" class="required"/> </div> </div>
执行新增或更新操做时,TravelRouteService类中,须要作响应的修改,先删除联合表中的数据,再添加:
@Transactional(readOnly = false) public void save(TravelRoute travelRoute) { if (StringUtils.isBlank(travelRoute.getId())){ travelRouteDao.insert(travelRoute); } else { travelRouteDao.update(travelRoute); } travelRouteDao.deleteTravelRouteScenicArea(travelRoute); travelRouteDao.insertTravelRouteScenicArea(travelRoute); }
TravelRouteDao,在联合表中插入数据须要注意:
<!-- 删除推荐旅游路线和景区关联表数据 --> <update id="deleteTravelRouteScenicArea"> DELETE FROM hnly_travel_route_scenic_area WHERE hnly_travel_route_id = #{id} </update> <!-- 插入推荐旅游路线和景区关联表数据 --> <insert id="insertTravelRouteScenicArea" useGeneratedKeys="true" keyProperty="id"> INSERT INTO hnly_travel_route_scenic_area(hnly_travel_route_id, hnly_scenic_area_id) <foreach collection="scenicAreaList" item="scenicArea" separator=" union all "> SELECT #{id}, #{scenicArea.id} <if test="dbName != 'mssql'"> FROM dual </if> </foreach> </insert> <!-- 根据路线ID获取推荐旅游路线关联的景区数据 --> <select id="findTravelRouteScenicAreaByTR" resultType="ScenicArea"> SELECT a.hnly_scenic_area_id AS "id", sa.name AS "name", sa.addr AS "addr", sa.lat AS "lat", sa.lon AS "lon", sa.hnly_panoramic_id AS "panoramic.id" FROM hnly_travel_route_scenic_area a LEFT JOIN hnly_scenic_area sa ON sa.id = a.hnly_scenic_area_id WHERE a.hnly_travel_route_id = #{id} </select>
图样图森破
图片及文件上传均使用的CF控件,在页面编辑的同时就已经将图片和文件数据上传完了,最后表单提交的时候是一串上传地址,因此后台数据格式为String字符串类型便可。
<div class="control-group"> <label class="control-label">图片:</label> <div class="controls"> <form:hidden id="pic" path="pic" htmlEscape="false" maxlength="255" class="input-xlarge"/> <sys:ckfinder input="pic" type="images" uploadPath="/hnly/activity" maxHeight="100" maxWidth="100"/> </div> </div> <div class="control-group"> <label class="control-label">文件:</label> <div class="controls"> <form:hidden id="fil" path="fil" htmlEscape="false" maxlength="255" class="input-xlarge"/> <sys:ckfinder input="fil" type="files" uploadPath="/hnly/activity" selectMultiple="true"/> </div> </div>
由两部分组成,form:hidden隐藏文本和sys:ckfinder控件,type分为两种images和files;uploadPath为上传路径;selectMultiple为是否为文件模式的是否容许多文件上传;maxHeight和maxWeight为图片模式使用的回显图片长宽;
若是系统中使用到时间数据格式是多样化的,如年月日/日分等等,建议后台和数据库的时间数据格式设置为文本,在页面中取消时间格式化就行了,原系统中如何设置请自行参考,这里我只贴修改后的。
<div class="control-group"> <label class="control-label">时间:</label> <div class="controls"> <input name="publishTime" type="text" readonly="readonly" maxlength="20" class="input-medium Wdate " value="${activity.publishTime}" onclick="WdatePicker({dateFmt:'yyyy-MM-dd HH:mm:ss',isShowClear:false});"/> </div> </div>
value,为提交和回显属性,这里我已经将格式化方法去除,再也不作格式化,且数据库和后台类型为字符串类型,若是使用原格式化方法处理则必须统一数据格式,不能使用字符串类型,去除后可以使用。WdatePicker为控件调用方式;dataFmt,可设置多种时间显示方法;
<div class="control-group"> <label class="control-label">标题:</label> <div class="controls"> <form:input path="title" htmlEscape="false" maxlength="255" class="input-xlarge "/> </div> </div>
<div class="control-group"> <label class="control-label">内容:</label> <div class="controls"> <form:textarea path="content" htmlEscape="false" rows="4" class="input-xxlarge "/> </div> </div>