Merge remote-tracking branch 'origin/main'

This commit is contained in:
@jyuhsin
2025-08-29 09:57:56 +08:00
62 changed files with 15910 additions and 14042 deletions
@@ -65,6 +65,10 @@ public interface FlowConst {
String NR_OF_INSTANCES = "nrOfInstances";
// 会签已完成实例数
String NR_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
// 会签已完成并且已通过实例数
String NR_OF_COMPLETED_AGREE_INSTANCES = "nrOfCompletedAgreeInstances";
// 会签操作人列表
String COUNTERSIGN_OPERATOR_LIST = "operatorList";
// 会签类型 PARALLEL表示并行会签,SEQUENTIAL表示串行会签
@@ -106,4 +110,5 @@ public interface FlowConst {
String PROCESS_INSTANCE_NAME = "instanceName";
}
@@ -15,52 +15,63 @@ import java.util.stream.Collectors;
/**
* 会签任务处理,用于判断会签任务是否可通过
*
* @author mldong
* @date 2023/11/24
*/
public class CountersignHandler implements IHandler {
private TaskModel taskModel;
public CountersignHandler(TaskModel taskModel) {
this.taskModel = taskModel;
}
@Override
public void handle(Execution execution) {
boolean isMerged = false;
String countersignType = taskModel.getExt().get("countersignType","PARALLEL");
String countersignCompletionCondition = taskModel.getExt().get("countersignCompletionCondition","");
String countersignType = taskModel.getExt().get("countersignType", "PARALLEL");
String countersignCompletionCondition = taskModel.getExt().get("countersignCompletionCondition", "");
countersignCompletionCondition = taskModel.getCountersignCompletionCondition();
String prefix = FlowConst.COUNTERSIGN_VARIABLE_PREFIX +taskModel.getName()+"_";
String prefix = FlowConst.COUNTERSIGN_VARIABLE_PREFIX + taskModel.getName() + "_";
// 会签办理人列表
List<String> operatorList = Convert.toList(String.class,execution.getArgs().get(prefix+FlowConst.COUNTERSIGN_OPERATOR_LIST));
List<String> operatorList = Convert.toList(String.class, execution.getArgs().get(prefix + FlowConst.COUNTERSIGN_OPERATOR_LIST));
// 循环计数器,办理人在列表中的索引
int loopCounter = operatorList.indexOf(execution.getOperator());
// 追加计数器
execution.getArgs().put(prefix+FlowConst.LOOP_COUNTER,loopCounter);
execution.getArgs().put(prefix + FlowConst.LOOP_COUNTER, loopCounter);
// 追加已完成数量
execution.getArgs().put(prefix + FlowConst.NR_OF_COMPLETED_INSTANCES,
execution.getArgs().get(prefix + FlowConst.NR_OF_COMPLETED_INSTANCES,0)+1);
execution.getArgs().get(prefix + FlowConst.NR_OF_COMPLETED_INSTANCES, 0) + 1);
// 追加已完成并且同意数量
if (!execution.getArgs().containsKey(FlowConst.COUNTERSIGN_DISAGREE_FLAG)) {
execution.getArgs().put(prefix + FlowConst.NR_OF_COMPLETED_AGREE_INSTANCES,
execution.getArgs().get(prefix + FlowConst.NR_OF_COMPLETED_AGREE_INSTANCES, 0) + 1);
}
/**
*
* ● 全部通过:为空
* ● 按数量通过:#nrOfCompletedInstances==n,这里表示n人完成任务,会签结束。
* ● 按比例通过:#nrOfCompletedInstances/nrOfInstances==n,这里表示已完成会签数与总实例数达到一定比例时,会签结束
* ● 一票通过:#nrOfCompletedInstances==1,这里表示1人完成任务,会签结束。
* ● 一票否决:ONE_VOTE_VETO
*/
if("ONE_VOTE_VETO".equalsIgnoreCase(countersignCompletionCondition)) {
if ("ONE_VOTE_VETO".equalsIgnoreCase(countersignCompletionCondition)) {
// 一票否决
if(execution.getArgs().containsKey(FlowConst.COUNTERSIGN_DISAGREE_FLAG)) {
if (execution.getArgs().containsKey(FlowConst.COUNTERSIGN_DISAGREE_FLAG)) {
// 存在拒绝标识,则直接通过
isMerged = true;
}
} else if(!StrUtil.isBlank(countersignCompletionCondition)) {
} else if (!StrUtil.isBlank(countersignCompletionCondition)) {
// 根据条件判断是否通过
Dict dict = Dict.create();
execution.getArgs().forEach((k,v)->{
dict.set(k.replace(prefix,""),v);
execution.getArgs().forEach((k, v) -> {
dict.set(k.replace(prefix, ""), v);
});
isMerged = Convert.toBool(ExpressionUtil.eval(countersignCompletionCondition, dict));
}
if(!isMerged && CountersignTypeEnum.SEQUENTIAL.toString().equalsIgnoreCase(countersignType)) {
if (!isMerged && CountersignTypeEnum.SEQUENTIAL.toString().equalsIgnoreCase(countersignType)) {
// 串行未通过,则判断是否为最后一个
if (loopCounter == operatorList.size() - 1) {
isMerged = true;
@@ -69,27 +80,28 @@ public class CountersignHandler implements IHandler {
execution.getEngine().processTaskService().createCountersignTask(taskModel, execution);
}
}
if(!isMerged && CountersignTypeEnum.PARALLEL.toString().equalsIgnoreCase(countersignType)) {
if (!isMerged && CountersignTypeEnum.PARALLEL.toString().equalsIgnoreCase(countersignType)) {
// 是否所有会签任务已完成
isMerged = execution.getEngine().processTaskService().getDoingTaskList(execution.getProcessInstanceId(), new String[]{taskModel.getName()}).size()==0;
if(!isMerged) {
isMerged = execution.getEngine().processTaskService().getDoingTaskList(execution.getProcessInstanceId(), new String[]{taskModel.getName()}).size() == 0;
if (!isMerged) {
// 未通过,更新已完成实例数量
Dict addVariable = Dict.create();
addVariable.put(prefix + FlowConst.NR_OF_COMPLETED_INSTANCES, execution.getArgs().get(prefix+FlowConst.NR_OF_COMPLETED_INSTANCES));
addVariable.put(prefix + FlowConst.NR_OF_COMPLETED_INSTANCES, execution.getArgs().get(prefix + FlowConst.NR_OF_COMPLETED_INSTANCES));
addVariable.put(prefix + FlowConst.NR_OF_COMPLETED_AGREE_INSTANCES, execution.getArgs().get(prefix + FlowConst.NR_OF_COMPLETED_AGREE_INSTANCES));
execution.getEngine().processInstanceService().addVariable(execution.getProcessInstanceId(), addVariable);
}
}
if(isMerged) {
if (isMerged) {
// 获取所有会签参数键值
List<String> keys = execution.getArgs().keySet().stream().filter(k->k.startsWith(prefix)).collect(Collectors.toList());
List<String> keys = execution.getArgs().keySet().stream().filter(k -> k.startsWith(prefix)).collect(Collectors.toList());
keys.add(FlowConst.COUNTERSIGN_DISAGREE_FLAG);
// 如果可以合并,则把流程实例中的会签参数清空
execution.getEngine().processInstanceService().removeVariable(
execution.getProcessInstanceId(),
keys.toArray(new String[]{}));
// 如果为并行会签,需将其他会签任务设置为废弃
if(CountersignTypeEnum.PARALLEL.toString().equalsIgnoreCase(countersignType)) {
execution.getEngine().processTaskService().getDoingTaskList(execution.getProcessInstanceId(), new String[]{taskModel.getName()}).stream().forEach(t->{
if (CountersignTypeEnum.PARALLEL.toString().equalsIgnoreCase(countersignType)) {
execution.getEngine().processTaskService().getDoingTaskList(execution.getProcessInstanceId(), new String[]{taskModel.getName()}).stream().forEach(t -> {
execution.getEngine().processTaskService().abandonProcessTask(t.getId(), FlowConst.AUTO_ID, execution.getArgs());
});
}
@@ -42,6 +42,10 @@ public class ProcessTaskActor extends BaseModel {
@Column
private String actorName;
@Comment("参与者单位ID")
@Column
private String actorUnitId;
@Comment("参与者单位")
@Column
private String actorUnitName;
@@ -36,18 +36,14 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
*/
boolean update(ProcessTask param);
/**
* 自定义分页查询流程任务
* @param param
* @return
*/
// CommonPage<ProcessTaskVO> page(ProcessTaskPageParam param);
/**
* 通过id查询
* @param id
* @return
*/
ProcessTaskVO findById(Long id);
/**
* 保存流程任务
* @param processTask
@@ -67,6 +63,7 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
* @return
*/
List<ProcessTask> getDoingTaskList(Long processInstanceId, String[] taskNames);
/**
* 根据流程实例ID获取已完成的任务
* @param processInstanceId 流程实例ID
@@ -74,6 +71,7 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
* @return
*/
List<ProcessTask> getDoneTaskList(Long processInstanceId, String[] taskNames);
/**
* 将流程任务修改为已完成
* @param processTaskId
@@ -104,12 +102,14 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
* @return
*/
ProcessTask getById(Long id);
/**
* 向指定的任务id添加参与者
* @param processTaskId 任务id
* @param actors 参与者
*/
void addTaskActor(Long processTaskId, List<String> actors);
/**
* 向指定的任务id添加参与者
* @param processTaskId 流程任务id
@@ -137,18 +137,7 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
* @return
*/
List<String> getTaskActors(Long processTaskId);
/**
* 查询待办列表
* @param param
* @return
*/
// CommonPage<ProcessTaskVO> todoList(ProcessTaskPageParam param);
/**
* 查询已办列表
* @param param
* @return
*/
// CommonPage<ProcessTaskVO> doneList(ProcessTaskPageParam param);
/**
* 根据当前任务对象驳回至上一步处理
* @param model 流程定义模型,用以获取上一步模型对象
@@ -164,12 +153,6 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
*/
List<LabelValueVO> jumpAbleTaskNameList(Long processInstanceId);
/**
* 分页查询获取候选人
* @param query
* @return
*/
// CommonPage<Map<String,Object>> candidatePage(Dict query);
/**
* 创建会签任务
* @param taskModel
@@ -177,6 +160,7 @@ public interface ProcessTaskService extends BaseService<ProcessTask> {
* @return
*/
List<ProcessTask> createCountersignTask(TaskModel taskModel, Execution execution);
/**
* 根据执行对象、自定义节点模型创建历史任务记录
* @param execution 执行对象
@@ -211,7 +211,7 @@ public class ProcessTaskServiceImpl extends BaseServiceImpl<ProcessTask> impleme
if (CollectionUtil.isEmpty(actors)) return;
List<String> dbActors = getTaskActors(processTaskId);
List<String> newActors = actors.stream().filter(actor -> !dbActors.contains(actor)).toList();
Sql sql = Sqls.create("select id,username,loginname,unitname from vw_user where id in (@ids)");
Sql sql = Sqls.create("select id,username,loginname,unitName from vw_user where id in (@ids)");
sql.setParam("ids", newActors);
List<NutMap> list = listMap(sql);
@@ -221,7 +221,7 @@ public class ProcessTaskServiceImpl extends BaseServiceImpl<ProcessTask> impleme
processTaskActor.setActorId(actor.getString("id"));
processTaskActor.setActorName(actor.getString("username"));
processTaskActor.setActorAccount(actor.getString("loginname"));
processTaskActor.setActorUnitName(actor.getString("unitname"));
processTaskActor.setActorUnitName(actor.getString("unitName"));
processTaskActor.setCreatedAt(System.currentTimeMillis());
System.out.println(StrUtil.format("给任务:{},添加参与者:{}", processTaskId, actor.toString()));
insert(processTaskActor);
@@ -0,0 +1,70 @@
package com.budwk.app.zhgh.dayofficework.edu.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters;
import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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 org.nutz.mvc.annotation.Param;
import java.util.List;
@IocBean
@At("/platform/edu/chapters")
@Ok("json:full")
@Api(tags = "理论学习课程章节")
public class EduChaptersController {
@Inject
private Dao dao;
@At
@SaCheckPermission("edu.courses")
@ApiOperation("数据列表")
public Result list(@Param("courseId") String courseId) {
List<EduChapters> list = dao.query(EduChapters.class, Cnd.where(EduChapters::getCourseId, "=", courseId).asc(EduChapters::getSortCode));
for (EduChapters chapters : list) {
dao.fetchLinks(chapters, "videos", Cnd.NEW().asc(EduVideos::getSortCode));
}
return Result.success(list);
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("添加")
@SLog(tag = "理论学习课程", msg = "添加课程章节")
public Result insert(EduChapters eduChapters) {
dao.insert(eduChapters);
return Result.success();
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("修改")
@SLog(tag = "理论学习课程", msg = "修改课程章节")
public Result update(EduChapters eduChapters) {
dao.update(eduChapters);
return Result.success();
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("删除")
@SLog(tag = "理论学习课程", msg = "删除课程章节,id:${args[0]}")
public Result delete(@Param("id") String id) {
dao.delete(EduChapters.class, id);
return Result.success();
}
}
@@ -0,0 +1,77 @@
package com.budwk.app.zhgh.dayofficework.edu.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.dayofficework.edu.models.EduCourses;
import com.budwk.app.zhgh.dayofficework.edu.service.EduCoursesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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 org.nutz.mvc.annotation.Param;
@IocBean
@At("/platform/edu/courses")
@Ok("json:full")
@Api(tags = "理论学习课程")
public class EduCoursesController {
@Inject
private Dao dao;
@Inject
private EduCoursesService eduCoursesService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/edu/courses/index.html")
@SaCheckPermission("edu.courses")
public void index() {
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("数据列表")
public Result pageData(PageForm pageForm) {
Cnd cnd = Cnd.NEW();
Pagination pagination = eduCoursesService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
return Result.success(pagination);
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("添加")
@SLog(tag = "理论学习课程", msg = "添加课程")
public Result insert(EduCourses eduCourses) {
dao.insert(eduCourses);
return Result.success();
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("修改")
@SLog(tag = "理论学习课程", msg = "修改课程")
public Result update(EduCourses eduCourses) {
dao.update(eduCourses);
return Result.success();
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("删除")
@SLog(tag = "理论学习课程", msg = "删除课程,id:${args[0]}")
public Result delete(@Param("id") String id) {
dao.delete(EduCourses.class, id);
return Result.success();
}
}
@@ -0,0 +1,67 @@
package com.budwk.app.zhgh.dayofficework.edu.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters;
import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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 org.nutz.mvc.annotation.Param;
import java.util.List;
@IocBean
@At("/platform/edu/video")
@Ok("json:full")
@Api(tags = "理论学习课程视频")
public class EduVideoController {
@Inject
private Dao dao;
@At
@SaCheckPermission("edu.courses")
@ApiOperation("数据列表")
public Result list(@Param("chapterId") String chapterId) {
List<EduVideos> list = dao.query(EduVideos.class, Cnd.where(EduVideos::getChapterId, "=", chapterId).asc(EduVideos::getSortCode));
return Result.success(list);
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("添加")
@SLog(tag = "理论学习课程", msg = "添加课程视频")
public Result insert(EduVideos eduVideos) {
dao.insert(eduVideos);
return Result.success();
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("修改")
@SLog(tag = "理论学习课程", msg = "修改课程视频")
public Result update(EduVideos eduVideos) {
dao.update(eduVideos);
return Result.success();
}
@At
@SaCheckPermission("edu.courses")
@ApiOperation("删除")
@SLog(tag = "理论学习课程", msg = "删除课程视频,id:${args[0]}")
public Result delete(@Param("id") String id) {
dao.delete(EduVideos.class, id);
return Result.success();
}
}
@@ -6,6 +6,8 @@ import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@Table("edu_chapters")
@@ -33,6 +35,11 @@ public class EduChapters extends BaseModel {
@Column
private Integer sortCode;
/**
* 视频
*/
@Many(field = "chapterId")
private List<EduVideos> videos;
}
@@ -0,0 +1,7 @@
package com.budwk.app.zhgh.dayofficework.edu.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.dayofficework.edu.models.EduCourses;
public interface EduCoursesService extends BaseService<EduCourses> {
}
@@ -0,0 +1,14 @@
package com.budwk.app.zhgh.dayofficework.edu.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.dayofficework.edu.models.EduCourses;
import com.budwk.app.zhgh.dayofficework.edu.service.EduCoursesService;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean(args = {"refer:dao"})
public class EduCoursesServiceImpl extends BaseServiceImpl<EduCourses> implements EduCoursesService {
public EduCoursesServiceImpl(Dao dao) {
super(dao);
}
}
@@ -1,81 +0,0 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.bpm.param.BpmTaskApprovalParam;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.zhgh.democratic.grassrootscongress.service.GrassrootsCongressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.aop.Aop;
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 org.nutz.mvc.annotation.Param;
import javax.validation.Valid;
import java.util.Map;
/**
* @version 1.0
* @Author zzr
* @nameGrassrootsCongressApprovalController
* @Date 2024/8/16 17:21
* @注释 基层双代会批复
*/
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/approval")
@Api(tags = "基层双代会批复")
public class GrassrootsCongressApprovalController {
@Inject
private GrassrootsCongressService grassrootsCongressService;
@Inject
private BpmService bpmService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/approval/index.html")
@SaCheckPermission("grassrootsCongress.approval")
public void index() {
}
@At
@ApiOperation("会议列表")
@SaCheckPermission("grassrootsCongress.approval")
public Result pageData(PageForm pageForm, Integer year, String unionId) {
Pagination pagination = grassrootsCongressService.approvalPageData(pageForm, year, unionId);
return Result.success(pagination);
}
@At
@Aop(TransAop.READ_COMMITTED)
@ApiOperation("会议批复")
@SaCheckPermission("grassrootsCongress.approval")
@SLog(type = "基层双代会", tag = "基层双代会批复", msg = "校工会批复信息")
public Result approval(@Param("approval") @Valid BpmTaskApprovalParam approvalParam) {
Map<String, Object> variables = BeanUtil.beanToMap(approvalParam);
bpmService.completeTask(approvalParam.getProcessInstanceTaskId(), approvalParam.getBpmTaskApprovalTypeEnum(), variables, null);
return Result.success();
}
@At
@Aop(TransAop.READ_COMMITTED)
@ApiOperation("会议批复撤回")
@SaCheckPermission("grassrootsCongress.approval")
@SLog(type = "基层双代会", tag = "基层双代会批复撤回", msg = "校工会批复信息撤回")
public Result revoke(@Valid String taskId) {
bpmService.revokeTask(taskId);
return Result.success();
}
}
@@ -1,71 +0,0 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.democratic.grassrootscongress.param.GrassrootsCongressPageForm;
import com.budwk.app.zhgh.democratic.grassrootscongress.service.GrassrootsCongressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.Static;
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;
/**
* @version 1.0
* @Author zzr
* @nameGrassrootsCongressMeetingStatisticsController
* @Date 2024/11/14 19:25
* @注释
*/
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/meetingStatistics")
@Api(tags = "基层双代会汇总统计")
public class GrassrootsCongressMeetingStatisticsController {
@Inject
private GrassrootsCongressService grassrootsCongressService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/meetingstatistics/index.html")
@SaCheckPermission("grassrootsCongress.meetingStatistics")
public void index() {
}
@At
@ApiOperation("汇总统计列表")
@SaCheckPermission("grassrootsCongress.myMeeting")
public Result pageData(GrassrootsCongressPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
su.*,
sum(CASE WHEN info.unionId = su.id THEN 1 ELSE 0 END) as unionNum
FROM
sys_union su
LEFT JOIN grassroots_congress_meeting_info info ON su.id = info.unionId $yearSql $nameSql
$condition
""");
Cnd cnd = Cnd.NEW();
if (pageForm.getYear() != null) {
sql.setVar("yearSql", new Static(" and YEAR(info.createTime) = %s".formatted( pageForm.getYear())));
}
if (StrUtil.isNotBlank(pageForm.getFullName())) {
sql.setVar("nameSql", new Static(" and info.fullName = '%s'".formatted(pageForm.getFullName())));
}
// cnd.andEX("YEAR(info.createTime)", "=", pageForm.getYear());
// cnd.andEX("info.fullName", "=", pageForm.getFullName());
cnd.andEX("su.id", "=", pageForm.getUnionId());
cnd.groupBy("su.id");
sql.setCondition(cnd);
return Result.success(grassrootsCongressService.listMap(sql));
}
}
@@ -1,100 +0,0 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.zhgh.democratic.grassrootscongress.models.GrassrootsCongressMeetingInfo;
import com.budwk.app.zhgh.democratic.grassrootscongress.param.GrassrootsCongressPageForm;
import com.budwk.app.zhgh.democratic.grassrootscongress.service.GrassrootsCongressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
import java.util.List;
/**
* @ClassName GrassrootsCongressMyMeetingController
* @Description 我的申请
* @Author zhf
* @Date 2024/9/5 9:57
*/
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/myMeeting")
@Api(tags = "基层双代会我的请示")
public class GrassrootsCongressMyMeetingController {
@Inject
private BaseService baseService;
@Inject
private BpmService bpmService;
@Inject
private GrassrootsCongressService grassrootsCongressService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/myMeetings/index.html")
@SaCheckPermission("grassrootsCongress.myMeeting")
public void index() {
}
@At
@ApiOperation("我的请示列表")
@SaCheckPermission("grassrootsCongress.myMeeting")
public Result pageData(@Valid GrassrootsCongressPageForm pageForm, Integer year) {
Pagination pagination = grassrootsCongressService.pageData(pageForm, year);
return Result.success(pagination);
}
@At
@ApiOperation("删除会议请示")
@SaCheckPermission("grassrootsCongress.myMeeting")
@Aop(TransAop.READ_COMMITTED)
@SLog(type = "grassrootsCongress", tag = "基层双代会", msg = "删除会议请示")
public Result doDelete(@Valid String id) {
baseService.dao().delete(GrassrootsCongressMeetingInfo.class, id);
grassrootsCongressService.delete(id);
bpmService.deleteInstance(id);
return Result.success();
}
@At
@Aop(TransAop.READ_COMMITTED)
@ApiOperation("会议请示撤回")
@SaCheckPermission("grassrootsCongress.myMeeting")
@SLog(type = "基层双代会", tag = "基层双代会请示撤回", msg = "会议请示信息撤回")
public Result revoke(@Valid String id) {
bpmService.revokeApply(id);
return Result.success();
}
@At
@ApiOperation("基层双代会届次")
@SaCheckPermission("grassrootsCongress.myMeeting")
public Result getAllJc(Integer year){
List<GrassrootsCongressMeetingInfo> query = baseService.dao().query(GrassrootsCongressMeetingInfo.class,
Cnd.where("YEAR(createTime)", "=", year).and("fullName", "is not", null).groupBy("fullName"));
if (Lang.isNotEmpty(query)) {
List<String> list = query.stream().map(GrassrootsCongressMeetingInfo::getFullName).toList();
return Result.success(list);
}
return Result.success();
}
}
@@ -0,0 +1,104 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller.meeting;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.grassrootscongress.service.GrassrootsCongressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd;
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 java.util.List;
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/meeting/approval")
@Api(tags = "基层双代会批复")
public class GrassrootsCongressMeetingApprovalController {
@Inject
private GrassrootsCongressService grassrootsCongressService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/meeting/approval/index.html")
@SaCheckPermission("grassrootsCongress.meeting.approval")
public void index() {
}
@At
@ApiOperation("会议列表")
@SaCheckPermission("grassrootsCongress.meeting.approval")
public Result pageData(PageForm pageForm, Integer year, String meetingName, String unionId, boolean approval) {
Sql sql = Sqls.create("""
SELECT
info.*,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
t.taskType,
t.performType taskPerformType,
t.taskState,
t.finishTime,
t.taskParentId,
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 grassroots_congress_meeting_info 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();
cnd.and("t.taskName", "=", "8384aafd-3cdb-49ab-a11f-c5d145b1672c");
if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())){
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
}
if (approval) {
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
} else {
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
}
cnd.andEX("YEAR(info.createTime)", "=", year);
cnd.and(Cnd.likeEX("info.meetingName", meetingName));
cnd.andEX("info.unionId", "=", unionId);
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.desc("info.createdAt");
} else {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
cnd.groupBy("t.id");
sql.setCondition(cnd);
Pagination<NutMap> pageVO = grassrootsCongressService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pageVO);
}
}
@@ -0,0 +1,34 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller.meeting;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.democratic.grassrootscongress.models.GrassrootsCongressMeetingInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
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 org.nutz.mvc.annotation.Param;
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/meeting/common")
@Api(tags = "基层双代会")
public class GrassrootsCongressMeetingCommonController {
@Inject
private Dao dao;
@At
@SaCheckLogin
@ApiOperation("获取申请信息")
public Result info(@Param("id") String id) {
GrassrootsCongressMeetingInfo info = dao.fetch(GrassrootsCongressMeetingInfo.class, id);
return Result.success(info);
}
}
@@ -0,0 +1,126 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller.meeting;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.grassrootscongress.models.GrassrootsCongressMeetingInfo;
import com.budwk.app.zhgh.democratic.grassrootscongress.param.GrassrootsCongressPageForm;
import com.budwk.app.zhgh.democratic.grassrootscongress.service.GrassrootsCongressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
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.Lang;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
import java.util.List;
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/meeting/mine")
@Api(tags = "基层双代会我的请示")
public class GrassrootsCongressMeetingMineController {
@Inject
private BaseService baseService;
@Inject
private FlowEngine flowEngine;
@Inject
private GrassrootsCongressService grassrootsCongressService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/meeting/mine/index.html")
@SaCheckPermission("grassrootsCongress.meeting.mine")
public void index() {
}
@At
@ApiOperation("我的请示列表")
@SaCheckPermission("grassrootsCongress.meeting.mine")
public Result pageData(@Valid GrassrootsCongressPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
info.*,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.id taskId,
t.taskName AS taskKey,
t.displayName taskName,
t.taskType,
t.performType taskPerformType,
t.taskState,
t.finishTime,
t.taskParentId,
t.variable taskVariable,
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' AND taskState in (10,20)) AS startTaskId
FROM
grassroots_congress_meeting_info info
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("info.createdBy", "=", SecurityUtil.getUserId());
cnd.andEX("YEAR(info.createTime)", "=", pageForm.getYear());
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
cnd.and(Cnd.likeEX("info.meetingName", pageForm.getSearchKeyword()));
}
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
cnd.and("info.createUserId", "=", SecurityUtil.getUserId());
}
cnd.desc("info.createTime");
sql.setCondition(cnd);
Pagination<NutMap> pagination = grassrootsCongressService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@ApiOperation("删除会议请示")
@SaCheckPermission("grassrootsCongress.meeting.mine")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "基层双代会-我的请示", msg = "删除会议请示")
public Result delete(@Valid String id) {
grassrootsCongressService.delete(id);
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
return Result.success();
}
@At
@ApiOperation("基层双代会届次")
@SaCheckPermission("grassrootsCongress.meeting.mine")
public Result getAllJc(Integer year) {
List<GrassrootsCongressMeetingInfo> query = baseService.dao().query(GrassrootsCongressMeetingInfo.class,
Cnd.where("YEAR(createTime)", "=", year).and("fullName", "is not", null).groupBy("fullName"));
if (Lang.isNotEmpty(query)) {
List<String> list = query.stream().map(GrassrootsCongressMeetingInfo::getFullName).toList();
return Result.success(list);
}
return Result.success();
}
}
@@ -0,0 +1,75 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller.meeting;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.grassrootscongress.param.GrassrootsCongressPageForm;
import com.budwk.app.zhgh.democratic.grassrootscongress.service.GrassrootsCongressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.Static;
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;
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/meeting/statistics")
@Api(tags = "基层双代会汇总统计")
public class GrassrootsCongressMeetingStatisticsController {
@Inject
private GrassrootsCongressService grassrootsCongressService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/meeting/statistics/index.html")
@SaCheckPermission("grassrootsCongress.meeting.statistics")
public void index() {
}
@At
@ApiOperation("汇总统计列表")
@SaCheckPermission("grassrootsCongress.meeting.statistics")
public Result pageData(GrassrootsCongressPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
info.*,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId
FROM
grassroots_congress_meeting_info info
LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("ins.state","=", ProcessInstanceStateEnum.FINISHED.getCode());
cnd.andEX("YEAR(info.createTime)", "=", pageForm.getYear());
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
cnd.and(Cnd.likeEX("info.meetingName", pageForm.getSearchKeyword()));
}
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
cnd.and("info.createUserId", "=", SecurityUtil.getUserId());
}
cnd.desc("info.createTime");
sql.setCondition(cnd);
Pagination<NutMap> pagination = grassrootsCongressService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
}
@@ -1,27 +1,27 @@
package com.budwk.app.zhgh.democratic.grassrootscongress.controller;
package com.budwk.app.zhgh.democratic.grassrootscongress.controller.meeting;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.lang.Dict;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.BpmProcessConstant;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
import com.budwk.app.flow.service.FlowCommonService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.controllers.open.commons.service.CommonService;
import com.budwk.app.zhgh.democratic.grassrootscongress.models.GrassrootsCongressMeetingInfo;
import com.budwk.app.zhgh.democratic.grassrootscongress.vo.GrassrootsCongressVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
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.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -32,78 +32,86 @@ import org.nutz.mvc.annotation.Param;
import javax.validation.Valid;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @nameGrassrootsCongressApplyController
* @Date 2024/8/16 16:44
* @注释 基层双代会请示
*/
@Slf4j
@IocBean
@Ok("json:full")
@At("/platform/grassrootsCongress/meeting")
@Api(tags = "基层双代会请示")
public class GrassrootsCongressMeetingController {
@At("/platform/grassrootsCongress/meeting/write")
@Api(tags = "基层双代会-会议请示")
public class GrassrootsCongressMeetingWriteController {
@Inject
private Dao dao;
@Inject
private BpmService bpmService;
private FlowEngine flowEngine;
@Inject
private BaseService baseService;
@Inject
private CommonService commonService;
private FlowCommonService flowCommonService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/meetings/index.html")
@SaCheckPermission("grassrootsCongress.meeting")
@Ok("beetl:/platform/zhgh/democratic/grassrootscongress/meeting/write/index.html")
@SaCheckPermission("grassrootsCongress.meeting.write")
public void index() {
}
@At
@ApiOperation("提交")
@ApiOperation("保存")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "基层双代会", msg = "会议请示添加会议")
@SaCheckPermission("grassrootsCongress.meeting")
public Result doSubmit(@Param("data") GrassrootsCongressMeetingInfo data) {
@SLog(tag = "基层双代会-会议请示", msg = "保存会议")
@SaCheckPermission("grassrootsCongress.meeting.write")
public Result save(@Param("data") GrassrootsCongressMeetingInfo data) {
data.setCreateTime(DateUtil.now());
data.setCreateUserId(SecurityUtil.getUserId());
data.setCreateUserName(SecurityUtil.getUserUsername());
dao.insertOrUpdate(data);
List<String> loginNameList = commonService.findUsersLoginNameByRoleCode(RoleConstant.SCHOOL_UNION_WC_AUDIT_ADMIN);
if (ObjectUtil.isEmpty(loginNameList)) {
return Result.error("校工会基层双代会批复人未设置");
}
bpmService.startSubmitProcessInstance(BpmProcessConstant.GRASSROOTS_CONGRESS.name(), data.getMeetingName(), data.getId(), loginNameList, null);
return Result.success();
}
@At
@ApiOperation("保存")
@ApiOperation("提交")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "基层双代会", msg = "会议请示添加会议")
@SaCheckPermission("grassrootsCongress.meeting")
public Result doSave(@Param("data") GrassrootsCongressMeetingInfo data) {
@SLog(tag = "基层双代会-会议请示", msg = "提交会议")
@SaCheckPermission("grassrootsCongress.meeting.write")
public Result submit(@Param("data") GrassrootsCongressMeetingInfo data) {
data.setCreateTime(DateUtil.now());
data.setCreateUserId(SecurityUtil.getUserId());
data.setCreateUserName(SecurityUtil.getUserUsername());
dao.insertOrUpdate(data);
bpmService.startSaveProcessInstance(BpmProcessConstant.GRASSROOTS_CONGRESS.name(), data.getMeetingName(), data.getId(), null);
// 开启流程实例
Dict args = Dict.create();
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
ProcessInstance instance = flowEngine.startProcessInstanceByKey("JCSDH", data.getId(), SecurityUtil.getUserId(), args);
// 自动完成第一个申请任务
List<ProcessTask> doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null);
for (ProcessTask task : doingTaskList) {
flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
}
return Result.success();
}
@At
@SaCheckLogin
@ApiOperation("重新提交申请")
@SLog(tag = "基层双代会-会议请示", msg = "重新提交申请")
@SaCheckPermission("grassrootsCongress.meeting.write")
public Result submitAgain(@Param("data") GrassrootsCongressMeetingInfo data, @Param("taskId") Long taskId) {
dao.insertOrUpdate(data);
Dict dict = Dict.create();
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
flowCommonService.executeTask(dict);
return Result.success();
}
@At
@SaCheckPermission("grassrootsCongress")
@ApiOperation("查询单个会议信息")
public Result findOne(@Valid String id) {
Sql sql = Sqls.create("""
select * from grassroots_congress_meeting_info where id=@id
""").setParam("id", id);
GrassrootsCongressVo grassrootsCongressVo = (GrassrootsCongressVo) baseService.fetchVO(sql, GrassrootsCongressVo.class);
grassrootsCongressVo.setNodeTasks(bpmService.getNodeTasks(BpmProcessConstant.GRASSROOTS_CONGRESS, id));
return Result.success(grassrootsCongressVo);
public Result info(@Valid String id) {
GrassrootsCongressMeetingInfo info = dao.fetch(GrassrootsCongressMeetingInfo.class, id);
return Result.success(info);
}
@@ -61,41 +61,17 @@ public class ProposalQueryCollectProgressController {
info.createUserName,
type.NAME AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
inst.processInstanceNodeName,
count( secondedTask.id ) seconderSum,
sum( CASE WHEN secondedTask.taskStatus = 'ACTIVE' THEN 1 ELSE 0 END ) activeCount,
sum( CASE WHEN secondedTask.taskStatus = 'COMPLETE' THEN 1 ELSE 0 END ) completeCount
tcd.`name` AS delegationName
FROM
proposal_info info
LEFT JOIN proposal_type type ON type.id = info.typeId
LEFT JOIN teacher_congress_session tcs ON tcs.id = info.sessionId
LEFT JOIN teacher_congress_delegation tcd ON tcd.id = info.delegationId
LEFT JOIN teacher_congress_delegate tcde on tcde.loginName = info.createUserLoginName
LEFT JOIN bpm_process_instance inst ON inst.processInstanceBusinessId = info.id
LEFT JOIN bpm_process_task secondedTask ON secondedTask.processInstanceId = inst.id
AND secondedTask.taskStatus IN ( 'ACTIVE', 'COMPLETE' )
AND secondedTask.processTaskNodeCode = 20
$condition
""");
sql.setParam("sessionId", pageForm.getSessionId());
Cnd cnd = Cnd.NEW();
// Sql subSql = Sqls.create("""
// SELECT
// inst.id
// FROM
// bpm_process_instance inst
// INNER JOIN proposal_info info ON info.id = inst.processInstanceBusinessId
// $condition
// """);
// Cnd subCnd = Cnd.NEW();
// subCnd.and("info.sessionId", "=", pageForm.getSessionId());
// subCnd.and("inst.processInstanceNodeCode", "in", pageForm.getCollectIds());
// if (ArrayUtil.contains(pageForm.getCollectIds(), 50)) {
// subCnd.and("inst.processInstanceNodeCode", ">", pageForm.getCollectIds());
// }
// subSql.setCondition(subCnd);
// cnd.and("inst.id", "in", subSql);
SqlExpressionGroup seg = new SqlExpressionGroup();
if (ArrayUtil.contains(pageForm.getCollectIds(), 10)) {
@@ -53,13 +53,14 @@ public class ProposalQueryComprehensiveController {
type.name AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
inst.processInstanceNodeId,
inst.processInstanceNodeCode,
inst.processInstanceNodeName,
inst.processInstanceTaskIds,
inst.processInstanceStatus,
JSON_UNQUOTE(JSON_EXTRACT(caseUnitTasks.extVariable, '$.hostUnit')) AS masterUnderTakeName,
JSON_EXTRACT(caseUnitTasks.extVariable, '$.helpUnits') AS slaveUnderTakeNames
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.displayName curTaskName,
JSON_UNQUOTE(JSON_EXTRACT(caseTasks.variable, '$.tf_hostUnitName')) AS masterUnitName,
JSON_EXTRACT(caseTasks.variable, '$.tf_helpUnitNames') AS slaveUnitNames
FROM
proposal_info info
LEFT JOIN proposal_consolidation p ON JSON_CONTAINS(p.consolidationIds, JSON_QUOTE(info.id))
@@ -67,32 +68,20 @@ public class ProposalQueryComprehensiveController {
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
LEFT JOIN teacher_congress_delegation tcd on tcd.id = info.delegationId
LEFT JOIN teacher_congress_delegate tcde on tcde.loginName = info.createUserLoginName
LEFT JOIN bpm_process_instance inst ON inst.processInstanceBusinessId = info.id
LEFT JOIN (
SELECT
processInstanceId,
MAX(endOn) AS maxEndOn
FROM
bpm_process_task
WHERE
processTaskNodeCode = 70 AND taskStatus = 'COMPLETE'
GROUP BY
processInstanceId
) latestTasks ON latestTasks.processInstanceId = inst.id
LEFT JOIN bpm_process_task caseUnitTasks ON caseUnitTasks.processInstanceId = inst.id AND caseUnitTasks.processTaskNodeCode = 70 AND caseUnitTasks.taskStatus = 'COMPLETE' AND caseUnitTasks.endOn = latestTasks.maxEndOn
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
LEFT JOIN (SELECT processInstanceId, MAX(finishTime) AS finishTime FROM wf_process_task WHERE taskName = '9846ab38-40c5-4093-bafc-a9b3b443338b' AND taskState = 20 GROUP BY processInstanceId) latestTasks ON latestTasks.processInstanceId = ins.id
LEFT JOIN wf_process_task caseTasks ON caseTasks.processInstanceId = ins.id AND caseTasks.taskName = '9846ab38-40c5-4093-bafc-a9b3b443338b' AND caseTasks.taskState = 20 AND caseTasks.finishTime = latestTasks.finishTime
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
$condition
""");
Cnd cnd = Cnd.NEW();
if(StrUtil.isNotBlank(pageForm.getUndertakeUnitId())){
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.or("JSON_EXTRACT(caseUnitTasks.extVariable, '$.hostUnitId')","=",pageForm.getUndertakeUnitId());
seg.orLike("JSON_UNQUOTE(JSON_EXTRACT(caseUnitTasks.extVariable, '$.helpUnitIds'))",pageForm.getUndertakeUnitId());
cnd.and(seg);
}
ProposalQueryComprehensiveParam.buildSearch(cnd, pageForm);
cnd.groupBy("info.id");
sql.setCondition(cnd);
Pagination pagination = baseService.listPageVO(pageForm,sql, ProposalInfoPageVO.class);
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@@ -84,18 +84,20 @@ public class ProposalQueryDelegationController {
type.name AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
inst.processInstanceNodeId,
inst.processInstanceNodeCode,
inst.processInstanceNodeName,
inst.processInstanceTaskIds,
inst.processInstanceStatus
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.displayName curTaskName
FROM
proposal_info info
LEFT JOIN proposal_consolidation p ON JSON_CONTAINS(p.consolidationIds, JSON_QUOTE(info.id))
LEFT JOIN proposal_type type on type.id = info.typeId
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
LEFT JOIN teacher_congress_delegation tcd on tcd.id = info.delegationId
LEFT JOIN bpm_process_instance inst ON inst.processInstanceBusinessId = info.id
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
$condition
""");
Cnd cnd = Cnd.NEW();
@@ -46,11 +46,14 @@ public class ProposalQueryHistoryController {
type.name AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
inst.processInstanceNodeId,
inst.processInstanceNodeCode,
inst.processInstanceNodeName,
inst.processInstanceTaskIds,
inst.processInstanceStatus
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.displayName curTaskName,
JSON_UNQUOTE(JSON_EXTRACT(caseTasks.variable, '$.tf_hostUnitName')) AS masterUnitName,
JSON_EXTRACT(caseTasks.variable, '$.tf_helpUnitNames') AS slaveUnitNames
FROM
proposal_info info
LEFT JOIN proposal_consolidation p ON JSON_CONTAINS(p.consolidationIds, JSON_QUOTE(info.id))
@@ -58,7 +61,10 @@ public class ProposalQueryHistoryController {
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
LEFT JOIN teacher_congress_delegation tcd on tcd.id = info.delegationId
LEFT JOIN teacher_congress_delegate tcde on tcde.loginName = info.createUserLoginName
LEFT JOIN bpm_process_instance inst ON inst.processInstanceBusinessId = info.id
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
LEFT JOIN (SELECT processInstanceId, MAX(finishTime) AS finishTime FROM wf_process_task WHERE taskName = '9846ab38-40c5-4093-bafc-a9b3b443338b' AND taskState = 20 GROUP BY processInstanceId) latestTasks ON latestTasks.processInstanceId = ins.id
LEFT JOIN wf_process_task caseTasks ON caseTasks.processInstanceId = ins.id AND caseTasks.taskName = '9846ab38-40c5-4093-bafc-a9b3b443338b' AND caseTasks.taskState = 20 AND caseTasks.finishTime = latestTasks.finishTime
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
$condition
""");
Cnd cnd = Cnd.NEW();
@@ -7,7 +7,11 @@ import cn.hutool.json.JSONObject;
import com.budwk.app.base.result.Result;
import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum;
import com.budwk.app.bpm.models.BpmProcessTask;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
import lombok.extern.slf4j.Slf4j;
@@ -17,6 +21,7 @@ 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.json.Json;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@@ -47,53 +52,45 @@ public class ProposalQueryUnitReplyController {
@At
@SaCheckPermission("proposal.query.unitReply")
public Result data(String sessionId, String undertakeUnitId) {
Sql sql = Sqls.create("""
SELECT
info.id,
inst.id AS instId
FROM
proposal_info info
INNER JOIN bpm_process_instance inst ON inst.processInstanceBusinessId = info.id
WHERE info.sessionId = @sessionId
""");
sql.setParam("sessionId", sessionId);
List<NutMap> list = proposalCommonService.listMap(sql);
List<String> instIds = list.stream().map(v -> v.getString("instId")).toList();
List<ProposalInfo> infos = dao.query(ProposalInfo.class, Cnd.where(ProposalInfo::getSessionId, "=", sessionId));
List<String> infoIds = infos.stream().map(v -> v.getId()).toList();
List<ProcessInstance> instances = dao.query(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "in", infoIds));
List<Long> instIds = instances.stream().map(v -> v.getId()).toList();
//查询提案委员会分配的承办单位
List<BpmProcessTask> caseUnitTasks = dao.query(BpmProcessTask.class, Cnd.where(BpmProcessTask::getProcessInstanceId, "in", instIds)
.and(BpmProcessTask::getTaskStatus, "=", BpmProcessTaskStatusEnum.COMPLETE.name())
.and(BpmProcessTask::getProcessTaskNodeCode, "=", 70)
.and(BpmProcessTask::getDelFlag, "=", 0)
);
List<JSONObject> caseUnitTaskExtVariables = caseUnitTasks.stream().map(BpmProcessTask::getExtVariable).toList();
// 立案任务记录
List<ProcessTask> caseTasks = dao.query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "in", instIds)
.and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.FINISHED.getCode())
.and(ProcessTask::getTaskName, "=", "9846ab38-40c5-4093-bafc-a9b3b443338b"));
//所有承办单位
Set<String> underTakeIds = new HashSet<>();
// 主办任务记录
List<ProcessTask> masterUnitTasks = dao.query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "in", instIds)
.and(ProcessTask::getTaskState, "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.DOING.getCode()))
.and(ProcessTask::getTaskName, "=", "85cf23da-2dd5-4007-a1e9-bd9bfddc68f0"));
// 协办任务记录
List<ProcessTask> slaveUnitTasks = dao.query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "in", instIds)
.and(ProcessTask::getTaskState, "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.DOING.getCode()))
.and(ProcessTask::getTaskName, "=", "c9a1586e-272b-41b8-b438-0be9f9e3781d"));
//该届次所有涉及到的承办单位
List<String> underTakeIds = caseTasks.stream().map(v -> {
NutMap variable = Json.fromJson(NutMap.class, v.getVariable());
String hostUnitId = variable.getString("tf_hostUnitId");
List<String> helpUnitIds = variable.getAsList("tf_helpUnitIds", String.class);
List<String> list = new ArrayList<>();
list.add(hostUnitId);
list.addAll(helpUnitIds);
return list;
})
.flatMap(List::stream)
.distinct()
.toList();
if (StrUtil.isNotBlank(undertakeUnitId)) {
underTakeIds.add(undertakeUnitId);
} else {
for (JSONObject caseUnitTaskExtVariable : caseUnitTaskExtVariables) {
String hostUnitId = caseUnitTaskExtVariable.getStr("hostUnitId");
List<String> helpUnitIds = caseUnitTaskExtVariable.getBeanList("helpUnitIds", String.class);
underTakeIds.addAll(helpUnitIds);
underTakeIds.add(hostUnitId);
}
}
List<ProposalUndertake> undertakes = dao.query(ProposalUndertake.class, Cnd.where(ProposalUndertake::getId, "in", underTakeIds));
Map<String, ProposalUndertake> undertakeMap = undertakes.stream().collect(Collectors.toMap(ProposalUndertake::getId, v -> v));
//查询承办单位任务
List<BpmProcessTask> underTakeTasks = dao.query(BpmProcessTask.class, Cnd.where(BpmProcessTask::getProcessInstanceId, "in", instIds)
.and(BpmProcessTask::getProcessTaskNodeCode, "=", 80)
.and(BpmProcessTask::getDelFlag, "=", 0)
);
ProposalConfig proposalConfig = dao.fetch(ProposalConfig.class, Cnd.NEW());
Boolean slaveNeedReply = ObjectUtil.defaultIfNull(proposalConfig.getSlaveUnitLeaderNeedApprove(), false);
List<NutMap> tableData = new ArrayList<>();
for (String underTakeId : underTakeIds) {
@@ -102,11 +99,31 @@ public class ProposalQueryUnitReplyController {
tableRow.put("name", undertakeMap.get(underTakeId).getName());
//找出承办提案总数
long sum = caseUnitTasks.stream().filter(v -> v.getExtVariable().getStr("hostUnitId").equals(underTakeId) || v.getExtVariable().getBeanList("helpUnitIds", String.class).contains(underTakeId)).map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
// long sum = caseTasks.stream().filter(v -> (Json.fromJson(NutMap.class, v.getVariable())).getString("tf_hostUnitId").equals(underTakeId) || (Json.fromJson(NutMap.class, v.getVariable())).getAsList("helpUnitIds", String.class).contains(underTakeId)).map(ProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
long sum = caseTasks.stream()
.filter(v -> {
NutMap variable = Json.fromJson(NutMap.class, v.getVariable());
if (variable == null) {
return false;
}
String hostUnitId = variable.getString("tf_hostUnitId");
List<String> helpUnitIds = variable.getAsList("tf_helpUnitIds", String.class);
boolean isHost = underTakeId != null && underTakeId.equals(hostUnitId);
boolean isHelper = helpUnitIds != null && helpUnitIds.contains(underTakeId);
return isHost || isHelper;
})
.map(ProcessTask::getProcessInstanceId)
.distinct()
.count();
//找出主办提案数量
long hostSum = underTakeTasks.stream().filter(v -> v.getCreateVariable().getStr("underTakeId").equals(underTakeId) && v.getCreateVariable().getBool("isMaster", false)).map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
long hostSum = masterUnitTasks.stream().map(v -> Json.fromJson(NutMap.class, v.getVariable())).filter(variable -> underTakeId.equals(variable.getString("unitId")) && variable.getBoolean("isMaster")).count();
//主办已答复的数量
long hostReplySum = underTakeTasks.stream().filter(v -> v.getCreateVariable().getStr("underTakeId").equals(underTakeId) && v.getCreateVariable().getBool("isMaster", false) && v.getTaskStatus().equals(BpmProcessTaskStatusEnum.COMPLETE.name())).map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
long hostReplySum = masterUnitTasks.stream().filter(v -> Objects.equals(v.getTaskState(), ProcessTaskStateEnum.FINISHED.getCode())).map(v -> Json.fromJson(NutMap.class, v.getVariable())).filter(variable -> underTakeId.equals(variable.getString("unitId")) && variable.getBoolean("isMaster")).count();
//主办未答复的数量
long hostNoReplySum = hostSum - hostReplySum;
@@ -115,25 +132,25 @@ public class ProposalQueryUnitReplyController {
tableRow.put("hostReplySum", hostReplySum);
tableRow.put("hostNoReplySum", hostNoReplySum);
if (slaveNeedReply) {
//协办提案数量
long helpSum = underTakeTasks.stream().filter(v -> v.getCreateVariable().getStr("underTakeId").equals(underTakeId) && !v.getCreateVariable().getBool("isMaster", false)).map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
//协办已答复的数量
long helpReplySum = underTakeTasks.stream().filter(v -> v.getCreateVariable().getStr("underTakeId").equals(underTakeId) && !v.getCreateVariable().getBool("isMaster", false) && v.getTaskStatus().equals(BpmProcessTaskStatusEnum.COMPLETE.name())).map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
//协办未答复的数量
long helpNoReplySum = helpSum - helpReplySum;
tableRow.put("helpSum", helpSum);
tableRow.put("helpReplySum", helpReplySum);
tableRow.put("helpNoReplySum", helpNoReplySum);
} else {
//不需要协办答复 计算出提案总数即可
int helpSum = caseUnitTasks.stream()
.filter(v -> v.getExtVariable().getBeanList("helpUnitIds", String.class).contains(underTakeId))
.map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
tableRow.put("helpSum", helpSum);
}
// if (slaveNeedReply) {
// //协办提案数量
// long helpSum = underTakeTasks.stream().filter(v -> v.getCreateVariable().getStr("underTakeId").equals(underTakeId) && !v.getCreateVariable().getBool("isMaster", false)).map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
// //协办已答复的数量
// long helpReplySum = underTakeTasks.stream().filter(v -> v.getCreateVariable().getStr("underTakeId").equals(underTakeId) && !v.getCreateVariable().getBool("isMaster", false) && v.getTaskStatus().equals(BpmProcessTaskStatusEnum.COMPLETE.name())).map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
// //协办未答复的数量
// long helpNoReplySum = helpSum - helpReplySum;
// tableRow.put("helpSum", helpSum);
// tableRow.put("helpReplySum", helpReplySum);
// tableRow.put("helpNoReplySum", helpNoReplySum);
// } else {
// //不需要协办答复 计算出提案总数即可
// int helpSum = caseUnitTasks.stream()
// .filter(v -> v.getExtVariable().getBeanList("helpUnitIds", String.class).contains(underTakeId))
// .map(BpmProcessTask::getProcessInstanceId).collect(Collectors.toSet()).size();
// tableRow.put("helpSum", helpSum);
// }
tableData.add(tableRow);
}
return Result.success().addData(Map.of("tableData", tableData, "slaveNeedReply", slaveNeedReply));
return Result.success().addData(Map.of("tableData", tableData, "slaveNeedReply", false));
}
}
@@ -6,11 +6,13 @@ import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.zhgh.democratic.proposal.controller.vo.ProposalInfoPageVO;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalSeconded;
import com.budwk.app.zhgh.democratic.proposal.param.ProposalQueryComprehensiveParam;
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
@@ -35,9 +37,9 @@ public class ProposalSeniorDeleteController {
@Inject
private Dao dao;
@Inject
private BaseService baseService;
private ProposalCommonService proposalCommonService;
@Inject
private BpmService bpmService;
private FlowEngine flowEngine;
@At("")
@Ok("beetl:/platform/zhgh/democratic/proposal/senior/delete/index.html")
@@ -55,26 +57,20 @@ public class ProposalSeniorDeleteController {
COUNT(p.consolidationIds) > 0 AS isConsolidation,
type.name AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
inst.processInstanceNodeId,
inst.processInstanceNodeCode,
inst.processInstanceNodeName,
inst.processInstanceTaskIds,
inst.processInstanceStatus
tcd.`name` AS delegationName
FROM
proposal_info info
LEFT JOIN proposal_consolidation p ON JSON_CONTAINS(p.consolidationIds, JSON_QUOTE(info.id))
LEFT JOIN proposal_type type on type.id = info.typeId
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
LEFT JOIN teacher_congress_delegation tcd on tcd.id = info.delegationId
LEFT JOIN bpm_process_instance inst ON inst.processInstanceBusinessId = info.id
$condition
""");
Cnd cnd = Cnd.NEW();
ProposalQueryComprehensiveParam.buildSearch(cnd, pageForm);
cnd.groupBy("info.id");
sql.setCondition(cnd);
Pagination pagination = baseService.listPageVO(pageForm, sql, ProposalInfoPageVO.class);
Pagination pagination = proposalCommonService.listPageVO(pageForm, sql, ProposalInfoPageVO.class);
return Result.success(pagination);
}
@@ -85,10 +81,12 @@ public class ProposalSeniorDeleteController {
@SLog(tag = "提案管理系统-高级管理-万能删除提案", msg = "删除提案")
@Aop(TransAop.READ_COMMITTED)
public Result delete(String id) {
dao.clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", id));
dao.clear(ProposalSeconded.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", id));
dao.clear(ProposalInfo.class, Cnd.where(ProposalInfo::getId, "=", id));
bpmService.deleteInstance(id);
// dao.clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", id));
// dao.clear(ProposalSeconded.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", id));
// dao.clear(ProposalInfo.class, Cnd.where(ProposalInfo::getId, "=", id));
// bpmService.deleteInstance(id);
dao.clear(ProposalInfo.class, Cnd.where("id", "=", id));
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
return Result.success();
}
@@ -51,19 +51,13 @@ public class ProposalSeniorTypeController {
COUNT(p.consolidationIds) > 0 AS isConsolidation,
type.name AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
inst.processInstanceNodeId,
inst.processInstanceNodeCode,
inst.processInstanceNodeName,
inst.processInstanceTaskIds,
inst.processInstanceStatus
tcd.`name` AS delegationName
FROM
proposal_info info
LEFT JOIN proposal_consolidation p ON JSON_CONTAINS(p.consolidationIds, JSON_QUOTE(info.id))
LEFT JOIN proposal_type type on type.id = info.typeId
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
LEFT JOIN teacher_congress_delegation tcd on tcd.id = info.delegationId
LEFT JOIN bpm_process_instance inst ON inst.processInstanceBusinessId = info.id
$condition
""");
Cnd cnd = Cnd.NEW();
@@ -8,17 +8,18 @@ import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.entity.ProcessTaskActor;
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.service.FlowCommonService;
import com.budwk.app.flow.service.ProcessTaskService;
import com.budwk.app.sys.services.SysMsgService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.proposal.controller.vo.ProposalInviteSeconderVO;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
@@ -34,6 +35,7 @@ import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@@ -51,12 +53,8 @@ public class ProposalMineController {
@Inject
private Dao dao;
@Inject
private BaseService baseService;
@Inject
private ProposalCommonService proposalCommonService;
@Inject
private SysMsgService sysMsgService;
@Inject
private FlowEngine flowEngine;
@Inject
private ProcessTaskService processTaskService;
@@ -138,38 +136,111 @@ public class ProposalMineController {
@ApiOperation("查询可邀请的附议人")
public Result listSeconder(@Valid PageForm pageForm, @Valid String proposalId, @Valid String sessionId,
String delegationId, boolean isInvite) {
// 查询已经邀请的附议人
ProcessInstance processInstance = dao.fetch(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "=", proposalId));
// 查询最新一次的邀请附议人任务
ProcessTask inviteTask = dao.fetch(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstance.getId())
.and(ProcessTask::getTaskName, "=", "85b7b9bd-d706-48cb-99a1-ef1370fb1819")
.and(ProcessTask::getTaskState, "in", List.of(ProcessTaskStateEnum.DOING.getCode(), ProcessTaskStateEnum.FINISHED.getCode()))
.desc(ProcessTask::getCreatedAt));
List<ProcessTask> taskList = dao.query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstance.getId())
.and(ProcessTask::getTaskName, "=", "74458b33-ad6e-46c4-b8d9-1aa897142b25")
.and(ProcessTask::getTaskState, "in", List.of(ProcessTaskStateEnum.DOING.getCode(), ProcessTaskStateEnum.FINISHED.getCode()))
.and(ProcessTask::getId, ">", inviteTask.getId())
);
List<ProcessTaskActor> taskActors = dao.query(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "in", taskList.stream().map(ProcessTask::getId).toList()));
Sql sql = Sqls.create("""
SELECT
t1.loginName,
t1.userName,
t1.sex,
t1.unitName,
t1.unionName,
t2.NAME AS delegationName
FROM
teacher_congress_delegate t1
LEFT JOIN teacher_congress_delegation t2 ON t2.id = t1.delegationId
$condition
""");
Cnd cnd = Cnd.where("t1.sessionId", "=", sessionId);
cnd.andEX("t1.delegationId", "=", delegationId);
cnd.and("t1.roleId", "=", "72e24b5b4c4f4e90a6641e6af8487e42");
cnd.and("t1.loginName", "!=", SecurityUtil.getUserLoginname());
if (isInvite) {
// 查询已经邀请的附议人
cnd.and("t1.loginName", "in", taskActors.stream().map(ProcessTaskActor::getActorAccount).toList());
} else {
// 查询可邀请的附议人
Sql sql = Sqls.create("""
SELECT
t1.loginName,
t1.userName,
t1.sex,
t1.unitName,
t1.unionName,
t2.NAME AS delegationName
FROM
teacher_congress_delegate t1
LEFT JOIN teacher_congress_delegation t2 ON t2.id = t1.delegationId
$condition
""");
Cnd cnd = Cnd.where("t1.sessionId", "=", sessionId);
cnd.andEX("t1.delegationId", "=", delegationId);
cnd.and("t1.roleId", "=", "72e24b5b4c4f4e90a6641e6af8487e42");
cnd.and("t1.loginName", "!=", SecurityUtil.getUserLoginname());
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.orLike("t1.loginName", pageForm.getSearchKeyword());
seg.orLike("t1.userName", pageForm.getSearchKeyword());
cnd.and(seg);
}
sql.setCondition(cnd);
Pagination<ProposalInviteSeconderVO> pagination = proposalCommonService.listPageVO(pageForm, sql, ProposalInviteSeconderVO.class);
return Result.success(pagination);
cnd.andEX("t1.loginName", "not in", taskActors.stream().map(ProcessTaskActor::getActorAccount).toList());
}
return Result.success();
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.orLike("t1.loginName", pageForm.getSearchKeyword());
seg.orLike("t1.userName", pageForm.getSearchKeyword());
cnd.and(seg);
}
sql.setCondition(cnd);
Pagination<ProposalInviteSeconderVO> pagination = proposalCommonService.listPageVO(pageForm, sql, ProposalInviteSeconderVO.class);
return Result.success(pagination);
// if (isInvite) {
// // 先执行条件过滤再手动分页
// List<ProposalInviteSeconderVO> pageList = voList;
// if (StrUtil.isNotBlank(delegationId)) {
// pageList = voList.stream().filter(vo -> vo.getDelegationId().equals(delegationId)).toList();
// }
// if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
// pageList = voList.stream().filter(vo -> (vo.getLoginName().contains(pageForm.getSearchKeyword()) || vo.getUserName().contains(pageForm.getSearchKeyword()))).toList();
// }
//
// pageList = pageList.stream()
// .skip((long) (pageForm.getPageNumber() - 1) * pageForm.getPageSize()).limit(pageForm.getPageSize()).toList();
//
// Pagination<ProposalInviteSeconderVO> pagination = new Pagination<>();
// pagination.setList(pageList);
// pagination.setPageNo(pageForm.getPageNumber());
// pagination.setPageSize(pageForm.getPageSize());
// pagination.setTotalCount(voList.size());
// return Result.success(pagination);
// } else {
// // 查询可邀请的附议人
// Sql sql = Sqls.create("""
// SELECT
// t1.loginName,
// t1.userName,
// t1.sex,
// t1.unitName,
// t1.unionName,
// t2.NAME AS delegationName
// FROM
// teacher_congress_delegate t1
// LEFT JOIN teacher_congress_delegation t2 ON t2.id = t1.delegationId
// $condition
// """);
// Cnd cnd = Cnd.where("t1.sessionId", "=", sessionId);
// cnd.andEX("t1.delegationId", "=", delegationId);
// cnd.and("t1.roleId", "=", "72e24b5b4c4f4e90a6641e6af8487e42");
// cnd.and("t1.loginName", "!=", SecurityUtil.getUserLoginname());
// // 过滤到已邀请的附议人
// cnd.and("t1.loginName", "not in", voList.stream().map(ProposalInviteSeconderVO::getLoginName).toList());
//
// if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
// SqlExpressionGroup seg = new SqlExpressionGroup();
// seg.orLike("t1.loginName", pageForm.getSearchKeyword());
// seg.orLike("t1.userName", pageForm.getSearchKeyword());
// cnd.and(seg);
// }
// sql.setCondition(cnd);
// Pagination<ProposalInviteSeconderVO> pagination = proposalCommonService.listPageVO(pageForm, sql, ProposalInviteSeconderVO.class);
// return Result.success(pagination);
// }
}
@At
@@ -177,10 +248,32 @@ public class ProposalMineController {
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "提案", msg = "邀请附议人")
public Result inviteSeconder(@Param("seconders") String[] seconders, @Valid String proposalId) {
//插入附议人数据
// 查询已经邀请的附议人
ProcessInstance processInstance = dao.fetch(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "=", proposalId));
// 查询最新一次的邀请附议人任务
ProcessTask inviteTask = dao.fetch(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstance.getId())
.and(ProcessTask::getTaskName, "=", "85b7b9bd-d706-48cb-99a1-ef1370fb1819")
.and(ProcessTask::getTaskState, "in", List.of(ProcessTaskStateEnum.DOING.getCode(), ProcessTaskStateEnum.FINISHED.getCode()))
.desc(ProcessTask::getCreatedAt));
List<ProcessTask> taskList = dao.query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", processInstance.getId())
.and(ProcessTask::getTaskName, "=", "74458b33-ad6e-46c4-b8d9-1aa897142b25")
.and(ProcessTask::getTaskState, "in", List.of(ProcessTaskStateEnum.DOING.getCode(), ProcessTaskStateEnum.FINISHED.getCode()))
.and(ProcessTask::getId, ">", inviteTask.getId())
);
ProposalConfig proposalConfig = dao.fetch(ProposalConfig.class, Cnd.NEW());
if (taskList.size() + seconders.length < proposalConfig.getSeconderNum()) {
return Result.error("至少邀请" + proposalConfig.getSeconderNum() + "个附议人");
}
Sql sql = Sqls.create("""
SELECT
t1.id seconderId,
t1.id,
t1.userId,
t1.loginName,
t1.userName,
t1.sex,
@@ -196,9 +289,7 @@ public class ProposalMineController {
sql.setCondition(Cnd.where("t1.loginName", "in", seconders).groupBy("t1.loginName"));
List<NutMap> list = proposalCommonService.listMap(sql);
// 附议人ID
List<String> userIds = list.stream().map(item -> item.getString("seconderId")).toList();
// 获取流程实例
ProcessInstance processInstance = flowEngine.processInstanceService().fetch(Cnd.where(ProcessInstance::getBusinessNo, "=", proposalId));
List<String> userIds = list.stream().map(item -> item.getString("userId")).toList();
// 获取正在执行的任务(邀请附议人||提案附议)
List<ProcessTask> doingTaskList = flowEngine.processTaskService().getDoingTaskList(processInstance.getId(), null);
@@ -211,11 +302,17 @@ public class ProposalMineController {
args.set(FlowConst.NEXT_NODE_OPERATOR, userIds);
args.set(FlowConst.TASK_FORM_DATA_PREFIX + "seconder", list);
flowCommonService.executeTask(args);
// flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args);
}
} else {
// 加签
processTaskService.addCandidateActor(doingTaskList.get(0).getId(), userIds);
NutMap variable = Json.fromJson(NutMap.class, inviteTask.getVariable());
List<NutMap> tfSeconders = variable.getAsList(FlowConst.TASK_FORM_DATA_PREFIX + "seconder", NutMap.class);
tfSeconders.addAll(list);
variable.put(FlowConst.TASK_FORM_DATA_PREFIX + "seconder", tfSeconders);
inviteTask.setVariable(Json.toJson(variable));
dao.update(inviteTask, "variable");
}
return Result.success();
@@ -86,6 +86,7 @@ public class ProposalSecondedController {
t.finishTime,
t.taskParentId,
t.variable taskVariable,
ta.actorName taskActorName,
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
FROM
@@ -102,7 +103,10 @@ public class ProposalSecondedController {
""");
Cnd cnd = Cnd.NEW();
cnd.and("t.taskName", "=", "74458b33-ad6e-46c4-b8d9-1aa897142b25");
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())){
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
}
if (approval) {
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
@@ -1,9 +1,12 @@
package com.budwk.app.zhgh.democratic.proposal.controller.transact;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.service.ProcessTaskService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
import com.budwk.app.zhgh.democratic.proposal.service.ProposalUnderTakeReplyService;
@@ -16,6 +19,7 @@ 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;
@@ -65,13 +69,16 @@ public class ProposalUnderTakeReplyController {
t.taskParentId,
t.variable taskVariable,
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName,
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
IFNULL(GROUP_CONCAT(DISTINCT nt.taskName),'结束') curTaskKey,
CASE WHEN t.taskState = 20 AND ( rt.id IS NULL OR rt.taskState = 10 ) THEN 1 ELSE 0 END AS canRevoke,
t.variable->>'$.unitName' AS taskUnitName,
IF(JSON_EXTRACT(t.variable, '$.isMaster') = true, 1, 0) AS taskIsMaster
FROM
wf_process_task t
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
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
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id
LEFT JOIN proposal_info info ON info.id = ins.businessNo
LEFT JOIN proposal_type type on type.id = info.typeId
LEFT JOIN teacher_congress_session tcs on tcs.id = info.sessionId
@@ -80,7 +87,10 @@ public class ProposalUnderTakeReplyController {
""");
Cnd cnd = Cnd.NEW();
cnd.and("t.taskName", "in", List.of("85cf23da-2dd5-4007-a1e9-bd9bfddc68f0", "c9a1586e-272b-41b8-b438-0be9f9e3781d"));
// cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
}
if (approval) {
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
@@ -92,6 +102,17 @@ public class ProposalUnderTakeReplyController {
cnd.desc("t.createdAt");
sql.setCondition(cnd);
Pagination pagination = proposalCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
List<NutMap> list = pagination.getList();
for (NutMap row : list) {
if (row.getInt("taskIsMaster") == 0) {
boolean b = List.of("85cf23da-2dd5-4007-a1e9-bd9bfddc68f0", "c9a1586e-272b-41b8-b438-0be9f9e3781d", "04ecf80c-a9d0-4986-8aac-231758d6a7af").stream()
.anyMatch(a -> row.getString("curTaskKey").contains(a));
row.setv("canRevoke",b);
}
}
pagination.setList(list);
return Result.success(pagination);
}
@@ -110,10 +110,10 @@ public class ProposalInfoPageVO extends BpmTaskApprovalVo {
private boolean isConsolidation;
@ApiModelProperty("主办承办单位")
private String masterUnderTakeName;
private String masterUnitName;
@ApiModelProperty("协办承办单位")
private String[] slaveUnderTakeNames;
private String[] slaveUnitNames;
@ApiModelProperty("承办单位答复是否转办")
private boolean underTakeReplyIsTransfer;
@@ -1,24 +0,0 @@
package com.budwk.app.zhgh.democratic.proposal.interceptor;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.FlowInterceptor;
import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.service.ProposalWriteService;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.json.Json;
/**
* 提案申请拦截器
*/
public class ProposalApplyInterceptor implements FlowInterceptor {
@Override
public void intercept(Execution execution) {
}
}
@@ -0,0 +1,53 @@
package com.budwk.app.zhgh.democratic.proposal.interceptor;
import com.budwk.app.flow.engine.FlowInterceptor;
import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.entity.ProcessTaskActor;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.aop.Aop;
import org.nutz.json.Json;
import org.nutz.lang.util.NutMap;
import java.util.List;
/**
* 提案委员会立案后置拦截器
*/
public class ProposalUnitNameInterceptor implements FlowInterceptor {
@Override
@Aop(TransAop.READ_COMMITTED)
public void intercept(Execution execution) {
Dao dao = ServiceContext.find(Dao.class);
List<ProcessTask> processTaskList = execution.getProcessTaskList();
for (ProcessTask task : processTaskList) {
NutMap variable = Json.fromJson(NutMap.class, task.getVariable());
ProcessTaskActor taskActor = dao.fetch(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", task.getId()));
// 单位名称
variable.setv("unitName", taskActor.getActorUnitName());
variable.setv("unitId",taskActor.getActorUnitId());
// 是否主办
variable.setv("isMaster", task.getTaskName().equals("85cf23da-2dd5-4007-a1e9-bd9bfddc68f0"));
task.setVariable(Json.toJson(variable));
}
// 更新立案结果
ProcessInstance processInstance = execution.getProcessInstance();
String businessNo = processInstance.getBusinessNo();
dao.update(ProposalInfo.class, Chain.make("caseFilingResult", execution.getArgs().getStr("")), Cnd.where(ProposalInfo::getId, "=", businessNo));
dao.update(processTaskList, "variable");
}
}
File diff suppressed because one or more lines are too long
@@ -1,73 +1,8 @@
#nprogress {
pointer-events: none
}
#nprogress .bar {
background: #29d;
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px
}
#nprogress .peg {
display: block;
position: absolute;
right: 0;
width: 100px;
height: 100%;
box-shadow: 0 0 10px #29d, 0 0 5px #29d;
opacity: 1;
-webkit-transform: rotate(3deg) translate(0, -4px);
-ms-transform: rotate(3deg) translate(0, -4px);
transform: rotate(3deg) translate(0, -4px)
}
#nprogress .spinner {
display: block;
position: fixed;
z-index: 1031;
top: 15px;
right: 15px
}
#nprogress .spinner-icon {
width: 18px;
height: 18px;
box-sizing: border-box;
border: 2px solid transparent;
border-top-color: #29d;
border-left-color: #29d;
border-radius: 50%;
-webkit-animation: nprogress-spinner 400ms linear infinite;
animation: nprogress-spinner 400ms linear infinite
}
.nprogress-custom-parent {
overflow: hidden;
position: relative
}
.nprogress-custom-parent #nprogress .bar, .nprogress-custom-parent #nprogress .spinner {
position: absolute
}
@-webkit-keyframes nprogress-spinner {
0% {
-webkit-transform: rotate(0deg)
}
100% {
-webkit-transform: rotate(360deg)
}
}
@keyframes nprogress-spinner {
0% {
transform: rotate(0deg)
}
100% {
transform: rotate(360deg)
}
}
/**
* Minified by jsDelivr using clean-css v5.3.3.
* Original file: /npm/nprogress@0.2.0/nprogress.css
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0,-4px);-ms-transform:rotate(3deg) translate(0,-4px);transform:rotate(3deg) translate(0,-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
/*# sourceMappingURL=/sm/4400c1e6b434bc414f3870cc8d155b3335f1f32d1a07381e06cc8a8bd869de73.map */
@@ -21,10 +21,11 @@
<!-- import ElementUI -->
<script src="${base!}/assets/platform/plugins/element-ui/lib/index.js"></script>
<script src="${base!}/assets/platform/plugins/element-ui/lib/i18n/${lang,escape}.js"></script>
<link rel="stylesheet" href="https://cdn.staticfile.net/element-ui/2.15.14/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index_custom.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css" />
<!-- import common css -->
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css" />
<!-- import Jquery -->
@@ -32,7 +33,7 @@
<!-- pjax是异步加载html片段的工具,模拟前端路由机制 -->
<script src="${base!}/assets/platform/plugins/pjax/jquery.pjax.js"></script>
<!--nprogress 配合pjax使用-->
<link rel="stylesheet" href="https://cdn.staticfile.net/nprogress/0.2.0/nprogress.css" />
<link ref="stylesheet" href="${base!}/assets/platform/plugins/nprogress/nprogress.css"/>
<script src="${base!}/assets/platform/plugins/nprogress/nprogress.js"></script>
<!-- 农历插件 -->
@@ -0,0 +1,74 @@
const basicForm = {
template: /*language=HTML*/ `
<el-dialog :visible.sync="visible" :title="formData.id ? '编辑' : '新增'">
<el-form :model="formData" :rules="rules" ref="formRef" label-width="80px">
<el-form-item label="课程标题" prop="title">
<el-input v-model="formData.title" placeholder="请输入课程标题"></el-input>
</el-form-item>
<el-form-item label="课程描述" prop="description">
<el-input type="textarea" v-model="formData.description" placeholder="请输入课程描述"
:rows="4"></el-input>
</el-form-item>
<el-form-item label="封面地址">
<file-upload
:value.sync="formData.cover"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item label="课程分类" prop="category">
<el-select v-model="formData.category" placeholder="请选择分类" style="width: 100%;">
<el-option label="前端开发" value="前端开发"></el-option>
<el-option label="后端开发" value="后端开发"></el-option>
<el-option label="移动开发" value="移动开发"></el-option>
<el-option label="数据库" value="数据库"></el-option>
<el-option label="运维部署" value="运维部署"></el-option>
<el-option label="人工智能" value="人工智能"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否启用">
<el-switch v-model="formData.disabled" :active-value="false" :inactive-value="true"></el-switch>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="onSave">确定</el-button>
</div>
</el-dialog>
`,
data() {
return {
visible: false,
formData: {},
rules: {
title: [{required: true, message: '请输入课程标题', trigger: 'blur'}],
description: [{required: true, message: '请输入课程描述', trigger: 'blur'}],
category: [{required: true, message: '请选择课程分类', trigger: 'change'}]
}
}
},
methods: {
onOpen(row = null) {
this.visible = true
this.formData = {...row}
},
onSave() {
this.$refs.formRef.validate(valid => {
if (valid) {
this.$axios.post('/platform/edu/courses/' + (this.formData.id ? 'update' : 'insert'), this.formData).then(res => {
if (res.code === 0) {
this.visible = false
this.$message.success(res.msg)
this.$emit('refresh', null)
}
})
}
})
}
}
}
@@ -0,0 +1,424 @@
const contentForm = {
template: /*language=HTML*/ `
<el-dialog :visible.sync="visible" width="70%" title="章节视频管理" top="50px" class="edu_content_dialog">
<div v-if="selectedCourse">
<div class="section-header">
<div>
<h2 style="margin: 0; color: #303133;">{{ selectedCourse.title }} - 内容管理</h2>
<p style="margin: 5px 0 0; color: #909399;">管理课程章节和视频</p>
</div>
<div>
<el-button type="primary" icon="el-icon-plus" size="small" @click="onOpenChapter()">
添加章节
</el-button>
</div>
</div>
<div style="padding: 0 20px 20px;">
<div class="stats-card">
<!-- <el-row :gutter="20">-->
<!-- <el-col :span="8">-->
<!-- <h3 style="margin: 0;">{{ currentChapters.length }}</h3>-->
<!-- <p style="margin: 5px 0 0;">章节数量</p>-->
<!-- </el-col>-->
<!-- <el-col :span="8">-->
<!-- <h3 style="margin: 0;">{{ getTotalVideos() }}</h3>-->
<!-- <p style="margin: 5px 0 0;">视频数量</p>-->
<!-- </el-col>-->
<!-- <el-col :span="8">-->
<!-- <h3 style="margin: 0;">{{ formatDuration(getTotalDuration()) }}</h3>-->
<!-- <p style="margin: 5px 0 0;">总时长</p>-->
<!-- </el-col>-->
<!-- </el-row>-->
</div>
<div v-if="currentChapters.length === 0" style="text-align: center; padding: 50px; color: #909399;">
<i class="el-icon-folder-opened"
style="font-size: 64px; display: block; margin-bottom: 20px;"></i>
<p>暂无章节,请添加章节开始管理内容</p>
</div>
<div v-for="chapter in currentChapters" :key="chapter.id" class="chapter-card">
<div class="chapter-header">
<div>
<h3 style="margin: 0; color: #303133;">{{ chapter.title }}</h3>
<p style="margin: 5px 0 0; color: #909399;">
{{ chapter?.videos.length || 0 }} 个视频
</p>
</div>
<div>
<el-button size="small" type="primary" @click="onOpenVideo(chapter.id)">
添加视频
</el-button>
<el-button size="small" @click="onOpenChapter(chapter)">
编辑章节
</el-button>
<el-button size="small" type="danger" @click="deleteChapter(chapter.id)">
删除章节
</el-button>
</div>
</div>
<div class="chapter-content">
<div v-if="chapter?.videos.length === 0"
style="text-align: center; color: #909399; padding: 30px;">
<i class="el-icon-video-camera"
style="font-size: 32px; display: block; margin-bottom: 10px;"></i>
<p>暂无视频,点击"添加视频"开始添加内容</p>
</div>
<div v-for="video in chapter?.videos" :key="video.id" class="video-item">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div style="flex: 1;">
<h4 style="margin: 0 0 5px; color: #303133;">{{ video.title }}</h4>
<p style="margin: 0; color: #909399; font-size: 14px;">
<i class="el-icon-time"></i> {{ formatDuration(video.duration) }}
<span style="margin-left: 15px;">
<i class="el-icon-link"></i> {{ video.url }}
</span>
</p>
</div>
<div>
<el-button size="mini" @click="playVideo(video)">播放</el-button>
<el-button size="mini" @click="onOpenVideo(video.chapterId,video)">编辑
</el-button>
<el-button size="mini" type="danger" @click="deleteVideo(video.id)">删除
</el-button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else style="text-align: center; padding: 100px; color: #909399;">
<i class="el-icon-warning" style="font-size: 64px; display: block; margin-bottom: 20px;"></i>
<p>请先选择一个课程进行内容管理</p>
</div>
<!-- 章节弹窗 -->
<el-dialog :title="chapterForm.id ? '编辑章节' : '添加章节'" :visible.sync="chapterDialogVisible"
append-to-body
width="500px">
<el-form :model="chapterForm" :rules="chapterRules" ref="chapterFormRef" label-width="80px">
<el-form-item label="章节标题" prop="title">
<el-input v-model="chapterForm.title" placeholder="请输入章节标题"></el-input>
</el-form-item>
<el-form-item label="排序码" prop="sortCode">
<el-input-number v-model="chapterForm.sortCode" :min="1" style="width: 100%;"></el-input-number>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="chapterDialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveChapter">确定</el-button>
</div>
</el-dialog>
<!-- 视频弹窗 -->
<el-dialog :title="videoForm.id ? '编辑视频' : '添加视频'" :visible.sync="videoDialogVisible" width="600px"
append-to-body>
<el-form :model="videoForm" :rules="videoRules" ref="videoFormRef" label-width="80px">
<el-form-item label="视频标题" prop="title">
<el-input v-model="videoForm.title" placeholder="请输入视频标题"></el-input>
</el-form-item>
<el-form-item label="视频地址" prop="url">
<!-- <el-input v-model="videoForm.url" placeholder="请输入视频地址"></el-input>-->
<file-upload
:value.sync="videoForm.url"
:upload_number="1"
upload_mode="file"
upload_result_category="interval"
upload_result_type="url"
accept="video/*"
></file-upload>
</el-form-item>
<!-- <el-form-item label="视频时长" prop="duration">-->
<!-- <el-input-number v-model="videoForm.duration" :min="1" placeholder="秒"-->
<!-- style="width: 100%;"></el-input-number>-->
<!-- <div class="duration-display">{{ formatDuration(videoForm.duration || 0) }}</div>-->
<!-- </el-form-item>-->
<el-form-item label="排序码" prop="sortCode">
<el-input-number v-model="videoForm.sortCode" :min="1" style="width: 100%;"></el-input-number>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="videoDialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveVideo">确定</el-button>
</div>
</el-dialog>
<!-- 弹窗:视频播放器 -->
<el-dialog title="视频播放" :visible.sync="videoPlayDialogVisible" @close="handleVideoPlayDialogClose" append-to-body>
<div style="text-align: center;">
<video
ref="videoPlayer"
class="video-player"
:src="currentVideoSrc"
controls
autoplay
style="width:100%;max-width: 100%; height: auto;"
>
您的浏览器不支持视频标签。
</video>
</div>
</el-dialog>
</el-dialog>
`,
data() {
return {
visible: false,
selectedCourse: null,
// 弹窗显示状态
chapterDialogVisible: false,
videoDialogVisible: false,
// 表单数据
chapterForm: {},
videoForm: {},
// 表单验证规则
chapterRules: {
title: [{required: true, message: '请输入章节标题', trigger: 'blur'}],
sortCode: [{required: true, message: '请输入排序码', trigger: 'blur'}]
},
videoRules: {
title: [{required: true, message: '请输入视频标题', trigger: 'blur'}],
url: [{required: true, message: '请输入视频地址', trigger: 'blur'}],
duration: [{required: true, message: '请输入视频时长', trigger: 'blur'}],
sortCode: [{required: true, message: '请输入排序码', trigger: 'blur'}]
},
// 数据
chapters: [],
videos: [],
// 视频播放
videoPlayDialogVisible: false,
currentVideoSrc: null
}
},
computed: {
currentChapters() {
if (!this.selectedCourse) return [];
return this.chapters.filter(chapter => chapter.courseId === this.selectedCourse.id)
.sort((a, b) => a.sortCode - b.sortCode);
}
},
methods: {
onOpen(selectedCourse) {
this.visible = true
this.selectedCourse = selectedCourse
this.listChapter()
},
// 查询章节
listChapter() {
this.$axios.post('/platform/edu/chapters/list', {courseId: this.selectedCourse.id}).then(res => {
if (res.code === 0) {
this.chapters = res.data
}
})
},
// 新增/编辑章节
onOpenChapter(chapter = null) {
this.chapterForm = chapter ? {...chapter} : {
id: '',
courseId: this.selectedCourse.id,
title: '',
sortCode: this.currentChapters.length + 1
};
this.chapterDialogVisible = true;
this.$nextTick(() => {
this.$refs.chapterFormRef && this.$refs.chapterFormRef.clearValidate();
});
},
// 删除章节
deleteChapter(id) {
this.$confirm('此操作将永久删除该章节及其所有视频,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message.success('删除成功');
});
},
// 保存章节
saveChapter() {
this.$refs.chapterFormRef.validate(valid => {
if (valid) {
this.$axios.post('/platform/edu/chapters/' + (this.chapterForm.id ? 'update' : 'insert'), this.chapterForm).then(res => {
if (res.code === 0) {
this.chapterDialogVisible = false
this.$message.success(res.msg)
this.listChapter()
}
})
}
})
},
// 新增/编辑视频
onOpenVideo(chapterId, video = null) {
const chapter = this.chapters.find(chapter => chapter.id === chapterId)
this.videoForm = video ? {...video} : {
id: '',
chapterId: chapterId,
title: '',
url: '',
duration: 0,
sortCode: chapter ? chapter.videos.length + 1 : 1
};
this.videoDialogVisible = true;
this.$nextTick(() => {
this.$refs.videoFormRef && this.$refs.videoFormRef.clearValidate();
});
},
// 保存视频
saveVideo() {
this.$refs.videoFormRef.validate(valid => {
if (valid) {
this.$axios.post('/platform/edu/video/' + (this.videoForm.id ? 'update' : 'insert'), this.videoForm).then(res => {
if (res.code === 0) {
this.videoDialogVisible = false
this.$message.success(res.msg)
this.listChapter()
}
})
}
});
},
// 删除视频
deleteVideo(id) {
this.$confirm('确定删除此视频吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/edu/video/delete', {id: id}).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.listChapter()
}
})
});
},
// 播放视频
playVideo(video) {
this.currentVideoSrc = video.url;
this.videoPlayDialogVisible = true;
// 确保 dialog 打开后视频能正确加载并播放(异步)
this.$nextTick(() => {
const videoEl = this.$refs.videoPlayer;
videoEl.load(); // 重新加载视频源
videoEl.play().catch(err => {
console.warn('自动播放失败,需用户点击播放按钮:', err);
});
});
},
// 关闭视频播放对话框
handleVideoPlayDialogClose(){
const videoEl = this.$refs.videoPlayer;
if (videoEl) {
videoEl.pause();
videoEl.currentTime = 0;
}
// 清空 src 避免音频仍在播放(某些浏览器)
this.currentVideoSrc = '';
},
formatDuration(seconds) {
if (!seconds) return '0分0秒';
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const remainingSeconds = seconds % 60;
if (hours > 0) {
return hours + '小时' + minutes + '分' + remainingSeconds + '秒'
} else {
return minutes + '分' + remainingSeconds + '秒'
}
}
},
style: /*language=CSS*/ `
.edu_content_dialog .el-dialog__body {
height: calc(100vh - 155px);
overflow-y: auto;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 20px 20px 0;
}
.video-item {
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
transition: all 0.3s;
}
.video-item:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
.chapter-card {
border: 1px solid #e4e7ed;
border-radius: 8px;
margin-bottom: 20px;
overflow: hidden;
}
.chapter-header {
background: #f5f7fa;
padding: 15px 20px;
border-bottom: 1px solid #e4e7ed;
display: flex;
justify-content: space-between;
align-items: center;
}
.chapter-content {
padding: 20px;
}
.stats-card {
color: white;
padding: 20px;
border-radius: 8px;
text-align: center;
margin-bottom: 20px;
}
.course-cover {
width: 100px;
height: 60px;
object-fit: cover;
border-radius: 4px;
}
.duration-display {
color: #909399;
font-size: 12px;
}
`
}
@@ -0,0 +1,102 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<table-tool>
<el-button type="primary" size="small" icon="el-icon-plus" @click="$refs.basicFormRef.onOpen()">新增</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="课程标题" min-width="150">
<template slot-scope="scope">
<div style="display: flex; align-items: center;">
<img v-if="scope.row.cover" :src="scope.row.cover" class="course-cover"
style="margin-right: 10px;">
<div v-else
style="width: 100px; height: 60px; background: #f0f0f0; border-radius: 4px; margin-right: 10px; display: flex; align-items: center; justify-content: center; color: #999;">
无封面
</div>
<strong>{{ scope.row.title }}</strong>
</div>
</template>
</el-table-column>
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip></el-table-column>
<el-table-column prop="category" label="分类" width="120">
<template slot-scope="scope">
<el-tag size="small">{{ scope.row.category }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="disabled" label="状态" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="scope.row.disabled ? 'danger' : 'success'" size="small">
{{ scope.row.disabled ? '已禁用' : '启用中' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="300" align="center" fixed="right">
<template slot-scope="scope">
<el-button size="mini" @click="manageCourse(scope.row)" type="primary">
管理内容
</el-button>
<el-button size="mini" @click="$refs.basicFormRef.onOpen(scope.row)" type="primary">
编辑
</el-button>
<el-button size="mini" @click="onDelete(scope.row.id)" type="danger">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<basic-form ref="basicFormRef" @refresh="pageData"></basic-form>
<content-form ref="contentFormRef"></content-form>
</div>
<script>
<!--#include('basicForm.js'){}#-->
<!--#include('contentForm.js'){}#-->
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
components: {
'basic-form': basicForm,
'content-form': contentForm
},
data() {
return {}
},
methods: {
manageCourse(row) {
this.$refs.contentFormRef.onOpen(row)
},
onDelete(id) {
this.$confirm('此操作将永久删除该课程及其所有章节和视频,是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post('/platform/edu/courses/delete', {id}).then(res => {
this.$message.success('删除成功')
this.pageData()
})
}).catch(() => {
})
}
},
created() {
this.pageData()
}
});
</script>
<!--#
}
#-->
@@ -0,0 +1,183 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
placeholder="选择年"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="会议名称">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入会议名称"
v-model="pageForm.searchKeyword">
</el-input>
</search-item>
<search-item label="所属工会:">
<el-select v-model="pageForm.unionId" placeholder="请选择所属工会" filterable clearable
style="width: 100%">
<el-option v-for="item in unionList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="会议列表">
<el-radio-group v-model="pageForm.approval" size="small" @change="doSearch">
<el-radio-button :label="true">已审核</el-radio-button>
<el-radio-button :label="false">未审核</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder">
<el-table-column :index="indexMethod" align="center" header-align="center" label="序号" type="index"
width="80px"></el-table-column>
<el-table-column label="会议名称" prop="meetingName"></el-table-column>
<el-table-column label="会议时间" prop="meetingTime"></el-table-column>
<el-table-column label="届" prop="j"></el-table-column>
<el-table-column label="次" prop="c"></el-table-column>
<el-table-column label="申请人" prop="createUserName"></el-table-column>
<el-table-column label="所属工会" prop="unionName"></el-table-column>
<el-table-column label="会议类型" prop="meetingType"></el-table-column>
<el-table-column label="会议时间" prop="meetingTime"></el-table-column>
<el-table-column label="当前节点" prop="curTaskName"></el-table-column>
<el-table-column label="流程状态" prop="instanceState">
<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 align="center" header-align="center" label="操作" prop="userOnline" width="300">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskState === 10" @click="openAudit(row)" size="mini" type="primary">审核
</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<grassroots-congress-meeting-info ref="grassrootsCongressMeetingInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">
{{formData.taskName}}
</div>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix=""
class="flow-task-form">
<el-form-item label="审批意见" prop="tf_opinion"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.tf_opinion"></user-opinion-textarea>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button @click="$refs.guava.index()" size="small">取消</el-button>
<el-button @click="handleTaskAction(6)" size="small" type="info">退回到提案人</el-button>
<el-button @click="handleTaskAction(20)" size="small" type="danger">不同意</el-button>
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意</el-button>
</el-row>
</div>
</grassroots-congress-meeting-info>
</template>
</guava>
</div>
<script>
<!--#include("../info.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"grassroots-congress-meeting-info": GRASSROOTS_CONGRESS_MEETING_INFO
},
data() {
return {
unionList: [],
pageForm: {
year: this.$moment().format("YYYY"),
approval: false
},
showApprovalForm: false,
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.grassrootsCongressMeetingInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.grassrootsCongressMeetingInfoRef.onOpen(row)
})
},
handleTaskAction(val) {
this.$refs.formRef.validate(valid => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
})
},
onRevoke(row) {
this.$confirm("您确定要撤回吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
async created() {
this.unionList = await this.$businessTool.listUnion()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,117 @@
const GRASSROOTS_CONGRESS_MEETING_INFO = {
template: /*language=HTML*/ `
<div>
<div class="process-title">
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="2" border class="margin-top" style="margin: 10px" title="">
<el-descriptions-item label="会议名称" span="2">
<span class="item-center"> {{ viewData.meetingName }}</span>
</el-descriptions-item>
<el-descriptions-item label="类型">
{{viewData.fullName}}
</el-descriptions-item>
<el-descriptions-item label="申请人">
{{viewData.createUserName}}
</el-descriptions-item>
<el-descriptions-item label="申请时间">
{{viewData.createTime}}
</el-descriptions-item>
<el-descriptions-item label="申请单位">
{{viewData.unitName}}
</el-descriptions-item>
<el-descriptions-item label="申请工会">
{{viewData.unitName}}
</el-descriptions-item>
<el-descriptions-item></el-descriptions-item>
<el-descriptions-item label="会议议程" span="2">
<div v-html="viewData.meetingTopic"></div>
</el-descriptions-item>
<el-descriptions-item label="备注" span="2">
{{viewData.meetingRemark}}
</el-descriptions-item>
<el-descriptions-item label="请示附件" span="2">
<file-preview :files="viewData.files" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="mt10">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id"
v-if="task.ext.isFirstTaskNode">
<el-descriptions-item label="申请用户">{{ task.ext.initiatorName
}}({{task.ext.initiatorAccount}})
</el-descriptions-item>
<el-descriptions-item label="申请时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
</el-descriptions>
<el-descriptions border class="flow-task-form" :column="3" :key="task.id" v-else>
<el-descriptions-item label="办理用户">{{ task.taskFormData.userName
}}({{task.taskFormData.loginName}})
</el-descriptions-item>
<el-descriptions-item label="办理时间">{{ task.finishTime }}</el-descriptions-item>
<el-descriptions-item label="办理结果">
<dict-tag :options="dict.type.PROCESS_TASK_SUBMIT_TYPE"
:value="task.ext.submitType"></dict-tag>
</el-descriptions-item>
<el-descriptions-item label="办理意见" v-if="!task.ext.isFirstTaskNode">{{
task.taskFormData.opinion }}
</el-descriptions-item>
</el-descriptions>
</div>
</template>
<slot></slot>
<snaker-chart ref="snakerChartRef"></snaker-chart>
</div>
`,
store,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
visible: false,
viewData: {},
doneTasks: [],
row: null
}
},
methods: {
// 打开
onOpen(row) {
this.row = row
this.visible = true
this.getInfo()
this.getDoneTasks()
},
// 获取申请信息
getInfo() {
this.$axios.post('/platform/grassrootsCongress/meeting/common/info', {id: this.row.id}).then((res) => {
if (res.code === 0) {
this.viewData = res.data
}
})
},
// 获取已办任务审批记录
getDoneTasks() {
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data
}
})
},
// 查看流程图
openChart() {
this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId)
}
}
}
@@ -0,0 +1,124 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker placeholder="选择年" style="width: 100%" type="year" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
</search-item>
<search-item label="会议名称">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入会议名称" v-model="pageForm.searchKeyword"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="会议列表"></table-tool>
<el-table :data="tableData" @sort-change="pageOrder">
<el-table-column :index="indexMethod" align="center" header-align="center" label="序号" type="index" width="80px"></el-table-column>
<el-table-column label="会议名称" prop="meetingName"></el-table-column>
<el-table-column label="会议时间" prop="meetingTime"></el-table-column>
<el-table-column label="届" prop="j"></el-table-column>
<el-table-column label="次" prop="c"></el-table-column>
<el-table-column label="申请人" prop="createUserName"></el-table-column>
<el-table-column label="所属工会" prop="unionName"></el-table-column>
<el-table-column label="会议类型" prop="meetingType"></el-table-column>
<el-table-column label="会议时间" prop="meetingTime"></el-table-column>
<el-table-column prop="taskName" 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 align="center" header-align="center" label="操作" prop="userOnline" width="300">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskKey === 'startTask' || !row.instanceId" @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.taskKey === 'startTask' || !row.instanceId" @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #public>
<info ref="infoRef"></info>
</template>
</guava>
</div>
<script>
<!--#include("../info.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
info: GRASSROOTS_CONGRESS_MEETING_INFO
},
data() {
return {
pageForm: {
year: this.$moment().format("YYYY")
},
}
},
methods: {
openView(row) {
this.$refs.guava.public(() => {
this.$refs.infoRef.onOpen(row)
})
},
onEdit(row) {
window.location.href = '/platform/grassrootsCongress/meeting/write?taskId=' + (row.startTaskId || '') + "&bizId=" + row.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()
}
})
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/grassrootsCongress/meeting/mine/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
}
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,83 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker placeholder="选择年" style="width: 100%" type="year" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
</search-item>
<search-item label="会议名称">
<el-input @keyup.enter.native="doSearch" clearable placeholder="请输入会议名称" v-model="pageForm.searchKeyword"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="会议列表"></table-tool>
<el-table :data="tableData" @sort-change="pageOrder">
<el-table-column :index="indexMethod" align="center" header-align="center" label="序号" type="index" width="80px"></el-table-column>
<el-table-column label="会议名称" prop="meetingName"></el-table-column>
<el-table-column label="会议时间" prop="meetingTime"></el-table-column>
<el-table-column label="届" prop="j"></el-table-column>
<el-table-column label="次" prop="c"></el-table-column>
<el-table-column label="申请人" prop="createUserName"></el-table-column>
<el-table-column label="所属工会" prop="unionName"></el-table-column>
<el-table-column label="会议类型" prop="meetingType"></el-table-column>
<el-table-column label="会议时间" prop="meetingTime"></el-table-column>
<el-table-column prop="taskName" 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="操作" width="100" fixed="right">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #public>
<info ref="infoRef"></info>
</template>
</guava>
</div>
<script>
<!--#include("../info.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
info: GRASSROOTS_CONGRESS_MEETING_INFO
},
data() {
return {
pageForm: {
year: this.$moment().format("YYYY")
},
}
},
methods: {
openView(row) {
this.$refs.guava.public(() => {
this.$refs.infoRef.onOpen(row)
})
}
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,239 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<snaker-start slot="header" label="双代会请示" define_key="JCSDH"></snaker-start>
<el-form :model="formData" :rules="formRules" label-width="120px" ref="formRef">
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="届数" prop="j">
<dict-select @change="jChange" code="TEACHER_CONGRESS_J"
v-model="formData.j"></dict-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="次数" prop="c">
<dict-select @change="cChange" code="TEACHER_CONGRESS_C"
v-model="formData.c"></dict-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会议名称" prop="meetingName">
<el-input
clearable
maxlength="100"
placeholder="请填写会议名称"
v-model="formData.meetingName">
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类型" prop="meetingType">
<el-radio-group v-model="formData.meetingType">
<el-radio-button label="换届会">换届会</el-radio-button>
<el-radio-button label="届中会">届中会</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="申请单位" prop="unitName">
<el-input :clearable="false"
placeholder="申请单位"
readonly
v-model="formData.unitName">
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="所在工会" prop="unionName">
<el-input :clearable="false"
placeholder="所在工会"
readonly
v-model="formData.unionName">
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="会议时间" prop="meetingTime">
<el-date-picker
:clearable="false"
format="yyyy-MM-dd HH:mm"
placeholder="选择会议时间"
style="width: 100%"
type="datetime"
v-model="formData.meetingTime"
value-format="yyyy-MM-dd HH:mm">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="申请时间" prop="createTime">
<el-input :clearable="false"
placeholder="申请时间"
readonly
v-model="formData.createTime">
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="会议议程" prop="meetingTopic">
<text-editor v-model="formData.meetingTopic"></text-editor>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="meetingRemark">
<el-input :rows="4" maxlength="500" placeholder="请输入备注" type="textarea"
v-model="formData.meetingRemark"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="请示附件" prop="files">
<file-upload
:value.sync="formData.files"
:upload_number="1"
upload_result_category="array"
complete_result
upload_mode="drag"
accept=".doc,.docx,.xls,.xlsx,.pdf"
>
</file-upload>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-row type="flex" justify="end" class="mt20">
<el-button type="primary" plain @click="onSave">保存</el-button>
<el-button type="primary" @click="onSubmit" v-if="!taskId">提交</el-button>
<el-button type="primary" @click="submitAgain" v-else>提交1</el-button>
</el-row>
</el-card>
</guava>
</div>
<script>
new Vue({
el: "#app",
store,
data() {
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
formRules: {
meetingName: [{required: true, message: "请填写会议名称", trigger: ["blur", "change"]}],
meetingTime: [{required: true, message: "请填写会议时间", trigger: ["blur", "change"]}],
meetingTopic: [{required: true, message: "请填写会议议程", trigger: ["blur", "change"]}],
files: [{required: true, message: "必填", trigger: ["change", "blur"]}],
j: [{required: true, message: "请填写届数", trigger: ["blur", "change"]}],
c: [{required: true, message: "请填写次数", trigger: ["blur", "change"]}]
},
formData: {
j: "",
c: "",
files: [],
meetingName: "",
meetingType: "届中会"
}
}
},
methods: {
// 保存
onSave() {
this.$confirm("您确定保存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/grassrootsCongress/meeting/write/save', {data: JSON.stringify(this.formData)}).then(res => {
if (res.code === 0) {
this.$message.success("保存成功")
window.location.href = '/platform/grassrootsCongress/meeting/mine'
}
})
})
},
// 提交
onSubmit() {
this.$refs.formRef.validate(valid => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/grassrootsCongress/meeting/write/submit', {
data: JSON.stringify(this.formData)
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
window.location.href = '/platform/grassrootsCongress/meeting/mine'
}
})
})
})
},
// 提交
submitAgain() {
this.$refs.formRef.validate(valid => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/grassrootsCongress/meeting/write/submitAgain', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
window.location.href = '/platform/grassrootsCongress/meeting/mine'
}
})
})
})
},
jChange() {
const j = this.formData.j ? "第" + this.formData.j : ""
const c = this.formData.c ? "第" + this.formData.c : ""
this.formData.meetingName = "关于召开" + this.formData.unitName + j + c + "教职工代表大会、工会会员代表大会的请示"
},
cChange() {
const j = this.formData.j ? "第" + this.formData.j : ""
const c = this.formData.c ? "第" + this.formData.c : ""
this.formData.meetingName = "关于召开" + this.formData.unitName + j + c + "教职工代表大会、工会会员代表大会的请示"
},
// 初始化
init() {
if (this.bizId) {
this.$axios.post("/platform/grassrootsCongress/meeting/write/info", {id: this.bizId}).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
} else {
this.$set(this.formData, "createTime", this.$moment(new Date()).format("YYYY-MM-DD"))
this.$set(this.formData, "unionId", this.$store.state.user.union.id)
this.$set(this.formData, "unionName", this.$store.state.user.union.name)
this.$set(this.formData, "unitId", this.$store.state.user.unit.id)
this.$set(this.formData, "unitName", this.$store.state.user.unit.name)
}
}
},
created() {
this.init()
}
})
</script>
<!--#
}
#-->
@@ -45,7 +45,13 @@ layout("/layouts/platform.html"){
show-overflow-tooltip
v-for="column in tableColumns"
></el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName" show-overflow-tooltip></el-table-column>
<el-table-column prop="taskName" 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 align="center" header-align="center" label="操作" prop="userOnline" width="300">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
@@ -13,90 +13,97 @@ layout("/layouts/platform.html"){
<el-card shadow="never">
<search @search="doSearch">
<search-item label="教代会">
<el-select @change="meetingChange" clearable filterable placeholder="所属教代会" v-model="pageForm.sessionId">
<el-option :key="item.id" :label="item.fullName" :value="item.id" v-for="item in sessionOptions"></el-option>
<el-select @change="meetingChange" clearable filterable placeholder="所属教代会"
v-model="pageForm.sessionId">
<el-option :key="item.id" :label="item.fullName" :value="item.id"
v-for="item in sessionOptions"></el-option>
</el-select>
</search-item>
<search-item label="提案名称">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案名称"
v-model="pageForm.name"
style="width: 100%"
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案名称"
v-model="pageForm.name"
style="width: 100%"
></el-input>
</search-item>
<search-item label="提案编码">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案编码"
v-model="pageForm.code"
style="width: 100%"
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案编码"
v-model="pageForm.code"
style="width: 100%"
></el-input>
</search-item>
<search-item label="提案人姓名">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人姓名"
v-model="pageForm.createUserName"
style="width: 100%"
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人姓名"
v-model="pageForm.createUserName"
style="width: 100%"
></el-input>
</search-item>
<search-item label="提案人工号">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人工号"
v-model="pageForm.createUserLoginName"
style="width: 100%"
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人工号"
v-model="pageForm.createUserLoginName"
style="width: 100%"
></el-input>
</search-item>
<search-item label="代表团">
<el-select clearable filterable placeholder="所属代表团" v-model="pageForm.delegationId">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in delegationOptions"></el-option>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in delegationOptions"></el-option>
</el-select>
</search-item>
<search-item label="提案分工会">
<el-select clearable filterable placeholder="分工会" v-model="pageForm.unionId" @change="pageForm.unitId=null;listUnit();">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unionOptions"></el-option>
<el-select clearable filterable placeholder="分工会" v-model="pageForm.unionId"
@change="pageForm.unitId=null;listUnit();">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unionOptions"></el-option>
</el-select>
</search-item>
<search-item label="提案单位">
<el-select clearable filterable placeholder="提案单位" v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitOptions"></el-option>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in unitOptions"></el-option>
</el-select>
</search-item>
<search-item label="承办单位">
<el-select clearable filterable placeholder="承办单位" v-model="pageForm.undertakeUnitId">
<el-option :key="item.code" :label="item.name" :value="item.id" v-for="item in underTakeOptions"></el-option>
<el-option :key="item.code" :label="item.name" :value="item.id"
v-for="item in underTakeOptions"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">提案类别</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">提案类别</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
>
{{ item.name }}
</el-tag>
</div>
</div>
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">立案结果</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">立案结果</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
>
{{ item.label }}
</el-tag>
@@ -106,9 +113,12 @@ layout("/layouts/platform.html"){
<el-card shadow="never">
<table-tool>
<el-button type="primary" size="small" @click="exportAllProposalAsZip">导出全部提案压缩包</el-button>
<el-button type="primary" size="small" @click="exportAllProposalFeedBackAsZip">导出全部提案反馈表压缩包</el-button>
<el-button type="primary" size="small" @click="exportAllProposalFeedBackAsZip">
导出全部提案反馈表压缩包
</el-button>
<el-button type="primary" size="small" @click="exportProposalSummaryAsExcel">导出汇总表</el-button>
<el-button type="primary" size="small" @click="exportProposalRegisterSummaryAsExcel">导出立案汇总表</el-button>
<el-button type="primary" size="small" @click="exportProposalRegisterSummaryAsExcel">导出立案汇总表
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"></el-table-column>
@@ -120,7 +130,8 @@ layout("/layouts/platform.html"){
<el-table-column label="代表团" prop="delegationName"></el-table-column>
<el-table-column label="立案结果" prop="caseFilingResult">
<template scope="{row}">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT" :value="row.caseFilingResult"></dict-tag>
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="row.caseFilingResult"></dict-tag>
</template>
</el-table-column>
<el-table-column label="是否并案" prop="isConsolidation">
@@ -131,7 +142,8 @@ layout("/layouts/platform.html"){
</el-table-column>
<el-table-column label="主办单位" prop="masterUnderTakeName" show-overflow-tooltip></el-table-column>
<el-table-column label="协办单位" prop="slaveUnderTakeNames" show-overflow-tooltip></el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName" show-overflow-tooltip></el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName"
show-overflow-tooltip></el-table-column>
<el-table-column label="操作" fixed="right" width="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
@@ -156,7 +168,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -179,7 +191,7 @@ layout("/layouts/platform.html"){
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
exportAllProposalAsZip() {
@@ -193,7 +205,7 @@ layout("/layouts/platform.html"){
})
},
exportDocx(id) {
this.$downLoad("/platform/proposal/common/exportProposalAsDocx", { id })
this.$downLoad("/platform/proposal/common/exportProposalAsDocx", {id})
},
exportProposalSummaryAsExcel() {
this.$downLoad("/platform/proposal/export/comprehensive/exportProposalSummaryAsExcel", {
@@ -228,7 +240,7 @@ layout("/layouts/platform.html"){
this.listDelegation()
},
listDelegation() {
this.$axios.post("/platform/proposal/common/listDelegation", { sessionId: this.pageForm.sessionId }).then((res) => {
this.$axios.post("/platform/proposal/common/listDelegation", {sessionId: this.pageForm.sessionId}).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
}
@@ -72,28 +72,28 @@ layout("/layouts/platform.html"){
</el-card>
<el-card shadow="never">
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">提案类别</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">提案类别</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
>
{{ item.name }}
</el-tag>
</div>
</div>
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">征集状态</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">立案结果</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in collectOptions"
:key="item.code"
:effect="pageForm.collectIds && pageForm.collectIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('collectIds',item.id)"
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
>
{{ item.name }}
{{ item.label }}
</el-tag>
</div>
</div>
@@ -132,7 +132,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -145,7 +145,7 @@ layout("/layouts/platform.html"){
unitOptions: [],
pageForm: {
typeIds: [],
collectIds: [],
caseFilingResults: [],
unionId: null,
unitId: null
}
@@ -154,7 +154,7 @@ layout("/layouts/platform.html"){
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
tagToggle(key, val) {
@@ -68,35 +68,35 @@ layout("/layouts/platform.html"){
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitOptions"></el-option>
</el-select>
</search-item>
<search-item label="承办单位">
<el-select clearable filterable placeholder="承办单位" v-model="pageForm.undertakeUnitId">
<el-option :key="item.code" :label="item.name" :value="item.id" v-for="item in underTakeOptions"></el-option>
</el-select>
</search-item>
<!-- <search-item label="承办单位">-->
<!-- <el-select clearable filterable placeholder="承办单位" v-model="pageForm.undertakeUnitId">-->
<!-- <el-option :key="item.code" :label="item.name" :value="item.id" v-for="item in underTakeOptions"></el-option>-->
<!-- </el-select>-->
<!-- </search-item>-->
</search>
</el-card>
<el-card shadow="never">
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">提案类别</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">提案类别</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
>
{{ item.name }}
</el-tag>
</div>
</div>
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">立案结果</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">立案结果</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
>
{{ item.label }}
</el-tag>
@@ -123,9 +123,15 @@ layout("/layouts/platform.html"){
<el-tag size="mini" v-else type="danger"></el-tag>
</template>
</el-table-column>
<el-table-column label="主办单位" prop="masterUnderTakeName" show-overflow-tooltip></el-table-column>
<el-table-column label="协办单位" prop="slaveUnderTakeNames" show-overflow-tooltip></el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName" show-overflow-tooltip></el-table-column>
<el-table-column label="主办单位" prop="masterUnitName" show-overflow-tooltip></el-table-column>
<el-table-column label="协办单位" prop="slaveUnitNames" show-overflow-tooltip></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="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
@@ -150,7 +156,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -171,7 +177,7 @@ layout("/layouts/platform.html"){
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
exportDocx(id) {
@@ -88,7 +88,7 @@ layout("/layouts/platform.html"){
},
components: {
"proposal-table": PROPOSAL_TABLE,
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
methods: {
openView(row) {
@@ -102,7 +102,7 @@ layout("/layouts/platform.html"){
viewSingleProposal(row) {
this.proposalInfoVisible = true
this.$nextTick(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
listSession() {
@@ -9,7 +9,7 @@ const PROPOSAL_TABLE = {
<el-table-column label="提案类别" prop="typeName"></el-table-column>
<el-table-column label="届次" prop="sessionName"></el-table-column>
<el-table-column label="代表团" prop="delegationName"></el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName"></el-table-column>
<el-table-column label="当前节点" prop="curTaskName"></el-table-column>
<el-table-column label="操作" fixed="right" width="100px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="$emit('view-single-proposal',row)">查看</el-button>
@@ -68,35 +68,35 @@ layout("/layouts/platform.html"){
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in unitOptions"></el-option>
</el-select>
</search-item>
<search-item label="承办单位">
<el-select clearable filterable placeholder="承办单位" v-model="pageForm.undertakeUnitId">
<el-option :key="item.code" :label="item.name" :value="item.code" v-for="item in underTakeOptions"></el-option>
</el-select>
</search-item>
<!-- <search-item label="承办单位">-->
<!-- <el-select clearable filterable placeholder="承办单位" v-model="pageForm.undertakeUnitId">-->
<!-- <el-option :key="item.code" :label="item.name" :value="item.code" v-for="item in underTakeOptions"></el-option>-->
<!-- </el-select>-->
<!-- </search-item>-->
</search>
</el-card>
<el-card shadow="never">
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">提案类别</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">提案类别</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
>
{{ item.name }}
</el-tag>
</div>
</div>
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">立案结果</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">立案结果</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
>
{{ item.label }}
</el-tag>
@@ -123,7 +123,15 @@ layout("/layouts/platform.html"){
<el-tag size="mini" v-else type="danger"></el-tag>
</template>
</el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName" show-overflow-tooltip></el-table-column>
<el-table-column label="主办单位" prop="masterUnitName" show-overflow-tooltip></el-table-column>
<el-table-column label="协办单位" prop="slaveUnitNames" show-overflow-tooltip></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="200px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
@@ -148,7 +156,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -169,7 +177,7 @@ layout("/layouts/platform.html"){
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
exportDocx(id) {
@@ -44,7 +44,7 @@ layout("/layouts/platform.html"){
el: "#app",
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -77,26 +77,26 @@ layout("/layouts/platform.html"){
</el-card>
<el-card shadow="never">
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">提案类别</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">提案类别</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
v-for="item in typeOptions"
:key="item.code"
:effect="pageForm.typeIds && pageForm.typeIds.includes(item.id) ? 'dark':'plain'"
@click="tagToggle('typeIds',item.id)"
>
{{ item.name }}
</el-tag>
</div>
</div>
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<div style="width: 90px">立案结果</div>
<div style="flex: auto">
<div style="width: 90px;margin-right: 10px">立案结果</div>
<div style="flex: 1;display: flex;gap: 5px;">
<el-tag
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"
:key="item.code"
:effect="pageForm.caseFilingResults && pageForm.caseFilingResults.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingResults',item.code)"
>
{{ item.label }}
</el-tag>
@@ -107,8 +107,8 @@ layout("/layouts/platform.html"){
<table-tool>
<el-button type="primary" size="small" @click="exportYearReport">导出提案报告</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" size="small" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" type="index" :index="indexMethod"></el-table-column>
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" width="50px" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="提案编号" prop="code" width="200px"></el-table-column>
<el-table-column label="提案名称" prop="name"></el-table-column>
<el-table-column label="提案人" prop="createUserName"></el-table-column>
@@ -152,7 +152,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -173,7 +173,7 @@ layout("/layouts/platform.html"){
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
exportYearReport() {
@@ -171,7 +171,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -193,12 +193,11 @@ layout("/layouts/platform.html"){
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
onOpenEdit(row) {
this.$refs.guava.edit()
this.$nextTick(() => {
this.$refs.guava.edit(()=>{
this.formData = { ...row }
})
},
@@ -73,8 +73,8 @@ layout("/layouts/platform.html"){
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" size="small" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" type="index" :index="indexMethod"></el-table-column>
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="提案编号" prop="code" width="200px"></el-table-column>
<el-table-column label="提案名称" prop="name"></el-table-column>
<el-table-column label="提案人" prop="createUserName"></el-table-column>
@@ -116,7 +116,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -73,8 +73,8 @@ layout("/layouts/platform.html"){
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" size="small" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" type="index" :index="indexMethod"></el-table-column>
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%" row-key="id">
<el-table-column label="序号" width="50px" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="提案编号" prop="code" width="200px"></el-table-column>
<el-table-column label="提案名称" prop="name">
<template scope="{row}">
@@ -112,7 +112,7 @@ layout("/layouts/platform.html"){
</template>
</guava>
<el-dialog title="修改提案类" :close-on-click-modal="false" width="40%" :visible.sync="typeDialog">
<el-dialog title="修改提案类" :close-on-click-modal="false" width="40%" :visible.sync="typeDialog">
<el-form :model="formData" ref="form" label-width="120px">
<el-form-item prop="oldTypeName" label="原类型">
<el-input disabled :value="formData.oldTypeName" type="text"></el-input>
@@ -138,7 +138,7 @@ layout("/layouts/platform.html"){
store,
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO_COMPONENT
"proposal-info": PROPOSAL_INFO
},
data() {
return {
@@ -162,8 +162,7 @@ layout("/layouts/platform.html"){
methods: {
onOpen(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.showApprovalForm = false
this.$refs.infoRef.onOpen(row)
})
},
onOpenEdit(row) {
@@ -186,7 +186,8 @@ layout("/layouts/platform.html"){
...this.formData,
submitType: val,
tf_hostUnitName: this.formData.tf_hostUnitId ? this.underTakeOptions.find(v => v.id === this.formData.tf_hostUnitId)?.name : null,
tf_helpUnitNames: this.formData.tf_helpUnitIds.map(v => this.underTakeOptions.find(v2 => v2.id === v)?.name)
tf_helpUnitNames: this.formData.tf_helpUnitIds.map(v => this.underTakeOptions.find(v2 => v2.id === v)?.name),
tf_helpUnitNameStr: this.formData.tf_helpUnitIds.map(v => this.underTakeOptions.find(v2 => v2.id === v)?.name).join(','),
})
}).then((res) => {
if (res.code === 0) {
@@ -7,11 +7,14 @@ layout("/layouts/platform.html"){
<el-card shadow="never">
<search @search="doSearch">
<search-item label="提案名称">
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable style="width: 100%"></el-input>
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
style="width: 100%"></el-input>
</search-item>
<search-item label="教代会">
<el-select @change="meetingChange" clearable filterable placeholder="所属教代会" v-model="pageForm.sessionId">
<el-option :key="item.id" :label="item.fullName" :value="item.id" v-for="item in sessionOptions"></el-option>
<el-select @change="meetingChange" clearable filterable placeholder="所属教代会"
v-model="pageForm.sessionId">
<el-option :key="item.id" :label="item.fullName" :value="item.id"
v-for="item in sessionOptions"></el-option>
</el-select>
</search-item>
</search>
@@ -113,22 +116,25 @@ layout("/layouts/platform.html"){
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
this.$refs.formRef.validate(valid => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
@@ -146,10 +152,42 @@ layout("/layouts/platform.html"){
}
})
})
},
// 教代会
async meetingChange(val) {
this.formData.delegationId = null
this.formData.committeeId = null
this.listDelegation()
},
// 代表团
listDelegation() {
this.$axios.post("/platform/proposal/common/listDelegation", {sessionId: this.pageForm.sessionId}).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
}
})
},
// 查询开启的教代会
listOpenSession() {
this.$axios.post("/platform/proposal/common/listOpenSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
if (this.sessionOptions) {
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].id)
this.pageData()
this.listDelegation()
}
}
})
}
},
created() {
this.pageData()
this.listOpenSession()
}
})
</script>
@@ -91,7 +91,7 @@ layout("/layouts/platform.html"){
methods: {
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row.id)
this.$refs.infoRef.onOpen(row)
})
},
openEdit(row) {
@@ -8,7 +8,8 @@ const PROPOSAL_INVITE_SECONDER_COMPONENT = {
clearable></el-input>
</el-col>
<el-col :span="6">
<el-select clearable filterable placeholder="所属代表团" v-model="pageForm.delegationId">
<el-select clearable filterable placeholder="所属代表团" v-model="pageForm.delegationId"
style="width: 100%">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in delegationOptions"></el-option>
</el-select>
@@ -27,10 +28,10 @@ const PROPOSAL_INVITE_SECONDER_COMPONENT = {
<el-radio-button :label="false">可邀请</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" ref="tableRef" @sort-change="pageOrder" size="small" header-align="center"
<el-table :data="tableData" ref="tableRef" @sort-change="pageOrder" header-align="center"
style="width: 100%" :row-key="getRowKey">
<el-table-column type="selection" reserve-selection v-if="!pageForm.isInvite"></el-table-column>
<el-table-column label="序号" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="序号" width="50px" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="工号" prop="loginName"></el-table-column>
<el-table-column label="姓名" prop="userName"></el-table-column>
<el-table-column label="性别" prop="sex"></el-table-column>
@@ -95,6 +96,7 @@ const PROPOSAL_INVITE_SECONDER_COMPONENT = {
this.$message.warning("请先选择附议人后在点击邀请")
return
}
const loginNames = selection.map((s) => s.loginName)
const userName = selection.map((s) => s.userName)
this.$confirm("您确定要邀请" + userName.join("、") + "代表附议吗?", "提示", {
@@ -117,18 +119,16 @@ const PROPOSAL_INVITE_SECONDER_COMPONENT = {
})
},
pageData() {
this.$axios
.post(loc() + "/listSeconder", {
...this.pageForm,
sessionId: this.record.sessionId,
proposalId: this.record.id
})
.then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
this.$axios.post("/platform/proposal/mine/listSeconder", {
...this.pageForm,
sessionId: this.record.sessionId,
proposalId: this.record.id
}).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
//查询代表团
@@ -7,11 +7,14 @@ layout("/layouts/platform.html"){
<el-card shadow="never">
<search @search="doSearch">
<search-item label="提案名称">
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable style="width: 100%"></el-input>
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
style="width: 100%"></el-input>
</search-item>
<search-item label="教代会">
<el-select @change="meetingChange" clearable filterable placeholder="所属教代会" v-model="pageForm.sessionId">
<el-option :key="item.id" :label="item.fullName" :value="item.id" v-for="item in sessionOptions"></el-option>
<el-select @change="meetingChange" clearable filterable placeholder="所属教代会"
v-model="pageForm.sessionId">
<el-option :key="item.id" :label="item.fullName" :value="item.id"
v-for="item in sessionOptions"></el-option>
</el-select>
</search-item>
</search>
@@ -29,8 +32,9 @@ layout("/layouts/platform.html"){
<el-table-column label="提案编号" prop="code"></el-table-column>
<el-table-column label="提案名称" prop="name" show-overflow-tooltip></el-table-column>
<el-table-column label="提案类别" prop="typeName"></el-table-column>
<el-table-column label="届次" prop="sessionName"></el-table-column>
<el-table-column label="提案人" prop="createUserName"></el-table-column>
<el-table-column label="代表团" prop="delegationName"></el-table-column>
<el-table-column label="附议人" prop="taskActorName"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
@@ -90,7 +94,9 @@ layout("/layouts/platform.html"){
pageForm: {
approval: false
},
showApprovalForm: false
showApprovalForm: false,
sessionOptions: [],
delegationOptions: [],
}
},
methods: {
@@ -112,22 +118,25 @@ layout("/layouts/platform.html"){
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
this.$refs.formRef.validate(valid => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/flow/common/executeTask", {
data: JSON.stringify({
...this.formData,
submitType: val
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
}).then((res) => {
if (res.code === 0) {
this.$refs.guava.index()
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
@@ -145,10 +154,42 @@ layout("/layouts/platform.html"){
}
})
})
},
// 教代会
async meetingChange(val) {
this.formData.delegationId = null
this.formData.committeeId = null
this.listDelegation()
},
// 代表团
listDelegation() {
this.$axios.post("/platform/proposal/common/listDelegation", {sessionId: this.pageForm.sessionId}).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
}
})
},
// 查询开启的教代会
listOpenSession() {
this.$axios.post("/platform/proposal/common/listOpenSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
if (this.sessionOptions) {
this.$set(this.pageForm, "sessionId", this.sessionOptions[0].id)
this.pageData()
this.listDelegation()
}
}
})
}
},
created() {
this.pageData()
this.listOpenSession()
}
})
</script>
@@ -54,11 +54,11 @@ layout("/layouts/platform.html"){
<el-table-column label="提案编号" prop="code"></el-table-column>
<el-table-column label="提案名称" prop="name" show-overflow-tooltip></el-table-column>
<el-table-column label="提案类别" prop="typeName"></el-table-column>
<el-table-column label="届次" prop="sessionName"></el-table-column>
<el-table-column label="代表团" prop="delegationName"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="taskName" label="承办类型"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<el-table-column label="当前节点" prop="curTaskName"></el-table-column>
<el-table-column label="承办单位" prop="taskUnitName"></el-table-column>
<el-table-column label="承办类型" prop="taskName"></el-table-column>
<el-table-column label="流程状态" prop="instanceState">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
@@ -85,7 +85,7 @@ layout("/layouts/platform.html"){
</div>
<el-form :model="formData" ref="formRef" label-width="120px" :rules="formRules" label-suffix="">
<el-form-item label="承办单位">
<el-input :value="formData.underTakeName" disabled></el-input>
<el-input :value="formData.taskUnitName" disabled></el-input>
</el-form-item>
<!-- <el-form-item label="落实情况" prop="implementState" :rules="[{required:true,message:'必填',trigger:['change','blur']}]">-->
<!-- <dict-select v-model="formData.implementState" code="PROPOSAL_REPLY_IMPLEMENT"></dict-select>-->
@@ -95,7 +95,8 @@ layout("/layouts/platform.html"){
<text-editor v-model="formData.tf_opinion"></text-editor>
</el-form-item>
<el-form-item label="校领导" prop="tf_nextNodeOperator"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
:rules="[{required:true,message:'必填',trigger:['change','blur']}]"
v-if="supportCandidate && formData.taskIsMaster">
<el-select v-model="formData.tf_nextNodeOperator" placeholder="请选择校领导">
<el-option :key="item.id" :label="item.userName" :value="item.userId"
v-for="item in candidates"></el-option>
@@ -146,15 +147,14 @@ layout("/layouts/platform.html"){
openAudit(row) {
this.loadCandidates(row.taskId)
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskKey: row.taskKey,
taskName: row.taskName,
hostUnitId: null,
helpUnitIds: []
taskUnitName: row.taskUnitName,
taskIsMaster: row.taskIsMaster
}
this.$refs.proposalInfoRef.onOpen(row)
})