十八、报销单流程开发
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>
十八、报销单流程开发相关推荐
- NC报销单流程如何重新修改
报销单审批定义 一.审批流定义 二.根据单据流程重新修改或创建新流程
- 跟燕十八学习PHP-第十八天-开发项目(2)
/** 燕十八 公益PHP培训 课堂地址:YY频道88354001 学习社区:www.zixue.it **/ <?php require('./include/init.php'); ...
- 智能一代云平台(三十八):单元测试推动开发,如何避免服务之间依赖拖了工期
[前言] 在开发过程中,会涉及到调用别人的服务,这时候由于别的服务的工期确实排的比较紧张,自己需要等,下面我们采用了写mock数据的方式来有效的避免了这种情况,提高开发速度. [如何提高速度] 一.针 ...
- ballerina 学习二十八 快速grpc 服务开发
ballerina 的grpc 开发模型,对于开发者来说简单了好多,不是schema first 的方式,而是我们 只要编写简单的ballerina service 就可以了,proto 文件是自动帮 ...
- Hello Qt(二十八)——计算器实例开发
一.计算器界面制作 计算器界面需要QWidget组件作为顶层窗口,QLineEdit组件作为输入框,QPsuhButton作为按钮. 界面规划设计如下: #include <QApplicati ...
- 纸质的报销单错了就得重新来,可不可以填写电子报销单?
电子报销单是一款以财务为中心,以电子发票及其他纸质发票为核心功能的报销单提交工具,其目的通过发票管理与单据提交功能智能数字化,取代传统的纸质单据的填写,为企业提供关键财务数据数字化服务. 其基本功能为 ...
- 使用O2OA二次开发搭建企业办公平台(十三)流程开发篇:报销审批流程表单开发...
本博客为O2OA系列教程.O2OA使用手册,教程目录和各章节天梯将在连载完后更新. 使用O2OA二次开发搭建企业办公平台(一)平台部署篇:平台下载和部署 使用O2OA二次开发搭建企业办公平台(二)平台 ...
- 使用O2OA二次开发搭建企业办公平台(十三)流程开发篇:报销审批流程表单开发
本博客为O2OA系列教程.O2OA使用手册,教程目录和各章节天梯将在连载完后更新. 使用O2OA二次开发搭建企业办公平台(一)平台部署篇:平台下载和部署 使用O2OA二次开发搭建企业办公平台(二)平台 ...
- 使用O2OA二次开发搭建企业办公平台(十五)流程开发篇:创建报销审批流程
本博客为O2OA系列教程.O2OA使用手册,教程目录和各章节天梯将在连载完后更新. 使用O2OA二次开发搭建企业办公平台(一)平台部署篇:平台下载和部署 使用O2OA二次开发搭建企业办公平台(二)平台 ...
最新文章
- C++如何监听http请求
- 【测评】海康EliteX---全球首款USB4.0移动固态硬盘,硬盘黑科技,移动闪电侠
- 基于事件驱动架构构建微服务第5部分:容器化(Web Api Core 和 SQL Server Linux)
- mysql 查询默认编码_查看及修改MYSQL默认编码
- 阿里云部署flask
- systemctl和正则表达式
- 数据结构实验:电话号码查询系统
- Pr2023(Premiere Pro)中文版软件下载「附带安装教程」
- 如何求复数的模用计算机,Excel怎么计算复数? Excel对复数进行加减乘除指数对数模的教程...
- 域控制器组策略:部署软件自动下发
- 网站被黑总被跳转到其他网站的处理解决过程
- 苹果mac系统隐藏文件的显示和取消显示
- linux 的源码怎么查看,查看linux源代码
- 最新自己怎么建网站零基础教程-李廷学
- 网络远程访问的方式使用树莓派
- konga 连接postgresql 12+启动异常:error: column r.consrc does not exist
- web前端,css清除浮动的常见方法
- AppleScript基础语法讲解
- hana服务器销售资质,hana认证服务器
- plot取部分点画图,解决了plot函数画图时标记过多!