JeeSite 框架学习笔记
JeeSite 框架学习笔记
目录
- JeeSite 框架学习笔记
- 一、全局配置
- 1. 获取 Resource资源实际路径 DefaultResourceLoader
- 2. 配置前端 js css
- 二、JAVA 处理 Word 和 打印
- 1. JAVA 处理 Word
- 2. JAVA 打印
- 3. Word转图片
- 4. 前端 js 打印页面
- 三、Form 页面
- 1. 单列页面
- 2. 参数控制
- 3. select 控件 和 input 控件同一行无法对齐
- 4. input 控件
- 5. jQuery Validate自定义验证
- 6. textarea 禁止自定义大小
- 7. 图片路径获取
- 8. div onresize事件
- 9. 去掉 comboTree的图标
- 10. jQuery validator
- 11. 输入范围在 {0} 到 {1} 之间的数值
- 12. 强行将字段更新为 null
- 13. 传到后端的值中多了逗号 ","
- 14. 刷新 list 页面
- 四、DataGrid
- 1. 禁止拖拽表格列头
- 2. 多次表头出现多出一列
- 3. action 图标对齐
- 4. 最小高度设置 options.gridMinMeight
- 5. 下载文件处理
- 五、jQuery 应用
- 1. 属性选择器处理按钮
- 2. SELECT 控件操作
- 3. ajax 请求数据
- 六、IDEA 配置
- 1. 手动加的 lib 加入到 git
- 2. 快速查找和定位文件位置
- 3. run application报错
- 4. DashBoard/ Services不显示端口号
- 5. 底部显示 service 窗口
- 6. 快捷键
- 七、修改 JeeSite内置页面
- 1. 修改登录页面
- 八、权限配置
- 1. 无需登录直接访问 url
- 九、Beetl
- 1. 注意点
- 十、不同窗口之间交互
- 十一、使用经验总结:
- 1. 查看表单中的控件禁用:
- 2. ajax 请求:
- 3. DataGrid 中 Action 按钮操作方式
- 4. js.getCurrentTabPage 打开新页面窗口回调
- 5. 文本中加入汉字空格
- n. temp
- 十二、JavaScript 操作DOM:
- 1. 向 document中手动添加 style:
- 十三、调试技巧:
- 1. 跟踪前端底层代码:
- 十四、DataGrid:
- 1. 同一页面根据 url 参数不同显示内容不同:
- 十五、自动生成:
- 1. 新增/修改 表单 自动生成 详设文档:
一、全局配置
1. 获取 Resource资源实际路径 DefaultResourceLoader
示例:
// 获取 Resource资源实际路径ResourceLoader resourceLoader = new DefaultResourceLoader();System.out.println(resourceLoader.getResource("classpath:static/font/").getURI());
参考链接:
java web获取配置文件路径.
java web获取配置文件路径_绝对路径、相对路径.
2. 配置前端 js css
配置前端 js css:
// resources\views\include\jslibs.html
// resources\views\include\csslibs.html
二、JAVA 处理 Word 和 打印
1. JAVA 处理 Word
参考链接:
Java多种方式动态生成doc文档.
POI设置 word文本下划线样式及文字底纹.
2. JAVA 打印
参考链接:
使用Java调用打印机进行打印(JPG、PDF和Word三种文件格式).
Java jacob调用打印机打印word文档.
3. Word转图片
// 测试:从本地读取word保存图片到本地
File fWord = new File("d:\\test.docx");
InputStream inStream = new FileInputStream(fWord);List<BufferedImage> tempImg = WordAspose.wordToImg(inStream);
BufferedImage mergeImage = WordAspose.mergeImage(false, tempImg);ImageIO.write(mergeImage, "jpg", new File("D:\\1.jpg"));
4. 前端 js 打印页面
// 打印选项设置
// 注意:如果写成 magin: 0mm; 可能会不起作用
// 此方法不适用IE内核的浏览器,IE 使用 pagesetup_null()
<style media="print">@page {margin-bottom: 0mm;margin-top: 0mm}/*@page {*//* size: auto; !* auto is the initial value *!*//* margin: 0mm; !* this affects the margin in the printer settings *!*//*}*/.noprint {display: none;}
</style>// 页面打印
function doPrint() {let bdhtml = window.document.body.innerHTML;// 设置打印页面内容window.document.body.innerHTML = bdhtml;if (getExplorer() == "IE") {pagesetup_null();}window.print();
}// 获取浏览器类型
function getExplorer() {let explorer = window.navigator.userAgent;//ieif (explorer.indexOf("MSIE") >= 0) {return "IE";}//firefoxelse if (explorer.indexOf("Firefox") >= 0) {return "Firefox";}//Chromeelse if (explorer.indexOf("Chrome") >= 0) {return "Chrome";}//Operaelse if (explorer.indexOf("Opera") >= 0) {return "Opera";}//Safarielse if (explorer.indexOf("Safari") >= 0) {return "Safari";}
}// 设置去除页眉页脚
function pagesetup_null() {let hkey_root, hkey_path, hkey_key;hkey_root = "HKEY_CURRENT_USER";hkey_path = "\\Software\\Microsoft\\Internet Explorer\\PageSetup\\";try {let RegWsh = new ActiveXObject("WScript.Shell");hkey_key = "header";RegWsh.RegWrite(hkey_root + hkey_path + hkey_key, "");hkey_key = "footer";RegWsh.RegWrite(hkey_root + hkey_path + hkey_key, "");} catch (e) {}
}
打印页面中特定内容:
// 需要打印的页面内容
<div class=""><!--startprint--><img src="${ctx}/management/v1/minio/file/view?path=${outBarnCertQuery.outCertPicUrl}"><!--endprint-->
</div>// 指定部分内容打印
function doPrint() {let bdhtml = window.document.body.innerHTML;// 用于截断字符串的内容,截取到指定的图片内容了let sprnstr = "<!--startprint-->";let eprnstr = "<!--endprint-->";let prnhtml = bdhtml.substr(bdhtml.indexOf(sprnstr) + 17);prnhtml = prnhtml.substring(0, prnhtml.indexOf(eprnstr));
// let printContent = $("#printConent")[0].innerHTML; //利用jquery获取打印内容;
// window.document.body.innerHTML = printContent;// 设置打印页面内容window.document.body.innerHTML = prnhtml;if (getExplorer() == "IE") {pagesetup_null();}window.print();// 还原原有页面内容window.document.body.innerHTML = bdhtml;
}
参考链接:
window.print():去除页眉页脚及网址.
三、Form 页面
1. 单列页面
a) label 和控件在一行
// 全部用 col-xs-*
<div class="row"><div class="col-xs-12"><div class="form-group"><label class="control-label col-xs-2" title=""><span class="required ">*</span> ${text('编码')}:<i class="fa icon-question hide"></i></label><div class="col-xs-10"><#form:input path="code" maxlength="30" class="form-control required"/></div></div></div>
</div>
b) 底部按钮与编辑框右对齐
// 使用 pull-right,再用 pr 或 mr 调节
<div class="row pr10"><div class="pull-right mr5"><button type="submit" class="btn btn-sm btn-primary" id="btnSubmit"><i class="fa fa-check"></i> ${text('保 存')}</button>;<button type="button" class="btn btn-sm btn-default" id="btnCancel" onclick="closeCurrentLayer()"><i class="fa fa-reply-all"></i> ${text('关 闭')}</button></div>
</div>
2. 参数控制
a) 参数模板控制
// controller
@RequiresPermissions("management:baseinfo:enterprise:view")
@RequestMapping(value = "form")
public String form(Enterprise enterprise, Model model) {enterprise.setIsEnabled(1L);if (StringUtils.isBlank(enterprise.getEnterpriseId())) {model.addAttribute("operation", "0");} else {model.addAttribute("operation", "1");}model.addAttribute("enterprise", enterprise);return "modules/management/baseinfo/mgtEnterprise/enterpriseForm";
}
// form.html
<div class="col-xs-9"><% if(operation != "0"){ %><#form:input path="creditCode" readonly="true" maxlength="20" class="form-control required"/><% }else{ %><#form:input path="creditCode" maxlength="20" onblur="checkCreditCode()" class="form-control required"/><% } %>
</div>
b) 利用实体的 isNewRecord 判断
${text(storageInPlan.isNewRecord ? '新增入库计划' : '编辑入库计划')}<% if(storageInPlan.isNewRecord){ %><div class="form-unit">${text('基本信息')}</div>
<% } %>
3. select 控件 和 input 控件同一行无法对齐
a) select 控件 和 input 控件同一行无法对齐
// 1. 在 select 控件 和 input 控件外再包一层 div.col-xs-12 ,再微调一下 margin 和 padding
<div class="col-xs-12"><div class="col-xs-6"><div class="form-group" style="margin-left: -30px;"><label class="control-label col-xs-4" title=""><span class="required ">*</span> ${text('是否有劳动能力')}:<i class="fa icon-question hide"></i></label><div class="col-xs-8"><% if (formType == "1"){ %><#form:input name="isLaborAbility" value="${regUnemployment.isLaborAbility == 0 ? '否' : '是'}" class="form-control" disabled="true"/><% } else { %><#form:select path="isLaborAbility" dictType="sys_yes_no" blankOption="true" blankOptionLabel="请选择" class="form-control"/><% } %></div></div></div><div class="col-xs-6"><div class="form-group" style="margin-left: -8px;"><label class="control-label col-xs-4" title=""><span class="required hide">*</span> ${text('专业技能证件')}:<i class="fa icon-question hide"></i></label><div class="col-xs-8 pr0"><#form:input path="skillCertName" maxlength="64" class="form-control"/></div></div></div>
</div>// 2. 设置 Select 控件的高度与 Input 控件一样
<div class="col-xs-6"><div class="form-group"><label class="control-label col-xs-4" title=""><span class="required ">*</span> ${text('业务类型')}:<i class="fa icon-question hide"></i></label><div class="col-xs-8" style="height: 30px"><#form:select path="clsInoutReasonId" items="${clsInoutReasonList!}" itemLabel="nameAbbr" itemValue="code" blankOption="true" data-placeholder="请选择" class="form-control required"/></div></div>
</div>
4. input 控件
a) input 控件中显示数组元素
// form
<div class="form-group"><label class="control-label col-xs-4" title=""><span class="required ">*</span> ${text('致残类型')}:<i class="fa icon-question hide"></i></label><div class="col-xs-8"><% var cripItems = ["其他", "视力残疾", "听力残疾", "言语残疾", "力残疾", "肢体残疾", "精神残疾", "多重残疾"]; %><% if (formType == "1"){ %><#form:input name="typeCrip" value="${cripItems[regDisabler.typeCrip]}" class="form-control required" disabled="true"/><% } else { %><#form:select path="typeCrip" dictType="crip_type" blankOption="true" blankOptionLabel="请选择" class="form-control required"/><% } %></div>
</div>
b) input 控件中显示字典中的值
// form
<div class="form-group"><label class="control-label col-xs-3" title=""><span class="required ">*</span> ${text('建筑用途')}:<i class="fa icon-question hide"></i></label><div class="col-xs-9"><% if (formType != "1"){ %><#form:select path="houseUsage" dictType="HOUSE_USAGE" blankOption="true" blankOptionLabel="请选择" class="form-control"/><% } else { %><% var tempHouseUsage2 = "商住两用"; %><% var tempHouseUsage3 = @DictUtils.getDictListJson('HOUSE_USAGE'); %><% var tempHouseUsage = @DictUtils.getDictLabel('msg_inner_content_level', '1', '普通'); %>// 注意: @DictUtils.getDictLabel 的第二个参数是String类型,传入整型会报错<#form:input name="houseUsage" value="${@DictUtils.getDictLabel('HOUSE_USAGE', resDoorAddr.houseUsage, ' ')}" class="form-control" disabled="true"/><% } %></div>
</div>
c) input 控件中自定义格式化
<#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 "/>
d) input 控件中显示单位
<div class="form-group"><label class="control-label col-xs-4" title=""><span class="required hide">*</span> 应急资金投入:<i class="fa icon-question hide"></i></label><div class="col-xs-8"><#form:input path="yjzjtr" maxlength="14" class="form-control digits"/><span style="position: absolute; top: 0; right: 15px; display: table-cell; white-space: nowrap; padding: 5px 10px;">元</span></div>
</div>
5. jQuery Validate自定义验证
// 注册验证方法
$(function(){// 身份证号码验证$.validator.addMethod("isIdCardNo", function(value, element) {return this.optional(element) || (checkIdcard(value) == 'ok');}, "请输入正确的身份证号码");
});$("#inputForm").validate({// 定义验证规则rules: {// householderIdnum : 控件ID// isIdCardNo 验证方法名,[]: 参数列表(此处为空)householderIdnum: {isIdCardNo:[]}},submitHandler: function (form) {js.ajaxSubmitForm($(form), function (data) {js.showMessage(data.message);if (data.result == Global.TRUE) {parent.refreshList();closeCurrentLayer();}}, "json");}
});
6. textarea 禁止自定义大小
// 添加 style="resize: none;"
<#form:textarea path="spYj" rows="8" maxlength="200" style="resize: none;" class="form-control"/>
7. 图片路径获取
// ${ctxStatic} 对应 resources/static 路径
// ${ctx}
// box-sizing: border-box 盒子模型:height = margin + padding + content;
<div id="alarmImageDiv" style="width: 100%; border: #e7e7e7 solid 1px; padding: 10px; box-sizing: border-box;" ><img id="alarmImageBox" style="width: 100%;" src="${ctxStatic}/images/videoAlarm/personIn.png" alt="">
</div>
8. div onresize事件
// 在监控的过程中发现每次改变浏览器窗口的时候 onresize 事件都会触发两次(产生 的原因貌似比较复杂,网上没有定论,发现在最大化浏览器的时候,浏览器也会闪一下,有两次窗口大小的改变)。
// 解决方法: setTimeout()
// 解决触发两次的情况,实际浏览器的 resize 事件可能会触发 n 次,持续时间并不一定是 100 毫秒,例如用户拖动浏览器的边框,以下代码会执行多次 callback 事件;
$(function () {window.onresize = function () {var target = this;if (target.resizeFlag) {clearTimeout(target.resizeFlag);}target.resizeFlag = setTimeout(function() {resizeWidget();target.resizeFlag = null;}, 800);}
});// gridData 控件调整大小有延时,设置一定的时间间隔才能获取到最新的宽高
function resizeWidget() {$('#alarmImageDiv').height($('#gbox_dataGrid').height() - 20);
}
9. 去掉 comboTree的图标
<style>/*去掉 comboTree的图标*/.tree-folder{ width: 0px !important; }.tree-file{ width: 0px !important; }
</style>
10. jQuery validator
a) validate 表单提交前二次验证数据的合法性
// 验证数据的合法性,不合法 return false;
$("#inputForm").validate({submitHandler: function(form){let zzValue = $("#zz").val();if (zzValue == "" || zzValue == "请选择") {js.alert("请选择组长", {icon: 7});console.log(zzValue);return false;}let zgbmValue = $("#zgbmCombo").val();if (zgbmValue == "" || zgbmValue == "请选择") {js.alert("请选择主管部门", {icon: 7});console.log(zgbmValue);return false;}$('#zgbmdm').attr('disabled', false);js.ajaxSubmitForm($(form), function(data){js.showMessage(data.message);if(data.result == Global.TRUE){js.getCurrentTabPage(function(window){window.refresh()closeCurrentLayer()},false);}}, "json");}
});
b) 添加自定义校验
// 中文字两个字节
jQuery.validator.addMethod("byteRangeLength", function(value, element, param) {var length = value.length;for(var i = 0; i < value.length; i++){if(value.charCodeAt(i) > 127){length++;}}return this.optional(element) || ( length >= param[0] && length <= param[1] );
}, $.validator.format("请确保输入的值在{0}-{1}个字节之间(一个中文字算2个字节)"));// 实用工具:用参数代替模板中的 {n}。
jQuery.format(template,argument,argumentN...)// 邮政编码验证
jQuery.validator.addMethod("isZipCode", function(value, element) { var tel = /^[0-9]{6}$/;return this.optional(element) || (tel.test(value));
}, "请正确填写您的邮政编码");// 固话和手机号码验证
$.validator.addMethod("telOrMobile", function(value, element) {var tel = /^(((\d{3,4}-?)?[0-9]{7,8})|(1(3|4|5|6|7|8|9)\d{9}))$/g;return this.optional(element) || (tel.test(value));
}, $.validator.messages.phone);
11. 输入范围在 {0} 到 {1} 之间的数值
// 输入范围在 0 到 9999.999999 之间的数值;
<#form:input path="safetyReserve" maxlength="11" type="number" min="0" max="9999.999999" style="width:173px" class="form-control required number"/>
12. 强行将字段更新为 null
// 增加 isUpdateForce = true
@Column(name="parent_id", attrName="parentId", label="父节点", comment="父节点", isUpdateForce = true),
13. 传到后端的值中多了逗号 “,”
// 问题原因: 表单中存在重名的控件
14. 刷新 list 页面
// 1. 通过 iframe 的name 属性获取对应的 window对象
<iframe id="storageInPlanListIframe" name="storageInPlanListIframe" class="ui-layout-content p0 b0 " src="${ctx}/plan/storageInPlan/list"></iframe>
js.getCurrentTabPage(function(contentWindow){try {contentWindow.storageInPlanListIframe.refresh();} catch (e) {console.log("reloadList error: ", e);}
});// 2.
js.getCurrentTabPage(function (contentWindow){let dom = contentWindow.document.getElementById("mainIframe").contentWindowupdateDataGrid(dom.$("#dataGrid"),data.data);
});// 3.
js.closeCurrentTabPage(function(contentWindow){contentWindow[0].$('#dataGrid').dataGrid('refresh');closeCurrentLayer();
});
四、DataGrid
1. 禁止拖拽表格列头
// 初始化DataGrid对象
$('#dataGrid').dataGrid({searchForm: $("#searchForm"),showRownum: false, // 是否显示行号frozenCols: true, // 禁止拖拽表格列头sortableColumn: false, // 是否允许列排序columnModel: []});
2. 多次表头出现多出一列
// 1. 设置 css 强调把多出的一列高度设置为 0
<style>/*.jqg-first-row-header {display: none !important;}*/.ui-jqgrid-hbox tr {height: 0px !important;}
</style>// 初始化DataGrid对象
$('#dataGrid').dataGrid({searchForm: $("#searchForm"),columnModel: [],// 2. 设置多级表头groupHeaders: {twoLevel:[{startColumnName: 'dateUnemp', numberOfColumns: 8, titleText: '失业信息'},{startColumnName: 'isReEmp', numberOfColumns: 8, titleText: '再就业信息'}]},});
3. action 图标对齐
// 新增一个隐藏的图标
actions.push('<a href="javascript:0" title="${text(' ')}" style="visibility: hidden;"><i class="fa fa-eye"></i></a> ');
4. 最小高度设置 options.gridMinMeight
统一上下结构列表的样式:
- 上下结构的列表页, 下方Pannel高度统一:
带分页控件的,高度350px,
不带分页控件的,高度300px - 下方Panel内,dataGrid设置属性 gridMinMeight: 150
// 统一上下结构列表的样式
// 1. 布局 south__size: '350'
$('body').layout({south__size: '350',south__closable: false,south__onresize: function () {// 调整iframe的高度var height = $("#parent").height();$('#emerPersonFrame').height(height - 32);}
});// 2. Datagrid 最小高度设置: gridMinMeight: 150
// 初始化DataGrid对象
$('#dataGrid').dataGrid({searchForm: $("#searchForm"),showRownum: false, // 列排序resizable: true, // 列宽固定shrinkToFit: true,sortableColumn: false,gridMinMeight: 150,columnModel: [{header:'<span class="col-align-left">人员姓名</span>', name:'xm', index:'a.xm', width:150, align:"left"},],// 加载成功后执行事件ajaxSuccess: function(data){}
});
5. 下载文件处理
// dataGrid
actions.push('<a οnclick="downloadFile('+"'"+row.emerDealArchivesId+"'"+');" title="${text('下载资料')}"><i class="fa fa-download"></i></a> ');// javascript
function downloadFile(emerDealArchivesId) {js.ajaxSubmitForm($('#searchForm'), {url:'${ctx}/biz/emer_deal/emerDealArchives/downFile?emerDealArchivesId='+emerDealArchivesId,callback:function (data){// 失败提示if(data.result == Global.FALSE){js.showMessage(data.message);}},downloadFile:true});
}
五、jQuery 应用
1. 属性选择器处理按钮
//刷新按钮触发事件
function refresh(){$('button[type=submit]').click();
}
2. SELECT 控件操作
// 遍历所有选项
$('#parentCode option').each(function () {console.log($(this).val());
})// 默认选中项
$('#parentCode').val("654023101").select2();// 打印选中选项
console.log($("#parentCode").find("option:selected").text());;// data-ajax select 设置默认值
<#form:select path="transport"
data-ajax--url="${ctx}/biz/inv_manager/inventoryOutEmergency/queryResCar"
data-ajax--delay="500"
blankOption="true" data-placeholder="请输入车牌号"
class="form-control"/>$('#transport').select2({data:[{id: data.numberCar, text: data.numberCar}]}).val(data.numberCar).select2();
3. ajax 请求数据
a) 415 错误
// 解决:
// 前端:
// contentType 与 data 都设置为JSON
// contentType: 'application/json; charset=UTF-8'
// JSON.stringify(data)
$.ajax({type: "post",async: false,url: "${ctx}/emer_manager/emerPlanEnact/saveSelectEmerEvent",contentType: 'application/json; charset=UTF-8',data: JSON.stringify(data),dataType: "json",success: function (msg) {console.log(msg);},error: function (obj) {js.alert('系统发生异常!');}
});// 后台:
// 参数列表中加入@RequestBody注解/*** 保存应急事件数据* url: "${ctx}/emer_manager/emerPlanEnact/saveSelectEmerEvent"* param: emerEventId* return: EmerPlan*/
@RequiresPermissions("emer_manager:emerPlanEnact:edit")
@PostMapping(value = "saveSelectEmerEvent")
@ResponseBody
public String saveSelectEmerEvent(@RequestBody EmerEvent emerEvent) {
}
参考链接:
415错误及解决方法.
[Resolved org.springframework.web.HttpMediaTypeNotSupportedException: Content type.
六、IDEA 配置
1. 手动加的 lib 加入到 git
// 问题描述:
[ERROR] Failed to execute goal on project jeesite-cloud-module-management: Could not resolve dependencies for project com.jeesite:jeesite-cloud-module-management:war:4.3.3-SNAPSHOT: Could not find artifact aspose.words:aspose-words:jar:15.8.0 at specified path /home/tfs-agent/_work/2/s/modules/management/management/src/main/webapp/WEB-INF/lib/aspose-words-15.8.0.jar// 解决方案:
// 1. 打开 .gitignore
// 2. 在最后新增一行
!**/webapp/WEB-INF/lib/*.jar
2. 快速查找和定位文件位置
3. run application报错
a) 报错信息:Error running Application. Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun.
解决:
方案一:
方案二:
全局设置
由于方案一是当前项目设置,其他项目打开又没有了,所以可以设置全局,点击File→New Projects Settings→Run Configuration Templates for New Projects
点击springboot项目,跟方案一的配置一样。
参考链接:
IDEA报错Command line is too long.
IDEA报错Command line is too long.
4. DashBoard/ Services不显示端口号
解决方案:
打开启动项管理,把Enable JMX agent复选框选中,重新启动对应服务即可显示端口号。(IDEA 版本:2021.3.1)
5. 底部显示 service 窗口
a) View => Tool Windows => Service (快捷键: Alt + 8)
b) Service 窗口点 " + " 按钮 => Run Configuration Type +. Spring Boot
6. 快捷键
// 1. Surround with
CTRL+ALT+T
// eg.
//region Description
//endregion// 2. 生成变量
CTRL+ALT+V
七、修改 JeeSite内置页面
1. 修改登录页面
a) 禁止登录页面出现滚动条
// 以下配置会出现纵向滚动条
/*.login-page {*/
/* background-image: url(${ctxStatic}/themes/login/bg.png);*/
/* background-size: 100% 100%;*/
/* background-repeat: no-repeat;*/
/* color: #FFFFFF;*/
/*}*/.login-page {min-height: 500px;background-image: url(${ctxStatic}/themes/login/bg.png);background-position: center center;background-repeat: no-repeat; /*background-attachment: fixed;*/ /* 底图固定:不随滚动条的滚动而滚动*//*background-size: cover;*/overflow: hidden; /* 设置禁止出现滚动条 */
}
八、权限配置
1. 无需登录直接访问 url
需求:通过 http://localhost:8980/js/a/track/home/homeIndex 就可以直接打开首页。
注意点:通过 nacos 配置对应模块下的 jeesite-cloud-module-track.yml
# URI 权限过滤器定义(自定义添加参数时,请不要移除 ${adminPath}/** = user,否则会导致权限异常)# 提示:填写过滤规则,请注意先后顺序,从上到下,先匹配先受用规则,匹配成功后不再继续匹配。filterChainDefinitions: |# 过滤掉这些接口(anno表示可匿名使用,可以理解为匿名用户或游客,即不登录就可以访问这个接口)${adminPath}/track/home/** = anon/inner/api/** = inner/api/** = user${adminPath}/** = user# # URI 权限过滤器定义(以下参考,必须登录user可访问的地址和不需要登录anon可访问地址)
# filterChainDefinitions: |
# /ReportServer/** = user
# ${adminPath}/file/** = anon
# ${adminPath}/cms/* = anon
# ${adminPath}/cms/site/select = anon
# ${adminPath}/cms/site/* = anon
# ${adminPath}/cms/category/treeData = anon
# ${adminPath}/cms/category/* = anon
# ${adminPath}/cms/article/* = anon
# ${adminPath}/cms/link/* = anon
# ${adminPath}/sys/corpAdmin/treeData = anon
# ${adminPath}/${spring.application.name}/swagger/** = anon
# ${adminPath}/** = user
案例:
// 1. Nacos 的 jeesite-cloud-module-management.yml 增加
#Shiro 相关配置
shiro:# URI 权限过滤器定义filterChainDefinitions: |${adminPath}/management/inoutsupervise/outBarnCertQuery/** = anon/inner/api/** = inner/api/** = user${adminPath}/** = user// 2. Controller 增加映射
// @RequiresPermissions("management:inoutsupervise:outBarnCertQuery:view") // 去掉权限@RequestMapping(value = {"mIndex", ""})public String mIndex(OutBarnCertQuery outBarnCertQuery, Model model) {model.addAttribute("outBarnCertQuery", outBarnCertQuery);return "modules/management/inoutsupervise/outBarnCert/mIndex";}// 3. 访问方式
http://localhost:8980/js/a/management/inoutsupervise/outBarnCertQuery/mIndex
九、Beetl
1. 注意点
a) 需要知道Java集合,数组长度,统一用虚拟属性~size来表示
// 需要知道Java集合,数组长度,统一用虚拟属性~size来表示
var list=[1,2,3];
var size = list.~size
b) for-in循环
// 1.
<%for(user in userList){print(userLP.index);print(user.name);}
%>
//第三行代码 userLP是Beetl隐含定义的变量,是一个ILoopStatus实例,能在循环体内使用。其命名规范是item名称后加上LP,他提供了当前循环的信息,如// - **userLP.index **当前的索引,从1开始
// - userLP.dataIndex 索引,从0开始
// - **userLP.size **集合的长度
// - userLP.first 是否是第一个
// - userLP.last 是否是最后一个
// - userLP.even 索引是否是偶数
// - userLP.odd 索引是否是奇数// 2.
// 对于渲染逻辑更为常见的是经典的for循环语句
<%
var a = [1,2,3];
// a.~size 是集合的大小,beetl 中的虚拟属性
for(var i=0;i<a.~size;i++){print(a[i]);
}
%>// 3.
// 不同于通常程序语言,如果没有进入循环体,则不需额外的处理,模板渲染逻辑更常见情况是如果没有进入循环体,还需要做点什么,因此,对于for循环来说,还有elsefor 用来表达如果循环体没有进入,则执行elsefor 后的语句
<%
var list = [];
for(item in list){}elsefor{print("未有记录");
}
%>
c) 安全输出
模板中还有两种情况会导致模板输出异常
- 有时候模板变量并不存在,这时候必须报错,如果简单忽略不输出(Velocity就是这样),很容易留坑
- 模板变量为null,但输出的是此变量的一个属性,如 ${user.wife.name}
// 安全输出指示符号: !
// 可以在!后增加一个常量(字符串,数字类型等),或者另外一个变量,方法,本地调用,作为默认输出,譬如:
// 如果user为null,或者user.wife为null,或者user.wife.name为null,输出单身
${user.wife.name!"单身"}// 表示如果user为null,或者user. birthday为null,输出 System.constants.DefaultBir
${user.birthday!@System.constants.DefaultBir}
d) 调用Java方法与属性
可以通过符号@来表明后面表达式调用是java风格,可以调用对象的方法,属性
${@user.getMaxFriend(“lucy”)}
${@user.maxFriend[0].getName()}
${@com.xxxx.constants.Order.getMaxNum()}
// 内部类(包括枚举)访问同java一样,如User类有个内部枚举类Gender,访问是User$Gender
${@com.xxxx.User$Gender.MAN}
<%
var max = @com.xxxx.constants.Order.MAX_NUM;
var c =1;
var d = @user.getWife(c).getName();
%>
十、不同窗口之间交互
a) 三层及以上窗口交互:通过当前 layer 向上一层 layer 传递数据,窗口层次关系如下图:
// 方案一:利用 parent.window 获取目标窗口
// 调试技巧,在 F12调试窗口的控制台中输入 parent查看,在目标中添加类似aaaPlanEmerForm的function方便确认是否是目标窗口
parent.window[0].aaaPlanEmerForm();// 方案二:利用 parent.layer
var index = parent.layer.getFrameIndex("layui-layer-iframe1");
var body = parent.layer.getChildFrame('body', index);
body.children().find('#xzcy').val('小组成员赋值'); // 小组成员赋值%>
b) 同一 Tab 下的不同 window 之间交互,窗口之间的关系如下图:
// 1:获取 currentTabWindow,保存各窗口引用
// xxx1.html
let currentTabWindow;
js.getCurrentTabPage(function (w) {// 将当前 window 保存到 currentTabWindow的属性中,这样就可以在同tab 的其他window中访问w.mainListWindow = window;currentTabWindow = w;
});// xxx2.html
let currentTabWindow;
js.getCurrentTabPage(function (w) {w.listWindow = window;currentTabWindow = w;
});// 2:利用 currentTabWindow 保存的窗口引用操作相应窗口
onSelectRow: function(id, isSelect, event) {let rowData =$('#dataGrid').dataGrid('getRowData', id);let mainListWindow = currentTabWindow.mainListWindow;let listWindow = currentTabWindow.listWindow;console.log("currentTabWindow = ", currentTabWindow);console.log("mainListWindow = ", mainListWindow);console.log("listWindow = ", listWindow);
},
%>
十一、使用经验总结:
1. 查看表单中的控件禁用:
// planEmerForm.html
$(function () {$('#isEnabled').select2({minimumResultsForSearch: -1});if ($('#zt').val() != "新的") {$('#inputForm *').attr('disabled', true);$('#btnSubmit').css('display', 'none');$('#btnCancel').attr('disabled', false);$('#zgbmCombo').combotree('disable');}
});
2. ajax 请求:
a) JQuery:
// 使用示例
$.ajax({type: "get",async: false,url: "${ctx}/biz/emerManager/emerPlan/getEmerPersonList",data: {'emerOrgId': emerOrgId},dataType: "json",success: function (msg) {console.log(msg);},error: function (obj) {js.alert('系统发生异常!');}
});
b) JeeSite:
/*** AJAX 提交* @param urlOrOpt 请求地址,或 AJAX 的选项(Opt为4.2.0新增)* @param data 请求参数* @param callback 请求 AJAX 后的回调方法* @param dataType 返回数据类型(默认JSON)* @param async 是否异步(默认true)* @param message 调用 js.loading(message) 的提示信息。* @usage js.ajaxSubmit('/js/a/index', function(data){ log(data) })* @usage js.ajaxSubmit('/js/a/index', {param: 1}, function(data){ log(data) })* @usage js.ajaxSubmit('/js/a/index', {param: 1}, function(data){ log(data) },'json', true, '正在获取数据...')* @usage js.ajaxSubmit({url: '/js/a/index', data: {id: '123', name: '456'}, callback: function(data){ log(data) }, dataType: 'json',async: true, message: '正在获取数据...'});*/
js.ajaxSubmit(urlOrOpt, data, callback, dataType, async, message);
3. DataGrid 中 Action 按钮操作方式
// <a> + href=url
actions.push('<a href="${ctx}/biz/emer_manager/emerEvent/delete?emerEventId='+row.emerEventId+'" class="btnList" title="${text('删除应急事件信息')}" data-confirm="${text('确认要删除该应急事件信息吗?')}"><i class="fa fa-trash-o"></i></a> ');
// <a> + οnclick=fun()
actions.push('<a οnclick="addOrEditForm('+"'"+row.emerEventId+"'"+')" title="${text('编辑应急事件信息')}"><i class="fa fa-pencil"></i></a> ');
// <a> + href=javascript:fun()
actions.push('<a href="javascript:lookForm('+ "'" + row.emerEventId + "'" + ')" title="${text('查看应急事件信息')}"><i class="fa fa-eye"></i></a> ');
4. js.getCurrentTabPage 打开新页面窗口回调
// innerCallback 回调
// 获取百度点坐标
function getPoint(){var jd = $("#jd").val();var wd = $("#wd").val();var dtlAddress = $("#dtlAddress").val();var url = '${ctxPath}/biz/commonunit/baiduMapPoint';if(isDefine(jd) && isDefine(wd)){url = url+"?longitude="+jd+"&latitude="+wd+"&address="+dtlAddress;}js.getCurrentTabPage(function (contentWindow) {contentWindow.layer.open({type: 2,title: '获取经纬度及地址',maxmin: false,resize :false,scrollbar: false,area: ['1000px', '705px'],content: [url, 'no'],innerCallback: function(index, layero, data){if(typeof mapPointCallback == 'function'){mapPointCallback(data);}return true;}});});
}
5. 文本中加入汉字空格
// 英文空格:
// 汉字空格:  
<a href="#tabOther" aria-controls="tabOther" role="tab" data-toggle="tab"> 其他 </a>
n. temp
// Hello world
console.log("Hello world!");
十二、JavaScript 操作DOM:
1. 向 document中手动添加 style:
// mobilizationCapability/index.vue
// document中 append sytle
var style = this.$refs.mapcontainer.contentWindow.document.createElement("style");
style.type = "text/css";
style.innerHTML =".custom-popup { width: 100%; height: 100%; padding: 5px; color: white; font-size: 16px; text-align: left; } .custom-popup2 { width: 100%; height: 100%; padding: 5px; color: yellow; font-size: 14px; text-align: left; }";
this.$refs.mapcontainer.contentWindow.document.getElementsByTagName("head").item(0).appendChild(style);// 使用
let pointid = this.mapEdit.addpoint(res,icon,{content: `<div class="custom-popup2"><div class="custom-popup">${res.ssqymc}</div><div>储备能力:200吨</div><div>储备物资:100吨</div><div>日生产能力:15吨</div><div>日加工能力:20吨</div><div>日配送能力:60吨</div><div>配送车辆数:5辆</div><div>响应能力:2小时</div></div>`,},)
十三、调试技巧:
1. 跟踪前端底层代码:
十四、DataGrid:
1. 同一页面根据 url 参数不同显示内容不同:
// url 配置:
// 登记 url:/biz/inv_manager/inventoryIn/index
// 审核 url:/biz/inv_manager/inventoryIn/index?type=submit
// index 页面中:
<iframe id="inventoryInMainFrame" name="inventoryInMainFrame"class="ui-layout-content p0"src="${ctx}/biz/inv_manager/inventoryIn/list?type=${parameter.type}"
></iframe>
// DataGrid
{header:'${text(" ")}', name:'actions', width:('${parameter.type}' == 'submit' ? 58 : 102), align: 'right', fixed:true, sortable:false, title:false, frozen: true,formatter: function(val, obj, row, act){var actions = [];if(row.statusIo=="待入库"){//<% if(hasPermi('inv_manager:inventoryIn:edit') && parameter.type != 'submit'){ %>actions.push('<a href="javascript:addOrEditForm('+ "'" + row.ivyInoutDtlId + "'" + ')" title="${text("编辑日常入库信息")}"><i class="fa fa-pencil"></i></a> ');actions.push('<a href="${ctx}/biz/inv_manager/inventoryIn/del?ivyInoutDtlId='+row.ivyInoutDtlId+'" class="btnList" title="${text("删除日常入库信息")}" data-confirm="${text("确认要删除该日常入库信息吗?")}"><i class="fa fa-trash-o"></i></a> ');actions.push('<a href="javascript:chouyang('+ "'" + row.ivyInoutDtlId + "'" + ')" title="${text("生成样品")}"><i class="fa fa-bitbucket"></i></a> ');//<% } %>//<% if(hasPermi('inv_manager:inventoryIn:check') && parameter.type == 'submit'){ %>actions.push('<a href="javascript:checkFileSample('+ "'" + row.ivyInoutDtlId + "'" + ')" title="${text("提交日常入库信息")}"><i class="fa fa-check"></i></a> ');//<% } %>}actions.push('<a href="javascript:viewForm('+ "'" + row.ivyInoutDtlId + "'"+')" title="${text("查看日常入库信息")}"><i class="fa fa-eye"></i></a> ');return actions.join('');
}},
十五、自动生成:
1. 新增/修改 表单 自动生成 详设文档:
// 打印文档
$(document).ready(function(){var regArray = ['email', 'mobile', 'phone', 'contactPhone', 'simplePhone', 'zipCode', 'idcard'];var ctlList = [];$('#inputForm label').each(function () {ctlList.push({label: $(this).text().trim().replace('* ', '')});});// console.log(ctlList);var ctlList2 = [];$('#inputForm input, #inputForm select').each(function () {if ($(this).attr('type') != 'hidden') {var maxlength = $(this).attr('maxlength');var isReg = false;for (let i = 0; i < regArray.length; i++) {if ($(this).hasClass(regArray[i])) {isReg = true;break;}}var bSelectCtl = false;if ($(this).is('select')) {bSelectCtl = true;}if ($(this).attr('id') != 'cntUnitName' && $(this).attr('id') != 'weightUnitName') {ctlList2.push({id: $(this).attr('id'),maxlength: (maxlength != undefined ? ',长度'+maxlength+'位':''),required: ($(this).hasClass('required') ? '必填' : '选填'),bSelectCtl: (bSelectCtl ? ',下拉列表' : ''),isReg: (isReg ? ',使用正则校验':'')});}}});// console.log(ctlList2);if (ctlList.length != ctlList2.length) {console.log("两个数组长度不一样,请手工核验!");}for (let i = 0; i < ctlList.length; i++) {var output = i+1 + '. ' + ctlList[i].label + ctlList2[i].required + ctlList2[i].bSelectCtl + ctlList2[i].maxlength + ctlList2[i].isReg;if (i == ctlList.length-1) output = output + '。'else output = output + ';'console.log(output);}});
JeeSite 框架学习笔记相关推荐
- SpringMVC框架--学习笔记(下)
接上篇:SpirngMVC框架--学习笔记(上):https://blog.csdn.net/a745233700/article/details/81038382 17.全局异常处理: 系统中异常包 ...
- SpringMVC框架--学习笔记(上)
1.SpringMVC入门程序: (1)导入jar包:spring核心jar包.spring-webmvc整合Jar包 (2)配置前端控制器:web.xml文件中 <?xml version=& ...
- mybatis框架--学习笔记(下)
上篇:mybatis框架--学习笔记(上):https://blog.csdn.net/a745233700/article/details/81034021 8.高级映射: (1)一对一查询: ①使 ...
- mybatis框架--学习笔记(上)
使用JDBC操作数据库的问题总结: (1)数据库连接,使用时创建,不使用时立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能. 设想:使用数据库连接池管理数据库连接. (2) ...
- JavaSE中Map框架学习笔记
前言:最近几天都在生病,退烧之后身体虚弱.头疼.在床上躺了几天,什么事情都干不了.接下来这段时间,要好好加快进度才好. 前面用了三篇文章的篇幅学习了Collection框架的相关内容,而Map框架相对 ...
- python表单提交的两种方式_Flask框架学习笔记之表单基础介绍与表单提交方式
本文实例讲述了Flask框架学习笔记之表单基础介绍与表单提交方式.分享给大家供大家参考,具体如下: 表单介绍 表单是HTML页面中负责数据采集功能的部件.由表单标签,表单域和表单按钮组成.通过表单,将 ...
- php框架费尔康,GitHub - majixian/study-phalcon: phalcon(费尔康)框架学习笔记
phalcon(费尔康)框架学习笔记 以实例程序invo为例(invo程序放在网站根目录下的invo文件夹里,推荐php版本>=5.4) 环境不支持伪静态网址时的配置 第一步: 在app\con ...
- [Spring+SpringMVC+Mybatis]框架学习笔记(四):Spring实现AOP
上一章:[Spring+SpringMVC+Mybatis]框架学习笔记(三):Spring实现JDBC 下一章:[Spring+SpringMVC+Mybatis]框架学习笔记(五):SpringA ...
- Samza框架-----学习笔记
Samza框架-----学习笔记 基本概念: 作业:是对一组输入流进行处理转化成输出流的程序. 分区: Samza的流数据单位既不是Storm中的元组,也不是Spark Streaming中的DStr ...
最新文章
- 优化营商环境建议个人_优化营商环境的几点建议(三)
- 6次课(相对和绝对路径、cd命令、创建和删除目录mkdir/rmdir、rm命令)
- Linux: grep命令
- 中学计算机老师 当领导可能性,求分享,当中学计算机老师带信息学奥赛是怎样的感受 - 信息科学技术学院(EECS)版 - 北大未名BBS...
- HTML5 兼容IE浏览器
- java ee junit_JavaEE——Junit
- ffmpeg windows版本交叉编译方法
- 【自动化测试】在做自动化测试之前你需要知道的
- 各类推荐算法图表详解
- Assetbundle coustomerScripts
- 深入剖析Redis主从复制
- EasyAr聚焦模式
- 将WinPE安装至硬盘
- 计算机网络第七版笔记--第一章
- 怎样用c语言编程解多元方程组,求用C#编程实现:求一个多元一次方程组解
- [机器学习笔记] 什么是经验风险?什么是结构风险?
- mysql重启后应用也要重启_数据库重启后应用也必须重启
- AcWing算法基础课 第一讲小结(持续更新中)
- 【Three.js:3D模型】常用建模软件
- 北航计算机学院的博士待遇,北航博士毕业留校让人寒心的工资
热门文章
- <audio>播放音频Chrome浏览器禁止自动播放问题 play() failed because the user didn‘t interact with the document first
- PX4实战之旅(三):通过OFFBOARD模式控制无人机自主飞行
- Nagios配置文件介绍
- 解读苹果新财报:iPhone销量回暖实现逆增长,苹果再唱高歌?
- excel-文本函数
- code128 java_如何使用Code128字体将文本转换为code128条形码
- gulp-前端打包工具
- java安装界面 问号_win7系统打开软件安装界面全部都是问号的解决方法
- DirectUI浅谈
- 抖音上纸短情长音符用计算机打de,抖音纸短情长怎么录-抖音纸短情长怎么制作-PC6教学视频...