请假单模块开发示例、请假单模块开发过程演示


1. 后端开发过程 - 演示


1.1 演示代码存放位置说明

    存放位置说明:  直接在javamis-web工程下编写您自己的业务代码,本模块因为是作为演示使用,所以创建了"demo"目录,代码将写在demo目录下的各各目录下,比如:

  • controller层代码写于:javamis-web/src/main/java/com/javamis/modular/demo/controller目录下
  • service层代码写于:javamis-web/src/main/java/com/javamis/modular/demo/service目录下
  • entity层代码写于:javamis-web/src/main/java/com/javamis/modular/demo/entity目录下
  • dao层代码写于:javamis-web/src/main/java/com/javamis/modular/demo/dao目录下

      温馨提示1:演示代码目前暂放在新创建的demo目录下,您如果不再需要演示代码作为参考,可将demo目录删除即可!  您真正开发的业务代码请放在business目录下。

      温馨提示2:本次是以开发 <小型业务系统>作为行演示对象;大型业务系统的开发和创建包结构也是一样的,只是需要单独创建一个或多个工程,然后被javamis-parent管理,同时被javamis-web引入,详细请参照: <后端-开发规范>章节~



    ★代码开发技巧★:  

  • 首先,复制javamis-core工程下的dao、controller相关类 至 javamis-web工程下的demo目录下。
  • 然后,重命名复制过来的类,如:AbsentMapper.java、AbsentController.java
  • 最后,替换相应的参数和实体类即可,因为新增/更新/修改/删除/查询都是通用的写法~

1.2 演示代码存放位置目录

(图-1:演示后端代码目录说明)

1.3 实体层代码

AssStorage.java

														
@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("sys_leave") public class Absent extends Flowable implements Serializable { /** * 主键id */ private String id; /** * 请假类型(公休、病假、事假、调休、婚假) */ private String type; /** * 请假天数 */ @TableField(value = "days") private Integer days; .............................. /** * @description 设置检索条件数据 * @param leave 请假类 * @return */ public Map setData(Absent leave){ Map queryMap = new HashMap<>(); if(!"0".equals(leave.getType())&&!"".equals(leave.getType()) && leave.getType() !=null) { queryMap.put("type", leave.getType()); }if(leave.getDays() !=null&&leave.getDays()!=0) { queryMap.put("days", leave.getDays()); }if(leave.getReason() !="" && leave.getReason() !=null) { queryMap.put("reason", leave.getReason()); }if(leave.getLeaderOpinion() !="" && leave.getLeaderOpinion() !=null) { queryMap.put("leaderOpinion", leave.getLeaderOpinion()); }if(leave.getStatus() !=null) { queryMap.put("status", leave.getStatus()); } return queryMap; } }

代码开发说明:  

  • 继承Flowable类:因为请假单业务需要使用工作流,所以继承 Flowable.java类; 如果您的业务不涉及工作流,无需继承;无工作流请参考:User.java
  • @TableName("sys_leave"):表示实体类对应的数据表的名称是"sys_leave";
  • @TableField(value = "xxx"): 表示数据表"sys_leave"的非主键字段;
  • Integer:属性是数值类型,请使用Integer类型,尽量不使用int类型,因为Integer无值时默认为null,比较容易统一判断。


1.4 dao层代码

AbsentMapper.java

														
public interface AbsentMapper extends BaseMapper { }

代码开发说明:  

  • 继承BaseMapper接口:泛型参数传对应的Absent实体类;所有dao层接口都需要继承BaseMapper接口 ;


1.5 service接口层代码

AbsentService.java

														
public interface AbsentService extends IService<Absent>{ /** * @name 重新封装标题内容;将流程定义、流程实例封装到分页列表数据集中 * @param params 封装后的分页列表数据 * @return 封装后的分页列表数据集 */ public List<Absent> listData(List<Absent> absentLists); /** * @name 启动流程 * @param absent 请假单实体 * @param flowable 流程实体 */ public Message<String> save(Absent absent,Flowable flowable); /** * @name 封装必要的参数 * @param absent 请假单 * @return 流程实例 */ public Absent edit(Absent absent); /** * @name 审批流程 * @param isAgree 审批时,是否同意 */ public void edit(Absent absent,Integer isAgree); }

代码开发说明:  

  • 继承IService接口:泛型参数传对应的Absent实体类;所有接口层接口都需要继承BaseMapper接口;
  • 类命名规则:xxxService;
  • 方法命名规则:尽量与controller层方法同名;


1.6 service接口实现层代码

AbsentServiceImpl.java

														
@Service public class AbsentServiceImpl extends ServiceImpl<AbsentMapper, Absent> implements AbsentService { @Override public List<Absent> listData(List<Absent> absentLists) { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); List<Absent> absentsWarp = new ArrayList<Absent>(); for(Absent absent: absentLists) { String titleName = absent.getTitleName(); String date = formatter.format(absent.getOperTime()); absent.setTitleName(titleName+" "+date+" 的 请假单"); FlowableMisModelForm misModelForm = flowableOfficeMapper.selectByBusinessTableId(absent.getId()); absent.setProcDefId(misModelForm.getProcessDefinitionId()); absent.setProcInsId(misModelForm.getProcessInstanceId()); if(flowTaskService.getHistoryProcIns(misModelForm.getProcessInstanceId()).getEndActivityId()!=null) { absent.setProcessIsFinished("10002");//已完结(该流程已走完所有流程的审批过程,该流程已关闭) } else { absent.setProcessIsFinished("10001");//审核中(该流程正在审核过程中) } absentsWarp.add(absent); } return absentsWarp; } @Override public Message<String> save(Absent absent,Flowable flowable) { ShiroInfo shiroInfo = getShiroInfo(); String loginCode =shiroInfo.getUserCode(); // 初次-发起流程 if (StringUtils.isBlank(flowable.getBusinessId())) { String modelKey = "leave-2020";//模型key ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(modelKey).latestVersion().singleResult(); flowable.setFormId(absent.getId()); FlowFormBusiness formBusiness = new FlowFormBusiness(flowable.getFormId()); formBusiness.preInsert(); String procIns=""; Map<String, Object> variables1 = new LinkedHashMap<>(); try { FlowableStartProcessInstance spiv = new FlowableStartProcessInstance(); spiv.setProcessDefinitionKey(modelKey); spiv.setBusinessKey(UUIDUtils.counter()); String leaveId = UUIDUtils.counter(); FlowableStartProcessInstance flowableStartProcessInstance = new FlowableStartProcessInstance(); flowableStartProcessInstance.setBusinessKey(leaveId); flowableStartProcessInstance.setCreator(loginCode); flowableStartProcessInstance.setCurrentUserCode(loginCode); flowableStartProcessInstance.setFormName("请假登记流程"); flowableStartProcessInstance.setProcessDefinitionKey(modelKey); flowableStartProcessInstance.setProcessDefinition(processDefinition); variables1=initLeave2020Variables(absent.getDays()); flowableStartProcessInstance.setVariables(variables1); Message<ProcessInstance> returnStart = iFlowableProcessInstanceService.startProcessInstanceByKey(flowableStartProcessInstance); if (returnStart.getCode() == 100){ procIns = returnStart.getData().getProcessInstanceId(); } }catch(Exception e) { return Message.error(500, " 流程key: "+modelKey+" 的流程以被 '挂起', 请联系管理人员恢复该工作流程! "); } // 保存流程实例关联模型版本信息 formBusiness.setProcInsId(procIns); String relationUrl = flowableModelMapper.selectImsModelByModelKey(modelKey).getFormUrl();//url数据来源于模型关联表单 String formUrl = relationUrl+"/"+absent.getId()+"?"; Map<String,Object> map = JsonTransferUtils.keyReversalValueMap(variables1); if(flowableOfficeMapper.insertImsFlowRelationTable(UUIDUtils.counter(),absent.getId(),processDefinition.getId(),procIns,modelKey,formUrl,new Date(),JsonTransferUtils.mapConvertToJson(variables1),JsonTransferUtils.mapConvertToJson(map))>0) { return Message.success("添加流程表单成功啦!"); }else { return Message.success("流程启动失败!"); } } return Message.success("流程启动成功啦!"); //提交流程-end } @Override public Absent edit(Absent leave) { if (leave.getProcInsId() != null && !leave.getStatus().equals("lookup")) { // 获取流程实例对象 ProcessInstance procIns = actTaskService.getProcIns(leave.getProcInsId());// 非发起流程 if(procIns!=null) { leave.setBusinessId(procIns.getBusinessKey()); }else { HistoricProcessInstance history = actTaskService.getHistoryProcIns(leave.getProcInsId()); leave.setBusinessId(history.getBusinessKey()); } leave.setTaskId(leave.getTaskId()); leave.setProcInsId(leave.getProcInsId()); leave.setModelKey(leave.getModelKey()); leave.setHasUnAuditPassFlow(false); } return leave; } @Override public void edit(Absent absent,Integer isAgree) { //审批 if(absent.getIsAgree() != null) { if(absent.getIsAgree() == 1) { FlowableCompleteTask flowableCompleteTask = new FlowableCompleteTask(); flowableCompleteTask.setTaskId(absent.getTaskId()); flowableCompleteTask.setUserCode(getShiroInfo().getUserCode());//当前登录人 flowableCompleteTask.setMessage(absent.getLeaderOpinion()); flowableCompleteTask.setProcessInstanceId(absent.getProcInsId()); flowableCompleteTask.setType("SP"); iFlowableTaskService.complete(flowableCompleteTask); } } } }

代码开发说明:  

  • 继承ServiceImpl类:泛型参数传对应的AbsentMapper和Absent实体类,实现AbsentService接口;所有接口实现层类都需要继承ServiceImpl类,实现对应的xxxService;
  • @Service:所有接口实现层类都必须引用;
  • 类命名规则:xxxServiceImpl;
  • 方法命名规则:与接口抽象方法同名;


      ★温馨提示:"请假单" service接口的实现类,主要用于处理工作流的业务。 如果您的业务也需要集成工作流,那么选择参照这里的代码写法将是非常棒的选择。

1.7 Controller层代码

AbsentController.java

														
@Controller @RequestMapping("/absent") @SuppressWarnings("rawtypes") public class AbsentController { /** *请假单列表 */ @RequestMapping(value = "list",method = RequestMethod.GET) public String list(Model model) { return "demo/absent/list"; } @RequestMapping(value = "listData") @ResponseBody @SuppressWarnings("unlikely-arg-type") public PageWarpper<Absent> listData(Absent leave){ PageWarpper<Absent> pageWarpper = new PageWarpper<Absent>(); IPage<Absent> page = new Page<>(pageWarpper.getCurrentPage(), pageWarpper.getPageSize()); QueryWrapper<Absent> queryWrapper = new QueryWrapper<>(); Map<String, Object> queryMap = leave.setData(leave); String sort = pageWarpper.getSortName(); String sortOrder = pageWarpper.getSortOrder(); if(queryMap.isEmpty() && sort == null) { leaveMapper.selectPage(page, null); }if(queryMap.isEmpty() && sort != null) { if(sortOrder.equals("desc")) { queryWrapper.orderByDesc(sort); }if(sortOrder.equals("asc")) { queryWrapper.orderByAsc(sort); } leaveMapper.selectPage(page, queryWrapper); }if(!queryMap.isEmpty()) { queryWrapper.allEq(queryMap); leaveMapper.selectPage(page, queryWrapper); } pageWarpper.setTotal(new Long(page.getTotal()).intValue()); List<Absent> absents = page.getRecords(); List<Absent> absentsWarp = absentService.listData(absents); //pageWarpper.setRows(absents); pageWarpper.setRows(absentsWarp); return pageWarpper; } /** * 请假单页面 * @param model * @return */ @RequestMapping(value = "form") public String form() { return "demo/absent/form"; } /** * 添加流程表单 */ @RequestMapping("/save") @ResponseBody @Logger(detail = "添加请假单-流程表单",level = 3,unit = LoggerModule.LEAVE,type = LoggerType.INSERT) public Message<String> save(@Valid Absent absent,Flowable flowable, HttpServletRequest request) { absent.setId(UUIDUtils.counter()); absent.setOperTime(new Date()); this.leaveMapper.insert(absent); return absentService.save(absent,flowable); } /** * 根据请假单id,修改请假单信息 * @param id * @param model * @return */ @RequestMapping(value="edit/{id}") public String edit(@PathVariable String id, Absent absent,Model model) { Absent leaveObj = leaveMapper.selectById(id); absent.setType(leaveObj.getType()); absent.setDays(leaveObj.getDays()); absent.setReason(leaveObj.getReason()); absent.setLeaderOpinion(leaveObj.getLeaderOpinion()); Absent leave = absentService.edit(absent); model.addAttribute("leave",leave); return "demo/absent/edit"; } /** * 修改请假单 */ @RequestMapping("/edit") @ResponseBody public Message<String> edit(@Valid Absent absent,BindingResult result) { this.leaveMapper.updateById(absent); absentService.edit(absent, absent.getIsAgree()); return Message.success("修改请假单成功啦!"); } /** * 删除请假单 */ @RequestMapping(value="delete") @ResponseBody @Logger(unit = LoggerModule.USER,type = LoggerType.DELETE) public Message delete(@RequestParam Integer id) { this.leaveMapper.deleteById(id); return Message.success(); } }

代码开发说明:  

  • @Controller:所有controller层类都必须引用;
  • 类命名规则:xxxController;
  • 方法命名规则:列表:list; 列表数据:listData; 新增:form; 保存:save; 按id编辑:edit/{id}; 编辑:edit; 删除方法:delete;
  • @RequestMapping("/absent"):请求路径,请求路径尽量与实体类同名;
  • @RequestMapping(value = "list",method = RequestMethod.GET):请求路径;list是请求路径;RequestMethod.GET是请求方式为GET方式,而不是POST方式;
  • @ResponseBody:当返回前端的类型是json类型时,需要引用
  • @Logger(unit = LoggerModule.LEAVE,type = LoggerType.DELETE):当前端请求该删除方法时会被记录下来,并将删除信息插入至数据表,可在[监控管理] → [系统日志]模块查看
  • 返回前端消息:
    成功:Message.success()  或   Message.success("xxx成功了~");      
    失败:Message.error(xxx,xxx);参数一:int数值类型; 参数二:String字符串类型。如:error(500,"后台数据异常,请联系管理员处理...")


2. 前端开发过程 - 演示


2.1 演示代码存放位置说明

    存放位置说明:  直接在javamis-web工程下编写您自己的业务代码,本模块因为是作为演示使用,所以创建了"demo"目录,代码将写在demo目录下的业务目录下,比如:

  • 前台静态文件(js/css/img)代码写于:javamis-web/src/main/resources/static/js/demo/absent目录下
  • 前台html文件代码写于:javamis-web/src/main/resources/views/demo/absent目录下

      温馨提示1:演示代码目前暂放在新创建的demo目录下,您如果不再需要演示代码作为参考,可将demo目录删除即可!  您真正开发的业务代码请放在business目录下。

      温馨提示2:本次是以开发 <小型业务系统>作为行演示对象;大型业务系统的开发和创建包结构也是一样的,只是需要单独创建一个或多个工程,然后被javamis-parent管理,同时被javamis-web引入,详细请参照: <后端-开发规范>章节~



    ★代码开发技巧★:  

  • 首先,复制javamis-core工程../views/system目录下的edit.html、form.html、list.html文件 至 javamis-web工程../views/demo/absent目录下。
  • 然后,根据您entity下的实体类的属性替换js和html页面内的属性即可,因为新增/更新/修改/删除/查询/搜索封装的函数都是通用的写法~

2.2 演示代码存放位置目录

(图-1:演示前端代码目录说明)

2.3 js脚本代码

absent.js

														
var obj = { table: null, departmentId:0, departmentPid:0, tableId:'tableList', /** * 初始化表格的列 */ initColumns:function () { var columns = [ {title: 'Id', field: 'id', visible: true, align: 'center', valign: 'middle',width:'3%',sortable: true,cellStyle:ims.hidden,formatter: function (value, row, index) { return ims.serialNumber(index,obj.tableId); }}, {title: '请假标题', field: 'titleName', align: 'left', valign: 'middle', width:'30%',sortable: true,cellStyle:ims.hidden,formatter:ims.display}, {title: '请假类型', field: 'type', align: 'center', valign: 'middle',width:'7%', sortable: true,cellStyle:ims.hidden,formatter:function(val, obj, row, act){ return ims.dictLabel("leave_type",val,"未知"); }}, {title: '请假天数', field: 'days', align: 'center', valign: 'middle', width:'7%',sortable: true,cellStyle:ims.hidden,formatter:ims.display}, {title: '请假原因', field: 'reason', align: 'center', valign: 'middle', width:'15%', sortable: true,cellStyle:ims.hidden,formatter:ims.display}, {title: '领导意见', field: 'leaderOpinion', align: 'center', valign: 'middle',width:'16%', sortable: true,cellStyle:ims.hidden,formatter:ims.display}, { field: 'payStatus', width: '19%', title: '操作', formatter: actionFormatter, align:'center' } ]; return columns; }, /** * 搜索参数 */ params:function(){ var params = { "type":$("#type").val(), "days":$("#days").val(), "reason":$.trim($("#reason").val()), "leaderOpinion":$.trim($("#leaderOpinion").val()), "status":$("#status").val() }; return params; }, /** * 搜索 */ search:function(){ obj.table.refresh({query: obj.params()}); } }; //操作栏的格式化 function actionFormatter(value, row, index) { var id = row.id; var userCode = row.userCode; var userName = row.userName; var procDefId = row.procDefId; var procInsId = row.procInsId; var processIsFinished = row.processIsFinished; var result = ""; result += "<a href='javascript:;' class='btn btn-white btn-sm' onclick=\"addPage('/absent/edit/" + id + "', '请假单编辑')\" title='编辑'>编辑</a>"; result += "<a href='javascript:;' class='btn btn-red btn-sm' onclick=\"deletePage('/absent/delete','" + id +"','"+userName+"')\" title='删除'>删除</a>"; if(processIsFinished == "10002"){//10002:已完结;当已完结时为hisInsId赋值procInsId;当未完结时为instanceId赋值procInsId; 如果不加判断未完结的流程图显示不正确(偶尔也会显示已完结)!!! result += "<a href='javascript:;' class='btn btn-blue-width27-min btn-sm' onclick=\"addLayerCustom('/flowableOffice/taskDiagram?definitionId=" +procDefId + "&hisInsId=" + procInsId +"', '查看流程图','1280','590')\" title='查看流程图'>流程追踪</a>"; }else{ result += "<a href='javascript:;' class='btn btn-light-blue-width27-min btn-sm' onclick=\"addLayerCustom('/flowableOffice/taskDiagram?definitionId=" +procDefId + "&instanceId=" + procInsId +"', '查看流程图','1280','590')\" title='查看流程图'>流程追踪</a>"; } return result; } //单击事件,向后台发起请求 function zTreeOnClick(event, treeId, treeNode) { obj.departmentId = treeNode.id; obj.departmentPid=treeNode.parentId; obj.search(); } $(function () { //1.为form页面加载请假类型字典值 loadDict(); //2.初始化列表 obj.table = new initTable(obj.tableId,"/absent/listData","server",obj.initColumns()); obj.table.setParams(obj.params()); obj.table.init(); //3.表单验证 formValidator.init("form",formValidator.formValidate()); //4.时间函数-用于在absent/form和edit页面显示当前系统时间,该函数不是框架必须使用,所以可保留亦可删除-start-HuiJia var timerDiv=document.querySelector('.timer');//获取timer的dom对象 function times(){//时间的方法函数 //创建一个当前日期对象 var d=new Date(); var y=d.getFullYear(); //年 var m=d.getMonth()+1; //月 var dd=d.getDate(); //日 var hh=d.getHours(); //时 var min=d.getMinutes(); //分 var ss=d.getSeconds(); //秒 var timeFormat=y+'年'+m+'月'+dd+'日'+hh+'时'+min+'分'+ss+'秒'; timerDiv.innerHTML=timeFormat; //通过js插到div内容里面去 } times(); //定时器里面的是一秒钟之后才会执行的,所以呢,如果不调用这个函数的话,那一秒钟之前他是没有数字显示的,所以必须要在一秒钟之前的时候调用这个函数,那它才会正常显示,那一秒钟之后的话,它就执行那个定时器里面的函数 //使其刷新前不留空白 setInterval(times,1000); //定时器 //定时器里的参数单位是毫秒,1秒=1000毫秒 //时间函数-用于在absent/form和edit页面显示当前系统时间,该函数不是框架必须使用,所以可保留亦可删除-end-HuiJia });

代码开发说明:  

            一、var obj = {table: null,tableId:'tableList'...}:所有业务js通用写法,直接复制粘贴即可;意思是定义一个名称为obj的集合,
    obj集合里面含:table、departmentId、departmentPid、tableId、initColumns、params、search七个变量,下面是详细介绍:
    变量table:   默认值设置为null;
    变量departmentId:   部门Id,默认值设置为0;
    变量departmentPid:   父部门Id,默认值设置为0;
    变量tableId:   默认值设置为'tableList';
    变量initColumns:   默认值设置为初始化表格函数;
    变量params:   默认值设置为列表搜索框-搜索参数函数;
    变量search:   搜索函数;

  • 变量initColumns默认值初始化表格函数介绍:   
    title:  表格头标题名称,值是字符串类型;
    field:  域(字段属性),值是表格头标题名称对应的类属性,有两种方式:
                 第一种普通方式:title值如果是'请假原因',那么field值就是'reason';
                 第二种是操作栏列field: 'payStatus',这是随意设置的值,payStatus没有实际意义;
    align:  水平对齐;left:左对齐; center:居中对齐; right:右对齐;
    valign:   垂直对齐;middle:居中对齐;width:   表格列宽;值是百分比表示;
    sortable:   是否排序(含:正序,倒序列),true:排序;false:不排序;
    cellStyle:内容超出表格列宽度时隐藏超出的部分;值默认设置为ims.hidden;
    formatter:  为该域(字段属性)赋值;有两种赋值方式:
                          默认(普通)赋值方式:ims.display;
                          自增长序号赋值方式:function (value, row, index) {return ims.serialNumber(index,obj.tableId);
                          数据字典赋值方式:function(val, obj, row, act){return ims.dictLabel("leave_type",val,"未知");}};
                          操作栏格式化赋值方式:参见[actionFormatter]函数
  • 变量params搜索参数函数介绍:
    返回params集合;params集合是key和value的键值对;key是Absent实体类内的属性;value是获取搜索框的输入值;
  • 变量search搜索函数介绍:调用搜索函数功能,将前端搜索框输入值传至后端进行搜索,然后将搜索后的结果返回给前端;

  •         二、actionFormatter(value, row, index) {...}函数:所有业务js通用写法,直接复制粘贴即可;意思是定义一个名称为actionFormatter的函数,actionFormatter函数里面含:'编辑'、'删除'、'流程追踪'三个按钮,下面是详细介绍:
  • '编辑'按钮介绍:
    <a href='javascript:;' class='btn btn-white btn-sm' onclick="addPage('/absent/edit/"+id+"', '请假单编辑')" title='编辑'>编辑</a>
  • '删除'按钮介绍:
    <a href='javascript:;' class='btn btn-red btn-sm' onclick="deletePage('/absent/delete','"+id+"','"+userName+"')" title='删除'>删除</a>
  • '流程追踪'按钮介绍:
    <a href='javascript:;' class='btn btn-light-blue-width27-min btn-sm' onclick=\"addLayerCustom('/flowableOffice/taskDiagram?
    definitionId=" +procDefId + "&instanceId=" + procInsId +"', '查看流程图','1280','590')\" title='查看流程图'>流程追踪</a>

  •         三、zTreeOnClick(event, treeId, treeNode) {...}函数:部门树单击事件函数,所有业务js通用写法,直接复制粘贴即可;意思是定义一个名称为zTreeOnClick的函数,zTreeOnClick函数分别为obj.departmentId、obj.departmentPid变量赋值,同时调用obj.search()函数执行搜索任务;
    注:zTreeOnClick函数暂时在这里没有被使用,只是为了给大家展示如何使用及用法,使用可参考user.js

            四、$(function () {...}函数:所有业务js通用写法,直接复制粘贴即可;意思是页面加载完毕之后,直接执行该函数;一些需要初始化的函数都可以放在该函数下,function ()函数里面含:'初始化Table表格'、'初始化表单验证控件'二个初始化插件函数,下面是详细介绍:
  • 1.为form页面加载请假类型字典值
    loadDict();
    说明:加载数据字典函数;如果页面需要调用数据字典,加上loadDict()函数即可!
  • 2、初始化Table表格
    obj.table = new initTable(obj.tableId,"/absent/listData","server",obj.initColumns());
    说明:创建Table表格对象;参数一、默认表格id;参数二、列表数据路径:/absent/listData;参数三、默认初始化列;
    obj.table.setParams(obj.params());
    说明:设置搜索参数;参数:默认将'搜索参数'集合传入;
    obj.table.init();
    说明:表格初始化函数
  • 3、初始化表单验证控件
    formValidator.init("form",formValidator.formValidate());
    说明:初始化表单验证函数;参数一、默认验证"form"表单; 参数二、调用验证格式函数
  • 4、时间函数
    说明:这里定义时间函数,提供给form.html和edit.html页面调用;
    注:这里展示出来也是给大家讲解如何创建时间函数及如何使用,如果您的业务需要获取当前系统时间,可以直接copy走吧~

      ★温馨提示:上面的absent.js 属性通用写法,每个js都是这样的写法,您只需根据实体类要替换字段属性即可,非常简单。


2.4 新增表单代码

form.html

														
<%layout("/common.html"){%> <div class="box-header with-border"> <div class="box-title"> <i class="fa fa-user-o" style="font-size:12px;color:#6495ED;padding:0px 7px 0px 5px;"></i> <i style="font-size:16px">添加请假流程表单</i> <li class="long-gray-underline"></li> </div> <div class="box-title"> <div class="font-italic" style="font-size:15px;color:#1e5edb;padding:0px 7px 0px 26px;"> <div style="width:800px;height:30px;float:left; padding-bottom:0em;border-bottom: 1px solid #eaecef;margin-bottom: 30px;"> <div style=height:30px;float:left;">${shiro.getPrimaryPrincipal().userName} 在   </div> <div class="timer" style="height:30px;float:left;"></div> <div height:100px;float:left;>  填写请假单</div> </div> </div> </div> </div> <div class="form-content"> <div class="form-horizontal" id="form"> <input type="hidden" id="id" value=""> <input type="hidden" id="deptId" value=""> <input type="hidden" id="titleName" value="${shiro.getPrimaryPrincipal().userName}"> <div class="row"> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 请假类型:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <select class="input-sm form-control" id="type" name="type" dictType="leave_type" defaultValue="1"></select> </div> </div> </div> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 请假天数:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <#form:input id="days" type="number" class="required"/> </div> </div> </div> </div> <div class="row"> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 请假原因:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <#form:input id="reason" /> </div> </div> </div> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 领导意见:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <#form:input id="leaderOpinion"/> </div> </div> </div> </div> <div class="row"> <div class="button"> <#form:button class="btn btn-info" name="提交" id="ensure" icon="fa-check" onclick="submitPage('/absent/save')"/> <#form:button class="btn btn-default" name="关闭" id="cancel" icon="fa-mail-reply-all" onclick="closePage()"/> </div> </div> </div> </div> <script type="text/javascript" src="${ctxPath}/js/demo/absent/absent.js"></script> <%}%>

代码开发说明:  

  • <%layout("/common.html"){%>...<%}%>
    说明:所有业务html通用写法,直接复制粘贴即可;意思是引入通用页面,每个业务页面无需再重复引用静态文件。
  • <script type="text/javascript" src="${ctxPath}/js/flowable/demo/storage/assStorage.js"></script>
    说明:引入页面对应的js脚本
  • <i style="font-size:16px">添加请假流程表单</i>
    说明:表单引导信息
  • <li class="long-gray-underline"></li>
    说明:表单引导信息下方的下划线
  • <div class="row">....</div>
    说明:使用 栅栏页面布局方式,也称为响应式布局;   点击进入:学习教程
  • <#form:button class="btn btn-info" name="提交" id="ensure" icon="fa-check" onclick="submitPage('/absent/save')"/>
    说明:'提交'按钮
  • <#form:button class="btn btn-default" name="关闭" id="cancel" icon="fa-mail-reply-all" onclick="closePage()"/>
    说明:'关闭'按钮
  • <input type="hidden" id="titleName" value="${shiro.getPrimaryPrincipal().userName}">
    说明:定义一个隐藏类型的输入域,value值:${shiro.getPrimaryPrincipal().userName} 通过shiro获取到用户名;

      ★温馨提示:上面的form.html 是属性通用写法,每个form都是这样的写法,您只需根据实体类要替换字段属性即可,非常简单吧 :D


2.5 编辑表单代码

edit.html

														
<%layout("/common.html"){%> <div class="box-header with-border"> <div class="box-title"> <i class="fa fa-user-o" style="font-size:12px;color:#6495ED;padding:0px 7px 0px 5px;"></i> <i style="font-size:16px">编辑请假流程表单</i> <li class="long-gray-underline"></li> </div> <div class="box-title"> <div class="font-italic" style="font-size:15px;color:#1e5edb;padding:0px 7px 0px 26px;"> <div style="width:800px;height:30px;float:left; padding-bottom:0em;border-bottom: 1px solid #eaecef;margin-bottom: 30px;"> <div style=height:30px;float:left;">${shiro.getPrimaryPrincipal().userName} 在   </div> <div class="timer" style="height:30px;float:left;"></div> <div height:100px;float:left;>  编辑请假单</div> </div> </div> </div> </div> <div class="form-content"> <div class="form-horizontal" id="form"> <input type="hidden" id="id" value="${leave.id}"> <input type="hidden" id="leave" name="leave" value="${leave}"/> <input type="hidden" id="taskId" name="taskId" value="${leave.taskId}"/> <input type="hidden" id="procInsId" name="procInsId" value="${leave.procInsId}"/> <input type="hidden" id="modelKey" name="modelKey" value="${leave.modelKey}"/> <!-- <input type="hidden" id="titleName" value="${shiro.getPrimaryPrincipal().userName}"> --> <div class="row"> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 请假类型:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <select class="input-sm form-control" id="type" name="type" dictType="leave_type" defaultValue="${leave.type}"></select> </div> </div> </div> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 请假天数:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <#form:input id="days" type="number" class="required" value="${leave.days}"/> </div> </div> </div> </div> <div class="row"> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 请假原因:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <#form:input id="reason" value="${leave.reason}"/> </div> </div> </div> <div class="col-xs-6"> <!--<div class="form-group">--> <div class="input-group"> <label class="control-label col-sm-4" title=""> 领导意见:<i class="fa icon-question hide"></i></label> <div class="col-sm-8"> <#form:input id="leaderOpinion"/> </div> </div> </div> </div> <div class="row"> <div class="button"> <#form:button class="btn btn-info" name="暂存" id="submit" icon="fa-check" onclick="submitPage('/absent/edit?isAgree=0')"/>  <% if(leave.status == 'todo'){ %> <% if(leave.hasUnAuditPassFlow){ %> <#form:button class="btn btn-info" name="重发流程" id="submit" icon="fa-check" onclick="submitPage('/absent/edit')"/> <% } else { %> <#form:button class="btn btn-info" name="同意" id="submit" icon="fa-check" onclick="submitPage('/absent/edit?isAgree=1')"/>  <#form:button class="btn btn-info" name="驳回" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/back?taskId=${leave.taskId}&procInsId=${leave.procInsId}&modelKey=${leave.modelKey}', '驳回','560','350')"/> <#form:button class="btn btn-info" name="前加签" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/beforeAddSign?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '前加签','560','350')"/>  <#form:button class="btn btn-info" name="后加签" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/afterAddSign?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '后加签','560','350')"/>  <#form:button class="btn btn-info" name="转办" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/transfer?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '转办','560','350')"/>  <#form:button class="btn btn-info" name="委派" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/delegate?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '委派','560','350')"/> <% } %> <% } %> <#form:button class="btn btn-default" name="关闭" id="cancel" icon="fa-mail-reply-all" onclick="closePage()"/> </div> </div> </div> </div> <script type="text/javascript" src="${ctxPath}/js/demo/absent/absent.js"></script> <%}%>

代码开发说明:  

  • 1、<%layout("/common.html"){%>...<%}%>
    说明:所有业务html通用写法,直接复制粘贴即可;意思是引入通用页面,每个业务页面无需再重复引用静态文件。
  • 2、<script type="text/javascript" src="${ctxPath}/js/demo/absent/absent.js"></script>
    说明:引入页面对应的js脚本
  • 3、<i style="font-size:16px">编辑请假流程表单</i>
    说明:表单引导信息
  • 4、<li class="long-gray-underline"></li>
    说明:表单引导信息下方的下划线
  • 5、<div class="row">....</div>
    说明:使用 栅栏页面布局方式,也称为响应式布局;   点击进入:学习教程
  • 6、<#form:button class="btn btn-info" name="暂存" id="submit" icon="fa-check" onclick="submitPage('/absent/edit?isAgree=0')"/>
    说明:'暂存'按钮
  • 7、<#form:button class="btn btn-info" name="重发流程" id="submit" icon="fa-check" onclick="submitPage('/absent/edit')"/>
    说明:'重发流程'按钮,可选项(如果您的业务没有工作流程可将该项去掉)
  • 8、<#form:button class="btn btn-info" name="同意" id="submit" icon="fa-check" onclick="submitPage('/absent/edit?isAgree=1')"/>
    说明:'同意'按钮,也称呼 '审批'按钮,可选项(如果您的业务没有工作流程可将该项去掉)
  • 9、<#form:button class="btn btn-info" name="驳回" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/back?taskId=${leave.taskId}&procInsId=${leave.procInsId}&modelKey=${leave.modelKey}', '驳回','560','350')"/>
    说明:'驳回'按钮,可选项(如果您的业务没有工作流程可将该项去掉)
  • 10、<#form:button class="btn btn-info" name="前加签" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/beforeAddSign?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '前加签','560','350')"/>
    说明:'前加签'按钮,可选项(如果您的业务没有工作流程可将该项去掉)
  • 11、<#form:button class="btn btn-info" name="后加签" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/afterAddSign?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '后加签','560','350')"/>
    说明:'后加签'按钮,可选项(如果您的业务没有工作流程可将该项去掉)
  • 12、<#form:button class="btn btn-info" name="转办" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/transfer?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '转办','560','350')"/>
    说明:'转办'按钮,可选项(如果您的业务没有工作流程可将该项去掉)
  • 13、<#form:button class="btn btn-info" name="委派" id="submit" icon="fa-check" onclick="addLayerCustom('/flowableOffice/delegate?taskId=${leave.taskId}&procInsId=${leave.procInsId}', '委派','560','350')"/>
    说明:'委派'按钮,可选项(如果您的业务没有工作流程可将该项去掉)
  • 14、<#form:button class="btn btn-default" name="关闭" id="cancel" icon="fa-mail-reply-all" onclick="closePage()"/>
    说明:'关闭'按钮

      ★温馨提示:上面的edit.html 是属性通用写法,每个edit都是这样的写法,您只需根据实体类要替换字段属性即可,非常简单吧 :D


2.6列表表单代码

list.html

														
<%layout("/common.html"){%> <div class=" page-content clearfix"> <div id="fold-expand" class="fold-expand"> <div class="h_products_list clearfix " id="mcs-list"> <!-- 用户列表管理-开始 --> <div class="widget-box-none"> <div style="padding:3px 0px 8px;"></div> <div class="row table-body" id="testIframe"> <!-- 查询条件框-开始 --> <div class="table-search"> <div class="form-group search-condition"> <label class="control-label search-label">请假类型:</label> <div class="control-inline search-inline"> <select class="input-dict-sm" id="type" name="type" dictType="leave_type" defaultValue="0"></select> </div> </div> <div class="form-group search-condition"> <label class="control-label search-label">请假天数:</label> <div class="control-inline search-inline"> <#form:list id="days" type="number"/> </div> </div> <div class="form-group search-condition"> <label class="control-label search-label">请假原因:</label> <div class="control-inline search-inline"> <#form:list id="reason"/> </div> </div> <div class="form-group search-condition"> <label class="control-label search-label">领导意见:</label> <div class="control-inline search-inline"> <#form:list id="leaderOpinion"/> </div> </div> <div class="form-group search-condition"> <label class="control-label search-label">流程状态:</label> <div class="control-inline search-inline"> <#form:list id="status"/> </div> </div> <div class="form-group search-button"> <#form:button class="btn btn-default btn-sm" onclick="obj.search()" name="查询"/> <#form:button class="btn btn-add btn-sm button-item" icon="fa-plus" iconLocation="icon-before" onclick="addPage('/absent/form','新增请假流程表单')" name="新增"/> <#form:button class="btn btn-add btn-sm button-item refreshButton" icon="fa-sort-desc" iconLocation="icon-after" onclick="refreshPage()" name="刷新" /> <#form:button class="btn btn-add btn-sm button-item" icon="fa-sort-desc" iconLocation="icon-after" name="更多" /> </div> </div> <!-- 查询条件框-结束 --> <!-- 表格table-开始--> <div id="table-list" style="margin-left:9px;"> <table id="tableList" style = "table-layout:fixed;width:100%;"></table> </div> <!-- 表格table-结束--> </div> </div> <!-- 用户列表管理-结束 --> </div> </div> </div> <script type="text/javascript" src="${ctxPath}/js/demo/absent/absent.js"></script> <%}%>

代码开发说明:  

  • <%layout("/common.html"){%>...<%}%>
    说明:所有业务html通用写法,直接复制粘贴即可;意思是引入通用页面,每个业务页面无需再重复引用静态文件。
  • <script type="text/javascript" src="${ctxPath}/js/demo/absent/absent.js"></script>
    说明:引入页面对应的js脚本
  • <div class="table-search">...</div>
    说明:平台搜索框布局通用写法;   关于form-group的用法:点击进入:学习教程
  • <#form:list id="xxx"/>
    说明:搜索框;xxx是Absent实体类的属性,您需要以哪个属性作为搜索条件,则输入哪个属性即可;如:以请假天数作为搜索条件,那么写法是:<#form:list id="days" type="number"/>
  • <#form:button class="btn btn-default btn-sm" onclick="obj.search()" name="查询"/>
    说明:'查询'按钮
  • <#form:button class="btn btn-add btn-sm button-item" icon="fa-plus" iconLocation="icon-before" onclick="addPage('/absent/form','新增请假流程表单')" name="新增"/>
    说明:'新增'按钮
  • <#form:button class="btn btn-add btn-sm button-item refreshButton" icon="fa-sort-desc" iconLocation="icon-after" onclick="refreshPage()" name="刷新" />
    说明:'刷新'按钮
  • <#form:button class="btn btn-add btn-sm button-item" icon="fa-sort-desc" iconLocation="icon-after" name="更多" />
    说明:'更多'按钮,目前暂未挂链接未启用
  • <table id="tableList" style = "table-layout:fixed;width:100%;"></table>
    说明:Table表格

      ★温馨提示:上面的list.html 是属性通用写法,每个list都是这样的写法,您只需根据实体类要替换字段属性即可,非常简单吧 :D