Merge remote-tracking branch 'origin/main'

This commit is contained in:
2026-05-22 15:02:11 +08:00
59 changed files with 4615 additions and 406 deletions
@@ -25,6 +25,7 @@ RoleConstant {
SCHOOL_UNION_WC_ADMIN("校工会工代会管理员"),
SCHOOL_UNION_DC_ADMIN("校工会民主管理员"),
SCHOOL_UNION_PROPOSAL_ADMIN("校工会提案管理员"),
APPEAL_COMMITTEE_MEMBER("申诉处理委员会成员"),
SCHOOL_UNION_CLUB_ADMIN("校工会协会管理员"),
SCHOOL_UNION_ACTIVITY_ADMIN("校工会活动管理员"),
SCHOOL_UNION_ARTICLE_CLUB_ADMIN("校工会协会新闻审批管理员"),
@@ -61,6 +61,9 @@ public class FlowEngineImpl implements FlowEngine {
@Override
public ProcessInstance startProcessInstanceByKey(String key, String businessKey, String operator, Dict args) {
ProcessDefine define = processDefineService.getLastByName(key);
if (define == null) {
throw new BaseException("流程定义不存在或未启用:" + key);
}
return startProcessInstanceById(define.getId(), businessKey, operator, args);
}
@@ -0,0 +1,53 @@
package com.budwk.app.flow.handler;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.flow.engine.AssignmentHandler;
import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.engine.model.TaskModel;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.lang.Lang;
import java.util.List;
/**
* 获取申诉处理委员会成员
*/
public class FlowAppealCommitteeAssignmentHandler implements AssignmentHandler {
@Override
public List<String> assign(TaskModel model, Execution execution) {
Dao dao = ServiceContext.find(Dao.class);
Sql sql = Sqls.create("""
SELECT
userRole.userId
FROM
`sys_user_role` userRole
LEFT JOIN sys_role role ON role.id = userRole.roleId
WHERE
role.`code` = @roleCode
GROUP BY
userRole.userId
""").setParam("roleCode", RoleConstant.APPEAL_COMMITTEE_MEMBER.name());
sql.setCallback(Sqls.callback.strList());
dao.execute(sql);
List<String> userIds = sql.getList(String.class);
if (Lang.isEmpty(userIds)) {
throw new BaseException("申诉处理委员会成员没有设置,请联系管理员!");
}
return userIds;
}
@Override
public String getMessage() {
return "申诉处理委员会成员";
}
@Override
public int getOrder() {
return 10;
}
}
@@ -0,0 +1,54 @@
package com.budwk.app.flow.handler;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.flow.engine.AssignmentHandler;
import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.engine.model.TaskModel;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.services.SysRoleService;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.lang.Lang;
import java.util.List;
/**
* 获取被申诉单位分工会管理员
*/
public class FlowAppealDefendantUnitAssignmentHandler implements AssignmentHandler {
@Override
public List<String> assign(TaskModel model, Execution execution) {
Dao dao = ServiceContext.find(Dao.class);
SysRoleService sysRoleService = ServiceContext.find(SysRoleService.class);
String unitId = StrUtil.blankToDefault(execution.getArgs().getStr("appealDefendantUnitId"), execution.getArgs().getStr("defendantUnitId"));
if (StrUtil.isBlank(unitId)) {
throw new BaseException("被申诉单位不能为空!");
}
Sys_role sysRole = sysRoleService.getByCode(RoleConstant.BRANCH_UNION_ADMIN);
List<Sys_user_role> userRoles = dao.query(Sys_user_role.class, Cnd.where("roleId", "=", sysRole.getId()).and("unitId", "=", unitId));
if (Lang.isEmpty(userRoles)) {
userRoles = dao.query(Sys_user_role.class, Cnd.where("roleId", "=", sysRole.getId()).and("unionId", "=", unitId));
}
if (Lang.isEmpty(userRoles)) {
throw new BaseException("被申诉单位分工会管理员没有设置,请联系管理员!", sysRole.getCode());
}
return userRoles.stream().map(Sys_user_role::getUserId).distinct().toList();
}
@Override
public String getMessage() {
return "被申诉单位分工会管理员";
}
@Override
public int getOrder() {
return 10;
}
}
@@ -114,9 +114,9 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
user.setMenus(allMenus);
//pc端菜单
List<Sys_menu> pcMenus = allMenus.stream().filter(menu -> menu.getPlatform().equals("PC")).toList();
List<Sys_menu> pcMenus = allMenus.stream().filter(menu -> StrUtil.equals(menu.getPlatform(), "PC")).toList();
//h5端菜单
List<Sys_menu> h5Menus = allMenus.stream().filter(menu -> menu.getPlatform().equals("H5")).toList();
List<Sys_menu> h5Menus = allMenus.stream().filter(menu -> StrUtil.equals(menu.getPlatform(), "H5")).toList();
//所有的模块
Set<String> allModuleIds = allMenus.stream().map(Sys_menu::getModuleId).collect(Collectors.toSet());
@@ -0,0 +1,152 @@
package com.budwk.app.zhgh.democratic.appeal.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Dict;
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.constant.FlowConst;
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.service.FlowCommonService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.appeal.models.AppealInfo;
import com.budwk.app.zhgh.democratic.appeal.service.AppealInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import java.util.Date;
import java.util.List;
@IocBean
@At("/platform/appeal/accept")
@Ok("json:full")
@Api("申诉管理-受理")
public class AppealAcceptController {
@Inject
private AppealInfoService appealInfoService;
@Inject
private FlowCommonService flowCommonService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/appeal/accept/index.html")
@SaCheckPermission("appeal.accept")
public void index() {
}
@At
@SaCheckPermission("appeal.accept")
public Result pageData(Integer pageNumber, Integer pageSize, String searchKeyword, String appealTypeId,
Integer year, boolean approval) {
Sql sql = listSql();
Cnd cnd = taskCondition("appealAccept", "受理", approval);
if (StrUtil.isNotBlank(searchKeyword)) {
cnd.and("info.title", "like", "%" + searchKeyword + "%");
}
cnd.andEX("info.appealTypeId", "=", appealTypeId);
cnd.andEX("YEAR(info.applyDate)", "=", year);
cnd.desc("info.applyDate");
cnd.groupBy("t.id");
sql.setCondition(cnd);
Pagination<NutMap> pagination = appealInfoService.listPageMap(pageNumber, pageSize, sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("appeal.accept")
@ApiOperation("查询受理任务")
public Result queryTask(@Param("taskId") Long taskId) {
Sql sql = listSql();
sql.setCondition(Cnd.where("t.id", "=", taskId));
return Result.success(appealInfoService.fetchMap(sql));
}
@At
@SaCheckPermission("appeal.accept")
@ApiOperation("受理申诉")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "申诉管理-受理", msg = "受理申诉")
public Result accept(@Param("data") AppealInfo appealInfo, @Param("taskId") Long taskId,
@Param("submitType") Integer submitType) {
AppealInfo old = appealInfoService.fetch(appealInfo.getId());
BeanUtil.copyProperties(appealInfo, old, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
old.setAcceptUserId(SecurityUtil.getUserId());
old.setAcceptUserName(SecurityUtil.getUserUsername());
old.setAcceptTime(new Date());
if (ProcessSubmitTypeEnum.AGREE.getCode().equals(submitType)) {
old.setState("待执行");
} else if (ProcessSubmitTypeEnum.ROLLBACK_TO_OPERATOR.getCode().equals(submitType)) {
old.setState("退回修改");
} else if (ProcessSubmitTypeEnum.REJECT.getCode().equals(submitType)) {
old.setState("已办结");
}
appealInfoService.updateIgnoreNull(old);
Dict dict = Dict.create();
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
dict.set(FlowConst.SUBMIT_TYPE, submitType);
dict.set(FlowConst.FORM_DATA, old);
dict.set("appealDefendantUnitId", old.getDefendantUnitId());
dict.set("defendantUnitId", old.getDefendantUnitId());
flowCommonService.executeTask(dict);
return Result.success();
}
private Sql listSql() {
return 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 appeal_info info ON info.id = ins.businessNo
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
$condition
""");
}
private Cnd taskCondition(String taskName, String displayName, boolean approval) {
Cnd cnd = Cnd.NEW();
cnd.and(Cnd.exps("t.taskName", "=", taskName).or("t.displayName", "=", displayName));
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());
}
return cnd;
}
}
@@ -0,0 +1,91 @@
package com.budwk.app.zhgh.democratic.appeal.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.democratic.appeal.service.AppealTypeService;
import io.swagger.annotations.Api;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@IocBean
@At("/platform/appeal/common")
@Ok("json:full")
@Api("申诉管理-公共接口")
public class AppealCommonController {
@Inject
private Dao dao;
@Inject
private AppealTypeService appealTypeService;
@At
@SaCheckLogin
public Result typeOptions() {
return Result.success(appealTypeService.query(Cnd.where("enabled", "=", true).asc("sort").desc("createdAt")));
}
@At
@SaCheckLogin
public Result queryTypeOptions() {
Sql sql = Sqls.create("""
SELECT
type_data.*
FROM
(
SELECT
atype.id,
atype.`name`,
atype.enabled,
atype.sort
FROM
appeal_type atype
WHERE
atype.enabled = 1
UNION
SELECT
info.appealTypeId AS id,
COALESCE(MAX(atype.`name`), MAX(info.appealTypeName)) AS `name`,
COALESCE(MAX(atype.enabled), 0) AS enabled,
COALESCE(MAX(atype.sort), 999999) AS sort
FROM
appeal_info info
LEFT JOIN appeal_type atype ON atype.id = info.appealTypeId
WHERE
info.appealTypeId IS NOT NULL
AND info.appealTypeId != ''
GROUP BY
info.appealTypeId
) type_data
ORDER BY
type_data.sort ASC,
type_data.`name` ASC
""");
return Result.success(appealTypeService.listMap(sql));
}
@At
@SaCheckLogin
public Result unitOptions(String unionId) {
Sql sql = Sqls.create("""
SELECT
unit.*,
su.`name` AS unionName
FROM
`sys_unit` unit
LEFT JOIN sys_union su ON su.id = unit.unionId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("unit.unionId", "=", unionId);
cnd.and("unit.unitLevel", "=", "2");
cnd.asc("unit.unitcode");
sql.setCondition(cnd);
return Result.success(appealTypeService.listMap(sql));
}
}
@@ -0,0 +1,143 @@
package com.budwk.app.zhgh.democratic.appeal.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Dict;
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.constant.FlowConst;
import com.budwk.app.flow.enums.ProcessSubmitTypeEnum;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.service.FlowCommonService;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.appeal.models.AppealInfo;
import com.budwk.app.zhgh.democratic.appeal.service.AppealInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import java.util.Date;
import java.util.List;
@IocBean
@At("/platform/appeal/execute")
@Ok("json:full")
@Api("申诉管理-执行")
public class AppealExecuteController {
@Inject
private AppealInfoService appealInfoService;
@Inject
private FlowCommonService flowCommonService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/appeal/execute/index.html")
@SaCheckPermission("appeal.execute")
public void index() {
}
@At
@SaCheckPermission("appeal.execute")
public Result pageData(Integer pageNumber, Integer pageSize, String searchKeyword, String appealTypeId,
Integer year, boolean approval) {
Sql sql = listSql();
Cnd cnd = taskCondition("appealExecute", "执行", approval);
if (StrUtil.isNotBlank(searchKeyword)) {
cnd.and("info.title", "like", "%" + searchKeyword + "%");
}
cnd.andEX("info.appealTypeId", "=", appealTypeId);
cnd.andEX("YEAR(info.applyDate)", "=", year);
cnd.desc("info.applyDate");
cnd.groupBy("t.id");
sql.setCondition(cnd);
Pagination<NutMap> pagination = appealInfoService.listPageMap(pageNumber, pageSize, sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("appeal.execute")
@ApiOperation("查询执行任务")
public Result queryTask(@Param("taskId") Long taskId) {
Sql sql = listSql();
sql.setCondition(Cnd.where("t.id", "=", taskId));
return Result.success(appealInfoService.fetchMap(sql));
}
@At
@SaCheckPermission("appeal.execute")
@ApiOperation("提交执行情况")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "申诉管理-执行", msg = "提交执行情况")
public Result execute(@Param("data") AppealInfo appealInfo, @Param("taskId") Long taskId) {
AppealInfo old = appealInfoService.fetch(appealInfo.getId());
BeanUtil.copyProperties(appealInfo, old, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
old.setExecuteUserId(SecurityUtil.getUserId());
old.setExecuteUserName(SecurityUtil.getUserUsername());
old.setExecuteTime(new Date());
old.setState("已办结");
appealInfoService.updateIgnoreNull(old);
Dict dict = Dict.create();
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.AGREE.getCode());
dict.set(FlowConst.FORM_DATA, old);
flowCommonService.executeTask(dict);
return Result.success();
}
private Sql listSql() {
return 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 appeal_info info ON info.id = ins.businessNo
LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id
LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10
LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10
$condition
""");
}
private Cnd taskCondition(String taskName, String displayName, boolean approval) {
Cnd cnd = Cnd.NEW();
cnd.and(Cnd.exps("t.taskName", "=", taskName).or("t.displayName", "=", displayName));
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());
}
return cnd;
}
}
@@ -0,0 +1,83 @@
package com.budwk.app.zhgh.democratic.appeal.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.result.Result;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.appeal.service.AppealInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
@IocBean
@At("/platform/appeal/mine")
@Ok("json:full")
@Api("申诉管理-我的申诉")
public class AppealMineController {
@Inject
private FlowEngine flowEngine;
@Inject
private AppealInfoService appealInfoService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/appeal/mine/index.html")
@SaCheckPermission("appeal.mine")
public void index() {
}
@At
@SaCheckPermission("appeal.mine")
public Result pageData(Integer pageNumber, Integer pageSize, String searchKeyword, String appealTypeId, Integer year) {
Sql sql = Sqls.create("""
SELECT
info.*,
ins.id AS instanceId,
ins.state instanceState,
t.id startTaskId,
t.taskName AS taskKey,
IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') taskName,
IF(rt.id IS NOT NULL, 1, 0) AS canRevoke
FROM
appeal_info info
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskName = 'startTask'
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.where("info.userId", "=", SecurityUtil.getUserId());
if (StrUtil.isNotBlank(searchKeyword)) {
cnd.and("info.title", "like", "%" + searchKeyword + "%");
}
cnd.andEX("info.appealTypeId", "=", appealTypeId);
cnd.andEX("YEAR(info.applyDate)", "=", year);
cnd.groupBy("info.id");
cnd.desc("info.applyDate");
sql.setCondition(cnd);
Pagination<NutMap> pagination = appealInfoService.listPageMap(pageNumber, pageSize, sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("appeal.mine")
@Aop(TransAop.READ_COMMITTED)
@ApiOperation("删除申诉")
public Result delete(@Param("id") String id) {
appealInfoService.delete(id);
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
return Result.success();
}
}
@@ -0,0 +1,88 @@
package com.budwk.app.zhgh.democratic.appeal.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.result.Result;
import com.budwk.app.zhgh.democratic.appeal.service.AppealInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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;
@IocBean
@At("/platform/appeal/query")
@Ok("json:full")
@Api("申诉管理-查询统计")
public class AppealQueryController {
@Inject
private AppealInfoService appealInfoService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/appeal/query/index.html")
@SaCheckPermission("appeal.query")
public void index() {
}
@At
@SaCheckPermission("appeal.query")
public Result pageData(Integer pageNumber, Integer pageSize, String searchKeyword, String appealTypeId, String state,
String unitId, String defendantUnitId, Integer year) {
Sql sql = Sqls.create("""
SELECT
info.*,
ins.id AS instanceId,
ins.state instanceState
FROM
appeal_info info
LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id
$condition
""");
Cnd cnd = buildCondition(searchKeyword, appealTypeId, state, unitId, defendantUnitId, year);
cnd.desc("info.applyDate");
sql.setCondition(cnd);
Pagination<NutMap> pagination = appealInfoService.listPageMap(pageNumber, pageSize, sql);
return Result.success(pagination);
}
@At
@SaCheckPermission("appeal.query")
@ApiOperation("申诉统计")
public Result statistics(String searchKeyword, String appealTypeId, String state, String unitId,
String defendantUnitId, Integer year) {
Sql sql = Sqls.create("""
SELECT
COUNT(1) totalCount,
SUM(CASE WHEN info.state = '待受理' THEN 1 ELSE 0 END) waitAcceptCount,
SUM(CASE WHEN info.state = '待执行' THEN 1 ELSE 0 END) waitExecuteCount,
SUM(CASE WHEN info.state = '已办结' THEN 1 ELSE 0 END) finishCount
FROM
appeal_info info
$condition
""");
sql.setCondition(buildCondition(searchKeyword, appealTypeId, state, unitId, defendantUnitId, year));
NutMap data = appealInfoService.fetchMap(sql);
return Result.success(data);
}
private Cnd buildCondition(String searchKeyword, String appealTypeId, String state, String unitId,
String defendantUnitId, Integer year) {
Cnd cnd = Cnd.NEW();
if (StrUtil.isNotBlank(searchKeyword)) {
cnd.and("info.title", "like", "%" + searchKeyword + "%");
}
cnd.andEX("info.appealTypeId", "=", appealTypeId);
cnd.andEX("info.state", "=", state);
cnd.andEX("info.unitId", "=", unitId);
cnd.andEX("info.defendantUnitId", "=", defendantUnitId);
cnd.andEX("YEAR(info.applyDate)", "=", year);
return cnd;
}
}
@@ -0,0 +1,92 @@
package com.budwk.app.zhgh.democratic.appeal.controller;
import cn.dev33.satoken.annotation.SaCheckLogin;
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.zhgh.democratic.appeal.models.AppealInfo;
import com.budwk.app.zhgh.democratic.appeal.models.AppealType;
import com.budwk.app.zhgh.democratic.appeal.service.AppealTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
@IocBean
@At("/platform/appeal/type")
@Ok("json:full")
@Api("申诉管理-类型维护")
public class AppealTypeController {
@Inject
private AppealTypeService appealTypeService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/appeal/type/index.html")
@SaCheckPermission("appeal.type")
public void index() {
}
@At
@SaCheckPermission("appeal.type")
public Result pageData(Integer pageNumber, Integer pageSize, String name) {
Cnd cnd = Cnd.NEW();
if (StrUtil.isNotBlank(name)) {
cnd.and("name", "like", "%" + name + "%");
}
cnd.asc("sort").desc("createdAt");
Pagination page = appealTypeService.listPage(pageNumber, pageSize, cnd);
return Result.success(page);
}
@At
@SaCheckPermission("appeal.type")
@ApiOperation("保存申诉类型")
@SLog(tag = "申诉管理-类型维护", msg = "保存申诉类型")
public Result save(@Param("data") AppealType appealType) {
if (appealType.getEnabled() == null) {
appealType.setEnabled(true);
}
if (appealType.getSort() == null) {
appealType.setSort(0);
}
appealTypeService.insertOrUpdate(appealType);
return Result.success();
}
@At
@SaCheckPermission("appeal.type")
@ApiOperation("修改申诉类型启用状态")
@SLog(tag = "申诉管理-类型维护", msg = "修改申诉类型启用状态")
public Result statusChange(String id, Boolean enabled) {
appealTypeService.update(Chain.make("enabled", enabled), Cnd.where("id", "=", id));
return Result.success();
}
@At
@SaCheckPermission("appeal.type")
@ApiOperation("删除申诉类型")
@SLog(tag = "申诉管理-类型维护", msg = "删除申诉类型")
public Result delete(@Param("id") String id) {
int count = appealTypeService.dao().count(AppealInfo.class, Cnd.where("appealTypeId", "=", id));
if (count > 0) {
return Result.error("该类型有关联的申诉,无法删除!");
}
appealTypeService.delete(id);
return Result.success();
}
@At
@SaCheckLogin
@ApiOperation("申诉类型下拉")
public Result options() {
return Result.success(appealTypeService.query(Cnd.where("enabled", "=", true).asc("sort").desc("createdAt")));
}
}
@@ -0,0 +1,161 @@
package com.budwk.app.zhgh.democratic.appeal.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
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.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.democratic.appeal.models.AppealInfo;
import com.budwk.app.zhgh.democratic.appeal.models.AppealType;
import com.budwk.app.zhgh.democratic.appeal.service.AppealInfoService;
import com.budwk.app.zhgh.democratic.appeal.service.AppealTypeService;
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.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/appeal/write")
@Ok("json:full")
@Api("申诉管理-提交申诉")
public class AppealWriteController {
private static final String DEFINE_KEY = "SSGL";
@Inject
private Dao dao;
@Inject
private FlowEngine flowEngine;
@Inject
private FlowCommonService flowCommonService;
@Inject
private AppealInfoService appealInfoService;
@Inject
private AppealTypeService appealTypeService;
@At("")
@Ok("beetl:/platform/zhgh/democratic/appeal/write/index.html")
@SaCheckPermission("appeal.write")
public void index() {
}
@At
@SaCheckPermission("appeal.write")
@ApiOperation("当前用户信息")
public Result currentUserInfo() {
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId()));
AppealInfo info = new AppealInfo();
if (user != null) {
info.setUserId(user.getId());
info.setUserName(user.getUsername());
info.setLoginName(user.getLoginname());
info.setSex(user.getSex());
info.setBirthday(user.getBirthday());
info.setPolitical(user.getPolitical());
info.setUnitId(user.getUnitId());
info.setUnitName(user.getUnitName());
info.setPositionName(user.getPosition());
info.setMobile(user.getMobile());
} else {
info.setUserId(SecurityUtil.getUserId());
info.setUserName(SecurityUtil.getUserUsername());
info.setLoginName(SecurityUtil.getUserLoginname());
info.setUnitId(SecurityUtil.getUnitId());
}
info.setApplyDate(new Date());
return Result.success(info);
}
@At
@SaCheckPermission("appeal.write")
@ApiOperation("获取申诉信息")
public Result info(@Param("id") String id) {
return Result.success(appealInfoService.fetch(id));
}
@At
@SaCheckPermission("appeal.write")
@ApiOperation("保存申诉")
@SLog(tag = "申诉管理-提交申诉", msg = "保存申诉")
public Result save(@Param("data") AppealInfo appealInfo) {
fillTypeName(appealInfo);
appealInfoService.insertOrUpdate(appealInfo);
return Result.success(appealInfo);
}
@At
@SaCheckPermission("appeal.write")
@ApiOperation("提交申诉")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "申诉管理-提交申诉", msg = "提交申诉")
public Result submit(@Param("data") AppealInfo appealInfo) {
fillTypeName(appealInfo);
if (appealInfo.getApplyDate() == null) {
appealInfo.setApplyDate(new Date());
}
appealInfo.setState("待受理");
appealInfoService.insertOrUpdate(appealInfo);
Dict args = Dict.create();
args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode());
args.set(FlowConst.FORM_DATA, appealInfo);
args.set("appealDefendantUnitId", appealInfo.getDefendantUnitId());
args.set("defendantUnitId", appealInfo.getDefendantUnitId());
ProcessInstance instance = flowEngine.startProcessInstanceByKey(DEFINE_KEY, appealInfo.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(appealInfo);
}
@At
@SaCheckPermission("appeal.write")
@ApiOperation("重新提交申诉")
@Aop(TransAop.READ_COMMITTED)
@SLog(tag = "申诉管理-提交申诉", msg = "重新提交申诉")
public Result submitAgain(@Param("data") AppealInfo appealInfo, @Param("taskId") Long taskId) {
fillTypeName(appealInfo);
appealInfo.setState("待受理");
appealInfoService.insertOrUpdate(appealInfo);
Dict dict = Dict.create();
dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId);
dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode());
dict.set(FlowConst.FORM_DATA, appealInfo);
dict.set("appealDefendantUnitId", appealInfo.getDefendantUnitId());
dict.set("defendantUnitId", appealInfo.getDefendantUnitId());
flowCommonService.executeTask(dict);
return Result.success(appealInfo);
}
private void fillTypeName(AppealInfo appealInfo) {
if (appealInfo == null || StrUtil.isBlank(appealInfo.getAppealTypeId())) {
return;
}
AppealType type = appealTypeService.fetch(appealInfo.getAppealTypeId());
if (type != null) {
appealInfo.setAppealTypeName(type.getName());
}
}
}
@@ -0,0 +1,210 @@
package com.budwk.app.zhgh.democratic.appeal.models;
import cn.hutool.json.JSONObject;
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;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Table("appeal_info")
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("教职工申诉")
@Data
public class AppealInfo 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 userId;
@Column
@Comment("申诉人姓名")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String userName;
@Column
@Comment("申诉人工号")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String loginName;
@Column
@Comment("性别")
@ColDefine(type = ColType.VARCHAR, width = 20)
private String sex;
@Column
@Comment("出生年月")
@ColDefine(type = ColType.DATE)
private Date birthday;
@Column
@Comment("政治面貌")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String political;
@Column
@Comment("所在单位ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String unitId;
@Column
@Comment("所在单位")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String unitName;
@Column
@Comment("岗位")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String positionName;
@Column
@Comment("住址")
@ColDefine(type = ColType.VARCHAR, width = 300)
private String address;
@Column
@Comment("联系方式")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String mobile;
@Column
@Comment("申诉类型ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String appealTypeId;
@Column
@Comment("申诉类型名称")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String appealTypeName;
@Column
@Comment("被申诉单位ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String defendantUnitId;
@Column
@Comment("被申诉单位")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String defendantUnitName;
@Column
@Comment("被申诉单位地址")
@ColDefine(type = ColType.VARCHAR, width = 300)
private String defendantAddress;
@Column
@Comment("被申诉单位联系方式")
@ColDefine(type = ColType.VARCHAR, width = 100)
private String defendantContact;
@Column
@Comment("申诉标题")
@ColDefine(type = ColType.VARCHAR, width = 200)
private String title;
@Column
@Comment("申诉事项")
@ColDefine(type = ColType.TEXT)
private String appealMatter;
@Column
@Comment("申诉理由")
@ColDefine(type = ColType.TEXT)
private String reason;
@Column
@Comment("申诉要求")
@ColDefine(type = ColType.TEXT)
private String request;
@Column
@Comment("申请日期")
@ColDefine(type = ColType.DATE)
private Date applyDate;
@Column
@Comment("申诉人签名")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String signature;
@Column
@Comment("附件")
@ColDefine(type = ColType.MYSQL_JSON)
private List<JSONObject> files;
@Column
@Comment("业务状态")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String state;
@Column
@Comment("受理人ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String acceptUserId;
@Column
@Comment("受理人姓名")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String acceptUserName;
@Column
@Comment("受理时间")
@ColDefine(type = ColType.DATETIME)
private Date acceptTime;
@Column
@Comment("处理决定")
@ColDefine(type = ColType.TEXT)
private String decisionContent;
@Column
@Comment("事实理由及适用依据")
@ColDefine(type = ColType.TEXT)
private String legalBasis;
@Column
@Comment("作出决定日期")
@ColDefine(type = ColType.DATE)
private Date decisionDate;
@Column
@Comment("决定书附件")
@ColDefine(type = ColType.MYSQL_JSON)
private List<JSONObject> decisionFiles;
@Column
@Comment("执行人ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String executeUserId;
@Column
@Comment("执行人姓名")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String executeUserName;
@Column
@Comment("执行时间")
@ColDefine(type = ColType.DATETIME)
private Date executeTime;
@Column
@Comment("执行情况")
@ColDefine(type = ColType.TEXT)
private String executeContent;
@Column
@Comment("执行附件")
@ColDefine(type = ColType.MYSQL_JSON)
private List<JSONObject> executeFiles;
}
@@ -0,0 +1,43 @@
package com.budwk.app.zhgh.democratic.appeal.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;
@EqualsAndHashCode(callSuper = true)
@Table("appeal_type")
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("申诉类型")
@Data
public class AppealType 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 name;
@Column
@Comment("排序")
@ColDefine(type = ColType.INT)
@Default("0")
private Integer sort;
@Column
@Comment("是否启用")
@ColDefine(type = ColType.BOOLEAN)
@Default("1")
private Boolean enabled;
@Column
@Comment("备注")
@ColDefine(type = ColType.VARCHAR, width = 500)
private String remark;
}
@@ -0,0 +1,7 @@
package com.budwk.app.zhgh.democratic.appeal.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.democratic.appeal.models.AppealInfo;
public interface AppealInfoService extends BaseService<AppealInfo> {
}
@@ -0,0 +1,7 @@
package com.budwk.app.zhgh.democratic.appeal.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.democratic.appeal.models.AppealType;
public interface AppealTypeService extends BaseService<AppealType> {
}
@@ -0,0 +1,14 @@
package com.budwk.app.zhgh.democratic.appeal.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.democratic.appeal.models.AppealInfo;
import com.budwk.app.zhgh.democratic.appeal.service.AppealInfoService;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean(args = {"refer:dao"})
public class AppealInfoServiceImpl extends BaseServiceImpl<AppealInfo> implements AppealInfoService {
public AppealInfoServiceImpl(Dao dao) {
super(dao);
}
}
@@ -0,0 +1,14 @@
package com.budwk.app.zhgh.democratic.appeal.service.impl;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.democratic.appeal.models.AppealType;
import com.budwk.app.zhgh.democratic.appeal.service.AppealTypeService;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
@IocBean(args = {"refer:dao"})
public class AppealTypeServiceImpl extends BaseServiceImpl<AppealType> implements AppealTypeService {
public AppealTypeServiceImpl(Dao dao) {
super(dao);
}
}
@@ -9,8 +9,7 @@ import com.budwk.app.base.result.Result;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import com.budwk.app.zhgh.staffmanage.member.service.MemberInfoService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
@@ -24,12 +23,12 @@ import javax.validation.Valid;
public class MemberApplyCommonController {
@Inject
private Dao dao;
private MemberInfoService memberInfoService;
@At
@SaCheckLogin
public Result findOne(@Valid String id) {
View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", id));
View_user user = memberInfoService.getMemberInfoDetail(id);
if (ObjectUtil.isNull(user)) {
return Result.error("用户信息不存在");
}
@@ -39,8 +38,8 @@ public class MemberApplyCommonController {
return Result.success(user);
}
// 分会主席只能查看本分会用户或未分配分会的用户 分工会操作员同主席权限一致
if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name()) && (user.getUnionId().equals(SecurityUtil.getUnionId()) || StrUtil.isBlank(user.getUnionId()))) {
// 分会主席、分工会操作员只能查看本分会用户,无工会人员不再放行,避免空工会人员查看时报错。
if (AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_CHAIRMAN.name(), RoleConstant.BRANCH_UNION_OPERATOR.name()) && StrUtil.isNotBlank(user.getUnionId()) && user.getUnionId().equals(SecurityUtil.getUnionId())) {
user.setIdCard(DesensitizedUtil.idCardNum(user.getIdCard(), 3, 4));
user.setMobile(DesensitizedUtil.mobilePhone(user.getMobile()));
return Result.success(user);
@@ -10,6 +10,7 @@ import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.bpm.service.BpmService;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.staffmanage.member.models.MemberChangeRecord;
@@ -73,7 +74,7 @@ public class MemberChangeMineController {
info.loginname,
info.sex,
info.unitName,
info.unionName,
IFNULL(su.name, info.unionName) AS unionName,
info.userState,
info.preparedBy,
info.personType,
@@ -100,16 +101,15 @@ public class MemberChangeMineController {
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
-- 使用工会表实时名称展示,避免历史变更记录冗余工会名称不一致。
LEFT JOIN sys_union su ON su.id = info.unionId
$condition
""");
Cnd cnd = Cnd.NEW();
pageForm.buildSearch(cnd, "info.");
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_MEMBER_ADMIN.name())) {
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
cnd.and("info.unionId", "=", SecurityUtil.getUnionId());
} else {
cnd.and("info.userId", "=", SecurityUtil.getUserId());
}
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
// 除超管和校工会管理员外,其他角色只查看当前所属分工会的变更申请。
cnd.and("info.unionId", "=", SecurityUtil.getUnionId());
}
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.desc("info.applyDateTime");
@@ -152,6 +152,11 @@ public class MemberChangeMineController {
public Result findMemberChangeRecord(String id){
MemberChangeRecord record = dao.fetch(MemberChangeRecord.class, id);
NutMap nutMap = Lang.obj2nutmap(record);
Sys_union union = dao.fetch(Sys_union.class, record.getUnionId());
// 查看页所属工会与列表一致,优先使用 unionId 对应的实时工会名称。
if (Lang.isNotEmpty(union)) {
nutMap.put("unionName", union.getName());
}
List<NutMap> changeInfos = memberCommonService.getChangeInfos(nutMap.getString("id"));
nutMap.put("changeInfos", changeInfos);
@@ -0,0 +1,55 @@
package com.budwk.app.zhgh.staffmanage.member.controller.check;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.date.DateUtil;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.staffmanage.member.service.MemberCheckTaskService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @version 1.0
* @Author zzr
* @name:MemberCheckConfirmController
* @Date 2025/9/26 15:31
* @注释 会员核对确认统计
*/
@Slf4j
@IocBean
@Ok("json")
@At("/platform/member/check/confirm")
public class MemberCheckConfirmController {
@Inject
private MemberCheckTaskService memberCheckTaskService;
@At("")
@Ok("beetl:/platform/zhgh/staffmanage/member/check/confirm/index.html")
@SaCheckPermission("member.check.confirm")
public void index() {}
@At
@ApiOperation("工会确认情况分页统计")
@SaCheckPermission("member.check.confirm")
public Result pageData(PageForm pageForm, Integer year, String checkTaskId, String unionId) {
return Result.success(memberCheckTaskService.confirmStatistics(
pageForm.getPageNumber(),
pageForm.getPageSize(),
year,
checkTaskId,
unionId
));
}
@At
@ApiOperation("按年度查询事项")
@SaCheckPermission("member.check.confirm")
public Result listEnabledTask(Integer year) {
return Result.success(memberCheckTaskService.listEnabledTask(year == null ? DateUtil.thisYear() : year));
}
}
@@ -0,0 +1,229 @@
package com.budwk.app.zhgh.staffmanage.member.controller.check;
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 cn.hutool.json.JSONUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.model.ExcelImportRes;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberCheckPageForm;
import com.budwk.app.zhgh.staffmanage.member.service.MemberCheckTaskService;
import com.budwk.app.zhgh.staffmanage.member.template.MemberCheckTaskUserImportTemp;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
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.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @version 1.0
* @Author zzr
* @name:MemberCheckRosterController
* @Date 2025/9/24 11:24
* @注释 会员核对人员名单
*/
@Slf4j
@IocBean
@Ok("json")
@At("/platform/member/check/roster")
public class MemberCheckRosterController {
@Inject
private MemberCheckTaskService memberCheckTaskService;
@At("")
@Ok("beetl:/platform/zhgh/staffmanage/member/check/roster/index.html")
@SaCheckPermission("member.check.roster")
public void index() {}
@At
@ApiOperation("查询已发布事项")
@SaCheckPermission("member.check.roster")
public Result listEnabledTask(Integer year) {
return Result.success(memberCheckTaskService.listEnabledTask(year == null ? DateUtil.thisYear() : year));
}
@At
@ApiOperation("人员名单分页查询")
@SaCheckPermission("member.check.roster")
public Result pageData(@Param("pageForm") MemberCheckPageForm pageForm) {
return Result.success(memberCheckTaskService.checkUserPageData(pageForm));
}
@At
@ApiOperation("分页查询可添加人员")
@SaCheckPermission("member.check.roster")
@Ok("json:{dateFormat:'yyyy-MM-dd'}")
public Result notCheckUserPageData(@Param("pageForm") MemberCheckPageForm pageForm) {
if (StrUtil.isBlank(pageForm.getCheckTaskId())) {
return Result.error("请选择事项");
}
return Result.success(memberCheckTaskService.notCheckUserPageData(pageForm));
}
@At
@ApiOperation("按筛选条件添加人员")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.roster")
public Result addCheckUser(@Param("pageForm") MemberCheckPageForm pageForm) {
if (StrUtil.isBlank(pageForm.getCheckTaskId())) {
return Result.error("请选择事项");
}
NutMap result = memberCheckTaskService.addCheckUser(pageForm);
if (result.getInt("code") == 0) {
return Result.success(result.getString("msg"));
}
return Result.error(result.getString("msg"));
}
@At
@ApiOperation("按事项和工会确认名单")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.roster")
@SLog(tag = "会员核对名单", msg = "按事项和工会确认名单")
public Result doConfirmUser(String checkTaskId, String unionId, Boolean flag) {
if (StrUtil.isBlank(checkTaskId)) {
return Result.error("请选择事项");
}
if (StrUtil.isBlank(unionId)) {
unionId = SecurityUtil.getUnionId();
}
if (StrUtil.isBlank(unionId)) {
return Result.error("请选择分工会");
}
NutMap result = memberCheckTaskService.confirmByTaskAndUnion(checkTaskId, unionId, flag);
if (result.getInt("code") == 0) {
return Result.success(result.getString("msg"));
}
return Result.error(result.getString("msg"));
}
@At
@ApiOperation("按勾选人员确认名单")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.roster")
@SLog(tag = "会员核对名单", msg = "按勾选人员确认名单")
public Result doConfirmSelected(String ids, Boolean flag) {
String[] idArray = parseIds(ids);
if (idArray.length == 0) {
return Result.error("请选择需要操作的人员");
}
memberCheckTaskService.confirmSelected(idArray, flag);
return Result.success();
}
@At
@ApiOperation("按勾选人员删除名单")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.roster")
@SLog(tag = "会员核对名单", msg = "按勾选人员删除名单")
public Result deleteSelected(String ids) {
String[] idArray = parseIds(ids);
if (idArray.length == 0) {
return Result.error("请选择需要删除的人员");
}
memberCheckTaskService.deleteSelected(idArray);
return Result.success();
}
@At
@Ok("void")
@ApiOperation("下载人员名单导入模板")
@SaCheckPermission("member.check.roster")
public void downloadTem(HttpServletResponse response) {
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号", "loginname", 20));
entities.add(new ExcelExportEntity("姓名", "username", 20));
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, Collections.emptyList());
CommonDownloadUtil.download("会员核对人员名单导入模板.xlsx", workbook, response);
}
@At
@ApiOperation("导入人员名单")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.roster")
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
public Result importCheckUser(TempFile file, String checkTaskId) {
if (file == null || file.getFile() == null) {
return Result.error("请选择导入文件");
}
if (StrUtil.isBlank(checkTaskId)) {
return Result.error("请选择事项");
}
ExcelImportRes<MemberCheckTaskUserImportTemp> result = memberCheckTaskService.importCheckUser(file.getFile(), checkTaskId);
return Result.success(result);
}
@At
@Ok("void")
@ApiOperation("导出人员名单")
@SaCheckPermission("member.check.roster")
public void exportCheckUser(@Param("pageForm") MemberCheckPageForm pageForm, HttpServletResponse response) {
List<NutMap> list = memberCheckTaskService.checkUserList(pageForm);
for (int i = 0; i < list.size(); i++) {
NutMap row = list.get(i);
row.put("index", i + 1);
row.put("branchUnionCheckedText", Boolean.TRUE.equals(row.getBoolean("branchUnionChecked")) ? "已确认" : "未确认");
Object auditTime = row.get("auditTime");
if (auditTime instanceof java.util.Date) {
row.put("auditTimeText", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.util.Date) auditTime));
} else if (auditTime != null) {
row.put("auditTimeText", auditTime.toString());
}
}
List<ExcelExportEntity> entityList = new ArrayList<>();
entityList.add(new ExcelExportEntity("序号", "index", 10));
entityList.add(new ExcelExportEntity("工号", "loginname", 20));
entityList.add(new ExcelExportEntity("姓名", "username", 20));
entityList.add(new ExcelExportEntity("性别", "sex", 20));
entityList.add(new ExcelExportEntity("所属工会", "unionName", 20));
entityList.add(new ExcelExportEntity("所属单位", "unitName", 20));
entityList.add(new ExcelExportEntity("事项名称", "taskName", 30));
entityList.add(new ExcelExportEntity("手机号", "mobile", 20));
entityList.add(new ExcelExportEntity("身份证号", "idCard", 25));
entityList.add(new ExcelExportEntity("是否确认", "branchUnionCheckedText", 20));
entityList.add(new ExcelExportEntity("确认时间", "auditTimeText", 25));
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
exportParams.setTitle("会员核对人员名单");
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list);
CommonDownloadUtil.download("会员核对人员名单.xlsx", workbook, response);
}
private String[] parseIds(String ids) {
if (StrUtil.isBlank(ids)) {
return new String[0];
}
String value = ids.trim();
if (value.startsWith("[")) {
return JSONUtil.parseArray(value).toList(String.class).toArray(new String[0]);
}
return value.split(",");
}
}
@@ -1,50 +1,30 @@
package com.budwk.app.zhgh.staffmanage.member.controller.check;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.ManyAddOrRenewUtil;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.staffmanage.member.models.check.MemberCheckTask;
import com.budwk.app.zhgh.staffmanage.member.models.check.MemberCheckTaskUser;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberCheckPageForm;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberStatisticsPageForm;
import com.budwk.app.zhgh.staffmanage.member.service.MemberCheckTaskService;
import com.budwk.app.zhgh.staffmanage.member.service.MemberCommonService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
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.dao.util.cri.SqlExpressionGroup;
import org.nutz.dao.util.cri.Static;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.random.R;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import java.util.List;
import org.nutz.mvc.annotation.Param;
/**
* @version 1.0
* @Author zzr
* @name:MemberCheckTaskController
* @Date 2025/9/24 9:53
* @注释 会员核对任务创建
* @注释 会员核对事项管理
*/
@Slf4j
@IocBean
@@ -52,10 +32,6 @@ import java.util.List;
@At("/platform/member/check/task")
public class MemberCheckTaskController {
@Inject
private Dao dao;
@Inject
private ManyAddOrRenewUtil renewUtil;
@Inject
private MemberCheckTaskService memberCheckTaskService;
@@ -64,44 +40,59 @@ public class MemberCheckTaskController {
@SaCheckPermission("member.check.task")
public void index() {}
@At
@ApiOperation("页面数据")
@ApiOperation("事项页面数据")
@SaCheckPermission("member.check.task")
public Result pageData(MemberCheckPageForm pageForm) {
Sql sql = Sqls.create("select * from member_check_task $condition");
Cnd cnd = Cnd.NEW();
cnd.andEX("`year`", "=", pageForm.getYear());
cnd.andEX("checkTaskId", "=", pageForm.getCheckTaskId());
sql.setCondition(cnd);
Pagination pagination = memberCheckTaskService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
return Result.success(memberCheckTaskService.taskPageData(pageForm));
}
@At
@ApiOperation("添加或修改")
@ApiOperation("添加或修改事项")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.task")
@SLog(tag = "会员核对任务创建", msg = "添加或修改会员核对任务创建:${args[0].taskName}")
public Result doAddOrModify(MemberCheckTask memberCheckTask) {
dao.insertOrUpdate(memberCheckTask);
dao.clear(MemberCheckTaskUser.class, Cnd.where(MemberCheckTaskUser::getCheckTaskId, "=", memberCheckTask.getId()));
List<String> userStates = memberCheckTask.getUserStates();
List<Sys_user> query = dao.query(Sys_user.class, Cnd.where(Sys_user::getUserState, "in", userStates).or(Sys_user::getMember, "=", 1));
List<MemberCheckTaskUser> list = query.stream().map(v -> {
MemberCheckTaskUser memberCheckTaskUser = new MemberCheckTaskUser();
BeanUtil.copyProperties(v, memberCheckTaskUser);
memberCheckTaskUser.setId(R.UU32());
memberCheckTaskUser.setCheckTaskId(memberCheckTask.getId());
memberCheckTaskUser.setUserId(v.getId());
return memberCheckTaskUser;
}).toList();
renewUtil.asyncExecuteFastInsert(list, 200);
@SLog(tag = "会员核对事项管理", msg = "添加或修改会员核对事项:${args[0].taskName}")
public Result doAddOrModify(@Param("data") MemberCheckTask memberCheckTask) {
if (StrUtil.isBlank(memberCheckTask.getTaskName())) {
return Result.error("请输入事项名称");
}
if (memberCheckTask.getStartTime() == null || memberCheckTask.getEndTime() == null) {
return Result.error("请选择开始时间和结束时间");
}
if (memberCheckTask.getStartTime().after(memberCheckTask.getEndTime())) {
return Result.error("开始时间不能晚于结束时间");
}
memberCheckTaskService.saveTask(memberCheckTask);
return Result.success();
}
@At
@ApiOperation("状态切换")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.task")
public Result switchChange(MemberCheckTask memberCheckTask) {
memberCheckTaskService.dao().updateIgnoreNull(memberCheckTask);
return Result.success();
}
@At
@ApiOperation("删除事项")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("member.check.task")
public Result delete(@Param("id") String id) {
if (StrUtil.isBlank(id)) {
return Result.error("请选择需要删除的事项");
}
memberCheckTaskService.dao().delete(MemberCheckTask.class, id);
memberCheckTaskService.dao().update(MemberCheckTaskUser.class,
org.nutz.dao.Chain.make("delFlag", true),
Cnd.where(MemberCheckTaskUser::getCheckTaskId, "=", id));
return Result.success();
}
@At
@SaCheckPermission("member.check.task")
public Result findOne(String id) {
return Result.success(memberCheckTaskService.dao().fetch(MemberCheckTask.class, id));
}
}
@@ -1,43 +0,0 @@
package com.budwk.app.zhgh.staffmanage.member.controller.check;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberCheckPageForm;
import com.budwk.app.zhgh.staffmanage.member.service.MemberCheckTaskService;
import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @version 1.0
* @Author zzr
* @name:MemberCheckTaskSchoolController
* @Date 2025/9/26 15:31
* @注释 校工会核对
*/
@Slf4j
@IocBean
@Ok("json")
@At("/platform/member/checkTask/school")
public class MemberCheckTaskSchoolController {
@Inject
private Dao dao;
@Inject
private MemberCheckTaskService memberCheckTaskService;
@At("")
@Ok("beetl:/platform/zhgh/staffmanage/member/check/school/index.html")
@SaCheckPermission("member.checkTask.school")
public void index() {}
@At
@SaCheckPermission("member.checkTask.school")
public Result pageData(MemberCheckPageForm pageForm) {
return Result.success();
}
}
@@ -1,179 +0,0 @@
package com.budwk.app.zhgh.staffmanage.member.controller.check;
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.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberCheckPageForm;
import com.budwk.app.zhgh.staffmanage.member.service.MemberCheckTaskService;
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;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @version 1.0
* @Author zzr
* @name:MemberCheckTaskUnionController
* @Date 2025/9/24 11:24
* @注释
*/
@Slf4j
@IocBean
@Ok("json")
@At("/platform/member/checkTask/union")
public class MemberCheckTaskUnionController {
@Inject
private Dao dao;
@Inject
private MemberCheckTaskService memberCheckTaskService;
@At("")
@Ok("beetl:/platform/zhgh/staffmanage/member/check/union/index.html")
@SaCheckPermission("member.checkTask.union")
public void index() {}
@At
@ApiOperation("页面数据")
@SaCheckPermission("member.checkTask.union")
public Result pageData(MemberCheckPageForm pageForm){
Sql sql = Sqls.create("""
SELECT
u.id,
u.loginname,
u.username,
u.sex,
u.birthday,
u.political,
u.joinPartyDate,
u.nation,
u.nativePlace,
u.nationality,
u.idCardType,
u.mobile,
u.education,
u.academicDegree,
u.position,
u.personType,
u.preparedBy,
u.identityType,
u.userState,
u.unionName,
u.unitName,
u.member,
u.postDoctoralJoinDate
FROM
`vw_user` u
$condition
""");
Cnd cnd = getCnd(pageForm);
if (StrUtil.isNotBlank(pageForm.getIsUnit())) {
cnd.and("u.unitId", "true".equals(pageForm.getIsUnit()) ? "is not" : "is", null);
}
if (StrUtil.isNotBlank(pageForm.getIsUnion())) {
cnd.and("u.unionId", "true".equals(pageForm.getIsUnion()) ? "is not" : "is", null);
}
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.or("u.username", "like", "%" + pageForm.getSearchKeyword() + "%");
seg.or("u.loginname", "like", "%" + pageForm.getSearchKeyword() + "%");
cnd.and(seg);
}
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and(Cnd.exps("u.unionId", "=", SecurityUtil.getUnionId())
.or("u.unionId", "is", null).or("u.unionId", "=", ""));
}
cnd.desc("u.unionName,u.id");
cnd.groupBy("u.id");
sql.setCondition(cnd);
Pagination pagination = memberCheckTaskService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
public Cnd getCnd(MemberCheckPageForm pageForm) {
Boolean reverseSelection = pageForm.getReverseSelection();
String IN_OR_NIN_OP = reverseSelection ? "NOT IN" : "IN";
String EQ_OR_NEQ_OP = reverseSelection ? "!=" : "=";
//小于等于
String LE_OR_NLE_OP = reverseSelection ? ">=" : "<=";
//大于等于
String GE_OR_NGE_OP = reverseSelection ? "<=" : ">=";
Cnd cnd = Cnd.NEW();
if (StrUtil.isAllNotBlank(pageForm.getPageOrderBy(), pageForm.getPageOrderName())) {
cnd.orderBy(pageForm.getPageOrderName(), "ascending".equalsIgnoreCase(pageForm.getPageOrderBy()) ? "ASC" : "DESC");
}
if (Lang.isNotEmpty(pageForm.getUserTypes())) {
if (pageForm.getUserTypes().contains("工会会员")) {
cnd.and("u.member", EQ_OR_NEQ_OP, true);
}
if (pageForm.getUserTypes().contains("福利会员")) {
cnd.and("u.welfareMember", EQ_OR_NEQ_OP, true);
}
}
if (Lang.isNotEmpty(pageForm.getAge()) && !"0".equals(pageForm.getAge().get(1))) {
if (reverseSelection) {
cnd.andNot("TIMESTAMPDIFF(YEAR, u.birthday, CURDATE())", "between", pageForm.getAge().toArray());
} else {
cnd.and("TIMESTAMPDIFF(YEAR, u.birthday, CURDATE())", "between", pageForm.getAge().toArray());
}
}
if (Strings.isNotBlank(pageForm.getBirthdayStartDate()) && Strings.isNotBlank(pageForm.getBirthdayEndDate())) {
if (reverseSelection) {
cnd.andNot("DATE(u.birthday)", "between", new String[]{pageForm.getBirthdayStartDate(), pageForm.getBirthdayEndDate()});
} else {
cnd.and("DATE(u.birthday)", "between", new String[]{pageForm.getBirthdayStartDate(), pageForm.getBirthdayEndDate()});
}
}
if (Strings.isNotBlank(pageForm.getBirthdayStartDate()) && Strings.isBlank(pageForm.getBirthdayEndDate())) {
cnd.and("DATE(u.birthday)", GE_OR_NGE_OP, pageForm.getBirthdayStartDate());
}
if (Strings.isBlank(pageForm.getBirthdayStartDate()) && Strings.isNotBlank(pageForm.getBirthdayEndDate())) {
cnd.and("DATE(u.birthday)", LE_OR_NLE_OP, pageForm.getBirthdayEndDate());
}
try {
handleField("id", pageForm.getUserInfos(), reverseSelection, IN_OR_NIN_OP, cnd);
handleField("unionId", pageForm.getUnionIds(), reverseSelection, IN_OR_NIN_OP, cnd);
handleField("unitId", pageForm.getUnitIds(), reverseSelection, IN_OR_NIN_OP, cnd);
handleField("personType", pageForm.getPersonTypes(), reverseSelection, IN_OR_NIN_OP, cnd);
handleField("preparedBy", pageForm.getPreparedBys(), reverseSelection, IN_OR_NIN_OP, cnd);
handleField("userState", pageForm.getUserStates(), reverseSelection, IN_OR_NIN_OP, cnd);
handleField("sex", pageForm.getSexTypes(), reverseSelection, IN_OR_NIN_OP, cnd);
} catch (Exception e) {
throw new RuntimeException(e);
}
return cnd;
}
void handleField(String fieldName, Object fieldValue, boolean reverseSelection, String IN_OR_NIN_OP, Cnd cnd) {
if (reverseSelection && Lang.isNotEmpty(fieldValue)) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.or("u." + fieldName, "is", null);
seg.or("u." + fieldName, IN_OR_NIN_OP, fieldValue);
cnd.and(seg);
} else {
cnd.andEX("u." + fieldName, IN_OR_NIN_OP, fieldValue);
}
}
}
@@ -40,8 +40,8 @@ public class MemberCheckTask extends BaseModel {
private String taskName;
@Column
@Comment("说明")
@ColDefine(type = ColType.VARCHAR, width = 50)
@Comment("内容详情")
@ColDefine(type = ColType.TEXT)
private String description;
@Column
@@ -38,7 +38,7 @@ public class MemberCheckPageForm extends PageForm {
// 单位id
@ApiModelProperty("单位id")
private String unitIds;
private List<String> unitIds;
@ApiModelProperty("出生日期开始时间")
private String birthdayStartDate;
@@ -50,10 +50,6 @@ public class MemberCheckPageForm extends PageForm {
@ApiModelProperty("在职状态")
private List<String> userStates;
// 在职状态
@ApiModelProperty("编制类别")
private List<String> preparedBys;
// 教职工类别
@ApiModelProperty("教职工类别")
private List<String> personTypes;
@@ -75,4 +71,19 @@ public class MemberCheckPageForm extends PageForm {
@ApiModelProperty("用户信息查询列表")
private List<String> userInfos;
@ApiModelProperty("事项名称")
private String taskName;
@ApiModelProperty("是否发布")
private Boolean isEnabled;
@ApiModelProperty("姓名")
private String userName;
@ApiModelProperty("工号")
private String loginName;
@ApiModelProperty("是否会员")
private Boolean isMember;
}
@@ -120,8 +120,8 @@ public class MemberInfoPageForm extends PageForm {
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.or(prefix + "unionId", "=", SecurityUtil.getUnionId());
seg.or(prefix + "unionId", "is", null);
seg.or(prefix + "unionId", "=", "");
// seg.or(prefix + "unionId", "is", null);
// seg.or(prefix + "unionId", "=", "");
cnd.and(seg);
} else {
cnd.andEX(prefix + "unionId", "=", this.getUnionId());
@@ -1,7 +1,16 @@
package com.budwk.app.zhgh.staffmanage.member.service;
import com.budwk.app.base.model.ExcelImportRes;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.staffmanage.member.models.check.MemberCheckTask;
import com.budwk.app.zhgh.staffmanage.member.models.check.MemberCheckTaskUser;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberCheckPageForm;
import com.budwk.app.zhgh.staffmanage.member.template.MemberCheckTaskUserImportTemp;
import org.nutz.lang.util.NutMap;
import java.io.File;
import java.util.List;
/**
* @version 1.0
@@ -11,4 +20,65 @@ import com.budwk.app.zhgh.staffmanage.member.models.check.MemberCheckTaskUser;
* @注释
*/
public interface MemberCheckTaskService extends BaseService<MemberCheckTaskUser> {
/**
* 查询会员核对事项。
*/
Pagination<NutMap> taskPageData(MemberCheckPageForm pageForm);
/**
* 保存会员核对事项,只维护事项本身,不重建名单。
*/
void saveTask(MemberCheckTask memberCheckTask);
/**
* 查询已发布的会员核对事项。
*/
List<MemberCheckTask> listEnabledTask(Integer year);
/**
* 查询会员核对名单,统一承载页面列表和导出数据范围。
*/
Pagination<NutMap> checkUserPageData(MemberCheckPageForm pageForm);
/**
* 查询会员核对名单,不分页,用于按当前筛选条件导出。
*/
List<NutMap> checkUserList(MemberCheckPageForm pageForm);
/**
* 导入会员核对名单,并按工号从系统用户视图补齐人员基础信息。
*/
ExcelImportRes<MemberCheckTaskUserImportTemp> importCheckUser(File file, String checkTaskId);
/**
* 分页查询当前筛选条件下尚未加入名单的系统人员。
*/
Pagination<NutMap> notCheckUserPageData(MemberCheckPageForm pageForm);
/**
* 将当前筛选条件下的系统人员批量加入会员核对名单。
*/
NutMap addCheckUser(MemberCheckPageForm pageForm);
/**
* 按事项和工会批量确认或取消确认名单。
*/
NutMap confirmByTaskAndUnion(String checkTaskId, String unionId, Boolean flag);
/**
* 按列表勾选记录批量确认或取消确认名单。
*/
void confirmSelected(String[] ids, Boolean flag);
/**
* 按列表勾选记录批量删除人员名单,非校工会管理员只能删除本工会数据。
*/
void deleteSelected(String[] ids);
/**
* 按工会统计会员核对名单确认完成情况。
*/
Pagination<NutMap> confirmStatistics(Integer pageNumber, Integer pageSize, Integer year,
String checkTaskId, String unionId);
}
@@ -2,6 +2,7 @@ package com.budwk.app.zhgh.staffmanage.member.service;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberInfoPageForm;
import org.apache.poi.ss.usermodel.Workbook;
import org.nutz.dao.sql.Sql;
@@ -27,6 +28,13 @@ public interface MemberInfoService extends BaseService<Sys_user> {
*/
Sql getSql(MemberInfoPageForm pageForm);
/**
* 获取会员详情,特殊人员优先返回工会关系所属工会,便于详情权限和列表权限保持一致。
* @param id 用户id
* @return 会员详情
*/
View_user getMemberInfoDetail(String id);
/**
* 获取会员历史
* @param pageForm
@@ -1,11 +1,38 @@
package com.budwk.app.zhgh.staffmanage.member.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.model.ExcelImportRes;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.base.utils.easyexcel.EasyExcelUtil;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.staffmanage.member.models.check.MemberCheckTask;
import com.budwk.app.zhgh.staffmanage.member.models.check.MemberCheckTaskUser;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberCheckPageForm;
import com.budwk.app.zhgh.staffmanage.member.service.MemberCheckTaskService;
import com.budwk.app.zhgh.staffmanage.member.template.MemberCheckTaskUserImportTemp;
import org.nutz.dao.Dao;
import org.nutz.dao.Chain;
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.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.apache.poi.ss.formula.functions.T;
import java.io.File;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* @version 1.0
@@ -20,4 +47,466 @@ public class MemberCheckTaskServiceImpl extends BaseServiceImpl<MemberCheckTaskU
public MemberCheckTaskServiceImpl(Dao dao) {
super(dao);
}
@Override
public Pagination<NutMap> taskPageData(MemberCheckPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
*
FROM member_check_task
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("`year`", "=", pageForm.getYear());
cnd.and(Cnd.likeEX("taskName", pageForm.getTaskName()));
cnd.andEX("isEnabled", "=", pageForm.getIsEnabled());
cnd.desc("startTime");
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
@Override
public void saveTask(MemberCheckTask memberCheckTask) {
if (memberCheckTask.getStartTime() != null) {
memberCheckTask.setYear(DateUtil.year(memberCheckTask.getStartTime()));
} else if (memberCheckTask.getYear() == null) {
memberCheckTask.setYear(DateUtil.thisYear());
}
dao().insertOrUpdate(memberCheckTask);
}
@Override
public List<MemberCheckTask> listEnabledTask(Integer year) {
Cnd cnd = Cnd.NEW();
cnd.andEX("year", "=", year);
cnd.and("isEnabled", "=", true);
cnd.desc("startTime");
return dao().query(MemberCheckTask.class, cnd);
}
@Override
public Pagination<NutMap> checkUserPageData(MemberCheckPageForm pageForm) {
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), buildCheckUserSql(pageForm));
}
@Override
public List<NutMap> checkUserList(MemberCheckPageForm pageForm) {
return listMap(buildCheckUserSql(pageForm));
}
@Override
public ExcelImportRes<MemberCheckTaskUserImportTemp> importCheckUser(File file, String checkTaskId) {
List<T> rows = EasyExcelUtil.syncReadModel(file, MemberCheckTaskUserImportTemp.class, 0, 1);
List<MemberCheckTaskUserImportTemp> importRows = JSONUtil.parseArray(JSONUtil.toJsonStr(rows)).toList(MemberCheckTaskUserImportTemp.class);
ExcelImportRes<MemberCheckTaskUserImportTemp> result = new ExcelImportRes<>();
result.setTotalRecords(importRows.size());
MemberCheckTask task = validateCheckUserTask(checkTaskId);
if (task == null) {
markAllFailed(importRows, "事项不存在、未发布或不在时间范围内");
fillImportResult(result, importRows, 0);
return result;
}
List<String> loginNames = importRows.stream()
.map(MemberCheckTaskUserImportTemp::getLoginname)
.filter(StrUtil::isNotBlank)
.map(Strings::trim)
.distinct()
.collect(Collectors.toList());
List<View_user> users = loginNames.isEmpty()
? Collections.emptyList()
: dao().query(View_user.class, Cnd.where(View_user::getLoginname, "in", loginNames));
int successCount = 0;
for (int i = 0; i < importRows.size(); i++) {
MemberCheckTaskUserImportTemp row = importRows.get(i);
String loginName = Strings.trim(row.getLoginname());
if (StrUtil.isBlank(loginName)) {
row.setErrInfo("工号不能为空", i + 1);
continue;
}
if (importRows.stream().filter(item -> loginName.equals(Strings.trim(item.getLoginname()))).count() > 1) {
row.setErrInfo("导入文件中工号重复", i + 1);
continue;
}
View_user user = users.stream()
.filter(item -> loginName.equals(item.getLoginname()))
.findFirst()
.orElse(null);
if (user == null) {
row.setErrInfo("工号在系统中不存在", i + 1);
continue;
}
upsertCheckUser(task, user);
successCount++;
}
fillImportResult(result, importRows, successCount);
return result;
}
@Override
public Pagination<NutMap> notCheckUserPageData(MemberCheckPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
u.id,
u.loginname,
u.username,
u.sex,
u.birthday,
u.personType,
u.userState,
u.unitId,
u.unitName,
u.unionId,
u.unionName,
u.member
FROM vw_user u
LEFT JOIN member_check_task_user info ON u.id = info.userId
AND info.checkTaskId = @checkTaskId
AND info.delFlag = 0
$condition
""").setParam("checkTaskId", pageForm.getCheckTaskId());
Cnd cnd = buildAddUserFilterCnd(pageForm);
cnd.and("info.userId", "is", null);
sql.setCondition(cnd);
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
}
@Override
public NutMap addCheckUser(MemberCheckPageForm pageForm) {
MemberCheckTask task = validateCheckUserTask(pageForm.getCheckTaskId());
if (task == null) {
return NutMap.NEW().addv("code", 1).addv("msg", "添加失败,请选择已发布且在时间范围内的事项");
}
Sql sql = Sqls.create("""
SELECT
u.id,
u.loginname,
u.username,
u.sex,
u.birthday,
u.political,
u.joinPartyDate,
u.nation,
u.nativePlace,
u.nationality,
u.idCardType,
u.idCard,
u.email,
u.mobile,
u.education,
u.academicDegree,
u.position,
u.personType,
u.identityType,
u.userState,
u.unitId,
u.unitName,
u.unionId,
u.unionName,
u.member,
u.welfareMember,
u.retireDate,
u.personalData,
u.postDoctoralJoinDate
FROM vw_user u
$condition
""");
Cnd cnd = buildAddUserFilterCnd(pageForm);
cnd.and("u.id", "not in", Sqls.create("""
SELECT userId FROM member_check_task_user
WHERE checkTaskId = @checkTaskId AND delFlag = 0
""").setParam("checkTaskId", pageForm.getCheckTaskId()));
sql.setCondition(cnd);
List<NutMap> users = listMap(sql);
if (users.isEmpty()) {
return NutMap.NEW().addv("code", 1).addv("msg", "添加失败,暂无数据");
}
for (NutMap user : users) {
upsertCheckUser(task, user);
}
return NutMap.NEW().addv("code", 0).addv("msg", "添加成功");
}
@Override
public NutMap confirmByTaskAndUnion(String checkTaskId, String unionId, Boolean flag) {
Cnd cnd = Cnd.NEW().and("checkTaskId", "=", checkTaskId).and("unionId", "=", unionId).and("delFlag", "=", false);
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("unionId", "=", SecurityUtil.getUnionId());
}
// 按工会确认依赖当前事项和工会筛选结果,空数据时明确返回失败,避免页面误认为已确认。
if (count(cnd) == 0) {
return NutMap.NEW().addv("code", 1).addv("msg", "确认失败,暂无数据");
}
updateAuditState(cnd, flag);
return NutMap.NEW().addv("code", 0).addv("msg", "操作成功");
}
@Override
public void confirmSelected(String[] ids, Boolean flag) {
if (ids == null || ids.length == 0) {
return;
}
Cnd cnd = Cnd.where("id", "in", ids).and("delFlag", "=", false);
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("unionId", "=", SecurityUtil.getUnionId());
}
updateAuditState(cnd, flag);
}
@Override
public void deleteSelected(String[] ids) {
if (ids == null || ids.length == 0) {
return;
}
Cnd cnd = Cnd.where("id", "in", ids).and("delFlag", "=", false);
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("unionId", "=", SecurityUtil.getUnionId());
}
// 人员名单删除采用逻辑删除,避免核对名单被物理清除后无法追溯。
dao().update(MemberCheckTaskUser.class, Chain.make("delFlag", true), cnd);
}
@Override
public Pagination<NutMap> confirmStatistics(Integer pageNumber, Integer pageSize, Integer year, String checkTaskId, String unionId) {
Sql sql = Sqls.create("""
SELECT
su.id AS unionId,
su.name AS unionName,
COUNT(CASE WHEN task.id IS NOT NULL THEN info.id END) AS totalCount,
SUM(CASE WHEN task.id IS NOT NULL AND info.branchUnionChecked = 1 THEN 1 ELSE 0 END) AS confirmedCount,
SUM(CASE WHEN task.id IS NOT NULL AND info.id IS NOT NULL AND (info.branchUnionChecked IS NULL OR info.branchUnionChecked <> 1) THEN 1 ELSE 0 END) AS unconfirmedCount,
CASE
WHEN COUNT(CASE WHEN task.id IS NOT NULL THEN info.id END) > 0
AND COUNT(CASE WHEN task.id IS NOT NULL THEN info.id END) = SUM(CASE WHEN task.id IS NOT NULL AND info.branchUnionChecked = 1 THEN 1 ELSE 0 END) THEN '已完成'
ELSE '未完成'
END AS completeStatus
FROM sys_union su
LEFT JOIN member_check_task_user info ON info.unionId = su.id
AND info.delFlag = 0
AND info.checkTaskId = @checkTaskId
LEFT JOIN member_check_task task ON task.id = info.checkTaskId
AND task.delFlag = 0
AND task.year = @year
$condition
""").setParam("checkTaskId", checkTaskId).setParam("year", year);
Cnd cnd = Cnd.NEW();
cnd.andEX("su.id", "=", unionId);
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("su.id", "=", SecurityUtil.getUnionId());
}
cnd.groupBy("su.id,su.name");
cnd.asc("completeStatus");
cnd.asc("su.unionCode");
sql.setCondition(cnd);
return listPageMap(pageNumber, pageSize, sql);
}
private Sql buildCheckUserSql(MemberCheckPageForm pageForm) {
Sql sql = Sqls.create("""
SELECT
info.*,
task.taskName,
task.year AS taskYear,
CASE WHEN info.branchUnionChecked = 1 THEN FROM_UNIXTIME(info.updatedAt / 1000) ELSE NULL END AS auditTime
FROM member_check_task_user info
LEFT JOIN member_check_task task ON task.id = info.checkTaskId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("info.delFlag", "=", false);
cnd.and("task.delFlag", "=", false);
cnd.andEX("task.year", "=", pageForm.getYear());
cnd.andEX("info.checkTaskId", "=", pageForm.getCheckTaskId());
cnd.andEX("info.unionId", "=", pageForm.getUnionIds());
cnd.andEX("info.unitId", "in", pageForm.getUnitIds());
if (pageForm.getAudit() != null) {
cnd.and("info.branchUnionChecked", "=", pageForm.getAudit());
}
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.andEX("info.unionId", "=", SecurityUtil.getUnionId());
}
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup group = new SqlExpressionGroup();
group.orLike("info.username", pageForm.getSearchKeyword());
group.orLike("info.loginname", pageForm.getSearchKeyword());
cnd.and(group);
}
cnd.desc("info.createdAt");
cnd.desc("info.updatedAt");
sql.setCondition(cnd);
return sql;
}
private MemberCheckTask validateCheckUserTask(String checkTaskId) {
if (StrUtil.isBlank(checkTaskId)) {
return null;
}
MemberCheckTask task = dao().fetch(MemberCheckTask.class,
Cnd.where("id", "=", checkTaskId).and("isEnabled", "=", true).and("delFlag", "=", false));
if (task == null) {
return null;
}
Date now = new Date();
if ((task.getStartTime() != null && now.before(task.getStartTime()))
|| (task.getEndTime() != null && now.after(task.getEndTime()))) {
return null;
}
return task;
}
private Cnd buildAddUserFilterCnd(MemberCheckPageForm pageForm) {
Cnd cnd = Cnd.NEW();
if (StrUtil.isNotBlank(pageForm.getUserName())) {
cnd.and(Cnd.likeEX("u.username", pageForm.getUserName()));
}
if (StrUtil.isNotBlank(pageForm.getLoginName())) {
cnd.and(Cnd.likeEX("u.loginname", pageForm.getLoginName()));
}
cnd.andEX("u.unionId", "=", pageForm.getUnionIds());
cnd.andEX("u.unitId", "in", pageForm.getUnitIds());
cnd.andEX("u.personType", "in", pageForm.getPersonTypes());
cnd.andEX("u.userState", "in", pageForm.getUserStates());
cnd.andEX("u.member", "=", pageForm.getIsMember());
if (pageForm.getSexTypes() != null && !pageForm.getSexTypes().isEmpty()) {
cnd.andEX("u.sex", "in", pageForm.getSexTypes());
}
if (Strings.isNotBlank(pageForm.getBirthdayStartDate()) && Strings.isNotBlank(pageForm.getBirthdayEndDate())) {
cnd.and("DATE(u.birthday)", "between", new String[]{pageForm.getBirthdayStartDate(), pageForm.getBirthdayEndDate()});
}
if (Strings.isNotBlank(pageForm.getBirthdayStartDate()) && Strings.isBlank(pageForm.getBirthdayEndDate())) {
cnd.and("DATE(u.birthday)", ">=", pageForm.getBirthdayStartDate());
}
if (Strings.isBlank(pageForm.getBirthdayStartDate()) && Strings.isNotBlank(pageForm.getBirthdayEndDate())) {
cnd.and("DATE(u.birthday)", "<=", pageForm.getBirthdayEndDate());
}
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("u.unionId", "=", SecurityUtil.getUnionId());
}
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.asc("u.unionCode");
cnd.asc("u.unitCode");
cnd.asc("u.loginname");
} else {
cnd.orderBy("u." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
}
return cnd;
}
private void updateAuditState(Cnd cnd, Boolean flag) {
Chain chain = Chain.make("branchUnionChecked", Boolean.TRUE.equals(flag));
dao().update(MemberCheckTaskUser.class, chain, cnd);
}
private void upsertCheckUser(MemberCheckTask task, View_user user) {
MemberCheckTaskUser info = dao().fetch(MemberCheckTaskUser.class,
Cnd.where("checkTaskId", "=", task.getId()).and("userId", "=", user.getId()));
if (info == null) {
info = new MemberCheckTaskUser();
info.setCheckTaskId(task.getId());
info.setBranchUnionChecked(false);
info.setSchoolUnionChecked(false);
info.setIsChanged(false);
}
info.setDelFlag(false);
fillCheckUser(info, user);
dao().insertOrUpdate(info);
}
private void upsertCheckUser(MemberCheckTask task, NutMap user) {
MemberCheckTaskUser info = dao().fetch(MemberCheckTaskUser.class,
Cnd.where("checkTaskId", "=", task.getId()).and("userId", "=", user.getString("id")));
if (info == null) {
info = new MemberCheckTaskUser();
info.setCheckTaskId(task.getId());
info.setBranchUnionChecked(false);
info.setSchoolUnionChecked(false);
info.setIsChanged(false);
}
info.setDelFlag(false);
fillCheckUser(info, user);
dao().insertOrUpdate(info);
}
private void fillCheckUser(MemberCheckTaskUser info, View_user user) {
info.setUserId(user.getId());
info.setLoginname(user.getLoginname());
info.setUsername(user.getUsername());
info.setSex(user.getSex());
info.setBirthday(user.getBirthday());
info.setPolitical(user.getPolitical());
info.setNation(user.getNation());
info.setIdCard(user.getIdCard());
info.setEmail(user.getEmail());
info.setMobile(user.getMobile());
info.setEducation(user.getEducation());
info.setAcademicDegree(user.getAcademicDegree());
info.setPosition(user.getPosition());
info.setPersonType(user.getPersonType());
info.setUserState(user.getUserState());
info.setUnitId(user.getUnitId());
info.setUnitName(user.getUnitName());
info.setUnionId(user.getUnionId());
info.setUnionName(user.getUnionName());
info.setMember(user.getMember() != null && user.getMember() == 1);
info.setWelfareMember(user.getWelfareMember() != null && user.getWelfareMember() == 1);
info.setCampus(user.getCampusName());
info.setRetireDate(user.getRetireDate());
info.setPersonalData(user.getPersonalData());
info.setWelfareStopDate(user.getWelfareStopDate() == null ? null : DateUtil.formatDate(user.getWelfareStopDate()));
}
private void fillCheckUser(MemberCheckTaskUser info, NutMap user) {
info.setUserId(user.getString("id"));
info.setLoginname(user.getString("loginname"));
info.setUsername(user.getString("username"));
info.setSex(user.getString("sex"));
info.setBirthday(getDate(user, "birthday"));
info.setPolitical(user.getString("political"));
info.setNation(user.getString("nation"));
info.setIdCard(user.getString("idCard"));
info.setEmail(user.getString("email"));
info.setMobile(user.getString("mobile"));
info.setEducation(user.getString("education"));
info.setAcademicDegree(user.getString("academicDegree"));
info.setPosition(user.getString("position"));
info.setPersonType(user.getString("personType"));
info.setUserState(user.getString("userState"));
info.setUnitId(user.getString("unitId"));
info.setUnitName(user.getString("unitName"));
info.setUnionId(user.getString("unionId"));
info.setUnionName(user.getString("unionName"));
info.setMember("1".equals(user.getString("member")) || Boolean.TRUE.equals(user.getBoolean("member")));
info.setWelfareMember("1".equals(user.getString("welfareMember")) || Boolean.TRUE.equals(user.getBoolean("welfareMember")));
info.setCampus(user.getString("campus"));
info.setRetireDate(getDate(user, "retireDate"));
info.setPersonalData(user.getString("personalData"));
}
private Date getDate(NutMap user, String key) {
Object value = user.get(key);
if (value instanceof Date) {
return (Date) value;
}
if (value == null || StrUtil.isBlank(value.toString())) {
return null;
}
return DateUtil.parse(value.toString());
}
private void markAllFailed(List<MemberCheckTaskUserImportTemp> rows, String msg) {
for (int i = 0; i < rows.size(); i++) {
rows.get(i).setErrInfo(msg, i + 1);
}
}
private void fillImportResult(ExcelImportRes<MemberCheckTaskUserImportTemp> result,
List<MemberCheckTaskUserImportTemp> rows,
int successCount) {
result.setSuccessCount(successCount);
result.setErrorDetails(rows.stream().filter(row -> StrUtil.isNotBlank(row.getErrMsg())).collect(Collectors.toList()));
result.setFailedCount(result.getErrorDetails().size());
}
}
@@ -15,6 +15,7 @@ import com.budwk.app.base.utils.easyexcel.EasyExcelUtil;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_unit;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
@@ -22,6 +23,7 @@ import com.budwk.app.zhgh.staffmanage.member.models.MemberHistory;
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberInfoPageForm;
import com.budwk.app.zhgh.staffmanage.member.service.MemberInfoService;
import com.budwk.app.zhgh.staffmanage.member.vo.MemberImportVo;
import com.budwk.app.zhgh.staffmanage.specialstaff.model.SpecialStaff;
import org.apache.poi.ss.formula.functions.T;
import org.apache.poi.ss.usermodel.Workbook;
import org.nutz.aop.interceptor.ioc.TransAop;
@@ -64,9 +66,14 @@ public class MemberInfoServiceImpl extends BaseServiceImpl<Sys_user> implements
@Override
public Sql getSql(MemberInfoPageForm pageForm) {
// 特殊人员优先使用工会关系所属工会,普通人员继续使用用户当前所属工会。
Sql sql = Sqls.create("""
SELECT
u.id,
u.unionId,
u.unionCode,
u.unitId,
u.unitCode,
u.loginname,
u.username,
u.sex,
@@ -103,7 +110,58 @@ public class MemberInfoServiceImpl extends BaseServiceImpl<Sys_user> implements
u.member,
DATE_FORMAT(u.postDoctoralJoinDate, '%Y-%m-%d') AS postDoctoralJoinDate
FROM
vw_user u
(
SELECT
vu.id,
CASE
WHEN NULLIF(s.unionRelationUnionId, '') IS NOT NULL THEN s.unionRelationUnionId
ELSE vu.unionId
END AS unionId,
vu.unionCode,
vu.unitId,
vu.unitCode,
vu.loginname,
vu.username,
vu.sex,
vu.birthday,
vu.political,
vu.joinPartyDate,
vu.nation,
vu.nativePlace,
vu.nationality,
vu.idCardType,
vu.mobile,
vu.idCard,
vu.marriage,
vu.education,
vu.academicDegree,
vu.position,
vu.jobCategory,
vu.professionalTitle,
vu.professionalLevel,
vu.employeeSource,
vu.administrativeLevel,
vu.positionSeries,
vu.positionLevel,
vu.administrativePositionLevel,
vu.arrivalAtSchoolDate,
vu.personType,
vu.preparedBy,
vu.identityType,
vu.userState,
CASE
WHEN NULLIF(s.unionRelationUnionId, '') IS NOT NULL THEN s.unionRelationUnionName
ELSE vu.unionName
END AS unionName,
vu.unitName,
vu.teachingTime,
vu.expectedLeaveSchoolDate,
vu.member,
vu.postDoctoralJoinDate
FROM
vw_user vu
LEFT JOIN special_staff s ON s.userId = vu.id
) u
$condition
""");
Cnd cnd = Cnd.NEW();
@@ -113,6 +171,24 @@ public class MemberInfoServiceImpl extends BaseServiceImpl<Sys_user> implements
return sql;
}
@Override
public View_user getMemberInfoDetail(String id) {
View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", id));
if (user == null) {
return null;
}
SpecialStaff specialStaff = dao().fetch(SpecialStaff.class, Cnd.where("userId", "=", id));
// 详情权限和列表权限共用有效工会口径:特殊人员优先使用工会关系,普通人员使用原所属工会。
if (specialStaff != null && StrUtil.isNotBlank(specialStaff.getUnionRelationUnionId())) {
user.setUnionId(specialStaff.getUnionRelationUnionId());
user.setUnionName(specialStaff.getUnionRelationUnionName());
user.setUnionGroupId(specialStaff.getUnionRelationUnionGroupId());
user.setUnionGroupName(specialStaff.getUnionRelationUnionGroupName());
}
return user;
}
@Override
public Sql getMemberHistorySql(MemberInfoPageForm pageForm) {
@@ -0,0 +1,26 @@
package com.budwk.app.zhgh.staffmanage.member.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;
/**
* 会员核对名单导入模板。
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ContentRowHeight(20)
@HeadRowHeight(20)
@ColumnWidth(25)
public class MemberCheckTaskUserImportTemp extends ExcelImportError {
@ExcelProperty("工号")
private String loginname;
@ExcelProperty("姓名")
private String username;
}
@@ -23,8 +23,8 @@ import com.budwk.app.zhgh.welfare.model.WelfareProjectSubjectOption;
import com.budwk.app.zhgh.welfare.param.WelfareSelectionSituationPageForm;
import com.budwk.app.zhgh.welfare.service.WelfareSelectionSituationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
@@ -255,9 +255,9 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
return map;
}).toList();
// 分组
// 按工会名称分组,工会名称为空时使用默认 sheet 名称,避免导出时 groupingBy 空 key 报错
Map<String, List<Map<String, Object>>> listMap = safeList.stream()
.collect(Collectors.groupingBy(n -> (String) n.get("welfareUnionName")));
.collect(Collectors.groupingBy(n -> StrUtil.blankToDefault(Objects.toString(n.get("welfareUnionName"), ""), "未设置工会"), LinkedHashMap::new, Collectors.toList()));
// 构建 Excel 列
List<ExcelExportEntity> entities = new ArrayList<>();
@@ -272,15 +272,15 @@ public class WelfareSelectionSituationServiceImpl extends BaseServiceImpl<Welfar
entities.add(userSignEntity);
// 导出
Workbook workbook = new HSSFWorkbook();
Workbook workbook = new XSSFWorkbook();
listMap.forEach((k, v) -> {
ExcelExportService service = new ExcelExportService();
ExportParams exportParams = new ExportParams();
exportParams.setSheetName(k);
exportParams.setType(ExcelType.HSSF);
exportParams.setType(ExcelType.XSSF);
service.createSheetForMap(workbook, exportParams, entities, v);
});
CommonDownloadUtil.download("领取表.xls", workbook, response);
CommonDownloadUtil.download("领取表.xlsx", workbook, response);
}
}
@@ -498,11 +498,11 @@ public class WelfareStatisticsServiceImpl extends BaseServiceImpl<WelfareProject
for (NutMap union : mapUnions) {
// 福利人数
long teacherSum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id"))).count();
long teacherSum = welfareSelectionList.stream().filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId", "").equals(union.getString("id"))).count();
union.put("teacherSum", teacherSum);
// 已选人数
long selectedNum = welfareSelectionList.stream().filter(v -> v.getString("welfareUnionId").equals(union.getString("id")) && v.getBoolean("has_selected")).count();
long selectedNum = welfareSelectionList.stream().filter(v -> StrUtil.isNotBlank(v.getString("welfareUnionId")) && v.getString("welfareUnionId", "").equals(union.getString("id")) && v.getBoolean("has_selected")).count();
union.put("selectedNum", selectedNum);
// 未选人数
@@ -25,6 +25,9 @@ const flowMixins = {
console.log(this.$refs)
console.log(this.$refs.guava)
// 首页待办已完成页面跳转,自动定位待办详情逻辑暂未启用时,及时关闭加载动画避免页面卡住
loading.close();
// this.oepnAudit({})
//
//
@@ -420,7 +420,7 @@ layout("/layouts/v4/baseLayout.html"){
this.$message.warning("当前流程没有配置地址")
return
}
window.open(formKey + "?taskId=" + taskId + "bizId=" + businessNo + "taskKey=" + taskKey)
window.open(formKey + "?taskId=" + taskId + "&bizId=" + businessNo + "&taskKey=" + taskKey)
},
// 获取空状态文本
@@ -0,0 +1,223 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.appeal-search-page .search {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 20px;
row-gap: 10px;
}
.appeal-search-page .search .search-item {
width: 100%;
}
.appeal-search-page .search .search-item-label {
width: 76px;
min-width: 76px;
margin-right: 8px;
}
.appeal-search-page .search .search-item-option {
min-width: calc(100% - 76px - 8px);
}
@media screen and (max-width: 1350px) {
.appeal-search-page .search {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media screen and (max-width: 1200px) {
.appeal-search-page .search {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media screen and (max-width: 992px) {
.appeal-search-page .search {
grid-template-columns: 1fr;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava" class="appeal-search-page">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" style="width: 100%" placeholder="请选择年度"></el-date-picker>
</search-item>
<search-item label="申诉类型">
<el-select v-model="pageForm.appealTypeId" filterable clearable style="width: 100%" placeholder="请选择申诉类型">
<el-option v-for="item in typeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="申诉标题">
<el-input v-model="pageForm.searchKeyword" clearable placeholder="请输入申诉标题" @keyup.enter.native="doSearch"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool :app="this" label="审批列表">
<el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.approval">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="taskId" style="width: 100%">
<el-table-column type="index" label="序号" width="60" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="申诉标题" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="申诉人" width="100"></el-table-column>
<el-table-column prop="appealTypeName" label="申诉类型" width="140"></el-table-column>
<el-table-column prop="defendantUnitName" label="被申诉单位" width="180" show-overflow-tooltip></el-table-column>
<el-table-column prop="applyDate" label="申请日期" width="120"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点" width="120"></el-table-column>
<el-table-column prop="instanceState" label="流程状态" width="120">
<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="210">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="onOpen(row)">查看</el-button>
<el-button size="mini" type="primary" v-if="row.taskState === 10" @click="onDeal(row)">审核</el-button>
<el-button size="mini" type="danger" v-if="row.canRevoke" @click="onRevoke(row)">撤回</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<appeal-info ref="infoRef"></appeal-info>
</template>
</guava>
<el-dialog title="受理申诉" :visible.sync="dialogVisible" width="900px" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="130px">
<el-form-item label="申诉标题">
<el-input v-model="formData.title" disabled></el-input>
</el-form-item>
<el-form-item label="作出决定日期" prop="decisionDate" :rules="[{required:true,message:'请选择决定日期',trigger:'change'}]">
<el-date-picker v-model="formData.decisionDate" value-format="yyyy-MM-dd" type="date" style="width: 100%"></el-date-picker>
</el-form-item>
<el-form-item label="处理决定内容" prop="decisionContent" :rules="[{required:true,validator:validateText,message:'请输入处理决定内容',trigger:['blur','change']}]">
<el-input v-model="formData.decisionContent" type="textarea" :rows="5" maxlength="2000" show-word-limit placeholder="请输入处理决定内容"></el-input>
</el-form-item>
<el-form-item label="事实理由及依据" prop="legalBasis" :rules="[{required:true,validator:validateText,message:'请输入事实理由及依据',trigger:['blur','change']}]">
<el-input v-model="formData.legalBasis" type="textarea" :rows="6" maxlength="3000" show-word-limit placeholder="请输入事实理由及依据"></el-input>
</el-form-item>
<el-form-item label="决定书附件" prop="decisionFiles">
<file-upload :value.sync="formData.decisionFiles" :upload_number="5" upload_mode="drag" upload_result_category="array" complete_result></file-upload>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="dialogVisible=false">取消</el-button>
<el-button type="warning" @click="doAccept(6)">退回修改</el-button>
<el-button type="danger" @click="doAccept(2)">不予受理</el-button>
<el-button type="primary" @click="doAccept(1)">受理并转执行</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"appeal-info": APPEAL_INFO
},
data() {
return {
pageForm: {
approval: false
},
typeOptions: [],
dialogVisible: false,
formData: {},
currentTaskId: null
}
},
methods: {
onOpen(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
onDeal(row) {
this.currentTaskId = row.taskId
this.$axios.post("/platform/appeal/accept/queryTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.formData = res.data || row
if (!this.formData.decisionDate) {
this.$set(this.formData, "decisionDate", this.$moment().format("YYYY-MM-DD"))
}
this.dialogVisible = true
}
})
},
doAccept(submitType) {
const submit = () => {
this.$axios.post("/platform/appeal/accept/accept", {
data: JSON.stringify(this.formData),
taskId: this.currentTaskId,
submitType
}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogVisible = false
this.pageData()
}
})
}
if (submitType !== 6) {
this.$refs.formRef.validate((valid) => {
if (valid) submit()
})
} else {
submit()
}
},
validateText(rule, value, callback) {
if (!(value || "").trim()) {
callback(new Error(rule.message))
return
}
callback()
},
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()
}
})
})
},
loadTypeOptions() {
this.$axios.post("/platform/appeal/common/typeOptions").then((res) => {
if (res.code === 0) this.typeOptions = res.data || []
})
}
},
created() {
this.loadTypeOptions()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,127 @@
const APPEAL_INFO = {
name: "AppealInfo",
/*language=HTML*/
template: `
<div class="appeal-info">
<div class="process-title">申诉基础信息</div>
<h3 style="text-align: center;font-weight: 600" class="pt10 pb10">{{ viewData.title }}</h3>
<el-descriptions :column="3" border>
<el-descriptions-item label="申诉人">{{ text(viewData.userName) }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ text(viewData.sex) }}</el-descriptions-item>
<el-descriptions-item label="出生年月">{{ text(viewData.birthday) }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ text(viewData.political) }}</el-descriptions-item>
<el-descriptions-item label="工号">{{ text(viewData.loginName) }}</el-descriptions-item>
<el-descriptions-item label="所在单位">{{ text(viewData.unitName) }}</el-descriptions-item>
<el-descriptions-item label="岗位">{{ text(viewData.positionName) }}</el-descriptions-item>
<el-descriptions-item label="联系电话">{{ text(viewData.mobile) }}</el-descriptions-item>
<el-descriptions-item label="申请日期">{{ text(viewData.applyDate) }}</el-descriptions-item>
<el-descriptions-item label="住址" :span="3">{{ text(viewData.address) }}</el-descriptions-item>
<el-descriptions-item label="申诉类型">{{ text(viewData.appealTypeName) }}</el-descriptions-item>
<el-descriptions-item label="业务状态">
<el-tag size="mini">{{ viewData.state || '草稿' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="被申诉单位">{{ text(viewData.defendantUnitName) }}</el-descriptions-item>
<el-descriptions-item label="被申诉单位地址" :span="2">{{ text(viewData.defendantAddress) }}</el-descriptions-item>
<el-descriptions-item label="被申诉单位电话">{{ text(viewData.defendantContact) }}</el-descriptions-item>
<el-descriptions-item label="申诉事项" :span="3">
<div class="text-left" style="white-space: pre-wrap;" v-text="plainText(viewData.appealMatter)"></div>
</el-descriptions-item>
<el-descriptions-item label="申诉理由" :span="3">
<div class="text-left" style="white-space: pre-wrap;" v-text="plainText(viewData.reason)"></div>
</el-descriptions-item>
<el-descriptions-item label="申诉要求" :span="3">
<div class="text-left" style="white-space: pre-wrap;" v-text="plainText(viewData.request)"></div>
</el-descriptions-item>
<el-descriptions-item label="申诉材料附件" :span="3">
<file-preview :files="viewData.files" complete_result></file-preview>
</el-descriptions-item>
<el-descriptions-item label="申诉人签名" :span="3">
<el-image v-if="viewData.signature" :src="viewData.signature" class="signature-image"></el-image>
<span v-else>暂无</span>
</el-descriptions-item>
</el-descriptions>
<div class="process-title mt10" v-if="viewData.acceptTime || viewData.decisionContent">受理与处理决定</div>
<el-descriptions :column="3" border v-if="viewData.acceptTime || viewData.decisionContent">
<el-descriptions-item label="受理人">{{ viewData.acceptUserName }}</el-descriptions-item>
<el-descriptions-item label="受理时间">{{ viewData.acceptTime }}</el-descriptions-item>
<el-descriptions-item label="决定日期">{{ viewData.decisionDate }}</el-descriptions-item>
<el-descriptions-item label="决定内容" :span="3">
<div class="text-left" style="white-space: pre-wrap;" v-text="plainText(viewData.decisionContent)"></div>
</el-descriptions-item>
<el-descriptions-item label="事实理由及依据" :span="3">
<div class="text-left" style="white-space: pre-wrap;" v-text="plainText(viewData.legalBasis)"></div>
</el-descriptions-item>
<el-descriptions-item label="决定书附件" :span="3">
<file-preview :files="viewData.decisionFiles" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
<div class="process-title mt10" v-if="viewData.executeTime || viewData.executeContent">执行情况</div>
<el-descriptions :column="3" border v-if="viewData.executeTime || viewData.executeContent">
<el-descriptions-item label="执行人">{{ viewData.executeUserName }}</el-descriptions-item>
<el-descriptions-item label="执行时间">{{ viewData.executeTime }}</el-descriptions-item>
<el-descriptions-item label="执行状态">{{ viewData.state }}</el-descriptions-item>
<el-descriptions-item label="执行情况" :span="3">
<div class="text-left" style="white-space: pre-wrap;" v-text="plainText(viewData.executeContent)"></div>
</el-descriptions-item>
<el-descriptions-item label="执行附件" :span="3">
<file-preview :files="viewData.executeFiles" complete_result></file-preview>
</el-descriptions-item>
</el-descriptions>
<template v-for="task in doneTasks">
<div class="mt10" :key="task.id">
<div class="process-title">{{ task.displayName }}</div>
<el-descriptions border class="flow-task-form" :column="3">
<el-descriptions-item label="办理用户">
{{ task.taskFormData && task.taskFormData.userName ? task.taskFormData.userName : task.ext.initiatorName }}
</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="办理意见" :span="3" v-if="task.taskFormData && task.taskFormData.tf_opinion">
<div v-html="task.taskFormData.tf_opinion"></div>
</el-descriptions-item>
</el-descriptions>
</div>
</template>
</div>
`,
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
data() {
return {
viewData: {},
doneTasks: []
}
},
methods: {
onOpen(row) {
this.viewData = {...row}
this.getDoneTasks()
},
getDoneTasks() {
if (!this.viewData.id) {
this.doneTasks = []
return
}
this.$axios.post("/flow/common/doneTasks", {bizId: this.viewData.id}).then((res) => {
if (res.code === 0) {
this.doneTasks = res.data || []
}
})
},
text(value) {
return value || "-"
},
plainText(value) {
return (value || "")
.replace(/<br\s*\/?>/gi, "\n")
.replace(/<\/p>/gi, "\n")
.replace(/<[^>]+>/g, "")
.replace(/&nbsp;/g, " ")
.trim() || "-"
}
}
}
@@ -0,0 +1,205 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.appeal-search-page .search {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 20px;
row-gap: 10px;
}
.appeal-search-page .search .search-item {
width: 100%;
}
.appeal-search-page .search .search-item-label {
width: 76px;
min-width: 76px;
margin-right: 8px;
}
.appeal-search-page .search .search-item-option {
min-width: calc(100% - 76px - 8px);
}
@media screen and (max-width: 1350px) {
.appeal-search-page .search {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media screen and (max-width: 1200px) {
.appeal-search-page .search {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media screen and (max-width: 992px) {
.appeal-search-page .search {
grid-template-columns: 1fr;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava" class="appeal-search-page">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" style="width: 100%" placeholder="请选择年度"></el-date-picker>
</search-item>
<search-item label="申诉类型">
<el-select v-model="pageForm.appealTypeId" filterable clearable style="width: 100%" placeholder="请选择申诉类型">
<el-option v-for="item in typeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="申诉标题">
<el-input v-model="pageForm.searchKeyword" clearable placeholder="请输入申诉标题" @keyup.enter.native="doSearch"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool :app="this" label="审批列表">
<el-radio-group @change="doSearch" class="mr5" size="small" v-model="pageForm.approval">
<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" :size="tableSize" @sort-change="pageOrder" ref="table" row-key="taskId" style="width: 100%">
<el-table-column type="index" label="序号" width="60" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="申诉标题" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="申诉人" width="100"></el-table-column>
<el-table-column prop="appealTypeName" label="申诉类型" width="140"></el-table-column>
<el-table-column prop="defendantUnitName" label="被申诉单位" width="180" show-overflow-tooltip></el-table-column>
<el-table-column prop="applyDate" label="申请日期" width="120"></el-table-column>
<el-table-column prop="curTaskName" label="当前节点" width="120"></el-table-column>
<el-table-column prop="instanceState" label="流程状态" width="120">
<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="210">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="onOpen(row)">查看</el-button>
<el-button size="mini" type="primary" v-if="row.taskState === 10" @click="onDeal(row)">审核</el-button>
<el-button size="mini" type="danger" v-if="row.canRevoke" @click="onRevoke(row)">撤回</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<appeal-info ref="infoRef"></appeal-info>
</template>
</guava>
<el-dialog title="执行反馈" :visible.sync="dialogVisible" width="900px" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="120px">
<el-form-item label="申诉标题">
<el-input v-model="formData.title" disabled></el-input>
</el-form-item>
<el-form-item label="执行情况" prop="executeContent" :rules="[{required:true,validator:validateText,message:'请输入执行情况',trigger:['blur','change']}]">
<el-input v-model="formData.executeContent" type="textarea" :rows="5" maxlength="2000" show-word-limit placeholder="请输入执行情况"></el-input>
</el-form-item>
<el-form-item label="执行附件" prop="executeFiles">
<file-upload :value.sync="formData.executeFiles" :upload_number="5" upload_mode="drag" upload_result_category="array" complete_result></file-upload>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="dialogVisible=false">取消</el-button>
<el-button type="primary" @click="doExecute">提交</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"appeal-info": APPEAL_INFO
},
data() {
return {
pageForm: {
approval: false
},
typeOptions: [],
dialogVisible: false,
formData: {},
currentTaskId: null
}
},
methods: {
onOpen(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
onDeal(row) {
this.currentTaskId = row.taskId
this.$axios.post("/platform/appeal/execute/queryTask", {taskId: row.taskId}).then((res) => {
if (res.code === 0) {
this.formData = res.data || row
this.dialogVisible = true
}
})
},
doExecute() {
this.$refs.formRef.validate((valid) => {
if (!valid) return
this.$axios.post("/platform/appeal/execute/execute", {
data: JSON.stringify(this.formData),
taskId: this.currentTaskId
}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogVisible = false
this.pageData()
}
})
})
},
validateText(rule, value, callback) {
if (!(value || "").trim()) {
callback(new Error(rule.message))
return
}
callback()
},
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()
}
})
})
},
loadTypeOptions() {
this.$axios.post("/platform/appeal/common/typeOptions").then((res) => {
if (res.code === 0) this.typeOptions = res.data || []
})
}
},
created() {
this.loadTypeOptions()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,169 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.appeal-search-page .search {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 20px;
row-gap: 10px;
}
.appeal-search-page .search .search-item {
width: 100%;
}
.appeal-search-page .search .search-item-label {
width: 76px;
min-width: 76px;
margin-right: 8px;
}
.appeal-search-page .search .search-item-option {
min-width: calc(100% - 76px - 8px);
}
@media screen and (max-width: 1350px) {
.appeal-search-page .search {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media screen and (max-width: 1200px) {
.appeal-search-page .search {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media screen and (max-width: 992px) {
.appeal-search-page .search {
grid-template-columns: 1fr;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava" class="appeal-search-page">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" style="width: 100%" placeholder="请选择年度"></el-date-picker>
</search-item>
<search-item label="申诉类型">
<el-select v-model="pageForm.appealTypeId" filterable clearable style="width: 100%" placeholder="请选择申诉类型">
<el-option v-for="item in typeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="申诉标题">
<el-input v-model="pageForm.searchKeyword" clearable placeholder="请输入申诉标题" @keyup.enter.native="doSearch"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button type="primary" size="small" icon="el-icon-plus" @click="onWrite">提交申诉</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" label="序号" width="60" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="申诉标题" show-overflow-tooltip></el-table-column>
<el-table-column prop="appealTypeName" label="申诉类型" width="140"></el-table-column>
<el-table-column prop="defendantUnitName" label="被申诉单位" width="180" show-overflow-tooltip></el-table-column>
<el-table-column prop="applyDate" label="申请日期" width="120"></el-table-column>
<el-table-column prop="state" label="业务状态" width="110">
<template slot-scope="{row}">
<el-tag size="mini">{{ row.state || '草稿' }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="taskName" label="当前节点" width="120"></el-table-column>
<el-table-column label="操作" fixed="right" width="200">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="onOpen(row)">查看</el-button>
<el-button size="mini" type="primary" v-if="canEdit(row)" @click="onEdit(row)">修改</el-button>
<el-button size="mini" type="warning" v-if="row.canRevoke" @click="onRevoke(row)">撤回</el-button>
<el-button size="mini" type="danger" v-if="!row.instanceId || row.state === '草稿'" @click="onDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<appeal-info ref="infoRef"></appeal-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"appeal-info": APPEAL_INFO
},
data() {
return {
pageForm: {
year: new Date().getFullYear().toString()
},
typeOptions: []
}
},
methods: {
onWrite() {
window.location.href = "/platform/appeal/write"
},
onOpen(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
canEdit(row) {
return !row.instanceId || row.state === '草稿' || row.state === '退回修改'
},
onEdit(row) {
let url = "/platform/appeal/write?id=" + row.id
if (row.startTaskId) {
url += "&taskId=" + row.startTaskId
}
window.location.href = url
},
onDelete(row) {
this.$confirm("您确定删除该申诉吗?", "提示", {type: "warning"}).then(() => {
this.$axios.post("/platform/appeal/mine/delete", {id: row.id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
onRevoke(row) {
this.$confirm("您确定撤回当前申诉吗?", "提示", {type: "warning"}).then(() => {
this.$axios.post("/flow/common/revokeTask", {taskId: row.startTaskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
},
loadTypeOptions() {
this.$axios.post("/platform/appeal/common/typeOptions").then((res) => {
if (res.code === 0) this.typeOptions = res.data || []
})
}
},
created() {
this.loadTypeOptions()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,289 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.appeal-query-page .stat-row {
margin: 10px 0;
}
.appeal-query-page .stat-row .el-col {
margin-bottom: 10px;
}
.appeal-query-page .stat-card {
border: 1px solid #ebeef5;
border-radius: 6px;
}
.appeal-query-page .stat-card .el-card__body {
padding: 14px 16px;
}
.appeal-query-page .stat-card-content {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 72px;
}
.appeal-query-page .stat-title {
color: #606266;
font-size: 13px;
line-height: 20px;
}
.appeal-query-page .stat-value {
margin-top: 8px;
color: #303133;
font-size: 28px;
font-weight: 600;
line-height: 32px;
}
.appeal-query-page .stat-tip {
margin-top: 4px;
color: #909399;
font-size: 12px;
line-height: 18px;
}
.appeal-query-page .stat-icon {
width: 42px;
height: 42px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 22px;
}
.appeal-query-page .stat-total .stat-icon {
color: #409eff;
background: #ecf5ff;
}
.appeal-query-page .stat-wait .stat-icon {
color: #e6a23c;
background: #fdf6ec;
}
.appeal-query-page .stat-execute .stat-icon {
color: #13c2c2;
background: #e6fffb;
}
.appeal-query-page .stat-finish .stat-icon {
color: #67c23a;
background: #f0f9eb;
}
.appeal-query-page .table-card {
border-radius: 6px;
}
.appeal-search-page .search {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 20px;
row-gap: 10px;
}
.appeal-search-page .search .search-item {
width: 100%;
}
.appeal-search-page .search .search-item-label {
width: 76px;
min-width: 76px;
margin-right: 8px;
}
.appeal-search-page .search .search-item-option {
min-width: calc(100% - 76px - 8px);
}
@media screen and (max-width: 1350px) {
.appeal-search-page .search {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media screen and (max-width: 1200px) {
.appeal-search-page .search {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media screen and (max-width: 992px) {
.appeal-search-page .search {
grid-template-columns: 1fr;
}
}
</style>
<div id="app" v-cloak>
<guava ref="guava" class="appeal-query-page appeal-search-page">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker v-model="pageForm.year" type="year" value-format="yyyy" style="width: 100%" placeholder="请选择年度"></el-date-picker>
</search-item>
<search-item label="申诉类型">
<el-select v-model="pageForm.appealTypeId" filterable clearable style="width: 100%" placeholder="请选择申诉类型">
<el-option v-for="item in typeOptions" :key="item.id" :label="typeOptionLabel(item)" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="申诉标题">
<el-input v-model="pageForm.searchKeyword" clearable placeholder="请输入申诉标题" @keyup.enter.native="doSearch"></el-input>
</search-item>
<search-item label="业务状态">
<el-select v-model="pageForm.state" clearable style="width: 100%" placeholder="请选择业务状态">
<el-option label="待受理" value="待受理"></el-option>
<el-option label="退回修改" value="退回修改"></el-option>
<el-option label="待执行" value="待执行"></el-option>
<el-option label="已办结" value="已办结"></el-option>
</el-select>
</search-item>
<search-item label="申诉单位">
<el-select v-model="pageForm.unitId" filterable clearable style="width: 100%" placeholder="请选择申诉单位">
<el-option v-for="item in unitOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="被申诉单位">
<el-select v-model="pageForm.defendantUnitId" filterable clearable style="width: 100%" placeholder="请选择被申诉单位">
<el-option v-for="item in unitOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-row :gutter="12" class="stat-row">
<el-col v-for="item in statCards" :key="item.prop" :xs="24" :sm="12" :md="6" :lg="6">
<el-card shadow="never" class="stat-card" :class="item.className">
<div class="stat-card-content">
<div>
<div class="stat-title">{{ item.title }}</div>
<div class="stat-value">{{ statisticValue(item.prop) }}</div>
<div class="stat-tip">{{ item.tip }}</div>
</div>
<div class="stat-icon">
<i :class="item.icon"></i>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-card shadow="never" class="table-card">
<table-tool label="申诉列表"></table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" label="序号" width="60" :index="indexMethod"></el-table-column>
<el-table-column prop="title" label="申诉标题" show-overflow-tooltip></el-table-column>
<el-table-column prop="userName" label="申诉人" width="100"></el-table-column>
<el-table-column prop="unitName" label="申诉单位" width="170" show-overflow-tooltip></el-table-column>
<el-table-column prop="appealTypeName" label="申诉类型" width="140"></el-table-column>
<el-table-column prop="defendantUnitName" label="被申诉单位" width="180" show-overflow-tooltip></el-table-column>
<el-table-column prop="applyDate" label="申请日期" width="120"></el-table-column>
<el-table-column prop="state" label="业务状态" width="100">
<template slot-scope="{row}">
<el-tag :type="stateTagType(row.state)" size="mini">{{ row.state || '草稿' }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="instanceState" label="流程状态" width="110">
<template slot-scope="{row}">
<enum-tag v-if="row.instanceState" :value="row.instanceState" name="ProcessInstanceStateEnum" label_key="message" size="small"></enum-tag>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="90">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="onOpen(row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<appeal-info ref="infoRef"></appeal-info>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("../common/info.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
components: {
"appeal-info": APPEAL_INFO
},
data() {
return {
pageForm: {
year: new Date().getFullYear().toString()
},
typeOptions: [],
unitOptions: [],
statCards: [
{title: "申诉总数", prop: "totalCount", tip: "当前筛选范围", icon: "el-icon-document", className: "stat-total"},
{title: "待受理", prop: "waitAcceptCount", tip: "委员会待审核", icon: "el-icon-time", className: "stat-wait"},
{title: "待执行", prop: "waitExecuteCount", tip: "单位待反馈", icon: "el-icon-s-operation", className: "stat-execute"},
{title: "已办结", prop: "finishCount", tip: "流程已结束", icon: "el-icon-finished", className: "stat-finish"}
],
statistics: {}
}
},
methods: {
statisticValue(prop) {
return (this.statistics && this.statistics[prop]) || 0
},
typeOptionLabel(item) {
return item.enabled === false || item.enabled === 0 ? item.name + "(已停用)" : item.name
},
stateTagType(state) {
const map = {
"待受理": "warning",
"退回修改": "danger",
"待执行": "",
"已办结": "success"
}
return map[state] || "info"
},
onOpen(row) {
this.$refs.guava.view(() => {
this.$refs.infoRef.onOpen(row)
})
},
doSearch() {
this.pageNumber = 1
this.pageData()
this.loadStatistics()
},
loadOptions() {
this.$axios.post("/platform/appeal/common/queryTypeOptions").then((res) => {
if (res.code === 0) this.typeOptions = res.data || []
})
this.$businessTool.listUnit().then((res) => {
this.unitOptions = res || []
})
},
loadStatistics() {
this.$axios.post("/platform/appeal/query/statistics", this.pageForm).then((res) => {
if (res.code === 0) this.statistics = res.data || {}
})
}
},
created() {
this.loadOptions()
this.pageData()
this.loadStatistics()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,181 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.appeal-search-page .search {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
column-gap: 20px;
row-gap: 10px;
}
.appeal-search-page .search .search-item {
width: 100%;
}
.appeal-search-page .search .search-item-label {
width: 76px;
min-width: 76px;
margin-right: 8px;
}
.appeal-search-page .search .search-item-option {
min-width: calc(100% - 76px - 8px);
}
@media screen and (max-width: 1350px) {
.appeal-search-page .search {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media screen and (max-width: 1200px) {
.appeal-search-page .search {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media screen and (max-width: 992px) {
.appeal-search-page .search {
grid-template-columns: 1fr;
}
}
</style>
<div id="app" v-cloak>
<guava class="appeal-search-page">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="类型名称">
<el-input v-model="pageForm.name" clearable maxlength="100" placeholder="请输入类型名称" @keyup.enter.native="doSearch"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button type="primary" size="small" icon="el-icon-plus" @click="onAdd">新增</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" style="width: 100%">
<el-table-column type="index" label="序号" width="60" :index="indexMethod"></el-table-column>
<el-table-column prop="name" label="类型名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="sort" label="排序" width="100"></el-table-column>
<el-table-column prop="enabled" label="是否启用" width="120">
<template slot-scope="{row}">
<el-switch
v-model="row.enabled"
:disabled="row.enabledLoading"
active-color="#13ce66"
inactive-color="#ff4949"
@change="(val)=>{onEnabledChange(row, val)}">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="165">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="onEdit(row)">编辑</el-button>
<el-button size="mini" type="danger" @click="onDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog :title="formData.id ? '编辑申诉类型' : '新增申诉类型'" :visible.sync="dialogVisible" width="500px" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="100px">
<el-form-item label="类型名称" prop="name" :rules="[{required:true,message:'请输入类型名称',trigger:'blur'}]">
<el-input v-model="formData.name" maxlength="100" show-word-limit clearable placeholder="请输入类型名称"></el-input>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" controls-position="right" style="width: 100%"></el-input-number>
</el-form-item>
<el-form-item label="是否启用" prop="enabled">
<el-switch v-model="formData.enabled"></el-switch>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="dialogVisible=false">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</span>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
dialogVisible: false,
pageForm: {},
formData: {}
}
},
methods: {
onAdd() {
this.formData = {enabled: true, sort: 0}
this.dialogVisible = true
},
onEdit(row) {
this.formData = {...row}
this.dialogVisible = true
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (!valid) return
this.$axios.post("/platform/appeal/type/save", {data: JSON.stringify(this.formData)}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogVisible = false
this.pageData()
}
})
})
},
onEnabledChange(row, enabled) {
const oldEnabled = !enabled
const actionName = enabled ? "启用" : "禁用"
this.$confirm("您确定要" + actionName + "申诉类型“" + row.name + "”吗?", "提示", {type: "warning"}).then(() => {
this.$set(row, "enabledLoading", true)
this.$axios.post("/platform/appeal/type/statusChange", {id: row.id, enabled: enabled}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
} else {
row.enabled = oldEnabled
this.$message.error(res.msg)
}
this.$set(row, "enabledLoading", false)
}).catch(() => {
row.enabled = oldEnabled
this.$set(row, "enabledLoading", false)
})
}).catch(() => {
row.enabled = oldEnabled
})
},
onDelete(row) {
this.$confirm("您确定删除申诉类型“" + row.name + "”吗?", "提示", {type: "warning"}).then(() => {
this.$axios.post("/platform/appeal/type/delete", {id: row.id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
} else {
this.$message.error(res.msg)
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,259 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<custom-card>
<snaker-start slot="header" label="提交申诉" define_key="SSGL"></snaker-start>
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="130px">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="申诉人" prop="userName">
<el-input v-model="formData.userName" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="性别" prop="sex">
<el-input v-model="formData.sex" clearable maxlength="20" show-word-limit></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="出生年月" prop="birthday">
<el-date-picker v-model="formData.birthday" value-format="yyyy-MM-dd" type="date" style="width: 100%" placeholder="请选择出生年月"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="政治面貌" prop="political">
<el-input v-model="formData.political" clearable maxlength="100" show-word-limit></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="工号" prop="loginName">
<el-input v-model="formData.loginName" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="所在单位" prop="unitName">
<el-input v-model="formData.unitName" disabled></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="岗位" prop="positionName">
<el-input v-model="formData.positionName" clearable maxlength="100" show-word-limit></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系电话" prop="mobile">
<el-input v-model="formData.mobile" clearable maxlength="100" placeholder="请输入手机或办公电话"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="申请日期" prop="applyDate">
<el-date-picker v-model="formData.applyDate" value-format="yyyy-MM-dd" type="date" style="width: 100%" placeholder="请选择申请日期"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="住址" prop="address">
<el-input v-model="formData.address" clearable maxlength="300" show-word-limit></el-input>
</el-form-item>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="申诉类型" prop="appealTypeId">
<el-select v-model="formData.appealTypeId" filterable clearable style="width: 100%" @change="onTypeChange">
<el-option v-for="item in typeOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="申诉标题" prop="title">
<el-input v-model="formData.title" clearable maxlength="200" show-word-limit placeholder="请输入申诉标题"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="被申诉单位" prop="defendantUnitId">
<el-select v-model="formData.defendantUnitId" filterable clearable style="width: 100%" @change="onUnitChange">
<el-option v-for="item in unitOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="被申诉单位地址" prop="defendantAddress">
<el-input v-model="formData.defendantAddress" clearable maxlength="300" show-word-limit></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="被申诉单位电话" prop="defendantContact">
<el-input v-model="formData.defendantContact" clearable maxlength="100" placeholder="请输入联系电话"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="申诉事项" prop="appealMatter">
<el-input v-model="formData.appealMatter" type="textarea" :rows="5" maxlength="1000" show-word-limit placeholder="请输入申诉事项"></el-input>
</el-form-item>
<el-form-item label="申诉理由" prop="reason">
<el-input v-model="formData.reason" type="textarea" :rows="6" maxlength="2000" show-word-limit placeholder="请输入申诉理由"></el-input>
</el-form-item>
<el-form-item label="申诉要求" prop="request">
<el-input v-model="formData.request" type="textarea" :rows="5" maxlength="1000" show-word-limit placeholder="请输入申诉要求"></el-input>
</el-form-item>
<el-form-item label="申诉人签名" prop="signature">
<pc-signature v-model="formData.signature"></pc-signature>
</el-form-item>
<el-form-item label="申诉材料附件" prop="files">
<file-upload :value.sync="formData.files" :upload_number="5" upload_mode="drag" upload_result_category="array" complete_result></file-upload>
</el-form-item>
</el-form>
<template slot="footer">
<el-button type="primary" @click="onSave">保存</el-button>
<el-button type="primary" @click="onSubmit">{{ hasTaskId() ? '提交' : '提交申诉' }}</el-button>
</template>
</custom-card>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
store,
data() {
return {
typeOptions: [],
unitOptions: [],
taskId: null,
formData: {},
formRules: {
sex: [{required: true, message: "请输入性别", trigger: "blur"}],
birthday: [{required: true, message: "请选择出生年月", trigger: "change"}],
political: [{required: true, message: "请输入政治面貌", trigger: "blur"}],
positionName: [{required: true, message: "请输入岗位", trigger: "blur"}],
mobile: [
{required: true, message: "请输入联系电话", trigger: "blur"},
{validator: this.validatePhone, trigger: "blur"}
],
applyDate: [{required: true, message: "请选择申请日期", trigger: "change"}],
address: [{required: true, message: "请输入住址", trigger: "blur"}],
appealTypeId: [{required: true, message: "请选择申诉类型", trigger: "change"}],
defendantUnitId: [{required: true, message: "请选择被申诉单位", trigger: "change"}],
defendantAddress: [{required: true, message: "请输入被申诉单位地址", trigger: "blur"}],
defendantContact: [
{required: true, message: "请输入被申诉单位电话", trigger: "blur"},
{validator: this.validatePhone, trigger: "blur"}
],
title: [{required: true, message: "请输入申诉标题", trigger: "blur"}],
appealMatter: [{required: true, validator: this.validateText, message: "请输入申诉事项", trigger: ["blur", "change"]}],
reason: [{required: true, validator: this.validateText, message: "请输入申诉理由", trigger: ["blur", "change"]}],
request: [{required: true, validator: this.validateText, message: "请输入申诉要求", trigger: ["blur", "change"]}],
signature: [{required: true, message: "请完成申诉人签名", trigger: ["blur", "change"]}],
files: [{required: true, validator: this.validateFiles, message: "请上传申诉材料附件", trigger: "change"}]
}
}
},
methods: {
validatePhone(rule, value, callback) {
if (!value) {
callback()
return
}
const reg = /^((1[3-9]\d{9})|(0\d{2,3}-?\d{7,8})|(\d{6,12}))$/
if (!reg.test(value)) {
callback(new Error("请输入正确的联系电话"))
return
}
callback()
},
validateText(rule, value, callback) {
if (!(value || "").trim()) {
callback(new Error(rule.message))
return
}
callback()
},
validateFiles(rule, value, callback) {
if (!value || !value.length) {
callback(new Error(rule.message))
return
}
callback()
},
queryParam(name) {
return new URLSearchParams(window.location.search).get(name)
},
loadOptions() {
this.$axios.post("/platform/appeal/common/typeOptions").then((res) => {
if (res.code === 0) this.typeOptions = res.data || []
})
this.$businessTool.listUnit().then((res) => {
this.unitOptions = res || []
})
},
loadCurrentUser() {
this.$axios.post("/platform/appeal/write/currentUserInfo").then((res) => {
if (res.code === 0) {
this.formData = Object.assign({}, res.data, this.formData)
}
})
},
loadInfo(id) {
this.$axios.post("/platform/appeal/write/info", {id}).then((res) => {
if (res.code === 0 && res.data) {
this.formData = res.data
}
})
},
onTypeChange(val) {
const item = this.typeOptions.find((type) => type.id === val)
this.$set(this.formData, "appealTypeName", item ? item.name : "")
},
onUnitChange(val) {
const item = this.unitOptions.find((unit) => unit.id === val)
this.$set(this.formData, "defendantUnitName", item ? item.name : "")
this.$set(this.formData, "defendantAddress", item ? item.address : this.formData.defendantAddress)
this.$set(this.formData, "defendantContact", item ? item.telephone : this.formData.defendantContact)
},
onSave() {
this.$axios.post("/platform/appeal/write/save", {data: JSON.stringify(this.formData)}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.formData = res.data
}
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (!valid) return
const url = this.hasTaskId() ? "/platform/appeal/write/submitAgain" : "/platform/appeal/write/submit"
this.$confirm("您确定提交该申诉吗?", "提示", {type: "warning"}).then(() => {
this.$axios.post(url, {data: JSON.stringify(this.formData), taskId: this.taskId}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
window.location.href = "/platform/appeal/mine"
}
})
})
})
},
hasTaskId() {
return !!this.taskId && this.taskId !== "undefined" && this.taskId !== "null"
}
},
created() {
this.taskId = this.queryParam("taskId")
const id = this.queryParam("id")
this.loadOptions()
if (id) {
this.loadInfo(id)
} else {
this.loadCurrentUser()
}
}
})
</script>
<!--#
}
#-->
@@ -10,12 +10,12 @@ layout("/layouts/platform.html"){
<table-tool label="子女信息"></table-tool>
<el-descriptions :column="2" border>
<el-descriptions-item label="就读年级">
<el-form-item prop="childRelationship">
<dict-select v-model="formData.childRelationship" code="CHILD_MANAGE_GRADE" style="width: 100%" placeholder="请选择就读年级">
<el-form-item prop="childrenGrade">
<dict-select v-model="formData.childrenGrade" code="CHILD_MANAGE_GRADE" style="width: 100%" placeholder="请选择就读年级">
</dict-select>
</el-form-item></el-descriptions-item>
<el-descriptions-item label="入学年份">
<el-form-item prop="childrenBirthday">
<el-form-item prop="childrenYear">
<el-date-picker
v-model="formData.childrenYear"
type="year"
@@ -146,7 +146,7 @@ layout("/layouts/platform.html"){
bizId: GetQueryString("bizId"),
formData: {},
formRules: {
childRelationship: [{ required: true, message: '请选择就读年级', trigger: 'change' }],
childrenGrade: [{ required: true, message: '请选择就读年级', trigger: 'change' }],
childrenYear: [{ required: true, message: '请选择入学年份', trigger: 'change' }],
childrenName: [{ required: true, message: '请输入子女姓名', trigger: 'blur' }],
childrenIdCard: [{ 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])|10|20|30|31)\d{3}[0-9Xx]$/, message: '请输入正确的身份证号码', trigger: 'blur'}],
@@ -220,6 +220,7 @@ layout("/layouts/platform.html"){
unionId: union.id,
mobile: mobile,
// 自动填充监护人1信息
guardianUserId1: id,
guardianUserName1: username,
guardianLoginName1: loginname,
guardianMobile1: mobile,
@@ -21,8 +21,8 @@ const INFO = {
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{ viewData.unitname }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.unionname }}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{ viewData.unitName }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.unionName }}</el-descriptions-item>
<el-descriptions-item label="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
@@ -51,26 +51,26 @@ const INFO = {
<el-descriptions-item></el-descriptions-item>
<!-- <template v-if="viewData.loginname == $store.state.user.loginname">-->
<template>
<template v-if="viewData.loginname == $store.state.user.loginname">
<el-descriptions-item label="家庭主要成员" :span="3">
<el-table v-if="viewData.families&&viewData.families.length"
:data="viewData.families" size="mini" border
:header-cell-style="{background:'#eff3f6'}"
style="width: 100%">
<el-table-column prop="relation" label="与本人关系" align="center"
<el-table-column prop="relation" label="关系" align="center"
header-align="center">
</el-table-column>
<el-table-column prop="name" label="姓名" align="center" header-align="center">
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" header-align="center">
<el-table-column prop="unit" label="工作单位" align="center" header-align="center">
</el-table-column>
<el-table-column prop="remark" label="备注" align="center" header-align="center">
</el-table-column>
</el-table>
<el-empty v-else :image-size="50" description="暂无家庭成员信息"></el-empty>
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<template slot="label">个人简况</template>
<el-descriptions-item label="个人简历" :span="3">
<template slot="label">个人简历</template>
<div v-if="viewData.personalData" class="text-left" v-html="viewData.personalData"></div>
<span v-else>无数据</span>
</el-descriptions-item>
@@ -15,8 +15,8 @@ const MEMBER_ALL_CHANGE_INFO = {
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{ viewData.unitname }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.unionname }}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{ viewData.unitName }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.unionName }}</el-descriptions-item>
<el-descriptions-item label="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
@@ -56,7 +56,7 @@ const MEMBER_ALL_CHANGE_INFO = {
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<template slot="label">个人简况</template>
<div v-if="viewData.vita" class="text-left" v-html="viewData.vita"></div>
<div v-if="viewData.personalData" class="text-left" v-html="viewData.personalData"></div>
<span v-else>无数据</span>
</el-descriptions-item>
</template>
@@ -350,9 +350,11 @@ const MEMBER_CHANGE = {
},
methods: {
getUnionName(val){
debugger
const data = this.units.find(v => v.id === val)
this.$set(this.formData, 'unionName', data ? data.unionName : '')
// 选择工作单位后,同步保存单位名称和所属工会信息,避免变更记录快照不一致。
this.$set(this.formData, 'unitName', data ? data.name : null)
this.$set(this.formData, 'unionId', data ? (data.unionId || data.unionid) : null)
this.$set(this.formData, 'unionName', data ? (data.unionName || data.unionname) : '')
},
allowFields(prop) {
return !this.allowChangeFields.map(v => v.code).includes(prop)
@@ -74,7 +74,7 @@ layout("/layouts/platform.html"){
{ prop: "unitName", label: "所属单位", sortable: true },
{ prop: "changeTypes", label: "变更类型", sortable: true, width: 200 },
{ prop: "applyDateTime", label: "申请时间", sortable: true },
{ prop: "curTaskName", label: "当前节点"},
{ prop: "taskName", label: "当前节点"},
{ prop: "instanceState", label: "流程状态"}
],
changeTypeData: [],
@@ -428,7 +428,10 @@
},
getUnionName(val){
const data = this.units.find(v => v.id === val)
this.$set(this.formData, 'unionName', data ? data.unionname : '')
// 选择工作单位后,同步保存单位名称和所属工会信息,避免变更记录快照不一致。
this.$set(this.formData, 'unitName', data ? data.name : null)
this.$set(this.formData, 'unionId', data ? (data.unionId || data.unionid) : null)
this.$set(this.formData, 'unionName', data ? (data.unionName || data.unionname) : '')
},
allowFields(prop) {
return !this.allowChangeFields.map(v => v.code).includes(prop)
@@ -427,7 +427,10 @@ layout("/layouts/platform.html"){
// 获取表单工会名称
getUnionName(val){
const data = this.units.find(v => v.id === val)
this.$set(this.formData, 'unionName', data ? data.unionName : '')
// 选择工作单位后,同步保存单位名称和所属工会信息,避免变更记录快照不一致。
this.$set(this.formData, 'unitName', data ? data.name : null)
this.$set(this.formData, 'unionId', data ? (data.unionId || data.unionid) : null)
this.$set(this.formData, 'unionName', data ? (data.unionName || data.unionname) : '')
},
// 获取表单可编辑的字段信息
allowFields(prop) {
@@ -14,8 +14,8 @@
<el-descriptions-item label="学位">{{ viewData.academicDegree }}</el-descriptions-item>
<el-descriptions-item label="党政职务">{{ viewData.position }}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{ viewData.unitname }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.unionname }}</el-descriptions-item>
<el-descriptions-item label="工作单位">{{ viewData.unitName }}</el-descriptions-item>
<el-descriptions-item label="所属工会">{{ viewData.unionName }}</el-descriptions-item>
<el-descriptions-item label="所属校区">{{ viewData.campus }}</el-descriptions-item>
<el-descriptions-item label="身份证号码">{{ viewData.idCard }}</el-descriptions-item>
@@ -54,7 +54,7 @@
</el-descriptions-item>
<el-descriptions-item label="个人简况" :span="3">
<template slot="label">个人简况</template>
<div v-if="viewData.vita" class="text-left" v-html="viewData.vita"></div>
<div v-if="viewData.personalData" class="text-left" v-html="viewData.personalData"></div>
<span v-else>无数据</span>
</el-descriptions-item>
</el-descriptions>
@@ -0,0 +1,136 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" class="platform" v-cloak>
<guava ref="guava" padding="0 5%">
<template>
<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%"
@change="yearChange"></el-date-picker>
</search-item>
<search-item label="任务名称">
<el-select v-model="pageForm.checkTaskId"
clearable
filterable
placeholder="请选择任务"
style="width: 100%"
@change="doSearch">
<el-option v-for="item in taskOptions"
:key="item.id"
:label="item.taskName"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属工会">
<el-select v-model="pageForm.unionId"
clearable
filterable
placeholder="请选择所属工会"
style="width: 100%"
@change="doSearch">
<el-option v-for="item in unions"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="工会确认情况统计"></table-tool>
<el-table :data="tableData"
:size="tableSize"
row-key="unionId"
style="width: 100%"
v-loading="tableLoading"
ref="table"
class="vi-table">
<el-table-column type="index" :index="indexMethod" label="序号" width="80px" align="center" header-align="center"></el-table-column>
<el-table-column prop="unionName" label="工会名称" align="center" header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="totalCount" label="总人数" align="center" header-align="center"></el-table-column>
<el-table-column prop="confirmedCount" label="已确认人数" align="center" header-align="center"></el-table-column>
<el-table-column prop="unconfirmedCount" label="未确认人数" align="center" header-align="center"></el-table-column>
<el-table-column prop="completeStatus" label="确认完成状态" align="center" header-align="center"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
pageForm: {
year: moment().format("YYYY"),
checkTaskId: "",
unionId: ""
},
unions: [],
taskOptions: []
}
},
methods: {
yearChange() {
return $.get("/platform/member/check/confirm/listEnabledTask", {year: this.pageForm.year}).then((resp) => {
if (resp.code === 0) {
this.taskOptions = resp.data || []
if (this.taskOptions.length > 0 && !this.pageForm.checkTaskId) {
this.$set(this.pageForm, "checkTaskId", this.taskOptions[0].id)
}
if (this.taskOptions.length === 0) {
this.$set(this.pageForm, "checkTaskId", "")
}
this.doSearch()
} else {
this.notifyError(resp.msg)
}
})
},
pageData() {
if (!this.pageForm.year || !this.pageForm.checkTaskId) {
this.tableData = []
this.$set(this.pageForm, "totalCount", 0)
return Promise.resolve()
}
this.tableLoading = true
return $.post("/platform/member/check/confirm/pageData", this.pageForm).then((resp) => {
if (resp.code === 0) {
this.tableData = resp.data.list || []
this.$set(this.pageForm, "totalCount", resp.data.totalCount || 0)
} else {
this.notifyError(resp.msg)
}
}).always(() => {
this.tableLoading = false
})
},
doSearch() {
this.$set(this.pageForm, "pageNumber", 1)
return this.pageData()
}
},
created() {
this.$businessTool.listUnion().then((res) => {
this.unions = res
if (!this.pageForm.unionId && this.unions && this.unions.length === 1) {
this.$set(this.pageForm, "unionId", this.unions[0].id)
}
})
this.yearChange()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,513 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" class="platform" v-cloak>
<guava ref="guava" padding="0 5%">
<template>
<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%"
@change="yearChange"></el-date-picker>
</search-item>
<search-item label="任务名称">
<el-select v-model="pageForm.checkTaskId"
placeholder="请选择任务"
clearable
filterable
style="width: 100%"
@change="doSearch">
<el-option v-for="item in taskOptions"
:key="item.id"
:label="item.taskName"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" clearable placeholder="请输入姓名或工号"></el-input>
</search-item>
<search-item label="所属工会" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
<el-select v-model="pageForm.unionIds"
placeholder="请选择所属工会"
clearable
filterable
style="width: 100%"
@change="flushUnits"
@clear="flushUnits">
<el-option v-for="item in unions"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitIds"
placeholder="请选择所属单位"
clearable
filterable
multiple
collapse-tags
style="width: 100%">
<el-option v-for="item in units"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="确认状态">
<el-select v-model="pageForm.audit" placeholder="请选择确认状态" clearable style="width: 100%">
<el-option label="已确认" :value="true"></el-option>
<el-option label="未确认" :value="false"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="人员名单">
<el-button type="primary" size="small" @click="openImport">导入名单</el-button>
<el-button type="primary" size="small" @click="openAddUser">添加人员</el-button>
<el-button type="primary" size="small" @click="exportData">导出</el-button>
<el-button type="primary" size="small" :disabled="!pageForm.checkTaskId" @click="doAuditByUnion(true)">按工会确认</el-button>
<el-button type="danger" size="small" :disabled="!pageForm.checkTaskId" @click="doAuditByUnion(false)">按工会取消确认</el-button>
<el-button type="primary" size="small" :disabled="selectedIds.length === 0" @click="doConfirmSelected(true)">勾选确认</el-button>
<el-button type="danger" size="small" :disabled="selectedIds.length === 0" @click="doConfirmSelected(false)">勾选取消确认</el-button>
<el-button type="danger" size="small" :disabled="selectedIds.length === 0" @click="deleteSelected">批量删除</el-button>
</table-tool>
<el-table :data="tableData"
style="width: 100%"
row-key="id"
:size="tableSize"
v-loading="tableLoading"
@selection-change="handleSelectionChange"
@sort-change="pageOrder"
ref="table"
class="vi-table">
<el-table-column type="selection" width="55" align="center" header-align="center"></el-table-column>
<el-table-column type="index" :index="indexMethod" label="序号" width="80px" align="center" header-align="center"></el-table-column>
<el-table-column prop="loginname" label="工号" align="center" header-align="center"></el-table-column>
<el-table-column prop="username" label="姓名" align="center" header-align="center"></el-table-column>
<el-table-column prop="sex" label="性别" align="center" header-align="center"></el-table-column>
<el-table-column prop="unionName" label="所属工会" align="center" header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="unitName" label="所属单位" align="center" header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="taskName" label="任务名称" min-width="180px" align="center" header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="mobile" label="手机号" align="center" header-align="center"></el-table-column>
<el-table-column prop="idCard" label="身份证号" min-width="170px" align="center" header-align="center"></el-table-column>
<el-table-column prop="branchUnionChecked" label="确认状态" align="center" header-align="center">
<template slot-scope="{row}">
<el-tag type="success" v-if="row.branchUnionChecked">已确认</el-tag>
<el-tag type="info" v-else>未确认</el-tag>
</template>
</el-table-column>
<el-table-column prop="auditTime" label="确认时间" min-width="160px" align="center" header-align="center"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
<el-dialog title="添加人员" :visible.sync="addUserVisible" width="80%" :close-on-click-modal="false">
<el-card shadow="never">
<search @search="addUserDoSearch">
<search-item label="姓名">
<el-input v-model="addUserPageForm.userName" @keyup.enter.native="addUserDoSearch" clearable placeholder="请输入姓名"></el-input>
</search-item>
<search-item label="工号">
<el-input v-model="addUserPageForm.loginName" @keyup.enter.native="addUserDoSearch" clearable placeholder="请输入工号"></el-input>
</search-item>
<search-item label="性别">
<el-select v-model="addUserPageForm.sexTypes" clearable multiple collapse-tags placeholder="请选择性别" style="width: 100%">
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
</search-item>
<search-item label="出生开始">
<el-date-picker v-model="addUserPageForm.birthdayStartDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择出生开始"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="出生结束">
<el-date-picker v-model="addUserPageForm.birthdayEndDate"
type="date"
value-format="yyyy-MM-dd"
placeholder="选择出生结束"
style="width: 100%"></el-date-picker>
</search-item>
<search-item label="所属工会" v-if="$auth.hasRoleOr(['SYSADMIN', 'SCHOOL_UNION_ADMIN'])">
<el-select v-model="addUserPageForm.unionIds"
clearable
filterable
placeholder="请选择所属工会"
style="width: 100%"
@change="addUserUnionChange"
@clear="addUserUnionChange">
<el-option v-for="item in addUserUnionOptions"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位">
<el-select v-model="addUserPageForm.unitIds"
clearable
filterable
multiple
collapse-tags
placeholder="请选择所属单位"
style="width: 100%">
<el-option v-for="item in addUserUnitOptions"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="人员类型">
<dict-select clearable
code="USER_PERSON_TYPE"
multiple
collapse-tags
placeholder="请选择人员类型"
v-model="addUserPageForm.personTypes"></dict-select>
</search-item>
<search-item label="在职状态">
<dict-select clearable
code="USER_STATE"
multiple
collapse-tags
placeholder="请选择人员状态"
v-model="addUserPageForm.userStates"></dict-select>
</search-item>
<search-item label="是否会员">
<el-select v-model="addUserPageForm.isMember" clearable placeholder="请选择是否会员" style="width: 100%">
<el-option label="是" :value="true"></el-option>
<el-option label="否" :value="false"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<el-table :data="addUserTableData"
:size="tableSize"
row-key="id"
v-loading="addUserTableLoading"
style="width: 100%">
<el-table-column type="index" :index="addUserIndexMethod" label="序号" width="80px" align="center"></el-table-column>
<el-table-column prop="loginname" label="工号" align="center" header-align="center"></el-table-column>
<el-table-column prop="username" label="姓名" align="center" header-align="center"></el-table-column>
<el-table-column prop="sex" label="性别" align="center" header-align="center"></el-table-column>
<el-table-column prop="birthday" label="出生日期" align="center" header-align="center"></el-table-column>
<el-table-column prop="personType" label="人员类型" align="center" header-align="center"></el-table-column>
<el-table-column prop="userState" label="在职状态" align="center" header-align="center"></el-table-column>
<el-table-column prop="unionName" label="所属工会" align="center" header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="unitName" label="所属单位" align="center" header-align="center" show-overflow-tooltip></el-table-column>
</el-table>
<div class="mt10 text-right">
<el-pagination background
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="addUserPageForm.pageNumber"
:page-size.sync="addUserPageForm.pageSize"
:page-sizes="[10, 20, 50, 100]"
:total="addUserPageForm.totalCount || 0"
@size-change="addUserPageData"
@current-change="addUserPageData"></el-pagination>
</div>
</el-card>
<template slot="footer">
<el-button @click="addUserVisible=false">取消</el-button>
<el-button type="primary" @click="submitAddUser">确定</el-button>
</template>
</el-dialog>
<excel-import
ref="excelImportRef"
url="/platform/member/check/roster/importCheckUser"
template_url="/platform/member/check/roster/downloadTem"
:visible.sync="importVisible"
title="导入人员名单"
width="700px"
:extra_params="{checkTaskId:pageForm.checkTaskId}"
@import-success="doSearch"
></excel-import>
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
pageForm: {
year: moment().format("YYYY"),
checkTaskId: "",
searchKeyword: "",
unionIds: "",
unitIds: [],
audit: null
},
unions: [],
units: [],
taskOptions: [],
selectedIds: [],
importVisible: false,
addUserVisible: false,
addUserTableLoading: false,
addUserTableData: [],
addUserUnionOptions: [],
addUserUnitOptions: [],
addUserPageForm: {}
}
},
methods: {
handleSelectionChange(rows) {
this.selectedIds = rows.map(function (item) {
return item.id
})
},
yearChange() {
return $.get("/platform/member/check/roster/listEnabledTask", {year: this.pageForm.year}).then((resp) => {
if (resp.code === 0) {
this.taskOptions = resp.data || []
if (this.taskOptions.length > 0 && !this.pageForm.checkTaskId) {
this.$set(this.pageForm, "checkTaskId", this.taskOptions[0].id)
}
if (this.taskOptions.length === 0) {
this.$set(this.pageForm, "checkTaskId", "")
}
this.doSearch()
} else {
this.notifyError(resp.msg)
}
})
},
pageData() {
this.tableLoading = true
return $.post("/platform/member/check/roster/pageData", {
pageForm: JSON.stringify(this.pageForm)
}).then((resp) => {
if (resp.code === 0) {
this.tableData = resp.data.list || []
this.$set(this.pageForm, "totalCount", resp.data.totalCount || 0)
this.selectedIds = []
} else {
this.notifyError(resp.msg)
}
}).always(() => {
this.tableLoading = false
})
},
doSearch() {
this.$set(this.pageForm, "pageNumber", 1)
return this.pageData()
},
flushUnits() {
this.$set(this.pageForm, "unitIds", [])
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.$businessTool.listUnit(this.pageForm.unionIds).then((res) => {
this.units = res
})
} else {
this.$businessTool.listUnit().then((res) => {
this.units = res
})
}
this.doSearch()
},
openImport() {
if (!this.pageForm.checkTaskId) {
this.notifyWarning("请先选择任务")
return
}
this.importVisible = true
},
resetAddUserPageForm() {
this.addUserPageForm = {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
checkTaskId: "",
userName: "",
loginName: "",
sexTypes: [],
birthdayStartDate: "",
birthdayEndDate: "",
unionIds: "",
unitIds: [],
personTypes: [],
userStates: [],
isMember: null
}
this.addUserTableData = []
},
openAddUser() {
if (!this.pageForm.checkTaskId) {
this.notifyWarning("请先选择任务")
return
}
this.resetAddUserPageForm()
this.$set(this.addUserPageForm, "checkTaskId", this.pageForm.checkTaskId)
this.addUserVisible = true
this.$businessTool.listUnion().then((res) => {
this.addUserUnionOptions = res
})
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.$businessTool.listUnit(this.addUserPageForm.unionIds).then((res) => {
this.addUserUnitOptions = res
})
} else {
this.$businessTool.listUnit().then((res) => {
this.addUserUnitOptions = res
})
}
this.addUserPageData()
},
addUserUnionChange() {
this.$set(this.addUserPageForm, "unitIds", [])
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])) {
this.$businessTool.listUnit(this.addUserPageForm.unionIds).then((res) => {
this.addUserUnitOptions = res
})
}
},
addUserPageData() {
this.addUserTableLoading = true
return $.post("/platform/member/check/roster/notCheckUserPageData", {
pageForm: JSON.stringify(this.addUserPageForm)
}).then((resp) => {
if (resp.code === 0) {
this.addUserTableData = resp.data.list || []
this.$set(this.addUserPageForm, "totalCount", resp.data.totalCount || 0)
} else {
this.notifyError(resp.msg)
}
}).always(() => {
this.addUserTableLoading = false
})
},
addUserDoSearch() {
this.$set(this.addUserPageForm, "pageNumber", 1)
this.addUserPageData()
},
addUserIndexMethod(index) {
return (this.addUserPageForm.pageNumber - 1) * this.addUserPageForm.pageSize + index + 1
},
submitAddUser() {
if (!this.pageForm.checkTaskId) {
this.notifyWarning("请先选择任务")
return
}
this.$set(this.addUserPageForm, "checkTaskId", this.pageForm.checkTaskId)
this.$confirm("当前筛选出" + (this.addUserPageForm.totalCount || 0) + "条数据,确认添加到人员名单吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
const loading = this.$loading({
lock: true,
text: "数据保存中,请稍后...",
spinner: "el-icon-loading"
})
$.post("/platform/member/check/roster/addCheckUser", {
pageForm: JSON.stringify(this.addUserPageForm)
}).then((resp) => {
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.addUserVisible = false
this.doSearch()
} else {
this.notifyError(resp.msg)
}
}).always(() => {
loading.close()
})
})
},
doAuditByUnion(flag) {
if (this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"]) && !this.pageForm.unionIds) {
this.notifyWarning("请选择需要确认的分工会")
return
}
const msg = flag ? "确定按当前任务和分工会确认名单吗?" : "确定按当前任务和分工会取消确认吗?"
this.$confirm(msg, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post("/platform/member/check/roster/doConfirmUser", {
checkTaskId: this.pageForm.checkTaskId,
unionId: this.pageForm.unionIds,
flag: flag
}).then((resp) => {
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
} else {
this.notifyError(resp.msg)
}
})
})
},
doConfirmSelected(flag) {
const msg = flag ? "确定确认勾选人员吗?" : "确定取消确认勾选人员吗?"
this.$confirm(msg, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post("/platform/member/check/roster/doConfirmSelected", {
ids: this.selectedIds.join(","),
flag: flag
}).then((resp) => {
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
} else {
this.notifyError(resp.msg)
}
})
})
},
deleteSelected() {
this.$confirm("确认删除勾选人员吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post("/platform/member/check/roster/deleteSelected", {
ids: this.selectedIds.join(",")
}).then((resp) => {
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
} else {
this.notifyError(resp.msg)
}
})
})
},
exportData() {
const form = JSON.stringify(this.pageForm)
window.open("/platform/member/check/roster/exportCheckUser?pageForm=" + encodeURIComponent(form))
}
},
created() {
this.$businessTool.listUnion().then((res) => {
this.unions = res
if (!this.pageForm.unionIds && this.unions && this.unions.length === 1) {
this.$set(this.pageForm, "unionIds", this.unions[0].id)
}
})
this.flushUnits()
this.yearChange()
}
})
</script>
<!--#
}
#-->
@@ -1,28 +0,0 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return{
}
},
methods: {
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -1,25 +1,215 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<div id="app" v-cloak>
<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.taskName" placeholder="请输入任务名称查询" clearable></el-input>
</search-item>
<!-- <search-item label="发布状态">-->
<!-- <el-select v-model="pageForm.isEnabled" placeholder="请选择发布状态" clearable style="width: 100%">-->
<!-- <el-option label="已发布" :value="true"></el-option>-->
<!-- <el-option label="未发布" :value="false"></el-option>-->
<!-- </el-select>-->
<!-- </search-item>-->
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="任务列表">
<el-button size="small" type="primary" icon="el-icon-plus" @click="openAdd">新增</el-button>
</table-tool>
<el-table :data="tableData"
row-key="id"
:size="tableSize"
v-loading="tableLoading"
class="vi-table">
<el-table-column type="index" width="80px" label="序号" :index="indexMethod" align="center" header-align="center"></el-table-column>
<el-table-column prop="taskName" label="任务名称" align="center" header-align="center" show-overflow-tooltip></el-table-column>
<el-table-column prop="year" label="年度" align="center" header-align="center"></el-table-column>
<el-table-column prop="startTime" label="开始时间" align="center" header-align="center" min-width="160px"></el-table-column>
<el-table-column prop="endTime" label="结束时间" align="center" header-align="center" min-width="160px"></el-table-column>
<el-table-column prop="isEnabled" label="是否发布" align="center" header-align="center">
<template slot-scope="{row}">
<el-switch v-model="row.isEnabled"
active-color="#13ce66"
inactive-color="#ff4949"
@change="switchChange(row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="180px" fixed="right" align="center" header-align="center">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
<el-button size="mini" type="danger" @click="onDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="50%" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" label-width="100px" :rules="rules">
<el-form-item label="任务名称" prop="taskName">
<el-input v-model="formData.taskName" maxlength="20" placeholder="请输入任务名称"></el-input>
</el-form-item>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker v-model="formData.startTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择开始时间"
style="width: 100%"></el-date-picker>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker v-model="formData.endTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="请选择结束时间"
style="width: 100%"></el-date-picker>
</el-form-item>
<el-form-item label="内容详情" prop="description">
<el-input v-model="formData.description" type="textarea" :rows="5" placeholder="请输入内容详情"></el-input>
</el-form-item>
<!-- <el-form-item label="是否发布" prop="isEnabled">-->
<!-- <el-switch v-model="formData.isEnabled" active-color="#13ce66" inactive-color="#ff4949"></el-switch>-->
<!-- </el-form-item>-->
</el-form>
<template slot="footer">
<el-button @click="dialogVisible=false">取消</el-button>
<el-button type="primary" @click="submitForm">确定</el-button>
</template>
</el-dialog>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return{
}
},
methods: {
},
created() {
}
})
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
computed: {
dialogTitle() {
return this.formData.id ? "编辑任务" : "新增任务"
}
},
data() {
return {
pageForm: {
year: moment().format("YYYY"),
taskName: "",
isEnabled: null
},
dialogVisible: false,
formData: {
taskName: "",
startTime: "",
endTime: "",
description: "",
isEnabled: true
},
rules: {
taskName: [{required: true, message: "请输入任务名称", trigger: ["change", "blur"]}],
startTime: [{required: true, message: "请选择开始时间", trigger: ["change", "blur"]}],
endTime: [{required: true, message: "请选择结束时间", trigger: ["change", "blur"]}],
description: [{required: true, message: "请输入内容详情", trigger: ["change", "blur"]}]
}
}
},
methods: {
pageData() {
this.tableLoading = true
return $.post("/platform/member/check/task/pageData", this.pageForm).then((resp) => {
if (resp.code === 0) {
this.tableData = resp.data.list || []
this.$set(this.pageForm, "totalCount", resp.data.totalCount || 0)
} else {
this.notifyError(resp.msg)
}
}).always(() => {
this.tableLoading = false
})
},
doSearch() {
this.$set(this.pageForm, "pageNumber", 1)
return this.pageData()
},
openAdd() {
this.formData = {
taskName: "",
startTime: "",
endTime: "",
description: "",
isEnabled: true
}
this.dialogVisible = true
this.$nextTick(() => {
this.$refs.formRef.clearValidate()
})
},
openEdit(row) {
$.get("/platform/member/check/task/findOne", {id: row.id}).then((resp) => {
if (resp.code === 0) {
this.formData = Object.assign({}, resp.data)
this.dialogVisible = true
} else {
this.notifyError(resp.msg)
}
})
},
submitForm() {
this.$refs.formRef.validate((valid) => {
if (!valid) {
return
}
$.post("/platform/member/check/task/doAddOrModify", {
data: JSON.stringify(this.formData)
}).then((resp) => {
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.dialogVisible = false
this.doSearch()
} else {
this.notifyError(resp.msg)
}
})
})
},
switchChange(row) {
$.post("/platform/member/check/task/switchChange", row).then((resp) => {
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.pageData()
} else {
this.notifyError(resp.msg)
}
})
},
onDelete(id) {
this.$confirm("确认删除该任务及其人员名单吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post("/platform/member/check/task/delete", {id: id}).then((resp) => {
if (resp.code === 0) {
this.notifySuccess(resp.msg)
this.doSearch()
} else {
this.notifyError(resp.msg)
}
})
}).catch(() => {})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
@@ -1,26 +0,0 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
data() {
return{
}
},
methods: {
},
created() {
}
})
</script>
<!--#
}
#-->
@@ -112,6 +112,7 @@ layout("/layouts/platform.html"){
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
@@ -169,7 +169,8 @@ const selectView = {
selectedOptions: [],
detailVisible: false,
currentOption: null,
activeNames:[]
activeNames:[],
defaultWelfareImage: "/assets/platform/img/v4/not-image.png"
}
},
computed: {
@@ -179,7 +180,7 @@ const selectView = {
return {
...item,
optionName: option.optionName || "未知选项",
imgUrl: option.imgUrl,
imgUrl: option.imgUrl || this.defaultWelfareImage,
description: option.description
}
})
@@ -267,7 +268,11 @@ const selectView = {
},
handleImageError(e) {
e.target.src = "/static/images/default-welfare.png"
// 兜底图加载失败时不再重复替换,避免控制台持续刷 404。
if (!e || !e.target || e.target.src.indexOf(this.defaultWelfareImage) > -1) {
return
}
e.target.src = this.defaultWelfareImage
},
formatDate(dateStr) {