mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-02-06 18:45:42 +08:00
【v3.8.0合并】Merge remote-tracking branch 'origin/springboot3' into springboot3_sas
# Conflicts:
# jeecg-boot/jeecg-boot-base-core/pom.xml
# jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/encryption/AesEncryptUtil.java
# jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/firewall/interceptor/LowCodeModeInterceptor.java
# jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
# jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDataSourceController.java
# jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartPermissionController.java
# jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartRoleController.java
# jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysRoleIndexController.java
# jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysTableWhiteListController.java
# jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysTenantPackServiceImpl.java
# jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/resources/jeecg/code-template-online/default/tree/java/${bussiPackage}/${entityPackage}/controller/${entityName}Controller.javai
# jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
# jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml
# jeecg-boot/jeecg-module-system/jeecg-system-start/src/test/java/org/jeecg/modules/system/test/InsertDemoTest.java
# jeecg-boot/pom.xml
# jeecgboot-vue3/pnpm-lock.yaml
This commit is contained in:
@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-module-system</artifactId>
|
||||
<version>3.7.3</version>
|
||||
<version>3.8.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -4,14 +4,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.constant.SymbolConstant;
|
||||
import org.jeecg.common.exception.JeecgSqlInjectionException;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.common.util.sqlparse.JSqlParserUtils;
|
||||
import org.jeecg.common.util.sqlparse.vo.SelectSqlInfo;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler;
|
||||
import org.jeecg.config.firewall.interceptor.LowCodeModeInterceptor;
|
||||
import org.jeecg.modules.system.entity.SysTableWhiteList;
|
||||
import org.jeecg.modules.system.security.DictQueryBlackListHandler;
|
||||
import org.jeecg.modules.system.service.ISysTableWhiteListService;
|
||||
import org.jeecgframework.minidao.sqlparser.impl.vo.SelectSqlInfo;
|
||||
import org.jeecgframework.minidao.util.MiniDaoUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -65,7 +65,7 @@ public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler
|
||||
public boolean isPassBySql(String sql) {
|
||||
Map<String, SelectSqlInfo> parsedMap = null;
|
||||
try {
|
||||
parsedMap = JSqlParserUtils.parseAllSelectTable(sql);
|
||||
parsedMap = MiniDaoUtil.parseAllSelectTable(sql);
|
||||
} catch (Exception e) {
|
||||
log.warn("校验sql语句,解析报错:{}", e.getMessage());
|
||||
}
|
||||
@ -127,7 +127,7 @@ public class DictTableWhiteListHandlerImpl implements IDictTableWhiteListHandler
|
||||
log.info("字典拼接的查询SQL:{}", sql);
|
||||
try {
|
||||
// 进行SQL解析
|
||||
JSqlParserUtils.parseSelectSqlInfo(sql);
|
||||
MiniDaoUtil.parseSelectSqlInfo(sql);
|
||||
} catch (Exception e) {
|
||||
// 如果SQL解析失败,则通过字段名和表名进行校验
|
||||
return checkWhiteList(tableName, new HashSet<>(Arrays.asList(fields)));
|
||||
|
||||
@ -26,8 +26,11 @@ public class CodeTemplateInitListener implements ApplicationListener<Application
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
try {
|
||||
log.info(" Init Code Generate Template [ 检测如果是JAR启动环境,Copy模板到config目录 ] ");
|
||||
long startTime = System.currentTimeMillis(); // 记录开始时间
|
||||
log.info(" Init Code Generate Template [ 检测如果是JAR启动,Copy模板到config目录 ] ");
|
||||
this.initJarConfigCodeGeneratorTemplate();
|
||||
long endTime = System.currentTimeMillis(); // 记录结束时间
|
||||
log.info(" Init Code Generate Template completed in " + (endTime - startTime) + " ms"); // 计算并记录耗时
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package org.jeecg.config.init;
|
||||
|
||||
import io.undertow.server.DefaultByteBufferPool;
|
||||
import io.undertow.server.handlers.BlockingHandler;
|
||||
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
|
||||
import org.jeecg.modules.monitor.actuator.undertow.CustomUndertowMetricsHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Undertow配置
|
||||
*
|
||||
* 解决启动提示: WARN io.undertow.websockets.jsr:68 - UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used
|
||||
*/
|
||||
@Configuration
|
||||
public class UndertowConfiguration implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
|
||||
|
||||
/**
|
||||
* 自定义undertow监控指标工具类
|
||||
* for [QQYUN-11902]tomcat 替换undertow 这里的功能还没修改
|
||||
*/
|
||||
@Autowired
|
||||
private CustomUndertowMetricsHandler customUndertowMetricsHandler;
|
||||
|
||||
@Override
|
||||
public void customize(UndertowServletWebServerFactory factory) {
|
||||
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
|
||||
|
||||
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
|
||||
|
||||
// 设置合理的参数
|
||||
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(true, 8192));
|
||||
|
||||
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
|
||||
|
||||
// 添加自定义 监控 handler
|
||||
deploymentInfo.addInitialHandlerChainWrapper(next -> new BlockingHandler(customUndertowMetricsHandler.wrap(next)));
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
package org.jeecg.modules.monitor.actuator.undertow;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.undertow.server.HttpHandler;
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.server.session.*;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
/**
|
||||
* 自定义undertow监控指标工具类
|
||||
* for [QQYUN-11902]tomcat 替换undertow 这里的功能还没修改
|
||||
* @author chenrui
|
||||
* @date 2025/4/8 19:06
|
||||
*/
|
||||
@Component("jeecgCustomUndertowMetricsHandler")
|
||||
public class CustomUndertowMetricsHandler {
|
||||
|
||||
// 用于统计已创建的 session 数量
|
||||
private final LongAdder sessionsCreated = new LongAdder();
|
||||
|
||||
// 用于统计已销毁的 session 数量
|
||||
private final LongAdder sessionsExpired = new LongAdder();
|
||||
|
||||
// 当前活跃的 session 数量
|
||||
private final AtomicInteger activeSessions = new AtomicInteger();
|
||||
|
||||
// 历史最大活跃 session 数
|
||||
private final AtomicInteger maxActiveSessions = new AtomicInteger();
|
||||
|
||||
// Undertow 内存 session 管理器(用于创建与管理 session)
|
||||
private final InMemorySessionManager sessionManager = new InMemorySessionManager("undertow-session-manager");
|
||||
|
||||
// 使用 Cookie 存储 session ID
|
||||
private final SessionConfig sessionConfig = new SessionCookieConfig();
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param meterRegistry
|
||||
* @author chenrui
|
||||
* @date 2025/4/8 19:07
|
||||
*/
|
||||
public CustomUndertowMetricsHandler(MeterRegistry meterRegistry) {
|
||||
// 注册 Micrometer 指标
|
||||
meterRegistry.gauge("undertow.sessions.created", sessionsCreated, LongAdder::longValue);
|
||||
meterRegistry.gauge("undertow.sessions.expired", sessionsExpired, LongAdder::longValue);
|
||||
meterRegistry.gauge("undertow.sessions.active.current", activeSessions, AtomicInteger::get);
|
||||
meterRegistry.gauge("undertow.sessions.active.max", maxActiveSessions, AtomicInteger::get);
|
||||
|
||||
// 添加 session 生命周期监听器,统计 session 创建与销毁
|
||||
sessionManager.registerSessionListener(new SessionListener() {
|
||||
@Override
|
||||
public void sessionCreated(Session session, HttpServerExchange exchange) {
|
||||
sessionsCreated.increment();
|
||||
int now = activeSessions.incrementAndGet();
|
||||
maxActiveSessions.getAndUpdate(max -> Math.max(max, now));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
|
||||
sessionsExpired.increment();
|
||||
activeSessions.decrementAndGet();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 包装 Undertow 的 HttpHandler,实现 session 自动创建逻辑
|
||||
* @param next
|
||||
* @return
|
||||
* @author chenrui
|
||||
* @date 2025/4/8 19:07
|
||||
*/
|
||||
public HttpHandler wrap(HttpHandler next) {
|
||||
return exchange -> {
|
||||
// 获取当前 session,如果不存在则创建
|
||||
Session session = sessionManager.getSession(exchange, sessionConfig);
|
||||
if (session == null) {
|
||||
try {
|
||||
sessionManager.createSession(exchange, sessionConfig);
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
|
||||
// 执行下一个 Handler
|
||||
next.handleRequest(exchange);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
//package org.jeecg.modules.ngalain.aop;
|
||||
//
|
||||
//import javax.servlet.http.HttpServletRequest;
|
||||
//import jakarta.servlet.http.HttpServletRequest;
|
||||
//
|
||||
//import org.aspectj.lang.ProceedingJoinPoint;
|
||||
//import org.aspectj.lang.annotation.Around;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
//import java.util.List;
|
||||
//import java.util.Map;
|
||||
//
|
||||
//import javax.servlet.http.HttpServletRequest;
|
||||
//import jakarta.servlet.http.HttpServletRequest;
|
||||
//
|
||||
//import org.apache.shiro.SecurityUtils;
|
||||
//import org.jeecg.common.api.vo.Result;
|
||||
|
||||
@ -0,0 +1,112 @@
|
||||
package org.jeecg.modules.openapi.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiAuth;
|
||||
import org.jeecg.modules.openapi.generator.AKSKGenerator;
|
||||
import org.jeecg.modules.openapi.service.OpenApiAuthService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:54
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/openapi/auth")
|
||||
public class OpenApiAuthController extends JeecgController<OpenApiAuth, OpenApiAuthService> {
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param openApiAuth
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/list")
|
||||
public Result<?> queryPageList(OpenApiAuth openApiAuth, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
|
||||
QueryWrapper<OpenApiAuth> queryWrapper = QueryGenerator.initQueryWrapper(openApiAuth, req.getParameterMap());
|
||||
Page<OpenApiAuth> page = new Page<>(pageNo, pageSize);
|
||||
IPage<OpenApiAuth> pageList = service.page(page, queryWrapper);
|
||||
return Result.ok(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param openApiAuth
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/add")
|
||||
public Result<?> add(@RequestBody OpenApiAuth openApiAuth) {
|
||||
service.save(openApiAuth);
|
||||
return Result.ok("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param openApiAuth
|
||||
* @return
|
||||
*/
|
||||
@PutMapping(value = "/edit")
|
||||
public Result<?> edit(@RequestBody OpenApiAuth openApiAuth) {
|
||||
service.updateById(openApiAuth);
|
||||
return Result.ok("修改成功!");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
service.removeById(id);
|
||||
return Result.ok("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
|
||||
this.service.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.ok("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
OpenApiAuth openApiAuth = service.getById(id);
|
||||
return Result.ok(openApiAuth);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成AKSK
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("genAKSK")
|
||||
public Result<String[]> genAKSK() {
|
||||
return Result.ok(AKSKGenerator.genAKSKPair());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,415 @@
|
||||
package org.jeecg.modules.openapi.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.RestUtil;
|
||||
import org.jeecg.modules.openapi.entity.OpenApi;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiAuth;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiHeader;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiParam;
|
||||
import org.jeecg.modules.openapi.generator.PathGenerator;
|
||||
import org.jeecg.modules.openapi.service.OpenApiAuthService;
|
||||
import org.jeecg.modules.openapi.service.OpenApiService;
|
||||
import org.jeecg.modules.openapi.swagger.*;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:11
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/openapi")
|
||||
public class OpenApiController extends JeecgController<OpenApi, OpenApiService> {
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
@Autowired
|
||||
private ISysUserService sysUserService;
|
||||
@Autowired
|
||||
private OpenApiAuthService openApiAuthService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param openApi
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/list")
|
||||
public Result<?> queryPageList(OpenApi openApi, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
|
||||
QueryWrapper<OpenApi> queryWrapper = QueryGenerator.initQueryWrapper(openApi, req.getParameterMap());
|
||||
Page<OpenApi> page = new Page<>(pageNo, pageSize);
|
||||
IPage<OpenApi> pageList = service.page(page, queryWrapper);
|
||||
return Result.ok(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param openApi
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/add")
|
||||
public Result<?> add(@RequestBody OpenApi openApi) {
|
||||
service.save(openApi);
|
||||
return Result.ok("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param openApi
|
||||
* @return
|
||||
*/
|
||||
@PutMapping(value = "/edit")
|
||||
public Result<?> edit(@RequestBody OpenApi openApi) {
|
||||
service.updateById(openApi);
|
||||
return Result.ok("修改成功!");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
service.removeById(id);
|
||||
return Result.ok("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
|
||||
this.service.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.ok("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
OpenApi OpenApi = service.getById(id);
|
||||
return Result.ok(OpenApi);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接口调用
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/call/{path}", method = {RequestMethod.GET,RequestMethod.POST})
|
||||
public Result<?> call(@PathVariable String path, @RequestBody(required = false) String json, HttpServletRequest request) {
|
||||
OpenApi openApi = service.findByPath(path);
|
||||
if (Objects.isNull(openApi)) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("code", 404);
|
||||
result.put("data", null);
|
||||
return Result.error("失败", result);
|
||||
}
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
if (StrUtil.isNotEmpty(openApi.getHeadersJson())) {
|
||||
List<OpenApiHeader> headers = JSON.parseArray(openApi.getHeadersJson(),OpenApiHeader.class);
|
||||
if (headers.size()>0) {
|
||||
for (OpenApiHeader header : headers) {
|
||||
httpHeaders.put(header.getHeaderKey(), Lists.newArrayList(request.getHeader(header.getHeaderKey())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String url = openApi.getOriginUrl();
|
||||
String method = openApi.getRequestMethod();
|
||||
String appkey = request.getHeader("appkey");
|
||||
OpenApiAuth openApiAuth = openApiAuthService.getByAppkey(appkey);
|
||||
SysUser systemUser = sysUserService.getById(openApiAuth.getSystemUserId());
|
||||
String token = this.getToken(systemUser.getUsername(), systemUser.getPassword());
|
||||
httpHeaders.put("X-Access-Token", Lists.newArrayList(token));
|
||||
httpHeaders.put("Content-Type",Lists.newArrayList("application/json"));
|
||||
HttpEntity<String> httpEntity = new HttpEntity<>(json, httpHeaders);
|
||||
url = RestUtil.getBaseUrl() + url;
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
|
||||
if (HttpMethod.GET.matches(method)
|
||||
|| HttpMethod.DELETE.matches(method)
|
||||
|| HttpMethod.OPTIONS.matches(method)
|
||||
|| HttpMethod.TRACE.matches(method)) {
|
||||
//拼接参数
|
||||
if (!request.getParameterMap().isEmpty()) {
|
||||
if (StrUtil.isNotEmpty(openApi.getParamsJson())) {
|
||||
List<OpenApiParam> params = JSON.parseArray(openApi.getParamsJson(),OpenApiParam.class);
|
||||
if (params.size()>0) {
|
||||
Map<String, OpenApiParam> openApiParamMap = params.stream().collect(Collectors.toMap(p -> p.getParamKey(), p -> p, (e, r) -> e));
|
||||
request.getParameterMap().forEach((k, v) -> {
|
||||
OpenApiParam openApiParam = openApiParamMap.get(k);
|
||||
if (Objects.nonNull(openApiParam)) {
|
||||
if(v==null&&StrUtil.isNotEmpty(openApiParam.getDefaultValue())){
|
||||
builder.queryParam(openApiParam.getParamKey(), openApiParam.getDefaultValue());
|
||||
}
|
||||
if (v!=null){
|
||||
builder.queryParam(openApiParam.getParamKey(), v);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
URI targetUrl = builder.build().encode().toUri();
|
||||
return restTemplate.exchange(targetUrl.toString(), Objects.requireNonNull(HttpMethod.resolve(method)), httpEntity, Result.class, request.getParameterMap()).getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成接口访问令牌 Token
|
||||
*
|
||||
* @param USERNAME
|
||||
* @param PASSWORD
|
||||
* @return
|
||||
*/
|
||||
private String getToken(String USERNAME, String PASSWORD) {
|
||||
String token = JwtUtil.sign(USERNAME, PASSWORD);
|
||||
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
|
||||
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, 60);
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/json")
|
||||
public SwaggerModel swaggerModel() {
|
||||
|
||||
SwaggerModel swaggerModel = new SwaggerModel();
|
||||
swaggerModel.setSwagger("2.0");
|
||||
swaggerModel.setInfo(swaggerInfo());
|
||||
swaggerModel.setHost("jeecg.com");
|
||||
swaggerModel.setBasePath("/jeecg-boot");
|
||||
swaggerModel.setSchemes(Lists.newArrayList("http", "https"));
|
||||
|
||||
SwaggerTag swaggerTag = new SwaggerTag();
|
||||
swaggerTag.setName("openapi");
|
||||
swaggerModel.setTags(Lists.newArrayList(swaggerTag));
|
||||
|
||||
pathsAndDefinitions(swaggerModel);
|
||||
|
||||
return swaggerModel;
|
||||
}
|
||||
|
||||
private void pathsAndDefinitions(SwaggerModel swaggerModel) {
|
||||
Map<String, Map<String, SwaggerOperation>> paths = new HashMap<>();
|
||||
Map<String, SwaggerDefinition> definitions = new HashMap<>();
|
||||
List<OpenApi> openapis = service.list();
|
||||
for (OpenApi openApi : openapis) {
|
||||
Map<String, SwaggerOperation> operations = new HashMap<>();
|
||||
SwaggerOperation operation = new SwaggerOperation();
|
||||
operation.setTags(Lists.newArrayList("openapi"));
|
||||
operation.setSummary(openApi.getName());
|
||||
operation.setDescription(openApi.getName());
|
||||
operation.setOperationId(openApi.getRequestUrl()+"Using"+openApi.getRequestMethod());
|
||||
operation.setProduces(Lists.newArrayList("application/json"));
|
||||
parameters(operation, openApi);
|
||||
|
||||
// body入参
|
||||
if (StringUtils.hasText(openApi.getBody())) {
|
||||
SwaggerDefinition definition = new SwaggerDefinition();
|
||||
definition.setType("object");
|
||||
Map<String, SwaggerDefinitionProperties> definitionProperties = new HashMap<>();
|
||||
definition.setProperties(definitionProperties);
|
||||
if (openApi.getBody()!=null){
|
||||
JSONObject jsonObject = JSONObject.parseObject(openApi.getBody());
|
||||
if (jsonObject.size()>0){
|
||||
for (Map.Entry<String, Object> properties : jsonObject.entrySet()) {
|
||||
SwaggerDefinitionProperties swaggerDefinitionProperties = new SwaggerDefinitionProperties();
|
||||
swaggerDefinitionProperties.setType("string");
|
||||
swaggerDefinitionProperties.setDescription(properties.getValue()+"");
|
||||
definitionProperties.put(properties.getKey(), swaggerDefinitionProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
// body的definition构建完成
|
||||
definitions.put(openApi.getRequestUrl()+"Using"+openApi.getRequestMethod()+"body", definition);
|
||||
|
||||
SwaggerOperationParameter bodyParameter = new SwaggerOperationParameter();
|
||||
bodyParameter.setDescription(openApi.getName() + " body");
|
||||
bodyParameter.setIn("body");
|
||||
bodyParameter.setName(openApi.getName() + " body");
|
||||
bodyParameter.setRequired(true);
|
||||
|
||||
Map<String, String> bodySchema = new HashMap<>();
|
||||
bodySchema.put("$ref", "#/definitions/" + openApi.getRequestUrl()+"Using"+openApi.getRequestMethod()+"body");
|
||||
bodyParameter.setSchema(bodySchema);
|
||||
|
||||
// 构建参数构建完成
|
||||
operation.getParameters().add(bodyParameter);
|
||||
|
||||
}
|
||||
|
||||
// 响应
|
||||
Map<String, SwaggerOperationResponse> responses = new HashMap<>();
|
||||
SwaggerOperationResponse resp200 = new SwaggerOperationResponse();
|
||||
resp200.setDescription("OK");
|
||||
Map<String, String> respSchema = new HashMap<>();
|
||||
respSchema.put("$ref", "#/definitions/OpenApiResult");
|
||||
resp200.setSchema(respSchema);
|
||||
|
||||
responses.put("200", resp200);
|
||||
|
||||
Map<String, String> emptySchema = new HashMap<>();
|
||||
SwaggerOperationResponse resp201 = new SwaggerOperationResponse();
|
||||
resp201.setDescription("Created");
|
||||
resp201.setSchema(emptySchema);
|
||||
responses.put("201", resp201);
|
||||
SwaggerOperationResponse resp401 = new SwaggerOperationResponse();
|
||||
resp401.setDescription("Unauthorized");
|
||||
resp401.setSchema(emptySchema);
|
||||
responses.put("401", resp401);
|
||||
SwaggerOperationResponse resp403 = new SwaggerOperationResponse();
|
||||
resp403.setDescription("Forbidden");
|
||||
resp403.setSchema(emptySchema);
|
||||
responses.put("403", resp403);
|
||||
SwaggerOperationResponse resp404 = new SwaggerOperationResponse();
|
||||
resp404.setDescription("Not Found");
|
||||
resp404.setSchema(emptySchema);
|
||||
responses.put("404", resp404);
|
||||
|
||||
// 构建响应definition
|
||||
SwaggerDefinition respDefinition = new SwaggerDefinition();
|
||||
respDefinition.setType("object");
|
||||
|
||||
Map<String, SwaggerDefinitionProperties> definitionProperties = new HashMap<>();
|
||||
respDefinition.setProperties(definitionProperties);
|
||||
|
||||
SwaggerDefinitionProperties codeProperties = new SwaggerDefinitionProperties();
|
||||
codeProperties.setType("integer");
|
||||
codeProperties.setDescription("返回代码");
|
||||
definitionProperties.put("code", codeProperties);
|
||||
SwaggerDefinitionProperties messageProperties = new SwaggerDefinitionProperties();
|
||||
messageProperties.setType("string");
|
||||
messageProperties.setDescription("返回处理消息");
|
||||
definitionProperties.put("message", messageProperties);
|
||||
SwaggerDefinitionProperties resultProperties = new SwaggerDefinitionProperties();
|
||||
resultProperties.setType("object");
|
||||
resultProperties.setDescription("返回数据对象");
|
||||
definitionProperties.put("result", resultProperties);
|
||||
SwaggerDefinitionProperties successProperties = new SwaggerDefinitionProperties();
|
||||
successProperties.setType("boolean");
|
||||
successProperties.setDescription("成功标志");
|
||||
definitionProperties.put("success", successProperties);
|
||||
SwaggerDefinitionProperties timestampProperties = new SwaggerDefinitionProperties();
|
||||
timestampProperties.setType("integer");
|
||||
timestampProperties.setDescription("时间戳");
|
||||
definitionProperties.put("timestamp", timestampProperties);
|
||||
|
||||
definitions.put("OpenApiResult", respDefinition);
|
||||
|
||||
|
||||
operation.setResponses(responses);
|
||||
operations.put(openApi.getRequestMethod().toLowerCase(), operation);
|
||||
paths.put("/openapi/call/"+openApi.getRequestUrl(), operations);
|
||||
}
|
||||
|
||||
swaggerModel.setDefinitions(definitions);
|
||||
swaggerModel.setPaths(paths);
|
||||
|
||||
}
|
||||
|
||||
private void parameters(SwaggerOperation operation, OpenApi openApi) {
|
||||
List<SwaggerOperationParameter> parameters = new ArrayList<>();
|
||||
if (openApi.getParamsJson()!=null) {
|
||||
List<OpenApiParam> openApiParams = JSON.parseArray(openApi.getParamsJson(), OpenApiParam.class);
|
||||
for (OpenApiParam openApiParam : openApiParams) {
|
||||
SwaggerOperationParameter parameter = new SwaggerOperationParameter();
|
||||
parameter.setIn("path");
|
||||
parameter.setName(openApiParam.getParamKey());
|
||||
parameter.setRequired(openApiParam.getRequired() == 1);
|
||||
parameter.setDescription(openApiParam.getNote());
|
||||
parameters.add(parameter);
|
||||
}
|
||||
}
|
||||
if (openApi.getHeadersJson()!=null) {
|
||||
List<OpenApiHeader> openApiHeaders = JSON.parseArray(openApi.getHeadersJson(), OpenApiHeader.class);
|
||||
for (OpenApiHeader openApiHeader : openApiHeaders) {
|
||||
SwaggerOperationParameter parameter = new SwaggerOperationParameter();
|
||||
parameter.setIn("header");
|
||||
parameter.setName(openApiHeader.getHeaderKey());
|
||||
parameter.setRequired(openApiHeader.getRequired() == 1);
|
||||
parameter.setDescription(openApiHeader.getNote());
|
||||
parameters.add(parameter);
|
||||
}
|
||||
}
|
||||
operation.setParameters(parameters);
|
||||
}
|
||||
|
||||
private SwaggerInfo swaggerInfo() {
|
||||
SwaggerInfo info = new SwaggerInfo();
|
||||
|
||||
info.setDescription("OpenAPI 接口列表");
|
||||
info.setVersion("3.8.0");
|
||||
info.setTitle("OpenAPI 接口列表");
|
||||
info.setTermsOfService("https://jeecg.com");
|
||||
|
||||
SwaggerInfoContact contact = new SwaggerInfoContact();
|
||||
contact.setName("jeecg@qq.com");
|
||||
|
||||
info.setContact(contact);
|
||||
|
||||
SwaggerInfoLicense license = new SwaggerInfoLicense();
|
||||
license.setName("Apache 2.0");
|
||||
license.setUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
|
||||
|
||||
info.setLicense(license);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成接口路径
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("genPath")
|
||||
public Result<String> genPath() {
|
||||
Result<String> r = new Result<String>();
|
||||
r.setSuccess(true);
|
||||
r.setCode(CommonConstant.SC_OK_200);
|
||||
r.setResult(PathGenerator.genPath());
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package org.jeecg.modules.openapi.controller;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.config.shiro.IgnoreAuth;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @date 2024/12/20 14:04
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/openapi/demo")
|
||||
public class OpenApiIndexController {
|
||||
|
||||
@GetMapping("index")
|
||||
@IgnoreAuth
|
||||
public Result<Map<String, String>> index() {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("first", "Hello World");
|
||||
return Result.ok(result);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
package org.jeecg.modules.openapi.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiLog;
|
||||
import org.jeecg.modules.openapi.service.OpenApiLogService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:57
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/openapi/record")
|
||||
public class OpenApiLogController extends JeecgController<OpenApiLog, OpenApiLogService> {
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param OpenApiLog
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/list")
|
||||
public Result<?> queryPageList(OpenApiLog OpenApiLog, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
|
||||
QueryWrapper<OpenApiLog> queryWrapper = QueryGenerator.initQueryWrapper(OpenApiLog, req.getParameterMap());
|
||||
Page<OpenApiLog> page = new Page<>(pageNo, pageSize);
|
||||
IPage<OpenApiLog> pageList = service.page(page, queryWrapper);
|
||||
return Result.ok(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param OpenApiLog
|
||||
* @return
|
||||
*/
|
||||
@PostMapping(value = "/add")
|
||||
public Result<?> add(@RequestBody OpenApiLog OpenApiLog) {
|
||||
service.save(OpenApiLog);
|
||||
return Result.ok("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param OpenApiLog
|
||||
* @return
|
||||
*/
|
||||
@PutMapping(value = "/edit")
|
||||
public Result<?> edit(@RequestBody OpenApiLog OpenApiLog) {
|
||||
service.updateById(OpenApiLog);
|
||||
return Result.ok("修改成功!");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
service.removeById(id);
|
||||
return Result.ok("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
|
||||
this.service.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.ok("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
OpenApiLog OpenApiLog = service.getById(id);
|
||||
return Result.ok(OpenApiLog);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package org.jeecg.modules.openapi.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiPermission;
|
||||
import org.jeecg.modules.openapi.service.OpenApiPermissionService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/openapi/permission")
|
||||
public class OpenApiPermissionController extends JeecgController<OpenApiPermission, OpenApiPermissionService> {
|
||||
|
||||
@PostMapping("add")
|
||||
public Result add(@RequestBody OpenApiPermission openApiPermission) {
|
||||
List<String> list = Arrays.asList(openApiPermission.getApiId().split(","));
|
||||
if (CollectionUtil.isNotEmpty(list)) {
|
||||
list.forEach(l->{
|
||||
OpenApiPermission saveApiPermission = new OpenApiPermission();
|
||||
saveApiPermission.setApiId(l);
|
||||
saveApiPermission.setApiAuthId(openApiPermission.getApiAuthId());
|
||||
service.save(saveApiPermission);
|
||||
});
|
||||
}
|
||||
return Result.ok("保存成功");
|
||||
}
|
||||
@GetMapping("/list")
|
||||
public Result list( String apiAuthId) {
|
||||
return Result.ok(service.list(Wrappers.<OpenApiPermission>lambdaQuery().eq(OpenApiPermission::getApiAuthId,apiAuthId)));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,98 @@
|
||||
package org.jeecg.modules.openapi.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 接口表
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class OpenApi implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 接口名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 请求方式,如POST、GET
|
||||
*/
|
||||
private String requestMethod;
|
||||
|
||||
/**
|
||||
* 对外开放的相对接口路径
|
||||
*/
|
||||
private String requestUrl;
|
||||
|
||||
/**
|
||||
* IP 黑名单
|
||||
*/
|
||||
private String blackList;
|
||||
/**
|
||||
* 请求头json
|
||||
*/
|
||||
private String headersJson;
|
||||
/**
|
||||
* 请求参数json
|
||||
*/
|
||||
private String paramsJson;
|
||||
|
||||
|
||||
/**
|
||||
* 目前仅支持json
|
||||
*/
|
||||
private String body;
|
||||
|
||||
/**
|
||||
* 原始接口路径
|
||||
*/
|
||||
private String originUrl;
|
||||
|
||||
/**
|
||||
* 状态(1:正常 2:废弃 )
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 删除状态(0,正常,1已删除)
|
||||
*/
|
||||
@TableLogic
|
||||
private Integer delFlag;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package org.jeecg.modules.openapi.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 权限表
|
||||
* @date 2024/12/10 9:38
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class OpenApiAuth implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5933153354153738498L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 受权名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* access key
|
||||
*/
|
||||
private String ak;
|
||||
|
||||
/**
|
||||
* secret key
|
||||
*/
|
||||
private String sk;
|
||||
|
||||
/**
|
||||
* 系统用户ID
|
||||
*/
|
||||
@Dict(dictTable = "sys_user",dicCode = "id",dicText = "username")
|
||||
private String systemUserId;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package org.jeecg.modules.openapi.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 请求头表
|
||||
* @date 2024/12/10 14:37
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class OpenApiHeader implements Serializable {
|
||||
private static final long serialVersionUID = 5032708503120184683L;
|
||||
|
||||
|
||||
/**
|
||||
* key
|
||||
*/
|
||||
private String headerKey;
|
||||
|
||||
/**
|
||||
* 是否必填(0:否,1:是)
|
||||
*/
|
||||
private Integer required;
|
||||
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
private String note;
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package org.jeecg.modules.openapi.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 调用记录表
|
||||
* @date 2024/12/10 9:41
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class OpenApiLog implements Serializable {
|
||||
private static final long serialVersionUID = -5870384488947863579L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 接口ID
|
||||
*/
|
||||
private String apiId;
|
||||
|
||||
/**
|
||||
* 调用ID
|
||||
*/
|
||||
private String callAuthId;
|
||||
|
||||
/**
|
||||
* 调用时间
|
||||
*/
|
||||
private Date callTime;
|
||||
|
||||
/**
|
||||
* 耗时
|
||||
*/
|
||||
private Long usedTime;
|
||||
|
||||
/**
|
||||
* 响应时间
|
||||
*/
|
||||
private Date responseTime;
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package org.jeecg.modules.openapi.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* query部分参数表
|
||||
* @date 2024/12/10 14:37
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class OpenApiParam implements Serializable {
|
||||
private static final long serialVersionUID = -6174831468578022357L;
|
||||
|
||||
/**
|
||||
* key
|
||||
*/
|
||||
private String paramKey;
|
||||
|
||||
/**
|
||||
* 是否必填(0:否,1:是)
|
||||
*/
|
||||
private Integer required;
|
||||
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
private String defaultValue;
|
||||
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
private String note;
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package org.jeecg.modules.openapi.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* @date 2024/12/19 17:41
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
public class OpenApiPermission implements Serializable {
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 接口ID
|
||||
*/
|
||||
private String apiId;
|
||||
|
||||
/**
|
||||
* 认证ID
|
||||
*/
|
||||
private String apiAuthId;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private String createBy;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 更新人
|
||||
*/
|
||||
private String updateBy;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date updateTime;
|
||||
}
|
||||
@ -0,0 +1,204 @@
|
||||
package org.jeecg.modules.openapi.filter;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.modules.openapi.entity.OpenApi;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiAuth;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiLog;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiPermission;
|
||||
import org.jeecg.modules.openapi.service.OpenApiAuthService;
|
||||
import org.jeecg.modules.openapi.service.OpenApiLogService;
|
||||
import org.jeecg.modules.openapi.service.OpenApiPermissionService;
|
||||
import org.jeecg.modules.openapi.service.OpenApiService;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @date 2024/12/19 16:55
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApiAuthFilter implements Filter {
|
||||
|
||||
private OpenApiLogService openApiLogService;
|
||||
private OpenApiAuthService openApiAuthService;
|
||||
private OpenApiPermissionService openApiPermissionService;
|
||||
private OpenApiService openApiService;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
long startTime = System.currentTimeMillis();
|
||||
Date callTime = new Date();
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest)servletRequest;
|
||||
String ip = request.getRemoteAddr();
|
||||
|
||||
String appkey = request.getHeader("appkey");
|
||||
String signature = request.getHeader("signature");
|
||||
String timestamp = request.getHeader("timestamp");
|
||||
|
||||
OpenApi openApi = findOpenApi(request);
|
||||
|
||||
// IP 黑名单核验
|
||||
checkBlackList(openApi, ip);
|
||||
|
||||
// 签名核验
|
||||
checkSignValid(appkey, signature, timestamp);
|
||||
|
||||
OpenApiAuth openApiAuth = openApiAuthService.getByAppkey(appkey);
|
||||
// 认证信息核验
|
||||
checkSignature(appkey, signature, timestamp, openApiAuth);
|
||||
// 业务核验
|
||||
checkPermission(openApi, openApiAuth);
|
||||
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
long endTime = System.currentTimeMillis();
|
||||
|
||||
OpenApiLog openApiLog = new OpenApiLog();
|
||||
openApiLog.setApiId(openApi.getId());
|
||||
openApiLog.setCallAuthId(openApiAuth.getId());
|
||||
openApiLog.setCallTime(callTime);
|
||||
openApiLog.setUsedTime(endTime - startTime);
|
||||
openApiLog.setResponseTime(new Date());
|
||||
openApiLogService.save(openApiLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
ServletContext servletContext = filterConfig.getServletContext();
|
||||
WebApplicationContext applicationContext = (WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
|
||||
this.openApiService = applicationContext.getBean(OpenApiService.class);
|
||||
this.openApiLogService = applicationContext.getBean(OpenApiLogService.class);
|
||||
this.openApiAuthService = applicationContext.getBean(OpenApiAuthService.class);
|
||||
this.openApiPermissionService = applicationContext.getBean(OpenApiPermissionService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* IP 黑名单核验
|
||||
* @param openApi
|
||||
* @param ip
|
||||
*/
|
||||
protected void checkBlackList(OpenApi openApi, String ip) {
|
||||
if (!StringUtils.hasText(openApi.getBlackList())) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> blackList = Arrays.asList(openApi.getBlackList().split(","));
|
||||
if (blackList.contains(ip)) {
|
||||
throw new JeecgBootException("目标接口限制IP[" + ip + "]进行访问,IP已记录,请停止访问");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名验证
|
||||
* @param appkey
|
||||
* @param signature
|
||||
* @param timestamp
|
||||
* @return
|
||||
*/
|
||||
protected void checkSignValid(String appkey, String signature, String timestamp) {
|
||||
if (!StringUtils.hasText(appkey)) {
|
||||
throw new JeecgBootException("appkey为空");
|
||||
}
|
||||
if (!StringUtils.hasText(signature)) {
|
||||
throw new JeecgBootException("signature为空");
|
||||
}
|
||||
if (!StringUtils.hasText(timestamp)) {
|
||||
throw new JeecgBootException("timastamp时间戳为空");
|
||||
}
|
||||
if (!timestamp.matches("[0-9]*")) {
|
||||
throw new JeecgBootException("timastamp时间戳不合法");
|
||||
}
|
||||
if (System.currentTimeMillis() - Long.parseLong(timestamp) > 5 * 60 * 1000) {
|
||||
throw new JeecgBootException("signature签名已过期(超过五分钟)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证信息核验
|
||||
* @param appKey
|
||||
* @param signature
|
||||
* @param timestamp
|
||||
* @param openApiAuth
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void checkSignature(String appKey, String signature, String timestamp, OpenApiAuth openApiAuth) {
|
||||
if(openApiAuth==null){
|
||||
throw new JeecgBootException("不存在认证信息");
|
||||
}
|
||||
|
||||
if(!appKey.equals(openApiAuth.getAk())){
|
||||
throw new JeecgBootException("appkey错误");
|
||||
}
|
||||
|
||||
if (!signature.equals(md5(appKey + openApiAuth.getSk() + timestamp))) {
|
||||
throw new JeecgBootException("signature签名错误");
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkPermission(OpenApi openApi, OpenApiAuth openApiAuth) {
|
||||
List<OpenApiPermission> permissionList = openApiPermissionService.findByAuthId(openApiAuth.getId());
|
||||
|
||||
boolean hasPermission = false;
|
||||
for (OpenApiPermission permission : permissionList) {
|
||||
if (permission.getApiId().equals(openApi.getId())) {
|
||||
hasPermission = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPermission) {
|
||||
throw new JeecgBootException("该appKey未授权当前接口");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String 返回类型
|
||||
* @Title: MD5
|
||||
* @Description: 【MD5加密】
|
||||
*/
|
||||
protected static String md5(String sourceStr) {
|
||||
String result = "";
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(sourceStr.getBytes("utf-8"));
|
||||
byte[] hash = md.digest();
|
||||
int i;
|
||||
StringBuffer buf = new StringBuffer(32);
|
||||
for (int offset = 0; offset < hash.length; offset++) {
|
||||
i = hash[offset];
|
||||
if (i < 0) {
|
||||
i += 256;
|
||||
}
|
||||
if (i < 16) {
|
||||
buf.append("0");
|
||||
}
|
||||
buf.append(Integer.toHexString(i));
|
||||
}
|
||||
result = buf.toString();
|
||||
} catch (Exception e) {
|
||||
log.error("sign签名错误", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected OpenApi findOpenApi(HttpServletRequest request) {
|
||||
String uri = request.getRequestURI();
|
||||
String path = uri.substring(uri.lastIndexOf("/") + 1);
|
||||
return openApiService.findByPath(path);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
long timestamp = System.currentTimeMillis();
|
||||
System.out.println("timestamp:" + timestamp);
|
||||
System.out.println("signature:" + md5("ak-eAU25mrMxhtaZsyS" + "rjxMqB6YyUXpSHAz4DCIz8vZ5aozQQiV" + timestamp));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package org.jeecg.modules.openapi.filter;
|
||||
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @date 2024/12/19 17:09
|
||||
*/
|
||||
@Configuration
|
||||
public class ApiFilterConfig {
|
||||
|
||||
/**
|
||||
*
|
||||
* @Description: 【注册api加密过滤器】
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean<ApiAuthFilter> authFilter() {
|
||||
FilterRegistrationBean<ApiAuthFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(new ApiAuthFilter());
|
||||
registration.setName("apiAuthFilter");
|
||||
registration.addUrlPatterns("/openapi/call/*");
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package org.jeecg.modules.openapi.generator;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
|
||||
/**
|
||||
* AK/SK生成器
|
||||
*/
|
||||
public class AKSKGenerator {
|
||||
private static final String CHAR_POOL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
private static final int AK_LENGTH = 16; // Adjust as per requirements
|
||||
private static final int SK_LENGTH = 32;
|
||||
|
||||
public static String[] genAKSKPair() {
|
||||
return new String[]{genAK(), genSK()};
|
||||
}
|
||||
|
||||
public static String genAK() {
|
||||
return "ak-" + generateRandomString(AK_LENGTH);
|
||||
}
|
||||
|
||||
public static String genSK() {
|
||||
return generateRandomString(SK_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
private static String generateRandomString(int length) {
|
||||
SecureRandom random = new SecureRandom();
|
||||
StringBuilder sb = new StringBuilder(length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(CHAR_POOL.charAt(random.nextInt(CHAR_POOL.length())));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package org.jeecg.modules.openapi.generator;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 10:00
|
||||
*/
|
||||
@UtilityClass
|
||||
public class PathGenerator {
|
||||
|
||||
// Base62字符集
|
||||
private static final String BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
/**
|
||||
* 生成随机路径
|
||||
* @return
|
||||
*/
|
||||
public static String genPath() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
Random random = new Random();
|
||||
for (int i=0; i<8; i++) {
|
||||
result.append(BASE62.charAt(random.nextInt(62)));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package org.jeecg.modules.openapi.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiAuth;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:49
|
||||
*/
|
||||
@Mapper
|
||||
public interface OpenApiAuthMapper extends BaseMapper<OpenApiAuth> {
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package org.jeecg.modules.openapi.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiLog;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:50
|
||||
*/
|
||||
@Mapper
|
||||
public interface OpenApiLogMapper extends BaseMapper<OpenApiLog> {
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package org.jeecg.modules.openapi.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.jeecg.modules.openapi.entity.OpenApi;
|
||||
|
||||
@Mapper
|
||||
public interface OpenApiMapper extends BaseMapper<OpenApi> {
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package org.jeecg.modules.openapi.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiPermission;
|
||||
|
||||
/**
|
||||
* @date 2024/12/19 17:43
|
||||
*/
|
||||
@Mapper
|
||||
public interface OpenApiPermissionMapper extends BaseMapper<OpenApiPermission> {
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package org.jeecg.modules.openapi.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiAuth;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:50
|
||||
*/
|
||||
public interface OpenApiAuthService extends IService<OpenApiAuth> {
|
||||
OpenApiAuth getByAppkey(String appkey);
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package org.jeecg.modules.openapi.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiLog;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:51
|
||||
*/
|
||||
public interface OpenApiLogService extends IService<OpenApiLog> {
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package org.jeecg.modules.openapi.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiPermission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @date 2024/12/19 17:44
|
||||
*/
|
||||
public interface OpenApiPermissionService extends IService<OpenApiPermission> {
|
||||
List<OpenApiPermission> findByAuthId(String authId);
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package org.jeecg.modules.openapi.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.openapi.entity.OpenApi;
|
||||
|
||||
public interface OpenApiService extends IService<OpenApi> {
|
||||
OpenApi findByPath(String path);
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package org.jeecg.modules.openapi.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiAuth;
|
||||
import org.jeecg.modules.openapi.mapper.OpenApiAuthMapper;
|
||||
import org.jeecg.modules.openapi.service.OpenApiAuthService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:51
|
||||
*/
|
||||
@Service
|
||||
public class OpenApiAuthServiceImpl extends ServiceImpl<OpenApiAuthMapper, OpenApiAuth> implements OpenApiAuthService {
|
||||
@Override
|
||||
public OpenApiAuth getByAppkey(String appkey) {
|
||||
return baseMapper.selectOne(Wrappers.lambdaUpdate(OpenApiAuth.class).eq(OpenApiAuth::getAk, appkey), false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package org.jeecg.modules.openapi.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiLog;
|
||||
import org.jeecg.modules.openapi.mapper.OpenApiLogMapper;
|
||||
import org.jeecg.modules.openapi.service.OpenApiLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @date 2024/12/10 9:53
|
||||
*/
|
||||
@Service
|
||||
public class OpenApiLogServiceImpl extends ServiceImpl<OpenApiLogMapper, OpenApiLog> implements OpenApiLogService {
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package org.jeecg.modules.openapi.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.jeecg.modules.openapi.entity.OpenApiPermission;
|
||||
import org.jeecg.modules.openapi.mapper.OpenApiPermissionMapper;
|
||||
import org.jeecg.modules.openapi.service.OpenApiPermissionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @date 2024/12/19 17:44
|
||||
*/
|
||||
@Service
|
||||
public class OpenApiPermissionServiceImpl extends ServiceImpl<OpenApiPermissionMapper, OpenApiPermission> implements OpenApiPermissionService {
|
||||
@Override
|
||||
public List<OpenApiPermission> findByAuthId(String authId) {
|
||||
return baseMapper.selectList(Wrappers.lambdaQuery(OpenApiPermission.class).eq(OpenApiPermission::getApiAuthId, authId));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package org.jeecg.modules.openapi.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.jeecg.modules.openapi.entity.OpenApi;
|
||||
import org.jeecg.modules.openapi.mapper.OpenApiMapper;
|
||||
import org.jeecg.modules.openapi.service.OpenApiService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class OpenApiServiceImpl extends ServiceImpl<OpenApiMapper, OpenApi> implements OpenApiService {
|
||||
@Override
|
||||
public OpenApi findByPath(String path) {
|
||||
return baseMapper.selectOne(Wrappers.lambdaQuery(OpenApi.class).eq(OpenApi::getRequestUrl, path), false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:17
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerDefinition {
|
||||
private String type;
|
||||
private Map<String, SwaggerDefinitionProperties> properties;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 13:54
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerDefinitionProperties {
|
||||
private String type;
|
||||
private String example;
|
||||
private String description;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:05
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerInfo {
|
||||
private String description;
|
||||
private String version;
|
||||
private String title;
|
||||
private String termsOfService;
|
||||
private SwaggerInfoContact contact;
|
||||
private SwaggerInfoLicense license;
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:08
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerInfoContact {
|
||||
private String name;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:09
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerInfoLicense {
|
||||
private String name;
|
||||
private String url;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:05
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerModel {
|
||||
private String swagger;
|
||||
private SwaggerInfo info;
|
||||
private String host;
|
||||
private String basePath;
|
||||
private List<SwaggerTag> tags;
|
||||
private List<String> schemes;
|
||||
private Map<String, Map<String, SwaggerOperation>> paths;
|
||||
private Map<String, SwaggerDefinition> definitions;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:16
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerOperation {
|
||||
private List<String> tags;
|
||||
private String summary;
|
||||
private String description;
|
||||
private String operationId;
|
||||
private List<String> produces;
|
||||
private List<SwaggerOperationParameter> parameters;
|
||||
private Map<String, SwaggerOperationResponse> responses;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:43
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerOperationParameter {
|
||||
private String name;
|
||||
private String in;
|
||||
private String description;
|
||||
private Boolean required;
|
||||
private Map<String, String> schema;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:47
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerOperationResponse {
|
||||
private String description;
|
||||
private Map<String, String> schema;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:51
|
||||
*/
|
||||
public class SwaggerSchema {
|
||||
private String $ref;
|
||||
|
||||
public String get$ref() {
|
||||
return $ref;
|
||||
}
|
||||
|
||||
public void set$ref(String $ref) {
|
||||
this.$ref = $ref;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package org.jeecg.modules.openapi.swagger;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @date 2025/1/26 11:15
|
||||
*/
|
||||
@Data
|
||||
public class SwaggerTag {
|
||||
private String name;
|
||||
}
|
||||
@ -36,7 +36,7 @@ public class DuplicateCheckController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/check", method = RequestMethod.GET)
|
||||
@Operation(summary = "重复校验接口")
|
||||
@Operation(summary ="重复校验接口")
|
||||
public Result<String> doDuplicateCheck(DuplicateCheckVo duplicateCheckVo, HttpServletRequest request) {
|
||||
log.debug("----duplicate check------:"+ duplicateCheckVo.toString());
|
||||
|
||||
|
||||
@ -107,8 +107,10 @@ public class LoginController {
|
||||
}
|
||||
String lowerCaseCaptcha = captcha.toLowerCase();
|
||||
// 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
|
||||
String origin = lowerCaseCaptcha+sysLoginModel.getCheckKey()+jeecgBaseConfig.getSignatureSecret();
|
||||
String realKey = Md5Util.md5Encode(origin, "utf-8");
|
||||
//update-begin---author:chenrui ---date:20250107 for:[QQYUN-10775]验证码可以复用 #7674------------
|
||||
String keyPrefix = Md5Util.md5Encode(sysLoginModel.getCheckKey()+jeecgBaseConfig.getSignatureSecret(), "utf-8");
|
||||
String realKey = keyPrefix + lowerCaseCaptcha;
|
||||
//update-end---author:chenrui ---date:20250107 for:[QQYUN-10775]验证码可以复用 #7674------------
|
||||
Object checkCode = redisUtil.get(realKey);
|
||||
//当进入登录页时,有一定几率出现验证码错误 #1714
|
||||
if(checkCode==null || !checkCode.toString().equals(lowerCaseCaptcha)) {
|
||||
@ -427,7 +429,7 @@ public class LoginController {
|
||||
* @param jsonObject
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary ="手机号登录接口")
|
||||
@Operation(summary = "手机号登录接口")
|
||||
@PostMapping("/phoneLogin")
|
||||
public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
|
||||
Result<JSONObject> result = new Result<JSONObject>();
|
||||
@ -546,7 +548,7 @@ public class LoginController {
|
||||
* @param response
|
||||
* @param key
|
||||
*/
|
||||
@Operation(summary ="获取验证码")
|
||||
@Operation(summary = "获取验证码")
|
||||
@GetMapping(value = "/randomImage/{key}")
|
||||
public Result<String> randomImage(HttpServletResponse response,@PathVariable("key") String key){
|
||||
Result<String> res = new Result<String>();
|
||||
@ -558,10 +560,12 @@ public class LoginController {
|
||||
|
||||
//update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
|
||||
// 加入密钥作为混淆,避免简单的拼接,被外部利用,用户自定义该密钥即可
|
||||
String origin = lowerCaseCode+key+jeecgBaseConfig.getSignatureSecret();
|
||||
String realKey = Md5Util.md5Encode(origin, "utf-8");
|
||||
//update-begin---author:chenrui ---date:20250107 for:[QQYUN-10775]验证码可以复用 #7674------------
|
||||
String keyPrefix = Md5Util.md5Encode(key+jeecgBaseConfig.getSignatureSecret(), "utf-8");
|
||||
String realKey = keyPrefix + lowerCaseCode;
|
||||
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
|
||||
|
||||
redisUtil.removeAll(keyPrefix);
|
||||
//update-end---author:chenrui ---date:20250107 for:[QQYUN-10775]验证码可以复用 #7674------------
|
||||
redisUtil.set(realKey, lowerCaseCode, 60);
|
||||
log.info("获取验证码,Redis key = {},checkCode = {}", realKey, code);
|
||||
//返回前端
|
||||
|
||||
@ -213,7 +213,7 @@ public class SysCommentController extends JeecgController<SysComment, ISysCommen
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "系统评论回复表-通过id删除")
|
||||
@Operation(summary= "系统评论回复表-通过id删除")
|
||||
@Operation(summary = "系统评论回复表-通过id删除")
|
||||
//@RequiresPermissions("org.jeecg.modules.demo:sys_comment:delete")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
|
||||
@ -3,6 +3,7 @@ package org.jeecg.modules.system.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
||||
@ -80,8 +80,8 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
|
||||
HttpServletRequest req) {
|
||||
QueryWrapper<SysDepartRole> queryWrapper = QueryGenerator.initQueryWrapper(sysDepartRole, req.getParameterMap());
|
||||
Page<SysDepartRole> page = new Page<SysDepartRole>(pageNo, pageSize);
|
||||
LoginUser user = SecureUtil.currentUser();
|
||||
List<String> deptIds = null;
|
||||
// LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
// List<String> deptIds = null;
|
||||
// if(oConvertUtils.isEmpty(deptId)){
|
||||
// if(oConvertUtils.isNotEmpty(user.getUserIdentity()) && user.getUserIdentity().equals(CommonConstant.USER_IDENTITY_2) ){
|
||||
// deptIds = sysDepartService.getMySubDepIdsByDepId(user.getDepartIds());
|
||||
|
||||
@ -4,11 +4,11 @@ package org.jeecg.modules.system.controller;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CacheConstant;
|
||||
@ -161,7 +161,7 @@ public class SysDictItemController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/dictItemCheck", method = RequestMethod.GET)
|
||||
@Operation(summary = "字典重复校验接口")
|
||||
@Operation(summary ="字典重复校验接口")
|
||||
public Result<Object> doDictItemCheck(SysDictItem sysDictItem, HttpServletRequest request) {
|
||||
Long num = Long.valueOf(0);
|
||||
LambdaQueryWrapper<SysDictItem> queryWrapper = new LambdaQueryWrapper<SysDictItem>();
|
||||
|
||||
@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
@ -16,6 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -101,7 +101,13 @@ public class SysRoleController {
|
||||
public Result<IPage<SysRole>> queryPageList(SysRole role,
|
||||
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
|
||||
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
|
||||
@RequestParam(name="isMultiTranslate", required = false) Boolean isMultiTranslate,
|
||||
HttpServletRequest req) {
|
||||
//update-begin---author:wangshuai---date:2025-03-26---for:【issues/7948】角色解决根据id查询回显不对---
|
||||
if(null != isMultiTranslate && isMultiTranslate){
|
||||
pageSize = 100;
|
||||
}
|
||||
//update-end---author:wangshuai---date:2025-03-26---for:【issues/7948】角色解决根据id查询回显不对---
|
||||
Result<IPage<SysRole>> result = new Result<IPage<SysRole>>();
|
||||
//QueryWrapper<SysRole> queryWrapper = QueryGenerator.initQueryWrapper(role, req.getParameterMap());
|
||||
//IPage<SysRole> pageList = sysRoleService.page(page, queryWrapper);
|
||||
@ -188,7 +194,7 @@ public class SysRoleController {
|
||||
LoginUser sysUser = SecureUtil.currentUser();
|
||||
Integer tenantId = oConvertUtils.getInt(TenantContext.getTenant(), 0);
|
||||
String username = "admin";
|
||||
if (!tenantId.equals(role.getTenantId()) && !username.equals(sysUser.getUsername())) {
|
||||
if (!tenantId.equals(sysrole.getTenantId()) && !username.equals(sysUser.getUsername())) {
|
||||
baseCommonService.addLog("未经授权,修改非本租户下的角色ID:" + role.getId() + ",操作人:" + sysUser.getUsername(), CommonConstant.LOG_TYPE_2, CommonConstant.OPERATE_TYPE_3);
|
||||
return Result.error("修改角色失败,当前角色不在此租户中。");
|
||||
}
|
||||
|
||||
@ -2,12 +2,11 @@ package org.jeecg.modules.system.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
|
||||
@ -24,7 +24,11 @@ import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.config.security.utils.SecureUtil;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
import org.jeecg.modules.system.service.*;
|
||||
import org.jeecg.modules.system.service.ISysTenantPackService;
|
||||
import org.jeecg.modules.system.service.ISysTenantService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.jeecg.modules.system.service.ISysUserTenantService;
|
||||
import org.jeecg.modules.system.service.ISysDepartService;
|
||||
import org.jeecg.modules.system.vo.SysUserTenantVo;
|
||||
import org.jeecg.modules.system.vo.tenant.TenantDepartAuthInfo;
|
||||
import org.jeecg.modules.system.vo.tenant.TenantPackModel;
|
||||
|
||||
@ -23,7 +23,7 @@ import java.util.Date;
|
||||
@TableName("sys_check_rule")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description = "sys_check_rule对象")
|
||||
@Schema(description = "编码校验规则")
|
||||
public class SysCheckRule {
|
||||
|
||||
/**
|
||||
|
||||
@ -26,7 +26,7 @@ import java.util.Date;
|
||||
@TableName("sys_comment")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description="sys_comment对象")
|
||||
@Schema(description="系统评论回复表")
|
||||
public class SysComment implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_data_source")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description = "sys_data_source对象")
|
||||
@Schema(description = "多数据源管理")
|
||||
public class SysDataSource {
|
||||
|
||||
/**
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
/**
|
||||
|
||||
@ -1,16 +1,19 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
/**
|
||||
* @Description: 部门角色
|
||||
@ -22,7 +25,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_depart_role")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description="sys_depart_role对象")
|
||||
@Schema(description="部门角色")
|
||||
public class SysDepartRole {
|
||||
|
||||
/**id*/
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
/**
|
||||
* @Description: 部门角色权限
|
||||
@ -21,7 +24,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_depart_role_permission")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description="sys_depart_role_permission对象")
|
||||
@Schema( description="部门角色权限")
|
||||
public class SysDepartRolePermission {
|
||||
|
||||
/**id*/
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
/**
|
||||
@ -19,7 +24,7 @@ import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
@TableName("sys_depart_role_user")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description="sys_depart_role_user对象")
|
||||
@Schema(description="部门角色人员信息")
|
||||
public class SysDepartRoleUser {
|
||||
|
||||
/**主键id*/
|
||||
|
||||
@ -21,7 +21,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_fill_rule")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema( description = "填值规则")
|
||||
@Schema(description = "填值规则")
|
||||
public class SysFillRule {
|
||||
|
||||
/**
|
||||
|
||||
@ -10,7 +10,6 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -23,7 +22,7 @@ import java.util.Date;
|
||||
@TableName("sys_form_file")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description="sys_form_file对象")
|
||||
@Schema(description="表单评论文件")
|
||||
public class SysFormFile {
|
||||
|
||||
/**id*/
|
||||
|
||||
@ -26,7 +26,7 @@ import java.util.Date;
|
||||
@TableName("sys_gateway_route")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description="sys_gateway_route对象")
|
||||
@Schema(description="gateway路由管理")
|
||||
public class SysGatewayRoute implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @Description: 产品包菜单关系表
|
||||
|
||||
@ -22,7 +22,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_position")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description = "sys_position对象")
|
||||
@Schema(description = "职务表")
|
||||
public class SysPosition {
|
||||
|
||||
/**
|
||||
|
||||
@ -1,16 +1,18 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
/**
|
||||
* @Description: 角色首页配置
|
||||
@ -22,7 +24,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_role_index")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description="sys_role_index对象")
|
||||
@Schema(description="角色首页配置")
|
||||
public class SysRoleIndex {
|
||||
|
||||
/**id*/
|
||||
|
||||
@ -21,7 +21,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_table_white_list")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description = "sys_table_white_list对象")
|
||||
@Schema(description = "系统表白名单")
|
||||
public class SysTableWhiteList {
|
||||
|
||||
/**
|
||||
|
||||
@ -1,20 +1,17 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @Description: 租户产品包
|
||||
* @Author: jeecg-boot
|
||||
@ -25,7 +22,7 @@ import java.util.Date;
|
||||
@TableName("sys_tenant_pack")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description="sys_tenant_pack对象")
|
||||
@Schema(description="租户产品包")
|
||||
public class SysTenantPack implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ import java.io.Serializable;
|
||||
@TableName("sys_tenant_pack_user")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description="sys_tenant_pack_user对象")
|
||||
@Schema(description="租户产品包用户关系表")
|
||||
public class SysTenantPackUser implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@ -21,7 +21,7 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
@TableName("sys_third_account")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description="sys_third_account对象")
|
||||
@Schema(description="第三方登录账号表")
|
||||
public class SysThirdAccount {
|
||||
|
||||
/**编号*/
|
||||
|
||||
@ -10,7 +10,6 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -23,7 +22,7 @@ import java.util.Date;
|
||||
@TableName("sys_third_app_config")
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@Schema(description="sys_third_app_config对象")
|
||||
@Schema(description="第三方配置表")
|
||||
public class SysThirdAppConfig {
|
||||
|
||||
/**编号*/
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@ -18,7 +17,7 @@ import java.util.Date;
|
||||
* @Date: 2023-02-14
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Schema(description="sys_user_position对象")
|
||||
@Schema(description="用户职位关系表")
|
||||
@Data
|
||||
@TableName("sys_user_position")
|
||||
public class SysUserPosition implements Serializable {
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
package org.jeecg.modules.system.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* @Description: sys_user_tenant_relation
|
||||
@ -24,7 +23,7 @@ import java.util.Date;
|
||||
@TableName("sys_user_tenant")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(description="sys_user_tenant对象")
|
||||
@Schema(description="sys_user_tenant")
|
||||
public class SysUserTenant implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@ -136,7 +136,7 @@
|
||||
|
||||
<!--根据用户id获取用户id和部门名称-->
|
||||
<select id="getUserDepartByTenantUserId" resultType="org.jeecg.modules.system.vo.SysUserDepVo">
|
||||
SELECT sd.depart_name, sud.user_id
|
||||
SELECT sd.depart_name, sud.user_id, sd.id as deptId, sd.parent_id
|
||||
FROM sys_depart sd
|
||||
RIGHT JOIN sys_user_depart sud on sd.id = sud.dep_id and sd.del_flag = 0
|
||||
WHERE sud.user_id IN
|
||||
|
||||
@ -23,6 +23,20 @@
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
<!--增加id查询 for:【issues/7948】角色解决根据id查询回显不对-->
|
||||
<if test="role.id!='' and role.id!=null">
|
||||
<choose>
|
||||
<when test="role.id.indexOf(',') != -1">
|
||||
AND id in
|
||||
<foreach item="item" index="index" collection="role.id.split(',')" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</when>
|
||||
<otherwise>
|
||||
AND id = #{role.id}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
order by create_time desc
|
||||
</select>
|
||||
|
||||
|
||||
@ -43,8 +43,7 @@
|
||||
<select id="queryTenantPackUserCount" resultType="org.jeecg.modules.system.vo.tenant.TenantPackUserCount">
|
||||
SELECT pack_code, count(*) as user_count FROM sys_tenant_pack a
|
||||
join sys_tenant_pack_user b on a.id = b.pack_id
|
||||
join sys_user_tenant sut on a.tenant_id = sut.tenant_id and b.user_id = sut.user_id and sut.status = 1
|
||||
where a.tenant_id = #{tenantId}
|
||||
where a.tenant_id = #{tenantId} and b.tenant_id = #{tenantId}
|
||||
and a.pack_code in ('superAdmin', 'accountAdmin', 'appAdmin')
|
||||
and b.status = 1
|
||||
group by a.pack_code
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.jeecg.modules.system.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package org.jeecg.modules.system.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.system.entity.SysTenantPack;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.jeecg.modules.system.entity.SysTenantPackUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -26,6 +26,7 @@ import org.jeecg.modules.system.vo.SysCommentVO;
|
||||
import org.jeecg.modules.system.vo.UserAvatar;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
@ -271,7 +271,13 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteUser(String userId) {
|
||||
//1.删除用户
|
||||
//update-begin---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】admin用户禁止删除---
|
||||
//1.验证当前用户是管理员账号 admin
|
||||
//验证用户是否为管理员
|
||||
this.checkUserAdminRejectDel(userId);
|
||||
//update-end---author:wangshuai---date:2024-01-16---for:【QQYUN-7974】admin用户禁止删除---
|
||||
|
||||
//2.删除用户
|
||||
this.removeById(userId);
|
||||
return false;
|
||||
}
|
||||
@ -280,7 +286,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
@CacheEvict(value={CacheConstant.SYS_USERS_CACHE}, allEntries=true)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean deleteBatchUsers(String userIds) {
|
||||
//1.删除用户
|
||||
//1.验证当前用户是管理员账号 admin
|
||||
this.checkUserAdminRejectDel(userIds);
|
||||
//2.删除用户
|
||||
this.removeByIds(Arrays.asList(userIds.split(",")));
|
||||
return false;
|
||||
}
|
||||
@ -881,7 +889,6 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
SysUserTenant userTenant = new SysUserTenant();
|
||||
userTenant.setStatus(CommonConstant.USER_TENANT_QUIT);
|
||||
userTenantMapper.update(userTenant,query);
|
||||
//update-end---author:wangshuai ---date:20230111 for:[QQYUN-3951]租户用户离职重构------------
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1907,7 +1914,6 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void changePhone(JSONObject json, String username) {
|
||||
String smscode = json.getString("smscode");
|
||||
@ -1941,7 +1947,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
userMapper.updateById(sysUser);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证手机号
|
||||
*
|
||||
@ -1961,7 +1967,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
||||
//验证完成之后清空手机验证码
|
||||
redisUtil.removeAll(phoneKey);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendChangePhoneSms(JSONObject jsonObject, String username, String ipAddress) {
|
||||
String type = jsonObject.getString("type");
|
||||
|
||||
@ -32,7 +32,10 @@ import org.jeecg.common.constant.enums.MessageTypeEnum;
|
||||
import org.jeecg.common.exception.JeecgBootBizTipException;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.util.*;
|
||||
import org.jeecg.common.util.PasswordUtil;
|
||||
import org.jeecg.common.util.RestUtil;
|
||||
import org.jeecg.common.util.SpringContextUtils;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
@ -741,6 +744,7 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
||||
}
|
||||
sysDepart.setDepartName(department.getName());
|
||||
sysDepart.setDepartOrder(department.getOrder());
|
||||
sysDepart.setDingIdentifier(department.getSource_identifier());
|
||||
return sysDepart;
|
||||
}
|
||||
|
||||
|
||||
@ -12,4 +12,13 @@ import lombok.Data;
|
||||
public class SysUserDepVo {
|
||||
private String userId;
|
||||
private String departName;
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
private String deptId;
|
||||
|
||||
/**
|
||||
* 部门的父级id
|
||||
*/
|
||||
private String parentId;
|
||||
}
|
||||
|
||||
@ -1,64 +0,0 @@
|
||||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by Fernflower decompiler)
|
||||
//
|
||||
|
||||
package org.springframework.boot.autoconfigure.mongo;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.client.MongoClient;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoClientFactory;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoPropertiesClientSettingsBuilderCustomizer;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Primary
|
||||
@AutoConfiguration
|
||||
@ConditionalOnClass({MongoClient.class})
|
||||
@ConditionalOnProperty(name = "spring.data.mongodb.uri", havingValue = "", matchIfMissing = false)
|
||||
@EnableConfigurationProperties({MongoProperties.class})
|
||||
@ConditionalOnMissingBean(
|
||||
type = {"org.springframework.data.mongodb.MongoDatabaseFactory"}
|
||||
)
|
||||
public class MongoAutoConfiguration {
|
||||
public MongoAutoConfiguration() {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean({MongoClient.class})
|
||||
public MongoClient mongo(ObjectProvider<MongoClientSettingsBuilderCustomizer> builderCustomizers, MongoClientSettings settings) {
|
||||
return (MongoClient)(new MongoClientFactory((List)builderCustomizers.orderedStream().collect(Collectors.toList()))).createMongoClient(settings);
|
||||
}
|
||||
|
||||
@Configuration(
|
||||
proxyBeanMethods = false
|
||||
)
|
||||
@ConditionalOnMissingBean({MongoClientSettings.class})
|
||||
static class MongoClientSettingsConfiguration {
|
||||
MongoClientSettingsConfiguration() {
|
||||
}
|
||||
|
||||
@Bean
|
||||
MongoClientSettings mongoClientSettings() {
|
||||
return MongoClientSettings.builder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
MongoPropertiesClientSettingsBuilderCustomizer mongoPropertiesCustomizer(MongoProperties properties, Environment environment) {
|
||||
return new MongoPropertiesClientSettingsBuilderCustomizer(properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,8 +34,8 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
<#assign bpm_flag=false>
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
import { render } from '@/common/renderUtils';
|
||||
//列表数据
|
||||
export const columns = [
|
||||
<#list columns as po>
|
||||
<#if po.isShowList =='Y' && po.fieldName !='id' && po.fieldName !='delFlag'>
|
||||
{
|
||||
title: '${po.filedComment}',
|
||||
align:"center",
|
||||
<#if po.sort=='Y'>
|
||||
sorter: true,
|
||||
</#if>
|
||||
<#if po.classType=='date'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
<#elseif po.fieldDbType=='Blob'>
|
||||
dataIndex: '${po.fieldName}String'
|
||||
<#elseif po.classType=='umeditor'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
<#elseif po.classType=='pca'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
<#elseif po.classType=='file'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
<#elseif po.classType=='image'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
customRender:render.renderImage,
|
||||
<#elseif po.classType=='switch'>
|
||||
dataIndex: '${po.fieldName}',
|
||||
<#assign switch_extend_arr=['Y','N']>
|
||||
<#if po.dictField?default("")?contains("[")>
|
||||
<#assign switch_extend_arr=po.dictField?eval>
|
||||
</#if>
|
||||
<#list switch_extend_arr as a>
|
||||
<#if a_index == 0>
|
||||
<#assign switch_extend_arr1=a>
|
||||
<#else>
|
||||
<#assign switch_extend_arr2=a>
|
||||
</#if>
|
||||
</#list>
|
||||
customRender:({text}) => {
|
||||
return render.renderSwitch(text, [{text:'是',value:'${switch_extend_arr1}'},{text:'否',value:'${switch_extend_arr2}'}])
|
||||
},
|
||||
<#elseif po.classType == 'sel_tree' || po.classType=='list' || po.classType=='list_multi' || po.classType=='sel_search' || po.classType=='radio' || po.classType=='checkbox' || po.classType=='sel_depart' || po.classType=='sel_user' || po.classType=='popup_dict'>
|
||||
dataIndex: '${po.fieldName}_dictText'
|
||||
<#else>
|
||||
dataIndex: '${po.fieldName}'
|
||||
</#if>
|
||||
},
|
||||
</#if>
|
||||
</#list>
|
||||
];
|
||||
@ -0,0 +1,512 @@
|
||||
<#include "/common/utils.ftl">
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationStyle: 'custom',
|
||||
navigationBarTitleText: '${tableVo.ftlDescription}',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<PageLayout :navTitle="navTitle" :backRouteName="backRouteName">
|
||||
<scroll-view class="scrollArea" scroll-y>
|
||||
<view class="form-container">
|
||||
<wd-form ref="form" :model="myFormData">
|
||||
<wd-cell-group border>
|
||||
<#list columns as po><#rt/>
|
||||
<#assign form_field_dictCode="">
|
||||
<#if po.dictTable?default("")?trim?length gt 1 && po.dictText?default("")?trim?length gt 1 && po.dictField?default("")?trim?length gt 1>
|
||||
<#assign form_field_dictCode="${po.dictTable},${po.dictText},${po.dictField}">
|
||||
<#elseif po.dictField?default("")?trim?length gt 1>
|
||||
<#assign form_field_dictCode="${po.dictField}">
|
||||
</#if>
|
||||
<view class="{ 'mt-14px': ${po_index % 2} == 0 }">
|
||||
<#if po.fieldName !='id' && po.isShow =='Y' && po.fieldName !='delFlag'><#rt/>
|
||||
<#if po.classType =='image'>
|
||||
<!-- 图片 -->
|
||||
<wd-cell
|
||||
:title="get4Label('${po.filedComment}')"
|
||||
title-width="100px"
|
||||
<#if po.nullable == 'N'>
|
||||
:required="true"
|
||||
</#if>
|
||||
>
|
||||
<online-image
|
||||
v-model:value="myFormData[${autoStringSuffix(po)}]"
|
||||
name=${autoStringSuffix(po)}
|
||||
<#if po.uploadnum??>
|
||||
:maxNum="${po.uploadnum}"
|
||||
</#if>
|
||||
/>
|
||||
</wd-cell>
|
||||
<#elseif po.classType =='file'>
|
||||
<wd-cell
|
||||
:title="get4Label('${po.filedComment}')"
|
||||
title-width="100px"
|
||||
<#if po.nullable == 'N'>
|
||||
:required="true"
|
||||
</#if>
|
||||
>
|
||||
<!-- #ifndef APP-PLUS -->
|
||||
<online-file
|
||||
v-model:value="myFormData[${autoStringSuffix(po)}]"
|
||||
name=${autoStringSuffix(po)}
|
||||
></online-file>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<online-file-custom
|
||||
v-model:value="myFormData[${autoStringSuffix(po)}]"
|
||||
name=${autoStringSuffix(po)}
|
||||
></online-file-custom>
|
||||
<!-- #endif -->
|
||||
</wd-cell>
|
||||
<#elseif po.classType =='datetime' || po.classType =='time'>
|
||||
<DateTime
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
type="${po.classType}"
|
||||
<#if po.classType =='datetime'>
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
<#else>
|
||||
format="HH:mm:ss"
|
||||
</#if>
|
||||
name=${autoStringSuffix(po)}
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
></DateTime>
|
||||
<#elseif po.classType =='date'>
|
||||
<online-date
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
<#if po.extendParams?exists && po.extendParams.picker?exists>
|
||||
:type="getDateExtendType('${po.extendParams.picker}')"
|
||||
<#else>
|
||||
type="${po.classType}"
|
||||
</#if>
|
||||
name=${autoStringSuffix(po)}
|
||||
v-model:value="myFormData[${autoStringSuffix(po)}]"
|
||||
></online-date>
|
||||
<#elseif po.classType =='switch'>
|
||||
<#assign switch_extend_arr=['Y','N']>
|
||||
<#if po.dictField?default("")?contains("[")>
|
||||
<#assign switch_extend_arr=po.dictField?eval>
|
||||
</#if>
|
||||
<!-- 开关 -->
|
||||
<wd-cell
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
name=${autoStringSuffix(po)}
|
||||
title-width="100px"
|
||||
center
|
||||
>
|
||||
<wd-switch
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
name=${autoStringSuffix(po)}
|
||||
size="18px"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
active-value="${switch_extend_arr[0]}"
|
||||
inactive-value="${switch_extend_arr[1]}"
|
||||
/>
|
||||
</wd-cell>
|
||||
<#elseif po.classType =='list' || po.classType =='sel_search'>
|
||||
<online-select
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
type="${po.classType}"
|
||||
name=${autoStringSuffix(po)}
|
||||
dict="${form_field_dictCode}"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
></online-select>
|
||||
<#elseif po.classType =='checkbox'>
|
||||
<online-checkbox
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
type="${po.classType}"
|
||||
name=${autoStringSuffix(po)}
|
||||
dict="${form_field_dictCode}"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
></online-checkbox>
|
||||
<#elseif po.classType =='radio'>
|
||||
<online-radio
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
type="${po.classType}"
|
||||
name=${autoStringSuffix(po)}
|
||||
dict="${form_field_dictCode}"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
></online-radio>
|
||||
<#elseif po.classType =='list_multi'>
|
||||
<online-multi
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
type="${po.classType}"
|
||||
name=${autoStringSuffix(po)}
|
||||
dict="${form_field_dictCode}"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
></online-multi>
|
||||
<#elseif po.classType =='textarea' || po.classType =='markdown' || po.classType =='umeditor'>
|
||||
<wd-textarea
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
type="${po.classType}"
|
||||
name=${autoStringSuffix(po)}
|
||||
prop=${autoStringSuffix(po)}
|
||||
clearable
|
||||
:maxlength="300"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
></wd-textarea>
|
||||
<#elseif po.classType =='password'>
|
||||
<wd-input
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
show-password
|
||||
name=${autoStringSuffix(po)}
|
||||
prop=${autoStringSuffix(po)}
|
||||
clearable
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
></wd-input>
|
||||
<#elseif po.classType =='popup_dict'>
|
||||
<PopupDict
|
||||
labelWidth="100px"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
:multi="${po.extendParams.popupMulti?c}"
|
||||
dictCode="${po.dictTable},${po.dictText},${po.dictField}"
|
||||
></PopupDict>
|
||||
<#elseif po.classType =='popup'>
|
||||
<#assign sourceFields = po.dictField?default("")?trim?split(",")/>
|
||||
<#assign targetFields = po.dictText?default("")?trim?split(",")/>
|
||||
<Popup
|
||||
labelWidth="100px"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
:multi="${po.extendParams.popupMulti?c}"
|
||||
code="${po.dictTable}"
|
||||
:setFieldsValue="setFieldsValue"
|
||||
:fieldConfig="[
|
||||
<#list sourceFields as fieldName>
|
||||
{ source: '${fieldName}', target: '${dashedToCamel(targetFields[fieldName_index])}' },
|
||||
</#list>
|
||||
]"
|
||||
></Popup>
|
||||
<#elseif po.classType =='link_table'>
|
||||
<online-popup-link-record
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
labelWidth="100px"
|
||||
name=${autoStringSuffix(po)}
|
||||
:formSchema="getFormSchema('${po.dictTable}','${po.dictField}','${po.dictText}')"
|
||||
v-model:value="myFormData[${autoStringSuffix(po)}]"
|
||||
></online-popup-link-record>
|
||||
<#elseif po.classType =='sel_user'>
|
||||
<select-user
|
||||
labelWidth="100px"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
name=${autoStringSuffix(po)}
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if>
|
||||
></select-user>
|
||||
<#elseif po.classType =='sel_depart'>
|
||||
<select-dept
|
||||
labelWidth="100px"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
name=${autoStringSuffix(po)}
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
<#if po.extendParams?exists && po.extendParams.text?exists>labelKey="${po.extendParams.text}"</#if>
|
||||
<#if po.extendParams?exists && po.extendParams.store?exists>rowKey="${po.extendParams.store}"</#if>
|
||||
:multiple="${po.extendParams.multi?default('true')}"
|
||||
></select-dept>
|
||||
<#elseif po.classType =='cat_tree'>
|
||||
<CategorySelect
|
||||
labelWidth="100px"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
pcode="${po.dictField?default("")}"
|
||||
></CategorySelect>
|
||||
<#elseif po.classType =='sel_tree'>
|
||||
<TreeSelect
|
||||
labelWidth="100px"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
<#if po.dictText??>
|
||||
<#if po.dictText?split(',')[2]?? && po.dictText?split(',')[0]??>
|
||||
dict="${po.dictTable},${po.dictText?split(',')[2]},${po.dictText?split(',')[0]}"
|
||||
<#elseif po.dictText?split(',')[1]??>
|
||||
pidField="${po.dictText?split(',')[1]}"
|
||||
<#elseif po.dictText?split(',')[3]??>
|
||||
hasChildField="${po.dictText?split(',')[3]}"
|
||||
</#if>
|
||||
</#if>
|
||||
:pidValue="`${po.dictField}`"
|
||||
></TreeSelect>
|
||||
<#elseif po.fieldDbType=='int' || po.fieldDbType=='double' || po.fieldDbType=='BigDecimal'>
|
||||
<wd-input
|
||||
label-width="100px"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
name=${autoStringSuffix(po)}
|
||||
prop=${autoStringSuffix(po)}
|
||||
placeholder="请选择${po.filedComment}"
|
||||
inputMode="numeric"
|
||||
:rules="[
|
||||
<#if po.fieldName != 'id'>
|
||||
<#assign fieldValidType = po.fieldValidType!''>
|
||||
<#-- 非空校验 -->
|
||||
<#if po.nullable == 'N' || fieldValidType == '*'>
|
||||
{ required: true, message: '请输入${po.filedComment}!'},
|
||||
<#elseif fieldValidType!=''>
|
||||
{ required: false},
|
||||
</#if>
|
||||
<#-- 6到16位数字 -->
|
||||
<#if fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
<#-- 6到18位字母 -->
|
||||
<#elseif fieldValidType == 's6-18'>
|
||||
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
|
||||
<#-- 网址 -->
|
||||
<#elseif fieldValidType == 'url'>
|
||||
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
|
||||
<#-- 电子邮件 -->
|
||||
<#elseif fieldValidType == 'e'>
|
||||
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
|
||||
<#-- 手机号码 -->
|
||||
<#elseif fieldValidType == 'm'>
|
||||
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
|
||||
<#-- 邮政编码 -->
|
||||
<#elseif fieldValidType == 'p'>
|
||||
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'},
|
||||
<#-- 字母 -->
|
||||
<#elseif fieldValidType == 's'>
|
||||
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
|
||||
<#-- 数字 -->
|
||||
<#elseif fieldValidType == 'n'>
|
||||
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
|
||||
<#-- 整数 -->
|
||||
<#elseif fieldValidType == 'z'>
|
||||
{ pattern: /^-?\d+$/, message: '请输入整数!'},
|
||||
<#-- 金额 -->
|
||||
<#elseif fieldValidType == 'money'>
|
||||
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
|
||||
<#-- 正则校验 -->
|
||||
<#elseif fieldValidType != '' && fieldValidType != '*'>
|
||||
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
|
||||
<#-- 无校验 -->
|
||||
<#else>
|
||||
<#t>
|
||||
</#if>
|
||||
</#if>
|
||||
]"
|
||||
clearable
|
||||
/>
|
||||
<#else>
|
||||
<wd-input
|
||||
label-width="100px"
|
||||
v-model="myFormData[${autoStringSuffix(po)}]"
|
||||
:label="get4Label('${po.filedComment}')"
|
||||
name=${autoStringSuffix(po)}
|
||||
prop=${autoStringSuffix(po)}
|
||||
placeholder="请选择${po.filedComment}"
|
||||
:rules="[
|
||||
<#if po.fieldName != 'id'>
|
||||
<#assign fieldValidType = po.fieldValidType!''>
|
||||
<#-- 非空校验 -->
|
||||
<#if po.nullable == 'N' || fieldValidType == '*'>
|
||||
{ required: true, message: '请输入${po.filedComment}!'},
|
||||
<#elseif fieldValidType!=''>
|
||||
{ required: false},
|
||||
</#if>
|
||||
<#-- 6到16位数字 -->
|
||||
<#if fieldValidType == 'n6-16'>
|
||||
{ pattern: /^\d{6,16}$|^(?=\d+\.\d+)[\d.]{7,17}$/, message: '请输入6到16位数字!'},
|
||||
<#-- 6到16位任意字符 -->
|
||||
<#elseif fieldValidType == '*6-16'>
|
||||
{ pattern: /^.{6,16}$/, message: '请输入6到16位任意字符!'},
|
||||
<#-- 6到18位字母 -->
|
||||
<#elseif fieldValidType == 's6-18'>
|
||||
{ pattern: /^[a-z|A-Z]{6,18}$/, message: '请输入6到18位字母!'},
|
||||
<#-- 网址 -->
|
||||
<#elseif fieldValidType == 'url'>
|
||||
{ pattern: /^((ht|f)tps?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/, message: '请输入正确的网址!'},
|
||||
<#-- 电子邮件 -->
|
||||
<#elseif fieldValidType == 'e'>
|
||||
{ pattern: /^([\w]+\.*)([\w]+)@[\w]+\.\w{3}(\.\w{2}|)$/, message: '请输入正确的电子邮件!'},
|
||||
<#-- 手机号码 -->
|
||||
<#elseif fieldValidType == 'm'>
|
||||
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号码!'},
|
||||
<#-- 邮政编码 -->
|
||||
<#elseif fieldValidType == 'p'>
|
||||
{ pattern: /^[0-9]\d{5}$/, message: '请输入正确的邮政编码!'},
|
||||
<#-- 字母 -->
|
||||
<#elseif fieldValidType == 's'>
|
||||
{ pattern: /^[A-Z|a-z]+$/, message: '请输入字母!'},
|
||||
<#-- 数字 -->
|
||||
<#elseif fieldValidType == 'n'>
|
||||
{ pattern: /^-?\d+\.?\d*$/, message: '请输入数字!'},
|
||||
<#-- 整数 -->
|
||||
<#elseif fieldValidType == 'z'>
|
||||
{ pattern: /^-?\d+$/, message: '请输入整数!'},
|
||||
<#-- 金额 -->
|
||||
<#elseif fieldValidType == 'money'>
|
||||
{ pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/, message: '请输入正确的金额!'},
|
||||
<#-- 正则校验 -->
|
||||
<#elseif fieldValidType != '' && fieldValidType != '*'>
|
||||
{ pattern: '${fieldValidType}', message: '不符合校验规则!'},
|
||||
<#-- 无校验 -->
|
||||
<#else>
|
||||
<#t>
|
||||
</#if>
|
||||
</#if>
|
||||
]"
|
||||
clearable
|
||||
/>
|
||||
</#if>
|
||||
</#if>
|
||||
</view>
|
||||
</#list>
|
||||
</wd-cell-group>
|
||||
</wd-form>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="footer">
|
||||
<wd-button :disabled="loading" block :loading="loading" @click="handleSubmit">提交</wd-button>
|
||||
</view>
|
||||
</PageLayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { http } from '@/utils/http'
|
||||
import { useToast } from 'wot-design-uni'
|
||||
import { useRouter } from '@/plugin/uni-mini-router'
|
||||
import { ref, onMounted, computed,reactive } from 'vue'
|
||||
import OnlineImage from '@/components/online/view/online-image.vue'
|
||||
import OnlineFile from '@/components/online/view/online-file.vue'
|
||||
import OnlineFileCustom from '@/components/online/view/online-file-custom.vue'
|
||||
import OnlineSelect from '@/components/online/view/online-select.vue'
|
||||
import OnlineTime from '@/components/online/view/online-time.vue'
|
||||
import OnlineDate from '@/components/online/view/online-date.vue'
|
||||
import OnlineRadio from '@/components/online/view/online-radio.vue'
|
||||
import OnlineCheckbox from '@/components/online/view/online-checkbox.vue'
|
||||
import OnlineMulti from '@/components/online/view/online-multi.vue'
|
||||
import OnlinePopupLinkRecord from '@/components/online/view/online-popup-link-record.vue'
|
||||
import SelectDept from '@/components/SelectDept/SelectDept.vue'
|
||||
import SelectUser from '@/components/SelectUser/SelectUser.vue'
|
||||
defineOptions({
|
||||
name: '${entityName}Form',
|
||||
options: {
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
const toast = useToast()
|
||||
const router = useRouter()
|
||||
const form = ref(null)
|
||||
// 定义响应式数据
|
||||
const myFormData = reactive({})
|
||||
const loading = ref(false)
|
||||
const navTitle = ref('新增')
|
||||
const dataId = ref('')
|
||||
const backRouteName = ref('${entityName}List')
|
||||
// 定义 initForm 方法
|
||||
const initForm = (item) => {
|
||||
console.log('initForm item', item)
|
||||
if(item?.dataId){
|
||||
dataId.value = item.dataId;
|
||||
navTitle.value = item.dataId?'编辑':'新增';
|
||||
initData();
|
||||
}
|
||||
}
|
||||
// 初始化数据
|
||||
const initData = () => {
|
||||
http.get("/${entityPackagePath}/${entityName?uncap_first}/queryById",{id:dataId.value}).then((res) => {
|
||||
if (res.success) {
|
||||
let obj = res.result
|
||||
Object.assign(myFormData, { ...obj })
|
||||
}else{
|
||||
toast.error(res?.message || '表单加载失败!')
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleSuccess = () => {
|
||||
uni.$emit('refreshList');
|
||||
router.back()
|
||||
}
|
||||
// 提交表单
|
||||
const handleSubmit = () => {
|
||||
let url = dataId.value?'/${entityPackagePath}/${entityName?uncap_first}/edit':'/${entityPackagePath}/${entityName?uncap_first}/add';
|
||||
form.value
|
||||
.validate()
|
||||
.then(({ valid, errors }) => {
|
||||
if (valid) {
|
||||
loading.value = true;
|
||||
http.post(url,myFormData).then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
toast.success('保存成功');
|
||||
handleSuccess()
|
||||
}else{
|
||||
toast.error(res?.message || '表单保存失败!')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error, 'error')
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
// 标题
|
||||
const get4Label = computed(() => {
|
||||
return (label) => {
|
||||
return label && label.length > 4 ? label.substring(0, 4) : label;
|
||||
}
|
||||
})
|
||||
|
||||
// 标题
|
||||
const getFormSchema = computed(() => {
|
||||
return (dictTable,dictCode,dictText) => {
|
||||
return {
|
||||
dictCode,
|
||||
dictTable,
|
||||
dictText
|
||||
};
|
||||
}
|
||||
})
|
||||
/**
|
||||
* 获取日期控件的扩展类型
|
||||
* @param picker
|
||||
* @returns {string}
|
||||
*/
|
||||
const getDateExtendType = (picker: string) => {
|
||||
let mapField = {
|
||||
month: 'year-month',
|
||||
year: 'year',
|
||||
quarter: 'quarter',
|
||||
week: 'week',
|
||||
day: 'date',
|
||||
}
|
||||
return picker && mapField[picker]
|
||||
? mapField[picker]
|
||||
: 'date'
|
||||
}
|
||||
//设置pop返回值
|
||||
const setFieldsValue = (data) => {
|
||||
Object.assign(myFormData, {...data })
|
||||
}
|
||||
// onLoad 生命周期钩子
|
||||
onLoad((option) => {
|
||||
initForm(option)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.footer {
|
||||
width: 100%;
|
||||
padding: 10px 20px;
|
||||
padding-bottom: calc(constant(safe-area-inset-bottom) + 10px);
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 10px);
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,148 @@
|
||||
<route lang="json5" type="page">
|
||||
{
|
||||
layout: 'default',
|
||||
style: {
|
||||
navigationBarTitleText: '${tableVo.ftlDescription}',
|
||||
navigationStyle: 'custom',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<PageLayout navTitle="${tableVo.ftlDescription}" backRouteName="index" routeMethod="pushTab">
|
||||
<view class="wrap">
|
||||
<z-paging
|
||||
ref="paging"
|
||||
:fixed="false"
|
||||
v-model="dataList"
|
||||
@query="queryList"
|
||||
:default-page-size="15"
|
||||
>
|
||||
<template v-for="item in dataList" :key="item.id">
|
||||
<wd-swipe-action>
|
||||
<view class="list" @click="handleEdit(item)">
|
||||
<template v-for="(cItem, cIndex) in columns" :key="cIndex">
|
||||
<view v-if="cIndex < 3" class="box" :style="getBoxStyle">
|
||||
<view class="field ellipsis">{{ cItem.title }}</view>
|
||||
<view class="value cu-text-grey">{{ item[cItem.dataIndex] }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<template #right>
|
||||
<view class="action">
|
||||
<view class="button" @click="handleAction('del', item)">删除</view>
|
||||
</view>
|
||||
</template>
|
||||
</wd-swipe-action>
|
||||
</template>
|
||||
</z-paging>
|
||||
<view class="add u-iconfont u-icon-add" @click="handleAdd"></view>
|
||||
</view>
|
||||
</PageLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { http } from '@/utils/http'
|
||||
import usePageList from '@/hooks/usePageList'
|
||||
import {columns} from './${entityName}Data';
|
||||
defineOptions({
|
||||
name: '${entityName}List',
|
||||
options: {
|
||||
styleIsolation: 'shared',
|
||||
}
|
||||
})
|
||||
//分页加载配置
|
||||
let { toast, router, paging, dataList, queryList } = usePageList('/${entityPackagePath}/${entityName?uncap_first}/list');
|
||||
|
||||
//样式
|
||||
const getBoxStyle = computed(() => {
|
||||
return { width: "calc(33% - 5px)" }
|
||||
})
|
||||
|
||||
// 其他操作
|
||||
const handleAction = (val, item) => {
|
||||
if (val == 'del') {
|
||||
http.delete("/${entityPackagePath}/${entityName?uncap_first}/delete?id="+item.id,{id:item.id}).then((res) => {
|
||||
toast.success('删除成功~')
|
||||
paging.value.reload()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// go 新增页
|
||||
const handleAdd = () => {
|
||||
router.push({
|
||||
name: '${entityName}Form'
|
||||
})
|
||||
}
|
||||
|
||||
//go 编辑页
|
||||
const handleEdit = (record) => {
|
||||
router.push({
|
||||
name: '${entityName}Form',
|
||||
params: {dataId: record.id},
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 监听刷新列表事件
|
||||
uni.$on('refreshList', () => {
|
||||
queryList(1,10)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrap {
|
||||
height: 100%;
|
||||
}
|
||||
:deep(.wd-swipe-action) {
|
||||
margin-top: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.list {
|
||||
padding: 10px 10px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.box {
|
||||
width: 33%;
|
||||
.field {
|
||||
margin-bottom: 10px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.action {
|
||||
width: 60px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
&:first-child {
|
||||
background-color: #fa4350;
|
||||
}
|
||||
}
|
||||
}
|
||||
.add {
|
||||
height: 70upx;
|
||||
width: 70upx;
|
||||
text-align: center;
|
||||
line-height: 70upx;
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
position: fixed;
|
||||
bottom: 80upx;
|
||||
right: 30upx;
|
||||
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.1);
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
@ -2,6 +2,7 @@
|
||||
<div>
|
||||
<#assign list_need_category=false>
|
||||
<#assign list_need_pca=false>
|
||||
<#assign list_has_popup_dict=false>
|
||||
<#assign bpm_flag=false>
|
||||
|
||||
<#-- 开始循环 -->
|
||||
@ -12,6 +13,9 @@
|
||||
<#if po.classType=='cat_tree' && po.dictText?default("")?trim?length == 0>
|
||||
<#assign list_need_category=true>
|
||||
</#if>
|
||||
<#if po.classType=='popup_dict'>
|
||||
<#assign list_has_popup_dict=true>
|
||||
</#if>
|
||||
<#if po.classType=='pca'>
|
||||
<#assign list_need_pca=true>
|
||||
</#if>
|
||||
@ -91,6 +95,10 @@
|
||||
import { loadCategoryData } from '/@/api/common/api'
|
||||
import { getAuthCache, setAuthCache } from '/@/utils/auth';
|
||||
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
|
||||
</#if>
|
||||
<#if list_has_popup_dict>
|
||||
import {getPopDictByCode} from "@/utils/dict";
|
||||
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
|
||||
</#if>
|
||||
<#if bpm_flag==true>
|
||||
import { startProcess } from '/@/api/common/api';
|
||||
@ -146,6 +154,9 @@
|
||||
beforeFetch: (params) => {
|
||||
return Object.assign(params, queryParam);
|
||||
},
|
||||
<#if list_has_popup_dict>
|
||||
afterFetch: afterFetch
|
||||
</#if>
|
||||
},
|
||||
exportConfig: {
|
||||
name:"${tableVo.ftlDescription}",
|
||||
@ -319,6 +330,28 @@
|
||||
}
|
||||
initDictConfig();
|
||||
</#if>
|
||||
|
||||
<#if list_has_popup_dict>
|
||||
/**
|
||||
* 翻译Popup字典配置
|
||||
*/
|
||||
async function afterFetch(records){
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y' || po.isShowList=='Y'>
|
||||
<#if po.classType=='popup_dict' && list_has_popup_dict==true>
|
||||
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
|
||||
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
|
||||
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
|
||||
records.forEach((item) => {
|
||||
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
|
||||
});
|
||||
}
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
return records;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@ -172,6 +172,10 @@
|
||||
<#if need_pca>
|
||||
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
|
||||
</#if>
|
||||
<#if need_popup_dict>
|
||||
import {getPopDictByCode} from "@/utils/dict";
|
||||
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
|
||||
</#if>
|
||||
<#if bpm_flag==true>
|
||||
import { startProcess } from '/@/api/common/api';
|
||||
</#if>
|
||||
@ -204,11 +208,18 @@
|
||||
return Object.assign(params, queryParam);
|
||||
</#if>
|
||||
},
|
||||
<#if need_popup_dict>
|
||||
afterFetch: afterFetch
|
||||
</#if>
|
||||
},
|
||||
exportConfig: {
|
||||
name: "${tableVo.ftlDescription}",
|
||||
url: getExportUrl,
|
||||
<#if is_range>
|
||||
params: setRangeQuery,
|
||||
<#else>
|
||||
params: queryParam,
|
||||
</#if>
|
||||
},
|
||||
importConfig: {
|
||||
url: getImportUrl,
|
||||
@ -461,6 +472,28 @@
|
||||
return queryParamClone;
|
||||
}
|
||||
</#if>
|
||||
|
||||
<#if need_popup_dict>
|
||||
/**
|
||||
* 翻译Popup字典配置
|
||||
*/
|
||||
async function afterFetch(records){
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y' || po.isShowList=='Y'>
|
||||
<#if po.classType=='popup_dict'>
|
||||
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
|
||||
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
|
||||
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
|
||||
records.forEach((item) => {
|
||||
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
|
||||
});
|
||||
}
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
return records;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@ -42,8 +42,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
<#assign bpm_flag=false>
|
||||
@ -190,7 +190,7 @@ public class ${entityName}Controller {
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "${sub.ftlDescription}通过主表ID查询")
|
||||
@Operation(summary="${sub.ftlDescription}-通主表ID查询")
|
||||
@Operation(summary="${sub.ftlDescription}主表ID查询")
|
||||
@GetMapping(value = "/query${sub.entityName}ByMainId")
|
||||
public Result<List<${sub.entityName}>> query${sub.entityName}ListByMainId(@RequestParam(name="id",required=true) String id) {
|
||||
List<${sub.entityName}> ${sub.entityName?uncap_first}List = ${sub.entityName?uncap_first}Service.selectByMainId(id);
|
||||
|
||||
@ -15,6 +15,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
<#assign pidFieldName = "">
|
||||
<#assign hasChildrenField = "">
|
||||
<#assign bpm_flag=false>
|
||||
<#assign list_has_popup_dict=false>
|
||||
<#list originalColumns as po>
|
||||
<#if po.fieldDbName == tableVo.extendParams.pidField>
|
||||
<#assign pidFieldName = po.fieldName>
|
||||
@ -19,6 +20,9 @@
|
||||
<#if po.classType=='pca'>
|
||||
<#assign list_need_pca=true>
|
||||
</#if>
|
||||
<#if po.classType=='popup_dict'>
|
||||
<#assign list_has_popup_dict=true>
|
||||
</#if>
|
||||
</#list>
|
||||
<template>
|
||||
<div>
|
||||
@ -93,6 +97,10 @@
|
||||
<#if list_need_pca>
|
||||
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
|
||||
</#if>
|
||||
<#if list_has_popup_dict>
|
||||
import {getPopDictByCode} from "@/utils/dict";
|
||||
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
|
||||
</#if>
|
||||
<#if bpm_flag==true>
|
||||
import { startProcess } from '/@/api/common/api';
|
||||
</#if>
|
||||
@ -150,6 +158,9 @@
|
||||
params.hasQuery = "true";
|
||||
return Object.assign(params, queryParam);
|
||||
},
|
||||
<#if list_has_popup_dict>
|
||||
afterFetch: afterFetch
|
||||
</#if>
|
||||
},
|
||||
exportConfig: {
|
||||
name:"${tableVo.ftlDescription}",
|
||||
@ -442,7 +453,27 @@
|
||||
await reload();
|
||||
}
|
||||
</#if>
|
||||
|
||||
<#if list_has_popup_dict>
|
||||
/**
|
||||
* 翻译Popup字典配置
|
||||
*/
|
||||
async function afterFetch(records){
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y' || po.isShowList=='Y'>
|
||||
<#if po.classType=='popup_dict' && list_has_popup_dict==true>
|
||||
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
|
||||
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
|
||||
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
|
||||
records.forEach((item) => {
|
||||
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
|
||||
});
|
||||
}
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
return records;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@ -181,6 +181,10 @@
|
||||
<#if need_pca>
|
||||
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
|
||||
</#if>
|
||||
<#if need_popup_dict>
|
||||
import {getPopDictByCode} from "@/utils/dict";
|
||||
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
|
||||
</#if>
|
||||
<#if is_range>
|
||||
import { cloneDeep } from "lodash-es";
|
||||
</#if>
|
||||
@ -214,6 +218,9 @@
|
||||
return Object.assign(params, queryParam.value);
|
||||
</#if>
|
||||
},
|
||||
<#if need_popup_dict>
|
||||
afterFetch: afterFetch
|
||||
</#if>
|
||||
},
|
||||
exportConfig: {
|
||||
name: "${tableVo.ftlDescription}",
|
||||
@ -623,6 +630,28 @@
|
||||
return queryParamClone;
|
||||
}
|
||||
</#if>
|
||||
|
||||
<#if need_popup_dict>
|
||||
/**
|
||||
* 翻译Popup字典配置
|
||||
*/
|
||||
async function afterFetch(records){
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y' || po.isShowList=='Y'>
|
||||
<#if po.classType=='popup_dict'>
|
||||
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
|
||||
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
|
||||
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
|
||||
records.forEach((item) => {
|
||||
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
|
||||
});
|
||||
}
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
return records;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@ -24,8 +24,8 @@ import ${bussiPackage}.${entityPackage}.service.I${entityName}Service;
|
||||
<#list subTables as sub>
|
||||
import ${bussiPackage}.${entityPackage}.service.I${sub.entityName}Service;
|
||||
</#list>
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.jeecg.config.security.utils.SecureUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
|
||||
@ -15,6 +15,7 @@ import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
|
||||
@ -16,6 +16,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import java.util.Date;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<#assign list_need_category=false>
|
||||
<#assign list_need_pca=false>
|
||||
<#assign bpm_flag=false>
|
||||
|
||||
<#assign list_has_popup_dict=false>
|
||||
<#-- 开始循环 -->
|
||||
<#list columns as po>
|
||||
<#if po.fieldDbName=='bpm_status'>
|
||||
@ -15,6 +15,9 @@
|
||||
<#if po.classType=='pca'>
|
||||
<#assign list_need_pca=true>
|
||||
</#if>
|
||||
<#if po.classType=='popup_dict'>
|
||||
<#assign list_has_popup_dict=true>
|
||||
</#if>
|
||||
</#list>
|
||||
<#-- 结束循环 -->
|
||||
<div class="content">
|
||||
@ -103,6 +106,10 @@
|
||||
import { getAreaTextByCode } from '/@/components/Form/src/utils/Area';
|
||||
</#if>
|
||||
<#if list_need_category>
|
||||
<#if list_has_popup_dict>
|
||||
import {getPopDictByCode} from "@/utils/dict";
|
||||
import {filterMultiDictText} from "@/utils/dict/JDictSelectUtil";
|
||||
</#if>
|
||||
import { loadCategoryData } from '/@/api/common/api'
|
||||
import { getAuthCache, setAuthCache } from '/@/utils/auth';
|
||||
import { DB_DICT_DATA_KEY } from '/@/enums/cacheEnum';
|
||||
@ -158,6 +165,9 @@
|
||||
beforeFetch: (params) => {
|
||||
return Object.assign(params, queryParam);
|
||||
},
|
||||
<#if list_has_popup_dict>
|
||||
afterFetch: afterFetch,
|
||||
</#if>
|
||||
pagination:{
|
||||
current: 1,
|
||||
pageSize: 5,
|
||||
@ -341,6 +351,28 @@
|
||||
}
|
||||
initDictConfig();
|
||||
</#if>
|
||||
|
||||
<#if list_has_popup_dict>
|
||||
/**
|
||||
* 翻译Popup字典配置
|
||||
*/
|
||||
async function afterFetch(records){
|
||||
<#list columns as po>
|
||||
<#if po.isQuery=='Y' || po.isShowList=='Y'>
|
||||
<#if po.classType=='popup_dict' && list_has_popup_dict==true>
|
||||
const ${po.fieldName}Keys = [...new Set(records.map((item) => item['${po.fieldName}']).flatMap((item) => item && item.split(',')))];
|
||||
if(${po.fieldName}Keys && ${po.fieldName}Keys.length){
|
||||
const dictOptions = await getPopDictByCode(${po.fieldName}Keys.join(','), '${po.dictTable},${po.dictField},${po.dictText}');
|
||||
records.forEach((item) => {
|
||||
item['${po.fieldName}_dictText'] = filterMultiDictText(dictOptions, item['${po.fieldName}']);
|
||||
});
|
||||
}
|
||||
</#if>
|
||||
</#if>
|
||||
</#list>
|
||||
return records;
|
||||
}
|
||||
</#if>
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user