JeeSite 快速开发平台
官方网站
    • 平台简介
    • 架构特点
    • 技术选型
    • 功能介绍
    • 安装部署
    • 常见问题
    • 目录结构
    • 更新日志
    • Vue 文档
    • BPM 文档
    • Cloud 文档
V4 演示
Vue 演示
💖联系
  • 我要提意见、文档纠错
  • JeeSite 代码库, 请⭐Star关注
  • JeeSite Vue 代码库, 请⭐关注
  • Spring Cloud 微服务架构
  • JeeSite 手机端/移动端
  • Flowable 中国式工作流
  • OAauth2 统一认证服务器
  • 政务内外网环境中间件
  • 访问 ThinkGem 官方博客
  • 点击进入,下拉查看动态
官方网站
    • 平台简介
    • 架构特点
    • 技术选型
    • 功能介绍
    • 安装部署
    • 常见问题
    • 目录结构
    • 更新日志
    • Vue 文档
    • BPM 文档
    • Cloud 文档
V4 演示
Vue 演示
💖联系
  • 我要提意见、文档纠错
  • JeeSite 代码库, 请⭐Star关注
  • JeeSite Vue 代码库, 请⭐关注
  • Spring Cloud 微服务架构
  • JeeSite 手机端/移动端
  • Flowable 中国式工作流
  • OAauth2 统一认证服务器
  • 政务内外网环境中间件
  • 访问 ThinkGem 官方博客
  • 点击进入,下拉查看动态
  • 快速了解

  • 开发手册

    • 快速开始、安装部署
    • 代码生成、表结构 ER 图
    • 持久层、@Table、多数据源
    • 业务层、数据权限、库事务
    • 控制层、功能权限、Shiro
    • 后台常用工具类、Utils
    • Form 表单组件、Beetl
      • 引言
        • 模板语言界定符选择
        • 举例一个通用布局的页面
      • 定义常用函数库
        • 常用工具类导入
      • 基本表单控件应用(类似 Spring MVC 表单标签)
        • form 表单标签
        • input 输入框标签
        • select 下拉框标签
        • radio 单选框标签
        • checkbox 复选框标签
        • textarea 文本域标签
        • hidden 隐藏域标签
      • 高级表单组件封装应用
        • treeselect 树结构选择
        • listselect 列表选择
        • iconselect 图标选择
        • validcode 验证码
        • fileupload 文件上传
        • imageclip 图片裁剪
        • ueditor 在线编辑器
        • extend 扩展字段
      • 自定义 form 标签组件
      • 表单验证内置类型
      • 前端组件资源
    • Data Grid 表格组件
    • JS 常用工具和组件
    • 修改内置登录页面
    • 国际化、多语言
    • API 接口开发
    • ★ 常见问题 ★
  • Vue 开发手册

  • 扩展功能专题

  • 云服务技术架构

  • 技术服务与支持

Form 表单组件、前端组件、表单布局、表单验证、Beetl

# 引言

前端 CSS 框架选用 BootStrap3 和 AdminLTE 作为管理框架为基础,JS 库采用 jQuery3 为核心框架,前端视图采用目前比较流行简单的 Beetl 模板引擎(使用 JS 语法,是我用过最好用,速度最快的后端模板引擎),取消了之前的JSP视图,为了减少耦合,并将所有视图文件分布到各个工程模块的资源目录下(如:/modules/core/src/main/resources/views/),JeeSite4 对 Beetl 做了一个强化,主要包括如下几点:

  • 常用函数库,如:字符串工具类,集合工具类,映射转换工具类,配置工具类,权限用户工具类等;
  • 封装常用表单控件参考Spring MVC的form标签,实现更便捷的输入框、下拉框等,自动进行数据绑定;
  • 封装常用表单组件,如:多级树结构选择组件,列表选择组件,文件上传组件,验证码生成组件等等;
  • 封装常用JS类库,如:动态加载,对话框,消息框,加载框,JS模板,Ajax,格式化,动态Tab等等;
  • 封装JS数据表格DataGrid,分页,排序,多表头,分组,子表,冻结,小计,合计,编辑行,树表表格等;
  • 提供丰富例子,如:Box盒子、表单布局、栅格布局、图表等等

更多资料:beetl 官方文档 (opens new window)

如果你会用 JavaScript 和 Spring MVC 标签库 几乎不用学习,只需了解有哪些标签,对应文档查找属性用法。

# 模板语言界定符选择

Beetl模板语言类似JS语言和习俗,只需要将Beetl语言放入定界符号里即可,JeeSite使用jsp标准定界符<% %>来作为模板语言的定界符,一方同比较容易被理解,并明确是后端运行的语法,另一方面冲突少,比较好界定边界

# 举例一个通用布局的页面

<% layout('/layouts/default.html', {title: '菜单管理', libs: ['validate'], bodyClass: ''}){ %>
<div class="main-content">
	<div class="box box-main">
		<div class="box-header with-border">
			<div class="box-title">
				<i class="fa icon-book-open"></i> 菜单管理
			</div>
			<div class="box-tools pull-right">
				<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
			</div>
		</div>
		<div class="box-body">
			
		</div>
		<div class="box-footer">
			
		</div>
	</div>
</div>
<% } %>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

调用默认布局 /layouts/default.html,自动引入页面头部和尾部内容,通过参数设置要加载的css和js类库,参数如下:

title参数: 设置页面的标题名字

libs参数: 设置页面要引入的css和js类库,支持类库如下:

默认引入:layer、laydate、select2

  • zTree:树结构控件
  • tabPage:动态页签插件
  • dataGrid:数据表格组件
  • validate:表单验证组件
  • inputmask:表单格式化工具
  • fileupload:文件上传插件
  • ueditor:富文本编辑器控件

bodyClass参数: 设置body的class属性值

# 定义常用函数库

# 常用工具类导入

以下工具类可通过@类型快速调用,如:${@Global.getConfig('key')}

  • Global:全局配置类,全局常量,读取属性文件参数值等
  • EncodeUtils:封装各种格式的编码解码工具类,HEX、Base64、HTML、URL、XSS过滤、SQL过滤等
  • ListUtils:List常用工具类,继承Apache的ListUtils,New工具、快速提取属性值、类型转换等
  • MapUtils:Map常用工具类,继承Apache的MapUtils,New工具、Map与Bean互转等
  • SetUtils:Set常用工具类,继承Apache的SetUtils,New工具等
  • IdGenerate:封装各种生成唯一性ID算法的工具类,生成LongUUID,StringUUID,Code生成等
  • ByteUtils:字节转换工具
  • DateUtils:日期工具类,继承Apache的DateUtils
  • NumberUtils:BigDecimal工具类,继承Apache的NumberUtils类
  • ObjectUtils:对象操作工具类,继承Apache的ObjectUtils类
  • StringUtils:字符串工具类,继承Apache的StringUtils类
  • TimeUtils:时间计算工具类,xx天xx时xx分xx秒,刚刚,xx秒,xx分钟,xx小时前、xx天前
  • WorkDayUtils:工作日计算工具类,计算日期直接的工作日等
  • BeanMapper:简单封装Dozer,对象数据映射
  • JaxbMapper:Jaxb实现XML与Java Object的转换
  • JsonMapper:简单封装Jackson,实现Json与Java Object的转换
  • ClassUtils:Class扫描工具类,根据接口查询类,根据继承查询类等
  • ReflectUtils:反射工具类,方便进行getter/setter方法, 访问私有变量, 调用私有方法
  • ModuleUtils:模块工具类,方便获取系统模块信息,例如 ${@ModuleUtils.getModule('core')}
  • DictUtils:字典工具类,例如 ${@DictUtils.getDictListJson('sys_menu_type')}
  • UserUtils:用户工具类,方便获取进行用户及相关信息,例如 ${@UserUtils.getUser()}
  • EmpUtils:员工工具类,获取当前用户员工信息、所在部门、公司,${@EmpUtils.getEmployee()}
  • RoleUtils:角色工具类,判断当前或某用户是否包含某角色,${@RoleUtils.hasUserRole('user','role')}

以下是Beetl函数及扩展函数

  • date:返回一个java.util.Date类型的变量,如 date() 返回一个当前时间(对应java的java.util.Date); ${date( "2011-1-1" , "yyyy-MM-dd" )} 返回指定日期
  • print:打印一个对象 print(user.name);
  • println:打印一个对象以及回车换行符号,回车换号符号使用的是模板本身的,而不是本地系统的.如果仅仅打印一个换行符,则直接调用println() 即可
  • nvl:函数nvl,如果对象为null,则返回第二个参数,否则,返回自己 nvl(user,"不存在")
  • isEmpty:判断变量或者表达式是否为空,变量不存在,变量为null,变量是空字符串,变量是空集合,变量是空数组,此函数都将返回true
  • isNotEmpty:同上,判断对象是否不为空
  • has:变量名为参数,判断是否存在此全局变量,如 has(userList),类似于1.x版本的exist("userList"),但不需要输入引号了
  • assert:如果表达式为false,则抛出异常
  • trim:截取数字或者日期,返回字符,如trim(12.456,2)返回"12.45",trim(date,'yyyyy')返回"2017"
  • trunc:截取数字,保留指定的小数位,如trunc(12.456,2) 输出是12.45.不推荐使用,因为处理float有问题,兼容原因保留了
  • decode:一个简化的if else 结构,如 decode(a,1,"a=1",2,"a=2","不知道了")},如果a是1,这decode输出"a=1",如果a是2,则输出"a==2", 如果是其他值,则输出"不知道了"
  • debug:在控制台输出debug指定的对象以及所在模板文件以及模板中的行数,如debug(1),则输出1 [在3行@/org/beetl/core/lab/hello.txt],也可以输出多个,如debug("hi",a),则输出hi,a=123,[在3行@/org/beetl/core/lab/hello.txt]
  • range:接收三个参数,初始值,结束值,还有步增(可以不需要,则默认为1),返回一个Iterator,常用于循环中,如for(var i in range(1,5)) {print(i)},将依次打印1234.
  • flush:强制io输出。
  • pageCtx:仅仅在web开发中,设置一个变量,然后可以在页面渲染过程中,调用此api获取,如pageCtx("title","用户添加页面"),在其后任何地方,可以pageCtx("title") 获取该变量
  • cookie:返回指定的cookie对象 ,如var userCook = cookie("user"), allCookies = cookie();
  • isBlank:判断对象是否是一个空字符串,${isBlank('str')}
  • isNotBlank:判断对象是否不是一个空字符串,${isBlank('str')}
  • toJson:将对象转Json字符串,${toJson(Object)}
  • fromJson:将Json字符串转换为对象,${fromJson(Object)}
  • hasPermi:判断是否有改权限;单个权限验证:${hasPermi('sys:user:edit')};多个AND关系:${hasPermi('sys:user:view,sys:user:edit', 'and')}; 多个OR关系:${hasPermi('sys:user:view,sys:user:edit', 'or')}
  • cookie:获取cookie值,${cookie(name, isRemove)}
  • lang: 获取当前国际化语言名称,例如:lang(),返回:zh_CN、en、等
  • text: 获取当前国际化代码译文,例如:text('中国'),当前语言英文状态下,返回:China;支持格式化参数,如:text('第{0}天', 3)

数据类型格式化

日期格式化:

Today is ${date,dateFormat='yyyy-MM-dd'}
Today is ${date,dateFormat}
如果date为日期类型可简写:
${date,'yyyy-MM-dd'}
1
2
3
4

数值格式化:

Salary is ${salary,numberFormat='##.##'}
1

# 基本表单控件应用(类似 Spring MVC 表单标签)

# form 表单标签

必备基础知识:HTML 表单 (opens new window)、HTML 表单元素 (opens new window)、HTML 输入类型 (opens new window)、HTML 输入属性 (opens new window)

1、生成一个 HTML 表单,可指定model属性,自动给表单内的控件绑定属性值:
<#form:form id="inputForm" model="${user}" action="${ctx}/sys/user" method="POST" class="form-horizontal">
    表单内容
</#form:form>

2、生成支持上传文件的 HTML 表单:
<#form:form id="inputForm" model="${user}" action="${ctx}/sys/user" method="POST" enctype="multipart/form-data" class="form-horizontal">
    表单内容
</#form:form>
1
2
3
4
5
6
7
8
9

特别提示:model 属性

  • model 是表单的与后台绑定的数据对象,来自后台 @ModelAttribute 和 model.addAttribute("user", user) 返回给视图的属性名,如指定为 ${user} 属性值,她会自动给表单内的组件或控件绑定数据,并显示到表单组件或控件上。
  • 如果你用过 SpringMVC 的 form 标签,一定会非常熟悉,类似:<form:form modelAttribute=""/>

组件属性:

var p = {

	// 标签参数
	id: id!,					// 表单ID
	model: model!,				// 绑定Model对象,例如:${user!}
	action: action!,			// 表单请求地址
	method: method!,			// 请求方法,默认 post
	enctype: enctype!,			// 发送之前进行数据编码,上传文件时指定:multipart/form-data
	
};
1
2
3
4
5
6
7
8
9
10

# input 输入框标签

必备基础知识:HTML<input>标签 (opens new window)

1、自动绑定 form:form 上指定的 model 下的 userName 属性:
<#form:input path="userName" maxlength="100" class="form-control required "/>

2、日期格式化:
<#form:input path="createDate" dataFormat="date" class="form-control "/>

3、数值格式化:
<#form:input path="createDate" dataFormat="number" class="form-control "/>

4、数值格式化(保留2位):
<#form:input path="createDate" dataFormat="number2" class="form-control "/>

5、自定义格式化:
<#form:input name="field" value="${@DateUtils.formatDate(model.field,'yyyyMMdd')}" class="form-control "/>
<#form:input name="field" value="${${@NumberUtils.formatNumber(model.field,'0.0')}}" class="form-control "/>

6、不自动绑定,把 path 改为 name 就可以(否则 value 赋值不生效):
<#form:input name="field" value="${model.field}" class="form-control "/>

7、指定默认值(当 model 的属性为空的时候,显示默认值):
<#form:input path="userName" defaultValue="123" class="form-control "/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

特别提示:path 属性

  • path 是绑定 form 上 model 中属性的值(是 name 和 value 的语法糖)
  • 如:path="userName" 同等于 name="userName" value="${user.userName}"
  • 即:如果指定了 path,则会自动生成 name 和 value 属性,自动读取 model 对象中对应 path 的属性值,设置到 value 中,如上所示。
  • 如果控件没有指定 id,则 path 为 id,自动生成,如果包含 . 则替换为 _ (因为 HTML id 中不允许有点)
  • 如果不想自动绑定,请将 path 替换为 name,否则你设置的 value 将不生效。
  • 如果你用过 SpringMVC 的 form 标签,一定会非常熟悉,类似:<form:input path=""/>
  • 该 path 适应于下面小节中所有的 path 用法解释。

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同

	path: path!,				// 绑定 form 上 model 中属性的值(是 name 和 value 的语法糖)

	name: name!,				// 元素名称,不填写时,使用 path 名称
	value: value!,				// 元素值(如果不使用 path 自动绑定,手动设定 value 时,请把 path 改为 name)

	// 以下3个属性是 path 属性的自动绑定参数,包含 path 属性的 form 组件都可以使用
	xss: xss!false,					// 是否对输出 value 进行 XSS 过滤
	encodeHtml: encodeHtml!false,	// 是否对输出 value 进行 HTML 编码
	defaultValue: defaultValue!,	// 如果未获得绑定值,则采用这个默认值输出到 value v4.1.5
	
	type: type!'text',			// 元素的类型,默认text
	
	dataFormat: dataFormat!'',	// 数据格式化,支持如下值:
								// date: 日期;默认值设置:defaultValue="${date()}"
								// yyyy: 年;默认值设置:defaultValue="${date('2019','yyyy')}"
								// yyyy-MM: 年月;默认值设置:defaultValue="${date('2019-11','yyyy-MM')}"
								// datetime: 日期时间 yyyy-MM-dd HH:mm 格式化
								// datetime2: 日期时间,带秒  yyyy-MM-dd HH:mm:ss 格式化
								// 自定义日期  path 改为  name 加 value="${@DateUtils.formatDate(model.field,'yyyyMMdd')}}"
								// number: 数值类型 #.## 格式化,默认值设置:defaultValue="${0}"
								// number2: 数值类型 0.00 格式化,默认值设置:defaultValue="${0}"
								// 自定义数值  path 改为  name 加 value="${@NumberUtils.formatNumber(model.field,'0.0')}}"
	
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

laydate 日期选择控件:

1、日期格式化(带日期选择控件):
<#form:input path="createDate" dataFormat="date" 
	class="form-control laydate" data-type="date" data-format="yyyy-MM-dd"/>
<#form:input path="createDate" dataFormat="date" 
	class="form-control laydate" data-type="date" data-format="yyyy-MM-dd" />

2、日期范围选择(开始日期、结束日期):
<#form:input path="testDate_gte" readonly="true" maxlength="20" class="form-control laydate width-date"
	dataFormat="date" data-type="date" data-format="yyyy-MM-dd" data-done="testDate_lte.click()"/>
&nbsp;-&nbsp;
<#form:input path="testDate_lte" readonly="true" maxlength="20" class="form-control laydate width-date"
	dataFormat="date" data-type="date" data-format="yyyy-MM-dd"/>
1
2
3
4
5
6
7
8
9
10
11
12
  • 日期选择控件,class 增加 laydate 则转换为日期选择控件
  • data-type 是格式化类型支持:year、month、date、time、datetime
  • data-format 是前端日期控件格式化参数,dataFormat 是后端实体属性格式化参数
  • data-done 相当于 laydate 的 done 选择日期完成后的一些操作
  • 更多文档示例:https://www.layuion.com/laydate/ (opens new window)

日期回调,支持函数传参 v4.3.3,如下:

<#form:input data-done="function(value, date, endDate){}" />
<#form:input data-change="function(value, date, endDate){}" />
<#form:input data-ready="function(date){}" />
1
2
3

支持自定义日期选项 v4.3.3,如下:

<#form:input data-options="{range: ['#startDate', '#endDate']}" />
1

使用 jquery.inputmask 格式化:

<% layout('/layouts/default.html', {libs: ['inputmask']}){ %>
	<#form:input path="testInput_money" maxlength="200" class="form-control inputmask"
			data-inputmask-alias="money" data-inputmask="'digits':'2'"/>
<% } %>
<script>
	$("#inputForm").validate({
		submitHandler: function(form){
			// 数据格式化恢复(表单提交之前调用)
			$('.inputmask').inputmask('remove');
			// 提交表单
			js.ajaxSubmitForm($(form), function(data){
				js.showMessage(data.message);
				if(data.result == Global.TRUE){
					js.closeCurrentTabPage(function(contentWindow){
						contentWindow.page();
					});
				}
			}, "json");
			// 数据格式化(初始化完成表单后调用)
			$(".inputmask").inputmask();
		}
	});
	//数据格式化(初始化完成表单后调用)
	$(".inputmask").inputmask();
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

更多文档示例:https://www.baidu.com/s?wd=jquery.inputmask (opens new window)

# select 下拉框标签

1、根据字典类型设置下拉数据:
<#form:select path="userType" dictType="sys_user_type" class="form-control required " />

2、增加一个空白选项:
<#form:select path="roleType" dictType="sys_role_type" blankOption="true" class="form-control " />
<#form:select path="roleType" dictType="sys_role_type" blankOption="true" blankOptionLabel="请选择" class="form-control " />

3、多选下拉列表:
<#form:select path="roleType" dictType="sys_role_type" multiple="true" class="form-control " />

4、后台赋值:model.addAttribute("moduleList", new List<Module>()),类似SrpingMVC的<form:options items="" />:
<#form:select path="moduleCodes" items="${moduleList}" itemLabel="moduleName" itemValue="moduleCode" class="form-control required" />

5、在视图上直接赋值(如果你的平台版本比较旧,需要更新下 ReflectUtils.java 为最新的,才可以生效):
<% var items = [{label:'是',value:'1'},{label:'否',value:'0'},{label:'禁用选项',value:'2',status:'2'}]; %>
<#form:select path="field" items="${items}" itemLabel="label" itemValue="value" class="form-control required" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

该组件使用 jQuery Select2 美化,常用操作举例如下:

$('#userType').val(); 			// 取值方式1
$('#userType').select2('val'); 	// 取值方式2
$('#userType').val('employee').trigger('change'); 	// 赋值方式1
$('#userType').select2('val', 'employee'); 			// 赋值方式2
$('#userType').select2(); 		// 重新初始化
1
2
3
4
5

更多文档详见:https://jeesite.com/front/jquery-select2/4.0/options.htm (opens new window)

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
	dictType: dictType!,		// 字典类型,从字典里获取,自动设置items、itemLabel、itemValue
								// 字典类型加 __all(双下划线+all) 后缀,则显示停用的字典 v4.2.0
	
	items: items![],			// 列表数据,可接受对象集合,如:List<DictData>
	itemLabel: itemLabel!'',	// 指定列表数据中的什么属性名作为option的标签名
	itemValue: itemValue!'',	// 指定列表数据中的什么属性名作为option的value值
	itemStatus: itemStatus!'',	// option 的 disabled,如果是字符串类型(0正常,!0禁用)v4.2.0
	
	multiple: multiple!'false', // 是否为多选框
	
	readonly: toBoolean(readonly!false),		// 是否只读模式 v4.1.7
	
	blankOption: toBoolean(blankOption!false), // 是否默认有个空白选择项目
	blankOptionValue: blankOptionValue!'', // 给空白选择项目设置一个值,默认:空字符串 v4.2.0
	blankOptionLabel: blankOptionLabel!'&nbsp;', // 给空白选择项目设置一个标签,如:请选择、全部
	// data-placeholder: '请选择人员信息', // 下拉选择框的提示信息
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# radio 单选框标签

1、类似<#form:select/>标签的使用方法
<#form:radio path="menuType" dictType="sys_menu_type" class="form-control required" />
1
2

该组件使用 iCheck 美化,常用操作举例如下:

$('#menuType').iCheck('check'); 	// 修改为选择状态
$('#menuType').iCheck('uncheck'); 	// 修改为非选择状态
$('#menuType').iCheck('toggle'); 	// 选择和非选择状态之间切换
$('#menuType').iCheck('disable'); 	// 禁用选择框
$('#menuType').iCheck('enable'); 	// 启用选择框
$('#menuType').iCheck('update');	// 刷新选择状态
$('#menuType input:radio:checked').val();// 取值
// 选中事件
$('#menuType').on('ifChecked', function(){ });
// 取消选中事件
$('#menuType').on('ifUnchecked', function(){ });
// 单击选择框事件
$('#menuType').on('ifClicked', function(){ });
1
2
3
4
5
6
7
8
9
10
11
12
13

更多文档详见:https://jeesite.com/front/icheck/demo/index.html (opens new window)

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
	dictType: dictType!,		// 字典类型,从字典里获取,自动设置items、itemLabel、itemValue
	
	items: items!([]),			// 列表数据,可接受对象集合,如:List<DictData>
	itemLabel: itemLabel!'',	// 指定列表数据中的什么属性名作为option的标签名
	itemValue: itemValue!'',	// 指定列表数据中的什么属性名作为option的value值
	
	readonly: toBoolean(readonly!false),		// 是否只读模式 v4.2.0

	blankOption: toBoolean(blankOption!false), // 是否默认有个空白选择项目 v4.2.0
	blankOptionValue: blankOptionValue!'', // 给空白选择项目设置一个值,默认:空字符串 v4.2.0
	blankOptionLabel: blankOptionLabel!'全部', // 给空白选择项目设置一个标签,如:请选择、全部 v4.2.0
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# checkbox 复选框标签

1、类似<#form:select/>标签的使用方法
<#form:checkbox path="menuType" dictType="sys_menu_type" class="form-control required" />

2、后台接受moduleCodes为字符串,选择多个自动使用“,”分隔,相比SpringMVC必须是List方便的多
<#form:checkbox path="moduleCodes" items="${moduleList}" itemLabel="moduleName" itemValue="moduleCode" class="form-control required" />

3、生成一个复选框按钮(开关),后台接受 replaceFile 为 Global.YES 或 Global.NO 字符串类型的值
<#form:checkbox path="replaceFile" label="是否替换现有文件" class="form-control"/>
1
2
3
4
5
6
7
8

该组件使用 iCheck 美化,常用操作举例如下:

$('#menuType').iCheck('check'); 	// 修改为选择状态
$('#menuType').iCheck('uncheck'); 	// 修改为非选择状态
$('#menuType').iCheck('toggle'); 	// 选择和非选择状态之间切换
$('#menuType').iCheck('disable'); 	// 禁用选择框
$('#menuType').iCheck('enable'); 	// 启用选择框
$('#menuType').iCheck('update');	// 刷新选择状态
$('#menuType input:checkbox:checked').each(function(i,v){
	log($(this).val()) // 取值
});
// 选中事件
$('#menuType').on('ifChecked', function(){ });
// 取消选中事件
$('#menuType').on('ifUnchecked', function(){ });
// 单击选择框事件
$('#menuType').on('ifClicked', function(){ });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

更多文档详见:https://jeesite.com/front/icheck/demo/index.html (opens new window)

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
	dictType: dictType!'',		// 字典类型,从字典里获取,自动设置items、itemLabel、itemValue
	
	items: items!([]),			// 列表数据,可接受对象集合,如:List<DictData>
	itemLabel: itemLabel!'',	// 指定列表数据中的什么属性名作为option的标签名
	itemValue: itemValue!'',	// 指定列表数据中的什么属性名作为option的value值
	
	label: label!,				// 只有一个复选按钮的情况下设置
	
	readonly: toBoolean(readonly!false),		// 是否只读模式 v4.2.0
	
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# textarea 文本域标签

<#form:textarea path="remarks" rows="3" maxlength="200" class="form-control"/>
1

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
};
1
2
3
4
5
6
7
8
9
10

# hidden 隐藏域标签

<#form:hidden path="menuCode" />
1

组件属性:

var p = {
	
	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
};
1
2
3
4
5
6
7
8
9
10

# 高级表单组件封装应用

# treeselect 树结构选择

封装 layer + zTree 实现树结构选择组件、支持单选多选、异步加载下级节点、支持回显选择状态。使用场景如:部门选择,行政区划选择,栏目列表选择等 ;该组件整合 zTree 插件,它性能比较优秀,使用简单,如果遇到超大数据量,或者选择时想展示更多信息,可以使用 listselect 组件。

1、用户选择:
<#form:treeselect id="testUser" title="用户选择" path="testUser.userCode" labelPath="testUser.userName"
	url="${ctx}/sys/office/treeData?isLoadUser=true" class="" allowClear="true"/>

2、用户选择(多选):
<#form:treeselect id="testUser2" title="用户选择" path="testUser.userCode" labelPath="testUser.userName"
	url="${ctx}/sys/office/treeData?isLoadUser=true" class="" allowClear="true" checkbox="true"/>

3、机构选择:
<#form:treeselect id="testOffice" title="机构选择"
	path="testOffice.officeCode" labelPath="testOffice.officeName"
	url="${ctx}/sys/office/treeData" class="" allowClear="true"/>

4、区域选择(异步加载):
<#form:treeselect id="testAreaCode" title="区域选择" path="testAreaCode" labelPath="testAreaName"
	url="${ctx}/sys/area/treeData?parentCode=0" class="" allowClear="true"/>

5、字典树选择:
<#form:treeselect id="testSelect" title="选择字典" path="testSelect"
	labelValue="${@DictUtils.getDictLabel('sys_menu_type', testData.testSelect, '')}" 
	url="${ctx}/sys/dictData/treeData?dictType=sys_menu_type" isReturnValue="true"
	class="" allowClear="true"/>

6、字典树选择(多选):
<#form:treeselect id="testSelectMultiple" title="选择字典" path="testSelectMultiple"
	labelValue="${@DictUtils.getDictLabels('sys_menu_type', testData.testSelectMultiple, '')}" 
	url="${ctx}/sys/dictData/treeData?dictType=sys_menu_type" isReturnValue="true"
	class="" allowClear="true" checkbox="true"/>

7、菜单选择(允许清理、允许选择根节点、允许选择父节点):
<#form:treeselect id="testMenu" title="菜单选择" path="menu.menuCode" labelPath="menu.menuNameOrig" 
	url="${ctx}/sys/menu/treeData?excludeCode=${menu.menuCode}&sysCode=${menu.sysCode}&isShowNameOrig=true"
	class="" allowClear="true" canSelectRoot="true" canSelectParent="true"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 隐藏域名称(隐藏域id生成规则为 id+Code)
	value: value!,				// 隐藏域值
	defaultValue: defaultValue!,// 隐藏域默认值 v4.1.5
	
	labelPath: labelPath!,		// 绑定form上model中属性的值
	labelName: labelName!,		// 标签框名称(标签框id生成规则为 id+Name)
	labelValue: labelValue!,	// 标签框值
	defaultLabel: defaultLabel!,// 标签框默认值 v4.1.5
	
	class: class!'',			// 标签框的CSS类名
	placeholder: placeholder!,	// 标签框的预期值的提示信息
	dataMsgRequired: thisTag.attrs['data-msg-required'],	// 必填错误提示信息
	
	btnClass: btnClass!,		// 标签框后面的按钮CSS类名
	
	title: title!text('选项选择'),	 // 对话框标题
	boxWidth: boxWidth!300, 		// 对话框宽度,默认300像素
	boxHeight: boxHeight!400,		// 对话框高度,默认400像素
	
	url: url!,						// 树结构,数据源地址 [{id, pid, name}]
	
	readonly: toBoolean(readonly!false),		// 是否只读模式
	
	allowInput: toBoolean(allowInput!false),	// 是否允许label框输入
	allowClear: toBoolean(allowClear!true),		// 是否允许清空选择内容
	
	checkbox: toBoolean(checkbox!false),		// 是否显示复选框,是否支持多选,如果设置canSelectParent=true则返回父节点数据
	chkboxType: chkboxType!'',					// 复选框级联选择规则 v4.0.6,默认:{'Y':'ps','N':'ps'}
	expandLevel: @ObjectUtils.toInteger(expandLevel!(-1)),		// 默认展开层次级别(默认:如果有1个根节点,则展开一级节点,否则不展开)
	
	canSelectRoot: toBoolean(canSelectRoot!false),		// 可以选择跟节点
	canSelectParent: toBoolean(canSelectParent!false),	// 可以选择父级节点
	
	isReturnValue: isReturnValue!'false',				// 是否返回树结构的value值,而不是返回id(默认id)
	
	returnFullName: toBoolean(returnFullName!false),	// 是否返回全路径,包含所有上级信息,以 returnFullNameSplit 参数分隔
	returnFullNameSplit: returnFullNameSplit!'/',		// 是否返回全路径,的分隔符,默认“/”

	fastSearch: toBoolean(allowClear!true),		// 快速查询,查询框输入后接着进行查询,关闭后,点击查询按钮或回车再查询 v4.5.0 v5.0.2
	
	openFuncName: openFuncName!'treeselectOpen',				// 可自定义弹窗前调用的函数名   v4.2.0
	checkFuncName: checkFuncName!'treeselectCheck',				// 可自定义验证方法的函数名  v4.1.5
	callbackFuncName: callbackFuncName!'treeselectCallback',	// 可自定义回调方法的函数名   v4.1.0
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

JS回调事件:

/**
 * 选择前调用,数据验证函数,返回false代表验证失败
 * @param id  标签的id
 * @param node  验证的数据
 * @return true 验证成功,false 验证失败
 */
function treeselectCheck(id, nodes){
	if (id == 'parent'){
		log(nodes); // 选择的节点数据
		js.showMessage('验证失败提醒!');
		return false; // 验证失败,阻止关闭
	}
	return true; // 验证成功
}
/**
 * 选择回调方法
 * @param id  标签的id
 * @param act 动作事件:ok、clear、cancel
 * @param index layer的索引号
 * @param layero layer内容的jQuery对象
 * @param nodes 当前选择的树节点数组
 */
function treeselectCallback(id, act, index, layero, nodes){
	if (id == 'parent' && (act == 'ok' || act == 'clear')){
		var win = layero.iframeWindow();
		log(win);    // 选择框内容的window对象
		log(act);    // 回调活动事件(ok、clear、cancel)
		log(index);  // layer的index
		log(layero); // layer实例对象
		log(selectData);  // 选择的节点数据
		log(nodes);  // 选择的节点数据
	}
}
/**
 * 弹出对话框前调用 v4.2.0
 * @param id  标签的id
 * @param options  弹窗选项
 * @return 返回 false 则不弹框,直接返回
 */
function treeselectOpen(id, options){
	if (id == 'parent'){
		log(options);
		// 弹窗前修改弹窗的数据地址
		options.content = ctx+'/sys/office/treeData';
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

# listselect 列表选择

弹窗显示 DataGrid 列表风格来选择数据,甚至左树右表风格选择数据。支持单选多选、支持返回选择数据的完整信息,例如:选择了员工,将员工编码和名称返回到表单里,还可以将员工的性别、档案等信息返回到表单里;支持超大数据量分页展示,切换分页不影响选择状态。

1、用户列表选择:
<#form:listselect id="testUser3" title="用户选择"
	path="testUser.userCode" labelPath="testUser.userName"
	url="${ctx}/sys/empUser/empUserSelect" allowClear="false" 
	checkbox="false" itemCode="userCode" itemName="userName"/>
后台接口参考:EmpUserController.java 类的 empUserSelect 方法,
返回的视图列表选择页面参考:empUserSelect.html 文件。

2、用户列表多选:
<#form:listselect id="testUser4" title="用户选择"
	path="testUser.userCode" labelPath="testUser.userName"
	url="${ctx}/sys/empUser/empUserSelect" allowClear="false" 
	checkbox="true" itemCode="userCode" itemName="userName"/>

3、用户选择(不含组织机构):
<#form:listselect id="userSelect" title="用户"
	path="testUser.userCode" labelPath="testUser.userName"
	url="${ctx}/sys/user/userSelect?userType=employee" allowClear="false" 
	checkbox="false" itemCode="userCode" itemName="userName"/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 隐藏域名称(隐藏域id生成规则为 id+Code)
	value: value!,				// 隐藏域值
	defaultValue: defaultValue!,// 隐藏域默认值 v4.1.5
	
	labelPath: labelPath!,		// 绑定form上model中属性的值
	labelName: labelName!,		// 标签框名称(标签框id生成规则为 id+Name)
	labelValue: labelValue!,	// 标签框值
	defaultLabel: defaultLabel!,// 标签框默认值 v4.1.5
	
	class: class!'',			// 标签框的CSS类名
	placeholder: placeholder!,	// 标签框的预期值的提示信息
	dataMsgRequired: thisTag.attrs['data-msg-required'],	// 必填错误提示信息
	
	btnClass: btnClass!,		// 标签框后面的按钮CSS类名
	
	title: title!'选项',		// 对话框标题
	boxWidth: boxWidth!'$(top.window).width() - 100', 		// 对话框宽度
	boxHeight: boxHeight!'$(top.window).height() - 100',	// 对话框高度 
	
	url: url!,					// 列表地址,参考EmpUserController的empUserSelect方法
	
	readonly: toBoolean(readonly!false),		// 是否只读模式
	
	allowInput: toBoolean(allowInput!false),	// 是否允许label框输入
	allowClear: toBoolean(allowClear!true),		// 是否允许清空选择内容
	
	checkbox: toBoolean(checkbox!false),		// 是否显示复选框,是否支持多选,如果设置canSelectParent=true则返回父节点数据
	
	itemCode: itemCode!,	// 选择后结果集中的Code属性名,返回到隐藏域的值
	itemName: itemName!,	// 选择后结果集中的Name属性名,返回到输入框的值
	
	getSelectDataFuncName: getSelectDataFuncName!'listselectGetSelectData',	// 选择页面,获取已经选择的数据,回显到选择页面  v4.1.5
	setSelectDataFuncName: setSelectDataFuncName!'listselectSetSelectData',	// 选择之后,点击确定,将选择数据设置到业务表单  v4.2.0
	
	openFuncName: openFuncName!'listselectOpen',				// 可自定义弹窗前调用的函数名   v4.2.0
	checkFuncName: checkFuncName!'listselectCheck',				// 可自定义验证方法的函数名  v4.2.0
	callbackFuncName: callbackFuncName!'listselectCallback',	// 可自定义回调方法的函数名  v4.1.5
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

JS回调事件:

/**
 * 选择前调用,数据验证函数,返回false代表验证失败
 * @param id  标签的id
 * @param selectData  当前选择列表的数据MAP
 * @return true 验证成功,false 验证失败
 */
function listselectCheck(id, selectData){
	if (id == 'parent'){
		log(selectData); // 选择的节点数据
		js.showMessage('验证失败提醒!');
		return false; // 验证失败,阻止关闭
	}
	return true; // 验证成功
}
/**
 * 选择框回调方法
 * @param id  标签的id
 * @param act 动作事件:ok、cloear、cancel
 * @param index layer的索引号
 * @param layero layer内容的jQuery对象
 * @param selectData 当前选择列表的数据MAP
 */
function listselectCallback(id, act, index, layero, selectData){
	if (id == 'parent' && (act == 'ok' || act == 'clear')){
		var win = layero.iframeWindow();
		log(win);    // 选择框内容的window对象
		log(act);    // 回调活动事件(ok、clear、cancel)
		log(index);  // layer的index
		log(layero); // layer实例对象
		log(selectData);  // 选择的节点数据
	}
}
/**
 * 弹出对话框,列表数据回显调用方法
 * @param id  标签的id
 * @return selectData 当前选择列表的数据MAP
 */
function listselectGetSelectData(id){
	var selectData = {};
	if (id == 'parent' && (act == 'ok' || act == 'clear')){
		selectData['主键字段值'] = {行数据};
	}
	return selectData;
}
/**
 * 选择后,设置到业务表单调用方法 v4.2.0
 * @param id  标签的id
 * @param selectData 当前选择列表的数据MAP
 */
function listselectSetSelectData(id, selectData){
	if (id == 'parent'){
		log(selectData);
	}
}
/**
 * 弹出对话框前调用 v4.2.0
 * @param id  标签的id
 * @param options  弹窗选项
 * @return 返回 false 则不弹框,直接返回
 */
function listselectOpen(id, options){
	if (id == 'parent'){
		log(options);
		// 弹窗前修改弹窗的数据地址
		options.content = ctx+'/sys/empUser/empUserSelect';
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# iconselect 图标选择

<#form:iconselect path="menuIcon" class=""/>
1

组件属性:

var p = {
	
	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
	class: class!'',			// 隐藏域和标签框的CSS类名
	
};
1
2
3
4
5
6
7
8
9
10
11
12

# validcode 验证码

<#form:validcode name="validCode" isRequired="true" isRemote="true" />
1

组件属性:

var p = {

	id: id!name,				// 验证码输入框ID
	name: name!,				// 验证码输入框名称(必填)
	
	isRequired: toBoolean(isRequired!true),					// 是否必填,默认必填
	dataMsgRequired: thisTag.attrs['data-msg-required'],	// 必填错误提示信息
	
	isRemote: toBoolean(isRemote!true),						// 是否支持实时远程验证
	dataMsgRemote: thisTag.attrs['data-msg-remote'],		// 必填错误提示信息
	
	isLazy: toBoolean(isLazy!false),			// 是否懒加载验证码图片,原noRefresh参数

	isShowLabel: toBoolean(isShowLabel!true),	// 是否显示“验证码”标签,默认true(V4.0.5)

};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# fileupload 文件上传

<% layout(... libs: ['fileupload'] ...}){ %>

1、文件上传:
<#form:fileupload id="upload1" bizKey="${user.id}" bizType="user_upload1"
	uploadType="all" class="required" readonly="false"/>
后台代码:FileUploadUtils.saveFileUpload(user, user.getId(), "user_upload1");

2、图片上传:
<#form:fileupload id="upload2" bizKey="${user.id}" bizType="user_upload2"
	uploadType="image" class="required" readonly="false"/>
后台代码:FileUploadUtils.saveFileUpload(user, user.getId(), "user_upload2");

3、返回路径:
<#form:fileupload id="upload3" returnPath="true"
	filePathInputId="upload3Path" fileNameInputId="upload3Name"
	uploadType="image" readonly="false" maxUploadNum="3" isMini="false"/>
<#form:input path="upload3Path" class="form-control"/>
<#form:input path="upload3Name" class="form-control"/>

4、在线文件预览(增加 preview="true" 属性, 4.2之前版本:preview="weboffice"):
<#form:fileupload id="upload4" bizKey="${user.id}" bizType="user_upload4"
	uploadType="all" class="required" readonly="false" preview="true"/>
支持自定义文件预览,可改变该属性值,如:preview="custom" 对应预览地址为:/file/custom/preview

5、支持指定文件查询地址,如 bizKey 右模糊查询数据,适应 parentBizKey 的场景(v4.1.5):
<#form:fileupload id="upload5" bizKey="${entity.parentCode}_" bizType="upload5"
	uploadType="all" class="" readonly="true" preview="true"
	serviceFileList="${ctxAdmin}/file/fileList?bizKeyIsLike=true"/>

6、更改上传按钮文字(例子中的 #upload2_wup 规则为:fileupload id + _wup):
<script>$(function(){$('#upload2_wup .webuploader-pick').text('上传图片')});</script>

7、通过后台 Java 上传文件:联系售后技术人员获取 FileUploadTest 实例代码

8、文件打包批量下载:联系售后技术人员获取 FileBatchDownTest 实例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

常见问题1:

  • 我的业务表里需要创建上传文件字段吗?不需要,fileupload 组件里设计了 bizKey 和 bizType 属性,用来保存业务表和文件上传表之间的关联关系,所以无需在你的业务表里创建上传文件字段。

  • 如果想将上传文件名称和文件路径存储到业务表里?可以使用 returnPath(返回路径)属性,将文件上传信息写入指定的 input 控件里,保存即可。

  • 一个页面里是否可以写多个上传文件控件?可以的,通过 bizType 进行分类区分,多个组件指定不同的 id 和 bizType 属性值即可。

常见问题2:

  • 为什么没有保存 bizKey 和 bizType 值到后台?因为在上传文件的时候,新增的表单还没有生成主键,当你点击表单保存后,后台代码调用 FileUploadUtils.saveFileUpload 更新这两个值,才会真正建立文件和业务数据的关系。

  • 为什么点击组件的任何按钮都没反应?请检查是否添加类库:<% layout(... libs: ['fileupload'] ...}){ %>

常见问题3:

  • 为什么有时候点击上传文件按钮没有反应,可能是因为你的 fileupload 控件隐藏或控件的 top 位置改变造成的, 你只需在显示隐藏控件后或 onload 事件后执行如下代码刷新上传按钮位置即可:
if (typeof window.webuploaderRefresh == 'function'){
	window.webuploaderRefresh();
}
1
2
3
  • 切换 Bootstrap Tab 页签后点击上传按钮没反应:
$(function(){
	$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
		if(typeof window.webuploaderRefresh == 'function'){
			window.webuploaderRefresh();
		}
	});
});
1
2
3
4
5
6
7
  • 旧版本中可能会出现子表左右滚动后点击上传按钮没反应:
$(function(){
	$('#dataGrid').parent().scroll(function (e) {
		if(typeof window.webuploaderRefresh == 'function'){
			window.webuploaderRefresh();
		}
	});
});
1
2
3
4
5
6
7

重载文件列表数据:

// 刷新文件列表(重载“业务关联”的文件列表)
$('#upload1Uploader').webuploader('refreshFileListByBizData');
// 刷新文件列表(重载“返回路径”方式指定的input文件列表)
$('#upload1Uploader').webuploader('refreshFileListByPath');
// 加载自定义数据到文件列表
$.ajax({
    url: ctxAdmin+'/file/fileList?__t=' + new Date().getTime(),
    data: {
        "bizKey" : '1242793777583443968',
        "bizType" : 'upload1_file'
    },
    dataType : 'json',
    success : function(data){
        if (!(data.result == "false")) {
            for (var i in data){
                data[i].id += '_new'; // 后台应对该后缀的数据进行复制并插入
            }
            $('#upload1Uploader').webuploader('refreshFileList', [data, true]);
        }
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

注意:upload1Uploader 格式为 id+Uploader。别忘加 Uploader 后缀。

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID
	
	bizKey: bizKey!,			// 业务表的主键值(与附件关联的业务数据)
	bizType: bizType!,			// 业务表的上传类型(全网唯一,推荐格式:实体名_上传类型,例如,文章图片:article_photo)
	
	returnPath: toBoolean(returnPath!false), 	// 是否是返回文件路径到输入框(默认false),可将路径直接保存到某个字段里
	filePathInputId: filePathInputId!,	// 设置文件URL存放的输入框的ID,当returnPath为true的时候,返回文件URL到这个输入框
	fileNameInputId: fileNameInputId!,	// 设置文件名称存放的输入框的ID,当returnPath为true的时候,返回文件名称到这个输入框
	
	uploadType: uploadType!'',			// 上传文件类型:all、file、image、media,若不设置,则自动根据上传文件后缀获取
	class: class!'',					// 标签框的CSS类名,设置 required 加入必填验证
	readonly: toBoolean(readonly!false),		// 是否只读模式,只读模式下为查看模式,只允许下载
	
	allowSuffixes: allowSuffixes!'', 	// 允许上传的后缀,前台的限制,不能超越file.*AllowSuffixes的设置,例如:.jpg,.png,
	maxFileSize: maxFileSize!'',		// 当前控件的文件上传大小设置(500*1024*1024)单位字节,不可超过配置文件设置的文件大小
	maxUploadNum: @ObjectUtils.toInteger(maxUploadNum!300),		// 多文件下允许最多上传几个,默认300个,设置-1代表不限制
	
	cueWords: cueWords!'',				// 提示语,默认:或将照片(文件)拖到这里,最多可选 maxUploadNum 张(个) v4.1.5

	imageMaxWidth: @ObjectUtils.toInteger(imageMaxWidth!1024),	// 图片压缩,最大宽度(uploadType为image生效),设置-1代表不做任何处理
	imageMaxHeight: @ObjectUtils.toInteger(imageMaxHeight!768),	// 图片压缩,最大宽度(uploadType为image生效),设置-1代表不做任何处理
	
	serviceUpload: serviceUpload!(ctxAdmin+'/file/upload'),			// 上传文件后台服务  v4.1.5
	serviceDownload: serviceDownload!(ctxAdmin+'/file/download/'),	// 下载文件后台服务  v4.1.5
	serviceFileList: serviceFileList!(ctxAdmin+'/file/fileList'),	// 查询文件后台服务  v4.1.5
	
	extendParams: extendParams!'',	// 提交的上传扩展参数,例如:n1:'v1',n2:'v2',后台接受:fileEntity.getFileUploadParams().getExtend() v4.1.3
	
	isLazy: toBoolean(isLazy!false),	// 设置为ture需要点击上传按钮才上传文件,否则选择后就直接上传
	
	isMini: toBoolean(isMini!false),	// 是否是精简上传窗口,无边距,无边框
	
	preview: preview!'',	// 是否显示预览按钮,接受参数:v4.2.0 之前版本为 weboffice,之后版本为 true,可根据需要扩展预览引擎
	
	callbackFuncName: callbackFuncName!'fileuploadCallback',	// 可自定义回调方法的函数名   v4.1.8+ v4.2.0+
	
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

组件事件:

WebUploader 支持事件绑定,可用于回调。

$(function(){
	var uploader = window.webuploader[0];
	uploader.on('all',  function(type, file) {
		log(type)
		log(file)
	});
});
/**
 * 上传组件回调 v4.2.0
 * @param id  标签的id
 * @param act 动作事件:create、ready、addFile、delFile
 * @param $this webuploader 组件对象
 * @param fileUpload 添加文件时的数据 v4.2.2
 */
function fileuploadCallback(id, act, $this, fileUploadId, fileUrl, fileName, fileUpload){
	log(id + ' ' + act + ' ' + fileUploadId + ' ' + fileUrl + ' ' + fileName)
	if (act == 'addFile') { log(fileUpload); }
	log($this)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

后台 FileUploadUtils API:

/** 
 * 保存上传附件与业务的关系
 * @param bizKey 业务主键
 * @param bizType 业务类型
 * @example
 * 		// 保存上传的附件
 * 		FileUploadUtils.saveFileUpload(testData.getId(), "test_data_field1");
 */
public static void saveFileUpload(String bizKey, String bizType);

/** 
 * 保存上传附件与业务的关系(手机端、移动端、分离端,需要设置 entity 来支持 RequestBody 方式参数)
 * @param entity 业务实体(获取 entity.dataMap 里的参数)
 * @param bizKey 业务主键
 * @param bizType 业务类型
 * @example
 * 		// 保存上传的附件
 * 		FileUploadUtils.saveFileUpload(testData, testData.getId(), "test_data_field1");
 */
public static void saveFileUpload(DataEntity<?> entity, String bizKey, String bizType);

/** 
 * 保存上传附件与业务的关系
 * @param bizKey 业务主键
 * @param bizType 业务类型
 * @param fileUploadIds 对应的上传文件编码
 * @param delFileUploadIds 对应的上传文件需要删除的编码
 */
public static void saveFileUpload(String bizKey, String bizType,
		String fileUploadIds, String delFileUploadIds);

/** 
 * 查询业务关系的上传附件
 * @param bizKey 业务主键
 * @param bizType 业务类型
 */
public static List<FileUpload> findFileUpload(String bizKey, String bizType);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

手机端上传附件:

如果你采用html5混合模式开发,你可解压 jeesite-framework.jar 并将 /static/webuploader 文件夹拷贝到你的手机端APP里面,可删掉 swf 和其它用不到的文件。然后在你的对应页面引入 webuploader.css、webuploader.extend.css、webuploader.extend.js、webuploader.js(v4.1.1下可引入webuploader.mobile.js)等文件,其它依赖文件也要引入,如:jquery-3.5.0.min.js、bootstrap.min.css、jeesite.js、jeesite_zh_CN.js。接下来,随便在PC后端beetl视图页面里加入如下代码:

<#form:fileupload id="uploadImage" bizKey="当前业务主键" bizType="当前业务类型_image" uploadType="image"
		class="" readonly="false" isMini="true"/>
1
2

通过Chrome浏览器访问这个控制器视图,空白处右键“查看当前框架页面的源代码”,搜索 class="wup_container 拷贝该div和紧挨着下方的script标签内容到你的手机页面,修改对应fileupload接受参数即可。

若你是原生开发:

还请参照此控件自己实现上传UI即可,参照方法: 浏览器 F12 打开 network 监控,监控请求路径及数据,共分为2次请求:

  1. 第一次发送文件的MD5码(10M部分,不足10M取全部),后台返回result结果。生成MD5方法,例如:Md5Utils.md5File(file, 0, 10 * 1024 * 1024);
  2. result为true,则代表已经上传过,并返回 fileUpload 数据,并放到 bizType 命名的隐藏域中。
  3. result为false,则待办未上传过,还请你根据F12监控到的数据,需要你第二次发送上传文件请求。
  4. 提交表单时,请将 bizType 隐藏域和 bizType__del 隐藏域提交到后台。(重要)
  5. 后台通过 FileUplandUtils 接受到该值并文件与当前表单主键建立关系。
  6. 接口测试(可以导入Postman):https://gitee.com/thinkgem/jeesite4/attach_files/249363/download (opens new window)
  7. 推荐使用 Apifox 接口工具:https://www.apifox.cn (opens new window)

如何将文件上传到云存储?

请看对象存储专题:对象存储 MinIO、阿里云、腾讯云、七牛云

# imageclip 图片裁剪

<img id="avatarImg" class="profile-user-img img-responsive img-circle"
    src="${@user.getAvatarUrl().replaceFirst('/ctxPath', ctxPath)}">
<#form:imageclip name="imageBase64" btnText="修改头像" btnClass="btn-block"
	imageId="avatarImg" imageDefaultSrc="${ctxStatic+'/images/user1.jpg'}"
	circle="true"/>
1
2
3
4
5

后台代码:

// 如果设置了头像,则保存头像
if (StringUtils.isNotBlank(imageBase64)){
	if ("EMPTY".equals(imageBase64)){
		user.setAvatar(StringUtils.EMPTY);
	}else{
		String imageUrl = "avatar/"+user.getUserCode()
				+"."+FileUtils.getFileExtensionByImageBase64(imageBase64);
		String fileName = Global.getUserfilesBaseDir(imageUrl);
		FileUtils.writeToFileByImageBase64(fileName, imageBase64);
		user.setAvatar(Global.USERFILES_BASE_URL + imageUrl);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
	class: class!'',			// 隐藏域的CSS类名
	
	btnText: btnText!text('选择图片'),	// 按钮的名字
	btnClass: btnClass!'',				// 按钮的CSS类名
	
	imageId: imageId!'',					// 裁剪后base64返回到img的id
	imageDefaultSrc: imageDefaultSrc!'',	// 图片默认地址,清除后使用地址
	
	ratio: ratio!'1/1', 		// 图片裁剪比例 v4.1.7
	circle: circle!'false', 	// 是否圆形图片
	
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# ueditor 在线编辑器

UEditor 是流行的富文本在线编辑器,所见即所得。

<% layout(... libs: ['ueditor'] ...}){ %>
<#form:ueditor path="text" maxlength="10000" height="200" class="required"
	simpleToolbars="false" readonly="false" outline="false"/>
1
2
3

获取UE对象,格式:id+UE 或 path+UE,例如:path="text" 返回的对象为 textUE,举例如下:

// 设置编辑器内容
textUE.setContent('hello');
// 获取编辑器内容
textUE.getContent()
// 获取编辑器纯文本内容
textUE.getContentTxt()
1
2
3
4
5
6

组件属性:

var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
	class: class!'',			// 标签框的CSS类名,设置 required 加入必填验证
	
	maxlength: maxlength!'',	// 编辑器最大输入字数,为空代表无限制
	height: height!'200',		// 编辑器的高度,默认200
	
	simpleToolbars: toBoolean(simpleToolbars!false), // 是否是简单的工具条
	
	readonly: toBoolean(readonly!false), 			// 是否只读模式
	
	outline: toBoolean(outline!false), 				// 大纲视图
	
	options: options!'',		// UE附加选项,逗号隔开。
	
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

注意:如果需要将文件上传到其它文件服务,重写 jeesite-common 项目下的 StorageManager 类 uploadFileSuccess 方法即可,举例如下:

/**
 * UEditor上传文件成功后调用事件
 * @param physicalPath 上传文件实际路径 storageState.url 返回到客户端的文件访问地址
*/
public static void uploadFileSuccess(String physicalPath, State storageState){
	String fileName = StringUtils.substringAfterLast(physicalPath, "/");
	String ossPath = FileUploadParams.FILEUPLOAD_BASE_URL + "/ueditor/" + fileName;
	try {
		// 上传到 OSS 文件服务器
		File file = new File(physicalPath);
		String endpoint = properties.getEndpoint();
		String bucketName = properties.getBucketName();
		aliyunOssClient.putObject(bucketName, ossPath, file);
		String url = endpoint + "/" + bucketName + "/" + ossPath;
		storageState.putInfo("url", FileUtils.path(url));
	} catch (Exception e) {
		throw ExceptionUtils.unchecked(e);
	} finally {
		// 文件上传后删除临时文件
		FileUtils.deleteFile(fileRealPath);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# extend 扩展字段

<#form:extend collapsed="true" />
1

组件属性:

var p = {

	// 标签参数
	collapsed: toBoolean(collapsed!true),	// 初始状态是否折叠
	
	title: text('扩展字段'),		// 显示标题、折叠标题,v4.2.3 版本以后版本生效
	
	extendS1: text('String 1'),		// extendS1 及以下属性的标签名 v4.2.3 版本以后版本生效
	extendS2: text('String 2'),
	extendS3: text('String 3'),
	extendS4: text('String 4'),
	extendS5: text('String 5'),
	extendS6: text('String 6'),
	extendS7: text('String 7'),
	extendS8: text('String 8'),
	extendI1: text('Integer 1'),
	extendI2: text('Integer 2'),
	extendI3: text('Integer 3'),
	extendI4: text('Integer 4'),
	extendF1: text('Float 1'),
	extendF2: text('Float 2'),
	extendF3: text('Float 3'),
	extendF4: text('Float 4'),
	extendD1: text('Date 1'),
	extendD2: text('Date 2'),
	extendD3: text('Date 3'),
	extendD4: text('Date 4'),
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 自定义 form 标签组件

第一步:标签都需要放到指定目录下:

/src/main/resources/views/htmltags/
1

第二步:举例一个 form:input 组件的实现:

/src/main/resources/views/htmltags/form/input.html
1

第三步:组件内容如下:

<%/* Copyright (c) 2013-Now http://jeesite.com All rights reserved. */

/**
 * 表单控件:输入框
 * @author ThinkGem
 * @version 2017-3-5
 */
var p = {

	// 标签参数
	id: id!,					// 元素ID,如果不填写,则与name相同
	path: path!,				// 绑定form上model中属性的值
	name: name!,				// 元素名称,不填写
	value: value!,				// 元素值
	defaultValue: defaultValue!,// 默认值 v4.1.5
	
	type: type!'text',			// 元素的类型,默认text
	
	dataFormat: dataFormat!'',	// 数据格式化
	
	// 内置参数
	thisTag: thisTag,
	exclAttrs: ['id', 'path', 'name', 'value', 'defaultValue', 'type', 'dataFormat']
};

// 编译绑定参数
form.path(p);

// 数据格式化
var df = '';
if (p.dataFormat == 'date'){
	df = { %> value="${p.value,dateFormat='yyyy-MM-dd'}"<% };
}else if (p.dataFormat == 'datetime'){
	df = { %> value="${p.value,dateFormat='yyyy-MM-dd HH:mm'}"<% };
}else if (p.dataFormat == 'number'){
	df = { %> value="${p.value,numberFormat='#.##'}"<% };
}else{
	df = { %> value="${p.value}"<% };
}
p.attrs = p.attrs!'' + df;

// 编译属性参数
form.attrs(p);
		
%><input type="${p.type}" id="${p.id}" name="${p.name}"${p.attrs}/>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 表单验证内置类型

第一步:libs 引入库

<% layout('/layouts/default.html', {libs: ['validate']}){ %>
1

第二步:绑定表单验证

$("#inputForm").validate({
	submitHandler: function(form){
		// 提交表单
		js.ajaxSubmitForm($(form), function(data){
			js.showMessage(data.message);
			if(data.result == Global.TRUE){
				js.closeCurrentTabPage(function(contentWindow){
					contentWindow.page();
				});
			}
		}, "json");
	}
});
1
2
3
4
5
6
7
8
9
10
11
12
13

第三步:将类型放入控件 class 即可

<input class="form-control required " />
1

内置验证类型:

(function ($) {
	$.extend($.validator.messages, {
		required: "必填信息",
		remote: "请修正该信息",
		email: "请输入正确格式的电子邮件",
		url: "请输入合法的网址",
		date: "请输入合法的日期",
		dateISO: "请输入合法的日期 (YYYY-MM-DD).",
		number: "请输入合法的数值",
		digits: "请输入一个正整数",
		equalTo: "请再次输入相同的值",
		maxlength: $.validator.format("最多可以输入 {0} 个字符"),
		minlength: $.validator.format("最少要输入 {0} 个字符"),
		rangelength: $.validator.format("请输入长度在 {0} 到 {1} 之间的字符串"),
		range: $.validator.format("请输入范围在 {0} 到 {1} 之间的数值"),
		max: $.validator.format("请输入不大于 {0} 的数值"),
		min: $.validator.format("请输入不小于 {0} 的数值"),
		errorMessage: "您填写的信息有误,请根据提示修正。",
		userName: "登录账号只能包括中文字、英文字母、数字和下划线",
		realName: "姓名只能为2-30个汉字",
		abc: "请输入字母数字或下划线",
		noEqualTo: "请再次输入不同的值",
		mobile: "请正确填写您的手机号码,只能是13,14,15,16,17,18,19号段",
		simplePhone: "请正确填写您的电话号码,固话为区号(3-4位)号码(7-9位)",
		phone: "请正确填写您的电话号码,固话为区号(3-4位)号码(7-9位),手机为13,14,15,16,17,18,19号段",
		zipCode: "请正确填写您的邮政编码",
		integer: "请输入一个整数",
		ipv4: "请输入一个有效的 IP v4 地址",
		ipv6: "请输入一个有效的 IP v6 地址",
		qq: "请正确填写您的QQ号码",
		idcard: "请输入正确的身份证号码(15-18位)"
	});
}(jQuery));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

扩展自定义验证:

// 手机号码验证
jQuery.validator.addMethod("mobile", function(value, element) {
	var tel = /^1[3,4,5,6,7,8,9]\d{9}$/g;
	return this.optional(element) || (tel.test(value));
}, $.validator.messages.mobile);
1
2
3
4
5

# 前端组件资源

  • 后台管理模板:AdminLTE 2.4 (opens new window)

  • Web前端框架:Bootstrap 3.3 (opens new window)

  • 下拉框:jQurey Select2 4.0 (opens new window)

  • 单选框、复选框:iCheck 1.0 (opens new window)

  • 表单验证:jQurey Validation 1.16 (opens new window)

  • Web弹窗/层:Layer 3.0 (opens new window)

  • 日期选择控件:LayDate 5.3 (opens new window)

  • JavaScript模板:Laytpl 1.2 (opens new window)

  • 树插件API:jQurey zTree API 3.5 (opens new window)

  • 树插件Demo:jQurey zTree Demo 3.5 (opens new window)

  • 数据表格插件:jQuery jqGrid 4.7 (opens new window)

进入 JeeSite 源码仓库页面,点击右上角 ⭐ Star 加星关注。

← 后台常用工具类、Utils Data Grid 表格组件→

联系我们:s.jeesite.com  |  微信号:jeesitex  |  邮箱:jeesite@163.com
© 2013-2023 济南卓源软件有限公司 版权所有 | Theme Vdoing

关注 JeeSite 公众号,了解最新动态

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式