Merge branch 'main' of https://dd3skj.picp.vip/JyuHsin/zhgh_cug_v4
This commit is contained in:
@@ -8,6 +8,7 @@ import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.sys.models.Sys_menu;
|
||||
import com.budwk.app.sys.models.Sys_module;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.sys.models.Sys_unit;
|
||||
import com.budwk.app.sys.models.Sys_user;
|
||||
@@ -23,6 +24,8 @@ import org.nutz.dao.FieldFilter;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.Daos;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
@@ -120,6 +123,7 @@ public class SysRoleController {
|
||||
@Ok("json:full")
|
||||
@SaCheckPermission("sys.manager.role")
|
||||
public Object pageData(@Param("searchUnit") String searchUnit,
|
||||
@Param("moduleId") String moduleId,
|
||||
@Param("searchName") String searchName,
|
||||
@Param("searchKeyword") String searchKeyword,
|
||||
@Param("searchName2") String searchName2,
|
||||
@@ -130,9 +134,10 @@ public class SysRoleController {
|
||||
try {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
role.*
|
||||
role.*, module.name AS moduleName
|
||||
FROM
|
||||
sys_role role
|
||||
LEFT JOIN sys_module module ON module.id = role.moduleId
|
||||
LEFT JOIN sys_user_role ur ON role.id = ur.roleId
|
||||
LEFT JOIN sys_user u ON u.id = ur.userId
|
||||
$condition
|
||||
@@ -163,6 +168,9 @@ public class SysRoleController {
|
||||
if (StrUtil.isAllNotBlank(searchName2, searchKeyword2)) {
|
||||
cnd.and("u." + searchName2, "like", "%" + searchKeyword2 + "%");
|
||||
}
|
||||
if (StrUtil.isNotBlank(moduleId)) {
|
||||
cnd.and("role.moduleId", "=", moduleId);
|
||||
}
|
||||
if (Strings.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) {
|
||||
cnd.orderBy(pageOrderName, PageUtil.getOrder(pageOrderBy));
|
||||
} else {
|
||||
@@ -287,8 +295,13 @@ public class SysRoleController {
|
||||
@Ok("json")
|
||||
@SaCheckPermission("sys.manager.role.add")
|
||||
@SLog(tag = "添加角色", msg = "角色名称:${args[1].name}")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object addDo(@Param("..") Sys_role role, HttpServletRequest req) {
|
||||
try {
|
||||
// 所属模块只允许选择已配置的 PC 端模块,避免角色关联无效或 H5 模块。
|
||||
if (!isPcModule(role.getModuleId())) {
|
||||
return Result.error("请选择所属模块");
|
||||
}
|
||||
int num = sysRoleService.count(Cnd.where("code", "=", role.getCode().trim()));
|
||||
if (num > 0) {
|
||||
return Result.error("角色编码已存在");
|
||||
@@ -360,8 +373,13 @@ public class SysRoleController {
|
||||
@Ok("json")
|
||||
@SaCheckPermission("sys.manager.role.edit")
|
||||
@SLog(tag = "修改角色", msg = "角色名称:${args[0].name}")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Object editDo(@Param("..") Sys_role role, HttpServletRequest req) {
|
||||
try {
|
||||
// 编辑时同样校验模块,保证历史角色补录后始终关联有效 PC 模块。
|
||||
if (!isPcModule(role.getModuleId())) {
|
||||
return Result.error("请选择所属模块");
|
||||
}
|
||||
Sys_role oldRole = sysRoleService.fetch(role.getId());
|
||||
if (oldRole != null && !Strings.sBlank(oldRole.getCode()).equalsIgnoreCase(role.getCode())) {
|
||||
int num = sysRoleService.count(Cnd.where("code", "=", role.getCode().trim()));
|
||||
@@ -503,6 +521,35 @@ public class SysRoleController {
|
||||
cnd.and(Cnd.exps("parentId", "is", null).or("parentId", "=", ""));
|
||||
return Result.success(Daos.ext(sysRoleService.dao(), fieldFilter).query(Sys_menu.class, cnd));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询角色可选择的 PC 端模块。
|
||||
*
|
||||
* @return PC 端模块列表,按模块排序编号升序返回,元素包含模块 ID 和模块名称
|
||||
*/
|
||||
@At
|
||||
@Ok("json:full")
|
||||
@SaCheckPermission("sys.manager.role")
|
||||
public Result listModule() {
|
||||
List<Sys_module> modules = sysRoleService.dao().query(Sys_module.class,
|
||||
Cnd.where(Sys_module::getPlatform, "=", "PC").asc(Sys_module::getSortNum));
|
||||
return Result.success(modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验所属模块是否存在且属于 PC 平台。
|
||||
*
|
||||
* @param moduleId 模块主键,必须来自 sys_module 的 PC 端模块记录
|
||||
* @return 模块有效时返回 true,否则返回 false
|
||||
*/
|
||||
private boolean isPcModule(String moduleId) {
|
||||
if (StrUtil.isBlank(moduleId)) {
|
||||
return false;
|
||||
}
|
||||
Sys_module module = sysRoleService.dao().fetch(Sys_module.class, moduleId);
|
||||
return module != null && "PC".equals(module.getPlatform());
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("json:full")
|
||||
@SaCheckLogin
|
||||
|
||||
@@ -60,7 +60,7 @@ public class Sys_log extends BaseModel implements Serializable {
|
||||
|
||||
@Column
|
||||
@Comment("请求结果")
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
@ColDefine(customType = "MEDIUMTEXT")
|
||||
private String param;
|
||||
|
||||
@Column
|
||||
|
||||
@@ -45,6 +45,11 @@ public class Sys_role extends BaseModel implements Serializable {
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unitid;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@Comment("所属模块ID")
|
||||
private String moduleId;
|
||||
|
||||
@Column
|
||||
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||
private String note;
|
||||
|
||||
+22
-9
@@ -133,10 +133,20 @@ public class ActivityBasicScopeUserDataController {
|
||||
|
||||
|
||||
/**
|
||||
* 删除一条记录
|
||||
* 删除活动分组人员。
|
||||
* id 有值时删除单个人员;id 为空时按当前页面的姓名/工号、工会、单位、人员类别和在职状态筛选后批量删除。
|
||||
* groupId 为待删除人员所在的活动分组;existsLoginNameRedisKey 为导入核对名单生成的工号筛选缓存键。
|
||||
* 返回 Result,code 为 0 表示删除处理成功。
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
* @param id 单个人员 ID;批量删除时传空
|
||||
* @param groupId 当前活动分组 ID
|
||||
* @param searchKeyword 姓名或工号关键字
|
||||
* @param unionId 所属工会 ID
|
||||
* @param unitId 所属单位 ID
|
||||
* @param personType 教职工类别
|
||||
* @param userState 在职状态
|
||||
* @param existsLoginNameRedisKey 导入核对名单的 Redis 缓存键
|
||||
* @return 删除结果
|
||||
*/
|
||||
@At
|
||||
@SLog(tag = "活动人员查询", msg = "删除活动人员")
|
||||
@@ -145,7 +155,6 @@ public class ActivityBasicScopeUserDataController {
|
||||
public Result doDelete(@Param(value = "id") String id,
|
||||
@Param(value = "groupId") Integer groupId,
|
||||
@Param(value = "searchKeyword") String searchKeyword,
|
||||
@Param(value = "searchName") String searchName,
|
||||
@Param(value = "unionId") String unionId,
|
||||
@Param(value = "unitId") String unitId,
|
||||
@Param(value = "personType") String personType,
|
||||
@@ -160,7 +169,7 @@ public class ActivityBasicScopeUserDataController {
|
||||
}
|
||||
}
|
||||
|
||||
List<String> targetUserIds = queryGroupUserIds(groupId, id, searchKeyword, searchName, unionId, unitId, personType, userState, existsLoginNames);
|
||||
List<String> targetUserIds = queryGroupUserIds(groupId, id, searchKeyword, unionId, unitId, personType, userState, existsLoginNames);
|
||||
if (Lang.isEmpty(targetUserIds)) {
|
||||
return Result.success();
|
||||
}
|
||||
@@ -282,9 +291,10 @@ public class ActivityBasicScopeUserDataController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除时需要先按页面当前筛选条件圈定目标人员,再根据分组类型删除对应存储表中的快照数据。
|
||||
* 删除时需要先按页面当前筛选条件圈定目标人员。姓名或工号关键字必须与列表查询使用相同的匹配规则,
|
||||
* 再根据分组类型删除对应存储表中的快照数据。
|
||||
*/
|
||||
private List<String> queryGroupUserIds(Integer groupId, String id, String searchKeyword, String searchName,
|
||||
private List<String> queryGroupUserIds(Integer groupId, String id, String searchKeyword,
|
||||
String unionId, String unitId, String personType, String userState,
|
||||
List<String> existsLoginNames) {
|
||||
Sql sql = Sqls.queryString("""
|
||||
@@ -296,8 +306,11 @@ public class ActivityBasicScopeUserDataController {
|
||||
""");
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("u.id", "in", activityBasicScopeService.buildGroupUserIdSubSql(groupId));
|
||||
if (StrUtil.isNotBlank(searchName) && StrUtil.isNotBlank(searchKeyword)) {
|
||||
cnd.and(Cnd.likeEX(searchName, searchKeyword));
|
||||
if (StrUtil.isNotBlank(searchKeyword)) {
|
||||
SqlExpressionGroup group = new SqlExpressionGroup();
|
||||
group.orLike("u.username", searchKeyword);
|
||||
group.orLike("u.loginname", searchKeyword);
|
||||
cnd.and(group);
|
||||
}
|
||||
cnd.andEX("u.unionid", "=", unionId);
|
||||
cnd.andEX("u.unitid", "=", unitId);
|
||||
|
||||
+1
@@ -49,6 +49,7 @@ public class ArticleQueryController {
|
||||
info.loginName,
|
||||
info.unitName,
|
||||
info.unionName,
|
||||
info.clubName,
|
||||
info.submitTime,
|
||||
info.origin,
|
||||
ins.id AS instanceId,
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
@@ -153,7 +154,7 @@ public class AssetManageController {
|
||||
|
||||
@At
|
||||
@ApiOperation("查询责任人")
|
||||
@SaCheckPermission("asset.manage")
|
||||
@SaCheckPermission(value = {"asset.manage", "asset.stocktaking", "h5.asset.stocktaking"}, mode = SaMode.OR)
|
||||
public Result searchAssetUseUser(String query) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.where().orLike("username", query);
|
||||
|
||||
+31
@@ -4,12 +4,15 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.flow.engine.FlowEngine;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.model.CadreTrainingAct;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.model.CadreTrainingSignUp;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.service.CadreTrainingActService;
|
||||
import com.budwk.app.zhgh.dayofficework.cadreTraining.service.CadreTrainingSignUpService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -29,6 +32,7 @@ import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author : hongqiwei
|
||||
@@ -112,6 +116,33 @@ public class CadreTrainingMineController {
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询“我的报名”查看页的报名人员。
|
||||
* 管理角色按活动和分工会查看全部报名人员;普通用户仅返回本人记录,避免扩大人员信息可见范围。
|
||||
*
|
||||
* @param activityId 培训活动 ID,对应 cadre_training 表主键
|
||||
* @param unionId 当前查看报名记录所属的分工会 ID
|
||||
* @return 报名记录列表,元素包含人员姓名、工号、单位、分工会、联系方式及备注
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("查询我的报名活动人员")
|
||||
@SaCheckPermission(value = {"cadreTraining.mine", "h5.cadreTraining.mine"}, mode = SaMode.OR)
|
||||
public Result listSignUsers(@Valid String activityId, String unionId) {
|
||||
Cnd cnd = Cnd.where(CadreTrainingSignUp::getCadreTrainingActId, "=", activityId);
|
||||
if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
|
||||
// 管理角色必须携带当前报名记录所属的分工会,防止空参数绕过分工会范围。
|
||||
if (StrUtil.isBlank(unionId)) {
|
||||
return Result.error("分工会信息不能为空");
|
||||
}
|
||||
cnd.and(CadreTrainingSignUp::getUnionId, "=", unionId);
|
||||
} else {
|
||||
cnd.and(CadreTrainingSignUp::getUserId, "=", SecurityUtil.getUserId());
|
||||
}
|
||||
cnd.asc(CadreTrainingSignUp::getApplyTime);
|
||||
List<CadreTrainingSignUp> signUsers = dao.query(CadreTrainingSignUp.class, cnd);
|
||||
return Result.success(signUsers);
|
||||
}
|
||||
|
||||
@At
|
||||
@ApiOperation("删除")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
|
||||
+1
-1
@@ -141,7 +141,7 @@ public class GhkhKhphController {
|
||||
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||
exportEntities.add(new ExcelExportEntity("序号", "index", 10));
|
||||
exportEntities.add(new ExcelExportEntity("年度", "annual", 10));
|
||||
exportEntities.add(new ExcelExportEntity("分工会名称", "unionName", 30));
|
||||
exportEntities.add(new ExcelExportEntity("分工会名称", "unionname", 30));
|
||||
exportEntities.add(new ExcelExportEntity("线上得分", "xgh_score", 20));
|
||||
exportEntities.add(new ExcelExportEntity("线上最终得分" + (config.getOnLine() != null ? "(" + config.getOnLine() + "%)" : ""), "onLineFinalScore", 20));
|
||||
exportEntities.add(new ExcelExportEntity("线下得分", "offLineScore", 20));
|
||||
|
||||
+6
-1
@@ -3,11 +3,13 @@ package com.budwk.app.zhgh.dayofficework.honor.controller;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
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.sys.models.Sys_union;
|
||||
import com.budwk.app.sys.services.SysUnionService;
|
||||
import com.budwk.app.sys.services.SysUserService;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.dayofficework.honor.models.Honor;
|
||||
import com.budwk.app.zhgh.dayofficework.honor.service.HonorCommonService;
|
||||
@@ -90,7 +92,10 @@ public class HonorRegistrationController {
|
||||
seg.orLike("t1.username",keyWord);
|
||||
cnd.and(seg);
|
||||
}
|
||||
cnd.and("t1.unionId","=", SecurityUtil.getUnionId());
|
||||
// 系统管理员可跨分工会查询人员,其他角色仍限定为当前所属分工会。
|
||||
if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) {
|
||||
cnd.and("t1.unionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = sysUserService.listPageMap(1, 50, sql);
|
||||
return Result.success(pagination.getList());
|
||||
|
||||
+3
-3
@@ -54,8 +54,8 @@ public class HonorSummaryController {
|
||||
@SaCheckPermission("honor.honorLevel.Summary")
|
||||
public Result unionData(HonorPageForm pageForm) {
|
||||
List<HonorBasicSettings> query = dao.query(HonorBasicSettings.class, Cnd.where("queryTypeCode", "in", List.of(HonorTypeOrigin.HONOR_SINGLE.name(), HonorTypeOrigin.HONOR_LIST.name())));
|
||||
String listHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_LIST.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String singleHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_SINGLE.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String personalHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_SINGLE.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
String collectiveHonorId = query.stream().filter(v->v.getQueryTypeCode().equals(HonorTypeOrigin.HONOR_LIST.name())).findFirst().orElse(new HonorBasicSettings()).getId();
|
||||
Cnd cnd = Cnd.NEW();
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
@@ -65,7 +65,7 @@ public class HonorSummaryController {
|
||||
( SELECT COUNT( 1 ) FROM honor h WHERE h.honorType = @collectiveHonor AND h.unionId = un.id $cnd) collectiveHonorNum
|
||||
FROM
|
||||
sys_union un $condition
|
||||
""").setParam("personalHonor", listHonorId).setParam("collectiveHonor", singleHonorId);
|
||||
""").setParam("personalHonor", personalHonorId).setParam("collectiveHonor", collectiveHonorId);
|
||||
cnd.andEX("id", "=", pageForm.getUnionId());
|
||||
if (pageForm.getYear() != null) {
|
||||
sql.setVar("cnd", "and YEAR(grantDate)=" + pageForm.getYear());
|
||||
|
||||
+44
@@ -3,11 +3,14 @@ package com.budwk.app.zhgh.dayofficework.meeting.controller;
|
||||
import cn.dev33.satoken.annotation.SaCheckLogin;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.RepeatSubmit;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.base.utils.PageUtil;
|
||||
import com.budwk.app.sys.models.Sys_module;
|
||||
import com.budwk.app.sys.models.Sys_role;
|
||||
import com.budwk.app.zhgh.dayofficework.meeting.model.MeetingInfo;
|
||||
import com.budwk.app.zhgh.dayofficework.meeting.model.MeetingTimePeriod;
|
||||
import com.budwk.app.zhgh.dayofficework.meeting.model.MeetingTimePeriodUser;
|
||||
@@ -101,6 +104,7 @@ public class MeetingManageController {
|
||||
@At
|
||||
@ApiOperation("新增/修改会议")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@RepeatSubmit
|
||||
@SaCheckPermission("meeting.manage")
|
||||
@SLog(tag = "会议管理系统-会议管理", msg = "新增/修改会议")
|
||||
public Object submit(@Param("data") MeetingInfo info,
|
||||
@@ -161,6 +165,10 @@ public class MeetingManageController {
|
||||
if (StrUtil.isNotBlank(roleId)) {
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s')".formatted(roleId)));
|
||||
}
|
||||
// 选择届次但未选择角色时,按届次筛选全部相关人员;同时选择角色时限定为同一角色关联记录。
|
||||
if (StrUtil.isBlank(roleId) && StrUtil.isNotBlank(teacherCongressSessionId)) {
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where tcSessionId = '%s')".formatted(teacherCongressSessionId)));
|
||||
}
|
||||
if (StrUtil.isNotBlank(roleId) && StrUtil.isNotBlank(teacherCongressSessionId)) {
|
||||
cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s' and tcSessionId = '%s')".formatted(roleId, teacherCongressSessionId)));
|
||||
}
|
||||
@@ -225,4 +233,40 @@ public class MeetingManageController {
|
||||
List<Worker_congress_session> list = dao.query(Worker_congress_session.class, Cnd.where(Teacher_congress_session::getEnable, "=", true).desc("year"));
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询会议选择用户时可筛选的 PC 端模块。
|
||||
*
|
||||
* @return 模块列表,元素包含模块 ID、名称和平台,按排序编号升序返回
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("查询 PC 端模块")
|
||||
@SaCheckPermission("meeting.manage")
|
||||
public Result listModule() {
|
||||
List<Sys_module> modules = dao.query(Sys_module.class,
|
||||
Cnd.where(Sys_module::getPlatform, "=", "PC").asc(Sys_module::getSortNum));
|
||||
return Result.success(modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按模块查询会议选择用户时可筛选的启用角色。
|
||||
*
|
||||
* @param moduleId PC 端模块 ID,来源于 sys_module 表
|
||||
* @return 角色列表,元素包含角色 ID、名称和角色标识,未传模块时返回空列表
|
||||
*/
|
||||
@At
|
||||
@ApiOperation("按模块查询角色")
|
||||
@SaCheckPermission("meeting.manage")
|
||||
public Result listRole(String moduleId) {
|
||||
if (StrUtil.isBlank(moduleId)) {
|
||||
return Result.success(List.of());
|
||||
}
|
||||
Sys_module module = dao.fetch(Sys_module.class, moduleId);
|
||||
if (module == null || !"PC".equals(module.getPlatform())) {
|
||||
return Result.success(List.of());
|
||||
}
|
||||
List<Sys_role> roles = dao.query(Sys_role.class,
|
||||
Cnd.where(Sys_role::getModuleId, "=", moduleId).and(Sys_role::isDisabled, "=", false).asc(Sys_role::getSort));
|
||||
return Result.success(roles);
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -93,6 +93,10 @@ public class MeetingMineController {
|
||||
|
||||
List<MeetingTimePeriodUser> periodUsers = dao.query(MeetingTimePeriodUser.class, Cnd.where(MeetingTimePeriodUser::getUserId, "=", SecurityUtil.getUserId()));
|
||||
List<String> idList = periodUsers.stream().map(MeetingTimePeriodUser::getMeetingId).toList();
|
||||
// 当前用户未被安排参会时,直接返回空分页,避免生成空 IN 条件导致数据库语法错误。
|
||||
if (idList.isEmpty()) {
|
||||
return Result.success(new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, List.of()));
|
||||
}
|
||||
|
||||
cnd.and("id", "in", idList);
|
||||
cnd.andEX("typeId", "=", type);
|
||||
@@ -217,6 +221,14 @@ public class MeetingMineController {
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SLog(tag = "会务管理-我的会议-签到", msg = "会议签到")
|
||||
public Result sign(@Valid String periodId) {
|
||||
MeetingTimePeriod timePeriod = dao.fetch(MeetingTimePeriod.class, periodId);
|
||||
if (timePeriod == null) {
|
||||
return Result.error("会议场次不存在!");
|
||||
}
|
||||
// 以服务端时间校验场次开始时间,避免客户端时间或页面状态被绕过。
|
||||
if (timePeriod.getStartTime() == null || DateUtil.date().before(timePeriod.getStartTime())) {
|
||||
return Result.error("会议尚未开始,暂不能签到!");
|
||||
}
|
||||
MeetingTimePeriodUser user = dao.fetch(
|
||||
MeetingTimePeriodUser.class,
|
||||
Cnd.where(MeetingTimePeriodUser::getTimePeriodId, "=", periodId)
|
||||
|
||||
+25
-5
@@ -19,6 +19,7 @@ import org.nutz.lang.Lang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -44,11 +45,12 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
// 插入会议表和会议场次表
|
||||
info.setCreateTime(DateUtil.now());
|
||||
insertWith(info, "timePeriods");
|
||||
List<MeetingTimePeriodUser> uniqueUsers = distinctUsers(users);
|
||||
// 插入参与人员表
|
||||
if (Lang.isNotEmpty(info.getTimePeriods()) && Lang.isNotEmpty(users)) {
|
||||
if (Lang.isNotEmpty(info.getTimePeriods()) && Lang.isNotEmpty(uniqueUsers)) {
|
||||
List<MeetingTimePeriodUser> relations = info.getTimePeriods()
|
||||
.stream()
|
||||
.flatMap(period -> Arrays.stream(users).map(user -> buildRelation(info.getId(), period.getId(), user)))
|
||||
.flatMap(period -> uniqueUsers.stream().map(user -> buildRelation(info.getId(), period.getId(), user)))
|
||||
.toList();
|
||||
dao().insert(relations);
|
||||
}
|
||||
@@ -58,6 +60,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void edit(MeetingInfo info, MeetingTimePeriodUser[] users) {
|
||||
String meetingId = info.getId();
|
||||
List<MeetingTimePeriodUser> uniqueUsers = distinctUsers(users);
|
||||
|
||||
// 设置外键并保存场次(含新增和修改)
|
||||
info.getTimePeriods().forEach(p -> p.setMeetingId(meetingId));
|
||||
@@ -79,7 +82,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// 页面传过来的新人员
|
||||
Set<String> newUserIds = Arrays.stream(users).map(MeetingTimePeriodUser::getUserId).collect(Collectors.toSet());
|
||||
Set<String> newUserIds = uniqueUsers.stream().map(MeetingTimePeriodUser::getUserId).collect(Collectors.toSet());
|
||||
|
||||
// 删除废弃场次及其所有关联
|
||||
Set<String> deletedPeriodIds = Sets.difference(oldPeriodIds, newPeriodIds);
|
||||
@@ -99,7 +102,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
List<MeetingTimePeriodUser> newRelations = new ArrayList<>();
|
||||
|
||||
// 新增的用户 → 所有现存场次
|
||||
List<MeetingTimePeriodUser> newUsers = Arrays.stream(users).filter(u -> StrUtil.isBlank(u.getId())).toList();
|
||||
List<MeetingTimePeriodUser> newUsers = uniqueUsers.stream().filter(u -> StrUtil.isBlank(u.getId())).toList();
|
||||
for (String periodId : newPeriodIds) {
|
||||
for (MeetingTimePeriodUser user : newUsers) {
|
||||
newRelations.add(buildRelation(meetingId, periodId, user));
|
||||
@@ -109,7 +112,7 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
// 新增的场次 → 所有现存老用户(避免重复插入新用户)
|
||||
Set<String> addedPeriodIds = Sets.difference(newPeriodIds, oldPeriodIds);
|
||||
for (String periodId : addedPeriodIds) {
|
||||
for (MeetingTimePeriodUser user : users) {
|
||||
for (MeetingTimePeriodUser user : uniqueUsers) {
|
||||
if (StrUtil.isBlank(user.getId())) continue;
|
||||
newRelations.add(buildRelation(meetingId, periodId, user));
|
||||
}
|
||||
@@ -131,4 +134,21 @@ public class MeetingInfoServiceImpl extends BaseServiceImpl<MeetingInfo> impleme
|
||||
rel.setJoinStatus(true);
|
||||
return rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按用户 ID 去重会议参会人员,保留首次选择的人员信息。
|
||||
* 同一用户在一个会议的每个场次只允许生成一条参会关系,防止重复提交或重复选择产生重复记录。
|
||||
*
|
||||
* @param users 前端提交的参会人员数组,每项必须包含 userId
|
||||
* @return 去重后的参会人员列表,userId 为空的无效项不会参与保存
|
||||
*/
|
||||
private List<MeetingTimePeriodUser> distinctUsers(MeetingTimePeriodUser[] users) {
|
||||
if (users == null || users.length == 0) {
|
||||
return List.of();
|
||||
}
|
||||
return new ArrayList<>(Arrays.stream(users)
|
||||
.filter(user -> StrUtil.isNotBlank(user.getUserId()))
|
||||
.collect(Collectors.toMap(MeetingTimePeriodUser::getUserId, user -> user, (first, duplicate) -> first, LinkedHashMap::new))
|
||||
.values());
|
||||
}
|
||||
}
|
||||
|
||||
+28
-14
@@ -9,7 +9,7 @@ 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.activity.basic.models.ActivityUserScope;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvOption;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject;
|
||||
@@ -55,6 +55,8 @@ public class QsvOnlineController {
|
||||
private QsvUserAnswerRecordService qsvUserAnswerRecordService;
|
||||
@Inject
|
||||
private QsvQuizService qsvQuizService;
|
||||
@Inject
|
||||
private ActivityBasicScopeService activityBasicScopeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/qsv/online/index.html")
|
||||
@@ -63,27 +65,41 @@ public class QsvOnlineController {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前用户可参与的在线问卷、答题和投票活动。
|
||||
* pageForm 传入页码、每页数量与搜索关键字;year 为活动开始年份;title 为标题关键字;
|
||||
* isAnswered 用于筛选已答或未答活动。返回 Pagination,列表数据仅包含当前用户命中活动分组的活动。
|
||||
*
|
||||
* @param pageForm 分页及搜索参数
|
||||
* @param year 活动开始年份
|
||||
* @param title 活动标题关键字
|
||||
* @param isAnswered 是否只查看已答活动
|
||||
* @return 当前用户可参与的在线活动分页结果
|
||||
*/
|
||||
@At
|
||||
@SaCheckPermission("qsv.online")
|
||||
@ApiOperation("在线答题任务分页")
|
||||
public Result pageData(@Valid PageForm pageForm, Integer year, String title, Boolean isAnswered) {
|
||||
List<Integer> groupIds = dao.query(ActivityUserScope.class, Cnd.where("userId", "=", SecurityUtil.getUserId()))
|
||||
.stream().map(ActivityUserScope::getGroupId).collect(Collectors.toList());
|
||||
if (groupIds.isEmpty()) {
|
||||
return Result.success(new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, new ArrayList<>()));
|
||||
}
|
||||
|
||||
Cnd cnd = Cnd.where("enabled", "=", true);
|
||||
cnd.and("groupId", "in", groupIds);
|
||||
cnd.andEX("YEAR(startTime)", "=", year);
|
||||
cnd.and(Cnd.likeEX("title", title));
|
||||
cnd.desc("startTime");
|
||||
|
||||
int totalCount = dao.count(QsvActivity.class, cnd);
|
||||
if (totalCount == 0) {
|
||||
List<QsvActivity> activities = dao.query(QsvActivity.class, cnd);
|
||||
if (activities.isEmpty()) {
|
||||
return Result.success(new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, new ArrayList<>()));
|
||||
}
|
||||
List<QsvActivity> activities = dao.query(QsvActivity.class, cnd);
|
||||
|
||||
// SQL条件分组不保存 userId 明细,统一通过分组服务动态判断当前用户是否命中活动分组。
|
||||
List<Integer> visibleGroupIds = activityBasicScopeService.filterGroupIdsByUser(
|
||||
activities.stream().map(QsvActivity::getGroupId).collect(Collectors.toList()), SecurityUtil.getUserId());
|
||||
activities = activities.stream()
|
||||
.filter(activity -> visibleGroupIds.contains(activity.getGroupId()))
|
||||
.collect(Collectors.toList());
|
||||
if (activities.isEmpty()) {
|
||||
return Result.success(new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, new ArrayList<>()));
|
||||
}
|
||||
|
||||
List<String> activityIds = activities.stream().map(QsvActivity::getId).collect(Collectors.toList());
|
||||
Map<String, List<QsvUserAnswerRecord>> recordGroup = dao.query(QsvUserAnswerRecord.class, Cnd.where("userId", "=", SecurityUtil.getUserId())
|
||||
.and("activityId", "in", activityIds))
|
||||
@@ -248,9 +264,7 @@ public class QsvOnlineController {
|
||||
}
|
||||
|
||||
private Result checkUserScope(QsvActivity activity) {
|
||||
int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getGroupId())
|
||||
.and("userId", "=", SecurityUtil.getUserId()));
|
||||
if (count != 1) {
|
||||
if (!activityBasicScopeService.isUserInGroup(activity.getGroupId(), SecurityUtil.getUserId())) {
|
||||
return Result.error("您无需参加此次调查,感谢您的关注!");
|
||||
}
|
||||
return null;
|
||||
|
||||
+15
-7
@@ -8,7 +8,7 @@ import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.dto.QsvCheckAnswerResult;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject;
|
||||
@@ -46,6 +46,8 @@ public class H5QsvQuizController {
|
||||
private QsvUserAnswerRecordService qsvUserAnswerRecordService;
|
||||
@Inject
|
||||
private QsvQuizService qsvQuizService;
|
||||
@Inject
|
||||
private ActivityBasicScopeService activityBasicScopeService;
|
||||
|
||||
@At("")
|
||||
@SaCheckLogin
|
||||
@@ -61,18 +63,24 @@ public class H5QsvQuizController {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取移动端答题活动的题目和当前用户答题记录。
|
||||
* activityId 传入 qsv_activity 表中的活动 ID;返回 Result,data 包含活动信息、题目列表和答题记录 ID。
|
||||
* 进入前会校验当前登录用户是否命中活动分组,结果分组和 SQL 条件分组均按统一规则判断。
|
||||
*
|
||||
* @param activityId 答题活动 ID
|
||||
* @return 包含答题题目及答题记录信息的结果
|
||||
*/
|
||||
@At
|
||||
@SaCheckLogin
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result subjects(@Valid String activityId) {
|
||||
QsvActivity activity = dao.fetch(QsvActivity.class, activityId);
|
||||
|
||||
if (activity.getGroupId() != null) {
|
||||
int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getGroupId())
|
||||
.and("userId", "=", SecurityUtil.getUserId()));
|
||||
if (count != 1) {
|
||||
return Result.error("您无需参加此次答题,感谢您的关注!");
|
||||
}
|
||||
// SQL条件分组不保存 userId 明细,统一通过分组服务动态判断当前用户是否属于活动范围。
|
||||
if (activity.getGroupId() != null
|
||||
&& !activityBasicScopeService.isUserInGroup(activity.getGroupId(), SecurityUtil.getUserId())) {
|
||||
return Result.error("您无需参加此次答题,感谢您的关注!");
|
||||
}
|
||||
|
||||
String mode = activity.getMode();
|
||||
|
||||
+7
-5
@@ -4,7 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvUserAnswerRecord;
|
||||
@@ -39,6 +39,8 @@ public class H5QsvSurveyController {
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private QsvUserAnswerRecordService qsvUserAnswerRecordService;
|
||||
@Inject
|
||||
private ActivityBasicScopeService activityBasicScopeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/qsv/survey/index.html")
|
||||
@@ -54,10 +56,10 @@ public class H5QsvSurveyController {
|
||||
return activityStatusResult;
|
||||
}
|
||||
|
||||
int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getGroupId())
|
||||
.and("userId", "=", SecurityUtil.getUserId()));
|
||||
if (count != 1) {
|
||||
return Result.error("您无需参加此次投票,感谢您的关注!");
|
||||
// SQL 条件分组不保存用户明细,需由分组服务实时判断当前用户是否命中活动范围。
|
||||
if (activity.getGroupId() != null
|
||||
&& !activityBasicScopeService.isUserInGroup(activity.getGroupId(), SecurityUtil.getUserId())) {
|
||||
return Result.error("您无需参加此次调查,感谢您的关注!");
|
||||
}
|
||||
|
||||
String answerRecordId = null;
|
||||
|
||||
+5
-4
@@ -4,7 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvOption;
|
||||
import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject;
|
||||
@@ -41,6 +41,8 @@ public class H5QsvVoteController {
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private QsvUserAnswerRecordService qsvUserAnswerRecordService;
|
||||
@Inject
|
||||
private ActivityBasicScopeService activityBasicScopeService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhghh5/dayofficework/qsv/vote/index.html")
|
||||
@@ -172,9 +174,8 @@ public class H5QsvVoteController {
|
||||
if (activity.getGroupId() == null) {
|
||||
return null;
|
||||
}
|
||||
int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getGroupId())
|
||||
.and("userId", "=", SecurityUtil.getUserId()));
|
||||
if (count != 1) {
|
||||
// SQL条件分组不保存 userId 明细,统一通过分组服务动态判断当前用户是否属于投票范围。
|
||||
if (!activityBasicScopeService.isUserInGroup(activity.getGroupId(), SecurityUtil.getUserId())) {
|
||||
return Result.error("\u60a8\u65e0\u9700\u53c2\u52a0\u6b64\u6b21\u6295\u7968\uff0c\u611f\u8c22\u60a8\u7684\u5173\u6ce8\uff01");
|
||||
}
|
||||
return null;
|
||||
|
||||
+10
@@ -7,6 +7,8 @@ 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.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHall;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallMeeting;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallSeat;
|
||||
@@ -40,6 +42,9 @@ public class GuildHallMeetingController {
|
||||
@Inject
|
||||
private GuildHallMeetingService guildHallMeetingService;
|
||||
|
||||
@Inject
|
||||
private ActivityBasicScopeService activityBasicScopeService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("guildHall.meeting")
|
||||
@Ok("beetl:/platform/zhgh/democratic/teachercongress/guildhall/meeting/index.html")
|
||||
@@ -109,6 +114,11 @@ public class GuildHallMeetingController {
|
||||
if(DateUtil.compare(DateUtil.date(), meeting.getEndTime()) > 0) {
|
||||
continue;
|
||||
}
|
||||
// 配置参与组别后,仅向组内用户返回可选会议;未配置组别时默认全员可见。
|
||||
if (meeting.getGroupId() != null
|
||||
&& !activityBasicScopeService.isUserInGroup(meeting.getGroupId(), SecurityUtil.getUserId())) {
|
||||
continue;
|
||||
}
|
||||
NutMap nutMap = Lang.obj2nutmap(meeting);
|
||||
GuildHall hall = dao.fetch(GuildHall.class, meeting.getHallId());
|
||||
nutMap.put("address", hall.getAddress());
|
||||
|
||||
+34
@@ -3,13 +3,16 @@ package com.budwk.app.zhgh.democratic.teachercongress.guildhall.controller;
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
|
||||
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallMeeting;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallSeat;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.models.GuildHallSeatSelect;
|
||||
import com.budwk.app.zhgh.democratic.teachercongress.guildhall.service.GuildHallService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
@@ -36,6 +39,8 @@ public class GuildHallSelectSeatController {
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private GuildHallService guildHallService;
|
||||
@Inject
|
||||
private ActivityBasicScopeService activityBasicScopeService;
|
||||
|
||||
@At("")
|
||||
@SaCheckPermission("guildHall.selectSeat")
|
||||
@@ -52,6 +57,11 @@ public class GuildHallSelectSeatController {
|
||||
@At
|
||||
@SaCheckPermission("guildHall.selectSeat")
|
||||
public Result loadSeats(@Param("meetingId") String meetingId) {
|
||||
Result permissionResult = checkMeetingPermission(meetingId);
|
||||
if (permissionResult != null) {
|
||||
return permissionResult;
|
||||
}
|
||||
|
||||
// 已选择情况
|
||||
List<GuildHallSeatSelect> selectedSeats = dao.query(GuildHallSeatSelect.class, Cnd.where("meetingId", "=", meetingId));
|
||||
|
||||
@@ -79,7 +89,13 @@ public class GuildHallSelectSeatController {
|
||||
|
||||
@At
|
||||
@SaCheckPermission("guildHall.selectSeat")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result doSelect(@Param("meetingId") String meetingId, Integer rowNumber, Integer colNumber) {
|
||||
Result permissionResult = checkMeetingPermission(meetingId);
|
||||
if (permissionResult != null) {
|
||||
return permissionResult;
|
||||
}
|
||||
|
||||
GuildHallSeatSelect oldSeat = dao.fetch(GuildHallSeatSelect.class, Cnd.where("meetingId", "=", meetingId).and("userId", "=", SecurityUtil.getUserId()));
|
||||
if(oldSeat != null){
|
||||
oldSeat.setUserId(null);
|
||||
@@ -94,4 +110,22 @@ public class GuildHallSelectSeatController {
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验当前用户是否可参与指定会议;未配置参与组别的会议默认允许选座。
|
||||
*
|
||||
* @param meetingId 会议主键,用于查询会议的参与组别配置
|
||||
* @return 校验通过时返回 {@code null};会议不存在或用户不在参与组别时返回错误结果
|
||||
*/
|
||||
private Result checkMeetingPermission(String meetingId) {
|
||||
GuildHallMeeting meeting = dao.fetch(GuildHallMeeting.class, meetingId);
|
||||
if (meeting == null) {
|
||||
return Result.error("会议不存在或已删除");
|
||||
}
|
||||
if (meeting.getGroupId() != null
|
||||
&& !activityBasicScopeService.isUserInGroup(meeting.getGroupId(), SecurityUtil.getUserId())) {
|
||||
return Result.error("您不在本次会议参与组别内");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -87,6 +87,7 @@ public class ThirtyTeachController {
|
||||
@ApiOperation("一键设置三十龄教工")
|
||||
@SaCheckPermission("thirtyTeach.manage")
|
||||
@SLog(type = "30龄教工-教职工管理", tag = "设置三十龄教工",msg = "设置三十龄教工设置教龄${args[0]}")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result setThirtyTeach(Integer setNum, boolean isFlag){
|
||||
if (isFlag) {
|
||||
sysUserService.update(Chain.make("isThirtyTeach", 0), Cnd.NEW());
|
||||
@@ -95,6 +96,8 @@ public class ThirtyTeachController {
|
||||
cnd.and("arrivalAtSchoolDate", "is not", null);
|
||||
cnd.and("arrivalAtSchoolDate", "!=", "");
|
||||
cnd.and(TEACH_NUM_SQL, ">", setNum);
|
||||
// 一键设置只标记已确认会员,确保设置范围与管理列表保持一致。
|
||||
cnd.and("member", "=", true);
|
||||
sysUserService.update(Chain.make("isThirtyTeach", 1), cnd);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
+2
@@ -55,6 +55,8 @@ public class ThirtyTeachServiceImpl extends BaseServiceImpl implements ThirtyTea
|
||||
sql.setVar("teachNumSql", new Static(TEACH_NUM_SQL));
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("isThirtyTeach", "=", 1);
|
||||
// 三十年教龄名单仅展示已确认会员,避免非会员进入管理及导出范围。
|
||||
cnd.and("member", "=", true);
|
||||
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.orLike("loginname", pageForm.getSearchKeyword());
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
</div>
|
||||
|
||||
<div class="search-query">
|
||||
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
|
||||
<el-button type="primary" icon="el-icon-search" :loading="tableLoading" @click="doSearch">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@@ -133,7 +133,8 @@
|
||||
删除{{ currentGroupName }}
|
||||
</el-button>
|
||||
</table-tool>
|
||||
<el-table ref="userTable" :data="tableData" stripe border :size="tableSize" @sort-change="pageOrder">
|
||||
<el-table ref="userTable" v-loading="tableLoading" element-loading-text="正在查询,请稍候..."
|
||||
:data="tableData" stripe border :size="tableSize" @sort-change="pageOrder">
|
||||
<el-table-column label="序号" type="index" width="80">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1 }}</span>
|
||||
@@ -334,12 +335,19 @@ module.exports = {
|
||||
const {data} = await $.post("/platform/activity/basic/scope/getRolesAndUnion")
|
||||
this.roleData = data
|
||||
},
|
||||
async pageData() {
|
||||
const resp = await $.post("/platform/activity/basic/user/pageData", this.pageForm)
|
||||
if (resp.code === 0) {
|
||||
this.tableData = resp.data.list
|
||||
this.pageForm.totalCount = resp.data.totalCount
|
||||
}
|
||||
pageData() {
|
||||
// 分页查询期间展示加载状态,避免慢查询时用户误以为页面无响应。
|
||||
this.tableLoading = true
|
||||
$.post("/platform/activity/basic/user/pageData", this.pageForm)
|
||||
.then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.tableData = resp.data.list
|
||||
this.pageForm.totalCount = resp.data.totalCount
|
||||
}
|
||||
})
|
||||
.always(() => {
|
||||
this.tableLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
|
||||
@@ -360,13 +360,15 @@
|
||||
v-for="item in sameTypeGroupList"
|
||||
:key="item.groupId"
|
||||
:label="item.groupId"
|
||||
:disabled="!isSelectedActivityGroup(item)"
|
||||
border
|
||||
class="existing-group-radio"
|
||||
>
|
||||
{{ formatGroupDisplayName(item) }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<div v-if="sameTypeGroupList.length === 0" class="form-tip">当前还没有同类型分组,请先创建新分组。</div>
|
||||
<div v-if="!selectedActivityGroup" class="form-tip">请先在筛选条件中选择活动组别。</div>
|
||||
<div v-else class="form-tip">仅允许添加至当前选择的活动组别:{{ formatGroupDisplayName(selectedActivityGroup) }}</div>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
|
||||
@@ -499,6 +501,9 @@ module.exports = {
|
||||
unionid() {
|
||||
return this.roleData.unionid
|
||||
},
|
||||
selectedActivityGroup() {
|
||||
return this.activityGroupList.find((item) => Number(item.groupId) === Number(this.pageForm.activityGroupId))
|
||||
},
|
||||
sameTypeGroupList() {
|
||||
return this.activityGroupList.filter((item) => Number(item.groupType) === Number(this.formData.groupType))
|
||||
}
|
||||
@@ -549,7 +554,11 @@ module.exports = {
|
||||
handleSetGroupModeChange() {
|
||||
if (this.formData.setGroupType === 1) {
|
||||
this.formData.setGroupName = ""
|
||||
if (!this.sameTypeGroupList.some((item) => item.groupId === this.formData.setGroupId)) {
|
||||
if (this.selectedActivityGroup) {
|
||||
// 原有分组只能使用当前筛选的活动组别,保存方式需与该分组类型一致。
|
||||
this.formData.groupType = Number(this.selectedActivityGroup.groupType)
|
||||
this.formData.setGroupId = this.selectedActivityGroup.groupId
|
||||
} else {
|
||||
this.formData.setGroupId = null
|
||||
}
|
||||
return
|
||||
@@ -557,10 +566,18 @@ module.exports = {
|
||||
this.formData.setGroupId = null
|
||||
},
|
||||
handleGroupTypeChange() {
|
||||
if (this.formData.setGroupType === 1 && this.selectedActivityGroup) {
|
||||
this.formData.groupType = Number(this.selectedActivityGroup.groupType)
|
||||
this.formData.setGroupId = this.selectedActivityGroup.groupId
|
||||
return
|
||||
}
|
||||
if (!this.sameTypeGroupList.some((item) => item.groupId === this.formData.setGroupId)) {
|
||||
this.formData.setGroupId = null
|
||||
}
|
||||
},
|
||||
isSelectedActivityGroup(group) {
|
||||
return this.selectedActivityGroup && Number(group.groupId) === Number(this.selectedActivityGroup.groupId)
|
||||
},
|
||||
handleActivityGroupChange(val) {
|
||||
this.pageForm.memberTypes = val ? [] : ["工会会员"]
|
||||
this.doSearch()
|
||||
|
||||
@@ -207,7 +207,8 @@
|
||||
|
||||
<el-table-column v-if="!is_view" label="操作" width="100px">
|
||||
<template v-slot="{row,$index}">
|
||||
<el-button size="mini" :disabled="nr.bzs.length<=1 || (!row.canDelete && row.id !== null)" type="danger" icon="el-icon-delete"
|
||||
<!-- 新建行没有 id 时允许删除;已保存行仍按 canDelete 控制删除权限。 -->
|
||||
<el-button size="mini" :disabled="nr.bzs.length<=1 || (!row.canDelete && row.id)" type="danger" icon="el-icon-delete"
|
||||
@click="nr.bzs.splice($index,1)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -329,7 +329,8 @@
|
||||
},
|
||||
actions: {}
|
||||
})
|
||||
$.get("/platform/sys/user/getLogonUser").then((res) => {
|
||||
// 暴露当前登录用户的加载状态,业务页面可在用户、角色和所属工会写入 store 后再执行初始化。
|
||||
window.logonUserReady = $.get("/platform/sys/user/getLogonUser").then((res) => {
|
||||
if (res.code === 0) {
|
||||
window.sessionStorage.setItem("user", JSON.stringify(res.data))
|
||||
store.commit("setUser", res.data)
|
||||
|
||||
@@ -14,9 +14,9 @@ layout("/layouts/platform.html"){
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<el-row type="flex" style="column-gap: 10px">
|
||||
<el-select v-model="pageForm.system_name" style="width: 180px" filterable clearable
|
||||
<el-select v-model="pageForm.moduleId" style="width: 180px" filterable clearable
|
||||
placeholder="请选择所属模块">
|
||||
<el-option v-for="item in menuOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" style="width: 300px"
|
||||
@keyup.enter.native="doSearch">
|
||||
@@ -75,15 +75,7 @@ layout("/layouts/platform.html"){
|
||||
<el-table-column sortable prop="sort" label="排序编号" align="center"></el-table-column>
|
||||
<el-table-column prop="code" sortable label="角色标识" align="center"
|
||||
:show-overflow-tooltip="true"></el-table-column>
|
||||
<!-- <el-table-column prop="menuName" label="所属模块" align="center" :show-overflow-tooltip="true" sortable>-->
|
||||
<!-- <template slot-scope="scope">
|
||||
<span v-if="scope.row.unit==null" style="font-weight: bold">
|
||||
系统角色
|
||||
</span>
|
||||
<span v-if="scope.row.unit!=null">
|
||||
{{scope.row.unit.name}}
|
||||
</span>
|
||||
</template>-->
|
||||
<el-table-column prop="moduleName" label="所属模块" align="center" :show-overflow-tooltip="true">
|
||||
</el-table-column>
|
||||
<el-table-column sortable prop="disabled" label="启用状态" align="center" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
@@ -135,11 +127,11 @@ layout("/layouts/platform.html"){
|
||||
<el-dialog append-to-body title="新建角色" :visible.sync="addDialogVisible" :close-on-click-modal="false"
|
||||
width="70%">
|
||||
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
|
||||
<!-- <el-form-item class="is-required" prop="system_name" label="所属系统" label-width="80px">-->
|
||||
<!-- <el-select v-model="formData.system_name" style="width: 100%" filterable clearable placeholder="请选择">-->
|
||||
<!-- <el-option v-for="item in menuOptions" :key="item.name" :label="item.name" :value="item.name"></el-option>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item prop="moduleId" label="所属模块">
|
||||
<el-select v-model="formData.moduleId" style="width: 100%" filterable placeholder="请选择所属模块">
|
||||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="name" label="角色名称">
|
||||
<el-input maxlength="50" placeholder="角色名称" v-model="formData.name" auto-complete="off" tabindex="2"
|
||||
type="text"></el-input>
|
||||
@@ -186,11 +178,11 @@ layout("/layouts/platform.html"){
|
||||
<el-input maxlength="150" placeholder="角色标识" v-model="formData.code" auto-complete="off"
|
||||
tabindex="3" type="text"></el-input>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item prop="code" label="所属系统">-->
|
||||
<!-- <el-select v-model="formData.system_name" style="width: 100%" filterable clearable placeholder="请选择">-->
|
||||
<!-- <el-option v-for="item in menuOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item prop="moduleId" label="所属模块">
|
||||
<el-select v-model="formData.moduleId" style="width: 100%" filterable placeholder="请选择所属模块">
|
||||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sort" label="排序编号">
|
||||
<el-input-number placeholder="排序编号" v-model="formData.sort"></el-input-number>
|
||||
</el-form-item>
|
||||
@@ -396,7 +388,7 @@ layout("/layouts/platform.html"){
|
||||
isLeaf: "leaf"
|
||||
},
|
||||
tableData: [],
|
||||
menuOptions: [],
|
||||
moduleOptions: [],
|
||||
options: [],
|
||||
parentUnit: [],
|
||||
parentUnitSearch: [],
|
||||
@@ -406,6 +398,7 @@ layout("/layouts/platform.html"){
|
||||
searchKeyword: "",
|
||||
searchName2: "username",
|
||||
searchKeyword2: "",
|
||||
moduleId: "",
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
totalCount: 0,
|
||||
@@ -415,6 +408,7 @@ layout("/layouts/platform.html"){
|
||||
formData: {
|
||||
id: "",
|
||||
unitid: "",
|
||||
moduleId: "",
|
||||
disabled: false,
|
||||
menuIds: ""
|
||||
},
|
||||
@@ -424,7 +418,8 @@ layout("/layouts/platform.html"){
|
||||
code: [
|
||||
{required: true, message: "角色标识", trigger: ["blur", "change"]},
|
||||
{validator: validateName, trigger: ["blur", "change"]}
|
||||
]
|
||||
],
|
||||
moduleId: [{required: true, message: "所属模块必填", trigger: ["blur", "change"]}]
|
||||
},
|
||||
editRules: {
|
||||
// parentUnit: [{ validator: validateUnit, trigger: ["blur", "change"] }],
|
||||
@@ -580,6 +575,14 @@ layout("/layouts/platform.html"){
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageData()
|
||||
},
|
||||
// 加载可选 PC 模块,创建、编辑和列表筛选共用同一数据源。
|
||||
loadModuleOptions() {
|
||||
this.$axios.post("/platform/sys/role/listModule").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "moduleOptions", res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
addMenuLoad() {
|
||||
this.$axios.post("/platform/sys/role/menuAll/", {}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
@@ -896,7 +899,8 @@ layout("/layouts/platform.html"){
|
||||
// this.menuOptions = data
|
||||
// }
|
||||
},
|
||||
async created() {
|
||||
created() {
|
||||
this.loadModuleOptions()
|
||||
this.pageData()
|
||||
// await this.getMenuOptions()
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ layout("/layouts/platform.html"){
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" @click="onAdd">
|
||||
<i class="ti-plus"></i>
|
||||
新增计划
|
||||
新增总结
|
||||
</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @sort-change="pageOrder" :size="tableSize">
|
||||
|
||||
+7
-1
@@ -31,7 +31,7 @@ let ASSSET_STOCKTAKING_FORM = {
|
||||
remote
|
||||
style="width: 100%"
|
||||
v-model="formData.assetUseUserId">
|
||||
<el-option :label="item.username+'-'+item.loginname"
|
||||
<el-option :label="item.username + (item.loginname ? '-' + item.loginname : '')"
|
||||
:value="item.id"
|
||||
:key="item.id"
|
||||
v-for="item in assetUseUserOption"></el-option>
|
||||
@@ -102,6 +102,12 @@ let ASSSET_STOCKTAKING_FORM = {
|
||||
this.$set(this.formData, "assetName", row.assetName)
|
||||
this.$set(this.formData, "assetUsedDate", row.assetUsedDate)
|
||||
this.$set(this.formData, "assetStorageLocation", row.assetStorageLocation)
|
||||
// 回显台账责任人,并预置为下拉选项以保证首次打开表单即可显示名称。
|
||||
this.$set(this.formData, "assetUseUserId", row.assetUseUserId || null)
|
||||
this.assetUseUserOption = row.assetUseUserId && row.assetUseUserName ? [{
|
||||
id: row.assetUseUserId,
|
||||
username: row.assetUseUserName
|
||||
}] : []
|
||||
},
|
||||
doSubmit(){
|
||||
this.$refs["AddForm"].validate((valid) => {
|
||||
|
||||
+29
-33
@@ -32,7 +32,7 @@ const kpiForm = {
|
||||
</el-button>
|
||||
</el-row>
|
||||
|
||||
<div>
|
||||
<div class="category-table-wrapper">
|
||||
<table>
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
@@ -44,7 +44,7 @@ const kpiForm = {
|
||||
<th style="width: 10%">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody ref="categoryList" style="height: 50vh;overflow-y: auto;display: table;width: 100%">
|
||||
<tbody ref="categoryList">
|
||||
<template v-for="(category,categoryIndex) in formData.categoryList">
|
||||
<tr v-for="(item,itemIndex) in category.items"
|
||||
:class="{'category-split':itemIndex+1===category.items.length}">
|
||||
@@ -129,7 +129,7 @@ const kpiForm = {
|
||||
</el-button>
|
||||
</el-row>
|
||||
<table class="score-levels-table">
|
||||
<thead class="bg-gray-50" style="display: table;width: 100%">
|
||||
<thead class="bg-gray-50">
|
||||
<tr>
|
||||
<th style="width: 30%;">最小分数</th>
|
||||
<th style="width: 30%;">最大分数</th>
|
||||
@@ -137,7 +137,7 @@ const kpiForm = {
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody ref="scoreLevels" style="display: table;width: 100%">
|
||||
<tbody ref="scoreLevels">
|
||||
<tr v-for="(scoreLevel,scoreLevelIndex) in formData.scoreLevels">
|
||||
<td>
|
||||
<el-input-number v-model="scoreLevel.min" :min="1"
|
||||
@@ -401,35 +401,31 @@ const kpiForm = {
|
||||
}
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.kpi-plus {
|
||||
/deep/ .kpi-plus {
|
||||
|
||||
}
|
||||
|
||||
.kpi-plus table {
|
||||
/deep/ .kpi-plus .category-table-wrapper {
|
||||
max-height: 50vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/deep/ .kpi-plus table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.kpi-plus table thead {
|
||||
background: #fafafa;
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: calc(100% - 1em);
|
||||
}
|
||||
|
||||
.kpi-plus table tbody {
|
||||
display: block;
|
||||
/deep/ .kpi-plus table thead {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.kpi-plus thead th,
|
||||
.kpi-plus tbody td {
|
||||
width: auto;
|
||||
min-width: 100px;
|
||||
/deep/ .kpi-plus thead th,
|
||||
/deep/ .kpi-plus tbody td {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.kpi-plus table thead th {
|
||||
/deep/ .kpi-plus table thead th {
|
||||
color: rgb(107 114 128);
|
||||
background: #fafafa;
|
||||
font-weight: 600;
|
||||
@@ -437,13 +433,13 @@ const kpiForm = {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.kpi-plus table tr:last-child {
|
||||
/deep/ .kpi-plus table tr:last-child {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.kpi-plus table tbody tr td {
|
||||
/deep/ .kpi-plus table tbody tr td {
|
||||
padding: 14px 20px;
|
||||
color: rgb(17 24 39);
|
||||
line-height: 20px;
|
||||
@@ -451,53 +447,53 @@ const kpiForm = {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.kpi-plus table tbody tr td:hover {
|
||||
/deep/ .kpi-plus table tbody tr td:hover {
|
||||
background: rgb(249 250 251);
|
||||
}
|
||||
|
||||
.kpi-plus table tbody tr td:hover .td-extra {
|
||||
/deep/ .kpi-plus table tbody tr td:hover .td-extra {
|
||||
opacity: 1;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.kpi-plus table tbody td.item-content {
|
||||
/deep/ .kpi-plus table tbody td.item-content {
|
||||
border-bottom: 1px solid rgb(229 231 235);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.kpi-plus table tbody .category-split td {
|
||||
/deep/ .kpi-plus table tbody .category-split td {
|
||||
border-bottom: 1px solid rgb(33 40 53) !important;
|
||||
}
|
||||
|
||||
.kpi-plus table tbody tr td[rowspan] {
|
||||
/deep/ .kpi-plus table tbody tr td[rowspan] {
|
||||
border-bottom: 1px solid rgb(33 40 53);
|
||||
}
|
||||
|
||||
.kpi-plus .score-levels-table .el-input-number{
|
||||
/deep/ .kpi-plus .score-levels-table .el-input-number{
|
||||
width: unset!important;
|
||||
}
|
||||
|
||||
|
||||
.td-extra {
|
||||
/deep/ .td-extra {
|
||||
/*display: none;*/
|
||||
/*opacity: 0;*/
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.td-extra .edit {
|
||||
/deep/ .td-extra .edit {
|
||||
color: #0a84ff;
|
||||
}
|
||||
|
||||
.td-extra .edit:hover {
|
||||
/deep/ .td-extra .edit:hover {
|
||||
color: #1375d8;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.td-extra .delete {
|
||||
/deep/ .td-extra .delete {
|
||||
color: #ff3b30;
|
||||
}
|
||||
|
||||
.td-extra .delete:hover {
|
||||
/deep/ .td-extra .delete:hover {
|
||||
color: #ec2216;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,16 @@ const cadreTrainingInfo = {
|
||||
<el-descriptions-item label="活动内容" > <div v-html="viewData.notice"></div></el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<table-tool label="人员信息"></table-tool>
|
||||
<el-descriptions :column="2" border class="flow-task-form">
|
||||
<el-table v-if="signUsersUrl" :data="signUsers" border class="flow-task-form">
|
||||
<el-table-column label="姓名" prop="userName"></el-table-column>
|
||||
<el-table-column label="工号" prop="loginName"></el-table-column>
|
||||
<el-table-column label="分工会" prop="unionName"></el-table-column>
|
||||
<el-table-column label="单位" prop="unitName"></el-table-column>
|
||||
<el-table-column label="性别" prop="sex" width="80"></el-table-column>
|
||||
<el-table-column label="手机号" prop="mobile"></el-table-column>
|
||||
<el-table-column label="备注" prop="remark"></el-table-column>
|
||||
</el-table>
|
||||
<el-descriptions v-else :column="2" border class="flow-task-form">
|
||||
<el-descriptions-item label="姓名">{{viewData.userName}}</el-descriptions-item>
|
||||
<el-descriptions-item label="分工会">{{viewData.unionName}}</el-descriptions-item>
|
||||
<el-descriptions-item label="单位">{{viewData.unitName}}</el-descriptions-item>
|
||||
@@ -67,11 +76,18 @@ const cadreTrainingInfo = {
|
||||
`,
|
||||
store,
|
||||
dicts: ["PROCESS_TASK_SUBMIT_TYPE"],
|
||||
props: {
|
||||
signUsersUrl: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
viewData: {},
|
||||
doneTasks: [],
|
||||
signUsers: [],
|
||||
row: null
|
||||
}
|
||||
},
|
||||
@@ -81,6 +97,7 @@ const cadreTrainingInfo = {
|
||||
this.row = row
|
||||
this.visible = true
|
||||
this.getInfo()
|
||||
this.getSignUsers()
|
||||
this.getDoneTasks()
|
||||
},
|
||||
|
||||
@@ -94,6 +111,24 @@ const cadreTrainingInfo = {
|
||||
// })
|
||||
},
|
||||
|
||||
// 查询当前查看范围内的报名人员;未传查询地址时保留公共组件原有的单人展示。
|
||||
getSignUsers() {
|
||||
this.$set(this, "signUsers", [])
|
||||
if (!this.signUsersUrl || !this.row) {
|
||||
return
|
||||
}
|
||||
this.$axios.post(this.signUsersUrl, {
|
||||
activityId: this.row.cadreTrainingActId,
|
||||
unionId: this.row.unionId
|
||||
}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "signUsers", res.data || [])
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取已办任务审批记录
|
||||
getDoneTasks() {
|
||||
this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => {
|
||||
|
||||
@@ -42,7 +42,9 @@ layout("/layouts/platform.html"){
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
<template #view>
|
||||
<cadre-training-info ref="cadreTrainingInfoRef"></cadre-training-info>
|
||||
<cadre-training-info
|
||||
ref="cadreTrainingInfoRef"
|
||||
sign-users-url="/platform/cadreTraining/mine/listSignUsers"></cadre-training-info>
|
||||
</template>
|
||||
</guava>
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ const signForm = {
|
||||
<!-- 个人报名信息 -->
|
||||
<div class="process-title">选择报名人员</div>
|
||||
<el-select
|
||||
v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, BRANCH_UNION_ADMIN')"
|
||||
v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, BRANCH_UNION_CHAIRMAN')"
|
||||
v-model="searchTeammateUserId"
|
||||
filterable
|
||||
clearable
|
||||
@@ -47,7 +47,7 @@ const signForm = {
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-button
|
||||
v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, BRANCH_UNION_ADMIN')"
|
||||
v-if="$auth.hasRoleOr('SYSADMIN, SCHOOL_UNION_ADMIN, BRANCH_UNION_CHAIRMAN')"
|
||||
class="ml5" type="primary" icon="el-icon-plus"
|
||||
@click="addTeamUser">添加
|
||||
</el-button>
|
||||
|
||||
@@ -132,44 +132,54 @@ const basicForm = {
|
||||
</div>
|
||||
</el-form>
|
||||
<el-row class="mt10" justify="end" type="flex">
|
||||
<el-button @click="$emit('refresh')">取消</el-button>
|
||||
<el-button v-if="activeName === 1" type="primary" @click="activeName = 0">上一步</el-button>
|
||||
<el-button v-if="activeName === 2" type="primary" @click="activeName = 1">上一步</el-button>
|
||||
<el-button v-if="activeName === 0" type="primary" @click="next()">下一步</el-button>
|
||||
<el-button v-if="activeName === 1" type="primary" @click="activeName = 2">下一步</el-button>
|
||||
<el-button @click="onSave" type="primary">保存</el-button>
|
||||
<el-button @click="onSubmit" type="primary">提交</el-button>
|
||||
<el-button :disabled="formLoading" @click="$emit('refresh')">取消</el-button>
|
||||
<el-button v-if="activeName === 1" :disabled="formLoading" type="primary" @click="activeName = 0">上一步</el-button>
|
||||
<el-button v-if="activeName === 2" :disabled="formLoading" type="primary" @click="activeName = 1">上一步</el-button>
|
||||
<el-button v-if="activeName === 0" :disabled="formLoading" type="primary" @click="next()">下一步</el-button>
|
||||
<el-button v-if="activeName === 1" :disabled="formLoading" type="primary" @click="activeName = 2">下一步</el-button>
|
||||
<el-button :disabled="formLoading" :loading="formLoading" @click="onSave" type="primary">保存</el-button>
|
||||
<el-button :disabled="formLoading" :loading="formLoading" @click="onSubmit" type="primary">提交</el-button>
|
||||
</el-row>
|
||||
|
||||
<el-dialog title="选择用户" :visible.sync="selectDialogVisible" width="70%" append-to-body>
|
||||
<div class="btn-group tool-button">
|
||||
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 260px">
|
||||
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
|
||||
<el-option label="工号" value="u.loginName"></el-option>
|
||||
<el-option label="姓名" value="u.userName"></el-option>
|
||||
<el-option label="手机" value="u.mobile"></el-option>
|
||||
<el-row>
|
||||
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 260px">
|
||||
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
|
||||
<el-option label="工号" value="u.loginName"></el-option>
|
||||
<el-option label="姓名" value="u.userName"></el-option>
|
||||
<el-option label="手机" value="u.mobile"></el-option>
|
||||
</el-select>
|
||||
</el-input>
|
||||
<el-select v-model="pageForm.sex" placeholder="请选择性别" clearable>
|
||||
<el-option label="男" value="男"></el-option>
|
||||
<el-option label="女" value="女"></el-option>
|
||||
</el-select>
|
||||
</el-input>
|
||||
<el-select v-model="pageForm.sex" placeholder="请选择性别" clearable>
|
||||
<el-option label="男" value="男"></el-option>
|
||||
<el-option label="女" value="女"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits" placeholder="请选择所属工会" filterable clearable>
|
||||
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable>
|
||||
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="pageForm.roleId" placeholder="请选择角色" filterable clearable>
|
||||
<el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-button icon="el-icon-search" @click="doSearch" type="primary"></el-button>
|
||||
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits" placeholder="请选择所属工会" filterable clearable>
|
||||
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable>
|
||||
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-button icon="el-icon-search" @click="doSearch" type="primary"></el-button>
|
||||
</el-row>
|
||||
<el-row class="mt10">
|
||||
<el-select v-model="pageForm.moduleId" @change="handleModuleChange" placeholder="请选择模块" filterable clearable>
|
||||
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-select v-model="pageForm.roleId" @change="doSearch" :disabled="!pageForm.moduleId" placeholder="请选择角色" filterable clearable>
|
||||
<el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-select v-if="isDemocraticModule" v-model="pageForm.teacherCongressSessionId" @change="doSearch" placeholder="请选择教代会届次" filterable clearable>
|
||||
<el-option v-for="item in teacherCongressOptions" :key="item.id" :label="item.fullName" :value="item.id"></el-option>
|
||||
</el-select>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="left-span-label mt20">人员列表</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
@selection-change="handleSelectionChange"
|
||||
row-key="id"
|
||||
row-key="userId"
|
||||
ref="tableRef"
|
||||
>
|
||||
<el-table-column type="selection" reserve-selection width="60"></el-table-column>
|
||||
@@ -204,6 +214,7 @@ const basicForm = {
|
||||
data() {
|
||||
return {
|
||||
activeName: 0,
|
||||
formLoading: false,
|
||||
formData: {
|
||||
timePeriods: [{ canLeave: false }],
|
||||
},
|
||||
@@ -219,14 +230,25 @@ const basicForm = {
|
||||
|
||||
selectDialogVisible: false,
|
||||
roleList: [],
|
||||
moduleOptions: [],
|
||||
selectUsers: [],
|
||||
pageForm: {
|
||||
searchName: 'u.userName',
|
||||
moduleId: '',
|
||||
roleId: '',
|
||||
teacherCongressSessionId: '',
|
||||
},
|
||||
teacherCongressOptions: [],
|
||||
workerCongressOptions: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 民主管理模块才需要按教代会届次筛选人员。
|
||||
isDemocraticModule() {
|
||||
const module = this.moduleOptions.find((item) => item.id === this.pageForm.moduleId)
|
||||
return module && module.name === '民主管理'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
next() {
|
||||
if(!this.formData.typeId) {
|
||||
@@ -269,9 +291,31 @@ const basicForm = {
|
||||
}
|
||||
this.selectDialogVisible = false
|
||||
},
|
||||
async getRoleList() {
|
||||
const resp = await this.$axios.post("/platform/sys/msg/getRoleList")
|
||||
return resp.data
|
||||
// 查询选择用户时可用的 PC 端模块。
|
||||
queryModule() {
|
||||
this.$axios.post("/platform/meeting/manage/listModule").then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "moduleOptions", res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 模块变更后重置关联条件,并按当前模块刷新角色候选项。
|
||||
handleModuleChange(moduleId) {
|
||||
this.$set(this.pageForm, "roleId", "")
|
||||
this.$set(this.pageForm, "teacherCongressSessionId", "")
|
||||
this.$set(this, "roleList", [])
|
||||
if (moduleId) {
|
||||
this.queryRoleByModule(moduleId)
|
||||
}
|
||||
this.doSearch()
|
||||
},
|
||||
// 角色仅查询当前选中模块下的启用角色。
|
||||
queryRoleByModule(moduleId) {
|
||||
this.$axios.post("/platform/meeting/manage/listRole", {moduleId: moduleId}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.$set(this, "roleList", res.data)
|
||||
}
|
||||
})
|
||||
},
|
||||
openSelect() {
|
||||
this.selectDialogVisible = true
|
||||
@@ -297,6 +341,7 @@ const basicForm = {
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
this.formLoading = true
|
||||
this.$axios.post('/platform/meeting/manage/submit', {
|
||||
data: JSON.stringify(this.formData),
|
||||
users: JSON.stringify(this.userTableData)
|
||||
@@ -307,6 +352,8 @@ const basicForm = {
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.formLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
@@ -340,17 +387,21 @@ const basicForm = {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(async () => {
|
||||
const resp = await this.$axios.post("/platform/meeting/manage/submit", {
|
||||
}).then(() => {
|
||||
this.formLoading = true
|
||||
this.$axios.post("/platform/meeting/manage/submit", {
|
||||
data: JSON.stringify(this.formData),
|
||||
users: JSON.stringify(this.userTableData)
|
||||
}).then((resp) => {
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
this.$emit('refresh')
|
||||
} else {
|
||||
this.$message.warning(resp.msg)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.formLoading = false
|
||||
})
|
||||
if (resp.code === 0) {
|
||||
this.$message.success(resp.msg)
|
||||
this.$emit('refresh')
|
||||
} else {
|
||||
this.$message.warning(resp.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -382,11 +433,11 @@ const basicForm = {
|
||||
})
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
created() {
|
||||
this.queryMeetingType()
|
||||
this.queryTeacherCongress()
|
||||
this.queryWorkerCongress()
|
||||
this.roleList = await this.getRoleList()
|
||||
this.queryModule()
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ layout("/layouts/platform.html"){
|
||||
<el-row justify="space-around" style="border-top: 1px solid #ebeef5;padding: 10px 0 0 0" type="flex">
|
||||
<el-button v-if="tp.joinStatus === true" @click="onLeave(tp)" size="medium" type="text">请假</el-button>
|
||||
<el-button v-if="tp.joinStatus === false" size="medium" type="text" disabled>您已请假</el-button>
|
||||
<el-button v-if="tp.signStatus === false" @click="onSign(tp)" size="medium" type="text">签到</el-button>
|
||||
<el-button v-if="tp.signStatus === false" :disabled="isSignDisabled(tp.startTime)" @click="onSign(tp)" size="medium" type="text">签到</el-button>
|
||||
<el-button v-if="tp.signStatus === true" size="medium" type="text" disabled>您已签到</el-button>
|
||||
</el-row>
|
||||
</el-card>
|
||||
@@ -127,6 +127,10 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 场次开始前禁用签到,避免用户在会议开始前提交签到操作。
|
||||
isSignDisabled(startTime) {
|
||||
return this.$moment().isBefore(this.$moment(startTime))
|
||||
},
|
||||
onLeave(row) {
|
||||
if(!row.canLeave) {
|
||||
this.$message.warning('该场次不能请假')
|
||||
|
||||
@@ -180,11 +180,11 @@ layout("/layouts/platform.html"){
|
||||
</el-row>
|
||||
|
||||
<el-table :data="userData" :max-height="signTableHeight" class="mt20" ref="signTable">
|
||||
<el-table-column label="姓名" prop="username"></el-table-column>
|
||||
<el-table-column label="工号" prop="loginname"></el-table-column>
|
||||
<el-table-column label="姓名" prop="userName"></el-table-column>
|
||||
<el-table-column label="工号" prop="loginName"></el-table-column>
|
||||
<el-table-column label="性别" prop="sex"></el-table-column>
|
||||
<el-table-column label="单位" prop="unitname"></el-table-column>
|
||||
<el-table-column label="签到时间" prop="signInDateTime"></el-table-column>
|
||||
<el-table-column label="单位" prop="unitName"></el-table-column>
|
||||
<el-table-column label="签到时间" prop="signTime"></el-table-column>
|
||||
<el-table-column label="签到名次">
|
||||
<template slot-scope="scope">
|
||||
{{userData.length - scope.$index}}
|
||||
@@ -271,8 +271,8 @@ layout("/layouts/platform.html"){
|
||||
ud.unshift(...resp.data.userData)
|
||||
let uMap = new Map()
|
||||
for (let u of ud) {
|
||||
if (!uMap.has(u.loginname)) {
|
||||
uMap.set(u.loginname, u)
|
||||
if (!uMap.has(u.loginName)) {
|
||||
uMap.set(u.loginName, u)
|
||||
}
|
||||
}
|
||||
this.$set(this, 'userData', [...uMap.values()])
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
const optionImg = {
|
||||
template: /*language=HTML*/ `
|
||||
<el-dialog :visible.sync="visible" title="设置图片" append-to-body width="700px">
|
||||
<div style="background: #f7f8f9;text-align: center;border: solid 1px #d7d8d9;border-radius: 4px;">
|
||||
<el-upload
|
||||
action="/platform/sys/file/uploadDynamicReturnUrl"
|
||||
:show-file-list="false"
|
||||
:on-success="handleSuccess"
|
||||
:before-upload="beforeUpload">
|
||||
<img v-if="img" :src="img" class="avatar">
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
||||
</el-upload>
|
||||
</div>
|
||||
<div style="padding: 10px 0">
|
||||
请上传图片
|
||||
</div>
|
||||
<file-upload
|
||||
:upload_number="1"
|
||||
:value.sync="img"
|
||||
accept=".jpg,.jpeg,.png"
|
||||
upload_mode="image"
|
||||
upload_result_category="interval"
|
||||
upload_result_type="url"
|
||||
></file-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="onConfirm">确 定</el-button>
|
||||
@@ -29,21 +24,10 @@ const optionImg = {
|
||||
},
|
||||
methods: {
|
||||
onOpen(img = null, ext) {
|
||||
this.img = img
|
||||
this.img = img || ""
|
||||
this.ext = ext
|
||||
this.visible = true
|
||||
},
|
||||
handleSuccess(response, file, fileList) {
|
||||
console.log(response)
|
||||
console.log(file)
|
||||
console.log(fileList)
|
||||
if (response.code === 0) {
|
||||
this.img = response.data
|
||||
// this.img = "/platform/sys/file/download?id=t38dmq4beuhrupqb54prl52t4u"
|
||||
this.$message.success("图片上传成功")
|
||||
}
|
||||
},
|
||||
beforeUpload(file) {},
|
||||
onConfirm() {
|
||||
this.$emit("confirm", {
|
||||
img: this.img,
|
||||
@@ -51,33 +35,5 @@ const optionImg = {
|
||||
})
|
||||
this.visible = false
|
||||
}
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
.avatar-uploader .el-upload {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload:hover {
|
||||
border-color: #409EFF;
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
line-height: 178px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 178px;
|
||||
height: 178px;
|
||||
display: block;
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ layout("/layouts/platform.html"){
|
||||
|
||||
.qsv-online-drawer .el-drawer__body {
|
||||
padding: 0;
|
||||
background: #f5f7fa;
|
||||
background: #eef4ff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
@@ -53,7 +53,7 @@ layout("/layouts/platform.html"){
|
||||
min-height: 0;
|
||||
max-height: none;
|
||||
overflow-y: auto;
|
||||
padding: 16px 24px 32px;
|
||||
padding: 20px 24px 32px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -101,50 +101,59 @@ layout("/layouts/platform.html"){
|
||||
}
|
||||
|
||||
.qsv-online-vote {
|
||||
max-width: 800px;
|
||||
max-width: 1040px;
|
||||
margin: 0 auto;
|
||||
background: #fff7f2;
|
||||
background: transparent;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.qsv-online-vote-header {
|
||||
padding: 36px 20px 22px;
|
||||
background: radial-gradient(circle at right top, #fff 0, #fff7f2 42%, #fffdfb 100%);
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.qsv-online-vote-title {
|
||||
margin: 0 0 28px;
|
||||
color: #ff4d00;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.qsv-online-vote-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
border: 1px solid #ff7b3c;
|
||||
border-radius: 10px;
|
||||
padding: 18px 10px;
|
||||
background: rgba(255, 255, 255, .55);
|
||||
min-height: 90px;
|
||||
border: 1px solid #d7e4ff;
|
||||
border-radius: 12px;
|
||||
padding: 0 12px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 3px 8px rgba(46, 107, 214, .08);
|
||||
}
|
||||
|
||||
.qsv-online-vote-stat strong {
|
||||
display: block;
|
||||
color: #ff4d00;
|
||||
font-size: 24px;
|
||||
color: #2468e8;
|
||||
font-size: 22px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.qsv-online-vote-stat span {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
margin-top: 6px;
|
||||
color: #6f7f9d;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.qsv-online-vote-stat + .qsv-online-vote-stat {
|
||||
border-left: 1px solid #e2ebfb;
|
||||
}
|
||||
|
||||
.qsv-online-vote-rank {
|
||||
color: #ff4d00;
|
||||
color: #2468e8;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -153,113 +162,104 @@ layout("/layouts/platform.html"){
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 16px 22px;
|
||||
color: #ff4d00;
|
||||
background: #fff4ee;
|
||||
font-size: 14px;
|
||||
margin-top: 12px;
|
||||
padding: 10px 16px;
|
||||
border: 1px solid #d7e4ff;
|
||||
border-radius: 10px;
|
||||
color: #3f5b88;
|
||||
background: #ffffff;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 3px 8px rgba(46, 107, 214, .05);
|
||||
}
|
||||
|
||||
.qsv-online-vote-countdown b {
|
||||
display: inline-block;
|
||||
min-width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 2px;
|
||||
background: #ff5a1f;
|
||||
min-width: 24px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
background: #2f70e8;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 22px;
|
||||
line-height: 20px;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-search {
|
||||
display: flex;
|
||||
border-top: 8px solid #ffd8c5;
|
||||
border-bottom: 8px solid #ffd8c5;
|
||||
background: #fff;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.qsv-online-vote-search .el-input__inner {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
height: 36px;
|
||||
border: 1px solid #cfe0ff;
|
||||
border-radius: 9px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.qsv-online-vote-search .el-button {
|
||||
width: 120px;
|
||||
width: 68px;
|
||||
height: 36px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-left: 1px solid #ebeef5;
|
||||
border-radius: 0;
|
||||
color: #ff4d00;
|
||||
border-radius: 9px;
|
||||
color: #ffffff;
|
||||
background: #2f70e8;
|
||||
}
|
||||
|
||||
.qsv-online-vote-subject {
|
||||
padding: 18px 20px 24px;
|
||||
background: #fff;
|
||||
padding: 14px 0 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.qsv-online-vote-subject-title {
|
||||
margin-bottom: 16px;
|
||||
font-size: 16px;
|
||||
line-height: 1.55;
|
||||
margin-bottom: 10px;
|
||||
color: #18345e;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.qsv-online-vote-subject-title em {
|
||||
color: #909399;
|
||||
color: #6d82a7;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list-2,
|
||||
.qsv-online-vote-option-list-3 {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list-2 {
|
||||
gap: 12px;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list-3 {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.qsv-online-vote-option {
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid transparent;
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
margin: 0;
|
||||
border: 1px solid #d2e1fb;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
transition: border-color .2s, background-color .2s;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list-2 .qsv-online-vote-option,
|
||||
.qsv-online-vote-option-list-3 .qsv-online-vote-option {
|
||||
min-width: 0;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 3px 8px rgba(46, 107, 214, .05);
|
||||
transition: border-color .2s, box-shadow .2s, background-color .2s;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option.active {
|
||||
border-color: #ff4d00;
|
||||
background: #fff8f4;
|
||||
border-color: #2f70e8;
|
||||
background: #f3f7ff;
|
||||
box-shadow: 0 4px 12px rgba(47, 112, 232, .14);
|
||||
}
|
||||
|
||||
.qsv-online-vote-img {
|
||||
position: relative;
|
||||
height: 260px;
|
||||
border-radius: 6px;
|
||||
background: #f4f4f4;
|
||||
height: 174px;
|
||||
border-radius: 0;
|
||||
background: #eaf2ff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list-2 .qsv-online-vote-img {
|
||||
height: 210px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list-3 .qsv-online-vote-img {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-img img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -272,17 +272,16 @@ layout("/layouts/platform.html"){
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ff7b3c;
|
||||
font-size: 42px;
|
||||
color: #9fc0f8;
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
background: linear-gradient(135deg, #fff7f2, #ffe4d7);
|
||||
background: linear-gradient(135deg, #f6f9ff, #dfebff);
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-body {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
display: block;
|
||||
min-height: 58px;
|
||||
padding: 10px 12px 12px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-text {
|
||||
@@ -292,19 +291,71 @@ layout("/layouts/platform.html"){
|
||||
|
||||
.qsv-online-vote-option-text strong {
|
||||
display: block;
|
||||
color: #ff4d00;
|
||||
margin-bottom: 4px;
|
||||
color: #4b74bf;
|
||||
margin-bottom: 5px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-text span {
|
||||
color: #303133;
|
||||
color: #18345e;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-actions {
|
||||
flex-shrink: 0;
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 7px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-actions .el-button {
|
||||
padding: 4px 0;
|
||||
color: #2f70e8;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-check {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-check .el-checkbox__label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-check .el-checkbox__inner {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-color: #9ebdf1;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, .92);
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-check .el-checkbox__input.is-checked .el-checkbox__inner {
|
||||
border-color: #2f70e8;
|
||||
background: #2f70e8;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-check .el-checkbox__input.is-checked .el-checkbox__inner::after {
|
||||
top: 3px;
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 720px) {
|
||||
.qsv-online-preview-body {
|
||||
padding: 14px 12px 24px;
|
||||
}
|
||||
|
||||
.qsv-online-vote-option-list {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.qsv-online-vote-img {
|
||||
height: 190px;
|
||||
}
|
||||
}
|
||||
|
||||
.qsv-online-footer {
|
||||
@@ -487,12 +538,18 @@ layout("/layouts/platform.html"){
|
||||
</em>
|
||||
<em v-else>【请选择{{currentVoteSubject.type === 'radio' ? '1' : '至少1'}}项】</em>
|
||||
</div>
|
||||
<div :class="getVoteOptionListClass(currentVoteSubject)">
|
||||
<div class="qsv-online-vote-option-list">
|
||||
<div
|
||||
v-for="(option, index) in filteredVoteOptions"
|
||||
:key="option.id"
|
||||
:class="['qsv-online-vote-option', isOptionSelected(currentVoteSubject, option.id) ? 'active' : '']"
|
||||
@click="toggleVoteOption(option)">
|
||||
<el-checkbox
|
||||
class="qsv-online-vote-option-check"
|
||||
:value="isOptionSelected(currentVoteSubject, option.id)"
|
||||
:disabled="answerDialog.readonly || isVoteEnd"
|
||||
@click.native.stop="toggleVoteOption(option)">
|
||||
</el-checkbox>
|
||||
<div class="qsv-online-vote-img" v-if="option.imgUrl">
|
||||
<img :src="option.imgUrl" alt="">
|
||||
</div>
|
||||
@@ -500,11 +557,6 @@ layout("/layouts/platform.html"){
|
||||
<span>{{index + 1}}</span>
|
||||
</div>
|
||||
<div class="qsv-online-vote-option-body">
|
||||
<el-checkbox
|
||||
:value="isOptionSelected(currentVoteSubject, option.id)"
|
||||
:disabled="answerDialog.readonly || isVoteEnd"
|
||||
@click.native.stop="toggleVoteOption(option)">
|
||||
</el-checkbox>
|
||||
<div class="qsv-online-vote-option-text">
|
||||
<strong>{{getVoteOptionVotes(option.id)}}票({{getVoteOptionPercent(option.id)}}%)</strong>
|
||||
<span>{{option.text}}</span>
|
||||
|
||||
+25
-1
@@ -2,6 +2,29 @@
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
|
||||
<style>
|
||||
/* 固定会议编辑弹框,避免表单内容撑高整个弹框。 */
|
||||
.guild-hall-meeting-dialog {
|
||||
height: calc(100vh - 120px);
|
||||
max-width: calc(100vw - 32px);
|
||||
max-height: 700px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.guild-hall-meeting-dialog .el-dialog__header,
|
||||
.guild-hall-meeting-dialog .el-dialog__footer {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 表单内容超出可用高度时,仅在弹框内容区内滚动。 */
|
||||
.guild-hall-meeting-dialog .el-dialog__body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
@@ -34,7 +57,8 @@ layout("/layouts/platform.html"){
|
||||
<!--#include("/layouts/pagination.html"){}#-->
|
||||
</el-card>
|
||||
|
||||
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogVisible" width="70%">
|
||||
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogVisible" width="1000px"
|
||||
custom-class="guild-hall-meeting-dialog">
|
||||
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px">
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名称"></el-input>
|
||||
|
||||
@@ -428,6 +428,7 @@ layout("/layouts/platform.html"){
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
store,
|
||||
mixins: [initTableMixins],
|
||||
data() {
|
||||
return {
|
||||
@@ -644,25 +645,47 @@ layout("/layouts/platform.html"){
|
||||
},
|
||||
getTreeData() {
|
||||
const hasAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN", "SCHOOL_UNION_MEMBER_ADMIN"])
|
||||
const unionId = hasAdmin ? null : this.$store.state.user.union.id
|
||||
this.$businessTool.listUnion(unionId).then((data) => {
|
||||
const currentUser = this.$store.state.user || {}
|
||||
const currentUnion = currentUser.union || {}
|
||||
const unionId = hasAdmin ? null : currentUnion.id
|
||||
const setTreeData = (data) => {
|
||||
const unionList = data || []
|
||||
// 仅有一个可选分工会时默认收起左栏,仍可通过折叠按钮手动展开。
|
||||
this.treeCollapsed = unionList.length === 1
|
||||
this.treeData = [{
|
||||
id: this.unionRootId,
|
||||
name: "工会委员会",
|
||||
type: "root",
|
||||
children: (data || []).map((item) => ({
|
||||
children: unionList.map((item) => ({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: "union"
|
||||
}))
|
||||
}]
|
||||
this.$nextTick(() => {
|
||||
this.currentTreeData = this.treeData[0]
|
||||
this.setCurrentTreeNode(this.unionRootId)
|
||||
if (this.tabActive !== "memberList") {
|
||||
this.tabActive = "memberList"
|
||||
}
|
||||
// 唯一分工会作为默认查询节点;多条或无数据时继续使用工会根节点。
|
||||
const defaultNode = unionList.length === 1 ? this.treeData[0].children[0] : this.treeData[0]
|
||||
this.treeNodeClick(defaultNode)
|
||||
this.setCurrentTreeNode(defaultNode.id)
|
||||
this.updateTableHeight()
|
||||
if (this.$refs.memberTableRef) {
|
||||
this.$refs.memberTableRef.doLayout()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 非管理员只能加载本人所属分工会;用户信息异常时保留根节点,禁止空参数查询全部分工会。
|
||||
if (!hasAdmin && !unionId) {
|
||||
setTreeData([])
|
||||
return
|
||||
}
|
||||
this.$businessTool.listUnion(unionId).then((data) => {
|
||||
setTreeData(data)
|
||||
}).catch(() => {
|
||||
// 组织树加载失败时回退到根节点,会员列表仍按后端数据权限正常查询。
|
||||
setTreeData([])
|
||||
})
|
||||
},
|
||||
setCurrentTreeNode(nodeKey) {
|
||||
@@ -764,8 +787,17 @@ layout("/layouts/platform.html"){
|
||||
created() {
|
||||
this.checkedFields = this.tableColumns.filter(c => c.checked !== 0).map(c => c.prop);
|
||||
this.initDefaultView()
|
||||
this.getTreeData()
|
||||
this.pageData()
|
||||
const initPage = () => {
|
||||
this.getTreeData()
|
||||
}
|
||||
// 等待公共布局完成当前登录用户回显,避免首次登录或切换账号时读取不到所属分工会。
|
||||
if (window.logonUserReady && window.logonUserReady.always) {
|
||||
window.logonUserReady.always(() => {
|
||||
initPage()
|
||||
})
|
||||
} else {
|
||||
initPage()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const tabsContent = this.$el.querySelector(".member-group-list-card .el-tabs__content")
|
||||
|
||||
+3
@@ -149,6 +149,9 @@ let H5_ASSET_STOCKTAKING_FORM = {
|
||||
this.$set(this.formData, "assetName", row.assetName)
|
||||
this.$set(this.formData, "assetUsedDate", row.assetUsedDate)
|
||||
this.$set(this.formData, "assetStorageLocation", row.assetStorageLocation)
|
||||
// 回显台账责任人;用户可通过责任人选择面板重新搜索并替换。
|
||||
this.$set(this.formData, "assetUseUserId", row.assetUseUserId || null)
|
||||
this.$set(this.formData, "assetUseName", row.assetUseUserName || null)
|
||||
this.assetUsageStateNameOption = await this.$businessTool.getDictOptions("ASSET_USAGE_STATE")
|
||||
this.visible = true
|
||||
},
|
||||
|
||||
@@ -58,9 +58,9 @@ layout("/layouts/platform_h5.html"){
|
||||
</div>
|
||||
</div>
|
||||
<div class="sign_button">
|
||||
<van-button v-if="item.joinStatus === true" @click.stop="onLeave(item)" size="mini" type="info">请假</van-button>
|
||||
<van-button v-if="item.joinStatus === true" :disabled="leaveLoading" :loading="leaveLoading" @click.stop="onLeave(item)" size="mini" type="info">请假</van-button>
|
||||
<van-button v-if="item.joinStatus === false" size="mini" type="info" disabled>您已请假</van-button>
|
||||
<van-button v-if="item.signStatus === false" @click.stop="onSign(item)" size="mini" type="info">签到</van-button>
|
||||
<van-button v-if="item.signStatus === false" :disabled="leaveLoading || isSignDisabled(item.startTime)" @click.stop="onSign(item)" size="mini" type="info">签到</van-button>
|
||||
<van-button v-if="item.signStatus === true" size="mini" type="info" disabled>您已签到</van-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -109,9 +109,14 @@ layout("/layouts/platform_h5.html"){
|
||||
reasonVisible: false,
|
||||
leaveReason: '',
|
||||
periodRow: {},
|
||||
leaveLoading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 场次开始前禁用签到,避免用户在会议开始前提交签到操作。
|
||||
isSignDisabled(startTime) {
|
||||
return this.$moment().isBefore(this.$moment(startTime))
|
||||
},
|
||||
async onReady() {
|
||||
const typeList = await this.queryMeetingType()
|
||||
this.typeOptions = [
|
||||
@@ -131,18 +136,27 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$toast('请输入请假事由')
|
||||
done(false)
|
||||
} else {
|
||||
this.leaveLoading = true
|
||||
this.$axios.post("/platform/meeting/mine/leave", {
|
||||
periodId: this.periodRow.id,
|
||||
leaveReason: this.leaveReason,
|
||||
})
|
||||
.then((res) => {
|
||||
done()
|
||||
this.$toast(res.msg)
|
||||
if (res.code === 0) {
|
||||
done()
|
||||
this.doSearch()
|
||||
this.reasonVisible = false
|
||||
this.leaveVisible = false
|
||||
} else {
|
||||
done(false)
|
||||
}
|
||||
}).catch(() => { done() })
|
||||
}).catch(() => {
|
||||
done(false)
|
||||
}).finally(() => {
|
||||
// 请假请求结束后恢复按钮状态,接口失败时允许用户修正事由后重新提交。
|
||||
this.leaveLoading = false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
done()
|
||||
|
||||
@@ -113,6 +113,15 @@ layout("/layouts/platform_h5.html"){
|
||||
this.$axios.post("/platform/h5/qsv/quiz/subjects", {activityId: this.id}).then((res) => {
|
||||
if (res.code === 0) {
|
||||
this.activity = res.data.activity
|
||||
// 历史链接可能误将投票或问卷指向答题页,按活动实际类型跳转到对应的移动端入口。
|
||||
if (this.activity.category === "VOTE") {
|
||||
pjaxReplace("/platform/h5/qsv/vote?id=" + this.id)
|
||||
return
|
||||
}
|
||||
if (this.activity.category === "SURVEY") {
|
||||
pjaxReplace("/platform/h5/qsv/survey?id=" + this.id)
|
||||
return
|
||||
}
|
||||
this.subjects = res.data.subjects
|
||||
this.answerRecordId = res.data.answerRecordId
|
||||
// this.checkGroupPermission()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user