..
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
package com.budwk.app.flow.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.entity.ProcessCategory;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/flow/category")
|
||||
@Ok("json:full")
|
||||
@Api("流程分类")
|
||||
public class FlowCategoryController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
public Result list() {
|
||||
List<ProcessCategory> list = dao.query(ProcessCategory.class, Cnd.NEW());
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,16 +4,20 @@ import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.vo.LabelValueVO;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.flow.engine.event.ProcessEvent;
|
||||
import com.budwk.app.flow.engine.event.ProcessPublisher;
|
||||
import com.budwk.app.flow.engine.model.ProcessModel;
|
||||
import com.budwk.app.flow.engine.model.TaskModel;
|
||||
import com.budwk.app.flow.entity.Candidate;
|
||||
import com.budwk.app.flow.entity.ProcessDefine;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.enums.ProcessEventTypeEnum;
|
||||
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
|
||||
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
|
||||
import com.budwk.app.flow.vo.ProcessInstanceVO;
|
||||
@@ -66,17 +70,9 @@ public class FlowCommonController {
|
||||
todoTaskVos.add(taskVO);
|
||||
}
|
||||
|
||||
// List<ProcessTaskVO> doneTaskVos = new ArrayList<>();
|
||||
// List<ProcessTask> doneTaskList = flowEngine.processTaskService().getDoneTaskList(instanceId, null);
|
||||
// for (ProcessTask doneTask : doneTaskList) {
|
||||
// ProcessTaskVO taskVO = flowEngine.processTaskService().findById(doneTask.getId());
|
||||
// doneTaskVos.add(taskVO);
|
||||
// }
|
||||
|
||||
HashMap<String, Object> result = new HashMap<>();
|
||||
result.put("processInstance", instanceVO);
|
||||
result.put("todoTasks", todoTaskVos);
|
||||
// result.put("doneTasks", doneTaskVos);
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
@@ -105,12 +101,20 @@ public class FlowCommonController {
|
||||
@At("/defineInfo")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("流程定义详情")
|
||||
public Result defineInfo(String defineKey) {
|
||||
// 通过defineKey获取最新的流程定义
|
||||
ProcessDefine define = flowEngine.processDefineService().getLastByName(defineKey);
|
||||
if (define == null) {
|
||||
return Result.error("未找到指定的流程定义");
|
||||
public Result defineInfo(String defineKey, Long instanceId) {
|
||||
ProcessDefine define = null;
|
||||
if (StrUtil.isNotBlank(defineKey)) {
|
||||
define = flowEngine.processDefineService().getLastByName(defineKey);
|
||||
}
|
||||
if (instanceId != null) {
|
||||
ProcessInstance instance = dao.fetch(ProcessInstance.class, instanceId);
|
||||
define = flowEngine.processDefineService().getById(instanceId);
|
||||
}
|
||||
|
||||
if (define == null) {
|
||||
return Result.error("没有流程定义");
|
||||
}
|
||||
|
||||
return Result.success(define);
|
||||
}
|
||||
|
||||
@@ -170,9 +174,34 @@ public class FlowCommonController {
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@ApiOperation("撤回流程实例")
|
||||
public Result withdrawInstance(@Param("instanceId") Long instanceId) {
|
||||
flowEngine.processInstanceService().withdraw(instanceId, SecurityUtil.getUserId());
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@ApiOperation("重新发起流程实例")
|
||||
public Result reissueInstance(@Param("instanceId") Long instanceId, @Param("bizData") String bizData) {
|
||||
// // 把已撤销流程修改为进行中
|
||||
// dao.update(ProcessInstance.class, Chain.make("state", ProcessInstanceStateEnum.DOING.getCode()), Cnd.where(ProcessInstance::getId, "=", instanceId));
|
||||
// Dict args = Dict.create();
|
||||
// args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
|
||||
// args.set(FlowConst.FORM_DATA, bizData);
|
||||
//
|
||||
// // 查找第一个提交任务节点
|
||||
// ProcessInstance instance = dao.fetch(ProcessInstance.class, instanceId);
|
||||
// ProcessModel processModel = flowEngine.processDefineService().getProcessModel(instance.getProcessDefineId());
|
||||
//
|
||||
// args.set(FlowConst.PROCESS_INSTANCE_ID_KEY, instanceId);
|
||||
// args.set(FlowConst.INITIATOR,instance.getCreatedBy());
|
||||
//
|
||||
// // 构建执行参数对象
|
||||
// Execution execution = new Execution();
|
||||
// execution.setProcessModel(processModel);
|
||||
// execution.setProcessInstance(instance);
|
||||
// execution.setProcessInstanceId(instance.getId());
|
||||
// execution.setEngine(flowEngine);
|
||||
// execution.setArgs(args);
|
||||
// execution.setOperator(SecurityUtil.getUserId());
|
||||
// // 拿到开始节点模型,调用其execute方法
|
||||
// processModel.getStart().execute(execution);
|
||||
//
|
||||
// return Result.success();
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@@ -215,6 +244,10 @@ public class FlowCommonController {
|
||||
// 会签不同意,追加不同意标识
|
||||
args.put(FlowConst.COUNTERSIGN_DISAGREE_FLAG, 1);
|
||||
flowEngine.executeProcessTask(processTaskId, operator, args);
|
||||
} else if (ObjectUtil.equals(submitType, ProcessSubmitTypeEnum.RE_APPLY.getCode())) {
|
||||
// 重新提交
|
||||
// args.put(FlowConst.FORM_DATA, args.getStr(FlowConst.FORM_DATA));
|
||||
flowEngine.executeProcessTask(processTaskId, operator, args);
|
||||
} else {
|
||||
// 默认执行
|
||||
flowEngine.executeProcessTask(processTaskId, operator, args);
|
||||
@@ -222,6 +255,32 @@ public class FlowCommonController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@ApiOperation("撤销任务")
|
||||
public Result revokeTask(@Param("taskId") Long taskId) {
|
||||
// 1.撤销任务
|
||||
List<ProcessTask> taskList = dao.query(ProcessTask.class, Cnd.where(ProcessTask::getTaskParentId, "=", taskId));
|
||||
for (ProcessTask processTask : taskList) {
|
||||
processTask.setTaskState(ProcessTaskStateEnum.WITHDRAW.getCode());
|
||||
dao.update(processTask);
|
||||
}
|
||||
|
||||
// 2.再次激活自己任务
|
||||
ProcessTask processTask = dao.fetch(ProcessTask.class, taskId);
|
||||
processTask.setTaskState(ProcessTaskStateEnum.DOING.getCode());
|
||||
dao.update(processTask);
|
||||
|
||||
|
||||
// 3.发送任务撤回事件 确保上面执行成功
|
||||
for (ProcessTask task : taskList) {
|
||||
ProcessPublisher.notify(ProcessEvent.builder().eventType(ProcessEventTypeEnum.PROCESS_TASK_REVOKE).sourceId(task.getId()).build());
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At("/candidate")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取候选用户")
|
||||
@@ -252,5 +311,13 @@ public class FlowCommonController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At("/addCandidate")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("代理")
|
||||
public Result addCandidate(@Param("taskId") Long taskId, @Param("actorIds") String[] actorIds) {
|
||||
flowEngine.processTaskService().addCandidateActor(taskId, Arrays.asList(actorIds));
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -122,8 +122,9 @@ public class FlowDesignController {
|
||||
jsonObject.set("category", processDesign.getCategory());
|
||||
jsonObject.set("instanceUrl", processDesign.getInstanceUrl());
|
||||
jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl());
|
||||
jsonObject.set("instanceViewUrl",processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl",processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("icon", processDesign.getIcon());
|
||||
processDesign.setContent(jsonObject);
|
||||
dao.insert(processDesign);
|
||||
return Result.success();
|
||||
@@ -139,8 +140,9 @@ public class FlowDesignController {
|
||||
jsonObject.set("category", processDesign.getCategory());
|
||||
jsonObject.set("instanceUrl", processDesign.getInstanceUrl());
|
||||
jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl());
|
||||
jsonObject.set("instanceViewUrl",processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl",processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("icon", processDesign.getIcon());
|
||||
processDesign.setContent(jsonObject);
|
||||
processDesignService.update(processDesign);
|
||||
return Result.success();
|
||||
@@ -156,8 +158,9 @@ public class FlowDesignController {
|
||||
jsonObject.set("category", processDesign.getCategory());
|
||||
jsonObject.set("instanceUrl", processDesign.getInstanceUrl());
|
||||
jsonObject.set("h5InstanceUrl", processDesign.getH5InstanceUrl());
|
||||
jsonObject.set("instanceViewUrl",processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl",processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("instanceViewUrl", processDesign.getInstanceViewUrl());
|
||||
jsonObject.set("h5InstanceViewUrl", processDesign.getH5InstanceViewUrl());
|
||||
jsonObject.set("icon", processDesign.getIcon());
|
||||
processDesign.setContent(jsonObject);
|
||||
processDesignService.update(processDesign);
|
||||
return Result.success();
|
||||
|
||||
@@ -43,14 +43,16 @@ public class FlowTodoCenter {
|
||||
public Result todo(Integer pageNumber, Integer pageSize, String keyword, String categoty) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t.id,
|
||||
t.id AS taskId,
|
||||
t.displayName AS taskName,
|
||||
t.taskState,
|
||||
t.formKey,
|
||||
t.createdAt,
|
||||
t.finishTime,
|
||||
t.variable,
|
||||
ins.state AS instanceState
|
||||
ins.state AS instanceState,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo
|
||||
FROM
|
||||
wf_process_task t
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
@@ -76,12 +78,16 @@ public class FlowTodoCenter {
|
||||
public Result done(Integer pageNumber, Integer pageSize, String keyword, String categoty) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t.id,
|
||||
t.id AS taskId,
|
||||
t.displayName AS taskName,
|
||||
t.taskState,
|
||||
t.formKey,
|
||||
t.createdAt,
|
||||
t.finishTime,
|
||||
ins.state AS instanceState
|
||||
t.variable,
|
||||
ins.state AS instanceState,
|
||||
ins.id AS instanceId,
|
||||
ins.businessNo
|
||||
FROM
|
||||
wf_process_task t
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
@@ -107,14 +113,14 @@ public class FlowTodoCenter {
|
||||
public Result started(Integer pageNumber, Integer pageSize, String keyword, String categoty) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
ins.id,
|
||||
ins.id AS instanceId,
|
||||
ins.processDefineId,
|
||||
ins.state,
|
||||
ins.businessNo,
|
||||
ins.operator,
|
||||
ins.variable,
|
||||
ins.createdAt,
|
||||
GROUP_CONCAT(t.displayName) as taskName
|
||||
GROUP_CONCAT(DISTINCT t.displayName) as taskName
|
||||
FROM
|
||||
wf_process_instance ins
|
||||
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id and t.taskState = 10
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.budwk.app.flow.service.ProcessDefineService;
|
||||
import com.budwk.app.flow.service.ProcessInstanceService;
|
||||
import com.budwk.app.flow.service.ProcessTaskService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.stream.Collectors;
|
||||
@Data
|
||||
public class ProcessModel extends BaseModel {
|
||||
private String type; // 流程定义分类
|
||||
private String icon; // 流程定义图标
|
||||
private String category; // 流程定义分类
|
||||
private String instanceUrl; // 启动实例要填写的表单key
|
||||
private String h5InstanceUrl; // 启动实例要填写的手机端表单key
|
||||
|
||||
@@ -4,15 +4,17 @@ import com.budwk.app.flow.engine.model.BaseModel;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* logicFlow模型
|
||||
*
|
||||
* @author mldong
|
||||
* @date 2023/4/26
|
||||
*/
|
||||
@Data
|
||||
public class LfModel extends BaseModel {
|
||||
private String type; // 流程定义分类
|
||||
private String category;
|
||||
private String expireTime;// 过期时间(常量或变量)
|
||||
private String instanceUrl; // 启动实例的url,前后端分离后,定义为路由名或或路由地址
|
||||
private String h5InstanceUrl;
|
||||
|
||||
@@ -78,6 +78,7 @@ public class ModelParser {
|
||||
processModel.setName(lfModel.getName());
|
||||
processModel.setDisplayName(lfModel.getDisplayName());
|
||||
processModel.setType(lfModel.getType());
|
||||
processModel.setCategory(lfModel.getCategory());
|
||||
processModel.setInstanceUrl(lfModel.getInstanceUrl());
|
||||
processModel.setH5InstanceUrl(lfModel.getH5InstanceUrl());
|
||||
processModel.setInstanceViewUrl(lfModel.getInstanceViewUrl());
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.budwk.app.flow.entity;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table("wf_process_category")
|
||||
@Comment("流程分类")
|
||||
public class ProcessCategory extends BaseModel {
|
||||
|
||||
@Id
|
||||
@Comment("ID")
|
||||
private Long id;
|
||||
|
||||
@Comment("名称")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||
private String name;
|
||||
|
||||
@Comment("图标")
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||
private String icon;
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.budwk.app.flow.entity;
|
||||
|
||||
import cn.hutool.extra.pinyin.PinyinUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Getter;
|
||||
@@ -72,4 +73,9 @@ public class ProcessDefine extends BaseModel {
|
||||
@Column
|
||||
private Integer version;
|
||||
|
||||
@Comment
|
||||
@Column
|
||||
@ColDefine(type = ColType.CHAR)
|
||||
private Character pinyinName;
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ public enum ProcessEventTypeEnum{
|
||||
PROCESS_INSTANCE_END(2, "流程实例结束事件"),
|
||||
PROCESS_TASK_START(3, "流程任务开始事件"),
|
||||
PROCESS_TASK_END(4, "流程任务结束事件"),
|
||||
|
||||
PROCESS_TASK_REVOKE(5, "流程任务撤销事件"),
|
||||
|
||||
;
|
||||
private final Integer code;
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.budwk.app.flow.listenter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.event.ProcessEvent;
|
||||
import com.budwk.app.flow.engine.event.ProcessEventListener;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.entity.ProcessTask;
|
||||
import com.budwk.app.flow.enums.ProcessEventTypeEnum;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
/**
|
||||
* 流程任务撤销事件监听器
|
||||
*/
|
||||
@IocBean
|
||||
public class ProcessTaskRevokeEventListener implements ProcessEventListener {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
|
||||
@Override
|
||||
public void onEvent(ProcessEvent event) {
|
||||
if(event.getEventType()== ProcessEventTypeEnum.PROCESS_TASK_REVOKE){
|
||||
Long taskId = event.getSourceId();
|
||||
ProcessTask task = dao.fetch(ProcessTask.class, taskId);
|
||||
|
||||
String taskDisplayName = task.getDisplayName();
|
||||
|
||||
ProcessInstance instance = dao.fetch(ProcessInstance.class, task.getProcessInstanceId());
|
||||
|
||||
JSONObject variable = JSONUtil.parseObj(instance.getVariable());
|
||||
String initiatorName = variable.getStr(FlowConst.INITIATOR_NAME);
|
||||
String instanceName = variable.getStr(FlowConst.PROCESS_INSTANCE_NAME);
|
||||
|
||||
|
||||
// 消息API提醒
|
||||
String msgTemplate = "{},您的{}已被撤销,无需审核。";
|
||||
String msg = StrUtil.format(msgTemplate, instanceName, taskDisplayName);
|
||||
|
||||
// 发送 go go go
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,4 +233,17 @@ public interface ProcessInstanceService extends BaseService<ProcessInstance> {
|
||||
* @return
|
||||
*/
|
||||
List<LabelValueVO> getAssigneeTextData(Long processInstanceId);
|
||||
|
||||
/**
|
||||
* 删除流程实例
|
||||
* @param processInstanceId
|
||||
*/
|
||||
void deleteProcessInstanceById(Long processInstanceId);
|
||||
|
||||
/**
|
||||
* 删除流程实例
|
||||
* @param businessKey
|
||||
*/
|
||||
void deleteProcessInstanceByBusinessKey(String businessKey);
|
||||
|
||||
}
|
||||
|
||||
@@ -3,17 +3,14 @@ package com.budwk.app.flow.service.impl;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.pinyin.PinyinUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.enums.UpAndDownParam;
|
||||
import com.budwk.app.base.exception.BaseException;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.flow.engine.model.ProcessModel;
|
||||
import com.budwk.app.flow.engine.parser.ModelParser;
|
||||
import com.budwk.app.flow.entity.ProcessDefine;
|
||||
import com.budwk.app.flow.entity.ProcessInstance;
|
||||
import com.budwk.app.flow.service.ProcessDefineService;
|
||||
import com.budwk.app.flow.vo.ProcessDefineVO;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
@@ -23,9 +20,7 @@ import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class ProcessDefineServiceImpl extends BaseServiceImpl<ProcessDefine> implements ProcessDefineService {
|
||||
@@ -100,8 +95,6 @@ public class ProcessDefineServiceImpl extends BaseServiceImpl<ProcessDefine> imp
|
||||
// 1. json定义文件转成流程模型
|
||||
ProcessModel processModel = ModelParser.parse(defineJsonStr);
|
||||
// 2. 根据名称查询,取最新版本的流程定义记录
|
||||
List<ProcessDefine> processDefineList = query(Cnd.where(ProcessDefine::getName, "=", processModel.getName()).desc(ProcessDefine::getId));
|
||||
|
||||
ProcessDefine latestDefine = dao().fetch(ProcessDefine.class, Cnd.where(ProcessDefine::getName, "=", processModel.getName()).desc(ProcessDefine::getId));
|
||||
|
||||
ProcessDefine define = null;
|
||||
@@ -122,9 +115,8 @@ public class ProcessDefineServiceImpl extends BaseServiceImpl<ProcessDefine> imp
|
||||
define.setH5InstanceUrl(processModel.getH5InstanceUrl());
|
||||
define.setInstanceViewUrl(processModel.getInstanceViewUrl());
|
||||
define.setH5InstanceViewUrl(processModel.getH5InstanceViewUrl());
|
||||
|
||||
// define.setInstanceViewUrl(latestDefine.getInstanceViewUrl());
|
||||
// define.setH5InstanceViewUrl(latestDefine.getH5InstanceViewUrl());
|
||||
define.setIcon(processModel.getIcon());
|
||||
define.setPinyinName(PinyinUtil.getFirstLetter(define.getDisplayName().charAt(0)));
|
||||
|
||||
define.setState(1);
|
||||
define.setContent(JSONUtil.parseObj(defineJsonStr));
|
||||
|
||||
@@ -9,11 +9,9 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.expression.ExpressionUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.budwk.app.base.enums.YesNoEnum;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.base.vo.LabelValueVO;
|
||||
import com.budwk.app.flow.constant.FlowConst;
|
||||
import com.budwk.app.flow.engine.Context;
|
||||
import com.budwk.app.flow.engine.DecisionHandler;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.flow.engine.core.Execution;
|
||||
@@ -93,7 +91,13 @@ public class ProcessInstanceServiceImpl extends BaseServiceImpl<ProcessInstance>
|
||||
|
||||
ProcessInstanceVO instanceVO = new ProcessInstanceVO();
|
||||
BeanUtil.fillBeanWithMapIgnoreCase(nutMap, instanceVO, true);
|
||||
instanceVO.setJsonObject(processDefineService.getDefineJsonObject(instanceVO.getProcessDefineId()));
|
||||
|
||||
ProcessDefine define = processDefineService.fetch(instanceVO.getProcessDefineId());
|
||||
|
||||
// instanceVO.setJsonObject(processDefineService.getDefineJsonObject(instanceVO.getProcessDefineId()));
|
||||
|
||||
instanceVO.setJsonObject(JSONUtil.parseObj(define));
|
||||
|
||||
return instanceVO;
|
||||
}
|
||||
|
||||
@@ -319,24 +323,38 @@ public class ProcessInstanceServiceImpl extends BaseServiceImpl<ProcessInstance>
|
||||
|
||||
@Override
|
||||
public void withdraw(Long processInstanceId, String operator) {
|
||||
Date now = new Date();
|
||||
// Date now = new Date();
|
||||
// 1. 将该流程实例状态修改为撤回
|
||||
ProcessInstance processInstance = new ProcessInstance();
|
||||
processInstance.setId(processInstanceId);
|
||||
processInstance.setState(ProcessInstanceStateEnum.WITHDRAW.getCode());
|
||||
processInstance.setUpdatedAt(System.currentTimeMillis());
|
||||
processInstance.setUpdatedBy(operator);
|
||||
int update = dao().update(ProcessInstance.class, Chain.from(processInstance), Cnd.where(ProcessInstance::getId, "=", processInstanceId)
|
||||
.and(ProcessInstance::getState, "=", ProcessInstanceStateEnum.DOING.getCode()));
|
||||
int updated = dao().updateIgnoreNull(processInstance);
|
||||
|
||||
if (update >= 1) {
|
||||
// 2. 将该流程实例产生的任务状态修改为撤回
|
||||
ProcessTask processTask = new ProcessTask();
|
||||
processTask.setTaskState(ProcessTaskStateEnum.WITHDRAW.getCode());
|
||||
processTask.setUpdatedAt(System.currentTimeMillis());
|
||||
processTask.setUpdatedBy(operator);
|
||||
dao().update(ProcessTask.class, Chain.from(processTask), Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId)
|
||||
.and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.DOING.getCode()));
|
||||
// 2. 将该流程实例产生的任务状态修改为撤回
|
||||
if (updated > 0) {
|
||||
List<ProcessTask> taskList = dao().query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId).and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.DOING.getCode()));
|
||||
for (ProcessTask processTask : taskList) {
|
||||
processTask.setTaskState(ProcessTaskStateEnum.WITHDRAW.getCode());
|
||||
processTask.setUpdatedAt(System.currentTimeMillis());
|
||||
processTask.setUpdatedBy(operator);
|
||||
}
|
||||
dao().update(taskList, "taskState|updateAt|updateBy");
|
||||
}
|
||||
|
||||
// int update = dao().update(ProcessInstance.class, Chain.from(processInstance), Cnd.where(ProcessInstance::getId, "=", processInstanceId)
|
||||
// .and(ProcessInstance::getState, "=", ProcessInstanceStateEnum.DOING.getCode()));
|
||||
//
|
||||
// if (update >= 1) {
|
||||
// // 2. 将该流程实例产生的任务状态修改为撤回
|
||||
// ProcessTask processTask = new ProcessTask();
|
||||
// processTask.setTaskState(ProcessTaskStateEnum.WITHDRAW.getCode());
|
||||
// processTask.setUpdatedAt(System.currentTimeMillis());
|
||||
// processTask.setUpdatedBy(operator);
|
||||
// dao().update(ProcessTask.class, Chain.from(processTask), Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId)
|
||||
// .and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.DOING.getCode()));
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,4 +549,22 @@ public class ProcessInstanceServiceImpl extends BaseServiceImpl<ProcessInstance>
|
||||
.collect(Collectors.toList());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void deleteProcessInstanceById(Long processInstanceId) {
|
||||
List<ProcessTask> taskList = dao().query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId));
|
||||
List<Long> taskIds = taskList.stream().map(ProcessTask::getId).toList();
|
||||
dao().clear(ProcessTask.class, Cnd.where(ProcessTask::getId, "in", taskIds));
|
||||
dao().clear(ProcessInstance.class, Cnd.where(ProcessInstance::getId, "=", processInstanceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteProcessInstanceByBusinessKey(String businessKey) {
|
||||
ProcessInstance processInstance = fetch(Cnd.where(ProcessInstance::getBusinessNo, "=", businessKey));
|
||||
if (processInstance != null) {
|
||||
deleteProcessInstanceById(processInstance.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ public class ProcessTaskServiceImpl extends BaseServiceImpl<ProcessTask> impleme
|
||||
|
||||
@Override
|
||||
public List<ProcessTask> getDoneTaskList(Long processInstanceId, String[] taskNames) {
|
||||
Cnd cnd = Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId).and(ProcessTask::getTaskState, "!=", ProcessTaskStateEnum.DOING.getCode());
|
||||
Cnd cnd = Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstanceId).and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.FINISHED.getCode());
|
||||
cnd.andEX(ProcessTask::getTaskName, "", taskNames);
|
||||
List<ProcessTask> processTaskList = query(cnd);
|
||||
return processTaskList;
|
||||
|
||||
@@ -47,6 +47,16 @@ public class SysHomeV4Controller {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务中心
|
||||
*/
|
||||
@At("/serv")
|
||||
@Ok("beetl:/layouts/v4/serv.html")
|
||||
@SaCheckLogin
|
||||
public void serv(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 子系统
|
||||
* @param appId 应用ID
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.budwk.app.sys.controller.v4;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.entity.ProcessCategory;
|
||||
import com.budwk.app.sys.services.SysMenuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/v4/serv")
|
||||
@Api(value = "服务中心接口", tags = "服务中心接口")
|
||||
public class SysV4ServController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private SysMenuService sysMenuService;
|
||||
|
||||
@At("/categories")
|
||||
@Ok("json")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取分类")
|
||||
public Result categories() {
|
||||
List<ProcessCategory> list = dao.query(ProcessCategory.class, Cnd.NEW());
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@At("/list")
|
||||
@Ok("json:full")
|
||||
@SaCheckLogin
|
||||
@ApiOperation("获取应用列表")
|
||||
public Result list(@Param("categoryId") String categoryId, @Param("letter") String letter, @Param("keyword") String keyword, HttpServletRequest req) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT t.*
|
||||
FROM wf_process_define t
|
||||
INNER JOIN (
|
||||
SELECT name, MAX(id) AS max_id
|
||||
FROM wf_process_define
|
||||
GROUP BY name
|
||||
) sub ON t.name = sub.name AND t.id = sub.max_id
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
if (StrUtil.isNotBlank(keyword)) {
|
||||
cnd.where().andLike("t.disPlayName", keyword);
|
||||
}
|
||||
cnd.andEX("t.category", "=", categoryId);
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> list = sysMenuService.listMap(sql);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+20
-2
@@ -3,17 +3,22 @@ package com.budwk.app.zhgh.democratic.suggestionBox.controller;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.democratic.suggestionBox.service.SuggestionBoxService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/suggestionBox2/apply")
|
||||
@@ -23,11 +28,13 @@ public class SuggestionApplyController {
|
||||
|
||||
@Inject
|
||||
private SuggestionBoxService suggestionBoxService;
|
||||
@Inject
|
||||
private FlowEngine flowEngine;
|
||||
|
||||
@At("/index")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/suggestionBox/apply/index.html")
|
||||
@SaCheckLogin
|
||||
public void index(){
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
@@ -62,7 +69,9 @@ public class SuggestionApplyController {
|
||||
t.taskState,
|
||||
t.finishTime,
|
||||
t.taskParentId,
|
||||
t.variable taskVariale
|
||||
t.variable taskVariale,
|
||||
IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke,
|
||||
(select MAX(id) from wf_process_task where processInstanceId = ins.id and taskName = 'startTask') AS startTaskId
|
||||
FROM
|
||||
suggestion_box info
|
||||
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
|
||||
@@ -78,5 +87,14 @@ public class SuggestionApplyController {
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@ApiOperation("删除")
|
||||
public Result delete(@Param("id") String id) {
|
||||
suggestionBoxService.delete(id);
|
||||
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-3
@@ -68,12 +68,16 @@ public class SuggestionXghController {
|
||||
t.taskState,
|
||||
t.finishTime,
|
||||
t.taskParentId,
|
||||
t.variable taskVariale
|
||||
t.variable taskVariable,
|
||||
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
|
||||
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
|
||||
FROM
|
||||
wf_process_task t
|
||||
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
|
||||
LEFT JOIN suggestion_box info ON info.id = ins.businessNo
|
||||
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
|
||||
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
|
||||
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
|
||||
$condition
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
@@ -86,8 +90,6 @@ public class SuggestionXghController {
|
||||
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
|
||||
}
|
||||
|
||||
cnd.desc("t.createdAt");
|
||||
|
||||
cnd.andEX("YEAR(info.submitTime)", "=", year);
|
||||
cnd.and(Cnd.likeEX("info.title", title));
|
||||
|
||||
@@ -96,6 +98,8 @@ public class SuggestionXghController {
|
||||
} else {
|
||||
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||
}
|
||||
cnd.groupBy("t.id");
|
||||
cnd.desc("t.createdAt");
|
||||
sql.setCondition(cnd);
|
||||
Pagination<NutMap> pageVO = suggestionBoxService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return Result.success(pageVO);
|
||||
|
||||
@@ -664,7 +664,6 @@ td.no-b {
|
||||
}
|
||||
|
||||
.flow-task-form .el-descriptions-item__label.is-bordered-label {
|
||||
color: rgb(102, 102, 102) !important;
|
||||
background: rgb(248, 249, 250) !important;
|
||||
padding: 8px 12px !important;
|
||||
border: 1px solid rgb(221, 221, 221) !important;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<div class="panel-content">
|
||||
<div class="info-table">
|
||||
<!-- 新申请场景 -->
|
||||
<template v-if="isNewApplication">
|
||||
<template v-if="isNewApplication || (processInstance && processInstance.state === 30)">
|
||||
<div class="info-row">
|
||||
<div class="info-label">流程名称:</div>
|
||||
<div class="info-value">{{ processDefinition.displayName || processDefinition.name }}</div>
|
||||
@@ -82,13 +82,20 @@
|
||||
</div>
|
||||
|
||||
<!-- 表单处理区域 -->
|
||||
<div class="form-panel" v-if="isNewApplication || todoTasks.map((v) => v.id).includes(taskId)">
|
||||
<div
|
||||
class="form-panel"
|
||||
v-if="isNewApplication || (processInstance && processInstance.state === 30) || todoTasks.map((v) => v.id).includes(taskId)"
|
||||
>
|
||||
<div class="panel-header">
|
||||
<h3 class="panel-title">{{ formPanelTitle }}</h3>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<!-- 新申请表单 -->
|
||||
<div v-if="isNewApplication" id="application-form-container" class="form-content">
|
||||
<div
|
||||
v-if="isNewApplication || (processInstance && processInstance.state === 30)"
|
||||
id="application-form-container"
|
||||
class="form-content"
|
||||
>
|
||||
<div v-if="pjaxLoading.apply" class="loading-state">
|
||||
<i class="el-icon-loading"></i>
|
||||
<span>正在加载申请表单...</span>
|
||||
@@ -121,7 +128,72 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script type="text/javascript">
|
||||
class PjaxSync {
|
||||
constructor() {
|
||||
this.isLoading = false
|
||||
this.queue = []
|
||||
}
|
||||
|
||||
async request(url, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const requestData = { url, options, resolve, reject }
|
||||
|
||||
if (this.isLoading) {
|
||||
this.queue.push(requestData)
|
||||
return
|
||||
}
|
||||
|
||||
this._executeRequest(requestData)
|
||||
})
|
||||
}
|
||||
|
||||
_executeRequest({ url, options, resolve, reject }) {
|
||||
this.isLoading = true
|
||||
|
||||
const defaultOptions = {
|
||||
timeout: 10000,
|
||||
push: false,
|
||||
replace: false,
|
||||
...options
|
||||
}
|
||||
|
||||
const successHandler = (event, data, status, xhr) => {
|
||||
this._cleanup()
|
||||
resolve({ data, status, xhr })
|
||||
this._processQueue()
|
||||
}
|
||||
|
||||
const errorHandler = (event, xhr, textStatus, errorThrown) => {
|
||||
this._cleanup()
|
||||
reject(new Error(textStatus || "PJAX request failed"))
|
||||
this._processQueue()
|
||||
}
|
||||
|
||||
$(document).one("pjax:success", successHandler)
|
||||
$(document).one("pjax:error", errorHandler)
|
||||
|
||||
$.pjax({
|
||||
url: url,
|
||||
...defaultOptions
|
||||
})
|
||||
}
|
||||
|
||||
_cleanup() {
|
||||
this.isLoading = false
|
||||
$(document).off("pjax:success pjax:error")
|
||||
}
|
||||
|
||||
_processQueue() {
|
||||
if (this.queue.length > 0) {
|
||||
const nextRequest = this.queue.shift()
|
||||
this._executeRequest(nextRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 创建全局实例
|
||||
const pjaxSync = new PjaxSync()
|
||||
|
||||
module.exports = {
|
||||
name: "SnakerFlow",
|
||||
data() {
|
||||
@@ -221,7 +293,7 @@ module.exports = {
|
||||
} else if (this.shouldShowTaskForm) {
|
||||
return this.currentTask.displayName || "任务表单"
|
||||
} else if (this.shouldShowHistoryProcess) {
|
||||
return "办理过程"
|
||||
return "申请表单"
|
||||
} else {
|
||||
return "表单信息"
|
||||
}
|
||||
@@ -236,7 +308,6 @@ module.exports = {
|
||||
|
||||
// 是否显示任务表单
|
||||
shouldShowTaskForm() {
|
||||
debugger
|
||||
return this.taskId != null
|
||||
},
|
||||
|
||||
@@ -277,20 +348,20 @@ module.exports = {
|
||||
},
|
||||
created() {
|
||||
this.initComponent()
|
||||
// 监听
|
||||
window.addEventListener("message", (event) => {
|
||||
// 监听消息
|
||||
new BroadcastChannel("zhgh-global-channel").addEventListener("message", (event) => {
|
||||
if (event.data.type === "task-complete") {
|
||||
this.initComponent()
|
||||
}
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
console.log("beforeDestroy")
|
||||
},
|
||||
methods: {
|
||||
// 初始化组件
|
||||
async initComponent() {
|
||||
this.loading = true
|
||||
|
||||
debugger
|
||||
|
||||
if (this.isNewApplication) {
|
||||
// 新申请:加载流程定义信息
|
||||
await this.loadProcessDefinition()
|
||||
@@ -299,6 +370,12 @@ module.exports = {
|
||||
} else if (this.isExistingProcess) {
|
||||
// 已有流程:加载流程实例信息
|
||||
await this.loadProcessInstance()
|
||||
if (this.processInstance && this.processInstance.state === 30) {
|
||||
// 流程被撤回了 此时加载申请表单
|
||||
// 加载流程申请表单
|
||||
await this.loadApplicationForm()
|
||||
}
|
||||
|
||||
// 加载任务信息
|
||||
await this.loadCurrentTask()
|
||||
// 如果有businessId且不是第一个任务节点,加载历史办理过程
|
||||
@@ -317,9 +394,11 @@ module.exports = {
|
||||
// 加载流程定义信息
|
||||
async loadProcessDefinition() {
|
||||
if (!this.defineKey) return
|
||||
|
||||
try {
|
||||
const response = await $.get("/flow/common/defineInfo", { defineKey: this.defineKey })
|
||||
const response = await $.get("/flow/common/defineInfo", {
|
||||
defineKey: this.defineKey,
|
||||
instanceId: this.instanceId
|
||||
})
|
||||
if (response.code === 0) {
|
||||
this.processDefinition = response.data
|
||||
}
|
||||
@@ -334,20 +413,11 @@ module.exports = {
|
||||
|
||||
this.pjaxLoading.apply = true
|
||||
|
||||
$.pjax({
|
||||
url: this.processDefinition.instanceUrl,
|
||||
container: "#application-form-container",
|
||||
push: false,
|
||||
replace: false,
|
||||
timeout: 10000
|
||||
await pjaxSync.request(this.processDefinition.instanceUrl, {
|
||||
container: "#application-form-container"
|
||||
})
|
||||
.done(() => {
|
||||
this.pjaxLoading.apply = false
|
||||
})
|
||||
.fail(() => {
|
||||
this.pjaxLoading.apply = false
|
||||
console.log(this.processDefinition.instanceUrl, "申请表单加载失败")
|
||||
})
|
||||
|
||||
this.pjaxLoading.apply = false
|
||||
},
|
||||
|
||||
// 加载流程实例信息
|
||||
@@ -356,6 +426,7 @@ module.exports = {
|
||||
const { code, data, msg } = await $.get("/flow/common/instanceInfo", { instanceId: this.instanceId })
|
||||
if (code === 0) {
|
||||
this.processInstance = data.processInstance
|
||||
this.processDefinition = data.processInstance?.jsonObject
|
||||
this.todoTasks = data.todoTasks
|
||||
}
|
||||
},
|
||||
@@ -381,43 +452,23 @@ module.exports = {
|
||||
|
||||
this.pjaxLoading.taskForm = true
|
||||
|
||||
$.pjax({
|
||||
url: this.currentTask.taskModel.form,
|
||||
container: "#task-form-container",
|
||||
push: false,
|
||||
replace: false,
|
||||
timeout: 10000
|
||||
await pjaxSync.request(this.currentTask.taskModel.form, {
|
||||
container: "#task-form-container"
|
||||
})
|
||||
.done(() => {
|
||||
this.pjaxLoading.taskForm = false
|
||||
})
|
||||
.fail(() => {
|
||||
this.pjaxLoading.taskForm = false
|
||||
console.log(this.currentTask.taskModel.form, "任务表单加载失败")
|
||||
})
|
||||
},
|
||||
|
||||
// 加载历史办理过程
|
||||
async loadHistoryProcess() {
|
||||
if (!this.businessId) return
|
||||
const { instanceViewUrl } = this.processInstance.jsonObject
|
||||
|
||||
this.pjaxLoading.historyProcess = true
|
||||
if (instanceViewUrl) {
|
||||
$.pjax({
|
||||
url: `${instanceViewUrl}?businessId=${this.businessId}&instanceId=${this.instanceId}`,
|
||||
container: "#history-process-container",
|
||||
push: false,
|
||||
replace: false,
|
||||
timeout: 10000
|
||||
this.pjaxLoading.historyProcess = true
|
||||
|
||||
await pjaxSync.request(`${instanceViewUrl}?businessId=${this.businessId}&instanceId=${this.instanceId}`, {
|
||||
container: "#history-process-container"
|
||||
})
|
||||
.done(() => {
|
||||
this.pjaxLoading.historyProcess = false
|
||||
})
|
||||
.fail(() => {
|
||||
this.pjaxLoading.historyProcess = false
|
||||
console.log("历史办理过程加载失败")
|
||||
})
|
||||
|
||||
this.pjaxLoading.historyProcess = false
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -149,8 +149,7 @@ module.exports = {
|
||||
// 处理提交操作
|
||||
handleSubmit() {
|
||||
// 根据是否有流程实例来确定操作类型
|
||||
// const submitAction = this.instanceId ? this.actionEnum.RE_APPLY : this.actionEnum.APPLY
|
||||
const submitAction = this.actionEnum.APPLY
|
||||
const submitAction = this.instanceId ? this.actionEnum.RE_APPLY : this.actionEnum.APPLY
|
||||
|
||||
// 触发父组件事件,传递提交操作
|
||||
this.$emit("task-action", {
|
||||
@@ -160,7 +159,6 @@ module.exports = {
|
||||
defineId: this.defineId,
|
||||
defineKey: this.defineKey,
|
||||
businessId: this.businessId
|
||||
// currentTask: this.taskInfo
|
||||
})
|
||||
},
|
||||
|
||||
@@ -201,7 +199,11 @@ module.exports = {
|
||||
|
||||
// 取消操作
|
||||
handleCancel() {
|
||||
this.$emit("cancel")
|
||||
const func = () => window.close()
|
||||
this.$emit("cancel", func)
|
||||
if (!this.$listeners.cancel) {
|
||||
func()
|
||||
}
|
||||
},
|
||||
|
||||
// 刷新任务信息
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<script src="${base!}/assets/platform/plugins/form-create/form-create.min.js"></script>
|
||||
<script src="${base!}/assets/platform/plugins/form-create/index.umd.js"></script>
|
||||
|
||||
<!-- <script src="${base!}/assets/platform/plugins/snaker/SnakerflowDesigner.umd.min.js"></script>-->
|
||||
<!-- <script src="${base!}/assets/platform/plugins/snaker/SnakerflowDesigner.umd.min.js"></script>-->
|
||||
|
||||
<script src="${base!}/components/plugins/sysDict/DictData.js"></script>
|
||||
<script src="${base!}/assets/platform/js/util/commonUtil.js"></script>
|
||||
@@ -101,6 +101,11 @@
|
||||
Vue.use(FcDesigner.formCreate)
|
||||
</script>
|
||||
|
||||
<!--广播频道-->
|
||||
<script type="text/javascript">
|
||||
window.GlobalBroadcastChannel = new BroadcastChannel("zhgh-global-channel")
|
||||
</script>
|
||||
|
||||
<!--ws-->
|
||||
<script type="text/javascript">
|
||||
class WebSocketPubSub {
|
||||
@@ -334,12 +339,17 @@
|
||||
Vue.component("excel-import", httpVueLoader("/components/plugins/sysImport/excelImport.vue?v=" + new Date().getTime()))
|
||||
Vue.component("flow-form-button", httpVueLoader("/components/plugins/flowable/formButton.vue?v=" + new Date().getTime()))
|
||||
Vue.component("snaker-flow", httpVueLoader("/components/plugins/snaker/snakerFlow.vue?v=" + new Date().getTime()))
|
||||
Vue.component("snaker-flow-task-form-action", httpVueLoader("/components/plugins/snaker/snakerFlowTaskFormAction.vue?v=" + new Date().getTime()))
|
||||
Vue.component("snaker-flow-history-approval", httpVueLoader("/components/plugins/snaker/snakerFlowHisApproval.vue?v=" + new Date().getTime()))
|
||||
Vue.component(
|
||||
"snaker-flow-task-form-action",
|
||||
httpVueLoader("/components/plugins/snaker/snakerFlowTaskFormAction.vue?v=" + new Date().getTime())
|
||||
)
|
||||
Vue.component(
|
||||
"snaker-flow-history-approval",
|
||||
httpVueLoader("/components/plugins/snaker/snakerFlowHisApproval.vue?v=" + new Date().getTime())
|
||||
)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
.v4-header {
|
||||
background-color: rgb(0, 109, 185);
|
||||
box-shadow: 0 2px 10px rgba(0, 109, 185, 0.3);
|
||||
@@ -555,6 +565,10 @@
|
||||
<i class="fa fa-th-large"></i>
|
||||
应用中心
|
||||
</a>
|
||||
<a href="/platform/v4/serv" data-pjax class="v4-nav-item">
|
||||
<i class="fa fa-th-large"></i>
|
||||
服务中心
|
||||
</a>
|
||||
<a href="/flow/todoCenter" data-pjax class="v4-nav-item">
|
||||
<i class="fa fa-th-large"></i>
|
||||
待办中心
|
||||
|
||||
@@ -0,0 +1,597 @@
|
||||
<!--#
|
||||
layout("/layouts/v4/baseLayout.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
.apps-hero {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/*border-radius: 8px 8px 0 0;*/
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.apps-hero img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.apps-container {
|
||||
display: flex;
|
||||
/*height: calc(100vh - 64px - 48px - 180px);*/
|
||||
background-color: #fff;
|
||||
/*border-radius: 0 0 8px 8px;*/
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.apps-sidebar {
|
||||
width: 220px;
|
||||
background-color: #f7f7f7;
|
||||
border-right: 1px solid #e8e8e8;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.apps-sidebar-item {
|
||||
padding: 16px 20px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.apps-sidebar-item.active {
|
||||
background-color: #e6f7ff;
|
||||
color: var(--color-primary);
|
||||
border-right: 2px solid #1890ff;
|
||||
}
|
||||
|
||||
.apps-sidebar-item:hover:not(.active) {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.apps-content {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.apps-header {
|
||||
padding: 0 0 20px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.apps-search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.apps-search {
|
||||
position: relative;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.apps-search input {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
padding: 0 15px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.apps-search .search-icon {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.apps-filter {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.apps-filter-title {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.apps-filter-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.filter-tag {
|
||||
padding: 5px 15px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.filter-tag.active {
|
||||
background-color: var(--color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.filter-tag:not(.active) {
|
||||
background-color: #f0f0f0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.filter-tag:not(.active):hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.apps-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
grid-auto-rows: min-content;
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
.app-card {
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.app-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.app-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 15px;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.app-icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.app-icon i {
|
||||
color: var(--color-primary);
|
||||
font-size: 38px;
|
||||
}
|
||||
|
||||
.favorite-icon {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-size: 18px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.favorite-icon.active {
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
.favorite-icon:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.app-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.app-desc {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.alphabet-filter {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.alphabet-item {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.alphabet-item.active {
|
||||
background-color: var(--color-primary);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.alphabet-item:not(.active) {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.alphabet-item:hover:not(.active) {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
.app-status {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background-color: #ff9800;
|
||||
color: #fff;
|
||||
padding: 2px 10px;
|
||||
font-size: 12px;
|
||||
border-bottom-left-radius: 8px;
|
||||
}
|
||||
|
||||
.apps-wrapper {
|
||||
/*margin: 0 auto;*/
|
||||
/*margin: 24px;*/
|
||||
/*padding: 24px;*/
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 64px);
|
||||
}
|
||||
|
||||
.no-results {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 300px;
|
||||
padding: 40px 20px;
|
||||
}
|
||||
|
||||
.no-results-content {
|
||||
text-align: center;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.no-results i {
|
||||
color: #c0c4cc;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.no-results .title {
|
||||
font-size: 16px;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.no-results .hint {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.page-item.disabled {
|
||||
color: #c0c4cc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.page-item.disabled:hover {
|
||||
border-color: #d9d9d9;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
text-align: center;
|
||||
padding: 40px 0;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="apps-wrapper" id="app">
|
||||
<div class="apps-hero">
|
||||
<img src="https://i.cug.edu.cn/data/sys-attach/download/1i8hmpaqdwmvwajjvw2c8isi61jj0gkmosw0" alt="应用中心" />
|
||||
</div>
|
||||
|
||||
<div class="apps-container">
|
||||
<!-- Left Sidebar -->
|
||||
<div class="apps-sidebar">
|
||||
<div
|
||||
v-for="category in allCategories"
|
||||
:key="category.id"
|
||||
:class="['apps-sidebar-item', activeCategory === category.id ? 'active' : '']"
|
||||
@click="changeCategory(category.id)"
|
||||
>
|
||||
<i :class="category.icon"></i>
|
||||
{{ category.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="apps-content">
|
||||
<div class="apps-header">
|
||||
<div class="apps-search-container">
|
||||
<div class="apps-search">
|
||||
<input type="text" v-model="searchKeyword" @keyup.enter="search" placeholder="请输入内容" />
|
||||
<i class="el-icon-search search-icon" @click="search"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 字母过滤 -->
|
||||
<div class="apps-filter">
|
||||
<div class="apps-filter-title">首字母:</div>
|
||||
<div class="apps-filter-tags alphabet-filter">
|
||||
<div :class="['filter-tag', activeAlphabet === '' ? 'active' : '']" @click="changeAlphabet('')">全部</div>
|
||||
<div
|
||||
v-for="letter in alphabets"
|
||||
:key="letter"
|
||||
:class="['alphabet-item', activeAlphabet === letter ? 'active' : '']"
|
||||
@click="changeAlphabet(letter)"
|
||||
>
|
||||
{{ letter }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 应用网格 -->
|
||||
<div class="apps-grid" v-if="applications.length > 0">
|
||||
<div v-for="app in applications" :key="app.id" class="app-card" @click.stop="openApp(app)">
|
||||
<div :class="['app-icon', app.iconType]">
|
||||
<i v-if="app.icon" :class="app.icon"></i>
|
||||
<i v-else class="fa fa-skype"></i>
|
||||
</div>
|
||||
<div class="app-info">
|
||||
<div class="app-title">{{ app.displayName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<div class="loading-container" v-if="loading">
|
||||
<i class="el-icon-loading"></i>
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
|
||||
<!-- 无搜索结果 -->
|
||||
<div class="no-results" v-else-if="applications.length === 0">
|
||||
<div class="no-results-content">
|
||||
<i class="el-icon-document" style="font-size: 48px"></i>
|
||||
<p class="title">没有找到匹配的服务</p>
|
||||
<p class="hint">请尝试不同的搜索词或筛选条件</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data: {
|
||||
// 应用列表
|
||||
applications: [],
|
||||
// 分类列表
|
||||
categories: [{ id: "all", name: "全部服务", icon: "fa fa-th-large" }],
|
||||
// 动态加载的分类
|
||||
dynamicCategories: [],
|
||||
// 当前选中的分类
|
||||
activeCategory: "all",
|
||||
// 字母表筛选
|
||||
alphabets: [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"L",
|
||||
"M",
|
||||
"N",
|
||||
"O",
|
||||
"P",
|
||||
"Q",
|
||||
"R",
|
||||
"S",
|
||||
"T",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"X",
|
||||
"Y",
|
||||
"Z"
|
||||
],
|
||||
activeAlphabet: "",
|
||||
// 搜索关键词
|
||||
searchKeyword: "",
|
||||
// 分页相关
|
||||
currentPage: 1,
|
||||
pageSize: 15,
|
||||
totalPage: 1,
|
||||
total: 0,
|
||||
// 加载状态
|
||||
loading: true
|
||||
},
|
||||
computed: {
|
||||
// 所有分类(固定分类 + 动态分类)
|
||||
allCategories() {
|
||||
return [...this.categories, ...this.dynamicCategories]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 页面加载时获取分类和应用数据
|
||||
this.loadCategories()
|
||||
this.loadApps()
|
||||
},
|
||||
methods: {
|
||||
// 加载分类数据
|
||||
loadCategories() {
|
||||
$.get("/platform/v4/serv/categories")
|
||||
.then((result) => {
|
||||
if (result.code === 0) {
|
||||
this.dynamicCategories = result.data || []
|
||||
} else {
|
||||
console.error("获取应用分类失败:", result.msg)
|
||||
}
|
||||
})
|
||||
.fail((error) => {
|
||||
console.error("获取应用分类异常:", error)
|
||||
})
|
||||
},
|
||||
|
||||
// 加载应用数据
|
||||
loadApps() {
|
||||
this.loading = true
|
||||
|
||||
// 构建请求参数
|
||||
const params = {
|
||||
categoryId:
|
||||
this.activeCategory === "all"
|
||||
? ""
|
||||
: this.activeCategory === "favorites" || this.activeCategory === "recommended"
|
||||
? this.activeCategory
|
||||
: this.activeCategory,
|
||||
letter: this.activeAlphabet,
|
||||
keyword: this.searchKeyword
|
||||
}
|
||||
|
||||
// 将参数转换为URL查询参数
|
||||
const queryString = Object.keys(params)
|
||||
.filter((key) => params[key] !== null && params[key] !== undefined && params[key] !== "")
|
||||
.map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(params[key]))
|
||||
.join("&")
|
||||
|
||||
// 如果是"我的收藏"分类
|
||||
if (this.activeCategory === "favorites") {
|
||||
this.loadFavorites()
|
||||
return
|
||||
}
|
||||
|
||||
// 发送请求获取普通应用列表
|
||||
$.get("/platform/v4/serv/list?" + queryString)
|
||||
.then((result) => {
|
||||
if (result.code === 0) {
|
||||
this.applications = result.data || []
|
||||
} else {
|
||||
console.error("获取应用列表失败:", result.msg)
|
||||
}
|
||||
this.loading = false
|
||||
})
|
||||
.fail((error) => {
|
||||
console.error("获取应用列表异常:", error)
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
|
||||
// 加载收藏的应用
|
||||
loadFavorites() {
|
||||
$.get("/platform/v4/serv/favorite")
|
||||
.then((result) => {
|
||||
if (result.code === 0) {
|
||||
this.applications = result.data || []
|
||||
} else {
|
||||
console.error("获取收藏应用失败:", result.msg)
|
||||
}
|
||||
})
|
||||
.fail((error) => {
|
||||
console.error("获取收藏应用异常:", error)
|
||||
})
|
||||
},
|
||||
|
||||
// 切换应用收藏状态
|
||||
toggleFavorite(appId) {
|
||||
const app = this.applications.find((a) => a.id === appId)
|
||||
if (!app) return
|
||||
|
||||
const url = app.isFavorite ? "/platform/v4/serv/removeFavorite" : "/platform/v4/serv/addFavorite"
|
||||
const params = { appId: appId }
|
||||
|
||||
$.post(url, params)
|
||||
.then((result) => {
|
||||
if (result.code === 0) {
|
||||
app.isFavorite = !app.isFavorite
|
||||
this.$message.success(app.isFavorite ? "收藏成功" : "取消收藏成功")
|
||||
} else {
|
||||
console.error(app.isFavorite ? "取消收藏失败:" : "收藏失败:", result.msg)
|
||||
}
|
||||
})
|
||||
.fail((error) => {
|
||||
console.error(app.isFavorite ? "取消收藏异常:" : "收藏异常:", error)
|
||||
})
|
||||
},
|
||||
|
||||
// 切换应用分类
|
||||
changeCategory(categoryId) {
|
||||
this.activeCategory = categoryId
|
||||
this.currentPage = 1
|
||||
|
||||
// 如果是"我的收藏"分类
|
||||
if (categoryId === "favorites") {
|
||||
this.loadFavorites()
|
||||
} else {
|
||||
this.loadApps()
|
||||
}
|
||||
},
|
||||
|
||||
// 切换应用字母
|
||||
changeAlphabet(letter) {
|
||||
this.activeAlphabet = letter
|
||||
this.currentPage = 1
|
||||
this.loadApps()
|
||||
},
|
||||
|
||||
// 搜索
|
||||
search() {
|
||||
this.loadApps()
|
||||
},
|
||||
|
||||
// 打开应用
|
||||
openApp(app) {
|
||||
console.log(app)
|
||||
// 新标签页打开
|
||||
window.open("/flow/common/approval/form?defineKey=" + app.name, "_blank")
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
@@ -84,7 +84,8 @@ layout("/layouts/platform.html"){
|
||||
<el-input v-model="formData.h5InstanceViewUrl" placeholder="请输入手机端发起地址"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="图标" prop="icon">
|
||||
<el-input v-model="formData.icon" placeholder="请输入图标"></el-input>
|
||||
<el-input maxlength="100" placeholder="图标" v-model="formData.icon"></el-input>
|
||||
<i :class="formData.icon" v-if="formData.icon"></i>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -201,11 +202,11 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
|
||||
listCategory() {
|
||||
// this.$axios.get("/platform/warmFlow/category/list").then((res) => {
|
||||
// if (res.code === 0) {
|
||||
// this.categoryOptions = res.data
|
||||
// }
|
||||
// })
|
||||
this.$axios.post("/flow/category/list").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.categoryOptions = res.data
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -2,172 +2,6 @@
|
||||
layout("/layouts/v4/baseLayout.html"){
|
||||
#-->
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<div class="task-todo-center">
|
||||
<!-- 统计数据区域 -->
|
||||
<el-row :gutter="20" class="statistics-section">
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon todo-icon">
|
||||
<i class="el-icon-s-claim"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{todoCount}}</div>
|
||||
<div class="stat-label">待办任务</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon done-icon">
|
||||
<i class="el-icon-finished"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{doneCount}}</div>
|
||||
<div class="stat-label">已办任务</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon started-icon">
|
||||
<i class="el-icon-s-promotion"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{startedCount}}</div>
|
||||
<div class="stat-label">我发起的</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 搜索筛选区域 -->
|
||||
<el-card shadow="never" class="filter-section">
|
||||
<el-form :inline="true" :model="searchForm" class="search-form">
|
||||
<el-form-item>
|
||||
<el-input v-model="searchForm.keyword" placeholder="请输入关键词搜索" prefix-icon="el-icon-search" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchForm.category" placeholder="所有流程类型" clearable>
|
||||
<el-option v-for="type in processTypes" :key="type.value" :label="type.label" :value="type.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="search">搜索</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 任务列表区域 -->
|
||||
<el-card shadow="never" class="task-section">
|
||||
<div slot="header" class="task-header">
|
||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="待办任务" name="todo"></el-tab-pane>
|
||||
<el-tab-pane label="已办任务" name="done"></el-tab-pane>
|
||||
<el-tab-pane label="我发起的" name="started"></el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
<!-- 表格展示 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="tasks"
|
||||
style="width: 100%"
|
||||
:key="activeTab"
|
||||
:header-cell-style="{backgroundColor: '#f5f7fa'}"
|
||||
:row-class-name="tableRowClassName"
|
||||
>
|
||||
<el-table-column prop="processInstanceName" label="流程名称" min-width="180" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<span class="task-title">{{scope.row.processInstanceName || scope.row.title}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="taskName" label="任务节点" min-width="150" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="processDefinitionName" label="流程类型" min-width="150" show-overflow-tooltip>
|
||||
<template slot-scope="scope">{{scope.row.processDefinitionName || scope.row.processType}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="initiatorName" label="申请人" min-width="120">
|
||||
<template slot-scope="{row}">
|
||||
{{row.variable.initiatorName}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="时间" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<div v-if="activeTab === 'todo'">
|
||||
<i class="el-icon-time"></i>
|
||||
{{scope.row.createdAt}}
|
||||
</div>
|
||||
<div v-else-if="activeTab === 'done'">
|
||||
<i class="el-icon-check"></i>
|
||||
{{scope.row.finishTime}}
|
||||
</div>
|
||||
<div v-else-if="activeTab === 'started'">
|
||||
<i class="el-icon-s-promotion"></i>
|
||||
{{scope.row.createdAt}}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="activeTab === 'started'" label="状态" width="100">
|
||||
<template slot-scope="{row}">
|
||||
{{processStatusMap[row.state]?.text}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="250" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="activeTab === 'todo'" type="primary" size="mini" @click="handleTask(scope.row)">处理</el-button>
|
||||
<el-button type="info" size="mini" @click="viewTaskDetail(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 空状态展示 -->
|
||||
<el-empty v-if="tasks.length === 0" :description="getEmptyText()"></el-empty>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container" v-if="tasks.length > 0">
|
||||
<el-pagination
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="pageSize"
|
||||
layout="prev, pager, next, jumper"
|
||||
:total="total"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 任务详情对话框 -->
|
||||
<el-dialog title="任务详情" :visible.sync="dialogVisible" width="600px" :close-on-click-modal="false">
|
||||
<div v-if="currentTask" class="task-detail">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="流程名称">{{currentTask.processInstanceName || currentTask.title}}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务名称">{{currentTask.taskName || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="流程类型">{{currentTask.processDefinitionName || currentTask.processType}}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请人">{{currentTask.applyUserName || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请部门">{{currentTask.applyUserUnitId || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{currentTask.createTime}}</el-descriptions-item>
|
||||
<el-descriptions-item v-if="currentTask.description" label="任务描述">
|
||||
<div class="description-content">{{currentTask.description}}</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="currentTask.taskMobileFormUrl" label="表单链接">
|
||||
<el-link type="primary" :href="currentTask.taskMobileFormUrl" target="_blank">点击查看详细表单</el-link>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">关闭</el-button>
|
||||
<el-button v-if="activeTab === 'todo'" type="primary" @click="handleTask(currentTask)">处理任务</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.task-todo-center {
|
||||
padding: 20px;
|
||||
@@ -369,20 +203,138 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
height: 28px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* 任务详情样式 */
|
||||
.task-detail .el-descriptions {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.description-content {
|
||||
background-color: #f5f7fa;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<div class="task-todo-center">
|
||||
<!-- 统计数据区域 -->
|
||||
<el-row :gutter="20" class="statistics-section">
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon todo-icon">
|
||||
<i class="el-icon-s-claim"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{todoCount}}</div>
|
||||
<div class="stat-label">待办任务</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon done-icon">
|
||||
<i class="el-icon-finished"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{doneCount}}</div>
|
||||
<div class="stat-label">已办任务</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="stat-card">
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon started-icon">
|
||||
<i class="el-icon-s-promotion"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<div class="stat-value">{{startedCount}}</div>
|
||||
<div class="stat-label">我发起的</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 搜索筛选区域 -->
|
||||
<el-card shadow="never" class="filter-section">
|
||||
<el-form :inline="true" :model="searchForm" class="search-form">
|
||||
<el-form-item>
|
||||
<el-input v-model="searchForm.keyword" placeholder="请输入关键词搜索" prefix-icon="el-icon-search" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchForm.category" placeholder="所有流程分类" clearable>
|
||||
<el-option v-for="type in categoryOptions" :key="type.id" :label="type.name" :value="type.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="search">搜索</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 任务列表区域 -->
|
||||
<el-card shadow="never" class="task-section">
|
||||
<div slot="header" class="task-header">
|
||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="待办任务" name="todo"></el-tab-pane>
|
||||
<el-tab-pane label="已办任务" name="done"></el-tab-pane>
|
||||
<el-tab-pane label="我发起的" name="started"></el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
<!-- 表格展示 -->
|
||||
<el-table v-loading="loading" :data="tasks" style="width: 100%" :key="activeTab" :header-cell-style="{backgroundColor: '#f5f7fa'}">
|
||||
<el-table-column prop="processInstanceName" label="流程名称" min-width="180" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<span class="task-title">{{scope.row.variable?.instanceName}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="taskName" label="任务节点" min-width="150" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="categoryName" label="流程分类" min-width="150" show-overflow-tooltip>
|
||||
<template slot-scope="{row}">{{categoryOptions.find(item => item.id === row.category)?.name}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="initiatorName" label="申请人" min-width="120">
|
||||
<template slot-scope="{row}">{{row.variable.initiatorName}}</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="时间" min-width="180">-->
|
||||
<!-- <template slot-scope="scope">-->
|
||||
<!-- <div v-if="activeTab === 'todo'">-->
|
||||
<!-- <i class="el-icon-time"></i>-->
|
||||
<!-- {{scope.row.createdAt}}-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-else-if="activeTab === 'done'">-->
|
||||
<!-- <i class="el-icon-check"></i>-->
|
||||
<!-- {{scope.row.finishTime}}-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-else-if="activeTab === 'started'">-->
|
||||
<!-- <i class="el-icon-s-promotion"></i>-->
|
||||
<!-- {{scope.row.createdAt}}-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column v-if="activeTab === 'started'" label="状态" width="100">
|
||||
<template slot-scope="{row}">{{processStatusMap[row.state]?.text}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100px" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="primary" size="mini" @click="openView(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 空状态展示 -->
|
||||
<el-empty v-if="tasks.length === 0" :description="getEmptyText()"></el-empty>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container" v-if="tasks.length > 0">
|
||||
<el-pagination
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="pageSize"
|
||||
layout="prev, pager, next, jumper"
|
||||
:total="total"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
new Vue({
|
||||
el: "#app",
|
||||
@@ -400,7 +352,7 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
},
|
||||
|
||||
// 流程类型选项
|
||||
processTypes: [],
|
||||
categoryOptions: [],
|
||||
|
||||
// 任务列表
|
||||
tasks: [],
|
||||
@@ -436,9 +388,7 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
INTERRUPT: 40,
|
||||
PENDING: 50,
|
||||
ABANDON: 99
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -450,12 +400,18 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
|
||||
created() {
|
||||
this.initData()
|
||||
// 监听
|
||||
window.GlobalBroadcastChannel.addEventListener("message", (event) => {
|
||||
if (event.data.type === "task-complete") {
|
||||
this.initData()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 初始化数据
|
||||
async initData() {
|
||||
await Promise.all([this.getStatistics(), this.getProcessTypes(), this.getTasks()])
|
||||
await Promise.all([this.getStatistics(), this.listCategory(), this.getTasks()])
|
||||
},
|
||||
|
||||
// 获取统计数据
|
||||
@@ -475,16 +431,12 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
},
|
||||
|
||||
// 获取流程类型
|
||||
async getProcessTypes() {
|
||||
try {
|
||||
const res = await $.post("/platform/warmFlow/todoCenter/category")
|
||||
async listCategory() {
|
||||
this.$axios.post("/flow/category/list").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.processTypes = res.data
|
||||
this.categoryOptions = res.data
|
||||
}
|
||||
} catch (error) {
|
||||
this.$message.error("获取流程类型失败")
|
||||
console.error("获取流程类型失败:", error)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取任务列表
|
||||
@@ -549,31 +501,12 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
},
|
||||
|
||||
// 处理任务
|
||||
async handleTask(task) {
|
||||
if (!task) return
|
||||
|
||||
// 如果有表单链接,直接跳转
|
||||
if (task.taskMobileFormUrl) {
|
||||
window.open(task.taskMobileFormUrl, "_blank")
|
||||
return
|
||||
}
|
||||
},
|
||||
|
||||
// 获取状态对应的类型
|
||||
getStatusType(task) {
|
||||
if (!task.status) return "info"
|
||||
|
||||
switch (task.status) {
|
||||
case "审批中":
|
||||
return "primary"
|
||||
case "已完成":
|
||||
return "success"
|
||||
case "已通过":
|
||||
return "success"
|
||||
case "已拒绝":
|
||||
return "danger"
|
||||
default:
|
||||
return "info"
|
||||
async openView(task) {
|
||||
const { taskId, taskState, instanceId, businessNo } = task
|
||||
if (taskState === this.taskStateEnum.DOING) {
|
||||
window.open("/flow/common/approval/form?instanceId=" + instanceId + "&taskId=" + taskId + "&businessId=" + businessNo)
|
||||
} else {
|
||||
window.open("/flow/common/approval/form?instanceId=" + instanceId + "&businessId=" + businessNo)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -589,11 +522,6 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
default:
|
||||
return "暂无数据"
|
||||
}
|
||||
},
|
||||
|
||||
// 表格行类名
|
||||
tableRowClassName({ row, rowIndex }) {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
+54
-16
@@ -17,7 +17,7 @@
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-form>
|
||||
<snaker-flow-task-form-action @task-action="handleTaskAction" @save-draft="handleSaveDraft" @cancel="handleCancel"></snaker-flow-task-form-action>
|
||||
<snaker-flow-task-form-action @task-action="handleTaskAction" @save-draft="handleSaveDraft"></snaker-flow-task-form-action>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -27,6 +27,7 @@
|
||||
data() {
|
||||
return {
|
||||
businessId: GetQueryString("businessId"),
|
||||
instanceId: GetQueryString("instanceId"),
|
||||
formData: {},
|
||||
formRules: {
|
||||
title: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
|
||||
@@ -39,20 +40,54 @@
|
||||
console.log(val)
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (valid) {
|
||||
this.$axios
|
||||
.post("/flow/common/startInstanceAndExecute", {
|
||||
...val,
|
||||
bizData: JSON.stringify(this.formData)
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success("操作成功")
|
||||
window.parent.postMessage({ type: "task-complete" }, "*")
|
||||
}
|
||||
})
|
||||
if (!this.instanceId) {
|
||||
this.handleApply(val)
|
||||
} else {
|
||||
this.handleReApply(val)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 提交申请
|
||||
handleApply(val) {
|
||||
this.$axios
|
||||
.post("/flow/common/startInstanceAndExecute", {
|
||||
...val,
|
||||
bizData: JSON.stringify(this.formData)
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
window.GlobalBroadcastChannel.postMessage({
|
||||
type: "task-complete"
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 重新提交申请
|
||||
handleReApply(val) {
|
||||
this.$axios
|
||||
.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
processTaskId: val.taskId,
|
||||
processInstanceId: val.instanceId,
|
||||
submitType: val.submitType,
|
||||
f_data: JSON.stringify(this.formData)
|
||||
})
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
window.GlobalBroadcastChannel.postMessage({
|
||||
type: "task-complete"
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 保存申请
|
||||
handleSaveDraft(val) {
|
||||
this.$refs.formRef.validateField(["title"], (errMsg) => {
|
||||
if (errMsg) {
|
||||
@@ -78,12 +113,15 @@
|
||||
})
|
||||
})
|
||||
},
|
||||
handleCancel() {
|
||||
// 关闭浏览器窗口
|
||||
window.close()
|
||||
},
|
||||
|
||||
// 初始化
|
||||
init() {
|
||||
if (this.businessId) {
|
||||
this.$axios.post("/platform/suggestionBox/view/info", { id: this.businessId }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.formData = res.data
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const { username, loginname, id, unit, union, mobile } = this.$store.state.user
|
||||
this.formData = {
|
||||
|
||||
+53
-9
@@ -33,12 +33,12 @@ layout("/layouts/platform.html"){
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="300px">
|
||||
<template slot-scope="{row}">
|
||||
<el-button @click="onOpen(row.id)" size="mini" type="primary">查看</el-button>
|
||||
<el-button v-if="row.taskKey === 'apply' || !row.instanceId" @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
|
||||
<el-button v-if="['waiting'].includes(row.flow_status)" size="mini" type="danger" @click="onRevoke(row.id)">撤销</el-button>
|
||||
<el-button v-if="row.taskKey === 'apply' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">
|
||||
删除
|
||||
</el-button>
|
||||
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
|
||||
<el-button v-if="row.taskKey === 'startTask'" @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
|
||||
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
|
||||
<!-- <el-button v-if="row.instanceState === 10" size="mini" type="danger" @click="onWithDraw(row)">撤销</el-button>-->
|
||||
<!-- v-if="row.instanceState === 30"-->
|
||||
<el-button @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -58,7 +58,9 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen(id) {},
|
||||
openView(row) {
|
||||
window.open("/flow/common/approval/form?" + "instanceId=" + (row.instanceId || "") + "&businessId=" + row.id + "&defineKey=XWTG")
|
||||
},
|
||||
onEdit(row) {
|
||||
window.open(
|
||||
"/flow/common/approval/form?taskId=" +
|
||||
@@ -70,8 +72,50 @@ layout("/layouts/platform.html"){
|
||||
"&defineKey=XWTG"
|
||||
)
|
||||
},
|
||||
onRevoke(id) {},
|
||||
onDelete(id) {}
|
||||
|
||||
onRevoke(row) {
|
||||
this.$confirm("您确定要撤回吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/revokeTask", { taskId: row.startTaskId }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
onWithDraw({ instanceId }) {
|
||||
this.$confirm("您确定要撤销申请吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post("/flow/common/withdrawInstance", { instanceId }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
onDelete(id) {
|
||||
this.$confirm("您确定要删除吗?", "提示", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.$axios.post("/platform/suggestionBox2/apply/delete", { id }).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.pageData()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageData()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<el-descriptions-item label="工号">{{viewData.loginName}}</el-descriptions-item>
|
||||
<el-descriptions-item label="单位">{{viewData.unitName}}</el-descriptions-item>
|
||||
<el-descriptions-item label="工会">{{viewData.unionName}}</el-descriptions-item>
|
||||
<el-descriptions-item label="标题" :span="2">{{viewData.viewData}}</el-descriptions-item>
|
||||
<el-descriptions-item label="标题" :span="2">{{viewData.title}}</el-descriptions-item>
|
||||
<el-descriptions-item label="填写意见建议内容" :span="2">{{viewData.content}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
methods: {
|
||||
handleTaskAction(val) {
|
||||
console.log(val)
|
||||
|
||||
this.$axios
|
||||
.post("/flow/common/executeTask", {
|
||||
data: JSON.stringify({
|
||||
@@ -32,12 +33,10 @@
|
||||
if (res.code === 0) {
|
||||
this.$message.success("操作成功")
|
||||
// 发送完成消息
|
||||
window.parent.postMessage(
|
||||
{
|
||||
type: "task-complete"
|
||||
},
|
||||
"*"
|
||||
)
|
||||
window.GlobalBroadcastChannel.postMessage({
|
||||
type: "task-complete",
|
||||
payload: val
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@@ -30,16 +30,17 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column prop="unitName" label="投稿人单位"></el-table-column>
|
||||
<el-table-column prop="unionName" label="投稿人工会"></el-table-column>
|
||||
<el-table-column prop="submitTime" label="投稿时间"></el-table-column>
|
||||
<el-table-column prop="taskName" label="当前节点"></el-table-column>
|
||||
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
|
||||
<el-table-column prop="instanceState" label="流程状态">
|
||||
<template slot-scope="{row}">
|
||||
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="300px">
|
||||
<el-table-column label="操作" fixed="right" width="200px">
|
||||
<template slot-scope="{row}">
|
||||
<el-button @click="onOpen(row.id)" size="mini" type="primary">查看</el-button>
|
||||
<el-button v-if="row.taskState === 10" @click="openApproval(row)" size="mini" type="primary">审核</el-button>
|
||||
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
|
||||
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
|
||||
<!-- <el-button v-if="row.taskState === 10" @click="openView(row)" size="mini" type="primary">审核</el-button>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -62,9 +63,11 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onOpen() {},
|
||||
openApproval(row) {
|
||||
openView(row) {
|
||||
window.open("/flow/common/approval/form?taskId=" + row.taskId + "&instanceId=" + row.instanceId + "&businessId=" + row.businessNo)
|
||||
},
|
||||
onRevoke(row) {
|
||||
console.log(row)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
Reference in New Issue
Block a user