diff --git a/pom.xml b/pom.xml index 91efa6fa..ab8b6358 100644 --- a/pom.xml +++ b/pom.xml @@ -408,6 +408,13 @@ juel 2.1.3 + + + + + + + diff --git a/src/main/java/com/budwk/app/base/utils/CommonDownloadUtil.java b/src/main/java/com/budwk/app/base/utils/CommonDownloadUtil.java index 1e270cc1..14ad3e25 100644 --- a/src/main/java/com/budwk/app/base/utils/CommonDownloadUtil.java +++ b/src/main/java/com/budwk/app/base/utils/CommonDownloadUtil.java @@ -22,6 +22,7 @@ import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.OutputStream; /** * 文件下载工具类,使用本类前,对参数校验的异常使用CommonResponseUtil.renderError()方法进行渲染 diff --git a/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java b/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java index fa56f367..d0307834 100644 --- a/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java +++ b/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java @@ -8,6 +8,8 @@ import com.budwk.app.flow.entity.ProcessInstance; import com.budwk.app.flow.entity.ProcessTask; import com.budwk.app.flow.entity.ProcessTaskActor; import com.budwk.app.flow.enums.ProcessEventTypeEnum; +import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService; +import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; @@ -21,17 +23,20 @@ import java.util.List; * 流程任务开始监听器 */ @IocBean +@Slf4j public class ProcessTaskStartEventListener implements ProcessEventListener { @Inject private Dao dao; + @Inject + private GlobalMessageSendService globalMessageSendService; @Override public void onEvent(ProcessEvent event) { if (event.getEventType() == ProcessEventTypeEnum.PROCESS_TASK_START) { Long sourceId = event.getSourceId(); ProcessTask task = dao.fetch(ProcessTask.class, sourceId); - sendMessage( task); + sendMessage(task); } } @@ -54,8 +59,9 @@ public class ProcessTaskStartEventListener implements ProcessEventListener { for (ProcessTaskActor taskActor : taskActors) { // 模拟发送消息 - String message = StrUtil.format("{}您有一条待办任务,实例:{},任务:{}", taskActor.getActorName(), instanceName, taskDisplayName); - System.out.println(message); + String message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{}", taskActor.getActorName(), instanceName, taskDisplayName); + log.info(message); + globalMessageSendService.sendMessage(taskDisplayName, message, 2, List.of(taskActor.getActorId()), null); } diff --git a/src/main/java/com/budwk/app/sys/controller/SysFileController.java b/src/main/java/com/budwk/app/sys/controller/SysFileController.java index ec974c9a..16424b2f 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysFileController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysFileController.java @@ -2,6 +2,7 @@ package com.budwk.app.sys.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.StrUtil; import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; @@ -11,8 +12,11 @@ import com.budwk.app.sys.enums.SysFileEngineTypeEnum; import com.budwk.app.sys.models.Sys_file; import com.budwk.app.sys.services.SysConfigService; import com.budwk.app.sys.services.SysFileService; +import com.budwk.app.sys.utils.SysFileMinIoUtil; +import com.google.common.net.HttpHeaders; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -23,19 +27,21 @@ import org.nutz.mvc.upload.UploadAdaptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.OutputStream; import java.util.List; @IocBean @At("/platform/sys/file") @Ok("json:full") @Api(tags = "文件管理") +@Slf4j public class SysFileController { @Inject private SysFileService sysFileService; - @Inject private SysConfigService sysConfigService; + private SysFileMinIoUtil sysFileMinIoUtil; @At("") @Ok("beetl:/platform/sys/file/index.html") @@ -110,7 +116,7 @@ public class SysFileController { @SaCheckLogin @ApiOperation("文件管理-转换HTML") @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) - public Result convertHtml(TempFile file){ + public Result convertHtml(TempFile file) { return Result.success().addData(sysFileService.convertHtml(file)); } @@ -141,5 +147,64 @@ public class SysFileController { return Result.success(files); } + @At + @SaCheckLogin + @ApiOperation("文件管理-视频播放") + @Ok("void") + public void videoPlay(String id, HttpServletRequest request, HttpServletResponse response) { + Sys_file sys_file = sysFileService.detail(id); + byte[] bytes = SysFileMinIoUtil.getFileBytes(sys_file.getBucket(), sys_file.getStoragePath()); + + + // 设置响应头 + String fileName = sys_file.getName(); + String contentType = null; + + switch (FileUtil.extName(fileName).toLowerCase()) { + case "mp4" -> contentType = "video/mp4"; + case "avi" -> contentType = "video/x-msvideo"; + case "mkv" -> contentType = "video/x-matroska"; + case "mov" -> contentType = "video/quicktime"; + case "wmv" -> contentType = "video/x-ms-wmv"; + default -> contentType = "application/octet-stream"; + } + + response.setContentType(contentType); + response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes"); + + String rangeHeader = request.getHeader(HttpHeaders.RANGE); + if (StrUtil.isNotBlank(rangeHeader) && rangeHeader.startsWith("bytes=")) { + // 处理Range请求 + String[] ranges = rangeHeader.substring(6).split("-"); + long start = StrUtil.isNotBlank(ranges[0]) ? Long.parseLong(ranges[0]) : 0; + long end = (ranges.length > 1 && StrUtil.isNotBlank(ranges[1])) ? + Long.parseLong(ranges[1]) : bytes.length - 1; + + if (start >= bytes.length || end >= bytes.length) { + response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + bytes.length); + response.setStatus(416); + return; + } + + int contentLength = (int) (end - start + 1); + response.setStatus(206); + response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength)); + response.setHeader(HttpHeaders.CONTENT_RANGE, StrUtil.format("bytes {}-{}/{}", start, end, bytes.length)); + + try (OutputStream out = response.getOutputStream()) { + out.write(bytes, (int) start, contentLength); + } catch (IOException e) { + log.error("视频播放失败", e); + } + } else { + // 非Range请求 + response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(bytes.length)); + try (OutputStream out = response.getOutputStream()) { + out.write(bytes); + } catch (IOException e) { + log.error("视频播放失败", e); + } + } + } } diff --git a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java index fad0dc27..a5017e12 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java @@ -70,7 +70,7 @@ public class SysHomeController { String userAgentStr = req.getHeader("User-Agent"); UserAgent userAgent = UserAgentUtil.parse(userAgentStr); if (!userAgent.isMobile()) { - return "beetl:/platform/sys/home/index.html"; + return "beetl:/layouts/v4/home.html"; } else { return "beetl:/platform/zhghh5/sys/home/index.html"; } @@ -222,86 +222,6 @@ public class SysHomeController { // return Result.success(hasPermisiionList); } - @At - @SaCheckLogin - @ApiOperation("待办列表") - @Ok("json") - public Result listTodo(@Valid PageForm pageForm) { - Sql sql = Sqls.create(""" - SELECT - task.id, - inst.processInstanceName, - inst.processInstanceInitiatorName, - inst.processInstanceNodeName, - task.formUrl AS taskFormUrl, - task.formMobileUrl AS taskFormMobileUrl - FROM - `bpm_process_task` task - INNER JOIN bpm_process_instance inst ON inst.id = task.processInstanceId - WHERE - JSON_CONTAINS( task.assignments, @loginName ) - AND task.taskStatus = 'ACTIVE' - GROUP BY - task.id - ORDER BY - task.createdOn DESC - """); - sql.setParam("loginName", "\"" + SecurityUtil.getUserLoginname() + "\""); - Pagination pagination = sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); - } - - @At - @SaCheckLogin - @ApiOperation("已办列表") - @Ok("json") - public Result listDone(@Valid PageForm pageForm) { - Sql sql = Sqls.create(""" - SELECT - task.id, - inst.processInstanceName, - inst.processInstanceInitiatorName, - inst.processInstanceNodeName, - task.formUrl AS taskFormUrl, - task.formMobileUrl AS taskFormMobileUrl - FROM - `bpm_process_task` task - INNER JOIN bpm_process_instance inst ON inst.id = task.processInstanceId - WHERE - JSON_CONTAINS( task.assignments, @loginName ) - AND task.taskStatus in ('COMPLETE','TRANSFER') - GROUP BY - task.id - ORDER BY - task.createdOn DESC - """); - sql.setParam("loginName", "\"" + SecurityUtil.getUserLoginname() + "\""); - Pagination pagination = sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); - } - - @At - @SaCheckLogin - @ApiOperation("我的发起") - @Ok("json") - public Result listMyInitiation(@Valid PageForm pageForm) { - Sql sql = Sqls.create(""" - SELECT - id, - processInstanceName, - processInstanceInitiatorName, - processInstanceNodeName, - processInstanceUrl - FROM - bpm_process_instance - WHERE - processInstanceInitiatorLoginName = @loginName - ORDER BY processInstanceInitiationTime DESC - """); - sql.setParam("loginName", SecurityUtil.getUserLoginname()); - Pagination pagination = sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); - } @At @SaCheckLogin diff --git a/src/main/java/com/budwk/app/sys/controller/SysHomeV4Controller.java b/src/main/java/com/budwk/app/sys/controller/SysHomeV4Controller.java index 7f1a8939..f047d1eb 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysHomeV4Controller.java +++ b/src/main/java/com/budwk/app/sys/controller/SysHomeV4Controller.java @@ -2,6 +2,7 @@ package com.budwk.app.sys.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import com.budwk.app.sys.services.SysUserService; +import io.swagger.annotations.Api; import org.nutz.dao.Dao; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -13,6 +14,7 @@ import javax.servlet.http.HttpServletRequest; @IocBean @At("/platform/v4") +@Api(value = "V4首页") public class SysHomeV4Controller { @Inject @@ -27,9 +29,6 @@ public class SysHomeV4Controller { } - /** - * 首页门户 - */ @At("/home") @Ok("beetl:/layouts/v4/home.html") @SaCheckLogin @@ -37,13 +36,6 @@ public class SysHomeV4Controller { } - @At("/home2") - @Ok("beetl:/layouts/v4/home2.html") - @SaCheckLogin - public void home2() { - - } - /** * 应用中心 */ @@ -64,6 +56,27 @@ public class SysHomeV4Controller { } + /** + * 待办中心 + */ + @At("/todo") + @Ok("beetl:/layouts/v4/todo.html") + @SaCheckLogin + public void todo(){ + + } + + /** + * 消息中心 + */ + @At("/msg") + @Ok("beetl:/layouts/v4/msg.html") + @SaCheckLogin + public void msg(){ + + } + + /** * 子系统 * @param appId 应用ID diff --git a/src/main/java/com/budwk/app/sys/controller/SysUserController.java b/src/main/java/com/budwk/app/sys/controller/SysUserController.java index c708d8f0..48df3f1a 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysUserController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysUserController.java @@ -2,6 +2,7 @@ package com.budwk.app.sys.controller; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import com.budwk.app.base.annotation.SLog; @@ -339,7 +340,11 @@ public class SysUserController { @SaCheckLogin public Result subAppMenus(@Param("appId") String appId) { List menus = sysUserService.getMenus(SecurityUtil.getUserId()); - List list = Sys_menu.createTreeMenus(menus, appId); + List list = SysMenuUtil.createTreeMenus(menus, appId); + if (ObjectUtil.isEmpty(list)) { + List self = menus.stream().filter(menu -> menu.getId().equals(appId)).toList(); + return Result.success().addData(self); + } return Result.success(list); } diff --git a/src/main/java/com/budwk/app/sys/controller/v4/SysV4MsgController.java b/src/main/java/com/budwk/app/sys/controller/v4/SysV4MsgController.java new file mode 100644 index 00000000..8340f0a3 --- /dev/null +++ b/src/main/java/com/budwk/app/sys/controller/v4/SysV4MsgController.java @@ -0,0 +1,166 @@ +package com.budwk.app.sys.controller.v4; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.message.models.GlobalMessage; +import com.budwk.app.zhgh.dayofficework.message.models.GlobalMessageReceiver; +import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageSendService; +import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.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.HttpServletRequest; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +@IocBean +@At("/platform/v4/msg") +@Api(value = "消息中心", tags = "消息中心接口") +@Ok("json:full") +public class SysV4MsgController { + + @Inject + private Dao dao; + @Inject + private GlobalMessageService globalMessageService; + @Inject + private GlobalMessageSendService globalMessageSendService; + + @At + @ApiOperation("获取消息列表") + @SaCheckLogin + public Result pageData(PageForm pageForm, @Param("isRead") int isRead, @Param("type") Integer type, HttpServletRequest req) { + Sql sql = Sqls.create(""" + SELECT + m.id, + m.title, + m.content, + m.type, + r.isRead, + r.readTime + FROM + global_message m + INNER JOIN global_message_receiver r ON m.id = r.messageId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("m.status", "=", 2); + cnd.and("r.receiverId", "=", SecurityUtil.getUserId()); + + if (isRead == 0) { + cnd.and("r.isRead", "=", 0); + } else if (isRead == 1) { + cnd.and("r.isRead", "=", 1); + } + + + cnd.andEX("m.type", "=", type); + cnd.desc("m.sendTime"); + sql.setCondition(cnd); + + String title = "审批待办"; + String content = "您有一个新的审批任务需要处理,请及时登录系统查看。"; + List receiverIds = Arrays.asList("17a7f8ad3ee947b4a26175049a9c253d"); + + // 自动发送到所有启用的渠道 + // globalMessageSendService.sendMessage(title, content, 2, receiverIds, null); + + Pagination pagination = globalMessageService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At("/stats") + @ApiOperation("获取消息统计信息") + @SaCheckLogin + public Result getStats() { + List messageList = dao.query(GlobalMessage.class, Cnd.where(GlobalMessage::getStatus, "=", 2)); + List messageIds = messageList.stream().map(GlobalMessage::getId).toList(); + + // 查询总数 + int totalCount = dao.count(GlobalMessageReceiver.class, Cnd.where(GlobalMessageReceiver::getReceiverId, "=", SecurityUtil.getUserId()).and(GlobalMessageReceiver::getMessageId, "in", messageIds)); + + // 查询未读数 + int unreadCount = dao.count(GlobalMessageReceiver.class, Cnd.where(GlobalMessageReceiver::getReceiverId, "=", SecurityUtil.getUserId()).and(GlobalMessageReceiver::getIsRead, "=", 0).and(GlobalMessageReceiver::getMessageId, "in", messageIds)); + + // 查询已读数 + int readCount = totalCount - unreadCount; + + NutMap stats = NutMap.NEW() + .addv("total", totalCount) + .addv("unread", unreadCount) + .addv("read", readCount); +// .addv("typeStats", typeStats); + + return Result.success(stats); + + } + + @At("/detail/?") + @ApiOperation("获取消息详情") + @SaCheckLogin + public Result getDetail(String messageId) { + GlobalMessageReceiver receiver = dao.fetch(GlobalMessageReceiver.class, Cnd.where(GlobalMessageReceiver::getMessageId, "=", messageId).and(GlobalMessageReceiver::getReceiverId, "=", SecurityUtil.getUserId())); + dao.fetchLinks(receiver, "globalMessage"); + + // 标记为已读 + if (receiver != null && !receiver.getIsRead()) { + receiver.setIsRead(true); + receiver.setReadTime(new Date()); + dao.update(receiver); + } + return Result.success(receiver); + } + + @At("/read/?") + @ApiOperation("标记消息为已读") + public Result markAsRead(String messageId) { + GlobalMessageReceiver receiver = dao.fetch(GlobalMessageReceiver.class, Cnd.where("messageId", "=", messageId).and("receiverId", "=", SecurityUtil.getUserId())); + if (receiver != null && !receiver.getIsRead()) { + receiver.setIsRead(true); + receiver.setReadTime(new Date()); + dao.update(receiver); + } + return Result.success(); + } + + @At("/read/batch") + @ApiOperation("批量标记消息为已读") + @SaCheckLogin + public Result batchMarkAsRead(@Param("messageIds") String[] messageIds) { + List receivers = dao.query(GlobalMessageReceiver.class, Cnd.where("messageId", "in", messageIds).and("receiverId", "=", SecurityUtil.getUserId())); + for (GlobalMessageReceiver receiver : receivers) { + receiver.setIsRead(true); + receiver.setReadTime(new Date()); + } + dao.update(receivers); + return Result.success(); + } + + @At("/read/all") + @ApiOperation("标记所有消息为已读") + @SaCheckLogin + public Result markAllAsRead() { + List receivers = dao.query(GlobalMessageReceiver.class, Cnd.where("receiverId", "=", SecurityUtil.getUserId())); + for (GlobalMessageReceiver receiver : receivers) { + receiver.setIsRead(true); + receiver.setReadTime(new Date()); + } + dao.update(receivers); + return Result.success(); + } + +} diff --git a/src/main/java/com/budwk/app/sys/models/Sys_menu.java b/src/main/java/com/budwk/app/sys/models/Sys_menu.java index 5928ef75..6dccd83a 100644 --- a/src/main/java/com/budwk/app/sys/models/Sys_menu.java +++ b/src/main/java/com/budwk/app/sys/models/Sys_menu.java @@ -132,21 +132,4 @@ public class Sys_menu extends BaseModel implements Serializable { //子菜单 private List children = new ArrayList<>(); - - /** - * 前端菜单数据 - * - * @param menus - * @param parentId - * @return - */ - public static List createTreeMenus(List menus, String parentId) { - List filterMenus = menus.stream().filter(v -> StringUtils.defaultString(v.getParentId(), "").equals(StringUtils.defaultString(parentId, ""))).collect(Collectors.toList()); - for (Sys_menu menu : filterMenus) { - List childMenus = createTreeMenus(menus, menu.getId()); - menu.setChildren(childMenus); - } - return new ArrayList<>(filterMenus); - } - } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysFileServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysFileServiceImpl.java index d82cd909..92f35e8c 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysFileServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysFileServiceImpl.java @@ -147,7 +147,7 @@ public class SysFileServiceImpl extends BaseServiceImpl implements Sys @Override public Sys_file detail(String id) { - return null; + return fetch(id); } @Override @@ -181,13 +181,13 @@ public class SysFileServiceImpl extends BaseServiceImpl implements Sys String[] parts = srcValue.split(";base64,"); String base64Content = parts[1]; - try{ + try { //转为在线地址 base64很喜欢被信息中心拦截 byte[] imageBytes = Base64.getDecoder().decode(base64Content); String imgUrl = storageFile(SysFileEngineTypeEnum.MINIO.getValue(), genFileKey(R.UU32(), R.UU32() + ".png"), imageBytes, false); String replacement = ""; matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement)); - }catch (Exception e){ + } catch (Exception e) { matcher.appendReplacement(sb, Matcher.quoteReplacement("")); } } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java index ac5ec228..f0ec7d19 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysUserServiceImpl.java @@ -13,6 +13,7 @@ import com.budwk.app.base.exception.UnknownAccountException; import com.budwk.app.base.interceptor.sLog.SLogService; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.base.utils.PwdUtil; +import com.budwk.app.base.utils.SysMenuUtil; import com.budwk.app.sys.models.*; import com.budwk.app.sys.services.SysMenuService; import com.budwk.app.sys.services.SysRoleService; @@ -126,27 +127,27 @@ public class SysUserServiceImpl extends BaseServiceImpl implements Sys List userModules = dao().query(Sys_module.class, Cnd.where("id", "in", allModuleIds.toArray()).asc(Sys_module::getSortNum)); //设置pc菜单到模块 - if (Lang.isNotEmpty(pcModuleIds)) { - //用户的pc端模块 - List pcModules = userModules.stream().filter(module -> pcModuleIds.contains(module.getId())).toList(); - //pc菜单转为树结构 - List pcTreeMenus = Sys_menu.createTreeMenus(pcMenus, null); - for (Sys_module pcModule : pcModules) { - pcModule.setMenus(pcTreeMenus.stream().filter(menu -> menu.getModuleId().equals(pcModule.getId())).collect(Collectors.toList())); - } - user.setPcModuleMenus(pcModules); - } - - //设置h5菜单到模块 - if (Lang.isNotEmpty(h5ModuleIds)) { - //用户的h5端模块 - List h5Modules = userModules.stream().filter(module -> h5ModuleIds.contains(module.getId())).toList(); - List h5TreeMenus = Sys_menu.createTreeMenus(h5Menus, null); - for (Sys_module h5Module : h5Modules) { - h5Module.setMenus(h5TreeMenus.stream().filter(menu -> menu.getModuleId().equals(h5Module.getId())).collect(Collectors.toList())); - } - user.setH5ModuleMenus(h5Modules); - } +// if (Lang.isNotEmpty(pcModuleIds)) { +// //用户的pc端模块 +// List pcModules = userModules.stream().filter(module -> pcModuleIds.contains(module.getId())).toList(); +// //pc菜单转为树结构 +// List pcTreeMenus = SysMenuUtil.createTreeMenus(pcMenus, null); +// for (Sys_module pcModule : pcModules) { +// pcModule.setMenus(pcTreeMenus.stream().filter(menu -> menu.getModuleId().equals(pcModule.getId())).collect(Collectors.toList())); +// } +// user.setPcModuleMenus(pcModules); +// } +// +// //设置h5菜单到模块 +// if (Lang.isNotEmpty(h5ModuleIds)) { +// //用户的h5端模块 +// List h5Modules = userModules.stream().filter(module -> h5ModuleIds.contains(module.getId())).toList(); +// List h5TreeMenus = SysMenuUtil.createTreeMenus(h5Menus, null); +// for (Sys_module h5Module : h5Modules) { +// h5Module.setMenus(h5TreeMenus.stream().filter(menu -> menu.getModuleId().equals(h5Module.getId())).collect(Collectors.toList())); +// } +// user.setH5ModuleMenus(h5Modules); +// } return user; } diff --git a/src/main/java/com/budwk/app/web/commons/auth/service/AuthService.java b/src/main/java/com/budwk/app/web/commons/auth/service/AuthService.java index 001c9dc9..f8eb83f4 100644 --- a/src/main/java/com/budwk/app/web/commons/auth/service/AuthService.java +++ b/src/main/java/com/budwk/app/web/commons/auth/service/AuthService.java @@ -1,6 +1,7 @@ package com.budwk.app.web.commons.auth.service; import cn.dev33.satoken.stp.StpUtil; +import com.budwk.app.base.utils.SysMenuUtil; import com.budwk.app.sys.models.Sys_menu; import com.budwk.app.sys.models.Sys_user; import com.budwk.app.sys.services.SysUserService; @@ -64,7 +65,7 @@ public class AuthService { public Object getSubAppMenus(String appId) { List menus = sysUserService.getMenus(SecurityUtil.getUserId()); - List pcTreeMenus = Sys_menu.createTreeMenus(menus, appId); + List pcTreeMenus = SysMenuUtil.createTreeMenus(menus, appId); return pcTreeMenus; } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java index bdcebfb4..9e129ad5 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/controller/EduCoursesController.java @@ -5,6 +5,8 @@ import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_file; +import com.budwk.app.sys.utils.SysFileMinIoUtil; import com.budwk.app.zhgh.dayofficework.edu.models.EduChapters; import com.budwk.app.zhgh.dayofficework.edu.models.EduCourses; import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos; @@ -132,6 +134,15 @@ public class EduCoursesController { @SLog(tag = "理论学习课程", msg = "添加课程视频") public Result insert(EduVideos eduVideos) { dao.insert(eduVideos); + String url = eduVideos.getUrl(); + String id = url.split("id=")[1]; + Sys_file file = dao.fetch(Sys_file.class, id); + byte[] bytes = SysFileMinIoUtil.getFileBytes(file.getBucket(), file.getStoragePath()); + + // 获取视频时长 + + + return Result.success(); } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java index 173ffe6c..df2a8e93 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/h5controller/H5EduController.java @@ -115,20 +115,19 @@ public class H5EduController { } // 获取课程总视频数 -// int totalVideos = dao.count("edu_videos v", -// "LEFT JOIN edu_chapters c ON v.chapterId = c.id", -// Cnd.where("c.courseId", "=", courseId)); - int totalVideos = 10; + List chapters = dao.query(EduChapters.class, Cnd.where(EduChapters::getCourseId, "=", courseId)); + List chapterIds = chapters.stream().map(EduChapters::getId).toList(); + int totalVideos = dao.count(EduVideos.class, Cnd.where(EduVideos::getChapterId, "in", chapterIds)); // 获取已完成的视频ID列表 List completedRecords = dao.query(EduStudyRecords.class, - Cnd.where("userId", "=", userId) - .and("courseId", "=", courseId) - .and("completed", "=", true)); + Cnd.where(EduStudyRecords::getUserId, "=", userId) + .and(EduStudyRecords::getCourseId, "=", courseId) + .and(EduStudyRecords::getIsCompleted, "=", 1)); List completedVideoIds = completedRecords.stream() - .map(EduStudyRecords::getVideoId) - .collect(java.util.stream.Collectors.toList()); + .map(EduStudyRecords::getVideoId) + .collect(java.util.stream.Collectors.toList()); int completedVideos = completedVideoIds.size(); @@ -196,13 +195,8 @@ public class H5EduController { return Result.error("观看时长不能为空或小于0"); } - String userId = SecurityUtil.getUserId(); - if (userId == null) { - return Result.error("用户未登录"); - } - EduStudyRecords record = eduStudyRecordsService.saveOrUpdateWatchProgress( - userId, videoId, courseId, watchedDuration); + SecurityUtil.getUserId(), videoId, courseId, watchedDuration); return Result.success(record); } catch (Exception e) { diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java index 63288820..f3ff042a 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/EduStudyRecordsService.java @@ -8,8 +8,6 @@ import java.util.List; /** * @ClassName EduStudyRecordsService * @Description 学习记录服务接口 - * @Author AI Assistant - * @Date 2024/01/01 */ public interface EduStudyRecordsService extends BaseService { @@ -79,17 +77,17 @@ public interface EduStudyRecordsService extends BaseService { // Getters and Setters public int getTotalVideos() { return totalVideos; } public void setTotalVideos(int totalVideos) { this.totalVideos = totalVideos; } - + public int getCompletedVideos() { return completedVideos; } public void setCompletedVideos(int completedVideos) { this.completedVideos = completedVideos; } - + public int getTotalDuration() { return totalDuration; } public void setTotalDuration(int totalDuration) { this.totalDuration = totalDuration; } - + public int getWatchedDuration() { return watchedDuration; } public void setWatchedDuration(int watchedDuration) { this.watchedDuration = watchedDuration; } - + public double getCompletionRate() { return completionRate; } public void setCompletionRate(double completionRate) { this.completionRate = completionRate; } } -} \ No newline at end of file +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java index a5500cb8..1c86c7a7 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/edu/service/impl/EduStudyRecordsServiceImpl.java @@ -1,5 +1,6 @@ package com.budwk.app.zhgh.dayofficework.edu.service.impl; +import com.budwk.app.base.exception.BaseException; import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.zhgh.dayofficework.edu.models.EduStudyRecords; import com.budwk.app.zhgh.dayofficework.edu.models.EduVideos; @@ -17,8 +18,6 @@ import java.util.List; /** * @ClassName EduStudyRecordsServiceImpl * @Description 学习记录服务实现类 - * @Author AI Assistant - * @Date 2024/01/01 */ @Slf4j @IocBean(args = {"refer:dao"}) @@ -74,7 +73,7 @@ public class EduStudyRecordsServiceImpl extends BaseServiceImpl } } catch (Exception e) { log.error("保存观看进度失败", e); - throw new RuntimeException("保存观看进度失败", e); + throw new BaseException("保存观看进度失败", e); } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessage.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessage.java index 420611b6..a3b729ac 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessage.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessage.java @@ -8,6 +8,7 @@ import lombok.experimental.Accessors; import org.nutz.dao.entity.annotation.*; import org.nutz.dao.interceptor.annotation.PrevInsert; +import java.util.Date; import java.util.List; @Table("global_message") @@ -74,6 +75,11 @@ public class GlobalMessage extends BaseModel { @ColDefine(type = ColType.INT) private Integer status; + @Column + @Comment("发送时间") + @ColDefine(type = ColType.DATETIME) + private Date sendTime; + @Column @Comment("发送成功") @ColDefine(type = ColType.BOOLEAN) diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessageReceiver.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessageReceiver.java index 23e7fcf8..a65cf4cf 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessageReceiver.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/models/GlobalMessageReceiver.java @@ -54,6 +54,7 @@ public class GlobalMessageReceiver extends BaseModel { @ColDefine(type = ColType.DATETIME) private Date readTime; - + @One(target = GlobalMessage.class, field = "messageId") + private GlobalMessage globalMessage; } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/GlobalMessageService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/GlobalMessageService.java new file mode 100644 index 00000000..c00b6121 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/GlobalMessageService.java @@ -0,0 +1,7 @@ +package com.budwk.app.zhgh.dayofficework.message.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.message.models.GlobalMessage; + +public interface GlobalMessageService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/impl/GlobalMessageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/impl/GlobalMessageServiceImpl.java new file mode 100644 index 00000000..8a0dc622 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/service/impl/GlobalMessageServiceImpl.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.dayofficework.message.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.message.models.GlobalMessage; +import com.budwk.app.zhgh.dayofficework.message.service.GlobalMessageService; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +@IocBean(args = {"refer:dao"}) +public class GlobalMessageServiceImpl extends BaseServiceImpl implements GlobalMessageService { + public GlobalMessageServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvActivityController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvActivityController.java index 65349f87..1963338e 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvActivityController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvActivityController.java @@ -6,6 +6,7 @@ import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; import com.budwk.app.zhgh.dayofficework.qsv.models.QsvActivity; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvBank; import com.budwk.app.zhgh.dayofficework.qsv.models.QsvOption; import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; import com.budwk.app.zhgh.dayofficework.qsv.service.QsvActivityService; @@ -49,7 +50,7 @@ public class QsvActivityController { public Result pageData(@Valid PageForm pageForm, Integer year, String title) { Cnd cnd = Cnd.NEW(); cnd.andEX("YEAR(startTime)", "=", year); - cnd.and(Cnd.likeEX("title",title)); + cnd.and(Cnd.likeEX("title", title)); Pagination pagination = qsvActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); return Result.success(pagination); } @@ -79,7 +80,7 @@ public class QsvActivityController { return Result.success(activity); } -// 删除问卷 + // 删除问卷 @At @SaCheckPermission("qsv.activity") @ApiOperation("删除问卷") @@ -90,7 +91,7 @@ public class QsvActivityController { } -// 保存问卷题目 + // 保存问卷题目 @At @SaCheckPermission("qsv.activity") @Aop(TransAop.READ_COMMITTED) @@ -143,15 +144,23 @@ public class QsvActivityController { return Result.success(); } -// 查询问卷题目 + // 查询问卷题目 @At @SaCheckPermission("qsv.activity") @ApiOperation("查询问卷题目") - @SLog(type = "qsv.activity", tag = "查询问卷题目", msg = "查询问卷题目") public Result listSubjects(@Valid String activityId) { List subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId).asc("sortNum")); - dao.fetchLinks(subjects, "options",Cnd.NEW().asc("sortNum")); + dao.fetchLinks(subjects, "options", Cnd.NEW().asc("sortNum")); return Result.success(subjects); } + + @At + @SaCheckPermission("qsv.activity") + @ApiOperation("查询问卷题库") + public Result listBank(@Valid String category) { + List list = dao.query(QsvBank.class, Cnd.where(QsvBank::getCategory, "=", category)); + return Result.success(list); + } + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvBankController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvBankController.java new file mode 100644 index 00000000..3e448b92 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/controller/QsvBankController.java @@ -0,0 +1,94 @@ +package com.budwk.app.zhgh.dayofficework.qsv.controller; + +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.zhgh.dayofficework.qsv.models.QsvBank; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvSubject; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvBankService; +import io.swagger.annotations.ApiOperation; +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; +import org.nutz.mvc.annotation.Param; + +import javax.validation.Valid; +import java.util.Arrays; + +@IocBean +@At("/platform/qsv/bank") +@Ok("json:full") +@ApiOperation("问卷调查题库管理") +public class QsvBankController { + + @Inject + private Dao dao; + @Inject + private QsvBankService qsvBankService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/qsv/bank/index.html") + @SaCheckPermission("qsv.bank") + public void index() { + } + + @At + @SaCheckPermission("qsv.bank") + public Result pageData(PageForm pageForm) { + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + cnd.where().andLike(QsvBank::getTitle, pageForm.getSearchKeyword()); + } + Pagination pagination = qsvBankService.listPage(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + return Result.success(pagination); + } + + @At + @SaCheckPermission("qsv.bank") + @ApiOperation("保存题库") + public Result save(@Param("qsvBank") QsvBank qsvBank) { + dao.insert(qsvBank); + return Result.success(); + } + + @At + @SaCheckPermission("qsv.bank") + @ApiOperation("修改题库") + public Result update(@Param("qsvBank") QsvBank qsvBank) { + dao.updateIgnoreNull(qsvBank); + return Result.success(); + } + + + @At + @SaCheckPermission("qsv.bank") + public Result findOne(@Valid String id) { + QsvBank qsvBank = dao.fetch(QsvBank.class, id); + return Result.success(qsvBank); + } + + @At + @SaCheckPermission("qsv.bank") + @ApiOperation("删除题库") + public Result delete(@Valid String id) { + dao.delete(QsvBank.class, id); + return Result.success(); + } + + @At + @SaCheckPermission("qsv.bank") + @ApiOperation("保存题库题目") + public Result saveSubjects(@Valid String id, @Param("subjects") QsvSubject[] subjects) { + QsvBank qsvBank = dao.fetch(QsvBank.class, id); + qsvBank.setSubjects(Arrays.asList(subjects)); + dao.updateIgnoreNull(qsvBank); + return Result.success(); + } + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvController.java index 89e39ccb..028b75ee 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/h5controller/H5QsvController.java @@ -1,6 +1,7 @@ package com.budwk.app.zhgh.dayofficework.qsv.h5controller; import cn.dev33.satoken.annotation.SaCheckLogin; +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; @@ -25,13 +26,13 @@ public class H5QsvController { @At("") @Ok("beetl:/platform/zhghh5/dayofficework/qsv/index.html") - @SaCheckLogin + @SaCheckPermission("h5.qsv") public void index() { } @At - @SaCheckLogin + @SaCheckPermission("h5.qsv") public Result pageData(@Valid PageForm pageForm, @Valid String category) { Cnd cnd = Cnd.NEW(); cnd.andEX("category", "=", category); diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvBank.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvBank.java new file mode 100644 index 00000000..7ce3e0e8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/models/QsvBank.java @@ -0,0 +1,45 @@ +package com.budwk.app.zhgh.dayofficework.qsv.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.util.List; + +@EqualsAndHashCode(callSuper = true) +@Data +@Table("qsv_bank") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("问卷调查题库") +public class QsvBank 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 title; + + @Column + @Comment("说明描述") + @ColDefine(type = ColType.TEXT) + private String description; + + @Column + @Comment("所属模块(quiz, survey, vote)") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String category; + + @Column + @Comment("题目") + @ColDefine(type = ColType.MYSQL_JSON) + private List subjects; + + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvBankService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvBankService.java new file mode 100644 index 00000000..11552978 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/QsvBankService.java @@ -0,0 +1,7 @@ +package com.budwk.app.zhgh.dayofficework.qsv.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvBank; + +public interface QsvBankService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvBankServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvBankServiceImpl.java new file mode 100644 index 00000000..1d6dd170 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/qsv/service/impl/QsvBankServiceImpl.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.dayofficework.qsv.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.qsv.models.QsvBank; +import com.budwk.app.zhgh.dayofficework.qsv.service.QsvBankService; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +@IocBean(args = {"refer:dao"}) +public class QsvBankServiceImpl extends BaseServiceImpl implements QsvBankService { + public QsvBankServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxMineController.java b/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxMineController.java index 4d6695e8..1bd9cc9a 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxMineController.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxMineController.java @@ -46,8 +46,8 @@ public class SuggestionBoxMineController { @At @Ok("beetl:/platform/zhghh5/democratic/suggestionBox/mine/index.html") - @SaCheckLogin - public void h5Index() { + @SaCheckPermission("h5.suggestionBox.mine") + public void h5() { } diff --git a/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxWriteController.java b/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxWriteController.java index 14589d53..83671494 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxWriteController.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionBoxWriteController.java @@ -24,6 +24,7 @@ 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; @IocBean @@ -48,8 +49,8 @@ public class SuggestionBoxWriteController { @At @Ok("beetl:/platform/zhghh5/democratic/suggestionBox/write/index.html") - @SaCheckLogin - public void h5Index(){ + @SaCheckPermission("h5.suggestionBox.write") + public void h5(){ } @@ -58,6 +59,7 @@ public class SuggestionBoxWriteController { @ApiOperation("保存申请") @SLog(tag = "建言献策-填写申请", msg = "保存申请") public Result save(@Param("data") SuggestionBox suggestionBox) { + suggestionBox.setSubmitTime(new Date()); dao.insertOrUpdate(suggestionBox); return Result.success(); } @@ -69,6 +71,7 @@ public class SuggestionBoxWriteController { @Aop(TransAop.READ_COMMITTED) @SLog(tag = "建言献策-填写申请", msg = "提交申请") public Result submit(@Param("data") SuggestionBox suggestionBox) { + suggestionBox.setSubmitTime(new Date()); dao.insertOrUpdate(suggestionBox); // 开启流程实例 Dict args = Dict.create(); diff --git a/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionXghController.java b/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionXghController.java index 83ec6e6c..0c03cc0f 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionXghController.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/suggestionBox/controller/SuggestionXghController.java @@ -1,6 +1,5 @@ package com.budwk.app.zhgh.democratic.suggestionBox.controller; -import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.StrUtil; import com.budwk.app.base.page.Pagination; @@ -43,8 +42,8 @@ public class SuggestionXghController { @At @Ok("beetl:/platform/zhghh5/democratic/suggestionBox/xgh/index.html") - @SaCheckPermission("suggestionBox.xgh") - public void h5Index() { + @SaCheckPermission("h5.suggestionBox.xgh") + public void h5() { } diff --git a/src/main/resources/static/assets/platform/js/main.js b/src/main/resources/static/assets/platform/js/main.js index fb9b3910..00c9c299 100644 --- a/src/main/resources/static/assets/platform/js/main.js +++ b/src/main/resources/static/assets/platform/js/main.js @@ -44,11 +44,11 @@ function pjaxReplace(url, data = {}) { } $.pjax({ url: url, - container: "#container", + container: "#sub-app-container-main-content-body", maxCacheLength: 0, push: false, replace: true, - fragment: "#container", + fragment: "#sub-app-container-main-content-body", timeout: 8000, data }) diff --git a/src/main/resources/static/assets/platform/js/util/commonUtil.js b/src/main/resources/static/assets/platform/js/util/commonUtil.js index b1491434..d344abe6 100644 --- a/src/main/resources/static/assets/platform/js/util/commonUtil.js +++ b/src/main/resources/static/assets/platform/js/util/commonUtil.js @@ -48,13 +48,13 @@ const commonUtil = { let loading = null - if(isMobile){ + if (isMobile) { loading = vant.Toast.loading({ duration: 0, forbidClick: true, message: '导出中,请耐心等待' }); - }else{ + } else { loading = ELEMENT.Loading.service({ lock: true, text: "导出中,请耐心等待", @@ -64,7 +64,7 @@ const commonUtil = { } Vue.prototype.$axios - .post(url, data, { responseType: "blob" }) + .post(url, data, {responseType: "blob"}) .then((response) => { if (response.data.type === "application/json") { try { @@ -102,9 +102,9 @@ const commonUtil = { loading.close() }) .finally(() => { - if(isMobile){ + if (isMobile) { loading.clear() - }else{ + } else { loading.close() } }) @@ -234,6 +234,7 @@ const commonUtil = { function doSm2Encrypt(msgString) { return sm2.doEncrypt(msgString, publicKey, cipherMode) } + // SM2数组加密 function doSm2ArrayEncrypt(msgString) { return sm2.doEncrypt(msgString, publicKey, cipherMode) @@ -243,6 +244,24 @@ const commonUtil = { doSm2Encrypt, doSm2ArrayEncrypt } + }, + + // pjax跳转 + pjaxPush(url, data = {}) { + const {pathname, search} = location + if (url === pathname + search) { + return + } + $.pjax({ + url: url, + container: "#sub-app-container-main-content-body", + maxCacheLength: 0, + push: false, + replace: true, + fragment: "#sub-app-container-main-content-body", + timeout: 8000, + data + }) } } @@ -259,7 +278,8 @@ function GetQueryString(name) { } function clearAllTimers() { - const maxTimeoutId = setTimeout(function () {}, 0) + const maxTimeoutId = setTimeout(function () { + }, 0) for (let i = 0; i <= maxTimeoutId; i++) { clearTimeout(i) clearInterval(i) @@ -291,10 +311,10 @@ function base64ToFile(base64Data, filename) { } // 使用Blob对象创建File对象 - const blob = new Blob([uInt8Array], { type: contentType }) + const blob = new Blob([uInt8Array], {type: contentType}) blob.lastModifiedDate = new Date() blob.name = filename - return new File([blob], filename, { type: contentType }) + return new File([blob], filename, {type: contentType}) } diff --git a/src/main/resources/static/assets/platform/plugins/nprogress/nprogress.css b/src/main/resources/static/assets/platform/plugins/nprogress/nprogress.css index 957ed9be..ca530b98 100644 --- a/src/main/resources/static/assets/platform/plugins/nprogress/nprogress.css +++ b/src/main/resources/static/assets/platform/plugins/nprogress/nprogress.css @@ -1,8 +1,72 @@ -/** - * Minified by jsDelivr using clean-css v5.3.3. - * Original file: /npm/nprogress@0.2.0/nprogress.css - * - * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files - */ -#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translate(0,-4px);-ms-transform:rotate(3deg) translate(0,-4px);transform:rotate(3deg) translate(0,-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:solid 2px transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{transform:rotate(0)}100%{transform:rotate(360deg)}} -/*# sourceMappingURL=/sm/4400c1e6b434bc414f3870cc8d155b3335f1f32d1a07381e06cc8a8bd869de73.map */ +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: #29d; + + position: fixed; + z-index: 1031; + top: 0; + left: 0; + + width: 100%; + height: 2px; +} + +/* Fancy blur effect */ +#nprogress .peg { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: 0 0 10px #29d, 0 0 5px #29d; + opacity: 1.0; + + -webkit-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +/* Remove these to get rid of the spinner */ +#nprogress .spinner { + display: block; + position: fixed; + z-index: 1031; + top: 15px; + right: 15px; +} + +#nprogress .spinner-icon { + width: 18px; + height: 18px; + box-sizing: border-box; + + border: solid 2px transparent; + border-top-color: #29d; + border-left-color: #29d; + border-radius: 50%; + + -webkit-animation: nprogress-spinner 400ms linear infinite; + animation: nprogress-spinner 400ms linear infinite; +} + +.nprogress-custom-parent { + overflow: hidden; + position: relative; +} + +.nprogress-custom-parent #nprogress .spinner, +.nprogress-custom-parent #nprogress .bar { + position: absolute; +} + +@-webkit-keyframes nprogress-spinner { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} +@keyframes nprogress-spinner { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/src/main/resources/static/components/plugins/Guava.vue b/src/main/resources/static/components/plugins/Guava.vue index 7ac4a3c4..849e7b16 100644 --- a/src/main/resources/static/components/plugins/Guava.vue +++ b/src/main/resources/static/components/plugins/Guava.vue @@ -1,179 +1,252 @@ - diff --git a/src/main/resources/views/layouts/platform.html b/src/main/resources/views/layouts/platform.html index 4e8003aa..444d5f7f 100644 --- a/src/main/resources/views/layouts/platform.html +++ b/src/main/resources/views/layouts/platform.html @@ -112,6 +112,7 @@ layout("/layouts/v4/baseLayout.html"){ .content-body { min-height: 400px; + height: 100%; } @media (max-width: 768px) { @@ -137,7 +138,8 @@ layout("/layouts/v4/baseLayout.html"){ - + @@ -145,11 +147,6 @@ layout("/layouts/v4/baseLayout.html"){
- - - - -
${layoutContent!}
@@ -169,7 +166,7 @@ layout("/layouts/v4/baseLayout.html"){ }) $(document).on("pjax:send", function () { - NProgress.configure({ parent: ".sub-app-container-main-content" }) + NProgress.configure({parent: ".sub-app-container-main-content"}) NProgress.start() $("#sub-app-container-main-content").hide() }) @@ -190,7 +187,8 @@ layout("/layouts/v4/baseLayout.html"){ try { const app = JSON.parse(window.sessionStorage.getItem("zhgh_sub_app")) $("#sub-app-container #sidebar-menu .menu-header .menu-title").text(app?.name) - } catch (e) {} + } catch (e) { + } } document.addEventListener("DOMContentLoaded", function () { @@ -209,36 +207,41 @@ layout("/layouts/v4/baseLayout.html"){ "menu-list": { name: "menu-list", template: - /*language=HTML*/ - ` -
- -
- `, + /*language=HTML*/ + ` +
+ +
+ `, props: ["menus", "depth"] } }, data() { return { + // 菜单数据 menus: [], + // 当前激活的菜单索引 activeMenuIndex: null, - openedMenus: [] + // 当前打开的菜单索引 + openedMenus: [], + // 默认选中菜单是否加载中 + defaultSelectLoading: true } }, computed: { @@ -260,12 +263,13 @@ layout("/layouts/v4/baseLayout.html"){ const app = JSON.parse(window.sessionStorage.getItem("zhgh_sub_app")) window.sessionStorage.setItem("zhgh_sub_app_left_menu_active_index-" + app.id, index) window.sessionStorage.setItem("zhgh_sub_app_left_menu_opens-" + app.id, JSON.stringify(indexPath)) - } catch (e) {} + } catch (e) { + } }, // 获取菜单 getMenus(appId) { if (!appId) return - $.get("/platform/sys/user/subAppMenus", { appId }).then((res) => { + this.$axios.post("/platform/sys/user/subAppMenus", {appId}).then((res) => { if (res.code === 0) { this.menus = res.data window.sessionStorage.setItem("zhgh_sub_app_menus", JSON.stringify(res.data)) @@ -276,6 +280,7 @@ layout("/layouts/v4/baseLayout.html"){ }) }, + // 设置应用信息 setAppInfo(app) { if (app) { // 储存到缓存 @@ -294,26 +299,73 @@ layout("/layouts/v4/baseLayout.html"){ this.openedMenus = JSON.parse(window.sessionStorage.getItem("zhgh_sub_app_left_menu_opens-" + app.id)) || [] console.log(this.openedMenus) console.log(this.activeMenuIndex) - } catch (e) {} + + if (!this.activeMenuIndex) { + this.defaultSelect() + } + + } catch (e) { + } + }, + + // 默认选中 + defaultSelect() { + // 查找第一个有href的子菜单 + function findFirstChildWithHref(menus) { + for (const menu of menus) { + // 如果当前菜单有href,返回它 + if (menu.href) { + return { + menu: menu, + parentIds: [menu.parentId] + }; + } + + // 如果有子菜单,递归查找 + if (menu.children && menu.children.length > 0) { + const result = findFirstChildWithHref(menu.children); + if (result) { + // 添加当前菜单的ID到父ID集合 + result.parentIds.push(menu.id); + return result; + } + } + } + return null; + } + + const result = findFirstChildWithHref(this.menus) + if (result) { + this.activeMenuIndex = result.menu.id + this.openedMenus = result.parentIds + this.$nextTick(() => { + this.menuSelect(this.activeMenuIndex, this.openedMenus) + // 使用pjax跳转 + commonUtil.pjaxPush(result.menu.href) + }) + } + }, + + init() { + // 页面加载时获取到正确的菜单 + const pathname = window.location.pathname + if (!pathname.startsWith("/platform/v4/subApp")) { + this.$axios.post("/platform/sys/user/rootMenuByPath", {pathname}).then((res) => { + if (res.code === 0) { + this.setAppInfo(res.data) + this.getMenus(res.data?.id) + } + }) + } else { + const appId = GetQueryString("appId") + if (!appId) return + this.getMenus(appId) + } } + }, mounted() { - // 页面加载时获取到正确的菜单 - const pathname = window.location.pathname - if (!pathname.startsWith("/platform/v4/subApp")) { - $.get("/platform/sys/user/rootMenuByPath", { pathname }).then((res) => { - if (res.code === 0) { - this.setAppInfo(res.data) - this.getMenus(res.data?.id) - } - }) - } else { - const appId = GetQueryString("appId") - if (!appId) { - return - } - this.getMenus(appId) - } + this.init() } }) diff --git a/src/main/resources/views/layouts/platform_h5.html b/src/main/resources/views/layouts/platform_h5.html index def11ba5..9ccd2276 100644 --- a/src/main/resources/views/layouts/platform_h5.html +++ b/src/main/resources/views/layouts/platform_h5.html @@ -165,12 +165,12 @@ } else { window.location.href = "/platform/h5/home" } - func && func() + func && typeof func === "function" && func() } Vue.mixin({ methods: { - historyBack: function(func) { + historyBack: function(func = ()=>{}) { historyBack(func); } } diff --git a/src/main/resources/views/layouts/v4/baseLayout.html b/src/main/resources/views/layouts/v4/baseLayout.html index 3ee57a14..cd7e075b 100644 --- a/src/main/resources/views/layouts/v4/baseLayout.html +++ b/src/main/resources/views/layouts/v4/baseLayout.html @@ -32,8 +32,8 @@ - - + + @@ -97,6 +97,8 @@ ELEMENT.Dialog.props.closeOnClickModal.default = false ELEMENT.Dialog.props.top.default = "50px" ELEMENT.Table.props.border.default = true + ELEMENT.TableColumn.props.headerAlign.default = 'center' + ELEMENT.TableColumn.props.align.default = 'center' ELEMENT.TableColumn.props.showOverflowTooltip = { type: Boolean, default: true } Vue.use(ELEMENT, { zIndex: 20000 @@ -603,7 +605,7 @@ @@ -663,7 +669,7 @@ var currentPath = window.location.pathname var footer = $("#v4-footer") - if (currentPath === "/platform/v4/home2") { + if (currentPath === "/platform/v4/home") { footer.show() } else { footer.hide() diff --git a/src/main/resources/views/layouts/v4/home.html b/src/main/resources/views/layouts/v4/home.html index ba9c36e5..f164b0e6 100644 --- a/src/main/resources/views/layouts/v4/home.html +++ b/src/main/resources/views/layouts/v4/home.html @@ -3,1569 +3,810 @@ layout("/layouts/v4/baseLayout.html"){ #--> -
-
-
-

欢迎使用数智工会

-

快速查找您需要的所有信息

-
-