This commit is contained in:
=
2025-10-15 10:51:22 +08:00
parent c20d5378e6
commit 0ec3a356b5
68 changed files with 4486 additions and 1091 deletions
@@ -58,6 +58,7 @@ public class FlowDefineController {
ProcessDefine define = dao.fetch(ProcessDefine.class, Cnd.where(ProcessDefine::getName, "=", defineKey).desc(ProcessDefine::getVersion));
if (define != null) {
request.setAttribute("defineId", define.getId());
request.setAttribute("showImg", true);
}
}
@@ -0,0 +1,99 @@
package com.budwk.app.zhgh.dayofficework.fund.controller;
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.dayofficework.fund.models.FundMember;
import com.budwk.app.zhgh.dayofficework.fund.service.FundMemberService;
import io.swagger.annotations.Api;
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;
@IocBean
@At("/platform/fundMember/branchUnionApproval")
@Ok("json:full")
@Api("基金会员-分工会审核")
public class FundMemberBranchUnionApprovalController {
@Inject
private FundMemberService fundMemberService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/fundMember/branchUnionApproval/index.html")
@SaCheckPermission("fundMember.branchUnionApproval")
public void index() {
}
@At
@SaCheckPermission("fundMember.branchUnionApproval")
public Result pageData(PageForm pageForm, String taskId, String searchKeyword, Integer year, 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 fund_member 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", "=", "fgh");
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());
}
if (StrUtil.isNotBlank(searchKeyword)) {
cnd.where().andLike("info.title", searchKeyword);
}
cnd.groupBy("t.id");
cnd.desc("t.createdAt");
sql.setCondition(cnd);
Pagination<NutMap> pagination = fundMemberService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
}
@@ -0,0 +1,94 @@
package com.budwk.app.zhgh.dayofficework.fund.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
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.vo.ProcessTaskVO;
import com.budwk.app.zhgh.dayofficework.fund.models.FundMember;
import com.budwk.app.zhgh.dayofficework.fund.service.FundMemberService;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
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 javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@IocBean
@At("/platform/fundMember/common")
@Ok("json:full")
@Api(tags = "基金会员-公共")
@Slf4j
public class FundMemberCommonController {
@Inject
private Dao dao;
@Inject
private FundMemberService fundMemberService;
@Inject
private FlowEngine flowEngine;
@Inject
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
@At
@SaCheckPermission("fundMember")
public Result info(@Valid String id) {
FundMember fundMember = fundMemberService.fetch(id);
return Result.success(fundMember);
}
@At
@SaCheckPermission("fundMember")
@Ok("void")
@ApiOperation("导出申请表")
public void exportDocx(@Valid String id, HttpServletResponse response) {
FundMember fundMember = dao.fetch(FundMember.class, id);
Map<String, Object> docData = BeanUtil.beanToMap(fundMember);
docData.put("birthday", DateUtil.format(fundMember.getBirthday(), "yyyy年MM月dd日"));
docData.put("joinWorkTime", DateUtil.format(fundMember.getJoinWorkTime(), "yyyy年MM月dd日"));
docData.put("retireTime", DateUtil.format(fundMember.getRetireTime(), "yyyy年MM月dd日"));
// 流程实例
ProcessInstance processInstance = dao.fetch(ProcessInstance.class, Cnd.where(ProcessInstance::getBusinessNo, "=", id));
List<ProcessTaskVO> doneTaskVos = new ArrayList<>();
List<ProcessTask> doneTaskList = flowEngine.processTaskService().getDoneTaskList(processInstance.getId(), null);
for (ProcessTask doneTask : doneTaskList) {
ProcessTaskVO taskVO = flowEngine.processTaskService().findById(doneTask.getId());
doneTaskVos.add(taskVO);
}
// 按任务节点分组
Map<String, List<ProcessTaskVO>> taskGroups = doneTaskVos.stream().collect(Collectors.groupingBy(ProcessTaskVO::getDisplayName));
docData.putAll(taskGroups);
Configure configure = Configure.builder().build();
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
XWPFTemplate.compile(sysOfficeTemplateUtil.getTemplate("fundMember"), configure).render(docData).writeAndClose(byteArrayOutputStream);
CommonDownloadUtil.download(fundMember.getUserName() + "的医疗互助“爱心”基金入会申请表.docx", byteArrayOutputStream.toByteArray(), response);
} catch (Exception e) {
log.error("导出word异常", e);
}
}
}
@@ -0,0 +1,96 @@
package com.budwk.app.zhgh.dayofficework.fund.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
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.flow.engine.FlowEngine;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.fund.models.FundMember;
import com.budwk.app.zhgh.dayofficework.fund.service.FundMemberService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.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;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
@IocBean
@At("/platform/fundMember/mine")
@Ok("json:full")
@Api("基金会员-我的申请")
public class FundMemberMineController {
@Inject
private Dao dao;
@Inject
private FlowEngine flowEngine;
@Inject
private FundMemberService fundMemberService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/fundMember/mine/index.html")
@SaCheckPermission("fundMember.mine")
public void index() {
}
@At
@SaCheckPermission("fundMember.mine")
public Result pageData(Integer pageNumber, Integer pageSize, String searchKeyword, Integer year) {
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
fund_member 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());
sql.setCondition(cnd);
Pagination<NutMap> pagination = fundMemberService.listPageMap(pageNumber, pageSize, sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("fundMember.mine")
@Aop(TransAop.READ_COMMITTED)
@ApiOperation("删除")
@SLog(tag = "基金会员-我的申请", msg = "删除")
public Result delete(@Param("id") String id) {
dao.delete(FundMember.class, id);
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
return Result.success();
}
}
@@ -0,0 +1,83 @@
package com.budwk.app.zhgh.dayofficework.fund.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
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.fund.service.FundMemberService;
import io.swagger.annotations.Api;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
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 javax.servlet.http.HttpServletResponse;
@IocBean
@At("/platform/fundMember/query")
@Ok("json:full")
@Api(tags = "基金会员-查询")
public class FundMemberQueryController {
@Inject
private FundMemberService fundMemberService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/fundMember/query/index.html")
@SaCheckPermission("fundMember.query")
public void index() {
}
@At
@SaCheckPermission("fundMember.query")
public Result pageData(PageForm pageForm, Integer year) {
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
FROM
fund_member 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();
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.orLike("info.userName", pageForm.getSearchKeyword());
seg.orLike("info.loginName", pageForm.getSearchKeyword());
cnd.and(seg);
}
cnd.andEX("YEAR(info.submitTime)", "=", year);
sql.setCondition(cnd);
Pagination pagination = fundMemberService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("fundMember.query")
@Ok("void")
public void exportExcel(Integer year, HttpServletResponse response) {
}
}
@@ -0,0 +1,97 @@
package com.budwk.app.zhgh.dayofficework.fund.controller;
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.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.dayofficework.fund.service.FundMemberService;
import io.swagger.annotations.Api;
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;
@IocBean
@At("/platform/fundMember/schoolUnionApproval")
@Ok("json:full")
@Api("基金会员-校工会审核")
public class FundMemberSchoolUnionApprovalController {
@Inject
private FundMemberService fundMemberService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/fundMember/schoolUnionApproval/index.html")
@SaCheckPermission("fundMember.schoolUnionApproval")
public void index() {
}
@At
@SaCheckPermission("fundMember.schoolUnionApproval")
public Result pageData(PageForm pageForm, String taskId, String searchKeyword, Integer year, 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 fund_member 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", "=", "xgh");
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());
}
if (StrUtil.isNotBlank(searchKeyword)) {
cnd.where().andLike("info.title", searchKeyword);
}
cnd.groupBy("t.id");
cnd.desc("t.createdAt");
sql.setCondition(cnd);
Pagination<NutMap> pagination = fundMemberService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
}
@@ -0,0 +1,106 @@
package com.budwk.app.zhgh.dayofficework.fund.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.lang.Dict;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.result.Result;
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.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.fund.models.FundMember;
import com.budwk.app.zhgh.democratic.suggestionBox.models.SuggestionBox;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Dao;
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 java.util.Date;
import java.util.List;
@IocBean
@At("/platform/fundMember/write")
@Ok("json:full")
@Api(tags = "基金会员申请")
public class FundMemberWriteController {
@Inject
private Dao dao;
@Inject
private FlowEngine flowEngine;
@Inject
private FlowCommonService flowCommonService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/fundMember/write/index.html")
@SaCheckPermission("fundMember.write")
public void index() {
}
@At
@SaCheckPermission("fundMember.write")
@ApiOperation("保存申请")
@SLog(tag = "建言献策-填写申请", msg = "保存申请")
public Result save(@Param("data") FundMember fundMember) {
dao.insertOrUpdate(fundMember);
return Result.success();
}
@At
@SaCheckPermission("fundMember.write")
@ApiOperation("提交申请")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "基金会员-填写申请", msg = "提交申请")
public Result submit(@Param("data") FundMember fundMember) {
fundMember.setSubmitTime(new Date());
dao.insertOrUpdate(fundMember);
// 开启流程实例
Dict args = Dict.create();
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
args.set(FlowConst.FORM_DATA, fundMember);
ProcessInstance instance = flowEngine.startProcessInstanceByKey("FUND_MEMBER", fundMember.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
@SaCheckPermission("fundMember.write")
@ApiOperation("重新提交申请")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "基金会员-填写申请", msg = "重新提交申请")
public Result submitAgain(@Param("data") FundMember fundMember, @Param("taskId") Long taskId) {
dao.insertOrUpdate(fundMember);
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("fundMember.write")
@ApiOperation("获取申请信息")
public Result info(@Param("id") String id) {
FundMember box = dao.fetch(FundMember.class, id);
return Result.success(box);
}
}
@@ -0,0 +1,90 @@
package com.budwk.app.zhgh.dayofficework.fund.models;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.util.Date;
@Data
@Table("fund_member")
@EqualsAndHashCode(callSuper = true)
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("基金会员")
public class FundMember extends BaseModel {
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("姓名")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String userName;
@Column
@Comment("工资号")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String loginName;
@Column
@Comment("性别")
@ColDefine(type = ColType.VARCHAR, width = 10)
private String sex;
@Column
@Comment("出生日期")
@ColDefine(type = ColType.DATE)
private Date birthday;
@Column
@Comment("身份证号")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String idCard;
@Column
@Comment("参加工作时间")
@ColDefine(type = ColType.DATE)
private Date joinWorkTime;
@Column
@Comment("退休时间")
@ColDefine(type = ColType.DATE)
private Date retireTime;
@Column
@Comment("家庭住址")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String address;
@Column
@Comment("手机号码")
@ColDefine(type = ColType.VARCHAR, width = 20)
private String mobile;
@Column
@Comment("住宅号码")
@ColDefine(type = ColType.VARCHAR, width = 20)
private String homePhone;
@Column
@Comment("照片")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String avatar;
@Column
@Comment("加入、退出")
@ColDefine(type = ColType.BOOLEAN)
@Default("1")
private Boolean isJoin;
@Column
@Comment("提交时间")
@ColDefine(type = ColType.DATETIME)
private Date submitTime;
}
@@ -0,0 +1,7 @@
package com.budwk.app.zhgh.dayofficework.fund.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.dayofficework.fund.models.FundMember;
public interface FundMemberService extends BaseService<FundMember> {
}
@@ -0,0 +1,14 @@
package com.budwk.app.zhgh.dayofficework.fund.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.dayofficework.fund.models.FundMember;
import com.budwk.app.zhgh.dayofficework.fund.service.FundMemberService;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean(args = {"refer:dao"})
public class FundMemberServiceImpl extends BaseServiceImpl<FundMember> implements FundMemberService {
public FundMemberServiceImpl(Dao dao) {
super(dao);
}
}
@@ -0,0 +1,216 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.model.ExcelImportRes;
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.CommonDownloadUtil;
import com.budwk.app.base.utils.EasyExcelUtil;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.zhgh.dayofficework.healthCheckup.template.HealthCheckupImportTemp;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsBatch;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsLedger;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.service.RetireSouvenirsBatchService;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.template.RetireSouvenirsImportTemp;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.Workbook;
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;
import org.nutz.lang.Strings;
import org.nutz.mvc.annotation.AdaptBy;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import org.nutz.mvc.upload.TempFile;
import org.nutz.mvc.upload.UploadAdaptor;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @ClassName RetireSouvenirsBatchController
* @Author JyuHsin
* @Date 2025/10/14 9:51
* @Version 1.0
* @Description TODO
*/
@IocBean
@Ok("json:full")
@ApiOperation("批次管理")
@At("/platform/retireSouvenirs/batch")
public class RetireSouvenirsBatchController {
@Inject
private Dao dao;
@Inject
private RetireSouvenirsBatchService batchService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/retiresouvenirs/batch/index.html")
@SaCheckPermission("retireSouvenirs.batch")
public void index() {
}
@At
@ApiOperation("分页查询")
@SaCheckPermission("retireSouvenirs.batch")
public Result pageData(PageForm pageForm,
@Param(value = "year") Integer year) {
Sql sql = Sqls.create("""
select
b.*,
u.username as userName,
(select count(1) from retire_souvenirs_ledger where batchId = b.id) as count
from
retire_souvenirs_batch b
left join vw_user u on u.id = b .createdBy
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("b.year", "=", year);
cnd.and(Cnd.likeEX("b.name", pageForm.getSearchKeyword()));
sql.setCondition(cnd);
Pagination pagination = batchService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@ApiOperation("新增/修改批次")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retireSouvenirs.batch")
@SLog(tag = "退休人员纪念品-批次管理", msg = "新增/修改批次")
public Result submit(RetireSouvenirsBatch batch) {
batchService.insertOrUpdate(batch);
return Result.success();
}
@At
@ApiOperation("删除批次")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retireSouvenirs.batch")
@SLog(tag = "退休人员纪念品-批次管理", msg = "删除批次")
public Result delete(String id) {
batchService.delete(id);
batchService.dao().clear(RetireSouvenirsLedger.class, Cnd.where(RetireSouvenirsLedger::getBatchId, "=", id));
return Result.success();
}
@At
@ApiOperation("查询批次")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retireSouvenirs")
public Result selectList() {
List<RetireSouvenirsBatch> list = batchService.query(Cnd.NEW().desc(RetireSouvenirsBatch::getCreatedAt));
return Result.success(list);
}
@At
@Ok("void")
@ApiOperation("下载人员名单导入模版")
@SaCheckPermission("retireSouvenirs.batch")
public void downloadTem(HttpServletResponse response) {
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号", "loginName", 20));
entities.add(new ExcelExportEntity("姓名", "userName", 20));
entities.add(new ExcelExportEntity("退休时间", "retireTime", 20));
ExportParams exportParams = new ExportParams();
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, Collections.emptyList());
CommonDownloadUtil.download("退休人员名单导入模版.xlsx", workbook, response);
}
@At
@ApiOperation("退休人员名单导入")
@SLog(tag = "退休人员纪念品-批次管理", msg = "人员名单导入")
@SaCheckPermission("retireSouvenirs.batch")
@Aop(TransAop.READ_COMMITTED)
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
public Result temImport(TempFile file, String batchId, String type) {
if(StrUtil.isBlank(batchId)) {
return Result.error("批次信息为空");
}
if("clear".equals(type)) {
dao.clear(RetireSouvenirsLedger.class, Cnd.where(RetireSouvenirsLedger::getBatchId, "=", batchId));
}
List<T> ts = EasyExcelUtil.syncReadModel(file.getFile(), RetireSouvenirsImportTemp.class, 0, 1);
List<RetireSouvenirsImportTemp> importTemps = JSONUtil.parseArray(JSONUtil.toJsonStr(ts)).toList(RetireSouvenirsImportTemp.class);
List<String> loginNames = importTemps.stream().map(RetireSouvenirsImportTemp::getLoginName).filter(Strings::isNotBlank).toList();
List<View_user> userList = dao.query(View_user.class, Cnd.where(View_user::getLoginname, "in", loginNames));
Map<String, View_user> userMap = userList.stream().collect(Collectors.toMap(View_user::getLoginname, o -> o));
String[] patterns = {
"yyyy-MM-dd",
"yyyy/MM/dd",
"yyyy-MM",
"yyyy/MM",
"yyyyMM",
"yyyyMMdd",
"yyyy年MM月dd日",
"yyyy年M月d日"
};
List<RetireSouvenirsLedger> result = new ArrayList<>();
for (int i = 0; i < importTemps.size(); i++) {
RetireSouvenirsImportTemp temp = importTemps.get(i);
if (StrUtil.isBlank(temp.getLoginName())) {
temp.setErrInfo("工号为空", i + 1);
continue;
}
if (importTemps.stream().filter(s -> s.getLoginName().equals(temp.getLoginName())).count() > 1) {
temp.setErrInfo("重复数据", i + 1);
}
View_user user = userMap.get(temp.getLoginName());
if (user == null) {
temp.setErrInfo("无此用户", i + 1);
continue;
}
DateTime retireTime = DateUtil.parse(temp.getRetireTime(), patterns);
String format = DateUtil.format(retireTime, DatePattern.NORM_DATE_PATTERN);
RetireSouvenirsLedger ledger = new RetireSouvenirsLedger();
ledger.setBatchId(batchId);
ledger.setUserId(user.getId());
ledger.setReceive(false);
ledger.setRetireTime(format);
result.add(ledger);
}
dao.insert(result);
// 创建结果集
ExcelImportRes<RetireSouvenirsImportTemp> excelImportRes = new ExcelImportRes<>();
excelImportRes.setTotalRecords(importTemps.size());
excelImportRes.setSuccessCount(Math.max(result.size() - excelImportRes.getFailedCount(), 0));
// 添加错误记录
excelImportRes.setErrorDetails(importTemps.stream().filter(s -> StrUtil.isNotBlank(s.getErrMsg())).toList());
excelImportRes.setFailedCount(excelImportRes.getErrorDetails().size());
return Result.success(excelImportRes);
}
}
@@ -0,0 +1,227 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
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.utils.CommonDownloadUtil;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsLedger;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsMsg;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.service.RetireSouvenirsLedgerService;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.vo.RetireSouvenirsLedgerPageForm;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
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.entity.annotation.SQL;
import org.nutz.dao.sql.Sql;
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.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName RetireSouvenirsLedgerController
* @Author JyuHsin
* @Date 2025/10/14 9:52
* @Version 1.0
* @Description TODO
*/
@IocBean
@Ok("json:full")
@ApiOperation("人员台账")
@At("/platform/retireSouvenirs/ledger")
public class RetireSouvenirsLedgerController {
@Inject
private Dao dao;
@Inject
private RetireSouvenirsLedgerService ledgerService;
@Inject
private GlobalMessageSendService sendService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/retiresouvenirs/ledger/index.html")
@SaCheckPermission("retireSouvenirs.ledger")
public void index() {
}
@At
@ApiOperation("分页查询")
@SaCheckPermission("retireSouvenirs.ledger")
public Result pageData(RetireSouvenirsLedgerPageForm pageForm) {
Sql sql = this.generateSql(pageForm);
Pagination pagination = ledgerService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@ApiOperation("删除人员")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retireSouvenirs.ledger")
@SLog(tag = "退休人员纪念品-人员台账", msg = "删除人员")
public Result delete(String id) {
ledgerService.delete(id);
return Result.success();
}
@At
@ApiOperation("设置领取状态")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retireSouvenirs.ledger")
@SLog(tag = "退休人员纪念品-人员台账", msg = "设置领取状态")
public Result receive(String id) {
RetireSouvenirsLedger ledger = ledgerService.fetch(id);
ledger.setReceive(!ledger.getReceive());
ledgerService.update(ledger);
return Result.success();
}
@At
@ApiOperation("短信提醒")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retireSouvenirs.ledger")
@SLog(tag = "退休人员纪念品-人员台账", msg = "短信提醒")
public Result msg(@Param(value = "pageForm") RetireSouvenirsLedgerPageForm pageForm,
@Param(value = "message") String message) {
Sql sql = this.generateSql(pageForm);
List<NutMap> listMap = ledgerService.listMap(sql);
List<RetireSouvenirsMsg> msgList = listMap.stream().map(o -> {
RetireSouvenirsMsg msg = new RetireSouvenirsMsg();
msg.setBatchId(pageForm.getBatchId());
msg.setUserId(o.getString("userId"));
msg.setSendUserId(SecurityUtil.getUserId());
msg.setSendUserName(SecurityUtil.getUserUsername());
msg.setMessage(message);
msg.setSendTime(DateUtil.now());
return msg;
}).toList();
List<String> list = listMap.stream().map(o -> o.getString("loginName")).toList();
sendService.sendMessage("智慧工会", message, list);
dao.insert(msgList);
return Result.success();
}
@At
@ApiOperation("查询短信发送记录")
@SaCheckPermission("retireSouvenirs.ledger")
public Result selectMsgList(String batchId, String userId) {
Cnd cnd = Cnd.NEW();
cnd.and(RetireSouvenirsMsg::getBatchId, "=", batchId);
cnd.and(RetireSouvenirsMsg::getUserId, "=", userId);
cnd.desc(RetireSouvenirsMsg::getSendTime);
List<RetireSouvenirsMsg> list = dao.query(RetireSouvenirsMsg.class, cnd);
return Result.success(list);
}
@At
@ApiOperation("删除短信发送记录")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("retireSouvenirs.ledger")
@SLog(tag = "退休人员纪念品-人员台账", msg = "删除短信发送记录")
public Result deleteMsg(String id) {
dao.delete(RetireSouvenirsMsg.class, id);
return Result.success();
}
@At
@Ok("void")
@SaCheckPermission("retireSouvenirs.ledger")
@ApiOperation("导出退休人员名单")
public void download(RetireSouvenirsLedgerPageForm pageForm,
HttpServletResponse response) {
Sql sql = this.generateSql(pageForm);
List<NutMap> listMap = ledgerService.listMap(sql);
List<ExcelExportEntity> exportEntities = new ArrayList<>();
exportEntities.add(new ExcelExportEntity("姓名", "userName", 16));
exportEntities.add(new ExcelExportEntity("工号", "loginName", 16));
exportEntities.add(new ExcelExportEntity("性别", "sex", 10));
exportEntities.add(new ExcelExportEntity("联系方式", "mobile", 20));
exportEntities.add(new ExcelExportEntity("所属单位", "unitName", 30));
exportEntities.add(new ExcelExportEntity("所属工会", "unionName", 30));
exportEntities.add(new ExcelExportEntity("退休时间", "retireTimeFormat", 20));
exportEntities.add(new ExcelExportEntity("是否领取", "receiveStatus", 10));
exportEntities.add(new ExcelExportEntity("签字", "sign", 20));
try {
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, listMap);
CommonDownloadUtil.download("退休人员名单台账.xlsx", workbook, response);
} catch (Exception e) {
e.printStackTrace();
}
}
private Sql generateSql(RetireSouvenirsLedgerPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
l.*,
u.userName,
u.loginName,
u.sex,
u.mobile,
u.unitName,
u.unionName,
if(l.receive = true, '已领取', '未领取') as receiveStatus,
DATE_FORMAT(l.retireTime, '%Y-%m') as retireTimeFormat,
(select count(1) from retire_souvenirs_msg where batchId = l.batchId and userId = l.userId) as msgCount
FROM
retire_souvenirs_ledger l
LEFT JOIN vw_user u ON u.id = l.userId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("l.batchId", "=", pageForm.getBatchId());
cnd.andEX("year(l.retireTime)", "=", pageForm.getYear());
if("prev".equals(pageForm.getSelectTime())) {
String time = DateUtil.thisYear() + "-" + String.format("%02d", pageForm.getMonth()) + "-01";
cnd.andEX("l.retireTime", "<", time);
} else {
cnd.andEX("month(l.retireTime)", "=", pageForm.getMonth());
}
cnd.andEX("u.unitId", "=", pageForm.getUnitId());
cnd.andEX("u.unionId", "=", pageForm.getUnionId());
cnd.andEX("l.receive", "=", pageForm.getReceive());
if(StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup group = new SqlExpressionGroup();
group.orLike("u.userName", pageForm.getSearchKeyword());
group.orLike("u.loginName", pageForm.getSearchKeyword());
cnd.and(group);
}
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.asc("l.receive").asc("l.retireTime");
} else {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
sql.setCondition(cnd);
return sql;
}
}
@@ -0,0 +1,43 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.model;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
/**
* @ClassName RetireSouvenirsBatch
* @Author JyuHsin
* @Date 2025/10/14 9:52
* @Version 1.0
* @Description 退休人员纪念品批次管理
*/
@Data
@Table
@Comment("退休人员纪念品-批次管理")
@EqualsAndHashCode(callSuper = true)
public class RetireSouvenirsBatch extends BaseModel {
@Name
@Column
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("年度")
@ColDefine(type = ColType.INT)
private Integer year;
@Column
@Comment("批次名称")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String name;
@Column
@Comment("备注")
@ColDefine(type = ColType.VARCHAR, width = 600)
private String remark;
}
@@ -0,0 +1,54 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.model;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
/**
* @ClassName RetireSouvenirsLedger
* @Author JyuHsin
* @Date 2025/10/14 9:52
* @Version 1.0
* @Description 退休人员纪念品人员台账管理
*/
@Data
@Table
@Comment("退休人员纪念品-人员台账")
@EqualsAndHashCode(callSuper = true)
public class RetireSouvenirsLedger extends BaseModel {
@Name
@Column
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("批次id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String batchId;
@Column
@Comment("人员Id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String userId;
@Column
@Comment("退休时间")
@ColDefine(type = ColType.VARCHAR, width = 30)
private String retireTime;
@Column
@Comment("是否领取")
@ColDefine(type = ColType.BOOLEAN)
@Default("0")
private Boolean receive;
@Column
@Comment("领取时间")
@ColDefine(type = ColType.VARCHAR, width = 30)
private String receiveTime;
}
@@ -0,0 +1,58 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.model;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
/**
* @ClassName RetireSouvenirsMsg
* @Author JyuHsin
* @Date 2025/10/15 10:03
* @Version 1.0
* @Description TODO
*/
@Data
@Table
@Comment("退休人员纪念品-短信发送记录")
@EqualsAndHashCode(callSuper = true)
public class RetireSouvenirsMsg extends BaseModel {
@Name
@Column
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("批次id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String batchId;
@Column
@Comment("人员Id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String userId;
@Column
@Comment("发送人")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String sendUserId;
@Column
@Comment("发送人姓名")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String sendUserName;
@Column
@Comment("发送内容")
@ColDefine(type = ColType.VARCHAR, width = 600)
private String message;
@Column
@Comment("发送时间")
@ColDefine(type = ColType.VARCHAR, width = 30)
private String sendTime;
}
@@ -0,0 +1,14 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsBatch;
/**
* @ClassName RetireSouvenirsBatchService
* @Author JyuHsin
* @Date 2025/10/14 14:22
* @Version 1.0
* @Description TODO
*/
public interface RetireSouvenirsBatchService extends BaseService<RetireSouvenirsBatch> {
}
@@ -0,0 +1,14 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsLedger;
/**
* @ClassName RetireSouvenirsLedgerService
* @Author JyuHsin
* @Date 2025/10/14 14:22
* @Version 1.0
* @Description TODO
*/
public interface RetireSouvenirsLedgerService extends BaseService<RetireSouvenirsLedger> {
}
@@ -0,0 +1,22 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsBatch;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.service.RetireSouvenirsBatchService;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
/**
* @ClassName RetireSouvenirsBatchServiceImpl
* @Author JyuHsin
* @Date 2025/10/14 14:22
* @Version 1.0
* @Description TODO
*/
@IocBean(args = {"refer:dao"})
public class RetireSouvenirsBatchServiceImpl extends BaseServiceImpl<RetireSouvenirsBatch> implements RetireSouvenirsBatchService {
public RetireSouvenirsBatchServiceImpl(Dao dao) {
super(dao);
}
}
@@ -0,0 +1,22 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.model.RetireSouvenirsLedger;
import com.budwk.app.zhgh.dayofficework.retiresouvenirs.service.RetireSouvenirsLedgerService;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
/**
* @ClassName RetireSouvenirsLedgerServiceImpl
* @Author JyuHsin
* @Date 2025/10/14 14:23
* @Version 1.0
* @Description TODO
*/
@IocBean(args = {"refer:dao"})
public class RetireSouvenirsLedgerServiceImpl extends BaseServiceImpl<RetireSouvenirsLedger> implements RetireSouvenirsLedgerService {
public RetireSouvenirsLedgerServiceImpl(Dao dao) {
super(dao);
}
}
@@ -0,0 +1,33 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.template;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import com.budwk.app.base.model.ExcelImportError;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @ClassName RetireSouvenirsImportTemp
* @Author JyuHsin
* @Date 2025/10/14 15:21
* @Version 1.0
* @Description TODO
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ContentRowHeight(20)
@HeadRowHeight(20)
@ColumnWidth(25)
public class RetireSouvenirsImportTemp extends ExcelImportError {
@ExcelProperty("工号" )
private String loginName;
@ExcelProperty("姓名")
private String userName;
@ExcelProperty("退休时间")
private String retireTime;
}
@@ -0,0 +1,23 @@
package com.budwk.app.zhgh.dayofficework.retiresouvenirs.vo;
import com.budwk.app.base.param.PageForm;
import lombok.Data;
/**
* @ClassName RetireSouvenirsLedgerPageForm
* @Author JyuHsin
* @Date 2025/10/15 9:52
* @Version 1.0
* @Description TODO
*/
@Data
public class RetireSouvenirsLedgerPageForm extends PageForm {
private String batchId;
private Integer year;
private Integer month;
private String unitId;
private String unionId;
private String selectTime;
private Boolean receive;
}
@@ -2,12 +2,9 @@ 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;
@@ -16,7 +13,6 @@ 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;
@@ -58,11 +54,12 @@ public class GrassrootsCongressMeetingStatisticsController {
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("ins.state","=", ProcessInstanceStateEnum.FINISHED.getCode());
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()));
}
cnd.andEX("info.unionId", "=", pageForm.getUnionId());
cnd.desc("info.createTime");
sql.setCondition(cnd);
Pagination<NutMap> pagination = grassrootsCongressService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
@@ -63,6 +63,7 @@ public class GrassrootsCongressMeetingInfo extends BaseModel {
@Comment("所属工会")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String unionId;
@Column
@Comment("所属工会")
@ColDefine(type = ColType.VARCHAR, width = 32)
@@ -8,6 +8,7 @@ import com.budwk.app.base.result.Result;
import com.budwk.app.flow.engine.model.ProcessModel;
import com.budwk.app.flow.engine.model.TaskModel;
import com.budwk.app.flow.entity.ProcessDefine;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.service.ProcessDefineService;
import com.budwk.app.sys.models.Sys_dict;
import com.budwk.app.sys.services.SysDictService;
@@ -72,7 +73,10 @@ public class ProposalDashboardController {
.addv("name", taskModel.getDisplayName())
.addv("id", taskModel.getName())
.addv("type", "task")
.addv("count", 0)).toList();
.addv("count", 0)
.addv("todoCount", 0)
.addv("doneCount", 0)
).toList();
nodes.addAll(taskNodes);
// 立案结果
@@ -88,22 +92,24 @@ public class ProposalDashboardController {
// 查询待办任务
Sql todoSql = Sqls.create("""
SELECT
t.taskName
t.taskName,
t.taskState
FROM
wf_process_task t
INNER JOIN wf_process_instance ins ON ins.id = t.processInstanceId
INNER JOIN proposal_info info ON info.id = ins.businessNo
WHERE
t.taskState = 10
AND info.sessionId = @sessionId
info.sessionId = @sessionId
""");
todoSql.setParam("sessionId", sessionId);
List<NutMap> todoTasks = processDefineService.listMap(todoSql);
for (NutMap node : nodes) {
if (node.getString("type").equals("task")) {
long count = todoTasks.stream().filter(task -> task.getString("taskName").equals(node.getString("id"))).count();
node.put("count", count);
long todoCount = todoTasks.stream().filter(task -> task.getInt("taskState") == ProcessTaskStateEnum.DOING.getCode() && task.getString("taskName").equals(node.getString("id"))).count();
node.put("todoCount", todoCount);
long doneCount = todoTasks.stream().filter(task -> task.getInt("taskState") == ProcessTaskStateEnum.FINISHED.getCode() && task.getString("taskName").equals(node.getString("id"))).count();
node.put("doneCount", doneCount);
} else if (node.getString("type").equals("total")) {
int count = dao.count(ProposalInfo.class, Cnd.where(ProposalInfo::getSessionId, "=", sessionId));
node.put("count", count);
@@ -119,11 +125,10 @@ public class ProposalDashboardController {
@At
@SaCheckPermission("proposal.dashboard")
public Result pageData(PageForm pageForm, String sessionId, String selectNodeId, String selectNodeType) {
public Result pageData(PageForm pageForm, String sessionId, String selectNodeId, String selectNodeType, String selectNodeMode) {
Sql sql = Sqls.create("""
SELECT
info.*,
COUNT(p.consolidationIds) > 0 AS isConsolidation,
type.name AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
@@ -137,24 +142,33 @@ public class ProposalDashboardController {
GROUP_CONCAT(DISTINCT CASE WHEN pru.isMaster = 0 THEN pru.unitName END) AS slaveUnitNames
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 teacher_congress_delegate tcde on tcde.loginName = info.createUserLoginName
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
LEFT JOIN proposal_reply_unit pru ON pru.proposalId = info.id
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = @taskState
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("info.sessionId", "=", sessionId);
cnd.groupBy("info.id");
if(StrUtil.isNotBlank(selectNodeType) && StrUtil.isNotBlank(selectNodeId)){
switch (selectNodeType){
// 默认显示进行中的任务
sql.setParam("taskState", ProcessTaskStateEnum.DOING.getCode());
if (StrUtil.isNotBlank(selectNodeType) && StrUtil.isNotBlank(selectNodeId)) {
switch (selectNodeType) {
case "task":
cnd.and("t.taskName", "=", selectNodeId);
if (selectNodeMode.equals("todo")) {
sql.setParam("taskState", ProcessTaskStateEnum.DOING.getCode());
} else {
sql.setParam("taskState", ProcessTaskStateEnum.FINISHED.getCode());
}
break;
case "total":
break;
@@ -4,12 +4,15 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.ArrayUtil;
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.entity.ProcessTask;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
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 lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
@@ -36,12 +39,14 @@ public class ProposalQueryCollectProgressController {
add(NutMap.NEW().addv("code", 10).addv("id", 10).addv("name", "撰写提案"));
add(NutMap.NEW().addv("code", 20).addv("id", 20).addv("name", "附议提案"));
add(NutMap.NEW().addv("code", 30).addv("id", 30).addv("name", "待团长审核"));
add(NutMap.NEW().addv("code", 40).addv("id", 40).addv("name", "团长审核退回"));
add(NutMap.NEW().addv("code", 50).addv("id", 50).addv("name", "团长审核通过"));
add(NutMap.NEW().addv("code", 40).addv("id", 40).addv("name", "团长审核"));
}};
@Inject
private BaseService baseService;
private ProposalCommonService proposalCommonService;
@Inject
private Dao dao;
@At("")
@Ok("beetl:/platform/zhgh/democratic/proposal/query/collectProgress/index.html")
@@ -61,43 +66,55 @@ public class ProposalQueryCollectProgressController {
info.createUserName,
type.NAME AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName
tcd.`name` AS delegationName,
(SELECT count(1) FROM proposal_second WHERE proposalId = info.id) AS inviteCount,
(SELECT count(1) FROM wf_process_task WHERE processInstanceId = ins.id AND taskName = 'second' AND taskState = 20) finishCount,
ins.id AS instanceId,
ins.state instanceState,
t.displayName curTaskName
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 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
""");
sql.setParam("sessionId", pageForm.getSessionId());
Cnd cnd = Cnd.NEW();
ProposalQueryComprehensiveParam.buildSearch(cnd, pageForm);
SqlExpressionGroup seg = new SqlExpressionGroup();
if (ArrayUtil.contains(pageForm.getCollectIds(), 10)) {
seg.or("inst.processInstanceNodeCode", "=", 10);
seg.or("t.taskName", "=", "startTask");
}
if (ArrayUtil.contains(pageForm.getCollectIds(), 20)) {
seg.or("inst.processInstanceNodeCode", "=", 20);
seg.or("t.taskName", "=", "second");
}
if (ArrayUtil.contains(pageForm.getCollectIds(), 30)) {
seg.or("inst.processInstanceNodeCode", "=", 30);
seg.or("t.taskName", "=", "delegation");
}
if (ArrayUtil.contains(pageForm.getCollectIds(), 40)) {
seg.or("inst.processInstanceNodeCode", "=", 40);
}
if (ArrayUtil.contains(pageForm.getCollectIds(), 50)) {
seg.or("inst.processInstanceNodeCode", ">", 50);
seg.or("t.taskName", "not in", List.of("startTask", "second", "delegation"));
seg.and("t.taskName", "is not", null);
}
if (!seg.isEmpty()) {
cnd.and(seg);
}
// cnd.and("inst.processInstanceNodeCode", "in", List.of(10, 20, 30, 40, 50));
ProposalQueryComprehensiveParam.buildSearch(cnd, pageForm);
cnd.groupBy("info.id");
sql.setCondition(cnd);
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
Pagination pagination = proposalCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
List<NutMap> list = (List<NutMap>) pagination.getList();
for (NutMap row : list) {
int count = dao.count(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", row.getString("instanceId"))
.and(ProcessTask::getTaskName, "=", "second")
.and(ProcessTask::getTaskState, "=", ProcessTaskStateEnum.FINISHED.getCode())
);
}
return Result.success(pagination);
}
@@ -0,0 +1,107 @@
package com.budwk.app.zhgh.democratic.proposal.controller.transact;
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.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalCommissionerOpinion;
import com.budwk.app.zhgh.democratic.proposal.param.ProposalSearchParam;
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
import io.swagger.annotations.Api;
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;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.validation.Valid;
import java.util.Date;
@IocBean
@At("/platform/proposal/commissioner")
@Slf4j
@Ok("json:full")
@Api(tags = "提案委员会委员查询")
public class ProposalCommissionerController {
@Inject
private Dao dao;
@Inject
private ProposalCommonService proposalCommonService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/proposal/transact/commissioner/index.html")
@SaCheckPermission("proposal.commissioner")
public void index() {
}
@At
@SaCheckPermission("proposal.commissioner")
public Result pageData(@Valid ProposalSearchParam pageForm, boolean approval) {
Sql sql = Sqls.create("""
SELECT
info.*,
type.NAME AS typeName,
tcs.fullName AS sessionName,
tcd.`name` AS delegationName,
ins.id AS instanceId,
ins.businessNo,
ins.state instanceState,
ins.variable instanceVariable,
ins.processDefineId instanceProcessDefineId,
t.displayName taskName,
(SELECT count(1) FROM proposal_commissioner_opinion WHERE proposalId = info.id AND caseFilingResult = 'CONFIRM_FILING') CONFIRM_FILING_COUNT,
(SELECT count(1) FROM proposal_commissioner_opinion WHERE proposalId = info.id AND caseFilingResult = 'SUGGESTION') SUGGESTION_COUNT,
(SELECT count(1) FROM proposal_commissioner_opinion WHERE proposalId = info.id AND caseFilingResult = 'NOT') NOT_COUNT,
pco.id pcoId
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 `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 proposal_commissioner_opinion pco on pco.proposalId = info.id and pco.commissioner = @userId
$condition
""");
sql.setParam("userId", SecurityUtil.getUserId());
Cnd cnd = Cnd.NEW();
ProposalSearchParam.buildSearch(cnd, pageForm);
cnd.and("pco.id", approval ? "is not" : "is", null);
cnd.groupBy("t.id");
cnd.desc("t.createdAt");
sql.setCondition(cnd);
Pagination pagination = proposalCommonService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("proposal.commissioner")
@SLog(tag = "提案委员会委员意见", msg = "")
@Aop(TransAop.READ_COMMITTED)
public Result doApproval(String proposalId, String opinion, String caseFilingResult, String caseFilingType) {
dao.clear(ProposalCommissionerOpinion.class, Cnd.where(ProposalCommissionerOpinion::getProposalId, "=", proposalId).and(ProposalCommissionerOpinion::getCommissioner, "=", SecurityUtil.getUserId()));
ProposalCommissionerOpinion commissionerOpinion = new ProposalCommissionerOpinion();
commissionerOpinion.setProposalId(proposalId);
commissionerOpinion.setCommissioner(SecurityUtil.getUserId());
commissionerOpinion.setOpinionText(opinion);
commissionerOpinion.setCaseFilingResult(caseFilingResult);
commissionerOpinion.setCaseFilingType(caseFilingType);
commissionerOpinion.setOpinionTime(new Date());
dao.insert(commissionerOpinion);
return Result.success();
}
}
@@ -28,7 +28,7 @@ public class ProposalMasterUnitAssignmentHandler implements AssignmentHandler {
// 提案ID
String proposalId = execution.getProcessInstance().getBusinessNo();
// 主办单位
ProposalReplyUnit masterUnit = dao.fetch(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", proposalId).and(ProposalReplyUnit::getIsMaster, "=", 1));
if (masterUnit == null) {
@@ -0,0 +1,57 @@
package com.budwk.app.zhgh.democratic.proposal.models;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = true)
@Table("proposal_commissioner_opinion")
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("提案委员意见")
@TableIndexes(value = {
@Index(name = "INDEX_PROPOSAL_COMMISSIONER_OPINION_PROPOSAL_ID", fields = {"proposalId"}, unique = false)
})
public class ProposalCommissionerOpinion extends BaseModel {
@Name
@Comment("ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@PrevInsert(uu32 = true)
private String id;
@Column
@Comment("提案ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String proposalId;
@Column
@Comment("立案结果(字典表)")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String caseFilingResult;
@Column
@Comment("立案类型(重点、普通提案)")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String caseFilingType;
@Column
@Comment("委员意见")
@ColDefine(type = ColType.TEXT)
private String opinionText;
@Column
@Comment("委员意见时间")
@ColDefine(type = ColType.DATETIME)
private Date opinionTime;
@Column
@Comment("委员ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String commissioner;
}
@@ -50,6 +50,9 @@ public class ProposalQueryComprehensiveParam extends PageForm {
@ApiModelProperty(name = "征集进度状态")
private Integer[] collectIds;
@ApiModelProperty(name = "通用关键字")
private String commonKeyword;
/**
* 构建通用查询参数
@@ -6,6 +6,7 @@ import com.budwk.app.base.utils.PageUtil;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.Cnd;
import org.nutz.dao.util.cri.SqlExpressionGroup;
/**
* 提案通用搜索
@@ -20,6 +21,7 @@ public class ProposalSearchParam extends PageForm {
private String delegationId;
private String createUserName;
private String createUserLoginName;
private String createUserKeyword;
private String caseFilingResult;
/**
@@ -46,11 +48,19 @@ public class ProposalSearchParam extends PageForm {
if (StrUtil.isNotBlank(searchParam.getCreateUserLoginName())) {
cnd.where().andLike("info.createUserLoginName", searchParam.getCreateUserLoginName());
}
if (StrUtil.isNotBlank(searchParam.getCreateUserKeyword())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.orLike("info.createUserName", searchParam.getCreateUserKeyword());
seg.orLike("info.createUserLoginName", searchParam.getCreateUserKeyword());
cnd.and(seg);
}
cnd.andEX("info.caseFilingResult", "=", searchParam.getCaseFilingResult());
if(StrUtil.isAllNotBlank(searchParam.getPageOrderName(), searchParam.getPageOrderBy())){
if (StrUtil.isAllNotBlank(searchParam.getPageOrderName(), searchParam.getPageOrderBy())) {
cnd.orderBy(searchParam.getPageOrderName(), PageUtil.getOrder(searchParam.getPageOrderBy()));
}else{
} else {
cnd.asc("info.code");
}
}
@@ -125,6 +125,22 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
info.put("merges", mergeInfos);
}
// 提案委员会成员意见
Sql commissionerSql = Sqls.create("""
SELECT
pco.*,
u.username commissionerName,
u.loginname commissionerLoginName
FROM
proposal_commissioner_opinion pco
LEFT JOIN vw_user u ON u.id = pco.commissioner
WHERE
pco.proposalId = @proposalId
""");
commissionerSql.setParam("proposalId", id);
List<NutMap> commissionerOpinions = listMap(commissionerSql);
info.put("commissionerOpinions", commissionerOpinions);
return info;
}
@@ -115,16 +115,57 @@ public class TeacherCongressDelegateManageController {
delegate.setSessionId(param.getSessionId());
delegate.setRoleId(param.getRoleId());
}
dao.insert(delegates);
for (String userId : userIds) {
dao.insert("sys_user_role", Chain.make("userId", userId).add("roleId", param.getRoleId()).add("tcSessionId", param.getSessionId()).add("tcDelegationId", param.getDelegationId()));
}
// 删除掉旧的权限
dao.clear(Sys_user_role.class, Cnd.where(Sys_user_role::getUserId, "in", userIds)
.and(Sys_user_role::getTcSessionId, "=", param.getSessionId())
.and(Sys_user_role::getRoleId, "=", param.getRoleId()));
List<Sys_user_role> userRoles = userIds.stream().map(userId -> {
Sys_user_role role = new Sys_user_role();
role.setUserId(userId);
role.setTcSessionId(param.getSessionId());
role.setTcDelegationId(param.getDelegationId());
role.setRoleId(param.getRoleId());
return role;
}).toList();
dao.insert(userRoles);
sysUserService.clearCache();
return Result.success();
}
@At
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("tc.delegate.manage")
@SLog(tag = "民主管理", msg = "教代会代表管理修改代表")
public Result update(@Valid TeacherCongressDelegateManageUpdateParam param) {
// 查询原来的记录
Teacher_congress_delegate old = dao.fetch(Teacher_congress_delegate.class, param.getId());
// 删除掉旧的权限
dao.clear(Sys_user_role.class, Cnd.where(Sys_user_role::getUserId, "=", old.getUserId())
.and(Sys_user_role::getRoleId, "=", old.getRoleId())
.and(Sys_user_role::getTcSessionId, "=", old.getSessionId())
.and(Sys_user_role::getTcDelegationId, "=", old.getDelegationId()));
old.setDelegationId(param.getDelegationId());
dao.update(old, "delegationId");
// 新增权限
Sys_user_role role = new Sys_user_role();
role.setUserId(param.getUserId());
role.setTcSessionId(param.getSessionId());
role.setTcDelegationId(param.getDelegationId());
role.setRoleId(param.getRoleId());
dao.insert(role);
sysUserService.clearCache();
return Result.success();
}
@At
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("tc.delegate.manage")
@@ -0,0 +1,101 @@
package com.budwk.app.zhgh.democratic.teachercongress.delegate.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.teachercongress.delegate.models.Teacher_congress_delegate;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.models.Teacher_congress_session;
import io.swagger.annotations.Api;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import java.util.HashMap;
import java.util.List;
@IocBean
@At("/platform/zhgh/democratic/teacherCongress/delegate/transition")
@Api(tags = "教代会代表换届变动信息")
@Ok("json:full")
public class TeacherCongressDelegateTransitionController {
@Inject
private Dao dao;
@At("")
@Ok("beetl:/platform/zhgh/democratic/teachercongress/delegate/transition/index.html")
@SaCheckPermission("tc.delegate.transition")
public void index() {
}
@At
@SaCheckPermission("tc.delegate.transition")
public Result pageData(String sessionId) {
// 当前届次
Teacher_congress_session session = dao.fetch(Teacher_congress_session.class, sessionId);
// 上一届次
Teacher_congress_session lastSession = dao.fetch(Teacher_congress_session.class, Cnd.where(Teacher_congress_session::getStartDate, "<", session.getStartDate()).desc(Teacher_congress_session::getStartDate));
// 当前届次代表团
List<Teacher_congress_delegation> delegations = dao.query(Teacher_congress_delegation.class, Cnd.where(Teacher_congress_delegation::getSessionId, "=", sessionId).asc(Teacher_congress_delegation::getCode));
// 当前届次代表
List<Teacher_congress_delegate> delegates = dao.query(Teacher_congress_delegate.class, Cnd.where(Teacher_congress_delegate::getSessionId, "=", sessionId));
dao.fetchLinks(delegates, "delegation");
// 上一届次代表
List<Teacher_congress_delegate> lastDelegates = dao.query(Teacher_congress_delegate.class, Cnd.where(Teacher_congress_delegate::getSessionId, "=", lastSession.getId()));
dao.fetchLinks(lastDelegates, "delegation");
// 代表数据
List<NutMap> delegateFull = delegates.stream().map(delegate -> {
NutMap delegateMap = NutMap.NEW();
delegateMap.put("userId", delegate.getUserId());
delegateMap.put("userName", delegate.getUserName());
// 本届次代表团信息
delegateMap.put("delegationId", delegate.getDelegationId());
delegateMap.put("delegationName", delegate.getDelegation().getName());
delegateMap.put("delegationCode", delegate.getDelegation().getCode());
// 上一届次代表团信息
lastDelegates.stream().filter(lastDelegate -> lastDelegate.getUserId().equals(delegate.getUserId())).findFirst().ifPresentOrElse(lastDelegate -> {
delegateMap.put("lastDelegationId", lastDelegate.getDelegationId());
delegateMap.put("lastDelegationName", lastDelegate.getDelegation().getName());
delegateMap.put("lastDelegationCode", lastDelegate.getDelegation().getCode());
}, () -> {
delegateMap.put("lastDelegationId", "");
delegateMap.put("lastDelegationName", "");
delegateMap.put("lastDelegationCode", "");
});
return delegateMap;
}).toList();
List<HashMap<String, Object>> list = delegations.stream().map(delegation -> {
HashMap<String, Object> map = new HashMap<>();
map.put("name", delegation.getName());
map.put("code", delegation.getCode());
// 上一届次人数
map.put("lastCount", delegateFull.stream().filter(delegate -> delegate.getString("lastDelegationCode").equals(delegation.getCode())).count());
// 增补代表数 (上一届次不是代表 但是本届次是代表)
map.put("addCount", delegateFull.stream().filter(delegate -> StrUtil.isBlank(delegate.getString("lastDelegationCode")) && delegate.getString("delegationCode").equals(delegation.getCode())));
// 转入代表数 (上一届次是代表 但是在别的代表团)
map.put("transferCount", delegateFull.stream().filter(delegate -> !delegate.getString("lastDelegationCode").equals(delegation.getCode()) && delegate.getString("delegationCode").equals(delegation.getCode())));
// 转出代表数 (上一届次在本团 本届次转出去了)
map.put("transferOutCount", delegateFull.stream().filter(delegate -> delegate.getString("lastDelegationCode").equals(delegation.getCode()) && StrUtil.isNotBlank(delegate.getString("delegationCode")) && !delegate.getString("delegationCode").equals(delegation.getCode())));
// 减少代表数 (上一届次是代表 本届次不是代表)
map.put("reduceCount", delegateFull.stream().filter(delegate -> delegate.getString("lastDelegationCode").equals(delegation.getCode()) && StrUtil.isBlank(delegate.getString("delegationCode"))));
// 当前代表数
map.put("currentCount", delegateFull.stream().filter(delegate -> delegate.getString("delegationCode").equals(delegation.getCode())).count());
return map;
}).toList();
return Result.success(list);
}
}
@@ -2,6 +2,7 @@ package com.budwk.app.zhgh.democratic.teachercongress.delegate.models;
import com.budwk.app.base.model.BaseModel;
import com.budwk.app.zhgh.democratic.teachercongress.delegation.models.Teacher_congress_delegation;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
@@ -85,4 +86,6 @@ public class Teacher_congress_delegate extends BaseModel {
@ColDefine(type = ColType.VARCHAR, width = 32)
private String roleId;
@One(field = "delegationId")
private Teacher_congress_delegation delegation;
}
@@ -0,0 +1,31 @@
package com.budwk.app.zhgh.democratic.teachercongress.delegate.param;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* 教代会代表更新对象
*/
@Data
public class TeacherCongressDelegateManageUpdateParam {
@NotBlank(message = "主键不能为空")
private String id;
@NotBlank(message = "教代会届次不能为空")
private String sessionId;
@NotBlank(message = "代表团不能为空")
private String delegationId;
@NotBlank(message = "代表类型不能为空")
private String roleId;
@NotEmpty(message = "用户不能为空")
private String userId;
}
@@ -21,7 +21,7 @@ module.exports = {
</script>
<template>
<el-dialog title="流程图预览" :visible.sync="designVisible" width="80%" top="50px" append-to-body>
<el-dialog title="流程图预览" :visible.sync="designVisible" fullscreen width="80%" top="50px" append-to-body>
<div class="diagram-viewer">
<iframe v-if="designVisible" :src="designUrl" frameborder="0"></iframe>
</div>
@@ -30,7 +30,8 @@ module.exports = {
<style scoped>
.diagram-viewer {
height: 65vh;
/*height: 65vh;*/
height: calc(100vh - 60px - 55px);
border: 1px solid #e4e7ed;
border-radius: 4px;
overflow: hidden;
@@ -15,6 +15,7 @@
<el-button :size="upload_button_size" type="primary">
{{ upload_text }}
</el-button>
<div class="el-upload__tip" v-html="upload_tips"></div>
</el-upload>
<!-- 图片上传模式 -->
@@ -123,6 +124,12 @@ module.exports = {
default: 1,
required: false
},
// 上传文件大小限制
upload_size: {
type: Number,
default: 1024 * 1024 * 10,
required: false
},
// 上传按钮文字
upload_text: {
type: String,
@@ -190,6 +197,8 @@ module.exports = {
upload_tips() {
const uploadNumber = this.upload_number
const fileAccept = this.fileAccept
const fileSize = this.upload_size
let tips = null
if (uploadNumber) {
tips = `只能上传<span style="color: red">${uploadNumber}</span>个文件;`
@@ -197,6 +206,9 @@ module.exports = {
if (fileAccept) {
tips = tips + `只能上传<span style="color: red">${fileAccept}</span>文件;`
}
if (fileSize) {
tips = tips + `单个文件大小不能超过<span style="color: red">${fileSize / 1024 / 1024}</span>M`
}
return tips
}
},
@@ -290,6 +302,13 @@ module.exports = {
// 这是兜底逻辑,保准只让这个image类型上传图片
beforeUpload(file) {
if (file.size > this.upload_size) {
this.$message.error("文件过大,请上传小于" + (this.upload_size / 1024 / 1024).toFixed(0) + "M的文件!")
return false
}
return true
// if (!this.fileAccept || typeof this.fileAccept !== "string") {
@@ -562,6 +581,7 @@ module.exports = {
.upload_file .el-upload {
/*width: 100%;*/
text-align: left;
}
.upload_file .el-upload .el-upload-dragger {
@@ -583,17 +603,17 @@ module.exports = {
pointer-events: none;
}
.el-upload--picture-card{
width: var(--upload-width, 148px)!important;
height: var(--upload-height, 148px)!important;
.el-upload--picture-card {
width: var(--upload-width, 148px) !important;
height: var(--upload-height, 148px) !important;
/*line-height: calc(var(--upload-height, 148px) - 2px) !important;*/
line-height: unset!important;
line-height: unset !important;
display: inline-flex;
align-items: center;
justify-content: center;
}
.el-upload-list--picture-card .el-upload-list__item{
.el-upload-list--picture-card .el-upload-list__item {
width: var(--upload-width, 148px);
height: var(--upload-height, 148px);
}
@@ -641,10 +641,10 @@
<span class="v4-user-name">${@auth.getPrincipalProperty('username')} (${@auth.getPrincipalProperty('loginname')})</span>
<!-- <i class="fa fa-angle-down"></i> -->
</div>
<div class="v4-logout">
<a class="v4-logout" href="/platform/login/logout">
<i class="fa fa-sign-out"></i>
退出
</div>
</a>
</div>
</header>
<div style="height: 64px"></div>
@@ -1,348 +1,350 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>流程设计器</title>
<script src="/assets/platform/plugins/vue/vue.js"></script>
<script src="/assets/platform/plugins/jquery/jquery.js"></script>
<script src="/assets/platform/plugins/element-ui/lib/index.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/override.css" />
<!-- 引入 core 包和对应 css-->
<script src="https://cdn.jsdelivr.net/npm/@logicflow/core@1.2.12/dist/logic-flow.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@logicflow/core@1.2.12/dist/style/index.css" />
<script src="/assets/platform/plugins/snaker/SnakerflowDesigner.umd.js"></script>
<style>
#snaker-flow-preview {
height: 100vh;
}
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>流程设计器</title>
<script src="/assets/platform/plugins/vue/vue.js"></script>
<script src="/assets/platform/plugins/jquery/jquery.js"></script>
<script src="/assets/platform/plugins/element-ui/lib/index.js"></script>
<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.css"/>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css"/>
<!-- 引入 core 包和对应 css-->
<script src="/assets/platform/plugins/logicflow/logic-flow.js"></script>
<link rel="stylesheet" href="/assets/platform/plugins/logicflow/index.css"/>
<script src="https://cdn.jsdelivr.net/npm/@logicflow/extension@2.1.4/dist/index.min.js"></script>
<script src="/assets/platform/plugins/snaker/SnakerflowDesigner.umd.js"></script>
<style>
#snaker-flow-preview {
height: 100vh;
}
.approval-card {
position: absolute;
width: 320px;
background: #ffffff;
border-radius: 8px;
border: 1px solid #d9e3f0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
z-index: 1000;
font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
transform: translate(10px, 10px);
overflow: hidden;
}
.approval-card {
position: absolute;
width: 320px;
background: #ffffff;
border-radius: 8px;
border: 1px solid #d9e3f0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
z-index: 1000;
font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
transform: translate(10px, 10px);
overflow: hidden;
}
.tab-container {
border-bottom: 1px solid #e8e8e8;
}
.tab-container {
border-bottom: 1px solid #e8e8e8;
}
.tab-header {
display: flex;
background: #fafafa;
}
.tab-header {
display: flex;
background: #fafafa;
}
.tab-item {
padding: 8px 16px;
cursor: pointer;
border-right: 1px solid #e8e8e8;
font-size: 12px;
color: #666;
background: #fafafa;
transition: all 0.2s;
}
.tab-item {
padding: 8px 16px;
cursor: pointer;
border-right: 1px solid #e8e8e8;
font-size: 12px;
color: #666;
background: #fafafa;
transition: all 0.2s;
}
.tab-item:last-child {
border-right: none;
}
.tab-item:last-child {
border-right: none;
}
.tab-item.active {
background: #fff;
color: #333;
border-bottom: 2px solid #1890ff;
margin-bottom: -1px;
}
.tab-item.active {
background: #fff;
color: #333;
border-bottom: 2px solid #1890ff;
margin-bottom: -1px;
}
.tab-item:hover {
background: #f0f0f0;
color: #333;
}
.tab-item:hover {
background: #f0f0f0;
color: #333;
}
/* 卡片标题栏(OA风格顶部色条) */
.approval-card .card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
background: #1a73e8;
color: white;
}
/* 卡片标题栏(OA风格顶部色条) */
.approval-card .card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
background: #1a73e8;
color: white;
}
.approval-card .card-header h3 {
margin: 0;
font-size: 15px;
font-weight: 500;
letter-spacing: 0.5px;
}
.approval-card .card-header h3 {
margin: 0;
font-size: 15px;
font-weight: 500;
letter-spacing: 0.5px;
}
.approval-card .card-header button {
background: rgba(255, 255, 255, 0.2);
border: none;
width: 24px;
height: 24px;
border-radius: 50%;
color: white;
font-size: 16px;
line-height: 1;
cursor: pointer;
transition: all 0.2s;
}
.approval-card .card-header button {
background: rgba(255, 255, 255, 0.2);
border: none;
width: 24px;
height: 24px;
border-radius: 50%;
color: white;
font-size: 16px;
line-height: 1;
cursor: pointer;
transition: all 0.2s;
}
.approval-card .card-header button:hover {
background: rgba(255, 255, 255, 0.3);
}
.approval-card .card-header button:hover {
background: rgba(255, 255, 255, 0.3);
}
/* 卡片内容区域 */
.approval-card .card-body {
padding: 16px;
}
/* 卡片内容区域 */
.approval-card .card-body {
padding: 16px;
}
/* 信息行样式 */
.approval-card .info-row {
display: flex;
margin-bottom: 12px;
align-items: flex-start;
}
/* 信息行样式 */
.approval-card .info-row {
display: flex;
margin-bottom: 12px;
align-items: flex-start;
}
.approval-card .info-label {
width: 80px;
color: #666;
font-size: 13px;
line-height: 1.5;
}
.approval-card .info-label {
width: 80px;
color: #666;
font-size: 13px;
line-height: 1.5;
}
.approval-card .info-value {
flex: 1;
color: #333;
font-size: 13px;
line-height: 1.5;
word-break: break-all;
}
.approval-card .info-value {
flex: 1;
color: #333;
font-size: 13px;
line-height: 1.5;
word-break: break-all;
}
/*!* 分隔线 *!*/
/*.approval-card .divider {*/
/* height: 1px;*/
/* background: #f0f0f0;*/
/* margin: 12px 0;*/
/*}*/
</style>
</head>
<body>
<div id="snaker-flow-preview">
<snaker-flow-designer
ref="designer"
v-model="flowData"
:show-doc="false"
:viewer="true"
node-render-type="html"
:high-light="highLight"
></snaker-flow-designer>
/*!* 分隔线 *!*/
/*.approval-card .divider {*/
/* height: 1px;*/
/* background: #f0f0f0;*/
/* margin: 12px 0;*/
/*}*/
</style>
</head>
<body>
<div id="snaker-flow-preview">
<snaker-flow-designer
ref="designer"
v-model="flowData"
:show-doc="false"
:viewer="true"
node-render-type="html"
:high-light="highLight"
></snaker-flow-designer>
<div
v-if="showApprovalCard"
class="approval-card"
:style="{
<div
v-if="showApprovalCard"
class="approval-card"
:style="{
left: cardPosition.x+'px',
top: cardPosition.y+'px'
}"
>
<div class="card-header">
<h3>详情</h3>
<button @click="closeCard">×</button>
</div>
<!-- Tab切换 -->
<div class="tab-container" v-if="approvalInfos.length > 1">
<div class="tab-header">
<div
v-for="(item, index) in approvalInfos"
:key="index"
class="tab-item"
:class="{active: activeTabIndex === index}"
@click="activeTabIndex = index"
>
记录{{index + 1}}
</div>
</div>
</div>
<div class="card-body">
<div v-for="(approvalInfo, index) in approvalInfos" :key="index" v-show="activeTabIndex === index">
<div class="info-row">
<span class="info-label">节点类型:</span>
<span class="info-value">{{approvalInfo.displayName}}</span>
</div>
<div class="info-row">
<span class="info-label">审批人:</span>
<span class="info-value" v-if="currentNode.id === 'startTask'">
{{approvalInfo.ext?.initiatorName}}({{approvalInfo.ext?.initiatorAccount}})
</span>
<span class="info-value" v-else>{{approvalInfo.taskFormData.userName}}({{approvalInfo.taskFormData?.loginName}})</span>
</div>
<div class="info-row">
<span class="info-label">审核状态:</span>
<span class="info-value">{{getTaskStateText(approvalInfo.taskState)}}</span>
</div>
<div class="info-row">
<span class="info-label">提交结果:</span>
<span class="info-value">{{getSubmitTypeText(approvalInfo.ext.submitType)}}</span>
</div>
<div class="info-row">
<span class="info-label">提交意见:</span>
<span class="info-value">{{approvalInfo.taskFormData.opinion}}</span>
</div>
<!-- <div class="divider"></div>-->
<div class="info-row">
<span class="info-label">提交时间:</span>
<span class="info-value">{{approvalInfo.finishTime}}</span>
</div>
</div>
>
<div class="card-header">
<h3>详情</h3>
<button @click="closeCard">×</button>
</div>
<!-- Tab切换 -->
<div class="tab-container" v-if="approvalInfos.length > 1">
<div class="tab-header">
<div
v-for="(item, index) in approvalInfos"
:key="index"
class="tab-item"
:class="{active: activeTabIndex === index}"
@click="activeTabIndex = index"
>
记录{{index + 1}}
</div>
</div>
</div>
</body>
<script>
Vue.use(SnakerflowDesigner.default)
new Vue({
el: "#snaker-flow-preview",
data() {
return {
// 流程定义ID
defineId: "${defineId!}",
// 流程实例ID
instanceId: "${instanceId!}",
// 流程定义数据
flowData: {},
// 高亮数据
highLight: {},
// 历史审批记录
hisApproval: [],
// 展示已审核信息
showApprovalCard: false,
// 审批信息卡片位置
cardPosition: { x: 0, y: 0 },
// 当前节点
currentNode: [],
// 审批信息数组
approvalInfos: [],
// 当前选中的tab索引
activeTabIndex: 0
}
},
computed: {
// approvalInfo() {
// if (this.currentNode) {
// return this.hisApproval.find((item) => item.taskName === this.currentNode.id)
// }
// }
},
methods: {
getDetail() {
$.get("/flow/define/detail", { id: this.defineId }).then((res) => {
if (res.code === 0) {
this.flowData = res.data.content
this.initNodeEvent()
}
})
},
getHighLight() {
$.get("/flow/common/instanceHighLight", { instanceId: this.instanceId }).then((res) => {
if (res.code === 0) {
this.highLight = res.data
}
})
},
getHisApproval() {
$.get("/flow/common/approvalRecord", { instanceId: this.instanceId }).then((res) => {
if (res.code === 0) {
this.hisApproval = res.data
}
})
},
initNodeEvent() {
this.$nextTick(() => {
console.log(this.$refs.designer.lf.graphModel.eventCenter)
this.$refs.designer.lf.graphModel.eventCenter.on("node:click", ({ e, data }) => {
console.log(data)
console.log(e)
// 获取点击位置(考虑页面滚动情况)
const scrollX = window.scrollX || window.pageXOffset
const scrollY = window.scrollY || window.pageYOffset
this.cardPosition = {
x: e.clientX + scrollX,
y: e.clientY + scrollY
}
if (data.type !== "snaker:task") return
const approvalInfos = this.hisApproval.filter((item) => item.taskName === data.id && item.taskState === 20)
if (approvalInfos && approvalInfos.length > 0) {
this.approvalInfos = approvalInfos
this.currentNode = data
this.activeTabIndex = 0
this.showApprovalCard = true
}
})
this.$refs.designer.lf.graphModel.eventCenter.on("blank:click", (args) => {
this.closeCard()
})
})
},
closeCard() {
this.showApprovalCard = false
this.activeTabIndex = 0
},
// 获取任务状态文本
getTaskStateText(taskState) {
const stateMap = {
10: "进行中",
20: "已完成",
30: "已撤回"
}
return stateMap[taskState] || taskState
},
// 获取提交结果文本
getSubmitTypeText(submitType) {
const typeMap = {
0: "发起申请",
1: "同意申请",
2: "拒绝申请",
3: "退回上一步",
4: "跳转",
5: "重新提交",
6: "退回发起人",
20: "拒绝申请"
}
return typeMap[submitType] || submitType
}
},
mounted() {
if (this.defineId) {
this.getDetail()
}
if (this.instanceId) {
this.getHighLight()
this.getHisApproval()
}
<div class="card-body">
<div v-for="(approvalInfo, index) in approvalInfos" :key="index" v-show="activeTabIndex === index">
<div class="info-row">
<span class="info-label">节点类型:</span>
<span class="info-value">{{approvalInfo.displayName}}</span>
</div>
<div class="info-row">
<span class="info-label">审批人:</span>
<span class="info-value" v-if="currentNode.id === 'startTask'">
{{approvalInfo.ext?.initiatorName}}({{approvalInfo.ext?.initiatorAccount}})
</span>
<span class="info-value"
v-else>{{approvalInfo.taskFormData.userName}}({{approvalInfo.taskFormData?.loginName}})</span>
</div>
<div class="info-row">
<span class="info-label">审核状态:</span>
<span class="info-value">{{getTaskStateText(approvalInfo.taskState)}}</span>
</div>
<div class="info-row">
<span class="info-label">提交结果:</span>
<span class="info-value">{{getSubmitTypeText(approvalInfo.ext.submitType)}}</span>
</div>
<div class="info-row">
<span class="info-label">提交意见:</span>
<span class="info-value">{{approvalInfo.taskFormData.opinion}}</span>
</div>
<!-- <div class="divider"></div>-->
<div class="info-row">
<span class="info-label">提交时间:</span>
<span class="info-value">{{approvalInfo.finishTime}}</span>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
Vue.use(SnakerflowDesigner.default)
const vue = new Vue({
el: "#snaker-flow-preview",
data() {
return {
// 流程定义ID
defineId: "${defineId!}",
// 流程实例ID
instanceId: "${instanceId!}",
// 流程定义数据
flowData: {},
// 高亮数据
highLight: {},
// 历史审批记录
hisApproval: [],
// 展示已审核信息
showApprovalCard: false,
// 审批信息卡片位置
cardPosition: {x: 0, y: 0},
// 当前节点
currentNode: [],
// 审批信息数组
approvalInfos: [],
// 当前选中的tab索引
activeTabIndex: 0
}
})
</script>
},
computed: {
// approvalInfo() {
// if (this.currentNode) {
// return this.hisApproval.find((item) => item.taskName === this.currentNode.id)
// }
// }
},
methods: {
getDetail() {
$.get("/flow/define/detail", {id: this.defineId}).then((res) => {
if (res.code === 0) {
this.flowData = res.data.content
this.initNodeEvent()
}
})
},
getHighLight() {
$.get("/flow/common/instanceHighLight", {instanceId: this.instanceId}).then((res) => {
if (res.code === 0) {
this.highLight = res.data
}
})
},
getHisApproval() {
$.get("/flow/common/approvalRecord", {instanceId: this.instanceId}).then((res) => {
if (res.code === 0) {
this.hisApproval = res.data
}
})
},
initNodeEvent() {
this.$nextTick(() => {
console.log(this.$refs.designer.lf.graphModel.eventCenter)
this.$refs.designer.lf.graphModel.eventCenter.on("node:click", ({e, data}) => {
console.log(data)
console.log(e)
// 获取点击位置(考虑页面滚动情况)
const scrollX = window.scrollX || window.pageXOffset
const scrollY = window.scrollY || window.pageYOffset
this.cardPosition = {
x: e.clientX + scrollX,
y: e.clientY + scrollY
}
if (data.type !== "snaker:task") return
const approvalInfos = this.hisApproval.filter((item) => item.taskName === data.id && item.taskState === 20)
if (approvalInfos && approvalInfos.length > 0) {
this.approvalInfos = approvalInfos
this.currentNode = data
this.activeTabIndex = 0
this.showApprovalCard = true
}
})
this.$refs.designer.lf.graphModel.eventCenter.on("blank:click", (args) => {
this.closeCard()
})
})
},
closeCard() {
this.showApprovalCard = false
this.activeTabIndex = 0
},
// 获取任务状态文本
getTaskStateText(taskState) {
const stateMap = {
10: "进行中",
20: "已完成",
30: "已撤回"
}
return stateMap[taskState] || taskState
},
// 获取提交结果文本
getSubmitTypeText(submitType) {
const typeMap = {
0: "发起申请",
1: "同意申请",
2: "拒绝申请",
3: "退回上一步",
4: "跳转",
5: "重新提交",
6: "退回发起人",
20: "拒绝申请"
}
return typeMap[submitType] || submitType
}
},
mounted() {
if (this.defineId) {
this.getDetail()
}
if (this.instanceId) {
this.getHighLight()
this.getHisApproval()
}
}
})
</script>
</html>
@@ -0,0 +1,156 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.searchKeyword" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<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" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<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>
<fund-member-info ref="fundMemberInfoRef">
<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(2)" size="small" type="danger">拒绝申请</el-button>
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
</el-row>
</div>
</fund-member-info>
</template>
</guava>
</div>
<script>
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
pageForm: {
approval: false
},
formData: {},
showApprovalForm: false
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.fundMemberInfoRef.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()
}
})
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,100 @@
const fundMemberInfo = {
template: /*language=HTML*/ `
<div>
<div class="process-title">
申请信息
<el-link type="primary" @click="openChart">点击查看流程图</el-link>
</div>
<el-descriptions :column="2" border>
<el-descriptions-item label="姓名">{{viewData.userName}}</el-descriptions-item>
<el-descriptions-item label="工号">{{viewData.loginName}}</el-descriptions-item>
<el-descriptions-item label="性别">{{viewData.sex}}</el-descriptions-item>
<el-descriptions-item label="出生年月">{{viewData.birthday}}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{viewData.idCard}}</el-descriptions-item>
<el-descriptions-item label="参加工作时间">{{viewData.joinWorkTime}}</el-descriptions-item>
<el-descriptions-item label="退休时间">{{viewData.retireTime}}</el-descriptions-item>
<el-descriptions-item label="家庭住址">{{viewData.address}}</el-descriptions-item>
<el-descriptions-item label="手机电话">{{viewData.mobile}}</el-descriptions-item>
<el-descriptions-item label="住宅号码">{{viewData.homePhone}}</el-descriptions-item>
<el-descriptions-item label="照片">{{viewData.avatar}}</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/fundMember/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)
}
}
}
@@ -1,76 +1,85 @@
<!--#
layout("/layouts/platform.html"){
#-->
<guava ref="guava">
<div id="app">
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度" style="width: 100%"></el-date-picker>
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.title" placeholder="标题" clearable></el-input>
<el-input v-model="pageForm.searchKeyword" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"></el-table-column>
<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 type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></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>
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="row.taskKey === 'startTask'" @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button v-if="row.canRevoke" @click="onRevoke(row)" size="mini" type="danger">撤回</el-button>
<el-button @click="onDelete(row.id)" size="mini" type="danger">删除</el-button>
<el-button @click="exportDocx(row.id)" 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 @click="onDelete(row.id)" v-if="row.taskKey === 'startTask' || !row.instanceId"
size="mini" type="danger">删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
</guava>
<template #edit>
<fund-member-info ref="fundMemberInfoRef"></fund-member-info>
</template>
</guava>
</div>
<script>
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
pageDataUrl: "/platform/proposal/apply/pageData"
}
return {}
},
methods: {
openView(row) {
window.open("/flow/common/approval/form?" + "instanceId=" + (row.instanceId || "") + "&businessId=" + row.id)
this.$refs.guava.edit(() => {
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
onEdit(row) {
window.open(
"/flow/common/approval/form?taskId=" + (row.taskId || "") + "&instanceId=" + (row.instanceId || "") + "&businessId=" + row.id
)
commonUtil.pjaxPush('/platform/fundMember/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) => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
@@ -78,19 +87,23 @@ layout("/layouts/platform.html"){
})
})
},
onDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/proposal/apply/delete", { id }).then((res) => {
this.$axios.post("/platform/fundMember/mine/delete", {id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
exportDocx(id){
this.$downLoad("/platform/fundMember/common/exportDocx", {id})
}
},
created() {
@@ -0,0 +1,166 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="工号/姓名">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入工号或者姓名查询" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"
fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'instanceState'" scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<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>
<fund-member-info ref="fundMemberInfoRef">
<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(2)" size="small" type="danger">拒绝申请</el-button>
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
</el-row>
</div>
</fund-member-info>
</template>
</guava>
</div>
<script>
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
tableColumns: [
{label: "工号", prop: "loginName"},
{label: "姓名", prop: "userName"},
{label: "性别", prop: "sex"},
{label: "出生年月", prop: "birthday"},
{label: "当前节点", prop: "taskName"},
{label: "流程状态", prop: "instanceState"}
],
pageForm: {
approval: false
},
formData: {},
showApprovalForm: false
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.fundMemberInfoRef.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()
}
})
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,156 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" placeholder="年度"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="标题">
<el-input v-model="pageForm.searchKeyword" placeholder="标题" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<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" style="width: 100%">
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="300px">
<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>
<fund-member-info ref="fundMemberInfoRef">
<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(2)" size="small" type="danger">拒绝申请</el-button>
<el-button @click="handleTaskAction(1)" size="small" type="primary">同意申请</el-button>
</el-row>
</div>
</fund-member-info>
</template>
</guava>
</div>
<script>
<!--#include('../info.js'){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"fund-member-info": fundMemberInfo
},
data() {
return {
pageForm: {
approval: false
},
formData: {},
showApprovalForm: false
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.fundMemberInfoRef.onOpen(row)
})
},
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
processTaskId: row.taskId,
taskName: row.curTaskName
}
this.$refs.fundMemberInfoRef.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()
}
})
})
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,256 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<snaker-start slot="header" label="医疗互助基金会员入会申请" define_key="FUND_MEMBER"></snaker-start>
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="120px">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="姓名" prop="userName">
<el-input v-model="formData.userName" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工号" prop="loginName">
<el-input v-model="formData.loginName" placeholder="请输入工号" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="出生年月" prop="birthday">
<el-date-picker
v-model="formData.birthday"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择出生年月"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="sex" size="small">
<el-radio-group v-model="formData.sex">
<el-radio label="男" border></el-radio>
<el-radio label="女" border></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="身份证号码" prop="idCard">
<el-input v-model="formData.idCard" placeholder="请输入身份证号码"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="家庭住址" prop="address">
<el-input v-model="formData.address" placeholder="请输入家庭住址"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="参加工作时间" prop="joinWorkTime">
<el-date-picker
v-model="formData.joinWorkTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择参加工作时间"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="退休时间" prop="retireTime">
<el-date-picker
v-model="formData.retireTime"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择退休时间"
style="width: 100%"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="家庭住址" prop="address">
<el-input v-model="formData.address" placeholder="请输入家庭住址"></el-input>
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="住宅号码" prop="homePhone">
<el-input v-model="formData.homePhone" placeholder="请输入住宅电话"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="照 片">
<file-upload
style="--upload-width: 150px;--upload-height:176px"
:value.sync="formData.avatar"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item>
<el-checkbox v-model="isAgree">
本人自愿申请参加南昌大学教职工医疗互助“爱心”基金会,同意并遵守《南昌大学教职工医疗互助“爱心”基金管理办法》的相关规定。
</el-checkbox>
</el-form-item>
</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="onFinishTask" v-else>提交申请</el-button>
</el-row>
</el-card>
</div>
<script>
new Vue({
el: '#app',
store,
data() {
return {
bizId: GetQueryString("bizId"),
taskId: GetQueryString("taskId"),
formData: {},
formRules: {
userName: [{required: true, message: '请输入姓名', trigger: 'blur'}],
loginName: [{required: true, message: '请输入工资号', trigger: 'blur'}],
birthday: [{required: true, message: '请选择出生年月', trigger: 'blur'}],
sex: [{required: true, message: '请选择性别', trigger: 'blur'}],
idCard: [{required: true, message: '请输入身份证号码', trigger: 'blur'},
{
pattern: /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))([0-2][1-9]|3[0-1])\d{3}[Xx\d]$/,
message: '请输入正确的身份证号码',
trigger: 'blur'
}
],
address: [{required: true, message: '请输入家庭住址', trigger: 'blur'}],
joinWorkTime: [{required: true, message: '请选择参加工作时间', trigger: 'blur'}],
retireTime: [{required: true, message: '请选择退休时间', trigger: 'blur'}],
mobile: [{required: true, message: '请输入手机号码', trigger: 'blur'},
{
pattern: /^1[3456789]\d{9}$/,
message: '请输入正确的手机号码',
trigger: 'blur'
}],
homePhone: [{required: true, message: '请输入住宅号码', trigger: 'blur'},
{
pattern: /^(0\d{2,3}-?)?\d{7,8}$/,
message: '请输入正确的住宅号码',
trigger: 'blur'
}
],
avatar: [{required: false, message: '请上传照片', trigger: 'blur'}]
},
isAgree: false
}
},
methods: {
// 保存
// onSave() {
// this.$confirm("您确定保存吗?", "提示", {
// confirmButtonText: "确定",
// cancelButtonText: "取消",
// type: "warning"
// }).then(() => {
// this.$axios.post('/platform/suggestionBox/write/save', {data: JSON.stringify(this.formData)}).then(res => {
// if (res.code === 0) {
// this.$message.success("保存成功")
// commonUtil.pjaxPush('/platform/suggestionBox/mine')
// }
// })
// })
// },
// 提交
onSubmit() {
this.$refs.formRef.validate(valid => {
if (!valid) return
if (!this.isAgree) {
this.$message.error("请先阅读并同意《南昌大学教职工医疗互助“爱心”基金管理办法》")
return
}
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/fundMember/write/submit', {
data: JSON.stringify(this.formData)
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/fundMember/mine')
}
})
})
})
},
onFinishTask() {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/suggestionBox/write/submitAgain', {
data: JSON.stringify(this.formData),
taskId: GetQueryString("taskId")
}).then(res => {
if (res.code === 0) {
this.$message.success("提交成功")
commonUtil.pjaxPush('/platform/suggestionBox/mine')
}
})
})
},
// 初始化
init() {
if (this.bizId) {
this.$axios.post("/platform/fundMember/write/info", {id: this.bizId}).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
} else {
const {username, loginname, sex, birthday, mobile} = this.$store.state.user
this.formData = {
userName: username,
loginName: loginname,
sex: sex,
birthday: birthday,
mobile: mobile
}
}
}
},
created() {
this.init()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,78 @@
const basicForm = {
template: /*language=HTML*/ `
<div>
<el-dialog :title="formData.id ? '编辑':'新增'" :visible.sync="visible" width="40%" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="110px" label-position="left">
<el-form-item label="年度" prop="year">
<el-date-picker
v-model="formData.year"
type="year"
value-format="yyyy"
placeholder="请选择年度"
style="width: 100%"
></el-date-picker>
</el-form-item>
<el-form-item label="批次名称" prop="name">
<el-input type="text" v-model="formData.name" maxlength="50"
placeholder="请输入批次名称"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="$emit('refresh'); visible = false">取消</el-button>
<el-button @click="onSubmit" type="primary">提交</el-button>
</div>
</el-dialog>
</div>
`,
data() {
return {
formData: {
year: new Date().getFullYear().toString(),
},
formRules: {
year: [{required: true, message: '必填', trigger: ['blur']}],
name: [{required: true, message: '必填', trigger: ['blur']}],
},
visible: false,
}
},
methods: {
onOpen(row) {
if(row && row.id) {
this.$set(row, 'year', row.year.toString())
this.formData = clone(row)
} else {
this.formData = {
year: new Date().getFullYear().toString()
}
}
this.visible = true
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/retireSouvenirs/batch/submit", this.formData)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.$emit('refresh')
this.visible = false
} else {
this.$message.warning(resp.msg)
}
})
}
})
},
},
style: /*language=CSS*/ `
`
}
@@ -0,0 +1,163 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度:">
<el-date-picker
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="请选择年度"
@change="doSearch"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="批次名称:">
<el-input placeholder="请输入批次名称查询" clearable v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch">
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="批次列表">
<el-button type="primary" size="small" @click="onAdd">
<i class="ti-plus"></i>
新增批次
</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template v-slot="{ row }" v-if="column.prop === 'createdAt'">
{{ $moment(row.createdAt).format('YYYY-MM-DD') }}
</template>
</el-table-column>
<el-table-column label="操作" width="300">
<template v-slot="{ row }">
<el-dropdown style="margin-right: 10px">
<el-button type="primary" size="mini">
导入人员
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="onImport(row, 'clear')">清空</el-dropdown-item>
<el-dropdown-item @click.native="onImport(row, 'append')">追加</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button @click="onEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button @click="onDelete(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<basic-form ref="basicFormRef" @refresh="refresh"></basic-form>
<excel-import
ref="excelImportRef"
url="/platform/retireSouvenirs/batch/temImport"
template_url="/platform/retireSouvenirs/batch/downloadTem"
:visible.sync="importVisible"
title="导入人员名单"
width="700px"
:extra_params="importParams"
@import-success="doSearch"
></excel-import>
</guava>
</div>
<script>
<!--#include('basicForm.js'){}#-->
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"basic-form": basicForm,
},
data() {
return {
tableColumns: [
{prop: 'year', label: '年度'},
{prop: 'name', label: '批次名称'},
{prop: 'remark', label: '备注'},
{prop: 'userName', label: '创建人'},
{prop: 'createdAt', label: '创建时间'},
{prop: 'count', label: '关联人员数'},
],
importVisible: false,
importParams: {},
}
},
methods: {
onImport(row, type) {
this.importParams = {
batchId: row.id,
type: type
}
this.importVisible = true
},
refresh() {
this.doSearch()
this.$refs.guava.index()
},
onAdd() {
this.$refs.basicFormRef.onOpen()
},
onEdit(row) {
this.$refs.basicFormRef.onOpen(row)
},
onDelete(row) {
let msg = row.count > 0 ? '该批次下有' + row.count + '条数据,' : ''
this.$confirm(msg + "您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/retireSouvenirs/batch/delete", { id: row.id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
.catch(() => {})
},
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
},
async created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,383 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.search-other {
display: flex;
align-items: center;
}
.search-other-label {
width: 90px;
min-width: 90px;
color: rgb(100, 100, 100);
margin-right: 10px;
flex-shrink: 0;
}
.search-other > div {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.search-other .el-tag {
margin-right: 10px;
cursor: pointer;
}
.search-other .el-link {
margin-right: 10px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="批次名称:">
<el-select v-model="pageForm.batchId" @change="doSearch" style="width: 100%"
placeholder="请选择批次名称" filterable>
<el-option v-for="item in batchOptions"
:value="item.id"
:key="item.id"
:label="item.name"
></el-option>
</el-select>
</search-item>
<search-item label="退休年份:">
<el-date-picker
v-model="pageForm.year"
type="year"
value-format="yyyy"
placeholder="请选择退休年份"
@change="doSearch"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="退休月份:">
<el-date-picker
v-model="pageForm.month"
type="month"
value-format="MM"
placeholder="请选择退休月份"
@change="doSearch"
style="width: 100%"
></el-date-picker>
</search-item>
<search-item label="领取状态:">
<el-select v-model="pageForm.receive" @change="doSearch" style="width: 100%"
placeholder="请选择领取状态" filterable clearable>
<el-option :value="null" label="全部"></el-option>
<el-option :value="false" label="未领取"></el-option>
<el-option :value="true" label="已领取"></el-option>
</el-select>
</search-item>
<search-item label="工号/姓名:">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入工号或者姓名查询" clearable></el-input>
</search-item>
<search-item label="所属单位:">
<el-select @change="doSearch"
clearable
filterable
placeholder="请选择单位"
style="width: 100%"
v-model="pageForm.unitId">
<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 v-model="pageForm.unionId"
placeholder="请选择所属工会"
filterable
clearable
@change="doSearch"
style="width: 100%">
<el-option
v-for="item in unionOptions"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<div class="search-other">
<div class="search-other-label">快捷查询:</div>
<div>
<el-tag style="margin-right: 10px;cursor: pointer"
:effect="pageForm.selectTime === 'current' ? 'dark' : 'plain'"
@click="tagClick('current')">
当月未领取(退休时间在当前月份,并且未领取)
</el-tag>
<el-tag style="margin-right: 10px;cursor: pointer"
:effect="pageForm.selectTime === 'prev' ? 'dark' : 'plain'"
@click="tagClick('prev')">
逾期未领取(退休时间在当前月份之前,并且未领取)
</el-tag>
<el-link type="danger"
v-if="pageForm.selectTime !== ''"
:underline="false"
@click="tagClear">清空
</el-link>
</div>
</div>
</el-card>
<el-card shadow="never" class="mt20">
<table-tool label="人员列表">
<el-button type="primary" size="small" @click="onMsg" icon="el-icon-mobile-phone">短信提醒</el-button>
<el-button type="primary" size="small" @click="onExport" icon="el-icon-download">导出名单</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:width="column.width"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template v-slot="{ row }" v-if="column.prop === 'receive'">
<span v-if="row.receive === true" style="color: #15db81;">已领取</span>
<span v-else>未领取</span>
</template>
<template v-slot="{ row }" v-else-if="column.prop === 'msgCount'">
<el-link type="primary" @click="onMsgView(row)">{{ row.msgCount }}</el-link>
</template>
</el-table-column>
<el-table-column label="操作" width="200">
<template v-slot="{ row }">
<el-button v-if="row.receive === false" @click="onReceive(row)" size="mini" type="primary">设置领取</el-button>
<el-button v-if="row.receive === true" @click="onReceive(row)" size="mini" type="info">设置未领取</el-button>
<el-button @click="onDelete(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
<el-dialog title="短信提醒" :visible.sync="dialogVisible" width="40%" :close-on-click-modal="false">
<el-alert
:title="'当前查询条件筛选人数为:' + pageForm.totalCount + '人'"
type="info"
class="mb5"
effect="dark">
</el-alert>
<el-alert
title="发送内容示例:老师您好,您有退休纪念品还未领取,请于xx及时到xx领取。"
type="info"
class="mb20"
effect="dark">
</el-alert>
<el-input type="textarea" v-model="message" placeholder="请输入发送内容" :rows="4"></el-input>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doMsg">确 定</el-button>
</div>
</el-dialog>
<el-dialog title="短信发送记录" :visible.sync="msgDialogVisible" :close-on-click-modal="false">
<el-table :data="msgTableData" max-height="500" size="small">
<el-table-column label="序号" type="index" width="60"></el-table-column>
<el-table-column label="发送时间" prop="sendTime"></el-table-column>
<el-table-column label="发送内容" prop="message" show-overflow-tooltip></el-table-column>
<el-table-column label="发送人" prop="sendUserName"></el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="{ row }">
<el-button @click="onDeleteMsg(row)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="msgDialogVisible = false">取 消</el-button>
</div>
</el-dialog>
</div>
<script>
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
},
data() {
return {
pageForm: {
receive: null,
},
tableColumns: [
{prop: 'userName', label: '姓名'},
{prop: 'loginName', label: '工号'},
{prop: 'sex', label: '性别'},
{prop: 'mobile', label: '联系方式'},
{prop: 'unitName', label: '所属单位'},
{prop: 'unionName', label: '所属工会'},
{prop: 'retireTimeFormat', label: '退休时间'},
{prop: 'msgCount', label: '短信提醒次数'},
{prop: 'receive', label: '是否领取'},
],
batchOptions: [],
unitOptions: [],
unionOptions: [],
message: '',
dialogVisible: false,
msgRow: {},
msgTableData: {},
msgDialogVisible: false,
}
},
methods: {
onDeleteMsg(row) {
this.$confirm("您确定要删除短信记录吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/retireSouvenirs/ledger/deleteMsg", {
id: row.id,
})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.onMsgView(this.msgRow)
this.pageData()
} else {
this.$message.warning(resp.msg)
}
})
},
onMsgView(row) {
this.msgRow = row
this.$axios.post("/platform/retireSouvenirs/ledger/selectMsgList", {
'batchId': row.batchId,
'userId': row.userId,
}).then(resp => {
if (resp.code === 0) {
this.msgTableData = resp.data
this.msgDialogVisible = true
} else {
this.$message.warning(resp.msg)
}
})
},
onMsg() {
this.message = ''
this.dialogVisible = true
},
doMsg() {
if(!this.message) {
this.$message.warning('请输入发送内容')
return
}
this.$confirm("您确定要发送短信吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/retireSouvenirs/ledger/msg", {
'pageForm': JSON.stringify(this.pageForm),
'message': this.message,
}).then(resp => {
if (resp.code === 0) {
this.pageData()
this.$message.success(resp.msg)
this.dialogVisible = false
} else {
this.$message.warning(resp.msg)
}
})
})
},
tagClick(type) {
this.$set(this.pageForm, 'month', (new Date().getMonth() + 1).toString())
this.$set(this.pageForm, 'receive', false)
this.$set(this.pageForm, 'selectTime', type)
this.doSearch()
},
tagClear() {
this.$set(this.pageForm, 'month', '')
this.$set(this.pageForm, 'receive', null)
this.$set(this.pageForm, 'selectTime', '')
this.doSearch()
},
onExport() {
this.$downLoad(loc() + "/download", this.pageForm)
},
onReceive(row) {
this.$confirm("您确定要设置吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/retireSouvenirs/ledger/receive", { id: row.id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
.catch(() => {})
},
onDelete(row) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/retireSouvenirs/ledger/delete", { id: row.id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
.catch(() => {})
},
pageData() {
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
selectList() {
this.$axios.post("/platform/retireSouvenirs/batch/selectList").then((res) => {
if (res.code === 0) {
this.batchOptions = res.data
if(this.batchOptions.length > 0) {
this.$set(this.pageForm, 'batchId', this.batchOptions[0].id)
}
}
})
},
},
async created() {
this.selectList()
this.unionOptions = await this.$businessTool.listUnion()
this.unitOptions = await this.$businessTool.listUnit()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -12,6 +12,11 @@ layout("/layouts/platform.html"){
<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 unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
@@ -63,6 +68,7 @@ layout("/layouts/platform.html"){
pageForm: {
year: this.$moment().format("YYYY")
},
unionOptions: []
}
},
methods: {
@@ -73,6 +79,7 @@ layout("/layouts/platform.html"){
}
},
async created() {
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
this.pageData()
}
})
@@ -27,13 +27,13 @@ layout("/layouts/platform.html"){
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column prop="name" label="单位名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="code" label="单位编码" width="150px"></el-table-column>
<el-table-column prop="branchSchoolLeader" label="分管校领导及联系方式" width="180px"></el-table-column>
<!-- <el-table-column prop="branchSchoolLeader" label="分管校领导及联系方式" width="180px"></el-table-column>-->
<el-table-column prop="unitLeader" label="单位领导及联系方式" width="180px" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="350px">
<template slot-scope="{row}">
<el-link size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,true)">设置分管校领导</el-link>
<el-link size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,false)">设置单位领导</el-link>
<el-link size="mini" type="danger">删除</el-link>
<!-- <el-button size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,true)">设置分管校领导</el-button>-->
<el-button size="mini" type="primary" @click="$refs.userRef.onOpen(row.id,false)">设置单位领导</el-button>
<el-button size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -24,6 +24,7 @@ layout("/layouts/platform.html"){
display: flex;
align-items: center;
min-height: 80px;
position: relative;
}
.node-card:hover {
@@ -32,6 +33,16 @@ layout("/layouts/platform.html"){
cursor: pointer;
}
.node-card.selected {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
border-top-width: 4px;
}
.node-card.selected .node-icon {
transform: scale(1.1);
}
.node-icon {
width: 50px;
height: 50px;
@@ -64,14 +75,33 @@ layout("/layouts/platform.html"){
line-height: 1;
}
.node-card.selected {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
border-top-width: 4px;
.task-toggle {
position: absolute;
top: 8px;
right: 8px;
display: flex;
background: rgba(255, 255, 255, 0.9);
padding: 2px;
}
.node-card.selected .node-icon {
transform: scale(1.1);
.task-toggle-btn {
padding: 4px 8px;
font-size: 12px;
border: none;
background: transparent;
color: #666;
cursor: pointer;
transition: all 0.2s ease;
min-width: 36px;
}
.task-toggle-btn.active {
background: var(--theme-color);
color: #fff;
}
.task-toggle-btn:hover:not(.active) {
background: rgba(0, 0, 0, 0.05);
}
@media (max-width: 768px) {
@@ -131,12 +161,30 @@ layout("/layouts/platform.html"){
:style="'--theme-color:' + getThemeColor(index)"
@click="selectNode(node,index)"
>
<!-- task类型节点的切换按钮 -->
<div v-if="node.type === 'task'" class="task-toggle" @click.stop>
<button
class="task-toggle-btn"
:class="{ active: getNodeDisplayMode(node.id) === 'todo' }"
@click="setNodeDisplayMode(node, 'todo')"
>
待办
</button>
<button
class="task-toggle-btn"
:class="{ active: getNodeDisplayMode(node.id) === 'done' }"
@click="setNodeDisplayMode(node, 'done')"
>
已办
</button>
</div>
<div class="node-icon">
<i class="fa fa-tasks"></i>
</div>
<div class="node-content">
<div class="node-name">{{ node.name || '未命名节点' }}</div>
<div class="node-count">{{ node.count || 0 }}</div>
<div class="node-count">{{ getNodeCount(node) }}</div>
</div>
</div>
</div>
@@ -202,6 +250,7 @@ layout("/layouts/platform.html"){
return {
sessionOptions: [],
nodes: [],
nodeDisplayModes: {}, // 存储每个节点的显示模式
pageForm: {
selectNodeId: null,
selectNodeType: null,
@@ -256,7 +305,28 @@ layout("/layouts/platform.html"){
selectNode(node, index) {
this.pageForm.selectNodeId = node.id
this.pageForm.selectNodeType = node.type
this.pageForm.selectNodeMode = this.getNodeDisplayMode(node.id)
this.doSearch()
},
// 获取节点显示数量
getNodeCount(node) {
if (node.type === 'task') {
const displayMode = this.getNodeDisplayMode(node.id)
return displayMode === 'todo' ? (node.todoCount || 0) : (node.doneCount || 0)
}
return node.count || 0
},
// 获取节点显示模式
getNodeDisplayMode(nodeId) {
return this.nodeDisplayModes[nodeId] || 'todo' // 默认显示待办
},
// 设置节点显示模式
setNodeDisplayMode(node, mode) {
this.$set(this.nodeDisplayModes, node.id, mode)
this.selectNode(node, null)
}
},
computed: {
@@ -3,9 +3,7 @@ layout("/layouts/platform.html"){
#-->
<style>
.el-tag {
cursor: pointer;
}
</style>
<div id="app" v-cloak>
@@ -13,102 +11,93 @@ 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%"
></el-input>
</search-item>
<search-item label="提案人工号">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人工号"
v-model="pageForm.createUserLoginName"
style="width: 100%"
></el-input>
<search-item label="姓名/工号:">
<el-input placeholder="请输入提案人姓名或工号查询" clearable
v-model="pageForm.createUserKeyword"></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 multiple placeholder="提案类别" v-model="pageForm.typeIds">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in typeOptions"></el-option>
</el-select>
</search-item>
<search-item label="立案结果">
<el-select clearable filterable multiple placeholder="立案结果"
v-model="pageForm.caseFilingResults">
<el-option :key="item.code" :label="item.label" :value="item.code"
v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"></el-option>
</el-select>
</search-item>
<search-item label="征集阶段">
<el-select v-model="pageForm.collectIds" clearable multiple filterable>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in collectOptions"></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;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)"
>
{{ 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;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)"
>
{{ item.label }}
</el-tag>
</div>
</div>
</el-card>
<el-card shadow="never">
<table-tool></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>
<el-table-column label="提案编号" prop="code" width="120px" sortable></el-table-column>
<el-table-column label="提案名称" prop="name" show-overflow-tooltip></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="seconderSum"></el-table-column>
<el-table-column label="已附议" prop="completeCount"></el-table-column>
<el-table-column label="当前节点" prop="processInstanceNodeName"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'instanceState'" 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="100px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="openView(row)">查看</el-button>
@@ -128,7 +117,7 @@ layout("/layouts/platform.html"){
<!--#include("../../common/info.js"){}#-->
new Vue({
el: "#app",
dicts: ["PROPOSAL_TYPE", "PROPOSAL_CASE_FILING_RESULT"],
dicts: ["PROPOSAL_TYPE", "PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE"],
store,
mixins: [initTableMixins],
components: {
@@ -136,6 +125,16 @@ layout("/layouts/platform.html"){
},
data() {
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案人", prop: "createUserName"},
{label: "代表团", prop: "delegationName"},
{label: "邀请附议人数", prop: "inviteCount"},
{label: "已附议人数", prop: "finishCount"},
{label: "当前节点", prop: "curTaskName"},
{label: "流程状态", prop: "instanceState"}
],
sessionOptions: [],
collectOptions: [],
typeOptions: [],
@@ -147,7 +146,8 @@ layout("/layouts/platform.html"){
typeIds: [],
caseFilingResults: [],
unionId: null,
unitId: null
unitId: null,
collectIds: []
}
}
},
@@ -157,14 +157,6 @@ layout("/layouts/platform.html"){
this.$refs.infoRef.onOpen(row)
})
},
tagToggle(key, val) {
if (this.pageForm[key].includes(val)) {
this.pageForm[key].splice(this.pageForm[key].indexOf(val), 1)
} else {
this.pageForm[key].push(val)
}
this.doSearch()
},
listCollectState() {
this.$axios.post("/platform/proposal/query/collectProgress/collectState").then((res) => {
@@ -187,7 +179,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
}
@@ -37,43 +37,62 @@ layout("/layouts/platform.html"){
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%"
></el-input>
</search-item>
<search-item label="提案人工号">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人工号"
v-model="pageForm.createUserLoginName"
style="width: 100%"
></el-input>
<search-item label="姓名/工号:">
<el-input placeholder="请输入提案人姓名或工号查询" clearable
v-model="pageForm.createUserKeyword"></el-input>
</search-item>
<!-- <search-item label="提案人姓名">-->
<!-- <el-input-->
<!-- @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%"-->
<!-- ></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-select>
</search-item>
<search-item label="提案分工会">
<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>
</search-item>
<search-item label="提案单位">
<el-select clearable filterable placeholder="提案单位" v-model="pageForm.unitId">
<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-select>
</search-item>
<search-item label="提案类别">
<el-select clearable filterable multiple placeholder="提案类别" v-model="pageForm.typeIds">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in typeOptions"></el-option>
</el-select>
</search-item>
<search-item label="立案结果">
<el-select clearable filterable multiple placeholder="立案结果" v-model="pageForm.caseFilingResults">
<el-option :key="item.code" :label="item.label" :value="item.code" v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"></el-option>
</el-select>
</search-item>
<search-item label="立案类型">
<el-select clearable filterable multiple placeholder="立案类型" v-model="pageForm.caseFilingTypes">
<el-option :key="item.code" :label="item.label" :value="item.code" v-for="item in dict.type.PROPOSAL_CASE_FILING_TYPE"></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>-->
@@ -81,78 +100,30 @@ layout("/layouts/platform.html"){
<!-- </search-item>-->
</search>
</el-card>
<el-card shadow="never" :body-style="{'padding-top': '0','padding-bottom': '0'}">
<div style="display: flex; align-items: center; min-height: 70px; border-bottom: 1px dashed rgb(230, 230, 230)">
<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)"
>
{{ 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;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)"
>
{{ item.label }}
</el-tag>
</div>
</div>
<div style="display: flex; align-items: center; min-height: 70px;">
<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_TYPE"
:key="item.code"
:effect="pageForm.caseFilingTypes && pageForm.caseFilingTypes.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingTypes',item.code)"
>
{{ item.label }}
</el-tag>
</div>
</div>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" ref="tableRef" style="width: 100%" row-key="id">
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" ref="tableRef"
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="100px" show-overflow-tooltip></el-table-column>
<el-table-column label="提案名称" prop="name" show-overflow-tooltip></el-table-column>
<el-table-column label="提案人" prop="createUserName"></el-table-column>
<el-table-column label="提案类别" prop="typeName"></el-table-column>
<el-table-column label="代表团" prop="delegationName"></el-table-column>
<el-table-column label="立案结果" prop="caseFilingResult">
<template scope="{row}">
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'caseFilingResult'" scope="{row}">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="row.caseFilingResult"></dict-tag>
</template>
</el-table-column>
<el-table-column label="立案类型" prop="caseFilingType">
<template scope="{row}">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_TYPE"
:value="row.caseFilingType"></dict-tag>
</template>
</el-table-column>
<el-table-column label="是否并案" prop="merge">
<template slot-scope="{row}">
<template v-else-if="column.prop === 'merge'" scope="{row}">
<el-tag v-if="row.merge" size="small"></el-tag>
</template>
</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}">
<template v-else-if="column.prop === 'instanceState'" scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
@@ -185,6 +156,20 @@ layout("/layouts/platform.html"){
},
data() {
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案人", prop: "createUserName"},
{label: "提案类别", prop: "typeName"},
{label: "代表团", prop: "delegationName"},
{label: "立案结果", prop: "caseFilingResult"},
{label: "立案类型", prop: "caseFilingType"},
{label: "是否并案", prop: "merge"},
{label: "主办单位", prop: "masterUnitName"},
{label: "协办单位", prop: "slaveUnitNames"},
{label: "当前节点", prop: "curTaskName"},
{label: "流程状态", prop: "instanceState"}
],
sessionOptions: [],
typeOptions: [],
delegationOptions: [],
@@ -68,6 +68,21 @@ 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 multiple placeholder="提案类别" v-model="pageForm.typeIds">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in typeOptions"></el-option>
</el-select>
</search-item>
<search-item label="立案结果">
<el-select clearable filterable multiple placeholder="立案结果" v-model="pageForm.caseFilingResults">
<el-option :key="item.code" :label="item.label" :value="item.code" v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"></el-option>
</el-select>
</search-item>
<search-item label="立案类型">
<el-select clearable filterable multiple placeholder="立案类型" v-model="pageForm.caseFilingTypes">
<el-option :key="item.code" :label="item.label" :value="item.code" v-for="item in dict.type.PROPOSAL_CASE_FILING_TYPE"></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>-->
@@ -75,47 +90,6 @@ layout("/layouts/platform.html"){
<!-- </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;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)"
>
{{ 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;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)"
>
{{ item.label }}
</el-tag>
</div>
</div>
<div style="display: flex; align-items: center; min-height: 70px;">
<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_TYPE"
:key="item.code"
:effect="pageForm.caseFilingTypes && pageForm.caseFilingTypes.includes(item.code) ? 'dark':'plain'"
@click="tagToggle('caseFilingTypes',item.code)"
>
{{ item.label }}
</el-tag>
</div>
</div>
</el-card>
<el-card shadow="never">
<table-tool></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%" row-key="id">
@@ -73,36 +73,23 @@ layout("/layouts/platform.html"){
<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 multiple placeholder="提案类别" v-model="pageForm.typeIds">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in typeOptions"></el-option>
</el-select>
</search-item>
<search-item label="立案结果">
<el-select clearable filterable multiple placeholder="立案结果" v-model="pageForm.caseFilingResults">
<el-option :key="item.code" :label="item.label" :value="item.code" v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT"></el-option>
</el-select>
</search-item>
<search-item label="立案类型">
<el-select clearable filterable multiple placeholder="立案类型" v-model="pageForm.caseFilingTypes">
<el-option :key="item.code" :label="item.label" :value="item.code" v-for="item in dict.type.PROPOSAL_CASE_FILING_TYPE"></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;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)"
>
{{ 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;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)"
>
{{ item.label }}
</el-tag>
</div>
</div>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button type="primary" size="small" @click="exportYearReport">导出提案报告</el-button>
@@ -1,309 +0,0 @@
<div id="proposal-transact-apply-form">
<el-form :model="formData" ref="formRef" :rules="formRules" label-width="0" label-suffix="" class="flow-task-form">
<el-descriptions :column="2" border>
<el-descriptions-item label="姓名">
<el-form-item>
<el-input :value="formData.createUserName" disabled></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="工号">
<el-form-item>
<el-input :value="formData.createUserLoginName" disabled></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="单位">{{formData.unitName}}</el-descriptions-item>
<el-descriptions-item label="联系电话">
<el-form-item label="联系电话" prop="mobile">
<el-input v-model="formData.mobile" clearable placeholder="联系电话"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属教代会">
<el-form-item label="所属教代会" prop="sessionId">
<el-select @change="meetingChange" clearable filterable placeholder="所属教代会" v-model="formData.sessionId" style="width: 100%">
<el-option :key="item.id" :label="item.fullName" :value="item.id" v-for="item in sessionOptions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属代表团">
<el-form-item label="所属代表团" prop="delegationId">
<el-select clearable filterable placeholder="所属代表团" v-model="formData.delegationId" style="width: 100%" disabled>
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in delegationOptions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="所属委员会" v-if="formData.mannerCode=='W03'" :span="2">
<el-form-item label="所属委员会" prop="committeeId">
<el-select clearable filterable placeholder="所属委员会" v-model="formData.committeeId" style="width: 100%">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in committeeOptions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="提案名称" :span="2">
<el-form-item label="提案名称" prop="name">
<el-input maxlength="100" placeholder="提案名称" v-model="formData.name"></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="提案方式" :span="2">
<el-form-item label="提案方式" prop="source">
<el-select v-model="formData.source" style="width: 100%">
<el-option :key="item.code" :label="item.name" :value="item.code" v-for="item in sourceOptions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="提案类别" :span="2">
<el-form-item label="提案类别" prop="typeId">
<el-select v-model="formData.typeId" style="width: 100%">
<el-option :key="item.code" :label="item.name" :value="item.id" v-for="item in typeOptions"></el-option>
</el-select>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="提案摘要" :span="2">
<el-form-item label="提案摘要" prop="excerpt">
<span slot="label">
提案摘要
<el-tooltip content="请简述提案内容和依据、改进建议和措施摘要" placement="right">
<i class="el-icon-question"></i>
</el-tooltip>
</span>
<el-input
v-model="formData.excerpt"
type="textarea"
autosize
:autosize="{ minRows: 4, maxRows: 4}"
placeholder="提案摘要"
></el-input>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="提案内容和依据" :span="2">
<el-form-item label="提案内容和依据" prop="brief">
<text-editor v-model="formData.brief" key="brief" placeholder="提案内容和依据"></text-editor>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="提案改进建议和措施" :span="2">
<el-form-item label="改进建议和措施" prop="measures">
<text-editor v-model="formData.measures" key="measures" placeholder="改进建议和措施"></text-editor>
</el-form-item>
</el-descriptions-item>
<el-descriptions-item label="提案附件" :span="2">
<el-form-item label="附件上传" prop="files">
<file-upload
:value.sync="formData.files"
:upload_number="5"
upload_result_category="array"
upload_mode="drag"
complete_result
></file-upload>
</el-form-item>
</el-descriptions-item>
</el-descriptions>
</el-form>
<snaker-flow-task-form-action @task-action="handleTaskAction" @save-draft="handleSaveDraft"></snaker-flow-task-form-action>
</div>
<script>
new Vue({
el: "#proposal-transact-apply-form",
store,
data() {
return {
businessId: GetQueryString("businessId"),
instanceId: GetQueryString("instanceId"),
formData: {},
sessionOptions: [],
sourceOptions: [],
delegationOptions: [],
committeeOptions: [],
typeOptions: [],
formRules: {
createUserName: [{ required: true, message: "请填写提案人", trigger: ["blur", "change"] }],
createTime: [{ required: true, message: "请填写提案时间", trigger: ["blur", "change"] }],
name: [{ required: true, message: "请填写提案名称", trigger: ["blur", "change"] }],
source: [{ required: true, message: "请选择提案方式", trigger: ["blur", "change"] }],
delegationId: [{ required: true, message: "请选择所属代表团", trigger: ["blur", "change"] }],
sessionId: [{ required: true, message: "请选择所属教代会", trigger: ["blur", "change"] }],
committeeId: [{ required: true, message: "请选择所属委员会", trigger: ["blur", "change"] }],
typeId: [{ required: true, message: "请选择提案类别", trigger: ["blur", "change"] }],
implementUnitId: [{ required: false, message: "请选择建以落实部门", trigger: ["blur", "change"] }],
sign: [{ required: true, message: "请扫描二维码进行签字", trigger: ["blur", "change"] }],
excerpt: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
brief: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
measures: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
unitName: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
mobile: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
signature: [{ required: true, message: "请扫描二维码进行签字", trigger: ["blur", "change"] }]
}
}
},
methods: {
handleTaskAction(val) {
console.log(val)
this.$refs.formRef.validate((valid) => {
if (valid) {
if (!this.instanceId) {
this.handleApply(val)
} else {
this.handleReApply(val)
}
}
})
},
// 提交申请
handleApply(val) {
this.$axios
.post("/flow/common/startInstanceAndExecute", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
window.GlobalBroadcastChannel.postMessage({
type: "task-complete"
})
commonUtil.pjaxPush("/platform/proposal/apply/index")
}
})
},
// 重新提交申请
handleReApply(val) {
this.$axios
.post("/flow/common/executeTask", {
data: JSON.stringify({
processTaskId: val.taskId,
processInstanceId: val.instanceId,
submitType: val.submitType,
f_data: JSON.stringify(this.formData)
})
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
window.GlobalBroadcastChannel.postMessage({
type: "task-complete"
})
}
})
},
// 保存申请
handleSaveDraft(val) {
this.$refs.formRef.validateField(["excerpt"], (errMsg) => {
if (errMsg) {
return
}
this.$axios
.post("/flow/common/startInstance", {
...val,
bizData: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
commonUtil.pjaxPush("/platform/proposal/apply/index")
}
})
})
},
// 教代会change
async meetingChange(val) {
this.formData.delegationId = null
this.formData.committeeId = null
this.listDelegation()
this.searchMineDelegation()
// this.delegationOptions = await proposal.getDelegation(val)
// this.committeeOptions = await this.getInstitutions(val)
},
// 查询开启的教代会
listOpenSession(isModify = false) {
this.$axios.post("/platform/proposal/common/listOpenSession").then(async (res) => {
if (res.code === 0) {
this.sessionOptions = res.data
if (this.sessionOptions.length === 0) {
this.$message.error("没有教代会信息")
return
}
if (!isModify && this.sessionOptions && this.sessionOptions.length) {
this.$set(this.formData, "sessionId", this.sessionOptions[0].id)
await this.searchMineDelegation()
}
await this.listDelegation()
await this.listSource()
}
})
},
// 查询代表团
listDelegation() {
return this.$axios.post("/platform/proposal/common/listDelegation", { sessionId: this.formData.sessionId }).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
}
})
},
//查询自己有权限的撰写方式
listSource() {
return this.$axios.post("/platform/proposal/write/listSource", { sessionId: this.formData.sessionId }).then((res) => {
if (res.code === 0) {
this.sourceOptions = res.data
}
})
},
//查询自己有权限的代表团
searchMineDelegation() {
return this.$axios.post("/platform/proposal/write/searchMineDelegation", { sessionId: this.formData.sessionId }).then((res) => {
if (res.code === 0) {
this.$set(this.formData, "delegationId", res.data)
}
})
},
// 获取提案类型
listProposalType() {
this.$axios.post("/platform/proposal/common/listProposalType").then((res) => {
if (res.code === 0) {
this.typeOptions = res.data
}
})
},
// 初始化
init() {
this.listProposalType()
if (this.businessId) {
this.$axios.post("/platform/proposal/apply/info", { id: this.businessId }).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.listOpenSession(true)
}
})
} else {
this.listOpenSession(false)
this.$set(this.formData, "createUserId", this.$store.state.user.id)
this.$set(this.formData, "createUserName", this.$store.state.user.username)
this.$set(this.formData, "createUserLoginName", this.$store.state.user.loginname)
this.$set(this.formData, "createTime", this.$moment().format("YYYY-MM-DD"))
this.$set(this.formData, "mobile", this.$store.state.user.mobile)
this.$set(this.formData, "unitName", this.$store.state.user.unit?.name)
}
}
},
created() {
this.init()
}
})
</script>
@@ -0,0 +1,219 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<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>
</search-item>
<search-item label="提案编号">
<el-input v-model="pageForm.code" placeholder="提案编号" @keyup.enter.native="doSearch" clearable
style="width: 100%"></el-input>
</search-item>
<search-item label="提案名称">
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
style="width: 100%"></el-input>
</search-item>
<search-item label="姓名/工号:">
<el-input placeholder="请输入提案人姓名或工号查询" clearable
v-model="pageForm.createUserKeyword"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool :columns.sync="tableColumns">
<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" ref="tableRef" row-key="id" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"
fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'caseFilingResult'" scope="{row}">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="row.caseFilingResult"></dict-tag>
</template>
<template v-else-if="column.prop === 'merge'" scope="{row}">
<el-tag v-if="row.merge" size="small"></el-tag>
</template>
<template v-else-if="column.prop === 'instanceState'" 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 slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">查看</el-button>
<el-button v-if="!row.pcoId" @click="openAudit(row)" size="mini" type="primary">审核</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #edit>
<proposal-info ref="proposalInfoRef">
<div v-if="showApprovalForm">
<div class="process-title">
提案委员会成员意见
</div>
<el-form :model="formData" ref="formRef" label-width="120px" :rules="formRules" label-suffix="">
<el-form-item label="立案结果" prop="caseFilingResult"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-radio-group v-model="formData.caseFilingResult" size="small">
<el-radio v-for="item in dict.type.PROPOSAL_CASE_FILING_RESULT" :label="item.code"
border>{{item.label}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="['CONFIRM_FILING'].includes(formData.caseFilingResult)" label="立案类型"
prop="caseFilingType"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<el-radio-group v-model="formData.caseFilingType" size="small">
<el-radio v-for="item in dict.type.PROPOSAL_CASE_FILING_TYPE" :label="item.code" border>
{{item.label}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="审核意见" prop="opinion"
:rules="[{required:true,message:'必填',trigger:['change','blur']}]">
<user-opinion-textarea v-model="formData.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="doSubmit" size="small" type="primary">提交</el-button>
</el-row>
</div>
</proposal-info>
</template>
</guava>
</div>
<script>
<!--#include('../../common/info.js'){}#-->
new Vue({
el: "#app",
store,
dicts: ["PROPOSAL_CASE_FILING_RESULT", "PROPOSAL_CASE_FILING_TYPE"],
mixins: [initTableMixins],
components: {
"proposal-info": PROPOSAL_INFO
},
data() {
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案类别", prop: "typeName"},
{label: "届次", prop: "sessionName"},
{label: "代表团", prop: "delegationName"},
{label: "立案票数", prop: "CONFIRM_FILING_COUNT"},
{label: "作为建议票数", prop: "SUGGESTION_COUNT"},
{label: "不予立案票数", prop: "NOT_COUNT"},
{label: "当前节点", prop: "taskName"},
{label: "流程状态", prop: "instanceState"}
],
pageForm: {
approval: false
},
formData: {
tf_masterUnitId: null,
tf_slaveUnitIds: []
},
showApprovalForm: false,
sessionOptions: [],
delegationOptions: [],
underTakeOptions: []
}
},
methods: {
openView(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = false
this.$refs.proposalInfoRef.onOpen(row)
})
},
// 审批
openAudit(row) {
this.$refs.guava.edit(() => {
this.showApprovalForm = true
this.formData = {
proposalId: row.id,
caseFilingResult: null,
caseFilingType: null,
opinion: null
}
this.$refs.proposalInfoRef.onOpen(row)
})
},
doSubmit() {
this.$refs.formRef.validate(async (valid) => {
if (!valid) return
this.$confirm("您确定要提交吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post('/platform/proposal/commissioner/doApproval', this.formData).then(res => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
this.$refs.guava.index()
}
})
})
})
},
// 教代会
async meetingChange(val) {
this.doSearch()
},
// 查询开启的教代会
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()
}
}
})
},
},
created() {
this.pageData()
this.listOpenSession()
}
})
</script>
<!--#
}
#-->
@@ -21,24 +21,27 @@ layout("/layouts/platform.html"){
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
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%"
></el-input>
</search-item>
<search-item label="提案人工号">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人工号"
v-model="pageForm.createUserLoginName"
style="width: 100%"
></el-input>
<search-item label="姓名/工号:">
<el-input placeholder="请输入提案人姓名或工号查询" clearable v-model="pageForm.createUserKeyword"></el-input>
</search-item>
<!-- <search-item label="提案人姓名">-->
<!-- <el-input-->
<!-- @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%"-->
<!-- ></el-input>-->
<!-- </search-item>-->
</search>
</el-card>
@@ -51,6 +54,7 @@ layout("/layouts/platform.html"){
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" ref="tableRef" row-key="id" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod" fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
@@ -178,7 +182,7 @@ layout("/layouts/platform.html"){
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案类别", prop: "typeName"},
{label: "届次", prop: "sessionName"},
{label: "代表团", prop: "delegationName"},
@@ -17,6 +17,9 @@ layout("/layouts/platform.html"){
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
style="width: 100%"></el-input>
</search-item>
<search-item label="姓名/工号:">
<el-input placeholder="请输入提案人姓名或工号查询" clearable v-model="pageForm.createUserKeyword"></el-input>
</search-item>
</search>
</el-card>
@@ -28,6 +31,7 @@ layout("/layouts/platform.html"){
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod" fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
@@ -102,7 +106,7 @@ layout("/layouts/platform.html"){
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案类别", prop: "typeName"},
{label: "届次", prop: "sessionName"},
{label: "代表团", prop: "delegationName"},
@@ -21,24 +21,6 @@ layout("/layouts/platform.html"){
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
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%"
></el-input>
</search-item>
<search-item label="提案人工号">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人工号"
v-model="pageForm.createUserLoginName"
style="width: 100%"
></el-input>
</search-item>
</search>
</el-card>
@@ -51,19 +33,28 @@ layout("/layouts/platform.html"){
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"></el-table-column>
<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 label="是否并案" prop="merge">
<template slot-scope="{row}">
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'caseFilingResult'" scope="{row}">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="row.caseFilingResult"></dict-tag>
</template>
<template v-else-if="column.prop === 'merge'" scope="{row}">
<el-tag v-if="row.merge" size="small"></el-tag>
</template>
</el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<template v-else-if="column.prop === 'underTakeIsMaster'" scope="{row}">
<el-tag v-if="row.underTakeIsMaster" size="small">主办</el-tag>
<el-tag v-else type="warning" size="small">协办</el-tag>
</template>
<template v-else-if="column.prop === 'instanceState'" scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
@@ -135,6 +126,14 @@ layout("/layouts/platform.html"){
},
data() {
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案类别", prop: "typeName"},
{label: "是否并案", prop: "merge"},
{label: "当前节点", prop: "curTaskName"},
{label: "流程状态", prop: "instanceState"}
],
pageForm: {
approval: false
},
@@ -21,24 +21,27 @@ layout("/layouts/platform.html"){
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
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%"
></el-input>
</search-item>
<search-item label="提案人工号">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入提案人工号"
v-model="pageForm.createUserLoginName"
style="width: 100%"
></el-input>
<search-item label="姓名/工号:">
<el-input placeholder="请输入提案人姓名或工号查询" clearable v-model="pageForm.createUserKeyword"></el-input>
</search-item>
<!-- <search-item label="提案人姓名">-->
<!-- <el-input-->
<!-- @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%"-->
<!-- ></el-input>-->
<!-- </search-item>-->
</search>
</el-card>
@@ -50,20 +53,29 @@ layout("/layouts/platform.html"){
</el-radio-group>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"></el-table-column>
<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 label="是否并案" prop="merge">
<template slot-scope="{row}">
<el-table-column label="序号" width="50" type="index" :index="indexMethod" fixed="left"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.key"
:min-width="column.width"
:fixed="column.fixed"
show-overflow-tooltip
v-for="column in tableColumns"
v-if="column.visible !== false"
>
<template v-if="column.prop === 'caseFilingResult'" scope="{row}">
<dict-tag :options="dict.type.PROPOSAL_CASE_FILING_RESULT"
:value="row.caseFilingResult"></dict-tag>
</template>
<template v-else-if="column.prop === 'merge'" scope="{row}">
<el-tag v-if="row.merge" size="small"></el-tag>
</template>
</el-table-column>
<el-table-column prop="curTaskName" label="当前节点"></el-table-column>
<el-table-column prop="instanceState" label="流程状态">
<template slot-scope="{row}">
<template v-else-if="column.prop === 'underTakeIsMaster'" scope="{row}">
<el-tag v-if="row.underTakeIsMaster" size="small">主办</el-tag>
<el-tag v-else type="warning" size="small">协办</el-tag>
</template>
<template v-else-if="column.prop === 'instanceState'" scope="{row}">
<enum-tag :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message"
size="small"></enum-tag>
</template>
@@ -118,6 +130,14 @@ layout("/layouts/platform.html"){
},
data() {
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案类别", prop: "typeName"},
{label: "是否并案", prop: "merge"},
{label: "当前节点", prop: "curTaskName"},
{label: "流程状态", prop: "instanceState"}
],
pageForm: {
approval: false
},
@@ -17,6 +17,9 @@ layout("/layouts/platform.html"){
<el-input v-model="pageForm.name" placeholder="提案名称" @keyup.enter.native="doSearch" clearable
style="width: 100%"></el-input>
</search-item>
<search-item label="姓名/工号:">
<el-input placeholder="请输入提案人姓名或工号查询" clearable v-model="pageForm.createUserKeyword"></el-input>
</search-item>
</search>
</el-card>
@@ -79,7 +82,7 @@ layout("/layouts/platform.html"){
return {
tableColumns: [
{label: "提案编号", prop: "code"},
{label: "提案名称", prop: "name"},
{label: "提案名称", prop: "name", width: "200px"},
{label: "提案类别", prop: "typeName"},
{label: "届次", prop: "sessionName"},
{label: "代表团", prop: "delegationName"},
@@ -18,7 +18,7 @@ layout("/layouts/platform.html"){
<table-tool></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="标题"></el-table-column>
<el-table-column prop="title" label="标题" min-width="300px"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
@@ -1,59 +1,57 @@
var AddForm = {
template: `
<el-dialog title="新增代表" :visible.sync="dialogFormVisible" width="70%" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="120px" :rules="formRules">
<el-form-item prop="sessionId" label="届次">
<el-select v-model="formData.sessionId"
style="width: 100%"
placeholder="代表所属教代会"
@change="sessionChange">
<el-option v-for="item in sessionOptions"
:key="item.id"
:label="item.fullName"
:value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="delegationId" label="代表团">
<el-select v-model="formData.delegationId" filterable @change="delegationChange" clearable style="width: 100%">
<el-option v-for="i in delegationOptions"
:label="i.name"
:key="i.id"
:value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="roleId" label="代表类型">
<el-select v-model="formData.roleId" filterable style="width: 100%">
<el-option v-for="i in roleOptions"
:label="i.name"
:key="i.id"
:value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="userIds" label="用户">
<user-select v-model="formData.userIds"
v-if="dialogFormVisible"
api="/platform/teacherCongress/delegate/manage/publicUser"
:api_params="{sessionId:formData.sessionId,delegationId:formData.delegationId}"
api_input_key_name="keyWord"
:option_label_func="(item)=>{return item.userName + item.loginName + '(' + item.unitName + ')'}"
:multiple="true"
style="width: 100%"></user-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
const AddForm = {
template: /*language=HTML*/ `
<el-dialog title="新增代表" :visible.sync="dialogFormVisible" width="70%" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="120px" :rules="formRules">
<el-form-item prop="sessionId" label="届次">
<el-select v-model="formData.sessionId"
style="width: 100%"
placeholder="代表所属教代会"
@change="sessionChange">
<el-option v-for="item in sessionOptions"
:key="item.id"
:label="item.fullName"
:value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="delegationId" label="代表团">
<el-select v-model="formData.delegationId" filterable @change="delegationChange" clearable
style="width: 100%">
<el-option v-for="i in delegationOptions"
:label="i.name"
:key="i.id"
:value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="roleId" label="代表类型">
<el-select v-model="formData.roleId" filterable style="width: 100%">
<el-option v-for="i in roleOptions"
:label="i.name"
:key="i.id"
:value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="userIds" label="用户">
<user-select v-model="formData.userIds"
v-if="dialogFormVisible"
api="/platform/teacherCongress/delegate/manage/publicUser"
:api_params="{sessionId:formData.sessionId,delegationId:formData.delegationId}"
api_input_key_name="keyWord"
:option_label_func="(item)=>{return item.userName + item.loginName + '(' + item.unitName + ')'}"
:multiple="true"
style="width: 100%"></user-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
`,
data() {
return {
dialogFormVisible: false,
formData: {
userIds: [],
sessionId: null,
delegationId: null,
roleId: null
userIds: [], sessionId: null, delegationId: null, roleId: null
},
formRules: {
sessionId: [{required: true, message: "必填", trigger: ["change", "blur"]}],
@@ -72,10 +70,7 @@
return
}
this.formData = {
userIds: [],
sessionId: sessionId,
delegationId: delegationId,
roleId: null
userIds: [], sessionId: sessionId, delegationId: delegationId, roleId: null
}
this.listSession()
@@ -131,7 +126,6 @@
}
})
}
},
created() {
}, created() {
}
}
@@ -0,0 +1,116 @@
const editForm = {
template: /*language=HTML*/ `
<el-dialog title="编辑代表" :visible.sync="dialogFormVisible" width="40%" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="120px" :rules="formRules">
<el-form-item prop="sessionId" label="届次">
<el-select v-model="formData.sessionId"
disabled
style="width: 100%"
placeholder="代表所属教代会">
<el-option v-for="item in sessionOptions"
:key="item.id"
:label="item.fullName"
:value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="userName" label="姓名">
<el-input v-model="formData.userName" disabled></el-input>
</el-form-item>
<el-form-item prop="delegationId" label="代表团">
<el-select v-model="formData.delegationId" filterable clearable
style="width: 100%">
<el-option v-for="i in delegationOptions"
:label="i.name"
:key="i.id"
:value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="roleId" label="代表身份">
<el-select v-model="formData.roleId" filterable clearable
style="width: 100%">
<el-option v-for="i in roleOptions"
:label="i.name"
:key="i.id"
:value="i.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
`,
data() {
return {
dialogFormVisible: false,
formData: {
userId: null, sessionId: null, delegationId: null, roleId: null
},
formRules: {
sessionId: [{required: true, message: "必填", trigger: ["change", "blur"]}],
delegationId: [{required: true, message: "必填", trigger: ["change", "blur"]}],
roleId: [{required: true, message: "必填", trigger: ["change", "blur"]}],
userId: [{required: true, message: "必填", trigger: ["change", "blur"]}]
},
sessionOptions: [],
delegationOptions: [],
roleOptions: []
}
},
methods: {
onOpen(row) {
this.formData = {
id: row.id,
roleId: row.roleId,
userName: row.userName,
sessionId: row.sessionId,
delegationId: row.delegationId,
userId: row.userId
}
this.listSession()
this.listDelegation(row.sessionId)
this.listRole()
this.dialogFormVisible = true
},
listSession() {
this.$axios.post("/platform/teacherCongress/common/listSession").then((res) => {
if (res.code === 0) {
this.sessionOptions = res.data
}
})
},
listDelegation(sessionId) {
this.$axios.post("/platform/teacherCongress/common/listDelegation", {sessionId}).then((res) => {
if (res.code === 0) {
this.delegationOptions = res.data
}
})
},
listRole() {
this.$axios.post("/platform/teacherCongress/common/listDelegateRole").then((res) => {
if (res.code === 0) {
this.roleOptions = res.data
}
})
},
doSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios.post("/platform/teacherCongress/delegate/manage/update", this.formData).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.$emit("refresh")
}
})
}
})
}
}
}
@@ -79,6 +79,7 @@ layout("/layouts/platform.html"){
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<!-- <el-button size="mini">查看</el-button>-->
<el-button size="mini" type="primary" @click="$refs.editFormRef.onOpen(scope.row)">编辑</el-button>
<el-button size="mini" type="danger" @click="doDelete([scope.row.id])">删除</el-button>
</template>
</el-table-column>
@@ -88,8 +89,9 @@ layout("/layouts/platform.html"){
<add-form ref="addFormRef" @refresh="doSearch"></add-form>
<adjust-form ref="adjustFormRef" @refresh="doSearch"></adjust-form>
<edit-form ref="editFormRef" @refresh="doSearch"></edit-form>
<adjust-form ref="adjustFormRef" @refresh="doSearch"></adjust-form>
<!--导入名单-->
<excel-import
@@ -105,15 +107,16 @@ layout("/layouts/platform.html"){
</div>
<script src="/assets/platform/module/democratic/teachercongress/teacherCongressCommonApi.js"></script>
<script>
<!--#include("addForm.js"){}#-->
<!--#include("editForm.js"){}#-->
<!--#include("adjust.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"add-form": AddForm,
"edit-form": editForm,
"adjust-form": AdjustForm
},
data() {
@@ -0,0 +1,22 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
</div>
<script>
const app = new Vue({
el: "#app",
data(){
return{
}
}
})
</script>
<!--#
}
#-->
@@ -74,7 +74,7 @@ layout("/layouts/platform.html"){
</el-form-item>
<el-form-item label="文件" prop="files">
<file-upload :upload_number="5" :value.sync="formData.files" complete_result upload_result_category="array"></file-upload>
<file-upload :upload_number="5" :upload_size="1024 * 1024 * 1" :value.sync="formData.files" complete_result upload_result_category="array"></file-upload>
</el-form-item>
</el-form>
<div class="dialog-footer" slot="footer">