慰问、会员入会接入待办

This commit is contained in:
2026-11-06 17:25:12 +08:00
parent e744b7c271
commit 49407374b0
3257 changed files with 604 additions and 549641 deletions
@@ -49,7 +49,9 @@ public class MemberAgendaController {
final String title = "【会员系统】";
List<NutMap> list = new ArrayList<>();
if (!ShiroUtil.hasAnyRoles("sysadmin,A06,gh01,H03")) {
if (!ShiroUtil.hasAnyRoles("sysadmin,A06,gh01,H03")
&& !org.apache.shiro.SecurityUtils.getSubject().isPermitted("member.apply.audit.union")
&& !org.apache.shiro.SecurityUtils.getSubject().isPermitted("member.apply.audit.school")) {
return list;
}
boolean anyRoles = ShiroUtil.hasAnyRoles("sysadmin,A06,H03");
@@ -67,20 +69,26 @@ public class MemberAgendaController {
int marUnionNum = 0;
Cnd marUnionCnd = Cnd.where("mar.stateId", "=", MemberApplyState.UNION);
if (!anyRoles) {
marUnionCnd.and("u.unionid", "=", Vi.getUnionId());
// 入会审核范围与 PC 部门审核列表一致,校级角色不能自动越过部门权限。
if (!ShiroUtil.hasAnyRoles("sysadmin")) {
marUnionCnd.and("mar.unionId", "=", Vi.getUnionId());
}
marSql.setCondition(marUnionCnd);
marUnionNum = memberService.count(marSql);
list.add(new NutMap().addv("title", title).addv("iconClass", vi.getIconByPath("/platform/member/apply/audit/union")).addv("label", "待部门工会入会审核").addv("number", marUnionNum).addv("url", "/platform/member/apply/audit/union"));
if (org.apache.shiro.SecurityUtils.getSubject().isPermitted("member.apply.audit.union"))
list.add(new NutMap().addv("title", title).addv("iconClass", vi.getIconByPath("/platform/member/apply/audit/union")).addv("label", "待部门工会入会审核").addv("number", marUnionNum).addv("url", "/platform/member/apply/audit/union"));
int marSchoolNum = 0;
Cnd marSchoolCnd = Cnd.where("mar.stateId", "=", MemberApplyState.SCHOOL_UNION);
marSql.setCondition(marSchoolCnd);
marSchoolNum = memberService.count(marSql);
list.add(new NutMap().addv("title", title).addv("iconClass", vi.getIconByPath("/platform/member/apply/audit/school")).addv("label", "待校工会入会审核").addv("number", marSchoolNum).addv("url", "/platform/member/apply/audit/school"));
if (org.apache.shiro.SecurityUtils.getSubject().isPermitted("member.apply.audit.school"))
list.add(new NutMap().addv("title", title).addv("iconClass", vi.getIconByPath("/platform/member/apply/audit/school")).addv("label", "待校工会入会审核").addv("number", marSchoolNum).addv("url", "/platform/member/apply/audit/school"));
// 非原会员变更管理角色仅返回按权限计算的入会待办。
if (!ShiroUtil.hasAnyRoles("sysadmin,A06,gh01,H03")) return list;
// 会员变更
Sql mcrSql = Sqls.create("""
SELECT
@@ -111,4 +119,24 @@ public class MemberAgendaController {
List<Sys_menu> menus = Optional.ofNullable(user).orElse(new Sys_user()).getMenus();
return list.stream().filter(v -> Strings.isNotBlank(v.getString("url")) && menus.stream().anyMatch(x -> Strings.isNotBlank(x.getHref()) && v.getString("url").contains(x.getHref()))).distinct().collect(Collectors.toList());
}
/**
* 无需参数,返回当前登录人今年可办理的入会审核节点。
* 每项 title/name/count/mobileHref 分别表示业务标题、节点名称、待办数量和手机入口。
*/
@At
@ViReturn
public Object getMobileAgenda() {
return memberService.getCurrentYearApplyAgenda();
}
/**
* 无需传入办理人,身份从登录会话获取;返回本人今年实际办理的会员入会记录。
* 每项 moduleName/auditState/auditTime/mobileUrl 为业务名称、办理节点、办理时间和只读详情地址。
*/
@At
@ViReturn
public Object getCompletes() {
return memberService.getCurrentYearApplyCompletes();
}
}
@@ -15,6 +15,8 @@ import io.v.nutz.util.ShiroUtil;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Sqls;
import org.nutz.ioc.aop.Aop;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -130,6 +132,7 @@ public class MemberApplyAuditController {
@At
@ViReturn
@Aop(TransAop.READ_COMMITTED)
public Object doAudit(@ViRequired String recordId, Audit audit) {
MemberApplyRecord record = memberApplyRecordViService.fetch(recordId);
MemberApplyAuditHandle applyHandle = Enum.instance(MemberApplyAuditHandle.class, record.getStateId());
@@ -7,6 +7,7 @@ import io.v.nutz.diseaseaid.constant.AidFundMemberAuditState;
import io.v.nutz.diseaseaid.mode.AidFundMemberMode;
import io.v.nutz.diseaseaid.model.AidFundMemberAuditRecord;
import io.v.nutz.member.UserMode;
import io.v.nutz.member.service.MemberService;
import io.v.nutz.member.constant.MemberApplyState;
import io.v.nutz.member.constant.MemberOrigin;
import io.v.nutz.member.model.MemberApplyRecord;
@@ -25,6 +26,8 @@ import io.v.nutz.util.ShiroUtil;
import io.v.nutz.util.ViResource;
import io.v.nutz.web.commons.base.Globals;
import lombok.Getter;
import org.nutz.ioc.aop.Aop;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
@@ -55,6 +58,7 @@ public enum MemberApplyAuditHandle {
*/
CREATE(null) {
@Override
@Aop(TransAop.READ_COMMITTED)
public MemberApplyRecord next(MemberApplyRecord record, Audit audit) {
record.setUserId(ShiroUtil.getPrincipalProperty("id").toString());
record.setStateId(MemberApplyState.UNION);
@@ -64,22 +68,8 @@ public enum MemberApplyAuditHandle {
Sys_user user = sysUserService.fetch(record.getUserId());
Sql sql = Sqls.create("""
SELECT
su.loginname,
su.username
FROM
sys_user_role sur
LEFT JOIN sys_user su ON su.id = sur.userId
WHERE
sur.roleId = @roleId
AND sur.unionid = @unionId
""")
// .setParam("roleId", Roles.UNION_MANGER)
.setParam("roleId", Roles.GH01)
.setParam("unionId", record.getUnionId());
List<NutMap> mapList = sysUserService.listMap(sql);
// 接收人由 PC 部门审核权限关联的角色确定,并限定申请所属工会。
List<NutMap> mapList = memberService.applyAuditRecipients(false, record.getUnionId());
if (Lang.isNotEmpty(mapList)) {
List<TodoTask.Processor> processors = new ArrayList<>();
@@ -102,6 +92,8 @@ public enum MemberApplyAuditHandle {
todoTask.setInitiatorId(user.getLoginname());
todoTask.setPcViewUrl(Globals.AppDomain + "/platform/member/apply/audit/union");
todoTask.setH5ViewUrl(Globals.AppDomain + "/mobile/member/audit");
todoTask.setDoneH5Url(Globals.AppDomain + "/mobile/member/audit?isAudit=true");
todoTask.setDonePcUrl(todoTask.getPcViewUrl() + "?audit=1");
todoTask.setBizId(insert.getId());
todoTask.setBizType("申请入会部门工会审核");
todoTask.setStatus(TodoTaskEnum.TaskStatus.ACTIVE.name());
@@ -121,6 +113,7 @@ public enum MemberApplyAuditHandle {
*/
AUDIT_UNION(MemberApplyState.UNION) {
@Override
@Aop(TransAop.READ_COMMITTED)
public MemberApplyRecord next(MemberApplyRecord record, Audit audit) {
record.setStateId(audit.getAuditPass() ? MemberApplyState.SCHOOL_UNION : MemberApplyState.UNION_FAIL);
@@ -130,18 +123,8 @@ public enum MemberApplyAuditHandle {
if (audit.getAuditPass()) {
Sql sql = Sqls.create("""
SELECT
su.loginname,
su.username
FROM
sys_user_role sur
LEFT JOIN sys_user su ON su.id = sur.userId
WHERE
sur.roleId = @roleId
""").setParam("roleId", Roles.H03);
List<NutMap> mapList = sysUserService.listMap(sql);
// 部门通过后仅向具有 PC 校工会审核权限的角色成员派发下一阶段待办。
List<NutMap> mapList = memberService.applyAuditRecipients(true, record.getUnionId());
if (Lang.isNotEmpty(mapList)) {
List<TodoTask.Processor> processors = new ArrayList<>();
@@ -163,6 +146,8 @@ public enum MemberApplyAuditHandle {
todoTask.setInitiatorId(user.getLoginname());
todoTask.setPcViewUrl(Globals.AppDomain + "/platform/member/apply/audit/school");
todoTask.setH5ViewUrl(Globals.AppDomain + "/mobile/member/audit");
todoTask.setDoneH5Url(Globals.AppDomain + "/mobile/member/audit?isAudit=true");
todoTask.setDonePcUrl(todoTask.getPcViewUrl() + "?audit=1");
todoTask.setBizId(record.getId());
todoTask.setBizType("申请入会校工会审核");
todoTask.setStatus(TodoTaskEnum.TaskStatus.ACTIVE.name());
@@ -178,14 +163,7 @@ public enum MemberApplyAuditHandle {
List.of(Map.of("tool", MsgApi.sendTool.wechat_enterprise.name())));
}
//部门工会的待办设置为完成
TodoTask todoTask = dao.fetch(TodoTask.class, Cnd.where("bizId", "=", record.getId())
.and("bizType", "=", "申请入会部门工会审核"));
if (todoTask != null) {
todoTask.setProcessorId(ShiroUtil.getPrincipalProperty("loginname").toString());
todoTask.setStatus(TodoTaskEnum.TaskStatus.COMPLETE.name());
todoTaskInterface.updateTask(todoTask);
}
memberService.completeApplyAuditTasks(record.getId(), false);
return record;
}
},
@@ -194,6 +172,7 @@ public enum MemberApplyAuditHandle {
*/
AUDIT_SCHOOL(MemberApplyState.SCHOOL_UNION) {
@Override
@Aop(TransAop.READ_COMMITTED)
public MemberApplyRecord next(MemberApplyRecord record, Audit audit) {
memberApplyRecordViService.transactional(() -> {
@@ -242,14 +221,7 @@ public enum MemberApplyAuditHandle {
List.of(Map.of("tool", MsgApi.sendTool.wechat_enterprise.name())));
}
//校工会的待办设置为完成
TodoTask todoTask = dao.fetch(TodoTask.class, Cnd.where("bizId", "=", record.getId())
.and("bizType", "=", "申请入会校工会审核"));
if (todoTask != null) {
todoTask.setProcessorId(ShiroUtil.getPrincipalProperty("loginname").toString());
todoTask.setStatus(TodoTaskEnum.TaskStatus.COMPLETE.name());
todoTaskInterface.updateTask(todoTask);
}
memberService.completeApplyAuditTasks(record.getId(), true);
});
sysUserService.deleteCache(record.getUserId());
@@ -270,6 +242,7 @@ public enum MemberApplyAuditHandle {
public TodoTaskInterface todoTaskInterface = ViResource.ioc.getByType(TodoTaskInterface.class);
public MsgApi msgApi = ViResource.ioc.getByType(MsgApi.class);
public Dao dao = ViResource.dao;
public MemberService memberService = ViResource.ioc.getByType(MemberService.class);
public abstract MemberApplyRecord next(MemberApplyRecord record, Audit audit);
@@ -34,4 +34,21 @@ public interface MemberService extends ViService<Sys_user> {
* @return
*/
Pagination memberChangeRecords(PageForm pageForm, CndPlus cnd);
/** 按当前用户 PC 审核权限查询手机列表;isAudit 为已审标记,year 可空,返回 list/totalCount 分页数据。 */
Object mobileApplyAuditPage(int pageNumber, int pageSize, boolean isAudit, Integer year);
/** 按申请记录校验访问范围并返回审核/只读视图,userId 必须属于该记录,done 强制只读。 */
String mobileApplyAuditView(String recordId, String userId, boolean done);
/** 查询拥有指定阶段审核权限的启用角色成员;部门阶段限定 unionId,返回 loginname/username。 */
List<NutMap> applyAuditRecipients(boolean school, String unionId);
/** 关闭指定申请当前阶段的全部有效待办,保留接收人并记录实际办理人和已办地址。 */
void completeApplyAuditTasks(String recordId, boolean school);
/** 返回当前年份入会待办卡片;身份取当前会话,部门限定本工会,超管可查看两级范围。 */
List<NutMap> getCurrentYearApplyAgenda();
/** 返回当前登录人本年度实际审核的入会记录及只读详情地址,不把角色范围内的已审视作本人已办。 */
List<NutMap> getCurrentYearApplyCompletes();
}
@@ -15,6 +15,21 @@ import org.nutz.lang.util.NutMap;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import java.util.List;
import java.util.Objects;
import io.v.nutz.base.utils.Vi;
import io.v.nutz.member.constant.MemberApplyState;
import io.v.nutz.member.model.MemberApplyRecord;
import io.v.nutz.todoTask.TodoTask;
import io.v.nutz.todoTask.TodoTaskInterface;
import io.v.nutz.web.commons.base.Globals;
import io.v.nutz.web.commons.utils.ShiroUtil;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.permission.WildcardPermission;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.aop.Aop;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.lang.Strings;
/**
@@ -70,4 +85,151 @@ public class MemberServiceImpl extends ViServiceImpl<Sys_user> implements Member
Sql sql = Sqls.create(MEMBER_CHANGE_RECORDS).setCondition(cnd);
return list(pageForm, sql);
}
@Inject
private TodoTaskInterface todoTaskInterface;
/** 与 PC 页面的权限注解一致,不能用待办角色名称替代审核权限。 */
private boolean canApplyAudit(boolean school) {
return ShiroUtil.hasPermission("member.apply.audit." + (school ? "school" : "union"));
}
@Override
public Object mobileApplyAuditPage(int pageNumber, int pageSize, boolean isAudit, Integer year) {
boolean union = canApplyAudit(false);
boolean school = canApplyAudit(true);
if (!union && !school) throw new UnauthorizedException("无会员审核权限");
Sql sql = Sqls.create("SELECT mar.*, st.stateName, st.stateColor, u.unionname, u.username, "
+ "u.loginname, u.personType FROM member_apply_record mar "
+ "LEFT JOIN audit_state st ON st.stateId=mar.stateId LEFT JOIN `user` u ON u.id=mar.userId $condition");
SqlExpressionGroup scope = new SqlExpressionGroup();
// 已审沿用 PC 各阶段 stateId > 当前阶段的口径;双权限取并集,避免重复记录。
if (union && (ShiroUtil.hasRole("sysadmin") || Strings.isNotBlank(Vi.getUnionId()))) {
Cnd department = Cnd.where("mar.stateId", isAudit ? ">" : "=", MemberApplyState.UNION);
if (!ShiroUtil.hasRole("sysadmin")) department.and("mar.unionId", "=", Vi.getUnionId());
scope.or(department.where());
} else if (!school) {
return listPageMap(Math.max(1, pageNumber), Math.max(1, pageSize), sql.setCondition(Cnd.where("1", "=", 0)));
}
if (school) scope.or("mar.stateId", isAudit ? ">" : "=", MemberApplyState.SCHOOL_UNION);
CndPlus cnd = CndPlus.create();
cnd.and(scope);
cnd.andExcludeEmpty("YEAR(mar.applyTime)", "=", year);
cnd.asc("mar.stateId").desc("mar.applyTime");
return listPageMap(Math.max(1, pageNumber), Math.max(1, Math.min(pageSize, 100)), sql.setCondition(cnd));
}
@Override
public String mobileApplyAuditView(String recordId, String userId, boolean done) {
MemberApplyRecord record = Strings.isBlank(recordId) ? null : dao().fetch(MemberApplyRecord.class, recordId);
if (record == null || !Objects.equals(record.getUserId(), userId)) {
throw new IllegalArgumentException("申请记录不存在或申请人不匹配");
}
boolean union = canApplyAudit(false) && (ShiroUtil.hasRole("sysadmin")
|| Strings.isNotBlank(Vi.getUnionId()) && Objects.equals(Vi.getUnionId(), record.getUnionId()));
boolean school = canApplyAudit(true) && record.getStateId() != null
&& record.getStateId() >= MemberApplyState.SCHOOL_UNION;
if (!union && !school) throw new UnauthorizedException("无权查看该申请");
if (!done && union && Objects.equals(record.getStateId(), MemberApplyState.UNION)) {
return "beetl:/mobile/member/union_Audit.html";
}
if (!done && school && Objects.equals(record.getStateId(), MemberApplyState.SCHOOL_UNION)) {
return "beetl:/mobile/member/school_Audit.html";
}
return "beetl:/mobile/member/detail.html";
}
@Override
public List<NutMap> applyAuditRecipients(boolean school, String unionId) {
// 从 PC 权限对应的角色成员取接收人,兼容 Shiro 通配权限并排除禁用角色、菜单和账号。
Sql sql = Sqls.create("SELECT DISTINCT su.loginname, su.username, sm.permission FROM sys_user_role sur "
+ "JOIN sys_user su ON su.id=sur.userId JOIN sys_role sr ON sr.id=sur.roleId "
+ "JOIN sys_role_menu srm ON srm.roleId=sr.id JOIN sys_menu sm ON sm.id=srm.menuId "
+ "WHERE sr.disabled=false AND sm.disabled=false AND su.disabled=false "
+ (school ? "" : "AND sur.unionid=@unionId AND su.unionid=@unionId "));
sql.setParam("unionId", unionId);
WildcardPermission required = new WildcardPermission("member.apply.audit." + (school ? "school" : "union"));
java.util.Map<String, NutMap> recipients = new java.util.LinkedHashMap<>();
for (NutMap row : listMap(sql)) {
String permission = row.getString("permission");
if (Strings.isNotBlank(permission) && Strings.isNotBlank(row.getString("loginname"))
&& new WildcardPermission(permission).implies(required)) {
recipients.putIfAbsent(row.getString("loginname"), row);
}
}
return new java.util.ArrayList<>(recipients.values());
}
@Override
@Aop(TransAop.READ_COMMITTED)
public void completeApplyAuditTasks(String recordId, boolean school) {
// 同阶段可能存在历史重复待办,只关闭 ACTIVE 项,保留接收角色成员列表用于已办归属。
List<TodoTask> tasks = dao().query(TodoTask.class, Cnd.where("bizId", "=", recordId)
.and("bizType", "=", school ? "申请入会校工会审核" : "申请入会部门工会审核")
.and("status", "=", "ACTIVE").and(Cnd.exps("delFlag", "=", false).or("delFlag", "is", null)));
for (TodoTask task : tasks) {
task.setProcessorId(ShiroUtil.getPrincipalProperty("loginname").toString());
task.setStatus("COMPLETE");
task.setDonePcUrl(Globals.AppDomain + "/platform/member/apply/audit/" + (school ? "school" : "union") + "?audit=1");
task.setDoneH5Url(Globals.AppDomain + "/mobile/member/audit?isAudit=true");
todoTaskInterface.updateTask(task);
}
}
@Override
public List<NutMap> getCurrentYearApplyAgenda() {
int year = java.time.LocalDate.now().getYear();
boolean admin = ShiroUtil.hasRole("sysadmin");
List<NutMap> items = new java.util.ArrayList<>();
for (boolean school : new boolean[]{false, true}) {
if (!admin && !canApplyAudit(school)) continue;
// 没有工会归属的部门审核人不能因空条件而获得全校范围。
if (!school && !admin && Strings.isBlank(Vi.getUnionId())) continue;
Cnd cnd = Cnd.where("stateId", "=", school ? MemberApplyState.SCHOOL_UNION : MemberApplyState.UNION)
.and("applyTime", ">=", year + "-01-01")
.and("applyTime", "<", (year + 1) + "-01-01");
if (!school && !admin) cnd.and("unionId", "=", Vi.getUnionId());
int count = dao().count(MemberApplyRecord.class, cnd);
items.add(new NutMap().setv("title", "【会员入会】")
.setv("name", school ? "待校工会入会审核" : "待部门工会入会审核")
.setv("count", count).setv("mobileHref", "/mobile/member/audit"));
}
return items;
}
@Override
public List<NutMap> getCurrentYearApplyCompletes() {
Object principalLoginname = ShiroUtil.getPrincipalProperty("loginname");
String loginname = principalLoginname == null ? "" : principalLoginname.toString();
boolean admin = ShiroUtil.hasRole("sysadmin");
boolean union = admin || canApplyAudit(false);
boolean school = admin || canApplyAudit(true);
if (Strings.isBlank(loginname) || !union && !school) return java.util.Collections.emptyList();
int year = java.time.LocalDate.now().getYear();
// 只读取当前申请实际关联的审核记录,按办理工号和办理年份筛选;同人办理两级保留两个节点。
Sql sql = Sqls.create("""
SELECT mar.id, a.id auditId, nodes.nodeId,
CONCAT('【会员入会】', COALESCE(u.username, '')) moduleName,
nodes.nodeName auditState, a.auditTime,
CONCAT('/mobile/member/audit/findOne?record_id=', mar.id,
'&user_id=', mar.userId, '&done=true') mobileUrl
FROM member_apply_record mar
LEFT JOIN `user` u ON u.id=mar.userId
JOIN (SELECT 1 nodeId, '部门工会审核' nodeName
UNION ALL SELECT 2, '校工会审核') nodes ON 1=1
JOIN audit a ON a.id=CASE nodes.nodeId WHEN 1 THEN mar.unionAuditId ELSE mar.schoolAuditId END
WHERE a.loginname=@loginname AND a.auditTime>=@startTime AND a.auditTime<@endTime
AND ((nodes.nodeId=1 AND @unionAllowed=1 AND (@admin=1 OR mar.unionId=@unionId))
OR (nodes.nodeId=2 AND @schoolAllowed=1))
ORDER BY a.auditTime DESC, mar.id, nodes.nodeId
""");
sql.setParam("loginname", loginname);
sql.setParam("startTime", year + "-01-01");
sql.setParam("endTime", (year + 1) + "-01-01");
sql.setParam("unionAllowed", union ? 1 : 0);
sql.setParam("schoolAllowed", school ? 1 : 0);
sql.setParam("admin", admin ? 1 : 0);
sql.setParam("unionId", Strings.sNull(Vi.getUnionId()));
return listMap(sql);
}
}
@@ -1,112 +1,47 @@
package io.v.nutz.mobile.member;
import cn.wizzer.framework.base.service.BaseService;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.utils.Vi;
import io.v.nutz.dao.CndPlus;
import io.v.nutz.member.constant.MemberApplyState;
import io.v.nutz.util.ShiroUtil;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import io.v.nutz.member.service.MemberService;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.Logical;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* @author zhf
* @date 2021/9/26 9:24
* @description
*/
/** 手机端会员审核统一入口,与 PC 端共享两级审核权限。 */
@IocBean
@At("/mobile/member/audit")
@Ok("json:full")
@RequiresAuthentication
@RequiresPermissions(value = {"member.apply.audit.union", "member.apply.audit.school"}, logical = Logical.OR)
public class MemberAuditUnionController {
@Inject
private MemberService memberService;
@At("")
@Ok("beetl:/mobile/member/audit_list.html")
public void indext() {
public void index() {
}
@Inject
private BaseService baseService;
/**
* pageNumber/pageSize 为页码和每页条数,isAudit 区分已审/待审,year 为申请年份(可空)。
* 返回分页对象,list 为申请记录,totalCount 为符合当前审核权限的数据总数。
*/
@At
@ViReturn
public Object pageData(int pageNumber, int pageSize, boolean isAudit, Integer year) {
Sql sql = Sqls.create("""
SELECT
mar.*,
st.stateName,
st.stateColor,
u.unionname,
u.username,
u.loginname,
u.personType
FROM
`member_apply_record` mar
LEFT JOIN audit_state st ON st.stateId = mar.stateId
LEFT JOIN `user` u ON u.id = mar.userId
$condition
""");
CndPlus cnd = CndPlus.create();
cnd.and("mar.memberStates", "=", 1);
if (ShiroUtil.hasAnyRoles("sysadmin")) {
cnd.and("mar.stateId", "in", isAudit ? Lang.array(MemberApplyState.UNION_FAIL, MemberApplyState.SCHOOL_UNION_FAIL, MemberApplyState.NORMAL_MEMBER) : Lang.array(MemberApplyState.UNION, MemberApplyState.SCHOOL_UNION));
} else {
if (ShiroUtil.hasAnyRoles("A06,wyh02") && ShiroUtil.hasAnyRoles("H04")) {
SqlExpressionGroup seg = new SqlExpressionGroup();
seg.or("mar.stateId", isAudit ? ">" : "=", MemberApplyState.SCHOOL_UNION);
seg.or(CndPlus.exps("mar.unionId", "=", Vi.getUnionId()).and("mar.stateId", isAudit ? ">" : "=", MemberApplyState.UNION));
cnd.and(seg);
} else if (ShiroUtil.hasAnyRoles("A06,wyh02")) {
cnd.and("mar.stateId", isAudit ? ">" : "=", MemberApplyState.SCHOOL_UNION);
} else if (ShiroUtil.hasAnyRoles("H04")) {
cnd.and("mar.unionId", "=", Vi.getUnionId());
cnd.and("mar.stateId", isAudit ? ">" : "=", MemberApplyState.UNION);
}
/*if (ShiroUtil.hasAnyRoles("A06,wyh02")) {
cnd.and("mar.stateId", isAudit ? ">" : "=", MemberApplyState.SCHOOL_UNION);
} else if (ShiroUtil.hasAnyRoles("H04")) {
cnd.and("mar.unionId", "=", Vi.getUnionId());
cnd.and("mar.stateId", isAudit ? ">" : "=", MemberApplyState.UNION);
}*/
}
/* if (!ShiroUtil.hasAnyRoles("sysadmin")) {
if (ShiroUtil.hasAnyRoles("A06,wyh02")) {
cnd.and("mar.stateId", isAudit ? ">" : "=", MemberApplyState.SCHOOL_UNION);
}
}*/
cnd.andExcludeEmpty("YEAR(mar.applyTime)", "=", year);
cnd.asc("mar.stateId");
cnd.desc("mar.applyTime");
sql.setCondition(cnd);
return baseService.listPageMap(pageNumber, pageSize, sql);
return memberService.mobileApplyAuditPage(pageNumber, pageSize, isAudit, year);
}
/**
* record_id 为申请记录 ID,user_id 为申请人 ID,done 表示从已办入口只读查看。
* 返回 Beetl 页面视图;实际审核阶段和访问范围均由数据库记录决定。
*/
@At("/findOne")
@Ok("re")
public String findOne(Integer stateId) {
if (stateId == MemberApplyState.UNION && ShiroUtil.hasAnyRoles("H04,A06,sysadmin")) {
return "beetl:/mobile/member/union_Audit.html";
} else if (stateId == MemberApplyState.SCHOOL_UNION && ShiroUtil.hasAnyRoles("A06,sysadmin")) {
return "beetl:/mobile/member/school_Audit.html";
} /*else if (stateId == MemberApplyState.NORMAL_MEMBER || stateId == MemberApplyState.UNION_FAIL || stateId == MemberApplyState.SCHOOL_UNION_FAIL) {
return "beetl:/mobile/member/detail.html";
}*/
return "beetl:/mobile/member/detail.html";
public String findOne(String record_id, String user_id, boolean done) {
return memberService.mobileApplyAuditView(record_id, user_id, done);
}
}
@@ -12,13 +12,11 @@ import io.v.nutz.sys.models.Sys_menu;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.zgfw.service.CondolenceService;
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.Strings;
import org.nutz.lang.util.NutMap;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
@@ -53,71 +51,24 @@ public class CondolenceAgentController {
List<NutMap> result = new ArrayList<>();
result.add(new NutMap().setv("title", title).setv("url", UCR).setv("iconClass", vi.getIconByPath(UCR)).setv("label", "待部门工会审核").setv("number", getUcrCount()));
result.add(new NutMap().setv("title", title).setv("url", FR).setv("iconClass", vi.getIconByPath(FR)).setv("label", "待二级党组织审核").setv("number", getFrCount()));
result.add(new NutMap().setv("title", title).setv("url", VCR).setv("iconClass", vi.getIconByPath(VCR)).setv("label", "待校工会审核").setv("number", getVcrCount()));
result.add(new NutMap().setv("title", title).setv("url", ECR).setv("iconClass", vi.getIconByPath(ECR)).setv("label", "待工会常务副主席审核").setv("number", getEcrCount()));
result.add(new NutMap().setv("title", title).setv("url", UCR).setv("iconClass", vi.getIconByPath(UCR)).setv("label", "待部门工会审核").setv("number", condolenceService.countCurrentYearAgenda(2000)));
result.add(new NutMap().setv("title", title).setv("url", FR).setv("iconClass", vi.getIconByPath(FR)).setv("label", "待二级党组织审核").setv("number", condolenceService.countCurrentYearAgenda(2012)));
result.add(new NutMap().setv("title", title).setv("url", VCR).setv("iconClass", vi.getIconByPath(VCR)).setv("label", "待校工会审核").setv("number", condolenceService.countCurrentYearAgenda(2020)));
result.add(new NutMap().setv("title", title).setv("url", ECR).setv("iconClass", vi.getIconByPath(ECR)).setv("label", "待工会常务副主席审核").setv("number", condolenceService.countCurrentYearAgenda(2050)));
Sys_user user = (Sys_user) ShiroUtil.getPrincipal();
List<Sys_menu> menus = Optional.ofNullable(user).orElse(new Sys_user()).getMenus();
return result.stream().filter(v -> Strings.isNotBlank(v.getString("url")) && menus.stream().anyMatch(x -> Strings.isNotBlank(x.getHref()) && v.getString("url").equals(x.getHref()))).distinct().collect(Collectors.toList());
}
/**
* 待工会主席审核
*
* @return
* 无需传参,身份取自登录会话,返回今年本人办理的慰问记录列表。
* 每项包含 moduleName(业务名称)、auditState(办理节点)、auditTime(审核日期)、mobileUrl(详情链接)。
*/
private Integer getUcrCount() {
Cnd cnd = Cnd.NEW();
Sql sql = Sqls.create("""
SELECT COUNT(1) FROM condolence con LEFT JOIN `user` us ON con.be_user=us.id $condition
""");
cnd.and("con.state_id", "=", 2000);
if (!ShiroUtil.hasAnyRoles("sysadmin,A06")) {
cnd.and("us.unionid", "=", vi.getUnionId());
}
sql.setCondition(cnd);
return condolenceService.count(sql);
@At
@ViReturn
@RequiresAuthentication
public Object getCompletes() {
return condolenceService.getCurrentYearCompletes();
}
/**
* 待工会会计审核
* 暂时没用
*
* @return
*/
private Integer getFrCount() {
Cnd cnd = Cnd.NEW();
Sql sql = Sqls.create("""
SELECT COUNT(1) FROM condolence con LEFT JOIN `user` us ON con.be_user=us.id $condition
""");
cnd.and("con.state_id", "=", 2012);
if (!ShiroUtil.hasAnyRoles("sysadmin,A06")) {
cnd.and("us.unionid", "=", vi.getUnionId());
}
sql.setCondition(cnd);
return condolenceService.count(sql);
}
/**
* 待校工会主席审核
*
* @return
*/
private Integer getVcrCount() {
return condolenceService.count(Cnd.where("state_id", "=", 2020));
}
/**
* 待工会常务副主席审核
* 暂时没用
*
* @return
*/
private Integer getEcrCount() {
return condolenceService.count(Cnd.where("state_id", "=", 2050));
}
}
@@ -5,6 +5,7 @@ import io.v.nutz.service.ViService;
import io.v.nutz.zgfw.model.condolence.Condolence;
import org.nutz.dao.entity.Record;
import org.nutz.lang.util.NutMap;
import java.util.List;
/**
@@ -19,6 +20,20 @@ public interface CondolenceService extends ViService<Condolence> {
*/
NutMap findOne(String id);
/**
* 无参数;按当前会话工号及本自然年审核日期查询本人慰问已办。
* @return 列表项包含 id、reviewId、moduleName、auditState、auditTime、mobileUrl;按审核日期倒序
*/
List<NutMap> getCurrentYearCompletes();
/**
* 统计当前登录用户可见范围内、申请时间属于当前自然年的慰问待办数量。
*
* @param stateId 审核状态:2000 部门工会、2012 二级党组织、2020 校工会、2050 历史常务副主席待办
* @return 待办数量(Integer);不支持的状态返回 0,权限菜单过滤仍由待办接口保留
*/
Integer countCurrentYearAgenda(int stateId);
/**
* 判断被慰问人在当前自然年是否已有住院慰问申请。
*
@@ -3,6 +3,8 @@ package io.v.nutz.zgfw.service.impl;
import cn.wizzer.framework.base.service.BaseService;
import io.v.nutz.base.utils.DateUtil;
import io.v.nutz.base.utils.Vi;
import io.v.nutz.util.ShiroUtil;
import io.v.nutz.modules.services.ReviewService;
import io.v.nutz.service.impl.ViServiceImpl;
import io.v.nutz.zgfw.model.condolence.Condolence;
@@ -19,6 +21,8 @@ import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import java.util.List;
import java.util.Collections;
/**
* @author 1V
@@ -37,6 +41,78 @@ public class CondolenceServiceImpl extends ViServiceImpl<Condolence> implements
this.condolenceDao = dao;
}
/**
* 按审核状态统计本自然年申请,保留原待办对部门工会、二级党组织节点的工会范围限制。
*
* @param stateId 2000、2012、2020 或 2050;其他值不属于本接口的待办节点
* @return 当前节点的待办条数,不包含往年或下一年度申请
*/
/**
* 按审核记录的办理人工号及办理年份筛选,不将申请当前状态误作个人审核结果。
* @return 本人今年的已办列表;未获得登录工号时返回空列表,禁止扩大到全员记录
*/
@Override
public List<NutMap> getCurrentYearCompletes() {
Object principalLoginname = ShiroUtil.getPrincipalProperty("loginname");
String loginname = principalLoginname == null ? "" : principalLoginname.toString();
if (Strings.isBlank(loginname)) {
return Collections.emptyList();
}
int year = DateUtil.getYear();
// 只读取申请当前关联的审核记录;再次审核覆盖的旧关联无法在此恢复。
Sql sql = Sqls.create("""
SELECT con.id, r.id reviewId,
CONCAT('【职工慰问】', COALESCE(con.be_user_username, '')) moduleName,
nodes.nodeName auditState, r.time auditTime,
CONCAT('/mobile/condolence/apply/info?id=', con.id) mobileUrl
FROM condolence con
JOIN (
SELECT 1 nodeId, '部门工会审核' nodeName
UNION ALL SELECT 2, '二级党组织审核'
UNION ALL SELECT 3, '校工会审核'
UNION ALL SELECT 4, '工会常务副主席审核'
) nodes ON 1=1
JOIN review r ON r.id = CASE nodes.nodeId
WHEN 1 THEN con.union_chairman_review
WHEN 2 THEN con.finance_review
WHEN 3 THEN con.vice_chairman_review
WHEN 4 THEN con.executive_chairman_review END
WHERE r.loginname = @loginname AND r.time >= @startTime AND r.time < @endTime
ORDER BY r.time DESC, con.id, nodes.nodeId
""");
sql.setParam("loginname", loginname);
sql.setParam("startTime", year + "-01-01");
sql.setParam("endTime", (year + 1) + "-01-01");
return listMap(sql);
}
@Override
public Integer countCurrentYearAgenda(int stateId) {
if (stateId != 2000 && stateId != 2012 && stateId != 2020 && stateId != 2050) {
return 0;
}
// 年份只读取一次;左闭右开范围包含年初当天及年末全部时间,跨年后自动切换。
int year = DateUtil.getYear();
if (stateId == 2000 || stateId == 2012) {
Cnd cnd = Cnd.where("con.state_id", "=", stateId)
.and("con.apply_time", ">=", year + "-01-01")
.and("con.apply_time", "<", (year + 1) + "-01-01");
// 沿用原待办的角色判断:系统管理员和校工会管理员不限制所属工会。
if (!ShiroUtil.hasAnyRoles("sysadmin,A06")) {
cnd.and("us.unionid", "=", Vi.getUnionId());
}
Sql sql = Sqls.create("""
SELECT COUNT(1) FROM condolence con LEFT JOIN `user` us ON con.be_user=us.id $condition
""");
sql.setCondition(cnd);
return count(sql);
}
// 校级节点保留原有全校统计范围,仅追加申请年份条件。
return count(Cnd.where("state_id", "=", stateId)
.and("apply_time", ">=", year + "-01-01")
.and("apply_time", "<", (year + 1) + "-01-01"));
}
@Override
public boolean hasHospitalCondolenceInCurrentYear(Condolence application) {
CondolenceType type = condolenceDao.fetch(CondolenceType.class, application.getType());
@@ -110,6 +186,14 @@ public class CondolenceServiceImpl extends ViServiceImpl<Condolence> implements
if (Strings.isNotBlank(record.getString("union_chairman_review"))) {
record.put("ucr", reviewService.fetch(record.getString("union_chairman_review")));
}
// 二级党组织审核沿用 finance_review 字段,详情以 fr 返回审核人、时间、意见和签字。
if (Strings.isNotBlank(record.getString("finance_review"))) {
record.put("fr", reviewService.fetch(record.getString("finance_review")));
}
// 历史常务副主席审核记录仅用于展示,不改变当前审批流转。
if (Strings.isNotBlank(record.getString("executive_chairman_review"))) {
record.put("ecr", reviewService.fetch(record.getString("executive_chairman_review")));
}
//校工会
if (Strings.isNotBlank(record.getString("vice_chairman_review"))) {
record.put("vcr", reviewService.fetch(record.getString("vice_chairman_review")));
@@ -235,6 +235,36 @@
</el-form>
</el-tab-pane>
<el-tab-pane v-if="hasPane(6)&&viewData.ecr" label="工会常务副主席审核信息" name="6">
<el-form label-width="130px" label-suffix=":" style="padding: 20px 0">
<vi-title title="审核信息"></vi-title>
<el-row gutter="20">
<el-col :span="12">
<el-form-item label="审核人员">
{{ viewData.ecr.username }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审核时间">
{{ viewData.ecr.time }}
</el-form-item>
</el-col>
</el-row>
<el-form-item label="审核意见">
<div class="textarea-div">{{ viewData.ecr.opinion ? viewData.ecr.opinion : '暂无' }}</div>
</el-form-item>
<el-form-item label="签&emsp;&emsp;字">
<el-image v-if="viewData.ecr.sign"
style="width: 300px; height: 100px"
:src="viewData.ecr.sign"
fit="contain"></el-image>
<span v-else>暂无</span>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane v-if="handle" :label="label" name="999">
<slot name="handle"></slot>
</el-tab-pane>
@@ -257,7 +287,7 @@ module.exports = {
},
panes: {
type: Array,
default: []
default: () => []
},
},
filters: {
@@ -278,27 +308,32 @@ module.exports = {
watch: {},
methods: {
hasPane(name) {
if (!this.handle) {
// 未指定页签范围时展示所有已有审核记录;显式传入范围时保持原有限制。
if (!this.handle || this.panes.length === 0) {
return true
}
return this.panes.includes(name)
},
async getInfo(id) {
this.loading = true
const {data, code, msg} = await $.get("/platform/fw/condolence/findOne", {id})
this.loading = false
if (data) {
this.activeName = this.handle ? "999" : "1"
condolence.toFormData(data)
this.viewData = data
} else {
this.viewData = {}
this.$message({
message: "获取信息失败",
type: 'error'
});
}
/**
* id 为慰问申请 ID;接口 data 为申请详情,ucr/fr/vcr/ecr 为各节点审核记录对象。
* 无记录时对应页签隐藏;请求结束后统一解除加载状态。
*/
getInfo(id) {
this.$set(this, 'loading', true)
this.$set(this, 'viewData', {})
return $.post('/platform/fw/condolence/findOne', {id})
.then((res) => {
if (res.code === 0 && res.data) {
condolence.toFormData(res.data)
this.$set(this, 'activeName', this.handle ? '999' : '1')
this.$set(this, 'viewData', res.data)
} else {
this.$message.error('获取信息失败')
}
})
.always(() => {
this.$set(this, 'loading', false)
})
},
},
created() {
+115 -19
View File
@@ -223,9 +223,12 @@ layout("/mobile/platform.html"){
roles: [],
active: 1,
needCount: 0,
needRequestId: 0,
needItems: [],
activeName: '0',
completedItems: [],
completedLoading: false,
completedRequestId: 0,
}
},
methods: {
@@ -244,7 +247,8 @@ layout("/mobile/platform.html"){
location.href = o.mobileHref
},
toHref(o) {
location.href = o.mobileUrl + '?audit=1';
// 详情链接已携带申请 ID,保留查询参数。
location.href = o.mobileUrl;
},
/**
* 入学登记待办
@@ -256,20 +260,111 @@ layout("/mobile/platform.html"){
this.needItems = this.needItems.concat(data.filter(v => v.number > 0))
}
},*/
async getNeedItems() {
const {data, code} = await $.get('/platform/needItems/getNeedItems')
if (code === 0) {
const obj = data.filter(v => {
return v.mobileHref != null && v.count > 0
/**
* requestId 为本轮刷新序号,忽略旧请求,避免返回页面或切换页签时覆盖新数据。
* 通用接口 data 为待办数组,使用 count 和 mobileHref;完成后继续加载慰问待办。
*/
getNeedItems(requestId) {
return $.post('/platform/needItems/getNeedItems')
.then((res) => {
if (requestId === this.needRequestId && res.code === 0) {
this.$set(this, 'needItems', (res.data || []).filter(v => v.mobileHref && v.count > 0
&& v.mobileHref.split('?')[0] !== '/mobile/member/audit'
&& !['/platform/member/apply/audit/union', '/platform/member/apply/audit/school'].includes((v.href || '').split('?')[0])))
}
})
.always(() => {
if (requestId === this.needRequestId) {
this.getCondolenceAgenda(requestId)
}
})
this.needItems = obj
}
},
async getCompletes() {
const {data, code} = await $.get('/platform/sys/completed/getCompletes')
if (code === 0) {
this.completedItems = data;
}
/**
* 复用 PC 慰问待办的菜单权限和统计口径,将 label/number 转为手机模板的 name/count。
* 仅映射手机端已有审核页面的三个节点,历史常务副主席节点不提供手机办理入口。
*/
getCondolenceAgenda(requestId) {
const auditUrls = [
'/platform/fw/condolence/ucr/union',
'/platform/fw/condolence/fr',
'/platform/fw/condolence/vcr/school'
]
return $.post('/platform/condolence/agent/getAgenda')
.then((res) => {
if (requestId !== this.needRequestId || res.code !== 0) {
return
}
const items = (res.data || []).filter(v => auditUrls.includes(v.url) && v.number > 0)
.map(v => ({
title: v.title,
name: v.label,
count: v.number,
mobileHref: '/mobile/condolence/audit'
}))
this.$set(this, 'needItems', this.needItems.concat(items))
})
.always(() => {
if (requestId === this.needRequestId) {
this.getMemberApplyAgenda(requestId)
}
})
},
/**
* 无需业务参数;后端按会话权限返回今年会员入会节点,字段与首页待办卡片一致。
* 专用数据替代通用配置中的同业务卡片,避免双计数;失败不影响已加载的慰问待办。
*/
getMemberApplyAgenda(requestId) {
return $.post('/platform/member/agenda/getMobileAgenda')
.then((res) => {
if (requestId !== this.needRequestId) return
if (res.code === 0) {
const items = (res.data || []).filter(v => v.count > 0 && v.mobileHref)
this.$set(this, 'needItems', this.needItems.concat(items))
} else {
vant.Toast.fail('会员入会待办加载失败,请重试')
}
}, () => {
if (requestId === this.needRequestId) vant.Toast.fail('会员入会待办加载失败,请重试')
})
.always(() => {
if (requestId === this.needRequestId) this.$set(this, 'needCount', this.needItems.length)
})
},
/**
* 两个接口均无需传办理人,按当前会话返回本人今年已办。
* 各业务独立合并;全部请求结束后关闭 loading,旧刷新结果不得覆盖当前列表。
*/
getCompletes() {
const requestId = this.completedRequestId + 1
this.$set(this, 'completedRequestId', requestId)
this.$set(this, 'completedItems', [])
this.$set(this, 'completedLoading', true)
const sources = [
{url: '/platform/condolence/agent/getCompletes', label: '慰问'},
{url: '/platform/member/agenda/getCompletes', label: '会员入会'}
]
let remaining = sources.length
const requests = sources.map(source => $.post(source.url)
.then((res) => {
if (requestId !== this.completedRequestId) return
if (res.code === 0) {
const items = this.completedItems.concat(res.data || [])
// 现有日期字段统一交给 moment 解析,兼容日期字符串和时间戳。
items.sort((a, b) => (moment(b.auditTime).valueOf() || 0) - (moment(a.auditTime).valueOf() || 0))
this.$set(this, 'completedItems', items)
} else {
vant.Toast.fail(source.label + '已办加载失败,请重试')
}
}, () => {
if (requestId === this.completedRequestId) vant.Toast.fail(source.label + '已办加载失败,请重试')
})
.always(() => {
remaining--
if (requestId === this.completedRequestId && remaining === 0) {
this.$set(this, 'completedLoading', false)
}
}))
return $.when.apply($, requests)
},
/**
* 会员个人核对待办
@@ -291,12 +386,13 @@ layout("/mobile/platform.html"){
this.needItems = this.needItems.concat(data.filter(v => v.count > 0))
}
},
async initData() {
await this.getNeedItems();
// await this.getMemberCheckSelfAgenda()
// await this.getWelfareCheckSelfAgenda()
// await this.getCompletes();
this.needCount = this.needItems.length
initData() {
this.getCompletes()
// 每轮重新合并通用、慰问和会员入会待办,防止重复追加;刷新序号隔离尚未完成的旧请求。
this.$set(this, 'needRequestId', this.needRequestId + 1)
this.$set(this, 'needItems', [])
this.$set(this, 'needCount', 0)
return this.getNeedItems(this.needRequestId)
},
async setNeedItems() {
const {data, code} = await $.get('/platform/needItems/getNeedItems')
@@ -59,9 +59,10 @@ layout("/mobile/platform.html"){
{text: '已审核', value: true},
],
handle: true,
queryVersion: 0,
pageForm: {
year: new Date().getFullYear(),
isAudit: false,
year: GetQueryString("isAudit") === "true" ? null : new Date().getFullYear(),
isAudit: GetQueryString("isAudit") === "true",
},
}
},
@@ -70,6 +71,7 @@ layout("/mobile/platform.html"){
},
methods: {
yearChange() {
this.queryVersion++
this.pageForm.pageNumber = 1
this.tableData = []
this.finished = false
@@ -77,40 +79,32 @@ layout("/mobile/platform.html"){
},
onLoad() {
this.loading = true
$.post(loc() + '/pageData', this.pageForm).then(res => {
// 捕获本次筛选条件,筛选切换后忽略旧请求,避免串页。
const requestKey = this.queryVersion || 0
$.post('/mobile/member/audit/pageData', Object.assign({}, this.pageForm)).then(res => {
if (requestKey !== (this.queryVersion || 0)) return
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
if (this.tableData.length === res.data.totalCount) {
this.finished = true
} else {
this.pageForm.pageNumber++
}
this.finished = this.tableData.length >= res.data.totalCount || res.data.list.length === 0
if (!this.finished) this.pageForm.pageNumber++
} else {
this.finished = true
this.$toast.fail(res.msg || '加载失败')
}
this.loading = false
}).fail(() => {
if (requestKey !== (this.queryVersion || 0)) return
this.finished = true
this.$toast.fail('加载失败,请重新筛选后重试')
}).always(() => {
if (requestKey === (this.queryVersion || 0)) this.loading = false
})
},
/* pageData() {
this.mLoading = true
setTimeout(async () => {
$.get(loc() + '/pageData', this.pageForm, (res) => {
if (res.code === 0) {
this.tableData = this.tableData.concat(res.data.list)
if (this.tableData.length === res.data.totalCount) {
this.finished = true
} else {
this.pageForm.pageNumber++
}
}
})
this.mLoading = false
}, 600)
},*/
openView(o) {
window.location.href = '/mobile/member/audit/findOne?stateId=' + o.stateId + '&record_id=' + o.id + '&user_id=' + o.userId
window.location.href = '/mobile/member/audit/findOne?stateId=' + o.stateId + '&record_id=' + o.id + '&user_id=' + o.userId + '&done=' + this.pageForm.isAudit
},
},
async created() {
created() {
this.yearList = [{text: '全部年份', value: null}]
let nowYear = new Date().getFullYear()
for (let i = nowYear; i >= nowYear - 9; i--) {
this.yearList.push({text: i, value: i})
@@ -26,7 +26,6 @@ layout("/mobile/platform.html"){
<van-field v-model="formData.auditTime" label="审核时间" readonly></van-field>
<van-field
required
v-model="formData.auditOpinion"
rows="1"
autosize
@@ -46,12 +45,12 @@ layout("/mobile/platform.html"){
<van-row gutter="20" style="margin-top: 30px;padding: 0 25px">
<van-col span="12">
<van-button :color="themeColor" plain block @click="doAudit(false)">拒 绝
<van-button :color="themeColor" plain block :loading="formLoading" :disabled="formLoading" @click="doAudit(false)">拒 绝
</van-button>
</van-col>
<van-col span="12">
<van-button :color="themeColor" block @click="doAudit(true)">通 过
<van-button :color="themeColor" block :loading="formLoading" :disabled="formLoading" @click="doAudit(true)">通 过
</van-button>
</van-col>
</van-row>
@@ -72,6 +71,7 @@ layout("/mobile/platform.html"){
data() {
return {
handle: true,
formLoading: false,
id: "",
formData: {},
}
@@ -81,25 +81,27 @@ layout("/mobile/platform.html"){
'mobile-sign': httpVueLoader('/components/sign/mobileSign.vue'),
},
methods: {
async doAudit(pass) {
if (!this.formData.auditOpinion) {
this.$toast.fail('请填写审核意见');
return
}
this.formData.auditPass = pass
const resp = await $.post("/platform/member/apply/audit/doAudit", this.formData)
requestLaterFun(resp, (data) => {
this.$toast.success('审核成功');
setTimeout(() => {
location.href = '/mobile/member/audit'
}, 1000)
}, () => {
this.$toast.fail('审核失败');
}, () => {
doAudit(pass) {
if (this.formLoading) return
// 与 PC 共用审核参数;提交前读取手写签名,避免仅提交历史签名。
this.$refs.signature.submitSign()
this.$set(this.formData, 'auditPass', pass)
this.formLoading = true
$.post('/platform/member/apply/audit/doAudit', this.formData).then(resp => {
requestLaterFun(resp, () => {
this.$toast.success('审核成功')
location.replace('/mobile/member/audit')
}, () => {
this.$toast.fail('审核失败')
}, () => {})
}).fail(() => {
this.$toast.fail('审核失败,请稍后重试')
}).always(() => {
this.formLoading = false
})
},
},
async created() {
created() {
const record_id = GetQueryString("record_id")
const user_id = GetQueryString("user_id")
setTimeout(() => {
@@ -26,7 +26,7 @@ layout("/mobile/platform.html"){
<van-field v-model="formData.auditTime" label="审核时间" readonly></van-field>
<van-field required
<van-field
v-model="formData.auditOpinion"
rows="1"
autosize
@@ -45,12 +45,12 @@ layout("/mobile/platform.html"){
<van-row gutter="20" style="margin-top: 30px;padding: 0 25px">
<van-col span="12">
<van-button :color="themeColor" plain block @click="doAudit(false)">拒 绝
<van-button :color="themeColor" plain block :loading="formLoading" :disabled="formLoading" @click="doAudit(false)">拒 绝
</van-button>
</van-col>
<van-col span="12">
<van-button :color="themeColor" block @click="doAudit(true)">通 过
<van-button :color="themeColor" block :loading="formLoading" :disabled="formLoading" @click="doAudit(true)">通 过
</van-button>
</van-col>
</van-row>
@@ -70,6 +70,7 @@ layout("/mobile/platform.html"){
data() {
return {
handle: true,
formLoading: false,
id: "",
formData: {},
}
@@ -80,25 +81,27 @@ layout("/mobile/platform.html"){
},
methods: {
async doAudit(pass) {
if (!this.formData.auditOpinion) {
this.$toast.fail('请填写审核意见');
return
}
this.formData.auditPass = pass
const resp = await $.post("/platform/member/apply/audit/doAudit", this.formData)
requestLaterFun(resp, (data) => {
this.$toast.success('审核成功');
setTimeout(() => {
location.href = '/mobile/member/audit'
}, 1000)
}, () => {
this.$toast.fail('审核失败');
}, () => {
doAudit(pass) {
if (this.formLoading) return
// 与 PC 共用审核参数;提交前读取手写签名,避免仅提交历史签名。
this.$refs.signature.submitSign()
this.$set(this.formData, 'auditPass', pass)
this.formLoading = true
$.post('/platform/member/apply/audit/doAudit', this.formData).then(resp => {
requestLaterFun(resp, () => {
this.$toast.success('审核成功')
location.replace('/mobile/member/audit')
}, () => {
this.$toast.fail('审核失败')
}, () => {})
}).fail(() => {
this.$toast.fail('审核失败,请稍后重试')
}).always(() => {
this.formLoading = false
})
},
},
async created() {
created() {
const record_id = GetQueryString("record_id")
const user_id = GetQueryString("user_id")
setTimeout(() => {
@@ -288,7 +288,8 @@
pageForm: {
source: source,
searchName: "u.username",
audit: 2
// 已办入口默认显示本阶段已审核记录。
audit: new URLSearchParams(window.location.search).get("audit") === "1" ? 1 : 2
},
unions: [],
tableColumns: [