Git clone –b day12 https://github.com/qixiangchen/gufang_fisys.git

学习如何使用工作流完成报销单模块,熟练掌握工作流引擎的常用接口,熟练掌握设计工作流模板。

工作流常用接口

报销单流程模板

<?xml version="1.0" encoding="gb2312"?>
<!--
注意:
流程触发外部接口,其类加载器必须位于工作流引擎类加载器平级或者更高一级
-->
<process id="expense" name="请款流程" description=""><status id="Start" name="开始" type="synchronized" isstart="true"><tostatuses><tostatus batchid="tomanager" id="account" name="财务审批" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="sendmail"/></tostatuses><actors></actors></status><status id="draft" name="修改" type="synchronized" isstart="false"><tostatuses><tostatus batchid="tomanager" id="account" name="财务审批" condition="false" invoke="" invokecommand=""/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/></tostatuses><actors><actor type="variable" id="starter"/></actors></status><status id="account" name="财务审批" type="asynchronized" isstart="false"><tostatuses><tostatus batchid="vp" id="vp" name="副总审批" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/><tostatus batchid="tostarter" id="draft" name="返回修改" condition="false" invoke="" invokecommand=""/></tostatuses><actors><actor type="user" loginid="fiadmin"/></actors></status><status id="vp" name="副总审批" type="asynchronized" isstart="false"><tostatuses><tostatus batchid="tonotice" id="notice" name="通知申请人" condition="false" invoke="" invokecommand=""/><tostatus batchid="tostarter" id="draft" name="返回修改" condition="false" invoke="" invokecommand=""/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/></tostatuses><actors><actor type="user" loginid="sysadmin"/></actors></status><status id="notice" name="通知申请人" type="asynchronized" isstart="false" workflow="outstore" condition="storeName EQ '发货库A(运达)'"><tostatuses><tostatus batchid="end" id="end" name="完成" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="outstore"/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="outstoredestory"/></tostatuses><actors><actor type="variable" id="starter"/></actors></status><status id="destory" name="作废" type="synchronized" isstart="false"><tostatuses></tostatuses><actors></actors></status><status id="end" name="结束" type="synchronized" isstart="false"><tostatuses></tostatuses><actors></actors></status>
</process>

单元测试类

进入模块页面有两个入口

打开页面操作模拟

新建业务数据

不存在工作流相关数据
(instanceid 业务实例ID,
Instprocessid 流程实例ID,
Instactivityid 活动实例ID,
Instworkitemid 代办件ID)
后台Controller通过流程名称获取流程相关数据userId为当前等于用户ID
processId为流程模块名称
instWorkitemId为空StatusFlowData sfdata = sfmng.getWorkflowData(userId, processId,instWorkitemId);System.out.println(sfdata.getNextBtnList());//通过Request对象传递sfdata.getNextBtnList()到前台页面//数据形式为:[//     {name=财务审批, actor=user3aa650d08695,财务总监, //           js=wfsubmit('account','user3aa650d08695,财务总监',''), id=account}//    ]

通过代办列表进入业务页面

通过Request对象获取工作流相关数据
(instanceid 业务实例ID,
Instprocessid 流程实例ID,
Instactivityid 活动实例ID,
Instworkitemid 代办件ID)
userId为当前等于用户ID
processId为流程模块名称
instWorkitemId为Request传入参数StatusFlowData sfdata = sfmng.getWorkflowData(userId, processId,instWorkitemId);System.out.println(sfdata.getNextBtnList());//通过Request对象传递sfdata.getNextBtnList()到前台页面//数据形式为:[//       {name=财务审批, actor=user3aa650d08695,财务总监, //           js=wfsubmit('account','user3aa650d08695,财务总监',''), id=account}//    ]

提交工作流操作

根据Request传入的instanceid是否为空,判断是启动流程还是提交流程。//2、前台提交数据到后台Controller,调用流程接口//代办列表中无记录,需要新建流程if("".equals(Util.fmtStr(instanceId))){//模拟业务数据保持后id=1instanceId = "1";String startUserId = "1";//流程实例启动用户String type = "报销单";//流程类型,通常取流程模板名称String title = "UserA的报销单";//流程实例标题String url = "/expense.action";//业务模块应用链接HashMap hmap = new HashMap();//工作流实例相关数据hmap.put("days", 5);//通过前台页面点击不同按钮,调用wfsubmit JS方法传递到后台//通过Request.getParameter("nextUserId")获取,userId间以逗号分隔//后台分割userId转存到List<String>List<String> userIdLst = new ArrayList<String>();userIdLst.add("1");//模拟测试,使用超级用户ID//通过Request.getParameter("nexttask")获取nexttask = "account";//创建工作流实例wapi.startWorkflow(processId, startUserId, userIdLst, instanceId, type, title, nexttask, url, hmap, flag, testMode);//wapi.setVariable("days","2")}//通过代办列表进入业务页面,已经存在流程实例else{                String type = "报销单";//流程类型,通常取流程模板名称String title = "UserA的报销单";//流程实例标题String url = "/expense.action";//业务模块应用链接HashMap hmap = new HashMap();//工作流实例相关数据hmap.put("days", 5);//通过前台页面点击不同按钮,调用wfsubmit JS方法传递到后台//通过Request.getParameter("nextUserId")获取,userId间以逗号分隔//后台分割userId转存到List<String>List<String> userIdLst = new ArrayList<String>();userIdLst.add("1");//模拟测试,使用超级用户ID//通过Request.getParameter("nexttask")获取//nexttask = "vp";List<Properties> nextBtnList = sfdata.getNextBtnList();Properties prop = nextBtnList.get(0);nexttask = prop.getProperty("id");wapi.submitWorkflow(instProcessId, instActivityId, instWorkitemId, userIdLst, instanceId, type, title, nexttask, url, hmap, flag, testMode);}

获取用户代办件列表

//1、打开业务页面时,检索工作流核心数据传递到前台String userId = "1";String processId = "expense";String instanceId = null;//业务表单的主键String instProcessId = null;//流程实例IDString instActivityId = null;//流程实例ActivityIdString instWorkitemId = null;//工作代办件IDString nexttask = null;//下一办理环节IDString flag = "gf";//区分客户标识,每一个用户分配统一的标识String testMode = "no";//是否进入测试模式//通过工作流接口获取个人代办工作列表List<DefWorkItem> wkList = wapi.getWorkitemList(userId, testMode);for(DefWorkItem dwi:wkList){if(processId.equals(dwi.getProcessId())){instanceId = dwi.getInstanceId();instProcessId = dwi.getInstProcessId();instActivityId = dwi.getInstActivityId();instWorkitemId = dwi.getId();}}

单元测试类代码

@RunWith(SpringRunner.class)
@SpringBootTest(classes=Starter.class)
public class Tester
{@Autowiredprivate StatusFlowWAPI wapi;@Autowiredprivate IOrgModel orgmodel;@Autowiredprivate StatusFlowMng sfmng;@Autowiredprivate HolidayService hldserv;@Testpublic void testMethod(){try{//1、打开业务页面时,检索工作流核心数据传递到前台String userId = "1";String processId = "expense";String instanceId = null;//业务表单的主键String instProcessId = null;//流程实例IDString instActivityId = null;//流程实例ActivityIdString instWorkitemId = null;//工作代办件IDString nexttask = null;//下一办理环节IDString flag = "gf";//区分客户标识,每一个用户分配统一的标识String testMode = "no";//是否进入测试模式//通过工作流接口获取个人代办工作列表List<DefWorkItem> wkList = wapi.getWorkitemList(userId, testMode);for(DefWorkItem dwi:wkList){if(processId.equals(dwi.getProcessId())){instanceId = dwi.getInstanceId();instProcessId = dwi.getInstProcessId();instActivityId = dwi.getInstActivityId();instWorkitemId = dwi.getId();}}//instWorkitemId 为空  新建业务表单入口//instWorkitemId 不为空  从代办列表进入业务表单StatusFlowData sfdata = sfmng.getWorkflowData(userId, processId,instWorkitemId);System.out.println(sfdata.getNextBtnList());//通过Request对象传递sfdata.getNextBtnList()到前台页面//数据形式为:[//       {name=财务审批, actor=user3aa650d08695,财务总监, //           js=wfsubmit('account','user3aa650d08695,财务总监',''), id=account}//    ]       //2、前台提交数据到后台Controller,调用流程接口//代办列表中无记录,需要新建流程if("".equals(Util.fmtStr(instanceId))){//模拟业务数据保持后id=1instanceId = "1";String startUserId = "1";//流程实例启动用户String type = "报销单";//流程类型,通常取流程模板名称String title = "UserA的报销单";//流程实例标题String url = "/expense.action";//业务模块应用链接HashMap hmap = new HashMap();//工作流实例相关数据hmap.put("days", 5);//通过前台页面点击不同按钮,调用wfsubmit JS方法传递到后台//通过Request.getParameter("nextUserId")获取,userId间以逗号分隔//后台分割userId转存到List<String>List<String> userIdLst = new ArrayList<String>();userIdLst.add("1");//模拟测试,使用超级用户ID//通过Request.getParameter("nexttask")获取nexttask = "account";//创建工作流实例wapi.startWorkflow(processId, startUserId, userIdLst, instanceId, type, title, nexttask, url, hmap, flag, testMode);//wapi.setVariable("days","2")}//通过代办列表进入业务页面,已经存在流程实例else{               String type = "报销单";//流程类型,通常取流程模板名称String title = "UserA的报销单";//流程实例标题String url = "/expense.action";//业务模块应用链接HashMap hmap = new HashMap();//工作流实例相关数据hmap.put("days", 5);//通过前台页面点击不同按钮,调用wfsubmit JS方法传递到后台//通过Request.getParameter("nextUserId")获取,userId间以逗号分隔//后台分割userId转存到List<String>List<String> userIdLst = new ArrayList<String>();userIdLst.add("1");//模拟测试,使用超级用户ID//通过Request.getParameter("nexttask")获取//nexttask = "vp";List<Properties> nextBtnList = sfdata.getNextBtnList();Properties prop = nextBtnList.get(0);nexttask = prop.getProperty("id");wapi.submitWorkflow(instProcessId, instActivityId, instWorkitemId, userIdLst, instanceId, type, title, nexttask, url, hmap, flag, testMode);}/**Wrapper<HolidayInfo> wrap = new EntityWrapper<HolidayInfo>();wrap.eq("days", 2);wrap.and().eq("userid", "1");List<HolidayInfo> list = hldserv.selectList(wrap);for(HolidayInfo hdi2:list){System.out.println("hdi2="+hdi2.getId()+",days="+hdi2.getDays());hdi2.setUserId("1");hldserv.updateById(hdi2);}hldserv.delete(wrap);*/}catch(Exception e){e.printStackTrace();}}
}

报销单开发流程

工作流模板及模板图片描述文件分别存放在GUFANG_HOME/workflow与GUFANG_HOME/workflowui目录下。
流程模板expense.xml

<?xml version="1.0" encoding="gb2312"?>
<!--
注意:
流程触发外部接口,其类加载器必须位于工作流引擎类加载器平级或者更高一级
-->
<process id="expense" name="请款流程" description=""><status id="Start" name="开始" type="synchronized" isstart="true"><tostatuses><tostatus batchid="tomanager" id="account" name="财务审批" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="sendmail"/></tostatuses><actors></actors></status><status id="draft" name="修改" type="synchronized" isstart="false"><tostatuses><tostatus batchid="tomanager" id="account" name="财务审批" condition="false" invoke="" invokecommand=""/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/></tostatuses><actors><actor type="variable" id="starter"/></actors></status><status id="account" name="财务审批" type="asynchronized" isstart="false"><tostatuses><tostatus batchid="vp" id="vp" name="副总审批" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/><tostatus batchid="tostarter" id="draft" name="返回修改" condition="false" invoke="" invokecommand=""/></tostatuses><actors><actor type="user" loginid="fiadmin"/></actors></status><status id="vp" name="副总审批" type="asynchronized" isstart="false"><tostatuses><tostatus batchid="tonotice" id="notice" name="通知申请人" condition="false" invoke="" invokecommand=""/><tostatus batchid="tostarter" id="draft" name="返回修改" condition="false" invoke="" invokecommand=""/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="orderdestory"/></tostatuses><actors><actor type="user" loginid="sysadmin"/></actors></status><status id="notice" name="通知申请人" type="asynchronized" isstart="false" workflow="outstore" condition="storeName EQ '发货库A(运达)'"><tostatuses><tostatus batchid="end" id="end" name="完成" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="outstore"/><tostatus batchid="destory" id="destory" name="作废" condition="false" invoke="com.gf.statusflow.TestInvokeApp" invokecommand="outstoredestory"/></tostatuses><actors><actor type="variable" id="starter"/></actors></status><status id="destory" name="作废" type="synchronized" isstart="false"><tostatuses></tostatuses><actors></actors></status><status id="end" name="结束" type="synchronized" isstart="false"><tostatuses></tostatuses><actors></actors></status>
</process>

流程模板图片描述文件expense.xml

<?xml version="1.0" encoding="gb2312"?><process id="gf_order" name="订单流程" description=""><node id="Start" name="开始" x="20" y="20" textx="20" texty="60" namex="20" namey="40" username=""><tonode id="account"/></node><node id="draft" name="修改" x="120" y="60" textx="120" texty="100" namex="120" namey="80" username=""><tonode id="account"/><tonode id="destory"/></node><node id="account" name="财务审批" x="220" y="20" textx="220" texty="60" namex="220" namey="40" username="财务审批人员"><tonode id="vp"/><tonode id="destory"/></node><node id="vp" name="副总审批" x="400" y="20" textx="430" texty="55" namex="420" namey="35" username="济南库管"><tonode id="destory"/><tonode id="end"/></node><node id="destory" name="作废" x="300" y="60" textx="300" texty="100" namex="300" namey="80" username=""></node><node id="notice" name="通知申请人" x="550" y="20" textx="560" texty="60" namex="560" namey="40" username=""></node><node id="end" name="结束" x="650" y="20" textx="660" texty="60" namex="660" namey="40" username=""></node>
</process>

设计实体类ExpenseInfo

@TableName("gf_expense")
public class ExpenseInfo implements Serializable{@TableIdprivate String id = null;private String name = null;private String company = null;private String bank = null;private String bankAccount = null;private BigDecimal amount = null;private String userId = null;@TableField(exist=false)private String userName = null;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCompany() {return company;}public void setCompany(String company) {this.company = company;}public String getBank() {return bank;}public void setBank(String bank) {this.bank = bank;}public String getBankAccount() {return bankAccount;}public void setBankAccount(String bankAccount) {this.bankAccount = bankAccount;}public BigDecimal getAmount() {return amount;}public void setAmount(BigDecimal amount) {this.amount = amount;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}
}
本模块使用Mybatis-plus实现,实体类需要添加Mybatis-plus的注解。

SQL

create table gf_expense(id varchar(32),name varchar(100),company varchar(100),bank varchar(100),bankaccount varchar(100),amount decimal(10,2),userId varchar(100)
);

Mapper XML

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gf.mapper.ExpenseMapper"></mapper>

Mapper接口

package com.gf.mapper;import org.apache.ibatis.annotations.Mapper;import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.gf.model.ExpenseInfo;@Mapper
public interface ExpenseMapper extends BaseMapper<ExpenseInfo>{}

服务接口

package com.gf.service;import com.baomidou.mybatisplus.service.IService;
import com.gf.model.ExpenseInfo;public interface ExpenseService extends IService<ExpenseInfo>{}

服务实现类

package com.gf.service.impl;import org.springframework.stereotype.Service;import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.gf.mapper.ExpenseMapper;
import com.gf.model.ExpenseInfo;
import com.gf.service.ExpenseService;@Service
public class ExpenseServiceImpl extends ServiceImpl<ExpenseMapper,ExpenseInfo>implements ExpenseService
{}

Controller类

@Controller
public class ExpenseCtrl {@Autowiredprivate StatusFlowMng sfmng;@Autowiredprivate StatusFlowWAPI wapi;@Autowiredprivate IOrgModel orgmodel;@Autowiredprivate ExpenseService expserv;//本方法可以通过新建业务数据进入,也可通过从工作流代办列表中进入@RequestMapping("/expense.action")public String expense(HttpServletRequest req){//从工作流代办列表中进入时,需要传递此四个参数String instanceid = req.getParameter("instanceid");String instprocessid = req.getParameter("instprocessid");String instactivityid = req.getParameter("instactivityid");String instworkitemid = req.getParameter("instworkitemid");//工作流方法返回结果对象StatusMsg wfMsg = null;//工作流下一个办理环节String nexttask = null;//工作流下一办理环节集合,用于生成页面上按钮List<Properties> nextBtnList = null;//获取当前登录用户IUser loginUser = Util.getLoginUser();String userId = loginUser.getId();//流程名称,与流程模板XML文件同名String processId = "expense";HashMap hmap = null;//获取工作流控制数据StatusFlowData wfdata = sfmng.getWorkflowData(userId, processId, nexttask, instworkitemid,hmap);//工作流下一办理环节集合,用于生成页面上按钮nextBtnList = wfdata.getNextBtnList();//返回到前台页面,用于生成页面上按钮req.setAttribute("button", nextBtnList);//如果实例ID不为空,说明是通过代办件列表进入业务页面的if(instanceid != null){//返回业务对象和工作流核心数据到页面ExpenseInfo eps = expserv.selectById(instanceid);req.setAttribute("eps", eps);req.setAttribute("instprocessid", instprocessid);req.setAttribute("instactivityid", instactivityid);req.setAttribute("instworkitemid", instworkitemid);}return "/fi/expense";}@RequestMapping("/expsubmit.action")@ResponseBodypublic StatusMsg expsave(HttpServletRequest req,ExpenseInfo exps){try{//如果实例ID为空,说明是新建业务数据,否则是通过工作流代办列表进入String instanceid = exps.getId();if("".equals(Util.fmtStr(instanceid)))instanceid = UUID.create("expense");//通过Request对象获取工作流核心控制数据String instprocessid = req.getParameter("instprocessid");String instactivityid = req.getParameter("instactivityid");String instworkitemid = req.getParameter("instworkitemid");//获取下一办理环节,对应页面上的按钮String nexttask = req.getParameter("nexttask");//获取下一办理环节上的审批人,通过前台页面上按钮事件参数传入String nextUserId = req.getParameter("nextUserId");//当前登录人IUser loginUser = Util.getLoginUser();String startUserId = loginUser.getId();//流程模板名称String processId = "expense";//流程分类,可以自定义String type = "expense";//流程标题String title = exps.getName()+":"+exps.getAmount().toString();//打开代办列表中不同流程的URLString url = "/expense.action";HashMap hmap = new HashMap();//flag,testMode使用默认值,其对应的功能当前未使用String flag = "gf";String testMode = "no";exps.setId(instanceid);//工作流操作返回结果对象StatusMsg wfMsg = null;//如果代办件ID为空,说明是启动流程if("".equals(Util.fmtStr(instworkitemid))){//保存业务对象数据expserv.insert(exps);//获取前台页面传入的下一个办理环节审批人列表List<String> userIdList = new ArrayList<String>();String[] dim = nextUserId.split(",");for(String s:dim){if(!"".equals(Util.fmtStr(s)))userIdList.add(s);}//启动工作流wfMsg = wapi.startWorkflow(processId,startUserId,userIdList,instanceid,type,title,nexttask,url,hmap,flag,testMode);}else//从代办件列表进入页面并提交{List<String> userIdList = new ArrayList<String>();String[] dim = nextUserId.split(",");for(String s:dim){if(!"".equals(Util.fmtStr(s)))userIdList.add(s);}//更新业务数据expserv.updateById(exps);//提交工作流程wfMsg = wapi.submitWorkflow(instprocessid,instactivityid,instworkitemid,userIdList,instanceid,type,title,nexttask,url,hmap,flag,testMode);}return wfMsg;}catch(Exception e){e.printStackTrace();}return null;}
}

JSP页面

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@ page import="java.util.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<script type="text/javascript" src="/static/easyui/jquery.min.js"></script>
<script type="text/javascript" src="/static/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="/static/easyui/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" href="/static/easyui/themes/default/easyui.css"/>
<link rel="stylesheet" href="/static/easyui/themes/icon.css"/>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>财务报销系统</title>
<script>
function wfsubmit(nexttask,nextuserid)
{var rtn = $('#frm').form('validate');if(!rtn)return;var userId = '';if('end' != nexttask && 'endall' != nexttask && 'destory' != nexttask){if(nextuserid == null || nextuserid == ''){$.messager.alert('错误提示','下一办理人为空!','error');return;}var objdim = nextuserid.split(";");for(var k=0;k<objdim.length;k++){var objdim2 = objdim[k].split(",");if(objdim2[0] == null || objdim2[0] == ''){$.messager.alert('错误提示','下一办理人为空!','error');return;}userId = userId + objdim2[0] + ',';}}//alert(nexttask+'---'+userId);var rtn = $('#frm').form('validate');if(rtn){$('#nexttask').val(nexttask);$('#nextUserId').val(userId);$('#frm').form('submit', {    url:'/expsubmit.action',    onSubmit: function(){    },    success:function(data){alert(data);alert(data.instProcessId);$('#buttondiv').empty();loadimg(data.instProcessId);}});}
}
function loadimg(instprocessid)
{var url = $("#wfuiimg").attr('src');$("#wfuiimg").attr('src', url+'&instprocessid='+instprocessid+'&r='+ Math.random());
}
</script>
</head>
<body class="easyui-layout"><div data-options="region:'center',title:'部门维护'" style="padding:5px;"><div ><img id="wfuiimg" height="100" width="800" src="/downimg.jsp?width=800&height=100&processid=expense&instprocessid=${instprocessid}&instanceid=${eps.id}&t=<%=new Date()%>"/></div><form id="frm" method="post"><input type="hidden" id="instprocessid" name="instprocessid" value="${instprocessid}"/><input type="hidden" id="instactivityid" name="instactivityid" value="${instactivityid}"/><input type="hidden" id="instworkitemid" name="instworkitemid" value="${instworkitemid}"/><input type="hidden" id="id" name="id" value="${eps.id}"/><input type="hidden" id="nexttask" name="nexttask"/><input type="hidden" id="nextUserId" name="nextUserId"/><input type="hidden" id="userId" name="userId" value="${eps.userId}"/><div style="margin-left:50px;margin-top:30px">   <input class="easyui-textbox" type="text" id="name" name="name" value="${eps.name}" data-options="width:300,label:'请款名称:'" />   </div>   <div style="margin-left:50px;margin-top:30px"> <input class="easyui-textbox" type="text" id="company" name="company" value="${eps.company}" data-options="width:300,label:'公司名称:'" />   </div><div style="margin-left:50px;margin-top:30px"> <input class="easyui-textbox" type="text" id="bank" name="bank" value="${eps.bank}" data-options="width:300,label:'银行名称:'" />   </div><div style="margin-left:50px;margin-top:30px"> <input class="easyui-textbox" type="text" id="bankAccount" name="bankAccount" value="${eps.bankAccount}" data-options="width:300,label:'银行账号:'" />   </div><div style="margin-left:50px;margin-top:30px"> <input class="easyui-textbox" type="text" id="amount" name="amount" value="${eps.amount}" data-options="width:300,label:'金额(单位:分):'" />   </div><div id="buttondiv" style="margin-left:50px;margin-top:30px">
<%List<Properties> button = (List<Properties>)request.getAttribute("button");for(Properties prop:button){String name = prop.getProperty("name");String js = prop.getProperty("js");
%><a id="btn" onclick="<%=js %>" class="easyui-linkbutton"><%=name %></a>
<%}
%>  </div></form></div>
</body>
</html>

十八、报销单流程开发相关推荐

  1. NC报销单流程如何重新修改

                    报销单审批定义 一.审批流定义 二.根据单据流程重新修改或创建新流程

  2. 跟燕十八学习PHP-第十八天-开发项目(2)

    /**  燕十八 公益PHP培训  课堂地址:YY频道88354001  学习社区:www.zixue.it  **/ <?php require('./include/init.php'); ...

  3. 智能一代云平台(三十八):单元测试推动开发,如何避免服务之间依赖拖了工期

    [前言] 在开发过程中,会涉及到调用别人的服务,这时候由于别的服务的工期确实排的比较紧张,自己需要等,下面我们采用了写mock数据的方式来有效的避免了这种情况,提高开发速度. [如何提高速度] 一.针 ...

  4. ballerina 学习二十八 快速grpc 服务开发

    ballerina 的grpc 开发模型,对于开发者来说简单了好多,不是schema first 的方式,而是我们 只要编写简单的ballerina service 就可以了,proto 文件是自动帮 ...

  5. Hello Qt(二十八)——计算器实例开发

    一.计算器界面制作 计算器界面需要QWidget组件作为顶层窗口,QLineEdit组件作为输入框,QPsuhButton作为按钮. 界面规划设计如下: #include <QApplicati ...

  6. 纸质的报销单错了就得重新来,可不可以填写电子报销单?

    电子报销单是一款以财务为中心,以电子发票及其他纸质发票为核心功能的报销单提交工具,其目的通过发票管理与单据提交功能智能数字化,取代传统的纸质单据的填写,为企业提供关键财务数据数字化服务. 其基本功能为 ...

  7. 使用O2OA二次开发搭建企业办公平台(十三)流程开发篇:报销审批流程表单开发...

    本博客为O2OA系列教程.O2OA使用手册,教程目录和各章节天梯将在连载完后更新. 使用O2OA二次开发搭建企业办公平台(一)平台部署篇:平台下载和部署 使用O2OA二次开发搭建企业办公平台(二)平台 ...

  8. 使用O2OA二次开发搭建企业办公平台(十三)流程开发篇:报销审批流程表单开发

    本博客为O2OA系列教程.O2OA使用手册,教程目录和各章节天梯将在连载完后更新. 使用O2OA二次开发搭建企业办公平台(一)平台部署篇:平台下载和部署 使用O2OA二次开发搭建企业办公平台(二)平台 ...

  9. 使用O2OA二次开发搭建企业办公平台(十五)流程开发篇:创建报销审批流程

    本博客为O2OA系列教程.O2OA使用手册,教程目录和各章节天梯将在连载完后更新. 使用O2OA二次开发搭建企业办公平台(一)平台部署篇:平台下载和部署 使用O2OA二次开发搭建企业办公平台(二)平台 ...

最新文章

  1. C++如何监听http请求
  2. 【测评】海康EliteX---全球首款USB4.0移动固态硬盘,硬盘黑科技,移动闪电侠
  3. 基于事件驱动架构构建微服务第5部分:容器化(Web Api Core 和 SQL Server Linux)
  4. mysql 查询默认编码_查看及修改MYSQL默认编码
  5. 阿里云部署flask
  6. systemctl和正则表达式
  7. 数据结构实验:电话号码查询系统
  8. Pr2023(Premiere Pro)中文版软件下载「附带安装教程」
  9. 如何求复数的模用计算机,Excel怎么计算复数? Excel对复数进行加减乘除指数对数模的教程...
  10. 域控制器组策略:部署软件自动下发
  11. 网站被黑总被跳转到其他网站的处理解决过程
  12. 苹果mac系统隐藏文件的显示和取消显示
  13. linux 的源码怎么查看,查看linux源代码
  14. 最新自己怎么建网站零基础教程-李廷学
  15. 网络远程访问的方式使用树莓派
  16. konga 连接postgresql 12+启动异常:error: column r.consrc does not exist
  17. web前端,css清除浮动的常见方法
  18. AppleScript基础语法讲解
  19. hana服务器销售资质,hana认证服务器
  20. plot取部分点画图,解决了plot函数画图时标记过多!

热门文章

  1. php中ceil的用法,php ceil函数怎么用?
  2. ITE(新联阳) soc显控芯片介绍
  3. html5之太阳地球月球,使用html5画出地球月球和太阳之间的环绕关系
  4. 视频内容相似度视频数字版权 综述
  5. 不要踏入window这条贼船 java也不要碰
  6. 【hibernate框架】面向对象的查询语法(QBE和QBC)
  7. ei eo eq什么意思_软件功能点估算
  8. SPICE模型库网址
  9. centos 7 定时备份文件夹,增量文件
  10. 【转载】数据分析中的两种偏差(选择性偏差、幸存者偏差)