diff --git a/src/main/java/io/v/nutz/activity/models/SchoolAssignGrades.java b/src/main/java/io/v/nutz/activity/models/SchoolAssignGrades.java index 05d5e2c..b89a305 100644 --- a/src/main/java/io/v/nutz/activity/models/SchoolAssignGrades.java +++ b/src/main/java/io/v/nutz/activity/models/SchoolAssignGrades.java @@ -37,7 +37,7 @@ public class SchoolAssignGrades { @Column - @Comment("所属单位") + @Comment("") @ColDefine(type = ColType.VARCHAR, width = 32) private String unitId; diff --git a/src/main/java/io/v/nutz/meeting/controller/mobile/MMeetingNotifyController.java b/src/main/java/io/v/nutz/meeting/controller/mobile/MMeetingNotifyController.java new file mode 100644 index 0000000..f944756 --- /dev/null +++ b/src/main/java/io/v/nutz/meeting/controller/mobile/MMeetingNotifyController.java @@ -0,0 +1,102 @@ +package io.v.nutz.meeting.controller.mobile; + +import cn.wizzer.framework.base.Result; +import io.v.nutz.annontation.ViReturn; +import io.v.nutz.meeting.models.MeetingInfo; +import io.v.nutz.meeting.models.MeetingTimePeriodUser; +import io.v.nutz.meeting.models.MeetingUser; +import io.v.nutz.web.commons.utils.ShiroUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authz.annotation.RequiresAuthentication; +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.Lang; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.GET; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +@IocBean +@Slf4j +@At("/mobile/meeting/notify") +public class MMeetingNotifyController { + + @Inject + private Dao dao; + + @At("") + @Ok("beetl:/mobile/meeting/notify.html") + @RequiresAuthentication + public void index(HttpServletRequest request) { + + } + + @At("/getMeetingInfo") + @Ok("json:full") + @ViReturn + @RequiresAuthentication + public Object getMeetingInfo(@Param("meetingId") String meetingId) { + MeetingInfo meetingInfo = dao.fetch(MeetingInfo.class, meetingId); + dao.fetchLinks(meetingInfo, "meetingTimePeriods", Cnd.NEW().asc("startTime")); + + Cnd cnd = Cnd.NEW(); + cnd.and("userId", "=", ShiroUtil.getPrincipalProperty("id")); + MeetingTimePeriodUser mtPu = dao.fetch(MeetingTimePeriodUser.class, cnd); + + if (Lang.isEmpty(meetingInfo)) { + return Result.error("参数错误"); + } + if (Lang.isEmpty(mtPu)) { + return Result.error("你不是当前会议人员"); + } + + return meetingInfo; + } + + @At("/joinDo") + @Ok("json:full") + @ViReturn + @RequiresAuthentication + public Object joinDo(@Param("isJoin") Boolean isJoin, + @Param("notJoinReason") String notJoinReason, + @Param("ids") String[] ids, + @Param("meetingId") String meetingId) { + List periodUsers = dao.query(MeetingTimePeriodUser.class, Cnd.where("meetingId", "=", meetingId) + .and("userId", "=", ShiroUtil.getPlatformUid())); + if (isJoin) { + //参加 + periodUsers.forEach(item -> { + item.setIsJoinByMsg(true); + }); + } else { + List strings = Arrays.asList(ids); + periodUsers.forEach(item -> { + if (strings.contains(item.getMeetingTimePeriodId())) { + item.setIsJoinByMsg(false); + item.setNotJoinReason(notJoinReason); + } else { + item.setIsJoinByMsg(true); + } + }); + } + dao.update(periodUsers); + return null; + } + + @At("/readDo") + @Ok("json:full") + @ViReturn + @RequiresAuthentication + public Object readDo(@Param("meetingId") String meetingId) { + dao.update(MeetingUser.class, Chain.make("isReadByMsg", true), Cnd.where("meetingId", "=", meetingId).and("userId", "=", ShiroUtil.getPlatformUid())); + return null; + } +} diff --git a/src/main/java/io/v/nutz/meeting/controller/mobile/MMeetingShortUrlController.java b/src/main/java/io/v/nutz/meeting/controller/mobile/MMeetingShortUrlController.java new file mode 100644 index 0000000..edd8be6 --- /dev/null +++ b/src/main/java/io/v/nutz/meeting/controller/mobile/MMeetingShortUrlController.java @@ -0,0 +1,30 @@ +package io.v.nutz.meeting.controller.mobile; + +import io.v.nutz.meeting.models.ShortUrl; +import io.v.nutz.web.commons.base.Globals; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authz.annotation.RequiresAuthentication; +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; + +@IocBean +@Slf4j +@At("/s") +public class MMeetingShortUrlController { + + @Inject + private Dao dao; + + @At("/**") + @Ok("re") + @RequiresAuthentication + public String index(String key) throws Exception { + ShortUrl shortUrl = dao.fetch(ShortUrl.class, Cnd.where("shortUrl", "=", key)); + String realPath = Globals.AppDomain + shortUrl.getRealUrl(); + return ">>:" + realPath; + } +} diff --git a/src/main/java/io/v/nutz/meeting/controller/pc/MeetingManageController.java b/src/main/java/io/v/nutz/meeting/controller/pc/MeetingManageController.java index ff78609..f52c677 100644 --- a/src/main/java/io/v/nutz/meeting/controller/pc/MeetingManageController.java +++ b/src/main/java/io/v/nutz/meeting/controller/pc/MeetingManageController.java @@ -1,16 +1,23 @@ package io.v.nutz.meeting.controller.pc; +import cn.hutool.core.util.StrUtil; +import cn.wizzer.framework.base.Result; import io.v.nutz.annontation.ViReturn; import io.v.nutz.meeting.models.MeetingInfo; import io.v.nutz.meeting.models.MeetingUser; +import io.v.nutz.meeting.models.ShortUrl; import io.v.nutz.meeting.service.MeetingManageService; import io.v.nutz.modules.models.PageForm; import io.v.nutz.msgNotify.models.MsgNotify; import io.v.nutz.msgNotify.service.MsgNotifyService; +import io.v.nutz.web.commons.base.Globals; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresPermissions; 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.sql.VarIndex; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.util.NutMap; @@ -20,8 +27,10 @@ import org.nutz.mvc.annotation.POST; import org.nutz.mvc.annotation.Param; import javax.servlet.http.HttpServletRequest; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; @IocBean @At("/platform/meeting/manage") @@ -155,4 +164,78 @@ public class MeetingManageController { return null; } + @At + @Ok("json:full") + @ViReturn + @RequiresPermissions("meeting.manage.search") + public Object getUserCount(String id) { + return meetingManageService.dao().count(MeetingUser.class, Cnd.where("meetingId", "=", id)); + } + + @At + @Ok("json:full") + @ViReturn + @RequiresPermissions("meeting.manage.search") + public Object sendMsg(String id) { + MeetingInfo meetingInfo = meetingManageService.fetch(id); + MsgNotify msgNotify = meetingManageService.dao().fetch(MsgNotify.class, meetingInfo.getNotifyId()); + + String content = msgNotify.getContent(); + if(StrUtil.isBlank(content)) { + return Result.error("短信内容为空,请点击编辑按钮核查"); + } + + Sql sql = Sqls.create(""" + SELECT + u.username, + u.loginname + FROM + `meeting_user` mu + LEFT JOIN USER u ON mu.userid = u.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("mu.meetingId", "=", id); + sql.setCondition(cnd); + List list = meetingManageService.listMap(sql); + List loginnameList = list.stream().map(o -> o.getString("loginname")).collect(Collectors.toList()); + + //生成短链 + String shortUrl; + int count; + do { + shortUrl = generateRandomString(); + count = dao.count(ShortUrl.class, Cnd.where("shortUrl", "=", shortUrl)); + } while (count > 0); + + //判断最后一个是不是句号 + if (content.endsWith("。") || content.endsWith(";")) { + content += ""; + } else { + content += ","; + } + content += "请点击" + Globals.AppDomain + shortUrl + ",确认是否参加。"; + System.out.println(content); + + ShortUrl sUrl = new ShortUrl(); + sUrl.setShortUrl(shortUrl); + sUrl.setRealUrl("/mobile/meeting/notify?meetingId=" + id); + dao.insert(sUrl); + + msgNotifyService.sendMsg(List.of("msg"), loginnameList, content); + return null; + } + + private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final int CODE_LENGTH = 8; + private static final SecureRandom random = new SecureRandom(); + + public String generateRandomString() { + StringBuilder code = new StringBuilder(CODE_LENGTH); + for (int i = 0; i < CODE_LENGTH; i++) { + int index = random.nextInt(CHARACTERS.length()); + code.append(CHARACTERS.charAt(index)); + } + return code.toString(); + } } diff --git a/src/main/java/io/v/nutz/meeting/controller/pc/statistics/MeetingMsgManageController.java b/src/main/java/io/v/nutz/meeting/controller/pc/statistics/MeetingMsgManageController.java new file mode 100644 index 0000000..558cee5 --- /dev/null +++ b/src/main/java/io/v/nutz/meeting/controller/pc/statistics/MeetingMsgManageController.java @@ -0,0 +1,107 @@ +package io.v.nutz.meeting.controller.pc.statistics; + +import cn.hutool.core.util.StrUtil; +import io.v.nutz.annontation.ViReturn; +import io.v.nutz.meeting.models.MeetingInfo; +import io.v.nutz.meeting.service.MeetingCommonService; +import io.v.nutz.meeting.service.MeetingManageService; +import io.v.nutz.modules.models.PageForm; +import org.apache.shiro.authz.annotation.RequiresPermissions; +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; + +import javax.servlet.http.HttpServletRequest; + +@IocBean +@At("/platform/meeting/msgManage") +public class MeetingMsgManageController { + + @Inject + private Dao dao; + + @Inject + private MeetingManageService meetingManageService; + + @At("") + @Ok("beetl:/platform/meeting/statistics/msgManage.html") + @RequiresPermissions("meeting.msg.manage") + public void index(HttpServletRequest request) { + + } + + @At("/pageData") + @Ok("json:full") + @ViReturn + @RequiresPermissions("meeting.msg.manage") + public Object pageData(PageForm pageForm, + @Param(value = "year", required = false) String year, + @Param(value = "meetingId", required = false) String meetingId, + @Param(value = "unionId", required = false) String unionId, + @Param(value = "unitId", required = false) String unitId) { + Sql sql = Sqls.create(""" + SELECT + mu.id, + mu.meetingId, + u.id as userId, + u.username, + u.loginname, + u.sex, + u.mobile, + u.unitname, + u.unionname, + mu.isReadByMsg, + (select count(1) from meeting_time_period_user mt where mt.meetingId = @meetingId and userId = mu.userId and isJoinByMsg = true) as isJoinByMsg + FROM + `meeting_user` mu left join `user` u on mu.userId = u.id + $condition + """).setParam("meetingId", meetingId); + Cnd cnd = Cnd.NEW(); + cnd.and("mu.meetingId", "=", meetingId); + cnd.andEX("u.unionId", "=", unionId); + cnd.andEX("u.unitId", "=", unitId); + cnd.desc("isReadByMsg").desc("isJoinByMsg"); + sql.setCondition(cnd); + return meetingManageService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + @At("/getMeetingList") + @Ok("json:full") + @ViReturn + @RequiresPermissions("meeting.msg.manage") + public Object getMeetingList(Integer year) { + return dao.query(MeetingInfo.class, Cnd.NEW().andEX("year(startTime)", "=", year)); + } + + @At("/getLeaveInfoByUser") + @Ok("json:full") + @ViReturn + @RequiresPermissions("meeting.msg.manage") + public Object getLeaveInfoByUser(String meetingId, String userId) { + Sql sql = Sqls.create(""" + SELECT + mp.timePeriodName, + mp.startTime, + mp.endTime, + mt.isJoinByMsg, + mt.notJoinReason + FROM + meeting_time_period_user mt + LEFT JOIN meeting_info mi ON mt.meetingId = mi.id + LEFT JOIN meeting_time_period mp ON mt.meetingTimePeriodId = mp.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("mt.meetingId", "=", meetingId); + cnd.and("mt.userId", "=", userId); + cnd.asc("mp.startTime"); + sql.setCondition(cnd); + return meetingManageService.listMap(sql); + } +} diff --git a/src/main/java/io/v/nutz/meeting/models/MeetingTimePeriodUser.java b/src/main/java/io/v/nutz/meeting/models/MeetingTimePeriodUser.java index 143e75f..be302e9 100644 --- a/src/main/java/io/v/nutz/meeting/models/MeetingTimePeriodUser.java +++ b/src/main/java/io/v/nutz/meeting/models/MeetingTimePeriodUser.java @@ -79,5 +79,13 @@ public class MeetingTimePeriodUser { @Comment("审核记录ID") private List auditIdList; + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否参加") + private Boolean isJoinByMsg; + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("不参加理由") + private String notJoinReason; } diff --git a/src/main/java/io/v/nutz/meeting/models/MeetingUser.java b/src/main/java/io/v/nutz/meeting/models/MeetingUser.java index f9410e8..c3005ad 100644 --- a/src/main/java/io/v/nutz/meeting/models/MeetingUser.java +++ b/src/main/java/io/v/nutz/meeting/models/MeetingUser.java @@ -75,4 +75,8 @@ public class MeetingUser { @Comment("审核记录ID") private List auditIdList; + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否已阅") + private Boolean isReadByMsg; } diff --git a/src/main/java/io/v/nutz/meeting/models/ShortUrl.java b/src/main/java/io/v/nutz/meeting/models/ShortUrl.java new file mode 100644 index 0000000..3919435 --- /dev/null +++ b/src/main/java/io/v/nutz/meeting/models/ShortUrl.java @@ -0,0 +1,27 @@ +package io.v.nutz.meeting.models; + +import lombok.Data; +import lombok.experimental.Accessors; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +@Table +@Data +@Accessors(chain = true) +public class ShortUrl { + + @Name + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("短链") + private String shortUrl; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 100) + @Comment("真实链接") + private String realUrl; +} diff --git a/src/main/resources/views/mobile/meeting/notify.html b/src/main/resources/views/mobile/meeting/notify.html new file mode 100644 index 0000000..a65bf39 --- /dev/null +++ b/src/main/resources/views/mobile/meeting/notify.html @@ -0,0 +1,386 @@ + + + +
+
+
+
+
会议通知
+
+
+
{{meetingInfo.meetingName}}
+
{{meetingInfo.location}}
+
+ + 会议类型:{{typeName}} + +
+ + + 会议时间: + {{moment(meetingInfo.startTime).format('YYYY-MM-DD HH:mm')}} + + + + + 结束时间: + {{moment(meetingInfo.endTime).format('YYYY-MM-DD HH:mm')}} + + +
+
+
+
+
+
|会议名称
+
+
+ + + + +
+
+
+ +
+
+
+ +
+
+

{{isIncorrect === true ? '操作成功' : '温馨提示'}}

+

{{incorrectMag}}

+
+

+ 点击返回 +

+
+ + + + +
+ + + + \ No newline at end of file diff --git a/src/main/resources/views/platform/meeting/index.html b/src/main/resources/views/platform/meeting/index.html index ceb4d21..c2823e0 100644 --- a/src/main/resources/views/platform/meeting/index.html +++ b/src/main/resources/views/platform/meeting/index.html @@ -62,7 +62,8 @@ layout("/layouts/platform.html"){ @@ -97,7 +98,26 @@ layout("/layouts/platform.html"){ } }, methods: { - + async sendMsg(row) { + const resp = await $.post(loc() + '/getUserCount', {id: row.id}) + if(resp.code === 0) { + const confirm = await this.$confirm('此操作将给' + resp.data + '位人员发送短信,请确认?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }) + if (confirm === "confirm") { + const resp = await $.post(loc() + '/sendMsg', {id: row.id}) + if(resp.code === 0) { + this.$message.success(resp.msg) + } else { + this.$message.warning(resp.msg) + } + } + } else { + this.$message.warning(resp.msg) + } + }, openView(row) { const {id, notifyId, hold} = row window.location.href = '/platform/meeting/manage/createMeeting?notifyId=' + notifyId + "&hold=" + true + "&id=" + id diff --git a/src/main/resources/views/platform/meeting/manage/add.html b/src/main/resources/views/platform/meeting/manage/add.html index 35b53a5..78d5f46 100644 --- a/src/main/resources/views/platform/meeting/manage/add.html +++ b/src/main/resources/views/platform/meeting/manage/add.html @@ -56,7 +56,7 @@ layout("/layouts/platform.html"){ - - + + diff --git a/src/main/resources/views/platform/meeting/statistics/msgManage.html b/src/main/resources/views/platform/meeting/statistics/msgManage.html new file mode 100644 index 0000000..4652a49 --- /dev/null +++ b/src/main/resources/views/platform/meeting/statistics/msgManage.html @@ -0,0 +1,214 @@ + + + +
+ + + + + + +
+ + + +