引入工作流程activiti 6.0
parent
1485897c9c
commit
a64949e943
12
build.gradle
12
build.gradle
|
@ -60,6 +60,18 @@ dependencies {
|
|||
|
||||
compile group: 'commons-lang', name: 'commons-lang', version: '2.6'
|
||||
|
||||
|
||||
compile group: 'org.projectlombok', name: 'lombok', version: '1.16.20'
|
||||
|
||||
/*activiti start*/
|
||||
compile group: 'org.activiti', name: 'activiti-spring-boot-starter-basic', version: '6.0.0'
|
||||
|
||||
/*activiti在线编辑器相关*/
|
||||
compile group: 'org.activiti', name: 'activiti-json-converter', version: '6.0.0'
|
||||
compile group: 'org.apache.xmlgraphics', name: 'batik-codec', version: '1.7'
|
||||
/*activiti end*/
|
||||
|
||||
|
||||
compileOnly 'org.springframework.boot:spring-boot-configuration-processor'
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package cn.palmte.work.config.activiti;
|
||||
|
||||
public class ActConstant {
|
||||
|
||||
/**
|
||||
* 流程启动用户变量
|
||||
*/
|
||||
public static final String START_PROCESS_USERID="startUserId";
|
||||
|
||||
|
||||
public static final String PROC_INS_ID="procInsId";
|
||||
|
||||
/**
|
||||
* 第一个用户任务 即:发起申请任务
|
||||
*/
|
||||
public static final int TASK_INDEX_FIRST_USER_TASK= 1;
|
||||
|
||||
public static final int TYPE_APPROVE= 1;
|
||||
public static final int TYPE_ROLLBACK= 2;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package cn.palmte.work.config.activiti;
|
||||
|
||||
import org.activiti.spring.SpringProcessEngineConfiguration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class ActivitiConfig {
|
||||
|
||||
@Autowired
|
||||
PlatformTransactionManager transactionManager;
|
||||
|
||||
@Autowired
|
||||
DataSource dataSource;
|
||||
|
||||
@Bean
|
||||
public SpringProcessEngineConfiguration getProcessEngineConfiguration() {
|
||||
SpringProcessEngineConfiguration config = new SpringProcessEngineConfiguration();
|
||||
config.setDataSource(dataSource);
|
||||
config.setTransactionManager(transactionManager);
|
||||
config.setDbHistoryUsed(true);
|
||||
config.setHistory("full");
|
||||
config.setActivityFontName("宋体");
|
||||
|
||||
//数据库更新策略
|
||||
//flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。(生产环境常用)
|
||||
//true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。(开发时常用)
|
||||
//create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。(单元测试常用)
|
||||
//drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。
|
||||
config.setDatabaseSchemaUpdate("true");
|
||||
return config;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package cn.palmte.work.controller.backend;
|
||||
|
||||
|
||||
import cn.palmte.work.bean.ResponseMsg;
|
||||
import cn.palmte.work.service.ActModelService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 流程模型
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/actModel")
|
||||
public class ActModelController extends BaseController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActModelController.class);
|
||||
|
||||
@Autowired
|
||||
private ActModelService activitiModelService;
|
||||
|
||||
@RequestMapping("/list")
|
||||
public String list(@RequestParam(value = "keywords", required = false) String keywords,
|
||||
@RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber,
|
||||
@RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize,
|
||||
Map<String, Object> model) {
|
||||
ConcurrentHashMap<String, String> searchInfo = getSearchInfo(keywords, model);
|
||||
model.put("pager", activitiModelService.list(searchInfo, pageNumber, pageSize));
|
||||
return "/admin/act_model_list";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/add")
|
||||
public String add(Map<String, Object> model) {
|
||||
return "/admin/act_model_input";
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
public String save(HttpServletRequest request) {
|
||||
try {
|
||||
activitiModelService.createModel(request.getParameter("procDefKey"), request.getParameter("modelName"));
|
||||
} catch (Exception e) {
|
||||
logger.error("", e);
|
||||
}
|
||||
return "redirect:/actModel/list";
|
||||
}
|
||||
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/delete")
|
||||
public ResponseMsg delete(@RequestParam("ids") String ids) {
|
||||
if ("".equals(ids)) {
|
||||
return ResponseMsg.buildFailedMsg("删除失败,无选中项!");
|
||||
} else {
|
||||
String[] deleteIds = ids.split("#%#");
|
||||
for (String id : deleteIds) {
|
||||
activitiModelService.deleteModel(id);
|
||||
}
|
||||
return ResponseMsg.buildSuccessMsg("删除成功");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/deploy")
|
||||
public ResponseMsg deploy(@RequestParam("id") String id) {
|
||||
try {
|
||||
activitiModelService.deploy(id);
|
||||
} catch (Exception e) {
|
||||
logger.error("", e);
|
||||
return ResponseMsg.buildFailedMsg(e.getMessage());
|
||||
}
|
||||
return ResponseMsg.buildSuccessMsg("部署成功");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package cn.palmte.work.controller.backend;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.activiti.editor.constants.ModelDataJsonConstants;
|
||||
import org.activiti.engine.ActivitiException;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.repository.Model;
|
||||
import org.apache.batik.transcoder.TranscoderInput;
|
||||
import org.apache.batik.transcoder.TranscoderOutput;
|
||||
import org.apache.batik.transcoder.image.PNGTranscoder;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* 流程网页编辑器
|
||||
*/
|
||||
@RestController
|
||||
public class ActModelEditorController implements ModelDataJsonConstants {
|
||||
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(ActModelEditorController.class);
|
||||
|
||||
@Autowired
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
|
||||
/**
|
||||
* 获取编辑器汉化文件
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/editor/stencilset", method = RequestMethod.GET, produces = "application/json;charset=utf-8")
|
||||
public String getStencilset() {
|
||||
InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json");
|
||||
try {
|
||||
return IOUtils.toString(stencilsetStream, "utf-8");
|
||||
} catch (Exception e) {
|
||||
//logger.error("an exception happens in try catch statement", e);
|
||||
throw new ActivitiException("Error while loading stencil set", e);
|
||||
} finally {
|
||||
if (stencilsetStream != null) {
|
||||
try {
|
||||
stencilsetStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据模型id获取json格式的数据
|
||||
*
|
||||
* @param modelId
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json")
|
||||
public ObjectNode getEditorJson(@PathVariable String modelId) {
|
||||
ObjectNode modelNode = null;
|
||||
Model model = repositoryService.getModel(modelId);
|
||||
if (model != null) {
|
||||
try {
|
||||
if (StringUtils.isNotEmpty(model.getMetaInfo())) {
|
||||
modelNode = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
|
||||
} else {
|
||||
modelNode = objectMapper.createObjectNode();
|
||||
modelNode.put(MODEL_NAME, model.getName());
|
||||
}
|
||||
modelNode.put(MODEL_ID, model.getId());
|
||||
String content = new String(repositoryService.getModelEditorSource(model.getId()), "utf-8");
|
||||
ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(content);
|
||||
modelNode.put("model", editorJsonNode);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("an exception happens in try catch statement", e);
|
||||
throw new ActivitiException("Error creating model JSON", e);
|
||||
}
|
||||
}
|
||||
return modelNode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 报错模型数据
|
||||
*
|
||||
* @param modelId
|
||||
* @param values
|
||||
*/
|
||||
@ResponseStatus(value = HttpStatus.OK)
|
||||
@RequestMapping(value = "/model/{modelId}/save", method = RequestMethod.PUT)
|
||||
public void saveModel(@PathVariable String modelId, @RequestParam MultiValueMap<String, String> values) {
|
||||
try {
|
||||
Model model = repositoryService.getModel(modelId);
|
||||
ObjectNode modelJson = (ObjectNode) objectMapper.readTree(model.getMetaInfo());
|
||||
modelJson.put(MODEL_NAME, values.getFirst("name"));
|
||||
modelJson.put(MODEL_DESCRIPTION, values.getFirst("description"));
|
||||
model.setMetaInfo(modelJson.toString());
|
||||
model.setName(values.getFirst("name"));
|
||||
repositoryService.saveModel(model);
|
||||
repositoryService.addModelEditorSource(model.getId(), values.getFirst("json_xml").getBytes("utf-8"));
|
||||
InputStream svgStream = new ByteArrayInputStream(values.getFirst("svg_xml").getBytes("utf-8"));
|
||||
TranscoderInput input = new TranscoderInput(svgStream);
|
||||
PNGTranscoder transcoder = new PNGTranscoder();
|
||||
// Setup output
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
TranscoderOutput output = new TranscoderOutput(outStream);
|
||||
// Do the transformation
|
||||
transcoder.transcode(input, output);
|
||||
final byte[] result = outStream.toByteArray();
|
||||
repositoryService.addModelEditorSourceExtra(model.getId(), result);
|
||||
outStream.close();
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("an exception happens in try catch statement", e);
|
||||
throw new ActivitiException("Error saving model", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package cn.palmte.work.controller.backend;
|
||||
|
||||
|
||||
import cn.palmte.work.bean.ResponseMsg;
|
||||
import cn.palmte.work.service.ActProcDefService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 流程定义
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/actProcDef")
|
||||
public class ActProcDefController extends BaseController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActProcDefController.class);
|
||||
|
||||
@Autowired
|
||||
private ActProcDefService actProcDefService;
|
||||
|
||||
@RequestMapping("/list")
|
||||
public String list(@RequestParam(value = "keywords", required = false) String keywords,
|
||||
@RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber,
|
||||
@RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize,
|
||||
Map<String, Object> model) {
|
||||
ConcurrentHashMap<String, String> searchInfo = getSearchInfo(keywords, model);
|
||||
model.put("pager", actProcDefService.list(searchInfo, pageNumber, pageSize));
|
||||
return "/admin/act_proc_def_list";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查看默认的未标红的流程图片
|
||||
*
|
||||
* @param response
|
||||
* @param deploymentId
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping("/procDefPng/{deploymentId}")
|
||||
public void png(HttpServletResponse response, @PathVariable("deploymentId") String deploymentId) throws Exception {
|
||||
actProcDefService.createProcDefPng(response, deploymentId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查看流程xml
|
||||
*
|
||||
* @param deploymentId
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/xml/{deploymentId}")
|
||||
public void xml(HttpServletResponse response, @PathVariable("deploymentId") String deploymentId) throws Exception {
|
||||
actProcDefService.getXmlByDeploymentId(response, deploymentId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除流程
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/delete")
|
||||
public ResponseMsg delete(@RequestParam("ids") String ids) {
|
||||
if ("".equals(ids)) {
|
||||
return ResponseMsg.buildFailedMsg("删除失败,无选中项!");
|
||||
} else {
|
||||
String[] deleteIds = ids.split("#%#");
|
||||
for (String id : deleteIds) {
|
||||
actProcDefService.deleteDeployment(id);
|
||||
}
|
||||
return ResponseMsg.buildSuccessMsg("删除成功");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 挂起与激活
|
||||
*
|
||||
* @param id
|
||||
* @param status 1-激活 2-挂起
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/suspend")
|
||||
public String suspend(@RequestParam String id, @RequestParam int status) {
|
||||
actProcDefService.suspend(id, status);
|
||||
return "redirect:/actProcDef/list";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package cn.palmte.work.controller.backend;
|
||||
|
||||
|
||||
import cn.palmte.work.bean.ResponseMsg;
|
||||
import cn.palmte.work.config.activiti.ActConstant;
|
||||
import cn.palmte.work.service.ActProcInsService;
|
||||
import cn.palmte.work.utils.InterfaceUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 流程实列相关
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/actProcIns")
|
||||
public class ActProcInsController extends BaseController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActProcInsController.class);
|
||||
|
||||
@Autowired
|
||||
private ActProcInsService actProcInsService;
|
||||
|
||||
/**
|
||||
* 列表
|
||||
* @param keywords
|
||||
* @param pageNumber
|
||||
* @param pageSize
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/list")
|
||||
public String list(@RequestParam(value = "keywords", required = false) String keywords,
|
||||
@RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber,
|
||||
@RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize,
|
||||
Map<String, Object> model) {
|
||||
ConcurrentHashMap<String, String> searchInfo = getSearchInfo(keywords, model);
|
||||
model.put("pager", actProcInsService.list(searchInfo, pageNumber, pageSize));
|
||||
return "/admin/act_proc_ins_list";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除流程实例
|
||||
*
|
||||
* @param procInsId
|
||||
* @param reason
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/deleteProcessInstance")
|
||||
public ResponseMsg deleteProcessInstance(@RequestParam String procInsId, @RequestParam String reason) {
|
||||
actProcInsService.deleteProcessInstance(procInsId, reason);
|
||||
return ResponseMsg.buildSuccessMsg("撤销成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 流程实列图片
|
||||
*
|
||||
* @param response
|
||||
* @param procInstId
|
||||
* @throws Exception
|
||||
*/
|
||||
@RequestMapping("/procInsPng/{procInstId}")
|
||||
public void png(HttpServletResponse response, @PathVariable("procInstId") String procInstId) throws Exception {
|
||||
actProcInsService.createProcInsPng(response, procInstId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动流程
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/startProcIns")
|
||||
public ResponseMsg startProcessInstance(@RequestParam String procDefKey) throws Exception{
|
||||
Map<String, Object> variables = new HashMap<>();
|
||||
variables.put(ActConstant.START_PROCESS_USERID, InterfaceUtil.getAdminId());
|
||||
String procInsId = actProcInsService.startProcessInstance(procDefKey, variables);
|
||||
return ResponseMsg.buildSuccessMsg("流程启动成功", procInsId);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package cn.palmte.work.controller.backend;
|
||||
|
||||
|
||||
import cn.palmte.work.bean.ResponseMsg;
|
||||
import cn.palmte.work.model.ActScript;
|
||||
import cn.palmte.work.model.ActScriptRepository;
|
||||
import cn.palmte.work.service.ActScriptService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 流程脚本管理
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/actScript")
|
||||
public class ActScriptController extends BaseController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActScriptController.class);
|
||||
|
||||
@Autowired
|
||||
private ActScriptService actScriptService;
|
||||
|
||||
@Autowired
|
||||
private ActScriptRepository actScriptRepository;
|
||||
|
||||
@RequestMapping("/list")
|
||||
public String list(@RequestParam(value = "keywords", required = false) String keywords,
|
||||
@RequestParam(value = PAGE_NUMBER, defaultValue = DEFAULT_PAGE_NUMBER) int pageNumber,
|
||||
@RequestParam(value = PAGE_SIZE, defaultValue = DEFAULT_PAGE_SIZE) int pageSize,
|
||||
Map<String, Object> model) {
|
||||
ConcurrentHashMap<String, String> searchInfo = getSearchInfo(keywords, model);
|
||||
model.put("pager", actScriptService.list(searchInfo, pageNumber, pageSize));
|
||||
return "/admin/act_script_list";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/add")
|
||||
public String add(Map<String, Object> model) {
|
||||
List<String> list = getScriptList();
|
||||
model.put("actScript", new ActScript());
|
||||
model.put("classList", list);
|
||||
|
||||
List<String> methodList = new ArrayList<>();
|
||||
for (String l : list) {
|
||||
methodList.addAll(getMethodList(l));
|
||||
}
|
||||
|
||||
model.put("methodList", methodList);
|
||||
return "/admin/act_script_input";
|
||||
}
|
||||
|
||||
private List<String> getScriptList() {
|
||||
List<String> list = new ArrayList<>(1);
|
||||
list.add("cn.palmte.work.service.ActCallbackScript");
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<String> getMethodList(String className) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
try {
|
||||
Method[] methods = Class.forName(className).getDeclaredMethods();
|
||||
for (Method method : methods) {
|
||||
list.add(method.getName());
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("", e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@GetMapping(value = "/edit")
|
||||
public String edit(@RequestParam int id, Map<String, Object> model) {
|
||||
List<String> list = getScriptList();
|
||||
model.put("actScript", actScriptRepository.findOne(id));
|
||||
model.put("classList", list);
|
||||
List<String> methodList = new ArrayList<>();
|
||||
for (String l : list) {
|
||||
methodList.addAll(getMethodList(l));
|
||||
}
|
||||
|
||||
model.put("methodList", methodList);
|
||||
return "/admin/act_script_input";
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
public String save(ActScript actScript) {
|
||||
actScriptService.save(actScript);
|
||||
return "redirect:/actScript/list";
|
||||
}
|
||||
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/delete")
|
||||
public ResponseMsg delete(@RequestParam("ids") String ids){
|
||||
if ("".equals(ids)){
|
||||
return ResponseMsg.buildFailedMsg("删除失败,无选中项!");
|
||||
}else {
|
||||
String[] deleteIds=ids.split("#%#");
|
||||
for (String id : deleteIds) {
|
||||
actScriptService.delete(Integer.parseInt(id));
|
||||
}
|
||||
return ResponseMsg.buildSuccessMsg("删除成功");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package cn.palmte.work.controller.backend;
|
||||
|
||||
|
||||
import cn.palmte.work.bean.ResponseMsg;
|
||||
import cn.palmte.work.model.ActScriptRepository;
|
||||
import cn.palmte.work.model.ActTaskDef;
|
||||
import cn.palmte.work.model.AdminRepository;
|
||||
import cn.palmte.work.service.ActTaskDefService;
|
||||
import cn.palmte.work.service.SysRoleService;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 流程任务
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/actTaskDef")
|
||||
public class ActTaskDefController extends BaseController {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActTaskDefController.class);
|
||||
|
||||
@Autowired
|
||||
private AdminRepository adminRepository;
|
||||
|
||||
@Autowired
|
||||
private SysRoleService sysRoleService;
|
||||
|
||||
@Autowired
|
||||
private ActScriptRepository actScriptRepository;
|
||||
|
||||
@Autowired
|
||||
private ActTaskDefService actTaskDefService;
|
||||
|
||||
/**
|
||||
* 去任务配置页面
|
||||
*
|
||||
* @param procDefId
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/config/{procDefId}")
|
||||
public String list(@PathVariable String procDefId, Map<String, Object> model) {
|
||||
List<ActTaskDef> list = actTaskDefService.findByProcDefId(procDefId);
|
||||
model.put("procDefId", procDefId);
|
||||
model.put("taskList", list);
|
||||
model.put("procDefName", list.get(0).getProcDefName());
|
||||
model.put("roleList", sysRoleService.getAllEnableSysRole());
|
||||
model.put("adminList", adminRepository.getAllEnable());
|
||||
model.put("scriptList", actScriptRepository.findAll());
|
||||
|
||||
return "/admin/act_task_def";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 任务配置保存
|
||||
*
|
||||
* @param taskDef
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping(value = "/saveConfig")
|
||||
public ResponseMsg saveConfig(ActTaskDef taskDef) {
|
||||
actTaskDefService.saveConfig(taskDef);
|
||||
return ResponseMsg.buildSuccessMsg("成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 完成某个任务
|
||||
* 审批通过或者驳回
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@PostMapping(value = "/completeTask")
|
||||
public ResponseMsg completeTask(@RequestBody String json) {
|
||||
JSONObject jsonParam = JSON.parseObject(json);
|
||||
actTaskDefService.completeTask(jsonParam);
|
||||
return ResponseMsg.buildSuccessMsg("处理成功");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package cn.palmte.work.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 流程脚本
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "act_script")
|
||||
public class ActScript {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private int id;
|
||||
|
||||
@Column(name = "script_name")
|
||||
private String scriptName;
|
||||
|
||||
/**
|
||||
* 脚本所在类
|
||||
*/
|
||||
@Column(name = "class_name")
|
||||
private String className;
|
||||
|
||||
/**
|
||||
* 脚本方法名
|
||||
*/
|
||||
@Column(name = "class_method")
|
||||
private String classMethod;
|
||||
|
||||
@Column(name = "created_time")
|
||||
private Date createdTime;
|
||||
|
||||
@Column(name = "last_updated_time")
|
||||
private Date lastUpdatedTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package cn.palmte.work.model;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
|
||||
public interface ActScriptRepository extends JpaRepository<ActScript, Integer> {
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package cn.palmte.work.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 流程图里解析出来的任务定义
|
||||
*/
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "act_task_def")
|
||||
public class ActTaskDef {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* 任务名称
|
||||
*/
|
||||
@Column(name = "task_name")
|
||||
private String taskName;
|
||||
|
||||
@Column(name = "task_key")
|
||||
private String taskKey;
|
||||
|
||||
/**
|
||||
* 任务类型 0-单实例(或签) 1-多实例(会签)
|
||||
*/
|
||||
@Column(name = "task_type")
|
||||
private int taskType;
|
||||
|
||||
@Column(name = "proc_def_id")
|
||||
private String procDefId;
|
||||
|
||||
@Column(name = "proc_def_name")
|
||||
private String procDefName;
|
||||
|
||||
@Column(name = "proc_def_key")
|
||||
private String procDefKey;
|
||||
|
||||
/**
|
||||
* 回退任务key
|
||||
*/
|
||||
@Column(name = "rollback_task_key")
|
||||
private String rollbackTaskKey;
|
||||
|
||||
/**
|
||||
* 节点位置 -1结束节点 0-开始节点 1-第一个用户任务
|
||||
*/
|
||||
@Column(name = "task_index")
|
||||
private int taskIndex;
|
||||
|
||||
|
||||
/**
|
||||
* 候选人
|
||||
*/
|
||||
@Column(name = "candidate_users")
|
||||
private String candidateUsers;
|
||||
|
||||
/**
|
||||
* 候选角色
|
||||
*/
|
||||
@Column(name = "candidate_roles")
|
||||
private String candidateRoles;
|
||||
|
||||
|
||||
/**
|
||||
* 审批通过执行的脚本 act_script表id
|
||||
*/
|
||||
@Column(name = "end_script")
|
||||
private int endScript;
|
||||
|
||||
/**
|
||||
* 审批驳回执行的脚本 act_script表id
|
||||
*/
|
||||
@Column(name = "rollback_script")
|
||||
private int rollbackScript;
|
||||
|
||||
@Column(name = "created_time")
|
||||
private Date createdTime;
|
||||
|
||||
@Column(name = "last_updated_time")
|
||||
private Date lastUpdatedTime;
|
||||
|
||||
|
||||
|
||||
@Transient
|
||||
private List<String> candidateUserList;
|
||||
|
||||
@Transient
|
||||
private List<String> candidateRoleList;
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package cn.palmte.work.model;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ActTaskDefRepository extends JpaRepository<ActTaskDef, Integer> {
|
||||
|
||||
|
||||
List<ActTaskDef> findByProcDefId(String procDefId);
|
||||
|
||||
|
||||
ActTaskDef findFirstByProcDefIdAndTaskKey(String procDefId, String taskKey);
|
||||
|
||||
void deleteByProcDefId(String procDefId);
|
||||
}
|
|
@ -34,4 +34,13 @@ public interface AdminRepository extends JpaRepository<Admin, Integer> {
|
|||
|
||||
@Query("from Admin where isDeleted=0 AND telephone=?1")
|
||||
Admin findByTelephone(String phone);
|
||||
|
||||
|
||||
/**
|
||||
* 查询所有未删除启用的账号
|
||||
* @return
|
||||
*/
|
||||
@Query("from Admin where isDeleted=0 AND enabled=1")
|
||||
List<Admin> getAllEnable();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package cn.palmte.work.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class ActModel {
|
||||
private int id;
|
||||
|
||||
private String modelName;
|
||||
|
||||
private int rev;
|
||||
|
||||
private String procDefKey;
|
||||
|
||||
private Date createdTime;
|
||||
|
||||
private Date lastUpdatedTime;
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package cn.palmte.work.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class ActProcDef {
|
||||
private String id;
|
||||
private String procName;
|
||||
private String procKey;
|
||||
private String version;
|
||||
private String deploymentId;
|
||||
private String resourceName;
|
||||
private String dgrmResourceName;
|
||||
private Date deployTime;
|
||||
private int suspensionState;
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package cn.palmte.work.pojo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class ActProcIns {
|
||||
private String procInsId;
|
||||
private String procName;
|
||||
private String procKey;
|
||||
private String version;
|
||||
|
||||
private String user;
|
||||
private Date startTime;
|
||||
|
||||
private String currentTask;
|
||||
private String currentTaskId;
|
||||
private String candidateUsers;
|
||||
|
||||
private Date endTime;
|
||||
|
||||
}
|
|
@ -17,15 +17,15 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
import top.jfunc.common.db.QueryHelper;
|
||||
import top.jfunc.common.db.bean.Page;
|
||||
import top.jfunc.common.db.bean.Record;
|
||||
import top.jfunc.common.db.utils.Pagination;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.beans.Transient;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Created by wang.lin@esstx.cn on 2018/4/20.
|
||||
|
@ -260,4 +260,38 @@ public class AccountService {
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过id查询姓名
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
public String getNameById(int id) {
|
||||
Admin one = adminRepository.findOne(id);
|
||||
return one == null ? "" : one.getRealName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过角色id查询用户姓名列表
|
||||
* @param roleIds
|
||||
* @return
|
||||
*/
|
||||
public List<String> getUserIsByRole(List<String> roleIds) {
|
||||
if (roleIds == null || roleIds.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
String sql = "select u.id as id from sys_user_role ur left join sys_user u on u.id=ur.user_id where ur.role_id in (?)";
|
||||
String ids = roleIds.stream().collect(Collectors.joining());
|
||||
List<Record> records = pagination.find(sql, ids);
|
||||
if (records == null || records.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<String> userIds = new ArrayList<>(roleIds.size());
|
||||
for (Record record : records) {
|
||||
userIds.add(record.getInt("id") + "");
|
||||
}
|
||||
return userIds;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package cn.palmte.work.service;
|
||||
|
||||
|
||||
import cn.palmte.work.config.activiti.ActConstant;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* 流程回调脚本 参数必须为Map
|
||||
*/
|
||||
@Service
|
||||
public class ActCallbackScript {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActCallbackScript.class);
|
||||
|
||||
|
||||
public void endScriptDemo(Map map) {
|
||||
logger.info("--- endScriptDemo--- : {} ", map);
|
||||
String startUserId = (String)map.get(ActConstant.START_PROCESS_USERID);
|
||||
String procInsId = (String)map.get(ActConstant.START_PROCESS_USERID);
|
||||
logger.info(" startUserId:{}, procInsId:{}", startUserId, procInsId);
|
||||
}
|
||||
|
||||
|
||||
public void rollbackScriptDemo(Map map) {
|
||||
logger.info("--- rollbackScriptDemo--- : {} ", map);
|
||||
String startUserId = (String)map.get(ActConstant.START_PROCESS_USERID);
|
||||
String procInsId = (String)map.get(ActConstant.START_PROCESS_USERID);
|
||||
logger.info(" startUserId:{}, procInsId:{}", startUserId, procInsId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package cn.palmte.work.service;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.activiti.engine.delegate.DelegateTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* 流程节点创建监听
|
||||
*/
|
||||
@Service
|
||||
public class ActListenerService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActListenerService.class);
|
||||
|
||||
|
||||
@Autowired
|
||||
private ActTaskDefService actTaskDefService;
|
||||
|
||||
public void create(DelegateTask delegateTask) throws Exception {
|
||||
logger.info("--- {}", JSONObject.toJSONString(delegateTask));
|
||||
|
||||
// 每一个任务节点监听运行时都要初始化流程定义规则数据到 流程引擎中
|
||||
String procDefId = delegateTask.getProcessDefinitionId();
|
||||
String procInsId = delegateTask.getProcessInstanceId();
|
||||
String taskDefKey = delegateTask.getTaskDefinitionKey();
|
||||
Set<String> candidateUsers = actTaskDefService.findCandidateUsers(procDefId, procInsId, taskDefKey);
|
||||
logger.info("addCandidateUsers : {}", candidateUsers);
|
||||
delegateTask.addCandidateUsers(candidateUsers);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
package cn.palmte.work.service;
|
||||
|
||||
import cn.palmte.work.config.activiti.ActConstant;
|
||||
import cn.palmte.work.model.ActTaskDef;
|
||||
import cn.palmte.work.model.ActTaskDefRepository;
|
||||
import cn.palmte.work.pojo.ActModel;
|
||||
import cn.palmte.work.utils.InterfaceUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.activiti.bpmn.converter.BpmnXMLConverter;
|
||||
import org.activiti.bpmn.model.*;
|
||||
import org.activiti.bpmn.model.Process;
|
||||
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.delegate.TaskListener;
|
||||
import org.activiti.engine.repository.Deployment;
|
||||
import org.activiti.engine.repository.DeploymentBuilder;
|
||||
import org.activiti.engine.repository.Model;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.jfunc.common.db.QueryHelper;
|
||||
import top.jfunc.common.db.bean.Page;
|
||||
import top.jfunc.common.db.utils.Pagination;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
@Service
|
||||
public class ActModelService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActModelService.class);
|
||||
@Autowired
|
||||
private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service
|
||||
|
||||
@Autowired
|
||||
private ActTaskDefRepository actTaskDefRepository;
|
||||
|
||||
@Autowired
|
||||
Pagination pagination;
|
||||
|
||||
|
||||
public Page<ActModel> list(ConcurrentHashMap<String, String> searchInfo, int pageNumber, int pageSize) {
|
||||
String select = "a.ID_ as id,a.REV_ as rev,a.NAME_ as modelName,a.KEY_ as procDefKey,a.CREATE_TIME_ as createdTime,a.LAST_UPDATE_TIME_ as lastUpdatedTime";
|
||||
QueryHelper queryHelper = new QueryHelper(select, " act_re_model a");
|
||||
String name = searchInfo.get("name");
|
||||
queryHelper.addCondition(StringUtils.isNotEmpty(name), "a.NAME_=? or a.KEY_=?", name, name);
|
||||
queryHelper.addOrderProperty("a.LAST_UPDATE_TIME_", false);
|
||||
return pagination.paginate(queryHelper.getSql(), ActModel.class, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
public void createModel(String processId, String modelName) throws Exception {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
ObjectNode editorNode = objectMapper.createObjectNode();
|
||||
editorNode.put("id", "canvs");
|
||||
editorNode.put("resourceId", "canvs");
|
||||
ObjectNode stencilSetNode = objectMapper.createObjectNode();
|
||||
stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#"); //命名空间(禁止修改)
|
||||
stencilSetNode.put("author", ""); //流程节点作者
|
||||
editorNode.set("stencilset", stencilSetNode);
|
||||
ObjectNode propertiesNode = objectMapper.createObjectNode();
|
||||
propertiesNode.put("process_id", processId); //流程唯一标识
|
||||
propertiesNode.put("process_author", InterfaceUtil.getAdmin().getUserName()); //流程作者
|
||||
propertiesNode.put("name", modelName); //流程名称
|
||||
editorNode.set("properties", propertiesNode);
|
||||
|
||||
ObjectNode modelObjectNode = objectMapper.createObjectNode();
|
||||
modelObjectNode.put("name", modelName); //模型名称
|
||||
modelObjectNode.put("revision", 1); //模型版本
|
||||
modelObjectNode.put("description", ""); //模型描述
|
||||
Model modelData = repositoryService.newModel();
|
||||
//modelData.setCategory(category); //模型分类
|
||||
modelData.setDeploymentId(null);
|
||||
modelData.setKey(processId);
|
||||
modelData.setMetaInfo(modelObjectNode.toString());
|
||||
modelData.setName(modelName); //模型名称
|
||||
modelData.setTenantId("");
|
||||
modelData.setVersion(1);
|
||||
|
||||
//保存模型,存储数据到表:act_re_model 流程设计模型部署表
|
||||
repositoryService.saveModel(modelData);
|
||||
|
||||
repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));//保存资源,存储数据到表:act_ge_bytearray 二进制数据表
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除模型
|
||||
* act_re_model 和 act_ge_bytearray 两张表中相关数据都删除
|
||||
*
|
||||
* @param modelId
|
||||
*/
|
||||
public void deleteModel(String modelId) {
|
||||
repositoryService.deleteModel(modelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 部署流程
|
||||
*
|
||||
* @param modelId
|
||||
* @throws Exception
|
||||
*/
|
||||
public void deploy(String modelId) throws Exception {
|
||||
Model modelData = repositoryService.getModel(modelId);
|
||||
ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
|
||||
byte[] bpmnBytes = null;
|
||||
BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
|
||||
BpmnModel model = jsonConverter.convertToBpmnModel(modelNode);
|
||||
|
||||
ActivitiListener activitiListener = new ActivitiListener();
|
||||
activitiListener.setEvent(TaskListener.EVENTNAME_CREATE);
|
||||
activitiListener.setImplementation("${actListenerService.create(task)}");
|
||||
activitiListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
|
||||
List<ActivitiListener> activitiListenerList = new ArrayList<>(1);
|
||||
activitiListenerList.add(activitiListener);
|
||||
|
||||
List<ActTaskDef> taskList = new ArrayList<>();
|
||||
Process process = model.getMainProcess();
|
||||
Collection<FlowElement> flowElements = process.getFlowElements();
|
||||
|
||||
int i = 0;
|
||||
ActTaskDef task;
|
||||
ActTaskDef first = null;
|
||||
for (FlowElement element : flowElements) {
|
||||
if (element instanceof UserTask) {
|
||||
UserTask userTask = (UserTask) element;
|
||||
userTask.setTaskListeners(activitiListenerList);
|
||||
|
||||
task = new ActTaskDef();
|
||||
task.setTaskName(element.getName());
|
||||
task.setTaskKey(element.getId());
|
||||
MultiInstanceLoopCharacteristics loopCharacteristics = ((UserTask) element).getLoopCharacteristics();
|
||||
if (loopCharacteristics != null) {
|
||||
task.setTaskType(1);
|
||||
}
|
||||
|
||||
if (i == 1) {
|
||||
task.setTaskIndex(ActConstant.TASK_INDEX_FIRST_USER_TASK);
|
||||
first = task;
|
||||
}
|
||||
taskList.add(task);
|
||||
}
|
||||
i ++;
|
||||
}
|
||||
|
||||
bpmnBytes = new BpmnXMLConverter().convertToXML(model);
|
||||
String processName = modelData.getName() + ".bpmn20.xml";
|
||||
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment().name(modelData.getName()); //部署名称
|
||||
deploymentBuilder.addString(processName, new String(bpmnBytes, "utf-8"));
|
||||
Deployment deployment = deploymentBuilder.deploy(); //完成部署
|
||||
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
|
||||
for (ActTaskDef actTaskDef : taskList) {
|
||||
if (first != null) {
|
||||
actTaskDef.setRollbackTaskKey(first.getTaskKey());
|
||||
}
|
||||
actTaskDef.setProcDefId(processDefinition.getId());
|
||||
actTaskDef.setProcDefName(processDefinition.getName());
|
||||
actTaskDef.setProcDefKey(processDefinition.getKey());
|
||||
actTaskDef.setCreatedTime(new Date());
|
||||
actTaskDef.setLastUpdatedTime(new Date());
|
||||
}
|
||||
|
||||
actTaskDefRepository.save(taskList);
|
||||
|
||||
logger.info("deploy success: deploymentId:{}, procDefName:{}, procDefKey:{}", deployment.getId(), processDefinition.getName(), processDefinition.getKey());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
package cn.palmte.work.service;
|
||||
|
||||
import cn.palmte.work.model.ActTaskDefRepository;
|
||||
import cn.palmte.work.pojo.ActProcDef;
|
||||
import org.activiti.bpmn.model.*;
|
||||
import org.activiti.engine.ProcessEngine;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.image.ProcessDiagramGenerator;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import top.jfunc.common.db.QueryHelper;
|
||||
import top.jfunc.common.db.bean.Page;
|
||||
import top.jfunc.common.db.utils.Pagination;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
@Service
|
||||
public class ActProcDefService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActProcDefService.class);
|
||||
|
||||
@Autowired
|
||||
private ProcessEngine processEngine; //流程引擎对象
|
||||
@Autowired
|
||||
private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service
|
||||
|
||||
@Autowired
|
||||
private ActTaskDefRepository actTaskDefRepository;
|
||||
|
||||
|
||||
@Autowired
|
||||
Pagination pagination;
|
||||
|
||||
|
||||
public Page<ActProcDef> list(ConcurrentHashMap<String, String> searchInfo, int pageNumber, int pageSize) {
|
||||
String select = "select p.ID_ as id,p.NAME_ as procName,p.KEY_ as procKey,p.VERSION_ as version,p.DEPLOYMENT_ID_ as deploymentId,p.RESOURCE_NAME_ as resourceName,\n" +
|
||||
" p.DGRM_RESOURCE_NAME_ as dgrmResourceName,p.SUSPENSION_STATE_ as suspensionState, d.DEPLOY_TIME_ as deployTime ";
|
||||
QueryHelper queryHelper = new QueryHelper(select, " act_re_procdef p LEFT JOIN act_re_deployment d on p.DEPLOYMENT_ID_ = d.ID_");
|
||||
String name = searchInfo.get("name");
|
||||
queryHelper.addCondition(StringUtils.isNotEmpty(name), "p.NAME_=? or p.KEY_=?", name, name);
|
||||
queryHelper.addOrderProperty("p.KEY_,p.VERSION_", false);
|
||||
return pagination.paginate(queryHelper.getSql(), ActProcDef.class, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
public void getXmlByDeploymentId(HttpServletResponse response, String deploymentId) throws IOException {
|
||||
InputStream pic=null;
|
||||
try {
|
||||
pic= getXmlStreamByDeploymentId(deploymentId);
|
||||
byte[] b = new byte[1024];
|
||||
int len = -1;
|
||||
while ((len = pic.read(b, 0, 1024)) != -1) {
|
||||
response.getOutputStream().write(b, 0, len);
|
||||
}
|
||||
}catch (Exception e){
|
||||
logger.error("an exception happens in try catch statement", e);
|
||||
}finally {
|
||||
if(pic!=null) {
|
||||
pic.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream getXmlStreamByDeploymentId(String deploymentId) throws IOException{
|
||||
List<String> names = repositoryService.getDeploymentResourceNames(deploymentId);
|
||||
for (String name : names) {
|
||||
if(name.contains("xml") ) {
|
||||
return repositoryService.getResourceAsStream(deploymentId, name);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建默认的png
|
||||
*
|
||||
* @param response
|
||||
* @param deploymentId
|
||||
* @throws IOException
|
||||
*/
|
||||
public void createProcDefPng(HttpServletResponse response, String deploymentId) throws IOException {
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId()); // 获取bpmnModel
|
||||
InputStream inputStream = generateDiagramInputStream(bpmnModel, new ArrayList<>(), new ArrayList<>());
|
||||
responsePng(response, inputStream);
|
||||
}
|
||||
|
||||
public void responsePng(HttpServletResponse response, InputStream inputStream) throws IOException {
|
||||
InputStream pic = null;
|
||||
try {
|
||||
pic = inputStream;
|
||||
byte[] b = new byte[1024];
|
||||
int len = -1;
|
||||
while ((len = pic.read(b, 0, 1024)) != -1) {
|
||||
response.getOutputStream().write(b, 0, len);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("an exception happens in try catch statement", e);
|
||||
} finally {
|
||||
if (pic != null) {
|
||||
pic.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public InputStream generateDiagramInputStream(BpmnModel bpmnModel, List<String> executedActivityIdList, List<String> flowIds) {
|
||||
try {
|
||||
ProcessDiagramGenerator processDiagramGenerator = processEngine.getProcessEngineConfiguration().getProcessDiagramGenerator();
|
||||
return processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList,
|
||||
flowIds, "宋体", "微软雅黑", "黑体", null, 2.0); //使用默认配置获得流程图表生成器,并生成追踪图片字符流
|
||||
} catch (Exception e) {
|
||||
logger.error("an exception happens in try catch statement", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteDeployment(String deploymentId) {
|
||||
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
|
||||
actTaskDefRepository.deleteByProcDefId(processDefinition.getId());
|
||||
|
||||
//repositoryService.deleteDeployment(deploymentId); //不带级联的删除,此删除只能删除没有启动的流程,否则抛出异常 .act_re_deployment,act_re_procdef 和 act_ge_bytearray 三张表中相关数据都删除
|
||||
repositoryService.deleteDeployment(deploymentId, true); //级联删除,不管流程是否启动,都可以删除
|
||||
}
|
||||
|
||||
public void suspend(String procDefId, int status) {
|
||||
if (1 == status) {
|
||||
repositoryService.activateProcessDefinitionById(procDefId, true, null);
|
||||
}else{
|
||||
repositoryService.suspendProcessDefinitionById(procDefId, true, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
package cn.palmte.work.service;
|
||||
|
||||
import cn.palmte.work.config.activiti.ActConstant;
|
||||
import cn.palmte.work.exception.ResponseException;
|
||||
import cn.palmte.work.pojo.ActProcIns;
|
||||
import cn.palmte.work.utils.InterfaceUtil;
|
||||
import org.activiti.bpmn.model.BpmnModel;
|
||||
import org.activiti.bpmn.model.FlowNode;
|
||||
import org.activiti.bpmn.model.SequenceFlow;
|
||||
import org.activiti.engine.HistoryService;
|
||||
import org.activiti.engine.RepositoryService;
|
||||
import org.activiti.engine.RuntimeService;
|
||||
import org.activiti.engine.TaskService;
|
||||
import org.activiti.engine.history.HistoricActivityInstance;
|
||||
import org.activiti.engine.history.HistoricProcessInstance;
|
||||
import org.activiti.engine.repository.ProcessDefinition;
|
||||
import org.activiti.engine.runtime.ProcessInstance;
|
||||
import org.activiti.engine.task.IdentityLink;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.activiti.image.ProcessDiagramGenerator;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.jfunc.common.db.QueryHelper;
|
||||
import top.jfunc.common.db.bean.Page;
|
||||
import top.jfunc.common.db.bean.Record;
|
||||
import top.jfunc.common.db.utils.Pagination;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
@Service
|
||||
public class ActProcInsService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActProcInsService.class);
|
||||
@Autowired
|
||||
private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service
|
||||
@Autowired
|
||||
private TaskService taskService; //任务管理 与正在执行的任务管理相关的Service
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@Autowired
|
||||
private RuntimeService runtimeService; //与正在执行的流程实例和执行对象相关的Service(执行管理,包括启动、推进、删除流程实例等操作)
|
||||
|
||||
@Autowired
|
||||
Pagination pagination;
|
||||
|
||||
@Autowired
|
||||
private ActProcDefService actProcDefService;
|
||||
|
||||
@Autowired
|
||||
private HistoryService historyService; //历史管理(执行完的数据的管理)
|
||||
|
||||
|
||||
public Page<ActProcIns> list(ConcurrentHashMap<String, String> searchInfo, int pageNumber, int pageSize) {
|
||||
String select = "select h.proc_inst_id_ as procInsId,h.proc_def_id_ as procDefId," +
|
||||
"h.start_time_ as startTime,h.end_time_ as endTime,p.key_ as procKey," +
|
||||
"p.name_ as procName,p.NAME_ as dgrmResourceName,p.version_ as version, GROUP_CONCAT(t.NAME_) as currentTask, GROUP_CONCAT(t.ID_) as currentTaskId";
|
||||
QueryHelper queryHelper = new QueryHelper(select, " act_hi_procinst h " +
|
||||
"left join ACT_RE_PROCDEF p on h.PROC_DEF_ID_ =p.ID_ " +
|
||||
"LEFT JOIN act_ru_task t on t.PROC_INST_ID_=h.proc_inst_id_ ");
|
||||
queryHelper.addGroupProperty("h.PROC_INST_ID_");
|
||||
queryHelper.addOrderProperty("h.start_time_", false);
|
||||
Page<ActProcIns> paginate = pagination.paginate(queryHelper.getSql(), ActProcIns.class, pageNumber, pageSize);
|
||||
List<ActProcIns> list = paginate.getList();
|
||||
|
||||
for (ActProcIns ins : list) {
|
||||
//查询流程发起人
|
||||
Record record = getVariable(ActConstant.START_PROCESS_USERID, ins.getProcInsId());
|
||||
if (record != null) {
|
||||
String userId = getStartUserId(ins.getProcInsId());
|
||||
ins.setUser(accountService.getNameById(Integer.parseInt(userId)));
|
||||
}
|
||||
|
||||
|
||||
//查询当前任务审批人
|
||||
String currentTaskId = ins.getCurrentTaskId();
|
||||
if (StringUtils.isNotBlank(currentTaskId)) {
|
||||
String[] split = currentTaskId.split(",");
|
||||
String candidateUsers = "";
|
||||
for (String taskId : split) {
|
||||
List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(taskId);
|
||||
for (IdentityLink identityLink : identityLinksForTask) {
|
||||
if ("assignee".equals(identityLink.getType()) || "candidate".equals(identityLink.getType())) {
|
||||
String userId = identityLink.getUserId();
|
||||
if (StringUtils.isNotBlank(candidateUsers)) {
|
||||
candidateUsers = candidateUsers + ",";
|
||||
}
|
||||
candidateUsers += accountService.getNameById(Integer.parseInt(userId));
|
||||
}
|
||||
}
|
||||
}
|
||||
ins.setCandidateUsers(candidateUsers);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return paginate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取流程实例里的变量
|
||||
*
|
||||
* @param variableName
|
||||
* @param procInsId
|
||||
* @return
|
||||
*/
|
||||
public Record getVariable(String variableName, String procInsId) {
|
||||
String sql = "select TEXT_ as text from ACT_HI_VARINST where NAME_=? and PROC_INST_ID_=?";
|
||||
return pagination.findFirst(sql, variableName, procInsId);
|
||||
}
|
||||
|
||||
|
||||
public String getStartUserId(String procInsId) {
|
||||
Record record = getVariable(ActConstant.START_PROCESS_USERID, procInsId);
|
||||
if (record != null) {
|
||||
return record.getStr("text");
|
||||
}
|
||||
return "0";
|
||||
}
|
||||
|
||||
|
||||
public List<Record> getVariables(String procInsId) {
|
||||
String sql = "select NAME_ as name, TEXT_ as text from ACT_HI_VARINST where PROC_INST_ID_=?";
|
||||
return pagination.find(sql, procInsId);
|
||||
}
|
||||
|
||||
|
||||
public void deleteProcessInstance(String procInsId, String reason) {
|
||||
runtimeService.deleteProcessInstance(procInsId, reason); //作废流程
|
||||
}
|
||||
|
||||
|
||||
public void createProcInsPng(HttpServletResponse response, String procInsId) throws IOException {
|
||||
try {
|
||||
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).singleResult(); //获取历史流程实例
|
||||
//获取流程中已经执行的节点,按照执行先后顺序排序
|
||||
List<HistoricActivityInstance> hai = historyService.createHistoricActivityInstanceQuery().processInstanceId(procInsId).orderByHistoricActivityInstanceStartTime().asc().list();
|
||||
// 历史流程节点中
|
||||
List<HistoricActivityInstance> newHisActInstanceList = new ArrayList<HistoricActivityInstance>();
|
||||
List<HistoricActivityInstance> newHisTaskInstanceList = new ArrayList<HistoricActivityInstance>();
|
||||
if (hai != null && hai.size() > 0) {
|
||||
for (int i = 0; i < hai.size(); i++) {
|
||||
HistoricActivityInstance historicActivityInstance = hai.get(i);
|
||||
String activityType = historicActivityInstance.getActivityType();
|
||||
if (activityType.equals("startEvent") || activityType.equals("endEvent")) {
|
||||
newHisActInstanceList.add(historicActivityInstance);
|
||||
} else if (activityType.equals("serviceTask") || activityType.equals("userTask") || activityType.equals("exclusiveGateway") || activityType.equals("parallelGateway")) {
|
||||
if (newHisTaskInstanceList.size() > 0) {
|
||||
for (int j = 0; j < newHisTaskInstanceList.size(); j++) {
|
||||
HistoricActivityInstance historicTaskInstance = newHisTaskInstanceList.get(j);
|
||||
if (historicTaskInstance.getActivityId().equals(historicActivityInstance.getActivityId())) { //如果列表中已包括
|
||||
newHisTaskInstanceList.clear();
|
||||
newHisTaskInstanceList.add(historicActivityInstance);
|
||||
break;
|
||||
} else {
|
||||
newHisTaskInstanceList.add(historicActivityInstance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newHisTaskInstanceList.add(historicActivityInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < newHisActInstanceList.size(); i++) {
|
||||
HistoricActivityInstance historicActivityInstance = newHisActInstanceList.get(i);
|
||||
newHisTaskInstanceList.add(historicActivityInstance);
|
||||
}
|
||||
|
||||
List<String> executedActivityIdList = new ArrayList<String>(); // 构造已执行的节点ID集合
|
||||
for (HistoricActivityInstance activityInstance : newHisTaskInstanceList) {
|
||||
executedActivityIdList.add(activityInstance.getActivityId());
|
||||
}
|
||||
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId()); // 获取bpmnModel
|
||||
List<String> flowIds = this.getExecutedFlows(bpmnModel, newHisTaskInstanceList); // 获取流程已发生流转的线ID集合
|
||||
InputStream inputStream = actProcDefService.generateDiagramInputStream(bpmnModel, executedActivityIdList, flowIds);
|
||||
actProcDefService.responsePng(response, inputStream);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("an exception happens in try catch statement", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<String> getExecutedFlows(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstances) {
|
||||
List<String> flowIdList = new ArrayList<String>(); //流转线ID集合
|
||||
List<FlowNode> historicFlowNodeList = new LinkedList<FlowNode>(); //全部活动实例
|
||||
List<HistoricActivityInstance> finishedActivityInstanceList = new LinkedList<HistoricActivityInstance>(); //已完成的历史活动节点
|
||||
List list = new ArrayList();
|
||||
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
|
||||
historicFlowNodeList.add((FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true));
|
||||
if (historicActivityInstance.getEndTime() != null) {
|
||||
finishedActivityInstanceList.add(historicActivityInstance);
|
||||
}
|
||||
|
||||
}
|
||||
for (int x = 0; x < historicActivityInstances.size(); x++) {
|
||||
HistoricActivityInstance historicActivityInstance = historicActivityInstances.get(x);
|
||||
String activityType = historicActivityInstance.getActivityType();
|
||||
String activityId = historicActivityInstance.getActivityId();
|
||||
if (!list.contains(activityId) && ("userTask".equals(activityType)
|
||||
|| "serviceTask".equals(activityType)
|
||||
|| "endEvent".equals(activityType)
|
||||
|| "exclusiveGateway".equals(activityType)
|
||||
|| "parallelGateway".equals(activityType))) {
|
||||
list.add(activityId);
|
||||
}
|
||||
}
|
||||
/**遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的*/
|
||||
FlowNode currentFlowNode = null;
|
||||
for (HistoricActivityInstance currentActivityInstance : finishedActivityInstanceList) {
|
||||
/**获得当前活动对应的节点信息及outgoingFlows信息*/
|
||||
currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
|
||||
List<SequenceFlow> sequenceFlowList = currentFlowNode.getOutgoingFlows();
|
||||
/**
|
||||
* 遍历outgoingFlows并找到已流转的
|
||||
* 满足如下条件任务已流转:
|
||||
* 1.当前节点是并行网关或包含网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
|
||||
* 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最近的流转节点视为有效流转
|
||||
*/
|
||||
FlowNode targetFlowNode = null;
|
||||
if ("parallelGateway".equals(currentActivityInstance.getActivityType())
|
||||
|| "inclusiveGateway".equals(currentActivityInstance.getActivityType())) {
|
||||
for (SequenceFlow sequenceFlow : sequenceFlowList) { //遍历历史活动节点,找到匹配Flow目标节点的
|
||||
targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
|
||||
if (historicFlowNodeList.contains(targetFlowNode)) {
|
||||
flowIdList.add(sequenceFlow.getId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<Map<String, String>> tempMapList = new LinkedList<Map<String, String>>();
|
||||
// for(SequenceFlow sequenceFlow : sequenceFlowList) { //遍历历史活动节点,找到匹配Flow目标节点的
|
||||
for (int i = 0; i < sequenceFlowList.size(); i++) { //遍历历史活动节点,找到匹配Flow目标节点的
|
||||
SequenceFlow sequenceFlow = sequenceFlowList.get(i);
|
||||
int taskSeq = list.indexOf(sequenceFlow.getSourceRef()); // 获取当前flow目标节点key在审批顺序
|
||||
String nextTaskKey = ""; // 下一个任务节点
|
||||
String beforeTaskKey = sequenceFlow.getSourceRef(); //上一个任务节点
|
||||
|
||||
if ((taskSeq + 1) < list.size()) { // 判断下一个任务节点是否存在
|
||||
nextTaskKey = String.valueOf(list.get((taskSeq + 1)));
|
||||
}
|
||||
if (taskSeq == list.size() - 1) {
|
||||
nextTaskKey = String.valueOf(list.get((taskSeq)));
|
||||
}
|
||||
for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
|
||||
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef()) && sequenceFlow.getSourceRef().equals(beforeTaskKey) && sequenceFlow.getTargetRef().equals(nextTaskKey)) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("flowId", sequenceFlow.getId());
|
||||
map.put("activityStartTime", String.valueOf(historicActivityInstance.getStartTime().getTime()));
|
||||
tempMapList.add(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
String flowId = null;
|
||||
for (Map<String, String> map : tempMapList) {
|
||||
flowId = map.get("flowId");
|
||||
flowIdList.add(flowId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return flowIdList;
|
||||
}
|
||||
|
||||
public String startProcessInstance(String procDefKey, Map<String, Object> variables) {
|
||||
List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).active().orderByProcessDefinitionVersion().desc().list();
|
||||
if (list == null || list.isEmpty()) {
|
||||
throw new ResponseException("procDefKey:" + procDefKey + " 未定义");
|
||||
}
|
||||
|
||||
//取最新版本的流程定义进行启动流程实列
|
||||
ProcessDefinition processDefinition = list.get(0);
|
||||
|
||||
//启动流程
|
||||
ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefinition.getId(), variables);
|
||||
|
||||
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult();
|
||||
if (task == null) {
|
||||
throw new ResponseException("procDefKey:" + procDefKey + " 启动异常");
|
||||
}
|
||||
|
||||
//设置发起人为办理人 然后完成任务 任务转入下一个审批节点
|
||||
task.setAssignee(InterfaceUtil.getAdminId() + "");
|
||||
taskService.complete(task.getId());
|
||||
return processInstance.getId();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package cn.palmte.work.service;
|
||||
|
||||
import cn.palmte.work.model.ActScript;
|
||||
import cn.palmte.work.model.ActScriptRepository;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.jfunc.common.db.QueryHelper;
|
||||
import top.jfunc.common.db.bean.Page;
|
||||
import top.jfunc.common.db.utils.Pagination;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
@Service
|
||||
public class ActScriptService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActScriptService.class);
|
||||
@Autowired
|
||||
private ActScriptRepository actScriptRepository;
|
||||
|
||||
@Autowired
|
||||
Pagination pagination;
|
||||
|
||||
|
||||
public Page<ActScript> list(ConcurrentHashMap<String, String> searchInfo, int pageNumber, int pageSize) {
|
||||
QueryHelper queryHelper = new QueryHelper("a.*", " act_script a");
|
||||
String name = searchInfo.get("name");
|
||||
queryHelper.addCondition(StringUtils.isNotEmpty(name), "a.script_name=? ", name);
|
||||
queryHelper.addOrderProperty("a.last_updated_time", false);
|
||||
return pagination.paginate(queryHelper.getSql(), ActScript.class, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
public void save(ActScript actScript) {
|
||||
Date now = new Date();
|
||||
int id = actScript.getId();
|
||||
if (id == 0) {
|
||||
actScript.setCreatedTime(now);
|
||||
}else {
|
||||
ActScript one = actScriptRepository.findOne(id);
|
||||
actScript.setCreatedTime(one.getCreatedTime());
|
||||
}
|
||||
actScript.setLastUpdatedTime(now);
|
||||
actScriptRepository.save(actScript);
|
||||
}
|
||||
|
||||
|
||||
public void delete(int id) {
|
||||
actScriptRepository.delete(id);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
package cn.palmte.work.service;
|
||||
|
||||
import cn.palmte.work.config.activiti.ActConstant;
|
||||
import cn.palmte.work.config.activiti.DeleteTaskCommand;
|
||||
import cn.palmte.work.config.activiti.JumpCommand;
|
||||
import cn.palmte.work.model.ActScript;
|
||||
import cn.palmte.work.model.ActScriptRepository;
|
||||
import cn.palmte.work.model.ActTaskDef;
|
||||
import cn.palmte.work.model.ActTaskDefRepository;
|
||||
import cn.palmte.work.utils.InterfaceUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.activiti.bpmn.model.FlowNode;
|
||||
import org.activiti.engine.*;
|
||||
import org.activiti.engine.task.Task;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.jfunc.common.db.bean.Record;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@Service
|
||||
public class ActTaskDefService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ActTaskDefService.class);
|
||||
@Autowired
|
||||
private RepositoryService repositoryService; //管理流程定义 与流程定义和部署对象相关的Service
|
||||
@Autowired
|
||||
private ProcessEngine processEngine; //流程引擎对象
|
||||
@Autowired
|
||||
private RuntimeService runtimeService; //与正在执行的流程实例和执行对象相关的Service(执行管理,包括启动、推进、删除流程实例等操作)
|
||||
@Autowired
|
||||
private TaskService taskService; //任务管理 与正在执行的任务管理相关的Service
|
||||
|
||||
@Autowired
|
||||
private ActTaskDefRepository actTaskDefRepository;
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@Autowired
|
||||
private ActProcInsService actProcInsService;
|
||||
|
||||
@Resource
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
private ActScriptRepository actScriptRepository;
|
||||
|
||||
public List<ActTaskDef> findByProcDefId(String procDefId) {
|
||||
List<ActTaskDef> list = actTaskDefRepository.findByProcDefId(procDefId);
|
||||
for (ActTaskDef actTaskDef : list) {
|
||||
ids2List(actTaskDef);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public ActTaskDef findFirstByProcDefIdAndTaskKey(String procDefId, String taskKey) {
|
||||
ActTaskDef def = actTaskDefRepository.findFirstByProcDefIdAndTaskKey(procDefId, taskKey);
|
||||
ids2List(def);
|
||||
return def;
|
||||
}
|
||||
|
||||
|
||||
public void saveConfig(ActTaskDef taskDef) {
|
||||
ActTaskDef one = actTaskDefRepository.findOne(taskDef.getId());
|
||||
one.setCandidateUsers(taskDef.getCandidateUsers());
|
||||
one.setCandidateRoles(taskDef.getCandidateRoles());
|
||||
one.setRollbackTaskKey(taskDef.getRollbackTaskKey());
|
||||
one.setEndScript(taskDef.getEndScript());
|
||||
one.setRollbackScript(taskDef.getRollbackScript());
|
||||
one.setLastUpdatedTime(new Date());
|
||||
|
||||
actTaskDefRepository.save(one);
|
||||
logger.info("saveTaskConfig uerId:{}, config:{}", InterfaceUtil.getAdminId(), JSONObject.toJSONString(one));
|
||||
}
|
||||
|
||||
|
||||
private void ids2List(ActTaskDef actTaskDef) {
|
||||
String candidateUsers = actTaskDef.getCandidateUsers();
|
||||
List<String> userIdList = new ArrayList<>();
|
||||
if (StringUtils.isNotBlank(candidateUsers)) {
|
||||
userIdList = Arrays.asList(candidateUsers.split("#"));
|
||||
}
|
||||
actTaskDef.setCandidateUserList(userIdList);
|
||||
|
||||
String candidateRoles = actTaskDef.getCandidateRoles();
|
||||
List<String> roleIdList = new ArrayList<>();
|
||||
if (StringUtils.isNotBlank(candidateRoles)) {
|
||||
roleIdList = Arrays.asList(candidateRoles.split("#"));
|
||||
}
|
||||
actTaskDef.setCandidateRoleList(roleIdList);
|
||||
}
|
||||
|
||||
|
||||
public Set<String> findCandidateUsers(String procDefId, String procInsId, String taskDefKey) {
|
||||
ActTaskDef taskDef = findFirstByProcDefIdAndTaskKey(procDefId, taskDefKey);
|
||||
if (taskDef.getTaskIndex() == ActConstant.TASK_INDEX_FIRST_USER_TASK) {
|
||||
String startUserId = actProcInsService.getStartUserId(procInsId);
|
||||
Set<String> res = new HashSet<>(1);
|
||||
logger.info("findCandidateUsers-0-task:{}, startUserId:{}", taskDef.getTaskName(), startUserId);
|
||||
res.add(startUserId);
|
||||
return res;
|
||||
}
|
||||
|
||||
List<String> resList = new ArrayList<>();
|
||||
List<String> candidateUserList = taskDef.getCandidateUserList();
|
||||
logger.info("findCandidateUsers-1-task:{}, userList:{}", taskDef.getTaskName(), candidateUserList);
|
||||
if (!candidateUserList.isEmpty()) {
|
||||
resList.addAll(candidateUserList);
|
||||
}
|
||||
|
||||
List<String> candidateRoleList = taskDef.getCandidateRoleList();
|
||||
logger.info("findCandidateUsers-2-task:{}, roleList:{}", taskDef.getTaskName(), candidateRoleList);
|
||||
List<String> list = accountService.getUserIsByRole(candidateRoleList);
|
||||
logger.info("findCandidateUsers-3-task:{}, userIdListByRole:{}", taskDef.getTaskName(), list);
|
||||
if (!list.isEmpty()) {
|
||||
resList.addAll(list);
|
||||
}
|
||||
|
||||
Set<String> res = new HashSet<>(resList);
|
||||
logger.info("findCandidateUsers-4-task:{}, resIds:{}", taskDef.getTaskName(), res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理任务
|
||||
* @param json
|
||||
*/
|
||||
public void completeTask(JSONObject json) {
|
||||
String taskId = json.getString("taskId");
|
||||
String procInstId = json.getString("procInsId");
|
||||
String message = json.getString("message");
|
||||
int type = json.getInteger("type");
|
||||
|
||||
taskService.addComment(taskId, procInstId, message);
|
||||
|
||||
Task currentTask = taskService.createTaskQuery().taskId(taskId).singleResult();
|
||||
ActTaskDef actTaskDef = findFirstByProcDefIdAndTaskKey(currentTask.getProcessDefinitionId(), currentTask.getTaskDefinitionKey());
|
||||
|
||||
if (ActConstant.TYPE_APPROVE == type) {
|
||||
//审批通过
|
||||
taskService.complete(taskId);
|
||||
|
||||
//执行配置的审批通过脚本
|
||||
int endScript = actTaskDef.getEndScript();
|
||||
if (endScript != 0) {
|
||||
invokeEventScript(endScript, procInstId);
|
||||
} else {
|
||||
logger.info("未配置审批通过脚本 task:{}", actTaskDef.getTaskName());
|
||||
}
|
||||
|
||||
} else if (ActConstant.TYPE_ROLLBACK == type) {
|
||||
//驳回
|
||||
String rollbackTaskKey = actTaskDef.getRollbackTaskKey();
|
||||
jumpToTargetTask(taskId, rollbackTaskKey);
|
||||
|
||||
//执行配置的驳回脚本
|
||||
int rollbackScript = actTaskDef.getRollbackScript();
|
||||
if (rollbackScript != 0) {
|
||||
invokeEventScript(rollbackScript, procInstId);
|
||||
} else {
|
||||
logger.info("未配置驳回脚本 task:{}", actTaskDef.getTaskName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 反射执行脚本
|
||||
*
|
||||
* @param scriptId
|
||||
* @param procInsId
|
||||
*/
|
||||
private void invokeEventScript(int scriptId, String procInsId) {
|
||||
ActScript actScript = actScriptRepository.findOne(scriptId);
|
||||
if (actScript == null) {
|
||||
logger.info("脚本配置错误");
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ActConstant.PROC_INS_ID, procInsId);
|
||||
List<Record> variables = actProcInsService.getVariables(procInsId);
|
||||
for (Record variable : variables) {
|
||||
map.put(variable.getStr("name"), variable.get("text"));
|
||||
}
|
||||
|
||||
//调用方法传递的参数
|
||||
Object[] args = new Object[1];
|
||||
args[0] = map;
|
||||
|
||||
logger.info("invokeEventScript class:{}, methond:{}, param:{}", actScript.getClassName(), actScript.getClassMethod(), map);
|
||||
try {
|
||||
Class<?> ownerClass = Class.forName(actScript.getClassName());
|
||||
Object bean = applicationContext.getBean(ownerClass);
|
||||
Class<?>[] paramsType = new Class[1];
|
||||
paramsType[0] = Class.forName("java.util.Map");
|
||||
//找到脚本方法对应的方法 注意:有且只有一个以Map为参数的方法
|
||||
Method method = ownerClass.getDeclaredMethod(actScript.getClassMethod(), paramsType);
|
||||
method.invoke(bean, args);
|
||||
} catch (Exception e) {
|
||||
logger.error("", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到指定任务节点
|
||||
*
|
||||
* @param currentTaskId 当前任务id
|
||||
* @param targetTaskDefKey 跳转目的任务key
|
||||
*/
|
||||
public void jumpToTargetTask(String currentTaskId, String targetTaskDefKey) {
|
||||
Task currentTask = taskService.createTaskQuery().taskId(currentTaskId).singleResult();
|
||||
// 获取流程定义
|
||||
org.activiti.bpmn.model.Process process = repositoryService.getBpmnModel(currentTask.getProcessDefinitionId()).getMainProcess();
|
||||
//获取目标节点定义
|
||||
FlowNode targetNode = (FlowNode) process.getFlowElement(targetTaskDefKey);
|
||||
|
||||
ManagementService managementService = processEngine.getManagementService();
|
||||
//删除当前运行任务
|
||||
String executionEntityId = managementService.executeCommand(new DeleteTaskCommand(currentTask.getId()));
|
||||
//流程执行到来源节点
|
||||
managementService.executeCommand(new JumpCommand(targetNode, executionEntityId));
|
||||
|
||||
Task singleResult = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
|
||||
singleResult.setParentTaskId(currentTask.getTaskDefinitionKey());
|
||||
taskService.saveTask(singleResult);
|
||||
}
|
||||
|
||||
}
|
|
@ -43,7 +43,7 @@ fourcal.token.pc.expires=60*60*24
|
|||
fourcal.excluded.client.urls=
|
||||
fourcal.excluded.pc.urls=
|
||||
#\u6392\u9664\u67D0\u4E9B\u65E5\u5FD7\u7684\u6253\u5370
|
||||
fourcal.log.excluded.urls=
|
||||
fourcal.log.excluded.urls=/editor/stencilset
|
||||
|
||||
|
||||
fourcal.slideInterval=1800000
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,233 @@
|
|||
<#assign base=request.contextPath />
|
||||
<#import "../common/defaultLayout.ftl" as defaultLayout>
|
||||
<@defaultLayout.layout>
|
||||
|
||||
<div class="admin-content">
|
||||
<div class="admin-content-body">
|
||||
<div class="am-cf am-padding">
|
||||
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">系统管理</strong> / <small>工作流程管理</small></div>
|
||||
</div>
|
||||
<form method="post" class="am-form" id="tmpForm" action="${base}/actModel/save">
|
||||
<!--选项卡(tabs)begin-->
|
||||
<div class="am-tabs am-margin" data-am-tabs>
|
||||
<ul class="am-tabs-nav am-nav am-nav-tabs">
|
||||
<li class="am-active">
|
||||
<a href="#tab1">模型信息</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="am-tabs-bd">
|
||||
<div class="am-tab-panel am-fade am-in am-active" id="tab1">
|
||||
|
||||
<input name="modelId" id="modelId" type="hidden" value="${modelId!}"/>
|
||||
|
||||
<!--验证表单元素(validate) begin-->
|
||||
<!--input begin-->
|
||||
<div class="am-g am-form-group am-margin-top">
|
||||
<div class="am-u-sm-4 am-u-md-2 am-text-right">
|
||||
<span style="color: red;">*</span>
|
||||
模型(流程)名称
|
||||
</div>
|
||||
<div class="am-u-sm-6 am-u-md-6">
|
||||
<input name="modelName" class="js-ajax-validate"
|
||||
data-validate-async data-validation-message="请输入模型名称(100字符以内)"
|
||||
type="text" id="modelName" value="${modelName!}" minlength="1" maxlength="100"
|
||||
placeholder="请输入模型名称(100字符以内)" required <#--onblur="checkmodelName($(this));"--> onKeyUp="clearValidInfo()" />
|
||||
</div>
|
||||
<div class="am-u-sm-2 am-u-md-4 input-msg" id="role_name_valid"></div>
|
||||
</div>
|
||||
|
||||
<div class="am-g am-form-group am-margin-top">
|
||||
<div class="am-u-sm-4 am-u-md-2 am-text-right">
|
||||
<span style="color: red;">*</span>
|
||||
流程标识
|
||||
</div>
|
||||
<div class="am-u-sm-6 am-u-md-6">
|
||||
<input name="procDefKey" class="js-ajax-validate"
|
||||
data-validate-async data-validation-message="请输入流程标识(20字符以内)"
|
||||
type="text" id="procDefKey" value="${procDefKey!}" minlength="1" maxlength="20"
|
||||
placeholder="请输入流程标识(20字符以内)" required <#--onblur="checkprocDefKey($(this));"--> onKeyUp="clearValidInfo()" />
|
||||
</div>
|
||||
<div class="am-u-sm-2 am-u-md-4 input-msg" id="role_procDefKey_valid"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<#--<div class="am-g am-form-group am-margin-top">
|
||||
<div class="am-u-sm-4 am-u-md-2 am-text-right">
|
||||
描述
|
||||
</div>
|
||||
<div class="am-u-sm-6 am-u-md-6">
|
||||
<input name="discription" class="js-ajax-validate"
|
||||
data-validate-async data-validation-message="请输入描述(1000字符以内)"
|
||||
type="text" id="discription" value="${description!}" minlength="1" maxlength="100"
|
||||
placeholder="请输入描述(1000字符以内)" <#–onblur="checkprocDefKey($(this));"–> onKeyUp="clearValidInfo()" />
|
||||
</div>
|
||||
<div class="am-u-sm-2 am-u-md-4 input-msg" id="role_description_valid"></div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--选项卡(tabs)end-->
|
||||
<div class="am-margin">
|
||||
<button type="submit" class="am-btn am-btn-primary am-btn-xs">提交保存</button>
|
||||
<button type="button" class="am-btn am-btn-warning am-btn-xs" onclick="javascript:history.go(-1);">返回上一级</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</@defaultLayout.layout>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
/*名称检验 start*/
|
||||
var urlBase = "${base}";
|
||||
var url;
|
||||
function checkRoleName(obj){
|
||||
var roleName = obj.val();
|
||||
var roleID = $("#roleID").val();
|
||||
if(roleName.length == 0){
|
||||
showRoleNameAlert($("#roleName").date("data-validation-message"));
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url : urlBase + "/role/check",
|
||||
type : 'POST',
|
||||
dataType : 'json',
|
||||
data : {
|
||||
role_id : roleID, role_name : roleName
|
||||
},
|
||||
cache : false
|
||||
}).done(function (result) {
|
||||
if (result.status==0) {
|
||||
showRoleNameAlert(result.msg);
|
||||
obj.focus();
|
||||
}else{
|
||||
showRoleNameAlert(result.msg);
|
||||
}
|
||||
|
||||
}).fail(function (){
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function clearValidInfo(){
|
||||
showRoleNameAlert("");
|
||||
}
|
||||
function showRoleNameAlert(message){
|
||||
var $alert = $("#role_name_valid").find('.am-alert');
|
||||
if (!$alert.length) {
|
||||
$alert = $('<div class="am-alert am-alert-danger"></div>').hide()
|
||||
$alert.appendTo($("#role_name_valid"));
|
||||
}
|
||||
if(message.length==0){
|
||||
$alert.hide();
|
||||
}else{
|
||||
$alert.text(message).show();
|
||||
}
|
||||
}
|
||||
/*角色名称检验 end*/
|
||||
|
||||
|
||||
/*复选框 全选:start*/
|
||||
$(".role-authority-checkall").click(function(){
|
||||
var $parentNode = $(this).parent().parent();
|
||||
var level = Number($parentNode.attr("level"));
|
||||
var $allParentNextNode = $parentNode.nextUntil(".level-"+level);
|
||||
var isChecked = $(this).is(":checked");
|
||||
$allParentNextNode.each(function(){
|
||||
var myLevel = Number($(this).attr("level"));
|
||||
var $checks = $(this).children().find("input[type='checkbox']");
|
||||
if(myLevel > level){
|
||||
return changeCheckedStatus($checks,isChecked);
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
var $checks = $(this).parent().prev().find("input[type='checkbox']");
|
||||
changeCheckedStatus($checks,isChecked);
|
||||
});
|
||||
|
||||
function changeCheckedStatus(checksObj,isChecked){
|
||||
checksObj.each(function(){
|
||||
if(isChecked){
|
||||
$(this).prop("checked",true);
|
||||
}else{
|
||||
$(this).prop("checked",false);
|
||||
}
|
||||
});
|
||||
}
|
||||
/*复选框 全选:end*/
|
||||
|
||||
$(function() {
|
||||
/*表单验证:begin*/
|
||||
//自定义规则,用法:验证元素上加class="js-pattern-sort"
|
||||
if ($.AMUI && $.AMUI.validator) {
|
||||
$.AMUI.validator.patterns.sort = /^([0-9]+)$/;
|
||||
}
|
||||
$("#tmpForm").validator({
|
||||
// 域通过验证时回调
|
||||
onValid: function(validity) {
|
||||
$(validity.field).closest('.am-form-group').find('.am-alert').hide();
|
||||
},
|
||||
// 域验证通过时添加的操作,通过该接口可定义各种验证提示
|
||||
markValid: function(validity) {
|
||||
// this is Validator instance
|
||||
var $field = $(validity.field);
|
||||
//add by zxl,只对有required属性的字段进行验证
|
||||
if(typeof($field.attr("required"))!="undefined"){
|
||||
var options = this.options;
|
||||
var $parent = $field.closest('.am-form-group');
|
||||
$field.addClass(options.validClass).
|
||||
removeClass(options.inValidClass);
|
||||
|
||||
$parent.addClass('am-form-success').removeClass('am-form-error');
|
||||
|
||||
options.onValid.call(this, validity);
|
||||
}
|
||||
},
|
||||
// 验证出错时的回调, validity 对象包含相关信息,格式通 H5 表单元素的 validity 属性
|
||||
onInValid: function(validity) {
|
||||
var $field = $(validity.field);
|
||||
var $group = $field.closest('.am-form-group');
|
||||
var $alert = $group.find('.am-alert');
|
||||
// 使用自定义的提示信息 或 插件内置的提示信息
|
||||
var msg = $field.data('validationMessage') || this.getValidationMessage(validity);
|
||||
|
||||
if (!$alert.length) {
|
||||
$alert = $("<div class='am-alert am-alert-danger'></div>").hide().
|
||||
appendTo($group.find(".input-msg"));
|
||||
}
|
||||
console.log("onInValid : "+$field.val());
|
||||
$alert.html(msg).show();
|
||||
}
|
||||
});
|
||||
/*表单验证:end*/
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
<style type="text/css">
|
||||
/*验证:提示信息样式 begin*/
|
||||
.am-alert-danger {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
color: red;
|
||||
}
|
||||
.am-alert {
|
||||
margin-bottom: 1em;
|
||||
padding: .625em;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
/*验证:提示信息样式 end*/
|
||||
</style>
|
|
@ -0,0 +1,214 @@
|
|||
<#assign base=request.contextPath />
|
||||
<#import "../common/defaultLayout.ftl" as defaultLayout>
|
||||
<@defaultLayout.layout>
|
||||
<link rel="stylesheet" href="${base}/assets/css/amazeui.switch.css"/>
|
||||
<div class="admin-content">
|
||||
<div class="am-cf am-padding" style="padding:1rem 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">工作流程</strong> /
|
||||
<small>模型管理</small>
|
||||
</div>
|
||||
</div>
|
||||
<form class="am-form" id="list-form" action="${base}/actModel/list" method="post">
|
||||
<input type="hidden" id="keywords" name="keywords" value='${keywords!""}'/>
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 am-u-md-6" style="padding:0px 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<div class="am-btn-toolbar">
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
<#--<@shiro.hasPermission name="ROLE_ADD">-->
|
||||
<button type="button" class="am-btn am-btn-default"
|
||||
onclick="location.href='${base}/actModel/add'">
|
||||
<span class="am-icon-plus"></span>
|
||||
新增
|
||||
</button>
|
||||
<#-- </@shiro.hasPermission>
|
||||
<@shiro.hasPermission name="ROLE_DELRTE">-->
|
||||
<button type="button" id="deleteButton" disabled="disabled"
|
||||
class="am-btn am-btn-default"
|
||||
onclick="deleteAll('${base}/actModel/delete')"><span
|
||||
class="am-icon-trash-o"></span> 删除
|
||||
</button>
|
||||
<#--</@shiro.hasPermission>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="am-u-sm-12 am-u-md-3">
|
||||
<div class="am-input-group am-input-group-sm">
|
||||
<input type="text" class="am-form-field" id="name" value="${name!}" placeholder="按名称和标识搜索"/>
|
||||
<span class="am-input-group-btn">
|
||||
<button id="searchButton" class="am-btn am-btn-default" type="button">搜索</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 am-scrollable-horizontal">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<table class="am-table am-table-striped am-table-hover table-main">
|
||||
<thead>
|
||||
<tr class="am-text-nowrap">
|
||||
<th class="table-check">
|
||||
<input type="checkbox" id="allCheck"></th>
|
||||
<th class="table-title">id</th>
|
||||
<th class="table-title">模型(流程)名称</th>
|
||||
<th class="table-title">流程标识</th>
|
||||
<th class="table-date">最新版本</th>
|
||||
<th class="table-date">创建日期</th>
|
||||
<th class="table-date">最后更新日期</th>
|
||||
<th class="table-set am-text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<#if (pager.list)?exists>
|
||||
<#list pager.list as list>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="ids" value="${list.id}"/>
|
||||
</td>
|
||||
<td>${list.id!}</td>
|
||||
<td>${list.modelName!}</td>
|
||||
<td>${list.procDefKey!}</td>
|
||||
<td>${list.rev!}</td>
|
||||
<td><#if list.createdTime??>${list.createdTime?datetime}</#if></td>
|
||||
<td><#if list.lastUpdatedTime??>${list.lastUpdatedTime?datetime}</#if></td>
|
||||
<td>
|
||||
<div class="am-btn-toolbar">
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="window.open('${base}/activiti-editor/modeler.html?modelId==${list.id?c}')">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
流程设计
|
||||
</button>
|
||||
|
||||
<#--<@shiro.hasPermission name="ROLE_EDIT">-->
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="deploy(${list.id?c})">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
部署
|
||||
</button>
|
||||
<#--</@shiro.hasPermission>-->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</#list>
|
||||
</#if>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="am-cf">
|
||||
<!-- 分页 -->
|
||||
<#if (pager.list)?exists && (pager.list?size>0) >
|
||||
<div class="am-fr">
|
||||
<#include "../common/common_pager.ftl">
|
||||
</div>
|
||||
<#else>
|
||||
<div class="am-kai" align="center">
|
||||
<h3>没有找到任何记录!</h3>
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</@defaultLayout.layout>
|
||||
|
||||
<script src="${base}/assets/js/amazeui.switch.js"></script>
|
||||
<script type="text/javascript">
|
||||
var urlBase = "${base}";
|
||||
var url;
|
||||
|
||||
$(function () {
|
||||
/*表单提交 start*/
|
||||
var keywordsObj = {};
|
||||
$("#searchButton").on("click", function () {
|
||||
if ($("#name").val()) {
|
||||
keywordsObj.name = $("#name").val();
|
||||
}
|
||||
var keywords = "";
|
||||
if (!$.isEmptyObject(keywordsObj)) {
|
||||
keywords = JSON.stringify(keywordsObj);
|
||||
}
|
||||
console.log("keywords = " + keywords);
|
||||
$("#keywords").val(keywords);
|
||||
$("#list-form").submit();
|
||||
});
|
||||
/*表单提交 end*/
|
||||
|
||||
/*复选框全选效果 start*/
|
||||
$("body").on('click', '.list-item', function () {
|
||||
$(".list-item").removeClass("tr-selected");
|
||||
$(this).addClass('tr-selected');
|
||||
});
|
||||
$("#allCheck").click(function () {
|
||||
$('input[name="ids"]').prop("checked", this.checked);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
var $citySubBox = $("input[name='ids']");
|
||||
$citySubBox.click(function () {
|
||||
$("#allCheckCity").prop("checked", $citySubBox.length == $("input[name='ids']:checked").length ? true : false);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
/*复选框全选效果 end*/
|
||||
|
||||
});
|
||||
|
||||
/*批量删除 start*/
|
||||
var deleteAll = function (url) {
|
||||
var $deleteButton = $("#deleteButton");// 删除按钮
|
||||
var ids = "";
|
||||
$("input[name='ids']:checked").each(function () {
|
||||
ids += $(this).val() + "#%#";
|
||||
});
|
||||
var params = {ids: ids};
|
||||
if (window.confirm('确定要删除吗?')) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
beforeSend: function (data) {
|
||||
$deleteButton.prop("disabled", true)
|
||||
},
|
||||
success: function (data) {
|
||||
$deleteButton.prop("disabled", false)
|
||||
if (data.status == 0) {
|
||||
alert(data.msg);
|
||||
window.location.href = window.location.href;
|
||||
} else if (data.status == 1) {
|
||||
alert(data.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/*批量删除 end*/
|
||||
|
||||
|
||||
var deploy = function (id) {
|
||||
var params = {id: id};
|
||||
$.ajax({
|
||||
url: '${base}/actModel/deploy',
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (data) {
|
||||
layer.msg(data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$(function () {
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,267 @@
|
|||
<#assign base=request.contextPath />
|
||||
<#import "../common/defaultLayout.ftl" as defaultLayout>
|
||||
<@defaultLayout.layout>
|
||||
<link rel="stylesheet" href="${base}/assets/css/amazeui.switch.css"/>
|
||||
<div class="admin-content">
|
||||
<div class="am-cf am-padding" style="padding:1rem 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">工作流程</strong> /
|
||||
<small>流程定义管理</small>
|
||||
</div>
|
||||
</div>
|
||||
<form class="am-form" id="list-form" action="${base}/actProcDef/list" method="post">
|
||||
<input type="hidden" id="keywords" name="keywords" value='${keywords!""}'/>
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 am-u-md-6" style="padding:0px 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<div class="am-btn-toolbar">
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
|
||||
<button type="button" id="deleteButton" disabled="disabled"
|
||||
class="am-btn am-btn-default"
|
||||
onclick="deleteAll('${base}/actProcDef/delete')"><span
|
||||
class="am-icon-trash-o"></span> 删除
|
||||
</button>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="am-u-sm-12 am-u-md-3">
|
||||
<div class="am-input-group am-input-group-sm">
|
||||
<input type="text" class="am-form-field" id="name" value="${name!}" placeholder="按名称和标识搜索"/>
|
||||
<span class="am-input-group-btn">
|
||||
<button id="searchButton" class="am-btn am-btn-default" type="button">搜索</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<#-- <div class="am-modal am-modal-no-btn" tabindex="-1" id="doc-modal-1">
|
||||
<div class="am-modal-dialog">
|
||||
<div class="am-modal-hd">Modal 标题
|
||||
<a href="javascript: void(0)" class="am-close am-close-spin" data-am-modal-close>×</a>
|
||||
</div>
|
||||
<div class="am-modal-bd">
|
||||
<img id="img" name="img" src="${base}/actProcDef/png/2501">
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 am-scrollable-horizontal">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<table class="am-table am-table-striped am-table-hover table-main">
|
||||
<thead>
|
||||
<tr class="am-text-nowrap">
|
||||
<th class="table-check">
|
||||
<input type="checkbox" id="allCheck"></th>
|
||||
<th class="table-title">流程id</th>
|
||||
<th class="table-title">流程名称</th>
|
||||
<th class="table-title">流程标识</th>
|
||||
<th class="table-date">版本</th>
|
||||
<th class="table-date">预览</th>
|
||||
<th class="table-date">激活/挂起</th>
|
||||
<th class="table-date">部署时间</th>
|
||||
<th class="table-set am-text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<#if (pager.list)?exists>
|
||||
<#list pager.list as list>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="ids" value="${list.deploymentId}"/>
|
||||
</td>
|
||||
<td>${list.id!}</td>
|
||||
<td>${list.procName!}</td>
|
||||
<td>${list.procKey!}</td>
|
||||
<td>${list.version!}</td>
|
||||
<td>
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="window.open('${base}/actProcDef/procDefPng/${list.deploymentId!}')">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
流程图片
|
||||
</button>
|
||||
|
||||
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="window.open('${base}/actProcDef/xml/${list.deploymentId!}')">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
流程xml
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<div class="switch-button">
|
||||
<#--1激活 2挂起-->
|
||||
<input id="${list.id}" type="checkbox" data-size='xs'
|
||||
data-am-switch data-on-text="已激活" data-off-text="已挂起"
|
||||
<#if list.suspensionState==1 >checked</#if>/>
|
||||
</div>
|
||||
</td>
|
||||
<td><#if list.deployTime??>${list.deployTime?datetime}</#if></td>
|
||||
<td>
|
||||
<div class="am-btn-toolbar">
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="location.href='${base}/actTaskDef/config/${list.id}'">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
任务配置
|
||||
</button>
|
||||
|
||||
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="startProcIns('${list.procKey}')">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
发起流程
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</#list>
|
||||
</#if>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="am-cf">
|
||||
<!-- 分页 -->
|
||||
<#if (pager.list)?exists && (pager.list?size>0) >
|
||||
<div class="am-fr">
|
||||
<#include "../common/common_pager.ftl">
|
||||
</div>
|
||||
<#else>
|
||||
<div class="am-kai" align="center">
|
||||
<h3>没有找到任何记录!</h3>
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</@defaultLayout.layout>
|
||||
|
||||
<script src="${base}/assets/js/amazeui.switch.js"></script>
|
||||
<script type="text/javascript">
|
||||
var urlBase = "${base}";
|
||||
var url;
|
||||
|
||||
$(function () {
|
||||
/*表单提交 start*/
|
||||
var keywordsObj = {};
|
||||
$("#searchButton").on("click", function () {
|
||||
if ($("#name").val()) {
|
||||
keywordsObj.name = $("#name").val();
|
||||
}
|
||||
var keywords = "";
|
||||
if (!$.isEmptyObject(keywordsObj)) {
|
||||
keywords = JSON.stringify(keywordsObj);
|
||||
}
|
||||
console.log("keywords = " + keywords);
|
||||
$("#keywords").val(keywords);
|
||||
$("#list-form").submit();
|
||||
});
|
||||
/*表单提交 end*/
|
||||
|
||||
/*复选框全选效果 start*/
|
||||
$("body").on('click', '.list-item', function () {
|
||||
$(".list-item").removeClass("tr-selected");
|
||||
$(this).addClass('tr-selected');
|
||||
});
|
||||
$("#allCheck").click(function () {
|
||||
$('input[name="ids"]').prop("checked", this.checked);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
var $citySubBox = $("input[name='ids']");
|
||||
$citySubBox.click(function () {
|
||||
$("#allCheckCity").prop("checked", $citySubBox.length == $("input[name='ids']:checked").length ? true : false);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
/*复选框全选效果 end*/
|
||||
|
||||
});
|
||||
|
||||
/*批量删除 start*/
|
||||
var deleteAll = function (url) {
|
||||
var $deleteButton = $("#deleteButton");// 删除按钮
|
||||
var ids = "";
|
||||
$("input[name='ids']:checked").each(function () {
|
||||
ids += $(this).val() + "#%#";
|
||||
});
|
||||
var params = {ids: ids};
|
||||
if (window.confirm('确定要删除吗?')) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
beforeSend: function (data) {
|
||||
$deleteButton.prop("disabled", true)
|
||||
},
|
||||
success: function (data) {
|
||||
$deleteButton.prop("disabled", false)
|
||||
if (data.status == 0) {
|
||||
alert(data.msg);
|
||||
window.location.href = window.location.href;
|
||||
} else if (data.status == 1) {
|
||||
alert(data.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/*批量删除 end*/
|
||||
|
||||
|
||||
/**
|
||||
* 为每个启用或禁用按钮增加事件
|
||||
*/
|
||||
$(function () {
|
||||
var $mycheckbox = $('.switch-button').find("input[type='checkbox']");
|
||||
$mycheckbox.each(function () {
|
||||
var myid = $(this).attr("id");
|
||||
var prop = $(this).attr("prop");
|
||||
|
||||
$(this).on({
|
||||
'switchChange.bootstrapSwitch': function (event, state) {
|
||||
toggle(myid, state ? 1 : 2);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
//启用或者禁用
|
||||
var toggle = function (id, status) {
|
||||
$.ajax({
|
||||
url: "${base}/actProcDef/suspend",
|
||||
data: {id: id, status: status},
|
||||
type: "get",
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (data) {
|
||||
parent.layer.msg(data.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var startProcIns = function (procDefKey) {
|
||||
var params = {procDefKey: procDefKey};
|
||||
$.ajax({
|
||||
url: '${base}/actProcIns/startProcIns',
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (data) {
|
||||
layer.msg(data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,240 @@
|
|||
<#assign base=request.contextPath />
|
||||
<#import "../common/defaultLayout.ftl" as defaultLayout>
|
||||
<@defaultLayout.layout>
|
||||
<link rel="stylesheet" href="${base}/assets/css/amazeui.switch.css"/>
|
||||
<div class="admin-content">
|
||||
<div class="am-cf am-padding" style="padding:1rem 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">工作流程</strong> /
|
||||
<small>流程实例</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 am-scrollable-horizontal">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<table class="am-table am-table-striped am-table-hover table-main">
|
||||
<thead>
|
||||
<tr class="am-text-nowrap">
|
||||
<th class="table-title">流程名称</th>
|
||||
<th class="table-title">流程标识</th>
|
||||
<th class="table-title">流程版本</th>
|
||||
<th class="table-date">申请人</th>
|
||||
<th class="table-date">申请时间</th>
|
||||
<th class="table-date">当前任务</th>
|
||||
<th class="table-date">当前审批人</th>
|
||||
<th class="table-date">结束时间</th>
|
||||
<th class="table-set am-text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<#if (pager.list)?exists>
|
||||
<#list pager.list as list>
|
||||
<tr>
|
||||
<td>${list.procName!}</td>
|
||||
<td>${list.procKey!}</td>
|
||||
<td>${list.version!}</td>
|
||||
<td>${list.user!}</td>
|
||||
<td>${list.startTime?datetime}</td>
|
||||
<td>${list.currentTask!}</td>
|
||||
<td>${list.candidateUsers!}</td>
|
||||
<td><#if list.endTime??>${list.endTime?datetime}</#if></td>
|
||||
<td>
|
||||
<#if !list.endTime??>
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="deleteProcIns('${list.procInsId}', '管理员撤销')">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
撤销流程
|
||||
</button>
|
||||
|
||||
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="completeTask('${list.procInsId}', '${list.currentTaskId}', 1)">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
审批通过
|
||||
</button>
|
||||
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="completeTask('${list.procInsId}', '${list.currentTaskId}', 2)">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
驳回
|
||||
</button>
|
||||
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="window.open('${base}/actProcIns/procInsPng/${list.procInsId!}')">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
流程图片
|
||||
</button>
|
||||
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</#list>
|
||||
</#if>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="am-cf">
|
||||
<!-- 分页 -->
|
||||
<#if (pager.list)?exists && (pager.list?size>0) >
|
||||
<div class="am-fr">
|
||||
<#include "../common/common_pager.ftl">
|
||||
</div>
|
||||
<#else>
|
||||
<div class="am-kai" align="center">
|
||||
<h3>没有找到任何记录!</h3>
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</@defaultLayout.layout>
|
||||
|
||||
<script src="${base}/assets/js/amazeui.switch.js"></script>
|
||||
<script type="text/javascript">
|
||||
var urlBase = "${base}";
|
||||
var url;
|
||||
|
||||
$(function () {
|
||||
/*表单提交 start*/
|
||||
var keywordsObj = {};
|
||||
$("#searchButton").on("click", function () {
|
||||
if ($("#name").val()) {
|
||||
keywordsObj.name = $("#name").val();
|
||||
}
|
||||
var keywords = "";
|
||||
if (!$.isEmptyObject(keywordsObj)) {
|
||||
keywords = JSON.stringify(keywordsObj);
|
||||
}
|
||||
console.log("keywords = " + keywords);
|
||||
$("#keywords").val(keywords);
|
||||
$("#list-form").submit();
|
||||
});
|
||||
/*表单提交 end*/
|
||||
|
||||
/*复选框全选效果 start*/
|
||||
$("body").on('click', '.list-item', function () {
|
||||
$(".list-item").removeClass("tr-selected");
|
||||
$(this).addClass('tr-selected');
|
||||
});
|
||||
$("#allCheck").click(function () {
|
||||
$('input[name="ids"]').prop("checked", this.checked);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
var $citySubBox = $("input[name='ids']");
|
||||
$citySubBox.click(function () {
|
||||
$("#allCheckCity").prop("checked", $citySubBox.length == $("input[name='ids']:checked").length ? true : false);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
/*复选框全选效果 end*/
|
||||
|
||||
});
|
||||
|
||||
/*批量删除 start*/
|
||||
var deleteAll = function (url) {
|
||||
var $deleteButton = $("#deleteButton");// 删除按钮
|
||||
var ids = "";
|
||||
$("input[name='ids']:checked").each(function () {
|
||||
ids += $(this).val() + "#%#";
|
||||
});
|
||||
var params = {ids: ids};
|
||||
if (window.confirm('确定要删除吗?')) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
beforeSend: function (data) {
|
||||
$deleteButton.prop("disabled", true)
|
||||
},
|
||||
success: function (data) {
|
||||
$deleteButton.prop("disabled", false)
|
||||
if (data.status == 0) {
|
||||
alert(data.msg);
|
||||
window.location.href = window.location.href;
|
||||
} else if (data.status == 1) {
|
||||
alert(data.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/*批量删除 end*/
|
||||
|
||||
|
||||
/**
|
||||
* 为每个启用或禁用按钮增加事件
|
||||
*/
|
||||
$(function () {
|
||||
var $mycheckbox = $('.switch-button').find("input[type='checkbox']");
|
||||
$mycheckbox.each(function () {
|
||||
var myid = $(this).attr("id");
|
||||
var prop = $(this).attr("prop");
|
||||
|
||||
$(this).on({
|
||||
'switchChange.bootstrapSwitch': function (event, state) {
|
||||
toggle(myid, state ? 1 : 2);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
//启用或者禁用
|
||||
var toggle = function (id, status) {
|
||||
$.ajax({
|
||||
url: "${base}/actProcDef/suspend",
|
||||
data: {id: id, status: status},
|
||||
type: "get",
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (data) {
|
||||
parent.layer.msg(data.msg);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var deleteProcIns = function (procInsId, reason) {
|
||||
var params = {procInsId: procInsId, reason: reason};
|
||||
$.ajax({
|
||||
url: '${base}/actProcIns/deleteProcessInstance',
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (data) {
|
||||
alert(data.msg);
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var completeTask = function (procInsId, taskId, type) {
|
||||
var params = {
|
||||
procInsId: procInsId,
|
||||
taskId: taskId,
|
||||
type: type,
|
||||
message: '管理员审批'
|
||||
};
|
||||
$.ajax({
|
||||
url: '${base}/actTaskDef/completeTask',
|
||||
data: JSON.stringify(params),
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
type: 'post',
|
||||
async: false,
|
||||
success: function (data) {
|
||||
alert(data.msg);
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,203 @@
|
|||
<#assign base=request.contextPath />
|
||||
<#import "../common/defaultLayout.ftl" as defaultLayout>
|
||||
<@defaultLayout.layout>
|
||||
|
||||
<div class="admin-content">
|
||||
<div class="admin-content-body">
|
||||
<div class="am-cf am-padding">
|
||||
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">工作流程</strong> / <small>流程脚本</small></div>
|
||||
</div>
|
||||
<form method="post" class="am-form" id="tmpForm" action="${base}/actScript/save">
|
||||
<!--选项卡(tabs)begin-->
|
||||
<div class="am-tabs am-margin" data-am-tabs>
|
||||
<ul class="am-tabs-nav am-nav am-nav-tabs">
|
||||
<li class="am-active">
|
||||
<a href="#tab1">脚本编辑</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="am-tabs-bd">
|
||||
<div class="am-tab-panel am-fade am-in am-active" id="tab1">
|
||||
|
||||
<input name="id" id="id" type="hidden" value="${actScript.id!}"/>
|
||||
|
||||
<!--验证表单元素(validate) begin-->
|
||||
<!--input begin-->
|
||||
<div class="am-g am-form-group am-margin-top">
|
||||
<div class="am-u-sm-4 am-u-md-2 am-text-right">
|
||||
<span style="color: red;">*</span>
|
||||
脚本名称
|
||||
</div>
|
||||
<div class="am-u-sm-6 am-u-md-6">
|
||||
<input name="scriptName" class="js-ajax-validate"
|
||||
data-validate-async data-validation-message="请输入脚本名称(20字符以内)"
|
||||
type="text" id="scriptName" value="${actScript.scriptName!}" minlength="1" maxlength="100"
|
||||
placeholder="请输入模型名称(100字符以内)" required onKeyUp="clearValidInfo()" />
|
||||
</div>
|
||||
<div class="am-u-sm-2 am-u-md-4 input-msg" id="role_name_valid"></div>
|
||||
</div>
|
||||
|
||||
<div class="am-g am-form-group am-margin-top">
|
||||
<div class="am-u-sm-4 am-u-md-2 am-text-right"><span style="color: red;">*</span>脚本所在类</div>
|
||||
<div class="am-u-sm-6 am-u-md-6">
|
||||
<select data-am-selected id="className" name="className" readonly="">
|
||||
<#list classList as l>
|
||||
<option value="${l}" <#if actScript.className! == l>selected</#if> >${l!}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</div>
|
||||
<div class="am-u-sm-2 am-u-md-4 input-msg"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="am-g am-form-group am-margin-top">
|
||||
<div class="am-u-sm-4 am-u-md-2 am-text-right"><span style="color: red;">*</span>方法名称</div>
|
||||
<div class="am-u-sm-6 am-u-md-6">
|
||||
<select data-am-selected id="classMethod" name="classMethod" readonly="">
|
||||
<#list methodList as l>
|
||||
<option value="${l}" <#if actScript.classMethod! == l>selected</#if> >${l!}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</div>
|
||||
<div class="am-u-sm-2 am-u-md-4 input-msg"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--选项卡(tabs)end-->
|
||||
<div class="am-margin">
|
||||
<button type="submit" class="am-btn am-btn-primary am-btn-xs">提交保存</button>
|
||||
<button type="button" class="am-btn am-btn-warning am-btn-xs" onclick="javascript:history.go(-1);">返回上一级</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</@defaultLayout.layout>
|
||||
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
/*名称检验 start*/
|
||||
var urlBase = "${base}";
|
||||
var url;
|
||||
|
||||
|
||||
function clearValidInfo(){
|
||||
showRoleNameAlert("");
|
||||
}
|
||||
function showRoleNameAlert(message){
|
||||
var $alert = $("#role_name_valid").find('.am-alert');
|
||||
if (!$alert.length) {
|
||||
$alert = $('<div class="am-alert am-alert-danger"></div>').hide()
|
||||
$alert.appendTo($("#role_name_valid"));
|
||||
}
|
||||
if(message.length==0){
|
||||
$alert.hide();
|
||||
}else{
|
||||
$alert.text(message).show();
|
||||
}
|
||||
}
|
||||
/*角色名称检验 end*/
|
||||
|
||||
|
||||
/*复选框 全选:start*/
|
||||
$(".role-authority-checkall").click(function(){
|
||||
var $parentNode = $(this).parent().parent();
|
||||
var level = Number($parentNode.attr("level"));
|
||||
var $allParentNextNode = $parentNode.nextUntil(".level-"+level);
|
||||
var isChecked = $(this).is(":checked");
|
||||
$allParentNextNode.each(function(){
|
||||
var myLevel = Number($(this).attr("level"));
|
||||
var $checks = $(this).children().find("input[type='checkbox']");
|
||||
if(myLevel > level){
|
||||
return changeCheckedStatus($checks,isChecked);
|
||||
}else{
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
var $checks = $(this).parent().prev().find("input[type='checkbox']");
|
||||
changeCheckedStatus($checks,isChecked);
|
||||
});
|
||||
|
||||
function changeCheckedStatus(checksObj,isChecked){
|
||||
checksObj.each(function(){
|
||||
if(isChecked){
|
||||
$(this).prop("checked",true);
|
||||
}else{
|
||||
$(this).prop("checked",false);
|
||||
}
|
||||
});
|
||||
}
|
||||
/*复选框 全选:end*/
|
||||
|
||||
$(function() {
|
||||
/*表单验证:begin*/
|
||||
//自定义规则,用法:验证元素上加class="js-pattern-sort"
|
||||
if ($.AMUI && $.AMUI.validator) {
|
||||
$.AMUI.validator.patterns.sort = /^([0-9]+)$/;
|
||||
}
|
||||
$("#tmpForm").validator({
|
||||
// 域通过验证时回调
|
||||
onValid: function(validity) {
|
||||
$(validity.field).closest('.am-form-group').find('.am-alert').hide();
|
||||
},
|
||||
// 域验证通过时添加的操作,通过该接口可定义各种验证提示
|
||||
markValid: function(validity) {
|
||||
// this is Validator instance
|
||||
var $field = $(validity.field);
|
||||
//add by zxl,只对有required属性的字段进行验证
|
||||
if(typeof($field.attr("required"))!="undefined"){
|
||||
var options = this.options;
|
||||
var $parent = $field.closest('.am-form-group');
|
||||
$field.addClass(options.validClass).
|
||||
removeClass(options.inValidClass);
|
||||
|
||||
$parent.addClass('am-form-success').removeClass('am-form-error');
|
||||
|
||||
options.onValid.call(this, validity);
|
||||
}
|
||||
},
|
||||
// 验证出错时的回调, validity 对象包含相关信息,格式通 H5 表单元素的 validity 属性
|
||||
onInValid: function(validity) {
|
||||
var $field = $(validity.field);
|
||||
var $group = $field.closest('.am-form-group');
|
||||
var $alert = $group.find('.am-alert');
|
||||
// 使用自定义的提示信息 或 插件内置的提示信息
|
||||
var msg = $field.data('validationMessage') || this.getValidationMessage(validity);
|
||||
|
||||
if (!$alert.length) {
|
||||
$alert = $("<div class='am-alert am-alert-danger'></div>").hide().
|
||||
appendTo($group.find(".input-msg"));
|
||||
}
|
||||
console.log("onInValid : "+$field.val());
|
||||
$alert.html(msg).show();
|
||||
}
|
||||
});
|
||||
/*表单验证:end*/
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
<style type="text/css">
|
||||
/*验证:提示信息样式 begin*/
|
||||
.am-alert-danger {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
color: red;
|
||||
}
|
||||
.am-alert {
|
||||
margin-bottom: 1em;
|
||||
padding: .625em;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
/*验证:提示信息样式 end*/
|
||||
</style>
|
|
@ -0,0 +1,204 @@
|
|||
<#assign base=request.contextPath />
|
||||
<#import "../common/defaultLayout.ftl" as defaultLayout>
|
||||
<@defaultLayout.layout>
|
||||
<link rel="stylesheet" href="${base}/assets/css/amazeui.switch.css"/>
|
||||
<div class="admin-content">
|
||||
<div class="am-cf am-padding" style="padding:1rem 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">工作流程</strong> /
|
||||
<small>模型管理</small>
|
||||
</div>
|
||||
</div>
|
||||
<form class="am-form" id="list-form" action="${base}/actScript/list" method="post">
|
||||
<input type="hidden" id="keywords" name="keywords" value='${keywords!""}'/>
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 am-u-md-6" style="padding:0px 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<div class="am-btn-toolbar">
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
<#--<@shiro.hasPermission name="ROLE_ADD">-->
|
||||
<button type="button" class="am-btn am-btn-default"
|
||||
onclick="location.href='${base}/actScript/add'">
|
||||
<span class="am-icon-plus"></span>
|
||||
新增
|
||||
</button>
|
||||
<#-- </@shiro.hasPermission>
|
||||
<@shiro.hasPermission name="ROLE_DELRTE">-->
|
||||
<button type="button" id="deleteButton" disabled="disabled"
|
||||
class="am-btn am-btn-default"
|
||||
onclick="deleteAll('${base}/actScript/delete')"><span
|
||||
class="am-icon-trash-o"></span> 删除
|
||||
</button>
|
||||
<#--</@shiro.hasPermission>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="am-u-sm-12 am-u-md-3">
|
||||
<div class="am-input-group am-input-group-sm">
|
||||
<input type="text" class="am-form-field" id="name" value="${name!}" placeholder="按名称搜索"/>
|
||||
<span class="am-input-group-btn">
|
||||
<button id="searchButton" class="am-btn am-btn-default" type="button">搜索</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 am-scrollable-horizontal">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<table class="am-table am-table-striped am-table-hover table-main">
|
||||
<thead>
|
||||
<tr class="am-text-nowrap">
|
||||
<th class="table-check">
|
||||
<input type="checkbox" id="allCheck"></th>
|
||||
<th class="table-title">id</th>
|
||||
<th class="table-title">脚本名称</th>
|
||||
<th class="table-title">脚本所在类</th>
|
||||
<th class="table-date">脚本方法</th>
|
||||
<th class="table-date">创建日期</th>
|
||||
<th class="table-date">最后更新日期</th>
|
||||
<th class="table-set am-text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<#if (pager.list)?exists>
|
||||
<#list pager.list as list>
|
||||
<tr>
|
||||
<td>
|
||||
<input type="checkbox" name="ids" value="${list.id}"/>
|
||||
</td>
|
||||
<td>${list.id!}</td>
|
||||
<td>${list.scriptName!}</td>
|
||||
<td>${list.className!}</td>
|
||||
<td>${list.classMethod!}</td>
|
||||
<td><#if list.createdTime??>${list.createdTime?datetime}</#if></td>
|
||||
<td><#if list.lastUpdatedTime??>${list.lastUpdatedTime?datetime}</#if></td>
|
||||
<td>
|
||||
<div class="am-btn-toolbar">
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="location.href='${base}/actScript/edit?id=${list.id}'"><span
|
||||
class="am-icon-pencil-square-o"></span>编辑
|
||||
</button>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</#list>
|
||||
</#if>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="am-cf">
|
||||
<!-- 分页 -->
|
||||
<#if (pager.list)?exists && (pager.list?size>0) >
|
||||
<div class="am-fr">
|
||||
<#include "../common/common_pager.ftl">
|
||||
</div>
|
||||
<#else>
|
||||
<div class="am-kai" align="center">
|
||||
<h3>没有找到任何记录!</h3>
|
||||
</div>
|
||||
</#if>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</@defaultLayout.layout>
|
||||
|
||||
<script src="${base}/assets/js/amazeui.switch.js"></script>
|
||||
<script type="text/javascript">
|
||||
var urlBase = "${base}";
|
||||
var url;
|
||||
|
||||
$(function () {
|
||||
/*表单提交 start*/
|
||||
var keywordsObj = {};
|
||||
$("#searchButton").on("click", function () {
|
||||
if ($("#name").val()) {
|
||||
keywordsObj.name = $("#name").val();
|
||||
}
|
||||
var keywords = "";
|
||||
if (!$.isEmptyObject(keywordsObj)) {
|
||||
keywords = JSON.stringify(keywordsObj);
|
||||
}
|
||||
console.log("keywords = " + keywords);
|
||||
$("#keywords").val(keywords);
|
||||
$("#list-form").submit();
|
||||
});
|
||||
/*表单提交 end*/
|
||||
|
||||
/*复选框全选效果 start*/
|
||||
$("body").on('click', '.list-item', function () {
|
||||
$(".list-item").removeClass("tr-selected");
|
||||
$(this).addClass('tr-selected');
|
||||
});
|
||||
$("#allCheck").click(function () {
|
||||
$('input[name="ids"]').prop("checked", this.checked);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
var $citySubBox = $("input[name='ids']");
|
||||
$citySubBox.click(function () {
|
||||
$("#allCheckCity").prop("checked", $citySubBox.length == $("input[name='ids']:checked").length ? true : false);
|
||||
$("#deleteButton").prop("disabled", $("input[name='ids']:checked").length == 0 ? true : false);
|
||||
});
|
||||
/*复选框全选效果 end*/
|
||||
|
||||
});
|
||||
|
||||
/*批量删除 start*/
|
||||
var deleteAll = function (url) {
|
||||
var $deleteButton = $("#deleteButton");// 删除按钮
|
||||
var ids = "";
|
||||
$("input[name='ids']:checked").each(function () {
|
||||
ids += $(this).val() + "#%#";
|
||||
});
|
||||
var params = {ids: ids};
|
||||
if (window.confirm('确定要删除吗?')) {
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
beforeSend: function (data) {
|
||||
$deleteButton.prop("disabled", true)
|
||||
},
|
||||
success: function (data) {
|
||||
$deleteButton.prop("disabled", false)
|
||||
if (data.status == 0) {
|
||||
alert(data.msg);
|
||||
window.location.href = window.location.href;
|
||||
} else if (data.status == 1) {
|
||||
alert(data.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/*批量删除 end*/
|
||||
|
||||
|
||||
var deploy = function (id) {
|
||||
var params = {id: id};
|
||||
$.ajax({
|
||||
url: '${base}/actScript/deploy',
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (data) {
|
||||
layer.msg(data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$(function () {
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
<#assign base=request.contextPath />
|
||||
<#import "../common/defaultLayout.ftl" as defaultLayout>
|
||||
<@defaultLayout.layout>
|
||||
<link rel="stylesheet" href="${base}/assets/css/amazeui.switch.css"/>
|
||||
<div class="admin-content">
|
||||
<div class="am-cf am-padding" style="padding:1rem 1.6rem 1.6rem 1rem;margin:0px;">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">${procDefName!}</strong> /
|
||||
<small>任务设置</small>
|
||||
</div>
|
||||
</div>
|
||||
<input name="procDefId" id="procDefId" type="hidden" value="${procDefId!}"/>
|
||||
<div class="am-g">
|
||||
<div class="am-u-sm-12 <#--am-scrollable-horizontal-->">
|
||||
<!-- padding:1px 2px 3px 4px;上、右、下,和左 -->
|
||||
<table class="am-table am-table-striped am-table-hover table-main">
|
||||
<thead>
|
||||
<tr class="am-text-nowrap">
|
||||
<th class="table-title">序号</th>
|
||||
<th class="table-title">任务名称</th>
|
||||
<th class="table-title">任务类型</th>
|
||||
<th class="table-date">回退任务</th>
|
||||
<th class="table-set am-text-center">审批人</th>
|
||||
<th class="table-set am-text-center">审批角色</th>
|
||||
<th class="table-set am-text-center">审批通过脚本</th>
|
||||
<th class="table-set am-text-center">审批驳回脚本</th>
|
||||
<th class="table-set am-text-center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<#list taskList as list>
|
||||
<tr>
|
||||
<td>${list_index+1}</td>
|
||||
<td>${list.taskName!}</td>
|
||||
<td>
|
||||
<#if list.taskIndex != 1>
|
||||
<#if list.taskType == 0>
|
||||
或签
|
||||
<#else>
|
||||
会签
|
||||
</#if>
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<#if list.taskIndex != 1>
|
||||
<select data-am-selected="{btnSize: 'sm',maxHeight: 500}"
|
||||
id="rollbackTask_${list.id}">
|
||||
<#list taskList as l>
|
||||
<option value="${l.taskKey}"
|
||||
<#if list.rollbackTaskKey == l.taskKey>selected</#if> >${l.taskName!}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<#if list.taskIndex != 1>
|
||||
<select multiple data-am-selected="{btnSize: 'sm',maxHeight: 500,searchBox: 1}"
|
||||
id="userSelect_${list.id}">
|
||||
<#list adminList as l>
|
||||
<option value="${l.id}"
|
||||
<#if list.candidateUserList?seq_contains(l.id?c)>selected</#if> >${l.realName!}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<#if list.taskIndex != 1>
|
||||
<select multiple data-am-selected="{btnSize: 'sm',maxHeight: 500,searchBox: 1}"
|
||||
id="roleSelect_${list.id}">
|
||||
<#list roleList as l>
|
||||
<option value="${l.id}"
|
||||
<#if list.candidateRoleList?seq_contains(l.id?c)>selected</#if> >${l.name!}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<#if list.taskIndex != 1>
|
||||
<select data-am-selected="{btnSize: 'sm',maxHeight: 500}"
|
||||
id="scriptSelect_${list.id}">
|
||||
<option value="0"></option>
|
||||
<#list scriptList as l>
|
||||
<option value="${l.id}"
|
||||
<#if list.endScript! == l.id>selected</#if> >${l.scriptName!}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<#if list.taskIndex != 1>
|
||||
<select data-am-selected="{btnSize: 'sm',maxHeight: 500}"
|
||||
id="rollbackScriptSelect_${list.id}">
|
||||
<option value="0"></option>
|
||||
<#list scriptList as l>
|
||||
<option value="${l.id}"
|
||||
<#if list.rollbackScript! == l.id>selected</#if> >${l.scriptName!}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<#if list.taskIndex != 1>
|
||||
<div class="am-btn-toolbar">
|
||||
<div class="am-btn-group am-btn-group-xs">
|
||||
<button type="button"
|
||||
class="am-btn am-btn-default am-btn-xs am-text-secondary"
|
||||
onclick="saveConfig('${list.id}')">
|
||||
<span class="am-icon-pencil-square-o"></span>
|
||||
保存
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</#if>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</#list>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="am-margin">
|
||||
<#--<button type="submit" class="am-btn am-btn-primary am-btn-xs">提交保存</button>-->
|
||||
<button type="button" class="am-btn am-btn-warning am-btn-xs"
|
||||
onclick="location.href='${base}/actProcDef/list'">返回
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</@defaultLayout.layout>
|
||||
|
||||
<script src="${base}/assets/js/amazeui.switch.js"></script>
|
||||
<script type="text/javascript">
|
||||
var urlBase = "${base}";
|
||||
var url;
|
||||
|
||||
|
||||
var saveConfig = function (taskId) {
|
||||
var rollbackTaskKey = $("#rollbackTask_" + taskId + " option:selected").val();
|
||||
var endScript = $("#scriptSelect_" + taskId + " option:selected").val();
|
||||
var rollbackScript = $("#rollbackScriptSelect_" + taskId + " option:selected").val();
|
||||
|
||||
var $userSelected = $("#userSelect_" + taskId + " option:selected");
|
||||
var userIds = '';
|
||||
$userSelected.each(function () {
|
||||
if (userIds == '') {
|
||||
userIds = $(this).val();
|
||||
} else {
|
||||
userIds = userIds + "#" + $(this).val();
|
||||
}
|
||||
});
|
||||
|
||||
var $roleSelected = $("#roleSelect_" + taskId + " option:selected");
|
||||
var roleIds = '';
|
||||
$roleSelected.each(function () {
|
||||
if (roleIds == '') {
|
||||
roleIds = $(this).val();
|
||||
} else {
|
||||
roleIds = roleIds + "#" + $(this).val();
|
||||
}
|
||||
});
|
||||
|
||||
var params = {
|
||||
id: taskId,
|
||||
procDefId: $("#procDefId").val(),
|
||||
rollbackTaskKey: rollbackTaskKey,
|
||||
endScript: endScript,
|
||||
rollbackScript: rollbackScript,
|
||||
candidateUsers: userIds,
|
||||
candidateRoles: roleIds
|
||||
};
|
||||
$.ajax({
|
||||
url: '${base}/actTaskDef/saveConfig',
|
||||
data: params,
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function (data) {
|
||||
layer.msg(data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
Loading…
Reference in New Issue