@@ -0,0 +1,145 @@ | |||
package cc.smtweb.system.bpm.web.design.flow; | |||
import cc.smtweb.framework.core.exception.BizException; | |||
import cc.smtweb.framework.core.util.CommUtil; | |||
import cc.smtweb.system.bpm.web.design.flow.define.Activity; | |||
import cc.smtweb.system.bpm.web.design.flow.define.Trans; | |||
import cc.smtweb.system.bpm.web.sys.base.billFlow.BillFlow; | |||
import cc.smtweb.system.bpm.web.sys.base.billFlow.BillFlowCache; | |||
import cc.smtweb.system.bpm.web.sys.user.userGroup.UserGroupHelper; | |||
import java.util.ArrayList; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
import java.util.Set; | |||
/** | |||
* Created by Akmm at 2022-08-02 18:38 | |||
* 工作流定义辅助类 | |||
*/ | |||
public class ModelProcHelper { | |||
/** | |||
* 获取配置的工作流程定义 | |||
* | |||
* @param bill_type 单据类型,常量 | |||
* @param user_id | |||
* @return | |||
*/ | |||
public static ModelProc getBillProc(int bill_type, long user_id) throws Exception { | |||
Set<BillFlow> list = BillFlowCache.getInstance().getByBillType(bill_type); | |||
if (CommUtil.isEmpty(list)) { | |||
return null; | |||
} | |||
long pcid = 0L; | |||
for (BillFlow bean : list) { | |||
//找到一个就走 | |||
if (UserGroupHelper.isInGroup(user_id, bean.getUserGroup())) { | |||
pcid = bean.getProc(); | |||
break; | |||
} | |||
} | |||
return ModelProcCache.getInstance().get(pcid); | |||
} | |||
/** | |||
* 得到流程的第一个活动步骤(开始节点出来的第一个节点) | |||
* | |||
* @param proc_id | |||
* @return | |||
*/ | |||
public static Activity getFirstActivity(String proc_id) { | |||
ModelProc proc = ModelProcCache.getInstance().get(proc_id); | |||
if (proc == null) return null; | |||
Activity start = null; | |||
//先找开始节点 | |||
List<Activity> list = proc.getProcInfo().getActivities(); | |||
for (Activity act : list) { | |||
if (act.getType() == FlowConst.ActivityType.START.value) { | |||
start = act; | |||
break; | |||
} | |||
} | |||
if (start == null) return null; | |||
//开始节点出去的第一个节点就是制单节点 | |||
for (Trans trans : proc.getProcInfo().getTrans()) { | |||
if (start.getId().equals(trans.getSrc())) { | |||
return proc.getProcInfo().findActivity(trans.getDst()); | |||
} | |||
} | |||
return null; | |||
} | |||
/** | |||
* 得到指定活动的下一任务节点 | |||
* | |||
* @param act_id | |||
* @return | |||
*/ | |||
public static Activity getNextActivity(String act_id) throws BizException { | |||
/*Activity act = ActivityBuffer.getInstance().get(act_id); | |||
if (act == null) { | |||
throw new BizException("未找到指定的活动节点定义!"); | |||
} | |||
List<Trans> list = TransBuffer.getInstance().getListByProcId(act.getProcId()); | |||
for (Trans t : list) { | |||
if (act_id.equals(t.getSrcAct())) { | |||
act = ActivityBuffer.getInstance().get(t.getDstAct()); | |||
return act; | |||
} | |||
} | |||
*/ | |||
return null; | |||
} | |||
/** | |||
* 得到指定活动的流出转移条件列表,按序号排序,act为并发/条件分支 | |||
* | |||
* @param act_id | |||
* @return | |||
*/ | |||
public static List<Trans> getNextTrans(String act_id) throws BizException { | |||
/*Activity act = ActivityBuffer.getInstance().get(act_id); | |||
if (act == null) { | |||
throw new BizException("未找到指定的活动节点定义!"); | |||
} | |||
List<Trans> listRet = new ArrayList<>(); | |||
List<Trans> list = TransBuffer.getInstance().getListByProcId(act.getProcId()); | |||
for (Trans t : list) { | |||
if (act_id.equals(t.getSrcAct())) { | |||
listRet.add(t); | |||
} | |||
} | |||
listRet.sort(Comparator.comparingInt(Trans::getTransSeq)); | |||
return listRet; | |||
*/ | |||
return null; | |||
} | |||
/** | |||
* 获取流程定义属性值 | |||
* | |||
* @param proc_id 流程定义id | |||
* @param ele_id 元素id | |||
* @param key 属性名 | |||
* @return | |||
*/ | |||
public static String getPropStr(String proc_id, String ele_id, String key) { | |||
// return PropertyEntityBuffer.getInstance().getPropValue(proc_id, ele_id, key); | |||
return null; | |||
} | |||
public static boolean getPropBool(String proc_id, String ele_id, String key) { | |||
// return UtilPub.toBoolean(getPropStr(proc_id, ele_id, key), false); | |||
return false; | |||
} | |||
public static int getPropInt(String proc_id, String ele_id, String key) { | |||
// return UtilPub.getIntIgnoreErr(getPropStr(proc_id, ele_id, key)); | |||
return 0; | |||
} | |||
} |
@@ -1,6 +1,7 @@ | |||
package cc.smtweb.system.bpm.web.design.flow.define; | |||
import lombok.Data; | |||
import org.apache.commons.lang3.StringUtils; | |||
import java.util.List; | |||
@@ -20,4 +21,14 @@ public class ProcInfo { | |||
private List<Activity> activities; | |||
//连接线 | |||
private List<Trans> trans; | |||
public Activity findActivity(String id) { | |||
if (StringUtils.isEmpty(id)) return null; | |||
for (Activity act: activities) { | |||
if (id.equalsIgnoreCase(act.getId())) { | |||
return act; | |||
} | |||
} | |||
return null; | |||
} | |||
} |
@@ -215,4 +215,9 @@ public class ModelForm extends DefaultEntity { | |||
public void setParent(long mf_parent) { | |||
put("mf_parent", mf_parent); | |||
} | |||
//返回单据类型id | |||
public long getBillType() { | |||
return getOpts().readLong("billType"); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package cc.smtweb.system.bpm.web.engine.flow; | |||
import cc.smtweb.framework.core.common.R; | |||
import cc.smtweb.system.bpm.web.engine.dynPage.AbstractDynPageHandler; | |||
/** | |||
* Created by Akmm at 2022/4/21 17:53 | |||
* 保存指定数据集操作 | |||
* 入参:{pageId, data:} | |||
*/ | |||
public class AbstractFlowHandler extends AbstractDynPageHandler { | |||
/** | |||
* 办理签收 | |||
*/ | |||
public R handle() { | |||
return R.success(); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package cc.smtweb.system.bpm.web.engine.flow; | |||
import cc.smtweb.framework.core.common.R; | |||
import cc.smtweb.system.bpm.web.engine.dynPage.AbstractDynPageHandler; | |||
/** | |||
* Created by Akmm at 2022/4/21 17:53 | |||
* 保存指定数据集操作 | |||
* 入参:{pageId, data:} | |||
*/ | |||
public class FlowHandler extends AbstractDynPageHandler { | |||
/** | |||
* 办理签收 | |||
*/ | |||
public R handle() { | |||
return R.success(); | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
package cc.smtweb.system.bpm.web.engine.flow; | |||
import cc.smtweb.framework.core.exception.BizException; | |||
import cc.smtweb.system.bpm.web.design.flow.FlowConst; | |||
import cc.smtweb.system.bpm.web.design.flow.ModelProcHelper; | |||
import cc.smtweb.system.bpm.web.design.flow.define.Activity; | |||
import cc.smtweb.system.bpm.web.design.flow.define.Trans; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
/** | |||
* Created by Akmm at 13-6-24 下午9:42 | |||
* 单据 | |||
*/ | |||
public class FlowHelper { | |||
/** | |||
* 得到指定活动的下一任务节点 | |||
* | |||
* @param act_id | |||
* @return | |||
*/ | |||
public static List<Activity> getNextActivity(FlowInstance flowInstance) throws Exception { | |||
Activity act = ModelProcHelper.getNextActivity(flowInstance.act_inst.getActId()); | |||
if (act == null) { | |||
throw new BizException("未找到可用的活动节点定义!"); | |||
} | |||
List<Activity> listRet = new ArrayList<>(); | |||
buildNextActivityRes(act, flowInstance, listRet); | |||
if (listRet.isEmpty()) { | |||
throw new BizException("未找到可用的活动节点定义!"); | |||
} | |||
return listRet; | |||
} | |||
/** | |||
* 递归处理,兼容判断后面加判断,并发后面跟并发 | |||
* | |||
* @param act | |||
* @param comp | |||
* @param listRet | |||
* @throws Exception | |||
*/ | |||
private static void buildNextActivityRes(Activity act, FlowInstance flowInstance, List<Activity> listRet) throws Exception { | |||
//待返回的结果集 | |||
// if (act.getActType() == FlowConst.ActivityType.scriptTask) 自动任务暂不支持 | |||
/*if (act.getType() == FlowConst.ActivityType.CONDITION.value) {//条件分支 | |||
List<Trans> list = ModelProcHelper.getNextTrans(act.getId()); | |||
for (Trans t : list) { | |||
if (flowInstance.execTrans(t.getExpr())) { | |||
Activity a = ActivityBuffer.getInstance().get(t.getDst()); | |||
if (a == null) { | |||
throw new BizException("无效的活动节点定义(" + t.getDst() + ")!"); | |||
} | |||
buildNextActivityRes(a, flowInstance, listRet); | |||
break; | |||
} | |||
} | |||
} else if (act.getActType() == FlowConst.ActivityType.parallelBegin.value) {//并发分支 | |||
List<Trans> list = BillFlowWfHelper.getNextTrans(act.getEntityId()); | |||
for (Trans t : list) { | |||
if (comp.execTrans(t.getCondExpr())) { | |||
Activity a = ActivityBuffer.getInstance().get(t.getDstAct()); | |||
if (a == null) { | |||
throw new BizException("无效的活动节点定义(" + t.getDstAct() + ")!"); | |||
} | |||
buildNextActivityRes(a, comp, listRet); | |||
} | |||
} | |||
} else { | |||
listRet.add(act); | |||
} | |||
*/ | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
package cc.smtweb.system.bpm.web.engine.flow; | |||
import cc.smtweb.framework.core.common.SwMap; | |||
import cc.smtweb.framework.core.db.DbEngine; | |||
import cc.smtweb.framework.core.db.EntityHelper; | |||
import cc.smtweb.framework.core.db.cache.ModelTableCache; | |||
import cc.smtweb.framework.core.db.vo.ModelTable; | |||
import cc.smtweb.framework.core.mvc.service.AbstractCompProvider; | |||
import cc.smtweb.framework.core.mvc.service.SqlNamedPara; | |||
import cc.smtweb.system.bpm.web.design.form.ModelForm; | |||
import cc.smtweb.system.bpm.web.design.form.ModelFormHelper; | |||
import cc.smtweb.system.bpm.web.design.form.define.PageDataset; | |||
import cc.smtweb.system.bpm.web.design.form.define.PageDatasets; | |||
import cc.smtweb.system.bpm.web.engine.dynPage.DynPageHelper; | |||
/** | |||
* Created by Akmm at 2022/5/26 18:40 | |||
* 工作流数据提供者 | |||
*/ | |||
public class FlowProvider extends AbstractCompProvider { | |||
//获取FlowInstance | |||
public FlowInstance findFlowInstance(long pageId, long us) { | |||
return doGetData("p_" + pageId, () -> { | |||
ModelForm form = ModelFormHelper.getFromCache(pageId); | |||
if (form == null || form.getBillType() <= 0L) return null; | |||
return null; | |||
}); | |||
} | |||
} |
@@ -1,15 +1,96 @@ | |||
package cc.smtweb.system.bpm.web.engine.flow; | |||
import cc.smtweb.framework.core.annotation.SwBody; | |||
import cc.smtweb.framework.core.common.R; | |||
import cc.smtweb.framework.core.common.SwMap; | |||
import cc.smtweb.framework.core.mvc.service.AbstractCompService; | |||
import cc.smtweb.framework.core.mvc.service.AbstractHandler; | |||
import cc.smtweb.framework.core.session.UserSession; | |||
/** | |||
* Created by Akmm at 2022/5/24 14:21 | |||
* 工作流 | |||
*/ | |||
public class FlowService extends AbstractCompService { | |||
public final static String TYPE_FLOW = "flow"; | |||
@Override | |||
protected AbstractHandler createHandler(String type) { | |||
return null; | |||
} | |||
protected R flowHandler(SwMap params, UserSession us, IFlowWorker worker) { | |||
try { | |||
FlowHandler handler = (FlowHandler)getHandler(params, us, TYPE_FLOW); | |||
return worker.doWork(handler); | |||
} catch (Exception e) { | |||
return R.error("操作失败!", e); | |||
} | |||
} | |||
/** | |||
* 办理,签收 | |||
* | |||
* @throws Exception | |||
*/ | |||
public void handle(@SwBody SwMap params, UserSession us) throws Exception { | |||
flowHandler(params, us, FlowHandler::handle); | |||
} | |||
/** | |||
* 提交 | |||
* | |||
* @throws Exception | |||
*/ | |||
public void submit(@SwBody SwMap params, UserSession us) throws Exception { | |||
flowHandler(params, us, FlowHandler::handle); | |||
} | |||
/** | |||
* 提交 | |||
* | |||
* @throws Exception | |||
*/ | |||
public void checkSubmit(@SwBody SwMap params, UserSession us) throws Exception { | |||
} | |||
/** | |||
* 作废 | |||
* | |||
* @throws Exception | |||
*/ | |||
public void disuse(@SwBody SwMap params, UserSession us) throws Exception { | |||
} | |||
/** | |||
* 取消提交 | |||
* | |||
* @throws Exception | |||
*/ | |||
public void retake(@SwBody SwMap params, UserSession us) throws Exception { | |||
} | |||
/** | |||
* 驳回 | |||
* | |||
* @throws Exception | |||
*/ | |||
public void reject(@SwBody SwMap params, UserSession us) throws Exception { | |||
} | |||
public void rejectToMake(@SwBody SwMap params, UserSession us) throws Exception { | |||
} | |||
interface IFlowWorker { | |||
R doWork(FlowHandler handler); | |||
} | |||
} |
@@ -0,0 +1,64 @@ | |||
package cc.smtweb.system.bpm.web.sys.base.billFlow; | |||
import cc.smtweb.framework.core.annotation.SwTable; | |||
import cc.smtweb.framework.core.common.SwMap; | |||
import cc.smtweb.framework.core.db.impl.DefaultEntity; | |||
/** | |||
* Created by 1 at 2022-08-02 20:44:36 | |||
* 实体【[单据流程分配](SYS_BILL_FLOW)】的Entity类 | |||
*/ | |||
@SwTable("SYS_BILL_FLOW") | |||
public class BillFlow extends DefaultEntity { | |||
public static final String ENTITY_NAME = "SYS_BILL_FLOW"; | |||
public BillFlow() { | |||
super(ENTITY_NAME); | |||
} | |||
/** 主键 */ | |||
public long getId() { | |||
return getLong("sbfl_id"); | |||
} | |||
/** 主键 */ | |||
public void setId(long sbfl_id) { | |||
put("sbfl_id", sbfl_id); | |||
} | |||
/** 用户组 */ | |||
public long getUserGroup() { | |||
return getLong("sbfl_user_group"); | |||
} | |||
/** 用户组 */ | |||
public void setUserGroup(long sbfl_user_group) { | |||
put("sbfl_user_group", sbfl_user_group); | |||
} | |||
/** 单据类型 */ | |||
public long getBillType() { | |||
return getLong("sbfl_bill_type"); | |||
} | |||
/** 单据类型 */ | |||
public void setBillType(long sbfl_bill_type) { | |||
put("sbfl_bill_type", sbfl_bill_type); | |||
} | |||
/** 流程 */ | |||
public long getProc() { | |||
return getLong("sbfl_proc"); | |||
} | |||
/** 流程 */ | |||
public void setProc(long sbfl_proc) { | |||
put("sbfl_proc", sbfl_proc); | |||
} | |||
/** 备注 */ | |||
public String getRemark() { | |||
return getStr("sbfl_remark"); | |||
} | |||
/** 备注 */ | |||
public void setRemark(String sbfl_remark) { | |||
put("sbfl_remark", sbfl_remark); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
package cc.smtweb.system.bpm.web.sys.base.billFlow; | |||
import cc.smtweb.framework.core.annotation.SwCache; | |||
import cc.smtweb.framework.core.cache.AbstractEntityCache; | |||
import cc.smtweb.framework.core.cache.CacheManager; | |||
import java.util.ArrayList; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
import java.util.Set; | |||
/** | |||
* Created by 1 at 2022-08-02 20:45:49 | |||
* 实体【[单据流程分配](SYS_BILL_FLOW)】的缓存类 | |||
*/ | |||
@SwCache(ident = "SYS_BILL_FLOW", title = "单据流程分配") | |||
public class BillFlowCache extends AbstractEntityCache<BillFlow> { | |||
//缓存key:按单据类型 | |||
public final static String mk_b = "b"; | |||
public static BillFlowCache getInstance() { | |||
return CacheManager.getIntance().getCache(BillFlowCache.class); | |||
} | |||
public BillFlowCache() { | |||
//缓存key:按单据类型 | |||
regList(mk_b, "sbfl_bill_type"); | |||
} | |||
//缓存key:按单据类型 | |||
public final Set<BillFlow> getByBillType(int billType) { | |||
return getListByKey(mk_b, String.valueOf(billType)); | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
package cc.smtweb.system.bpm.web.sys.user.userGroup; | |||
import cc.smtweb.framework.core.annotation.SwTable; | |||
import cc.smtweb.framework.core.common.SwMap; | |||
import cc.smtweb.framework.core.db.impl.DefaultEntity; | |||
import cc.smtweb.framework.core.util.JsonUtil; | |||
import cc.smtweb.system.bpm.web.design.flow.define.ProcInfo; | |||
import cc.smtweb.system.bpm.web.design.form.define.PageDataset; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
/** | |||
* Created by 1 at 2022-08-02 20:19:02 | |||
* 实体【[用户分组](SYS_USER_GROUP)】的Entity类 | |||
*/ | |||
@SwTable("SYS_USER_GROUP") | |||
public class UserGroup extends DefaultEntity { | |||
public static final String ENTITY_NAME = "SYS_USER_GROUP"; | |||
private transient List<UserGroupItem> items = null; | |||
public UserGroup() { | |||
super(ENTITY_NAME); | |||
} | |||
public List<UserGroupItem> getItems() { | |||
if (items == null) { | |||
synchronized ("ModelProc_" + getId()) { | |||
if (items == null) { | |||
UserGroupItem[] list = JsonUtil.parse(getContent(), UserGroupItem[].class); | |||
List<UserGroupItem> l = new ArrayList<>(); | |||
Collections.addAll(l, list); | |||
items = l; | |||
} | |||
} | |||
} | |||
return items; | |||
} | |||
/** 主键 */ | |||
public long getId() { | |||
return getLong("sugp_id"); | |||
} | |||
/** 主键 */ | |||
public void setId(long sugp_id) { | |||
put("sugp_id", sugp_id); | |||
} | |||
/** 编码 */ | |||
public String getCode() { | |||
return getStr("sugp_code"); | |||
} | |||
/** 编码 */ | |||
public void setCode(String sugp_code) { | |||
put("sugp_code", sugp_code); | |||
} | |||
/** 名称 */ | |||
public String getName() { | |||
return getStr("sugp_name"); | |||
} | |||
/** 名称 */ | |||
public void setName(String sugp_name) { | |||
put("sugp_name", sugp_name); | |||
} | |||
/** 备注 */ | |||
public String getRemark() { | |||
return getStr("sugp_remark"); | |||
} | |||
/** 备注 */ | |||
public void setRemark(String sugp_remark) { | |||
put("sugp_remark", sugp_remark); | |||
} | |||
/** 分组详细 */ | |||
public String getContent() { | |||
return getStr("sugp_content"); | |||
} | |||
/** 分组详细 */ | |||
public void setContent(String sugp_content) { | |||
put("sugp_content", sugp_content); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
package cc.smtweb.system.bpm.web.sys.user.userGroup; | |||
import cc.smtweb.framework.core.annotation.SwCache; | |||
import cc.smtweb.framework.core.cache.AbstractEntityCache; | |||
import cc.smtweb.framework.core.cache.CacheManager; | |||
import java.util.ArrayList; | |||
import java.util.Comparator; | |||
import java.util.List; | |||
import java.util.Set; | |||
/** | |||
* Created by 1 at 2022-08-02 20:19:02 | |||
* 实体【[用户分组](SYS_USER_GROUP)】的缓存类 | |||
*/ | |||
@SwCache(ident = "SYS_USER_GROUP", title = "用户分组") | |||
public class UserGroupCache extends AbstractEntityCache<UserGroup> { | |||
//缓存key:按编码 | |||
public final static String mk_code = "code"; | |||
public static UserGroupCache getInstance() { | |||
return CacheManager.getIntance().getCache(UserGroupCache.class); | |||
} | |||
public UserGroupCache() { | |||
//缓存key:按编码 | |||
regMap(mk_code, "sugp_code"); | |||
} | |||
//缓存key:按编码 | |||
public final UserGroup getByCode(String key) { | |||
return getByKey(mk_code, key); | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
package cc.smtweb.system.bpm.web.sys.user.userGroup; | |||
import cc.smtweb.framework.core.util.CommUtil; | |||
import java.util.List; | |||
/** | |||
* Created by Akmm at 2022-08-02 20:19 | |||
* 用户分组辅助类 | |||
*/ | |||
public class UserGroupHelper { | |||
/** | |||
* 用户是否在权限组 | |||
* | |||
* @param user_id | |||
* @param group_id | |||
* @return | |||
*/ | |||
public static boolean isInGroup(long user_id, long group_id) { | |||
/*if (group_id <= 0L) return true;//未设置分组,默认true | |||
UserGroup group = UserGroupCache.getInstance().get(group_id); | |||
List<UserGroupItem> items = group.getItems(); | |||
//设置了却没有找到分组,默认无权限 | |||
if (CommUtil.isEmpty(items)) { | |||
return false; | |||
}*/ | |||
return true; | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
package cc.smtweb.system.bpm.web.sys.user.userGroup; | |||
import lombok.Data; | |||
/** | |||
* Created by Akmm at 2022-08-02 20:21 | |||
* 用户分组明细 | |||
*/ | |||
@Data | |||
public class UserGroupItem { | |||
//"type": "类型,1-机构 2-部门 3-角色 4-人员 5-机构性质 5-部门性质", | |||
private int type; | |||
//"kind": "0-包含 1-排除", | |||
private int kind; | |||
//"value": "值", | |||
private String value; | |||
//"rec": "树形结构有效:0-仅本级 1-含下级" | |||
private int rec; | |||
} |