first commit
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package top.ysoft.admin;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import com.alicp.jetcache.anno.config.EnableMethodCache;
|
||||
import io.swagger.v3.oas.annotations.Hidden;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.x.file.storage.spring.EnableFileStorage;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.starter.core.autoconfigure.project.ProjectProperties;
|
||||
import top.continew.starter.extension.crud.annotation.EnableCrudRestController;
|
||||
import top.continew.starter.web.annotation.EnableGlobalResponse;
|
||||
import top.continew.starter.web.model.R;
|
||||
|
||||
/**
|
||||
* 启动程序
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/8 23:15
|
||||
*/
|
||||
@Slf4j
|
||||
@EnableFileStorage
|
||||
@EnableMethodCache(basePackages = "top.ysoft.admin")
|
||||
@EnableGlobalResponse
|
||||
@EnableCrudRestController
|
||||
@RestController
|
||||
@SpringBootApplication
|
||||
@RequiredArgsConstructor
|
||||
public class YsoftAdminApplication {
|
||||
|
||||
private final ProjectProperties projectProperties;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(YsoftAdminApplication.class, args);
|
||||
}
|
||||
|
||||
@Hidden
|
||||
@SaIgnore
|
||||
@GetMapping("/")
|
||||
public R index() {
|
||||
return R.ok(projectProperties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.ysoft.admin.config.log;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import top.ysoft.admin.system.mapper.LogMapper;
|
||||
import top.ysoft.admin.system.service.UserService;
|
||||
import top.continew.starter.log.annotation.ConditionalOnEnabledLog;
|
||||
import top.continew.starter.log.dao.LogDao;
|
||||
import top.continew.starter.web.autoconfigure.trace.TraceProperties;
|
||||
|
||||
/**
|
||||
* 日志配置
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/24 23:15
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnEnabledLog
|
||||
public class LogConfiguration {
|
||||
|
||||
/**
|
||||
* 日志持久层接口本地实现类
|
||||
*/
|
||||
@Bean
|
||||
public LogDao logDao(UserService userService, LogMapper logMapper, TraceProperties traceProperties) {
|
||||
return new LogDaoLocalImpl(userService, logMapper, traceProperties);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package top.ysoft.admin.config.log;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.URLUtil;
|
||||
import cn.hutool.http.HttpStatus;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import top.ysoft.admin.auth.enums.AuthTypeEnum;
|
||||
import top.ysoft.admin.auth.model.req.*;
|
||||
import top.ysoft.admin.common.constant.SysConstants;
|
||||
import top.ysoft.admin.system.enums.LogStatusEnum;
|
||||
import top.ysoft.admin.system.mapper.LogMapper;
|
||||
import top.ysoft.admin.system.model.entity.LogDO;
|
||||
import top.ysoft.admin.system.service.UserService;
|
||||
import top.continew.starter.core.constant.StringConstants;
|
||||
import top.continew.starter.core.util.ExceptionUtils;
|
||||
import top.continew.starter.core.util.StrUtils;
|
||||
import top.continew.starter.log.dao.LogDao;
|
||||
import top.continew.starter.log.model.LogRecord;
|
||||
import top.continew.starter.log.model.LogRequest;
|
||||
import top.continew.starter.log.model.LogResponse;
|
||||
import top.continew.starter.web.autoconfigure.trace.TraceProperties;
|
||||
import top.continew.starter.web.model.R;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 日志持久层接口本地实现类
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/12/16 23:55
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class LogDaoLocalImpl implements LogDao {
|
||||
|
||||
private final UserService userService;
|
||||
private final LogMapper logMapper;
|
||||
private final TraceProperties traceProperties;
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void add(LogRecord logRecord) {
|
||||
LogDO logDO = new LogDO();
|
||||
// 设置请求信息
|
||||
LogRequest logRequest = logRecord.getRequest();
|
||||
this.setRequest(logDO, logRequest);
|
||||
// 设置响应信息
|
||||
LogResponse logResponse = logRecord.getResponse();
|
||||
this.setResponse(logDO, logResponse);
|
||||
// 设置基本信息
|
||||
logDO.setDescription(logRecord.getDescription());
|
||||
logDO.setModule(StrUtils.blankToDefault(logRecord.getModule(), null, m -> m
|
||||
.replace("API", StringConstants.EMPTY)
|
||||
.trim()));
|
||||
logDO.setTimeTaken(logRecord.getTimeTaken().toMillis());
|
||||
logDO.setCreateTime(LocalDateTime.ofInstant(logRecord.getTimestamp(), ZoneId.systemDefault()));
|
||||
// 设置操作人
|
||||
this.setCreateUser(logDO, logRequest, logResponse);
|
||||
logMapper.insert(logDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求信息
|
||||
*
|
||||
* @param logDO 日志信息
|
||||
* @param logRequest 请求信息
|
||||
*/
|
||||
private void setRequest(LogDO logDO, LogRequest logRequest) {
|
||||
logDO.setRequestMethod(logRequest.getMethod());
|
||||
logDO.setRequestUrl(logRequest.getUrl().toString());
|
||||
logDO.setRequestHeaders(JSONUtil.toJsonStr(logRequest.getHeaders()));
|
||||
logDO.setRequestBody(logRequest.getBody());
|
||||
logDO.setIp(logRequest.getIp());
|
||||
logDO.setAddress(logRequest.getAddress());
|
||||
logDO.setBrowser(logRequest.getBrowser());
|
||||
logDO.setOs(StrUtil.subBefore(logRequest.getOs(), " or", false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置响应信息
|
||||
*
|
||||
* @param logDO 日志信息
|
||||
* @param logResponse 响应信息
|
||||
*/
|
||||
private void setResponse(LogDO logDO, LogResponse logResponse) {
|
||||
Map<String, String> responseHeaders = logResponse.getHeaders();
|
||||
logDO.setResponseHeaders(JSONUtil.toJsonStr(responseHeaders));
|
||||
logDO.setTraceId(responseHeaders.get(traceProperties.getTraceIdName()));
|
||||
String responseBody = logResponse.getBody();
|
||||
logDO.setResponseBody(responseBody);
|
||||
// 状态
|
||||
Integer statusCode = logResponse.getStatus();
|
||||
logDO.setStatusCode(statusCode);
|
||||
logDO.setStatus(statusCode >= HttpStatus.HTTP_BAD_REQUEST ? LogStatusEnum.FAILURE : LogStatusEnum.SUCCESS);
|
||||
if (StrUtil.isNotBlank(responseBody)) {
|
||||
R result = JSONUtil.toBean(responseBody, R.class);
|
||||
if (!result.isSuccess()) {
|
||||
logDO.setStatus(LogStatusEnum.FAILURE);
|
||||
logDO.setErrorMsg(result.getMsg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置操作人
|
||||
*
|
||||
* @param logDO 日志信息
|
||||
* @param logRequest 请求信息
|
||||
* @param logResponse 响应信息
|
||||
*/
|
||||
private void setCreateUser(LogDO logDO, LogRequest logRequest, LogResponse logResponse) {
|
||||
String requestUri = URLUtil.getPath(logDO.getRequestUrl());
|
||||
// 解析退出接口信息
|
||||
String responseBody = logResponse.getBody();
|
||||
if (requestUri.startsWith(SysConstants.LOGOUT_URI) && StrUtil.isNotBlank(responseBody)) {
|
||||
R result = JSONUtil.toBean(responseBody, R.class);
|
||||
logDO.setCreateUser(Convert.toLong(result.getData(), null));
|
||||
return;
|
||||
}
|
||||
// 解析登录接口信息
|
||||
if (requestUri.startsWith(SysConstants.LOGIN_URI) && LogStatusEnum.SUCCESS.equals(logDO.getStatus())) {
|
||||
String requestBody = logRequest.getBody();
|
||||
logDO.setDescription(JSONUtil.toBean(requestBody, LoginReq.class).getAuthType().getDescription() + "登录");
|
||||
// 解析账号登录用户为操作人
|
||||
if (requestBody.contains(AuthTypeEnum.ACCOUNT.getValue())) {
|
||||
AccountLoginReq authReq = JSONUtil.toBean(requestBody, AccountLoginReq.class);
|
||||
logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(authReq.getUsername())
|
||||
.getId()));
|
||||
return;
|
||||
} else if (requestBody.contains(AuthTypeEnum.EMAIL.getValue())) {
|
||||
EmailLoginReq authReq = JSONUtil.toBean(requestBody, EmailLoginReq.class);
|
||||
logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByEmail(authReq.getEmail()).getId()));
|
||||
return;
|
||||
} else if (requestBody.contains(AuthTypeEnum.PHONE.getValue())) {
|
||||
PhoneLoginReq authReq = JSONUtil.toBean(requestBody, PhoneLoginReq.class);
|
||||
logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByPhone(authReq.getPhone()).getId()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 解析 Token 信息
|
||||
Map<String, String> requestHeaders = logRequest.getHeaders();
|
||||
String headerName = HttpHeaders.AUTHORIZATION;
|
||||
boolean isContainsAuthHeader = CollUtil.containsAny(requestHeaders.keySet(), Set.of(headerName, headerName
|
||||
.toLowerCase()));
|
||||
if (MapUtil.isNotEmpty(requestHeaders) && isContainsAuthHeader) {
|
||||
String authorization = requestHeaders.getOrDefault(headerName, requestHeaders.get(headerName
|
||||
.toLowerCase()));
|
||||
String token = authorization.replace(SaManager.getConfig()
|
||||
.getTokenPrefix() + StringConstants.SPACE, StringConstants.EMPTY);
|
||||
logDO.setCreateUser(Convert.toLong(StpUtil.getLoginIdByToken(token)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package top.ysoft.admin.config.satoken;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 密码配置属性
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/6/15 22:15
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "auth.password")
|
||||
public class LoginPasswordProperties {
|
||||
|
||||
/**
|
||||
* 排除(放行)路径配置
|
||||
*/
|
||||
private String[] excludes = new String[0];
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package top.ysoft.admin.config.satoken;
|
||||
|
||||
import cn.dev33.satoken.fun.SaParamFunction;
|
||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.lang.Nullable;
|
||||
import top.ysoft.admin.common.context.UserContextHolder;
|
||||
|
||||
/**
|
||||
* Sa-Token 扩展拦截器
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2024/10/10 20:25
|
||||
*/
|
||||
public class SaExtensionInterceptor extends SaInterceptor {
|
||||
|
||||
public SaExtensionInterceptor(SaParamFunction<Object> auth) {
|
||||
super(auth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
boolean flag = super.preHandle(request, response, handler);
|
||||
if (flag && StpUtil.isLogin()) {
|
||||
UserContextHolder.getContext();
|
||||
UserContextHolder.getExtraContext();
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
Object handler,
|
||||
@Nullable Exception e) throws Exception {
|
||||
try {
|
||||
super.afterCompletion(request, response, handler, e);
|
||||
} finally {
|
||||
UserContextHolder.clearContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package top.ysoft.admin.config.satoken;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.context.model.SaRequest;
|
||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
import cn.dev33.satoken.sign.SaSignTemplate;
|
||||
import cn.dev33.satoken.sign.SaSignUtil;
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import top.ysoft.admin.common.context.UserContext;
|
||||
import top.ysoft.admin.common.context.UserContextHolder;
|
||||
import top.ysoft.admin.open.sign.OpenApiSignTemplate;
|
||||
import top.continew.starter.auth.satoken.autoconfigure.SaTokenExtensionProperties;
|
||||
import top.continew.starter.core.constant.StringConstants;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
import top.continew.starter.core.validation.CheckUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sa-Token 配置
|
||||
*
|
||||
* @author Charles7c
|
||||
* @author chengzi
|
||||
* @since 2022/12/19 22:13
|
||||
*/
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class SaTokenConfiguration {
|
||||
|
||||
private final SaTokenExtensionProperties properties;
|
||||
private final LoginPasswordProperties loginPasswordProperties;
|
||||
private final OpenApiSignTemplate signTemplate;
|
||||
|
||||
/**
|
||||
* Sa-Token 权限认证配置
|
||||
*/
|
||||
@Bean
|
||||
public StpInterface stpInterface() {
|
||||
return new SaTokenPermissionImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* SaToken 拦截器配置
|
||||
*/
|
||||
@Bean
|
||||
public SaInterceptor saInterceptor() {
|
||||
SaManager.setSaSignTemplate(signTemplate);
|
||||
return new SaExtensionInterceptor(handle -> SaRouter.match(StringConstants.PATH_PATTERN)
|
||||
.notMatch(properties.getSecurity().getExcludes())
|
||||
.check(r -> {
|
||||
// 如果包含 sign,进行 API 接口参数签名验证
|
||||
SaRequest saRequest = SaHolder.getRequest();
|
||||
List<String> paramNames = saRequest.getParamNames();
|
||||
if (paramNames.stream().anyMatch(SaSignTemplate.sign::equals)) {
|
||||
try {
|
||||
SaSignUtil.checkRequest(saRequest);
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException(e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 不包含 sign 参数,进行普通登录验证
|
||||
StpUtil.checkLogin();
|
||||
if (SaRouter.isMatchCurrURI(loginPasswordProperties.getExcludes())) {
|
||||
return;
|
||||
}
|
||||
UserContext userContext = UserContextHolder.getContext();
|
||||
CheckUtils.throwIf(userContext.isPasswordExpired(), "密码已过期,请修改密码");
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package top.ysoft.admin.config.satoken;
|
||||
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import top.ysoft.admin.common.context.UserContext;
|
||||
import top.ysoft.admin.common.context.UserContextHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sa-Token 权限认证实现
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/3/1 22:28
|
||||
*/
|
||||
public class SaTokenPermissionImpl implements StpInterface {
|
||||
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
UserContext userContext = UserContextHolder.getContext();
|
||||
return new ArrayList<>(userContext.getPermissions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRoleList(Object loginId, String loginType) {
|
||||
UserContext userContext = UserContextHolder.getContext();
|
||||
return new ArrayList<>(userContext.getRoleCodes());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package top.ysoft.admin.controller.auth;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.xkcoding.justauth.AuthRequestFactory;
|
||||
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 jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.ysoft.admin.auth.model.req.LoginReq;
|
||||
import top.ysoft.admin.auth.model.resp.LoginResp;
|
||||
import top.ysoft.admin.auth.model.resp.RouteResp;
|
||||
import top.ysoft.admin.auth.model.resp.SocialAuthAuthorizeResp;
|
||||
import top.ysoft.admin.auth.model.resp.UserInfoResp;
|
||||
import top.ysoft.admin.auth.service.AuthService;
|
||||
import top.ysoft.admin.common.context.UserContext;
|
||||
import top.ysoft.admin.common.context.UserContextHolder;
|
||||
import top.ysoft.admin.system.model.resp.user.UserDetailResp;
|
||||
import top.ysoft.admin.system.service.UserService;
|
||||
import top.continew.starter.core.exception.BadRequestException;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 认证 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/21 20:37
|
||||
*/
|
||||
@Tag(name = "认证 API")
|
||||
@Log(module = "登录")
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
private final UserService userService;
|
||||
private final AuthRequestFactory authRequestFactory;
|
||||
|
||||
@SaIgnore
|
||||
@Operation(summary = "登录", description = "用户登录")
|
||||
@PostMapping("/login")
|
||||
public LoginResp login(@Validated @RequestBody LoginReq req, HttpServletRequest request) {
|
||||
return authService.login(req, request);
|
||||
}
|
||||
|
||||
@Operation(summary = "登出", description = "注销用户的当前登录")
|
||||
@Parameter(name = "Authorization", description = "令牌", required = true, example = "Bearer xxxx-xxxx-xxxx-xxxx", in = ParameterIn.HEADER)
|
||||
@PostMapping("/logout")
|
||||
public Object logout() {
|
||||
Object loginId = StpUtil.getLoginId(-1L);
|
||||
StpUtil.logout();
|
||||
return loginId;
|
||||
}
|
||||
|
||||
@SaIgnore
|
||||
@Operation(summary = "三方账号登录授权", description = "三方账号登录授权")
|
||||
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
|
||||
@GetMapping("/{source}")
|
||||
public SocialAuthAuthorizeResp authorize(@PathVariable String source) {
|
||||
AuthRequest authRequest = this.getAuthRequest(source);
|
||||
return SocialAuthAuthorizeResp.builder()
|
||||
.authorizeUrl(authRequest.authorize(AuthStateUtils.createState()))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "获取用户信息", description = "获取登录用户信息")
|
||||
@GetMapping("/user/info")
|
||||
public UserInfoResp getUserInfo() {
|
||||
UserContext userContext = UserContextHolder.getContext();
|
||||
UserDetailResp userDetailResp = userService.get(userContext.getId());
|
||||
UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class);
|
||||
userInfoResp.setPermissions(userContext.getPermissions());
|
||||
userInfoResp.setRoles(userContext.getRoleCodes());
|
||||
userInfoResp.setPwdExpired(userContext.isPasswordExpired());
|
||||
return userInfoResp;
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "获取路由信息", description = "获取登录用户的路由信息")
|
||||
@GetMapping("/user/route")
|
||||
public List<RouteResp> listRoute() {
|
||||
return authService.buildRouteTree(UserContextHolder.getUserId());
|
||||
}
|
||||
|
||||
private AuthRequest getAuthRequest(String source) {
|
||||
try {
|
||||
return authRequestFactory.get(source);
|
||||
} catch (Exception e) {
|
||||
throw new BadRequestException("暂不支持 [%s] 平台账号登录".formatted(source));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package top.ysoft.admin.controller.code;
|
||||
|
||||
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 jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.ysoft.admin.generator.model.entity.FieldConfigDO;
|
||||
import top.ysoft.admin.generator.model.entity.GenConfigDO;
|
||||
import top.ysoft.admin.generator.model.query.GenConfigQuery;
|
||||
import top.ysoft.admin.generator.model.req.GenConfigReq;
|
||||
import top.ysoft.admin.generator.model.resp.GeneratePreviewResp;
|
||||
import top.ysoft.admin.generator.service.GeneratorService;
|
||||
import top.ysoft.admin.system.service.DictService;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 代码生成 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/8/3 22:58
|
||||
*/
|
||||
@Tag(name = "代码生成 API")
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/code/generator")
|
||||
public class GeneratorController {
|
||||
|
||||
private final GeneratorService baseService;
|
||||
private final DictService dictService;
|
||||
|
||||
@Operation(summary = "分页查询生成配置", description = "分页查询生成配置列表")
|
||||
@SaCheckPermission("code:generator:list")
|
||||
@GetMapping("/config")
|
||||
public PageResp<GenConfigDO> pageGenConfig(GenConfigQuery query, @Validated PageQuery pageQuery) {
|
||||
return baseService.pageGenConfig(query, pageQuery);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询生成配置信息", description = "查询生成配置信息")
|
||||
@Parameter(name = "tableName", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("code:generator:list")
|
||||
@GetMapping("/config/{tableName}")
|
||||
public GenConfigDO getGenConfig(@PathVariable String tableName) throws SQLException {
|
||||
return baseService.getGenConfig(tableName);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询字段配置列表", description = "查询字段配置列表")
|
||||
@Parameter(name = "tableName", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH)
|
||||
@Parameter(name = "requireSync", description = "是否需要同步", example = "false", in = ParameterIn.QUERY)
|
||||
@SaCheckPermission("code:generator:config")
|
||||
@GetMapping("/field/{tableName}")
|
||||
public List<FieldConfigDO> listFieldConfig(@PathVariable String tableName,
|
||||
@RequestParam(required = false, defaultValue = "false") Boolean requireSync) {
|
||||
return baseService.listFieldConfig(tableName, requireSync);
|
||||
}
|
||||
|
||||
@Operation(summary = "保存配置信息", description = "保存配置信息")
|
||||
@Parameter(name = "tableName", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("code:generator:config")
|
||||
@PostMapping("/config/{tableName}")
|
||||
public void saveConfig(@Validated @RequestBody GenConfigReq req, @PathVariable String tableName) {
|
||||
baseService.saveConfig(req, tableName);
|
||||
}
|
||||
|
||||
@Operation(summary = "生成预览", description = "预览生成代码")
|
||||
@Parameter(name = "tableNames", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("code:generator:preview")
|
||||
@GetMapping("/preview/{tableNames}")
|
||||
public List<GeneratePreviewResp> preview(@PathVariable List<String> tableNames) {
|
||||
return baseService.preview(tableNames);
|
||||
}
|
||||
|
||||
@Operation(summary = "生成下载代码", description = "生成下载代码")
|
||||
@Parameter(name = "tableNames", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("code:generator:generate")
|
||||
@PostMapping("/{tableNames}/download")
|
||||
public void downloadCode(@PathVariable List<String> tableNames, HttpServletResponse response) {
|
||||
baseService.downloadCode(tableNames, response);
|
||||
}
|
||||
|
||||
@Operation(summary = "生成代码", description = "生成代码")
|
||||
@Parameter(name = "tableNames", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("code:generator:generate")
|
||||
@PostMapping("/{tableNames}")
|
||||
public void generateCode(@PathVariable List<String> tableNames) {
|
||||
baseService.generateCode(tableNames);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询字典", description = "查询字典列表")
|
||||
@SaCheckPermission("code:generator:config")
|
||||
@GetMapping("/dict")
|
||||
public List<LabelValueResp> listDict() {
|
||||
List<LabelValueResp> dictList = dictService.listDict(null, null);
|
||||
dictList.addAll(dictService.listEnumDict());
|
||||
return dictList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package top.ysoft.admin.controller.common;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.lang.RegexPool;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||
import com.anji.captcha.model.common.RepCodeEnum;
|
||||
import com.anji.captcha.model.common.ResponseModel;
|
||||
import com.anji.captcha.model.vo.CaptchaVO;
|
||||
import com.anji.captcha.service.CaptchaService;
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.sms4j.api.SmsBlend;
|
||||
import org.dromara.sms4j.api.entity.SmsResponse;
|
||||
import org.dromara.sms4j.comm.constant.SupplierConstant;
|
||||
import org.dromara.sms4j.core.factory.SmsFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.ysoft.admin.auth.model.resp.CaptchaResp;
|
||||
import top.ysoft.admin.common.config.properties.CaptchaProperties;
|
||||
import top.ysoft.admin.common.constant.CacheConstants;
|
||||
import top.ysoft.admin.common.constant.SysConstants;
|
||||
import top.ysoft.admin.system.enums.OptionCategoryEnum;
|
||||
import top.ysoft.admin.system.service.OptionService;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.captcha.graphic.core.GraphicCaptchaService;
|
||||
import top.continew.starter.core.autoconfigure.project.ProjectProperties;
|
||||
import top.continew.starter.core.util.TemplateUtils;
|
||||
import top.continew.starter.core.validation.CheckUtils;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
import top.continew.starter.messaging.mail.util.MailUtils;
|
||||
import top.continew.starter.security.limiter.annotation.RateLimiter;
|
||||
import top.continew.starter.security.limiter.annotation.RateLimiters;
|
||||
import top.continew.starter.security.limiter.enums.LimitType;
|
||||
import top.continew.starter.web.model.R;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 验证码 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2022/12/11 14:00
|
||||
*/
|
||||
@Tag(name = "验证码 API")
|
||||
@SaIgnore
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/captcha")
|
||||
public class CaptchaController {
|
||||
|
||||
private final ProjectProperties projectProperties;
|
||||
private final CaptchaProperties captchaProperties;
|
||||
private final CaptchaService behaviorCaptchaService;
|
||||
private final GraphicCaptchaService graphicCaptchaService;
|
||||
private final OptionService optionService;
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "获取行为验证码", description = "获取行为验证码(Base64编码)")
|
||||
@GetMapping("/behavior")
|
||||
public Object getBehaviorCaptcha(CaptchaVO captchaReq, HttpServletRequest request) {
|
||||
captchaReq.setBrowserInfo(JakartaServletUtil.getClientIP(request) + request.getHeader(HttpHeaders.USER_AGENT));
|
||||
ResponseModel responseModel = behaviorCaptchaService.get(captchaReq);
|
||||
CheckUtils.throwIf(() -> !StrUtil.equals(RepCodeEnum.SUCCESS.getCode(), responseModel
|
||||
.getRepCode()), responseModel.getRepMsg());
|
||||
return responseModel.getRepData();
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "校验行为验证码", description = "校验行为验证码")
|
||||
@PostMapping("/behavior")
|
||||
public Object checkBehaviorCaptcha(@RequestBody CaptchaVO captchaReq, HttpServletRequest request) {
|
||||
captchaReq.setBrowserInfo(JakartaServletUtil.getClientIP(request) + request.getHeader(HttpHeaders.USER_AGENT));
|
||||
return behaviorCaptchaService.check(captchaReq);
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "获取图片验证码", description = "获取图片验证码(Base64编码,带图片格式:data:image/gif;base64)")
|
||||
@GetMapping("/image")
|
||||
public CaptchaResp getImageCaptcha() {
|
||||
int loginCaptchaEnabled = optionService.getValueByCode2Int("LOGIN_CAPTCHA_ENABLED");
|
||||
if (SysConstants.NO.equals(loginCaptchaEnabled)) {
|
||||
return CaptchaResp.builder().isEnabled(false).build();
|
||||
}
|
||||
String uuid = IdUtil.fastUUID();
|
||||
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + uuid;
|
||||
Captcha captcha = graphicCaptchaService.getCaptcha();
|
||||
long expireTime = LocalDateTimeUtil.toEpochMilli(LocalDateTime.now()
|
||||
.plusMinutes(captchaProperties.getExpirationInMinutes()));
|
||||
RedisUtils.set(captchaKey, captcha.text(), Duration.ofMinutes(captchaProperties.getExpirationInMinutes()));
|
||||
return CaptchaResp.of(uuid, captcha.toBase64(), expireTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邮箱验证码
|
||||
*
|
||||
* <p>
|
||||
* 限流规则:<br>
|
||||
* 1.同一邮箱同一模板,1分钟2条,1小时8条,24小时20条 <br>
|
||||
* 2、同一邮箱所有模板 24 小时 100 条 <br>
|
||||
* 3、同一 IP 每分钟限制发送 30 条
|
||||
* </p>
|
||||
*
|
||||
* @param email 邮箱
|
||||
* @return /
|
||||
*/
|
||||
@Operation(summary = "获取邮箱验证码", description = "发送验证码到指定邮箱")
|
||||
@GetMapping("/mail")
|
||||
@RateLimiters({
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX + "MIN", key = "#email + ':' + T(cn.hutool.extra.spring.SpringUtil).getProperty('captcha.mail.templatePath')", rate = 2, interval = 1, unit = TimeUnit.MINUTES, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX + "HOUR", key = "#email + ':' + T(cn.hutool.extra.spring.SpringUtil).getProperty('captcha.mail.templatePath')", rate = 8, interval = 1, unit = TimeUnit.HOURS, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX + "DAY'", key = "#email + ':' + T(cn.hutool.extra.spring.SpringUtil).getProperty('captcha.mail.templatePath')", rate = 20, interval = 24, unit = TimeUnit.HOURS, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX, key = "#email", rate = 100, interval = 24, unit = TimeUnit.HOURS, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX, key = "#email", rate = 30, interval = 1, unit = TimeUnit.MINUTES, type = LimitType.IP, message = "获取验证码操作太频繁,请稍后再试")})
|
||||
public R getMailCaptcha(@NotBlank(message = "邮箱不能为空") @Pattern(regexp = RegexPool.EMAIL, message = "邮箱格式错误") String email,
|
||||
CaptchaVO captchaReq) throws MessagingException {
|
||||
// 行为验证码校验
|
||||
ResponseModel verificationRes = behaviorCaptchaService.verification(captchaReq);
|
||||
ValidationUtils.throwIfNotEqual(verificationRes.getRepCode(), RepCodeEnum.SUCCESS.getCode(), verificationRes
|
||||
.getRepMsg());
|
||||
// 生成验证码
|
||||
CaptchaProperties.CaptchaMail captchaMail = captchaProperties.getMail();
|
||||
String captcha = RandomUtil.randomNumbers(captchaMail.getLength());
|
||||
// 发送验证码
|
||||
Long expirationInMinutes = captchaMail.getExpirationInMinutes();
|
||||
Map<String, String> siteConfig = optionService.getByCategory(OptionCategoryEnum.SITE);
|
||||
String content = TemplateUtils.render(captchaMail.getTemplatePath(), Dict.create()
|
||||
.set("siteUrl", projectProperties.getUrl())
|
||||
.set("siteTitle", siteConfig.get("SITE_TITLE"))
|
||||
.set("siteCopyright", siteConfig.get("SITE_COPYRIGHT"))
|
||||
.set("captcha", captcha)
|
||||
.set("expiration", expirationInMinutes));
|
||||
MailUtils.sendHtml(email, "【%s】邮箱验证码".formatted(projectProperties.getName()), content);
|
||||
// 保存验证码
|
||||
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + email;
|
||||
RedisUtils.set(captchaKey, captcha, Duration.ofMinutes(expirationInMinutes));
|
||||
return R.ok("发送成功,验证码有效期 %s 分钟".formatted(expirationInMinutes));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取短信验证码
|
||||
*
|
||||
* <p>
|
||||
* 限流规则:<br>
|
||||
* 1.同一号码同一模板,1分钟2条,1小时8条,24小时20条 <br>
|
||||
* 2、同一号码所有模板 24 小时 100 条 <br>
|
||||
* 3、同一 IP 每分钟限制发送 30 条
|
||||
* </p>
|
||||
*
|
||||
* @param phone 手机号
|
||||
* @param captchaReq 行为验证码信息
|
||||
* @return /
|
||||
*/
|
||||
@Operation(summary = "获取短信验证码", description = "发送验证码到指定手机号")
|
||||
@GetMapping("/sms")
|
||||
@RateLimiters({
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX + "MIN", key = "#phone + ':' + T(cn.hutool.extra.spring.SpringUtil).getProperty('captcha.sms.templateId')", rate = 2, interval = 1, unit = TimeUnit.MINUTES, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX + "HOUR", key = "#phone + ':' + T(cn.hutool.extra.spring.SpringUtil).getProperty('captcha.sms.templateId')", rate = 8, interval = 1, unit = TimeUnit.HOURS, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX + "DAY'", key = "#phone + ':' + T(cn.hutool.extra.spring.SpringUtil).getProperty('captcha.sms.templateId')", rate = 20, interval = 24, unit = TimeUnit.HOURS, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX, key = "#phone", rate = 100, interval = 24, unit = TimeUnit.HOURS, message = "获取验证码操作太频繁,请稍后再试"),
|
||||
@RateLimiter(name = CacheConstants.CAPTCHA_KEY_PREFIX, key = "#phone", rate = 30, interval = 1, unit = TimeUnit.MINUTES, type = LimitType.IP, message = "获取验证码操作太频繁,请稍后再试")})
|
||||
public R getSmsCaptcha(@NotBlank(message = "手机号不能为空") @Pattern(regexp = RegexPool.MOBILE, message = "手机号格式错误") String phone,
|
||||
CaptchaVO captchaReq) {
|
||||
// 行为验证码校验
|
||||
ResponseModel verificationRes = behaviorCaptchaService.verification(captchaReq);
|
||||
ValidationUtils.throwIfNotEqual(verificationRes.getRepCode(), RepCodeEnum.SUCCESS.getCode(), verificationRes
|
||||
.getRepMsg());
|
||||
CaptchaProperties.CaptchaSms captchaSms = captchaProperties.getSms();
|
||||
// 生成验证码
|
||||
String captcha = RandomUtil.randomNumbers(captchaSms.getLength());
|
||||
// 发送验证码
|
||||
Long expirationInMinutes = captchaSms.getExpirationInMinutes();
|
||||
SmsBlend smsBlend = SmsFactory.getBySupplier(SupplierConstant.CLOOPEN);
|
||||
Map<String, String> messageMap = MapUtil.newHashMap(2, true);
|
||||
messageMap.put("captcha", captcha);
|
||||
messageMap.put("expirationInMinutes", String.valueOf(expirationInMinutes));
|
||||
SmsResponse smsResponse = smsBlend.sendMessage(phone, captchaSms
|
||||
.getTemplateId(), (LinkedHashMap<String, String>)messageMap);
|
||||
CheckUtils.throwIf(!smsResponse.isSuccess(), "验证码发送失败");
|
||||
// 保存验证码
|
||||
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + phone;
|
||||
RedisUtils.set(captchaKey, captcha, Duration.ofMinutes(expirationInMinutes));
|
||||
return R.ok("发送成功,验证码有效期 %s 分钟".formatted(expirationInMinutes));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package top.ysoft.admin.controller.common;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alicp.jetcache.anno.Cached;
|
||||
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 jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.ysoft.admin.common.constant.CacheConstants;
|
||||
import top.ysoft.admin.common.util.PictureUtils;
|
||||
import top.ysoft.admin.peopleBranch.model.query.BranchQuery;
|
||||
import top.ysoft.admin.peopleBranch.service.BranchService;
|
||||
import top.ysoft.admin.space.model.query.PointQuery;
|
||||
import top.ysoft.admin.space.model.query.SpaceQuery;
|
||||
import top.ysoft.admin.space.service.PointService;
|
||||
import top.ysoft.admin.space.service.SpaceService;
|
||||
import top.ysoft.admin.system.enums.OptionCategoryEnum;
|
||||
import top.ysoft.admin.system.model.query.*;
|
||||
import top.ysoft.admin.system.model.resp.file.FileUploadResp;
|
||||
import top.ysoft.admin.system.service.*;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.model.query.SortQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公共 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/22 21:48
|
||||
*/
|
||||
@Tag(name = "公共 API")
|
||||
@Log(ignore = true)
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/common")
|
||||
public class CommonController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
|
||||
private final FileService fileService;
|
||||
private final DeptService deptService;
|
||||
private final MenuService menuService;
|
||||
private final UserService userService;
|
||||
private final RoleService roleService;
|
||||
private final BranchService branchService;
|
||||
private final DictItemService dictItemService;
|
||||
private final OptionService optionService;
|
||||
private final SpaceService spaceService;
|
||||
private final PointService pointService;
|
||||
|
||||
@Operation(summary = "上传文件", description = "上传文件")
|
||||
@PostMapping("/file")
|
||||
public FileUploadResp upload(@NotNull(message = "文件不能为空") MultipartFile file) {
|
||||
ValidationUtils.throwIf(file::isEmpty, "文件不能为空");
|
||||
FileInfo fileInfo = fileService.upload(file, true);
|
||||
return FileUploadResp.builder()
|
||||
.id(fileInfo.getId())
|
||||
.url(fileInfo.getUrl())
|
||||
.thUrl(fileInfo.getThUrl())
|
||||
.metadata(fileInfo.getMetadata())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Operation(summary = "上传文件", description = "上传文件")
|
||||
@PostMapping("/updateUpload")
|
||||
public FileUploadResp updateUpload(@NotNull(message = "文件不能为空") MultipartFile file, String savePath) {
|
||||
ValidationUtils.throwIf(file::isEmpty, "文件不能为空");
|
||||
FileInfo fileInfo = fileService.upload(file, savePath, null, false, false);
|
||||
return FileUploadResp.builder()
|
||||
.id(fileInfo.getId())
|
||||
.url(fileInfo.getUrl())
|
||||
.thUrl(fileInfo.getThUrl())
|
||||
.metadata(fileInfo.getMetadata())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Operation(summary = "上传文件", description = "上传文件")
|
||||
@PostMapping("/faceUpload")
|
||||
public FileUploadResp faceUpload(@NotNull(message = "图片不能为空") MultipartFile file, String savePath) {
|
||||
ValidationUtils.throwIf(file::isEmpty, "图片不能为空");
|
||||
|
||||
// 判断是否需要压缩图片
|
||||
if ((1024 * 1024 * 0.1) <= file.getSize()) {
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
float quality;
|
||||
// 根据文件大小设置不同的压缩质量
|
||||
if ((1024 * 1024 * 0.1) <= file.getSize() && file.getSize() <= (1024 * 1024)) {
|
||||
quality = 0.4f; // 小于1M的图片
|
||||
} else if ((1024 * 1024) < file.getSize() && file.getSize() <= (1024 * 1024 * 2)) {
|
||||
quality = 0.2f; // 1-2M的图片
|
||||
} else {
|
||||
quality = 0.1f; // 2M以上的图片
|
||||
}
|
||||
|
||||
// 直接在内存中压缩图片,避免使用临时文件
|
||||
file = PictureUtils.compressImage(inputStream, file.getOriginalFilename(), quality);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
FileInfo fileInfo = fileService.upload(file, savePath, null, false, false);
|
||||
return FileUploadResp.builder()
|
||||
.id(fileInfo.getId())
|
||||
.url(fileInfo.getUrl())
|
||||
.thUrl(fileInfo.getThUrl())
|
||||
.metadata(fileInfo.getMetadata())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询部门树", description = "查询树结构的部门列表")
|
||||
@GetMapping("/tree/dept")
|
||||
public List<Tree<Long>> listDeptTree(DeptQuery query, SortQuery sortQuery) {
|
||||
return deptService.tree(query, sortQuery, true);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询部门树", description = "查询树结构的部门列表")
|
||||
@GetMapping("/tree/branch")
|
||||
public List<Tree<String>> listBranchTree(BranchQuery query) {
|
||||
return branchService.tree(query);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询空间树", description = "查询树结构的空间列表")
|
||||
@GetMapping("/tree/space")
|
||||
public List<Tree<Long>> listSpaceTree(SpaceQuery query, SortQuery sortQuery) {
|
||||
return spaceService.tree(query, sortQuery, true);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询空间点位树", description = "查询树结构的菜单列表")
|
||||
@GetMapping("/tree/point")
|
||||
public List<Tree<Long>> listPointTree(PointQuery query) {
|
||||
return pointService.tree(query);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询菜单树", description = "查询树结构的菜单列表")
|
||||
@GetMapping("/tree/menu")
|
||||
public List<Tree<Long>> listMenuTree(MenuQuery query, SortQuery sortQuery) {
|
||||
return menuService.tree(query, sortQuery, true);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询用户字典", description = "查询用户字典列表")
|
||||
@GetMapping("/dict/user")
|
||||
public List<LabelValueResp> listUserDict(UserQuery query, SortQuery sortQuery) {
|
||||
return userService.listDict(query, sortQuery);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询角色字典", description = "查询角色字典列表")
|
||||
@GetMapping("/dict/role")
|
||||
public List<LabelValueResp> listRoleDict(RoleQuery query, SortQuery sortQuery) {
|
||||
return roleService.listDict(query, sortQuery);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询字典", description = "查询字典列表")
|
||||
@Parameter(name = "code", description = "字典编码", example = "notice_type", in = ParameterIn.PATH)
|
||||
@GetMapping("/dict/{code}")
|
||||
public List<LabelValueResp> listDict(@PathVariable String code) {
|
||||
return dictItemService.listByDictCode(code);
|
||||
}
|
||||
|
||||
@SaIgnore
|
||||
@Operation(summary = "查询系统配置参数", description = "查询系统配置参数")
|
||||
@GetMapping("/dict/option/site")
|
||||
@Cached(key = "'SITE'", name = CacheConstants.OPTION_KEY_PREFIX)
|
||||
public List<LabelValueResp<String>> listSiteOptionDict() {
|
||||
OptionQuery optionQuery = new OptionQuery();
|
||||
optionQuery.setCategory(OptionCategoryEnum.SITE.name());
|
||||
return optionService.list(optionQuery)
|
||||
.stream()
|
||||
.map(option -> new LabelValueResp<>(option.getCode(), StrUtil.nullToDefault(option.getValue(), option
|
||||
.getDefaultValue())))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package top.ysoft.admin.controller.common;
|
||||
|
||||
import com.alicp.jetcache.anno.CachePenetrationProtect;
|
||||
import com.alicp.jetcache.anno.CacheRefresh;
|
||||
import com.alicp.jetcache.anno.CacheType;
|
||||
import com.alicp.jetcache.anno.Cached;
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.constant.CacheConstants;
|
||||
import top.ysoft.admin.system.model.resp.dashboard.DashboardAccessTrendResp;
|
||||
import top.ysoft.admin.system.model.resp.dashboard.DashboardChartCommonResp;
|
||||
import top.ysoft.admin.system.model.resp.dashboard.DashboardNoticeResp;
|
||||
import top.ysoft.admin.system.model.resp.dashboard.DashboardOverviewCommonResp;
|
||||
import top.ysoft.admin.system.service.DashboardService;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 仪表盘 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/22 21:48
|
||||
*/
|
||||
@Tag(name = "仪表盘 API")
|
||||
@Log(ignore = true)
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/dashboard")
|
||||
public class DashboardController {
|
||||
|
||||
private final DashboardService dashboardService;
|
||||
|
||||
@Operation(summary = "查询公告列表", description = "查询公告列表")
|
||||
@GetMapping("/notice")
|
||||
public List<DashboardNoticeResp> listNotice() {
|
||||
return dashboardService.listNotice();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询PV总览", description = "查询PV总览")
|
||||
@GetMapping("/analysis/overview/pv")
|
||||
public DashboardOverviewCommonResp getOverviewPv() {
|
||||
return dashboardService.getOverviewPv();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询IP总览", description = "查询IP总览")
|
||||
@GetMapping("/analysis/overview/ip")
|
||||
public DashboardOverviewCommonResp getOverviewIp() {
|
||||
return dashboardService.getOverviewIp();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询地域分析", description = "查询地域分析")
|
||||
@GetMapping("/analysis/geo")
|
||||
@CachePenetrationProtect
|
||||
@CacheRefresh(refresh = 7200)
|
||||
@Cached(key = "'GEO'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
|
||||
public List<DashboardChartCommonResp> getAnalysisGeo() throws IOException {
|
||||
return dashboardService.getAnalysisGeo();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询访问趋势信息", description = "查询访问趋势信息")
|
||||
@Parameter(name = "days", description = "日期数", example = "30", in = ParameterIn.PATH)
|
||||
@GetMapping("/access/trend/{days}")
|
||||
@CachePenetrationProtect
|
||||
@CacheRefresh(refresh = 7200)
|
||||
@Cached(key = "#days", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
|
||||
public List<DashboardAccessTrendResp> listAccessTrend(@PathVariable Integer days) {
|
||||
ValidationUtils.throwIf(7 != days && 30 != days, "仅支持查询近 7/30 天访问趋势信息");
|
||||
return dashboardService.listAccessTrend(days);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询访问时段分析", description = "查询访问时段分析")
|
||||
@GetMapping("/analysis/timeslot")
|
||||
@CachePenetrationProtect
|
||||
@CacheRefresh(refresh = 7200)
|
||||
@Cached(key = "'TIMESLOT'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
|
||||
public List<DashboardChartCommonResp> getAnalysisTimeslot() {
|
||||
return dashboardService.getAnalysisTimeslot();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询模块分析", description = "查询模块分析")
|
||||
@GetMapping("/analysis/module")
|
||||
@CachePenetrationProtect
|
||||
@CacheRefresh(refresh = 7200)
|
||||
@Cached(key = "'MODULE'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
|
||||
public List<DashboardChartCommonResp> getAnalysisModule() {
|
||||
return dashboardService.getAnalysisModule();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询终端分析", description = "查询终端分析")
|
||||
@GetMapping("/analysis/os")
|
||||
@CachePenetrationProtect
|
||||
@CacheRefresh(refresh = 7200)
|
||||
@Cached(key = "'OS'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
|
||||
public List<DashboardChartCommonResp> getAnalysisOs() {
|
||||
return dashboardService.getAnalysisOs();
|
||||
}
|
||||
|
||||
@Operation(summary = "查询浏览器分析", description = "查询浏览器分析")
|
||||
@GetMapping("/analysis/browser")
|
||||
@CachePenetrationProtect
|
||||
@CacheRefresh(refresh = 7200)
|
||||
@Cached(key = "'BROWSER'", name = CacheConstants.DASHBOARD_KEY_PREFIX, cacheType = CacheType.BOTH, syncLocal = true)
|
||||
public List<DashboardChartCommonResp> getAnalysisBrowser() {
|
||||
return dashboardService.getAnalysisBrowser();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package top.ysoft.admin.controller.consume;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
import top.continew.starter.web.model.R;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.common.enums.OperTypeEnum;
|
||||
import top.ysoft.admin.consume.model.query.DownRecordQuery;
|
||||
import top.ysoft.admin.consume.model.req.DownRecordReq;
|
||||
import top.ysoft.admin.consume.model.resp.DownRecordResp;
|
||||
import top.ysoft.admin.consume.service.DownRecordService;
|
||||
|
||||
/**
|
||||
* 消费下发记录管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/02/25 11:01
|
||||
*/
|
||||
@Tag(name = "消费下发记录管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/consume/downRecord", api = {Api.PAGE, Api.EXPORT})
|
||||
public class DownRecordController extends BaseController<DownRecordService, DownRecordResp, DownRecordResp, DownRecordQuery, DownRecordReq> {
|
||||
|
||||
@Operation(summary = "下发", description = "下发")
|
||||
@SaCheckPermission("consume:downRecord:down")
|
||||
@PatchMapping("/down/{equipmentId}/{peopleId}")
|
||||
public R down(@PathVariable Long equipmentId, @PathVariable Long peopleId) {
|
||||
baseService.down(equipmentId, peopleId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package top.ysoft.admin.controller.consume;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.consume.model.query.GroupQuery;
|
||||
import top.ysoft.admin.consume.model.req.GroupReq;
|
||||
import top.ysoft.admin.consume.model.resp.GroupResp;
|
||||
import top.ysoft.admin.consume.service.GroupService;
|
||||
|
||||
/**
|
||||
* 消费组管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/01/27 13:48
|
||||
*/
|
||||
@Tag(name = "消费批量充值 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/consume/group", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class GroupController extends BaseController<GroupService, GroupResp, GroupResp, GroupQuery, GroupReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package top.ysoft.admin.controller.consume;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.consume.model.query.RechargeRecordQuery;
|
||||
import top.ysoft.admin.consume.model.req.RechargeRecordReq;
|
||||
import top.ysoft.admin.consume.model.resp.RechargeRecordResp;
|
||||
import top.ysoft.admin.consume.service.RechargeRecordService;
|
||||
|
||||
/**
|
||||
* 充值记录管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/01/29 16:11
|
||||
*/
|
||||
@Tag(name = "充值记录管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/admin/rechargeRecord", api = {Api.PAGE, Api.DELETE, Api.EXPORT})
|
||||
public class RechargeRecordController extends BaseController<RechargeRecordService, RechargeRecordResp, RechargeRecordResp, RechargeRecordQuery, RechargeRecordReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package top.ysoft.admin.controller.consume;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.consume.model.query.RecordQuery;
|
||||
import top.ysoft.admin.consume.model.req.RecordReq;
|
||||
import top.ysoft.admin.consume.model.resp.RecordResp;
|
||||
import top.ysoft.admin.consume.service.RecordService;
|
||||
|
||||
/**
|
||||
* 消费记录管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/01/21 17:53
|
||||
*/
|
||||
@Tag(name = "消费记录管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/consume/record", api = {Api.PAGE, Api.DETAIL, Api.DELETE, Api.EXPORT})
|
||||
public class RecordController extends BaseController<RecordService, RecordResp, RecordResp, RecordQuery, RecordReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package top.ysoft.admin.controller.consume;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.web.model.R;
|
||||
import top.ysoft.admin.consume.model.query.ReportQuery;
|
||||
import top.ysoft.admin.consume.model.resp.report.BranchReport;
|
||||
import top.ysoft.admin.consume.model.resp.report.MealReport;
|
||||
import top.ysoft.admin.consume.model.resp.report.MerchantReport;
|
||||
import top.ysoft.admin.consume.model.resp.report.PeopleReport;
|
||||
import top.ysoft.admin.consume.service.ReportService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "报表管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/consume/report")
|
||||
public class ReportController {
|
||||
|
||||
private final ReportService reportService;
|
||||
|
||||
@GetMapping("/merchant")
|
||||
public R<List<MerchantReport>> queryMerchantReport(ReportQuery query) {
|
||||
List<MerchantReport> list = reportService.queryMerchantReport(query);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@GetMapping("/meal")
|
||||
public R<List<MealReport>> queryMealReport(ReportQuery query) {
|
||||
List<MealReport> list = reportService.queryMealReport(query);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@GetMapping("/branch")
|
||||
public R<List<BranchReport>> queryBranchReport(ReportQuery query) {
|
||||
List<BranchReport> list = reportService.queryBranchReport(query);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
@GetMapping("/people")
|
||||
public PageResp<PeopleReport> queryPeopleReport(ReportQuery query, @Validated PageQuery pageQuery) {
|
||||
return reportService.page(query, pageQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/exportMerchant")
|
||||
public void exportMerchant(ReportQuery query, HttpServletResponse response) {
|
||||
reportService.exportMerchant(query, response);
|
||||
}
|
||||
|
||||
@GetMapping("/exportMeal")
|
||||
public void exportMeal(ReportQuery query, HttpServletResponse response) {
|
||||
reportService.exportMeal(query, response);
|
||||
}
|
||||
|
||||
@GetMapping("/exportBranch")
|
||||
public void exportBranch(ReportQuery query, HttpServletResponse response) {
|
||||
reportService.exportBranch(query, response);
|
||||
}
|
||||
|
||||
@GetMapping("/exportPeople")
|
||||
public void exportPeople(ReportQuery query, HttpServletResponse response) {
|
||||
reportService.exportPeople(query, response);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package top.ysoft.admin.controller.consume;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.consume.model.query.TenantQuery;
|
||||
import top.ysoft.admin.consume.model.req.TenantReq;
|
||||
import top.ysoft.admin.consume.model.resp.TenantResp;
|
||||
import top.ysoft.admin.consume.service.TenantService;
|
||||
|
||||
/**
|
||||
* 商户信息管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/01/30 14:55
|
||||
*/
|
||||
@Tag(name = "商户信息管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/consume/tenant", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class TenantController extends BaseController<TenantService, TenantResp, TenantResp, TenantQuery, TenantReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package top.ysoft.admin.controller.consume;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.consume.model.query.TimeIntervalQuery;
|
||||
import top.ysoft.admin.consume.model.req.TimeIntervalReq;
|
||||
import top.ysoft.admin.consume.model.resp.TimeIntervalResp;
|
||||
import top.ysoft.admin.consume.service.TimeIntervalService;
|
||||
|
||||
/**
|
||||
* 消费时段管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2026/01/30 14:56
|
||||
*/
|
||||
@Tag(name = "消费时段管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/consume/timeInterval", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class TimeIntervalController extends BaseController<TimeIntervalService, TimeIntervalResp, TimeIntervalResp, TimeIntervalQuery, TimeIntervalReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package top.ysoft.admin.controller.equipment;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.equipment.model.query.EquipmentQuery;
|
||||
import top.ysoft.admin.equipment.model.req.EquipmentReq;
|
||||
import top.ysoft.admin.equipment.model.resp.EquipmentDetailResp;
|
||||
import top.ysoft.admin.equipment.model.resp.EquipmentResp;
|
||||
import top.ysoft.admin.equipment.service.EquipmentService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 设备信息管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/04/09 15:20
|
||||
*/
|
||||
@Tag(name = "设备信息管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/system/equipment", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class EquipmentController extends BaseController<EquipmentService, EquipmentResp, EquipmentDetailResp, EquipmentQuery, EquipmentReq> {
|
||||
|
||||
@GetMapping(value = "/getEquipmentNameList")
|
||||
public List<LabelValueResp> getEquipmentNameList(EquipmentReq equipmentReq) {
|
||||
return baseService.getEquipmentNameList(equipmentReq);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package top.ysoft.admin.controller.equipment;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.PeopleEquipmentQuery;
|
||||
import top.ysoft.admin.system.model.req.PeopleEquipmentReq;
|
||||
import top.ysoft.admin.system.model.resp.PeopleEquipmentResp;
|
||||
import top.ysoft.admin.system.service.PeopleEquipmentService;
|
||||
|
||||
/**
|
||||
* 人员设备下发信息管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/03/27 14:59
|
||||
*/
|
||||
@Tag(name = "人员设备下发信息管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/peopleEquipment", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class PeopleEquipmentController extends BaseController<PeopleEquipmentService, PeopleEquipmentResp, PeopleEquipmentResp, PeopleEquipmentQuery, PeopleEquipmentReq> {}
|
||||
@@ -0,0 +1,37 @@
|
||||
package top.ysoft.admin.controller.equipment;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.equipment.model.query.ProductQuery;
|
||||
import top.ysoft.admin.equipment.model.req.ProductReq;
|
||||
import top.ysoft.admin.equipment.model.resp.ProductResp;
|
||||
import top.ysoft.admin.equipment.service.ProductService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 产品信息管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/05/26 15:18
|
||||
*/
|
||||
@Tag(name = "产品信息管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/equipment/product", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class ProductController extends BaseController<ProductService, ProductResp, ProductResp, ProductQuery, ProductReq> {
|
||||
|
||||
private final ProductService productService;
|
||||
|
||||
@GetMapping(value = "/getProductNameList")
|
||||
public List<LabelValueResp> getProductNameList() {
|
||||
return productService.getProductNameList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package top.ysoft.admin.controller.monitor;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
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.auth.model.query.OnlineUserQuery;
|
||||
import top.ysoft.admin.auth.model.resp.OnlineUserResp;
|
||||
import top.ysoft.admin.auth.service.OnlineUserService;
|
||||
import top.continew.starter.core.validation.CheckUtils;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
|
||||
/**
|
||||
* 在线用户 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/20 21:51
|
||||
*/
|
||||
@Tag(name = "在线用户 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/monitor/online")
|
||||
public class OnlineUserController {
|
||||
|
||||
private final OnlineUserService baseService;
|
||||
|
||||
@Operation(summary = "分页查询列表", description = "分页查询列表")
|
||||
@SaCheckPermission("monitor:online:list")
|
||||
@GetMapping
|
||||
public PageResp<OnlineUserResp> page(OnlineUserQuery query, @Validated PageQuery pageQuery) {
|
||||
return baseService.page(query, pageQuery);
|
||||
}
|
||||
|
||||
@Operation(summary = "强退在线用户", description = "强退在线用户")
|
||||
@Parameter(name = "token", description = "令牌", example = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOjEsInJuU3RyIjoiTUd6djdyOVFoeHEwdVFqdFAzV3M5YjVJRzh4YjZPSEUifQ.7q7U3ouoN7WPhH2kUEM7vPe5KF3G_qavSG-vRgIxKvE", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("monitor:online:kickout")
|
||||
@DeleteMapping("/{token}")
|
||||
public void kickout(@PathVariable String token) {
|
||||
String currentToken = StpUtil.getTokenValue();
|
||||
CheckUtils.throwIfEqual(token, currentToken, "不能强退自己");
|
||||
StpUtil.kickoutByTokenValue(token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package top.ysoft.admin.controller.open;
|
||||
|
||||
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.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.open.model.query.AppQuery;
|
||||
import top.ysoft.admin.open.model.req.AppReq;
|
||||
import top.ysoft.admin.open.model.resp.AppDetailResp;
|
||||
import top.ysoft.admin.open.model.resp.AppResp;
|
||||
import top.ysoft.admin.open.model.resp.AppSecretResp;
|
||||
import top.ysoft.admin.open.service.AppService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
/**
|
||||
* 应用管理 API
|
||||
*
|
||||
* @author chengzi
|
||||
* @author Charles7c
|
||||
* @since 2024/10/17 16:03
|
||||
*/
|
||||
@Tag(name = "应用管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/open/app", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class AppController extends BaseController<AppService, AppResp, AppDetailResp, AppQuery, AppReq> {
|
||||
|
||||
@Operation(summary = "获取密钥", description = "获取应用密钥")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("open:app:secret")
|
||||
@GetMapping("/{id}/secret")
|
||||
public AppSecretResp getSecret(@PathVariable Long id) {
|
||||
return baseService.getSecret(id);
|
||||
}
|
||||
|
||||
@Operation(summary = "重置密钥", description = "重置应用密钥")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("open:app:resetSecret")
|
||||
@PatchMapping("/{id}/secret")
|
||||
public void resetSecret(@PathVariable Long id) {
|
||||
baseService.resetSecret(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package top.ysoft.admin.controller.peopleBranch;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
import top.ysoft.admin.peopleBranch.model.query.BranchQuery;
|
||||
import top.ysoft.admin.peopleBranch.model.req.BranchReq;
|
||||
import top.ysoft.admin.peopleBranch.model.resp.BranchResp;
|
||||
import top.ysoft.admin.peopleBranch.service.BranchService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 部门管理管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/03/19 17:46
|
||||
*/
|
||||
@Tag(name = "部门管理管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/sysPeople/branch")
|
||||
public class BranchController {
|
||||
|
||||
private final BranchService branchService;
|
||||
|
||||
/**
|
||||
* 查询部门树形结构
|
||||
*
|
||||
* @param branchQuery
|
||||
* @return
|
||||
*/
|
||||
@Log(ignore = true)
|
||||
@SaCheckPermission("sysPeople:branch:tree")
|
||||
@GetMapping("/tree")
|
||||
public List<Tree<String>> selectBranchTree(BranchQuery branchQuery) {
|
||||
return branchService.selectBranchTree(branchQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门管理详细信息
|
||||
*/
|
||||
@SaCheckPermission("sysPeople:branch:query")
|
||||
@GetMapping(value = "/{id}")
|
||||
public BranchResp getInfo(@PathVariable("id") String id) {
|
||||
return branchService.selectBranchById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增部门管理
|
||||
*/
|
||||
@SaCheckPermission("sysPeople:branch:add")
|
||||
@Log(module = "新增部门")
|
||||
@PostMapping
|
||||
public String add(@RequestBody BranchReq branchReq) {
|
||||
return branchService.insertBranch(branchReq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改部门管理
|
||||
*/
|
||||
@SaCheckPermission("sysPeople:branch:edit")
|
||||
@Log(module = "修改部门")
|
||||
@PutMapping("/{id}")
|
||||
public void edit(@PathVariable("id") String id, @RequestBody BranchReq branchReq) {
|
||||
branchService.updateBranch(branchReq, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部门管理
|
||||
*/
|
||||
@SaCheckPermission("sysPeople:branch:remove")
|
||||
@Log(module = "删除部门")
|
||||
@DeleteMapping("/{id}")
|
||||
public void remove(@PathVariable("id") String id) {
|
||||
branchService.deleteBranchById(id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package top.ysoft.admin.controller.peopleBranch;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
import top.continew.starter.web.model.R;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.consume.model.req.PeopleDepositImportReq;
|
||||
import top.ysoft.admin.consume.model.resp.PeopleDepositImportParseResp;
|
||||
import top.ysoft.admin.peopleBranch.model.query.PeopleQuery;
|
||||
import top.ysoft.admin.peopleBranch.model.req.PeopleImportReq;
|
||||
import top.ysoft.admin.peopleBranch.model.req.PeopleReq;
|
||||
import top.ysoft.admin.peopleBranch.model.resp.ConsumePeopleResp;
|
||||
import top.ysoft.admin.peopleBranch.model.resp.PeopleImportParseResp;
|
||||
import top.ysoft.admin.peopleBranch.model.resp.PeopleImportResp;
|
||||
import top.ysoft.admin.peopleBranch.model.resp.PeopleResp;
|
||||
import top.ysoft.admin.peopleBranch.service.PeopleService;
|
||||
import top.ysoft.admin.system.model.req.user.UserImportReq;
|
||||
import top.ysoft.admin.system.model.resp.user.UserImportResp;
|
||||
import top.ysoft.admin.system.service.ImportExcelService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 人员管理管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/03/21 18:10
|
||||
*/
|
||||
@Tag(name = "人员管理管理 API")
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@Slf4j
|
||||
@CrudRequestMapping(value = "/sysPeople/people", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.EXPORT})
|
||||
public class PeopleController extends BaseController<PeopleService, PeopleResp, PeopleResp, PeopleQuery, PeopleReq> {
|
||||
|
||||
private final ImportExcelService importExcelService;
|
||||
|
||||
@GetMapping(value = "/getPeopleNameList")
|
||||
public List<LabelValueResp> getPeopleNameList(PeopleQuery peopleQuery) {
|
||||
return baseService.getPeopleNameList(peopleQuery);
|
||||
}
|
||||
|
||||
@GetMapping("/down/{ids}")
|
||||
public R down(@PathVariable Long[] ids) {
|
||||
String failNames = baseService.down(ids);
|
||||
if (StrUtil.isNotBlank(failNames)) {
|
||||
return R.fail("500", "存在失败记录,人员名称:" + failNames);
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{ids}")
|
||||
public R del(@PathVariable Long[] ids) {
|
||||
String failNames = baseService.del(Arrays.asList(ids));
|
||||
if (StrUtil.isNotBlank(failNames)) {
|
||||
return R.fail("500", "设备删除失败,人员名称:" + failNames);
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "下载导入模板", description = "下载导入模板")
|
||||
@SaCheckPermission("sysPeople:people:import")
|
||||
@GetMapping(value = "/import/template", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public void downloadImportTemplate(HttpServletResponse response) throws IOException {
|
||||
importExcelService.downloadImportTemplate(response, "people.xlsx", "人员导入模板.xlsx");
|
||||
}
|
||||
|
||||
//导入相关
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "解析导入数据", description = "解析导入数据")
|
||||
@SaCheckPermission("sysPeople:people:import")
|
||||
@PostMapping("/import/parse")
|
||||
public PeopleImportParseResp parseImport(@NotNull(message = "文件不能为空") MultipartFile file) {
|
||||
ValidationUtils.throwIf(file::isEmpty, "文件不能为空");
|
||||
return baseService.parseImport(file);
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "导入数据", description = "导入数据")
|
||||
@SaCheckPermission("sysPeople:people:import")
|
||||
@PostMapping(value = "/import")
|
||||
public PeopleImportResp importUser(@Validated @RequestBody PeopleImportReq req) {
|
||||
return baseService.importPeople(req);
|
||||
}
|
||||
|
||||
|
||||
//消费相关
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "分页查询人员消费列表", description = "分页查询列表")
|
||||
@GetMapping("/pageConsume")
|
||||
@SaCheckPermission("consume:PeopleDeposit:refund")
|
||||
public PageResp<ConsumePeopleResp> pageConsume(PeopleQuery query, @Validated PageQuery pageQuery) {
|
||||
return baseService.pageConsume(query, pageQuery);
|
||||
}
|
||||
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "导出人员充值列表", description = "导出人员充值列表")
|
||||
@GetMapping("/exportConsume")
|
||||
@SaCheckPermission("consume:PeopleDeposit:export")
|
||||
public void exportConsume(PeopleQuery query, HttpServletResponse response) {
|
||||
baseService.exportConsume(query, response);
|
||||
}
|
||||
|
||||
@Operation(summary = "补贴", description = "补贴")
|
||||
@PostMapping("/subsidy")
|
||||
@SaCheckPermission("consume:PeopleDeposit:subsidy")
|
||||
public R subsidy(@RequestBody PeopleReq req) {
|
||||
baseService.subsidy(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "充值", description = "充值")
|
||||
@PostMapping("/deposit")
|
||||
@SaCheckPermission("consume:PeopleDeposit:deposit")
|
||||
public R deposit(@RequestBody PeopleReq req) {
|
||||
baseService.deposit(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "退款", description = "退款")
|
||||
@PostMapping("/refund")
|
||||
@SaCheckPermission("consume:PeopleDeposit:refund")
|
||||
public R refund(@RequestBody PeopleReq req) {
|
||||
baseService.refund(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "消费冻结", description = "消费冻结")
|
||||
@PostMapping("/freeze")
|
||||
@SaCheckPermission("consume:PeopleDeposit:freeze")
|
||||
public R freeze(@RequestBody List<Long> ids) {
|
||||
baseService.freeze(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "消费解冻", description = "消费解冻")
|
||||
@PostMapping("/unFreeze")
|
||||
@SaCheckPermission("consume:PeopleDeposit:unfreeze")
|
||||
public R unFreeze(@RequestBody List<Long> ids) {
|
||||
baseService.unFreeze(ids);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "消费一键清零", description = "消费一键清零")
|
||||
@PostMapping("/resetMoney")
|
||||
@SaCheckPermission("consume:PeopleDeposit:import")
|
||||
public R resetMoney(@RequestBody PeopleReq req) {
|
||||
baseService.resetMoney(req);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "下载人员充值导入模板", description = "下载人员充值导入模板")
|
||||
@SaCheckPermission("consume:PeopleDeposit:import")
|
||||
@GetMapping(value = "/consume/import/template", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public void downloadConsumeImportTemplate(HttpServletResponse response) throws IOException {
|
||||
baseService.downloadConsumeImportTemplate(response);
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "解析人员充值导入数据", description = "解析人员充值导入数据")
|
||||
@SaCheckPermission("consume:PeopleDeposit:import")
|
||||
@PostMapping("/consume/import/parse")
|
||||
public PeopleDepositImportParseResp parseConsumeImport(@NotNull(message = "文件不能为空") MultipartFile file) {
|
||||
ValidationUtils.throwIf(file::isEmpty, "文件不能为空");
|
||||
return baseService.parseConsumeImport(file);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "导入数据", description = "导入数据")
|
||||
@SaCheckPermission("consume:PeopleDeposit:import")
|
||||
@PostMapping(value = "/consume/import")
|
||||
public UserImportResp importUser(@Validated @RequestBody PeopleDepositImportReq req) {
|
||||
return baseService.importConsumePeople(req);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package top.ysoft.admin.controller.peopleDownRecord;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.web.model.R;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.common.enums.OperTypeEnum;
|
||||
import top.ysoft.admin.peopleDownRecord.model.query.PeopleDownQuery;
|
||||
import top.ysoft.admin.peopleDownRecord.model.req.PeopleDownReq;
|
||||
import top.ysoft.admin.peopleDownRecord.model.resp.PeopleDownResp;
|
||||
import top.ysoft.admin.peopleDownRecord.service.PeopleDownService;
|
||||
import top.ysoft.admin.yfApi.service.ISysYFService;
|
||||
|
||||
@Tag(name = "下发管理 API")
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@Slf4j
|
||||
@CrudRequestMapping(value = "/sysDownRecord/record", api = {Api.PAGE, Api.DETAIL, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class PeopleDownController extends BaseController<PeopleDownService, PeopleDownResp, PeopleDownResp, PeopleDownQuery, PeopleDownReq> {
|
||||
|
||||
private final ISysYFService sysYFService;
|
||||
|
||||
@GetMapping("/down/{equipmentId}/{ruleId}/{peopleId}")
|
||||
public R down(@PathVariable Long equipmentId, @PathVariable Long ruleId, @PathVariable Long peopleId) {
|
||||
Boolean success = sysYFService.authDevice(peopleId, equipmentId, ruleId, OperTypeEnum.DOWN.getValue());
|
||||
if (!success) {
|
||||
return R.fail("500", "下发设备失败");
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.ysoft.admin.controller.rule;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.rule.model.query.EmpowerRecordQuery;
|
||||
import top.ysoft.admin.rule.model.req.EmpowerRecordReq;
|
||||
import top.ysoft.admin.rule.model.resp.EmpowerRecordResp;
|
||||
import top.ysoft.admin.rule.service.EmpowerRecordService;
|
||||
|
||||
/**
|
||||
* 授权记录管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/04/08 23:08
|
||||
*/
|
||||
@Tag(name = "授权记录管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/rule/empowerRecord", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class EmpowerRecordController extends BaseController<EmpowerRecordService, EmpowerRecordResp, EmpowerRecordResp, EmpowerRecordQuery, EmpowerRecordReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.ysoft.admin.controller.rule;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.rule.model.query.PeopleRecordQuery;
|
||||
import top.ysoft.admin.rule.model.req.PeopleRecordReq;
|
||||
import top.ysoft.admin.rule.model.resp.PeopleRecordResp;
|
||||
import top.ysoft.admin.rule.service.PeopleRecordService;
|
||||
|
||||
/**
|
||||
* 人员识别记录管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/04/08 23:06
|
||||
*/
|
||||
@Tag(name = "人员识别记录管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/rule/peopleRecord", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class PeopleRecordController extends BaseController<PeopleRecordService, PeopleRecordResp, PeopleRecordResp, PeopleRecordQuery, PeopleRecordReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package top.ysoft.admin.controller.rule;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||
import top.continew.starter.web.model.R;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.rule.model.query.RuleQuery;
|
||||
import top.ysoft.admin.rule.model.req.RuleReq;
|
||||
import top.ysoft.admin.rule.model.resp.RuleResp;
|
||||
import top.ysoft.admin.rule.service.RuleService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 通行规则管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/04/07 14:20
|
||||
*/
|
||||
@Tag(name = "通行规则管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/rule/rule", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class RuleController extends BaseController<RuleService, RuleResp, RuleResp, RuleQuery, RuleReq> {
|
||||
|
||||
private final RuleService ruleService;
|
||||
|
||||
@GetMapping(value = "/getRuleNameList")
|
||||
public List<LabelValueResp> getRuleNameList(RuleReq RuleReq) {
|
||||
return ruleService.getRuleNameList(RuleReq);
|
||||
}
|
||||
|
||||
@PostMapping("/add1")
|
||||
public R addRule1(@RequestBody RuleReq ruleReq) {
|
||||
String result = baseService.addRule1(ruleReq);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
@PutMapping("/update1/{id}")
|
||||
public R updateRule1(@PathVariable("id") Long id, @RequestBody RuleReq ruleReq) {
|
||||
String result = baseService.updateRule1(ruleReq, id);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package top.ysoft.admin.controller.space;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.space.model.query.PointQuery;
|
||||
import top.ysoft.admin.space.model.req.PointReq;
|
||||
import top.ysoft.admin.space.model.resp.PointResp;
|
||||
import top.ysoft.admin.space.service.PointService;
|
||||
|
||||
/**
|
||||
* 点位管理管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/04/03 15:01
|
||||
*/
|
||||
@Tag(name = "点位管理管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/space/point", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class PointController extends BaseController<PointService, PointResp, PointResp, PointQuery, PointReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.ysoft.admin.controller.space;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.space.model.query.SpaceQuery;
|
||||
import top.ysoft.admin.space.model.req.SpaceReq;
|
||||
import top.ysoft.admin.space.model.resp.SpaceResp;
|
||||
import top.ysoft.admin.space.model.resp.SpaceResp;
|
||||
import top.ysoft.admin.space.service.SpaceService;
|
||||
|
||||
/**
|
||||
* 空间管理管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/04/03 10:47
|
||||
*/
|
||||
@Tag(name = "空间管理管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/space/space", api = {Api.TREE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class SpaceController extends BaseController<SpaceService, SpaceResp, SpaceResp, SpaceQuery, SpaceReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.ClientQuery;
|
||||
import top.ysoft.admin.system.model.req.ClientReq;
|
||||
import top.ysoft.admin.system.model.resp.ClientResp;
|
||||
import top.ysoft.admin.system.service.ClientService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
/**
|
||||
* 终端管理 API
|
||||
*
|
||||
* @author KAI
|
||||
* @since 2024/12/03 16:04
|
||||
*/
|
||||
@Tag(name = "终端管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/client", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
|
||||
public class ClientController extends BaseController<ClientService, ClientResp, ClientResp, ClientQuery, ClientReq> {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.ConfigQuery;
|
||||
import top.ysoft.admin.system.model.req.ConfigReq;
|
||||
import top.ysoft.admin.system.model.resp.ConfigResp;
|
||||
import top.ysoft.admin.system.service.ConfigService;
|
||||
|
||||
/**
|
||||
* 参数配置管理 API
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/12/30 12:44
|
||||
*/
|
||||
@Tag(name = "参数配置管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/config", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class ConfigController extends BaseController<ConfigService, ConfigResp, ConfigResp, ConfigQuery, ConfigReq> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.DeptQuery;
|
||||
import top.ysoft.admin.system.model.req.DeptReq;
|
||||
import top.ysoft.admin.system.model.resp.DeptResp;
|
||||
import top.ysoft.admin.system.service.DeptService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
/**
|
||||
* 部门管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/22 17:50
|
||||
*/
|
||||
@Tag(name = "部门管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/dept", api = {Api.TREE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
|
||||
public class DeptController extends BaseController<DeptService, DeptResp, DeptResp, DeptQuery, DeptReq> {
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.constant.CacheConstants;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.DictQuery;
|
||||
import top.ysoft.admin.system.model.req.DictReq;
|
||||
import top.ysoft.admin.system.model.resp.DictResp;
|
||||
import top.ysoft.admin.system.service.DictService;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
/**
|
||||
* 字典管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/9/11 21:29
|
||||
*/
|
||||
@Tag(name = "字典管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/dict", api = {Api.LIST, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
|
||||
public class DictController extends BaseController<DictService, DictResp, DictResp, DictQuery, DictReq> {
|
||||
|
||||
@Operation(summary = "清除缓存", description = "清除缓存")
|
||||
@SaCheckPermission("system:dict:clearCache")
|
||||
@DeleteMapping("/cache/{code}")
|
||||
public void clearCache(@PathVariable String code) {
|
||||
RedisUtils.deleteByPattern(CacheConstants.DICT_KEY_PREFIX + code);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.DictItemQuery;
|
||||
import top.ysoft.admin.system.model.req.DictItemReq;
|
||||
import top.ysoft.admin.system.model.resp.DictItemResp;
|
||||
import top.ysoft.admin.system.service.DictItemService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
|
||||
/**
|
||||
* 字典项管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/9/11 21:29
|
||||
*/
|
||||
@Log(module = "字典管理")
|
||||
@Tag(name = "字典项管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/dict/item", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
|
||||
public class DictItemController extends BaseController<DictItemService, DictItemResp, DictItemResp, DictItemQuery, DictItemReq> {
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.FileQuery;
|
||||
import top.ysoft.admin.system.model.req.FileReq;
|
||||
import top.ysoft.admin.system.model.resp.file.FileResp;
|
||||
import top.ysoft.admin.system.model.resp.file.FileStatisticsResp;
|
||||
import top.ysoft.admin.system.service.FileService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
|
||||
/**
|
||||
* 文件管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/12/23 10:38
|
||||
*/
|
||||
@Tag(name = "文件管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/system/file", api = {Api.PAGE, Api.UPDATE, Api.DELETE})
|
||||
public class FileController extends BaseController<FileService, FileResp, FileResp, FileQuery, FileReq> {
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "查询文件资源统计", description = "查询文件资源统计")
|
||||
@SaCheckPermission("system:file:list")
|
||||
@GetMapping("/statistics")
|
||||
public FileStatisticsResp statistics() {
|
||||
return baseService.statistics();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.feiniaojin.gracefulresponse.api.ExcludeFromGracefulResponse;
|
||||
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 jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.system.model.query.LogQuery;
|
||||
import top.ysoft.admin.system.model.resp.log.LogDetailResp;
|
||||
import top.ysoft.admin.system.model.resp.log.LogResp;
|
||||
import top.ysoft.admin.system.service.LogService;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.query.SortQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
|
||||
/**
|
||||
* 系统日志 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/18 23:55
|
||||
*/
|
||||
@Tag(name = "系统日志 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/system/log")
|
||||
public class LogController {
|
||||
|
||||
private final LogService baseService;
|
||||
|
||||
@Operation(summary = "分页查询列表", description = "分页查询列表")
|
||||
@SaCheckPermission("monitor:log:list")
|
||||
@GetMapping
|
||||
public PageResp<LogResp> page(LogQuery query, @Validated PageQuery pageQuery) {
|
||||
return baseService.page(query, pageQuery);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询详情", description = "查询详情")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("monitor:log:detail")
|
||||
@GetMapping("/{id}")
|
||||
public LogDetailResp get(@PathVariable Long id) {
|
||||
return baseService.get(id);
|
||||
}
|
||||
|
||||
@ExcludeFromGracefulResponse
|
||||
@Operation(summary = "导出登录日志", description = "导出登录日志")
|
||||
@SaCheckPermission("monitor:log:export")
|
||||
@GetMapping("/export/login")
|
||||
public void exportLoginLog(LogQuery query, SortQuery sortQuery, HttpServletResponse response) {
|
||||
baseService.exportLoginLog(query, sortQuery, response);
|
||||
}
|
||||
|
||||
@ExcludeFromGracefulResponse
|
||||
@Operation(summary = "导出操作日志", description = "导出操作日志")
|
||||
@SaCheckPermission("monitor:log:export")
|
||||
@GetMapping("/export/operation")
|
||||
public void exportOperationLog(LogQuery query, SortQuery sortQuery, HttpServletResponse response) {
|
||||
baseService.exportOperationLog(query, sortQuery, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.constant.CacheConstants;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.MenuQuery;
|
||||
import top.ysoft.admin.system.model.req.MenuReq;
|
||||
import top.ysoft.admin.system.model.resp.MenuResp;
|
||||
import top.ysoft.admin.system.service.MenuService;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.constant.StringConstants;
|
||||
import top.continew.starter.core.util.URLUtils;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.annotation.CrudApi;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 菜单管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/15 20:35
|
||||
*/
|
||||
@Tag(name = "菜单管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/menu", api = {Api.TREE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
|
||||
public class MenuController extends BaseController<MenuService, MenuResp, MenuResp, MenuQuery, MenuReq> {
|
||||
|
||||
@Operation(summary = "清除缓存", description = "清除缓存")
|
||||
@SaCheckPermission("system:menu:clearCache")
|
||||
@DeleteMapping("/cache")
|
||||
public void clearCache() {
|
||||
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preHandle(CrudApi crudApi, Object[] args, Method targetMethod, Class<?> targetClass) throws Exception {
|
||||
super.preHandle(crudApi, args, targetMethod, targetClass);
|
||||
Api api = crudApi.value();
|
||||
if (!(Api.ADD.equals(api) || Api.UPDATE.equals(api))) {
|
||||
return;
|
||||
}
|
||||
MenuReq req = (MenuReq)args[0];
|
||||
Boolean isExternal = ObjectUtil.defaultIfNull(req.getIsExternal(), false);
|
||||
String path = req.getPath();
|
||||
ValidationUtils.throwIf(Boolean.TRUE.equals(isExternal) && !URLUtils
|
||||
.isHttpUrl(path), "路由地址格式错误,请以 http:// 或 https:// 开头");
|
||||
// 非外链菜单参数修正
|
||||
if (Boolean.FALSE.equals(isExternal)) {
|
||||
ValidationUtils.throwIf(URLUtils.isHttpUrl(path), "路由地址格式错误");
|
||||
req.setPath(StrUtil.isBlank(path) ? path : StrUtil.prependIfMissing(path, StringConstants.SLASH));
|
||||
req.setName(StrUtil.removePrefix(req.getName(), StringConstants.SLASH));
|
||||
req.setComponent(StrUtil.removePrefix(req.getComponent(), StringConstants.SLASH));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
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.common.context.UserContextHolder;
|
||||
import top.ysoft.admin.system.model.query.MessageQuery;
|
||||
import top.ysoft.admin.system.model.resp.message.MessageResp;
|
||||
import top.ysoft.admin.system.model.resp.message.MessageUnreadResp;
|
||||
import top.ysoft.admin.system.service.MessageService;
|
||||
import top.ysoft.admin.system.service.MessageUserService;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 消息管理 API
|
||||
*
|
||||
* @author Bull-BCLS
|
||||
* @since 2023/10/15 19:05
|
||||
*/
|
||||
@Tag(name = "消息管理 API")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/system/message")
|
||||
public class MessageController {
|
||||
|
||||
private final MessageService baseService;
|
||||
private final MessageUserService messageUserService;
|
||||
|
||||
@Operation(summary = "分页查询列表", description = "分页查询列表")
|
||||
@GetMapping
|
||||
public PageResp<MessageResp> page(MessageQuery query, @Validated PageQuery pageQuery) {
|
||||
query.setUserId(UserContextHolder.getUserId());
|
||||
return baseService.page(query, pageQuery);
|
||||
}
|
||||
|
||||
@Operation(summary = "删除数据", description = "删除数据")
|
||||
@Parameter(name = "ids", description = "ID 列表", example = "1,2", in = ParameterIn.PATH)
|
||||
@DeleteMapping("/{ids}")
|
||||
public void delete(@PathVariable List<Long> ids) {
|
||||
baseService.delete(ids);
|
||||
}
|
||||
|
||||
@Operation(summary = "标记已读", description = "将消息标记为已读状态")
|
||||
@Parameter(name = "ids", description = "消息ID列表", example = "1,2", in = ParameterIn.QUERY)
|
||||
@PatchMapping("/read")
|
||||
public void readMessage(@RequestParam(required = false) List<Long> ids) {
|
||||
messageUserService.readMessage(ids);
|
||||
}
|
||||
|
||||
@Log(ignore = true)
|
||||
@Operation(summary = "查询未读消息数量", description = "查询当前用户的未读消息数量")
|
||||
@Parameter(name = "isDetail", description = "是否查询详情", example = "true", in = ParameterIn.QUERY)
|
||||
@GetMapping("/unread")
|
||||
public MessageUnreadResp countUnreadMessage(@RequestParam(required = false) Boolean detail) {
|
||||
return messageUserService.countUnreadMessageByUserId(UserContextHolder.getUserId(), detail);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.enums.NoticeScopeEnum;
|
||||
import top.ysoft.admin.system.model.query.NoticeQuery;
|
||||
import top.ysoft.admin.system.model.req.NoticeReq;
|
||||
import top.ysoft.admin.system.model.resp.NoticeDetailResp;
|
||||
import top.ysoft.admin.system.model.resp.NoticeResp;
|
||||
import top.ysoft.admin.system.service.NoticeService;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.annotation.CrudApi;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 公告管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/8/20 10:55
|
||||
*/
|
||||
@Tag(name = "公告管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/notice", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
|
||||
public class NoticeController extends BaseController<NoticeService, NoticeResp, NoticeDetailResp, NoticeQuery, NoticeReq> {
|
||||
|
||||
@Override
|
||||
public void preHandle(CrudApi crudApi, Object[] args, Method targetMethod, Class<?> targetClass) throws Exception {
|
||||
super.preHandle(crudApi, args, targetMethod, targetClass);
|
||||
Api api = crudApi.value();
|
||||
if (!(Api.ADD.equals(api) || Api.UPDATE.equals(api))) {
|
||||
return;
|
||||
}
|
||||
NoticeReq req = (NoticeReq)args[0];
|
||||
// 校验生效时间
|
||||
LocalDateTime effectiveTime = req.getEffectiveTime();
|
||||
LocalDateTime terminateTime = req.getTerminateTime();
|
||||
if (null != effectiveTime && null != terminateTime) {
|
||||
ValidationUtils.throwIf(terminateTime.isBefore(effectiveTime), "终止时间必须晚于生效时间");
|
||||
}
|
||||
// 校验通知范围
|
||||
if (NoticeScopeEnum.USER.equals(req.getNoticeScope())) {
|
||||
ValidationUtils.throwIfEmpty(req.getNoticeUsers(), "通知用户不能为空");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.ysoft.admin.system.model.query.OptionQuery;
|
||||
import top.ysoft.admin.system.model.req.OptionReq;
|
||||
import top.ysoft.admin.system.model.req.OptionResetValueReq;
|
||||
import top.ysoft.admin.system.model.resp.OptionResp;
|
||||
import top.ysoft.admin.system.service.OptionService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 参数管理 API
|
||||
*
|
||||
* @author Bull-BCLS
|
||||
* @since 2023/8/26 19:38
|
||||
*/
|
||||
@Tag(name = "参数管理 API")
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/system/option")
|
||||
public class OptionController {
|
||||
|
||||
private final OptionService baseService;
|
||||
|
||||
@Operation(summary = "查询参数列表", description = "查询参数列表")
|
||||
@SaCheckPermission("system:config:list")
|
||||
@GetMapping
|
||||
public List<OptionResp> list(@Validated OptionQuery query) {
|
||||
return baseService.list(query);
|
||||
}
|
||||
|
||||
@Operation(summary = "修改参数", description = "修改参数")
|
||||
@SaCheckPermission("system:config:update")
|
||||
@PutMapping
|
||||
public void update(@Valid @RequestBody List<OptionReq> options) {
|
||||
baseService.update(options);
|
||||
}
|
||||
|
||||
@Operation(summary = "重置参数", description = "重置参数")
|
||||
@SaCheckPermission("system:config:reset")
|
||||
@PatchMapping("/value")
|
||||
public void resetValue(@Validated @RequestBody OptionResetValueReq req) {
|
||||
baseService.resetValue(req);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
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 jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.system.model.query.RoleQuery;
|
||||
import top.ysoft.admin.system.model.query.RoleUserQuery;
|
||||
import top.ysoft.admin.system.model.req.RoleReq;
|
||||
import top.ysoft.admin.system.model.req.RoleUpdatePermissionReq;
|
||||
import top.ysoft.admin.system.model.resp.role.RoleDetailResp;
|
||||
import top.ysoft.admin.system.model.resp.role.RoleResp;
|
||||
import top.ysoft.admin.system.model.resp.role.RoleUserResp;
|
||||
import top.ysoft.admin.system.service.RoleService;
|
||||
import top.ysoft.admin.system.service.UserRoleService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 角色管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/8 23:11
|
||||
*/
|
||||
@Tag(name = "角色管理 API")
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/system/role", api = {Api.LIST, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
|
||||
public class RoleController extends BaseController<RoleService, RoleResp, RoleDetailResp, RoleQuery, RoleReq> {
|
||||
|
||||
private final UserRoleService userRoleService;
|
||||
|
||||
@Operation(summary = "修改权限", description = "修改角色的功能权限")
|
||||
@SaCheckPermission("system:role:updatePermission")
|
||||
@PutMapping("/{id}/permission")
|
||||
public void updatePermission(@PathVariable("id") Long id, @Validated @RequestBody RoleUpdatePermissionReq req) {
|
||||
baseService.updatePermission(id, req);
|
||||
}
|
||||
|
||||
@Operation(summary = "分页查询关联用户", description = "分页查询角色关联的用户列表")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("system:role:list")
|
||||
@GetMapping("/{id}/user")
|
||||
public PageResp<RoleUserResp> pageUser(@PathVariable("id") Long id,
|
||||
@Validated RoleUserQuery query,
|
||||
@Validated PageQuery pageQuery) {
|
||||
query.setRoleId(id);
|
||||
return userRoleService.pageUser(query, pageQuery);
|
||||
}
|
||||
|
||||
@Operation(summary = "分配用户", description = "批量分配角色给用户")
|
||||
@SaCheckPermission("system:role:assign")
|
||||
@PostMapping("/{id}/user")
|
||||
public void assignToUsers(@PathVariable("id") Long id,
|
||||
@Validated @NotEmpty(message = "用户ID列表不能为空") @RequestBody List<Long> userIds) {
|
||||
baseService.assignToUsers(id, userIds);
|
||||
}
|
||||
|
||||
@Operation(summary = "取消分配用户", description = "批量取消分配角色给用户")
|
||||
@SaCheckPermission("system:role:unassign")
|
||||
@DeleteMapping("/user")
|
||||
public void unassignFromUsers(@Validated @NotEmpty(message = "用户列表不能为空") @RequestBody List<Long> userRoleIds) {
|
||||
userRoleService.deleteByIds(userRoleIds);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询关联用户ID", description = "查询角色关联的用户ID列表")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("system:role:list")
|
||||
@GetMapping("/{id}/user/id")
|
||||
public List<Long> listUserId(@PathVariable("id") Long id) {
|
||||
return userRoleService.listUserIdByRoleId(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
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 org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.common.model.req.CommonStatusUpdateReq;
|
||||
import top.ysoft.admin.system.model.query.StorageQuery;
|
||||
import top.ysoft.admin.system.model.req.StorageReq;
|
||||
import top.ysoft.admin.system.model.resp.StorageResp;
|
||||
import top.ysoft.admin.system.service.StorageService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
/**
|
||||
* 存储管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/12/26 22:09
|
||||
*/
|
||||
@Tag(name = "存储管理 API")
|
||||
@Validated
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/system/storage", api = {Api.LIST, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
|
||||
public class StorageController extends BaseController<StorageService, StorageResp, StorageResp, StorageQuery, StorageReq> {
|
||||
|
||||
@Operation(summary = "修改状态", description = "修改状态")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("system:storage:updateStatus")
|
||||
@PutMapping({"/{id}/status"})
|
||||
public void updateStatus(@Validated @RequestBody CommonStatusUpdateReq req, @PathVariable("id") Long id) {
|
||||
baseService.updateStatus(req, id);
|
||||
}
|
||||
|
||||
@Operation(summary = "设为默认存储", description = "设为默认存储")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("system:storage:setDefault")
|
||||
@PutMapping({"/{id}/default"})
|
||||
public void setDefault(@PathVariable("id") Long id) {
|
||||
baseService.setDefault(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import com.xkcoding.justauth.AuthRequestFactory;
|
||||
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 jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.ysoft.admin.common.constant.CacheConstants;
|
||||
import top.ysoft.admin.common.context.UserContextHolder;
|
||||
import top.ysoft.admin.common.util.SecureUtils;
|
||||
import top.ysoft.admin.system.enums.SocialSourceEnum;
|
||||
import top.ysoft.admin.system.model.entity.UserSocialDO;
|
||||
import top.ysoft.admin.system.model.req.user.UserBasicInfoUpdateReq;
|
||||
import top.ysoft.admin.system.model.req.user.UserEmailUpdateRequest;
|
||||
import top.ysoft.admin.system.model.req.user.UserPasswordUpdateReq;
|
||||
import top.ysoft.admin.system.model.req.user.UserPhoneUpdateReq;
|
||||
import top.ysoft.admin.system.model.resp.AvatarResp;
|
||||
import top.ysoft.admin.system.model.resp.user.UserSocialBindResp;
|
||||
import top.ysoft.admin.system.service.UserService;
|
||||
import top.ysoft.admin.system.service.UserSocialService;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.util.ExceptionUtils;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 个人中心 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/1/2 11:41
|
||||
*/
|
||||
@Tag(name = "个人中心 API")
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/system/user")
|
||||
public class UserCenterController {
|
||||
|
||||
private static final String DECRYPT_FAILED = "当前密码解密失败";
|
||||
private static final String CAPTCHA_EXPIRED = "验证码已失效";
|
||||
private final UserService userService;
|
||||
private final UserSocialService userSocialService;
|
||||
private final AuthRequestFactory authRequestFactory;
|
||||
|
||||
@Operation(summary = "修改头像", description = "用户修改个人头像")
|
||||
@PostMapping("/avatar")
|
||||
public AvatarResp updateAvatar(@NotNull(message = "头像不能为空") MultipartFile avatarFile) throws IOException {
|
||||
ValidationUtils.throwIf(avatarFile::isEmpty, "头像不能为空");
|
||||
String newAvatar = userService.updateAvatar(avatarFile, UserContextHolder.getUserId());
|
||||
return AvatarResp.builder().avatar(newAvatar).build();
|
||||
}
|
||||
|
||||
@Operation(summary = "修改基础信息", description = "修改用户基础信息")
|
||||
@PatchMapping("/basic/info")
|
||||
public void updateBasicInfo(@Validated @RequestBody UserBasicInfoUpdateReq req) {
|
||||
userService.updateBasicInfo(req, UserContextHolder.getUserId());
|
||||
}
|
||||
|
||||
@Operation(summary = "修改密码", description = "修改用户登录密码")
|
||||
@PatchMapping("/password")
|
||||
public void updatePassword(@Validated @RequestBody UserPasswordUpdateReq updateReq) {
|
||||
String rawOldPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq
|
||||
.getOldPassword()));
|
||||
ValidationUtils.throwIfNull(rawOldPassword, DECRYPT_FAILED);
|
||||
String rawNewPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq
|
||||
.getNewPassword()));
|
||||
ValidationUtils.throwIfNull(rawNewPassword, "新密码解密失败");
|
||||
userService.updatePassword(rawOldPassword, rawNewPassword, UserContextHolder.getUserId());
|
||||
}
|
||||
|
||||
@Operation(summary = "修改手机号", description = "修改手机号")
|
||||
@PatchMapping("/phone")
|
||||
public void updatePhone(@Validated @RequestBody UserPhoneUpdateReq updateReq) {
|
||||
String rawOldPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq
|
||||
.getOldPassword()));
|
||||
ValidationUtils.throwIfBlank(rawOldPassword, DECRYPT_FAILED);
|
||||
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + updateReq.getPhone();
|
||||
String captcha = RedisUtils.get(captchaKey);
|
||||
ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED);
|
||||
ValidationUtils.throwIfNotEqualIgnoreCase(updateReq.getCaptcha(), captcha, "验证码错误");
|
||||
RedisUtils.delete(captchaKey);
|
||||
userService.updatePhone(updateReq.getPhone(), rawOldPassword, UserContextHolder.getUserId());
|
||||
}
|
||||
|
||||
@Operation(summary = "修改邮箱", description = "修改用户邮箱")
|
||||
@PatchMapping("/email")
|
||||
public void updateEmail(@Validated @RequestBody UserEmailUpdateRequest updateReq) {
|
||||
String rawOldPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq
|
||||
.getOldPassword()));
|
||||
ValidationUtils.throwIfBlank(rawOldPassword, DECRYPT_FAILED);
|
||||
String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + updateReq.getEmail();
|
||||
String captcha = RedisUtils.get(captchaKey);
|
||||
ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED);
|
||||
ValidationUtils.throwIfNotEqualIgnoreCase(updateReq.getCaptcha(), captcha, "验证码错误");
|
||||
RedisUtils.delete(captchaKey);
|
||||
userService.updateEmail(updateReq.getEmail(), rawOldPassword, UserContextHolder.getUserId());
|
||||
}
|
||||
|
||||
@Operation(summary = "查询绑定的三方账号", description = "查询绑定的三方账号")
|
||||
@GetMapping("/social")
|
||||
public List<UserSocialBindResp> listSocialBind() {
|
||||
List<UserSocialDO> userSocialList = userSocialService.listByUserId(UserContextHolder.getUserId());
|
||||
return userSocialList.stream().map(userSocial -> {
|
||||
String source = userSocial.getSource();
|
||||
UserSocialBindResp userSocialBind = new UserSocialBindResp();
|
||||
userSocialBind.setSource(source);
|
||||
userSocialBind.setDescription(SocialSourceEnum.valueOf(source).getDescription());
|
||||
return userSocialBind;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@Operation(summary = "绑定三方账号", description = "绑定三方账号")
|
||||
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
|
||||
@PostMapping("/social/{source}")
|
||||
public void bindSocial(@PathVariable String source, @RequestBody AuthCallback callback) {
|
||||
AuthRequest authRequest = authRequestFactory.get(source);
|
||||
AuthResponse<AuthUser> response = authRequest.login(callback);
|
||||
ValidationUtils.throwIf(!response.ok(), response.getMsg());
|
||||
AuthUser authUser = response.getData();
|
||||
userSocialService.bind(authUser, UserContextHolder.getUserId());
|
||||
}
|
||||
|
||||
@Operation(summary = "解绑三方账号", description = "解绑三方账号")
|
||||
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
|
||||
@DeleteMapping("/social/{source}")
|
||||
public void unbindSocial(@PathVariable String source) {
|
||||
userSocialService.deleteBySourceAndUserId(source, UserContextHolder.getUserId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
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 jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.ysoft.admin.common.controller.BaseController;
|
||||
import top.ysoft.admin.common.constant.RegexConstants;
|
||||
import top.ysoft.admin.common.util.SecureUtils;
|
||||
import top.ysoft.admin.system.model.query.UserQuery;
|
||||
import top.ysoft.admin.system.model.req.user.UserImportReq;
|
||||
import top.ysoft.admin.system.model.req.user.UserPasswordResetReq;
|
||||
import top.ysoft.admin.system.model.req.user.UserReq;
|
||||
import top.ysoft.admin.system.model.req.user.UserRoleUpdateReq;
|
||||
import top.ysoft.admin.system.model.resp.user.UserDetailResp;
|
||||
import top.ysoft.admin.system.model.resp.user.UserImportParseResp;
|
||||
import top.ysoft.admin.system.model.resp.user.UserImportResp;
|
||||
import top.ysoft.admin.system.model.resp.user.UserResp;
|
||||
import top.ysoft.admin.system.service.UserService;
|
||||
import top.continew.starter.core.util.ExceptionUtils;
|
||||
import top.continew.starter.core.validation.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.extension.crud.model.resp.BaseIdResp;
|
||||
import top.continew.starter.extension.crud.validation.CrudValidationGroup;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 用户管理 API
|
||||
*
|
||||
* @author Charles7c
|
||||
* @since 2023/2/20 21:00
|
||||
*/
|
||||
@Tag(name = "用户管理 API")
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@CrudRequestMapping(value = "/system/user", api = {Api.PAGE, Api.LIST, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
|
||||
Api.EXPORT})
|
||||
public class UserController extends BaseController<UserService, UserResp, UserDetailResp, UserQuery, UserReq> {
|
||||
|
||||
@Override
|
||||
@Operation(summary = "新增数据", description = "新增数据")
|
||||
public BaseIdResp<Long> add(@Validated(CrudValidationGroup.Add.class) @RequestBody UserReq req) {
|
||||
String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getPassword()));
|
||||
ValidationUtils.throwIfNull(rawPassword, "密码解密失败");
|
||||
ValidationUtils.throwIf(!ReUtil
|
||||
.isMatch(RegexConstants.PASSWORD, rawPassword), "密码长度为 8-32 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字");
|
||||
req.setPassword(rawPassword);
|
||||
return super.add(req);
|
||||
}
|
||||
|
||||
@Operation(summary = "下载导入模板", description = "下载导入模板")
|
||||
@SaCheckPermission("system:user:import")
|
||||
@GetMapping(value = "/import/template", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public void downloadImportTemplate(HttpServletResponse response) throws IOException {
|
||||
baseService.downloadImportTemplate(response);
|
||||
}
|
||||
|
||||
@Operation(summary = "解析导入数据", description = "解析导入数据")
|
||||
@SaCheckPermission("system:user:import")
|
||||
@PostMapping("/import/parse")
|
||||
public UserImportParseResp parseImport(@NotNull(message = "文件不能为空") MultipartFile file) {
|
||||
ValidationUtils.throwIf(file::isEmpty, "文件不能为空");
|
||||
return baseService.parseImport(file);
|
||||
}
|
||||
|
||||
@Operation(summary = "导入数据", description = "导入数据")
|
||||
@SaCheckPermission("system:user:import")
|
||||
@PostMapping(value = "/import")
|
||||
public UserImportResp importUser(@Validated @RequestBody UserImportReq req) {
|
||||
return baseService.importUser(req);
|
||||
}
|
||||
|
||||
@Operation(summary = "重置密码", description = "重置用户登录密码")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("system:user:resetPwd")
|
||||
@PatchMapping("/{id}/password")
|
||||
public void resetPassword(@Validated @RequestBody UserPasswordResetReq req, @PathVariable Long id) {
|
||||
String rawNewPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getNewPassword()));
|
||||
ValidationUtils.throwIfNull(rawNewPassword, "新密码解密失败");
|
||||
ValidationUtils.throwIf(!ReUtil
|
||||
.isMatch(RegexConstants.PASSWORD, rawNewPassword), "密码长度为 8-32 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字");
|
||||
req.setNewPassword(rawNewPassword);
|
||||
baseService.resetPassword(req, id);
|
||||
}
|
||||
|
||||
@Operation(summary = "分配角色", description = "为用户新增或移除角色")
|
||||
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
|
||||
@SaCheckPermission("system:user:updateRole")
|
||||
@PatchMapping("/{id}/role")
|
||||
public void updateRole(@Validated @RequestBody UserRoleUpdateReq updateReq, @PathVariable Long id) {
|
||||
baseService.updateRole(updateReq, id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package top.ysoft.admin.controller.system;
|
||||
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import top.ysoft.admin.common.util.PictureUtils;
|
||||
// import top.ysoft.admin.controller.file.SysFileController;
|
||||
// import top.ysoft.admin.file.domain.SysFile;
|
||||
import top.ysoft.admin.system.model.resp.file.FileUploadResp;
|
||||
import top.ysoft.admin.system.service.FileService;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/test")
|
||||
public class zctest {
|
||||
|
||||
// @Autowired
|
||||
// private SysFileController fileController;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@PostMapping()
|
||||
public FileUploadResp test() {
|
||||
String urls = "http://bpic.588ku.com/element_origin_min_pic/19/03/15/75076c485081d15ed9c224ad3e4ce4a1.jpg";
|
||||
MultipartFile file = PictureUtils.createMultipartFile(urls, "zctest11111.jpg");
|
||||
// SysFile sysFile = fileController.uploadMinio(file, "zctest11111");
|
||||
// return sysFile;
|
||||
|
||||
FileInfo fileInfo = fileService.upload(file, "zctest", "minio", false, false);
|
||||
return FileUploadResp.builder()
|
||||
.id(fileInfo.getId())
|
||||
.url(fileInfo.getUrl())
|
||||
.thUrl(fileInfo.getThUrl())
|
||||
.metadata(fileInfo.getMetadata())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package top.ysoft.admin.controller.yfApi;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.feiniaojin.gracefulresponse.api.ExcludeFromGracefulResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.starter.log.annotation.Log;
|
||||
import top.ysoft.admin.yfApi.domain.BackInfo;
|
||||
import top.ysoft.admin.yfApi.domain.BackResult;
|
||||
import top.ysoft.admin.yfApi.domain.HeartInfo;
|
||||
import top.ysoft.admin.yfApi.service.IYFListenService;
|
||||
|
||||
/**
|
||||
* 宇泛人脸设备回调
|
||||
*
|
||||
* @author zc
|
||||
* @since 2025/03/21 18:10
|
||||
*/
|
||||
@Tag(name = "宇泛人脸设备回调 API")
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/sdk")
|
||||
public class YFListenController {
|
||||
|
||||
private final IYFListenService iyfListenService;
|
||||
|
||||
@Log(ignore = true)
|
||||
@PostMapping("/backUrlHeart")
|
||||
public void heart(HeartInfo info) {
|
||||
iyfListenService.heart(info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 宇泛人脸设备回调地址
|
||||
*
|
||||
* @return 回调信息
|
||||
*/
|
||||
@Log(ignore = true)
|
||||
@ExcludeFromGracefulResponse
|
||||
@PostMapping("/backUrl")
|
||||
public BackResult backUrl(@RequestBody BackInfo info) {
|
||||
log.info("宇泛人脸设备识别回调:{}", JSON.toJSONString(info));
|
||||
if (!StrUtil.equals(info.getPersonId(), "STRANGERBABY")) {
|
||||
//异步处理接收到的人员信息
|
||||
ThreadUtil.execAsync(() -> {
|
||||
iyfListenService.processPeopleRecord(info);
|
||||
});
|
||||
}
|
||||
return new BackResult(1, true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user