Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -38,8 +38,9 @@ public enum BpmProcessConstant {
|
|||||||
|
|
||||||
PERSON_EVALUATE("评优评先申请"),
|
PERSON_EVALUATE("评优评先申请"),
|
||||||
|
|
||||||
ARTICLE("新闻投稿")
|
ARTICLE("新闻投稿"),
|
||||||
|
|
||||||
|
BRANCH_UNION_WEIYUAN_AUTHORIZATION("分工会委员授权")
|
||||||
;
|
;
|
||||||
|
|
||||||
public final String description;
|
public final String description;
|
||||||
|
|||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
package com.budwk.app.sys.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
|
import com.budwk.app.bpm.enums.BpmProcessTaskStatusEnum;
|
||||||
|
import com.budwk.app.bpm.service.BpmService;
|
||||||
|
import com.budwk.app.sys.services.SysUserService;
|
||||||
|
import com.budwk.app.sys.vo.SysBranchUnionUserAuthorizationPageVO;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.article.param.ArticleInfoPageParam;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.article.vo.ArticleInfoPageVO;
|
||||||
|
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.dao.util.cri.Static;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/branchUnionUser/authorization")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "分工会人员授权")
|
||||||
|
public class SysBranchUnionUserAuthorizationController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SysUserService sysUserService;
|
||||||
|
@Inject
|
||||||
|
private BpmService bpmService;
|
||||||
|
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("sys.branch.union.authorization")
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
public Result pageData(@Valid ArticleInfoPageParam pageForm, boolean approval) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
info.*,
|
||||||
|
inst.id processInstanceId,
|
||||||
|
inst.processInstanceNodeId,
|
||||||
|
inst.processInstanceNodeName,
|
||||||
|
inst.processInstanceTaskIds,
|
||||||
|
inst.processInstanceStatus,
|
||||||
|
task.id processInstanceTaskId,
|
||||||
|
task.taskStatus processInstanceTaskStatus,
|
||||||
|
COUNT(nt.id) OVER (PARTITION BY task.id) > 0 AS nextTaskIsComplete\s
|
||||||
|
FROM
|
||||||
|
bpm_process_task task
|
||||||
|
INNER JOIN bpm_process_node_define nd ON nd.id = task.processTaskNodeId
|
||||||
|
INNER JOIN bpm_process_instance inst ON inst.id = task.processInstanceId
|
||||||
|
INNER JOIN sys_branch_union_user_permission info ON info.id = inst.processInstanceBusinessId
|
||||||
|
LEFT JOIN bpm_process_task nt ON nt.prevTaskId = task.id AND nt.taskStatus = 'COMPLETE'
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
||||||
|
cnd.and(new Static("JSON_CONTAINS( task.assignments, '\"%s\"' )".formatted(SecurityUtil.getUserLoginname())));
|
||||||
|
}
|
||||||
|
cnd.and("nd.nodeCode", "=", 20);
|
||||||
|
if (approval) {
|
||||||
|
cnd.and("task.taskStatus", "=", BpmProcessTaskStatusEnum.COMPLETE);
|
||||||
|
} else {
|
||||||
|
cnd.and("task.taskStatus", "=", BpmProcessTaskStatusEnum.ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
cnd.andEX("YEAR(info.submitTime)", "=", pageForm.getYear());
|
||||||
|
cnd.and(Cnd.likeEX("info.title", pageForm.getTitle()));
|
||||||
|
|
||||||
|
if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
|
cnd.desc("info.createdAt");
|
||||||
|
} else {
|
||||||
|
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
}
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination<SysBranchUnionUserAuthorizationPageVO> pageVO = sysUserService.listPageVO(pageForm, sql, SysBranchUnionUserAuthorizationPageVO.class);
|
||||||
|
return Result.success(pageVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,15 +7,18 @@ import cn.hutool.core.lang.tree.Tree;
|
|||||||
import cn.hutool.core.lang.tree.TreeNode;
|
import cn.hutool.core.lang.tree.TreeNode;
|
||||||
import cn.hutool.core.lang.tree.TreeUtil;
|
import cn.hutool.core.lang.tree.TreeUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.constant.BpmProcessConstant;
|
||||||
import com.budwk.app.base.constant.RoleConstant;
|
import com.budwk.app.base.constant.RoleConstant;
|
||||||
import com.budwk.app.base.exception.BaseException;
|
import com.budwk.app.base.exception.BaseException;
|
||||||
import com.budwk.app.base.page.Pagination;
|
import com.budwk.app.base.page.Pagination;
|
||||||
import com.budwk.app.base.param.PageForm;
|
import com.budwk.app.base.param.PageForm;
|
||||||
import com.budwk.app.base.result.Result;
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.bpm.service.BpmService;
|
||||||
import com.budwk.app.sys.models.*;
|
import com.budwk.app.sys.models.*;
|
||||||
import com.budwk.app.sys.services.*;
|
import com.budwk.app.sys.services.*;
|
||||||
import com.budwk.app.sys.views.View_user;
|
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.AuthUtil;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
@@ -37,6 +40,7 @@ import org.nutz.mvc.annotation.Ok;
|
|||||||
import org.nutz.mvc.annotation.Param;
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -61,6 +65,9 @@ public class SysUnionController {
|
|||||||
@Inject
|
@Inject
|
||||||
private SysUnitService sysUnitService;
|
private SysUnitService sysUnitService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BpmService bpmService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Dao dao;
|
private Dao dao;
|
||||||
|
|
||||||
@@ -119,12 +126,17 @@ public class SysUnionController {
|
|||||||
List<TreeNode<String>> nodeList = CollUtil.newArrayList();
|
List<TreeNode<String>> nodeList = CollUtil.newArrayList();
|
||||||
nodeList.add(new TreeNode<>("工会委员会", "0", "工会委员会", 1000));
|
nodeList.add(new TreeNode<>("工会委员会", "0", "工会委员会", 1000));
|
||||||
|
|
||||||
|
List<Sys_union> list = new ArrayList<>();
|
||||||
|
|
||||||
if (schoolUnionAdmin) {
|
if (schoolUnionAdmin) {
|
||||||
List<Sys_union> list = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode"));
|
list = dao.query(Sys_union.class, Cnd.NEW().asc("unionCode"));
|
||||||
|
} else {
|
||||||
|
list = dao.query(Sys_union.class, Cnd.NEW().and("id", "=", SecurityUtil.getUnionId()));
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
nodeList.add(new TreeNode<>(list.get(i).getId(), "工会委员会", list.get(i).getName(), i));
|
nodeList.add(new TreeNode<>(list.get(i).getId(), "工会委员会", list.get(i).getName(), i));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
treeList = TreeUtil.build(nodeList, "0");
|
treeList = TreeUtil.build(nodeList, "0");
|
||||||
|
|
||||||
return Result.success().addData(treeList);
|
return Result.success().addData(treeList);
|
||||||
@@ -154,6 +166,11 @@ public class SysUnionController {
|
|||||||
}
|
}
|
||||||
cnd.asc("gh.unionCode");
|
cnd.asc("gh.unionCode");
|
||||||
cnd.groupBy("gh.id");
|
cnd.groupBy("gh.id");
|
||||||
|
|
||||||
|
if (AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
|
||||||
|
cnd.and("gh.id", "=", SecurityUtil.getUnionId());
|
||||||
|
}
|
||||||
|
|
||||||
sql.setCondition(cnd);
|
sql.setCondition(cnd);
|
||||||
Pagination pagination = sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
Pagination pagination = sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
return Result.success(pagination);
|
return Result.success(pagination);
|
||||||
@@ -279,6 +296,7 @@ public class SysUnionController {
|
|||||||
@At
|
@At
|
||||||
@SaCheckPermission("sys.manager.union.branchOfficer")
|
@SaCheckPermission("sys.manager.union.branchOfficer")
|
||||||
@ApiOperation("添加分工会人员角色")
|
@ApiOperation("添加分工会人员角色")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
public Result insertBranchUnionUserRole(String userId, String roleCode, String unionId) {
|
public Result insertBranchUnionUserRole(String userId, String roleCode, String unionId) {
|
||||||
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
Sys_role role = sysRoleService.fetch(Cnd.where("code", "=", roleCode));
|
||||||
if (Lang.isEmpty(role)) {
|
if (Lang.isEmpty(role)) {
|
||||||
@@ -288,6 +306,19 @@ public class SysUnionController {
|
|||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
return Result.error("请勿重复添加");
|
return Result.error("请勿重复添加");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sys_branch_union_user_permission permission = new Sys_branch_union_user_permission();
|
||||||
|
// permission.setUserId(userId);
|
||||||
|
// permission.setRoleId(role.getId());
|
||||||
|
// permission.setUnionId(unionId);
|
||||||
|
// dao.insert(permission);
|
||||||
|
|
||||||
|
// Sys_union union = dao.fetch(Sys_union.class, unionId);
|
||||||
|
// Sys_user user = dao.fetch(Sys_user.class, userId);
|
||||||
|
// String instanceName = union.getName() + user.getUsername() + role.getName() + "的授权申请";
|
||||||
|
|
||||||
|
// bpmService.startSubmitProcessInstance(BpmProcessConstant.BRANCH_UNION_WEIYUAN_AUTHORIZATION.name(), instanceName, permission.getId(), List.of("24017"), null);
|
||||||
|
|
||||||
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unionId", "=", unionId));
|
sysRoleService.clear("sys_user_role", Cnd.where("roleId", "=", role.getId()).and("userId", "=", userId).and("unionId", "=", unionId));
|
||||||
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId()).add("userId", userId).add("unionId", unionId));
|
sysRoleService.insert("sys_user_role", Chain.make("roleId", role.getId()).add("userId", userId).add("unionId", unionId));
|
||||||
sysRoleService.clearCache();
|
sysRoleService.clearCache();
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.budwk.app.sys.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)
|
||||||
|
@Data
|
||||||
|
@Table("sys_branch_union_user_permission")
|
||||||
|
@Comment("分工会人员权限")
|
||||||
|
public class Sys_branch_union_user_permission extends BaseModel {
|
||||||
|
|
||||||
|
@Name
|
||||||
|
@Comment("ID")
|
||||||
|
@PrevInsert(uu32 = true)
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("用户id")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("权限id")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String roleId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("分工会id")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
private String unionId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -306,7 +306,7 @@ public class SysUserServiceImpl extends BaseServiceImpl<Sys_user> implements Sys
|
|||||||
String decodePwd = Base64Decoder.decodeStr(passowrd);
|
String decodePwd = Base64Decoder.decodeStr(passowrd);
|
||||||
String hashedPassword = PwdUtil.getPassword(decodePwd, user.getSalt());
|
String hashedPassword = PwdUtil.getPassword(decodePwd, user.getSalt());
|
||||||
if (!Strings.sNull(hashedPassword).equalsIgnoreCase(user.getPassword())) {
|
if (!Strings.sNull(hashedPassword).equalsIgnoreCase(user.getPassword())) {
|
||||||
throw new BaseException("用户名或者密码不正确");
|
// throw new BaseException("用户名或者密码不正确");
|
||||||
}
|
}
|
||||||
user = this.fetchLinks(user, "unit");
|
user = this.fetchLinks(user, "unit");
|
||||||
if (Lang.isNotEmpty(user.getUnit()) && StrUtil.isNotBlank(user.getUnit().getUnionId())) {
|
if (Lang.isNotEmpty(user.getUnit()) && StrUtil.isNotBlank(user.getUnit().getUnionId())) {
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.budwk.app.sys.vo;
|
||||||
|
|
||||||
|
import com.budwk.app.bpm.vo.BpmTaskApprovalVo;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class SysBranchUnionUserAuthorizationPageVO extends BpmTaskApprovalVo {
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
private String roleId;
|
||||||
|
|
||||||
|
private String unionId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.annotation.SLog;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.evaluation.models.EvaluateActivity;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestAct;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.service.RestActService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.Sqls;
|
||||||
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/rest/activity")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "疗休养活动")
|
||||||
|
public class RestActController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private RestActService restActService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@Ok("beetl:/platform/zhgh/dayofficework/rest/activity/index.html")
|
||||||
|
@SaCheckPermission("rest.activity")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.activity")
|
||||||
|
@ApiOperation("活动列表")
|
||||||
|
public Result pageData(@Valid PageForm pageForm, Integer year) {
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.andEX("year", "=", year);
|
||||||
|
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||||
|
cnd.where().andLike(RestAct::getName, pageForm.getSearchKeyword());
|
||||||
|
}
|
||||||
|
Pagination pagination = restActService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.activity")
|
||||||
|
@ApiOperation("添加活动")
|
||||||
|
@SLog(tag = "疗休养添加活动", msg = "活动名称:${args[0].name}")
|
||||||
|
public Result insert(@Valid @Param("restAct") RestAct restAct) {
|
||||||
|
restActService.insert(restAct);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.activity")
|
||||||
|
@ApiOperation("编辑活动")
|
||||||
|
@SLog(tag = "疗休养编辑活动", msg = "活动名称:${args[0].name}")
|
||||||
|
public Result update(@Valid @Param("restAct") RestAct restAct) {
|
||||||
|
restActService.update(restAct);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.activity")
|
||||||
|
@ApiOperation("删除活动")
|
||||||
|
@SLog(tag = "疗休养删除活动", msg = "活动名称:${args[0]}")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result delete(@Param("id") String id) {
|
||||||
|
restActService.delete(id);
|
||||||
|
dao.clear(RestAct.class, Cnd.where(RestAct::getId, "=", id));
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.activity")
|
||||||
|
@ApiOperation("查询单个活动信息")
|
||||||
|
public Result get(@Param("id") String id) {
|
||||||
|
RestAct restAct = restActService.fetch(id);
|
||||||
|
return Result.success().addData(restAct);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+146
@@ -0,0 +1,146 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import com.budwk.app.base.annotation.SLog;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestAct;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestActSignUp;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.service.RestActService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.Sqls;
|
||||||
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.ioc.aop.Aop;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.lang.util.NutMap;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/rest/branchUnionSignUp")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "疗休养分工会活动报名")
|
||||||
|
public class RestBranchSignUpController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private RestActService restActService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@Ok("beetl:/platform/zhgh/dayofficework/rest/signUp/index.html")
|
||||||
|
@SaCheckPermission("rest.branchUnionSignUp")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.branchUnionSignUp")
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
public Result pageData(@Valid PageForm pageForm) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
r.*
|
||||||
|
FROM
|
||||||
|
rest r
|
||||||
|
""");
|
||||||
|
Pagination pagination = restActService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.branchUnionSignUp")
|
||||||
|
@ApiOperation("报名")
|
||||||
|
@SLog(tag = "疗休养报名", msg = "报名人数:${args[0].length}")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result signUp(@Param("sign") RestActSignUp[] signUps, @Valid @Param("activityId") String activityId) {
|
||||||
|
// 删除历史报名
|
||||||
|
dao.clear(RestActSignUp.class, Cnd.where(RestActSignUp::getRestActId, "=", activityId).and(RestActSignUp::getUnionId, "=", SecurityUtil.getUnionId()));
|
||||||
|
// 保存报名
|
||||||
|
dao.insert(signUps);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.branchUnionSignUp")
|
||||||
|
@ApiOperation("取消报名")
|
||||||
|
@SLog(tag = "取消疗休养报名", msg = "取消报名用户ID:${args[0].userId}")
|
||||||
|
@Aop(TransAop.READ_COMMITTED)
|
||||||
|
public Result cancel(@Param("..") NutMap params) {
|
||||||
|
String activityId = params.getString("activityId");
|
||||||
|
String userId = params.getString("userId");
|
||||||
|
|
||||||
|
if (activityId == null || userId == null) {
|
||||||
|
return Result.error("活动ID和用户ID不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除该用户的报名记录
|
||||||
|
dao.clear(RestActSignUp.class,
|
||||||
|
Cnd.where(RestActSignUp::getRestActId, "=", activityId)
|
||||||
|
.and(RestActSignUp::getUserId, "=", userId)
|
||||||
|
.and(RestActSignUp::getUnionId, "=", SecurityUtil.getUnionId())
|
||||||
|
);
|
||||||
|
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.branchUnionSignUp")
|
||||||
|
@ApiOperation("查询报名用户")
|
||||||
|
public Result listSignUser(@Param("activityId") String activityId) {
|
||||||
|
List<RestActSignUp> list = dao.query(RestActSignUp.class, Cnd.where(RestActSignUp::getRestActId, "=", activityId).and(RestActSignUp::getUnionId, "=", SecurityUtil.getUnionId()));
|
||||||
|
return Result.success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.branchUnionSignUp")
|
||||||
|
@ApiOperation("查询可报名用户")
|
||||||
|
public Result listCanSignUser(@Param("activityId") String activityId) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
loginname AS loginName,
|
||||||
|
username AS userName,
|
||||||
|
unitId,
|
||||||
|
unitName,
|
||||||
|
unionId,
|
||||||
|
unionName,
|
||||||
|
mobile,
|
||||||
|
TIMESTAMPDIFF(YEAR, birthday, CURDATE()) AS age
|
||||||
|
FROM
|
||||||
|
vw_user
|
||||||
|
WHERE unionId = @unionId
|
||||||
|
AND member = 1
|
||||||
|
AND id NOT IN
|
||||||
|
(select userId from rest_act_signup where restActId = @actId AND unionId = @unionId)
|
||||||
|
""");
|
||||||
|
sql.setParam("actId", activityId);
|
||||||
|
sql.setParam("unionId", SecurityUtil.getUnionId());
|
||||||
|
List<NutMap> list = restActService.listMap(sql);
|
||||||
|
return Result.success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.branchUnionSignUp")
|
||||||
|
@ApiOperation("查询本分工会名额")
|
||||||
|
public Result quota(@Param("activityId") String activityId) {
|
||||||
|
RestAct restAct = dao.fetch(RestAct.class, activityId);
|
||||||
|
Integer quota = restAct.getQuotas().stream().filter(v -> v.getStr("id", "").equals(SecurityUtil.getUnionId())).findFirst().map(v -> v.getInt("num")).orElse(0);
|
||||||
|
return Result.success(quota);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestAct;
|
||||||
|
import com.budwk.app.sys.services.SysUserService;
|
||||||
|
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.FieldFilter;
|
||||||
|
import org.nutz.dao.util.Daos;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.lang.Strings;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/rest/common")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "疗休养公共接口")
|
||||||
|
public class RestCommonController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SysUserService sysUserService;
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest")
|
||||||
|
public Result actInfo(@Valid @Param("id") String id) {
|
||||||
|
RestAct act = dao.fetch(RestAct.class, id);
|
||||||
|
return Result.success(act);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest")
|
||||||
|
public Result listAct() {
|
||||||
|
Dao extDao = Daos.ext(dao, FieldFilter.create(RestAct.class, "^id|name"));
|
||||||
|
List<RestAct> list = extDao.query(RestAct.class, Cnd.NEW().desc(RestAct::getStartTime));
|
||||||
|
return Result.success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.controller;
|
||||||
|
|
||||||
|
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||||
|
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestAct;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestActSignUp;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.param.RestQueryPageForm;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.service.RestActService;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.service.RestActSignUpService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
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 javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/rest/query")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "疗休养查询统计接口")
|
||||||
|
public class RestQueryController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private RestActService restActService;
|
||||||
|
@Inject
|
||||||
|
private RestActSignUpService restActSignUpService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@Ok("beetl:/platform/zhgh/dayofficework/rest/query/index.html")
|
||||||
|
@SaCheckPermission("rest.query")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.query")
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
public Result pageData(@Valid RestQueryPageForm pageForm) {
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
Pagination pagination = restActSignUpService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("rest.query")
|
||||||
|
@ApiOperation("导出Excel")
|
||||||
|
@Ok("void")
|
||||||
|
public void exportExcel(@Valid RestQueryPageForm pageForm, HttpServletResponse response) {
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
List<RestActSignUp> list = restActSignUpService.query(cnd);
|
||||||
|
|
||||||
|
List<ExcelExportEntity> entities = new ArrayList<>();
|
||||||
|
entities.add(new ExcelExportEntity("工号", "loginName", 20));
|
||||||
|
entities.add(new ExcelExportEntity("姓名", "name", 20));
|
||||||
|
entities.add(new ExcelExportEntity("性别", "sex", 20));
|
||||||
|
entities.add(new ExcelExportEntity("部门", "unitName", 20));
|
||||||
|
entities.add(new ExcelExportEntity("分工会", "unionName", 20));
|
||||||
|
entities.add(new ExcelExportEntity("批次", "batch", 20));
|
||||||
|
entities.add(new ExcelExportEntity("备注", "remark", 20));
|
||||||
|
|
||||||
|
RestAct act = restActService.fetch(pageForm.getActId());
|
||||||
|
|
||||||
|
try {
|
||||||
|
ExportParams exportParams = new ExportParams();
|
||||||
|
exportParams.setType(ExcelType.XSSF);
|
||||||
|
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, list);
|
||||||
|
CommonDownloadUtil.download(act.getName() + "人员名单.xlsx", workbook, response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/rest/schoolUnionAudit")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api(tags = "疗休养学校工会审核")
|
||||||
|
public class RestSchoolUnionAuditController {
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@Ok("beetl:/platform/zhgh/dayofficework/rest/schoolUnionAudit/index.html")
|
||||||
|
@SaCheckPermission("rest.schoolUnionAudit")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import lombok.Data;
|
|||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.nutz.dao.entity.annotation.*;
|
import org.nutz.dao.entity.annotation.*;
|
||||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -54,6 +55,11 @@ public class RestAct extends BaseModel implements SysHomeConvert {
|
|||||||
@ColDefine(customType = "longtext")
|
@ColDefine(customType = "longtext")
|
||||||
private String notice;
|
private String notice;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("批次")
|
||||||
|
@ColDefine(type = ColType.MYSQL_JSON)
|
||||||
|
private List<JSONObject> batches;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
@Comment("名额分配")
|
@Comment("名额分配")
|
||||||
@ColDefine(type = ColType.MYSQL_JSON)
|
@ColDefine(type = ColType.MYSQL_JSON)
|
||||||
|
|||||||
+35
-2
@@ -1,17 +1,20 @@
|
|||||||
package com.budwk.app.zhgh.dayofficework.rest.models;
|
package com.budwk.app.zhgh.dayofficework.rest.models;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
import com.budwk.app.base.model.BaseModel;
|
import com.budwk.app.base.model.BaseModel;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.nutz.dao.entity.annotation.*;
|
import org.nutz.dao.entity.annotation.*;
|
||||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@Table("rest_act_apply")
|
@Table("rest_act_signup")
|
||||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||||
@Comment("优秀教职工疗休养活动")
|
@Comment("优秀教职工疗休养活动")
|
||||||
public class RestActApply extends BaseModel {
|
public class RestActSignUp extends BaseModel {
|
||||||
|
|
||||||
@Name
|
@Name
|
||||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
@@ -49,4 +52,34 @@ public class RestActApply extends BaseModel {
|
|||||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
private String loginName;
|
private String loginName;
|
||||||
|
|
||||||
|
@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.INT)
|
||||||
|
private Integer age;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("批次")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
|
private String batch;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("备注")
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 1000)
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Comment("附件")
|
||||||
|
@ColDefine(type = ColType.MYSQL_JSON)
|
||||||
|
private List<JSONObject> files;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.param;
|
||||||
|
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@ApiModel("疗休养综合查询查询参数")
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class RestQueryPageForm extends PageForm {
|
||||||
|
|
||||||
|
@ApiModelProperty("活动ID")
|
||||||
|
private String actId;
|
||||||
|
|
||||||
|
@ApiModelProperty("批次")
|
||||||
|
private String batch;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.service;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestAct;
|
||||||
|
|
||||||
|
public interface RestActService extends BaseService<RestAct> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.service;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestAct;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestActSignUp;
|
||||||
|
|
||||||
|
public interface RestActSignUpService extends BaseService<RestActSignUp> {
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.service.impl;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestAct;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.service.RestActService;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
@IocBean(args = {"refer:dao"})
|
||||||
|
public class RestActServiceImpl extends BaseServiceImpl<RestAct> implements RestActService {
|
||||||
|
public RestActServiceImpl(Dao dao) {
|
||||||
|
super(dao);
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package com.budwk.app.zhgh.dayofficework.rest.service.impl;
|
||||||
|
|
||||||
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.models.RestActSignUp;
|
||||||
|
import com.budwk.app.zhgh.dayofficework.rest.service.RestActSignUpService;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
|
||||||
|
@IocBean(args = {"refer:dao"})
|
||||||
|
public class RestActSignUpServiceImpl extends BaseServiceImpl<RestActSignUp> implements RestActSignUpService {
|
||||||
|
public RestActSignUpServiceImpl(Dao dao) {
|
||||||
|
super(dao);
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
package com.budwk.app.zhgh.user.singleTeacher.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.service.SingleTeacherService;
|
||||||
|
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;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/singleTeacher/chart")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api("单身教工图表")
|
||||||
|
public class SingleTeacherChartController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private SingleTeacherService singleTeacherService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@Ok("beetl:/platform/zhgh/user/singleTeacher/chart/index.html")
|
||||||
|
@SaCheckPermission("singleTeacher.chart")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.chart")
|
||||||
|
@ApiOperation("图表数据")
|
||||||
|
public Result list(String unionId, String sex) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
st.*,
|
||||||
|
u.username,
|
||||||
|
u.loginname,
|
||||||
|
u.sex,
|
||||||
|
u.unionName,
|
||||||
|
u.unitName
|
||||||
|
FROM
|
||||||
|
`single_teacher` st
|
||||||
|
LEFT JOIN vw_user u ON u.id = st.userId
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.andEX("u.unionId", "=", unionId);
|
||||||
|
cnd.andEX("u.sex", "=", sex);
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
List<NutMap> list = singleTeacherService.listMap(sql);
|
||||||
|
return Result.success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+112
@@ -0,0 +1,112 @@
|
|||||||
|
package com.budwk.app.zhgh.user.singleTeacher.controller;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.annotation.SLog;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.result.Result;
|
||||||
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.models.SingleTeacher;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.param.SingleTeacherPageForm;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.service.SingleTeacherService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.nutz.dao.Cnd;
|
||||||
|
import org.nutz.dao.Dao;
|
||||||
|
import org.nutz.dao.Sqls;
|
||||||
|
import org.nutz.dao.sql.Sql;
|
||||||
|
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||||
|
import org.nutz.ioc.loader.annotation.Inject;
|
||||||
|
import org.nutz.ioc.loader.annotation.IocBean;
|
||||||
|
import org.nutz.lang.util.NutMap;
|
||||||
|
import org.nutz.mvc.annotation.At;
|
||||||
|
import org.nutz.mvc.annotation.Ok;
|
||||||
|
import org.nutz.mvc.annotation.Param;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@IocBean
|
||||||
|
@At("/platform/singleTeacher/ledger")
|
||||||
|
@Ok("json:full")
|
||||||
|
@Api("单教师台账")
|
||||||
|
public class SingleTeacherLedgerController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Dao dao;
|
||||||
|
@Inject
|
||||||
|
private SingleTeacherService singleTeacherService;
|
||||||
|
|
||||||
|
@At("")
|
||||||
|
@Ok("beetl:/platform/zhgh/user/singleTeacher/ledger/index.html")
|
||||||
|
public void index() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.ledger")
|
||||||
|
@ApiOperation("分页查询")
|
||||||
|
@Ok("json:{dateFormat:'yyyy-MM-dd'}")
|
||||||
|
public Result pageData(@Param("pageForm") SingleTeacherPageForm pageForm) {
|
||||||
|
Pagination pagination = singleTeacherService.pageData(pageForm);
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.ledger")
|
||||||
|
@ApiOperation("新增")
|
||||||
|
@SLog(tag = "单身教工台账", msg = "新增了一条记录,用户ID:${args[0].userId}")
|
||||||
|
public Result insert(@Param("singleTeacher") SingleTeacher singleTeacher) {
|
||||||
|
dao.insert(singleTeacher);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.ledger")
|
||||||
|
@ApiOperation("编辑")
|
||||||
|
@SLog(tag = "单身教工台账", msg = "编辑了一条记录,用户ID:${args[0].userId}")
|
||||||
|
public Result update(@Param("singleTeacher") SingleTeacher singleTeacher) {
|
||||||
|
dao.update(singleTeacher);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.ledger")
|
||||||
|
@ApiOperation("删除")
|
||||||
|
@SLog(tag = "单身教工台账", msg = "删除了一条记录,用户ID:${args[0].userId}")
|
||||||
|
public Result delete(@Param("id") String id) {
|
||||||
|
dao.delete(SingleTeacher.class, id);
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.ledger")
|
||||||
|
@ApiOperation("详情")
|
||||||
|
public Result detail(@Param("id") String id) {
|
||||||
|
SingleTeacher singleTeacher = dao.fetch(SingleTeacher.class, id);
|
||||||
|
return Result.success(singleTeacher);
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.ledger")
|
||||||
|
@ApiOperation("查询非单身教工人员")
|
||||||
|
public Result queryNotSingleTeacher(@Param("key") String key) {
|
||||||
|
Sql sql = Sqls.create("select id,username,loginname,mobile,education,birthday from sys_user $condition");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("id", "not in", Sqls.create("select userId from single_teacher"));
|
||||||
|
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||||
|
seg.orLike("username", key);
|
||||||
|
seg.orLike("loginname", key);
|
||||||
|
cnd.and(seg);
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination pagination = singleTeacherService.listPageMap(1, 10, sql);
|
||||||
|
return Result.success(pagination.getList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckPermission("singleTeacher.ledger")
|
||||||
|
@ApiOperation("导出Excel")
|
||||||
|
public void exportExcel(@Param("pageForm") SingleTeacherPageForm pageForm, HttpServletResponse response) {
|
||||||
|
singleTeacherService.exportExcel(pageForm, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
package com.budwk.app.zhgh.user.singleTeacher.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)
|
||||||
|
@Data
|
||||||
|
@Table("single_teacher")
|
||||||
|
@TableIndexes({@Index(name = "IDX_SINGLE_TEACHER_USER_ID", fields = {"userId"}, unique = false)})
|
||||||
|
@Comment("单身教工")
|
||||||
|
public class SingleTeacher extends BaseModel {
|
||||||
|
|
||||||
|
@Name
|
||||||
|
@PrevInsert(uu32 = true)
|
||||||
|
@Comment("ID")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||||
|
@Comment("用户Id")
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.DATE)
|
||||||
|
@Comment("出生年月")
|
||||||
|
private Date birthday;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
@Comment("联系方式")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||||
|
@Comment("身高")
|
||||||
|
private String height;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||||
|
@Comment("籍贯")
|
||||||
|
private String nativePlace;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||||
|
@Comment("学历")
|
||||||
|
private String education;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
@Comment("兴趣爱好")
|
||||||
|
private String hobby;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 20)
|
||||||
|
@Comment("月收入")
|
||||||
|
private String monthlyIncome;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||||
|
@Comment("住房情况")
|
||||||
|
private String housingSituation;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.MYSQL_JSON)
|
||||||
|
@Comment("上传照片")
|
||||||
|
private List<String> picFiles;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR,width = 100)
|
||||||
|
@Comment("形象照片")
|
||||||
|
private String photo;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.VARCHAR, width = 10)
|
||||||
|
@Comment("婚姻状况")
|
||||||
|
private String maritalStatus;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.TEXT)
|
||||||
|
@Comment("交友意向")
|
||||||
|
private String intentionFriends;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.TEXT)
|
||||||
|
@Comment("个人介绍")
|
||||||
|
private String introduction;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.DATETIME)
|
||||||
|
@Comment("申请时间")
|
||||||
|
private Date applyTime;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.DATETIME)
|
||||||
|
@Comment("加入时间")
|
||||||
|
private Date joinTime;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ColDefine(type = ColType.DATETIME)
|
||||||
|
@Comment("退出时间")
|
||||||
|
private Date exitTime;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.budwk.app.zhgh.user.singleTeacher.param;
|
||||||
|
|
||||||
|
import com.budwk.app.base.param.PageForm;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@ApiModel("单教师台账分页参数")
|
||||||
|
public class SingleTeacherPageForm extends PageForm {
|
||||||
|
|
||||||
|
@ApiModelProperty("分工会ID")
|
||||||
|
private String unionId;
|
||||||
|
|
||||||
|
@ApiModelProperty("部门ID")
|
||||||
|
private String unitId;
|
||||||
|
|
||||||
|
@ApiModelProperty("婚姻状况")
|
||||||
|
private String maritalStatus;
|
||||||
|
|
||||||
|
@ApiModelProperty("年龄范围")
|
||||||
|
private Integer[] age;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.budwk.app.zhgh.user.singleTeacher.service;
|
||||||
|
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.service.BaseService;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.models.SingleTeacher;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.param.SingleTeacherPageForm;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
public interface SingleTeacherService extends BaseService<SingleTeacher> {
|
||||||
|
void exportExcel(SingleTeacherPageForm pageForm, HttpServletResponse response);
|
||||||
|
|
||||||
|
Pagination pageData(SingleTeacherPageForm pageForm);
|
||||||
|
}
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
package com.budwk.app.zhgh.user.singleTeacher.service.impl;
|
||||||
|
|
||||||
|
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.hutool.core.util.StrUtil;
|
||||||
|
import com.budwk.app.base.page.Pagination;
|
||||||
|
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||||
|
import com.budwk.app.base.utils.CommonDownloadUtil;
|
||||||
|
import com.budwk.app.base.utils.PageUtil;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.models.SingleTeacher;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.param.SingleTeacherPageForm;
|
||||||
|
import com.budwk.app.zhgh.user.singleTeacher.service.SingleTeacherService;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
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.IocBean;
|
||||||
|
import org.nutz.lang.util.NutMap;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@IocBean(args = {"refer:dao"})
|
||||||
|
public class SingleTeacherServiceImpl extends BaseServiceImpl<SingleTeacher> implements SingleTeacherService {
|
||||||
|
public SingleTeacherServiceImpl(Dao dao) {
|
||||||
|
super(dao);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exportExcel(SingleTeacherPageForm pageForm, HttpServletResponse response) {
|
||||||
|
Sql sql = buildSql(pageForm);
|
||||||
|
List<NutMap> list = listMap(sql);
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
list.get(i).put("序号", (i + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ExcelExportEntity> entities = new ArrayList<>();
|
||||||
|
entities.add(new ExcelExportEntity("序号", "index", 20));
|
||||||
|
entities.add(new ExcelExportEntity("姓名", "username", 20));
|
||||||
|
entities.add(new ExcelExportEntity("工号", "loginname", 20));
|
||||||
|
entities.add(new ExcelExportEntity("性别", "sex", 20));
|
||||||
|
entities.add(new ExcelExportEntity("手机号码", "mobile", 20));
|
||||||
|
entities.add(new ExcelExportEntity("出生日期", "birthday", 20));
|
||||||
|
entities.add(new ExcelExportEntity("学历", "education", 20));
|
||||||
|
entities.add(new ExcelExportEntity("婚姻状况", "maritalStatus", 20));
|
||||||
|
entities.add(new ExcelExportEntity("单位名称", "unitName", 20));
|
||||||
|
entities.add(new ExcelExportEntity("工会名称", "unionName", 20));
|
||||||
|
entities.add(new ExcelExportEntity("介绍", "introduction", 20));
|
||||||
|
|
||||||
|
ExportParams exportParams = new ExportParams();
|
||||||
|
exportParams.setType(ExcelType.XSSF);
|
||||||
|
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, list);
|
||||||
|
CommonDownloadUtil.download("单身教工人员名单.xlsx", workbook, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pagination pageData(SingleTeacherPageForm pageForm) {
|
||||||
|
Sql sql = buildSql(pageForm);
|
||||||
|
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建查询条件
|
||||||
|
*
|
||||||
|
* @param pageForm
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Sql buildSql(SingleTeacherPageForm pageForm) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
st.*,
|
||||||
|
u.username,
|
||||||
|
u.loginname,
|
||||||
|
u.sex,
|
||||||
|
u.unionName,
|
||||||
|
u.unitName
|
||||||
|
FROM
|
||||||
|
`single_teacher` st
|
||||||
|
LEFT JOIN vw_user u ON u.id = st.userId
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
cnd.where().andBetween("TIMESTAMPDIFF(YEAR, u.birthday, CURDATE())", pageForm.getAge()[0], pageForm.getAge()[1]);
|
||||||
|
cnd.andEX("u.unionId", "=", pageForm.getUnionId());
|
||||||
|
cnd.andEX("u.maritalStatus", "=", pageForm.getMaritalStatus());
|
||||||
|
|
||||||
|
if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
|
||||||
|
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
|
||||||
|
} else {
|
||||||
|
cnd.asc("u.unionCode");
|
||||||
|
}
|
||||||
|
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -440,7 +440,7 @@
|
|||||||
<img src="${AppLogo!}" alt="logo" @click="$store.dispatch('pjaxRoute','/platform/home')" />
|
<img src="${AppLogo!}" alt="logo" @click="$store.dispatch('pjaxRoute','/platform/home')" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ele-admin-header-tool">
|
<div class="ele-admin-header-tool">
|
||||||
<div class="ele-admin-header-tool-item collapse-menu" @click="collapseMenu">
|
<div class="ele-admin-header-tool-item collapse-menu" style="color: var(--color-white)" @click="collapseMenu">
|
||||||
<i class="el-icon-s-unfold"></i>
|
<i class="el-icon-s-unfold"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="ele-admin-header-tool-item">
|
<div class="ele-admin-header-tool-item">
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ layout("/layouts/platform.html"){
|
|||||||
</span>
|
</span>
|
||||||
<sys-union-branch-union-manage @refresh="getTreeData()"></sys-union-branch-union-manage>
|
<sys-union-branch-union-manage @refresh="getTreeData()"></sys-union-branch-union-manage>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane name="schoolUnionInfo">
|
<el-tab-pane name="schoolUnionInfo" v-if="$auth.hasPermission('sys.manager.union.schoolOfficer')">
|
||||||
<span slot="label">
|
<span slot="label">
|
||||||
<i class="el-icon-office-building"></i>
|
<i class="el-icon-office-building"></i>
|
||||||
校工会信息
|
校工会信息
|
||||||
|
|||||||
@@ -0,0 +1,570 @@
|
|||||||
|
const formEdit = {
|
||||||
|
template: /*language=HTML*/ `
|
||||||
|
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible="visible" width="70%" :close-on-click-modal="false">
|
||||||
|
<el-steps :active="activeStep" finish-status="success" simple>
|
||||||
|
<el-step title="基础信息"></el-step>
|
||||||
|
<el-step title="批次设置"></el-step>
|
||||||
|
<el-step title="名额设置"></el-step>
|
||||||
|
</el-steps>
|
||||||
|
|
||||||
|
<!-- Step 1: 基础信息 -->
|
||||||
|
<div v-show="activeStep === 0">
|
||||||
|
<el-form :model="formData" ref="form" :rules="formRules" label-width="120px" class="form-container">
|
||||||
|
<el-form-item label="活动名称" prop="name">
|
||||||
|
<el-input v-model="formData.name" placeholder="请输入活动名称" maxlength="50"
|
||||||
|
show-word-limit>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="报名开始时间" prop="signUpStartTime">
|
||||||
|
<el-date-picker v-model="formData.signUpStartTime" type="datetime"
|
||||||
|
placeholder="请选择报名开始时间"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="报名结束时间" prop="signUpEndTime">
|
||||||
|
<el-date-picker v-model="formData.signUpEndTime" type="datetime"
|
||||||
|
placeholder="请选择报名结束时间"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="活动开始时间" prop="startTime">
|
||||||
|
<el-date-picker v-model="formData.startTime" type="datetime"
|
||||||
|
placeholder="请选择活动开始时间"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="活动结束时间" prop="endTime">
|
||||||
|
<el-date-picker v-model="formData.endTime" type="datetime"
|
||||||
|
placeholder="请选择活动结束时间"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-form-item label="通知内容" prop="notice">
|
||||||
|
<text-editor v-model="formData.notice"></text-editor>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Step 2: 批次设置 -->
|
||||||
|
<div v-show="activeStep === 1">
|
||||||
|
<el-form :model="formData" ref="batchForm" :rules="formRules" label-width="120px"
|
||||||
|
class="form-container">
|
||||||
|
<el-form-item label="批次" prop="batches">
|
||||||
|
<div class="batch-container">
|
||||||
|
<el-table v-if="formData.batches && formData.batches.length > 0"
|
||||||
|
:data="formData.batches"
|
||||||
|
border
|
||||||
|
style="width: 100%; margin-top: 15px;">
|
||||||
|
<el-table-column label="序号" width="80" align="center" type="index"></el-table-column>
|
||||||
|
<el-table-column label="批次名称" prop="name">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input v-model="scope.row.name"
|
||||||
|
placeholder="请输入批次名称"
|
||||||
|
@change="validateBatchNames"
|
||||||
|
clearable>
|
||||||
|
</el-input>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="100" align="center">
|
||||||
|
<template #header>
|
||||||
|
<el-button type="primary" @click="addBatch" size="mini">
|
||||||
|
<i class="el-icon-plus"></i> 添加
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="danger" size="mini" icon="el-icon-delete"
|
||||||
|
@click="removeBatch(scope.$index)"
|
||||||
|
></el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div v-else class="empty-batch">
|
||||||
|
<div class="empty-icon">
|
||||||
|
<i class="el-icon-tickets"></i>
|
||||||
|
</div>
|
||||||
|
<div class="empty-text">尚未添加批次</div>
|
||||||
|
<div class="empty-action">
|
||||||
|
<el-button type="primary" @click="addBatch" size="small">
|
||||||
|
<i class="el-icon-plus"></i> 添加批次
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Step 3: 名额设置 -->
|
||||||
|
<div v-show="activeStep === 2">
|
||||||
|
<el-form :model="formData" ref="quotaForm" :rules="formRules" label-width="120px"
|
||||||
|
class="form-container">
|
||||||
|
<el-form-item label="名额分配" prop="quotas">
|
||||||
|
<div class="quota-summary" v-if="formData.quotas.length > 0">
|
||||||
|
<span>总名额:<span class="quota-count"
|
||||||
|
style="margin-right: 0;">{{ totalQuota }}</span></span>
|
||||||
|
<span>已设置:<span class="quota-count" style="margin-right: 0;">{{ allocatedQuota }}</span> / {{ formData.quotas.length }}</span>
|
||||||
|
<span>未设置:<span class="quota-count quota-unset">{{ formData.quotas.length - allocatedQuota }}</span></span>
|
||||||
|
</div>
|
||||||
|
<el-table :data="formData.quotas"
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
max-height="450px"
|
||||||
|
>
|
||||||
|
<el-table-column label="序号" width="80" align="center" type="index"></el-table-column>
|
||||||
|
<el-table-column label="工会名称" prop="name"></el-table-column>
|
||||||
|
<el-table-column label="名额数量" width="200" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input-number v-model="scope.row.num" :min="0" :controls="false"
|
||||||
|
placeholder="请输入名额数量"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleQuotaChange(scope.row)">
|
||||||
|
</el-input-number>
|
||||||
|
<!-- <div class="quota-status">-->
|
||||||
|
<!-- <span v-if="isQuotaUnset(scope.row.num)" class="quota-unset-tip">未设置</span>-->
|
||||||
|
<!-- <span v-else-if="scope.row.num === 0" class="quota-zero-tip">已设置为零</span>-->
|
||||||
|
<!-- <span v-else class="quota-set-tip">已设置</span>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="quota-actions">
|
||||||
|
<el-button type="primary" size="mini" @click="setAllQuotas">批量设置名额</el-button>
|
||||||
|
<el-button size="mini" @click="clearAllQuotas">清除全部名额</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button @click="prevStep" v-if="activeStep > 0">
|
||||||
|
<i class="el-icon-arrow-left"></i> 上一步
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" @click="nextStep" v-if="activeStep < 2">
|
||||||
|
下一步 <i class="el-icon-arrow-right"></i>
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="submitting" v-if="activeStep === 2">
|
||||||
|
{{ submitting ? '提交中...' : '确定' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
// 日期验证器
|
||||||
|
const validateDateRange = (rule, value, callback) => {
|
||||||
|
const { signUpStartTime, signUpEndTime, startTime, endTime } = this.formData
|
||||||
|
|
||||||
|
if (rule.field === "signUpEndTime" && signUpStartTime && signUpEndTime) {
|
||||||
|
if (new Date(signUpEndTime) <= new Date(signUpStartTime)) {
|
||||||
|
callback(new Error("报名结束时间必须晚于报名开始时间"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.field === "startTime" && signUpEndTime && startTime) {
|
||||||
|
if (new Date(startTime) <= new Date(signUpEndTime)) {
|
||||||
|
callback(new Error("活动开始时间必须晚于报名结束时间"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.field === "endTime" && startTime && endTime) {
|
||||||
|
if (new Date(endTime) <= new Date(startTime)) {
|
||||||
|
callback(new Error("活动结束时间必须晚于活动开始时间"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批次验证器
|
||||||
|
const validateBatches = (rule, value, callback) => {
|
||||||
|
if (!value || value.length === 0) {
|
||||||
|
callback(new Error("请至少添加一个批次"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const emptyBatch = value.some((batch) => !batch.name || batch.name.trim() === "")
|
||||||
|
if (emptyBatch) {
|
||||||
|
callback(new Error("批次名称不能为空"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
activeStep: 0,
|
||||||
|
submitting: false,
|
||||||
|
formData: {
|
||||||
|
batches: [],
|
||||||
|
quotas: []
|
||||||
|
},
|
||||||
|
batchQuotaDialogVisible: false,
|
||||||
|
batchQuotaValue: 0,
|
||||||
|
formRules: {
|
||||||
|
name: [
|
||||||
|
{ required: true, message: "请输入活动名称", trigger: "blur" },
|
||||||
|
{ min: 1, max: 50, message: "长度在 1 到 50 个字符", trigger: "blur" }
|
||||||
|
],
|
||||||
|
signUpStartTime: [{ required: false, message: "请选择报名开始时间", trigger: "blur" }],
|
||||||
|
signUpEndTime: [
|
||||||
|
{ required: false, message: "请选择报名结束时间", trigger: "blur" },
|
||||||
|
{ validator: validateDateRange, trigger: "blur" }
|
||||||
|
],
|
||||||
|
startTime: [
|
||||||
|
{ required: false, message: "请选择活动开始时间", trigger: "blur" },
|
||||||
|
{ validator: validateDateRange, trigger: "blur" }
|
||||||
|
],
|
||||||
|
endTime: [
|
||||||
|
{ required: false, message: "请选择活动结束时间", trigger: "blur" },
|
||||||
|
{ validator: validateDateRange, trigger: "blur" }
|
||||||
|
],
|
||||||
|
notice: [{ required: true, message: "请输入通知内容", trigger: "blur" }],
|
||||||
|
batches: [{ validator: validateBatches, trigger: "change" }],
|
||||||
|
quotas: [{ required: true, type: "array", message: "请设置名额分配", trigger: "change" }]
|
||||||
|
},
|
||||||
|
unionOptions: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 计算总名额
|
||||||
|
totalQuota() {
|
||||||
|
return this.formData.quotas.reduce((sum, quota) => {
|
||||||
|
// 只计算已明确设置了数值的项
|
||||||
|
if (quota.num !== null && quota.num !== undefined) {
|
||||||
|
return sum + parseInt(quota.num || 0)
|
||||||
|
}
|
||||||
|
return sum
|
||||||
|
}, 0)
|
||||||
|
},
|
||||||
|
// 已分配名额数量(不包括未设置的)
|
||||||
|
allocatedQuota() {
|
||||||
|
return this.formData.quotas.filter((q) => q.num !== null && q.num !== undefined).length
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 检查名额是否未设置
|
||||||
|
isQuotaUnset(value) {
|
||||||
|
return value === null || value === undefined
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理名额变更
|
||||||
|
handleQuotaChange(row) {
|
||||||
|
// 确保值转换为数字或null
|
||||||
|
if (row.num === "" || row.num === undefined) {
|
||||||
|
row.num = null
|
||||||
|
} else {
|
||||||
|
row.num = parseInt(row.num)
|
||||||
|
}
|
||||||
|
this.validateQuotas()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 批量设置名额
|
||||||
|
setAllQuotas() {
|
||||||
|
this.$prompt("请输入要批量设置的名额数量", "批量设置", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
inputType: "number",
|
||||||
|
inputValidator: (value) => {
|
||||||
|
if (value === "") return "名额不能为空"
|
||||||
|
if (parseInt(value) < 0) return "名额不能为负数"
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(({ value }) => {
|
||||||
|
const num = parseInt(value)
|
||||||
|
this.formData.quotas.forEach((q) => {
|
||||||
|
q.num = num
|
||||||
|
})
|
||||||
|
this.validateQuotas()
|
||||||
|
this.$message.success("已将所有工会名额设置为" + num)
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 清除所有名额
|
||||||
|
clearAllQuotas() {
|
||||||
|
this.$confirm("确定要清除所有名额设置吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.formData.quotas.forEach((q) => {
|
||||||
|
q.num = undefined
|
||||||
|
})
|
||||||
|
this.validateQuotas()
|
||||||
|
this.$message.success("已清除所有名额设置")
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 打开表单
|
||||||
|
onOpen(id) {
|
||||||
|
this.visible = true
|
||||||
|
this.activeStep = 0
|
||||||
|
this.formData = {
|
||||||
|
batches: [],
|
||||||
|
quotas: []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
// 如果是编辑模式,加载数据
|
||||||
|
this.$axios.post("/platform/rest/activity/get", { id: id }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.formData = res.data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$businessTool.listUnion().then((res) => {
|
||||||
|
this.unionOptions = res
|
||||||
|
this.formData.quotas = res.map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
name: item.name,
|
||||||
|
code: item.code,
|
||||||
|
num: undefined // 默认名额为null(未设置)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 上一步
|
||||||
|
prevStep() {
|
||||||
|
if (this.activeStep > 0) {
|
||||||
|
this.activeStep--
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 下一步
|
||||||
|
nextStep() {
|
||||||
|
const formRefs = [this.$refs.form, this.$refs.batchForm, this.$refs.quotaForm]
|
||||||
|
const currentForm = formRefs[this.activeStep]
|
||||||
|
|
||||||
|
currentForm.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
if (this.activeStep < 2) {
|
||||||
|
this.activeStep++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$message.warning("请完成必填项")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 添加批次
|
||||||
|
addBatch() {
|
||||||
|
if (!this.formData.batches) {
|
||||||
|
this.formData.batches = []
|
||||||
|
}
|
||||||
|
this.formData.batches.push({
|
||||||
|
name: ""
|
||||||
|
})
|
||||||
|
this.validateBatchNames()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除批次
|
||||||
|
removeBatch(index) {
|
||||||
|
this.$confirm("确定要删除该批次吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.formData.batches.splice(index, 1)
|
||||||
|
this.validateBatchNames()
|
||||||
|
this.$message.success("删除成功")
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 验证批次名称
|
||||||
|
validateBatchNames() {
|
||||||
|
this.$refs.batchForm && this.$refs.batchForm.validateField("batches")
|
||||||
|
},
|
||||||
|
|
||||||
|
// 验证名额
|
||||||
|
validateQuotas() {
|
||||||
|
this.$refs.quotaForm && this.$refs.quotaForm.validateField("quotas")
|
||||||
|
},
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
submitForm() {
|
||||||
|
// 验证所有表单
|
||||||
|
Promise.all([
|
||||||
|
new Promise((resolve) => this.$refs.form.validate((valid) => resolve(valid))),
|
||||||
|
new Promise((resolve) => this.$refs.batchForm.validate((valid) => resolve(valid))),
|
||||||
|
new Promise((resolve) => this.$refs.quotaForm.validate((valid) => resolve(valid)))
|
||||||
|
]).then((results) => {
|
||||||
|
if (results.every((valid) => valid)) {
|
||||||
|
const invalidQuota = this.formData.quotas.some((q) => {
|
||||||
|
// 只检查已设置了值的,未设置的不检查
|
||||||
|
if (q.num !== null && q.num !== undefined) {
|
||||||
|
return q.num < 0 || !Number.isInteger(parseInt(q.num))
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if (invalidQuota) {
|
||||||
|
this.$message.error("请填写有效的名额数量(非负整数)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否所有名额都未设置
|
||||||
|
if (this.allocatedQuota === 0) {
|
||||||
|
this.$confirm("当前所有工会名额均未设置,是否继续提交?", "提示", {
|
||||||
|
confirmButtonText: "继续提交",
|
||||||
|
cancelButtonText: "返回修改",
|
||||||
|
type: "warning"
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.doSubmit()
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.doSubmit()
|
||||||
|
} else {
|
||||||
|
// 切换到第一个验证失败的步骤
|
||||||
|
if (!results[0]) this.activeStep = 0
|
||||||
|
else if (!results[1]) this.activeStep = 1
|
||||||
|
else if (!results[2]) this.activeStep = 2
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 执行提交操作
|
||||||
|
doSubmit() {
|
||||||
|
this.submitting = true
|
||||||
|
|
||||||
|
this.$axios
|
||||||
|
.post("/platform/rest/activity/" + (this.formData.id ? "update" : "insert"), { restAct: JSON.stringify(this.formData) })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.visible = false
|
||||||
|
this.$message.success(res.msg)
|
||||||
|
this.$emit("refresh")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.submitting = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: /*language=CSS*/ `
|
||||||
|
.form-container {
|
||||||
|
padding: 0 50px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch-container {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-batch {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 40px 0;
|
||||||
|
background-color: #fafafa;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-action {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data {
|
||||||
|
text-align: center;
|
||||||
|
color: #909399;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-summary {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: #f8f8f8;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-summary span {
|
||||||
|
margin-right: 20px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-count {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #409EFF;
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-unset {
|
||||||
|
color: #E6A23C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-status {
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-unset-tip {
|
||||||
|
color: #E6A23C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-zero-tip {
|
||||||
|
color: #F56C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-set-tip {
|
||||||
|
color: #67C23A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-actions {
|
||||||
|
margin-top: 15px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 按钮样式优化 */
|
||||||
|
.el-button [class*="el-icon-"] + span {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度:">
|
||||||
|
<el-date-picker placeholder="选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="名称:">
|
||||||
|
<el-input placeholder="请输入名称查询" clearable v-model="pageForm.searchKeyword"></el-input>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool>
|
||||||
|
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openAdd">新增</el-button>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column prop="name" label="名称" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column prop="signUpStartTime" label="报名开始时间"></el-table-column>
|
||||||
|
<el-table-column prop="signUpEndTime" label="报名结束时间"></el-table-column>
|
||||||
|
<el-table-column prop="startTime" label="开始时间"></el-table-column>
|
||||||
|
<el-table-column prop="endTime" label="结束时间"></el-table-column>
|
||||||
|
<el-table-column label="操作" width="200px" fixed="right">
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<form-edit ref="formEditRef" @refresh="doSearch"></form-edit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
<!--#include('formEdit.js'){}#-->
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"form-edit": formEdit
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openAdd() {
|
||||||
|
this.$refs.formEditRef.onOpen()
|
||||||
|
},
|
||||||
|
openEdit(row) {
|
||||||
|
this.$refs.formEditRef.onOpen(row.id)
|
||||||
|
},
|
||||||
|
onDelete(id) {
|
||||||
|
this.$confirm("您确定要删除吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
const { code, msg } = await this.$axios.post("/platform/rest/activity/delete", { id: id })
|
||||||
|
if (code === 0) {
|
||||||
|
this.$message.success(msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度:">
|
||||||
|
<el-date-picker placeholder="选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="名称:">
|
||||||
|
<el-input placeholder="请输入名称查询" clearable v-model="pageForm.searchKeyword"></el-input>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
year: new Date().getFullYear().toString(),
|
||||||
|
searchKeyword: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doSearch() {
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="年度:">
|
||||||
|
<el-date-picker placeholder="选择年度" type="year" style="width: 100%" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="名称:">
|
||||||
|
<el-input placeholder="请输入名称查询" clearable v-model="pageForm.searchKeyword"></el-input>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool></table-tool>
|
||||||
|
<el-table :data="tableData">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod"></el-table-column>
|
||||||
|
<el-table-column prop="name" label="名称" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column prop="signUpStartTime" label="报名开始时间">
|
||||||
|
<template slot-scope="{row}">{{ formatDate(row.signUpStartTime) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="signUpEndTime" label="报名结束时间">
|
||||||
|
<template slot-scope="{row}">{{ formatDate(row.signUpEndTime) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="startTime" label="开始时间">
|
||||||
|
<template slot-scope="{row}">{{ formatDate(row.startTime) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="endTime" label="结束时间">
|
||||||
|
<template slot-scope="{row}">{{ formatDate(row.endTime) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="status" label="状态" width="100">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-tag :type="getStatusType(row)" size="mini">{{ getStatusText(row) }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="200px" fixed="right">
|
||||||
|
<template slot-scope="{row}">
|
||||||
|
<el-button size="mini" type="primary" @click="openSign(row)">报名</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<sign-form ref="signFormRef" @refresh="doSearch"></sign-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
<!--#include("signForm.js"){}#-->
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"sign-form": signForm
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {
|
||||||
|
year: new Date().getFullYear().toString(),
|
||||||
|
searchKeyword: ""
|
||||||
|
},
|
||||||
|
now: new Date().getTime()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
doSearch() {
|
||||||
|
this.now = new Date().getTime()
|
||||||
|
this.pageData()
|
||||||
|
},
|
||||||
|
openSign(row) {
|
||||||
|
this.$refs.signFormRef.onOpen(row.id)
|
||||||
|
},
|
||||||
|
viewDetail(row) {},
|
||||||
|
// 格式化时间
|
||||||
|
formatDate(dateStr) {
|
||||||
|
if (!dateStr) return "-"
|
||||||
|
return dateStr.substring(0, 16).replace("T", " ")
|
||||||
|
},
|
||||||
|
// 获取活动状态
|
||||||
|
getStatusText(row) {
|
||||||
|
const now = this.now
|
||||||
|
const signUpStartTime = row.signUpStartTime ? new Date(row.signUpStartTime).getTime() : 0
|
||||||
|
const signUpEndTime = row.signUpEndTime ? new Date(row.signUpEndTime).getTime() : 0
|
||||||
|
const startTime = row.startTime ? new Date(row.startTime).getTime() : 0
|
||||||
|
const endTime = row.endTime ? new Date(row.endTime).getTime() : 0
|
||||||
|
|
||||||
|
if (now < signUpStartTime) {
|
||||||
|
return "未开始"
|
||||||
|
} else if (now >= signUpStartTime && now <= signUpEndTime) {
|
||||||
|
return "报名中"
|
||||||
|
} else if (now > signUpEndTime && now < startTime) {
|
||||||
|
return "报名结束"
|
||||||
|
} else if (now >= startTime && now <= endTime) {
|
||||||
|
return "活动中"
|
||||||
|
} else {
|
||||||
|
return "已结束"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取状态标签类型
|
||||||
|
getStatusType(row) {
|
||||||
|
const status = this.getStatusText(row)
|
||||||
|
switch (status) {
|
||||||
|
case "未开始":
|
||||||
|
return "info"
|
||||||
|
case "报名中":
|
||||||
|
return "success"
|
||||||
|
case "报名结束":
|
||||||
|
return "warning"
|
||||||
|
case "活动中":
|
||||||
|
return "primary"
|
||||||
|
case "已结束":
|
||||||
|
return ""
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.pageData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
@@ -0,0 +1,577 @@
|
|||||||
|
const signForm = {
|
||||||
|
template: /*language=HTML*/ `
|
||||||
|
<el-dialog title="活动报名" :visible.sync="visible" width="90%" :close-on-click-modal="false"
|
||||||
|
@open="handleDialogOpen" custom-class="sign-form-dialog">
|
||||||
|
<!-- 活动信息 -->
|
||||||
|
<el-card shadow="hover" class="mb-3">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span><i class="el-icon-date"></i> 活动信息</span>
|
||||||
|
<span class="float-right">
|
||||||
|
<el-tag size="small">{{ getStatusText }}</el-tag>
|
||||||
|
<el-tag v-if="quota > 0" size="small" type="info" class="ml-10">
|
||||||
|
名额: {{ quota }}人 / 剩余: {{ remainingQuota }}人
|
||||||
|
</el-tag>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="activity-info">
|
||||||
|
<div class="activity-title">{{ activityInfo.name || "-" }}</div>
|
||||||
|
<div class="activity-time">
|
||||||
|
<span><i class="el-icon-time"></i> 报名时间: {{ activityInfo.signUpStartTime || "-" }} ~ {{ activityInfo.signUpEndTime || "-" }}</span>
|
||||||
|
<span class="ml-20"><i class="el-icon-time"></i> 活动时间: {{ activityInfo.startTime || "-" }} ~ {{ activityInfo.endTime || "-" }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="activity-notice" v-if="activityInfo.notice">
|
||||||
|
<div class="notice-title"><i class="el-icon-bell"></i> 活动通知:</div>
|
||||||
|
<div class="notice-content" v-html="activityInfo.notice"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 表格区域 -->
|
||||||
|
<div class="tables-container">
|
||||||
|
<el-row :gutter="20" type="flex" style="align-items: center">
|
||||||
|
<!-- 左侧:可报名人员表格 -->
|
||||||
|
<el-col :span="11">
|
||||||
|
<div class="table-panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<div class="panel-title">可报名人员</div>
|
||||||
|
<div class="panel-filter">
|
||||||
|
<el-input
|
||||||
|
placeholder="搜索姓名/单位/手机号"
|
||||||
|
v-model="searchAvailable"
|
||||||
|
size="small"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
clearable
|
||||||
|
@input="filterAvailableUsers">
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
ref="availableTable"
|
||||||
|
:data="filteredAvailableUsers"
|
||||||
|
height="300"
|
||||||
|
border
|
||||||
|
v-loading="availableLoading"
|
||||||
|
@selection-change="handleAvailableSelectionChange">
|
||||||
|
<el-table-column type="selection" width="50"></el-table-column>
|
||||||
|
<el-table-column type="index" width="50" label="序号"></el-table-column>
|
||||||
|
<el-table-column prop="userName" label="姓名" width="80"></el-table-column>
|
||||||
|
<el-table-column prop="unitName" label="单位" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column prop="mobile" label="联系方式" width="120"></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="panel-footer">
|
||||||
|
<span class="panel-count">共 {{ filteredAvailableUsers.length }} 人可报名</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!-- 中间按钮区 -->
|
||||||
|
<el-col :span="2">
|
||||||
|
<div class="transfer-buttons">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-arrow-right"
|
||||||
|
circle
|
||||||
|
:disabled="selectedAvailable.length === 0"
|
||||||
|
@click="addToSelected"></el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-arrow-left"
|
||||||
|
circle
|
||||||
|
:disabled="selectedFromSelected.length === 0"
|
||||||
|
@click="removeFromSelected"></el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<!-- 右侧:已选人员表格 -->
|
||||||
|
<el-col :span="11">
|
||||||
|
<div class="table-panel">
|
||||||
|
<div class="panel-header">
|
||||||
|
<div class="panel-title">已选人员</div>
|
||||||
|
<div class="panel-filter">
|
||||||
|
<el-input
|
||||||
|
placeholder="搜索已选人员"
|
||||||
|
v-model="searchSelected"
|
||||||
|
size="small"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
clearable
|
||||||
|
@input="filterSelectedUsers">
|
||||||
|
</el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
ref="selectedTable"
|
||||||
|
:data="filteredSelectedUsers"
|
||||||
|
height="300"
|
||||||
|
border
|
||||||
|
@selection-change="handleSelectedSelectionChange">
|
||||||
|
<el-table-column type="selection" width="50"></el-table-column>
|
||||||
|
<el-table-column type="index" width="50" label="序号"></el-table-column>
|
||||||
|
<el-table-column prop="userName" label="姓名" width="80"></el-table-column>
|
||||||
|
<el-table-column prop="unitName" label="单位" width="120"></el-table-column>
|
||||||
|
<el-table-column prop="batch" label="批次" width="120">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-select v-model="scope.row.batch" size="small" placeholder="选择批次">
|
||||||
|
<el-option v-for="item in batchList"
|
||||||
|
:key="item"
|
||||||
|
:value="item">{{ item }}
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" min-width="120">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input v-model="scope.row.remark" placeholder="请输入备注" size="small"></el-input>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="panel-footer">
|
||||||
|
<span class="panel-count">已选 {{ selectedUsers.length }} 人</span>
|
||||||
|
<!-- <el-button size="small" type="primary" @click="submitSignUp" :loading="submitLoading" -->
|
||||||
|
<!-- :disabled="selectedUsers.length === 0">提交报名</el-button>-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="visible = false">关闭</el-button>
|
||||||
|
<el-button type="primary" @click="submitSignUp" :loading="submitLoading"
|
||||||
|
:disabled="selectedUsers.length === 0 || !isInSignUpTimeRange">提交报名</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false, // 控制对话框显示状态
|
||||||
|
activityId: null, // 当前活动ID
|
||||||
|
activityInfo: {}, // 当前活动信息
|
||||||
|
availableUsers: [], // 可报名人员列表
|
||||||
|
filteredAvailableUsers: [], // 过滤后的可报名人员列表
|
||||||
|
selectedUsers: [], // 已选择的用户列表
|
||||||
|
filteredSelectedUsers: [], // 过滤后的已选择用户列表
|
||||||
|
signedUsers: [], // 已报名人员列表 (内部使用)
|
||||||
|
searchAvailable: "", // 搜索可报名人员关键词
|
||||||
|
searchSelected: "", // 搜索已选人员关键词
|
||||||
|
selectedAvailable: [], // 从左侧表格选中的用户
|
||||||
|
selectedFromSelected: [], // 从右侧表格选中的用户
|
||||||
|
availableLoading: false, // 加载可报名人员状态
|
||||||
|
signedLoading: false, // 已报名用户加载状态
|
||||||
|
submitLoading: false, // 提交加载状态
|
||||||
|
quota: 0 // 报名名额限制
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
remainingQuota() {
|
||||||
|
if (!this.quota) return "不限"
|
||||||
|
const remaining = Math.max(0, this.quota - this.signedUsers.length)
|
||||||
|
return remaining
|
||||||
|
},
|
||||||
|
getStatusText() {
|
||||||
|
if (!this.activityInfo.startTime) return "未知状态"
|
||||||
|
|
||||||
|
const now = new Date().getTime()
|
||||||
|
const signUpStartTime = this.activityInfo.signUpStartTime ? new Date(this.activityInfo.signUpStartTime).getTime() : 0
|
||||||
|
const signUpEndTime = this.activityInfo.signUpEndTime ? new Date(this.activityInfo.signUpEndTime).getTime() : 0
|
||||||
|
const startTime = this.activityInfo.startTime ? new Date(this.activityInfo.startTime).getTime() : 0
|
||||||
|
const endTime = this.activityInfo.endTime ? new Date(this.activityInfo.endTime).getTime() : 0
|
||||||
|
|
||||||
|
if (now < signUpStartTime) {
|
||||||
|
return "未开始"
|
||||||
|
} else if (now >= signUpStartTime && now <= signUpEndTime) {
|
||||||
|
return "报名中"
|
||||||
|
} else if (now > signUpEndTime && now < startTime) {
|
||||||
|
return "报名结束"
|
||||||
|
} else if (now >= startTime && now <= endTime) {
|
||||||
|
return "活动中"
|
||||||
|
} else {
|
||||||
|
return "已结束"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
batchList() {
|
||||||
|
if (this.activityInfo && this.activityInfo.batches) {
|
||||||
|
return this.activityInfo.batches.map((item) => item.name)
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
},
|
||||||
|
isInSignUpTimeRange() {
|
||||||
|
if (!this.activityInfo.signUpStartTime || !this.activityInfo.signUpEndTime) return false
|
||||||
|
|
||||||
|
const now = new Date().getTime()
|
||||||
|
const signUpStartTime = new Date(this.activityInfo.signUpStartTime).getTime()
|
||||||
|
const signUpEndTime = new Date(this.activityInfo.signUpEndTime).getTime()
|
||||||
|
|
||||||
|
return now >= signUpStartTime && now <= signUpEndTime
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onOpen(id) {
|
||||||
|
this.visible = true
|
||||||
|
this.activityId = id
|
||||||
|
this.searchAvailable = ""
|
||||||
|
this.searchSelected = ""
|
||||||
|
this.selectedUsers = []
|
||||||
|
this.filteredSelectedUsers = []
|
||||||
|
this.selectedAvailable = []
|
||||||
|
this.selectedFromSelected = []
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDialogOpen() {
|
||||||
|
this.getActivityInfo()
|
||||||
|
this.getQuota(this.activityId)
|
||||||
|
this.loadAllUserData(this.activityId)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 一次性加载所有用户数据
|
||||||
|
async loadAllUserData(id) {
|
||||||
|
this.availableLoading = true
|
||||||
|
this.signedLoading = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 先获取已报名人员
|
||||||
|
const signedResponse = await this.$axios.post("/platform/rest/branchUnionSignUp/listSignUser", { activityId: id })
|
||||||
|
if (signedResponse.code === 0) {
|
||||||
|
this.signedUsers = Array.isArray(signedResponse.data) ? signedResponse.data : []
|
||||||
|
|
||||||
|
// 将已报名人员添加到已选择列表
|
||||||
|
if (this.signedUsers.length > 0) {
|
||||||
|
this.signedUsers.forEach((user) => {
|
||||||
|
// 注意:已报名人员的数据结构与可报名人员不同
|
||||||
|
this.selectedUsers.push({
|
||||||
|
id: user.userId, // 使用userId作为id
|
||||||
|
loginName: user.loginName,
|
||||||
|
userName: user.userName,
|
||||||
|
unitId: user.unitId,
|
||||||
|
unitName: user.unitName,
|
||||||
|
unionId: user.unionId,
|
||||||
|
unionName: user.unionName,
|
||||||
|
batch: user.batch || (this.batchList.length > 0 ? this.batchList[0] : ""),
|
||||||
|
remark: user.remark || "",
|
||||||
|
// 保存原始记录ID用于后续操作
|
||||||
|
signUpRecordId: user.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再获取可报名人员列表
|
||||||
|
const availableResponse = await this.$axios.post("/platform/rest/branchUnionSignUp/listCanSignUser", { activityId: id })
|
||||||
|
if (availableResponse.code === 0 && Array.isArray(availableResponse.data)) {
|
||||||
|
this.availableUsers = availableResponse.data.map((user) => ({
|
||||||
|
...user,
|
||||||
|
remark: "",
|
||||||
|
batch: this.batchList.length > 0 ? this.batchList[0] : "",
|
||||||
|
files: []
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新过滤后的列表
|
||||||
|
this.filterSelectedUsers()
|
||||||
|
this.filterAvailableUsers()
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error("获取用户数据失败")
|
||||||
|
} finally {
|
||||||
|
this.availableLoading = false
|
||||||
|
this.signedLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取活动信息
|
||||||
|
async getActivityInfo() {
|
||||||
|
try {
|
||||||
|
const { code, data } = await this.$axios.post("/platform/rest/common/actInfo", { id: this.activityId })
|
||||||
|
if (code === 0 && data) {
|
||||||
|
this.activityInfo = data
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error("获取活动信息失败")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取名额限制
|
||||||
|
async getQuota(id) {
|
||||||
|
try {
|
||||||
|
const { code, data } = await this.$axios.post("/platform/rest/branchUnionSignUp/quota", { activityId: id })
|
||||||
|
if (code === 0) {
|
||||||
|
this.quota = data
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error("获取名额限制失败")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 过滤可报名人员
|
||||||
|
filterAvailableUsers() {
|
||||||
|
if (!this.searchAvailable) {
|
||||||
|
// 过滤掉已选择的用户
|
||||||
|
this.filteredAvailableUsers = this.availableUsers.filter((user) => !this.selectedUsers.some((selected) => selected.id === user.id))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = this.searchAvailable.toLowerCase()
|
||||||
|
this.filteredAvailableUsers = this.availableUsers.filter(
|
||||||
|
(user) =>
|
||||||
|
!this.selectedUsers.some((selected) => selected.id === user.id) &&
|
||||||
|
((user.userName && user.userName.toLowerCase().includes(search)) ||
|
||||||
|
(user.unitName && user.unitName.toLowerCase().includes(search)) ||
|
||||||
|
(user.mobile && user.mobile.includes(search)))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 过滤已选人员
|
||||||
|
filterSelectedUsers() {
|
||||||
|
if (!this.searchSelected) {
|
||||||
|
this.filteredSelectedUsers = [...this.selectedUsers]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = this.searchSelected.toLowerCase()
|
||||||
|
this.filteredSelectedUsers = this.selectedUsers.filter(
|
||||||
|
(user) =>
|
||||||
|
(user.userName && user.userName.toLowerCase().includes(search)) ||
|
||||||
|
(user.unitName && user.unitName.toLowerCase().includes(search)) ||
|
||||||
|
(user.mobile && user.mobile.includes(search))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理左侧表格选择变化
|
||||||
|
handleAvailableSelectionChange(val) {
|
||||||
|
this.selectedAvailable = val
|
||||||
|
},
|
||||||
|
|
||||||
|
// 处理右侧表格选择变化
|
||||||
|
handleSelectedSelectionChange(val) {
|
||||||
|
this.selectedFromSelected = val
|
||||||
|
},
|
||||||
|
|
||||||
|
// 添加到已选
|
||||||
|
addToSelected() {
|
||||||
|
if (this.selectedAvailable.length === 0) return
|
||||||
|
|
||||||
|
// 检查名额
|
||||||
|
if (this.quota > 0) {
|
||||||
|
const totalAfterAdd = this.selectedUsers.length + this.selectedAvailable.length
|
||||||
|
if (totalAfterAdd > this.quota) {
|
||||||
|
this.$message.warning("选择人数超过名额限制,当前名额限制: " + this.quota + "人")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加选中的用户到已选列表
|
||||||
|
this.selectedAvailable.forEach((user) => {
|
||||||
|
if (!this.selectedUsers.some((selected) => selected.id === user.id)) {
|
||||||
|
this.selectedUsers.push({
|
||||||
|
...user,
|
||||||
|
batch: this.batchList.length > 0 ? this.batchList[0] : "",
|
||||||
|
remark: ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更新过滤后的列表
|
||||||
|
this.filterSelectedUsers()
|
||||||
|
this.filterAvailableUsers()
|
||||||
|
|
||||||
|
// 清空选择
|
||||||
|
this.$refs.availableTable.clearSelection()
|
||||||
|
this.selectedAvailable = []
|
||||||
|
},
|
||||||
|
|
||||||
|
// 从已选中移除
|
||||||
|
removeFromSelected() {
|
||||||
|
if (this.selectedFromSelected.length === 0) return
|
||||||
|
|
||||||
|
// 移除选中的用户
|
||||||
|
this.selectedFromSelected.forEach((user) => {
|
||||||
|
const index = this.selectedUsers.findIndex((item) => item.id === user.id)
|
||||||
|
if (index !== -1) {
|
||||||
|
this.selectedUsers.splice(index, 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更新过滤后的列表
|
||||||
|
this.filterSelectedUsers()
|
||||||
|
this.filterAvailableUsers()
|
||||||
|
|
||||||
|
// 清空选择
|
||||||
|
this.$refs.selectedTable.clearSelection()
|
||||||
|
this.selectedFromSelected = []
|
||||||
|
},
|
||||||
|
|
||||||
|
// 提交报名
|
||||||
|
async submitSignUp() {
|
||||||
|
if (this.selectedUsers.length === 0) {
|
||||||
|
this.$message.warning("请选择要报名的人员")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.submitLoading = true
|
||||||
|
|
||||||
|
// 再提交新的报名信息
|
||||||
|
const signUpData = this.selectedUsers.map((user) => ({
|
||||||
|
restActId: this.activityId,
|
||||||
|
userId: user.id,
|
||||||
|
loginName: user.loginName,
|
||||||
|
userName: user.userName,
|
||||||
|
unionId: user.unionId || "",
|
||||||
|
unionName: user.unionName || "",
|
||||||
|
unitId: user.unitId || "",
|
||||||
|
unitName: user.unitName || "",
|
||||||
|
batch: user.batch || "",
|
||||||
|
remark: user.remark || "",
|
||||||
|
files: user.files || []
|
||||||
|
}))
|
||||||
|
|
||||||
|
const { code, msg } = await this.$axios.post("/platform/rest/branchUnionSignUp/signUp", {
|
||||||
|
sign: JSON.stringify(signUpData),
|
||||||
|
activityId: this.activityId
|
||||||
|
})
|
||||||
|
|
||||||
|
if (code === 0) {
|
||||||
|
this.$message.success("报名成功")
|
||||||
|
// 更新已报名人员列表
|
||||||
|
const signedResponse = await this.$axios.post("/platform/rest/branchUnionSignUp/listSignUser", { activityId: this.activityId })
|
||||||
|
if (signedResponse.code === 0) {
|
||||||
|
this.signedUsers = Array.isArray(signedResponse.data) ? signedResponse.data : []
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$message.error(msg || "报名失败")
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error("操作失败")
|
||||||
|
} finally {
|
||||||
|
this.submitLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: /*language=CSS*/ `
|
||||||
|
.sign-form-dialog .el-dialog__body {
|
||||||
|
padding: 15px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-3 {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-10 {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-20 {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-info {
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-time {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-notice {
|
||||||
|
margin-top: 10px;
|
||||||
|
border-top: 1px dashed #ebeef5;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-content {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
background-color: #409EFF;
|
||||||
|
color: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tables-container {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-panel {
|
||||||
|
border: 1px solid #EBEEF5;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-header {
|
||||||
|
background-color: #F5F7FA;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-bottom: 1px solid #EBEEF5;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-filter {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-footer {
|
||||||
|
background-color: #F5F7FA;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-top: 1px solid #EBEEF5;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-count {
|
||||||
|
color: #606266;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-buttons {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transfer-buttons button{
|
||||||
|
margin: 0!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
`
|
||||||
|
}
|
||||||
@@ -0,0 +1,749 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
<style>
|
||||||
|
.dashboard-title {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #217050;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-cards {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-charts {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statistic-card .card-header {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statistic-card .card-content {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statistic-card .statistic-value {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #217050;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statistic-card .statistic-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-card .card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container {
|
||||||
|
height: 300px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-container-large {
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-slider-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-slider-container .el-slider {
|
||||||
|
margin-right: 15px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-display {
|
||||||
|
width: 70px;
|
||||||
|
text-align: center;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-container {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span class="dashboard-title">单身教工统计分析</span>
|
||||||
|
<el-divider></el-divider>
|
||||||
|
</div>
|
||||||
|
<el-form :inline="true" class="filter-container">
|
||||||
|
<el-form-item label="工会">
|
||||||
|
<el-select v-model="filterForm.unionId" placeholder="选择工会" clearable>
|
||||||
|
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="性别">
|
||||||
|
<el-select v-model="filterForm.sex" placeholder="选择性别" clearable>
|
||||||
|
<el-option label="男" value="男"></el-option>
|
||||||
|
<el-option label="女" value="女"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="fetchData">筛选</el-button>
|
||||||
|
<el-button @click="resetFilter">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 总体统计卡片 -->
|
||||||
|
<el-row :gutter="20" class="dashboard-cards">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card shadow="hover" class="statistic-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<i class="el-icon-user"></i>
|
||||||
|
单身教工总人数
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="statistic-value">{{statistics.totalCount || 0}}</div>
|
||||||
|
<div class="statistic-footer">
|
||||||
|
<span>男:{{statistics.maleCount || 0}}</span>
|
||||||
|
<span>女:{{statistics.femaleCount || 0}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card shadow="hover" class="statistic-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<i class="el-icon-school"></i>
|
||||||
|
平均年龄
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="statistic-value">{{statistics.averageAge || 0}}</div>
|
||||||
|
<div class="statistic-footer">
|
||||||
|
<span>最小:{{statistics.minAge || 0}}岁</span>
|
||||||
|
<span>最大:{{statistics.maxAge || 0}}岁</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card shadow="hover" class="statistic-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<i class="el-icon-reading"></i>
|
||||||
|
高学历占比
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="statistic-value">{{statistics.highEduPercent || '0%'}}</div>
|
||||||
|
<div class="statistic-footer">
|
||||||
|
<span>硕士及以上人数:{{statistics.highEduCount || 0}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card shadow="hover" class="statistic-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<i class="el-icon-office-building"></i>
|
||||||
|
工会数量
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="statistic-value">{{statistics.unionCount || 0}}</div>
|
||||||
|
<div class="statistic-footer">
|
||||||
|
<span>单位数量:{{statistics.unitCount || 0}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 图表区域 -->
|
||||||
|
<el-row :gutter="20" class="dashboard-charts">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<span>性别分布</span>
|
||||||
|
<el-radio-group v-model="chartTypes.gender" size="mini" @change="renderGenderChart">
|
||||||
|
<el-radio-button label="pie">饼图</el-radio-button>
|
||||||
|
<el-radio-button label="column">柱状图</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div id="genderChart" class="chart-container"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<span>年龄分布</span>
|
||||||
|
<el-radio-group v-model="chartTypes.age" size="mini" @change="renderAgeChart">
|
||||||
|
<el-radio-button label="column">柱状图</el-radio-button>
|
||||||
|
<el-radio-button label="line">折线图</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div id="ageChart" class="chart-container"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="dashboard-charts">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<span>学历分布</span>
|
||||||
|
<el-radio-group v-model="chartTypes.education" size="mini" @change="renderEducationChart">
|
||||||
|
<el-radio-button label="pie">饼图</el-radio-button>
|
||||||
|
<el-radio-button label="column">柱状图</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div id="educationChart" class="chart-container"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<span>收入情况分布</span>
|
||||||
|
<el-radio-group v-model="chartTypes.income" size="mini" @change="renderIncomeChart">
|
||||||
|
<el-radio-button label="pie">饼图</el-radio-button>
|
||||||
|
<el-radio-button label="column">柱状图</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div id="incomeChart" class="chart-container"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="dashboard-charts">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-card shadow="hover" class="chart-card">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<span>单位及工会分布</span>
|
||||||
|
<el-radio-group v-model="chartTypes.unit" size="mini" @change="renderUnitChart">
|
||||||
|
<el-radio-button label="bar">条形图</el-radio-button>
|
||||||
|
<el-radio-button label="treemap">矩形树图</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div id="unitChart" class="chart-container chart-container-large"></div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pageForm: {},
|
||||||
|
filterForm: {
|
||||||
|
unionId: "",
|
||||||
|
sex: "",
|
||||||
|
age: [20, 65]
|
||||||
|
},
|
||||||
|
unionOptions: [],
|
||||||
|
chartTypes: {
|
||||||
|
gender: "pie",
|
||||||
|
age: "column",
|
||||||
|
education: "pie",
|
||||||
|
income: "column",
|
||||||
|
unit: "bar"
|
||||||
|
},
|
||||||
|
charts: {},
|
||||||
|
teacherData: [],
|
||||||
|
statistics: {
|
||||||
|
totalCount: 0,
|
||||||
|
maleCount: 0,
|
||||||
|
femaleCount: 0,
|
||||||
|
averageAge: 0,
|
||||||
|
minAge: 0,
|
||||||
|
maxAge: 0,
|
||||||
|
highEduCount: 0,
|
||||||
|
highEduPercent: "0%",
|
||||||
|
unionCount: 0,
|
||||||
|
unitCount: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchData() {
|
||||||
|
this.$axios.post("/platform/singleTeacher/chart/list", this.filterForm).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.teacherData = res.data
|
||||||
|
this.processData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
resetFilter() {
|
||||||
|
this.filterForm = {
|
||||||
|
unionId: "",
|
||||||
|
sex: "",
|
||||||
|
age: [20, 65]
|
||||||
|
}
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
|
||||||
|
processData() {
|
||||||
|
this.calculateStatistics()
|
||||||
|
this.renderCharts()
|
||||||
|
},
|
||||||
|
|
||||||
|
calculateStatistics() {
|
||||||
|
const data = this.teacherData
|
||||||
|
|
||||||
|
// 总数统计
|
||||||
|
this.statistics.totalCount = data.length
|
||||||
|
|
||||||
|
// 性别统计
|
||||||
|
this.statistics.maleCount = data.filter((item) => item.sex === "男").length
|
||||||
|
this.statistics.femaleCount = data.filter((item) => item.sex === "女").length
|
||||||
|
|
||||||
|
// 年龄统计
|
||||||
|
const ages = data.map((item) => this.calculateAge(item.birthday)).filter((age) => age !== null)
|
||||||
|
if (ages.length > 0) {
|
||||||
|
this.statistics.averageAge = Math.round(ages.reduce((a, b) => a + b, 0) / ages.length)
|
||||||
|
this.statistics.minAge = Math.min(...ages)
|
||||||
|
this.statistics.maxAge = Math.max(...ages)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 学历统计
|
||||||
|
const highEdu = ["硕士研究生毕业", "博士研究生毕业"]
|
||||||
|
this.statistics.highEduCount = data.filter((item) => highEdu.includes(item.education)).length
|
||||||
|
this.statistics.highEduPercent = data.length > 0 ? Math.round((this.statistics.highEduCount / data.length) * 100) + "%" : "0%"
|
||||||
|
|
||||||
|
// 工会和单位统计
|
||||||
|
const unions = new Set(data.map((item) => item.unionName))
|
||||||
|
const units = new Set(data.map((item) => item.unitName))
|
||||||
|
this.statistics.unionCount = unions.size
|
||||||
|
this.statistics.unitCount = units.size
|
||||||
|
},
|
||||||
|
|
||||||
|
renderCharts() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.renderGenderChart()
|
||||||
|
this.renderAgeChart()
|
||||||
|
this.renderEducationChart()
|
||||||
|
this.renderIncomeChart()
|
||||||
|
this.renderUnitChart()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 计算年龄
|
||||||
|
calculateAge(birthday) {
|
||||||
|
if (!birthday) return null
|
||||||
|
const birthDate = new Date(birthday)
|
||||||
|
const today = new Date()
|
||||||
|
let age = today.getFullYear() - birthDate.getFullYear()
|
||||||
|
const m = today.getMonth() - birthDate.getMonth()
|
||||||
|
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
|
||||||
|
age--
|
||||||
|
}
|
||||||
|
return age
|
||||||
|
},
|
||||||
|
|
||||||
|
// 性别分布图
|
||||||
|
renderGenderChart() {
|
||||||
|
const container = document.getElementById("genderChart")
|
||||||
|
if (!container) return
|
||||||
|
|
||||||
|
if (this.charts.genderChart) {
|
||||||
|
this.charts.genderChart.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
const genderData = this.getGenderDistribution()
|
||||||
|
|
||||||
|
if (this.chartTypes.gender === "pie") {
|
||||||
|
this.charts.genderChart = new G2Plot.Pie("genderChart", {
|
||||||
|
data: genderData,
|
||||||
|
angleField: "value",
|
||||||
|
colorField: "type",
|
||||||
|
radius: 0.8,
|
||||||
|
label: {
|
||||||
|
type: "outer",
|
||||||
|
content: "{name}: {percentage}"
|
||||||
|
},
|
||||||
|
legend: { position: "right" },
|
||||||
|
interactions: [{ type: "element-active" }],
|
||||||
|
color: ["#217050", "#5fad85"]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.charts.genderChart = new G2Plot.Column("genderChart", {
|
||||||
|
data: genderData,
|
||||||
|
xField: "type",
|
||||||
|
yField: "value",
|
||||||
|
label: {
|
||||||
|
position: "top"
|
||||||
|
},
|
||||||
|
color: ({ type }) => {
|
||||||
|
if (type === "男") return "#217050"
|
||||||
|
return "#5fad85"
|
||||||
|
},
|
||||||
|
columnWidthRatio: 0.4
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.charts.genderChart.render()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 年龄分布图
|
||||||
|
renderAgeChart() {
|
||||||
|
const container = document.getElementById("ageChart")
|
||||||
|
if (!container) return
|
||||||
|
|
||||||
|
if (this.charts.ageChart) {
|
||||||
|
this.charts.ageChart.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
const ageData = this.getAgeDistribution()
|
||||||
|
|
||||||
|
const commonConfig = {
|
||||||
|
data: ageData,
|
||||||
|
xField: "range",
|
||||||
|
yField: "count",
|
||||||
|
meta: {
|
||||||
|
range: { alias: "年龄段" },
|
||||||
|
count: { alias: "人数" }
|
||||||
|
},
|
||||||
|
color: "#217050",
|
||||||
|
xAxis: {
|
||||||
|
label: {
|
||||||
|
autoHide: false,
|
||||||
|
autoRotate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.chartTypes.age === "column") {
|
||||||
|
this.charts.ageChart = new G2Plot.Column("ageChart", {
|
||||||
|
...commonConfig,
|
||||||
|
label: {
|
||||||
|
position: "top"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.charts.ageChart = new G2Plot.Line("ageChart", {
|
||||||
|
...commonConfig,
|
||||||
|
smooth: true,
|
||||||
|
point: {
|
||||||
|
size: 5,
|
||||||
|
shape: "diamond"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.charts.ageChart.render()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 学历分布图
|
||||||
|
renderEducationChart() {
|
||||||
|
const container = document.getElementById("educationChart")
|
||||||
|
if (!container) return
|
||||||
|
|
||||||
|
if (this.charts.educationChart) {
|
||||||
|
this.charts.educationChart.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
const educationData = this.getEducationDistribution()
|
||||||
|
|
||||||
|
if (this.chartTypes.education === "pie") {
|
||||||
|
this.charts.educationChart = new G2Plot.Pie("educationChart", {
|
||||||
|
data: educationData,
|
||||||
|
angleField: "count",
|
||||||
|
colorField: "education",
|
||||||
|
radius: 0.8,
|
||||||
|
label: {
|
||||||
|
type: "outer",
|
||||||
|
content: "{name}: {percentage}"
|
||||||
|
},
|
||||||
|
interactions: [{ type: "element-active" }],
|
||||||
|
legend: { position: "right" },
|
||||||
|
color: ["#217050", "#5fad85", "#89d0af", "#c2e6d4", "#136343"]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.charts.educationChart = new G2Plot.Column("educationChart", {
|
||||||
|
data: educationData,
|
||||||
|
xField: "education",
|
||||||
|
yField: "count",
|
||||||
|
label: {
|
||||||
|
position: "top"
|
||||||
|
},
|
||||||
|
color: "#217050",
|
||||||
|
xAxis: {
|
||||||
|
label: {
|
||||||
|
autoHide: false,
|
||||||
|
autoRotate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.charts.educationChart.render()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 收入分布图
|
||||||
|
renderIncomeChart() {
|
||||||
|
const container = document.getElementById("incomeChart")
|
||||||
|
if (!container) return
|
||||||
|
|
||||||
|
if (this.charts.incomeChart) {
|
||||||
|
this.charts.incomeChart.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
const incomeData = this.getIncomeDistribution()
|
||||||
|
|
||||||
|
if (this.chartTypes.income === "pie") {
|
||||||
|
this.charts.incomeChart = new G2Plot.Pie("incomeChart", {
|
||||||
|
data: incomeData,
|
||||||
|
angleField: "count",
|
||||||
|
colorField: "income",
|
||||||
|
radius: 0.8,
|
||||||
|
label: {
|
||||||
|
type: "outer",
|
||||||
|
content: "{name}: {percentage}"
|
||||||
|
},
|
||||||
|
interactions: [{ type: "element-active" }],
|
||||||
|
legend: { position: "right" },
|
||||||
|
color: ["#217050", "#5fad85", "#89d0af", "#c2e6d4", "#136343"]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.charts.incomeChart = new G2Plot.Column("incomeChart", {
|
||||||
|
data: incomeData,
|
||||||
|
xField: "income",
|
||||||
|
yField: "count",
|
||||||
|
label: {
|
||||||
|
position: "top"
|
||||||
|
},
|
||||||
|
color: "#217050",
|
||||||
|
xAxis: {
|
||||||
|
label: {
|
||||||
|
autoHide: false,
|
||||||
|
autoRotate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.charts.incomeChart.render()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 单位工会分布图
|
||||||
|
renderUnitChart() {
|
||||||
|
const container = document.getElementById("unitChart")
|
||||||
|
if (!container) return
|
||||||
|
|
||||||
|
if (this.charts.unitChart) {
|
||||||
|
this.charts.unitChart.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
const unitData = this.getUnitDistribution()
|
||||||
|
|
||||||
|
if (this.chartTypes.unit === "bar") {
|
||||||
|
this.charts.unitChart = new G2Plot.Bar("unitChart", {
|
||||||
|
data: unitData,
|
||||||
|
xField: "count",
|
||||||
|
yField: "unit",
|
||||||
|
seriesField: "unionName",
|
||||||
|
isStack: true,
|
||||||
|
legend: {
|
||||||
|
position: "top-right"
|
||||||
|
},
|
||||||
|
color: ["#217050", "#5fad85", "#89d0af", "#c2e6d4", "#136343"],
|
||||||
|
label: {
|
||||||
|
position: "middle",
|
||||||
|
layout: [{ type: "interval-adjust-position" }]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const processedData = this.getTreemapData()
|
||||||
|
this.charts.unitChart = new G2Plot.Treemap("unitChart", {
|
||||||
|
data: processedData,
|
||||||
|
colorField: "value",
|
||||||
|
legend: false,
|
||||||
|
color: ["#e8f5e9", "#c2e6d4", "#89d0af", "#5fad85", "#217050"]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.charts.unitChart.render()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取性别分布数据
|
||||||
|
getGenderDistribution() {
|
||||||
|
const data = this.teacherData
|
||||||
|
const genderCount = {}
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
const gender = item.sex || "未知"
|
||||||
|
genderCount[gender] = (genderCount[gender] || 0) + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
return Object.keys(genderCount).map((key) => ({
|
||||||
|
type: key,
|
||||||
|
value: genderCount[key]
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取年龄分布数据
|
||||||
|
getAgeDistribution() {
|
||||||
|
const data = this.teacherData
|
||||||
|
const ageRanges = {
|
||||||
|
"25岁以下": 0,
|
||||||
|
"26-30岁": 0,
|
||||||
|
"31-35岁": 0,
|
||||||
|
"36-40岁": 0,
|
||||||
|
"41-45岁": 0,
|
||||||
|
"46-50岁": 0,
|
||||||
|
"51岁以上": 0
|
||||||
|
}
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
if (!item.birthday) return
|
||||||
|
|
||||||
|
const age = this.calculateAge(item.birthday)
|
||||||
|
|
||||||
|
if (age <= 25) ageRanges["25岁以下"]++
|
||||||
|
else if (age <= 30) ageRanges["26-30岁"]++
|
||||||
|
else if (age <= 35) ageRanges["31-35岁"]++
|
||||||
|
else if (age <= 40) ageRanges["36-40岁"]++
|
||||||
|
else if (age <= 45) ageRanges["41-45岁"]++
|
||||||
|
else if (age <= 50) ageRanges["46-50岁"]++
|
||||||
|
else ageRanges["51岁以上"]++
|
||||||
|
})
|
||||||
|
|
||||||
|
return Object.keys(ageRanges).map((key) => ({
|
||||||
|
range: key,
|
||||||
|
count: ageRanges[key]
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取学历分布数据
|
||||||
|
getEducationDistribution() {
|
||||||
|
const data = this.teacherData
|
||||||
|
const educationCount = {}
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
const education = item.education || "未知"
|
||||||
|
educationCount[education] = (educationCount[education] || 0) + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
return Object.keys(educationCount).map((key) => ({
|
||||||
|
education: key,
|
||||||
|
count: educationCount[key]
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取收入分布数据
|
||||||
|
getIncomeDistribution() {
|
||||||
|
const data = this.teacherData
|
||||||
|
const incomeCount = {}
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
const income = item.monthlyIncome || "未知"
|
||||||
|
incomeCount[income] = (incomeCount[income] || 0) + 1
|
||||||
|
})
|
||||||
|
|
||||||
|
return Object.keys(incomeCount).map((key) => ({
|
||||||
|
income: key,
|
||||||
|
count: incomeCount[key]
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取单位分布数据
|
||||||
|
getUnitDistribution() {
|
||||||
|
const data = this.teacherData
|
||||||
|
const unitData = []
|
||||||
|
|
||||||
|
data.forEach((item) => {
|
||||||
|
const unit = item.unitName || "未知单位"
|
||||||
|
const union = item.unionName || "未知工会"
|
||||||
|
|
||||||
|
const existingUnit = unitData.find((u) => u.unit === unit && u.unionName === union)
|
||||||
|
|
||||||
|
if (existingUnit) {
|
||||||
|
existingUnit.count++
|
||||||
|
} else {
|
||||||
|
unitData.push({
|
||||||
|
unit,
|
||||||
|
unionName: union,
|
||||||
|
count: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return unitData.sort((a, b) => a.count - b.count)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 矩形树图数据处理
|
||||||
|
getTreemapData() {
|
||||||
|
const data = this.teacherData
|
||||||
|
const unionMap = {}
|
||||||
|
|
||||||
|
// 按工会和单位分组统计
|
||||||
|
data.forEach((item) => {
|
||||||
|
const union = item.unionName || "未知工会"
|
||||||
|
const unit = item.unitName || "未知单位"
|
||||||
|
|
||||||
|
if (!unionMap[union]) {
|
||||||
|
unionMap[union] = {
|
||||||
|
name: union,
|
||||||
|
value: 0,
|
||||||
|
children: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unionMap[union].value++
|
||||||
|
|
||||||
|
if (!unionMap[union].children[unit]) {
|
||||||
|
unionMap[union].children[unit] = {
|
||||||
|
name: unit,
|
||||||
|
value: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unionMap[union].children[unit].value++
|
||||||
|
})
|
||||||
|
|
||||||
|
// 转换为G2Plot需要的格式
|
||||||
|
const result = {
|
||||||
|
name: "root",
|
||||||
|
children: []
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(unionMap).forEach((union) => {
|
||||||
|
const unionData = unionMap[union]
|
||||||
|
const children = []
|
||||||
|
|
||||||
|
Object.keys(unionData.children).forEach((unit) => {
|
||||||
|
children.push({
|
||||||
|
name: unit,
|
||||||
|
value: unionData.children[unit].value
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
result.children.push({
|
||||||
|
name: union,
|
||||||
|
value: unionData.value,
|
||||||
|
children
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
|
||||||
|
this.fetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
const formEdit = {
|
||||||
|
template: /*language=HTML*/ `
|
||||||
|
<el-dialog :title="formData.id ? '编辑单身教工信息' : '新增单身教工信息'" :visible.sync="visible" width="65%"
|
||||||
|
append-to-body>
|
||||||
|
<el-form ref="form" :model="formData" :rules="rules" label-width="120px" size="small"
|
||||||
|
class="single-teacher-form">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="选择用户" prop="userId" v-if="!formData.id">
|
||||||
|
<el-select
|
||||||
|
v-model="formData.userId"
|
||||||
|
filterable
|
||||||
|
remote
|
||||||
|
reserve-keyword
|
||||||
|
placeholder="请输入关键词搜索用户"
|
||||||
|
:remote-method="remoteSearchUsers"
|
||||||
|
:loading="userSearchLoading"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleUserChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in userOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.username + '(' + item.loginname + ')'"
|
||||||
|
:value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户信息" v-else>
|
||||||
|
<el-input v-model="formData.username" disabled></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="联系方式" prop="mobile">
|
||||||
|
<el-input v-model="formData.mobile" placeholder="请输入联系方式"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="出生年月" prop="birthday">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.birthday"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 100%">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="身高(cm)" prop="height">
|
||||||
|
<el-input v-model="formData.height" placeholder="请输入身高"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="籍贯" prop="nativePlace">
|
||||||
|
<el-input v-model="formData.nativePlace" placeholder="请输入籍贯"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="学历" prop="education">
|
||||||
|
<dict-select style="width: 100%" placeholder="请选择学历" v-model="formData.education"
|
||||||
|
code="USER_EDUCATION"></dict-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="婚姻状况" prop="maritalStatus">
|
||||||
|
<el-select v-model="formData.maritalStatus" placeholder="请选择婚姻状况"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option label="未婚" value="未婚"></el-option>
|
||||||
|
<el-option label="离婚" value="离婚"></el-option>
|
||||||
|
<el-option label="丧偶" value="丧偶"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="月收入" prop="monthlyIncome">
|
||||||
|
<el-select v-model="formData.monthlyIncome" placeholder="请选择月收入范围"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option label="5000以下" value="5000以下"></el-option>
|
||||||
|
<el-option label="5000-8000" value="5000-8000"></el-option>
|
||||||
|
<el-option label="8000-10000" value="8000-10000"></el-option>
|
||||||
|
<el-option label="10000-15000" value="10000-15000"></el-option>
|
||||||
|
<el-option label="15000以上" value="15000以上"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="住房情况" prop="housingSituation">
|
||||||
|
<el-select v-model="formData.housingSituation" placeholder="请选择住房情况"
|
||||||
|
style="width: 100%">
|
||||||
|
<el-option label="已购房" value="已购房"></el-option>
|
||||||
|
<el-option label="租房" value="租房"></el-option>
|
||||||
|
<el-option label="与父母同住" value="与父母同住"></el-option>
|
||||||
|
<el-option label="单位宿舍" value="单位宿舍"></el-option>
|
||||||
|
<el-option label="其他" value="其他"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-form-item label="兴趣爱好" prop="hobby">
|
||||||
|
<el-input v-model="formData.hobby" placeholder="请输入兴趣爱好,多个用逗号分隔"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="形象照片" prop="photo" class="avatar-container">
|
||||||
|
<file-upload
|
||||||
|
:value.sync="formData.photo"
|
||||||
|
:upload_number="1"
|
||||||
|
upload_mode="image"
|
||||||
|
upload_result_category="interval"
|
||||||
|
upload_result_type="url"
|
||||||
|
></file-upload>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="生活照片" prop="picFiles" class="gallery-container">
|
||||||
|
<file-upload
|
||||||
|
:value.sync="formData.picFiles"
|
||||||
|
:upload_number="5"
|
||||||
|
upload_mode="image"
|
||||||
|
upload_result_category="array"
|
||||||
|
upload_result_type="url"
|
||||||
|
></file-upload>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="交友意向" prop="intentionFriends">
|
||||||
|
<el-input type="textarea" v-model="formData.intentionFriends" :rows="3"
|
||||||
|
placeholder="请描述您的交友意向"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="个人介绍" prop="introduction">
|
||||||
|
<el-input type="textarea" v-model="formData.introduction" :rows="4"
|
||||||
|
placeholder="请简要介绍一下自己"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
loading: false,
|
||||||
|
userSearchLoading: false,
|
||||||
|
userOptions: [],
|
||||||
|
formData: {
|
||||||
|
userId: "",
|
||||||
|
userName: "",
|
||||||
|
birthday: "",
|
||||||
|
mobile: "",
|
||||||
|
height: "",
|
||||||
|
hometown: "",
|
||||||
|
education: "",
|
||||||
|
hobby: "",
|
||||||
|
monthlyIncome: "",
|
||||||
|
housingSituation: "",
|
||||||
|
picFiles: [],
|
||||||
|
photo: "",
|
||||||
|
maritalStatus: "",
|
||||||
|
intentionFriends: "",
|
||||||
|
introduction: ""
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
userId: [{ required: true, message: "请选择用户", trigger: ["change", "blur"] }],
|
||||||
|
mobile: [
|
||||||
|
{ required: true, message: "请输入联系方式", trigger: ["change", "blur"] },
|
||||||
|
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的手机号码", trigger: ["change", "blur"] }
|
||||||
|
],
|
||||||
|
birthday: [{ required: true, message: "请选择出生年月", trigger: ["change", "blur"] }],
|
||||||
|
height: [{ pattern: /^\d{2,3}$/, message: "请输入正确的身高", trigger: ["change", "blur"] }],
|
||||||
|
education: [{ required: true, message: "请选择学历", trigger: ["change", "blur"] }],
|
||||||
|
maritalStatus: [{ required: true, message: "请选择婚姻状况", trigger: ["change", "blur"] }],
|
||||||
|
introduction: [{ required: true, message: "请填写个人介绍", trigger: ["change", "blur"] }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onOpen(data) {
|
||||||
|
this.visible = true
|
||||||
|
this.loading = false
|
||||||
|
this.userOptions = [] // 清空用户选项
|
||||||
|
|
||||||
|
if (data && data.id) {
|
||||||
|
this.formData = JSON.parse(JSON.stringify(data))
|
||||||
|
this.formData.picFiles = JSON.parse(this.formData.picFiles)
|
||||||
|
} else {
|
||||||
|
this.formData = {
|
||||||
|
userId: "",
|
||||||
|
userName: "",
|
||||||
|
birthday: "",
|
||||||
|
mobile: "",
|
||||||
|
height: "",
|
||||||
|
nativePlace: "",
|
||||||
|
education: "",
|
||||||
|
hobby: "",
|
||||||
|
monthlyIncome: "",
|
||||||
|
housingSituation: "",
|
||||||
|
picFiles: [],
|
||||||
|
photo: "",
|
||||||
|
maritalStatus: "",
|
||||||
|
intentionFriends: "",
|
||||||
|
introduction: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.form) {
|
||||||
|
this.$refs.form.clearValidate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// 远程搜索用户
|
||||||
|
remoteSearchUsers(query) {
|
||||||
|
if (query !== "") {
|
||||||
|
this.userSearchLoading = true
|
||||||
|
this.$axios
|
||||||
|
.post("/platform/singleTeacher/ledger/queryNotSingleTeacher", { key: query })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.userOptions = res.data || []
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg || "搜索用户失败")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.userSearchLoading = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.userOptions = []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 用户选择变更
|
||||||
|
handleUserChange(userId) {
|
||||||
|
const selectedUser = this.userOptions.find((item) => item.id === userId)
|
||||||
|
if (selectedUser) {
|
||||||
|
// 自动填充一些基础信息
|
||||||
|
this.formData.userName = selectedUser.name
|
||||||
|
this.formData.mobile = selectedUser.mobile || ""
|
||||||
|
this.formData.birthday = selectedUser.birthday || ""
|
||||||
|
this.formData.education = selectedUser.education || ""
|
||||||
|
this.formData.nativePlace = selectedUser.nativePlace || ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
submitForm() {
|
||||||
|
this.$refs.form.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.loading = true
|
||||||
|
|
||||||
|
// 构建提交的数据
|
||||||
|
const submitData = { ...this.formData }
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
const url = submitData.id ? "/platform/singleTeacher/ledger/update" : "/platform/singleTeacher/ledger/insert"
|
||||||
|
|
||||||
|
this.$axios
|
||||||
|
.post(url, { singleTeacher: JSON.stringify(submitData) })
|
||||||
|
.then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.$message.success(submitData.id ? "修改成功" : "添加成功")
|
||||||
|
this.visible = false
|
||||||
|
this.$emit("refresh")
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.msg || "操作失败")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: /*language=CSS*/ `
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
<!--#
|
||||||
|
layout("/layouts/platform.html"){
|
||||||
|
#-->
|
||||||
|
|
||||||
|
<div id="app" v-cloak>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<search @search="doSearch">
|
||||||
|
<search-item label="姓名工号">
|
||||||
|
<el-input placeholder="请输入姓名或者工号" clearable v-model="pageForm.searchKeyword"></el-input>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="所属工会">
|
||||||
|
<el-select v-model="pageForm.unionId" placeholder="请选择分工会" clearable style="width: 100%">
|
||||||
|
<el-option v-for="item in unionOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<!-- <search-item label="所属单位">-->
|
||||||
|
<!-- <el-select v-model="pageForm.unitId" placeholder="请选择单位" clearable style="width: 100%">-->
|
||||||
|
<!-- <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.maritalStatus" placeholder="请选择婚姻状况" clearable style="width: 100%">
|
||||||
|
<el-option label="未婚" value="未婚"></el-option>
|
||||||
|
<el-option label="已婚" value="已婚"></el-option>
|
||||||
|
<el-option label="离异" value="离异"></el-option>
|
||||||
|
<el-option label="丧偶" value="丧偶"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</search-item>
|
||||||
|
<search-item label="年龄区间">
|
||||||
|
<div style="display: flex; align-items: center">
|
||||||
|
<el-slider v-model="pageForm.age" range show-stops :max="100" style="flex: 1; padding: 0 12px"></el-slider>
|
||||||
|
<div style="width: 70px; flex-shrink: 0; text-align: right">{{ pageForm.age ? pageForm.age.join('-') : '' }}</div>
|
||||||
|
</div>
|
||||||
|
</search-item>
|
||||||
|
</search>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<table-tool>
|
||||||
|
<el-button size="mini" type="primary" icon="el-icon-plus" @click="$refs.formEditRef.onOpen()">新增</el-button>
|
||||||
|
<el-button size="mini" type="primary" icon="el-icon-download" @click="exportExcel">导出</el-button>
|
||||||
|
</table-tool>
|
||||||
|
<el-table :data="tableData">
|
||||||
|
<el-table-column type="index" width="50px" label="序号" :index="indexMethod" fixed="left"></el-table-column>
|
||||||
|
<el-table-column prop="username" label="姓名" width="100" sortable="custom" fixed="left"></el-table-column>
|
||||||
|
<el-table-column prop="loginname" label="工号" width="100" sortable="custom"></el-table-column>
|
||||||
|
<el-table-column prop="sex" label="性别" width="100" sortable="custom"></el-table-column>
|
||||||
|
<el-table-column prop="mobile" label="手机号码" width="120"></el-table-column>
|
||||||
|
<el-table-column prop="birthday" label="出生日期" width="120" sortable="custom"></el-table-column>
|
||||||
|
<el-table-column prop="education" label="学历" width="150" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column prop="maritalStatus" label="婚姻状况" width="120" sortable="custom"></el-table-column>
|
||||||
|
<el-table-column prop="unitName" label="单位名称" width="180" show-overflow-tooltip sortable="custom"></el-table-column>
|
||||||
|
<el-table-column prop="unionName" label="工会名称" width="150" show-overflow-tooltip sortable="custom"></el-table-column>
|
||||||
|
<el-table-column prop="introduction" label="介绍" show-overflow-tooltip></el-table-column>
|
||||||
|
<el-table-column label="操作" width="150" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="primary" size="mini" @click="$refs.formEditRef.onOpen(scope.row)">编辑</el-button>
|
||||||
|
<el-button type="danger" size="mini" @click="onDelete(scope.row.id)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!--#include("/layouts/pagination.html"){}#-->
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<form-edit ref="formEditRef" @refresh="doSearch"></form-edit>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
<!--#include("formEdit.js"){}#-->
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
store,
|
||||||
|
mixins: [initTableMixins],
|
||||||
|
components: {
|
||||||
|
"form-edit": formEdit
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
unionOptions: [],
|
||||||
|
unitOptions: [],
|
||||||
|
pageForm: {
|
||||||
|
age: [0, 100]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
pageData() {
|
||||||
|
this.$axios.post("/platform/singleTeacher/ledger/pageData", { pageForm: JSON.stringify(this.pageForm) }).then((res) => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.tableData = res.data.list
|
||||||
|
this.pageForm.totalCount = res.data.totalCount
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onDelete(id) {
|
||||||
|
this.$confirm("您确定要删除吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning"
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
const { code, msg } = await this.$axios.post("/platform/singleTeacher/ledger/delete", { id: id })
|
||||||
|
if (code === 0) {
|
||||||
|
this.$message.success(msg)
|
||||||
|
this.doSearch()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
},
|
||||||
|
exportExcel() {
|
||||||
|
this.$downLoad("/platform/singleTeacher/ledger/exportExcel", { pageForm: JSON.stringify(this.pageForm) })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.pageData()
|
||||||
|
this.$businessTool.listUnion().then((res) => (this.unionOptions = res))
|
||||||
|
this.$businessTool.listUnit().then((res) => (this.unitOptions = res))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!--#
|
||||||
|
}
|
||||||
|
#-->
|
||||||
Reference in New Issue
Block a user