diff --git a/src/main/java/com/budwk/app/flow/handler/FlowFghzxAssignmentHandler.java b/src/main/java/com/budwk/app/flow/handler/FlowFghzxAssignmentHandler.java index ffa9b088..7b8f16f8 100644 --- a/src/main/java/com/budwk/app/flow/handler/FlowFghzxAssignmentHandler.java +++ b/src/main/java/com/budwk/app/flow/handler/FlowFghzxAssignmentHandler.java @@ -15,7 +15,7 @@ public class FlowFghzxAssignmentHandler implements AssignmentHandler { @Override public List assign(TaskModel model, Execution execution) { Dao dao = ServiceContext.find(Dao.class); - return List.of(); + return List.of("17a7f8ad3ee947b4a26175049a9c253d"); } @Override diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java index 5e502c40..cf38b46c 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java @@ -78,17 +78,17 @@ public class SysMsgServiceImpl extends BaseServiceImpl implements SysMs List viewUsers = Daos.ext(dao(), fieldFilter).query(View_user.class, cnd); List list = new CopyOnWriteArrayList<>(); for (View_user viewUser : viewUsers) { - Sys_msg_user sys_msg_user = new Sys_msg_user(); - sys_msg_user.setId(R.UU32()); - sys_msg_user.setMsgId(sysMsg.getId()); - sys_msg_user.setStatus(0); - sys_msg_user.setLoginname(viewUser.getLoginname()); - sys_msg_user.setUserName(viewUser.getUsername()); - sys_msg_user.setUnitId(viewUser.getUnitId()); - sys_msg_user.setUnitName(viewUser.getUnitName()); - sys_msg_user.setUnionId(viewUser.getUnionId()); - sys_msg_user.setUnionName(viewUser.getUnionName()); - list.add(sys_msg_user); + Sys_msg_user sysMsgUser = new Sys_msg_user(); + sysMsgUser.setId(R.UU32()); + sysMsgUser.setMsgId(sysMsg.getId()); + sysMsgUser.setStatus(0); + sysMsgUser.setLoginname(viewUser.getLoginname()); + sysMsgUser.setUserName(viewUser.getUsername()); + sysMsgUser.setUnitId(viewUser.getUnitId()); + sysMsgUser.setUnitName(viewUser.getUnitName()); + sysMsgUser.setUnionId(viewUser.getUnionId()); + sysMsgUser.setUnionName(viewUser.getUnionName()); + list.add(sysMsgUser); } dao().fastInsert(list); sysMsgUserService.clearCache(); @@ -106,12 +106,13 @@ public class SysMsgServiceImpl extends BaseServiceImpl implements SysMs // smsService.send(loginName, sysMsg.getTitle(), sysMsg.getNote()); // } ThreadUtil.execute(() -> { - smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl()); + //smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl()); }); return sysMsg; } + @Override @Aop(TransAop.READ_COMMITTED) public void deleteMsg(String id) { this.delete(id); @@ -208,8 +209,10 @@ public class SysMsgServiceImpl extends BaseServiceImpl implements SysMs public void innerMsg(String room, int size, List list) { NutMap map = new NutMap(); map.put("action", "innerMsg"); - map.put("size", size);//未读消息数 - map.put("list", list);//最新5条消息列表 type--系统消息/用户消息 title--标题 time--时间戳 + //未读消息数 + map.put("size", size); + //最新5条消息列表 type--系统消息/用户消息 title--标题 time--时间戳 + map.put("list", list); String msg = Json.toJson(map, JsonFormat.compact()); log.debug("msg::::" + msg); if (jedisAgent.isClusterMode()) { diff --git a/src/main/java/com/budwk/app/zhgh/activity/basic/models/ActivityBasicSettings.java b/src/main/java/com/budwk/app/zhgh/activity/basic/models/ActivityBasicSettings.java index 6691146e..f475ce54 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/basic/models/ActivityBasicSettings.java +++ b/src/main/java/com/budwk/app/zhgh/activity/basic/models/ActivityBasicSettings.java @@ -63,5 +63,8 @@ public class ActivityBasicSettings extends BaseModel implements Serializable { private List child; - + @Column + @Comment("服装项目") + @Default("0") + private Boolean clothing; } diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/constant/ColumnFormTypeEnum.java b/src/main/java/com/budwk/app/zhgh/activity/family/constant/ColumnFormTypeEnum.java new file mode 100644 index 00000000..9acbcd08 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/constant/ColumnFormTypeEnum.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.activity.family.constant; + +import com.budwk.app.base.annotation.DictEnum; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @Author JyuHsin + * @Date 2022/11/18 + * @Description + */ +@Getter +@DictEnum(key = "ColumnFormTypeEnum", name = "控件类型") +@AllArgsConstructor +public enum ColumnFormTypeEnum { + + INPUT("INPUT", "输入框"), + SELECT("SELECT", "选择框"), + //RADIO("RADIO", "单选框"),//选项数组 + FILE("FILE", "文件"); + + private String code; + private String description; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityAddController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityAddController.java new file mode 100644 index 00000000..67aa12fa --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityAddController.java @@ -0,0 +1,96 @@ +package com.budwk.app.zhgh.activity.family.controller.manage; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.activity.family.models.FamilyActivity; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @author zxy + * @Description 新建活动 + * @createTime 2022年03月07日 10:16:00 + */ +@Slf4j +@IocBean +@Api(tags = "新建亲子活动") +@At("/platform/family/manage/activity") +public class FamilyActivityAddController { + + @Inject + private Dao dao; + @Inject + private FamilyActivityService familyActivityManageService; + + @At + @Ok("json:full") + @ApiOperation("亲子活动新增/修改") + @SaCheckPermission("family.manage.activity") + @SLog(type = "family", tag = "新增/修改活动", msg = "新增/修改活动") + public Result doHandle(FamilyActivity activity) { + if (StrUtil.isBlank(activity.getId())) { + familyActivityManageService.add(activity, null); + } else { + familyActivityManageService.edit(activity); + } + return Result.success(); + } + + @At + @Ok("json:full") + @ApiOperation("获取分工会人数限制") + @SaCheckPermission("family.manage.activity") + public Result getUnionLimit(@Param(value = "activityScopeId") String activityScopeId) { + Sql sql = Sqls.create(""" + SELECT + gh.id, + gh.name, + gh.unioncode, + (select count(1) from `vw_user` where unionid = gh.id $cnd) as teacherCount, + NULL as ratio, + NULL as limitCount + FROM + sys_union gh + order by gh.unioncode + """); + if (StrUtil.isNotBlank(activityScopeId)) { + sql.setVar("cnd", "AND id in (select userId from activity_user_scope where groupId = '" + activityScopeId + "')"); + } + List list = familyActivityManageService.listMap(sql); + return Result.success().addData(list); + } + + @At + @Ok("json:full") + @ApiOperation("获取报名人员数量") + @SaCheckPermission("family.manage.activity") + public Result getRegisterUserCount(@Param(value = "courseId") String courseId) { + return Result.success().addData(dao.count(FamilyUser.class, Cnd.where("courseId", "=", courseId))); + } + + @At + @Ok("json:full") + @ApiOperation("获取历史活动列表") + @SaCheckPermission("family.manage.activity") + public Result getHistoricalActList() { + List query = dao.query(FamilyActivity.class, Cnd.NEW().desc("activityStartTime")); + return Result.success().addData(query); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityApplyController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityApplyController.java new file mode 100644 index 00000000..8bb65375 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityApplyController.java @@ -0,0 +1,178 @@ +package com.budwk.app.zhgh.activity.family.controller.manage; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_dict; +import com.budwk.app.sys.services.SysDictService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.family.models.*; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityService; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "活动报名") +@At("/platform/family/manage/apply") +public class FamilyActivityApplyController { + + @Inject + private FamilyActivityService familyActivityService; + @Inject + private SysDictService dictService; + @Inject + private FamilyActivityStatisticsService statisticsService; + + @At("") + @SaCheckPermission("family.manage.apply") + @Ok("beetl:/platform/zhgh/activity/family/apply/index.html") + public void index() { + } + + @At + @ApiOperation("活动查询") + @SaCheckPermission("family.manage.apply") + public Result activityData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "activityType") Integer activityType) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("`year`", "=", year); + //查询报名中 + if (activityType == 2) { + cnd.and(new Static("now() > activitySignUpStartTime and now() < activitySignUpEndTime")); + }//查询已结束的 + else if (activityType == 3) { + cnd.and(new Static("now() > activityEndTime")); + } + + if (AuthUtil.hasRole("H04") && !AuthUtil.hasRoleOr("sysadmin, A06")) { + cnd.and("activityMode", "=", 2).and("createdBy", "=", SecurityUtil.getUserId()); + } + + Pagination pagination = familyActivityService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + List familyActivities = pagination.getList(); + Map familyTypeMap = dictService.getSubListByCode("FAMILY_SIGNUP_TYPE").stream().collect(Collectors.toMap(Sys_dict::getCode, Sys_dict::getName)); + familyActivities.forEach(v -> v.setTrainType(familyTypeMap.get(v.getTrainType()))); + return Result.success(pagination); + } + + @At + @ApiOperation("分活动查询") + @SaCheckPermission("family.manage.apply") + public Result pageData(PageForm pageForm, + @Param(value = "courseTypeId") String courseTypeId, + @Param(value = "activityId") String activityId, + @Param(value = "assortTypes") String[] assortTypes) { + Sql sql = Sqls.create(""" + SELECT + tsuc.id, + tsuc.activityId, + tsuc.courseName, + tsuc.coursePeopleNumber, + tsuc.courseLocation, + tsuc.courseType, + tsuc.courseLocationCoordinates, + tsuc.courseReservedNumber, + tsuc.courseInstructor, + tsuc.campus, + tsuc.unionLimit, + tsuc.isMobileSign, + tsuc.signType, + tsuc.isReceiveGift, + tsuc.giftType, + tsuc.reserveMode, + tsuc.waitingNum, + tsuc.assort, + type.typeName, + tsuc.courseIsLimitApply + FROM + `family_course` tsuc + LEFT JOIN family_type type ON type.id = tsuc.courseType + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("type.id", "=", courseTypeId); + cnd.and("tsuc.activityId", "=", activityId); + if(Lang.isNotEmpty(assortTypes)) { + cnd.and("tsuc.assort", "in", assortTypes); + } + + List courseArray = familyActivityService.dao().query(FamilyCourse.class, Cnd.where("activityId", "=", activityId)); + courseArray = familyActivityService.filterCourseByHostUnion(courseArray); + cnd.and("tsuc.id", "in", courseArray.stream().map(FamilyCourse::getId).toList()); + + cnd.asc("tsuc.orderNum"); + cnd.asc("type.code"); + sql.setCondition(cnd); + + Pagination pagination = familyActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List courseList = pagination.getList(); + + courseList.forEach(c -> { + c.put("hasRegisterNum", statisticsService.queryCourseCount(c.getString("id"), c.getString("courseType"))); + c.put("hasWaitingNum", statisticsService.queryCourseWaitCount(c.getString("id"), c.getString("courseType"))); + //当前用户是否报过 + c.put("isSign", familyActivityService.isSignCourseByUser(c.getString("id"), SecurityUtil.getUserId())); + + if(StrUtil.isNotBlank(c.getString("unionLimit"))) { + List unionLimit = Json.fromJsonAsList(NutMap.class, c.getString("unionLimit")); + if(Lang.isNotEmpty(unionLimit)) { + NutMap nutMap = unionLimit.stream().filter(o -> o.getString("id").equals(SecurityUtil.getUnionId())).findFirst().orElse(null); + if(nutMap != null) { + c.put("coursePeopleNumber", nutMap.getInt("limitCount")); + } + } + } + }); + return Result.success(pagination); + } + + @At + @ApiOperation("获取分活动时间") + @SaCheckPermission("family.manage.apply") + public Result getCourseTime(String id) { + List list = familyActivityService.dao().query(FamilyActivityCourse.class, Cnd.where("courseId", "=", id)); + return Result.success(list); + } + + @At + @ApiOperation("查询分类标识集合") + @SaCheckPermission("family.manage.apply") + public Result queryCourseAssort(String activityId) { + List courseList = familyActivityService.dao().query( + FamilyCourse.class, + Cnd.where(FamilyCourse::getActivityId, "=", activityId).asc(FamilyCourse::getOrderNum) + ); + if(Lang.isEmpty(courseList)) { + return Result.success(new ArrayList<>()); + } + List assortList = courseList.stream().map(FamilyCourse::getAssort).filter(StrUtil::isNotBlank).toList(); + return Result.success(assortList); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityController.java new file mode 100644 index 00000000..95a8cf93 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyActivityController.java @@ -0,0 +1,145 @@ +package com.budwk.app.zhgh.activity.family.controller.manage; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_home_activity; +import com.budwk.app.zhgh.activity.family.models.*; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; +import org.nutz.trans.Trans; + +import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author zxy + * @Description 培训报名 活动管理 + * @createTime 2022年02月23日 09:57:00 + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "活动管理") +@At("/platform/family/manage/activity") +public class FamilyActivityController { + + @Inject + private FamilyActivityService familyActivityManageService; + + @Inject + private Dao dao; + + @At("") + @SaCheckPermission("family.manage.activity") + @Ok("beetl:/platform/zhgh/activity/family/manage/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("family.manage.activity") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "activityName") String activityName) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("year", "=", year); + cnd.and(Cnd.likeEX("activityName", activityName)); + cnd.orderBy("createdAt", "desc"); + return Result.success().addData(familyActivityManageService.pageData(pageForm, cnd)); + } + + @At + @ApiOperation("活动删除") + @SaCheckPermission("family.manage.activity") + @SLog(type = "family", tag = "删除活动", msg = "删除活动") + public Result onDelete(String id) { + Trans.exec(() -> { + familyActivityManageService.delete(id); + dao.clear(FamilyCourse.class, Cnd.where("activityId", "=", id)); + dao.clear(FamilyActivityCourse.class, Cnd.where("activityId", "=", id)); + dao.clear(FamilyUser.class, Cnd.where("activityId", "=", id)); + dao.clear(FamilyUserCourse.class, Cnd.where("activityId", "=", id)); + dao.clear(FamilyActivity.class, Cnd.where("id", "=", id)); + dao.clear(FamilyTypeLimit.class, Cnd.where("activityId", "=", id)); + dao.delete(Sys_home_activity.class, id); + }); + return Result.success(); + } + + @At + @ApiOperation("活动状态变更") + @SaCheckPermission("family.manage.activity") + public Result activityStatusChange(FamilyActivity activity) { + familyActivityManageService.updateActivityStatus(activity); + dao.update(Sys_home_activity.class, + Chain.make("enable", !activity.isDisabled()), + Cnd.where("id", "=", activity.getId())); + return Result.success(); + } + + @At + @ApiOperation("查询单个活动") + @SaCheckPermission("family.manage.activity") + public Result findOne(@Param("id") @NotNull String id) { + NutMap dataMap = familyActivityManageService.findOne(id, null, ""); + String activityStartTime = dataMap.getString("activityStartTime"); + String activityEndTime = dataMap.getString("activityEndTime"); + if(StrUtil.isNotBlank(activityStartTime) && StrUtil.isNotBlank(activityEndTime)) { + dataMap.put("activityTime", List.of(activityStartTime, activityEndTime)); + } else { + dataMap.put("activityTime", new ArrayList<>()); + } + + String activitySignUpStartTime = dataMap.getString("activitySignUpStartTime"); + String activitySignUpEndTime = dataMap.getString("activitySignUpEndTime"); + if(StrUtil.isNotBlank(activitySignUpStartTime) && StrUtil.isNotBlank(activitySignUpEndTime)) { + dataMap.put("activitySignTime", List.of(activitySignUpStartTime, activitySignUpEndTime)); + } else { + dataMap.put("activitySignTime", new ArrayList<>()); + } + + List courseList = dataMap.getList("courseList", NutMap.class); + + //查询所有的课程类型 + List familyTypeList = dao.query(FamilyType.class, Cnd.NEW()); + Map typeMap = familyTypeList.stream().collect(Collectors.toMap(FamilyType::getId, FamilyType::getTypeName)); + + courseList.forEach(v -> { + + List courseTimeList = v.getList("courseTimeList", NutMap.class); + //选择课程日期 下拉框 + List setUpCourseData = courseTimeList.stream().map(cd -> cd.getString("courseDate")).distinct().collect(Collectors.toList()); + v.put("setUpCourseData", setUpCourseData); + + courseTimeList.forEach(ct -> { + String courseStartTime = DateUtil.format(ct.getTime("courseStartTime"), "HH:mm"); + String courseEndTime = DateUtil.format(ct.getTime("courseEndTime"), "HH:mm"); + ct.put("courseStartTime", courseStartTime); + ct.put("courseEndTime", courseEndTime); + }); + + v.put("courseTypeName", typeMap.get(v.getString("courseType"))); + }); + + return Result.success().addData(dataMap); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyTypeController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyTypeController.java new file mode 100644 index 00000000..ca591cf0 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyTypeController.java @@ -0,0 +1,167 @@ +package com.budwk.app.zhgh.activity.family.controller.manage; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.EnumUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.zhgh.activity.family.models.FamilyMobileSignColumn; +import com.budwk.app.zhgh.activity.family.models.FamilyType; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.entity.annotation.ColType; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @Author JyuHsin + * @Date 2022/9/22 + * @Description + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "活动类型管理") +@At("/platform/family/manage/type") +public class FamilyTypeController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + + @At("") + @SaCheckPermission("family.manage.type") + @Ok("beetl:/platform/zhgh/activity/family/type/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("family.manage.type") + public Result pageData(PageForm pageForm, + @Param(value = "typeName") String typeName) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + select * from family_type $condition + """); + if (Strings.isNotBlank(typeName)) { + cnd.and("typeName", "like", "%" + typeName + "%"); + } + if(Strings.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())){ + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } else { + cnd.asc("xh"); + } + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List list = pagination.getList(); + list.forEach(item -> { + Cnd c = Cnd.NEW(); + c.and("typeId", "=", item.getString("id")); + c.asc("columnIndex"); + List signColumns = dao.query(FamilyMobileSignColumn.class, c); + item.put("familyMobileSignColumnList", signColumns); + + }); + return Result.success().addData(pagination); + } + + @At + @ApiOperation("活动类型新增") + @SaCheckPermission("family.manage.type") + @SLog(type = "family", tag = "活动类型新增", msg = "活动类型新增") + public Result doAdd(@Param("data") String data) throws Exception { + FamilyType type = Json.fromJson(FamilyType.class, data); + int count = dao.count(FamilyType.class, Cnd.where("code", "=", type.getCode())); + if (count > 0) { + return Result.error("编码重复!"); + } + int totalCount = dao.count(FamilyType.class); + type.setXh(totalCount + 1); + dao.insertWith(type, "familyMobileSignColumnList"); + return Result.success(); + } + + @At + @ApiOperation("活动类型修改") + @SaCheckPermission("family.manage.type") + @SLog(type = "family", tag = "活动类型修改", msg = "活动类型修改") + public Result doEdit(FamilyType type) { + int count = dao.count(FamilyType.class, Cnd.where("code", "=", type.getCode()).and("id", "!=", type.getId())); + if (count > 0) { + return Result.error("编码重复!"); + } + dao.update(type); + dao.clear(FamilyMobileSignColumn.class, Cnd.where("typeId", "=", type.getId())); + dao.insertLinks(type, "familyMobileSignColumnList"); + return Result.success(); + } + + @At + @ApiOperation("活动类型删除") + @SaCheckPermission("family.manage.type") + @SLog(type = "family", tag = "活动类型删除", msg = "活动类型删除") + public Object doDelete(@Param(value = "id") String id) { + dao.clear(FamilyType.class, Cnd.where("id", "=", id)); + dao.clear(FamilyMobileSignColumn.class, Cnd.where("typeId", "=", id)); + return Result.success(); + } + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("排序号变更") + @SaCheckPermission("family.manage.type") + public Object xhChange(String id, Integer xh, boolean toDown) { + if (toDown) { + FamilyType next = dao.fetch(FamilyType.class, Cnd.where("xh", "=", xh + 1)); + next.setXh(next.getXh() - 1); + dao.update(next); + dao.update(FamilyType.class, Chain.make("xh", xh + 1), Cnd.where("id", "=", id)); + } else { + FamilyType pre = dao.fetch(FamilyType.class, Cnd.where("xh", "=", xh - 1)); + pre.setXh(pre.getXh() + 1); + dao.update(pre); + dao.update(FamilyType.class, Chain.make("xh", xh - 1), Cnd.where("id", "=", id)); + } + return Result.success(); + } + + @At + @ApiOperation("获取所有类型") + @SaCheckLogin + public Result getAllType(@Param(value = "id") String id) { + List familyTypeList = dao.query(FamilyType.class, Cnd.NEW().andEX("id", "=", id).asc("xh")); + dao.fetchLinks(familyTypeList, "familyMobileSignColumnList", Cnd.NEW().asc("columnIndex")); + return Result.success().addData(familyTypeList); + } + + @At + @ApiOperation("自定义表单字段类型") + @SaCheckPermission("family.manage.type") + public Result getColumnType() { + List names = EnumUtil.getNames(ColType.class); + names.add("JSON"); + return Result.success(names); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyUserAdjustController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyUserAdjustController.java new file mode 100644 index 00000000..cca71fc0 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyUserAdjustController.java @@ -0,0 +1,178 @@ +package com.budwk.app.zhgh.activity.family.controller.manage; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.family.models.*; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityService; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @Author JyuHsin + * @Date 2022/9/21 + * @Description 人员调整 + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "亲子活动人员调整") +@At("/platform/family/manage/userAdjust") +public class FamilyUserAdjustController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + @Inject + private FamilyActivityService familyActivityManageService; + @Inject + private FamilyActivityStatisticsService familyActivityStatisticsService; + + @At("") + @SaCheckPermission("family.manage.activity.adjust") + @Ok("beetl:/platform/zhgh/activity/family/userAdjust/index.html") + public void index() { + } + + /** + * 活动list + * @param year 年度 + * @return + */ + @At + @ApiOperation("活动列表") + @SaCheckPermission("family.manage.activity.adjust") + public Result activityList(@Param(value = "year") Integer year) { + List activityList = dao.query(FamilyActivity.class, Cnd.NEW().andEX("year", "=", year).andEX("isDisabled", "=", false).desc("activityStartTime")); + return Result.success(activityList); + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("family.manage.activity.adjust") + public Result pageData(PageForm pageForm, + @Param(value = "activityId") String activityId) { + Pagination pagination = familyActivityStatisticsService.pageData(pageForm, activityId); + return Result.success(pagination); + } + + @At + @ApiOperation("子活动查询") + @SaCheckPermission("family.manage.activity.adjust") + public Result getCourse(String activityId) { + Sql sql = Sqls.create(""" + SELECT + tsuc.id, + tsuc.courseName, + tsuc.coursePeopleNumber, + tsuc.courseType, + tsuc.courseLocation, + tsuc.courseInstructor, + tsuc.courseReservedNumber, + tsuc.waitingNum, + tsuc.reserveMode + FROM + `family_course` tsuc + WHERE + tsuc.activityId = @activityId + ORDER BY courseName asc + """); + sql.setParam("activityId", activityId); + List courseList = baseService.listMap(sql); + courseList.forEach(c -> { + c.put("registerNum", familyActivityStatisticsService.queryCourseCount(c.getString("id"), c.getString("courseType"))); + c.put("hasWaitingNum", familyActivityStatisticsService.queryCourseWaitCount(c.getString("id"), c.getString("courseType"))); + }); + return Result.success(courseList); + } + + @At + @ApiOperation("报名用户列表") + @SaCheckPermission("family.manage.activity.adjust") + public Result registerUserList(@Param("courseId") String courseId, + @Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId, + @Param(value = "searchName") String searchName, + @Param(value = "searchKeyword") String searchKeyword) { + List list = familyActivityStatisticsService.registerUserList(courseId, unionId, unitId, searchName, searchKeyword); + return Result.success(list); + } + + @At + @ApiOperation("人员调整") + @SaCheckPermission("family.manage.activity.adjust") + @SLog(type = "family", tag = "人员调整", msg = "人员调整") + public Result adjust(String activityId, String oldCourseId, String newCourseId, String userId) { + + Cnd oldCnd = Cnd.where("activityId", "=", activityId) + .and("courseId", "=", oldCourseId).and("userId", "=", userId); + + Cnd newCnd = Cnd.where("activityId", "=", activityId) + .and("courseId", "=", newCourseId).and("userId", "=", userId); + + //旧的报名信息 + FamilyUser oldfamilyUser = dao.fetch(FamilyUser.class, oldCnd); + oldfamilyUser.setCourseId(newCourseId); + oldfamilyUser.setSignUpTime(DateUtil.date()); + dao.update(oldfamilyUser); + + //新的课程的信息,上课时间 + List activityCourseList = dao.query(FamilyActivityCourse.class, Cnd.where("activityId", "=", activityId) + .and("courseId", "=", newCourseId)); + //先清楚旧的信息 + dao.clear(FamilyUserCourse.class, oldCnd); + //添加新的信息 + List familyUserCourseList = new ArrayList<>(); + activityCourseList.forEach(item -> { + FamilyUserCourse course = new FamilyUserCourse(); + course.setActivityCourseId(activityId); + course.setCourseId(newCourseId); + course.setUserId(userId); + course.setCourseStartTime(item.getCourseStartTime()); + course.setCourseEndTime(item.getCourseEndTime()); + course.setActivityCourseId(item.getId()); + familyUserCourseList.add(course); + }); + dao.insert(familyUserCourseList); + return Result.success(); + } + + @At + @ApiOperation("删除报名人员") + @SaCheckPermission("family.manage.activity.adjust") + @SLog(type = "family", tag = "删除报名人员", msg = "删除报名人员") + public Result deleteSignUser(String activityId, String courseId, String userId) { + + //删除 + Cnd cnd = Cnd.NEW(); + cnd.and("activityId", "=", activityId); + cnd.and("courseId", "=", courseId); + cnd.and("userId", "=", userId); + + dao.clear(FamilyUser.class, cnd); + dao.clear(FamilyUserCourse.class, cnd); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyUserBlackListManageController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyUserBlackListManageController.java new file mode 100644 index 00000000..1ab5b45f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/manage/FamilyUserBlackListManageController.java @@ -0,0 +1,349 @@ +package com.budwk.app.zhgh.activity.family.controller.manage; + +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.afterturn.easypoi.excel.export.ExcelExportService; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.zhgh.activity.family.models.FamilyActivity; +import com.budwk.app.zhgh.activity.family.models.FamilyCourse; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; +import com.budwk.app.zhgh.activity.family.service.FamilyBlackListService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.net.URLEncoder; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author zxy + * @Description 人员管理 + * @createTime 2022年03月07日 14:27:00 + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "亲子活动人员黑名单") +@At("/platform/family/userManage") +public class FamilyUserBlackListManageController { + + @Inject + private Dao dao; + @Inject + private FamilyBlackListService familyBlackListService; + + @At("") + @SaCheckPermission("family.user.activity") + @Ok("beetl:/platform/zhgh/activity/family/userManage/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("family.user.activity") + public Result pageData(PageForm pageForm, + @Param(value = "activityId") String activityId, + @Param(value = "courseId") String courseId, + @Param(value = "year") Integer year, + @Param(value = "userKeyWord") String userKeyWord) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("tsuu.activityId", "=", activityId); + cnd.andEX("tsuu.courseId", "=", courseId); + cnd.andEX("act.year", "=", year); + if (StrUtil.isNotBlank(userKeyWord)) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + cnd.and(seg.andLike("u.username", userKeyWord).orLike("u.loginname", userKeyWord)); + } + if(Strings.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())){ + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + + Pagination pagination = familyBlackListService.pageData(pageForm, cnd, activityId, courseId); + return Result.success(pagination); + } + + @At + @ApiOperation("报名人员处理") + @SaCheckPermission("family.user.activity") + @SLog(type = "family", tag = "报名人员处理", msg = "报名人员处理") + public Result doHandleUser(@Param("userId") String userId) { + familyBlackListService.doHandleUser(userId); + return Result.success(); + } + + @At + @ApiOperation("根据活动Id获取子活动") + @SaCheckPermission("family.user.activity") + public Result getCourseByActivityId(@Param("activityId") String activityId) { + List list = dao.query(FamilyCourse.class, Cnd.where("activityId", "=", activityId)); + return Result.success(list); + } + + @At + @ApiOperation("获取子活动具体时间") + @SaCheckPermission("family.user.activity") + public Result attendClassRecord(String userId) { + familyBlackListService.attendClassRecord(userId); + return Result.success(); + } + + @At + @ApiOperation("获取候补人员") + @SaCheckPermission("family.user.activity") + public Result getReserveUser(String courseId) { + Sql sql = Sqls.create(""" + SELECT + uc.* , + (select signUpTime from family_user su where su.activityId=uc.activityId and su.courseId = uc.courseId and su.userId=uc.userId) as signUpTime, + (select state from family_user su where su.activityId=uc.activityId and su.courseId = uc.courseId and su.userId=uc.userId) as state, + u.username, + u.loginname, + u.mobile, + u.unitName, + u.unionName + FROM + family_user_course uc LEFT JOIN `vw_user` u on uc.userId = u.id + WHERE uc.courseId = @courseId and uc.isAttend = false HAVING state = 2 order by signUpTime desc + """).setParam("courseId", courseId); + return Result.success(familyBlackListService.listMap(sql)); + } + + @At + @ApiOperation("补充人员") + @SaCheckPermission("family.user.activity") + @SLog(type = "family", tag = "补充人员", msg = "补充人员") + public Result reserveSingUp(String[] ids, String courseId) { + //先查询这个课程有多少个未签到的人员 + Sql sql = Sqls.create(""" + SELECT + uc.* , + (select signUpTime from family_user su where su.activityId=uc.activityId and su.courseId = uc.courseId and su.userId=uc.userId) as signUpTime, + (select state from family_user su where su.activityId=uc.activityId and su.courseId = uc.courseId and su.userId=uc.userId) as state + FROM + family_user_course uc + WHERE uc.courseId = @courseId and uc.isAttend = false HAVING state = 1 order by signUpTime desc + """).setParam("courseId", courseId); + List list = familyBlackListService.listMap(sql); + if(ids.length > list.size()) { + return Result.error("您选择了" + ids.length + "位,未签到人员只有" + list.size() + "位"); + } + //ids的长度为几,就搞几个 + List mapList = list.subList(0, ids.length); + List idList = mapList.stream().map(o -> o.getString("userId")).collect(Collectors.toList()); + //将这几个没签到的设置为4 + dao.update(FamilyUser.class, Chain.make("state", 4), Cnd.where("courseId", "=", courseId) + .and("userId", "in", idList)); + //将补充的设置为1 + dao.update(FamilyUser.class, Chain.make("state", 1), Cnd.where("courseId", "=", courseId) + .and("userId", "in", ids)); + return Result.success(); + } + + @At + @Ok("void") + @ApiOperation("导出签到人员") + public void exportSignPerson(@Param(value = "activityId") String activityId, + HttpServletResponse response) { + FamilyActivity activity = dao.fetch(FamilyActivity.class, activityId); + + Sql sql = Sqls.create(""" + SELECT + uc.*, + DATE_FORMAT(uc.courseStartTime, '%Y-%m-%d %H:%i:%s') as courseStartTimeExcel, + DATE_FORMAT(uc.courseEndTime, '%Y-%m-%d %H:%i:%s') as courseEndTimeExcel, + DATE_FORMAT(uc.attendTime, '%Y-%m-%d %H:%i:%s') as attendTimeExcel, + u.username, + u.loginname, + u.unitName, + u.unionName, + u.sex + FROM + family_user_course uc + left join family_course course on uc.courseId = course.id + left join `vw_user` u on u.id = uc.userId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("uc.activityId", "=", activityId); + cnd.and("course.isMobileSign", "=", true); + cnd.desc("isAttend").desc("attendTime"); + sql.setCondition(cnd); + + List userList = familyBlackListService.listMap(sql); + + List courseList = dao.query(FamilyCourse.class, Cnd.where("activityId", "=", activityId)); + + List> sheetsList = new ArrayList<>(); + + List excelCommonExportEntity = new ArrayList<>(); + excelCommonExportEntity.add(new ExcelExportEntity("姓名", "username", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("工号", "loginname", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("单位", "unitName", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("分工会", "unionName", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("性别", "sex", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("开始时间", "courseStartTimeExcel", 22)); + excelCommonExportEntity.add(new ExcelExportEntity("结束时间", "courseEndTimeExcel", 22)); + excelCommonExportEntity.add(new ExcelExportEntity("是否签到", "isAttend", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("签到时间", "attendTimeExcel", 22)); + + for (FamilyCourse c : courseList) { + String courseId = c.getId(); + String courseName = c.getCourseName(); + List v = userList.stream().filter(x -> x.getString("courseId").equals(courseId)).collect(Collectors.toList()); + ExportParams userExportParams = new ExportParams(); + userExportParams.setSheetName(courseName); + + List currentEntities = new ArrayList<>(excelCommonExportEntity); + for (NutMap userSignData : v) { + if(!userSignData.getBoolean("isAttend")) { + userSignData.put("isAttend", "未签到"); + userSignData.put("attendTimeExcel", "未签到"); + }else { + userSignData.put("isAttend", "已签到"); + } + } + + Map userExportMap = new HashMap<>(); + userExportMap.put("name", courseName); + userExportMap.put("title", userExportParams); + userExportMap.put("entity", currentEntities); + userExportMap.put("data", v); + + sheetsList.add(userExportMap); + } + try { + String fileName = activity.getActivityName() + "签到人员名单.xls"; + String disposition = "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"); + response.setCharacterEncoding("utf-8"); + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", disposition); + + Workbook workbook = new HSSFWorkbook(); + for (Map map : sheetsList) { + ExcelExportService service = new ExcelExportService(); + service.createSheetForMap(workbook,(ExportParams) map.get("title"),(List) map.get("entity"),(Collection) map.get("data")); + } + + workbook.write(response.getOutputStream()); + workbook.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @At + @Ok("void") + @ApiOperation("导出领取人员") + public void exportGiftPerson(@Param(value = "activityId") String activityId, + HttpServletResponse response) { + FamilyActivity activity = dao.fetch(FamilyActivity.class, activityId); + + Sql sql = Sqls.create(""" + SELECT + uc.*, + DATE_FORMAT(uc.courseStartTime, '%Y-%m-%d %H:%i:%s') as courseStartTimeExcel, + DATE_FORMAT(uc.courseEndTime, '%Y-%m-%d %H:%i:%s') as courseEndTimeExcel, + DATE_FORMAT(uc.receiveTime, '%Y-%m-%d %H:%i:%s') as receiveTimeExcel, + u.username, + u.loginname, + u.unitName, + u.unionName, + u.sex + FROM + family_user_course uc + left join family_course course on uc.courseId = course.id + left join `vw_user` u on u.id = uc.userId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("uc.activityId", "=", activityId); + cnd.and("course.isReceiveGift", "=", true).and("course.giftType" ,"=", 1); + cnd.desc("isReceive").desc("receiveTime"); + sql.setCondition(cnd); + + List userList = familyBlackListService.listMap(sql); + + List courseList = dao.query(FamilyCourse.class, Cnd.where("activityId", "=", activityId)); + + List> sheetsList = new ArrayList<>(); + + List excelCommonExportEntity = new ArrayList<>(); + excelCommonExportEntity.add(new ExcelExportEntity("姓名", "username", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("工号", "loginname", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("单位", "unitName", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("分工会", "unionName", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("性别", "sex", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("开始时间", "courseStartTimeExcel", 22)); + excelCommonExportEntity.add(new ExcelExportEntity("结束时间", "courseEndTimeExcel", 22)); + excelCommonExportEntity.add(new ExcelExportEntity("是否领取", "isReceive", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("领取时间", "receiveTimeExcel", 22)); + + for (FamilyCourse c : courseList) { + String courseId = c.getId(); + String courseName = c.getCourseName(); + List v = userList.stream().filter(x -> x.getString("courseId").equals(courseId)).collect(Collectors.toList()); + ExportParams userExportParams = new ExportParams(); + userExportParams.setSheetName(courseName); + + List currentEntities = new ArrayList<>(excelCommonExportEntity); + for (NutMap userSignData : v) { + if(!userSignData.getBoolean("isReceive")) { + userSignData.put("isReceive", "未领取"); + userSignData.put("receiveTimeExcel", "未领取"); + }else { + userSignData.put("isReceive", "已领取"); + } + } + + Map userExportMap = new HashMap<>(); + userExportMap.put("name", courseName); + userExportMap.put("title", userExportParams); + userExportMap.put("entity", currentEntities); + userExportMap.put("data", v); + + sheetsList.add(userExportMap); + } + try { + String fileName = activity.getActivityName() + "礼品领取人员名单.xls"; + String disposition = "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"); + response.setCharacterEncoding("utf-8"); + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", disposition); + + Workbook workbook = new HSSFWorkbook(); + for (Map map : sheetsList) { + ExcelExportService service = new ExcelExportService(); + service.createSheetForMap(workbook,(ExportParams) map.get("title"),(List) map.get("entity"),(Collection) map.get("data")); + } + + workbook.write(response.getOutputStream()); + workbook.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/mobile/MFamilyActivityController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/mobile/MFamilyActivityController.java new file mode 100644 index 00000000..54b164ec --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/mobile/MFamilyActivityController.java @@ -0,0 +1,368 @@ +package com.budwk.app.zhgh.activity.family.controller.mobile; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; +import com.budwk.app.zhgh.activity.family.models.*; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.util.cri.Static; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; + +/** + * @author zxy + * @Description TODO + * @createTime 2022年02月25日 13:44:00 + */ +@IocBean +@Ok("json:full") +@Api(tags = "亲子活动移动端") +@At("/platform/mobile/familyActivity") +public class MFamilyActivityController { + + private static final String REDIS_KEY_PREFIX = "m_family_activity"; + private final ReentrantLock lock = new ReentrantLock(true); + @Inject + private Dao dao; + @Inject + private FamilyActivityService familyActivityService; + @Inject + private RedisService redisService; + + @At("/familyList") + @Ok("beetl:/platform/zhghh5/activity/family/familyList/index.html") + @SaCheckPermission("h5.family.sign") + public void familyList() { + } + + @At("/familyInfo") + @Ok("beetl:/platform/zhghh5/activity/family/familyInfo/index.html") + @SaCheckPermission("h5.family.sign") + public void familyInfo() { + } + + @At("/activityInfo") + @Ok("beetl:/platform/zhghh5/activity/family/activityInfo/index.html") + @SaCheckPermission("h5.family.sign") + public void activityInfo() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("h5.family.sign") + public Result pageData(PageForm pageForm, + @Param(value = "activityStatus") int activityStatus, + @Param(value = "year") Integer year, + @Param(value = "activityType") Integer activityType) { + Pagination pagination = familyActivityService.mPageData(pageForm, year, activityStatus, activityType); + return Result.success(pagination); + } + + /** + * @param id 活动id + * @param tabIndex 0全部 1我的 + * @return + */ + @At + @ApiOperation("查询单个活动") + @SaCheckPermission("h5.family.sign") + public Result findOne(@Param("id") String id, + @Param(value = "tabIndex") Integer tabIndex, + @Param(value = "fromMode") String fromMode) { + Cnd cnd = Cnd.NEW(); + if (tabIndex > 0) { + List mySignCourseList = dao.query(FamilyUser.class, Cnd.where("userId", "=", SecurityUtil.getUserId()).and("activityId", "=", id)); + List mySignCourseIdList = mySignCourseList.stream().map(FamilyUser::getCourseId).collect(Collectors.toList()); + cnd.and("id", "in", mySignCourseIdList); + } + NutMap nutMap = familyActivityService.findOne(id, cnd, fromMode); + List courseList = nutMap.getAsList("courseList", FamilyCourse.class); + courseList.forEach(v -> { + if (v.getCourseIsLimitApply() != null && v.getCourseIsLimitApply() && v.getIsSign()) { + FamilyActivityCourse course = dao.fetch(FamilyActivityCourse.class, Cnd.where("courseId", "=", v.getId())); + v.setCourseTimeName(DateUtil.format(course.getCourseStartTime(), "HH:mm") + "至" + DateUtil.format(course.getCourseEndTime(), "HH:mm") + "段"); + } + }); + return Result.success(nutMap); + } + + @At + @ApiOperation("查询子活动时间段") + @SaCheckPermission("h5.family.sign") + public Object getCourseTimeSelectList(String courseId) { + // 查课程的时间段 + List courseList = dao.query(FamilyActivityCourse.class, Cnd.where("courseId", "=", courseId)); + + // 查课程的报名人数 + List applyUserList = dao.query(FamilyUserCourse.class, Cnd.where("courseId", "=", courseId)); + // 按照课程下面时间段去分组 + Map> collectMap = applyUserList.stream().collect(Collectors.groupingBy(FamilyUserCourse::getActivityCourseId)); + List list = courseList.stream().map(v -> { + String id = v.getId(); + NutMap nutMap = NutMap.NEW(); + List familyUserCourses = collectMap.get(id); + int remainingNum = v.getCourseLimitNum(); + if (Lang.isNotEmpty(familyUserCourses)) { + remainingNum = v.getCourseLimitNum() - familyUserCourses.size(); + } + nutMap.put("remainingNum", remainingNum); + nutMap.put("text", DateUtil.format(v.getCourseStartTime(), "HH:mm") + "至" + DateUtil.format(v.getCourseEndTime(), "HH:mm") + "段(剩" + remainingNum + ")"); + nutMap.put("value", id); + return nutMap; + }).filter(v -> v.getInt("remainingNum") != 0).toList(); + return Result.success(list); + } + + @At + @ApiOperation("活动报名") + @SaCheckPermission("h5.family.sign") + @SLog(type = "family", tag = "活动报名", msg = "活动报名") + public Result doSignUp(FamilyUser familyUser) { + try { + lock.lock(); + boolean courseByUser = familyActivityService.isSignCourseByUser(familyUser.getCourseId(), SecurityUtil.getUserId()); + if(courseByUser) { + return Result.error("您已报过该活动"); + } + //判断人数 + int number = 0; + FamilyCourse course = familyActivityService.dao().fetch(FamilyCourse.class, familyUser.getCourseId()); + FamilyType type = familyActivityService.dao().fetch(FamilyType.class, course.getCourseType()); + if(type != null) { + if(type.getIsBringFamily() && type.getIsAddFamily()) { + List> mobileColumnsValue = familyUser.getMobileColumnsValue(); + number = Lang.isNotEmpty(mobileColumnsValue) ? mobileColumnsValue.size() : 0; + } + } + boolean signFull = familyActivityService.isSignFull(course, number); + if(signFull) { + return Result.error("当前报名人数已满"); + } + boolean signFullByUnionId = familyActivityService.isSignFullByUnionId(course, number); + if(signFullByUnionId) { + return Result.error("该活动您所在的分工会名额不足"); + } + familyActivityService.doSignUp(familyUser); + return Result.success(); + } catch (Exception e) { + e.printStackTrace(); + return Result.success("报名失败"); + } finally { + lock.unlock(); + } + } + + @At + @ApiOperation("取消报名") + @SaCheckPermission("h5.family.sign") + @SLog(type = "family", tag = "取消报名", msg = "取消报名") + public Result cancelSignUp(@Param("activityId") String activityId, @Param("courseId") String courseId) { + String userId = SecurityUtil.getUserId(); + //取消分两种情况 + //第一种没有设置分工会人数限制,那么将候补的人按时间倒叙往上补 + //第二种如果设置了分工会人数限制,那么只将本分工会的候补人员按照时间倒叙往上补,如果本分工会没有候补人员,则名额空出来,由校工会手动调整 + FamilyActivity activity = dao.fetch(FamilyActivity.class, activityId); + FamilyCourse course = dao.fetch(FamilyCourse.class, courseId); + FamilyType type = dao.fetch(FamilyType.class, course.getCourseType()); + //如果是正常报名取消了,将候补报名的按时间倒叙第一个改为正常报名 + Cnd cnd = Cnd.where("activityId", "=", activityId).and("courseId", "=", courseId) + .and("state", "=", 2); + //如果设置了分工会报名人数限制,则只查本分工会 + if (Lang.isNotEmpty(course.getUnionLimit())) { + cnd.and(new Static(" userId in (select id from user where unionid = '%s')".formatted(SecurityUtil.getUnionId()))); + } + cnd.asc("signUpTime"); + if (!type.getIsBringFamily() && course.getReserveMode() == 2) { + List signUpUsers = dao.query(FamilyUser.class, cnd); + int thisSignUpUserCount = dao.count(FamilyUser.class, + Cnd.where("activityId", "=", activityId) + .and("courseId", "=", courseId).and("userId", "=", userId) + .and("state", "in", List.of(1, 3))); + if (!signUpUsers.isEmpty() && thisSignUpUserCount > 0) { + FamilyUser familyUser = signUpUsers.get(0); + familyUser.setState(1); + dao.update(familyUser); + Sys_user user = dao.fetch(Sys_user.class, familyUser.getUserId()); + //msgApi.sendTextMsg("【" + activity.getActivityName() + "】已候补成功,请按时参加活动!", user.getLoginname()); + } + } + //删除报名记录 + dao.clear("family_user_course", Cnd.where("activityId", "=", activityId) + .and("courseId", "=", courseId).and("userId", "=", userId)); + + dao.clear("family_user", Cnd.where("activityId", "=", activityId) + .and("courseId", "=", courseId).and("userId", "=", userId)); + return Result.success(); + } + + @At + @ApiOperation("签到") + @SaCheckPermission("h5.family.sign") + @SLog(type = "family", tag = "签到", msg = "签到") + public Result doQd(@Param("id") String id, @Param("courseId") String courseId, @Param("point") Double[] points) { + FamilyCourse course = dao.fetch(FamilyCourse.class, courseId); + List coursePoints = course.getCourseLocationCoordinates(); +// if (Lang.isNotEmpty(coursePoints)) { +// //需要签到 +// if (ArrayUtil.isEmpty(points) || ArrayUtil.hasNull(points)) { +// return Result.error().addMsg("请获取当前的坐标信息"); +// } +// Double[] coursePointArray = coursePoints.toArray(new Double[]{}); +// float distance = AMapUtils.calculateLineDistance(new LatLng(points[0], points[1]), new LatLng(coursePointArray[0], coursePointArray[1])); +// +// if (distance > 500) { +// return Result.error().addMsg("请到签到点位附近签到"); +// } +// } + familyActivityService.doQd(id); + return Result.success(); + } + + /** + * 签到信息 + * + * @param activityId + * @return + */ + @At + @ApiOperation("获取签到信息") + @SaCheckPermission("h5.family.sign") + public Result getQdInfoList(@Param("activityId") String activityId) { + List list = familyActivityService.qdInfoByUserId(SecurityUtil.getUserId(), activityId); + return Result.success(list); + } + + @At + @ApiOperation("验证是否能报名") + @SaCheckPermission("h5.family.sign") + public Result validateSignUp(String courseId, + @Param(value = "currentFamilyNumber") Integer currentFamilyNumber) { + try { + lock.lock(); + if(StrUtil.isBlank(courseId)) { + return Result.error("报名信息为空"); + } + + currentFamilyNumber = currentFamilyNumber != null ? currentFamilyNumber : 0; + FamilyCourse course = dao.fetch(FamilyCourse.class, courseId); + FamilyActivity activity = dao.fetch(FamilyActivity.class, course.getActivityId()); + + //判断时间 + if(DateUtil.compare(new Date(), activity.getActivitySignUpStartTime(), "yyyy-MM-dd HH:mm:ss") < 0) { + return Result.error("报名未开始"); + } + if(DateUtil.compare(new Date(), activity.getActivitySignUpEndTime(), "yyyy-MM-dd HH:mm:ss") > 0) { + return Result.error("报名已结束"); + } + + //判断活动组别 + int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getActivityGroupId()).and("userId", "=", SecurityUtil.getUserId())); + if(count == 0) { + return Result.error("抱歉,您没有此次活动的权限"); + } + + //判断是否报名 + boolean courseByUser = familyActivityService.isSignCourseByUser(courseId, SecurityUtil.getUserId()); + if(courseByUser) { + return Result.error("抱歉,您已经报名"); + } + + //判断活动人数 + boolean signFull = familyActivityService.isSignFull(course, currentFamilyNumber); + if(signFull) { + return Result.error("名额剩余数量不足"); + } + + //判断活动限制 + boolean signCourse = familyActivityService.isSignCourse(course, activity); + if(!signCourse) { + if(activity.getRestrictLimit() != 3) { + return Result.error("您选择的类型已达上限,不能再报该类型的了"); + } else { + return Result.error(activity.getActivityName() + "限制报" + activity.getLimitNum() + "个活动,已达上限"); + } + } + + //判断分工会人数限制 + boolean signFullByUnionId = familyActivityService.isSignFullByUnionId(course, currentFamilyNumber); + if(signFullByUnionId) { + return Result.error("您所在的分工会名额不足"); + } + + return Result.success(); + }catch (Exception e) { + e.printStackTrace(); + return Result.error("报名失败"); + } finally { + lock.unlock(); + } + } + + @At + @ApiOperation("验证子活动是否能报名") + @SaCheckPermission("h5.family.sign") + public Object validateSourceSignUp(String activityCourseId) { + try { + lock.lock(); + // 该时间段下已报名的人数 + int count = dao.count(FamilyUserCourse.class, Cnd.where("activityCourseId", "=", activityCourseId)); + // 获取改时间段下的活动课程限制报名人数 + FamilyActivityCourse course = dao.fetch(FamilyActivityCourse.class, activityCourseId); + Integer courseLimitNum = course.getCourseLimitNum(); + // 报名加上自己,如果大于了限制人数,那就无法报名 + if (count + 1 > courseLimitNum) { + return Result.error("该时间段名额已报满,请选择其他时段报名"); + } else { + return Result.success(); + } + } catch (Exception e) { + e.printStackTrace(); + return Result.error("报名失败"); + } finally { + lock.unlock(); + } + } + + @At + @ApiOperation("二维码签到") + @SaCheckPermission("h5.family.sign") + @SLog(type = "family", tag = "二维码签到", msg = "二维码签到") + public Result codeSign(String id, String codeCourseId, String clickCourseId) { + if(StrUtil.isBlank(codeCourseId) || StrUtil.isBlank(clickCourseId)) { + return Result.error("签到失败,没有获取到扫描信息"); + } + if(!codeCourseId.equals(clickCourseId)) { + return Result.error("签到失败,二维码与您当前签到信息不符"); + } + dao.update(FamilyUserCourse.class, Chain.make("isAttend", true) + .add("attendTime", new Date()), Cnd.where("id", "=", id)); + return Result.success(); + } + +} + + diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/mobile/MFamilyActivityScannerQrCodeController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/mobile/MFamilyActivityScannerQrCodeController.java new file mode 100644 index 00000000..0c4aa62d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/mobile/MFamilyActivityScannerQrCodeController.java @@ -0,0 +1,201 @@ +package com.budwk.app.zhgh.activity.family.controller.mobile; + +import lombok.extern.slf4j.Slf4j; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * 品牌活动扫码 + */ +@IocBean +@At("/platform/mobile/familyActivityScannerQrCode") +@Ok("json:full") +@Slf4j +public class MFamilyActivityScannerQrCodeController { + + /*@Inject + private WxTokenUtil; + + @Inject + private familyActivityService familyActivityService; + + @Inject + private Dao dao; + + @At("") + @Ok("beetl:/mobile/scannerQrCode.html") + public void scannerQrCode() { + + } + + *//** + * 微信js验证 + * + * @param url + * @return + *//* + @At("/auth/sign") + @ViReturn + @RequiresAuthentication + public Object wxAuthSign(String url) { + String jsapi_ticket = wxTokenUtil.jsTicket(); + return sign(jsapi_ticket, url); + } + + *//** + * 二维码信息 + * + * @param userId 用户id + * @param signId 签到记录id + * @param activityId 活动id + * @return + *//* + @At("/qrCodeInfo") + @RequiresAuthentication + public Object qrCodeInfo(@Param("userId") String userId, @Param("signId") String signId, @Param("activityId") String activityId) { + if (StrUtil.isBlank(userId) || StrUtil.isBlank(signId) || StrUtil.isBlank(activityId)) { + return Result.error("参数错误"); + } + try { +// Sql activitySql = Sqls.create("select activityName,cover from family_activity where id = @activityId"); +// activitySql.setParam("activityId",activityId); +// NutMap activityMap = (NutMap) Daos.query(dao, activitySql.toString(), Sqls.callback.map()); + + Sql signSql = Sqls.create("select isAttend,attendTime,isReceive,receiveTime from family_user_course where id = @signId"); + signSql.setParam("signId", signId); + NutMap attendInfo = (NutMap) Daos.query(dao, signSql.toString(), Sqls.callback.map()); + Sql userSql = Sqls.create("select id,username,loginname,unitname,unionname,sex from `user` where id = @userId"); + userSql.setParam("userId", userId); + NutMap userMap = (NutMap) Daos.query(dao, userSql.toString(), Sqls.callback.map()); + return Result.success(Map.of("signInfo", attendInfo, "userInfo", userMap)); + } catch (Exception e) { + log.error(e.getMessage()); + return Result.error("获取信息失败"); + } + } + + @At("/signInfo") + @RequiresAuthentication + public Object signInfo(@Param("signId") String signId) { + if (StrUtil.isBlank(signId)) { + return Result.error("参数错误"); + } + try { + Sql signSql = Sqls.create("select isAttend,attendTime from family_user_course where id = @signId"); + signSql.setParam("signId", signId); + NutMap signInfo = familyActivityService.fetch(signSql); + return Result.success(signInfo); + } catch (Exception e) { + log.error(e.getMessage()); + return Result.error("获取信息失败"); + } + } + + *//** + * 发放礼品 + * + * @param signId + * @return + *//* + @At("/grantGiftByQrCode") + @RequiresAuthentication + public Object grantGiftByQrCode(@Param("signId") String signId) { + if (StrUtil.isBlank(signId)) { + return Result.error("参数错误"); + } + try { + Chain chain = Chain.make("isReceive", 1); + chain.add("receiveTime", new Date()); + chain.add("giftScannerCodeUserId", ShiroUtil.getPrincipalProperty("id")); + dao.update(familyUserCourse.class, chain, Cnd.where("id", "=", signId)); + Sql signSql = Sqls.create("select isAttend,attendTime,isReceive,receiveTime from family_user_course where id = @signId"); + signSql.setParam("signId", signId); + NutMap signInfo = familyActivityService.fetch(signSql); + return Result.success(signInfo); + } catch (Exception e) { + log.error(e.getMessage()); + return Result.error("获取信息失败"); + } + } + + *//** + * 二维码扫描确认签到 + * + * @param signId + * @return + *//* + @At("/confirmSignByQrCode") + @RequiresAuthentication + public Object confirmSignByQrCode(@Param("signId") String signId) { + if (StrUtil.isBlank(signId)) { + return Result.error("参数错误"); + } + try { + Chain chain = Chain.make("isAttend", 1); + chain.add("attendTime", new Date()); + chain.add("signScannerCodeUserId", ShiroUtil.getPrincipalProperty("id")); + dao.update(familyUserCourse.class, chain, Cnd.where("id", "=", signId)); + + Sql signSql = Sqls.create("select isAttend,attendTime,isReceive,receiveTime from family_user_course where id = @signId"); + signSql.setParam("signId", signId); + NutMap signInfo = familyActivityService.fetch(signSql); + return Result.success(signInfo); + } catch (Exception e) { + log.error(e.getMessage()); + return Result.error("获取信息失败"); + } + } + + + public static Map sign(String jsapi_ticket, String url) { + Map ret = new HashMap(); + String nonce_str = create_nonce_str(); + String timestamp = create_timestamp(); + String string1; + String signature = ""; + + //注意这里参数名必须全部小写,且必须有序 + string1 = "jsapi_ticket=" + jsapi_ticket + + "&noncestr=" + nonce_str + + "×tamp=" + timestamp + + "&url=" + url; + System.out.println(string1); + + try { + MessageDigest crypt = MessageDigest.getInstance("SHA-1"); + crypt.reset(); + crypt.update(string1.getBytes("UTF-8")); + signature = byteToHex(crypt.digest()); + } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { + e.printStackTrace(); + } + + ret.put("url", url); + ret.put("jsapi_ticket", jsapi_ticket); + ret.put("nonceStr", nonce_str); + ret.put("timestamp", timestamp); + ret.put("signature", signature); + + return ret; + } + + private static String byteToHex(final byte[] hash) { + Formatter formatter = new Formatter(); + for (byte b : hash) { + formatter.format("%02x", b); + } + String result = formatter.toString(); + formatter.close(); + return result; + } + + private static String create_nonce_str() { + return UUID.randomUUID().toString(); + } + + private static String create_timestamp() { + return Long.toString(System.currentTimeMillis() / 1000); + }*/ + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/controller/statistics/FamilyActivityStatisticsController.java b/src/main/java/com/budwk/app/zhgh/activity/family/controller/statistics/FamilyActivityStatisticsController.java new file mode 100644 index 00000000..7d3eaf4b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/controller/statistics/FamilyActivityStatisticsController.java @@ -0,0 +1,280 @@ +package com.budwk.app.zhgh.activity.family.controller.statistics; + +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.afterturn.easypoi.excel.export.ExcelExportService; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.sys.models.Sys_file; +import com.budwk.app.sys.utils.SysFileMinIoUtil; +import com.budwk.app.zhgh.activity.family.models.FamilyMobileSignColumn; +import com.budwk.app.zhgh.activity.family.models.FamilyActivity; +import com.budwk.app.zhgh.activity.family.models.FamilyCourse; +import com.budwk.app.zhgh.activity.family.models.FamilyType; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityService; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsService; +import io.minio.GetObjectArgs; +import io.minio.MinioClient; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Lang; +import org.nutz.lang.Streams; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + + +/** + * @author zxy + * @Description 培训报名 统计 + * @createTime 2022年02月23日 09:57:00 + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "亲子活动统计") +@At("/platform/family/statistics/activity") +public class FamilyActivityStatisticsController { + + @Inject + private FamilyActivityService familyActivityManageService; + @Inject + private FamilyActivityStatisticsService familyActivityStatisticsService; + @Inject + private Dao dao; + + @At("") + @SaCheckPermission("family.statistics.activity") + @Ok("beetl:/platform/zhgh/activity/family/statistics/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("family.statistics.activity") + public Result pageData(PageForm pageForm, + @Param(value = "activityId") String activityId) { + Pagination pagination = familyActivityStatisticsService.pageData(pageForm, activityId); + return Result.success(pagination); + } + + /** + * 活动list + * + * @param year 年度 + * @return + */ + @At + @ApiOperation("活动列表") + @SaCheckPermission("family.statistics.activity") + public Result activityList(@Param(value = "year") Integer year) { + List list = dao.query(FamilyActivity.class, Cnd.NEW().andEX("year", "=", year).desc("activityStartTime")); + return Result.success(list); + } + + /** + * 培训班报名人员list + * + * @param courseId + * @return + */ + @At + @ApiOperation("报名人员列表") + @SaCheckPermission("family.statistics.activity") + public Result registerUserList(@Param(value = "courseId") String courseId) { + return Result.success(familyActivityStatisticsService.registerUserList(courseId)); + } + + @At + @ApiOperation("报名动态列") + @SaCheckPermission("family.statistics.activity") + public Object getTaleColumnInfo(@Param(value = "courseId") String courseId) { + return Result.success(familyActivityStatisticsService.getTaleColumnInfo(courseId)); + } + + /** + * 培训班上课签到信息 + * + * @param courseId + * @return + */ + @At + @ApiOperation("获取签到信息") + @SaCheckPermission("family.statistics.activity") + public Result getSignInfo(@Param("courseId") String courseId) { + return Result.success(familyActivityStatisticsService.getSignInfo(courseId)); + } + + @At + @ApiOperation("开放报名") + @SaCheckPermission("family.statistics.activity") + public Result signChange(@Param("courseId") String courseId, @Param("openOtherUnion") Boolean openOtherUnion) { + dao.update(FamilyCourse.class, Chain.make("openOtherUnion", openOtherUnion) + , Cnd.where("id", "=", courseId)); + return Result.success(); + } + + @At + @Ok("void") + @ApiOperation("导出签到名单") + @SaCheckPermission("family.statistics.activity") + public void exportSignUser(@Param(value = "activityId") String activityId, + HttpServletResponse response) throws IOException { + try { + FamilyActivity activity = dao.fetch(FamilyActivity.class, activityId); + Sql sql = Sqls.create(""" + SELECT + ts.*, + u.username, + u.loginname, + u.sex, + ifnull(u.mobile, ts.mobile) as newMobile, + u.birthday, + tsc.courseName + FROM + family_user ts + left join `vw_user` u on u.id = ts. userId + left join family_course tsc on tsc.id = ts.courseId + WHERE + ts.activityId = @activityId + """).setParam("activityId", activityId); + List userList = familyActivityManageService.listMap(sql); + + List courseList = dao.query(FamilyCourse.class, Cnd.where("activityId", "=", activityId)); + + List familyTypeList = dao.query(FamilyType.class, Cnd.NEW()); + dao.fetchLinks(familyTypeList, "familyMobileSignColumnList", Cnd.NEW().asc("columnIndex")); + Map typeMap = familyTypeList.stream().collect(Collectors.toMap(FamilyType::getId, o -> o)); + + List> sheetsList = new ArrayList<>(); + + List> basicEntity = List.of( + Map.of("name", "姓名", "key", "username"), + Map.of("name", "工号", "key", "loginname"), + Map.of("name", "单位", "key", "unitName"), + Map.of("name", "分工会", "key", "unionName"), + Map.of("name", "性别", "key", "sex"), + Map.of("name", "手机号", "key", "newMobile") + ); + + List excelCommonExportEntity = basicEntity.stream().map(entity -> { + ExcelExportEntity excelExportEntity = new ExcelExportEntity(); + excelExportEntity.setKey(entity.get("key")); + excelExportEntity.setName(entity.get("name")); + excelExportEntity.setWidth(20); + excelExportEntity.setNeedMerge(true); + return excelExportEntity; + }).collect(Collectors.toCollection(ArrayList::new)); + + for (FamilyCourse c : courseList) { + String k = c.getCourseName(); + List courseSignUsers = userList.stream().filter(x -> x.getString("courseName").equals(k)).collect(Collectors.toCollection(ArrayList::new)); + ExportParams userExportParams = new ExportParams(); + userExportParams.setSheetName(k); + userExportParams.setType(ExcelType.HSSF); + + List currentEntities = new ArrayList<>(excelCommonExportEntity); + + FamilyType signUpType = typeMap.get(c.getCourseType()); + if (Lang.isNotEmpty(signUpType.getFamilyMobileSignColumnList())) { + ExcelExportEntity familyEntity = new ExcelExportEntity("家属信息", "familyInfos", 20); + List signColumn = signUpType.getFamilyMobileSignColumnList().stream().map(column -> { + ExcelExportEntity entity = new ExcelExportEntity(); + entity.setName(column.getColumnName()); + entity.setKey(column.getColumnCode()); + entity.setWidth(20); + if ("FILE".equals(column.getColumnFormType())) { + entity.setType(2); + entity.setExportImageType(2); + } + return entity; + }).collect(Collectors.toCollection(ArrayList::new)); + familyEntity.setList(signColumn); + currentEntities.add(familyEntity); + } + for (NutMap userSignData : courseSignUsers) { + String mobileColumnsValueStr = userSignData.getString("mobileColumnsValue"); + if (StrUtil.isNotBlank(mobileColumnsValueStr)) { + JSONArray outerArray = JSONUtil.parseArray(mobileColumnsValueStr); + List> result = outerArray.stream() + .map(item -> { + // 每个 item 又是一个数组 + JSONArray innerArray = (JSONArray) item; + return innerArray.toList(JSONObject.class); + }) + .toList(); + List familyInfos = new ArrayList<>(); + for (List list : result) { + NutMap familyMap = new NutMap(); + for (JSONObject column : list) { + if (!"FILE".equals(column.getStr("columnFormType"))) { + familyMap.put(column.getStr("columnCode"), column.getStr("columnValue")); + } else { + if (StrUtil.isNotBlank(column.getStr("columnValue"))) { + List columnValue = Json.fromJsonAsList(JSONObject.class, column.getStr("columnValue")); + if (columnValue.size() == 1) { + JSONObject sysFile = columnValue.get(0); + Sys_file file = dao.fetch(Sys_file.class, Cnd.where(Sys_file::getDownloadPath, "=", sysFile.get("url"))); + byte[] imageBytes = SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath()); + if (imageBytes.length > 0) { + familyMap.put(column.getStr("columnCode"), imageBytes); + } + } + } + } + } + familyInfos.add(familyMap); + } + userSignData.put("familyInfos", familyInfos); + } + } + + Map userExportMap = new HashMap<>(); + userExportMap.put("name", k); + userExportMap.put("title", userExportParams); + userExportMap.put("entity", currentEntities); + userExportMap.put("data", courseSignUsers); + + sheetsList.add(userExportMap); + } + + Workbook workbook = new HSSFWorkbook(); + for (Map map : sheetsList) { + ExcelExportService service = new ExcelExportService(); + service.createSheetForMap(workbook, (ExportParams) map.get("title"), (List) map.get("entity"), (Collection) map.get("data")); + } + CommonDownloadUtil.download(activity.getActivityName() + "报名人员名单" + ".xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java new file mode 100644 index 00000000..7f0207a6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivity.java @@ -0,0 +1,136 @@ +package com.budwk.app.zhgh.activity.family.models; + +import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.models.Sys_home_activity; +import com.budwk.app.sys.services.SysHomeConvert; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; +import org.nutz.lang.Lang; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("亲子活动") +@Table("family_activity") +@EqualsAndHashCode(callSuper = false) +public class FamilyActivity extends BaseModel implements Serializable, SysHomeConvert { + + @Name + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("活动名称") + private String activityName; + + @Column + @ColDefine(type = ColType.INT) + @Comment("年度") + private Integer year; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("活动报名开始时间") + private Date activitySignUpStartTime; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("活动报名开始时间") + private Date activitySignUpEndTime; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("活动开始时间") + private Date activityStartTime; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("活动结束时间") + private Date activityEndTime; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否禁用") + @Default("0") + private boolean isDisabled; + + @Column + @ColDefine(customType = "longtext") + @Comment("活动介绍") + private String introduce; + + @Column + @ColDefine(type = ColType.INT, width = 10) + @Comment("活动限制标识") + private Integer restrictLimit; + + @Column + @ColDefine(type = ColType.INT, width = 10) + @Comment("活动限制报名个数") + private Integer limitNum; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("活动封面") + private String cover; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("微信群二维码") + private String wechat; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("上课前是否通知") + @Default("0") + private boolean notice; + + @Column + @Comment("活动范围Id") + @ColDefine(type = ColType.INT, width = 32) + private Integer activityGroupId; + + @Column + @Comment("活动范围名称") + @ColDefine(type = ColType.VARCHAR, width = 40) + private String activityGroupName; + + @Many(field = "activityId") + private List courseList; + + @Many(field = "activityId") + private List typeLimits; + + @Column + @Comment("活动类型") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String trainType; + + @Override + public Sys_home_activity covertToSysHomeActivity() { + Sys_home_activity sysHomeActivity = new Sys_home_activity(); + sysHomeActivity.setId(this.getId()); + sysHomeActivity.setName(this.getActivityName()); + sysHomeActivity.setCover(this.getCover()); + sysHomeActivity.setUrl("/platform/family/manage/apply"); + sysHomeActivity.setH5Url("/platform/mobile/familyActivity/familyList"); + if (Lang.isNotEmpty(this.getActivitySignUpStartTime())) { + sysHomeActivity.setStartDate(this.getActivitySignUpStartTime()); + sysHomeActivity.setEndDate(this.getActivitySignUpEndTime()); + } + sysHomeActivity.setAllowUserGroupId(this.getActivityGroupId()); + sysHomeActivity.setEnable(!this.isDisabled()); + sysHomeActivity.setClassPath(this.getClass().getPackageName() + this.getClass().getName()); + return sysHomeActivity; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivityCourse.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivityCourse.java new file mode 100644 index 00000000..1dbd4fd5 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyActivityCourse.java @@ -0,0 +1,57 @@ +package com.budwk.app.zhgh.activity.family.models; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.Date; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("亲子活动下的子活动") +@Table("family_activity_course") +@EqualsAndHashCode(callSuper = false) +public class FamilyActivityCourse { + + @Name + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("活动ID") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("课程ID") + private String courseId; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("课程开始时间") + private Date courseStartTime; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("课程结束时间") + private Date courseEndTime; + + @Column + @ColDefine(type = ColType.DATE) + @Comment("课程时间") + private Date courseDate; + + @Column + @ColDefine(type = ColType.INT, width = 4) + @Comment("限制人数") + private Integer courseLimitNum; + + private Integer hasRegisterNum; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyBlackList.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyBlackList.java new file mode 100644 index 00000000..89aa3d58 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyBlackList.java @@ -0,0 +1,34 @@ +package com.budwk.app.zhgh.activity.family.models; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("亲子活动黑名单") +@Table("family_black_list") +@EqualsAndHashCode(callSuper = false) +public class FamilyBlackList { + + @Name + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户id") + private String userId; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否禁用") + private Boolean isDisabled; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyCourse.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyCourse.java new file mode 100644 index 00000000..bcab9709 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyCourse.java @@ -0,0 +1,148 @@ +package com.budwk.app.zhgh.activity.family.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; +import org.nutz.lang.util.NutMap; + +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +@Comment("亲子活动的子活动") +@Table("family_course") +@EqualsAndHashCode(callSuper = false) +public class FamilyCourse extends BaseModel implements Serializable { + + @Name + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("活动ID") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("课程名称") + private String courseName; + + @Column + @ColDefine(type = ColType.INT) + @Comment("课程人数") + private int coursePeopleNumber; + + @Column + @ColDefine(type = ColType.INT) + @Default(value = "0") + @Comment("预留名额") + private int courseReservedNumber; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("课程地点") + private String courseLocation; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("课程类型") + private String courseType; + + @Column + @ColDefine(type = ColType.MYSQL_JSON) + @Comment("课程地点坐标") + private List courseLocationCoordinates; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("课程讲师") + private String courseInstructor; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("校区") + private String campus; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("报名人数是否限制") + private Boolean courseIsLimitApply; + + @Column + @ColDefine(type = ColType.INT) + @Comment("序号") + private int orderNum; + + @Many(field = "courseId") + private List courseTimeList; + + @Column + @Comment("分工会人数限制") + @ColDefine(type = ColType.MYSQL_JSON) + private List unionLimit; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("移动端是否签到") + private boolean isMobileSign; + + @Column + @ColDefine(type = ColType.INT) + @Comment("签到方式 1.扫描二维码签到 2.被扫 3.gps签到") + private Integer signType; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("移动端是否签收礼品") + private boolean isReceiveGift; + + @Column + @ColDefine(type = ColType.INT) + @Comment("领取礼品方式 1.扫描二维码 2.线下") + private Integer giftType; + + @Column + @ColDefine(type = ColType.INT) + @Comment("预留名额方式 1.报名人员减少模式 2.报名人数不变模式") + private Integer reserveMode; + + @Column + @Comment("承办工会") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String hostUnionId; + + @Column + @Comment("对内报名时间") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String interTime; + + @Column + @Comment("是否开放给其他工会") + @ColDefine(type = ColType.BOOLEAN, width = 4) + private Boolean openOtherUnion; + + @Column + @Comment("分类标识") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String assort; + + @Column + @ColDefine(type = ColType.INT) + @Default(value = "0") + @Comment("候补名额数") + private Integer waitingNum; + + private Integer hasWaitingNum; + private String courseTimeName; + private Integer hasRegisterNum; + private Boolean isBringFamily; + private Boolean isAddFamily; + private Boolean isSign; + private Boolean canSignThisCourseType; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyMobileSignColumn.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyMobileSignColumn.java new file mode 100644 index 00000000..877b5156 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyMobileSignColumn.java @@ -0,0 +1,87 @@ +package com.budwk.app.zhgh.activity.family.models; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("亲子活动移动端动态表单") +@Table("family_mobile_sign_column") +@EqualsAndHashCode(callSuper = false) +public class FamilyMobileSignColumn implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("类型id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String typeId; + + @Column + @Comment("字段名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String columnName; + + @Column + @Comment("字段编码") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String columnCode; + + @Column + @Comment("字段值") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String columnValue; + + @Column + @Comment("字段类型") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String columnType; + + @Column + @Comment("下拉框的值") + @ColDefine(type = ColType.MYSQL_JSON) + private List selectValues; + + @Column + @Comment("是否必填") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isRequired; + + @Column + @Comment("控件类型") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String columnFormType; + + @Column + @Comment("文件个数") + @ColDefine(type = ColType.INT) + private Integer fileNumber; + + @Column + @Comment("文件类型") + @ColDefine(type = ColType.MYSQL_JSON) + private List fileType; + + @Column + @Comment("序号") + @ColDefine(type = ColType.INT, width = 1) + private Integer columnIndex; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyType.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyType.java new file mode 100644 index 00000000..69065610 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyType.java @@ -0,0 +1,73 @@ +package com.budwk.app.zhgh.activity.family.models; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("亲子活动的子活动类型") +@Table("family_type") +@EqualsAndHashCode(callSuper = false) +public class FamilyType extends BaseModel implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("类型编码") + @ColDefine(type = ColType.VARCHAR, width = 80) + private String code; + + @Column + @Comment("类型名称") + @ColDefine(type = ColType.VARCHAR, width = 80) + private String typeName; + + @Column + @Comment("序号") + @ColDefine(type = ColType.INT, width = 1) + private Integer xh; + + @Column + @Comment("是否携带家属") + @ColDefine(type = ColType.BOOLEAN) + @Default("1") + private Boolean isBringFamily; + + @Column + @Comment("家属纳入总人数") + @ColDefine(type = ColType.BOOLEAN) + @Default("1") + private Boolean isAddFamily; + + @Column + @Comment("本人纳入总人数") + @ColDefine(type = ColType.BOOLEAN) + @Default("1") + private Boolean selfAddFamily; + + @Many(field = "typeId") + private List familyMobileSignColumnList; + + @Column + @Comment("家属最多数") + @ColDefine(type = ColType.INT) + private Integer familyMaxCount; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyTypeLimit.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyTypeLimit.java new file mode 100644 index 00000000..21533205 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyTypeLimit.java @@ -0,0 +1,45 @@ +package com.budwk.app.zhgh.activity.family.models; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serial; +import java.io.Serializable; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("子活动类型限制条件") +@Table("family_type_limit") +@EqualsAndHashCode(callSuper = false) +public class FamilyTypeLimit implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("活动id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String activityId; + + @Column + @Comment("活动类型id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String typeId; + + @Column + @Comment("限制个数") + @ColDefine(type = ColType.INT, width = 10) + private int limitNum; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyUser.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyUser.java new file mode 100644 index 00000000..4ff9afed --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyUser.java @@ -0,0 +1,84 @@ +package com.budwk.app.zhgh.activity.family.models; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; +import org.nutz.lang.util.NutMap; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("亲子活动报名人员") +@Table("family_user") +@EqualsAndHashCode(callSuper = false) +@TableIndexes({@Index(name = "INDEX_FAMILY_USER_COURSEID", fields = {"courseId"}, unique = false)}) +public class FamilyUser implements Serializable { + + @Name + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("活动ID") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("课程ID") + private String courseId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户ID") + private String userId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("工会ID") + private String unionId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("单位ID") + private String unitId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("工会") + private String unionName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("单位") + private String unitName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("联系方式") + private String mobile; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("报名时间") + private Date signUpTime; + + @Column + @ColDefine(type = ColType.MYSQL_JSON) + @Comment("手机端报名字段和值") + private List> mobileColumnsValue; + + @Column + @ColDefine(type = ColType.INT) + @Comment("用户报名状态(1.正常 2.待报名成功 3.也是正常,但是是从2变为1的 4.废弃[就是没签到的意思])") + private Integer state; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyUserCourse.java b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyUserCourse.java new file mode 100644 index 00000000..7c0c234c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/models/FamilyUserCourse.java @@ -0,0 +1,90 @@ +package com.budwk.app.zhgh.activity.family.models; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author NINGMEI + */ +@Data +@Accessors(chain = true) +@Comment("亲子活动报名人员子活动表") +@Table("family_user_course") +@EqualsAndHashCode(callSuper = false) +@TableIndexes({ + @Index(name = "INDEX_FAMILY_USER_COURSE_USERID", fields = {"userId"}, unique = false), + @Index(name = "INDEX_FAMILY_USER_COURSE_COURSEID", fields = {"courseId"}, unique = false) +}) +public class FamilyUserCourse implements Serializable { + + @Name + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("活动ID") + private String activityId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("课程ID") + private String courseId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户ID") + private String userId; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("课程开始时间") + private Date courseStartTime; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("课程结束时间") + private Date courseEndTime; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否上课") + private boolean isAttend; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("上课打卡时间") + private Date attendTime; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否领取礼品") + private Boolean isReceive; + + @Column + @ColDefine(type = ColType.DATETIME) + @Comment("领取礼品时间") + private Date receiveTime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("签到扫码人员id(二维码模式)") + private String signScannerCodeUserId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("礼品扫码人员id(二维码模式)") + private String giftScannerCodeUserId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("关联family_activity_course表的id") + private String activityCourseId; + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityService.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityService.java new file mode 100644 index 00000000..537b297b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityService.java @@ -0,0 +1,116 @@ +package com.budwk.app.zhgh.activity.family.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.family.models.FamilyActivity; +import com.budwk.app.zhgh.activity.family.models.FamilyCourse; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; +import org.nutz.dao.Cnd; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +/** + * @author NINGMEI + */ +public interface FamilyActivityService extends BaseService { + + /** + * 添加活动 + * @param activity 活动信息 + * @param course 培训班信息 + */ + void add(FamilyActivity activity, FamilyCourse course); + + /** + * 编辑活动 + * @param activity 活动信息 + */ + void edit(FamilyActivity activity); + + /** + * 更新活动状态 + * @param activity 活动信息 + */ + void updateActivityStatus(FamilyActivity activity); + + /** + * 查询单条活动信息 + * @param id 活动ID + * @return 返回的数据与前端符合 + */ + NutMap findOne(String id, Cnd cnd, String fromMode); + + /** + * pc分页查询 + * @param pageForm + * @param cnd + * @return + */ + Pagination pageData(PageForm pageForm, Cnd cnd); + + + /** + * 手机端分页查询 + * @param pageForm 分页 + * @param year 年度 + * @param activityStatus 报名状态 0全部 1进行中 2结束 + * @return + */ + Pagination mPageData(PageForm pageForm, Integer year, int activityStatus, Integer activityType); + + /** + * 手机端报名 + * @param familyUser 活动ID + */ + void doSignUp(FamilyUser familyUser) throws Exception; + + /** + * 异步插入每个报名成功人员的课程数据 + * @param activityId + * @param courseId + * @param userId + */ + void asyncInsertUserCourse(String activityId, String courseId, String userId); + + /** + * 该培训班每个分工会名额是否报满 + * @return + */ + boolean isSignFullByUnionId(FamilyCourse course, Integer currentFamilyNumber); + + /** + * 该培训班是否报满 + */ + boolean isSignFull(FamilyCourse course, Integer currentFamilyNumber); + + /** + * 还能报该类型的培训班吗 比如书画班最多报一项 健身班两项 + * @return + */ + boolean isSignCourse(FamilyCourse course, FamilyActivity activity); + + /** + * 当前用户是否已报过该培训班 + * @param courseId + * @param userId + * @return + */ + boolean isSignCourseByUser(String courseId, String userId); + + /** + * 手机端签到 + * @param id 每个培训班每节课每个用户的记录ID + */ + void doQd(String id); + + /** + * 某个用户的签到信息 + * @param userId 用户id + * @param activityId 活动id + */ + List qdInfoByUserId(String userId, String activityId); + + List filterCourseByHostUnion(List courseList); +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityStatisticsService.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityStatisticsService.java new file mode 100644 index 00000000..598a4e0a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyActivityStatisticsService.java @@ -0,0 +1,62 @@ +package com.budwk.app.zhgh.activity.family.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; +import org.nutz.lang.util.NutMap; + +import java.util.List; +import java.util.Map; + +/** + * @author NINGMEI + */ +public interface FamilyActivityStatisticsService extends BaseService { + + /** + * 统计分页 + * @param pageForm + * @param activityId + * @return + */ + Pagination pageData(PageForm pageForm, String activityId); + + /** + * 该课程下的报名人员信息 + * @param courseId + * @return + */ + List registerUserList(String courseId); + + List getTaleColumnInfo(String courseId); + + /** + * 该课程下的报名人员信息 + * @param courseId + * @return + */ + List registerUserList(String courseId, String unionId, String unitId, String searchName, String searchKeyword); + + /** + * 获取每个课程的签到情况 + * @param courseId + * @return k->每个培训班每节课的上课时间 v->上课记录list + */ + Map> getSignInfo(String courseId); + + /** + * 报名人员list 导出 + * @param activityId + * @return + */ + List baoMingUserList(String activityId); + + int queryCourseCount(String courseId, String courseType); + + int queryCourseWaitCount(String courseId, String courseType); + + int queryCourseCount(String courseId, String courseType, String unionId); + + int queryCourseWaitCount(String courseId, String courseType, String unionId); +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyBlackListService.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyBlackListService.java new file mode 100644 index 00000000..83e728bb --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/FamilyBlackListService.java @@ -0,0 +1,37 @@ +package com.budwk.app.zhgh.activity.family.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.family.models.FamilyBlackList; +import org.nutz.dao.Cnd; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +/** + * @author NINGMEI + */ +public interface FamilyBlackListService extends BaseService { + + /** + * 分页 + * @param pageForm 分页 + * @return Pagination + */ + Pagination pageData(PageForm pageForm, Cnd cnd, String activityId, String courseId); + + /** + * 拉黑、解封用户 + * @param userId + */ + void doHandleUser(String userId); + + /** + * 上课记录 + * @param userId + * @return + */ + List attendClassRecord(String userId); + +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java new file mode 100644 index 00000000..5ee19e03 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityServiceImpl.java @@ -0,0 +1,458 @@ +package com.budwk.app.zhgh.activity.family.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_home_activity; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.family.models.*; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityService; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.async.Async; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + * @author NINGMEI + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class FamilyActivityServiceImpl extends BaseServiceImpl implements FamilyActivityService { + + @Inject + private FamilyActivityStatisticsService statisticsService; + + public FamilyActivityServiceImpl(Dao dao) { + super(dao); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void add(FamilyActivity activity, FamilyCourse course) { + + dao().insert(activity); + + //插入类型限制 + List typeLimits = activity.getTypeLimits(); + typeLimits.forEach(v -> v.setActivityId(activity.getId())); + dao().insert(typeLimits); + + List courseList = activity.getCourseList(); + for (FamilyCourse v : courseList) { + v.setActivityId(activity.getId()); + v.setOpenOtherUnion(false); + dao().insert(v); + this.setCourseTimeAndInsert(v); + } + + if (!activity.isDisabled()) { + Sys_home_activity sysHomeActivity = activity.covertToSysHomeActivity(); + dao().insertOrUpdate(sysHomeActivity); + } + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void edit(FamilyActivity activity) { + + //修改活动 + update(activity); + + //修改类型限制 + List typeLimits = activity.getTypeLimits(); + typeLimits.forEach(v -> v.setActivityId(activity.getId())); + if(Lang.isNotEmpty(typeLimits)) { + insertOrUpdate(typeLimits); + } + + List courseList = activity.getCourseList(); + courseList.forEach(v -> { + v.setActivityId(activity.getId()); + dao().insertOrUpdate(v); + if (Lang.isNotEmpty(v.getCourseTimeList())) { + this.setCourseTimeAndInsert(v); + } + }); + + //查询原来的活动 + List oldCourseList = dao().query(FamilyCourse.class, Cnd.where("activityId", "=", activity.getId())); + //原来的培训班id + List oldCourseIdList = oldCourseList.stream().map(FamilyCourse::getId).toList(); + + //原来的上课时间 + List oldActCourseTimeList = dao().query(FamilyActivityCourse.class, Cnd.where("activityId", "=", activity.getId())); + + //现在的上课时间 + List nowCourseTimeListId = new ArrayList<>(); + activity.getCourseList().forEach(v -> { + if (v.getCourseTimeList() != null) { + nowCourseTimeListId.addAll(v.getCourseTimeList().stream().map(FamilyActivityCourse::getId).toList()); + } + }); + + List deleteCourseTimeListId = oldActCourseTimeList.stream().map(FamilyActivityCourse::getId).filter(id -> !nowCourseTimeListId.contains(id)).collect(Collectors.toList()); + List courseIdList = courseList.stream().map(FamilyCourse::getId).collect(Collectors.toList()); + + //删除关联的培训班 + List deleteIdList = oldCourseIdList.stream().filter(v -> !courseIdList.contains(v)).collect(Collectors.toList()); + dao().clear(FamilyCourse.class, Cnd.where("id", "in", deleteIdList)); + + dao().clear(FamilyActivityCourse.class, Cnd.where("id", "in", deleteCourseTimeListId)); + dao().clear(FamilyUser.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); + dao().clear(FamilyUserCourse.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); + + //查询修改过培训时间的记录 + Sql tsuucSql = Sqls.create(""" + SELECT + tsuuc.id, + tsuac.courseStartTime, + tsuac.courseEndTime + FROM + `family_user_course` tsuuc + LEFT JOIN family_activity_course tsuac ON tsuac.id = tsuuc.activityCourseId + where tsuuc.courseStartTime != tsuac.courseStartTime or tsuuc.courseEndTime != tsuac.courseEndTime + """); + List tsuucList = listMap(tsuucSql); + tsuucList.forEach(v -> { + Chain chain = Chain.make("courseStartTime", v.getTime("courseStartTime")); + chain.add("courseEndTime", v.getTime("courseEndTime")); + Cnd cnd = Cnd.where("id", "=", v.getString("id")); + dao().update("family_user_course", chain, cnd); + }); + + if (!activity.isDisabled()) { + Sys_home_activity sysHomeActivity = activity.covertToSysHomeActivity(); + dao().insertOrUpdate(sysHomeActivity); + } else { + dao().delete(Sys_home_activity.class, activity.getId()); + } + } + + private void setCourseTimeAndInsert(FamilyCourse course) { + course.getCourseTimeList().forEach(courseTime -> { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(courseTime.getCourseDate()); + int year = calendar.get(Calendar.YEAR); + int month = calendar.get(Calendar.MONTH); + int day = calendar.get(Calendar.DATE); + + Calendar startCalendar = Calendar.getInstance(); + startCalendar.setTime(courseTime.getCourseStartTime()); + startCalendar.set(year, month, day); + courseTime.setCourseStartTime(startCalendar.getTime()); + + Calendar endCalendar = Calendar.getInstance(); + endCalendar.setTime(courseTime.getCourseEndTime()); + endCalendar.set(year, month, day); + courseTime.setCourseEndTime(endCalendar.getTime()); + + courseTime.setActivityId(course.getActivityId()); + courseTime.setCourseId(course.getId()); + dao().insertOrUpdate(courseTime); + }); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void updateActivityStatus(FamilyActivity activity) { + updateIgnoreNull(activity); + } + + @Override + public NutMap findOne(String id, Cnd cnd, String fromMode) { + if (Lang.isEmpty(cnd)) { + cnd = Cnd.NEW(); + } + + cnd.asc("orderNum").asc("campus").desc("courseLocation").asc("courseType").asc("courseName"); + List courseArray = dao().query(FamilyCourse.class, cnd.and("activityId", "=", id)); + + if (StrUtil.isNotBlank(fromMode) && "mobile".equals(fromMode)) { + courseArray = this.filterCourseByHostUnion(courseArray); + } + + FamilyActivity activity = fetchLinks(dao().fetch(FamilyActivity.class, id), "^(conditionStructure|typeLimits)$"); + activity.setCourseList(courseArray); + + List courseList = activity.getCourseList(); + + courseList.forEach(c -> { + if (StrUtil.isNotBlank(c.getCourseType())) { + dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime")); + int courseCount = statisticsService.queryCourseCount(c.getId(), c.getCourseType()); + c.setHasRegisterNum(courseCount); + int courseWaitCount = statisticsService.queryCourseWaitCount(c.getId(), c.getCourseType()); + c.setHasWaitingNum(courseWaitCount); + //当前用户是否报过 + c.setIsSign(isSignCourseByUser(c.getId(), SecurityUtil.getUserId())); + } + }); + return Lang.obj2nutmap(activity); + } + + @Override + public Pagination pageData(PageForm pageForm, Cnd cnd) { + Pagination pagination = listPageLinks(pageForm.getPageNumber(), pageForm.getPageSize(), cnd, "^(courseList)$"); + return pagination; + } + + @Override + public Pagination mPageData(PageForm pageForm, Integer year, int activityStatus, Integer activityType) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("year", "=", year); + switch (activityStatus) { + case 2 -> { + cnd.and(new Static("activitySignUpStartTime < now()")); + cnd.and(new Static("activitySignUpEndTime > now()")); + } + case 3 -> { + cnd.and(new Static("activityStartTime < now()")); + cnd.and(new Static("activityEndTime > now()")); + } + case 4 -> cnd.and(new Static("activityEndTime < now()")); + case 5 -> cnd.and(new Static("activityStartTime < now()")); + case 6 -> cnd.and(new Static("activityStartTime > now()")); + } + if (activityType != null && activityType == 1) { + cnd.and(new Static("id in (select activityId from family_user where userId = '%s')".formatted(SecurityUtil.getUserId()))); + } + cnd.and("isDisabled", "=", 0); + cnd.orderBy("activityEndTime", "desc"); + cnd.orderBy("isDisabled", "desc"); + cnd.orderBy("createdAt", "desc"); + return listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void doSignUp(FamilyUser familyUser) throws Exception { + String userId = SecurityUtil.getUserId(); + + //查询课程 + FamilyCourse course = dao().fetch(FamilyCourse.class, familyUser.getCourseId()); + FamilyType type = dao().fetch(FamilyType.class, course.getCourseType()); + //如果这个课程的预留名额方式为报名人数不变 + if (course.getReserveMode() == 2) { + //如果当前报名+已报小于这个课程限制人数 + //课程已报人数 + int normalCount = statisticsService.queryCourseCount(course.getId(), course.getCourseType()); + //+1是算自己 + int hasRegisterNum = type.getSelfAddFamily() ? normalCount + 1 : 0; + familyUser.setState((hasRegisterNum + course.getCourseReservedNumber()) > course.getCoursePeopleNumber() ? 2 : 1); + } else { + familyUser.setState(1); + } + + View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + familyUser.setUnionId(SecurityUtil.getUnionId()); + familyUser.setUnionName(user.getUnionName()); + familyUser.setUnitId(SecurityUtil.getUnitId()); + familyUser.setUnitName(user.getUnitName()); + familyUser.setUserId(userId); + familyUser.setSignUpTime(new Date()); + + dao().insert(familyUser); + asyncInsertUserCourse(familyUser.getActivityId(), familyUser.getCourseId(), userId); + } + + @Async + @Override + public void asyncInsertUserCourse(String activityId, String courseId, String userId) { + log.info("异步插入{}的上课信息,课程ID为{},活动ID为{}", userId, courseId, activityId); + List courseList = dao().query(FamilyActivityCourse.class, Cnd.where("courseId", "=", courseId)); + List list = new ArrayList<>(); + courseList.forEach(v -> { + FamilyUserCourse userCourse = new FamilyUserCourse(); + userCourse.setActivityId(activityId); + userCourse.setCourseId(courseId); + userCourse.setUserId(userId); + userCourse.setCourseStartTime(v.getCourseStartTime()); + userCourse.setCourseEndTime(v.getCourseEndTime()); + userCourse.setAttend(false); + userCourse.setAttendTime(null); + userCourse.setActivityCourseId(v.getId()); + list.add(userCourse); + }); + dao().insert(list); + } + + /** + * 该培训班每个分工会名额是否报满 + * @return + */ + @Override + public boolean isSignFullByUnionId(FamilyCourse course, Integer currentFamilyNumber) { + List unionLimit = course.getUnionLimit(); + if (Lang.isEmpty(unionLimit)) { + return false; + } + String unionId = SecurityUtil.getUnionId(); + NutMap unionLimitMap = unionLimit.stream().filter(v -> v.getString("id").equals(unionId)).findAny().orElse(null); + if (Lang.isEmpty(unionLimitMap)) { + return true; + } + + FamilyType type = dao().fetch(FamilyType.class, course.getCourseType()); + //分工会限制人数 + int limitCount = unionLimitMap.getInt("limitCount"); + + //该课程已经报名的总人数 + int hasSignCount = statisticsService.queryCourseCount(course.getId(), course.getCourseType(), unionId); + int hasWaitCount = statisticsService.queryCourseWaitCount(course.getId(), course.getCourseType()); + + //+1是算自己 + int current = type.getSelfAddFamily() ? 1 : 0; + currentFamilyNumber = type.getIsBringFamily() && type.getIsAddFamily() ? currentFamilyNumber : 0; + //如果还有正常名额 + if(limitCount - hasSignCount > 0) { + return (hasSignCount + current + currentFamilyNumber) > limitCount; + } else { + return (hasWaitCount + current + currentFamilyNumber) > course.getWaitingNum(); + } + } + + @Override + public boolean isSignFull(FamilyCourse course, Integer currentFamilyNumber) { + //课程限制人数 + int coursePeopleNumber = course.getCoursePeopleNumber(); + if (coursePeopleNumber == 0) { + return true; + } + //查询课程对应的类型 + FamilyType type = dao().fetch(FamilyType.class, course.getCourseType()); + //课程已报人数 + int hasSignCount = statisticsService.queryCourseCount(course.getId(), course.getCourseType()); + int hasWaitCount = statisticsService.queryCourseWaitCount(course.getId(), course.getCourseType()); + + //+1是算自己 + int current = type.getSelfAddFamily() ? 1 : 0; + currentFamilyNumber = type.getIsBringFamily() && type.getIsAddFamily() ? currentFamilyNumber : 0; + //如果还有正常名额 + if(coursePeopleNumber - hasSignCount > 0) { + return (hasSignCount + current + currentFamilyNumber + course.getCourseReservedNumber()) > coursePeopleNumber; + } else { + return (hasWaitCount + current + currentFamilyNumber) > course.getWaitingNum(); + } + } + + @Override + public boolean isSignCourse(FamilyCourse course, FamilyActivity activity) { + //培训班类型 + String courseType = course.getCourseType(); + + Sql sql = Sqls.create(""" + SELECT + count( tsus.id ) + FROM + `family_user` tsus + LEFT JOIN family_course tsuc ON tsuc.id = tsus.courseId + WHERE + tsuc.courseType = @courseType + AND tsus.userId = @userId + AND tsus.activityId = @activityId + """); + sql.setParam("courseType", courseType); + sql.setParam("activityId", activity.getId()); + sql.setParam("userId", SecurityUtil.getUserId()); + int hasRegisterNum = count(sql); + + //第一种无限制报名 + if (activity.getRestrictLimit() == null || activity.getRestrictLimit() == 1) { + return true; + } else if (activity.getRestrictLimit() == 2) { + FamilyTypeLimit familyTypeLimit = dao().fetch(FamilyTypeLimit.class, Cnd.where("typeId", "=", courseType).and("activityId", "=", activity.getId())); + if (familyTypeLimit == null) { + return true; + } + //此类型的班最多可报几项 + int personMaxRegisterNum = familyTypeLimit.getLimitNum(); + if (personMaxRegisterNum == 0) { + return true; + } + return hasRegisterNum < personMaxRegisterNum; + } else if (activity.getRestrictLimit() == 3) { + //第三种,限制报几个,不跟类型挂钩 + int aCount = dao().count(FamilyUser.class, Cnd.where("activityId", "=", activity.getId()).and("userId", "=", SecurityUtil.getUserId())); + return aCount < activity.getLimitNum(); + } + return false; + } + + @Override + public boolean isSignCourseByUser(String courseId, String userId) { + return dao().count(FamilyUser.class, Cnd.where("courseId", "=", courseId).and("userId", "=", userId)) > 0; + } + + @Override + public void doQd(String id) { + NutMap updateMap = NutMap.NEW(); + updateMap.put("isAttend", true); + updateMap.put("attendTime", new Date()); + dao().update(FamilyUserCourse.class, Chain.from(updateMap), Cnd.where("id", "=", id)); + } + + @Override + public List qdInfoByUserId(String userId, String activityId) { + Sql sql = Sqls.create(""" + SELECT + c.*, + t.courseLocationCoordinates, + t.isMobileSign, + t.signType, + t.isReceiveGift, + t.giftType, + (select state from family_user su where su.activityId = c.activityId and su.courseId = c.courseId and su.userId = c.userId) as state + FROM + `family_user_course` c + LEFT JOIN family_course t ON t.id = c.courseId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("c.activityId", "=", activityId); + cnd.and("c.userId", "=", userId); + cnd.asc("c.courseStartTime"); + + sql.setCondition(cnd); + return listMap(sql); + } + + @Override + public List filterCourseByHostUnion(List courseList) { + if (Lang.isEmpty(courseList)) { + return new ArrayList<>(); + } + return courseList.stream().filter(o -> { + if (StrUtil.isBlank(o.getInterTime()) || o.getOpenOtherUnion() == null || o.getOpenOtherUnion()) { + return true; + } else { + if (SecurityUtil.getUnionId().equals(o.getHostUnionId())) { + return true; + } else { + int compare = cn.hutool.core.date.DateUtil.compare(cn.hutool.core.date.DateUtil.date(), cn.hutool.core.date.DateUtil.parse(o.getInterTime()), "yyyy-MM-dd HH:mm"); + return compare >= 0; + } + } + }).toList(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityStatisticsServiceImpl.java new file mode 100644 index 00000000..0cc0e48a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyActivityStatisticsServiceImpl.java @@ -0,0 +1,269 @@ +package com.budwk.app.zhgh.activity.family.service.impl; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.family.models.FamilyMobileSignColumn; +import com.budwk.app.zhgh.activity.family.models.FamilyCourse; +import com.budwk.app.zhgh.activity.family.models.FamilyType; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + * @author zxy + * @Description TODO + * @createTime 2022年03月03日 10:02:00 + */ +@IocBean(args = {"refer:dao"}) +@Slf4j +public class FamilyActivityStatisticsServiceImpl extends BaseServiceImpl implements FamilyActivityStatisticsService { + + public FamilyActivityStatisticsServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Pagination pageData(PageForm pageForm, String activityId) { + Sql sql = Sqls.create(""" + SELECT + tsuc.id, + tsuc.courseName, + tsuc.coursePeopleNumber, + tsuc.courseReservedNumber, + type.typeName as courseType, + tsuc.courseLocation, + tsuc.courseInstructor, + tsuc.reserveMode, + tsuc.isMobileSign, + tsuc.hostUnionId, + tsuc.interTime, + tsuc.waitingNum, + tsuc.openOtherUnion, + tsuc.courseType as cType + FROM + `family_course` tsuc + LEFT JOIN + family_type type on tsuc.courseType = type.id + WHERE + tsuc.activityId = @activityId + ORDER BY tsuc.orderNum + """); + sql.setParam("activityId", activityId); + Pagination pagination = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List courseList = pagination.getList(); + courseList.forEach(c -> { + c.put("registerNum", queryCourseCount(c.getString("id"), c.getString("cType"))); + c.put("hasWaitingNum", queryCourseWaitCount(c.getString("id"), c.getString("cType"))); + }); + return pagination; + } + + @Override + public List registerUserList(String courseId) { + Sql sql = Sqls.create(""" + SELECT + u.loginname, + u.username, + u.sex, + tsuu.unionId, + tsuu.unionName, + tsuu.unitId, + tsuu.unitName, + ifnull(tsuu.mobile, u.mobile) as mobile, + tsuu.signUpTime, + tsuu.state, + tsuu.mobileColumnsValue + FROM + family_user tsuu + LEFT JOIN `vw_user` u ON u.id = tsuu.userId + $condition + ORDER BY FIELD( tsuu.state, 1, 3, 2, 4 ),u.unionid desc, u.unitid desc + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("tsuu.courseId", "=", courseId); + sql.setCondition(cnd); + List listMap = listMap(sql); + for (NutMap nutMap : listMap) { + // 第一步:解析为 JSONArray(外层数组) + JSONArray outerArray = JSONUtil.parseArray(nutMap.getString("mobileColumnsValue")); + // 第二步:转换为 List> + List> result = outerArray.stream() + .map(item -> { + // 每个 item 又是一个数组 + JSONArray innerArray = (JSONArray) item; + return innerArray.toList(JSONObject.class); + }) + .toList(); + nutMap.put("mobileColumnsValue", result); + nutMap.put("familyCount", result.size()); + } + return listMap; + } + + @Override + public List getTaleColumnInfo(String courseId) { + FamilyCourse course = dao().fetch(FamilyCourse.class, courseId); + FamilyType upType = dao().fetch(FamilyType.class, course.getCourseType()); + dao().fetchLinks(upType, "familyMobileSignColumnList", Cnd.NEW().asc("columnIndex")); + + List columnList = upType.getFamilyMobileSignColumnList(); + List columnTableList = columnList.stream().map(o -> NutMap.NEW().setv("label", o.getColumnName()).setv("prop", o.getColumnCode())).collect(Collectors.toList()); + return columnTableList; + } + + @Override + public List registerUserList(String courseId, String unionId, String unitId, String searchName, String searchKeyword) { + Sql sql = Sqls.create(""" + SELECT + tsuu.id, + u.id as userId, + u.loginname, + u.username, + u.unitname, + u.unionname, + u.sex, + u.mobile, + tsuu.signUpTime, + tsuu.state + FROM + family_user tsuu + LEFT JOIN `vw_user` u ON u.id = tsuu.userId + $condition + ORDER BY FIELD( tsuu.state, 1, 3, 2, 4 ),u.unionid desc, u.unitid desc + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("tsuu.courseId", "=", courseId); + cnd.andEX("u.unionid", "=", unionId); + cnd.andEX("u.unitid", "=", unitId); + if (StrUtil.isNotBlank(searchKeyword)) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.andLike("username", searchKeyword).orLike("loginname", searchKeyword); + cnd.and(group); + } + sql.setCondition(cnd); + return listMap(sql); + } + + @Override + public Map> getSignInfo(String courseId) { + Sql sql = Sqls.create(""" + SELECT + tsuuc.courseStartTime, + tsuuc.courseEndTime, + tsuuc.isAttend, + tsuuc.attendTime, + u.username, + u.loginname, + u.unitname, + u.unionname + FROM + `family_user_course` tsuuc + LEFT JOIN `vw_user` u ON u.id = tsuuc.userId + WHERE + tsuuc.courseId = @courseId + """); + sql.setParam("courseId", courseId); + List list = listMap(sql); + + Map> courseTimeMap = list.stream().map(v -> { + String courseTime = v.getString("courseStartTime") + " 至 " + v.getString("courseEndTime"); + v.put("courseTime", courseTime); + return v; + }).collect(Collectors.groupingBy(v -> v.getString("courseTime"))); + + // 使用Stream API进行降序排序 + Map> sortedDataMap = courseTimeMap.entrySet().stream() + .sorted(Map.Entry.comparingByKey(Comparator.reverseOrder())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); + + return sortedDataMap; + } + + @Override + public List baoMingUserList(String activityId) { + Sql sql = Sqls.create(""" + SELECT + u.loginname, + u.username, + u.unitname, + u.unionname, + u.sex, + u.mobile, + uc.courseName, + uc.campus + FROM + `family_user` uu + RIGHT JOIN family_course uc ON uc.id = uu.courseId + LEFT JOIN `vw_user` u ON u.id = uu.userId + WHERE + uc.activityId = @activityId + ORDER BY u.unitCode,u.unioncode,u.sex + """); + sql.setParam("activityId", activityId); + return listMap(sql); + } + + @Override + public int queryCourseCount(String courseId, String courseType) { + return this.queryCourseCount(courseId, courseType, null); + } + + @Override + public int queryCourseWaitCount(String courseId, String courseType) { + return this.queryCourseWaitCount(courseId, courseType, null); + } + + @Override + public int queryCourseCount(String courseId, String courseType, String unionId) { + return this.calcSignCount(courseId, courseType, unionId, List.of(1, 3)); + } + + @Override + public int queryCourseWaitCount(String courseId, String courseType, String unionId) { + return this.calcSignCount(courseId, courseType, unionId, List.of(2)); + } + + private int calcSignCount(String courseId, String courseType, String unionId, List stateList) { + if(StrUtil.isBlank(courseId) || StrUtil.isBlank(courseType)) { + return 0; + } + FamilyType type = dao().fetch(FamilyType.class, courseType); + AtomicInteger hasRegisterNum = new AtomicInteger(); + List signUpUsers = dao().query(FamilyUser.class, Cnd.where("courseId", "=", courseId) + .and("state", "in", stateList) + .andEX("unionId", "=", unionId)); + signUpUsers.forEach(item -> { + if (type.getSelfAddFamily()) { + hasRegisterNum.getAndIncrement(); + } + if (type.getIsBringFamily() && type.getIsAddFamily()) { + List> mapList = item.getMobileColumnsValue(); + if (Lang.isNotEmpty(mapList)) { + hasRegisterNum.addAndGet(mapList.size()); + } + } + }); + return hasRegisterNum.get(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyUserServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyUserServiceImpl.java new file mode 100644 index 00000000..64c52b8f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/family/service/impl/FamilyUserServiceImpl.java @@ -0,0 +1,103 @@ +package com.budwk.app.zhgh.activity.family.service.impl; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.activity.family.models.FamilyBlackList; +import com.budwk.app.zhgh.activity.family.service.FamilyBlackListService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Criteria; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +/** + * @author zxy + * @Description TODO + * @createTime 2022年03月07日 14:29:00 + */ +@IocBean(args = {"refer:dao"}) +public class FamilyUserServiceImpl extends BaseServiceImpl implements FamilyBlackListService { + + public FamilyUserServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Pagination pageData(PageForm pageForm, Cnd cnd, String activityId, String courseId) { + Sql sql = Sqls.create(""" + SELECT + u.id AS userId, + u.username, + u.loginname, + u.mobile, + u.unitname, + u.unionname, + tsuc.courseName, + tsuu.state, + ( SELECT count( 1 ) FROM family_user_course WHERE userId = tsuu.userId $var) tourseTotal, + ( SELECT count( 1 ) FROM family_user_course WHERE userId = tsuu.userId AND isAttend = 0 and tsuu.state!=2 AND now()> courseEndTime $var) AS absentCount, + if(tsubl.isDisabled=1,true,false) isDisabled, + group_CONCAT( tsuc.courseName ) AS courseNames + FROM + `family_user` tsuu + LEFT JOIN `vw_user` u ON u.id = tsuu.userId + LEFT JOIN family_activity act on act.id = tsuu.activityId + LEFT JOIN family_course tsuc ON tsuc.id = tsuu.courseId + LEFT JOIN family_black_list tsubl on tsubl.userId = tsuu.userId + $condition + ORDER BY FIELD( tsuu.state, 1, 3, 2, 4 ) + """); + cnd.groupBy("tsuu.userId"); + Criteria varCnd = Cnd.cri(); + varCnd.where().setTop(false); + varCnd.where().andEX("activityId", "=", activityId); + varCnd.where().andEX("courseId", "=", courseId); + if (!varCnd.where().isEmpty()) { + sql.vars().set("var", "and " + varCnd.toSql(null)); + } + sql.setCondition(cnd); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + + @Override + public void doHandleUser(String userId) { + FamilyBlackList blackRecord = dao().fetch(FamilyBlackList.class, Cnd.where("userId", "=", userId)); + if (Lang.isEmpty(blackRecord)) { + FamilyBlackList blackList = new FamilyBlackList(); + blackList.setUserId(userId); + blackList.setIsDisabled(true); + dao().insert(blackList); + } else { +// blackRecord.setIsDisabled(!blackRecord.getIsDisabled()); +// dao().update(blackRecord); + dao().delete(blackRecord); + } + + } + + @Override + public List attendClassRecord(String userId) { + Sql sql = Sqls.create(""" + SELECT + c.courseName, + uc.courseStartTime, + courseEndTime, + uc.isAttend, + uc.attendTime + FROM + `family_user_course` uc + LEFT JOIN family_course c ON c.id = uc.courseId + WHERE + uc.userId = @userId + """); + sql.setParam("userId", userId); + return listMap(sql); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/controller/YearPlanController.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/controller/YearPlanController.java new file mode 100644 index 00000000..eb7602b8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/controller/YearPlanController.java @@ -0,0 +1,142 @@ +package com.budwk.app.zhgh.activity.planSummary.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +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.sys.models.Sys_union; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.basic.models.ActivityBasicSettings; +import com.budwk.app.zhgh.activity.planSummary.model.YearPlan; +import com.budwk.app.zhgh.activity.planSummary.service.YearPlanService; +import com.budwk.app.zhgh.club.model.SysClub; +import com.budwk.app.zhgh.club.service.SysClubService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName YearPlanController + * @Author JyuHsin + * @Date 2025/7/23 16:15 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "年度计划") +@At("/platform/yearPlan/manage") +public class YearPlanController { + + @Inject + private Dao dao; + @Inject + private YearPlanService yearPlanService; + @Inject + private SysClubService sysClubService; + + @At("") + @SaCheckPermission("planSummary.yearPlan.manage") + @Ok("beetl:/platform/zhgh/activity/planSummary/yearPlan/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("planSummary.yearPlan.manage") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "tissueIdByUnion") String tissueIdByUnion, + @Param(value = "tissueIdByClub") String tissueIdByClub, + @Param(value = "planName") String planName) { + Cnd cnd = Cnd.NEW(); + + cnd.andEX("YEAR(yp.planTime)", "=", year); + cnd.andEX("yp.tissueId", "=", tissueIdByUnion); + cnd.andEX("yp.tissueId", "=", tissueIdByClub); + cnd.and(Cnd.likeEX("yp.planName", planName)); + + Pagination pagination = yearPlanService.pageData(pageForm, cnd); + return Result.success(pagination); + } + + @At + @ApiOperation("查询活动类型") + @SaCheckPermission("planSummary.yearPlan.manage") + public Result queryActivityType() { + List list = dao.query(ActivityBasicSettings.class, Cnd.where("parentId", "=", "b3b6bafe6dd74aa8b69691b6b75b50fd").asc("code")); + return Result.success(list); + } + + @At + @ApiOperation("查询单个年度计划") + @SaCheckPermission("planSummary.yearPlan.manage") + public Result fetchOne(String id) { + YearPlan plan = yearPlanService.fetch(id); + ActivityBasicSettings settings = dao.fetch(ActivityBasicSettings.class, Cnd.where("id", "=", plan.getActivityType())); + NutMap nutMap = Lang.obj2nutmap(plan); + nutMap.put("activityTypeName", settings.getName()); + return Result.success(nutMap); + } + + @At + @ApiOperation("新增/修改年度计划") + @SaCheckPermission("planSummary.yearPlan.manage") + @SLog(type = "yearPlan", tag = "新增/修改年度计划", msg = "新增/修改年度计划") + public Object onSubmit(YearPlan yearPlan) { + yearPlanService.insertOrUpdate(yearPlan); + return Result.success(); + } + + @At + @ApiOperation("删除年度计划") + @SaCheckPermission("planSummary.yearPlan.manage") + @SLog(type = "yearPlan", tag = "删除年度计划", msg = "删除年度计划") + public Object onDelete(String id) { + yearPlanService.delete(id); + return Result.success(); + } + + @At + @ApiOperation("获取工会") + @SaCheckPermission("planSummary.yearPlan.manage") + public Result queryUnion() { + Cnd cnd = Cnd.NEW(); + if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name()) && AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) { + cnd.and(Sys_union::getId, "=", SecurityUtil.getUnionId()); + } + cnd.asc(Sys_union::getUnionCode); + List list = dao.query(Sys_union.class, cnd); + return Result.success(list); + } + + @At + @ApiOperation("获取协会") + @SaCheckPermission("planSummary.yearPlan.manage") + public Result queryClub() { + Cnd cnd = Cnd.NEW(); + if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name()) && AuthUtil.hasRole(RoleConstant.CLUB_PRESIDENT.name())) { + List clubList = sysClubService.getMyManageClub(); + List list = clubList.stream().map(SysClub::getId).toList(); + cnd.and(SysClub::getId, "in", list); + } + cnd.asc(SysClub::getClubCode); + List list = dao.query(SysClub.class, cnd); + return Result.success(list); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/controller/YearSummaryController.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/controller/YearSummaryController.java new file mode 100644 index 00000000..3dc22a22 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/controller/YearSummaryController.java @@ -0,0 +1,122 @@ +package com.budwk.app.zhgh.activity.planSummary.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +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.sys.models.Sys_dict; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.basic.models.ActivityBasicSettings; +import com.budwk.app.zhgh.activity.planSummary.model.YearPlan; +import com.budwk.app.zhgh.activity.planSummary.model.YearSummary; +import com.budwk.app.zhgh.activity.planSummary.service.YearPlanService; +import com.budwk.app.zhgh.activity.planSummary.service.YearSummaryService; +import com.budwk.app.zhgh.club.model.SysClub; +import com.budwk.app.zhgh.club.service.SysClubService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName YearSummaryController + * @Author JyuHsin + * @Date 2025/7/23 16:15 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "年度总结") +@At("/platform/yearSummary/manage") +public class YearSummaryController { + + @Inject + private Dao dao; + @Inject + private YearSummaryService yearSummaryService; + @Inject + private SysClubService sysClubService; + + @At("") + @SaCheckPermission("planSummary.yearSummary.manage") + @Ok("beetl:/platform/zhgh/activity/planSummary/yearSummary/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("planSummary.yearSummary.manage") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "tissueIdByUnion") String tissueIdByUnion, + @Param(value = "tissueIdByClub") String tissueIdByClub, + @Param(value = "summaryType") String summaryType, + @Param(value = "summaryFrom") String summaryFrom) { + Cnd cnd = Cnd.NEW(); + + cnd.andEX("YEAR(ys.cTime)", "=", year); + cnd.andEX("ys.tissueId", "=", tissueIdByUnion); + cnd.andEX("ys.tissueId", "=", tissueIdByClub); + cnd.andEX("ys.summaryType", "=", summaryType); + cnd.andEX("ys.summaryFrom", "=", summaryFrom); + + Pagination pagination = yearSummaryService.pageData(pageForm, cnd); + return Result.success(pagination); + } + + @At + @ApiOperation("查询单个年度总结") + @SaCheckPermission("planSummary.yearSummary.manage") + public Result fetchOne(String id) { + YearSummary summary = yearSummaryService.fetch(id); + Sys_dict dict = dao.fetch(Sys_dict.class, Cnd.where("code", "=", summary.getSummaryType())); + NutMap nutMap = Lang.obj2nutmap(summary); + nutMap.put("summaryTypeName", dict.getName()); + return Result.success(nutMap); + } + + @At + @ApiOperation("新增/修改年度总结") + @SaCheckPermission("planSummary.yearSummary.manage") + @SLog(type = "yearSummary", tag = "新增/修改年度总结", msg = "新增/修改年度总结") + public Object onSubmit(YearSummary yearSummary) { + View_user user = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId())); + yearSummary.setUserId(SecurityUtil.getUserId()); + yearSummary.setCTime(DateUtil.now()); + yearSummary.setLoginName(user.getLoginname()); + yearSummary.setUserName(user.getUsername()); + yearSummary.setUnitId(user.getUnitId()); + yearSummary.setUnitName(user.getUnitName()); + yearSummary.setUnionId(user.getUnionId()); + yearSummary.setUnionName(user.getUnionName()); + yearSummaryService.insertOrUpdate(yearSummary); + return Result.success(); + } + + @At + @ApiOperation("删除年度总结") + @SaCheckPermission("planSummary.yearSummary.manage") + @SLog(type = "yearSummary", tag = "删除年度总结", msg = "删除年度总结") + public Object onDelete(String id) { + yearSummaryService.delete(id); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/model/YearPlan.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/model/YearPlan.java new file mode 100644 index 00000000..3dc145a3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/model/YearPlan.java @@ -0,0 +1,69 @@ +package com.budwk.app.zhgh.activity.planSummary.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName Plan + * @Author JyuHsin + * @Date 2025/7/23 13:53 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("年度计划") +@Accessors(chain = true) +@Table("year_plan") +@EqualsAndHashCode(callSuper = true) +public class YearPlan extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("计划名称") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String planName; + + @Column + @Comment("计划时间") + @ColDefine(type = ColType.VARCHAR, width = 200) + private String planTime; + + @Column + @Comment("计划内容") + @ColDefine(type = ColType.TEXT) + private String content; + + @Column + @Comment("预算费用") + @ColDefine(type = ColType.FLOAT) + private Double money; + + @Column + @Comment("计划类型(40001-校活动、40002-分工会活动、40003-协会社团活动)") + @ColDefine(type = ColType.VARCHAR, width = 7) + private String planType; + + @Column + @Comment("分工会ID或社团ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String tissueId; + + @Column + @Comment("分工会或社团") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String tissueName; + + @Column + @Comment("活动类型") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String activityType; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/model/YearSummary.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/model/YearSummary.java new file mode 100644 index 00000000..11b554af --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/model/YearSummary.java @@ -0,0 +1,98 @@ +package com.budwk.app.zhgh.activity.planSummary.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +/** + * @ClassName Summary + * @Author JyuHsin + * @Date 2025/7/23 13:53 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("年度总结") +@Accessors(chain = true) +@Table("year_summary") +@EqualsAndHashCode(callSuper = true) +public class YearSummary extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("提交人") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("提交人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("提交人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("提交人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("提交人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("提交人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("提交人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("提交时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String cTime; + + @Column + @Comment("工会/协会id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String tissueId; + + @Column + @Comment("分工会或社团") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String tissueName; + + @Column + @Comment("总结类型") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String summaryType; + + @Column + @Comment("总结来源(1-校活动、2-分工会活动、3协会社团活动)") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String summaryFrom; + + @Column + @Comment("文件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/YearPlanService.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/YearPlanService.java new file mode 100644 index 00000000..2198591b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/YearPlanService.java @@ -0,0 +1,19 @@ +package com.budwk.app.zhgh.activity.planSummary.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.planSummary.model.YearPlan; +import org.nutz.dao.Cnd; + +/** + * @ClassName YearPlanService + * @Author JyuHsin + * @Date 2025/7/23 16:16 + * @Version 1.0 + * @Description TODO + */ +public interface YearPlanService extends BaseService { + + Pagination pageData(PageForm pageForm, Cnd cnd); +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/YearSummaryService.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/YearSummaryService.java new file mode 100644 index 00000000..3ebf58a2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/YearSummaryService.java @@ -0,0 +1,19 @@ +package com.budwk.app.zhgh.activity.planSummary.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.planSummary.model.YearSummary; +import org.nutz.dao.Cnd; + +/** + * @ClassName YearSummaryService + * @Author JyuHsin + * @Date 2025/7/23 16:17 + * @Version 1.0 + * @Description TODO + */ +public interface YearSummaryService extends BaseService { + + Pagination pageData(PageForm pageForm, Cnd cnd); +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/impl/YearPlanServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/impl/YearPlanServiceImpl.java new file mode 100644 index 00000000..00cbd356 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/impl/YearPlanServiceImpl.java @@ -0,0 +1,73 @@ +package com.budwk.app.zhgh.activity.planSummary.service.impl; + +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.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_user_role; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.planSummary.model.YearPlan; +import com.budwk.app.zhgh.activity.planSummary.service.YearPlanService; +import com.budwk.app.zhgh.club.model.SysClub; +import com.budwk.app.zhgh.club.service.SysClubService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; + +import java.util.List; + +/** + * @ClassName YearPlanServiceImpl + * @Author JyuHsin + * @Date 2025/7/23 16:16 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class YearPlanServiceImpl extends BaseServiceImpl implements YearPlanService { + + @Inject + private SysClubService sysClubService; + + public YearPlanServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Pagination pageData(PageForm pageForm, Cnd cnd) { + Sql sql = Sqls.create(""" + SELECT + yp.*, + ab.name as activityTypeName, + year(yp.planTime) as `year`, + ((SELECT COUNT(1) FROM activity_school acs WHERE acs.planId = yp.id) >0 ) carryOut + FROM + year_plan yp + left join activity_basic_settings ab on ab.id = yp.activityType + $condition + """); + if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + if(AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) { + group.or("yp.tissueId", "=", SecurityUtil.getUnionId()); + } + if(AuthUtil.hasRole(RoleConstant.CLUB_PRESIDENT.name())) { + List clubList = sysClubService.getMyManageClub(); + List list = clubList.stream().map(SysClub::getId).toList(); + group.or("yp.tissueId", "in", list); + } + cnd.and(group); + } + cnd.desc("yp.planTime"); + sql.setCondition(cnd); + return this.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/impl/YearSummaryServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/impl/YearSummaryServiceImpl.java new file mode 100644 index 00000000..8b55e363 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/activity/planSummary/service/impl/YearSummaryServiceImpl.java @@ -0,0 +1,71 @@ +package com.budwk.app.zhgh.activity.planSummary.service.impl; + +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.service.impl.BaseServiceImpl; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.planSummary.model.YearSummary; +import com.budwk.app.zhgh.activity.planSummary.service.YearSummaryService; +import com.budwk.app.zhgh.club.model.SysClub; +import com.budwk.app.zhgh.club.model.SysClubUser; +import com.budwk.app.zhgh.club.service.SysClubService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; + +import java.util.List; + +/** + * @ClassName YearSummaryServiceImpl + * @Author JyuHsin + * @Date 2025/7/23 16:17 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class YearSummaryServiceImpl extends BaseServiceImpl implements YearSummaryService { + + @Inject + private SysClubService sysClubService; + + public YearSummaryServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Pagination pageData(PageForm pageForm, Cnd cnd) { + Sql sql = Sqls.create(""" + SELECT + ys.*, + d.name as summaryTypeName, + year(ys.cTime) as `year` + FROM + year_summary ys + left join sys_dict d on d.code = ys.summaryType + $condition + """); + if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + if(AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) { + group.or("ys.tissueId", "=", SecurityUtil.getUnionId()); + } + if(AuthUtil.hasRole(RoleConstant.CLUB_PRESIDENT.name())) { + List clubList = sysClubService.getMyManageClub(); + List list = clubList.stream().map(SysClub::getId).toList(); + group.or("ys.tissueId", "in", list); + } + cnd.and(group); + } + cnd.desc("ys.cTime"); + sql.setCondition(cnd); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/constant/ColumnFormTypeEnum.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/constant/ColumnFormTypeEnum.java index 7e733282..52d6c98e 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/constant/ColumnFormTypeEnum.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/constant/ColumnFormTypeEnum.java @@ -15,9 +15,9 @@ import lombok.Getter; public enum ColumnFormTypeEnum { INPUT("INPUT", "输入框"), - SELECT("SELECT", "选择框"),//选项数组, + SELECT("SELECT", "选择框"), //RADIO("RADIO", "单选框"),//选项数组 - FILE("FILE", "文件");//上传个数,格式 + FILE("FILE", "文件"); private String code; private String description; diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityAddController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityAddController.java index d48c08e8..263ee355 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityAddController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityAddController.java @@ -2,10 +2,13 @@ package com.budwk.app.zhgh.activity.trainSignUp.controller.manage; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.result.Result; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUser; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; @@ -29,27 +32,21 @@ import java.util.List; */ @Slf4j @IocBean +@Api(tags = "新建品牌活动") @At("/platform/trainSingUp/manage/activity") public class TrainSignUpActivityAddController { - @Inject - private TrainSignUpActivityService trainSignUpActivityManageService; - @Inject private Dao dao; - - @At("/add") - @SaCheckPermission("trainSingUp.manage.activity.add") - @Ok("beetl:/platform/zhgh/activity/trainSingUp/add/index.html") - public void add() { - } + @Inject + private TrainSignUpActivityService trainSignUpActivityManageService; @At @Ok("json:full") - @POST - @SaCheckPermission("trainSingUp.manage.activity.add") - public Result doHandle(@Param(value = "data") String data) { - TrainSignUpActivity activity = Json.fromJson(TrainSignUpActivity.class, data); + @ApiOperation("品牌活动新增/修改") + @SaCheckPermission("trainSingUp.manage.activity") + @SLog(type = "trainSignUp", tag = "新增/修改活动", msg = "新增/修改活动") + public Result doHandle(TrainSignUpActivity activity) { if (StrUtil.isBlank(activity.getId())) { trainSignUpActivityManageService.add(activity, null); } else { @@ -60,7 +57,8 @@ public class TrainSignUpActivityAddController { @At @Ok("json:full") - @SaCheckPermission("trainSingUp.manage.activity.add") + @ApiOperation("获取分工会人数限制") + @SaCheckPermission("trainSingUp.manage.activity") public Result getUnionLimit(@Param(value = "activityScopeId") String activityScopeId) { Sql sql = Sqls.create(""" SELECT @@ -83,18 +81,18 @@ public class TrainSignUpActivityAddController { @At @Ok("json:full") - @SaCheckPermission("trainSingUp.manage.activity.add") + @ApiOperation("获取报名人员数量") + @SaCheckPermission("trainSingUp.manage.activity") public Result getRegisterUserCount(@Param(value = "courseId") String courseId) { - //已报人数 return Result.success().addData(dao.count(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId))); } @At @Ok("json:full") - @SaCheckPermission("trainSingUp.manage.activity.add") + @ApiOperation("获取历史活动列表") + @SaCheckPermission("trainSingUp.manage.activity") public Result getHistoricalActList() { List query = dao.query(TrainSignUpActivity.class, Cnd.NEW().desc("activityStartTime")); return Result.success().addData(query); } - } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityApplyController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityApplyController.java index 28bcbddb..f17aff7f 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityApplyController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityApplyController.java @@ -1,6 +1,7 @@ package com.budwk.app.zhgh.activity.trainSignUp.controller.manage; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; @@ -8,11 +9,13 @@ import com.budwk.app.sys.models.Sys_dict; import com.budwk.app.sys.services.SysDictService; import com.budwk.app.web.commons.auth.utils.AuthUtil; import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivityCourse; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpType; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUser; +import com.budwk.app.zhgh.activity.family.models.FamilyCourse; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsService; +import com.budwk.app.zhgh.activity.trainSignUp.models.*; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; +import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; import org.nutz.dao.Sqls; @@ -20,12 +23,14 @@ import org.nutz.dao.sql.Sql; import org.nutz.dao.util.cri.Static; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -34,112 +39,139 @@ import java.util.stream.Collectors; @Slf4j @IocBean @Ok("json:full") +@Api(tags = "活动报名") @At("/platform/trainSingUp/manage/apply") public class TrainSignUpActivityApplyController { - @Inject - private TrainSignUpActivityService trainSignUpActivityService; + @Inject + private TrainSignUpActivityService trainSignUpActivityService; + @Inject + private SysDictService dictService; + @Inject + private TrainSignUpActivityStatisticsService statisticsService; - @Inject - private SysDictService dictService; + @At("") + @SaCheckPermission("trainSingUp.manage.apply") + @Ok("beetl:/platform/zhgh/activity/trainSingUp/apply/index.html") + public void index() { + } - @At("") - @SaCheckPermission("trainSingUp.manage.apply") - @Ok("beetl:/platform/zhgh/activity/trainSingUp/apply/index.html") - public void index() { - } + @At + @ApiOperation("活动查询") + @SaCheckPermission("trainSingUp.manage.apply") + public Result activityData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "activityType") Integer activityType) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("`year`", "=", year); + //查询报名中 + if (activityType == 2) { + cnd.and(new Static("now() > activitySignUpStartTime and now() < activitySignUpEndTime")); + }//查询已结束的 + else if (activityType == 3) { + cnd.and(new Static("now() > activityEndTime")); + } + if (AuthUtil.hasRole("H04") && !AuthUtil.hasRoleOr("sysadmin, A06")) { + cnd.and("activityMode", "=", 2).and("createdBy", "=", SecurityUtil.getUserId()); + } - @At - @SaCheckPermission("trainSingUp.manage.apply") - public Result activityData(@Param(value = "year") Integer year, - @Param(value = "activityType") Integer activityType) { - Cnd cnd = Cnd.NEW(); - cnd.andEX("`year`", "=", year); - //查询报名中 - if (activityType == 2) { - cnd.and(new Static("now() > activitySignUpStartTime and now() < activitySignUpEndTime")); - }//查询已结束的 - else if (activityType == 3) { - cnd.and(new Static("now() > activityEndTime")); - } + Pagination pagination = trainSignUpActivityService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + List trainSignUpActivities = pagination.getList(); + Map trainSignUpTypeMap = dictService.getSubListByCode("TRAIN_SIGNUP_TYPE").stream().collect(Collectors.toMap(Sys_dict::getCode, Sys_dict::getName)); + trainSignUpActivities.forEach(v -> v.setTrainType(trainSignUpTypeMap.get(v.getTrainType()))); + return Result.success(pagination); + } - if(AuthUtil.hasRole("H04") && !AuthUtil.hasRoleOr("sysadmin, A06")) { - cnd.and("activityMode", "=", 2).and("createdBy", "=", SecurityUtil.getUserId()); - } + @At + @ApiOperation("分活动查询") + @SaCheckPermission("trainSingUp.manage.apply") + public Result pageData(PageForm pageForm, + @Param(value = "courseTypeId") String courseTypeId, + @Param(value = "activityId") String activityId, + @Param(value = "assortTypes") String[] assortTypes) { + Sql sql = Sqls.create(""" + SELECT + tsuc.id, + tsuc.activityId, + tsuc.courseName, + tsuc.coursePeopleNumber, + tsuc.courseLocation, + tsuc.courseType, + tsuc.courseLocationCoordinates, + tsuc.courseReservedNumber, + tsuc.courseInstructor, + tsuc.campus, + tsuc.unionLimit, + tsuc.isMobileSign, + tsuc.signType, + tsuc.isReceiveGift, + tsuc.giftType, + tsuc.reserveMode, + tsuc.waitingNum, + tsuc.assort, + type.typeName, + tsuc.courseIsLimitApply + FROM + `train_sign_up_course` tsuc + LEFT JOIN train_sign_up_type type ON type.id = tsuc.courseType + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("type.id", "=", courseTypeId); + cnd.and("tsuc.activityId", "=", activityId); + if(Lang.isNotEmpty(assortTypes)) { + cnd.and("tsuc.assort", "in", assortTypes); + } - List trainSignUpActivities = trainSignUpActivityService.query(cnd); - Map trainSignUpTypeMap = dictService.getSubListByCode("TRAIN_SIGNUP_TYPE").stream().collect(Collectors.toMap(Sys_dict::getCode, Sys_dict::getName)); - trainSignUpActivities.forEach(v->v.setTrainType(trainSignUpTypeMap.get(v.getTrainType()))); - return Result.success(trainSignUpActivities); - } + List courseArray = trainSignUpActivityService.dao().query(TrainSignUpCourse.class, Cnd.where("activityId", "=", activityId)); + courseArray = trainSignUpActivityService.filterCourseByHostUnion(courseArray); + cnd.and("tsuc.id", "in", courseArray.stream().map(TrainSignUpCourse::getId).toList()); + cnd.asc("tsuc.orderNum"); + cnd.asc("type.code"); + sql.setCondition(cnd); - @At - @SaCheckPermission("trainSingUp.manage.apply") - public Result pageData(PageForm pageForm, - @Param(value = "courseTypeId") String courseTypeId, - @Param(value = "activityId") String activityId) { - Sql sql = Sqls.create(""" - SELECT - tsuc.id, - tsuc.activityId, - tsuc.courseName, - tsuc.coursePeopleNumber, - tsuc.courseLocation, - tsuc.courseType, - tsuc.courseLocationCoordinates, - tsuc.courseReservedNumber, - tsuc.courseInstructor, - tsuc.campus, - tsuc.unionLimit, - tsuc.isMobileSign, - tsuc.signType, - tsuc.isReceiveGift, - tsuc.giftType, - tsuc.reserveMode, - type.lxname - FROM - `train_sign_up_course` tsuc - LEFT JOIN train_sign_up_type type ON type.id = tsuc.courseType - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.andEX("type.id","=",courseTypeId); - cnd.and("tsuc.activityId","=",activityId); - cnd.asc("type.code"); - sql.setCondition(cnd); + Pagination pagination = trainSignUpActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List courseList = pagination.getList(); - Pagination pagination = trainSignUpActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - List courseList = pagination.getList(); + courseList.forEach(c -> { + c.put("hasRegisterNum", statisticsService.queryCourseCount(c.getString("id"), c.getString("courseType"))); + c.put("hasWaitingNum", statisticsService.queryCourseWaitCount(c.getString("id"), c.getString("courseType"))); + //当前用户是否报过 + c.put("isSign", trainSignUpActivityService.isSignCourseByUser(c.getString("id"), SecurityUtil.getUserId())); - courseList.forEach(c -> { - TrainSignUpType type = trainSignUpActivityService.dao().fetch(TrainSignUpType.class, c.getString("courseType")); -// trainSignUpActivityService.dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime")); - //已报人数 - AtomicInteger hasRegisterNum = new AtomicInteger(); - List signUpUsers = trainSignUpActivityService.dao().query(TrainSignUpUser.class, Cnd.where("courseId", "=", c.getString("id"))); - signUpUsers.forEach(item -> { - hasRegisterNum.getAndIncrement(); - if(type.getIsBringFamily() && type.getIsAddFamily()) { - List mapList = item.getMobileColumnsValue(); - if(Lang.isNotEmpty(mapList)) { - mapList.stream().filter(o -> "xdqsrs".equals(o.getString("columnCode"))).findAny().ifPresent(nutMap -> hasRegisterNum.addAndGet(nutMap.getInt("columnValue"))); - } - } - }); - c.put("hasRegisterNum",hasRegisterNum.get()); - //当前用户是否报过 - c.put("isSign",trainSignUpActivityService.isSignCourseByUser(c.getString("id"), SecurityUtil.getUserId())); - }); - return Result.success(pagination); - } + if(StrUtil.isNotBlank(c.getString("unionLimit"))) { + List unionLimit = Json.fromJsonAsList(NutMap.class, c.getString("unionLimit")); + if(Lang.isNotEmpty(unionLimit)) { + NutMap nutMap = unionLimit.stream().filter(o -> o.getString("id").equals(SecurityUtil.getUnionId())).findFirst().orElse(null); + if(nutMap != null) { + c.put("coursePeopleNumber", nutMap.getInt("limitCount")); + } + } + } + }); + return Result.success(pagination); + } - @At - @SaCheckPermission("trainSingUp.manage.apply") - public Result getCourseTime(String id){ - List list = trainSignUpActivityService.dao().query(TrainSignUpActivityCourse.class, Cnd.where("courseId", "=", id)); - return Result.success(list); - } + @At + @ApiOperation("获取分活动时间") + @SaCheckPermission("trainSingUp.manage.apply") + public Result getCourseTime(String id) { + List list = trainSignUpActivityService.dao().query(TrainSignUpActivityCourse.class, Cnd.where("courseId", "=", id)); + return Result.success(list); + } + + @At + @ApiOperation("查询分类标识集合") + @SaCheckPermission("trainSingUp.manage.apply") + public Result queryCourseAssort(String activityId) { + List courseList = trainSignUpActivityService.dao().query(TrainSignUpCourse.class, Cnd.where(TrainSignUpCourse::getActivityId, "=", activityId).asc(TrainSignUpCourse::getOrderNum)); + if(Lang.isEmpty(courseList)) { + return Result.success(new ArrayList<>()); + } + List assortList = courseList.stream().map(TrainSignUpCourse::getAssort).filter(StrUtil::isNotBlank).toList(); + return Result.success(assortList); + } } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityController.java index 7530129e..d2ebfcb4 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpActivityController.java @@ -3,11 +3,14 @@ package com.budwk.app.zhgh.activity.trainSignUp.controller.manage; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.zhgh.activity.trainSignUp.models.*; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; @@ -27,7 +30,6 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; - /** * @author zxy * @Description 培训报名 活动管理 @@ -36,12 +38,12 @@ import java.util.stream.Collectors; @Slf4j @IocBean @Ok("json:full") +@Api(tags = "活动管理") @At("/platform/trainSingUp/manage/activity") public class TrainSignUpActivityController { @Inject private TrainSignUpActivityService trainSignUpActivityManageService; - @Inject private Dao dao; @@ -52,6 +54,7 @@ public class TrainSignUpActivityController { } @At + @ApiOperation("分页查询") @SaCheckPermission("trainSingUp.manage.activity") public Result pageData(PageForm pageForm, @Param(value = "year") Integer year, @@ -64,8 +67,10 @@ public class TrainSignUpActivityController { } @At + @ApiOperation("活动删除") @SaCheckPermission("trainSingUp.manage.activity") - public Result doDelete(String id) { + @SLog(type = "trainSignUp", tag = "删除活动", msg = "删除活动") + public Result onDelete(String id) { Trans.exec(() -> { trainSignUpActivityManageService.delete(id); dao.clear(TrainSignUpCourse.class, Cnd.where("activityId", "=", id)); @@ -80,18 +85,7 @@ public class TrainSignUpActivityController { } @At - @SaCheckPermission("trainSingUp.manage.activity") - public Result doHandle(@Param("data") String data) { - TrainSignUpActivity activity = Json.fromJson(TrainSignUpActivity.class, data); - if (StrUtil.isBlank(activity.getId())) { - trainSignUpActivityManageService.add(activity, null); - } else { - trainSignUpActivityManageService.edit(activity); - } - return Result.success(); - } - - @At + @ApiOperation("活动状态变更") @SaCheckPermission("trainSingUp.manage.activity") public Result activityStatusChange(TrainSignUpActivity activity) { trainSignUpActivityManageService.updateActivityStatus(activity); @@ -102,6 +96,7 @@ public class TrainSignUpActivityController { } @At + @ApiOperation("查询单个活动") @SaCheckPermission("trainSingUp.manage.activity") public Result findOne(@Param("id") @NotNull String id) { NutMap dataMap = trainSignUpActivityManageService.findOne(id, null, ""); @@ -125,7 +120,7 @@ public class TrainSignUpActivityController { //查询所有的课程类型 List trainSignUpTypeList = dao.query(TrainSignUpType.class, Cnd.NEW()); - Map typeMap = trainSignUpTypeList.stream().collect(Collectors.toMap(TrainSignUpType::getId, TrainSignUpType::getLxname)); + Map typeMap = trainSignUpTypeList.stream().collect(Collectors.toMap(TrainSignUpType::getId, TrainSignUpType::getTypeName)); courseList.forEach(v -> { diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpTypeController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpTypeController.java index 6692d3e8..cbd735bf 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpTypeController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpTypeController.java @@ -1,7 +1,9 @@ package com.budwk.app.zhgh.activity.trainSignUp.controller.manage; +import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.EnumUtil; +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; @@ -9,6 +11,8 @@ import com.budwk.app.base.service.BaseService; import com.budwk.app.base.utils.PageUtil; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainMobileSignColumn; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpType; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Chain; @@ -37,12 +41,12 @@ import java.util.List; @Slf4j @IocBean @Ok("json:full") +@Api(tags = "活动类型管理") @At("/platform/trainSingUp/manage/type") public class TrainSignUpTypeController { @Inject private Dao dao; - @Inject private BaseService baseService; @@ -53,15 +57,16 @@ public class TrainSignUpTypeController { } @At + @ApiOperation("分页查询") @SaCheckPermission("trainSingUp.manage.type") public Result pageData(PageForm pageForm, - @Param(value = "lxname") String lxname) { + @Param(value = "typeName") String typeName) { Cnd cnd = Cnd.NEW(); Sql sql = Sqls.create(""" select * from train_sign_up_type $condition """); - if (Strings.isNotBlank(lxname)) { - cnd.and("lxname", "like", "%" + lxname + "%"); + if (Strings.isNotBlank(typeName)) { + cnd.and("typeName", "like", "%" + typeName + "%"); } if(Strings.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())){ cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); @@ -71,7 +76,7 @@ public class TrainSignUpTypeController { sql.setCondition(cnd); Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); List list = pagination.getList(); - list.stream().forEach(item -> { + list.forEach(item -> { Cnd c = Cnd.NEW(); c.and("typeId", "=", item.getString("id")); c.asc("columnIndex"); @@ -83,7 +88,9 @@ public class TrainSignUpTypeController { } @At + @ApiOperation("活动类型新增") @SaCheckPermission("trainSingUp.manage.type") + @SLog(type = "trainSignUp", tag = "活动类型新增", msg = "活动类型新增") public Result doAdd(@Param("data") String data) throws Exception { TrainSignUpType type = Json.fromJson(TrainSignUpType.class, data); int count = dao.count(TrainSignUpType.class, Cnd.where("code", "=", type.getCode())); @@ -97,7 +104,9 @@ public class TrainSignUpTypeController { } @At + @ApiOperation("活动类型修改") @SaCheckPermission("trainSingUp.manage.type") + @SLog(type = "trainSignUp", tag = "活动类型修改", msg = "活动类型修改") public Result doEdit(TrainSignUpType type) { int count = dao.count(TrainSignUpType.class, Cnd.where("code", "=", type.getCode()).and("id", "!=", type.getId())); if (count > 0) { @@ -110,7 +119,9 @@ public class TrainSignUpTypeController { } @At + @ApiOperation("活动类型删除") @SaCheckPermission("trainSingUp.manage.type") + @SLog(type = "trainSignUp", tag = "活动类型删除", msg = "活动类型删除") public Object doDelete(@Param(value = "id") String id) { dao.clear(TrainSignUpType.class, Cnd.where("id", "=", id)); dao.clear(TrainMobileSignColumn.class, Cnd.where("typeId", "=", id)); @@ -119,6 +130,7 @@ public class TrainSignUpTypeController { @At @Aop(TransAop.READ_COMMITTED) + @ApiOperation("排序号变更") @SaCheckPermission("trainSingUp.manage.type") public Object xhChange(String id, Integer xh, boolean toDown) { if (toDown) { @@ -136,6 +148,8 @@ public class TrainSignUpTypeController { } @At + @ApiOperation("获取所有类型") + @SaCheckLogin public Result getAllType(@Param(value = "id") String id) { List trainSignUpTypeList = dao.query(TrainSignUpType.class, Cnd.NEW().andEX("id", "=", id).asc("xh")); dao.fetchLinks(trainSignUpTypeList, "trainMobileSignColumnList", Cnd.NEW().asc("columnIndex")); @@ -143,6 +157,7 @@ public class TrainSignUpTypeController { } @At + @ApiOperation("自定义表单字段类型") @SaCheckPermission("trainSingUp.manage.type") public Result getColumnType() { List names = EnumUtil.getNames(ColType.class); diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserAdjustController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserAdjustController.java index 7942c822..0e562e2a 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserAdjustController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserAdjustController.java @@ -2,16 +2,18 @@ package com.budwk.app.zhgh.activity.trainSignUp.controller.manage; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; import com.budwk.app.base.service.BaseService; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivityCourse; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUser; -import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUserCourse; +import com.budwk.app.zhgh.activity.family.models.FamilyType; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; +import com.budwk.app.zhgh.activity.trainSignUp.models.*; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; @@ -19,6 +21,7 @@ import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; @@ -26,29 +29,28 @@ import org.nutz.mvc.annotation.Param; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; /** * @Author JyuHsin * @Date 2022/9/21 * @Description 人员调整 */ -@IocBean -@At("/platform/trainSingUp/manage/userAdjust") @Slf4j +@IocBean @Ok("json:full") +@Api(tags = "品牌活动人员调整") +@At("/platform/trainSingUp/manage/userAdjust") public class TrainSignUpUserAdjustController { - @Inject - private TrainSignUpActivityService trainSignUpActivityManageService; - - @Inject - private TrainSignUpActivityStatisticsService trainSignUpActivityStatisticsService; - @Inject private Dao dao; - @Inject private BaseService baseService; + @Inject + private TrainSignUpActivityService trainSignUpActivityManageService; + @Inject + private TrainSignUpActivityStatisticsService trainSignUpActivityStatisticsService; @At("") @SaCheckPermission("trainSingUp.manage.activity.adjust") @@ -58,11 +60,11 @@ public class TrainSignUpUserAdjustController { /** * 活动list - * * @param year 年度 * @return */ @At + @ApiOperation("活动列表") @SaCheckPermission("trainSingUp.manage.activity.adjust") public Result activityList(@Param(value = "year") Integer year) { List activityList = dao.query(TrainSignUpActivity.class, Cnd.NEW().andEX("year", "=", year).andEX("isDisabled", "=", false).desc("activityStartTime")); @@ -70,6 +72,7 @@ public class TrainSignUpUserAdjustController { } @At + @ApiOperation("分页查询") @SaCheckPermission("trainSingUp.manage.activity.adjust") public Result pageData(PageForm pageForm, @Param(value = "activityId") String activityId) { @@ -78,6 +81,7 @@ public class TrainSignUpUserAdjustController { } @At + @ApiOperation("子活动查询") @SaCheckPermission("trainSingUp.manage.activity.adjust") public Result getCourse(String activityId) { Sql sql = Sqls.create(""" @@ -89,7 +93,8 @@ public class TrainSignUpUserAdjustController { tsuc.courseLocation, tsuc.courseInstructor, tsuc.courseReservedNumber, - ( SELECT count( 1 ) FROM train_sign_up_user WHERE courseId = tsuc.id ) registerNum + tsuc.waitingNum, + tsuc.reserveMode FROM `train_sign_up_course` tsuc WHERE @@ -97,16 +102,16 @@ public class TrainSignUpUserAdjustController { ORDER BY courseName asc """); sql.setParam("activityId", activityId); - return Result.success(baseService.listMap(sql)); + List courseList = baseService.listMap(sql); + courseList.forEach(c -> { + c.put("registerNum", trainSignUpActivityStatisticsService.queryCourseCount(c.getString("id"), c.getString("courseType"))); + c.put("hasWaitingNum", trainSignUpActivityStatisticsService.queryCourseWaitCount(c.getString("id"), c.getString("courseType"))); + }); + return Result.success(courseList); } - /** - * 培训班报名人员list - * - * @param courseId - * @return - */ @At + @ApiOperation("报名用户列表") @SaCheckPermission("trainSingUp.manage.activity.adjust") public Result registerUserList(@Param("courseId") String courseId, @Param(value = "unionId") String unionId, @@ -118,7 +123,9 @@ public class TrainSignUpUserAdjustController { } @At + @ApiOperation("人员调整") @SaCheckPermission("trainSingUp.manage.activity.adjust") + @SLog(type = "trainSingUp", tag = "人员调整", msg = "人员调整") public Result adjust(String activityId, String oldCourseId, String newCourseId, String userId) { Cnd oldCnd = Cnd.where("activityId", "=", activityId) @@ -151,12 +158,13 @@ public class TrainSignUpUserAdjustController { trainSignUpUserCourseList.add(course); }); dao.insert(trainSignUpUserCourseList); - return Result.success(); } @At + @ApiOperation("删除报名人员") @SaCheckPermission("trainSingUp.manage.activity.adjust") + @SLog(type = "trainSingUp", tag = "删除报名人员", msg = "删除报名人员") public Result deleteSignUser(String activityId, String courseId, String userId) { //删除 diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserBlackListManageController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserBlackListManageController.java index dead7306..8f25a812 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserBlackListManageController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/manage/TrainSignUpUserBlackListManageController.java @@ -5,6 +5,7 @@ import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; import cn.afterturn.easypoi.excel.export.ExcelExportService; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; @@ -13,6 +14,8 @@ import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpCourse; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUser; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpBlackListService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Workbook; import org.nutz.dao.Chain; @@ -41,12 +44,12 @@ import java.util.stream.Collectors; */ @IocBean @Ok("json:full") +@Api(tags = "亲子活动人员黑名单") @At("/platform/trainSingUp/userManage") public class TrainSignUpUserBlackListManageController { @Inject private Dao dao; - @Inject private TrainSignUpBlackListService trainSignUpBlackListService; @@ -57,6 +60,7 @@ public class TrainSignUpUserBlackListManageController { } @At + @ApiOperation("分页查询") @SaCheckPermission("trainSingUp.user.activity") public Result pageData(PageForm pageForm, @Param(value = "activityId") String activityId, @@ -80,13 +84,16 @@ public class TrainSignUpUserBlackListManageController { } @At + @ApiOperation("报名人员处理") @SaCheckPermission("trainSingUp.user.activity") + @SLog(type = "trainSingUp", tag = "报名人员处理", msg = "报名人员处理") public Result doHandleUser(@Param("userId") String userId) { trainSignUpBlackListService.doHandleUser(userId); return Result.success(); } @At + @ApiOperation("根据活动Id获取子活动") @SaCheckPermission("trainSingUp.user.activity") public Result getCourseByActivityId(@Param("activityId") String activityId) { List list = dao.query(TrainSignUpCourse.class, Cnd.where("activityId", "=", activityId)); @@ -94,6 +101,7 @@ public class TrainSignUpUserBlackListManageController { } @At + @ApiOperation("获取子活动具体时间") @SaCheckPermission("trainSingUp.user.activity") public Result attendClassRecord(String userId) { trainSignUpBlackListService.attendClassRecord(userId); @@ -101,6 +109,7 @@ public class TrainSignUpUserBlackListManageController { } @At + @ApiOperation("获取候补人员") @SaCheckPermission("trainSingUp.user.activity") public Result getReserveUser(String courseId) { Sql sql = Sqls.create(""" @@ -121,7 +130,9 @@ public class TrainSignUpUserBlackListManageController { } @At + @ApiOperation("补充人员") @SaCheckPermission("trainSingUp.user.activity") + @SLog(type = "trainSingUp", tag = "补充人员", msg = "补充人员") public Result reserveSingUp(String[] ids, String courseId) { //先查询这个课程有多少个未签到的人员 Sql sql = Sqls.create(""" @@ -151,6 +162,7 @@ public class TrainSignUpUserBlackListManageController { @At @Ok("void") + @ApiOperation("导出签到人员") public void exportSignPerson(@Param(value = "activityId") String activityId, HttpServletResponse response) { TrainSignUpActivity activity = dao.fetch(TrainSignUpActivity.class, activityId); @@ -242,6 +254,7 @@ public class TrainSignUpUserBlackListManageController { @At @Ok("void") + @ApiOperation("导出领取人员") public void exportGiftPerson(@Param(value = "activityId") String activityId, HttpServletResponse response) { TrainSignUpActivity activity = dao.fetch(TrainSignUpActivity.class, activityId); diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/mobile/MTrainSignUpActivityController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/mobile/MTrainSignUpActivityController.java index 30e0868e..460611e9 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/mobile/MTrainSignUpActivityController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/mobile/MTrainSignUpActivityController.java @@ -3,23 +3,34 @@ package com.budwk.app.zhgh.activity.trainSignUp.controller.mobile; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_user; import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; +import com.budwk.app.zhgh.activity.family.models.FamilyActivity; +import com.budwk.app.zhgh.activity.family.models.FamilyCourse; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; import com.budwk.app.zhgh.activity.trainSignUp.models.*; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; +import org.nutz.dao.util.cri.Static; import org.nutz.integration.jedis.RedisService; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.*; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; @@ -30,6 +41,7 @@ import java.util.stream.Collectors; */ @IocBean @Ok("json:full") +@Api(tags = "亲子活动移动端") @At("/platform/mobile/trainSignUpActivity") public class MTrainSignUpActivityController { @@ -61,6 +73,7 @@ public class MTrainSignUpActivityController { } @At + @ApiOperation("分页查询") @SaCheckPermission("h5.trainSignUp.sign") public Result pageData(PageForm pageForm, @Param(value = "activityStatus") int activityStatus, @@ -76,6 +89,7 @@ public class MTrainSignUpActivityController { * @return */ @At + @ApiOperation("查询单个活动") @SaCheckPermission("h5.trainSignUp.sign") public Result findOne(@Param("id") String id, @Param(value = "tabIndex") Integer tabIndex, @@ -86,10 +100,46 @@ public class MTrainSignUpActivityController { List mySignCourseIdList = mySignCourseList.stream().map(TrainSignUpUser::getCourseId).collect(Collectors.toList()); cnd.and("id", "in", mySignCourseIdList); } - return Result.success(trainSignUpActivityService.findOne(id, cnd, fromMode)); + NutMap nutMap = trainSignUpActivityService.findOne(id, cnd, fromMode); + List courseList = nutMap.getAsList("courseList", TrainSignUpCourse.class); + courseList.forEach(v -> { + if (v.getCourseIsLimitApply() != null && v.getCourseIsLimitApply() && v.getIsSign()) { + TrainSignUpActivityCourse course = dao.fetch(TrainSignUpActivityCourse.class, Cnd.where("courseId", "=", v.getId())); + v.setCourseTimeName(DateUtil.format(course.getCourseStartTime(), "HH:mm") + "至" + DateUtil.format(course.getCourseEndTime(), "HH:mm") + "段"); + } + }); + return Result.success(nutMap); } @At + @ApiOperation("查询子活动时间段") + @SaCheckPermission("h5.trainSignUp.sign") + public Object getCourseTimeSelectList(String courseId) { + // 查课程的时间段 + List courseList = dao.query(TrainSignUpActivityCourse.class, Cnd.where("courseId", "=", courseId)); + + // 查课程的报名人数 + List applyUserList = dao.query(TrainSignUpUserCourse.class, Cnd.where("courseId", "=", courseId)); + // 按照课程下面时间段去分组 + Map> collectMap = applyUserList.stream().collect(Collectors.groupingBy(TrainSignUpUserCourse::getActivityCourseId)); + List list = courseList.stream().map(v -> { + String id = v.getId(); + NutMap nutMap = NutMap.NEW(); + List trainSignUpUserCourses = collectMap.get(id); + int remainingNum = v.getCourseLimitNum(); + if (Lang.isNotEmpty(trainSignUpUserCourses)) { + remainingNum = v.getCourseLimitNum() - trainSignUpUserCourses.size(); + } + nutMap.put("remainingNum", remainingNum); + nutMap.put("text", DateUtil.format(v.getCourseStartTime(), "HH:mm") + "至" + DateUtil.format(v.getCourseEndTime(), "HH:mm") + "段(剩" + remainingNum + ")"); + nutMap.put("value", id); + return nutMap; + }).filter(v-> v.getInt("remainingNum") != 0).toList(); + return Result.success(list); + } + + @At + @ApiOperation("活动报名") @SaCheckPermission("h5.trainSignUp.sign") public Result doSignUp(TrainSignUpUser trainSignUpUser) { try { @@ -109,13 +159,13 @@ public class MTrainSignUpActivityController { number = map != null ? map.getInt("columnValue") : 0; } } - boolean signFull = trainSignUpActivityService.isSignFull(trainSignUpUser.getCourseId(), number); + boolean signFull = trainSignUpActivityService.isSignFull(course, number); if(signFull) { return Result.error("当前报名人数已满"); } - boolean signFullByUnionId = trainSignUpActivityService.isSignFullByUnionId(trainSignUpUser.getCourseId(), number); + boolean signFullByUnionId = trainSignUpActivityService.isSignFullByUnionId(course, number); if(signFullByUnionId) { - return Result.error("该活动您所在的分工会名额已报满"); + return Result.error("该活动您所在的分工会名额不足"); } trainSignUpActivityService.doSignUp(trainSignUpUser); return Result.success("报名成功"); @@ -128,19 +178,36 @@ public class MTrainSignUpActivityController { } @At + @ApiOperation("取消报名") @SaCheckPermission("h5.trainSignUp.sign") public Result cancelSignUp(@Param("activityId") String activityId, @Param("courseId") String courseId) { String userId = SecurityUtil.getUserId(); - //如果是正常报名取消了,将候补报名的按时间倒叙第一个改为正常报名 + //取消分两种情况 + //第一种没有设置分工会人数限制,那么将候补的人按时间倒叙往上补 + //第二种如果设置了分工会人数限制,那么只将本分工会的候补人员按照时间倒叙往上补,如果本分工会没有候补人员,则名额空出来,由校工会手动调整 + TrainSignUpActivity activity = dao.fetch(TrainSignUpActivity.class, activityId); TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId); TrainSignUpType type = dao.fetch(TrainSignUpType.class, course.getCourseType()); - if(!type.getIsBringFamily() && course.getReserveMode() == 2) { - List signUpUsers = dao.query(TrainSignUpUser.class, Cnd.where("activityId", "=", activityId).and("courseId", "=", courseId) - .and("state", "=", 2).desc("signUpTime")); - if(!signUpUsers.isEmpty()) { + //如果是正常报名取消了,将候补报名的按时间倒叙第一个改为正常报名 + Cnd cnd = Cnd.where("activityId", "=", activityId).and("courseId", "=", courseId) + .and("state", "=", 2); + //如果设置了分工会报名人数限制,则只查本分工会 + if (Lang.isNotEmpty(course.getUnionLimit())) { + cnd.and(new Static(" userId in (select id from user where unionid = '%s')".formatted(SecurityUtil.getUnionId()))); + } + cnd.asc("signUpTime"); + if (!type.getIsBringFamily() && course.getReserveMode() == 2) { + List signUpUsers = dao.query(TrainSignUpUser.class, cnd); + int thisSignUpUserCount = dao.count(TrainSignUpUser.class, + Cnd.where("activityId", "=", activityId) + .and("courseId", "=", courseId).and("userId", "=", userId) + .and("state", "in", List.of(1, 3))); + if (!signUpUsers.isEmpty() && thisSignUpUserCount > 0) { TrainSignUpUser trainSignUpUser = signUpUsers.get(0); trainSignUpUser.setState(1); dao.update(trainSignUpUser); + Sys_user user = dao.fetch(Sys_user.class, trainSignUpUser.getUserId()); + //msgApi.sendTextMsg("【" + activity.getActivityName() + "】已候补成功,请按时参加活动!", user.getLoginname()); } } //删除报名记录 @@ -149,12 +216,13 @@ public class MTrainSignUpActivityController { dao.clear("train_sign_up_user", Cnd.where("activityId", "=", activityId) .and("courseId", "=", courseId).and("userId", "=", userId)); - return Result.success(); } @At + @ApiOperation("签到") @SaCheckPermission("h5.trainSignUp.sign") + @SLog(type = "family", tag = "签到", msg = "签到") public Result doQd(@Param("id") String id, @Param("courseId") String courseId, @Param("point") Double[] points) { TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId); List coursePoints = course.getCourseLocationCoordinates(); @@ -181,6 +249,7 @@ public class MTrainSignUpActivityController { * @return */ @At + @ApiOperation("获取签到信息") @SaCheckPermission("h5.trainSignUp.sign") public Result getQdInfoList(@Param("activityId") String activityId) { List list = trainSignUpActivityService.qdInfoByUserId(SecurityUtil.getUserId(), activityId); @@ -188,17 +257,21 @@ public class MTrainSignUpActivityController { } @At + @ApiOperation("验证是否能报名") @SaCheckPermission("h5.trainSignUp.sign") public Result validateSignUp(String courseId, - @Param(value = "cndId") String cndId, @Param(value = "currentFamilyNumber") Integer currentFamilyNumber) { try { lock.lock(); if(StrUtil.isBlank(courseId)) { - return Result.error("缺少参数"); + return Result.error("报名信息为空"); } + + currentFamilyNumber = currentFamilyNumber != null ? currentFamilyNumber : 0; TrainSignUpCourse course = dao.fetch(TrainSignUpCourse.class, courseId); TrainSignUpActivity activity = dao.fetch(TrainSignUpActivity.class, course.getActivityId()); + + //判断时间 if(DateUtil.compare(new Date(), activity.getActivitySignUpStartTime(), "yyyy-MM-dd HH:mm:ss") < 0) { return Result.error("报名未开始"); } @@ -206,36 +279,40 @@ public class MTrainSignUpActivityController { return Result.error("报名已结束"); } + //判断活动组别 + int count = dao.count(ActivityUserScope.class, Cnd.where("groupId", "=", activity.getActivityGroupId()).and("userId", "=", SecurityUtil.getUserId())); + if(count == 0) { + return Result.error("抱歉,您没有此次活动的权限"); + } + + //判断是否报名 boolean courseByUser = trainSignUpActivityService.isSignCourseByUser(courseId, SecurityUtil.getUserId()); if(courseByUser) { - return Result.error("您已报过该活动"); + return Result.error("抱歉,您已经报名"); } - //判断人数 - boolean signFull = trainSignUpActivityService.isSignFull(courseId, currentFamilyNumber); + + //判断活动人数 + boolean signFull = trainSignUpActivityService.isSignFull(course, currentFamilyNumber); if(signFull) { - return Result.error("当前报名人数已满"); + return Result.error("名额剩余数量不足"); } - boolean signCourse = trainSignUpActivityService.isSignCourse(courseId, activity.getId()); + + //判断活动限制 + boolean signCourse = trainSignUpActivityService.isSignCourse(course, activity); if(!signCourse) { if(activity.getRestrictLimit() != 3) { - return Result.error("您选择的类型的培训班已达上限,不能再报该类型的培训班了"); + return Result.error("您选择的类型已达上限,不能再报该类型的了"); } else { return Result.error(activity.getActivityName() + "限制报" + activity.getLimitNum() + "个活动,已达上限"); } } - boolean signFullByUnionId = trainSignUpActivityService.isSignFullByUnionId(courseId, currentFamilyNumber); + + //判断分工会人数限制 + boolean signFullByUnionId = trainSignUpActivityService.isSignFullByUnionId(course, currentFamilyNumber); if(signFullByUnionId) { - return Result.error("该活动您所在的分工会名额已报满"); - } - if(course.getReserveMode() == 2 && currentFamilyNumber == null) { - //课程已报人数 - List signUpUsers = dao.query(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId) - .and("state", "!=", 2)); - int hasRegisterNum = signUpUsers.size() + 1;//+1是算自己 - if(hasRegisterNum > course.getCoursePeopleNumber()) { - return Result.error(3, "您当前的报名为候补报名状态"); - } + return Result.error("您所在的分工会名额不足"); } + return Result.success(); }catch (Exception e) { e.printStackTrace(); @@ -246,7 +323,34 @@ public class MTrainSignUpActivityController { } @At + @ApiOperation("验证子活动是否能报名") @SaCheckPermission("h5.trainSignUp.sign") + public Object validateSourceSignUp(String activityCourseId) { + try { + lock.lock(); + // 该时间段下已报名的人数 + int count = dao.count(TrainSignUpUserCourse.class, Cnd.where("activityCourseId", "=", activityCourseId)); + // 获取改时间段下的活动课程限制报名人数 + TrainSignUpActivityCourse course = dao.fetch(TrainSignUpActivityCourse.class, activityCourseId); + Integer courseLimitNum = course.getCourseLimitNum(); + // 报名加上自己,如果大于了限制人数,那就无法报名 + if (count + 1 > courseLimitNum) { + return Result.error("该时间段名额已报满,请选择其他时段报名"); + } else { + return Result.success(); + } + } catch (Exception e) { + e.printStackTrace(); + return Result.error("报名失败"); + } finally { + lock.unlock(); + } + } + + @At + @ApiOperation("二维码签到") + @SaCheckPermission("h5.trainSignUp.sign") + @SLog(type = "family", tag = "二维码签到", msg = "二维码签到") public Result codeSign(String id, String codeCourseId, String clickCourseId) { if(StrUtil.isBlank(codeCourseId) || StrUtil.isBlank(clickCourseId)) { return Result.error("签到失败,没有获取到扫描信息"); diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/statistics/TrainSignUpActivityStatisticsController.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/statistics/TrainSignUpActivityStatisticsController.java index 782a5c9e..7500c37e 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/statistics/TrainSignUpActivityStatisticsController.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/controller/statistics/TrainSignUpActivityStatisticsController.java @@ -6,16 +6,23 @@ import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; import cn.afterturn.easypoi.excel.export.ExcelExportService; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.sys.models.Sys_file; +import com.budwk.app.sys.utils.SysFileMinIoUtil; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainMobileSignColumn; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpCourse; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpType; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.nutz.dao.Chain; @@ -26,6 +33,7 @@ import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.json.Json; +import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; @@ -33,12 +41,11 @@ import org.nutz.mvc.annotation.Param; import javax.servlet.http.HttpServletResponse; import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -49,18 +56,17 @@ import java.util.zip.ZipOutputStream; * @Description 培训报名 统计 * @createTime 2022年02月23日 09:57:00 */ -@IocBean -@At("/platform/trainSingUp/statistics/activity") @Slf4j +@IocBean @Ok("json:full") +@Api(tags = "品牌活动统计") +@At("/platform/trainSingUp/statistics/activity") public class TrainSignUpActivityStatisticsController { @Inject private TrainSignUpActivityService trainSignUpActivityManageService; - @Inject private TrainSignUpActivityStatisticsService trainSignUpActivityStatisticsService; - @Inject private Dao dao; @@ -71,6 +77,7 @@ public class TrainSignUpActivityStatisticsController { } @At + @ApiOperation("分页查询") @SaCheckPermission("trainSingUp.statistics.activity") public Result pageData(PageForm pageForm, @Param(value = "activityId") String activityId) { @@ -85,6 +92,7 @@ public class TrainSignUpActivityStatisticsController { * @return */ @At + @ApiOperation("活动列表") @SaCheckPermission("trainSingUp.statistics.activity") public Result activityList(@Param(value = "year") Integer year) { List list = dao.query(TrainSignUpActivity.class, Cnd.NEW().andEX("year", "=", year).desc("activityStartTime")); @@ -98,11 +106,19 @@ public class TrainSignUpActivityStatisticsController { * @return */ @At + @ApiOperation("报名人员列表") @SaCheckPermission("trainSingUp.statistics.activity") public Result registerUserList(@Param(value = "courseId") String courseId) { return Result.success(trainSignUpActivityStatisticsService.registerUserList(courseId)); } + @At + @ApiOperation("报名动态列") + @SaCheckPermission("trainSingUp.statistics.activity") + public Object getTaleColumnInfo(@Param(value = "courseId") String courseId) { + return Result.success(trainSignUpActivityStatisticsService.getTaleColumnInfo(courseId)); + } + /** * 培训班上课签到信息 * @@ -110,12 +126,14 @@ public class TrainSignUpActivityStatisticsController { * @return */ @At + @ApiOperation("获取签到信息") @SaCheckPermission("trainSingUp.statistics.activity") public Result getSignInfo(@Param("courseId") String courseId) { return Result.success(trainSignUpActivityStatisticsService.getSignInfo(courseId)); } @At + @ApiOperation("开放报名") @SaCheckPermission("trainSingUp.statistics.activity") public Result signChange(@Param("courseId") String courseId, @Param("openOtherUnion") Boolean openOtherUnion) { dao.update(TrainSignUpCourse.class, Chain.make("openOtherUnion", openOtherUnion) @@ -125,115 +143,118 @@ public class TrainSignUpActivityStatisticsController { @At @Ok("void") + @ApiOperation("导出签到名单") @SaCheckPermission("trainSingUp.statistics.activity") public void exportSignUser(@Param(value = "activityId") String activityId, HttpServletResponse response) throws IOException { - response.setContentType("application/octet-stream"); - response.setHeader("content-disposition", "attachment;filename=" - + URLEncoder.encode("报名人员.zip", StandardCharsets.UTF_8)); - Sql sql = Sqls.create(""" - SELECT - ts.*, - u.username, - u.loginname, - u.unitName, - u.unionName, - u.sex, - if(ts.mobile is null, u.mobile, ts.mobile) as mobile, - u.birthday, - tsc.courseName, - tsc.campus, - ts.state - FROM - train_sign_up_user ts - left join `vw_user` u on u.id = ts. userId - left join train_sign_up_course tsc on tsc.id = ts.courseId - WHERE - ts.activityId = @activityId - ORDER BY FIELD( ts.state, 1, 3, 2, 4 ),u.unionid desc, u.unitid desc - """).setParam("activityId", activityId); - List userList = trainSignUpActivityManageService.listMap(sql); - userList.forEach(item -> { - if (item.getInt("state") == 1) { - item.setv("stateName", "正常报名"); - } else if (item.getInt("state") == 2) { - item.setv("stateName", "候补报名"); - } else if (item.getInt("state") == 3) { - item.setv("stateName", "正常报名(候补)"); - } else if (item.getInt("state") == 4) { - item.setv("stateName", "无效报名(缺席)"); - } - }); + try { + TrainSignUpActivity activity = dao.fetch(TrainSignUpActivity.class, activityId); + Sql sql = Sqls.create(""" + SELECT + ts.*, + u.username, + u.loginname, + u.unitname, + u.unionname, + u.sex, + u.mobile, + u.birthday, + tsc.courseName + FROM + train_sign_up_user ts + left join `vw_user` u on u.id = ts. userId + left join train_sign_up_course tsc on tsc.id = ts.courseId + WHERE + ts.activityId = @activityId + """).setParam("activityId", activityId); + List userList = trainSignUpActivityManageService.listMap(sql); - List excelCommonExportEntity = new ArrayList<>(); - excelCommonExportEntity.add(new ExcelExportEntity("姓名", "username", 20)); - excelCommonExportEntity.add(new ExcelExportEntity("工号", "loginname", 20)); - excelCommonExportEntity.add(new ExcelExportEntity("单位", "unitName", 20)); - excelCommonExportEntity.add(new ExcelExportEntity("分工会", "unionName", 20)); - excelCommonExportEntity.add(new ExcelExportEntity("性别", "sex", 20)); - excelCommonExportEntity.add(new ExcelExportEntity("手机号", "mobile", 20)); - excelCommonExportEntity.add(new ExcelExportEntity("生日", "birthday", 20)); - excelCommonExportEntity.add(new ExcelExportEntity("报名状态", "stateName", 20)); + List courseList = dao.query(TrainSignUpCourse.class, Cnd.where("activityId", "=", activityId)); - List courseList = dao.query(TrainSignUpCourse.class, Cnd.where("activityId", "=", activityId)); - Map courseMap = courseList.stream().collect(Collectors.toMap(o -> o.getId(), o -> o)); + List trainSignUpTypeList = dao.query(TrainSignUpType.class, Cnd.NEW()); + dao.fetchLinks(trainSignUpTypeList, "trainMobileSignColumnList", Cnd.NEW().asc("columnIndex")); + Map typeMap = trainSignUpTypeList.stream().collect(Collectors.toMap(TrainSignUpType::getId, o -> o)); - //按校区分组 - Map> campus = userList.stream().collect(Collectors.groupingBy(o -> o.getString("campus"))); + List> sheetsList = new ArrayList<>(); - ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream())); + List excelCommonExportEntity = new ArrayList<>(); + excelCommonExportEntity.add(new ExcelExportEntity("姓名", "username", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("工号", "loginname", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("单位", "unitname", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("分工会", "unionname", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("性别", "sex", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("手机号", "mobile", 20)); + excelCommonExportEntity.add(new ExcelExportEntity("生日", "birthday", 20)); - campus.forEach((key, value) -> { - Map> userListMap = value.stream().collect(Collectors.groupingBy(v -> v.getString("courseId"))); - Workbook workbook = new XSSFWorkbook(); - userListMap.forEach((k, v) -> { - - //查询课程 - TrainSignUpCourse course = courseMap.get(k); - //查询课程类型 - TrainSignUpType trainSignUpType = dao.fetch(TrainSignUpType.class, Cnd.where("id", "=", course.getCourseType())); - dao.fetchLinks(trainSignUpType, "^trainMobileSignColumnList$"); - - ExcelExportService service = new ExcelExportService(); + for (TrainSignUpCourse c : courseList) { + String k = c.getCourseName(); + List v = userList.stream().filter(x -> x.getString("courseName").equals(k)).collect(Collectors.toList()); ExportParams userExportParams = new ExportParams(); - userExportParams.setTitle(course.getCourseName()); - userExportParams.setSheetName(course.getCourseName()); - userExportParams.setType(ExcelType.XSSF); + userExportParams.setSheetName(k); + userExportParams.setType(ExcelType.HSSF); List currentEntities = new ArrayList<>(); currentEntities.addAll(excelCommonExportEntity); - //将课程类型配置的移动端动态字段添加到excel列中 - List trainMobileSignColumnList = trainSignUpType.getTrainMobileSignColumnList(); - if (trainMobileSignColumnList != null && trainMobileSignColumnList.size() > 0) { - trainMobileSignColumnList.forEach(item -> { - currentEntities.add(new ExcelExportEntity(item.getColumnName(), item.getColumnCode(), 20)); - }); - } + TrainSignUpType signUpType = typeMap.get(c.getCourseType()); + if (Lang.isNotEmpty(signUpType.getTrainMobileSignColumnList())) { + for (TrainMobileSignColumn column : signUpType.getTrainMobileSignColumnList()) { + ExcelExportEntity entity = new ExcelExportEntity(); + entity.setName(column.getColumnName()); + entity.setKey(column.getColumnCode()); + entity.setWidth(20); + if (column.getColumnFormType().equals("FILE")) { + entity.setType(2); + entity.setExportImageType(2); + } + currentEntities.add(entity); + } + } for (NutMap userSignData : v) { String mobileColumnsValueStr = userSignData.getString("mobileColumnsValue"); if (StrUtil.isNotBlank(mobileColumnsValueStr)) { List mobileColumnsValue = Json.fromJsonAsList(NutMap.class, mobileColumnsValueStr); for (NutMap cv : mobileColumnsValue) { - if (cv.getString("columnFormType") != null && !cv.getString("columnFormType").equals("FILE")) { - userSignData.addv(cv.getString("columnCode"), cv.getString("columnValue")); + if (!"FILE".equals(cv.getString("columnFormType"))) { + userSignData.put(cv.getString("columnCode"), cv.getString("columnValue")); + } else { + if (StrUtil.isNotBlank(cv.getString("columnValue"))) { + List columnValue = Json.fromJsonAsList(JSONObject.class, cv.getString("columnValue")); + if (columnValue.size() == 1) { + JSONObject sysFile = columnValue.get(0); + Sys_file file = dao.fetch(Sys_file.class, Cnd.where(Sys_file::getDownloadPath, "=", sysFile.get("url"))); + byte[] imageBytes = SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath()); + if (imageBytes.length > 0) { + userSignData.put(cv.getString("columnCode"), imageBytes); + } + } + } } } + } } - service.createSheetForMap(workbook, userExportParams, currentEntities, v); - }); - try { - zipOutputStream.putNextEntry(new ZipEntry(key + "报名人员.xlsx")); - workbook.write(zipOutputStream); - zipOutputStream.closeEntry(); - response.flushBuffer(); - } catch (IOException e) { - e.printStackTrace(); + Map userExportMap = new HashMap<>(); + userExportMap.put("name", k); + userExportMap.put("title", userExportParams); + userExportMap.put("entity", currentEntities); + userExportMap.put("data", v); + + sheetsList.add(userExportMap); } - }); - zipOutputStream.flush(); - zipOutputStream.close(); + + Workbook workbook = new HSSFWorkbook(); + for (Map map : sheetsList) { + ExcelExportService service = new ExcelExportService(); + service.createSheetForMap(workbook, (ExportParams) map.get("title"), (List) map.get("entity"), (Collection) map.get("data")); + } + workbook.write(response.getOutputStream()); + workbook.close(); + + CommonDownloadUtil.download(activity.getActivityName() + "报名人员名单" + ".xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivityCourse.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivityCourse.java index caa0ce91..a40eed01 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivityCourse.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpActivityCourse.java @@ -46,5 +46,11 @@ public class TrainSignUpActivityCourse { @Comment("课程时间") private Date courseDate; + @Column + @ColDefine(type = ColType.INT, width = 4) + @Comment("限制人数") + private Integer courseLimitNum; + + private Integer hasRegisterNum; } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpCourse.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpCourse.java index 8af99664..7709989b 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpCourse.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpCourse.java @@ -70,6 +70,11 @@ public class TrainSignUpCourse extends BaseModel implements Serializable { @Comment("校区") private String campus; + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("报名人数是否限制") + private Boolean courseIsLimitApply; + @Column @ColDefine(type = ColType.INT) @Comment("序号") @@ -81,15 +86,10 @@ public class TrainSignUpCourse extends BaseModel implements Serializable { //已报人数 private Integer hasRegisterNum; - //已报家属人数 - private Integer hasFmailyNum; - private Boolean isBringFamily; private Boolean isAddFamily; - private Integer waitingNum; - //是否报过该课程 private Boolean isSign; @@ -146,4 +146,15 @@ public class TrainSignUpCourse extends BaseModel implements Serializable { @ColDefine(type = ColType.VARCHAR, width = 30) private String assort; + @Column + @ColDefine(type = ColType.INT) + @Default(value = "0") + @Comment("候补名额数") + private Integer waitingNum; + + //候补已报人数 + private Integer hasWaitingNum; + + private String courseTimeName; + } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpType.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpType.java index 11593f43..413e5947 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpType.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpType.java @@ -2,9 +2,11 @@ package com.budwk.app.zhgh.activity.trainSignUp.models; import com.budwk.app.base.model.BaseModel; import lombok.Data; +import lombok.EqualsAndHashCode; import org.nutz.dao.entity.annotation.*; import org.nutz.dao.interceptor.annotation.PrevInsert; +import java.io.Serial; import java.io.Serializable; import java.util.List; @@ -14,9 +16,12 @@ import java.util.List; * @author 赵欣雨 * @date 2020/8/18 9:16 */ -@Table("train_sign_up_type") @Data +@Table("train_sign_up_type") +@EqualsAndHashCode(callSuper = true) public class TrainSignUpType extends BaseModel implements Serializable { + + @Serial private static final long serialVersionUID = 1L; @Name @@ -33,7 +38,7 @@ public class TrainSignUpType extends BaseModel implements Serializable { @Column @Comment("类型名称") @ColDefine(type = ColType.VARCHAR, width = 80) - private String lxname; + private String typeName; @Column @Comment("序号") @@ -43,13 +48,21 @@ public class TrainSignUpType extends BaseModel implements Serializable { @Column @Comment("是否携带家属") @ColDefine(type = ColType.BOOLEAN) + @Default("0") private Boolean isBringFamily; @Column @Comment("家属纳入总人数") @ColDefine(type = ColType.BOOLEAN) + @Default("0") private Boolean isAddFamily; + @Column + @Comment("本人纳入总人数") + @ColDefine(type = ColType.BOOLEAN) + @Default("1") + private Boolean selfAddFamily; + @Many(field = "typeId") private List trainMobileSignColumnList; } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpUser.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpUser.java index daefb9bd..5adb994c 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpUser.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/models/TrainSignUpUser.java @@ -40,6 +40,26 @@ public class TrainSignUpUser implements Serializable { @Comment("用户ID") private String userId; + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("工会ID") + private String unionId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("单位ID") + private String unitId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("工会") + private String unionName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("单位") + private String unitName; + @Column @ColDefine(type = ColType.VARCHAR, width = 32) @Comment("联系方式") diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java index ee417a23..f7a3c547 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityService.java @@ -5,6 +5,7 @@ import com.budwk.app.base.param.PageForm; import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpActivity; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpCourse; +import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpType; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUser; import io.swagger.models.auth.In; import org.nutz.dao.Cnd; @@ -87,26 +88,20 @@ public interface TrainSignUpActivityService extends BaseService qdInfoByUserId(String userId, String activityId); + List filterCourseByHostUnion(List courseList); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityStatisticsService.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityStatisticsService.java index ab5ebf1b..df8f5c7b 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityStatisticsService.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/TrainSignUpActivityStatisticsService.java @@ -33,6 +33,8 @@ public interface TrainSignUpActivityStatisticsService extends BaseService registerUserList(String courseId); + List getTaleColumnInfo(String courseId); + /** * 该课程下的报名人员信息 * @@ -56,4 +58,11 @@ public interface TrainSignUpActivityStatisticsService extends BaseService baoMingUserList(String activityId); + int queryCourseCount(String courseId, String courseType); + + int queryCourseWaitCount(String courseId, String courseType); + + int queryCourseCount(String courseId, String courseType, String unionId); + + int queryCourseWaitCount(String courseId, String courseType, String unionId); } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java index cd6e00e5..d965a9f3 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityServiceImpl.java @@ -5,9 +5,15 @@ import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.sys.models.Sys_home_activity; +import com.budwk.app.sys.views.View_user; import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.family.models.FamilyActivity; +import com.budwk.app.zhgh.activity.family.models.FamilyCourse; +import com.budwk.app.zhgh.activity.family.models.FamilyType; +import com.budwk.app.zhgh.activity.family.service.FamilyActivityStatisticsService; import com.budwk.app.zhgh.activity.trainSignUp.models.*; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityService; +import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityStatisticsService; import lombok.extern.slf4j.Slf4j; import org.nutz.aop.interceptor.async.Async; import org.nutz.aop.interceptor.ioc.TransAop; @@ -18,6 +24,7 @@ import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; import org.nutz.dao.util.cri.Static; import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; @@ -34,503 +41,423 @@ import java.util.stream.Collectors; * @Description TODO * @createTime 2022年02月23日 17:14:00 */ -@IocBean(args = {"refer:dao"}) @Slf4j +@IocBean(args = {"refer:dao"}) public class TrainSignUpActivityServiceImpl extends BaseServiceImpl implements TrainSignUpActivityService { - public TrainSignUpActivityServiceImpl(Dao dao) { - super(dao); - } + @Inject + private TrainSignUpActivityStatisticsService statisticsService; - @Override - @Aop(TransAop.READ_COMMITTED) - public void add(TrainSignUpActivity activity, TrainSignUpCourse course) { + public TrainSignUpActivityServiceImpl(Dao dao) { + super(dao); + } - dao().insert(activity); - List courseList = activity.getCourseList(); - courseList.forEach(v -> { + @Override + @Aop(TransAop.READ_COMMITTED) + public void add(TrainSignUpActivity activity, TrainSignUpCourse course) { - v.setActivityId(activity.getId()); - v.setOpenOtherUnion(false); - dao().insert(v); + dao().insert(activity); - List courseTimeList = v.getCourseTimeList(); - courseTimeList.forEach(x -> { - x.setActivityId(activity.getId()); - x.setCourseId(v.getId()); + //插入类型限制 + List typeLimits = activity.getTypeLimits(); + typeLimits.forEach(v -> v.setActivityId(activity.getId())); + dao().insert(typeLimits); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(x.getCourseDate()); - int year = calendar.get(Calendar.YEAR); - int month = calendar.get(Calendar.MONTH); - int day = calendar.get(Calendar.DATE); + List courseList = activity.getCourseList(); + for (TrainSignUpCourse v : courseList) { + v.setActivityId(activity.getId()); + v.setOpenOtherUnion(false); + dao().insert(v); + this.setCourseTimeAndInsert(v); + } - Calendar startCalendar = Calendar.getInstance(); - startCalendar.setTime(x.getCourseStartTime()); - startCalendar.set(year, month, day); - x.setCourseStartTime(startCalendar.getTime()); + if (!activity.isDisabled()) { + Sys_home_activity sysHomeActivity = activity.covertToSysHomeActivity(); + dao().insertOrUpdate(sysHomeActivity); + } + } - Calendar endCalendar = Calendar.getInstance(); - endCalendar.setTime(x.getCourseEndTime()); - endCalendar.set(year, month, day); - x.setCourseEndTime(endCalendar.getTime()); - dao().insert(x); - }); - }); + @Override + @Aop(TransAop.READ_COMMITTED) + public void edit(TrainSignUpActivity activity) { - List typeLimits = activity.getTypeLimits(); - typeLimits.forEach(v -> { - v.setActivityId(activity.getId()); - dao().insert(v); - }); + //修改活动 + update(activity); - if (!activity.isDisabled()) { - Sys_home_activity sysHomeActivity = activity.covertToSysHomeActivity(); - dao().insertOrUpdate(sysHomeActivity); - } - } + //修改类型限制 + List typeLimits = activity.getTypeLimits(); + typeLimits.forEach(v -> v.setActivityId(activity.getId())); + if(Lang.isNotEmpty(typeLimits)) { + insertOrUpdate(typeLimits); + } - @Override - @Aop(TransAop.READ_COMMITTED) - public void edit(TrainSignUpActivity activity) { + List courseList = activity.getCourseList(); + courseList.forEach(v -> { + v.setActivityId(activity.getId()); + dao().insertOrUpdate(v); + if (Lang.isNotEmpty(v.getCourseTimeList())) { + this.setCourseTimeAndInsert(v); + } + }); - List oldCourseList = dao().query(TrainSignUpCourse.class, Cnd.where("activityId", "=", activity.getId())); - //原来的培训班id - List oldCourseIdList = oldCourseList.stream().map(TrainSignUpCourse::getId).toList(); + //查询原来的活动 + List oldCourseList = dao().query(TrainSignUpCourse.class, Cnd.where("activityId", "=", activity.getId())); + //原来的培训班id + List oldCourseIdList = oldCourseList.stream().map(TrainSignUpCourse::getId).toList(); - //原来的上课时间 - List oldActCourseTimeList = dao().query(TrainSignUpActivityCourse.class, Cnd.where("activityId", "=", activity.getId())); + //原来的上课时间 + List oldActCourseTimeList = dao().query(TrainSignUpActivityCourse.class, Cnd.where("activityId", "=", activity.getId())); + //现在的上课时间 + List nowCourseTimeListId = new ArrayList<>(); + activity.getCourseList().forEach(v -> { + if (v.getCourseTimeList() != null) { + nowCourseTimeListId.addAll(v.getCourseTimeList().stream().map(TrainSignUpActivityCourse::getId).toList()); + } + }); - update(activity); + List deleteCourseTimeListId = oldActCourseTimeList.stream().map(TrainSignUpActivityCourse::getId).filter(id -> !nowCourseTimeListId.contains(id)).collect(Collectors.toList()); + List courseIdList = courseList.stream().map(TrainSignUpCourse::getId).collect(Collectors.toList()); - List typeLimits = activity.getTypeLimits(); - typeLimits.forEach(v -> { - v.setActivityId(activity.getId()); - insertOrUpdate(v); - }); + //删除关联的培训班 + List deleteIdList = oldCourseIdList.stream().filter(v -> !courseIdList.contains(v)).collect(Collectors.toList()); + dao().clear(TrainSignUpCourse.class, Cnd.where("id", "in", deleteIdList)); - List courseList = activity.getCourseList(); - courseList.forEach(v -> { + dao().clear(TrainSignUpActivityCourse.class, Cnd.where("id", "in", deleteCourseTimeListId)); + dao().clear(TrainSignUpUser.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); + dao().clear(TrainSignUpUserCourse.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); - v.setActivityId(activity.getId()); - dao().insertOrUpdate(v); + //查询修改过培训时间的记录 + Sql tsuucSql = Sqls.create(""" + SELECT + tsuuc.id, + tsuac.courseStartTime, + tsuac.courseEndTime + FROM + `train_sign_up_user_course` tsuuc + LEFT JOIN train_sign_up_activity_course tsuac ON tsuac.id = tsuuc.activityCourseId + where tsuuc.courseStartTime != tsuac.courseStartTime or tsuuc.courseEndTime != tsuac.courseEndTime + """); + List tsuucList = listMap(tsuucSql); + tsuucList.forEach(v -> { + Chain chain = Chain.make("courseStartTime", v.getTime("courseStartTime")); + chain.add("courseEndTime", v.getTime("courseEndTime")); + Cnd cnd = Cnd.where("id", "=", v.getString("id")); + dao().update("train_sign_up_user_course", chain, cnd); + }); - List courseTimeList = v.getCourseTimeList(); - if(courseTimeList != null) { - courseTimeList.forEach(x -> { - x.setActivityId(activity.getId()); - x.setCourseId(v.getId()); + if (!activity.isDisabled()) { + Sys_home_activity sysHomeActivity = activity.covertToSysHomeActivity(); + dao().insertOrUpdate(sysHomeActivity); + } else { + dao().delete(Sys_home_activity.class, activity.getId()); + } + } - Calendar calendar = Calendar.getInstance(); - calendar.setTime(x.getCourseDate()); - int year = calendar.get(Calendar.YEAR); - int month = calendar.get(Calendar.MONTH); - int day = calendar.get(Calendar.DATE); + private void setCourseTimeAndInsert(TrainSignUpCourse course) { + course.getCourseTimeList().forEach(courseTime -> { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(courseTime.getCourseDate()); + int year = calendar.get(Calendar.YEAR); + int month = calendar.get(Calendar.MONTH); + int day = calendar.get(Calendar.DATE); - Calendar startCalendar = Calendar.getInstance(); - startCalendar.setTime(x.getCourseStartTime()); - startCalendar.set(year, month, day); - x.setCourseStartTime(startCalendar.getTime()); + Calendar startCalendar = Calendar.getInstance(); + startCalendar.setTime(courseTime.getCourseStartTime()); + startCalendar.set(year, month, day); + courseTime.setCourseStartTime(startCalendar.getTime()); - Calendar endCalendar = Calendar.getInstance(); - endCalendar.setTime(x.getCourseEndTime()); - endCalendar.set(year, month, day); - x.setCourseEndTime(endCalendar.getTime()); + Calendar endCalendar = Calendar.getInstance(); + endCalendar.setTime(courseTime.getCourseEndTime()); + endCalendar.set(year, month, day); + courseTime.setCourseEndTime(endCalendar.getTime()); - dao().insertOrUpdate(x); + courseTime.setActivityId(course.getActivityId()); + courseTime.setCourseId(course.getId()); + dao().insertOrUpdate(courseTime); + }); + } - }); - } - }); + @Override + @Aop(TransAop.READ_COMMITTED) + public void updateActivityStatus(TrainSignUpActivity activity) { + updateIgnoreNull(activity); + } - //现在的上课时间 - List nowCourseTimeListId = new ArrayList<>(); - activity.getCourseList().stream().forEach(v -> { - if(v.getCourseTimeList() != null) { - nowCourseTimeListId.addAll(v.getCourseTimeList().stream().map(x -> x.getId()).collect(Collectors.toList())); - } - }); + @Override + public NutMap findOne(String id, Cnd cnd, String fromMode) { + if (Lang.isEmpty(cnd)) { + cnd = Cnd.NEW(); + } - List deleteCourseTimeListId = oldActCourseTimeList.stream().filter(x -> !nowCourseTimeListId.contains(x.getId())).map(x -> x.getId()).collect(Collectors.toList()); + cnd.asc("orderNum").asc("campus").desc("courseLocation").asc("courseType").asc("courseName"); + List courseArray = dao().query(TrainSignUpCourse.class, cnd.and("activityId", "=", id)); + if (StrUtil.isNotBlank(fromMode) && "mobile".equals(fromMode)) { + courseArray = this.filterCourseByHostUnion(courseArray); + } - List courseIdList = courseList.stream().map(v -> v.getId()).collect(Collectors.toList()); + TrainSignUpActivity activity = fetchLinks(dao().fetch(TrainSignUpActivity.class, id), "^(conditionStructure|typeLimits)$"); + activity.setCourseList(courseArray); - //删除关联的培训班 - List deleteIdList = oldCourseIdList.stream().filter(v -> !courseIdList.contains(v)).collect(Collectors.toList()); - dao().clear(TrainSignUpCourse.class, Cnd.where("id", "in", deleteIdList)); + List courseList = activity.getCourseList(); + courseList.forEach(c -> { + if (StrUtil.isNotBlank(c.getCourseType())) { + dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime")); + int courseCount = statisticsService.queryCourseCount(c.getId(), c.getCourseType()); + c.setHasRegisterNum(courseCount); + int courseWaitCount = statisticsService.queryCourseWaitCount(c.getId(), c.getCourseType()); + c.setHasWaitingNum(courseWaitCount); + //当前用户是否报过 + c.setIsSign(isSignCourseByUser(c.getId(), SecurityUtil.getUserId())); + } + }); + return Lang.obj2nutmap(activity); + } - dao().clear(TrainSignUpActivityCourse.class, Cnd.where("id", "in", deleteCourseTimeListId)); - dao().clear(TrainSignUpUser.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); - dao().clear(TrainSignUpUserCourse.class, Cnd.where("courseId", "not in", courseIdList).and("activityId", "=", activity.getId())); + @Override + public Pagination pageData(PageForm pageForm, Cnd cnd) { + Pagination pagination = listPageLinks(pageForm.getPageNumber(), pageForm.getPageSize(), cnd, "^(courseList)$"); + return pagination; + } - //修改train_sign_up_user_course的数据 如果上课时间发生变化 + @Override + public Pagination mPageData(PageForm pageForm, Integer year, int activityStatus, Integer activityType) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("year", "=", year); + switch (activityStatus) { + case 2 -> { + cnd.and(new Static("activitySignUpStartTime < now()")); + cnd.and(new Static("activitySignUpEndTime > now()")); + } + case 3 -> { + cnd.and(new Static("activityStartTime < now()")); + cnd.and(new Static("activityEndTime > now()")); + } + case 4 -> cnd.and(new Static("activityEndTime < now()")); + case 5 -> cnd.and(new Static("activityStartTime < now()")); + case 6 -> cnd.and(new Static("activityStartTime > now()")); + } + if (activityType != null && activityType == 1) { + cnd.and(new Static("id in (select activityId from train_sign_up_user where userId = '%s')".formatted(SecurityUtil.getUserId()))); + } + cnd.and("isDisabled", "=", 0); + cnd.orderBy("activityEndTime", "desc"); + cnd.orderBy("isDisabled", "desc"); + cnd.orderBy("createdAt", "desc"); + return listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + } - //查询修改过培训时间的记录 - Sql tsuucSql = Sqls.create(""" - SELECT - tsuuc.id, - tsuac.courseStartTime, - tsuac.courseEndTime - FROM - `train_sign_up_user_course` tsuuc - LEFT JOIN train_sign_up_activity_course tsuac ON tsuac.id = tsuuc.activityCourseId - where tsuuc.courseStartTime != tsuac.courseStartTime or tsuuc.courseEndTime != tsuac.courseEndTime - """); - List tsuucList = listMap(tsuucSql); - tsuucList.forEach(v -> { - Chain chain = Chain.make("courseStartTime", v.getTime("courseStartTime")); - chain.add("courseEndTime", v.getTime("courseEndTime")); - Cnd cnd = Cnd.where("id", "=", v.getString("id")); - dao().update("train_sign_up_user_course", chain, cnd); - }); + @Override + @Aop(TransAop.READ_COMMITTED) + public void doSignUp(TrainSignUpUser trainSignUpUser) throws Exception { + String userId = SecurityUtil.getUserId(); - if (!activity.isDisabled()) { - Sys_home_activity sysHomeActivity = activity.covertToSysHomeActivity(); - dao().insertOrUpdate(sysHomeActivity); - } else { - dao().delete(Sys_home_activity.class, activity.getId()); - } + //查询课程 + TrainSignUpCourse course = dao().fetch(TrainSignUpCourse.class, trainSignUpUser.getCourseId()); + TrainSignUpType type = dao().fetch(TrainSignUpType.class, course.getCourseType()); + //如果这个课程的预留名额方式为报名人数不变 + if (course.getReserveMode() == 2) { + //如果当前报名+已报小于这个课程限制人数 + //课程已报人数 + int normalCount = statisticsService.queryCourseCount(course.getId(), course.getCourseType()); + //+1是算自己 + int hasRegisterNum = type.getSelfAddFamily() ? normalCount + 1 : 0; + trainSignUpUser.setState((hasRegisterNum + course.getCourseReservedNumber()) > course.getCoursePeopleNumber() ? 2 : 1); + } else { + trainSignUpUser.setState(1); + } - } + View_user user = dao().fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + trainSignUpUser.setUnionId(SecurityUtil.getUnionId()); + trainSignUpUser.setUnionName(user.getUnionName()); + trainSignUpUser.setUnitId(SecurityUtil.getUnitId()); + trainSignUpUser.setUnitName(user.getUnitName()); + trainSignUpUser.setUserId(userId); + trainSignUpUser.setSignUpTime(new Date()); - @Override - @Aop(TransAop.READ_COMMITTED) - public void updateActivityStatus(TrainSignUpActivity activity) { - updateIgnoreNull(activity); - } + dao().insert(trainSignUpUser); + asyncInsertUserCourse(trainSignUpUser.getActivityId(), trainSignUpUser.getCourseId(), userId); + } - @Override - public NutMap findOne(String id, Cnd cnd, String fromMode) { - if (Lang.isEmpty(cnd)) { - cnd = Cnd.NEW(); - } + @Async + @Override + public void asyncInsertUserCourse(String activityId, String courseId, String userId) { + log.info("异步插入{}的上课信息,课程ID为{},活动ID为{}", userId, courseId, activityId); + List courseList = dao().query(TrainSignUpActivityCourse.class, Cnd.where("courseId", "=", courseId)); + List list = new ArrayList<>(); + courseList.forEach(v -> { + TrainSignUpUserCourse userCourse = new TrainSignUpUserCourse(); + userCourse.setActivityId(activityId); + userCourse.setCourseId(courseId); + userCourse.setUserId(userId); + userCourse.setCourseStartTime(v.getCourseStartTime()); + userCourse.setCourseEndTime(v.getCourseEndTime()); + userCourse.setAttend(false); + userCourse.setAttendTime(null); + userCourse.setActivityCourseId(v.getId()); + list.add(userCourse); + }); + dao().insert(list); + } - cnd.asc("orderNum").asc("campus").desc("courseLocation").asc("courseType").asc("courseName"); - List courseArray = dao().query(TrainSignUpCourse.class, cnd.and("activityId", "=", id)); + /** + * 该培训班每个分工会名额是否报满 + * @return + */ + @Override + public boolean isSignFullByUnionId(TrainSignUpCourse course, Integer currentFamilyNumber) { + List unionLimit = course.getUnionLimit(); + if (Lang.isEmpty(unionLimit)) { + return false; + } + String unionId = SecurityUtil.getUnionId(); + NutMap unionLimitMap = unionLimit.stream().filter(v -> v.getString("id").equals(unionId)).findAny().orElse(null); + if (Lang.isEmpty(unionLimitMap)) { + return true; + } - if(StrUtil.isNotBlank(fromMode) && "mobile".equals(fromMode)) { - courseArray = courseArray.stream().filter(o -> { - if(StrUtil.isBlank(o.getInterTime()) || o.getOpenOtherUnion() == null || o.getOpenOtherUnion()) { - return true; - } else { - if(SecurityUtil.getUnionId().equals(o.getHostUnionId())) { - return true; - } else { - int compare = cn.hutool.core.date.DateUtil.compare(cn.hutool.core.date.DateUtil.date(), cn.hutool.core.date.DateUtil.parse(o.getInterTime()), "yyyy-MM-dd HH:mm"); - if(compare >= 0) { - return true; - } - } - } - return false; - }).collect(Collectors.toList()); - } + TrainSignUpType type = dao().fetch(TrainSignUpType.class, course.getCourseType()); + //分工会限制人数 + int limitCount = unionLimitMap.getInt("limitCount"); - TrainSignUpActivity activity = fetchLinks(dao().fetch(TrainSignUpActivity.class, id), "^(conditionStructure|typeLimits)$"); - activity.setCourseList(courseArray); + //该课程已经报名的总人数 + int hasSignCount = statisticsService.queryCourseCount(course.getId(), course.getCourseType(), unionId); + int hasWaitCount = statisticsService.queryCourseWaitCount(course.getId(), course.getCourseType()); - List courseList = activity.getCourseList(); + //+1是算自己 + int current = type.getSelfAddFamily() ? 1 : 0; + currentFamilyNumber = type.getIsBringFamily() && type.getIsAddFamily() ? currentFamilyNumber : 0; + //如果还有正常名额 + if(limitCount - hasSignCount > 0) { + return (hasSignCount + current + currentFamilyNumber) > limitCount; + } else { + return (hasWaitCount + current + currentFamilyNumber) > course.getWaitingNum(); + } + } - courseList.forEach(c -> { - if(StrUtil.isNotBlank(c.getCourseType())) { - TrainSignUpType type = dao().fetch(TrainSignUpType.class, c.getCourseType()); - dao().fetchLinks(c, "^(courseTimeList)$", Cnd.NEW().asc("courseStartTime")); - //已报人数 - AtomicInteger hasRegisterNum = new AtomicInteger(); - List signUpUsers = dao().query(TrainSignUpUser.class, Cnd.where("courseId", "=", c.getId())); - signUpUsers.forEach(item -> { - hasRegisterNum.getAndIncrement(); - if(type.getIsBringFamily() && type.getIsAddFamily()) { - List mapList = item.getMobileColumnsValue(); - if(Lang.isNotEmpty(mapList)) { - NutMap nutMap = mapList.stream().filter(o -> "xdqsrs".equals(o.getString("columnCode"))).findAny().orElse(null); - if(nutMap != null) { - hasRegisterNum.addAndGet(nutMap.getInt("columnValue")); - } - } - } - }); - c.setHasRegisterNum(hasRegisterNum.get()); - //候补报名人数 - int count = dao().count(TrainSignUpUser.class, Cnd.where("activityId", "=", activity.getId()).and("courseId", "=", c.getId()) - .and("state", "=", 2)); - c.setWaitingNum(count); - //当前用户是否报过 - c.setIsSign(isSignCourseByUser(c.getId(), SecurityUtil.getUserId())); - } - }); - return Lang.obj2nutmap(activity); - } + @Override + public boolean isSignFull(TrainSignUpCourse course, Integer currentFamilyNumber) { + //课程限制人数 + int coursePeopleNumber = course.getCoursePeopleNumber(); + if (coursePeopleNumber == 0) { + return true; + } + //查询课程对应的类型 + TrainSignUpType type = dao().fetch(TrainSignUpType.class, course.getCourseType()); + //课程已报人数 + int hasSignCount = statisticsService.queryCourseCount(course.getId(), course.getCourseType()); + int hasWaitCount = statisticsService.queryCourseWaitCount(course.getId(), course.getCourseType()); - @Override - public Pagination pageData(PageForm pageForm, Cnd cnd) { - Pagination pagination = listPageLinks(pageForm.getPageNumber(), pageForm.getPageSize(), cnd, "^(courseList)$"); - return pagination; - } + //+1是算自己 + int current = type.getSelfAddFamily() ? 1 : 0; + currentFamilyNumber = type.getIsBringFamily() && type.getIsAddFamily() ? currentFamilyNumber : 0; + //如果还有正常名额 + if(coursePeopleNumber - hasSignCount > 0) { + return (hasSignCount + current + currentFamilyNumber + course.getCourseReservedNumber()) > coursePeopleNumber; + } else { + return (hasWaitCount + current + currentFamilyNumber) > course.getWaitingNum(); + } + } - @Override - public Pagination mPageData(PageForm pageForm, Integer year, int activityStatus, Integer activityType) { - Cnd cnd = Cnd.NEW(); - cnd.andEX("year", "=", year); - switch (activityStatus) { - case 2 -> { - cnd.and(new Static("activitySignUpStartTime < now()")); - cnd.and(new Static("activitySignUpEndTime > now()")); - } - case 3 -> { - cnd.and(new Static("activityStartTime < now()")); - cnd.and(new Static("activityEndTime > now()")); - } - case 4 -> cnd.and(new Static("activityEndTime < now()")); - case 5 -> cnd.and(new Static("activityStartTime < now()")); - case 6 -> cnd.and(new Static("activityStartTime > now()")); - } - if(activityType != null && activityType == 1) { - cnd.and(new Static("id in (select activityId from train_sign_up_user where userId = '%s')".formatted(SecurityUtil.getUserId()))); - } - cnd.and("isDisabled", "=", 0); - cnd.orderBy("activityEndTime", "desc"); - cnd.orderBy("isDisabled", "desc"); - cnd.orderBy("createdAt", "desc"); - return listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); - } + @Override + public boolean isSignCourse(TrainSignUpCourse course, TrainSignUpActivity activity) { + //培训班类型 + String courseType = course.getCourseType(); - @Override - @Aop(TransAop.READ_COMMITTED) - public void doSignUp(TrainSignUpUser trainSignUpUser) throws Exception { - String userId = SecurityUtil.getUserId(); + Sql sql = Sqls.create(""" + SELECT + count( tsus.id ) + FROM + `train_sign_up_user` tsus + LEFT JOIN train_sign_up_course tsuc ON tsuc.id = tsus.courseId + WHERE + tsuc.courseType = @courseType + AND tsus.userId = @userId + AND tsus.activityId = @activityId + """); + sql.setParam("courseType", courseType); + sql.setParam("activityId", activity.getId()); + sql.setParam("userId", SecurityUtil.getUserId()); + int hasRegisterNum = count(sql); - //查询课程 - TrainSignUpCourse course = dao().fetch(TrainSignUpCourse.class, trainSignUpUser.getCourseId()); - //如果这个课程的预留名额方式为报名人数不变 - if(course.getReserveMode() == 2) { - //如果当前报名+已报小于这个课程限制人数 - //课程已报人数 - List signUpUsers = dao().query(TrainSignUpUser.class, Cnd.where("courseId", "=", trainSignUpUser.getCourseId()) - .and("state", "!=", 2)); - int hasRegisterNum = signUpUsers.size() + 1;//+1是算自己 - if(hasRegisterNum > course.getCoursePeopleNumber()) { - trainSignUpUser.setState(2); - } else { - trainSignUpUser.setState(1); - } - } else { - trainSignUpUser.setState(1); - } + //第一种无限制报名 + if (activity.getRestrictLimit() == null || activity.getRestrictLimit() == 1) { + return true; + } else if (activity.getRestrictLimit() == 2) { + TrainSignUpTypeLimit trainSignUpTypeLimit = dao().fetch(TrainSignUpTypeLimit.class, Cnd.where("typeId", "=", courseType).and("activityId", "=", activity.getId())); + if (trainSignUpTypeLimit == null) { + return true; + } + //此类型的班最多可报几项 + int personMaxRegisterNum = trainSignUpTypeLimit.getLimitNum(); + if (personMaxRegisterNum == 0) { + return true; + } + return hasRegisterNum < personMaxRegisterNum; + } else if (activity.getRestrictLimit() == 3) { + //第三种,限制报几个,不跟类型挂钩 + int aCount = dao().count(TrainSignUpUser.class, Cnd.where("activityId", "=", activity.getId()).and("userId", "=", SecurityUtil.getUserId())); + return aCount < activity.getLimitNum(); + } + return false; + } - trainSignUpUser.setUserId(userId); - trainSignUpUser.setSignUpTime(new Date()); + @Override + public boolean isSignCourseByUser(String courseId, String userId) { + return dao().count(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId).and("userId", "=", userId)) > 0; + } - dao().insert(trainSignUpUser); - asyncInsertUserCourse(trainSignUpUser.getActivityId(), trainSignUpUser.getCourseId(), userId); - } + @Override + public void doQd(String id) { + NutMap updateMap = NutMap.NEW(); + updateMap.put("isAttend", true); + updateMap.put("attendTime", new Date()); + dao().update(TrainSignUpUserCourse.class, Chain.from(updateMap), Cnd.where("id", "=", id)); + } - @Async - @Override - public void asyncInsertUserCourse(String activityId, String courseId, String userId) { - log.info("异步插入{}的上课信息,课程ID为{},活动ID为{}", userId, courseId, activityId); - List courseList = dao().query(TrainSignUpActivityCourse.class, Cnd.where("courseId", "=", courseId)); - List list = new ArrayList<>(); - courseList.forEach(v -> { - TrainSignUpUserCourse userCourse = new TrainSignUpUserCourse(); - userCourse.setActivityId(activityId); - userCourse.setCourseId(courseId); - userCourse.setUserId(userId); - userCourse.setCourseStartTime(v.getCourseStartTime()); - userCourse.setCourseEndTime(v.getCourseEndTime()); - userCourse.setAttend(false); - userCourse.setAttendTime(null); - userCourse.setActivityCourseId(v.getId()); - list.add(userCourse); - }); - dao().insert(list); - } + @Override + public List qdInfoByUserId(String userId, String activityId) { + Sql sql = Sqls.create(""" + SELECT + c.*, + t.courseLocationCoordinates, + t.isMobileSign, + t.signType, + t.isReceiveGift, + t.giftType, + (select state from train_sign_up_user su where su.activityId = c.activityId and su.courseId = c.courseId and su.userId = c.userId) as state + FROM + `train_sign_up_user_course` c + LEFT JOIN train_sign_up_course t ON t.id = c.courseId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("c.activityId", "=", activityId); + cnd.and("c.userId", "=", userId); + cnd.asc("c.courseStartTime"); - /** - * 该培训班每个分工会名额是否报满 - * - * @param courseId - * @return - */ - @Override - public boolean isSignFullByUnionId(String courseId, Integer currentFamilyNumber) { - TrainSignUpCourse course = dao().fetch(TrainSignUpCourse.class, courseId); - TrainSignUpType signUpType = dao().fetch(TrainSignUpType.class, course.getCourseType()); - List unionLimit = course.getUnionLimit(); - if (Lang.isEmpty(unionLimit)) { - return false; - } - String unionId = SecurityUtil.getUnionId(); - NutMap unionLimitMap = unionLimit.stream().filter(v -> v.getString("id").equals(unionId)).findAny().orElse(null); - if (Lang.isEmpty(unionLimitMap)) { - return true; - } - //分工会限制人数 - int limitCount = unionLimitMap.getInt("limitCount"); - - //查询该课程已经报了多少人 - Sql sql = Sqls.create(""" - SELECT - fu.* - FROM - `train_sign_up_user` fu - LEFT JOIN `user` u ON fu.userid = u.id - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.andEX("u.unionid", "=", unionId); - cnd.andEX("courseId", "=", courseId); - sql.setCondition(cnd); - //已经报名人数,这是教职工的 - List signUpUsers = listMap(sql); - int hasRegisterNum = signUpUsers.size() + 1;//+1是算自己 - //课程已报人数(携带的家属) - int hasFamilyNum = 0; - //如果携带家属,并且纳入人数,则mdzz - if(signUpType.getIsAddFamily() && signUpType.getIsBringFamily()) { - //如果携带家属,已报人数=教职工+每个教职工携带的家属 - AtomicInteger num = new AtomicInteger(); - signUpUsers.forEach(item -> { - List mapList = item.getAsList("", NutMap.class); - if(Lang.isNotEmpty(mapList)) { - NutMap nutMap = mapList.stream().filter(o -> "xdqsrs".equals(o.getString("columnCode"))).findAny().orElse(null); - if(nutMap != null) { - num.addAndGet(nutMap.getInt("columnValue")); - } - } - }); - hasFamilyNum = num.get() + (currentFamilyNumber != null ? currentFamilyNumber : 0);//currentFamilyNumber是当前报名时填的家属人数 - } - //如果已报人数+当前报名(自己)+家属 > 分工会限制人数 - return (hasRegisterNum + hasFamilyNum) > limitCount; - } - - @Override - public boolean isSignFull(String courseId, Integer currentFamilyNumber) { - //查询课程 - TrainSignUpCourse course = dao().fetch(TrainSignUpCourse.class, courseId); - //课程限制人数 - int coursePeopleNumber = course.getCoursePeopleNumber(); - if(coursePeopleNumber == 0) { - return false; - } - //查询课程对应的类型 - TrainSignUpType type = dao().fetch(TrainSignUpType.class, course.getCourseType()); - //课程已报人数 - List signUpUsers = dao().query(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId)); - int hasRegisterNum = signUpUsers.size() + 1;//+1是算自己 - //课程已报人数(携带的家属) - int hasFamilyNum = 0; - //如果这个类型携带家属并且计入总人数 - if(type.getIsBringFamily() && type.getIsAddFamily()) { - AtomicInteger num = new AtomicInteger(); - signUpUsers.forEach(item -> { - List mapList = item.getMobileColumnsValue(); - if(Lang.isNotEmpty(mapList)) { - NutMap nutMap = mapList.stream().filter(o -> "xdqsrs".equals(o.getString("columnCode"))).findAny().orElse(null); - if(nutMap != null) { - num.addAndGet(nutMap.getInt("columnValue")); - } - } - }); - hasFamilyNum = num.get() + (currentFamilyNumber != null ? currentFamilyNumber : 0);//currentFamilyNumber是当前报名时填的家属人数 - } - //如果预留名额模式是报名人数减少 - if(course.getReserveMode() == 1) { - //如果已报人数+预留人数+当前报名(自己)+家属 > 总人数 - return (hasRegisterNum + course.getCourseReservedNumber() + hasFamilyNum) > coursePeopleNumber; - }else {//如果预留名额模式是报名人数不变 - //如果已报人数+当前报名(自己)+家属 > 总人数+预留人数 - return (hasRegisterNum + hasFamilyNum) > (coursePeopleNumber + course.getCourseReservedNumber()); - } - } - - @Override - public boolean isSignCourse(String courseId, String activityId) { - TrainSignUpCourse course = dao().fetch(TrainSignUpCourse.class, courseId); - TrainSignUpActivity activity = dao().fetch(TrainSignUpActivity.class, activityId); - //培训班类型 - String courseType = course.getCourseType(); - - Sql sql = Sqls.create(""" - SELECT - count( tsus.id ) - FROM - `train_sign_up_user` tsus - LEFT JOIN train_sign_up_course tsuc ON tsuc.id = tsus.courseId - WHERE - tsuc.courseType = @courseType - AND tsus.userId = @userId - AND tsus.activityId = @activityId - """); - sql.setParam("courseType", courseType); - sql.setParam("activityId", activityId); - sql.setParam("userId", SecurityUtil.getUserId()); - int hasRegisterNum = count(sql); - - //第一种无限制报名 - if (activity.getRestrictLimit() == null || activity.getRestrictLimit() == 1) { - return true; - } else if (activity.getRestrictLimit() == 2) { - TrainSignUpTypeLimit trainSignUpTypeLimit = dao().fetch(TrainSignUpTypeLimit.class, Cnd.where("typeId", "=", courseType).and("activityId", "=", activityId)); - if(trainSignUpTypeLimit == null) { - return true; - } - //此类型的班最多可报几项 - int personMaxRegisterNum = trainSignUpTypeLimit.getLimitNum(); - if (personMaxRegisterNum == 0) { - return true; - } - return hasRegisterNum < personMaxRegisterNum; - } else if (activity.getRestrictLimit() == 3) { - //第三种,限制报几个,不跟类型挂钩 - int aCount = dao().count(TrainSignUpUser.class, Cnd.where("activityId", "=", activityId).and("userId", "=", SecurityUtil.getUserId())); - return aCount < activity.getLimitNum(); - } - - return false; - } - - @Override - public boolean isSignCourseByUser(String courseId, String userId) { - int count = dao().count(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId).and("userId", "=", userId)); - return dao().count(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId).and("userId", "=", userId)) > 0; - } - - @Override - public void doQd(String id) { - NutMap updateMap = NutMap.NEW(); - updateMap.put("isAttend", true); - updateMap.put("attendTime", new Date()); - dao().update(TrainSignUpUserCourse.class, Chain.from(updateMap), Cnd.where("id", "=", id)); - } - - @Override - public List qdInfoByUserId(String userId, String activityId) { - Sql sql = Sqls.create(""" - SELECT - c.*, - t.courseLocationCoordinates, - t.isMobileSign, - t.signType, - t.isReceiveGift, - t.giftType, - (select state from train_sign_up_user su where su.activityId = c.activityId and su.courseId = c.courseId and su.userId = c.userId) as state - FROM - `train_sign_up_user_course` c - LEFT JOIN train_sign_up_course t ON t.id = c.courseId - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.and("c.activityId", "=", activityId); - cnd.and("c.userId", "=", userId); - cnd.asc("c.courseStartTime"); - - sql.setCondition(cnd); - return listMap(sql); - } + sql.setCondition(cnd); + return listMap(sql); + } + @Override + public List filterCourseByHostUnion(List courseList) { + if (Lang.isEmpty(courseList)) { + return new ArrayList<>(); + } + return courseList.stream().filter(o -> { + if (StrUtil.isBlank(o.getInterTime()) || o.getOpenOtherUnion() == null || o.getOpenOtherUnion()) { + return true; + } else { + if (SecurityUtil.getUnionId().equals(o.getHostUnionId())) { + return true; + } else { + int compare = cn.hutool.core.date.DateUtil.compare(cn.hutool.core.date.DateUtil.date(), cn.hutool.core.date.DateUtil.parse(o.getInterTime()), "yyyy-MM-dd HH:mm"); + return compare >= 0; + } + } + }).toList(); + } } diff --git a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityStatisticsServiceImpl.java index 3982452b..628bbbf6 100644 --- a/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityStatisticsServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/activity/trainSignUp/service/impl/TrainSignUpActivityStatisticsServiceImpl.java @@ -4,6 +4,11 @@ import cn.hutool.core.util.StrUtil; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.activity.family.models.FamilyType; +import com.budwk.app.zhgh.activity.family.models.FamilyUser; +import com.budwk.app.zhgh.activity.trainSignUp.models.TrainMobileSignColumn; +import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpCourse; +import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpType; import com.budwk.app.zhgh.activity.trainSignUp.models.TrainSignUpUser; import com.budwk.app.zhgh.activity.trainSignUp.service.TrainSignUpActivityStatisticsService; import lombok.extern.slf4j.Slf4j; @@ -13,12 +18,14 @@ import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; import org.nutz.dao.util.cri.SqlExpressionGroup; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; /** @@ -42,15 +49,16 @@ public class TrainSignUpActivityStatisticsServiceImpl extends BaseServiceImpl courseList = pagination.getList(); + courseList.forEach(c -> { + c.put("registerNum", queryCourseCount(c.getString("id"), c.getString("cType"))); + c.put("hasWaitingNum", queryCourseWaitCount(c.getString("id"), c.getString("cType"))); + }); + return pagination; } @Override @@ -68,13 +82,15 @@ public class TrainSignUpActivityStatisticsServiceImpl extends BaseServiceImpl getTaleColumnInfo(String courseId) { + TrainSignUpCourse course = dao().fetch(TrainSignUpCourse.class, courseId); + TrainSignUpType upType = dao().fetch(TrainSignUpType.class, course.getCourseType()); + dao().fetchLinks(upType, "trainMobileSignColumnList", Cnd.NEW().asc("columnIndex")); + + List columnList = upType.getTrainMobileSignColumnList(); + List columnTableList = columnList.stream().map(o -> NutMap.NEW().setv("label", o.getColumnName()).setv("prop", o.getColumnCode())).collect(Collectors.toList()); + return columnTableList; + } + @Override public List registerUserList(String courseId, String unionId, String unitId, String searchName, String searchKeyword) { Sql sql = Sqls.create(""" @@ -178,4 +205,47 @@ public class TrainSignUpActivityStatisticsServiceImpl extends BaseServiceImpl stateList) { + if(StrUtil.isBlank(courseId) || StrUtil.isBlank(courseType)) { + return 0; + } + TrainSignUpType type = dao().fetch(TrainSignUpType.class, courseType); + AtomicInteger hasRegisterNum = new AtomicInteger(); + List signUpUsers = dao().query(TrainSignUpUser.class, Cnd.where("courseId", "=", courseId) + .and("state", "in", stateList) + .andEX("unionId", "=", unionId)); + signUpUsers.forEach(item -> { + if (type.getSelfAddFamily()) { + hasRegisterNum.getAndIncrement(); + } + if(type.getIsBringFamily() && type.getIsAddFamily()) { + List mobileColumnsValue = item.getMobileColumnsValue(); + NutMap map = mobileColumnsValue.stream().filter(o -> "xdqsrs".equals(o.getString("columnCode"))).findAny().orElse(null); + int number = map != null ? map.getInt("columnValue") : 0; + hasRegisterNum.addAndGet(number); + } + }); + return hasRegisterNum.get(); + } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingAccountController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingAccountController.java new file mode 100644 index 00000000..c4578d57 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingAccountController.java @@ -0,0 +1,50 @@ +package com.budwk.app.zhgh.dayofficework.clothing.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.dayofficework.clothing.service.ClothingService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * @ClassName ClothingAccountController + * @Author JyuHsin + * @Date 2025/7/23 8:46 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "服装登记台账") +@At("/platform/clothing/account") +public class ClothingAccountController { + + @Inject + private ClothingService clothingService; + + @At("") + @SaCheckPermission("clothing.account") + @Ok("beetl:/platform/zhgh/dayofficework/clothing/account/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("clothing.account") + public Result pageData(PageForm pageForm, + @Param(value = "year") String year, + @Param(value = "projectId") String projectId, + @Param(value = "unionId") String unionId) { + Pagination pagination = clothingService.pageData(pageForm, projectId, year, unionId); + return Result.success(pagination); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingApplyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingApplyController.java new file mode 100644 index 00000000..478e51ed --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingApplyController.java @@ -0,0 +1,77 @@ +package com.budwk.app.zhgh.dayofficework.clothing.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.activity.basic.models.ActivityBasicSettings; +import com.budwk.app.zhgh.dayofficework.clothing.service.ClothingService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName ClothingApplyController + * @Author JyuHsin + * @Date 2025/7/23 8:46 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "服装登记") +@At("/platform/clothing/apply") +public class ClothingApplyController { + + @Inject + private ClothingService clothingService; + + @At("") + @SaCheckPermission("clothing.apply") + @Ok("beetl:/platform/zhgh/dayofficework/clothing/apply/index.html") + public void index() { + } + + @At + @ApiOperation("获取人员") + @SaCheckPermission("clothing.apply") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "projectId") String projectId, + @Param(value = "isBuy") Boolean isBuy, + @Param(value = "sex") String sex, + @Param(value = "unionId") String unionId) { + Pagination pagination = clothingService.getRegisterUser(pageForm, year, projectId, isBuy, sex, unionId); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改服装登记") + @SaCheckPermission("clothing.apply") + @SLog(type = "clothing", tag = "新增/修改服装登记", msg = "新增/修改服装登记") + public Object doHandler(String[] ids, String projectId, Integer year, Boolean isBuy) { + if(!isBuy) { + clothingService.add(ids, projectId); + } else { + clothingService.removeBuyUser(ids, projectId, year); + } + return Result.success(); + } + + @At + @ApiOperation("获取服装项目") + @SaCheckPermission("clothing.apply") + public Result getBuyClothesProject() { + List list = clothingService.getBuyClothesProject(); + return Result.success(list); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingRecordController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingRecordController.java new file mode 100644 index 00000000..69a06022 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/controller/ClothingRecordController.java @@ -0,0 +1,152 @@ +package com.budwk.app.zhgh.dayofficework.clothing.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.base.utils.DateUtil; +import com.budwk.app.base.utils.SysOfficeTemplateUtil; +import com.budwk.app.zhgh.dayofficework.clothing.service.ClothingService; +import com.deepoove.poi.XWPFTemplate; +import com.deepoove.poi.config.Configure; +import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; + +/** + * @ClassName ClothingRecordController + * @Author JyuHsin + * @Date 2025/7/23 8:46 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "服装登记记录") +@At("/platform/clothing/record") +public class ClothingRecordController { + + @Inject + private ClothingService clothingService; + @Inject + private SysOfficeTemplateUtil officeTemplateUtil; + + @At("") + @SaCheckPermission("clothing.record") + @Ok("beetl:/platform/zhgh/dayofficework/clothing/record/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("clothing.record") + public Result pageData(PageForm pageForm, + @Param(value = "year") String year, + @Param(value = "projectId") String projectId, + @Param(value = "unionId") String unionId) { + Pagination pagination = clothingService.pageData(pageForm, projectId, year, unionId); + return Result.success(pagination); + } + + @At + @ApiOperation("根据项目删除") + @SaCheckPermission("clothing.record") + @SLog(type = "clothing", tag = "根据项目删除", msg = "根据项目删除") + public Result doDelete(String projectId, String year, String userId) { + if(StrUtil.isBlank(projectId)) { + Result.error("项目不能为空"); + } + if(StrUtil.isBlank(year)) { + Result.error("年份不能为空"); + } + if(StrUtil.isBlank(userId)) { + Result.error("登记人不能为空"); + } + boolean result = clothingService.doDelete(projectId, year, userId); + return result ? Result.success(): Result.error(); + } + + @At + @ApiOperation("查询人员") + @SaCheckPermission("clothing.record") + public Result findBuyClothesUser(String projectId, String userId, String year) { + if(StrUtil.isBlank(projectId)) { + return Result.error("项目不能为空"); + } + List buyClothesUsers = clothingService.findBuyClothesUser(projectId, userId, year); + return Result.success(buyClothesUsers); + } + + @At + @ApiOperation("删除单个人员") + @SaCheckPermission("clothing.record") + @SLog(type = "clothing", tag = "删除单个人员", msg = "删除单个人员") + public Result deleteBuyUser(String id) { + if(StrUtil.isBlank(id)) { + Result.error("项目不能为空"); + } + boolean result = clothingService.deleteBuyUser(id); + return result ? Result.success(): Result.error(); + } + + @At + @Ok("void") + @SaCheckPermission("clothing.record") + public void doExport(String year, + String projectId, + String userId, + HttpServletResponse response) throws IOException { + NutMap clothes = NutMap.NEW(); + clothes.put("ctime", DateUtil.getDate()); + + Sql sql = Sqls.create(""" + SELECT + c.*, + u.sex, + u.mobile, + '服装' as things + FROM + clothing_register c + LEFT JOIN `vw_user` u ON u.id = c.buyUserId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("year(c.ctime)", "=", year); + cnd.and("c.projectId", "=", projectId); + cnd.and("c.userId", "=", userId); + sql.setCondition(cnd); + List buyUserList = clothingService.listMap(sql); + for (int i = 0; i < buyUserList.size(); i++) { + buyUserList.get(i).put("index", i + 1); + } + + LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); + Configure config = Configure.builder().bind("buys", policy).build(); + clothes.put("buys", buyUserList); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + XWPFTemplate template = XWPFTemplate.compile(officeTemplateUtil.getTemplate("clothes"), config); + template.render(clothes).writeAndClose(os); + CommonDownloadUtil.download("服装登记表.docx", os.toByteArray(), response); + } +} + diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/model/ClothingRegister.java b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/model/ClothingRegister.java new file mode 100644 index 00000000..d0d65cdf --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/model/ClothingRegister.java @@ -0,0 +1,109 @@ +package com.budwk.app.zhgh.dayofficework.clothing.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName ClothingRegister + * @Author JyuHsin + * @Date 2025/7/22 18:51 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("服装登记") +@Accessors(chain = true) +@Table("clothing_register") +@EqualsAndHashCode(callSuper = true) +public class ClothingRegister extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("项目id") + private String projectId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("登记人") + private String userId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("登记人姓名") + private String userName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("登记人工号") + private String loginName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("登记人工会ID") + private String unionId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("登记人单位ID") + private String unitId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("登记人工会") + private String unionName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("登记人单位") + private String unitName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("登记时间") + private String ctime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("登记需要购买服装的用户") + private String buyUserId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("登记需要购买服装的姓名") + private String buyUserName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("登记需要购买服装的工号") + private String buyUserLoginName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("购买服装的用户工会ID") + private String buyUserUnionId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("购买服装的用户单位ID") + private String buyUserUnitId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("购买服装的用户工会") + private String buyUserUnionName; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("购买服装的用户单位") + private String buyUserUnitName; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/service/ClothingService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/service/ClothingService.java new file mode 100644 index 00000000..fe69a83a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/service/ClothingService.java @@ -0,0 +1,78 @@ +package com.budwk.app.zhgh.dayofficework.clothing.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.activity.basic.models.ActivityBasicSettings; +import com.budwk.app.zhgh.dayofficework.clothing.model.ClothingRegister; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +/** + * @ClassName ClothingService + * @Author JyuHsin + * @Date 2025/7/22 18:51 + * @Version 1.0 + * @Description TODO + */ +public interface ClothingService extends BaseService { + + /** + * 列表查询 + * + * @param pageForm: 表单 + * @param projectId: 项目id + * @param year: 年份 + * @return io.v.nutz.base.page.Pagination + * @author JyuHsin + * @date 2022/12/5 + */ + Pagination pageData(PageForm pageForm, String projectId, String year, String unionId); + + /** + * 获取所有买服装的项目 + * @author JyuHsin + * @date 2022/12/5 + * @return java.util.List + */ + List getBuyClothesProject(); + + /** + * 获取项目人员名单 + * @author JyuHsin + * @date 2022/12/5 + * @param projectId: 项目id + * @return java.util.List + */ + List findBuyClothesUser(String projectId, String userId, String year); + + /** + * 删除 + * @author JyuHsin + * @date 2022/12/5 + * @param projectId: 项目id + * @param year: 年份 + * @param userId: 登记人 + * @return void + */ + boolean doDelete(String projectId, String year, String userId); + + /** + * 服装登记菜单查询用户 + * @author JyuHsin + * @date 2022/12/5 + * @param pageForm: + * @param year: + * @param projectId: + * @param isBuy: + * @return cn.wizzer.framework.page.Pagination + */ + Pagination getRegisterUser(PageForm pageForm, Integer year, String projectId, Boolean isBuy, String sex, String unionId); + + Object add(String[] ids, String projectId); + + boolean removeBuyUser(String[] ids, String projectId, Integer year); + + boolean deleteBuyUser(String id); +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/service/impl/ClothingServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/service/impl/ClothingServiceImpl.java new file mode 100644 index 00000000..2d6f3b16 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/clothing/service/impl/ClothingServiceImpl.java @@ -0,0 +1,181 @@ +package com.budwk.app.zhgh.dayofficework.clothing.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.DateUtil; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.basic.models.ActivityBasicSettings; +import com.budwk.app.zhgh.dayofficework.clothing.model.ClothingRegister; +import com.budwk.app.zhgh.dayofficework.clothing.service.ClothingService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.trans.Trans; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName ClothingServiceImpl + * @Author JyuHsin + * @Date 2025/7/22 18:55 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class ClothingServiceImpl extends BaseServiceImpl implements ClothingService { + + public ClothingServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Pagination pageData(PageForm pageForm, String projectId, String year, String unionId) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + c.*, + YEAR ( c.ctime ) AS `year`, + a.name AS projectName, + count(c.buyUserId) AS buyCount + FROM + clothing_register c + LEFT JOIN activity_basic_settings a ON a.CODE = c.projectId + $condition + """); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + if(AuthUtil.hasRole(RoleConstant.BRANCH_UNION_CHAIRMAN.name())) { + cnd.and("c.unionid", "=", SecurityUtil.getUnionId()); + } + } + cnd.andEX("c.unionId", "=", unionId); + cnd.andEX("c.projectId", "=", projectId); + cnd.andEX("year(c.ctime)", "=", year); + cnd.groupBy("c.userId"); + cnd.desc("year").asc("projectId"); + sql.setCondition(cnd); + + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + @Override + public List getBuyClothesProject() { + return dao().query(ActivityBasicSettings.class, Cnd.where(ActivityBasicSettings::getClothing, "=", true)); + } + + @Override + public List findBuyClothesUser(String projectId, String userId, String year) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + c.*, + u.sex, + u.mobile + FROM + clothing_register c + LEFT JOIN `vw_user` u ON u.id = c.buyUserId + $condition + """); + cnd.andEX("c.projectId", "=", projectId); + cnd.andEX("c.userId", "=", userId); + cnd.andEX("year(c.ctime)", "=", year); + sql.setCondition(cnd); + return listMap(sql); + } + + @Override + public boolean doDelete(String projectId, String year, String userId) { + int clearCount = dao().clear(ClothingRegister.class, Cnd.where("projectId", "=", projectId) + .and("year(ctime)", "=", year).and("userId", "=", userId)); + return clearCount >= 0; + } + + @Override + public Pagination getRegisterUser(PageForm pageForm, Integer year, String projectId, Boolean isBuy, String sex, String unionId) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + select + id, + loginname as loginName, + username as userName, + unitname as unitName, + unionname as unionName, + sex, + mobile + from + `vw_user` u + $condition + """); + cnd.and("u.member", "=", true); + cnd.andEX("u.unionId", "=", StrUtil.isNotBlank(unionId) ? unionId : ""); + cnd.andEX("u.sex", "=", sex); + if (Strings.isNotBlank(pageForm.getSearchKeyword())) { + cnd.and(Cnd.exps("loginname", "like", "%" + pageForm.getSearchKeyword() + "%").or("username", "like", "%" + pageForm.getSearchKeyword() + "%")); + } + if(year != null) { + int lastYear = year - 1; + cnd.and(new Static("id %s (select buyUserId from clothing_register where projectId = '%s' and (year(ctime) = '%s' or year(ctime) = '%s'))" + .formatted(isBuy ? "in" : "not in", projectId, year, lastYear))); + } + cnd.asc("unitId"); + sql.setCondition(cnd); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + @Override + public Object add(String[] ids, String projectId) { + List clothingRegisterList = new ArrayList<>(); + + View_user loginUser = dao().fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId())); + for (String id : ids) { + View_user user = dao().fetch(View_user.class, Cnd.where(View_user::getId, "=", id)); + + ClothingRegister clothingRegister = new ClothingRegister(); + clothingRegister.setProjectId(projectId); + clothingRegister.setUserId(loginUser.getId()); + clothingRegister.setUserName(loginUser.getUsername()); + clothingRegister.setLoginName(loginUser.getLoginname()); + clothingRegister.setUnitId(loginUser.getUnitId()); + clothingRegister.setUnitName(loginUser.getUnitName()); + clothingRegister.setUnionId(loginUser.getUnionId()); + clothingRegister.setUnionName(loginUser.getUnionName()); + clothingRegister.setCtime(DateUtil.getDateTime()); + clothingRegister.setBuyUserId(id); + clothingRegister.setBuyUserName(user.getUsername()); + clothingRegister.setBuyUserLoginName(user.getLoginname()); + clothingRegister.setBuyUserUnitId(user.getUnitId()); + clothingRegister.setBuyUserUnitName(user.getUnitName()); + clothingRegister.setBuyUserUnionId(user.getUnionId()); + clothingRegister.setBuyUserUnionName(user.getUnionName()); + clothingRegisterList.add(clothingRegister); + } + return dao().insert(clothingRegisterList); + } + + @Override + public boolean removeBuyUser(String[] ids, String projectId, Integer year) { + Trans.exec(() -> { + dao().clear(ClothingRegister.class, Cnd.where("projectId", "=", projectId) + .and("year(ctime)", "=", year).and("buyUserId", "in", ids)); + }); + return true; + } + + @Override + public boolean deleteBuyUser(String id) { + int clearCount = dao().clear(ClothingRegister.class, Cnd.where("id", "=", id)); + return clearCount >= 0; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/controller/CondolenceApplyController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/controller/CondolenceApplyController.java new file mode 100644 index 00000000..e299462a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/controller/CondolenceApplyController.java @@ -0,0 +1,29 @@ +package com.budwk.app.zhgh.dayofficework.condolence.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.annotations.Api; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName CondolenceApplyController + * @Author JyuHsin + * @Date 2025/7/28 11:06 + * @Version 1.0 + * @Description TODO + */ +@IocBean +@At("/platform/condolence/apply") +@Api("新闻投稿统计分析") +@Ok("json:full") +public class CondolenceApplyController { + + @At("/form") + @Ok("beetl:/platform/zhgh/dayofficework/condolence/apply/index.html") + @SaCheckLogin + public void index() {} + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/controller/CondolenceUnionAuditController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/controller/CondolenceUnionAuditController.java new file mode 100644 index 00000000..bbf4d67d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/controller/CondolenceUnionAuditController.java @@ -0,0 +1,26 @@ +package com.budwk.app.zhgh.dayofficework.condolence.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import io.swagger.annotations.Api; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName CondolenceUnionAuditController + * @Author JyuHsin + * @Date 2025/7/28 11:33 + * @Version 1.0 + * @Description TODO + */ +@IocBean +@At("/platform/condolence/unionAudit") +@Api("新闻投稿统计分析") +@Ok("json:full") +public class CondolenceUnionAuditController { + + @At("/form") + @Ok("beetl:/platform/zhgh/dayofficework/condolence/unionAudit/index.html") + @SaCheckLogin + public void index() {} +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/interceptor/CondolenceSaveInterceptor.java b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/interceptor/CondolenceSaveInterceptor.java new file mode 100644 index 00000000..f2db21a2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/interceptor/CondolenceSaveInterceptor.java @@ -0,0 +1,40 @@ +package com.budwk.app.zhgh.dayofficework.condolence.interceptor; + +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.zhgh.dayofficework.article.models.Article; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.Json; + +/** + * @ClassName CondolenceSaveInterceptor + * @Author JyuHsin + * @Date 2025/7/28 11:01 + * @Version 1.0 + * @Description TODO + */ +public class CondolenceSaveInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + System.out.println(".................."); + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + Article article = Json.fromJson(Article.class, formDataStr); + + Dao dao = ServiceContext.find(Dao.class); + dao.insertOrUpdate(article); + + // 设置流程变量 + execution.getArgs().set("origin", article.getOrigin()); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", article.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId)); + + System.out.println(execution); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/model/Condolence.java b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/model/Condolence.java new file mode 100644 index 00000000..d09bc97a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/condolence/model/Condolence.java @@ -0,0 +1,83 @@ +package com.budwk.app.zhgh.dayofficework.condolence.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; +import org.nutz.dao.interceptor.annotation.PrevUpdate; + +import java.util.Date; +import java.util.List; + +/** + * @ClassName Condolence + * @Author JyuHsin + * @Date 2025/7/28 11:03 + * @Version 1.0 + * @Description TODO + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("condolence") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("职工慰问") +public class Condolence extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("说明") + @ColDefine(type = ColType.VARCHAR,width = 500) + private String excerpt; + + @Column + @Comment("稿件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; + + @Column + @Comment("投稿人ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("投稿人姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String userName; + + @Column + @Comment("投稿人工号") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String loginName; + + @Column + @Comment("投稿人分工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("投稿人分工会") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unionName; + + @Column + @Comment("投稿人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("投稿人单位") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unitName; + + @Column + @Comment("类型") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String origin; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionDetailedController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionDetailedController.java new file mode 100644 index 00000000..c926a975 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionDetailedController.java @@ -0,0 +1,104 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.controller; + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionApply; +import com.budwk.app.zhgh.staffbenefit.contribution.service.ContributionApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.usermodel.Workbook; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName ContributionDetailedController + * @Author JyuHsin + * @Date 2025/7/24 14:58 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "慈善捐款明细") +@At("/platform/contribution/detailed") +public class ContributionDetailedController { + + @Inject + private Dao dao; + @Inject + private ContributionApplyService applyService; + + @At("") + @SaCheckPermission("contribution.detailed") + @Ok("beetl:/platform/zhgh/staffbenefit/contribution/detailed/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("contribution.detailed") + public Result pageData(PageForm pageForm, + @Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId, + @Param(value = "payMode") String payMode, + @Param(value = "contributionName") String contributionName) { + Sql sql = applyService.generateSql(unionId, unitId, payMode, contributionName); + Pagination pagination = applyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @Ok("void") + @SaCheckPermission("contribution.detailed") + public void doExport(@Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId, + @Param(value = "payMode") String payMode, + @Param(value = "contributionName") String contributionName, + HttpServletResponse response) throws IOException { + Sql sql = applyService.generateSql(unionId, unitId, payMode, contributionName); + List listMap = applyService.listMap(sql); + for (int i = 0; i < listMap.size(); i++) { + listMap.get(i).put("index", i + 1); + } + + List entityList = new ArrayList<>(); + entityList.add(new ExcelExportEntity("序号", "index", 10)); + entityList.add(new ExcelExportEntity("捐款项目", "contributionName", 20)); + entityList.add(new ExcelExportEntity("捐款人工号", "loginName", 20)); + entityList.add(new ExcelExportEntity("捐款人姓名", "userName", 20)); + entityList.add(new ExcelExportEntity("联系方式", "mobile", 20)); + entityList.add(new ExcelExportEntity("所属工会", "unionName", 20)); + entityList.add(new ExcelExportEntity("所属单位", "unitName", 20)); + entityList.add(new ExcelExportEntity("善款金额", "money", 20)); + entityList.add(new ExcelExportEntity("捐赠方式", "payModeName", 20)); + entityList.add(new ExcelExportEntity("捐赠时间", "contributionTime", 20)); + + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, listMap); + CommonDownloadUtil.download("捐款明细.xlsx", workbook, response); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionProjectController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionProjectController.java new file mode 100644 index 00000000..1c4bbb63 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionProjectController.java @@ -0,0 +1,110 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionProject; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionType; +import com.budwk.app.zhgh.staffbenefit.contribution.service.ContributionTypeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName ContributionProjectController + * @Author JyuHsin + * @Date 2025/7/24 10:51 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "慈善捐款项目") +@At("/platform/contribution/list") +public class ContributionProjectController { + + @Inject + private Dao dao; + @Inject + private ContributionTypeService typeService; + + @At("") + @SaCheckPermission("contribution.list") + @Ok("beetl:/platform/zhgh/staffbenefit/contribution/list/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("contribution.list") + public Result pageData(PageForm pageForm, + @Param("contributionName") String contributionName) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + con.*, + type.typeName + FROM + `contribution_project` con + LEFT JOIN contribution_type type ON type.typeCode = con.contributionTypeCode + $condition + """); + if (Strings.isNotBlank(contributionName)) { + cnd.where().andLike("con.contributionName", contributionName); + } + cnd.asc("con.contributionTypeCode"); + sql.setCondition(cnd); + Pagination pagination = typeService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改慈善捐款项目") + @SaCheckPermission("contribution.list") + @SLog(type = "contribution", tag = "新增/修改慈善捐款项目", msg = "新增/修改慈善捐款项目") + public Object onSubmit(ContributionProject project) { + if(StrUtil.isBlank(project.getId())) { + project.setContributionCreationDate(DateUtil.now()); + } + typeService.dao().insertOrUpdate(project); + return Result.success(); + } + + @At + @ApiOperation("删除慈善捐款项目") + @SaCheckPermission("contribution.list") + @SLog(type = "contribution", tag = "删除慈善捐款项目", msg = "删除慈善捐款项目") + public Object onDelete(String id) { + typeService.dao().delete(ContributionProject.class, id); + return Result.success(); + } + + @At + @ApiOperation("查询慈善捐款项目") + @SaCheckPermission("contribution.list") + public Result queryContributionList() { + List list = typeService.dao().query( + ContributionProject.class, + Cnd.where(ContributionProject::getIsContributionEnable, "=", true) + .desc(ContributionProject::getContributionCreationDate) + ); + return Result.success(list); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionStatisticsController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionStatisticsController.java new file mode 100644 index 00000000..bd9ff960 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionStatisticsController.java @@ -0,0 +1,89 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionApply; +import com.budwk.app.zhgh.staffbenefit.contribution.service.ContributionApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.TreeSet; +import java.util.stream.Collectors; + +/** + * @ClassName ContributionStatisticsController + * @Author JyuHsin + * @Date 2025/7/24 15:42 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "慈善捐款分工会统计") +@At("/platform/contribution/statistics") +public class ContributionStatisticsController { + + @Inject + private Dao dao; + @Inject + private ContributionApplyService applyService; + + @At("") + @SaCheckPermission("contribution.statistics") + @Ok("beetl:/platform/zhgh/staffbenefit/contribution/statistics/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("contribution.statistics") + public Result pageData(@Param(value = "unionId") String unionId, + @Param(value = "contributionId") String contributionId) { + List unionList = dao.query(Sys_union.class, Cnd.NEW().andEX("id", "=", unionId).asc(Sys_union::getUnionCode)); + List applyList = applyService.query(Cnd.NEW().andEX(ContributionApply::getContributionId, "=", contributionId)); + + List resultList = new ArrayList<>(); + for (Sys_union union : unionList) { + NutMap map = Lang.obj2nutmap(union); + //找这个项目的人,去重 + List userList = applyList.stream() + .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ContributionApply::getUserId)))) + .stream() + .toList(); + + //这个项目每个分工会有多少个人捐款 + List list = userList.stream() + .filter(n -> n.getUnionId().equals(union.getId()) && n.getContributionId().equals(contributionId)) + .toList(); + map.setv("contributionUserNum", list.size()); + + //捐款多少笔 + long conCount = applyList.stream() + .filter(n -> n.getUnionId().equals(union.getId()) && n.getContributionId().equals(contributionId)) + .count(); + map.setv("contributionNum", conCount); + + //一共捐了多少钱 + double money = list.stream().mapToDouble(ContributionApply::getMoney).sum(); + map.setv("money", money); + + resultList.add(map); + } + return Result.success(resultList); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionTypeController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionTypeController.java new file mode 100644 index 00000000..3525daf6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/controller/ContributionTypeController.java @@ -0,0 +1,90 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionType; +import com.budwk.app.zhgh.staffbenefit.contribution.service.ContributionTypeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @ClassName contributionTypeController + * @Author JyuHsin + * @Date 2025/7/24 10:06 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "慈善捐款专题") +@At("/platform/contribution/type") +public class ContributionTypeController { + + @Inject + private Dao dao; + @Inject + private ContributionTypeService typeService; + + @At("") + @SaCheckPermission("contribution.type") + @Ok("beetl:/platform/zhgh/staffbenefit/contribution/type/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("contribution.type") + public Result pageData(PageForm pageForm) { + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(ContributionType::getTypeName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(ContributionType::getTypeCode, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + cnd.asc("typeCode"); + Pagination pagination = typeService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改慈善捐款专题") + @SaCheckPermission("contribution.type") + @SLog(type = "contribution", tag = "新增/修改慈善捐款专题", msg = "新增/修改慈善捐款专题") + public Object onSubmit(ContributionType type) { + typeService.insertOrUpdate(type); + return Result.success(); + } + + @At + @ApiOperation("删除慈善捐款专题") + @SaCheckPermission("contribution.type") + @SLog(type = "contribution", tag = "删除慈善捐款专题", msg = "删除慈善捐款专题") + public Object onDelete(String id) { + typeService.delete(id); + return Result.success(); + } + + @At + @ApiOperation("查询慈善捐款专题") + @SaCheckPermission("contribution.type") + public Result queryContributionType() { + List list = typeService.query(Cnd.NEW().desc(ContributionType::getTypeCode)); + return Result.success(list); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionApply.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionApply.java new file mode 100644 index 00000000..7ab75dd8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionApply.java @@ -0,0 +1,103 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.models.Sys_file; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.List; + +/** + * @ClassName ContributionApply + * @Author JyuHsin + * @Date 2025/7/24 10:03 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("慈善捐款明细") +@Accessors(chain = true) +@Table("contribution_apply") +@EqualsAndHashCode(callSuper = true) +public class ContributionApply extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("项目Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String contributionId; + + @Column + @Comment("项目") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String contributionName; + + @Column + @Comment("支付人Id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("支付人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("支付人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("支付人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("支付人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("支付人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("支付人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @Comment("捐款金额") + @ColDefine(type = ColType.DOUBLE) + private double money; + + @Column + @Comment("支付方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String payMode; + + @Column + @Comment("捐款时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String contributionTime; + + @Column + @Comment("捐款图片") + @ColDefine(type = ColType.MYSQL_JSON) + private List contributionFiles; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionProject.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionProject.java new file mode 100644 index 00000000..1081bd95 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionProject.java @@ -0,0 +1,82 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.List; + +/** + * @ClassName Contribution + * @Author JyuHsin + * @Date 2025/7/24 9:59 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("慈善捐款") +@Accessors(chain = true) +@Table("contribution_project") +@EqualsAndHashCode(callSuper = true) +public class ContributionProject extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("项目名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String contributionName; + + @Column + @Comment("项目介绍") + @ColDefine(type = ColType.TEXT) + private String contributionIntroduce; + + @Column + @Comment("所属捐款专题") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String contributionTypeCode; + + @Column + @Comment("项目图片") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String contributionFiles; + + @Column + @Comment("创建时间") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String contributionCreationDate; + + @Column + @Comment("是否启用") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isContributionEnable; + + @Column + @Comment("捐款模式") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String contributionMode; + + @Column + @Comment("捐款链接") + @ColDefine(type = ColType.TEXT) + private String contributionUrl; + + @Column + @Comment("捐款开启时间") + @ColDefine(type = ColType.VARCHAR, width = 40) + private String contributionStartTime; + + @Column + @Comment("捐款结束时间") + @ColDefine(type = ColType.VARCHAR, width = 40) + private String contributionEndTime; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionType.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionType.java new file mode 100644 index 00000000..6451d603 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/model/ContributionType.java @@ -0,0 +1,53 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.models.Sys_file; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.List; + +/** + * @ClassName ContributionType + * @Author JyuHsin + * @Date 2025/7/24 10:01 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("慈善捐款专题") +@Accessors(chain = true) +@Table("contribution_type") +@EqualsAndHashCode(callSuper = true) +public class ContributionType extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("专题名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String typeName; + + @Column + @Comment("专题编号") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String typeCode; + + @Column + @Comment("专题介绍") + @ColDefine(type = ColType.TEXT) + private String contributionTypeIntroduce; + + @Column + @Comment("专题图片") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String contributionTypeFiles; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/ContributionApplyService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/ContributionApplyService.java new file mode 100644 index 00000000..2614ec60 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/ContributionApplyService.java @@ -0,0 +1,22 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionApply; +import org.nutz.dao.Cnd; +import org.nutz.dao.sql.Sql; + +/** + * @ClassName ContributionApplyService + * @Author JyuHsin + * @Date 2025/7/24 15:00 + * @Version 1.0 + * @Description TODO + */ +public interface ContributionApplyService extends BaseService { + + /** + * 生成查询捐款明细的sql + * @return + */ + Sql generateSql(String unionId, String unitId, String payMode, String contributionName); +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/ContributionTypeService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/ContributionTypeService.java new file mode 100644 index 00000000..e64f47ea --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/ContributionTypeService.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionType; + +/** + * @ClassName ContributionTypeService + * @Author JyuHsin + * @Date 2025/7/24 10:07 + * @Version 1.0 + * @Description TODO + */ +public interface ContributionTypeService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/impl/ContributionApplyServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/impl/ContributionApplyServiceImpl.java new file mode 100644 index 00000000..fb59bf71 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/impl/ContributionApplyServiceImpl.java @@ -0,0 +1,51 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionApply; +import com.budwk.app.zhgh.staffbenefit.contribution.service.ContributionApplyService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Strings; + +/** + * @ClassName ContributionApplyServiceImpl + * @Author JyuHsin + * @Date 2025/7/24 15:00 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class ContributionApplyServiceImpl extends BaseServiceImpl implements ContributionApplyService { + + public ContributionApplyServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Sql generateSql(String unionId, String unitId, String payMode, String contributionName) { + Sql sql = Sqls.create(""" + select + ca.*, + CASE WHEN ca.payMode = 'WeChat' THEN '微信' ELSE '支付宝' END AS payModeName + from + contribution_apply ca + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX(ContributionApply::getUnionId, "=", unionId); + cnd.andEX(ContributionApply::getUnitId, "=", unitId); + cnd.andEX(ContributionApply::getPayMode, "=", payMode); + if (Strings.isNotBlank(contributionName)) { + cnd.where().andLike(ContributionApply::getContributionName, contributionName); + } + cnd.desc(ContributionApply::getContributionTime); + cnd.asc(ContributionApply::getUnitId); + sql.setCondition(cnd); + return sql; + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/impl/ContributionTypeServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/impl/ContributionTypeServiceImpl.java new file mode 100644 index 00000000..9585407d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/contribution/service/impl/ContributionTypeServiceImpl.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.staffbenefit.contribution.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.contribution.model.ContributionType; +import com.budwk.app.zhgh.staffbenefit.contribution.service.ContributionTypeService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName ContributionTypeServiceImpl + * @Author JyuHsin + * @Date 2025/7/24 10:08 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class ContributionTypeServiceImpl extends BaseServiceImpl implements ContributionTypeService { + + public ContributionTypeServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalApplyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalApplyController.java new file mode 100644 index 00000000..1d74469f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalApplyController.java @@ -0,0 +1,71 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalApply; +import com.budwk.app.zhgh.staffbenefit.legal.service.LegalApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName LegalApplyController + * @Author JyuHsin + * @Date 2025/7/25 15:08 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助预约") +@At("/platform/legal/apply") +public class LegalApplyController { + + @Inject + private Dao dao; + @Inject + private LegalApplyService applyService; + + @At("") + @SaCheckPermission("legal.apply") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/apply/index.html") + public void index() { + } + + @At + @ApiOperation("新增/修改法律援助预约") + @SaCheckPermission("legal.apply") + @SLog(type = "legal", tag = "新增/修改法律援助预约", msg = "新增/修改法律援助预约") + public Object onSubmit(LegalApply apply) { + LegalApply legalApply = applyService.fetch(apply.getId()); + if(StrUtil.isNotBlank(legalApply.getUserId())) { + return Result.error("该时段已被预约"); + } + View_user user = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId())); + apply.setUserId(user.getId()); + apply.setLoginName(user.getLoginname()); + apply.setUserName(user.getUsername()); + apply.setUnitId(user.getUnitId()); + apply.setUnitName(user.getUnitName()); + apply.setUnionId(user.getUnionId()); + apply.setUnionName(user.getUnionName()); + /*apply.setMobile(apply.getMobile()); + apply.setRemark(apply.getRemark()); + apply.setAskTypeValue(apply.getAskTypeValue());*/ + applyService.updateIgnoreNull(apply); + + //TODO:这里后面要加发短信 + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalAppointmentSetController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalAppointmentSetController.java new file mode 100644 index 00000000..56385154 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalAppointmentSetController.java @@ -0,0 +1,162 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalApply; +import com.budwk.app.zhgh.staffbenefit.legal.service.LegalApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @ClassName LegalAppointmentSetController + * @Author JyuHsin + * @Date 2025/7/25 10:04 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助预约安排") +@At("/platform/legal/appointmentSet") +public class LegalAppointmentSetController { + + @Inject + private Dao dao; + @Inject + private LegalApplyService applyService; + + @At("") + @SaCheckPermission("legal.appointmentSet") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/appointmentSet/index.html") + public void index() { + } + + @At + @ApiOperation("查询时间段内的预约信息") + @SaCheckPermission("legal.appointmentSet") + public Result queryAppointmentInfo(Long startTimeTs, Long endTimeTs) { + Sql sql = Sqls.create(""" + SELECT + pa.*, + pa.userId as appointmentUser, + pa.userName AS appointmentUserName, + pa.loginName AS appointmentLoginName, + pa.unitName AS appointmentUnitName, + pa.mobile AS appointmentMobile, + pd.specialty AS doctorSpecialty, + pd.introduce AS doctorIntroduce, + pd.sex AS doctorSex, + pd.technicalTitle AS doctorJobTitle, + pd.unitName AS doctorUnitName, + pd.avatar AS doctorAvatar, + pd.mobile AS doctorMobile, + pd.userName AS doctorUserName + FROM + `legal_apply` pa + LEFT JOIN legal_doctor pd ON pd.userId = pa.doctorUser + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("startTimeTs", ">=", startTimeTs); + cnd.and("endTimeTs", "<=", endTimeTs); + sql.setCondition(cnd); + List listMap = applyService.listMap(sql); + return Result.success(listMap); + } + + @At + @ApiOperation("新增/修改法律援助安排") + @SaCheckPermission("legal.appointmentSet") + @SLog(type = "legal", tag = "新增/修改法律援助安排", msg = "新增/修改法律援助安排") + public Object onSubmit(LegalApply apply) { + long startTimeTs = com.budwk.app.base.utils.DateUtil.formatDate(apply.getStartTime()); + long endTimeTs = com.budwk.app.base.utils.DateUtil.formatDate(apply.getEndTime()); + List list = new ArrayList<>(); + for (long i = startTimeTs; i < endTimeTs; i = i + 3600000) { + LegalApply app = new LegalApply(); + LegalApply legalAppointmentInfo = Lang.copyProperties(apply, app); + String start = com.budwk.app.base.utils.DateUtil.getDate(i / 1000); + long e = i + 3600000; + if ((endTimeTs - e) <= 0) { + e = i + (endTimeTs - i); + } + String end = com.budwk.app.base.utils.DateUtil.getDate(e / 1000); + legalAppointmentInfo.setStartTimeTs(i); + legalAppointmentInfo.setEndTimeTs(e); + legalAppointmentInfo.setStartTime(start); + legalAppointmentInfo.setEndTime(end); + list.add(legalAppointmentInfo); + } + dao.insert(list); + return Result.success(); + } + + @At + @ApiOperation("修改法律援助安排") + @SaCheckPermission("legal.appointmentSet") + @SLog(type = "legal", tag = "修改法律援助安排", msg = "修改法律援助安排") + public Object onEdit(String id, String[] askType) { + LegalApply apply = applyService.fetch(id); + apply.setAskType(Lang.isNotEmpty(askType) ? Arrays.asList(askType) : new ArrayList<>()); + apply.setAskTypeValue(null); + applyService.update(apply); + //TODO:以后这里加个发短信 + return Result.success(); + } + + @At + @ApiOperation("删除法律援助安排") + @SaCheckPermission("legal.appointmentSet") + @SLog(type = "legal", tag = "删除法律援助安排", msg = "删除法律援助安排") + public Object onDelete(String id) { + applyService.delete(id); + //TODO:以后这里加个发短信 + return Result.success(); + } + + @At + @ApiOperation("查询咨询师") + @SaCheckPermission("legal.appointmentSet") + public Result queryDoctorUser(String keyWord, long startTimeTs, long endTimeTs) { + //先查询该时间段没时间的咨询师 + Sql doctorSql = Sqls.create(""" + SELECT + pd.userId AS id, + pd.userName AS doctorUserName, + replace(pd.mobile,' ','') as mobile + FROM + legal_doctor pd + WHERE + pd.userId NOT IN + ( + SELECT doctorUser FROM legal_apply + WHERE startTimeTs >= @startTimeTs AND endTimeTs <= @endTimeTs + AND doctorUser IS NOT NULL + ) + and (pd.userName like @keyWord or pd.loginName like @keyWord) + """); + doctorSql.setParam("startTimeTs", startTimeTs); + doctorSql.setParam("endTimeTs", endTimeTs); + doctorSql.setParam("keyWord", "%" + keyWord + "%"); + Pagination pagination = applyService.listPageMap(1, 10, doctorSql); + return Result.success(pagination.getList()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalDoctorController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalDoctorController.java new file mode 100644 index 00000000..2d267d92 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalDoctorController.java @@ -0,0 +1,140 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.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.sys.models.Sys_user_role; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalDoctor; +import com.budwk.app.zhgh.staffbenefit.legal.service.LegalDoctorService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @ClassName LegalDoctorController + * @Author JyuHsin + * @Date 2025/7/24 18:18 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助咨询师") +@At("/platform/legal/doctorManage") +public class LegalDoctorController { + + @Inject + private Dao dao; + @Inject + private LegalDoctorService doctorService; + + @At("") + @SaCheckPermission("legal.doctorManage") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/doctorManage/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("legal.doctorManage") + public Result pageData(PageForm pageForm) { + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(LegalDoctor::getLoginName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(LegalDoctor::getUserName, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + Pagination pagination = doctorService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + return Result.success(pagination); + } + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("新增/修改法律援助师") + @SaCheckPermission("legal.doctorManage") + @SLog(type = "legal", tag = "新增/修改法律援助师", msg = "新增/修改法律援助师") + public Object onSubmit(LegalDoctor doctor) { + if(StrUtil.isBlank(doctor.getId())) { + int count = doctorService.count(Cnd.where(LegalDoctor::getUserId, "=", doctor.getUserId())); + if(count > 0) { + return Result.error("此咨询师信息已录入"); + } + View_user user = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", doctor.getUserId())); + doctor.setLoginName(user.getLoginname()); + doctor.setUserName(user.getUsername()); + doctor.setUnitId(user.getUnitId()); + doctor.setUnitName(user.getUnitName()); + doctor.setUnionId(user.getUnionId()); + doctor.setUnionName(user.getUnionName()); + //插入角色 + Sys_user_role userRole = new Sys_user_role(); + userRole.setUserId(doctor.getUserId()); + userRole.setRoleId(RoleConstant.PSYCHOLOGY_DOCTOR.name()); + dao.insert(userRole); + } + doctorService.insertOrUpdate(doctor); + return Result.success(); + } + + @At + @ApiOperation("删除法律援助师") + @SaCheckPermission("legal.doctorManage") + @SLog(type = "legal", tag = "删除法律援助师", msg = "删除法律援助师") + public Object onDelete(String id) { + doctorService.delete(id); + return Result.success(); + } + + @At + @ApiOperation("查询用户") + @SaCheckPermission("legal.doctorManage") + @SLog(type = "legal", tag = "查询用户", msg = "查询用户") + public Object listUser(String keyword) { + Sql sql = Sqls.create(""" + select + id, + username as userName, + loginname as loginName, + sex, + mobile, + technicalTitle, + unitname as unitName + from + vw_user + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(keyword)) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(View_user::getLoginname, "like", "%" + keyword + "%"); + seg.or(View_user::getUsername, "like", "%" + keyword + "%"); + cnd.and(seg); + } + List list = doctorService.query(Cnd.NEW()); + List idList = list.stream().map(LegalDoctor::getUserId).toList(); + cnd.andEX(View_user::getId, "not in", idList); + sql.setCondition(cnd); + Pagination pagination = doctorService.listPageMap(1, 50, sql); + return Result.success(pagination.getList()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalListController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalListController.java new file mode 100644 index 00000000..c90f09f1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalListController.java @@ -0,0 +1,106 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +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.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalApply; +import com.budwk.app.zhgh.staffbenefit.legal.service.LegalApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * @ClassName LegalListController + * @Author JyuHsin + * @Date 2025/7/25 16:00 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助我的预约") +@At("/platform/legal/list") +public class LegalListController { + + @Inject + private Dao dao; + @Inject + private LegalApplyService applyService; + + @At("") + @SaCheckPermission("legal.list") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/list/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("legal.list") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year) { + Sql sql = Sqls.create(""" + SELECT + pa.*, + pa.userName AS appointmentUserName, + pa.loginName AS appointmentLoginName, + pa.unitName AS appointmentUnitName, + pa.mobile AS appointmentMobile, + pd.specialty AS doctorSpecialty, + pd.introduce AS doctorIntroduce, + pd.sex AS doctorSex, + pd.technicalTitle AS doctorJobTitle, + pd.unitName AS doctorUnitName, + pd.avatar AS doctorAvatar, + pd.mobile AS doctorMobile, + pd.userName AS doctorUserName + FROM + `legal_apply` pa + LEFT JOIN legal_doctor pd ON pd.userId = pa.doctorUser + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("pa.userId", "IS NOT", null); + if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) { + cnd.and("pa.userId", "=", SecurityUtil.getUserId()); + } + cnd.andEX("YEAR(pa.startTime)", "=", year); + cnd.desc("pa.startTime"); + sql.setCondition(cnd); + Pagination pagination = applyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("删除法律援助预约") + @SaCheckPermission("legal.list") + @SLog(type = "legal", tag = "删除法律援助预约", msg = "删除法律援助预约") + public Object onDelete(String id) { + LegalApply apply = applyService.fetch(id); + apply.setUserId(null); + apply.setLoginName(null); + apply.setUserName(null); + apply.setUnitId(null); + apply.setUnitName(null); + apply.setUnionId(null); + apply.setUnionName(null); + apply.setRemark(null); + apply.setMobile(null); + applyService.update(apply); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalOnlinePostController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalOnlinePostController.java new file mode 100644 index 00000000..be7b59b2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalOnlinePostController.java @@ -0,0 +1,129 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalOnlinePost; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalOnlineReply; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName LegalOnlinePostController + * @Author JyuHsin + * @Date 2025/7/24 16:37 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助线上发帖") +@At("/platform/legal/onlinePost") +public class LegalOnlinePostController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + + @At("") + @SaCheckPermission("legal.onlinePost") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/onlinePost/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("legal.onlinePost") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "isReply") Boolean isReply) { + Sql sql = Sqls.create(""" + SELECT + pop.*, + IF( count( por.id ) = 0, false, true ) AS isReply + FROM + legal_online_post pop + LEFT JOIN legal_online_reply por on por.postId = pop.id + $condition + """); + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("poster", "=", SecurityUtil.getUserId()); + } + cnd.andEX("YEAR(pop.postingTime)", "=", year); + cnd.groupBy("pop.id"); + cnd.having(Cnd.where("count(por.id)", isReply == null ? ">=" : isReply ? ">" : "=", 0)); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改法律援助线上发帖") + @SaCheckPermission("legal.onlinePost") + @SLog(type = "legal", tag = "新增/修改法律援助线上发帖", msg = "新增/修改法律援助线上发帖") + public Object onSubmit(LegalOnlinePost post) { + if(StrUtil.isBlank(post.getId())) { + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + post.setPoster(user.getId()); + post.setLoginName(user.getLoginname()); + post.setUserName(user.getUsername()); + post.setUnitId(user.getUnitId()); + post.setUnitName(user.getUnitName()); + post.setUnionId(user.getUnionId()); + post.setUnionName(user.getUnionName()); + post.setMobile(user.getMobile()); + post.setPostingTime(DateUtil.now()); + } + dao.insertOrUpdate(post); + return Result.success(); + } + + @At + @ApiOperation("删除法律援助线上发帖") + @SaCheckPermission("legal.onlinePost") + @SLog(type = "legal", tag = "删除法律援助线上发帖", msg = "删除法律援助线上发帖") + public Object onDelete(String id) { + dao.delete(LegalOnlinePost.class, id); + return Result.success(); + } + + @At + @ApiOperation("查询法律援助线上发帖") + @SaCheckPermission("legal.onlinePost") + public Result fetchOne(String id) { + LegalOnlinePost onlinePost = dao.fetch(LegalOnlinePost.class, id); + List replyList = dao.query( + LegalOnlineReply.class, + Cnd.where(LegalOnlineReply::getPostId, "=", id).desc(LegalOnlineReply::getReplyTime) + ); + NutMap nutMap = Lang.obj2nutmap(onlinePost); + nutMap.put("replyList", replyList); + return Result.success(nutMap); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalOnlineReplyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalOnlineReplyController.java new file mode 100644 index 00000000..f2c36251 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalOnlineReplyController.java @@ -0,0 +1,124 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalOnlinePost; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalOnlineReply; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName LegalOnlineReplyController + * @Author JyuHsin + * @Date 2025/7/24 17:35 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助线上回复") +@At("/platform/legal/onlineReply") +public class LegalOnlineReplyController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + + @At("") + @SaCheckPermission("legal.onlineReply") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/onlineReply/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("legal.onlineReply") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "isReply") Boolean isReply) { + Sql sql = Sqls.create(""" + SELECT + pop.id, + pop.poster, + pop.loginName, + pop.postingTime, + pop.postTitle, + pop.postContent, + CONCAT( LEFT( pop.userName, 1 ), '**' ) AS posterUserName, + count( por.id ) AS replyCount + FROM + legal_online_post pop + LEFT JOIN legal_online_reply por ON por.postId = pop.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(pop.postingTime)", "=", year); + cnd.groupBy("pop.id"); + cnd.having(Cnd.where("count(por.id)", isReply == null ? ">=" : isReply ? ">" : "=", 0)); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改法律援助线上回复") + @SaCheckPermission("legal.onlineReply") + @SLog(type = "legal", tag = "新增/修改法律援助线上回复", msg = "新增/修改法律援助线上回复") + public Object onSubmit(LegalOnlineReply reply) { + if (StrUtil.isBlank(reply.getId())) { + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + reply.setReplyUserId(user.getId()); + reply.setLoginName(user.getLoginname()); + reply.setUserName(user.getUsername()); + reply.setUnitId(user.getUnitId()); + reply.setUnitName(user.getUnitName()); + reply.setUnionId(user.getUnionId()); + reply.setUnionName(user.getUnionName()); + reply.setMobile(user.getMobile()); + reply.setReplyTime(DateUtil.now()); + } + dao.insertOrUpdate(reply); + return Result.success(); + } + + @At + @ApiOperation("查询法律援助线上回复") + @SaCheckPermission("legal.onlineReply") + public Result fetchOne(String id) { + LegalOnlinePost onlinePost = dao.fetch(LegalOnlinePost.class, id); + List replyList = dao.query( + LegalOnlineReply.class, + Cnd.where(LegalOnlineReply::getPostId, "=", id).desc(LegalOnlineReply::getReplyTime) + ); + replyList.forEach(item -> item.setUserName(item.getUserName().charAt(0) + "**")); + NutMap nutMap = Lang.obj2nutmap(onlinePost); + nutMap.put("userName", onlinePost.getUserName().charAt(0) + "**"); + nutMap.put("replyList", replyList); + return Result.success(nutMap); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalStatisticsController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalStatisticsController.java new file mode 100644 index 00000000..da292107 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalStatisticsController.java @@ -0,0 +1,112 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalApply; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalDoctor; +import com.budwk.app.zhgh.staffbenefit.legal.service.LegalApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName LegalStatisticsController + * @Author JyuHsin + * @Date 2025/7/25 16:16 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助统计分析") +@At("/platform/legal/statistics") +public class LegalStatisticsController { + + @Inject + private Dao dao; + @Inject + private LegalApplyService applyService; + + @At("") + @SaCheckPermission("legal.statistics") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/statistics/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("legal.statistics") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "tableIndex") Integer tableIndex, + @Param(value = "doctorUser") String doctorUser) { + Sql sql = null; + Cnd cnd = Cnd.NEW(); + if (tableIndex == 1) { + sql = Sqls.create(""" + SELECT + pd.userId, + pd.userName AS doctorUserName, + pd.sex, + pd.technicalTitle as jobTitle, + (select count(*) from legal_apply pa where pa.doctorUser = pd.userId and pa.userId is not null) AS serviceNum + FROM + legal_doctor pd + LEFT JOIN legal_apply pa ON pa.doctorUser = pd.userId + $condition + """); + cnd.andEX("YEAR(pa.startTime)", "=", year); + cnd.groupBy("pd.userId"); + cnd.desc("serviceNum"); + } else if (tableIndex == 2) { + sql = Sqls.create(""" + SELECT + pa.*, + u.username AS doctorUserName + FROM + legal_apply pa + left join vw_user u on u.id = pa.doctorUser + $condition + """); + cnd.and("pa.userId", "is not", null); + cnd.andEX("pa.doctorUser", "=", doctorUser); + cnd.andEX("YEAR(pa.startTime)", "=", year); + } + sql.setCondition(cnd); + List listMap = applyService.listMap(sql); + return Result.success(listMap); + } + + @At + @ApiOperation("统计数量") + @SaCheckPermission("legal.statistics") + public Result queryCount(@Param(value = "year") Integer year) { + NutMap resultMap = new NutMap(); + List list = applyService.query(Cnd.NEW().andEX("YEAR(startTime)", "=", year)); + resultMap.put("total", list.size()); + + long serviceTeacherCount = list.stream().map(LegalApply::getUserId).filter(StrUtil::isNotBlank).distinct().count(); + resultMap.put("successNum", serviceTeacherCount); + resultMap.put("serviceTeacherCount", serviceTeacherCount); + + int doctorCount = applyService.dao().count(LegalDoctor.class, Cnd.NEW()); + resultMap.put("doctorCount", doctorCount); + + return Result.success(resultMap); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalStudyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalStudyController.java new file mode 100644 index 00000000..2170c277 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/controller/LegalStudyController.java @@ -0,0 +1,95 @@ +package com.budwk.app.zhgh.staffbenefit.legal.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalStudy; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName LegalStudyController + * @Author JyuHsin + * @Date 2025/7/24 16:19 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "法律援助资料学习") +@At("/platform/legal/study") +public class LegalStudyController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + + @At("") + @SaCheckPermission("legal.study") + @Ok("beetl:/platform/zhgh/staffbenefit/legal/study/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("legal.study") + public Result pageData(PageForm pageForm) { + Sql sql = Sqls.create(""" + select + s.*, + u.username + from + legal_study s + left join `vw_user` u on u.id = s.createdBy + $condition + """); + Cnd cnd = Cnd.NEW(); + if(StrUtil.isNotBlank(pageForm.getSearchKeyword())){ + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike("s.title", pageForm.getSearchKeyword()); + seg.orLike("s.url", pageForm.getSearchKeyword()); + cnd.and(seg); + } + if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改法律援助资料") + @SaCheckPermission("legal.study") + @SLog(type = "legal", tag = "新增/修改法律援助资料", msg = "新增/修改法律援助资料") + public Object onSubmit(LegalStudy study) { + dao.insertOrUpdate(study); + return Result.success(); + } + + @At + @ApiOperation("删除法律援助资料") + @SaCheckPermission("legal.study") + @SLog(type = "legal", tag = "删除法律援助资料", msg = "删除法律援助资料") + public Object onDelete(String id) { + dao.delete(LegalStudy.class, id); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalApply.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalApply.java new file mode 100644 index 00000000..5dbeab04 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalApply.java @@ -0,0 +1,114 @@ +package com.budwk.app.zhgh.staffbenefit.legal.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.List; + +/** + * @ClassName LegalApply + * @Author JyuHsin + * @Date 2025/7/24 16:12 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("法律援助预约") +@Accessors(chain = true) +@Table("legal_apply") +@EqualsAndHashCode(callSuper = true) +public class LegalApply extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("日期") + private String date; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("开始时间") + private String startTime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("结束时间") + private String endTime; + + @Column + @Comment("开始时间") + private Long startTimeTs; + + @Column + @Comment("结束时间") + private Long endTimeTs; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("预约人") + private String userId; + + @Column + @Comment("预约人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("预约人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("预约人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("预约人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("预约人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("预约人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("预约人备注") + private String remark; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("咨询师") + private String doctorUser; + + @Column + @ColDefine(type = ColType.MYSQL_JSON) + @Comment("咨询方式") + private List askType; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("预约人选择的咨询方式") + private String askTypeValue; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalDoctor.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalDoctor.java new file mode 100644 index 00000000..611a667f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalDoctor.java @@ -0,0 +1,100 @@ +package com.budwk.app.zhgh.staffbenefit.legal.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName LegalDoctor + * @Author JyuHsin + * @Date 2025/7/24 16:16 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("法律援助咨询师") +@Accessors(chain = true) +@Table("legal_doctor") +@EqualsAndHashCode(callSuper = true) +public class LegalDoctor extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户id") + private String userId; + + @Column + @Comment("工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 1) + @Comment("性别") + private String sex; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("职称") + private String technicalTitle; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 500) + @Comment("特长") + private String specialty; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 500) + @Comment("简介") + private String introduce; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 500) + @Comment("头像") + private String avatar; + + @Column + @Comment("是否禁用") + @ColDefine(type = ColType.BOOLEAN) + private boolean disabled; + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalOnlinePost.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalOnlinePost.java new file mode 100644 index 00000000..763f8496 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalOnlinePost.java @@ -0,0 +1,84 @@ +package com.budwk.app.zhgh.staffbenefit.legal.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName LegalOnlinePost + * @Author JyuHsin + * @Date 2025/7/24 16:17 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("法律援助线上发帖") +@Accessors(chain = true) +@Table("legal_online_post") +@EqualsAndHashCode(callSuper = true) +public class LegalOnlinePost extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("发帖人") + private String poster; + + @Column + @Comment("发帖人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("发帖人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("发帖人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("发帖人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("发帖人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("发帖人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("发帖时间") + private String postingTime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("发帖标题") + private String postTitle; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 1000) + @Comment("发帖内容") + private String postContent; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalOnlineReply.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalOnlineReply.java new file mode 100644 index 00000000..f1068b68 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalOnlineReply.java @@ -0,0 +1,84 @@ +package com.budwk.app.zhgh.staffbenefit.legal.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName LegalOnlineReply + * @Author JyuHsin + * @Date 2025/7/24 16:18 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("法律援助线上答复") +@Accessors(chain = true) +@Table("legal_online_reply") +@EqualsAndHashCode(callSuper = true) +public class LegalOnlineReply extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("帖子Id") + private String postId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("答复人") + private String replyUserId; + + @Column + @Comment("答复人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("答复人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("答复人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("答复人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("答复人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("答复人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("答复时间") + private String replyTime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 1000) + @Comment("答复内容") + private String replyContent; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalStudy.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalStudy.java new file mode 100644 index 00000000..f034f869 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/model/LegalStudy.java @@ -0,0 +1,44 @@ +package com.budwk.app.zhgh.staffbenefit.legal.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName LegalStudy + * @Author JyuHsin + * @Date 2025/7/24 16:11 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("法律援助资料学习") +@Accessors(chain = true) +@Table("legal_study") +@EqualsAndHashCode(callSuper = true) +public class LegalStudy extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("标题") + private String title; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("跳转链接") + private String url; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 200) + @Comment("备注") + private String bz; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/LegalApplyService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/LegalApplyService.java new file mode 100644 index 00000000..39cf9dfd --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/LegalApplyService.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.staffbenefit.legal.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalApply; + +/** + * @ClassName LegalApplyService + * @Author JyuHsin + * @Date 2025/7/25 10:07 + * @Version 1.0 + * @Description TODO + */ +public interface LegalApplyService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/LegalDoctorService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/LegalDoctorService.java new file mode 100644 index 00000000..d1509843 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/LegalDoctorService.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.staffbenefit.legal.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalDoctor; + +/** + * @ClassName LegalDoctorService + * @Author JyuHsin + * @Date 2025/7/25 9:13 + * @Version 1.0 + * @Description TODO + */ +public interface LegalDoctorService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/impl/LegalApplyServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/impl/LegalApplyServiceImpl.java new file mode 100644 index 00000000..6513b8ee --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/impl/LegalApplyServiceImpl.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.staffbenefit.legal.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalApply; +import com.budwk.app.zhgh.staffbenefit.legal.service.LegalApplyService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName LegalApplyServiceImpl + * @Author JyuHsin + * @Date 2025/7/25 10:07 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class LegalApplyServiceImpl extends BaseServiceImpl implements LegalApplyService { + + public LegalApplyServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/impl/LegalDoctorServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/impl/LegalDoctorServiceImpl.java new file mode 100644 index 00000000..6942c4c3 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/legal/service/impl/LegalDoctorServiceImpl.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.staffbenefit.legal.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.legal.model.LegalDoctor; +import com.budwk.app.zhgh.staffbenefit.legal.service.LegalDoctorService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName LegalDoctorServiceImpl + * @Author JyuHsin + * @Date 2025/7/25 9:14 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class LegalDoctorServiceImpl extends BaseServiceImpl implements LegalDoctorService { + + public LegalDoctorServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyApplyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyApplyController.java new file mode 100644 index 00000000..e98c273a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyApplyController.java @@ -0,0 +1,70 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyApply; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName PsychologyApplyController + * @Author JyuHsin + * @Date 2025/7/25 15:08 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询预约") +@At("/platform/psychology/apply") +public class PsychologyApplyController { + + @Inject + private Dao dao; + @Inject + private PsychologyApplyService applyService; + + @At("") + @SaCheckPermission("psychology.apply") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/apply/index.html") + public void index() { + } + + @At + @ApiOperation("新增/修改心理咨询预约") + @SaCheckPermission("psychology.apply") + @SLog(type = "psychology", tag = "新增/修改心理咨询预约", msg = "新增/修改心理咨询预约") + public Object onSubmit(PsychologyApply apply) { + PsychologyApply psychologyApply = applyService.fetch(apply.getId()); + if(StrUtil.isNotBlank(psychologyApply.getUserId())) { + return Result.error("该时段已被预约"); + } + View_user user = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId())); + apply.setUserId(user.getId()); + apply.setLoginName(user.getLoginname()); + apply.setUserName(user.getUsername()); + apply.setUnitId(user.getUnitId()); + apply.setUnitName(user.getUnitName()); + apply.setUnionId(user.getUnionId()); + apply.setUnionName(user.getUnionName()); + /*apply.setMobile(apply.getMobile()); + apply.setRemark(apply.getRemark()); + apply.setAskTypeValue(apply.getAskTypeValue());*/ + applyService.updateIgnoreNull(apply); + //TODO:这里后面要加发短信 + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyAppointmentSetController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyAppointmentSetController.java new file mode 100644 index 00000000..8020aec2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyAppointmentSetController.java @@ -0,0 +1,166 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyApply; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyOnlinePost; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyApplyService; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyDoctorService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.springframework.beans.BeanUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @ClassName PsychologyAppointmentSetController + * @Author JyuHsin + * @Date 2025/7/25 10:04 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询预约安排") +@At("/platform/psychology/appointmentSet") +public class PsychologyAppointmentSetController { + + @Inject + private Dao dao; + @Inject + private PsychologyApplyService applyService; + + @At("") + @SaCheckPermission("psychology.appointmentSet") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/appointmentSet/index.html") + public void index() { + } + + @At + @ApiOperation("查询时间段内的预约信息") + @SaCheckPermission("psychology.appointmentSet") + public Result queryAppointmentInfo(Long startTimeTs, Long endTimeTs) { + Sql sql = Sqls.create(""" + SELECT + pa.*, + pa.userId as appointmentUser, + pa.userName AS appointmentUserName, + pa.loginName AS appointmentLoginName, + pa.unitName AS appointmentUnitName, + pa.mobile AS appointmentMobile, + pd.specialty AS doctorSpecialty, + pd.introduce AS doctorIntroduce, + pd.sex AS doctorSex, + pd.technicalTitle AS doctorJobTitle, + pd.unitName AS doctorUnitName, + pd.avatar AS doctorAvatar, + pd.mobile AS doctorMobile, + pd.userName AS doctorUserName + FROM + `psychology_apply` pa + LEFT JOIN psychology_doctor pd ON pd.userId = pa.doctorUser + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("startTimeTs", ">=", startTimeTs); + cnd.and("endTimeTs", "<=", endTimeTs); + sql.setCondition(cnd); + List listMap = applyService.listMap(sql); + return Result.success(listMap); + } + + @At + @ApiOperation("新增/修改心理咨询安排") + @SaCheckPermission("psychology.appointmentSet") + @SLog(type = "psychology", tag = "新增/修改心理咨询安排", msg = "新增/修改心理咨询安排") + public Object onSubmit(PsychologyApply apply) { + long startTimeTs = com.budwk.app.base.utils.DateUtil.formatDate(apply.getStartTime()); + long endTimeTs = com.budwk.app.base.utils.DateUtil.formatDate(apply.getEndTime()); + List list = new ArrayList<>(); + for (long i = startTimeTs; i < endTimeTs; i = i + 3600000) { + PsychologyApply app = new PsychologyApply(); + PsychologyApply psychologyAppointmentInfo = Lang.copyProperties(apply, app); + String start = com.budwk.app.base.utils.DateUtil.getDate(i / 1000); + long e = i + 3600000; + if ((endTimeTs - e) <= 0) { + e = i + (endTimeTs - i); + } + String end = com.budwk.app.base.utils.DateUtil.getDate(e / 1000); + psychologyAppointmentInfo.setStartTimeTs(i); + psychologyAppointmentInfo.setEndTimeTs(e); + psychologyAppointmentInfo.setStartTime(start); + psychologyAppointmentInfo.setEndTime(end); + list.add(psychologyAppointmentInfo); + } + dao.insert(list); + return Result.success(); + } + + @At + @ApiOperation("修改心理咨询安排") + @SaCheckPermission("psychology.appointmentSet") + @SLog(type = "psychology", tag = "修改心理咨询安排", msg = "修改心理咨询安排") + public Object onEdit(String id, String[] askType) { + PsychologyApply apply = applyService.fetch(id); + apply.setAskType(Lang.isNotEmpty(askType) ? Arrays.asList(askType) : new ArrayList<>()); + apply.setAskTypeValue(null); + applyService.update(apply); + //TODO:以后这里加个发短信 + return Result.success(); + } + + @At + @ApiOperation("删除心理咨询安排") + @SaCheckPermission("psychology.appointmentSet") + @SLog(type = "psychology", tag = "删除心理咨询安排", msg = "删除心理咨询安排") + public Object onDelete(String id) { + applyService.delete(id); + //TODO:以后这里加个发短信 + return Result.success(); + } + + @At + @ApiOperation("查询咨询师") + @SaCheckPermission("psychology.appointmentSet") + public Result queryDoctorUser(String keyWord, long startTimeTs, long endTimeTs) { + //先查询该时间段没时间的咨询师 + Sql doctorSql = Sqls.create(""" + SELECT + pd.userId AS id, + pd.userName AS doctorUserName, + replace(pd.mobile,' ','') as mobile + FROM + psychology_doctor pd + WHERE + pd.userId NOT IN + ( + SELECT doctorUser FROM psychology_apply + WHERE startTimeTs >= @startTimeTs AND endTimeTs <= @endTimeTs + AND doctorUser IS NOT NULL + ) + and (pd.userName like @keyWord or pd.loginName like @keyWord) + """); + doctorSql.setParam("startTimeTs", startTimeTs); + doctorSql.setParam("endTimeTs", endTimeTs); + doctorSql.setParam("keyWord", "%" + keyWord + "%"); + Pagination pagination = applyService.listPageMap(1, 10, doctorSql); + return Result.success(pagination.getList()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyDoctorController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyDoctorController.java new file mode 100644 index 00000000..c5bf3b83 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyDoctorController.java @@ -0,0 +1,140 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.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.sys.models.Sys_user_role; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyDoctor; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyDoctorService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +import java.util.List; + +/** + * @ClassName PsychologyDoctorController + * @Author JyuHsin + * @Date 2025/7/24 18:18 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询咨询师") +@At("/platform/psychology/doctorManage") +public class PsychologyDoctorController { + + @Inject + private Dao dao; + @Inject + private PsychologyDoctorService doctorService; + + @At("") + @SaCheckPermission("psychology.doctorManage") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/doctorManage/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("psychology.doctorManage") + public Result pageData(PageForm pageForm) { + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(PsychologyDoctor::getLoginName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(PsychologyDoctor::getUserName, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + Pagination pagination = doctorService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + return Result.success(pagination); + } + + @At + @Aop(TransAop.READ_COMMITTED) + @ApiOperation("新增/修改心理咨询师") + @SaCheckPermission("psychology.doctorManage") + @SLog(type = "psychology", tag = "新增/修改心理咨询师", msg = "新增/修改心理咨询师") + public Object onSubmit(PsychologyDoctor doctor) { + if(StrUtil.isBlank(doctor.getId())) { + int count = doctorService.count(Cnd.where(PsychologyDoctor::getUserId, "=", doctor.getUserId())); + if(count > 0) { + return Result.error("此咨询师信息已录入"); + } + View_user user = dao.fetch(View_user.class, Cnd.where(View_user::getId, "=", doctor.getUserId())); + doctor.setLoginName(user.getLoginname()); + doctor.setUserName(user.getUsername()); + doctor.setUnitId(user.getUnitId()); + doctor.setUnitName(user.getUnitName()); + doctor.setUnionId(user.getUnionId()); + doctor.setUnionName(user.getUnionName()); + //插入角色 + Sys_user_role userRole = new Sys_user_role(); + userRole.setUserId(doctor.getUserId()); + userRole.setRoleId(RoleConstant.PSYCHOLOGY_DOCTOR.name()); + dao.insert(userRole); + } + doctorService.insertOrUpdate(doctor); + return Result.success(); + } + + @At + @ApiOperation("删除心理咨询师") + @SaCheckPermission("psychology.doctorManage") + @SLog(type = "psychology", tag = "删除心理咨询师", msg = "删除心理咨询师") + public Object onDelete(String id) { + doctorService.delete(id); + return Result.success(); + } + + @At + @ApiOperation("查询用户") + @SaCheckPermission("psychology.doctorManage") + @SLog(type = "psychology", tag = "查询用户", msg = "查询用户") + public Object listUser(String keyword) { + Sql sql = Sqls.create(""" + select + id, + username as userName, + loginname as loginName, + sex, + mobile, + technicalTitle, + unitname as unitName + from + vw_user + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(keyword)) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(View_user::getLoginname, "like", "%" + keyword + "%"); + seg.or(View_user::getUsername, "like", "%" + keyword + "%"); + cnd.and(seg); + } + List list = doctorService.query(Cnd.NEW()); + List idList = list.stream().map(PsychologyDoctor::getUserId).toList(); + cnd.andEX(View_user::getId, "not in", idList); + sql.setCondition(cnd); + Pagination pagination = doctorService.listPageMap(1, 50, sql); + return Result.success(pagination.getList()); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyListController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyListController.java new file mode 100644 index 00000000..499db407 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyListController.java @@ -0,0 +1,107 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +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.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyApply; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyOnlinePost; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +/** + * @ClassName PsychologyListController + * @Author JyuHsin + * @Date 2025/7/25 16:00 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询我的预约") +@At("/platform/psychology/list") +public class PsychologyListController { + + @Inject + private Dao dao; + @Inject + private PsychologyApplyService applyService; + + @At("") + @SaCheckPermission("psychology.list") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/list/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("psychology.list") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year) { + Sql sql = Sqls.create(""" + SELECT + pa.*, + pa.userName AS appointmentUserName, + pa.loginName AS appointmentLoginName, + pa.unitName AS appointmentUnitName, + pa.mobile AS appointmentMobile, + pd.specialty AS doctorSpecialty, + pd.introduce AS doctorIntroduce, + pd.sex AS doctorSex, + pd.technicalTitle AS doctorJobTitle, + pd.unitName AS doctorUnitName, + pd.avatar AS doctorAvatar, + pd.mobile AS doctorMobile, + pd.userName AS doctorUserName + FROM + `psychology_apply` pa + LEFT JOIN psychology_doctor pd ON pd.userId = pa.doctorUser + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("pa.userId", "IS NOT", null); + if(!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) { + cnd.and("pa.userId", "=", SecurityUtil.getUserId()); + } + cnd.andEX("YEAR(pa.startTime)", "=", year); + cnd.desc("pa.startTime"); + sql.setCondition(cnd); + Pagination pagination = applyService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("删除心理咨询预约") + @SaCheckPermission("psychology.list") + @SLog(type = "psychology", tag = "删除心理咨询预约", msg = "删除心理咨询预约") + public Object onDelete(String id) { + PsychologyApply apply = applyService.fetch(id); + apply.setUserId(null); + apply.setLoginName(null); + apply.setUserName(null); + apply.setUnitId(null); + apply.setUnitName(null); + apply.setUnionId(null); + apply.setUnionName(null); + apply.setRemark(null); + apply.setMobile(null); + applyService.update(apply); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyOnlinePostController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyOnlinePostController.java new file mode 100644 index 00000000..c6b59f14 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyOnlinePostController.java @@ -0,0 +1,129 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyOnlinePost; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyOnlineReply; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName PsychologyOnlinePostController + * @Author JyuHsin + * @Date 2025/7/24 16:37 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询线上发帖") +@At("/platform/psychology/onlinePost") +public class PsychologyOnlinePostController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + + @At("") + @SaCheckPermission("psychology.onlinePost") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/onlinePost/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("psychology.onlinePost") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "isReply") Boolean isReply) { + Sql sql = Sqls.create(""" + SELECT + pop.*, + IF( count( por.id ) = 0, false, true ) AS isReply + FROM + psychology_online_post pop + LEFT JOIN psychology_online_reply por on por.postId = pop.id + $condition + """); + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("poster", "=", SecurityUtil.getUserId()); + } + cnd.andEX("YEAR(pop.postingTime)", "=", year); + cnd.groupBy("pop.id"); + cnd.having(Cnd.where("count(por.id)", isReply == null ? ">=" : isReply ? ">" : "=", 0)); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改心理咨询线上发帖") + @SaCheckPermission("psychology.onlinePost") + @SLog(type = "psychology", tag = "新增/修改心理咨询线上发帖", msg = "新增/修改心理咨询线上发帖") + public Object onSubmit(PsychologyOnlinePost post) { + if(StrUtil.isBlank(post.getId())) { + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + post.setPoster(user.getId()); + post.setLoginName(user.getLoginname()); + post.setUserName(user.getUsername()); + post.setUnitId(user.getUnitId()); + post.setUnitName(user.getUnitName()); + post.setUnionId(user.getUnionId()); + post.setUnionName(user.getUnionName()); + post.setMobile(user.getMobile()); + post.setPostingTime(DateUtil.now()); + } + dao.insertOrUpdate(post); + return Result.success(); + } + + @At + @ApiOperation("删除心理咨询线上发帖") + @SaCheckPermission("psychology.onlinePost") + @SLog(type = "psychology", tag = "删除心理咨询线上发帖", msg = "删除心理咨询线上发帖") + public Object onDelete(String id) { + dao.delete(PsychologyOnlinePost.class, id); + return Result.success(); + } + + @At + @ApiOperation("查询心理咨询线上发帖") + @SaCheckPermission("psychology.onlinePost") + public Result fetchOne(String id) { + PsychologyOnlinePost onlinePost = dao.fetch(PsychologyOnlinePost.class, id); + List replyList = dao.query( + PsychologyOnlineReply.class, + Cnd.where(PsychologyOnlineReply::getPostId, "=", id).desc(PsychologyOnlineReply::getReplyTime) + ); + NutMap nutMap = Lang.obj2nutmap(onlinePost); + nutMap.put("replyList", replyList); + return Result.success(nutMap); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyOnlineReplyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyOnlineReplyController.java new file mode 100644 index 00000000..17514d6c --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyOnlineReplyController.java @@ -0,0 +1,124 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyOnlinePost; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyOnlineReply; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName PsychologyOnlineReplyController + * @Author JyuHsin + * @Date 2025/7/24 17:35 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询线上回复") +@At("/platform/psychology/onlineReply") +public class PsychologyOnlineReplyController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + + @At("") + @SaCheckPermission("psychology.onlineReply") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/onlineReply/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("psychology.onlineReply") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "isReply") Boolean isReply) { + Sql sql = Sqls.create(""" + SELECT + pop.id, + pop.poster, + pop.loginName, + pop.postingTime, + pop.postTitle, + pop.postContent, + CONCAT( LEFT( pop.userName, 1 ), '**' ) AS posterUserName, + count( por.id ) AS replyCount + FROM + psychology_online_post pop + LEFT JOIN psychology_online_reply por ON por.postId = pop.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("YEAR(pop.postingTime)", "=", year); + cnd.groupBy("pop.id"); + cnd.having(Cnd.where("count(por.id)", isReply == null ? ">=" : isReply ? ">" : "=", 0)); + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改心理咨询线上回复") + @SaCheckPermission("psychology.onlineReply") + @SLog(type = "psychology", tag = "新增/修改心理咨询线上回复", msg = "新增/修改心理咨询线上回复") + public Object onSubmit(PsychologyOnlineReply reply) { + if (StrUtil.isBlank(reply.getId())) { + View_user user = dao.fetch(View_user.class, Cnd.where("id", "=", SecurityUtil.getUserId())); + reply.setReplyUserId(user.getId()); + reply.setLoginName(user.getLoginname()); + reply.setUserName(user.getUsername()); + reply.setUnitId(user.getUnitId()); + reply.setUnitName(user.getUnitName()); + reply.setUnionId(user.getUnionId()); + reply.setUnionName(user.getUnionName()); + reply.setMobile(user.getMobile()); + reply.setReplyTime(DateUtil.now()); + } + dao.insertOrUpdate(reply); + return Result.success(); + } + + @At + @ApiOperation("查询心理咨询线上回复") + @SaCheckPermission("psychology.onlineReply") + public Result fetchOne(String id) { + PsychologyOnlinePost onlinePost = dao.fetch(PsychologyOnlinePost.class, id); + List replyList = dao.query( + PsychologyOnlineReply.class, + Cnd.where(PsychologyOnlineReply::getPostId, "=", id).desc(PsychologyOnlineReply::getReplyTime) + ); + replyList.forEach(item -> item.setUserName(item.getUserName().charAt(0) + "**")); + NutMap nutMap = Lang.obj2nutmap(onlinePost); + nutMap.put("userName", onlinePost.getUserName().charAt(0) + "**"); + nutMap.put("replyList", replyList); + return Result.success(nutMap); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyStatisticsController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyStatisticsController.java new file mode 100644 index 00000000..6afcb8d4 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyStatisticsController.java @@ -0,0 +1,112 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyApply; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyDoctor; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyApplyService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName PsychologyStatisticsController + * @Author JyuHsin + * @Date 2025/7/25 16:16 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询统计分析") +@At("/platform/psychology/statistics") +public class PsychologyStatisticsController { + + @Inject + private Dao dao; + @Inject + private PsychologyApplyService applyService; + + @At("") + @SaCheckPermission("psychology.statistics") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/statistics/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("psychology.statistics") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "tableIndex") Integer tableIndex, + @Param(value = "doctorUser") String doctorUser) { + Sql sql = null; + Cnd cnd = Cnd.NEW(); + if (tableIndex == 1) { + sql = Sqls.create(""" + SELECT + pd.userId, + pd.userName AS doctorUserName, + pd.sex, + pd.technicalTitle as jobTitle, + (select count(*) from psychology_apply pa where pa.doctorUser = pd.userId and pa.userId is not null) AS serviceNum + FROM + psychology_doctor pd + LEFT JOIN psychology_apply pa ON pa.doctorUser = pd.userId + $condition + """); + cnd.andEX("YEAR(pa.startTime)", "=", year); + cnd.groupBy("pd.userId"); + cnd.desc("serviceNum"); + } else if (tableIndex == 2) { + sql = Sqls.create(""" + SELECT + pa.*, + u.username AS doctorUserName + FROM + psychology_apply pa + left join vw_user u on u.id = pa.doctorUser + $condition + """); + cnd.and("pa.userId", "is not", null); + cnd.andEX("pa.doctorUser", "=", doctorUser); + cnd.andEX("YEAR(pa.startTime)", "=", year); + } + sql.setCondition(cnd); + List listMap = applyService.listMap(sql); + return Result.success(listMap); + } + + @At + @ApiOperation("统计数量") + @SaCheckPermission("psychology.statistics") + public Result queryCount(@Param(value = "year") Integer year) { + NutMap resultMap = new NutMap(); + List list = applyService.query(Cnd.NEW().andEX("YEAR(startTime)", "=", year)); + resultMap.put("total", list.size()); + + long serviceTeacherCount = list.stream().map(PsychologyApply::getUserId).filter(StrUtil::isNotBlank).distinct().count(); + resultMap.put("successNum", serviceTeacherCount); + resultMap.put("serviceTeacherCount", serviceTeacherCount); + + int doctorCount = applyService.dao().count(PsychologyDoctor.class, Cnd.NEW()); + resultMap.put("doctorCount", doctorCount); + + return Result.success(resultMap); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyStudyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyStudyController.java new file mode 100644 index 00000000..51346902 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/controller/PsychologyStudyController.java @@ -0,0 +1,95 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyStudy; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName PsychologyStudyController + * @Author JyuHsin + * @Date 2025/7/24 16:19 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "心理咨询资料学习") +@At("/platform/psychology/study") +public class PsychologyStudyController { + + @Inject + private Dao dao; + @Inject + private BaseService baseService; + + @At("") + @SaCheckPermission("psychology.study") + @Ok("beetl:/platform/zhgh/staffbenefit/psychology/study/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("psychology.study") + public Result pageData(PageForm pageForm) { + Sql sql = Sqls.create(""" + select + s.*, + u.username + from + psychology_study s + left join `vw_user` u on u.id = s.createdBy + $condition + """); + Cnd cnd = Cnd.NEW(); + if(StrUtil.isNotBlank(pageForm.getSearchKeyword())){ + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.orLike("s.title", pageForm.getSearchKeyword()); + seg.orLike("s.url", pageForm.getSearchKeyword()); + cnd.and(seg); + } + if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改心理咨询资料") + @SaCheckPermission("psychology.study") + @SLog(type = "psychology", tag = "新增/修改心理咨询资料", msg = "新增/修改心理咨询资料") + public Object onSubmit(PsychologyStudy study) { + dao.insertOrUpdate(study); + return Result.success(); + } + + @At + @ApiOperation("删除心理咨询资料") + @SaCheckPermission("psychology.study") + @SLog(type = "psychology", tag = "删除心理咨询资料", msg = "删除心理咨询资料") + public Object onDelete(String id) { + dao.delete(PsychologyStudy.class, id); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyApply.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyApply.java new file mode 100644 index 00000000..41e72dd6 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyApply.java @@ -0,0 +1,114 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.List; + +/** + * @ClassName PsychologyApply + * @Author JyuHsin + * @Date 2025/7/24 16:12 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("心理咨询预约") +@Accessors(chain = true) +@Table("psychology_apply") +@EqualsAndHashCode(callSuper = true) +public class PsychologyApply extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("日期") + private String date; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("开始时间") + private String startTime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("结束时间") + private String endTime; + + @Column + @Comment("开始时间") + private Long startTimeTs; + + @Column + @Comment("结束时间") + private Long endTimeTs; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("预约人") + private String userId; + + @Column + @Comment("预约人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("预约人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("预约人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("预约人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("预约人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("预约人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("预约人备注") + private String remark; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("咨询师") + private String doctorUser; + + @Column + @ColDefine(type = ColType.MYSQL_JSON) + @Comment("咨询方式") + private List askType; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 50) + @Comment("预约人选择的咨询方式") + private String askTypeValue; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyDoctor.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyDoctor.java new file mode 100644 index 00000000..f694ee01 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyDoctor.java @@ -0,0 +1,100 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName PsychologyDoctor + * @Author JyuHsin + * @Date 2025/7/24 16:16 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("心理咨询咨询师") +@Accessors(chain = true) +@Table("psychology_doctor") +@EqualsAndHashCode(callSuper = true) +public class PsychologyDoctor extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("用户id") + private String userId; + + @Column + @Comment("工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 1) + @Comment("性别") + private String sex; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("职称") + private String technicalTitle; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 500) + @Comment("特长") + private String specialty; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 500) + @Comment("简介") + private String introduce; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 500) + @Comment("头像") + private String avatar; + + @Column + @Comment("是否禁用") + @ColDefine(type = ColType.BOOLEAN) + private boolean disabled; + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyOnlinePost.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyOnlinePost.java new file mode 100644 index 00000000..d81e7093 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyOnlinePost.java @@ -0,0 +1,84 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName PsychologyOnlinePost + * @Author JyuHsin + * @Date 2025/7/24 16:17 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("心理咨询线上发帖") +@Accessors(chain = true) +@Table("psychology_online_post") +@EqualsAndHashCode(callSuper = true) +public class PsychologyOnlinePost extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("发帖人") + private String poster; + + @Column + @Comment("发帖人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("发帖人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("发帖人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("发帖人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("发帖人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("发帖人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("发帖时间") + private String postingTime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 20) + @Comment("发帖标题") + private String postTitle; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 1000) + @Comment("发帖内容") + private String postContent; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyOnlineReply.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyOnlineReply.java new file mode 100644 index 00000000..b1f682b2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyOnlineReply.java @@ -0,0 +1,84 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName PsychologyOnlineReply + * @Author JyuHsin + * @Date 2025/7/24 16:18 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("心理咨询线上答复") +@Accessors(chain = true) +@Table("psychology_online_reply") +@EqualsAndHashCode(callSuper = true) +public class PsychologyOnlineReply extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("帖子Id") + private String postId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("答复人") + private String replyUserId; + + @Column + @Comment("答复人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String loginName; + + @Column + @Comment("答复人姓名") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String userName; + + @Column + @Comment("答复人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("答复人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unitName; + + @Column + @Comment("答复人工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("答复人单位") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String unionName; + + @Column + @Comment("联系方式") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 30) + @Comment("答复时间") + private String replyTime; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 1000) + @Comment("答复内容") + private String replyContent; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyStudy.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyStudy.java new file mode 100644 index 00000000..beab782a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/model/PsychologyStudy.java @@ -0,0 +1,44 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName PsychologyStudy + * @Author JyuHsin + * @Date 2025/7/24 16:11 + * @Version 1.0 + * @Description TODO + */ +@Data +@Comment("心理咨询资料学习") +@Accessors(chain = true) +@Table("psychology_study") +@EqualsAndHashCode(callSuper = true) +public class PsychologyStudy extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("标题") + private String title; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("跳转链接") + private String url; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 200) + @Comment("备注") + private String bz; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/PsychologyApplyService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/PsychologyApplyService.java new file mode 100644 index 00000000..9a309e98 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/PsychologyApplyService.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyApply; + +/** + * @ClassName PsychologyApplyService + * @Author JyuHsin + * @Date 2025/7/25 10:07 + * @Version 1.0 + * @Description TODO + */ +public interface PsychologyApplyService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/PsychologyDoctorService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/PsychologyDoctorService.java new file mode 100644 index 00000000..4ea6509f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/PsychologyDoctorService.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyDoctor; + +/** + * @ClassName PsychologyDoctorService + * @Author JyuHsin + * @Date 2025/7/25 9:13 + * @Version 1.0 + * @Description TODO + */ +public interface PsychologyDoctorService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/impl/PsychologyApplyServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/impl/PsychologyApplyServiceImpl.java new file mode 100644 index 00000000..cd7b2cea --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/impl/PsychologyApplyServiceImpl.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyApply; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyApplyService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName PsychologyApplyServiceImpl + * @Author JyuHsin + * @Date 2025/7/25 10:07 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class PsychologyApplyServiceImpl extends BaseServiceImpl implements PsychologyApplyService { + + public PsychologyApplyServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/impl/PsychologyDoctorServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/impl/PsychologyDoctorServiceImpl.java new file mode 100644 index 00000000..31a14e07 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/psychology/service/impl/PsychologyDoctorServiceImpl.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.staffbenefit.psychology.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.psychology.model.PsychologyDoctor; +import com.budwk.app.zhgh.staffbenefit.psychology.service.PsychologyDoctorService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName PsychologyDoctorServiceImpl + * @Author JyuHsin + * @Date 2025/7/25 9:14 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class PsychologyDoctorServiceImpl extends BaseServiceImpl implements PsychologyDoctorService { + + public PsychologyDoctorServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.css b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.css new file mode 100644 index 00000000..796aa9da --- /dev/null +++ b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.css @@ -0,0 +1,1162 @@ +/*! + * FullCalendar v3.6.1 Stylesheet + * Docs & License: https://fullcalendar.io/ + * (c) 2017 Adam Shaw + */ + +.fc button, +.fc table, +body .fc { + font-size: 1em +} + +.fc-bg, +.fc-row .fc-bgevent-skeleton, +.fc-row .fc-highlight-skeleton { + bottom: 0 +} + +.fc-icon, +.fc-unselectable { + -webkit-touch-callout: none; + -khtml-user-select: none +} + +.fc { + direction: ltr; + text-align: left +} + +.fc-rtl { + text-align: right +} + +.fc th, +.fc-basic-view td.fc-week-number, +.fc-icon, +.fc-toolbar { + text-align: center +} + +.fc-highlight { + background: #bce8f1; + opacity: .3 +} + +.fc-bgevent { + background: #8fdf82; + opacity: .3 +} + +.fc-nonbusiness { + background: #d7d7d7 +} + +.fc button { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + /*height: 2.1em;*/ + padding: .5em .8em; + white-space: nowrap; + cursor: pointer +} + +.fc button::-moz-focus-inner { + margin: 0; + padding: 0 +} + +.fc-state-default { + color: #fff; + border: 1px solid #2C3E50; + background-color: #2C3E50; + /*background-image: -moz-linear-gradient(top, #fff, #e6e6e6); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #fff, #e6e6e6); + background-image: -o-linear-gradient(top, #fff, #e6e6e6); + background-image: linear-gradient(to bottom, #fff, #e6e6e6); + background-repeat: repeat-x; + border-color: #e6e6e6 #e6e6e6 #bfbfbf; + border-color: rgba(0, 0, 0, .1) rgba(0, 0, 0, .1) rgba(0, 0, 0, .25); + color: #333; + text-shadow: 0 1px 1px rgba(255, 255, 255, .75); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), 0 1px 2px rgba(0, 0, 0, .05)*/ +} + +.fc-state-default.fc-corner-left { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px +} + +.fc-state-default.fc-corner-right { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px +} + +.fc button .fc-icon { + position: relative; + top: -.05em; + margin: 0 .2em; + vertical-align: middle +} + +.fc-state-active, +.fc-state-disabled, +.fc-state-down, +.fc-state-hover { + /*color: #333; + background-color: #e6e6e6;*/ + color: #fff; + background-color: #1a252f; + border-color: #151e27; +} + +.fc-state-hover { + color: #fff; + /*color: #333;*/ + text-decoration: none; + background-position: 0 -15px; + -webkit-transition: background-position .1s linear; + -moz-transition: background-position .1s linear; + -o-transition: background-position .1s linear; + transition: background-position .1s linear +} + +.fc-state-active, +.fc-state-down { + color: #fff; + background-color: #1a252f; + border-color: #151e27; + /*background-color: #ccc;*/ + background-image: none; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, .15), 0 1px 2px rgba(0, 0, 0, .05) +} + +.fc-state-disabled { + cursor: default; + background-image: none; + opacity: .65; + box-shadow: none +} + +.fc-event.fc-draggable, +.fc-event[href], +.fc-popover .fc-header .fc-close, +a[data-goto] { + cursor: pointer +} + +.fc-button-group { + display: inline-block +} + +.fc .fc-button-group > * { + float: left; + margin: 0 0 0 -1px +} + +.fc .fc-button-group > :first-child { + margin-left: 0 +} + +.fc-popover { + position: absolute; + box-shadow: 0 2px 6px rgba(0, 0, 0, .15) +} + +.fc-popover .fc-header { + padding: 2px 4px +} + +.fc-popover .fc-header .fc-title { + margin: 0 2px +} + +.fc-ltr .fc-popover .fc-header .fc-title, +.fc-rtl .fc-popover .fc-header .fc-close { + float: left +} + +.fc-ltr .fc-popover .fc-header .fc-close, +.fc-rtl .fc-popover .fc-header .fc-title { + float: right +} + +.fc-divider { + border-style: solid; + border-width: 1px +} + +hr.fc-divider { + height: 0; + margin: 0; + padding: 0 0 2px; + border-width: 1px 0 +} + +.fc-bg table, +.fc-row .fc-bgevent-skeleton table, +.fc-row .fc-highlight-skeleton table { + height: 100% +} + +.fc-clear { + clear: both +} + +.fc-bg, +.fc-bgevent-skeleton, +.fc-helper-skeleton, +.fc-highlight-skeleton { + position: absolute; + top: 0; + left: 0; + right: 0 +} + +.fc table { + width: 100%; + box-sizing: border-box; + table-layout: fixed; + border-collapse: collapse; + border-spacing: 0 +} + +.fc td, +.fc th { + border-style: solid; + border-width: 1px; + padding: 0; + vertical-align: top +} + +.fc td.fc-today { + border-style: double +} + +a[data-goto]:hover { + text-decoration: underline +} + +.fc .fc-row { + border-style: solid; + border-width: 0 +} + +.fc-row table { + border-left: 0 hidden transparent; + border-right: 0 hidden transparent; + border-bottom: 0 hidden transparent +} + +.fc-row:first-child table { + border-top: 0 hidden transparent +} + +.fc-row { + position: relative +} + +.fc-row .fc-bg { + z-index: 1 +} + +.fc-row .fc-bgevent-skeleton td, +.fc-row .fc-highlight-skeleton td { + border-color: transparent +} + +.fc-row .fc-bgevent-skeleton { + z-index: 2 +} + +.fc-row .fc-highlight-skeleton { + z-index: 3 +} + +.fc-row .fc-content-skeleton { + position: relative; + z-index: 4; + padding-bottom: 2px +} + +.fc-row .fc-helper-skeleton { + z-index: 5 +} + +.fc .fc-row .fc-content-skeleton table, +.fc .fc-row .fc-content-skeleton td, +.fc .fc-row .fc-helper-skeleton td { + background: 0 0; + border-color: transparent +} + +.fc-row .fc-content-skeleton td, +.fc-row .fc-helper-skeleton td { + border-bottom: 0 +} + +.fc-row .fc-content-skeleton tbody td, +.fc-row .fc-helper-skeleton tbody td { + border-top: 0 +} + +.fc-scroller { + -webkit-overflow-scrolling: touch +} + +.fc-icon, +.fc-row.fc-rigid, +.fc-time-grid-event { + overflow: hidden +} + +.fc-scroller > .fc-day-grid, +.fc-scroller > .fc-time-grid { + position: relative; + width: 100% +} + +.fc-event { + position: relative; + display: block; + /*font-size: .85em;*/ + font-size: 14px; + line-height: 16px; + border-radius: 3px; + border: 1px solid #3a87ad +} + +.fc-event, +.fc-event-dot { + background-color: #3a87ad +} + +.fc-event, +.fc-event:hover { + color: #fff; + text-decoration: none +} + +.fc-not-allowed, +.fc-not-allowed .fc-event { + cursor: not-allowed +} + +.fc-event .fc-bg { + z-index: 1; + background: #fff; + opacity: .25 +} + +.fc-event .fc-content { + position: relative; + z-index: 2; + padding: 5px; +} + +.fc-event .fc-resizer { + position: absolute; + z-index: 4; + display: none +} + +.fc-event.fc-allow-mouse-resize .fc-resizer, +.fc-event.fc-selected .fc-resizer { + display: block +} + +.fc-event.fc-selected .fc-resizer:before { + content: ""; + position: absolute; + z-index: 9999; + top: 50%; + left: 50%; + width: 40px; + height: 40px; + margin-left: -20px; + margin-top: -20px +} + +.fc-event.fc-selected { + z-index: 9999 !important; + box-shadow: 0 2px 5px rgba(0, 0, 0, .2) +} + +.fc-event.fc-selected.fc-dragging { + box-shadow: 0 2px 7px rgba(0, 0, 0, .3) +} + +.fc-h-event.fc-selected:before { + content: ""; + position: absolute; + z-index: 3; + top: -10px; + bottom: -10px; + left: 0; + right: 0 +} + +.fc-ltr .fc-h-event.fc-not-start, +.fc-rtl .fc-h-event.fc-not-end { + margin-left: 0; + border-left-width: 0; + padding-left: 1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.fc-ltr .fc-h-event.fc-not-end, +.fc-rtl .fc-h-event.fc-not-start { + margin-right: 0; + border-right-width: 0; + padding-right: 1px; + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.fc-ltr .fc-h-event .fc-start-resizer, +.fc-rtl .fc-h-event .fc-end-resizer { + cursor: w-resize; + left: -1px +} + +.fc-ltr .fc-h-event .fc-end-resizer, +.fc-rtl .fc-h-event .fc-start-resizer { + cursor: e-resize; + right: -1px +} + +.fc-h-event.fc-allow-mouse-resize .fc-resizer { + width: 7px; + top: -1px; + bottom: -1px +} + +.fc-h-event.fc-selected .fc-resizer { + border-radius: 4px; + border-width: 1px; + width: 6px; + height: 6px; + border-style: solid; + border-color: inherit; + background: #fff; + top: 50%; + margin-top: -4px +} + +.fc-ltr .fc-h-event.fc-selected .fc-start-resizer, +.fc-rtl .fc-h-event.fc-selected .fc-end-resizer { + margin-left: -4px +} + +.fc-ltr .fc-h-event.fc-selected .fc-end-resizer, +.fc-rtl .fc-h-event.fc-selected .fc-start-resizer { + margin-right: -4px +} + +.fc-day-grid-event { + margin: 1px 2px 0; + padding: 0 1px +} + +tr:first-child > td > .fc-day-grid-event { + margin-top: 2px +} + +.fc-day-grid-event.fc-selected:after { + content: ""; + position: absolute; + z-index: 1; + top: -1px; + right: -1px; + bottom: -1px; + left: -1px; + background: #000; + opacity: .25 +} + +.fc-day-grid-event .fc-content { /* 事件中文本不换行 */ + /*white-space: nowrap; + overflow: hidden*/ +} + +.fc-day-grid-event .fc-time { + font-weight: 700 +} + +.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer, +.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer { + margin-left: -2px +} + +.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer, +.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer { + margin-right: -2px +} + +a.fc-more { + margin: 1px 3px; + font-size: .85em; + cursor: pointer; + text-decoration: none +} + +a.fc-more:hover { + text-decoration: underline +} + +.fc.fc-bootstrap3 a, +.ui-widget .fc-event { + text-decoration: none +} + +.fc-limited { + display: none +} + +.fc-icon, +.fc-toolbar .fc-center { + display: inline-block +} + +.fc-day-grid .fc-row { + z-index: 1 +} + +.fc-more-popover { + z-index: 2; + width: 220px +} + +.fc-more-popover .fc-event-container { + padding: 10px +} + +.fc-now-indicator { + position: absolute; + border: 0 solid red +} + +.fc-icon:after, +.fc-toolbar button { + position: relative +} + +.fc-unselectable { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: transparent +} + +.fc-unthemed .fc-content, +.fc-unthemed .fc-divider, +.fc-unthemed .fc-list-heading td, +.fc-unthemed .fc-list-view, +.fc-unthemed .fc-popover, +.fc-unthemed .fc-row, +.fc-unthemed tbody, +.fc-unthemed td, +.fc-unthemed th, +.fc-unthemed thead { + border-color: #ddd +} + +.fc-unthemed .fc-popover { + background-color: #fff; + border-width: 1px; + border-style: solid +} + +.fc-unthemed .fc-divider, +.fc-unthemed .fc-list-heading td, +.fc-unthemed .fc-popover .fc-header { + background: #eee +} + +.fc-unthemed td.fc-today { + background: #fcf8e3 +} + +.fc-unthemed .fc-disabled-day { + background: #d7d7d7; + opacity: .3 +} + +.fc-icon { + height: 1em; + line-height: 1em; + font-size: 1em; + font-family: "Courier New", Courier, monospace; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none +} + +.fc-icon-left-single-arrow:after { + content: "\02039"; + font-weight: 700; + font-size: 200%; + top: -7% +} + +.fc-icon-right-single-arrow:after { + content: "\0203A"; + font-weight: 700; + font-size: 200%; + top: -7% +} + +.fc-icon-left-double-arrow:after { + content: "\000AB"; + font-size: 160%; + top: -7% +} + +.fc-icon-right-double-arrow:after { + content: "\000BB"; + font-size: 160%; + top: -7% +} + +.fc-icon-left-triangle:after { + content: "\25C4"; + font-size: 125%; + top: 3% +} + +.fc-icon-right-triangle:after { + content: "\25BA"; + font-size: 125%; + top: 3% +} + +.fc-icon-down-triangle:after { + content: "\25BC"; + font-size: 125%; + top: 2% +} + +.fc-icon-x:after { + content: "\000D7"; + font-size: 200%; + top: 6% +} + +.fc-unthemed .fc-popover .fc-header .fc-close { + color: #666; + font-size: .9em; + margin-top: 2px +} + +.fc-unthemed .fc-list-item:hover td { + background-color: #f5f5f5 +} + +.ui-widget .fc-disabled-day { + background-image: none +} + +.fc-bootstrap3 .fc-time-grid .fc-slats table, +.fc-time-grid .fc-slats .ui-widget-content { + background: 0 0 +} + +.fc-popover > .ui-widget-header + .ui-widget-content { + border-top: 0 +} + +.ui-widget .fc-event { + color: #fff; + font-weight: 400 +} + +.ui-widget td.fc-axis { + font-weight: 400 +} + +.fc.fc-bootstrap3 a[data-goto]:hover { + text-decoration: underline +} + +.fc-bootstrap3 hr.fc-divider { + border-color: inherit +} + +.fc-bootstrap3 .fc-today.alert { + border-radius: 0 +} + +.fc-bootstrap3 .fc-popover .panel-body { + padding: 0 +} + +.fc-toolbar.fc-header-toolbar { + margin-bottom: 1em +} + +.fc-toolbar.fc-footer-toolbar { + margin-top: 1em +} + +.fc-toolbar .fc-left { + float: left +} + +.fc-toolbar .fc-right { + float: right +} + +.fc .fc-toolbar > * > * { + float: left; + margin-left: .75em +} + +.fc .fc-toolbar > * > :first-child { + margin-left: 0 +} + +.fc-toolbar h2 { + margin: 0 +} + +.fc-toolbar .fc-state-hover, +.fc-toolbar .ui-state-hover { + z-index: 2 +} + +.fc-toolbar .fc-state-down { + z-index: 3 +} + +.fc-toolbar .fc-state-active, +.fc-toolbar .ui-state-active { + z-index: 4 +} + +.fc-toolbar button:focus { + z-index: 5 +} + +.fc-view-container *, +.fc-view-container :after, +.fc-view-container :before { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box +} + +.fc-view, +.fc-view > table { + position: relative; + z-index: 1 +} + +.fc-basicDay-view .fc-content-skeleton, +.fc-basicWeek-view .fc-content-skeleton { + padding-bottom: 1em +} + +.fc-basic-view .fc-body .fc-row { + min-height: 4em +} + +.fc-row.fc-rigid .fc-content-skeleton { + position: absolute; + top: 0; + left: 0; + right: 0 +} + +.fc-day-top.fc-other-month { + opacity: .3 +} + +.fc-basic-view .fc-day-number, +.fc-basic-view .fc-week-number { + padding: 2px +} + +.fc-basic-view th.fc-day-number, +.fc-basic-view th.fc-week-number { + padding: 0 2px +} + +.fc-ltr .fc-basic-view .fc-day-top .fc-day-number { + float: right +} + +.fc-rtl .fc-basic-view .fc-day-top .fc-day-number { + float: left +} + +.fc-ltr .fc-basic-view .fc-day-top .fc-week-number { + float: left; + border-radius: 0 0 3px +} + +.fc-rtl .fc-basic-view .fc-day-top .fc-week-number { + float: right; + border-radius: 0 0 0 3px +} + +.fc-basic-view .fc-day-top .fc-week-number { + min-width: 1.5em; + text-align: center; + background-color: #f2f2f2; + color: grey +} + +.fc-basic-view td.fc-week-number > * { + display: inline-block; + min-width: 1.25em +} + +.fc-agenda-view .fc-day-grid { + position: relative; + z-index: 2 +} + +.fc-agenda-view .fc-day-grid .fc-row { + min-height: 3em +} + +.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton { + padding-bottom: 1em +} + +.fc .fc-axis { + vertical-align: middle; + padding: 0 4px; + white-space: nowrap +} + +.fc-ltr .fc-axis { + text-align: right +} + +.fc-rtl .fc-axis { + text-align: left +} + +.fc-time-grid, +.fc-time-grid-container { + position: relative; + z-index: 1 +} + +.fc-time-grid { + min-height: 100% +} + +.fc-time-grid table { + border: 0 hidden transparent +} + +.fc-time-grid > .fc-bg { + z-index: 1 +} + +.fc-time-grid .fc-slats, +.fc-time-grid > hr { + position: relative; + z-index: 2 +} + +.fc-time-grid .fc-content-col { + position: relative +} + +.fc-time-grid .fc-content-skeleton { + position: absolute; + z-index: 3; + top: 0; + left: 0; + right: 0 +} + +.fc-time-grid .fc-business-container { + position: relative; + z-index: 1 +} + +.fc-time-grid .fc-bgevent-container { + position: relative; + z-index: 2 +} + +.fc-time-grid .fc-highlight-container { + z-index: 3; + position: relative +} + +.fc-time-grid .fc-event-container { + position: relative; + z-index: 4 +} + +.fc-time-grid .fc-now-indicator-line { + z-index: 5 +} + +.fc-time-grid .fc-helper-container { + position: relative; + z-index: 6 +} + +.fc-time-grid .fc-slats td { + height: 1.5em; + border-bottom: 0 +} + +.fc-time-grid .fc-slats .fc-minor td { + border-top-style: dotted +} + +.fc-time-grid .fc-highlight { + position: absolute; + left: 0; + right: 0 +} + +.fc-ltr .fc-time-grid .fc-event-container { + margin: 0 2.5% 0 2px +} + +.fc-rtl .fc-time-grid .fc-event-container { + margin: 0 2px 0 2.5% +} + +.fc-time-grid .fc-bgevent, +.fc-time-grid .fc-event { + position: absolute; + z-index: 1 +} + +.fc-time-grid .fc-bgevent { + left: 0; + right: 0 +} + +.fc-v-event.fc-not-start { + border-top-width: 0; + padding-top: 1px; + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.fc-v-event.fc-not-end { + border-bottom-width: 0; + padding-bottom: 1px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0 +} + +.fc-time-grid-event.fc-selected { + overflow: visible +} + +.fc-time-grid-event.fc-selected .fc-bg { + display: none +} + +.fc-time-grid-event .fc-content { + overflow: hidden +} + +.fc-time-grid-event .fc-time, +.fc-time-grid-event .fc-title { + padding: 0 1px +} + +.fc-time-grid-event .fc-time { + font-size: .85em; + white-space: nowrap +} + +.fc-time-grid-event.fc-short .fc-content { + white-space: nowrap +} + +.fc-time-grid-event.fc-short .fc-time, +.fc-time-grid-event.fc-short .fc-title { + display: inline-block; + vertical-align: top +} + +.fc-time-grid-event.fc-short .fc-time span { + display: none +} + +.fc-time-grid-event.fc-short .fc-time:before { + content: attr(data-start) +} + +.fc-time-grid-event.fc-short .fc-time:after { + content: "\000A0-\000A0" +} + +.fc-time-grid-event.fc-short .fc-title { + font-size: .85em; + padding: 0 +} + +.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer { + left: 0; + right: 0; + bottom: 0; + height: 8px; + overflow: hidden; + line-height: 8px; + font-size: 11px; + font-family: monospace; + text-align: center; + cursor: s-resize +} + +.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after { + content: "=" +} + +.fc-time-grid-event.fc-selected .fc-resizer { + border-radius: 5px; + border-width: 1px; + width: 8px; + height: 8px; + border-style: solid; + border-color: inherit; + background: #fff; + left: 50%; + margin-left: -5px; + bottom: -5px +} + +.fc-time-grid .fc-now-indicator-line { + border-top-width: 1px; + left: 0; + right: 0 +} + +.fc-time-grid .fc-now-indicator-arrow { + margin-top: -5px +} + +.fc-ltr .fc-time-grid .fc-now-indicator-arrow { + left: 0; + border-width: 5px 0 5px 6px; + border-top-color: transparent; + border-bottom-color: transparent +} + +.fc-rtl .fc-time-grid .fc-now-indicator-arrow { + right: 0; + border-width: 5px 6px 5px 0; + border-top-color: transparent; + border-bottom-color: transparent +} + +.fc-event-dot { + display: inline-block; + width: 10px; + height: 10px; + border-radius: 5px +} + +.fc-rtl .fc-list-view { + direction: rtl +} + +.fc-list-view { + border-width: 1px; + border-style: solid +} + +.fc .fc-list-table { + table-layout: auto +} + +.fc-list-table td { + border-width: 1px 0 0; + padding: 8px 14px +} + +.fc-list-table tr:first-child td { + border-top-width: 0 +} + +.fc-list-heading { + border-bottom-width: 1px +} + +.fc-list-heading td { + font-weight: 700 +} + +.fc-ltr .fc-list-heading-main { + float: left +} + +.fc-ltr .fc-list-heading-alt, +.fc-rtl .fc-list-heading-main { + float: right +} + +.fc-rtl .fc-list-heading-alt { + float: left +} + +.fc-list-item.fc-has-url { + cursor: pointer +} + +.fc-list-item-marker, +.fc-list-item-time { + white-space: nowrap; + width: 1px +} + +.fc-ltr .fc-list-item-marker { + padding-right: 0 +} + +.fc-rtl .fc-list-item-marker { + padding-left: 0 +} + +.fc-list-item-title a { + text-decoration: none; + color: inherit +} + +.fc-list-item-title a[href]:hover { + text-decoration: underline +} + +.fc-list-empty-wrap2 { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0 +} + +.fc-list-empty-wrap1 { + width: 100%; + height: 100%; + display: table +} + +.fc-list-empty { + display: table-cell; + vertical-align: middle; + text-align: center +} + +.fc-unthemed .fc-list-empty { + background-color: #eee +} diff --git a/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.min.css b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.min.css new file mode 100644 index 00000000..2c96000b --- /dev/null +++ b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.min.css @@ -0,0 +1,5 @@ +/*! + * FullCalendar v3.6.1 Stylesheet + * Docs & License: https://fullcalendar.io/ + * (c) 2017 Adam Shaw + */.fc button,.fc table,body .fc{font-size:1em}.fc-bg,.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-icon,.fc-unselectable{-webkit-touch-callout:none;-khtml-user-select:none}.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}.fc th,.fc-basic-view td.fc-week-number,.fc-icon,.fc-toolbar{text-align:center}.fc-highlight{background:#bce8f1;opacity:.3}.fc-bgevent{background:#8fdf82;opacity:.3}.fc-nonbusiness{background:#d7d7d7}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;white-space:nowrap;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;box-shadow:none}.fc-event.fc-draggable,.fc-event[href],.fc-popover .fc-header .fc-close,a[data-goto]{cursor:pointer}.fc-button-group{display:inline-block}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-bg table,.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc table{width:100%;box-sizing:border-box;table-layout:fixed;border-collapse:collapse;border-spacing:0}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}a[data-goto]:hover{text-decoration:underline}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc .fc-row .fc-content-skeleton table,.fc .fc-row .fc-content-skeleton td,.fc .fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{-webkit-overflow-scrolling:touch}.fc-icon,.fc-row.fc-rigid,.fc-time-grid-event{overflow:hidden}.fc-scroller>.fc-day-grid,.fc-scroller>.fc-time-grid{position:relative;width:100%}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad}.fc-event,.fc-event-dot{background-color:#3a87ad}.fc-event,.fc-event:hover{color:#fff;text-decoration:none}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:4;display:none}.fc-event.fc-allow-mouse-resize .fc-resizer,.fc-event.fc-selected .fc-resizer{display:block}.fc-event.fc-selected .fc-resizer:before{content:"";position:absolute;z-index:9999;top:50%;left:50%;width:40px;height:40px;margin-left:-20px;margin-top:-20px}.fc-event.fc-selected{z-index:9999!important;box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event.fc-selected.fc-dragging{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-h-event.fc-selected:before{content:"";position:absolute;z-index:3;top:-10px;bottom:-10px;left:0;right:0}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-ltr .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-end-resizer{cursor:w-resize;left:-1px}.fc-ltr .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-start-resizer{cursor:e-resize;right:-1px}.fc-h-event.fc-allow-mouse-resize .fc-resizer{width:7px;top:-1px;bottom:-1px}.fc-h-event.fc-selected .fc-resizer{border-radius:4px;border-width:1px;width:6px;height:6px;border-style:solid;border-color:inherit;background:#fff;top:50%;margin-top:-4px}.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,.fc-rtl .fc-h-event.fc-selected .fc-end-resizer{margin-left:-4px}.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,.fc-rtl .fc-h-event.fc-selected .fc-start-resizer{margin-right:-4px}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}tr:first-child>td>.fc-day-grid-event{margin-top:2px}.fc-day-grid-event.fc-selected:after{content:"";position:absolute;z-index:1;top:-1px;right:-1px;bottom:-1px;left:-1px;background:#000;opacity:.25}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer{margin-left:-2px}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer{margin-right:-2px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc.fc-bootstrap3 a,.ui-widget .fc-event{text-decoration:none}.fc-limited{display:none}.fc-icon,.fc-toolbar .fc-center{display:inline-block}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-now-indicator{position:absolute;border:0 solid red}.fc-icon:after,.fc-toolbar button{position:relative}.fc-unselectable{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.fc-unthemed .fc-content,.fc-unthemed .fc-divider,.fc-unthemed .fc-list-heading td,.fc-unthemed .fc-list-view,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff;border-width:1px;border-style:solid}.fc-unthemed .fc-divider,.fc-unthemed .fc-list-heading td,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed td.fc-today{background:#fcf8e3}.fc-unthemed .fc-disabled-day{background:#d7d7d7;opacity:.3}.fc-icon{height:1em;line-height:1em;font-size:1em;font-family:"Courier New",Courier,monospace;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666;font-size:.9em;margin-top:2px}.fc-unthemed .fc-list-item:hover td{background-color:#f5f5f5}.ui-widget .fc-disabled-day{background-image:none}.fc-bootstrap3 .fc-time-grid .fc-slats table,.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.ui-widget .fc-event{color:#fff;font-weight:400}.ui-widget td.fc-axis{font-weight:400}.fc.fc-bootstrap3 a[data-goto]:hover{text-decoration:underline}.fc-bootstrap3 hr.fc-divider{border-color:inherit}.fc-bootstrap3 .fc-today.alert{border-radius:0}.fc-bootstrap3 .fc-popover .panel-body{padding:0}.fc-toolbar.fc-header-toolbar{margin-bottom:1em}.fc-toolbar.fc-footer-toolbar{margin-top:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-day-top.fc-other-month{opacity:.3}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:2px}.fc-basic-view th.fc-day-number,.fc-basic-view th.fc-week-number{padding:0 2px}.fc-ltr .fc-basic-view .fc-day-top .fc-day-number{float:right}.fc-rtl .fc-basic-view .fc-day-top .fc-day-number{float:left}.fc-ltr .fc-basic-view .fc-day-top .fc-week-number{float:left;border-radius:0 0 3px}.fc-rtl .fc-basic-view .fc-day-top .fc-week-number{float:right;border-radius:0 0 0 3px}.fc-basic-view .fc-day-top .fc-week-number{min-width:1.5em;text-align:center;background-color:#f2f2f2;color:grey}.fc-basic-view td.fc-week-number>*{display:inline-block;min-width:1.25em}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px;white-space:nowrap}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3;position:relative}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-helper-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event.fc-selected{overflow:visible}.fc-time-grid-event.fc-selected .fc-bg{display:none}.fc-time-grid-event .fc-content{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em;white-space:nowrap}.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after{content:"="}.fc-time-grid-event.fc-selected .fc-resizer{border-radius:5px;border-width:1px;width:8px;height:8px;border-style:solid;border-color:inherit;background:#fff;left:50%;margin-left:-5px;bottom:-5px}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent}.fc-event-dot{display:inline-block;width:10px;height:10px;border-radius:5px}.fc-rtl .fc-list-view{direction:rtl}.fc-list-view{border-width:1px;border-style:solid}.fc .fc-list-table{table-layout:auto}.fc-list-table td{border-width:1px 0 0;padding:8px 14px}.fc-list-table tr:first-child td{border-top-width:0}.fc-list-heading{border-bottom-width:1px}.fc-list-heading td{font-weight:700}.fc-ltr .fc-list-heading-main{float:left}.fc-ltr .fc-list-heading-alt,.fc-rtl .fc-list-heading-main{float:right}.fc-rtl .fc-list-heading-alt{float:left}.fc-list-item.fc-has-url{cursor:pointer}.fc-list-item-marker,.fc-list-item-time{white-space:nowrap;width:1px}.fc-ltr .fc-list-item-marker{padding-right:0}.fc-rtl .fc-list-item-marker{padding-left:0}.fc-list-item-title a{text-decoration:none;color:inherit}.fc-list-item-title a[href]:hover{text-decoration:underline}.fc-list-empty-wrap2{position:absolute;top:0;left:0;right:0;bottom:0}.fc-list-empty-wrap1{width:100%;height:100%;display:table}.fc-list-empty{display:table-cell;vertical-align:middle;text-align:center}.fc-unthemed .fc-list-empty{background-color:#eee} diff --git a/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.min.js b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.min.js new file mode 100644 index 00000000..a22c84bc --- /dev/null +++ b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.min.js @@ -0,0 +1,11 @@ +/*! + * FullCalendar v3.6.1 + * Docs & License: https://fullcalendar.io/ + * (c) 2017 Adam Shaw + */ +!function(t){"function"==typeof define&&define.amd?define(["jquery","moment"],t):"object"==typeof exports?module.exports=t(require("jquery"),require("moment")):t(jQuery,moment)}(function(t,e){function n(t){return j(t,qt)}function i(t,e){e.left&&t.css({"border-left-width":1,"margin-left":e.left-1}),e.right&&t.css({"border-right-width":1,"margin-right":e.right-1})}function r(t){t.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function s(){t("body").addClass("fc-not-allowed")}function o(){t("body").removeClass("fc-not-allowed")}function a(e,n,i){var r=Math.floor(n/e.length),s=Math.floor(n-r*(e.length-1)),o=[],a=[],u=[],c=0;l(e),e.each(function(n,i){var l=n===e.length-1?s:r,h=t(i).outerHeight(!0);h *").each(function(e,i){var r=t(i).outerWidth();r>n&&(n=r)}),n++,e.width(n),n}function c(t,e){var n,i=t.add(e);return i.css({position:"relative",left:-1}),n=t.outerHeight()-e.outerHeight(),i.css({position:"",left:""}),n}function h(e){var n=e.css("position"),i=e.parents().filter(function(){var e=t(this);return/(auto|scroll)/.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==n&&i.length?i:t(e[0].ownerDocument||document)}function d(t,e){var n=t.offset(),i=n.left-(e?e.left:0),r=n.top-(e?e.top:0);return{left:i,right:i+t.outerWidth(),top:r,bottom:r+t.outerHeight()}}function f(t,e){var n=t.offset(),i=p(t),r=n.left+w(t,"border-left-width")+i.left-(e?e.left:0),s=n.top+w(t,"border-top-width")+i.top-(e?e.top:0);return{left:r,right:r+t[0].clientWidth,top:s,bottom:s+t[0].clientHeight}}function g(t,e){var n=t.offset(),i=n.left+w(t,"border-left-width")+w(t,"padding-left")-(e?e.left:0),r=n.top+w(t,"border-top-width")+w(t,"padding-top")-(e?e.top:0);return{left:i,right:i+t.width(),top:r,bottom:r+t.height()}}function p(t){var e,n=t[0].offsetWidth-t[0].clientWidth,i=t[0].offsetHeight-t[0].clientHeight;return n=v(n),i=v(i),e={left:0,right:0,top:0,bottom:i},m()&&"rtl"==t.css("direction")?e.left=n:e.right=n,e}function v(t){return t=Math.max(0,t),t=Math.round(t)}function m(){return null===Yt&&(Yt=y()),Yt}function y(){var e=t("
").css({position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}).appendTo("body"),n=e.children(),i=n.offset().left>e.offset().left;return e.remove(),i}function w(t,e){return parseFloat(t.css(e))||0}function D(t){return 1==t.which&&!t.ctrlKey}function b(t){var e=t.originalEvent.touches;return e&&e.length?e[0].pageX:t.pageX}function E(t){var e=t.originalEvent.touches;return e&&e.length?e[0].pageY:t.pageY}function S(t){return/^touch/.test(t.type)}function C(t){t.addClass("fc-unselectable").on("selectstart",T)}function R(t){t.removeClass("fc-unselectable").off("selectstart",T)}function T(t){t.preventDefault()}function I(t,e){var n={left:Math.max(t.left,e.left),right:Math.min(t.right,e.right),top:Math.max(t.top,e.top),bottom:Math.min(t.bottom,e.bottom)};return n.left=1&&at(r)));n++);return i}function N(t,e){var n=O(t);return"week"===n&&"object"==typeof e&&e.days&&(n="day"),n}function V(t,n,i){return null!=i?i.diff(n,t,!0):e.isDuration(n)?n.as(t):n.end.diff(n.start,t,!0)}function G(t,e,n){var i;return _(n)?(e-t)/n:(i=n.asMonths(),Math.abs(i)>=1&&at(i)?e.diff(t,"months",!0)/i:e.diff(t,"days",!0)/n.asDays())}function U(t,e){var n,i;return _(t)||_(e)?t/e:(n=t.asMonths(),i=e.asMonths(),Math.abs(n)>=1&&at(n)&&Math.abs(i)>=1&&at(i)?n/i:t.asDays()/e.asDays())}function W(t,n){var i;return _(t)?e.duration(t*n):(i=t.asMonths(),Math.abs(i)>=1&&at(i)?e.duration({months:i*n}):e.duration({days:t.asDays()*n}))}function _(t){return Boolean(t.hours()||t.minutes()||t.seconds()||t.milliseconds())}function q(t){return"[object Date]"===Object.prototype.toString.call(t)||t instanceof Date}function Y(t){return"string"==typeof t&&/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(t)}function j(t,e){var n,i,r,s,o,a,l={};if(e)for(n=0;n=0;s--)if("object"==typeof(o=t[s][i]))r.unshift(o);else if(void 0!==o){l[i]=o;break}r.length&&(l[i]=j(r))}for(n=t.length-1;n>=0;n--){a=t[n];for(i in a)i in l||(l[i]=a[i])}return l}function Z(t,e){for(var n in t)Q(t,n)&&(e[n]=t[n])}function Q(t,e){return Qt.call(t,e)}function $(e,n,i){if(t.isFunction(e)&&(e=[e]),e){var r,s;for(r=0;r/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"
")}function nt(t){return t.replace(/&.*?;/g,"")}function it(e){var n=[];return t.each(e,function(t,e){null!=e&&n.push(t+":"+e)}),n.join(";")}function rt(e){var n=[];return t.each(e,function(t,e){null!=e&&n.push(t+'="'+et(e)+'"')}),n.join(" ")}function st(t){return t.charAt(0).toUpperCase()+t.slice(1)}function ot(t,e){return t-e}function at(t){return t%1==0}function lt(t,e){var n=t[e];return function(){return n.apply(t,arguments)}}function ut(t,e,n){var i,r,s,o,a,l=function(){var u=+new Date-o;u"),g.append(o("left")).append(o("right")).append(o("center")).append('
')):s()}function s(){g&&(g.remove(),g=f.el=null)}function o(i){var r=e.theme,s=t('
'),o=n.layout[i],a=e.opt("customButtons")||{},l=e.overrides.buttonText||{},u=e.opt("buttonText")||{};return o&&t.each(o.split(" "),function(n){var i,o=t(),c=!0;t.each(this.split(","),function(n,i){var s,h,d,f,g,v,m,y;"title"==i?(o=o.add(t("

 

")),c=!1):((s=a[i])?(d=function(t){s.click&&s.click.call(y[0],t)},(f=r.getCustomButtonIconClass(s))||(f=r.getIconClass(i))||(g=s.text)):(h=e.getViewSpec(i))?(p.push(i),d=function(){e.changeView(i)},(g=h.buttonTextOverride)||(f=r.getIconClass(i))||(g=h.buttonTextDefault)):e[i]&&(d=function(){e[i]()},(g=l[i])||(f=r.getIconClass(i))||(g=u[i])),d&&(m=["fc-"+i+"-button",r.getClass("button"),r.getClass("stateDefault")],g?v=et(g):f&&(v=""),y=t('").click(function(t){y.hasClass(r.getClass("stateDisabled"))||(d(t),(y.hasClass(r.getClass("stateActive"))||y.hasClass(r.getClass("stateDisabled")))&&y.removeClass(r.getClass("stateHover")))}).mousedown(function(){y.not("."+r.getClass("stateActive")).not("."+r.getClass("stateDisabled")).addClass(r.getClass("stateDown"))}).mouseup(function(){y.removeClass(r.getClass("stateDown"))}).hover(function(){y.not("."+r.getClass("stateActive")).not("."+r.getClass("stateDisabled")).addClass(r.getClass("stateHover"))},function(){y.removeClass(r.getClass("stateHover")).removeClass(r.getClass("stateDown"))}),o=o.add(y)))}),c&&o.first().addClass(r.getClass("cornerLeft")).end().last().addClass(r.getClass("cornerRight")).end(),o.length>1?(i=t("
"),c&&i.addClass(r.getClass("buttonGroup")),i.append(o),s.append(i)):s.append(o)}),s}function a(t){g&&g.find("h2").text(t)}function l(t){g&&g.find(".fc-"+t+"-button").addClass(e.theme.getClass("stateActive"))}function u(t){g&&g.find(".fc-"+t+"-button").removeClass(e.theme.getClass("stateActive"))}function c(t){g&&g.find(".fc-"+t+"-button").prop("disabled",!0).addClass(e.theme.getClass("stateDisabled"))}function h(t){g&&g.find(".fc-"+t+"-button").prop("disabled",!1).removeClass(e.theme.getClass("stateDisabled"))}function d(){return p}var f=this;f.setToolbarOptions=i,f.render=r,f.removeElement=s,f.updateTitle=a,f.activateButton=l,f.deactivateButton=u,f.disableButton=c,f.enableButton=h,f.getViewsWithButtons=d,f.el=null;var g,p=[]}function Et(t,e,n){var i;for(i=0;is&&r.push(new Ue(s,i.startMs)),i.endMs>s&&(s=i.endMs);return s=t.leftCol)return!0;return!1}function At(t,e){return t.leftCol-e.leftCol}function Lt(t){var e,n,i,r=[];for(e=0;ee.top&&t.tops&&(!l[o]||u.isSame(c,l[o]))&&(o-1!==s||"."!==f[o]);o--)v=f[o]+v;for(a=s;a<=o;a++)m+=f[a],y+=g[a];return(m||y)&&(w=r?y+i+m:m+i+y),d(p+w+v)}function r(t){return D[t]||(D[t]=s(t))}function s(t){var e=o(t);return{fakeFormatString:l(e),sameUnits:u(e)}}function o(t){for(var e,n=[],i=/\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;e=i.exec(t);)e[1]?n.push.apply(n,a(e[1])):e[2]?n.push({maybe:o(e[2])}):e[3]?n.push({token:e[3]}):e[5]&&n.push.apply(n,a(e[5]));return n}function a(t){return". "===t?["."," "]:[t]}function l(t){var e,n,i=[];for(e=0;er.value)&&(r=i);return r?r.unit:null}Wt.formatDate=t,Wt.formatRange=n,Wt.oldMomentFormat=e,Wt.queryMostGranularFormatUnit=f;var g="\v",p="",v="",m=new RegExp(v+"([^"+v+"]*)"+v,"g"),y={t:function(t){return e(t,"a").charAt(0)},T:function(t){return e(t,"A").charAt(0)}},w={Y:{value:1,unit:"year"},M:{value:2,unit:"month"},W:{value:3,unit:"week"},w:{value:3,unit:"week"},D:{value:4,unit:"day"},d:{value:4,unit:"day"}},D={}}();var ee=Wt.formatDate,ne=Wt.formatRange,ie=Wt.oldMomentFormat;Wt.Class=dt,dt.extend=function(){var t,e={};for(t=0;t0}},se=Wt.ListenerMixin=function(){var e=0;return{listenerId:null,listenTo:function(e,n,i){if("object"==typeof n)for(var r in n)n.hasOwnProperty(r)&&this.listenTo(e,r,n[r]);else"string"==typeof n&&e.on(n+"."+this.getListenerNamespace(),t.proxy(i,this))},stopListeningTo:function(t,e){t.off((e||"")+"."+this.getListenerNamespace())},getListenerNamespace:function(){return null==this.listenerId&&(this.listenerId=e++),"_listener"+this.listenerId}}}(),oe={standardPropMap:{},applyProps:function(t){var e,n=this.standardPropMap,i={},r={};for(e in t)!0===n[e]?this[e]=t[e]:!1===n[e]?i[e]=t[e]:r[e]=t[e];return this.applyMiscProps(r),this.applyManualStandardProps(i)},applyManualStandardProps:function(t){return!0},applyMiscProps:function(t){},isStandardProp:function(t){return t in this.standardPropMap}},ae=function(t){var e=this.prototype;e.hasOwnProperty("standardPropMap")||(e.standardPropMap=Object.create(e.standardPropMap)),Z(t,e.standardPropMap)},le=function(t,e){var n,i=this.prototype.standardPropMap;for(n in i)null!=t[n]&&!0===i[n]&&(e[n]=t[n])},ue=dt.extend(re,se,{_props:null,_watchers:null,_globalWatchArgs:{},constructor:function(){this._watchers={},this._props={},this.applyGlobalWatchers(),this.constructed()},constructed:function(){},applyGlobalWatchers:function(){var t,e=this._globalWatchArgs;for(t in e)this.watch.apply(this,e[t])},has:function(t){return t in this._props},get:function(t){return void 0===t?this._props:this._props[t]},set:function(t,e){var n;"string"==typeof t?(n={},n[t]=void 0===e?null:e):n=t,this.setProps(n)},reset:function(t){var e,n=this._props,i={};for(e in n)i[e]=void 0;for(e in t)i[e]=t[e];this.setProps(i)},unset:function(t){var e,n,i={};for(e="string"==typeof t?[t]:t,n=0;n=0;e--)switch(n=i[e],n.type){case"init":r=!1;case"add":case"remove":i.splice(e,1)}return r&&i.push(t),r}});Wt.RenderQueue=de;var fe=dt.extend(se,{isHidden:!0,options:null,el:null,margin:10,constructor:function(t){this.options=t||{}},show:function(){this.isHidden&&(this.el||this.render(),this.el.show(),this.position(),this.isHidden=!1,this.trigger("show"))},hide:function(){this.isHidden||(this.el.hide(),this.isHidden=!0,this.trigger("hide"))},render:function(){var e=this,n=this.options;this.el=t('
').addClass(n.className||"").css({top:0,left:0}).append(n.content).appendTo(n.parentEl),this.el.on("click",".fc-close",function(){e.hide()}),n.autoHide&&this.listenTo(t(document),"mousedown",this.documentMousedown)},documentMousedown:function(e){this.el&&!t(e.target).closest(this.el).length&&this.hide()},removeElement:function(){this.hide(),this.el&&(this.el.remove(),this.el=null),this.stopListeningTo(t(document),"mousedown")},position:function(){var e,n,i,r,s,o=this.options,a=this.el.offsetParent().offset(),l=this.el.outerWidth(),u=this.el.outerHeight(),c=t(window),d=h(this.el);r=o.top||0,s=void 0!==o.left?o.left:void 0!==o.right?o.right-l:0,d.is(window)||d.is(document)?(d=c,e=0,n=0):(i=d.offset(),e=i.top,n=i.left),e+=c.scrollTop(),n+=c.scrollLeft(),!1!==o.viewportConstrain&&(r=Math.min(r,e+d.outerHeight()-u-this.margin),r=Math.max(r,e+this.margin),s=Math.min(s,n+d.outerWidth()-l-this.margin),s=Math.max(s,n+this.margin)),this.el.css({top:r-a.top,left:s-a.left})},trigger:function(t){this.options[t]&&this.options[t].apply(this,Array.prototype.slice.call(arguments,1))}}),ge=Wt.CoordCache=dt.extend({els:null,forcedOffsetParentEl:null,origin:null,boundingRect:null,isHorizontal:!1,isVertical:!1,lefts:null,rights:null,tops:null,bottoms:null,constructor:function(e){this.els=t(e.els),this.isHorizontal=e.isHorizontal,this.isVertical=e.isVertical,this.forcedOffsetParentEl=e.offsetParent?t(e.offsetParent):null},build:function(){var t=this.forcedOffsetParentEl;!t&&this.els.length>0&&(t=this.els.eq(0).offsetParent()),this.origin=t?t.offset():null,this.boundingRect=this.queryBoundingRect(),this.isHorizontal&&this.buildElHorizontals(),this.isVertical&&this.buildElVerticals()},clear:function(){this.origin=null,this.boundingRect=null,this.lefts=null,this.rights=null,this.tops=null,this.bottoms=null},ensureBuilt:function(){this.origin||this.build()},buildElHorizontals:function(){var e=[],n=[];this.els.each(function(i,r){var s=t(r),o=s.offset().left,a=s.outerWidth();e.push(o),n.push(o+a)}),this.lefts=e,this.rights=n},buildElVerticals:function(){var e=[],n=[];this.els.each(function(i,r){var s=t(r),o=s.offset().top,a=s.outerHeight();e.push(o),n.push(o+a)}),this.tops=e,this.bottoms=n},getHorizontalIndex:function(t){this.ensureBuilt();var e,n=this.lefts,i=this.rights,r=n.length;for(e=0;e=n[e]&&t=n[e]&&t0&&(t=h(this.els.eq(0)),!t.is(document))?f(t):null},isPointInBounds:function(t,e){return this.isLeftInBounds(t)&&this.isTopInBounds(e)},isLeftInBounds:function(t){return!this.boundingRect||t>=this.boundingRect.left&&t=this.boundingRect.top&&t=i*i&&this.handleDistanceSurpassed(t),this.isDragging&&this.handleDrag(e,n,t)},handleDrag:function(t,e,n){this.trigger("drag",t,e,n),this.updateAutoScroll(n)},endDrag:function(t){this.isDragging&&(this.isDragging=!1,this.handleDragEnd(t))},handleDragEnd:function(t){this.trigger("dragEnd",t)},startDelay:function(t){var e=this;this.delay?this.delayTimeoutId=setTimeout(function(){e.handleDelayEnd(t)},this.delay):this.handleDelayEnd(t)},handleDelayEnd:function(t){this.isDelayEnded=!0,this.isDistanceSurpassed&&this.startDrag(t)},handleDistanceSurpassed:function(t){this.isDistanceSurpassed=!0,this.isDelayEnded&&this.startDrag(t)},handleTouchMove:function(t){this.isDragging&&this.shouldCancelTouchScroll&&t.preventDefault(),this.handleMove(t)},handleMouseMove:function(t){this.handleMove(t)},handleTouchScroll:function(t){this.isDragging&&!this.scrollAlwaysKills||this.endInteraction(t,!0)},trigger:function(t){this.options[t]&&this.options[t].apply(this,Array.prototype.slice.call(arguments,1)),this["_"+t]&&this["_"+t].apply(this,Array.prototype.slice.call(arguments,1))}});pe.mixin({isAutoScroll:!1,scrollBounds:null,scrollTopVel:null,scrollLeftVel:null,scrollIntervalId:null,scrollSensitivity:30,scrollSpeed:200,scrollIntervalMs:50,initAutoScroll:function(){var t=this.scrollEl;this.isAutoScroll=this.options.scroll&&t&&!t.is(window)&&!t.is(document),this.isAutoScroll&&this.listenTo(t,"scroll",ut(this.handleDebouncedScroll,100))},destroyAutoScroll:function(){this.endAutoScroll(),this.isAutoScroll&&this.stopListeningTo(this.scrollEl,"scroll")},computeScrollBounds:function(){this.isAutoScroll&&(this.scrollBounds=d(this.scrollEl))},updateAutoScroll:function(t){var e,n,i,r,s=this.scrollSensitivity,o=this.scrollBounds,a=0,l=0;o&&(e=(s-(E(t)-o.top))/s,n=(s-(o.bottom-E(t)))/s,i=(s-(b(t)-o.left))/s,r=(s-(o.right-b(t)))/s,e>=0&&e<=1?a=e*this.scrollSpeed*-1:n>=0&&n<=1&&(a=n*this.scrollSpeed),i>=0&&i<=1?l=i*this.scrollSpeed*-1:r>=0&&r<=1&&(l=r*this.scrollSpeed)),this.setScrollVel(a,l)},setScrollVel:function(t,e){this.scrollTopVel=t,this.scrollLeftVel=e,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(lt(this,"scrollIntervalFunc"),this.scrollIntervalMs))},constrainScrollVel:function(){var t=this.scrollEl;this.scrollTopVel<0?t.scrollTop()<=0&&(this.scrollTopVel=0):this.scrollTopVel>0&&t.scrollTop()+t[0].clientHeight>=t[0].scrollHeight&&(this.scrollTopVel=0),this.scrollLeftVel<0?t.scrollLeft()<=0&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&t.scrollLeft()+t[0].clientWidth>=t[0].scrollWidth&&(this.scrollLeftVel=0)},scrollIntervalFunc:function(){var t=this.scrollEl,e=this.scrollIntervalMs/1e3;this.scrollTopVel&&t.scrollTop(t.scrollTop()+this.scrollTopVel*e),this.scrollLeftVel&&t.scrollLeft(t.scrollLeft()+this.scrollLeftVel*e),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.endAutoScroll()},endAutoScroll:function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.handleScrollEnd())},handleDebouncedScroll:function(){this.scrollIntervalId||this.handleScrollEnd()},handleScrollEnd:function(){}});var ve=pe.extend({component:null,origHit:null,hit:null,coordAdjust:null,constructor:function(t,e){pe.call(this,e),this.component=t},handleInteractionStart:function(t){var e,n,i,r=this.subjectEl;this.component.hitsNeeded(),this.computeScrollBounds(),t?(n={left:b(t),top:E(t)},i=n,r&&(e=d(r),i=H(i,e)),this.origHit=this.queryHit(i.left,i.top),r&&this.options.subjectCenter&&(this.origHit&&(e=I(this.origHit,e)||e),i=M(e)),this.coordAdjust=x(i,n)):(this.origHit=null,this.coordAdjust=null),pe.prototype.handleInteractionStart.apply(this,arguments)},handleDragStart:function(t){var e;pe.prototype.handleDragStart.apply(this,arguments),(e=this.queryHit(b(t),E(t)))&&this.handleHitOver(e)},handleDrag:function(t,e,n){var i;pe.prototype.handleDrag.apply(this,arguments),i=this.queryHit(b(n),E(n)),vt(i,this.hit)||(this.hit&&this.handleHitOut(),i&&this.handleHitOver(i))},handleDragEnd:function(){this.handleHitDone(),pe.prototype.handleDragEnd.apply(this,arguments)},handleHitOver:function(t){var e=vt(t,this.origHit);this.hit=t,this.trigger("hitOver",this.hit,e,this.origHit)},handleHitOut:function(){this.hit&&(this.trigger("hitOut",this.hit),this.handleHitDone(),this.hit=null)},handleHitDone:function(){this.hit&&this.trigger("hitDone",this.hit)},handleInteractionEnd:function(){pe.prototype.handleInteractionEnd.apply(this,arguments),this.origHit=null,this.hit=null,this.component.hitsNotNeeded()},handleScrollEnd:function(){pe.prototype.handleScrollEnd.apply(this,arguments),this.isDragging&&(this.component.releaseHits(),this.component.prepareHits())},queryHit:function(t,e){return this.coordAdjust&&(t+=this.coordAdjust.left,e+=this.coordAdjust.top),this.component.queryHit(t,e)}});Wt.touchMouseIgnoreWait=500;var me=dt.extend(se,re,{isTouching:!1,mouseIgnoreDepth:0,handleScrollProxy:null,bind:function(){var e=this;this.listenTo(t(document),{touchstart:this.handleTouchStart,touchcancel:this.handleTouchCancel,touchend:this.handleTouchEnd,mousedown:this.handleMouseDown,mousemove:this.handleMouseMove,mouseup:this.handleMouseUp,click:this.handleClick,selectstart:this.handleSelectStart,contextmenu:this.handleContextMenu}),window.addEventListener("touchmove",this.handleTouchMoveProxy=function(n){e.handleTouchMove(t.Event(n))},{passive:!1}),window.addEventListener("scroll",this.handleScrollProxy=function(n){e.handleScroll(t.Event(n))},!0)},unbind:function(){this.stopListeningTo(t(document)),window.removeEventListener("touchmove",this.handleTouchMoveProxy),window.removeEventListener("scroll",this.handleScrollProxy,!0)},handleTouchStart:function(t){this.stopTouch(t,!0),this.isTouching=!0,this.trigger("touchstart",t)},handleTouchMove:function(t){this.isTouching&&this.trigger("touchmove",t)},handleTouchCancel:function(t){this.isTouching&&(this.trigger("touchcancel",t),this.stopTouch(t))},handleTouchEnd:function(t){this.stopTouch(t)},handleMouseDown:function(t){this.shouldIgnoreMouse()||this.trigger("mousedown",t)},handleMouseMove:function(t){this.shouldIgnoreMouse()||this.trigger("mousemove",t)},handleMouseUp:function(t){this.shouldIgnoreMouse()||this.trigger("mouseup",t)},handleClick:function(t){this.shouldIgnoreMouse()||this.trigger("click",t)},handleSelectStart:function(t){this.trigger("selectstart",t)},handleContextMenu:function(t){this.trigger("contextmenu",t)},handleScroll:function(t){this.trigger("scroll",t)},stopTouch:function(t,e){this.isTouching&&(this.isTouching=!1,this.trigger("touchend",t),e||this.startTouchMouseIgnore())},startTouchMouseIgnore:function(){var t=this,e=Wt.touchMouseIgnoreWait;e&&(this.mouseIgnoreDepth++,setTimeout(function(){t.mouseIgnoreDepth--},e))},shouldIgnoreMouse:function(){return this.isTouching||Boolean(this.mouseIgnoreDepth)}});!function(){var t=null,e=0;me.get=function(){return t||(t=new me,t.bind()),t},me.needed=function(){me.get(),e++},me.unneeded=function(){--e||(t.unbind(),t=null)}}();var ye=dt.extend(se,{options:null,sourceEl:null,el:null,parentEl:null,top0:null,left0:null,y0:null,x0:null,topDelta:null,leftDelta:null,isFollowing:!1,isHidden:!1,isAnimating:!1,constructor:function(e,n){this.options=n=n||{},this.sourceEl=e,this.parentEl=n.parentEl?t(n.parentEl):e.parent()},start:function(e){this.isFollowing||(this.isFollowing=!0,this.y0=E(e),this.x0=b(e),this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),S(e)?this.listenTo(t(document),"touchmove",this.handleMove):this.listenTo(t(document),"mousemove",this.handleMove))},stop:function(e,n){function i(){r.isAnimating=!1,r.removeElement(),r.top0=r.left0=null,n&&n()}var r=this,s=this.options.revertDuration;this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,this.stopListeningTo(t(document)),e&&s&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:s,complete:i})):i())},getEl:function(){var t=this.el;return t||(t=this.el=this.sourceEl.clone().addClass(this.options.additionalClass||"").css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}),t.addClass("fc-unselectable"),t.appendTo(this.parentEl)),t},removeElement:function(){this.el&&(this.el.remove(),this.el=null)},updatePosition:function(){var t,e;this.getEl(),null===this.top0&&(t=this.sourceEl.offset(),e=this.el.offsetParent().offset(),this.top0=t.top-e.top,this.left0=t.left-e.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},handleMove:function(t){this.topDelta=E(t)-this.y0,this.leftDelta=b(t)-this.x0,this.isHidden||this.updatePosition()},hide:function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},show:function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())}}),we=Wt.Scroller=dt.extend({el:null,scrollEl:null,overflowX:null,overflowY:null,constructor:function(t){t=t||{},this.overflowX=t.overflowX||t.overflow||"auto",this.overflowY=t.overflowY||t.overflow||"auto"},render:function(){this.el=this.renderEl(),this.applyOverflow()},renderEl:function(){return this.scrollEl=t('
')},clear:function(){this.setHeight("auto"),this.applyOverflow()},destroy:function(){this.el.remove()},applyOverflow:function(){this.scrollEl.css({"overflow-x":this.overflowX,"overflow-y":this.overflowY})},lockOverflow:function(t){var e=this.overflowX,n=this.overflowY;t=t||this.getScrollbarWidths(),"auto"===e&&(e=t.top||t.bottom||this.scrollEl[0].scrollWidth-1>this.scrollEl[0].clientWidth?"scroll":"hidden"),"auto"===n&&(n=t.left||t.right||this.scrollEl[0].scrollHeight-1>this.scrollEl[0].clientHeight?"scroll":"hidden"),this.scrollEl.css({"overflow-x":e,"overflow-y":n})},setHeight:function(t){this.scrollEl.height(t)},getScrollTop:function(){return this.scrollEl.scrollTop()},setScrollTop:function(t){this.scrollEl.scrollTop(t)},getClientWidth:function(){return this.scrollEl[0].clientWidth},getClientHeight:function(){return this.scrollEl[0].clientHeight},getScrollbarWidths:function(){return p(this.scrollEl)}});yt.prototype.proxyCall=function(t){var e=Array.prototype.slice.call(arguments,1),n=[];return this.items.forEach(function(i){n.push(i[t].apply(i,e))}),n};var De=dt.extend({view:null,component:null,constructor:function(t){this.view=t._getView(),this.component=t},opt:function(t){return this.view.opt(t)},end:function(){}}),be=De.extend({dragListener:null,constructor:function(t){De.call(this,t),this.dragListener=this.buildDragListener()},end:function(){this.dragListener.endInteraction()},bindToEl:function(t){var e=this.component,n=this.dragListener;e.bindDateHandlerToEl(t,"mousedown",function(t){e.shouldIgnoreMouse()||n.startInteraction(t)}),e.bindDateHandlerToEl(t,"touchstart",function(t){e.shouldIgnoreTouch()||n.startInteraction(t)})},buildDragListener:function(){var t,e=this,n=this.component,i=new ve(n,{scroll:this.opt("dragScroll"),interactionStart:function(){t=i.origHit},hitOver:function(e,n,i){n||(t=null)},hitOut:function(){t=null},interactionEnd:function(i,r){var s;!r&&t&&(s=n.getSafeHitFootprint(t))&&e.view.triggerDayClick(s,n.getHitEl(t),i)}});return i.shouldCancelTouchScroll=!1,i.scrollAlwaysKills=!0,i}}),Ee=Wt.DateSelecting=De.extend({dragListener:null,constructor:function(t){De.call(this,t),this.dragListener=this.buildDragListener()},end:function(){this.dragListener.endInteraction()},getDelay:function(){var t=this.opt("selectLongPressDelay");return null==t&&(t=this.opt("longPressDelay")),t},bindToEl:function(t){var e=this,n=this.component,i=this.dragListener;n.bindDateHandlerToEl(t,"mousedown",function(t){e.opt("selectable")&&!n.shouldIgnoreMouse()&&i.startInteraction(t,{distance:e.opt("selectMinDistance")})}),n.bindDateHandlerToEl(t,"touchstart",function(t){e.opt("selectable")&&!n.shouldIgnoreTouch()&&i.startInteraction(t,{delay:e.getDelay()})}),C(t)},buildDragListener:function(){var t,e=this,n=this.component;return new ve(n,{scroll:this.opt("dragScroll"),interactionStart:function(){t=null},dragStart:function(t){e.view.unselect(t)},hitOver:function(i,r,o){var a,l;o&&(a=n.getSafeHitFootprint(o),l=n.getSafeHitFootprint(i),t=a&&l?e.computeSelection(a,l):null,t?n.renderSelectionFootprint(t):!1===t&&s())},hitOut:function(){t=null,n.unrenderSelection()},hitDone:function(){o()},interactionEnd:function(n,i){!i&&t&&e.view.reportSelection(t,n)}})},computeSelection:function(t,e){var n=this.computeSelectionFootprint(t,e);return!(n&&!this.isSelectionFootprintAllowed(n))&&n},computeSelectionFootprint:function(t,e){var n=[t.unzonedRange.startMs,t.unzonedRange.endMs,e.unzonedRange.startMs,e.unzonedRange.endMs];return n.sort(ot),new We(new Ue(n[0],n[3]),t.isAllDay)},isSelectionFootprintAllowed:function(t){return this.component.dateProfile.validUnzonedRange.containsRange(t.unzonedRange)&&this.view.calendar.isSelectionFootprintAllowed(t)}}),Se=Wt.EventDragging=De.extend({eventPointing:null,dragListener:null,isDragging:!1,constructor:function(t,e){De.call(this,t),this.eventPointing=e},end:function(){this.dragListener&&this.dragListener.endInteraction()},getSelectionDelay:function(){var t=this.opt("eventLongPressDelay");return null==t&&(t=this.opt("longPressDelay")),t},bindToEl:function(t){var e=this.component;e.bindSegHandlerToEl(t,"mousedown",this.handleMousedown.bind(this)),e.bindSegHandlerToEl(t,"touchstart",this.handleTouchStart.bind(this))},handleMousedown:function(t,e){this.component.canStartDrag(t,e)&&this.buildDragListener(t).startInteraction(e,{distance:5})},handleTouchStart:function(t,e){var n=this.component,i={delay:this.view.isEventDefSelected(t.footprint.eventDef)?0:this.getSelectionDelay()};n.canStartDrag(t,e)?this.buildDragListener(t).startInteraction(e,i):n.canStartSelection(t,e)&&this.buildSelectListener(t).startInteraction(e,i)},buildSelectListener:function(t){var e=this,n=this.view,i=t.footprint.eventDef,r=t.footprint.eventInstance;if(this.dragListener)return this.dragListener;var s=this.dragListener=new pe({dragStart:function(t){s.isTouch&&!n.isEventDefSelected(i)&&r&&n.selectEventInstance(r)},interactionEnd:function(t){e.dragListener=null}});return s},buildDragListener:function(t){var e,n,i,r=this,a=this.component,l=this.view,u=l.calendar,c=u.eventManager,h=t.el,d=t.footprint.eventDef,f=t.footprint.eventInstance;if(this.dragListener)return this.dragListener;var g=this.dragListener=new ve(l,{scroll:this.opt("dragScroll"),subjectEl:h,subjectCenter:!0,interactionStart:function(i){t.component=a,e=!1,n=new ye(t.el,{additionalClass:"fc-dragging",parentEl:l.el,opacity:g.isTouch?null:r.opt("dragOpacity"),revertDuration:r.opt("dragRevertDuration"),zIndex:2}),n.hide(),n.start(i)},dragStart:function(n){g.isTouch&&!l.isEventDefSelected(d)&&f&&l.selectEventInstance(f),e=!0,r.eventPointing.handleMouseout(t,n),r.segDragStart(t,n),l.hideEventsWithId(t.footprint.eventDef.id)},hitOver:function(e,o,h){var f,p,v,m=!0;t.hit&&(h=t.hit),f=h.component.getSafeHitFootprint(h),p=e.component.getSafeHitFootprint(e),f&&p?(i=r.computeEventDropMutation(f,p,d),i?(v=c.buildMutatedEventInstanceGroup(d.id,i),m=a.isEventInstanceGroupAllowed(v)):m=!1):m=!1,m||(i=null,s()),i&&l.renderDrag(a.eventRangesToEventFootprints(v.sliceRenderRanges(a.dateProfile.renderUnzonedRange,u)),t,g.isTouch)?n.hide():n.show(),o&&(i=null)},hitOut:function(){l.unrenderDrag(t),n.show(),i=null},hitDone:function(){o()},interactionEnd:function(s){delete t.component,n.stop(!i,function(){e&&(l.unrenderDrag(t),r.segDragStop(t,s)),l.showEventsWithId(t.footprint.eventDef.id),i&&l.reportEventDrop(f,i,h,s)}),r.dragListener=null}});return g},segDragStart:function(t,e){this.isDragging=!0,this.component.publiclyTrigger("eventDragStart",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},segDragStop:function(t,e){this.isDragging=!1,this.component.publiclyTrigger("eventDragStop",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},computeEventDropMutation:function(t,e,n){var i=new rn;return i.setDateMutation(this.computeEventDateMutation(t,e)),i},computeEventDateMutation:function(t,e){var n,i,r=t.unzonedRange.getStart(),s=e.unzonedRange.getStart(),o=!1,a=!1,l=!1;return t.isAllDay!==e.isAllDay&&(o=!0,e.isAllDay?(l=!0,r.stripTime()):a=!0),n=this.component.diffDates(s,r),i=new sn,i.clearEnd=o,i.forceTimed=a,i.forceAllDay=l,i.setDateDelta(n),i}}),Ce=Wt.EventResizing=De.extend({eventPointing:null,dragListener:null,isResizing:!1,constructor:function(t,e){De.call(this,t),this.eventPointing=e},end:function(){this.dragListener&&this.dragListener.endInteraction()},bindToEl:function(t){var e=this.component;e.bindSegHandlerToEl(t,"mousedown",this.handleMouseDown.bind(this)),e.bindSegHandlerToEl(t,"touchstart",this.handleTouchStart.bind(this))},handleMouseDown:function(e,n){this.component.canStartResize(e,n)&&this.buildDragListener(e,t(n.target).is(".fc-start-resizer")).startInteraction(n,{distance:5})},handleTouchStart:function(e,n){this.component.canStartResize(e,n)&&this.buildDragListener(e,t(n.target).is(".fc-start-resizer")).startInteraction(n)},buildDragListener:function(t,e){var n,i,r=this,a=this.component,l=this.view,u=l.calendar,c=u.eventManager,h=t.el,d=t.footprint.eventDef,f=t.footprint.eventInstance;return this.dragListener=new ve(a,{scroll:this.opt("dragScroll"),subjectEl:h,interactionStart:function(){n=!1},dragStart:function(e){n=!0,r.eventPointing.handleMouseout(t,e),r.segResizeStart(t,e)},hitOver:function(n,o,h){var f,g=!0,p=a.getSafeHitFootprint(h),v=a.getSafeHitFootprint(n);p&&v?(i=e?r.computeEventStartResizeMutation(p,v,t.footprint):r.computeEventEndResizeMutation(p,v,t.footprint),i?(f=c.buildMutatedEventInstanceGroup(d.id,i),g=a.isEventInstanceGroupAllowed(f)):g=!1):g=!1,g?i.isEmpty()&&(i=null):(i=null,s()),i&&(l.hideEventsWithId(t.footprint.eventDef.id),l.renderEventResize(a.eventRangesToEventFootprints(f.sliceRenderRanges(a.dateProfile.renderUnzonedRange,u)),t))},hitOut:function(){i=null},hitDone:function(){l.unrenderEventResize(t),l.showEventsWithId(t.footprint.eventDef.id),o()},interactionEnd:function(e){n&&r.segResizeStop(t,e),i&&l.reportEventResize(f,i,h,e),r.dragListener=null}})},segResizeStart:function(t,e){this.isResizing=!0,this.component.publiclyTrigger("eventResizeStart",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},segResizeStop:function(t,e){this.isResizing=!1,this.component.publiclyTrigger("eventResizeStop",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,{},this.view]})},computeEventStartResizeMutation:function(t,e,n){var i,r,s=n.componentFootprint.unzonedRange,o=this.component.diffDates(e.unzonedRange.getStart(),t.unzonedRange.getStart());return s.getStart().add(o)s.getStart()&&(i=new sn,i.setEndDelta(o),r=new rn,r.setDateMutation(i),r)}}),Re=Wt.ExternalDropping=De.extend(se,{dragListener:null,isDragging:!1,end:function(){this.dragListener&&this.dragListener.endInteraction()},bindToDocument:function(){this.listenTo(t(document),{dragstart:this.handleDragStart,sortstart:this.handleDragStart})},unbindFromDocument:function(){this.stopListeningTo(t(document))},handleDragStart:function(e,n){var i,r;this.opt("droppable")&&(i=t((n?n.item:null)||e.target),r=this.opt("dropAccept"),(t.isFunction(r)?r.call(i[0],i):i.is(r))&&(this.isDragging||this.listenToExternalDrag(i,e,n)))},listenToExternalDrag:function(t,e,n){var i,r=this,a=this.component,l=this.view,u=wt(t);(r.dragListener=new ve(a,{interactionStart:function(){r.isDragging=!0},hitOver:function(t){var e,n=!0,o=t.component.getSafeHitFootprint(t);o?(i=r.computeExternalDrop(o,u),i?(e=new Je(i.buildInstances()),n=u.eventProps?a.isEventInstanceGroupAllowed(e):a.isExternalInstanceGroupAllowed(e)):n=!1):n=!1,n||(i=null,s()),i&&a.renderDrag(a.eventRangesToEventFootprints(e.sliceRenderRanges(a.dateProfile.renderUnzonedRange,l.calendar)))},hitOut:function(){i=null},hitDone:function(){o(),a.unrenderDrag()},interactionEnd:function(e){i&&l.reportExternalDrop(i,Boolean(u.eventProps),Boolean(u.stick),t,e,n),r.isDragging=!1,r.dragListener=null}})).startDrag(e)},computeExternalDrop:function(e,n){var i,r=this.view.calendar,s=Wt.moment.utc(e.unzonedRange.startMs).stripZone();return e.isAllDay&&(n.startTime?s.time(n.startTime):s.stripTime()),n.duration&&(i=s.clone().add(n.duration)),s=r.applyTimezone(s),i&&(i=r.applyTimezone(i)),$e.parse(t.extend({},n.eventProps,{start:s,end:i}),new on(r))}});Wt.dataAttrPrefix="";var Te=Wt.EventPointing=De.extend({mousedOverSeg:null,bindToEl:function(t){var e=this.component;e.bindSegHandlerToEl(t,"click",this.handleClick.bind(this)),e.bindSegHandlerToEl(t,"mouseenter",this.handleMouseover.bind(this)),e.bindSegHandlerToEl(t,"mouseleave",this.handleMouseout.bind(this))},handleClick:function(t,e){!1===this.component.publiclyTrigger("eventClick",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,this.view]})&&e.preventDefault()},handleMouseover:function(t,e){me.get().shouldIgnoreMouse()||this.mousedOverSeg||(this.mousedOverSeg=t,this.view.isEventDefResizable(t.footprint.eventDef)&&t.el.addClass("fc-allow-mouse-resize"),this.component.publiclyTrigger("eventMouseover",{context:t.el[0],args:[t.footprint.getEventLegacy(),e,this.view]}))},handleMouseout:function(t,e){this.mousedOverSeg&&(this.mousedOverSeg=null,this.view.isEventDefResizable(t.footprint.eventDef)&&t.el.removeClass("fc-allow-mouse-resize"),this.component.publiclyTrigger("eventMouseout",{context:t.el[0],args:[t.footprint.getEventLegacy(),e||{},this.view]}))},end:function(){this.mousedOverSeg&&this.handleMouseout(this.mousedOverSeg)}}),Ie=Wt.StandardInteractionsMixin={dateClickingClass:be,dateSelectingClass:Ee,eventPointingClass:Te,eventDraggingClass:Se,eventResizingClass:Ce,externalDroppingClass:Re},He=Wt.EventRenderer=dt.extend({view:null,component:null,fillRenderer:null,fgSegs:null,bgSegs:null,eventTimeFormat:null,displayEventTime:null,displayEventEnd:null,constructor:function(t,e){this.view=t._getView(),this.component=t,this.fillRenderer=e},opt:function(t){return this.view.opt(t)},rangeUpdated:function(){var t,e;this.eventTimeFormat=this.opt("eventTimeFormat")||this.opt("timeFormat")||this.computeEventTimeFormat(),t=this.opt("displayEventTime"),null==t&&(t=this.computeDisplayEventTime()),e=this.opt("displayEventEnd"),null==e&&(e=this.computeDisplayEventEnd()),this.displayEventTime=t,this.displayEventEnd=e},render:function(t){var e,n,i,r=this.component._getDateProfile(),s=[],o=[];for(e in t)n=t[e],i=n.sliceRenderRanges(r.activeUnzonedRange),n.getEventDef().hasBgRendering()?s.push.apply(s,i):o.push.apply(o,i);this.renderBgRanges(s),this.renderFgRanges(o)},unrender:function(){this.unrenderBgRanges(),this.unrenderFgRanges()},renderFgRanges:function(t){var e=this.component.eventRangesToEventFootprints(t),n=this.component.eventFootprintsToSegs(e);n=this.renderFgSegEls(n),!1!==this.renderFgSegs(n)&&(this.fgSegs=n)},unrenderFgRanges:function(){this.unrenderFgSegs(this.fgSegs||[]),this.fgSegs=null},renderBgRanges:function(t){var e=this.component.eventRangesToEventFootprints(t),n=this.component.eventFootprintsToSegs(e);!1!==this.renderBgSegs(n)&&(this.bgSegs=n)},unrenderBgRanges:function(){this.unrenderBgSegs(),this.bgSegs=null},getSegs:function(){return(this.bgSegs||[]).concat(this.fgSegs||[])},renderFgSegs:function(t){return!1},unrenderFgSegs:function(t){},renderBgSegs:function(t){var e=this;if(!this.fillRenderer)return!1;this.fillRenderer.renderSegs("bgEvent",t,{getClasses:function(t){return e.getBgClasses(t.footprint.eventDef)},getCss:function(t){return{"background-color":e.getBgColor(t.footprint.eventDef)}},filterEl:function(t,n){return e.filterEventRenderEl(t.footprint,n)}})},unrenderBgSegs:function(){this.fillRenderer&&this.fillRenderer.unrender("bgEvent")},renderFgSegEls:function(e,n){var i,r=this,s=this.view.hasPublicHandlers("eventRender"),o="",a=[];if(e.length){for(i=0;i"},attachSegEls:function(t,e){},reportEls:function(e,n){this.elsByFill[e]?this.elsByFill[e]=this.elsByFill[e].add(n):this.elsByFill[e]=t(n)}}),Pe=Wt.HelperRenderer=dt.extend({view:null,component:null,eventRenderer:null,helperEls:null,constructor:function(t,e){this.view=t._getView(),this.component=t,this.eventRenderer=e},renderComponentFootprint:function(t){this.renderEventFootprints([this.fabricateEventFootprint(t)])},renderEventDraggingFootprints:function(t,e,n){this.renderEventFootprints(t,e,"fc-dragging",n?null:this.view.opt("dragOpacity"))},renderEventResizingFootprints:function(t,e,n){this.renderEventFootprints(t,e,"fc-resizing")},renderEventFootprints:function(t,e,n,i){var r,s=this.component.eventFootprintsToSegs(t),o="fc-helper "+(n||"");for(s=this.eventRenderer.renderFgSegEls(s),r=0;r'+i+"":""+i+""},getAllDayHtml:function(){return this.opt("allDayHtml")||et(this.opt("allDayText"))},getDayClasses:function(t,e){var n,i=this._getView(),r=[];return this.dateProfile.activeUnzonedRange.containsDate(t)?(r.push("fc-"+jt[t.day()]),i.isDateInOtherMonth(t,this.dateProfile)&&r.push("fc-other-month"),n=i.calendar.getNow(),t.isSame(n,"day")?(r.push("fc-today"),!0!==e&&r.push(i.calendar.theme.getClass("today"))):t=this.nextDayThreshold&&s.add(1,"days"),s<=n&&(s=n.clone().add(1,"days")),{start:n,end:s}},isMultiDayRange:function(t){var e=this.computeDayRange(t);return e.end.diff(e.start,"days")>1}});var ke=Wt.InteractiveDateComponent=Fe.extend({dateClickingClass:null,dateSelectingClass:null,eventPointingClass:null,eventDraggingClass:null,eventResizingClass:null,externalDroppingClass:null,dateClicking:null,dateSelecting:null,eventPointing:null,eventDragging:null,eventResizing:null,externalDropping:null,segSelector:".fc-event-container > *",largeUnit:null,constructor:function(){Fe.call(this),this.dateSelectingClass&&(this.dateClicking=new this.dateClickingClass(this)),this.dateSelectingClass&&(this.dateSelecting=new this.dateSelectingClass(this)),this.eventPointingClass&&(this.eventPointing=new this.eventPointingClass(this)),this.eventDraggingClass&&this.eventPointing&&(this.eventDragging=new this.eventDraggingClass(this,this.eventPointing)),this.eventResizingClass&&this.eventPointing&&(this.eventResizing=new this.eventResizingClass(this,this.eventPointing)),this.externalDroppingClass&&(this.externalDropping=new this.externalDroppingClass(this))},setElement:function(t){Fe.prototype.setElement.apply(this,arguments),this.dateClicking&&this.dateClicking.bindToEl(t),this.dateSelecting&&this.dateSelecting.bindToEl(t),this.bindAllSegHandlersToEl(t)},unrender:function(){this.endInteractions(),Fe.prototype.unrender.apply(this,arguments)},executeEventUnrender:function(){this.endInteractions(),Fe.prototype.executeEventUnrender.apply(this,arguments)},bindGlobalHandlers:function(){Fe.prototype.bindGlobalHandlers.apply(this,arguments),this.externalDropping&&this.externalDropping.bindToDocument()},unbindGlobalHandlers:function(){Fe.prototype.unbindGlobalHandlers.apply(this,arguments),this.externalDropping&&this.externalDropping.unbindFromDocument()},bindDateHandlerToEl:function(e,n,i){var r=this;this.el.on(n,function(e){if(!t(e.target).is(r.segSelector+","+r.segSelector+" *,.fc-more,a[data-goto]"))return i.call(r,e)})},bindAllSegHandlersToEl:function(t){[this.eventPointing,this.eventDragging,this.eventResizing].forEach(function(e){e&&e.bindToEl(t)})},bindSegHandlerToEl:function(e,n,i){var r=this;e.on(n,this.segSelector,function(e){var n=t(this).data("fc-seg");if(n&&!r.shouldIgnoreEventPointing())return i.call(r,n,e)})},shouldIgnoreMouse:function(){return me.get().shouldIgnoreMouse()},shouldIgnoreTouch:function(){var t=this._getView();return t.isSelected||t.selectedEvent},shouldIgnoreEventPointing:function(){return this.eventDragging&&this.eventDragging.isDragging||this.eventResizing&&this.eventResizing.isResizing},canStartSelection:function(t,e){return S(e)&&!this.canStartResize(t,e)&&(this.isEventDefDraggable(t.footprint.eventDef)||this.isEventDefResizable(t.footprint.eventDef))},canStartDrag:function(t,e){return!this.canStartResize(t,e)&&this.isEventDefDraggable(t.footprint.eventDef)},canStartResize:function(e,n){var i=this._getView(),r=e.footprint.eventDef;return(!S(n)||i.isEventDefSelected(r))&&this.isEventDefResizable(r)&&t(n.target).is(".fc-resizer")},endInteractions:function(){[this.dateClicking,this.dateSelecting,this.eventPointing,this.eventDragging,this.eventResizing].forEach(function(t){t&&t.end()})},isEventDefDraggable:function(t){return this.isEventDefStartEditable(t)},isEventDefStartEditable:function(t){var e=t.isStartExplicitlyEditable();return null==e&&null==(e=this.opt("eventStartEditable"))&&(e=this.isEventDefGenerallyEditable(t)),e},isEventDefGenerallyEditable:function(t){var e=t.isExplicitlyEditable();return null==e&&(e=this.opt("editable")),e},isEventDefResizableFromStart:function(t){return this.opt("eventResizableFromStart")&&this.isEventDefResizable(t)},isEventDefResizableFromEnd:function(t){return this.isEventDefResizable(t)},isEventDefResizable:function(t){var e=t.isDurationExplicitlyEditable();return null==e&&null==(e=this.opt("eventDurationEditable"))&&(e=this.isEventDefGenerallyEditable(t)),e},diffDates:function(t,e){return this.largeUnit?L(t,e,this.largeUnit):B(t,e)},isEventInstanceGroupAllowed:function(t){var e,n=this._getView(),i=this.dateProfile,r=this.eventRangesToEventFootprints(t.getAllEventRanges());for(e=0;e=e.length?e[e.length-1]+1:e[n]},computeColHeadFormat:function(){return this.rowCnt>1||this.colCnt>10?"ddd":this.colCnt>1?this.opt("dayOfMonthFormat"):"dddd"},sliceRangeByRow:function(t){var e,n,i,r,s,o=this.daysPerRow,a=this.view.computeDayRange(t),l=this.getDateDayIndex(a.start),u=this.getDateDayIndex(a.end.clone().subtract(1,"days")),c=[];for(e=0;e'+this.renderHeadTrHtml()+"
"},renderHeadIntroHtml:function(){return this.renderIntroHtml()},renderHeadTrHtml:function(){return""+(this.isRTL?"":this.renderHeadIntroHtml())+this.renderHeadDateCellsHtml()+(this.isRTL?this.renderHeadIntroHtml():"")+""},renderHeadDateCellsHtml:function(){var t,e,n=[];for(t=0;t1?' colspan="'+e+'"':"")+(n?" "+n:"")+">"+(r?i.buildGotoAnchorHtml({date:t,forceOff:this.rowCnt>1||1===this.colCnt},o):o)+""},renderBgTrHtml:function(t){return""+(this.isRTL?"":this.renderBgIntroHtml(t))+this.renderBgCellsHtml(t)+(this.isRTL?this.renderBgIntroHtml(t):"")+""},renderBgIntroHtml:function(t){return this.renderIntroHtml()},renderBgCellsHtml:function(t){var e,n,i=[];for(e=0;e"},renderIntroHtml:function(){},bookendCells:function(t){var e=this.renderIntroHtml();e&&(this.isRTL?t.append(e):t.prepend(e))}},Ae=Wt.View=ke.extend({type:null,name:null,title:null,calendar:null,viewSpec:null,options:null,renderQueue:null,batchRenderDepth:0,queuedScroll:null,isSelected:!1,selectedEventInstance:null,eventOrderSpecs:null,isHiddenDayHash:null,isNowIndicatorRendered:null,initialNowDate:null,initialNowQueriedMs:null,nowIndicatorTimeoutID:null,nowIndicatorIntervalID:null,constructor:function(t,e){this.calendar=t,this.viewSpec=e,this.type=e.type,this.options=e.options,this.name=this.type,ke.call(this),this.initRenderQueue(),this.initHiddenDays(),this.bindBaseRenderHandlers(),this.eventOrderSpecs=P(this.opt("eventOrder")),this.initialize&&this.initialize()},_getView:function(){return this},opt:function(t){return this.options[t]},initRenderQueue:function(){this.renderQueue=new de({event:this.opt("eventRenderWait")}),this.renderQueue.on("start",this.onRenderQueueStart.bind(this)),this.renderQueue.on("stop",this.onRenderQueueStop.bind(this)),this.on("before:change",this.startBatchRender),this.on("change",this.stopBatchRender)},onRenderQueueStart:function(){this.calendar.freezeContentHeight(),this.addScroll(this.queryScroll())},onRenderQueueStop:function(){this.calendar.updateViewSize()&&this.popScroll(),this.calendar.thawContentHeight()},startBatchRender:function(){this.batchRenderDepth++||this.renderQueue.pause()},stopBatchRender:function(){--this.batchRenderDepth||this.renderQueue.resume()},requestRender:function(t,e,n){this.renderQueue.queue(t,e,n)},whenSizeUpdated:function(t){this.renderQueue.isRunning?this.renderQueue.one("stop",t.bind(this)):t.call(this)},computeTitle:function(t){var e;return e=/^(year|month)$/.test(t.currentRangeUnit)?t.currentUnzonedRange:t.activeUnzonedRange,this.formatRange({start:this.calendar.msToMoment(e.startMs,t.isRangeAllDay),end:this.calendar.msToMoment(e.endMs,t.isRangeAllDay)},t.isRangeAllDay,this.opt("titleFormat")||this.computeTitleFormat(t),this.opt("titleRangeSeparator"))},computeTitleFormat:function(t){var e=t.currentRangeUnit;return"year"==e?"YYYY":"month"==e?this.opt("monthYearFormat"):t.currentUnzonedRange.as("days")>1?"ll":"LL"},setDate:function(t){var e=this.get("dateProfile"),n=this.buildDateProfile(t,null,!0);e&&e.activeUnzonedRange.equals(n.activeUnzonedRange)||this.set("dateProfile",n)},unsetDate:function(){this.unset("dateProfile")},fetchInitialEvents:function(t){var e=this.calendar,n=t.isRangeAllDay&&!this.usesMinMaxTime;return e.requestEvents(e.msToMoment(t.activeUnzonedRange.startMs,n),e.msToMoment(t.activeUnzonedRange.endMs,n))},bindEventChanges:function(){this.listenTo(this.calendar,"eventsReset",this.resetEvents)},unbindEventChanges:function(){this.stopListeningTo(this.calendar,"eventsReset")},setEvents:function(t){this.set("currentEvents",t),this.set("hasEvents",!0)},unsetEvents:function(){this.unset("currentEvents"),this.unset("hasEvents")},resetEvents:function(t){this.startBatchRender(),this.unsetEvents(),this.setEvents(t),this.stopBatchRender()},requestDateRender:function(t){var e=this;this.requestRender(function(){e.executeDateRender(t)},"date","init")},requestDateUnrender:function(){var t=this;this.requestRender(function(){t.executeDateUnrender()},"date","destroy")},executeDateRender:function(t){Fe.prototype.executeDateRender.apply(this,arguments),this.render&&this.render(),this.trigger("datesRendered"),this.addScroll({isDateInit:!0}),this.startNowIndicator()},executeDateUnrender:function(){this.unselect(),this.stopNowIndicator(),this.trigger("before:datesUnrendered"),this.destroy&&this.destroy(),Fe.prototype.executeDateUnrender.apply(this,arguments)},bindBaseRenderHandlers:function(){var t=this;this.on("datesRendered",function(){t.whenSizeUpdated(t.triggerViewRender)}),this.on("before:datesUnrendered",function(){t.triggerViewDestroy()})},triggerViewRender:function(){this.publiclyTrigger("viewRender",{context:this,args:[this,this.el]})},triggerViewDestroy:function(){this.publiclyTrigger("viewDestroy",{context:this,args:[this,this.el]})},requestEventsRender:function(t){var e=this;this.requestRender(function(){e.executeEventRender(t),e.whenSizeUpdated(e.triggerAfterEventsRendered)},"event","init")},requestEventsUnrender:function(){var t=this;this.requestRender(function(){t.triggerBeforeEventsDestroyed(),t.executeEventUnrender()},"event","destroy")},requestBusinessHoursRender:function(t){var e=this;this.requestRender(function(){e.renderBusinessHours(t)},"businessHours","init")},requestBusinessHoursUnrender:function(){var t=this;this.requestRender(function(){t.unrenderBusinessHours()},"businessHours","destroy")},bindGlobalHandlers:function(){ke.prototype.bindGlobalHandlers.apply(this,arguments),this.listenTo(me.get(),{touchstart:this.processUnselect,mousedown:this.handleDocumentMousedown})},unbindGlobalHandlers:function(){ke.prototype.unbindGlobalHandlers.apply(this,arguments),this.stopListeningTo(me.get())},startNowIndicator:function(){var t,n,i,r=this;this.opt("nowIndicator")&&(t=this.getNowIndicatorUnit())&&(n=lt(this,"updateNowIndicator"),this.initialNowDate=this.calendar.getNow(),this.initialNowQueriedMs=+new Date,i=this.initialNowDate.clone().startOf(t).add(1,t)-this.initialNowDate,this.nowIndicatorTimeoutID=setTimeout(function(){r.nowIndicatorTimeoutID=null,n(),i=+e.duration(1,t),i=Math.max(100,i),r.nowIndicatorIntervalID=setInterval(n,i)},i))},updateNowIndicator:function(){this.isDatesRendered&&this.initialNowDate&&(this.unrenderNowIndicator(),this.renderNowIndicator(this.initialNowDate.clone().add(new Date-this.initialNowQueriedMs)),this.isNowIndicatorRendered=!0)},stopNowIndicator:function(){this.isNowIndicatorRendered&&(this.nowIndicatorTimeoutID&&(clearTimeout(this.nowIndicatorTimeoutID),this.nowIndicatorTimeoutID=null),this.nowIndicatorIntervalID&&(clearTimeout(this.nowIndicatorIntervalID),this.nowIndicatorIntervalID=null),this.unrenderNowIndicator(),this.isNowIndicatorRendered=!1)},updateSize:function(t,e,n){this.setHeight?this.setHeight(t,e):ke.prototype.updateSize.apply(this,arguments),this.updateNowIndicator()},addScroll:function(e){var n=this.queuedScroll||(this.queuedScroll={});t.extend(n,e)},popScroll:function(){this.applyQueuedScroll(),this.queuedScroll=null},applyQueuedScroll:function(){this.queuedScroll&&this.applyScroll(this.queuedScroll)},queryScroll:function(){var e={};return this.isDatesRendered&&t.extend(e,this.queryDateScroll()),e},applyScroll:function(e){e.isDateInit&&this.isDatesRendered&&t.extend(e,this.computeInitialDateScroll()),this.isDatesRendered&&this.applyDateScroll(e)},computeInitialDateScroll:function(){return{}},queryDateScroll:function(){return{}},applyDateScroll:function(t){},reportEventDrop:function(t,n,i,r){var s=this.calendar.eventManager,o=s.mutateEventsWithId(t.def.id,n,this.calendar),a=n.dateMutation;a&&(t.dateProfile=a.buildNewDateProfile(t.dateProfile,this.calendar)),this.triggerEventDrop(t,a&&a.dateDelta||e.duration(),o,i,r)},triggerEventDrop:function(t,e,n,i,r){this.publiclyTrigger("eventDrop",{context:i[0],args:[t.toLegacy(),e,n,r,{},this]})},reportExternalDrop:function(t,e,n,i,r,s){e&&this.calendar.eventManager.addEventDef(t,n),this.triggerExternalDrop(t,e,i,r,s)},triggerExternalDrop:function(t,e,n,i,r){this.publiclyTrigger("drop",{context:n[0],args:[t.dateProfile.start.clone(),i,r,this]}),e&&this.publiclyTrigger("eventReceive",{context:this,args:[t.buildInstance().toLegacy(),this]})},reportEventResize:function(t,e,n,i){var r=this.calendar.eventManager,s=r.mutateEventsWithId(t.def.id,e,this.calendar);t.dateProfile=e.dateMutation.buildNewDateProfile(t.dateProfile,this.calendar),this.triggerEventResize(t,e.dateMutation.endDelta,s,n,i)},triggerEventResize:function(t,e,n,i,r){this.publiclyTrigger("eventResize",{context:i[0],args:[t.toLegacy(),e,n,r,{},this]})},select:function(t,e){this.unselect(e),this.renderSelectionFootprint(t),this.reportSelection(t,e)},renderSelectionFootprint:function(t,e){this.renderSelection?this.renderSelection(t.toLegacy(this.calendar)):ke.prototype.renderSelectionFootprint.apply(this,arguments)},reportSelection:function(t,e){this.isSelected=!0,this.triggerSelect(t,e)},triggerSelect:function(t,e){var n=this.calendar.footprintToDateProfile(t);this.publiclyTrigger("select",{context:this,args:[n.start,n.end,e,this]})},unselect:function(t){this.isSelected&&(this.isSelected=!1,this.destroySelection&&this.destroySelection(),this.unrenderSelection(),this.publiclyTrigger("unselect",{context:this,args:[t,this]}))},selectEventInstance:function(t){this.selectedEventInstance&&this.selectedEventInstance===t||(this.unselectEventInstance(),this.getEventSegs().forEach(function(e){e.footprint.eventInstance===t&&e.el&&e.el.addClass("fc-selected")}),this.selectedEventInstance=t)},unselectEventInstance:function(){this.selectedEventInstance&&(this.getEventSegs().forEach(function(t){t.el&&t.el.removeClass("fc-selected")}),this.selectedEventInstance=null)},isEventDefSelected:function(t){return this.selectedEventInstance&&this.selectedEventInstance.def.id===t.id},handleDocumentMousedown:function(t){D(t)&&this.processUnselect(t)},processUnselect:function(t){this.processRangeUnselect(t),this.processEventUnselect(t)},processRangeUnselect:function(e){var n;this.isSelected&&this.opt("unselectAuto")&&((n=this.opt("unselectCancel"))&&t(e.target).closest(n).length||this.unselect(e))},processEventUnselect:function(e){this.selectedEventInstance&&(t(e.target).closest(".fc-selected").length||this.unselectEventInstance())},triggerBaseRendered:function(){this.publiclyTrigger("viewRender",{context:this,args:[this,this.el]})},triggerBaseUnrendered:function(){this.publiclyTrigger("viewDestroy",{context:this,args:[this,this.el]})},triggerDayClick:function(t,e,n){var i=this.calendar.footprintToDateProfile(t);this.publiclyTrigger("dayClick",{context:e,args:[i.start,n,this]})}});Ae.watch("displayingDates",["isInDom","dateProfile"],function(t){this.requestDateRender(t.dateProfile)},function(){this.requestDateUnrender()}),Ae.watch("displayingBusinessHours",["displayingDates","businessHourGenerator"],function(t){this.requestBusinessHoursRender(t.businessHourGenerator)},function(){this.requestBusinessHoursUnrender()}),Ae.watch("initialEvents",["dateProfile"],function(t){return this.fetchInitialEvents(t.dateProfile)}),Ae.watch("bindingEvents",["initialEvents"],function(t){this.setEvents(t.initialEvents),this.bindEventChanges()},function(){this.unbindEventChanges(),this.unsetEvents()}),Ae.watch("displayingEvents",["displayingDates","hasEvents"],function(){this.requestEventsRender(this.get("currentEvents"))},function(){this.requestEventsUnrender()}),Ae.watch("title",["dateProfile"],function(t){return this.title=this.computeTitle(t.dateProfile)}),Ae.watch("legacyDateProps",["dateProfile"],function(t){var e=this.calendar,n=t.dateProfile;this.start=e.msToMoment(n.activeUnzonedRange.startMs,n.isRangeAllDay),this.end=e.msToMoment(n.activeUnzonedRange.endMs,n.isRangeAllDay),this.intervalStart=e.msToMoment(n.currentUnzonedRange.startMs,n.isRangeAllDay),this.intervalEnd=e.msToMoment(n.currentUnzonedRange.endMs,n.isRangeAllDay)}),Ae.mixin({usesMinMaxTime:!1,start:null,end:null,intervalStart:null,intervalEnd:null,buildPrevDateProfile:function(t){var e=this.get("dateProfile"),n=t.clone().startOf(e.currentRangeUnit).subtract(e.dateIncrement);return this.buildDateProfile(n,-1)},buildNextDateProfile:function(t){var e=this.get("dateProfile"),n=t.clone().startOf(e.currentRangeUnit).add(e.dateIncrement);return this.buildDateProfile(n,1)},buildDateProfile:function(t,n,i){var r,s,o,a,l,u,c=!t.hasTime(),h=null,d=null;return r=this.buildValidRange(),r=this.trimHiddenDays(r),i&&(t=this.calendar.msToUtcMoment(r.constrainDate(t),c)),s=this.buildCurrentRangeInfo(t,n),o=/^(year|month|week|day)$/.test(s.unit),a=this.buildRenderRange(this.trimHiddenDays(s.unzonedRange),s.unit,o),a=this.trimHiddenDays(a),l=a.clone(),this.opt("showNonCurrentDates")||(l=l.intersect(s.unzonedRange)),h=e.duration(this.opt("minTime")),d=e.duration(this.opt("maxTime")),l=this.adjustActiveRange(l,h,d),l=l.intersect(r),l&&(t=this.calendar.msToUtcMoment(l.constrainDate(t),c)),u=s.unzonedRange.intersectsWith(r),{validUnzonedRange:r,currentUnzonedRange:s.unzonedRange,currentRangeUnit:s.unit,isRangeAllDay:o,activeUnzonedRange:l,renderUnzonedRange:a,minTime:h,maxTime:d,isValid:u,date:t,dateIncrement:this.buildDateIncrement(s.duration)}},buildValidRange:function(){return this.getUnzonedRangeOption("validRange",this.calendar.getNow())||new Ue},buildCurrentRangeInfo:function(t,e){var n,i=null,r=null,s=null;return this.viewSpec.duration?(i=this.viewSpec.duration,r=this.viewSpec.durationUnit,s=this.buildRangeFromDuration(t,e,i,r)):(n=this.opt("dayCount"))?(r="day",s=this.buildRangeFromDayCount(t,e,n)):(s=this.buildCustomVisibleRange(t))?r=O(s.getStart(),s.getEnd()):(i=this.getFallbackDuration(),r=O(i),s=this.buildRangeFromDuration(t,e,i,r)),{duration:i,unit:r,unzonedRange:s}},getFallbackDuration:function(){return e.duration({days:1})},adjustActiveRange:function(t,e,n){var i=t.getStart(),r=t.getEnd();return this.usesMinMaxTime&&(e<0&&i.time(0).add(e),n>864e5&&r.time(n-864e5)),new Ue(i,r)},buildRangeFromDuration:function(t,n,i,r){var s,o,a,l=this.opt("dateAlignment"),u=t.clone();return i.as("days")<=1&&this.isHiddenDay(u)&&(u=this.skipHiddenDays(u,n),u.startOf("day")),l||(o=this.opt("dateIncrement"),o?(a=e.duration(o),l=a").prependTo(n),this.initToolbars(),this.renderHeader(),this.renderFooter(),this.renderView(this.opt("defaultView")),this.opt("handleWindowResize")&&t(window).resize(this.windowResizeProxy=ut(this.windowResize.bind(this),this.opt("windowResizeDelay")))},destroy:function(){this.view&&this.clearView(),this.toolbarsManager.proxyCall("removeElement"),this.contentEl.remove(),this.el.removeClass("fc fc-ltr fc-rtl"),this.optionsModel.unwatch("settingTheme"),this.optionsModel.unwatch("settingBusinessHourGenerator"),this.el.off(".fc"),this.windowResizeProxy&&(t(window).unbind("resize",this.windowResizeProxy),this.windowResizeProxy=null),me.unneeded()},elementVisible:function(){return this.el.is(":visible")},bindViewHandlers:function(t){var e=this;t.watch("titleForCalendar",["title"],function(n){t===e.view&&e.setToolbarsTitle(n.title)}),t.watch("dateProfileForCalendar",["dateProfile"],function(n){t===e.view&&(e.currentDate=n.dateProfile.date,e.updateToolbarButtons(n.dateProfile))})},unbindViewHandlers:function(t){this.stopListeningTo(t),t.unwatch("titleForCalendar"),t.unwatch("dateProfileForCalendar")},renderView:function(e){var n,i=this.view;this.freezeContentHeight(),i&&e&&i.type!==e&&this.clearView(),!this.view&&e&&(n=this.view=this.viewsByType[e]||(this.viewsByType[e]=this.instantiateView(e)),this.bindViewHandlers(n),n.setElement(t("
").appendTo(this.contentEl)),this.toolbarsManager.proxyCall("activateButton",e)),this.view&&(this.view.get("businessHourGenerator")!==this.businessHourGenerator&&this.view.set("businessHourGenerator",this.businessHourGenerator),this.view.setDate(this.currentDate)),this.thawContentHeight()},clearView:function(){var t=this.view;this.toolbarsManager.proxyCall("deactivateButton",t.type),this.unbindViewHandlers(t),t.removeElement(),this.view=null},reinitView:function(){var t=this.view,e=t.queryScroll();this.freezeContentHeight(),this.clearView(),this.calcSize(),this.renderView(t.type),this.view.applyScroll(e),this.thawContentHeight()},getSuggestedViewHeight:function(){return null===this.suggestedViewHeight&&this.calcSize(),this.suggestedViewHeight},isHeightAuto:function(){return"auto"===this.opt("contentHeight")||"auto"===this.opt("height")},updateViewSize:function(t){var e,n=this.view;if(!this.ignoreUpdateViewSize&&n)return t&&(this.calcSize(),e=n.queryScroll()),this.ignoreUpdateViewSize++,n.updateSize(this.getSuggestedViewHeight(),this.isHeightAuto(),t),this.ignoreUpdateViewSize--,t&&n.applyScroll(e),!0},calcSize:function(){this.elementVisible()&&this._calcSize()},_calcSize:function(){var t=this.opt("contentHeight"),e=this.opt("height");this.suggestedViewHeight="number"==typeof t?t:"function"==typeof t?t():"number"==typeof e?e-this.queryToolbarsHeight():"function"==typeof e?e()-this.queryToolbarsHeight():"parent"===e?this.el.parent().height()-this.queryToolbarsHeight():Math.round(this.contentEl.width()/Math.max(this.opt("aspectRatio"),.5))},windowResize:function(t){t.target===window&&this.view&&this.view.isDatesRendered&&this.updateViewSize(!0)&&this.publiclyTrigger("windowResize",[this.view])},freezeContentHeight:function(){this.freezeContentHeightDepth++||this.forceFreezeContentHeight()},forceFreezeContentHeight:function(){this.contentEl.css({width:"100%",height:this.contentEl.height(),overflow:"hidden"})},thawContentHeight:function(){this.freezeContentHeightDepth--,this.contentEl.css({width:"",height:"",overflow:""}),this.freezeContentHeightDepth&&this.forceFreezeContentHeight()}}),Le.mixin({header:null,footer:null,toolbarsManager:null,initToolbars:function(){this.header=new bt(this,this.computeHeaderOptions()),this.footer=new bt(this,this.computeFooterOptions()),this.toolbarsManager=new yt([this.header,this.footer])},computeHeaderOptions:function(){return{extraClasses:"fc-header-toolbar",layout:this.opt("header")}},computeFooterOptions:function(){return{extraClasses:"fc-footer-toolbar",layout:this.opt("footer")}},renderHeader:function(){var t=this.header;t.setToolbarOptions(this.computeHeaderOptions()),t.render(),t.el&&this.el.prepend(t.el)},renderFooter:function(){var t=this.footer;t.setToolbarOptions(this.computeFooterOptions()),t.render(),t.el&&this.el.append(t.el)},setToolbarsTitle:function(t){this.toolbarsManager.proxyCall("updateTitle",t)},updateToolbarButtons:function(t){var e=this.getNow(),n=this.view,i=n.buildDateProfile(e),r=n.buildPrevDateProfile(this.currentDate),s=n.buildNextDateProfile(this.currentDate);this.toolbarsManager.proxyCall(i.isValid&&!t.currentUnzonedRange.containsDate(e)?"enableButton":"disableButton","today"),this.toolbarsManager.proxyCall(r.isValid?"enableButton":"disableButton","prev"),this.toolbarsManager.proxyCall(s.isValid?"enableButton":"disableButton","next")},queryToolbarsHeight:function(){return this.toolbarsManager.items.reduce(function(t,e){return t+(e.el?e.el.outerHeight(!0):0)},0)}}),Le.prototype.isEventInstanceGroupAllowed=function(t){var e,n=t.getEventDef(),i=this.eventRangesToEventFootprints(t.getAllEventRanges()),r=this.getPeerEventInstances(n),s=r.map(Pt),o=this.eventRangesToEventFootprints(s),a=n.getConstraint(),l=n.getOverlap(),u=this.opt("eventAllow");for(e=0;et.startMs)&&(null===this.startMs||null===t.endMs||this.startMs=this.startMs)&&(null===this.endMs||null!==t.endMs&&t.endMs<=this.endMs)},containsDate:function(t){var e=t.valueOf();return(null===this.startMs||e>=this.startMs)&&(null===this.endMs||e=this.endMs&&(e=this.endMs-1),e},equals:function(t){return this.startMs===t.startMs&&this.endMs===t.endMs},clone:function(){var t=new Ue(this.startMs,this.endMs);return t.isStart=this.isStart,t.isEnd=this.isEnd,t},getStart:function(){if(null!==this.startMs)return Wt.moment.utc(this.startMs).stripZone()},getEnd:function(){if(null!==this.endMs)return Wt.moment.utc(this.endMs).stripZone()},as:function(t){return e.utc(this.endMs).diff(e.utc(this.startMs),t,!0)}}),We=Wt.ComponentFootprint=dt.extend({unzonedRange:null,isAllDay:!1,constructor:function(t,e){this.unzonedRange=t,this.isAllDay=e},toLegacy:function(t){return{start:t.msToMoment(this.unzonedRange.startMs,this.isAllDay),end:t.msToMoment(this.unzonedRange.endMs,this.isAllDay)}}}),_e=dt.extend(re,{start:null,end:null,timezone:null,unzonedRange:null,requestsByUid:null,pendingCnt:0,freezeDepth:0,stuntedReleaseCnt:0,releaseCnt:0,eventDefsByUid:null,eventDefsById:null,eventInstanceGroupsById:null,constructor:function(t,e,n){this.start=t,this.end=e,this.timezone=n,this.unzonedRange=new Ue(t.clone().stripZone(),e.clone().stripZone()),this.requestsByUid={},this.eventDefsByUid={},this.eventDefsById={},this.eventInstanceGroupsById={}},isWithinRange:function(t,e){return!t.isBefore(this.start)&&!e.isAfter(this.end)},requestSources:function(t){this.freeze();for(var e=0;e
'),s=r.find("tr"),a>0&&s.append(''),s.append(n.el.attr("colspan",l-a)),l'),this.component.bookendCells(s),r}}),mn=He.extend({dayGrid:null,rowStructs:null,constructor:function(t){He.apply(this,arguments),this.dayGrid=t},renderBgRanges:function(e){e=t.grep(e,function(t){return t.eventDef.isAllDay()}),He.prototype.renderBgRanges.call(this,e)},renderFgSegs:function(e){var n=this.rowStructs=this.renderSegRows(e);this.dayGrid.rowEls.each(function(e,i){t(i).find(".fc-content-skeleton > table").append(n[e].tbodyEl)})},unrenderFgSegs:function(){for(var t,e=this.rowStructs||[];t=e.pop();)t.tbodyEl.remove();this.rowStructs=null},renderSegRows:function(t){var e,n,i=[];for(e=this.groupSegRows(t),n=0;n"),a.append(c)),v[r][o]=c,m[r][o]=c,o++}var r,s,o,a,l,u,c,h=this.dayGrid.colCnt,d=this.buildSegLevels(n),f=Math.max(1,d.length),g=t(""),p=[],v=[],m=[];for(r=0;r"),p.push([]),v.push([]),m.push([]),s)for(l=0;l').append(u.el),u.leftCol!=u.rightCol?c.attr("colspan",u.rightCol-u.leftCol+1):m[r][o]=c;o<=u.rightCol;)v[r][o]=c,p[r][o]=u,o++;a.append(c)}i(h),this.dayGrid.bookendCells(a),g.append(a)}return{row:e,tbodyEl:g,cellMatrix:v,segMatrix:p,segLevels:d,segs:n}},buildSegLevels:function(t){var e,n,i,r=[];for(this.sortEventSegs(t),e=0;e'+et(n)+""),i=''+(et(s.title||"")||" ")+"",'
'+(this.isRTL?i+" "+d:d+" "+i)+"
"+(l?'
':"")+(u?'
':"")+""}}),yn=Pe.extend({renderSegs:function(e,n){var i,r=[];return i=this.eventRenderer.renderSegRows(e),this.component.rowEls.each(function(e,s){var o,a,l=t(s),u=t('
');n&&n.row===e?a=n.el.position().top:(o=l.find(".fc-content-skeleton tbody"),o.length||(o=l.find(".fc-content-skeleton table")),a=o.position().top),u.css("top",a).find("table").append(i[e].tbodyEl),l.append(u),r.push(u[0])}),t(r)}}),wn=Wt.DayGrid=ke.extend(Ie,Be,{eventRendererClass:mn,businessHourRendererClass:Me,helperRendererClass:yn,fillRendererClass:vn,view:null,helperRenderer:null,cellWeekNumbersVisible:!1,bottomCoordPadding:0,headContainerEl:null,rowEls:null,cellEls:null,rowCoordCache:null,colCoordCache:null,isRigid:!1,hasAllDayBusinessHours:!0,constructor:function(t){this.view=t,ke.call(this)},componentFootprintToSegs:function(t){var e,n,i=this.sliceRangeByRow(t.unzonedRange);for(e=0;e
'+this.renderBgTrHtml(t)+'
'+(this.getIsNumbersVisible()?""+this.renderNumberTrHtml(t)+"":"")+"
"},getIsNumbersVisible:function(){return this.getIsDayNumbersVisible()||this.cellWeekNumbersVisible},getIsDayNumbersVisible:function(){return this.rowCnt>1},renderNumberTrHtml:function(t){return""+(this.isRTL?"":this.renderNumberIntroHtml(t))+this.renderNumberCellsHtml(t)+(this.isRTL?this.renderNumberIntroHtml(t):"")+""},renderNumberIntroHtml:function(t){return this.renderIntroHtml()},renderNumberCellsHtml:function(t){var e,n,i=[];for(e=0;e",this.cellWeekNumbersVisible&&t.day()==n&&(r+=i.buildGotoAnchorHtml({date:t,type:"week"},{class:"fc-week-number"},t.format("w"))),o&&(r+=i.buildGotoAnchorHtml(t,{class:"fc-day-number"},t.date())),r+=""):""},prepareHits:function(){this.colCoordCache.build(),this.rowCoordCache.build(),this.rowCoordCache.bottoms[this.rowCnt-1]+=this.bottomCoordPadding},releaseHits:function(){this.colCoordCache.clear(),this.rowCoordCache.clear()},queryHit:function(t,e){if(this.colCoordCache.isLeftInBounds(t)&&this.rowCoordCache.isTopInBounds(e)){var n=this.colCoordCache.getHorizontalIndex(t),i=this.rowCoordCache.getVerticalIndex(e);if(null!=i&&null!=n)return this.getCellHit(i,n)}},getHitFootprint:function(t){var e=this.getCellRange(t.row,t.col);return new We(new Ue(e.start,e.end),!0)},getHitEl:function(t){return this.getCellEl(t.row,t.col)},getCellHit:function(t,e){return{row:t,col:e,component:this,left:this.colCoordCache.getLeftOffset(e),right:this.colCoordCache.getRightOffset(e),top:this.rowCoordCache.getTopOffset(t),bottom:this.rowCoordCache.getBottomOffset(t)}},getCellEl:function(t,e){return this.cellEls.eq(t*this.colCnt+e)},unrenderEvents:function(){this.removeSegPopover(),ke.prototype.unrenderEvents.apply(this,arguments)},getOwnEventSegs:function(){return ke.prototype.getOwnEventSegs.apply(this,arguments).concat(this.popoverSegs||[])},renderDrag:function(t,e,n){var i;for(i=0;i td > :first-child").each(n),r.position().top+s>a)return i;return!1},limitRow:function(e,n){function i(i){for(;E").append(y),d.append(m),b.push(m[0])),E++}var r,s,o,a,l,u,c,h,d,f,g,p,v,m,y,w=this,D=this.eventRenderer.rowStructs[e],b=[],E=0;if(n&&n').attr("rowspan",f),u=h[p],y=this.renderMoreLink(e,l.leftCol+p,[l].concat(u)),m=t("
").append(y),v.append(m),g.push(v[0]),b.push(v[0]);d.addClass("fc-limited").after(t(g)),o.push(d[0])}}i(this.colCnt),D.moreEls=t(b),D.limitedEls=t(o)}},unlimitRow:function(t){var e=this.eventRenderer.rowStructs[t];e.moreEls&&(e.moreEls.remove(),e.moreEls=null),e.limitedEls&&(e.limitedEls.removeClass("fc-limited"),e.limitedEls=null)},renderMoreLink:function(e,n,i){var r=this,s=this.view;return t('').text(this.getMoreLinkText(i.length)).on("click",function(o){var a=r.opt("eventLimitClick"),l=r.getCellDate(e,n),u=t(this),c=r.getCellEl(e,n),h=r.getCellSegs(e,n),d=r.resliceDaySegs(h,l),f=r.resliceDaySegs(i,l);"function"==typeof a&&(a=r.publiclyTrigger("eventLimitClick",{context:s,args:[{date:l.clone(),dayEl:c,moreEl:u,segs:d,hiddenSegs:f},o,s]})),"popover"===a?r.showSegPopover(e,n,u,d):"string"==typeof a&&s.calendar.zoomTo(l,a)})},showSegPopover:function(t,e,n,i){var r,s,o=this,a=this.view,l=n.parent();r=1==this.rowCnt?a.el:this.rowEls.eq(t),s={className:"fc-more-popover "+a.calendar.theme.getClass("popover"),content:this.renderSegPopoverContent(t,e,i),parentEl:a.el,top:r.offset().top,autoHide:!0,viewportConstrain:this.opt("popoverViewportConstrain"),hide:function(){o.popoverSegs&&o.triggerBeforeEventSegsDestroyed(o.popoverSegs),o.segPopover.removeElement(),o.segPopover=null,o.popoverSegs=null}},this.isRTL?s.right=l.offset().left+l.outerWidth()+1:s.left=l.offset().left-1,this.segPopover=new fe(s),this.segPopover.show(),this.bindAllSegHandlersToEl(this.segPopover.el),this.triggerAfterEventSegsRendered(i)},renderSegPopoverContent:function(e,n,i){var r,s=this.view,o=s.calendar.theme,a=this.getCellDate(e,n).format(this.opt("dayPopoverFormat")),l=t('
'+et(a)+'
'),u=l.find(".fc-event-container");for(i=this.eventRenderer.renderFgSegEls(i,!0),this.popoverSegs=i,r=0;r').appendTo(e),this.el.find(".fc-body > tr > td").append(e),this.dayGrid.headContainerEl=this.el.find(".fc-head-container"),this.dayGrid.setElement(n)},unrenderSkeleton:function(){this.dayGrid.removeElement(),this.scroller.destroy()},renderSkeletonHtml:function(){var t=this.calendar.theme;return''+(this.opt("columnHeader")?'':"")+'
 
'},weekNumberStyleAttr:function(){return null!==this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},hasRigidRows:function(){var t=this.opt("eventLimit");return t&&"number"!=typeof t},updateSize:function(t,e,n){var s,o,a=this.opt("eventLimit"),l=this.dayGrid.headContainerEl.find(".fc-row");if(!this.dayGrid.rowEls)return void(e||(s=this.computeScrollerHeight(t),this.scroller.setHeight(s)));Ae.prototype.updateSize.apply(this,arguments),this.dayGrid.colWeekNumbersVisible&&(this.weekNumberWidth=u(this.el.find(".fc-week-number"))),this.scroller.clear(),r(l),this.dayGrid.removeSegPopover(),a&&"number"==typeof a&&this.dayGrid.limitRows(a),s=this.computeScrollerHeight(t),this.setGridHeight(s,e),a&&"number"!=typeof a&&this.dayGrid.limitRows(a),e||(this.scroller.setHeight(s),o=this.scroller.getScrollbarWidths(),(o.left||o.right)&&(i(l,o),s=this.computeScrollerHeight(t),this.scroller.setHeight(s)),this.scroller.lockOverflow(o))},computeScrollerHeight:function(t){return t-c(this.el,this.scroller.el)},setGridHeight:function(t,e){e?l(this.dayGrid.rowEls):a(this.dayGrid.rowEls,t,!0)},computeInitialDateScroll:function(){return{top:0}},queryDateScroll:function(){return{top:this.scroller.getScrollTop()}},applyDateScroll:function(t){void 0!==t.top&&this.scroller.setScrollTop(t.top)}}),bn={colWeekNumbersVisible:!1,renderHeadIntroHtml:function(){var t=this.view;return this.colWeekNumbersVisible?'"+et(this.opt("weekNumberTitle"))+"":""},renderNumberIntroHtml:function(t){var e=this.view,n=this.getCellDate(t,0);return this.colWeekNumbersVisible?'"+e.buildGotoAnchorHtml({date:n,type:"week",forceOff:1===this.colCnt},n.format("w"))+"":""},renderBgIntroHtml:function(){var t=this.view;return this.colWeekNumbersVisible?'":""},renderIntroHtml:function(){var t=this.view +;return this.colWeekNumbersVisible?'":""},getIsNumbersVisible:function(){return wn.prototype.getIsNumbersVisible.apply(this,arguments)||this.colWeekNumbersVisible}},En=Wt.MonthView=Dn.extend({buildRenderRange:function(t,e,n){var i,r=Dn.prototype.buildRenderRange.apply(this,arguments),s=this.calendar.msToUtcMoment(r.startMs,n),o=this.calendar.msToUtcMoment(r.endMs,n);return this.isFixedWeeks()&&(i=Math.ceil(o.diff(s,"weeks",!0)),o.add(6-i,"weeks")),new Ue(s,o)},setGridHeight:function(t,e){e&&(t*=this.rowCnt/6),a(this.dayGrid.rowEls,t,!e)},isFixedWeeks:function(){return this.opt("fixedWeekCount")},isDateInOtherMonth:function(t,n){return t.month()!==e.utc(n.currentUnzonedRange.startMs).month()}});_t.basic={class:Dn},_t.basicDay={type:"basic",duration:{days:1}},_t.basicWeek={type:"basic",duration:{weeks:1}},_t.month={class:En,duration:{months:1},defaults:{fixedWeekCount:!0}};var Sn=xe.extend({attachSegEls:function(t,e){var n,i=this.component;return"bgEvent"===t?n=i.bgContainerEls:"businessHours"===t?n=i.businessContainerEls:"highlight"===t&&(n=i.highlightContainerEls),i.updateSegVerticals(e),i.attachSegsByCol(i.groupSegsByCol(e),n),e.map(function(t){return t.el[0]})}}),Cn=He.extend({timeGrid:null,constructor:function(t){He.apply(this,arguments),this.timeGrid=t},renderFgSegs:function(t){this.renderFgSegsIntoContainers(t,this.timeGrid.fgContainerEls)},renderFgSegsIntoContainers:function(t,e){var n,i;for(n=this.timeGrid.groupSegsByCol(t),i=0;i
'+(n?'
'+et(n)+"
":"")+(u.title?'
'+et(u.title)+"
":"")+'
'+(d?'
':"")+""},updateFgSegCoords:function(t){this.timeGrid.computeSegVerticals(t),this.computeFgSegHorizontals(t),this.timeGrid.assignSegVerticals(t),this.assignFgSegHorizontals(t)},computeFgSegHorizontals:function(t){var e,n,i;if(this.sortEventSegs(t),e=Lt(t),Ot(e),n=e[0]){for(i=0;i=0;n--)if(i=e.duration(Pn[n]),r=U(i,t),at(r)&&r>1)return i;return e.duration(t)},renderDates:function(t){this.dateProfile=t,this.updateDayTable(),this.renderSlats(),this.renderColumns()},renderSkeleton:function(){var t=this.view.calendar.theme;this.el.html('
'),this.bottomRuleEl=this.el.find("hr")},renderSlats:function(){var t=this.view.calendar.theme;this.slatContainerEl=this.el.find("> .fc-slats").html(''+this.renderSlatRowHtml()+"
"),this.slatEls=this.slatContainerEl.find("tr"),this.slatCoordCache=new ge({els:this.slatEls,isVertical:!0})},renderSlatRowHtml:function(){for(var t,n,i,r=this.view,s=r.calendar,o=s.theme,a=this.isRTL,l=this.dateProfile,u="",c=e.duration(+l.minTime),h=e.duration(0);c"+(n?""+et(t.format(this.labelFormat))+"":"")+"",u+='"+(a?"":i)+''+(a?i:"")+"",c.add(this.slotDuration),h.add(this.slotDuration);return u},renderColumns:function(){var t=this.dateProfile,e=this.view.calendar.theme;this.dayRanges=this.dayDates.map(function(e){return new Ue(e.clone().add(t.minTime),e.clone().add(t.maxTime))}),this.headContainerEl&&this.headContainerEl.html(this.renderHeadHtml()),this.el.find("> .fc-bg").html(''+this.renderBgTrHtml(0)+"
"),this.colEls=this.el.find(".fc-day, .fc-disabled-day"),this.colCoordCache=new ge({els:this.colEls,isHorizontal:!0}),this.renderContentSkeleton()},renderContentSkeleton:function(){var e,n,i="";for(e=0;e
';n=t('
'+i+"
"),this.colContainerEls=n.find(".fc-content-col"),this.helperContainerEls=n.find(".fc-helper-container"),this.fgContainerEls=n.find(".fc-event-container:not(.fc-helper-container)"),this.bgContainerEls=n.find(".fc-bgevent-container"),this.highlightContainerEls=n.find(".fc-highlight-container"),this.businessContainerEls=n.find(".fc-business-container"),this.bookendCells(n.find("tr")),this.el.append(n)},groupSegsByCol:function(t){var e,n=[];for(e=0;e
').css("top",r).appendTo(this.colContainerEls.eq(i[n].col))[0]);i.length>0&&s.push(t('
').css("top",r).appendTo(this.el.find(".fc-content-skeleton"))[0]),this.nowIndicatorEls=t(s)},unrenderNowIndicator:function(){this.nowIndicatorEls&&(this.nowIndicatorEls.remove(),this.nowIndicatorEls=null)},updateSize:function(t,e,n){ke.prototype.updateSize.apply(this,arguments),this.slatCoordCache.build(),n&&this.updateSegVerticals([].concat(this.eventRenderer.getSegs(),this.businessSegs||[]))},getTotalSlatHeight:function(){return this.slatContainerEl.outerHeight()},computeDateTop:function(t,n){return this.computeTimeTop(e.duration(t-n.clone().stripTime()))},computeTimeTop:function(t){var e,n,i=this.slatEls.length,r=this.dateProfile,s=(t-r.minTime)/this.slotDuration;return s=Math.max(0,s),s=Math.min(i,s),e=Math.floor(s),e=Math.min(e,i-1),n=s-e,this.slatCoordCache.getTopPosition(e)+this.slatCoordCache.getHeight(e)*n},updateSegVerticals:function(t){this.computeSegVerticals(t),this.assignSegVerticals(t)},computeSegVerticals:function(t){var e,n,i,r=this.opt("agendaEventMinHeight");for(e=0;e').appendTo(e),this.el.find(".fc-body > tr > td").append(e),this.timeGrid.headContainerEl=this.el.find(".fc-head-container"),this.timeGrid.setElement(n),this.dayGrid&&(this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight())},unrenderSkeleton:function(){this.timeGrid.removeElement(),this.dayGrid&&this.dayGrid.removeElement(),this.scroller.destroy()},renderSkeletonHtml:function(){var t=this.calendar.theme;return''+(this.opt("columnHeader")?'':"")+'
 
'+(this.dayGrid?'

':"")+"
"},axisStyleAttr:function(){return null!==this.axisWidth?'style="width:'+this.axisWidth+'px"':""},getNowIndicatorUnit:function(){return this.timeGrid.getNowIndicatorUnit()},updateSize:function(t,e,n){var s,o,a;if(Ae.prototype.updateSize.apply(this,arguments),this.axisWidth=u(this.el.find(".fc-axis")),!this.timeGrid.colEls)return void(e||(o=this.computeScrollerHeight(t),this.scroller.setHeight(o)));var l=this.el.find(".fc-row:not(.fc-scroller *)");this.timeGrid.bottomRuleEl.hide(),this.scroller.clear(),r(l),this.dayGrid&&(this.dayGrid.removeSegPopover(),s=this.opt("eventLimit"),s&&"number"!=typeof s&&(s=xn),s&&this.dayGrid.limitRows(s)),e||(o=this.computeScrollerHeight(t),this.scroller.setHeight(o),a=this.scroller.getScrollbarWidths(),(a.left||a.right)&&(i(l,a),o=this.computeScrollerHeight(t),this.scroller.setHeight(o)),this.scroller.lockOverflow(a),this.timeGrid.getTotalSlatHeight()"+e.buildGotoAnchorHtml({date:i,type:"week",forceOff:this.colCnt>1},et(t))+""):'"},renderBgIntroHtml:function(){var t=this.view;return'"},renderIntroHtml:function(){return'"}},Mn={renderBgIntroHtml:function(){var t=this.view;return'"+t.getAllDayHtml()+""},renderIntroHtml:function(){return'"}},xn=5,Pn=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];_t.agenda={class:In,defaults:{allDaySlot:!0,slotDuration:"00:30:00",slotEventOverlap:!0}},_t.agendaDay={type:"agenda",duration:{days:1}},_t.agendaWeek={type:"agenda",duration:{weeks:1}};var zn=Wt.ListView=Ae.extend({segSelector:".fc-list-item",scroller:null,contentEl:null,dayDates:null,dayRanges:null,constructor:function(){Ae.apply(this,arguments),this.scroller=new we({overflowX:"hidden",overflowY:"auto"})},renderSkeleton:function(){this.el.addClass("fc-list-view "+this.calendar.theme.getClass("listView")),this.scroller.render(),this.scroller.el.appendTo(this.el),this.contentEl=this.scroller.scrollEl},unrenderSkeleton:function(){this.scroller.destroy()},updateSize:function(t,e,n){this.scroller.setHeight(this.computeScrollerHeight(t))},computeScrollerHeight:function(t){return t-c(this.el,this.scroller.el)},renderDates:function(t){for(var e=this.calendar,n=e.msToUtcMoment(t.renderUnzonedRange.startMs,!0),i=e.msToUtcMoment(t.renderUnzonedRange.endMs,!0),r=[],s=[];n'+(this.displayEventTime?''+(e||"")+"":"")+'"+et(o.title||"")+""},computeEventTimeFormat:function(){return this.opt("mediumTimeFormat")}}),eventPointingClass:Te.extend({handleClick:function(e,n){var i;Te.prototype.handleClick.apply(this,arguments),t(n.target).closest("a[href]").length||(i=e.footprint.eventDef.url)&&!n.isDefaultPrevented()&&(window.location.href=i)}}),renderEmptyMessage:function(){this.contentEl.html('
'+et(this.opt("noEventsMessage"))+"
")},renderSegList:function(e){var n,i,r,s=this.groupSegsByDay(e),o=t('
'),a=o.find("tbody");for(n=0;n'+(e?this.buildGotoAnchorHtml(t,{class:"fc-list-heading-main"},et(t.format(e))):"")+(n?this.buildGotoAnchorHtml(t,{class:"fc-list-heading-alt"},et(t.format(n))):"")+""}});return _t.list={class:zn,buttonTextKey:"list",defaults:{buttonText:"list",listDayFormat:"LL",noEventsMessage:"No events to display"}},_t.listDay={type:"list",duration:{days:1},defaults:{listDayFormat:"dddd"}},_t.listWeek={type:"list",duration:{weeks:1},defaults:{listDayFormat:"dddd",listDayAltFormat:"LL"}},_t.listMonth={type:"list",duration:{month:1},defaults:{listDayAltFormat:"dddd"}},_t.listYear={type:"list",duration:{year:1},defaults:{listDayAltFormat:"dddd"}},Wt}); diff --git a/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.print.css b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.print.css new file mode 100644 index 00000000..ca4f0c39 --- /dev/null +++ b/src/main/resources/static/assets/platform/plugins/fullcalendar/fullcalendar.print.css @@ -0,0 +1,208 @@ +/*! + * FullCalendar v3.6.1 Print Stylesheet + * Docs & License: https://fullcalendar.io/ + * (c) 2017 Adam Shaw + */ + +/* + * Include this stylesheet on your page to get a more printer-friendly calendar. + * When including this stylesheet, use the media='print' attribute of the tag. + * Make sure to include this stylesheet IN ADDITION to the regular fullcalendar.css. + */ + +.fc { + max-width: 100% !important; +} + + +/* Global Event Restyling +--------------------------------------------------------------------------------------------------*/ + +.fc-event { + background: #fff !important; + color: #000 !important; + page-break-inside: avoid; +} + +.fc-event .fc-resizer { + display: none; +} + + +/* Table & Day-Row Restyling +--------------------------------------------------------------------------------------------------*/ + +.fc th, +.fc td, +.fc hr, +.fc thead, +.fc tbody, +.fc-row { + border-color: #ccc !important; + background: #fff !important; +} + +/* kill the overlaid, absolutely-positioned components */ +/* common... */ +.fc-bg, +.fc-bgevent-skeleton, +.fc-highlight-skeleton, +.fc-helper-skeleton, + /* for timegrid. within cells within table skeletons... */ +.fc-bgevent-container, +.fc-business-container, +.fc-highlight-container, +.fc-helper-container { + display: none; +} + +/* don't force a min-height on rows (for DayGrid) */ +.fc tbody .fc-row { + height: auto !important; /* undo height that JS set in distributeHeight */ + min-height: 0 !important; /* undo the min-height from each view's specific stylesheet */ +} + +.fc tbody .fc-row .fc-content-skeleton { + position: static; /* undo .fc-rigid */ + padding-bottom: 0 !important; /* use a more border-friendly method for this... */ +} + +.fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td { /* only works in newer browsers */ + padding-bottom: 1em; /* ...gives space within the skeleton. also ensures min height in a way */ +} + +.fc tbody .fc-row .fc-content-skeleton table { + /* provides a min-height for the row, but only effective for IE, which exaggerates this value, + making it look more like 3em. for other browers, it will already be this tall */ + height: 1em; +} + + +/* Undo month-view event limiting. Display all events and hide the "more" links +--------------------------------------------------------------------------------------------------*/ + +.fc-more-cell, +.fc-more { + display: none !important; +} + +.fc tr.fc-limited { + display: table-row !important; +} + +.fc td.fc-limited { + display: table-cell !important; +} + +.fc-popover { + display: none; /* never display the "more.." popover in print mode */ +} + + +/* TimeGrid Restyling +--------------------------------------------------------------------------------------------------*/ + +/* undo the min-height 100% trick used to fill the container's height */ +.fc-time-grid { + min-height: 0 !important; +} + +/* don't display the side axis at all ("all-day" and time cells) */ +.fc-agenda-view .fc-axis { + display: none; +} + +/* don't display the horizontal lines */ +.fc-slats, +.fc-time-grid hr { /* this hr is used when height is underused and needs to be filled */ + display: none !important; /* important overrides inline declaration */ +} + +/* let the container that holds the events be naturally positioned and create real height */ +.fc-time-grid .fc-content-skeleton { + position: static; +} + +/* in case there are no events, we still want some height */ +.fc-time-grid .fc-content-skeleton table { + height: 4em; +} + +/* kill the horizontal spacing made by the event container. event margins will be done below */ +.fc-time-grid .fc-event-container { + margin: 0 !important; +} + + +/* TimeGrid *Event* Restyling +--------------------------------------------------------------------------------------------------*/ + +/* naturally position events, vertically stacking them */ +.fc-time-grid .fc-event { + position: static !important; + margin: 3px 2px !important; +} + +/* for events that continue to a future day, give the bottom border back */ +.fc-time-grid .fc-event.fc-not-end { + border-bottom-width: 1px !important; +} + +/* indicate the event continues via "..." text */ +.fc-time-grid .fc-event.fc-not-end:after { + content: "..."; +} + +/* for events that are continuations from previous days, give the top border back */ +.fc-time-grid .fc-event.fc-not-start { + border-top-width: 1px !important; +} + +/* indicate the event is a continuation via "..." text */ +.fc-time-grid .fc-event.fc-not-start:before { + content: "..."; +} + +/* time */ + +/* undo a previous declaration and let the time text span to a second line */ +.fc-time-grid .fc-event .fc-time { + white-space: normal !important; +} + +/* hide the the time that is normally displayed... */ +.fc-time-grid .fc-event .fc-time span { + display: none; +} + +/* ...replace it with a more verbose version (includes AM/PM) stored in an html attribute */ +.fc-time-grid .fc-event .fc-time:after { + content: attr(data-full); +} + + +/* Vertical Scroller & Containers +--------------------------------------------------------------------------------------------------*/ + +/* kill the scrollbars and allow natural height */ +.fc-scroller, +.fc-day-grid-container, /* these divs might be assigned height, which we need to cleared */ +.fc-time-grid-container { /* */ + overflow: visible !important; + height: auto !important; +} + +/* kill the horizontal border/padding used to compensate for scrollbars */ +.fc-row { + border: 0 !important; + margin: 0 !important; +} + + +/* Button Controls +--------------------------------------------------------------------------------------------------*/ + +.fc-button-group, +.fc button { + display: none; /* don't display any button-related controls */ +} diff --git a/src/main/resources/static/components/module/trainSignUp/TrainDynamicForm.vue b/src/main/resources/static/components/module/trainSignUp/TrainDynamicForm.vue index d1fca8b3..a254d419 100644 --- a/src/main/resources/static/components/module/trainSignUp/TrainDynamicForm.vue +++ b/src/main/resources/static/components/module/trainSignUp/TrainDynamicForm.vue @@ -9,7 +9,7 @@