first commit

This commit is contained in:
zc
2026-02-27 10:16:46 +08:00
commit 0ee56404c2
705 changed files with 47675 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
package top.ysoft.admin.controller.schedule;
import cn.hutool.core.util.StrUtil;
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
import com.aizuda.snailjob.common.log.SnailJobLog;
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import top.ysoft.admin.common.constant.CacheConstants;
import top.ysoft.admin.open.mapper.AppMapper;
import top.ysoft.admin.open.model.entity.AppDO;
import top.ysoft.admin.system.mapper.*;
import top.ysoft.admin.system.model.entity.*;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.constant.StringConstants;
import java.util.List;
import java.util.function.BooleanSupplier;
/**
* 演示环境任务(任务示例)
*
* @author Charles7c
* @since 2024/8/4 15:30
*/
@Component
@RequiredArgsConstructor
public class DemoEnvironmentJob {
private final DictItemMapper dictItemMapper;
private final DictMapper dictMapper;
private final StorageMapper storageMapper;
private final NoticeMapper noticeMapper;
private final MessageMapper messageMapper;
private final MessageUserMapper messageUserMapper;
private final UserMapper userMapper;
private final UserRoleMapper userRoleMapper;
private final UserSocialMapper userSocialMapper;
private final RoleMapper roleMapper;
private final RoleDeptMapper roleDeptMapper;
private final RoleMenuMapper roleMenuMapper;
private final MenuMapper menuMapper;
private final DeptMapper deptMapper;
private final AppMapper appMapper;
private final ClientMapper clientsMapper;
private static final Long DELETE_FLAG = 10000L;
private static final Long MESSAGE_FLAG = 0L;
private static final List<Long> USER_FLAG = List
.of(1L, 547889293968801822L, 547889293968801823L, 547889293968801824L, 547889293968801825L, 547889293968801826L, 547889293968801827L, 547889293968801828L, 547889293968801829L, 547889293968801830L, 547889293968801831L);
private static final List<Long> ROLE_FLAG = List.of(1L, 547888897925840927L, 547888897925840928L);
private static final Long DEPT_FLAG = 547887852587843611L;
/**
* 重置演示环境数据
*/
@JobExecutor(name = "ResetEnvironmentData")
@Transactional(rollbackFor = Exception.class)
public void resetEnvironmentData() {
try {
SnailJobLog.REMOTE.info("定时任务 [重置演示环境数据] 开始执行。");
// 检测待清理数据
SnailJobLog.REMOTE.info("开始检测演示环境待清理数据项,请稍候...");
Long dictItemCount = dictItemMapper.lambdaQuery().gt(DictItemDO::getId, DELETE_FLAG).count();
this.log(dictItemCount, "字典项");
Long dictCount = dictMapper.lambdaQuery().gt(DictDO::getId, DELETE_FLAG).count();
this.log(dictCount, "字典");
Long storageCount = storageMapper.lambdaQuery().gt(StorageDO::getId, DELETE_FLAG).count();
this.log(storageCount, "存储");
Long noticeCount = noticeMapper.lambdaQuery().gt(NoticeDO::getId, DELETE_FLAG).count();
this.log(noticeCount, "公告");
Long messageCount = messageMapper.lambdaQuery().count();
this.log(messageCount, "通知");
Long userCount = userMapper.lambdaQuery().notIn(UserDO::getId, USER_FLAG).count();
this.log(userCount, "用户");
Long roleCount = roleMapper.lambdaQuery().notIn(RoleDO::getId, ROLE_FLAG).count();
this.log(roleCount, "角色");
Long menuCount = menuMapper.lambdaQuery().gt(MenuDO::getId, DELETE_FLAG).count();
this.log(menuCount, "菜单");
Long deptCount = deptMapper.lambdaQuery().gt(DeptDO::getId, DEPT_FLAG).count();
this.log(deptCount, "部门");
Long appCount = appMapper.lambdaQuery().gt(AppDO::getId, DELETE_FLAG).count();
this.log(appCount, "应用");
Long clientCount = clientsMapper.lambdaQuery().gt(ClientDO::getId, DELETE_FLAG).count();
this.log(clientCount, "终端");
InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().blockAttack(true).build());
SnailJobLog.REMOTE.info("演示环境待清理数据项检测完成,开始执行清理。");
// 清理关联数据
messageUserMapper.lambdaUpdate().gt(MessageUserDO::getMessageId, MESSAGE_FLAG).remove();
userRoleMapper.lambdaUpdate().notIn(UserRoleDO::getRoleId, ROLE_FLAG).remove();
userRoleMapper.lambdaUpdate().notIn(UserRoleDO::getUserId, USER_FLAG).remove();
roleDeptMapper.lambdaUpdate().notIn(RoleDeptDO::getRoleId, ROLE_FLAG).remove();
roleMenuMapper.lambdaUpdate().notIn(RoleMenuDO::getRoleId, ROLE_FLAG).remove();
userSocialMapper.lambdaUpdate().notIn(UserSocialDO::getUserId, USER_FLAG).remove();
// 清理具体数据
this.clean(dictItemCount, "字典项", null, () -> dictItemMapper.lambdaUpdate()
.gt(DictItemDO::getId, DELETE_FLAG)
.remove());
this.clean(dictCount, "字典", CacheConstants.DICT_KEY_PREFIX, () -> dictMapper.lambdaUpdate()
.gt(DictDO::getId, DELETE_FLAG)
.remove());
this.clean(storageCount, "存储", null, () -> storageMapper.lambdaUpdate()
.gt(StorageDO::getId, DELETE_FLAG)
.remove());
this.clean(noticeCount, "公告", null, () -> noticeMapper.lambdaUpdate()
.gt(NoticeDO::getId, DELETE_FLAG)
.remove());
this.clean(messageCount, "通知", null, () -> messageMapper.lambdaUpdate()
.gt(MessageDO::getId, MESSAGE_FLAG)
.remove());
this.clean(userCount, "用户", null, () -> userMapper.lambdaUpdate().notIn(UserDO::getId, USER_FLAG).remove());
this.clean(roleCount, "角色", null, () -> roleMapper.lambdaUpdate().notIn(RoleDO::getId, ROLE_FLAG).remove());
this.clean(menuCount, "菜单", CacheConstants.ROLE_MENU_KEY_PREFIX, () -> menuMapper.lambdaUpdate()
.gt(MenuDO::getId, DELETE_FLAG)
.remove());
this.clean(deptCount, "部门", null, () -> deptMapper.lambdaUpdate().gt(DeptDO::getId, DEPT_FLAG).remove());
this.clean(appCount, "应用", null, () -> appMapper.lambdaUpdate().gt(AppDO::getId, DEPT_FLAG).remove());
this.clean(clientCount, "终端", null, () -> clientsMapper.lambdaUpdate()
.gt(ClientDO::getId, DEPT_FLAG)
.remove());
SnailJobLog.REMOTE.info("演示环境数据已清理完成。");
SnailJobLog.REMOTE.info("定时任务 [重置演示环境数据] 执行结束。");
} finally {
InterceptorIgnoreHelper.clearIgnoreStrategy();
}
}
/**
* 输出日志
*
* @param count 待清理数据项数量
* @param resource 资源名称
*/
private void log(Long count, String resource) {
if (count > 0) {
SnailJobLog.REMOTE.info("检测到 [{}] 待清理数据项:{}条", resource, count);
}
}
/**
* 清理数据
*
* @param count 待清理数据项数量
* @param resource 资源名称
* @param cacheKey 缓存键
* @param supplier 清理数据项函数
*/
private void clean(Long count, String resource, String cacheKey, BooleanSupplier supplier) {
if (count > 0 && supplier.getAsBoolean()) {
SnailJobLog.REMOTE.info("[{}] 数据项清理完成。", resource);
if (StrUtil.isNotBlank(cacheKey)) {
RedisUtils.deleteByPattern(cacheKey + StringConstants.ASTERISK);
SnailJobLog.REMOTE.info("[{}] 数据项缓存清理完成。", resource);
}
}
}
}

View File

@@ -0,0 +1,90 @@
package top.ysoft.admin.controller.schedule;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.ysoft.admin.schedule.model.query.JobQuery;
import top.ysoft.admin.schedule.model.req.JobReq;
import top.ysoft.admin.schedule.model.req.JobStatusReq;
import top.ysoft.admin.schedule.model.resp.JobResp;
import top.ysoft.admin.schedule.service.JobService;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.validation.CrudValidationGroup;
import top.continew.starter.log.annotation.Log;
import java.util.List;
/**
* 任务 API
*
* @author KAI
* @author Charles7c
* @since 2024/6/25 22:24
*/
@Tag(name = " 任务 API")
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/schedule/job")
public class JobController {
private final JobService baseService;
@Operation(summary = "分页查询任务列表", description = "分页查询任务列表")
@SaCheckPermission("schedule:job:list")
@GetMapping
public PageResp<JobResp> page(JobQuery query) {
return baseService.page(query);
}
@Operation(summary = "新增任务", description = "新增任务")
@SaCheckPermission("schedule:job:add")
@PostMapping
public void add(@Validated(CrudValidationGroup.Add.class) @RequestBody JobReq req) {
baseService.add(req);
}
@Operation(summary = "修改任务", description = "修改任务")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@SaCheckPermission("schedule:job:update")
@PutMapping("/{id}")
public void update(@Validated(CrudValidationGroup.Update.class) @RequestBody JobReq req, @PathVariable Long id) {
baseService.update(req, id);
}
@Operation(summary = "修改任务状态", description = "修改任务状态")
@SaCheckPermission("schedule:job:update")
@PatchMapping("/{id}/status")
public void updateStatus(@Validated @RequestBody JobStatusReq req, @PathVariable Long id) {
baseService.updateStatus(req, id);
}
@Operation(summary = "删除任务", description = "删除任务")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@SaCheckPermission("schedule:job:delete")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
baseService.delete(id);
}
@Operation(summary = "执行任务", description = "执行任务")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@SaCheckPermission("schedule:job:trigger")
@PostMapping("/trigger/{id}")
public void trigger(@PathVariable Long id) {
baseService.trigger(id);
}
@Log(ignore = true)
@Operation(summary = "查询任务分组列表", description = "查询任务分组列表")
@SaCheckPermission("schedule:job:list")
@GetMapping("/group")
public List<String> listGroup() {
return baseService.listGroup();
}
}

View File

@@ -0,0 +1,74 @@
package top.ysoft.admin.controller.schedule;
import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.ysoft.admin.schedule.model.JobInstanceLogPageResult;
import top.ysoft.admin.schedule.model.query.JobInstanceLogQuery;
import top.ysoft.admin.schedule.model.query.JobInstanceQuery;
import top.ysoft.admin.schedule.model.query.JobLogQuery;
import top.ysoft.admin.schedule.model.resp.JobInstanceResp;
import top.ysoft.admin.schedule.model.resp.JobLogResp;
import top.ysoft.admin.schedule.service.JobLogService;
import top.continew.starter.extension.crud.model.resp.PageResp;
import java.util.List;
/**
* 任务日志 API
*
* @author KAI
* @author Charles7c
* @since 2024/6/27 22:24
*/
@Tag(name = " 任务日志 API")
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/schedule/log")
public class JobLogController {
private final JobLogService baseService;
@Operation(summary = "分页查询任务日志列表", description = "分页查询任务日志列表")
@SaCheckPermission("schedule:log:list")
@GetMapping
public PageResp<JobLogResp> page(JobLogQuery query) {
return baseService.page(query);
}
@Operation(summary = "停止任务", description = "停止任务")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@SaCheckPermission("schedule:log:stop")
@PostMapping("/stop/{id}")
public void stop(@PathVariable Long id) {
baseService.stop(id);
}
@Operation(summary = "重试任务", description = "重试任务")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@SaCheckPermission("schedule:log:retry")
@PostMapping("/retry/{id}")
public void retry(@PathVariable Long id) {
baseService.retry(id);
}
@Operation(summary = "查询任务实例列表", description = "查询任务实例列表")
@SaCheckPermission("schedule:log:list")
@GetMapping("/instance")
public List<JobInstanceResp> listInstance(JobInstanceQuery query) {
return baseService.listInstance(query);
}
@Operation(summary = "分页查询任务实例日志列表", description = "分页查询任务实例日志列表")
@SaCheckPermission("schedule:log:list")
@GetMapping("/instance/log")
public JobInstanceLogPageResult pageInstanceLog(JobInstanceLogQuery query) {
return baseService.pageInstanceLog(query);
}
}