This commit is contained in:
那些花儿
2025-09-17 17:52:09 +08:00
parent 9821aebd0a
commit 3f40ee599e
59 changed files with 3697 additions and 4029 deletions
@@ -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()方法进行渲染
@@ -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);
}
@@ -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);
}
}
}
}
@@ -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
@@ -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
@@ -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<Sys_menu> menus = sysUserService.getMenus(SecurityUtil.getUserId());
List<Sys_menu> list = Sys_menu.createTreeMenus(menus, appId);
List<Sys_menu> list = SysMenuUtil.createTreeMenus(menus, appId);
if (ObjectUtil.isEmpty(list)) {
List<Sys_menu> self = menus.stream().filter(menu -> menu.getId().equals(appId)).toList();
return Result.success().addData(self);
}
return Result.success(list);
}
@@ -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<String> 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<GlobalMessage> messageList = dao.query(GlobalMessage.class, Cnd.where(GlobalMessage::getStatus, "=", 2));
List<String> 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<GlobalMessageReceiver> 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<GlobalMessageReceiver> 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();
}
}
@@ -132,21 +132,4 @@ public class Sys_menu extends BaseModel implements Serializable {
//子菜单
private List<Sys_menu> children = new ArrayList<>();
/**
* 前端菜单数据
*
* @param menus
* @param parentId
* @return
*/
public static List<Sys_menu> createTreeMenus(List<Sys_menu> menus, String parentId) {
List<Sys_menu> filterMenus = menus.stream().filter(v -> StringUtils.defaultString(v.getParentId(), "").equals(StringUtils.defaultString(parentId, ""))).collect(Collectors.toList());
for (Sys_menu menu : filterMenus) {
List<Sys_menu> childMenus = createTreeMenus(menus, menu.getId());
menu.setChildren(childMenus);
}
return new ArrayList<>(filterMenus);
}
}
@@ -147,7 +147,7 @@ public class SysFileServiceImpl extends BaseServiceImpl<Sys_file> implements Sys
@Override
public Sys_file detail(String id) {
return null;
return fetch(id);
}
@Override
@@ -181,13 +181,13 @@ public class SysFileServiceImpl extends BaseServiceImpl<Sys_file> 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 = "<img src=\"" + imgUrl + "\">";
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}catch (Exception e){
} catch (Exception e) {
matcher.appendReplacement(sb, Matcher.quoteReplacement("<img src=>"));
}
}
@@ -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<Sys_user> implements Sys
List<Sys_module> userModules = dao().query(Sys_module.class, Cnd.where("id", "in", allModuleIds.toArray()).asc(Sys_module::getSortNum));
//设置pc菜单到模块
if (Lang.isNotEmpty(pcModuleIds)) {
//用户的pc端模块
List<Sys_module> pcModules = userModules.stream().filter(module -> pcModuleIds.contains(module.getId())).toList();
//pc菜单转为树结构
List<Sys_menu> 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<Sys_module> h5Modules = userModules.stream().filter(module -> h5ModuleIds.contains(module.getId())).toList();
List<Sys_menu> 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<Sys_module> pcModules = userModules.stream().filter(module -> pcModuleIds.contains(module.getId())).toList();
// //pc菜单转为树结构
// List<Sys_menu> 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<Sys_module> h5Modules = userModules.stream().filter(module -> h5ModuleIds.contains(module.getId())).toList();
// List<Sys_menu> 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;
}
@@ -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<Sys_menu> menus = sysUserService.getMenus(SecurityUtil.getUserId());
List<Sys_menu> pcTreeMenus = Sys_menu.createTreeMenus(menus, appId);
List<Sys_menu> pcTreeMenus = SysMenuUtil.createTreeMenus(menus, appId);
return pcTreeMenus;
}
}
@@ -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();
}
@@ -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<EduChapters> chapters = dao.query(EduChapters.class, Cnd.where(EduChapters::getCourseId, "=", courseId));
List<String> chapterIds = chapters.stream().map(EduChapters::getId).toList();
int totalVideos = dao.count(EduVideos.class, Cnd.where(EduVideos::getChapterId, "in", chapterIds));
// 获取已完成的视频ID列表
List<EduStudyRecords> 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<String> 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) {
@@ -8,8 +8,6 @@ import java.util.List;
/**
* @ClassName EduStudyRecordsService
* @Description 学习记录服务接口
* @Author AI Assistant
* @Date 2024/01/01
*/
public interface EduStudyRecordsService extends BaseService<EduStudyRecords> {
@@ -79,17 +77,17 @@ public interface EduStudyRecordsService extends BaseService<EduStudyRecords> {
// 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; }
}
}
}
@@ -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<EduStudyRecords>
}
} catch (Exception e) {
log.error("保存观看进度失败", e);
throw new RuntimeException("保存观看进度失败", e);
throw new BaseException("保存观看进度失败", e);
}
}
@@ -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)
@@ -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;
}
@@ -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<GlobalMessage> {
}
@@ -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<GlobalMessage> implements GlobalMessageService {
public GlobalMessageServiceImpl(Dao dao) {
super(dao);
}
}
@@ -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<QsvSubject> 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<QsvBank> list = dao.query(QsvBank.class, Cnd.where(QsvBank::getCategory, "=", category));
return Result.success(list);
}
}
@@ -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();
}
}
@@ -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);
@@ -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<QsvSubject> subjects;
}
@@ -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<QsvBank> {
}
@@ -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<QsvBank> implements QsvBankService {
public QsvBankServiceImpl(Dao dao) {
super(dao);
}
}
@@ -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() {
}
@@ -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();
@@ -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() {
}