summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshizhendong <[email protected]>2024-06-26 10:29:24 +0800
committershizhendong <[email protected]>2024-06-26 10:29:24 +0800
commit58431f905304fc1b948f0969a11a04110ea0431e (patch)
treef6fd9521fa0bf5881b861ec4c59b8285be58ca79
parent0f9fff2f41d16a32c3c95606ca192ad2c33b810e (diff)
feat: ASW-2 新增项目基础接口
1. 系统认证接口 2. 用户相关接口 3. i18n 国际化接口
-rw-r--r--src/main/java/net/geedge/asw/common/config/I18nConfig.java122
-rw-r--r--src/main/java/net/geedge/asw/common/config/LocaleConfig.java66
-rw-r--r--src/main/java/net/geedge/asw/common/config/SaTokenConfigure.java2
-rw-r--r--src/main/java/net/geedge/asw/common/config/exception/ASWExceptionHandler.java36
-rw-r--r--src/main/java/net/geedge/asw/common/util/ASWException.java2
-rw-r--r--src/main/java/net/geedge/asw/common/util/Constants.java6
-rw-r--r--src/main/java/net/geedge/asw/common/util/RCode.java24
-rw-r--r--src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java15
-rw-r--r--src/main/java/net/geedge/asw/module/sys/controller/SysI18nController.java136
-rw-r--r--src/main/java/net/geedge/asw/module/sys/controller/SysRoleController.java24
-rw-r--r--src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java59
-rw-r--r--src/main/java/net/geedge/asw/module/sys/dao/SysI18nDao.java10
-rw-r--r--src/main/java/net/geedge/asw/module/sys/entity/SysI18nEntity.java53
-rw-r--r--src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java2
-rw-r--r--src/main/java/net/geedge/asw/module/sys/service/ISysI18nService.java23
-rw-r--r--src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java16
-rw-r--r--src/main/java/net/geedge/asw/module/sys/service/impl/SysI18nServiceImpl.java69
-rw-r--r--src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java17
-rw-r--r--src/main/resources/application-magic-api.yml8
-rw-r--r--src/main/resources/config/logback-spring.xml10
-rw-r--r--src/main/resources/db/migration/R__AZ_sys_i18n.sql44
-rw-r--r--src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql3
22 files changed, 627 insertions, 120 deletions
diff --git a/src/main/java/net/geedge/asw/common/config/I18nConfig.java b/src/main/java/net/geedge/asw/common/config/I18nConfig.java
new file mode 100644
index 0000000..b9621c1
--- /dev/null
+++ b/src/main/java/net/geedge/asw/common/config/I18nConfig.java
@@ -0,0 +1,122 @@
+package net.geedge.asw.common.config;
+
+import cn.hutool.log.Log;
+import jakarta.annotation.PostConstruct;
+import net.geedge.asw.common.util.Constants;
+import net.geedge.asw.common.util.T;
+import net.geedge.asw.module.sys.entity.SysI18nEntity;
+import net.geedge.asw.module.sys.service.ISysI18nService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.context.support.AbstractMessageSource;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.stereotype.Component;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Component
+public class I18nConfig extends AbstractMessageSource implements ResourceLoaderAware {
+
+ private static final Log log = Log.get();
+
+ @Autowired
+ private ISysI18nService sysI18nService;
+
+ /**
+ * 国际化缓存
+ */
+ public static final Map<String, Map<String, String>> I18N_CACHE = new HashMap<>();
+
+ @PostConstruct
+ public void init() {
+ this.reload();
+ }
+
+ /**
+ * 重新将数据库中的国际化配置加载
+ */
+ public void reload() {
+ I18N_CACHE.clear();
+ }
+
+
+ protected ResourceLoader resourceLoader;
+
+ @Override
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = (resourceLoader == null ? new DefaultResourceLoader() : resourceLoader);
+ }
+
+ @Override
+ protected MessageFormat resolveCode(String code, Locale locale) {
+ String msg = this.getSourceFromCache(code, locale);
+ MessageFormat messageFormat = new MessageFormat(msg, locale);
+ return messageFormat;
+ }
+
+ @Override
+ protected String resolveCodeWithoutArguments(String code, Locale locale) {
+ return this.getSourceFromCache(code, locale);
+ }
+
+ /**
+ * 从缓存中取出国际化配置对应的数据 或者从父级获取
+ *
+ * @param code
+ * @param locale
+ * @param param
+ * @return
+ */
+ public String getSourceFromCache(String code, Locale locale, Object... param) {
+ String language = locale.getLanguage();
+ if (T.ObjectUtil.isEmpty(I18N_CACHE)) {
+ this.loadAllMessageResourcesFromDB();
+ }
+ Map<String, String> props = I18N_CACHE.get(language);
+ if (null != props && props.containsKey(code)) {
+ String msg = props.get(code);
+ if (T.ObjectUtil.isEmpty(param)) {
+ return msg;
+ }
+ return MessageFormat.format(msg, param);
+ } else {
+ try {
+ if (null != this.getParentMessageSource()) {
+ return this.getParentMessageSource().getMessage(code, param, locale);
+ }
+ } catch (Exception e) {
+ log.error(e);
+ }
+ return code;
+ }
+ }
+
+ /**
+ * 从数据库中获取所有国际化配置
+ */
+ public void loadAllMessageResourcesFromDB() {
+ List<SysI18nEntity> list = sysI18nService.list();
+ if (T.CollUtil.isNotEmpty(list)) {
+ try {
+ for (String lang : Constants.LANG_LIST) {
+ Map<String, String> langMap = I18N_CACHE.get(lang);
+ langMap = T.ObjectUtil.defaultIfNull(langMap, new HashMap<>());
+ I18N_CACHE.put(lang, langMap);
+
+ List<SysI18nEntity> dataList = list.stream().filter(pojo -> T.StrUtil.equals(lang, pojo.getLang())).collect(Collectors.toList());
+ for (SysI18nEntity entity : dataList) {
+ langMap.put(entity.getCode(), entity.getValue());
+ }
+ }
+ } catch (Exception e) {
+ log.error(e);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/net/geedge/asw/common/config/LocaleConfig.java b/src/main/java/net/geedge/asw/common/config/LocaleConfig.java
new file mode 100644
index 0000000..9908dee
--- /dev/null
+++ b/src/main/java/net/geedge/asw/common/config/LocaleConfig.java
@@ -0,0 +1,66 @@
+package net.geedge.asw.common.config;
+
+import cn.hutool.log.Log;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import net.geedge.asw.common.util.T;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
+
+import java.util.Locale;
+
+@Configuration
+@EnableAutoConfiguration
+@ComponentScan
+public class LocaleConfig implements WebMvcConfigurer {
+
+ @Bean
+ public LocaleResolver localeResolver() {
+ SessionLocaleResolver slr = new SessionLocaleResolver();
+ // 默认语言
+ slr.setDefaultLocale(Locale.of("en"));
+ return slr;
+ }
+
+ @Bean
+ public LocaleChangeInterceptor localeChangeInterceptor() {
+ MyI18nInterceptor lci = new MyI18nInterceptor();
+ // 参数名
+ lci.setParamName("Language");
+ return lci;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(localeChangeInterceptor());
+ }
+
+}
+
+class MyI18nInterceptor extends LocaleChangeInterceptor {
+
+ private static final Log log = Log.get();
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+ try {
+ String language = request.getHeader(getParamName());
+ if (T.ObjectUtil.isNotEmpty(language)) {
+ Locale locale = parseLocaleValue(language);
+ LocaleContextHolder.setLocale(locale);
+ }
+ } catch (Exception e) {
+ log.error(e, "[preHandle] [error]");
+ }
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/net/geedge/asw/common/config/SaTokenConfigure.java b/src/main/java/net/geedge/asw/common/config/SaTokenConfigure.java
index 958c36c..3ebbd07 100644
--- a/src/main/java/net/geedge/asw/common/config/SaTokenConfigure.java
+++ b/src/main/java/net/geedge/asw/common/config/SaTokenConfigure.java
@@ -47,7 +47,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
// 注册 Sa-Token 拦截器,打开注解式鉴权功能
registry.addInterceptor(new SaInterceptor(handler -> {
SaRouter.match("/file/**").notMatch("/file/content/*").check(r -> StpUtil.checkLogin());
- SaRouter.match("/sys/**").notMatch("/sys/login").check(r -> StpUtil.checkLogin());
+ SaRouter.match("/api/v1/**").notMatch("/api/v1/login").check(r -> StpUtil.checkLogin());
})).addPathPatterns("/**");
}
}
diff --git a/src/main/java/net/geedge/asw/common/config/exception/ASWExceptionHandler.java b/src/main/java/net/geedge/asw/common/config/exception/ASWExceptionHandler.java
index c91c9db..c61c312 100644
--- a/src/main/java/net/geedge/asw/common/config/exception/ASWExceptionHandler.java
+++ b/src/main/java/net/geedge/asw/common/config/exception/ASWExceptionHandler.java
@@ -1,18 +1,20 @@
package net.geedge.asw.common.config.exception;
-import org.apache.catalina.connector.ClientAbortException;
-import org.springframework.dao.DuplicateKeyException;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-
import cn.dev33.satoken.exception.NotLoginException;
import cn.hutool.log.Log;
import jakarta.servlet.http.HttpServletRequest;
import net.geedge.asw.common.util.ASWException;
import net.geedge.asw.common.util.R;
import net.geedge.asw.common.util.RCode;
+import net.geedge.asw.common.util.T;
+import net.geedge.asw.module.sys.service.ISysI18nService;
+import org.apache.catalina.connector.ClientAbortException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 异常处理器
@@ -22,6 +24,9 @@ public class ASWExceptionHandler {
private static final Log log = Log.get();
+ @Autowired
+ private ISysI18nService sysI18nService;
+
/**
* 处理自定义异常
*/
@@ -29,7 +34,19 @@ public class ASWExceptionHandler {
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public R handleDHException(ASWException e, HttpServletRequest request) {
log.warn(e, "Request uri: {}", request.getRequestURI());
- return R.error(e.getCode(), e.getMsg());
+ R r = new R();
+ r.put("code", e.getCode());
+ String msg = "";
+ // by code
+ if (T.ObjectUtil.isNotEmpty(e.getCode())) {
+ msg = sysI18nService.queryValueByName(T.StrUtil.toString(e.getCode()), e.getParam());
+ }
+ if (T.StrUtil.isEmpty(msg) && (T.ObjectUtil.isEmpty(e.getRCode()) || T.ObjectUtil.equals(msg, e.getRCode().toString()))) {
+ r.put("msg", e.getMsg());
+ } else {
+ r.put("msg", msg);
+ }
+ return r;
}
/**
@@ -49,7 +66,8 @@ public class ASWExceptionHandler {
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public R handleDuplicateKeyException(DuplicateKeyException e, HttpServletRequest request) {
log.error(e, "Request uri: {}", request.getRequestURI());
- return R.error(RCode.SYS_DUPLICATE_RECORD);
+ String msg = sysI18nService.queryValueByName(RCode.SYS_DUPLICATE_RECORD.getCode().toString());
+ return R.error(RCode.SYS_DUPLICATE_RECORD.getCode(), msg);
}
@ExceptionHandler(Exception.class)
diff --git a/src/main/java/net/geedge/asw/common/util/ASWException.java b/src/main/java/net/geedge/asw/common/util/ASWException.java
index 47d56d9..eb47acc 100644
--- a/src/main/java/net/geedge/asw/common/util/ASWException.java
+++ b/src/main/java/net/geedge/asw/common/util/ASWException.java
@@ -12,12 +12,14 @@ public class ASWException extends RuntimeException {
private String msg = RCode.ERROR.getMsg();
private int code = RCode.ERROR.getCode();
private Object[] param = new Object[] {};
+ private RCode rCode;
public ASWException(RCode rCode) {
super(rCode.getMsg());
this.code = rCode.getCode();
this.msg = rCode.getMsg();
this.param = rCode.getParam();
+ this.rCode = rCode;
}
public ASWException(String msg) {
diff --git a/src/main/java/net/geedge/asw/common/util/Constants.java b/src/main/java/net/geedge/asw/common/util/Constants.java
index d2e343f..b2f6fd6 100644
--- a/src/main/java/net/geedge/asw/common/util/Constants.java
+++ b/src/main/java/net/geedge/asw/common/util/Constants.java
@@ -1,6 +1,7 @@
package net.geedge.asw.common.util;
import java.io.File;
+import java.util.List;
public class Constants {
@@ -14,6 +15,9 @@ public class Constants {
*/
public static final String TEMP_PATH = System.getProperty("user.dir") + File.separator + "tmp";
+ /**
+ * 国际化语言列表
+ */
+ public static final List<String> LANG_LIST = T.ListUtil.of("en", "zh");
-
}
diff --git a/src/main/java/net/geedge/asw/common/util/RCode.java b/src/main/java/net/geedge/asw/common/util/RCode.java
index f242b15..6308e8a 100644
--- a/src/main/java/net/geedge/asw/common/util/RCode.java
+++ b/src/main/java/net/geedge/asw/common/util/RCode.java
@@ -5,7 +5,7 @@ import java.text.MessageFormat;
public enum RCode {
/**
- * 10**** : 系统认证 或 通用错误提示 20**** : screen module
+ * 10**** : 系统认证 或 通用错误提示 20**** : sys module
*/
ERROR(999, "error"), // 通用错误/未知错误
@@ -19,28 +19,6 @@ public enum RCode {
USER_NO_LOGIN(100007, "user not login"), // 用户未登录
SYS_RECORD_NOT_FOUND(100008, "record not found"),// 未找到记录
-
- SCREEN_ID_CANNOT_EMPTY(200001, "id cannot be empty"),
-
- SCREE_DATASOURCE_DEFAULT_CANNOT_BE_DELETE(300001,"The default data source cannot be deleted."),
- SCREE_DATASOURCE_REPEAT(300002,"Screen datasource name duplicate"),
-
- /**
- * import
- */
- EXCELFILE_TYPE_ERROR(400001, "The type can only be xlsx, json, csv"),
- EXCELFILE_PARSE_ERROR(400002, "Import file resolution failed"),
- EXCELFILE_HEADER_TEMPLATE_ERROR(400003,"The header row of the import template is inconsistent with the system template"),
- EXCELFILE_HEADER_LANGUAGE_ERROR(400004, "Language must be en, zh or ru"),
- EXCELFILE_IMPORT_FILE_ISNULL(400005, "Import file is null"),
- EXCELFILE_HEADER_LANGUAGE_ISNULL(400006, "Language can not be empty"),
- EXCELFILE_IMPORT_ERROR(400007, "File import error"),
- EXCELFILE_SCHEDULE_TASK_IS_NULL(400008, "Schedule task can not be empty"),
- EXCELFILE_SCHEDULE_CRON_IS_NULL(400009, "Schedule cron can not be empty"),
- EXCELFILE_SCHEDULE_ENABLE_IS_NULL(400010, "Schedule enable can not be empty"),
- EXCELFILE_SCHEDULE_SCRIPT_IS_NULL(400011, "Schedule script can not be empty"),
-
-
SUCCESS(200, "success"); // 成功
private RCode(Integer code, String msg) {
diff --git a/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java b/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java
index 0fb8979..0a1ff37 100644
--- a/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java
+++ b/src/main/java/net/geedge/asw/module/sys/controller/SysAuthController.java
@@ -1,14 +1,5 @@
package net.geedge.asw.module.sys.controller;
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import net.geedge.asw.common.util.R;
@@ -16,9 +7,13 @@ import net.geedge.asw.common.util.RCode;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.sys.entity.SysUserEntity;
import net.geedge.asw.module.sys.service.ISysAuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
@RestController
-@RequestMapping("/sys")
+@RequestMapping("/api/v1")
public class SysAuthController {
@Autowired
diff --git a/src/main/java/net/geedge/asw/module/sys/controller/SysI18nController.java b/src/main/java/net/geedge/asw/module/sys/controller/SysI18nController.java
new file mode 100644
index 0000000..88f4887
--- /dev/null
+++ b/src/main/java/net/geedge/asw/module/sys/controller/SysI18nController.java
@@ -0,0 +1,136 @@
+package net.geedge.asw.module.sys.controller;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import net.geedge.asw.common.util.ASWException;
+import net.geedge.asw.common.util.R;
+import net.geedge.asw.common.util.RCode;
+import net.geedge.asw.common.util.T;
+import net.geedge.asw.module.sys.entity.SysI18nEntity;
+import net.geedge.asw.module.sys.entity.SysUserEntity;
+import net.geedge.asw.module.sys.service.ISysI18nService;
+import net.geedge.asw.module.sys.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/api/v1/i18n")
+public class SysI18nController {
+
+ @Autowired
+ private ISysUserService userService;
+
+ @Autowired
+ private ISysI18nService sysI18nService;
+
+ @GetMapping("/{id}")
+ public R detail(@PathVariable("id") String id) {
+ SysI18nEntity entity = sysI18nService.getById(id);
+ if (T.ObjectUtil.isNotNull(entity)) {
+ SysUserEntity user = userService.getById(entity.getUid());
+ user.setPwd(null);
+ entity.setUpdateUser(user);
+ }
+ return R.ok().putData("record", entity);
+ }
+
+ @GetMapping
+ public R list(String ids, String q, String lang, String code, String value,
+ @RequestParam(defaultValue = "1") Integer current,
+ @RequestParam(defaultValue = "20") Integer size,
+ @RequestParam(defaultValue = "name") String orderBy) {
+ QueryWrapper<SysI18nEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.in(T.StrUtil.isNotEmpty(ids), "id", T.StrUtil.split(ids, ','));
+ if (T.StrUtil.isNotBlank(q)) {
+ queryWrapper.and(wrapper -> wrapper.like("lang", q)
+ .or().like("code", q)
+ .or().like("value", q)
+ .or().like("remark", q)
+ );
+ }
+ queryWrapper.eq(T.StrUtil.isNotEmpty(lang), "lang", lang);
+ queryWrapper.like(T.StrUtil.isNotEmpty(code), "code", code);
+ queryWrapper.like(T.StrUtil.isNotEmpty(value), "value", value);
+ Page<SysI18nEntity> page = Page.of(current, size);
+ page.addOrder(T.PageUtil.decodeOrderByStr(orderBy));
+ page = sysI18nService.page(page, queryWrapper);
+ return R.ok(page);
+ }
+
+
+ @PostMapping
+ public R add(@RequestBody SysI18nEntity entity) {
+ T.VerifyUtil.is(entity).notNull()
+ .and(entity.getCode()).notEmpty()
+ .and(entity.getValue()).notEmpty()
+ .and(entity.getLang()).notEmpty();
+ SysI18nEntity one = sysI18nService.getOne(new LambdaQueryWrapper<SysI18nEntity>()
+ .eq(SysI18nEntity::getCode, entity.getCode())
+ .eq(SysI18nEntity::getLang, entity.getLang()));
+ if (T.ObjectUtil.isNotNull(one)) {
+ throw ASWException.builder().rcode(RCode.SYS_DUPLICATE_RECORD).build();
+ }
+ if (T.ObjectUtil.isEmpty(entity.getName())) {
+ entity.setName(entity.getCode());
+ }
+ entity.setUts(System.currentTimeMillis());
+ entity.setUid(StpUtil.getLoginIdAsString());
+ sysI18nService.save(entity);
+ return R.ok().putData("id", entity.getId());
+ }
+
+ @PutMapping
+ public R update(@RequestBody SysI18nEntity entity) {
+ T.VerifyUtil.is(entity).notNull()
+ .and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY)
+ .and(entity.getCode()).notEmpty()
+ .and(entity.getValue()).notEmpty()
+ .and(entity.getLang()).notEmpty();
+ SysI18nEntity one = sysI18nService.getOne(new LambdaQueryWrapper<SysI18nEntity>()
+ .eq(SysI18nEntity::getCode, entity.getCode())
+ .eq(SysI18nEntity::getLang, entity.getLang())
+ .ne(SysI18nEntity::getId, entity.getId()));
+ if (T.ObjectUtil.isNotNull(one)) {
+ throw ASWException.builder().rcode(RCode.SYS_DUPLICATE_RECORD).build();
+ }
+ if (T.ObjectUtil.isEmpty(entity.getName())) {
+ entity.setName(entity.getCode());
+ }
+ entity.setUts(System.currentTimeMillis());
+ entity.setUid(StpUtil.getLoginIdAsString());
+ sysI18nService.updateById(entity);
+ return R.ok().putData("id", entity.getId());
+ }
+
+ @DeleteMapping
+ public R delete(String[] ids) {
+ T.VerifyUtil.is(ids).notEmpty();
+ sysI18nService.removeBatchByIds(T.ListUtil.of(ids));
+ return R.ok();
+ }
+
+ @GetMapping("/lang")
+ public R lang(@RequestParam(required = false, defaultValue = "en,zh") String l) {
+ List<String> langList = T.StrUtil.split(l, ',');
+ Map result = T.MapUtil.builder().build();
+ for (String lang : langList) {
+ List<SysI18nEntity> dataList = sysI18nService.list(new LambdaQueryWrapper<SysI18nEntity>().eq(SysI18nEntity::getLang, lang));
+ Map<String, String> collect = dataList.stream().collect(Collectors.toMap(SysI18nEntity::getCode, SysI18nEntity::getValue));
+ result.put(lang, collect);
+ }
+ return R.ok(result);
+ }
+
+ @PutMapping("/clearCache")
+ public R clearCache() {
+ sysI18nService.clearCache();
+ return R.ok();
+ }
+
+}
diff --git a/src/main/java/net/geedge/asw/module/sys/controller/SysRoleController.java b/src/main/java/net/geedge/asw/module/sys/controller/SysRoleController.java
index 80c00e5..5afe814 100644
--- a/src/main/java/net/geedge/asw/module/sys/controller/SysRoleController.java
+++ b/src/main/java/net/geedge/asw/module/sys/controller/SysRoleController.java
@@ -1,29 +1,19 @@
package net.geedge.asw.module.sys.controller;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
+import cn.hutool.log.Log;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-
-import cn.hutool.log.Log;
import net.geedge.asw.common.util.ASWException;
import net.geedge.asw.common.util.R;
import net.geedge.asw.common.util.RCode;
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.sys.entity.SysRoleEntity;
import net.geedge.asw.module.sys.service.ISysRoleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
@RestController
-@RequestMapping("/sys/role")
+@RequestMapping("/api/v1/role")
public class SysRoleController {
private static final Log log = Log.get();
@@ -37,8 +27,10 @@ public class SysRoleController {
}
@GetMapping
- public R list(String ids, String name, @RequestParam(defaultValue = "1") Integer current,
- @RequestParam(defaultValue = "20") Integer size, @RequestParam(defaultValue = "name") String orderBy) {
+ public R list(String ids, String name,
+ @RequestParam(defaultValue = "1") Integer current,
+ @RequestParam(defaultValue = "20") Integer size,
+ @RequestParam(defaultValue = "name") String orderBy) {
QueryWrapper<SysRoleEntity> queryWrapper = new QueryWrapper<SysRoleEntity>();
queryWrapper.like(T.StrUtil.isNotBlank(name), "name", name).in(T.StrUtil.isNotBlank(ids), "id", ids.split(","));
Page<SysRoleEntity> page = Page.of(current, size);
diff --git a/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java b/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java
index 328b8a5..f97314c 100644
--- a/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java
+++ b/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java
@@ -1,34 +1,24 @@
package net.geedge.asw.module.sys.controller;
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
+import cn.hutool.log.Log;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-
-import cn.hutool.log.Log;
-import net.geedge.asw.common.util.ASWException;
-import net.geedge.asw.common.util.Constants;
-import net.geedge.asw.common.util.R;
-import net.geedge.asw.common.util.RCode;
-import net.geedge.asw.common.util.T;
+import net.geedge.asw.common.util.*;
import net.geedge.asw.module.sys.entity.SysRoleEntity;
import net.geedge.asw.module.sys.entity.SysUserEntity;
+import net.geedge.asw.module.sys.entity.SysUserRoleEntity;
import net.geedge.asw.module.sys.service.ISysRoleService;
+import net.geedge.asw.module.sys.service.ISysUserRoleService;
import net.geedge.asw.module.sys.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
@RestController
-@RequestMapping("/sys/user")
+@RequestMapping("/api/v1/user")
public class SysUserController {
private static final Log log = Log.get();
@@ -36,24 +26,35 @@ public class SysUserController {
private ISysUserService userService;
@Autowired
private ISysRoleService roleService;
+ @Autowired
+ private ISysUserRoleService uerRoleService;
@GetMapping("/{id}")
public R detail(@PathVariable("id") String id) {
SysUserEntity entity = userService.getById(id);
- entity.setPwd(null);
- List<SysRoleEntity> roleList = roleService.listByIds(T.ListUtil.of(entity.getRoleIds()));
- entity.setRoles(roleList);
+ if (T.ObjectUtil.isNotNull(entity)) {
+ entity.setPwd(null);
+ List<SysUserRoleEntity> userRoleList = uerRoleService.list(new LambdaQueryWrapper<SysUserRoleEntity>().eq(SysUserRoleEntity::getUserId, entity.getId()));
+ if (T.CollUtil.isNotEmpty(userRoleList)) {
+ List<String> roleIds = userRoleList.stream().map(SysUserRoleEntity::getRoleId).collect(Collectors.toList());
+ List<SysRoleEntity> roleList = roleService.listByIds(roleIds);
+ entity.setRoles(roleList);
+ }
+ }
return R.ok().putData("record", entity);
}
@GetMapping
- public R list(String name, @RequestParam(defaultValue = "1") Integer current,
- @RequestParam(defaultValue = "20") Integer size, @RequestParam(defaultValue = "name") String orderBy) {
- QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<SysUserEntity>();
+ public R list(String ids, String q,
+ @RequestParam(defaultValue = "1") Integer current,
+ @RequestParam(defaultValue = "20") Integer size,
+ @RequestParam(defaultValue = "name") String orderBy) {
+ QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
// 不查询 pwd 列
queryWrapper.select(SysUserEntity.class, entity -> !entity.getColumn().equals("pwd"));
- if (T.StrUtil.isNotBlank(name)) {
- queryWrapper.and(wrapper -> wrapper.like("name", name).or().like("user_name", name));
+ queryWrapper.in(T.StrUtil.isNotEmpty(ids), "id", T.StrUtil.split(ids, ','));
+ if (T.StrUtil.isNotBlank(q)) {
+ queryWrapper.and(wrapper -> wrapper.like("name", q).or().like("user_name", q));
}
Page<SysUserEntity> page = Page.of(current, size);
page.addOrder(T.PageUtil.decodeOrderByStr(orderBy));
diff --git a/src/main/java/net/geedge/asw/module/sys/dao/SysI18nDao.java b/src/main/java/net/geedge/asw/module/sys/dao/SysI18nDao.java
new file mode 100644
index 0000000..8db1c11
--- /dev/null
+++ b/src/main/java/net/geedge/asw/module/sys/dao/SysI18nDao.java
@@ -0,0 +1,10 @@
+package net.geedge.asw.module.sys.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import net.geedge.asw.module.sys.entity.SysI18nEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SysI18nDao extends BaseMapper<SysI18nEntity> {
+
+}
diff --git a/src/main/java/net/geedge/asw/module/sys/entity/SysI18nEntity.java b/src/main/java/net/geedge/asw/module/sys/entity/SysI18nEntity.java
new file mode 100644
index 0000000..a99ef00
--- /dev/null
+++ b/src/main/java/net/geedge/asw/module/sys/entity/SysI18nEntity.java
@@ -0,0 +1,53 @@
+package net.geedge.asw.module.sys.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 lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@TableName("sys_i18n")
+public class SysI18nEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ /**
+ * 主键
+ */
+ @TableId(type = IdType.AUTO)
+ private Long id;
+ /**
+ * 名称
+ */
+ private String name;
+ /**
+ * i18n code
+ */
+ private String code;
+ /**
+ * 语言
+ */
+ private String lang;
+ /**
+ * 翻译值
+ */
+ private String value;
+ /**
+ * 备注信息
+ */
+ private String remark;
+ /**
+ * 操作人
+ */
+ private String uid;
+ /**
+ * 操作时间
+ */
+ private Long uts;
+
+ @TableField(exist = false)
+ private SysUserEntity updateUser;
+
+}
diff --git a/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java b/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java
index d9ad678..803aa6c 100644
--- a/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java
+++ b/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java
@@ -20,7 +20,7 @@ public class SysUserEntity {
private String userName;
private String pwd;
@TableField(exist = false)
- private String[] roleIds;
+ private String roleIds;
@TableField(exist = false)
private List<SysRoleEntity> roles;
private Long createTimestamp;
diff --git a/src/main/java/net/geedge/asw/module/sys/service/ISysI18nService.java b/src/main/java/net/geedge/asw/module/sys/service/ISysI18nService.java
new file mode 100644
index 0000000..7eb7e92
--- /dev/null
+++ b/src/main/java/net/geedge/asw/module/sys/service/ISysI18nService.java
@@ -0,0 +1,23 @@
+package net.geedge.asw.module.sys.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import net.geedge.asw.module.sys.entity.SysI18nEntity;
+
+import java.util.Locale;
+
+public interface ISysI18nService extends IService<SysI18nEntity> {
+
+ String queryValue(String code);
+
+ String queryValue(String code, Object... param);
+
+ String queryValue(String code, String lang);
+
+ String queryValue(String code, Locale locale, Object... param);
+
+ String queryValueByName(String name, Object... param);
+
+ void clearCache();
+
+}
+
diff --git a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java
index 5de1c45..ec39cf5 100644
--- a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java
+++ b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java
@@ -1,16 +1,8 @@
package net.geedge.asw.module.sys.service.impl;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.log.Log;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import net.geedge.asw.common.util.ASWException;
import net.geedge.asw.common.util.Constants;
import net.geedge.asw.common.util.RCode;
@@ -21,6 +13,12 @@ import net.geedge.asw.module.sys.entity.SysMenuEntity;
import net.geedge.asw.module.sys.entity.SysRoleEntity;
import net.geedge.asw.module.sys.entity.SysUserEntity;
import net.geedge.asw.module.sys.service.ISysAuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
@Service
public class SysAuthServiceImpl implements ISysAuthService {
diff --git a/src/main/java/net/geedge/asw/module/sys/service/impl/SysI18nServiceImpl.java b/src/main/java/net/geedge/asw/module/sys/service/impl/SysI18nServiceImpl.java
new file mode 100644
index 0000000..5cf1c5c
--- /dev/null
+++ b/src/main/java/net/geedge/asw/module/sys/service/impl/SysI18nServiceImpl.java
@@ -0,0 +1,69 @@
+package net.geedge.asw.module.sys.service.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import net.geedge.asw.common.config.I18nConfig;
+import net.geedge.asw.common.util.T;
+import net.geedge.asw.module.sys.dao.SysI18nDao;
+import net.geedge.asw.module.sys.entity.SysI18nEntity;
+import net.geedge.asw.module.sys.service.ISysI18nService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Locale;
+
+@Service
+public class SysI18nServiceImpl extends ServiceImpl<SysI18nDao, SysI18nEntity> implements ISysI18nService {
+
+ @Autowired
+ private I18nConfig i18nConfig;
+
+ @Override
+ public String queryValue(String code) {
+ return this.queryValue(code, this.getLocale());
+ }
+
+ @Override
+ public String queryValue(String code, Object... param) {
+ return this.queryValue(code, this.getLocale(), param);
+ }
+
+ @Override
+ public String queryValue(String code, String lang) {
+ return this.queryValue(code, Locale.of(lang));
+ }
+
+ @Override
+ public String queryValue(String code, Locale locale, Object... param) {
+ return i18nConfig.getSourceFromCache(code, locale, param);
+ }
+
+ @Override
+ public String queryValueByName(String name, Object... param) {
+ String language = this.getLocale().getLanguage();
+ List<SysI18nEntity> list = this.list(new LambdaQueryWrapper<SysI18nEntity>().eq(SysI18nEntity::getName, name).eq(SysI18nEntity::getLang, language));
+ if (T.CollUtil.isEmpty(list)) {
+ return StrUtil.EMPTY;
+ }
+ SysI18nEntity sysI18nEntity = list.stream().findFirst().get();
+ return this.queryValue(sysI18nEntity.getCode(), this.getLocale(), param);
+ }
+
+ @Override
+ public void clearCache() {
+ i18nConfig.reload();
+ }
+
+ /**
+ * getLocale
+ *
+ * @return
+ */
+ private Locale getLocale() {
+ return LocaleContextHolder.getLocale();
+ }
+
+}
diff --git a/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java b/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java
index a89aa44..4eeb300 100644
--- a/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java
+++ b/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java
@@ -1,20 +1,17 @@
package net.geedge.asw.module.sys.service.impl;
-import java.util.List;
-import java.util.stream.Stream;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-
import net.geedge.asw.common.util.T;
import net.geedge.asw.module.sys.dao.SysUserDao;
import net.geedge.asw.module.sys.entity.SysUserEntity;
import net.geedge.asw.module.sys.entity.SysUserRoleEntity;
import net.geedge.asw.module.sys.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements ISysUserService {
@@ -32,9 +29,9 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> i
this.saveOrUpdate(entity);
// 保存 user role关系
List<SysUserRoleEntity> urList = T.ListUtil.list(false);
- Stream.of(entity.getRoleIds()).forEach(roleId -> {
+ for (String roleId : T.StrUtil.split(entity.getRoleIds(), ",")) {
urList.add(SysUserRoleEntity.builder().roleId(roleId).userId(entity.getId()).build());
- });
+ }
userRoleService.saveBatch(urList);
}
diff --git a/src/main/resources/application-magic-api.yml b/src/main/resources/application-magic-api.yml
index 64266ce..038d2d1 100644
--- a/src/main/resources/application-magic-api.yml
+++ b/src/main/resources/application-magic-api.yml
@@ -62,13 +62,13 @@ magic-api:
swagger:
version: 1.0
description: Digital Horizon API 接口信息
- title: DH API Swagger Docs
- name: DH API 接口
- location: /v2/api-docs/dh-api/swagger2.json
+ title: ASW Controller Swagger Docs
+ name: ASW Controller 接口
+ location: /v2/api-docs/asw-controller/swagger2.json
debug:
timeout: 60 # 断点超时时间,默认60s
task:
- thread-name-prefix: dh-task- #线程池名字前缀
+ thread-name-prefix: asw-controller-task- #线程池名字前缀
log: true # 打印日志
pool:
size: 8 #线程池大小,默认值为CPU核心数
diff --git a/src/main/resources/config/logback-spring.xml b/src/main/resources/config/logback-spring.xml
index 1dbdc8a..e107ee2 100644
--- a/src/main/resources/config/logback-spring.xml
+++ b/src/main/resources/config/logback-spring.xml
@@ -7,7 +7,7 @@
<logger name="org.springframework" level="info" />
<logger name="druid.sql" level="info" />
- <property name="log.path" value="/var/log/dh/" />
+ <property name="log.path" value="/var/log/asw-controller/" />
<!-- 输出格式 -->
<property name="out.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" />
<!-- 活动文件的大小 -->
@@ -20,7 +20,7 @@
<!-- 2.2 level为 INFO 日志,时间滚动输出 -->
<appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
- <file>${log.path}/dh-web.log</file>
+ <file>${log.path}/asw-controller.log</file>
<!--日志文档输出格式 -->
<encoder>
<pattern>${out.pattern}</pattern>
@@ -28,7 +28,7 @@
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
- <fileNamePattern>${log.path}/dh-web-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <fileNamePattern>${log.path}/asw-controller-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>${max.file.size}</maxFileSize>
<maxHistory>${max.history}</maxHistory>
<totalSizeCap>${total.size.cap}</totalSizeCap>
@@ -38,7 +38,7 @@
<!-- 2.1 level为 ERROR 日志,时间滚动输出 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文档的路径及文档名 -->
- <file>${log.path}/dh-web-error.log</file>
+ <file>${log.path}/asw-controller-error.log</file>
<!--日志文档输出格式 -->
<encoder>
<pattern>${out.pattern}</pattern>
@@ -46,7 +46,7 @@
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
- <fileNamePattern>${log.path}/dh-web-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+ <fileNamePattern>${log.path}/asw-controller-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>${max.file.size}</maxFileSize>
<maxHistory>${max.history}</maxHistory>
<totalSizeCap>${total.size.cap}</totalSizeCap>
diff --git a/src/main/resources/db/migration/R__AZ_sys_i18n.sql b/src/main/resources/db/migration/R__AZ_sys_i18n.sql
new file mode 100644
index 0000000..dd5d3b0
--- /dev/null
+++ b/src/main/resources/db/migration/R__AZ_sys_i18n.sql
@@ -0,0 +1,44 @@
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for sys_i18n
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_i18n`;
+CREATE TABLE `sys_i18n` (
+ `id` int(10) NOT NULL AUTO_INCREMENT,
+ `name` varchar(128) NOT NULL COMMENT '名称',
+ `code` varchar(128) NOT NULL COMMENT 'code码',
+ `value` longtext NOT NULL COMMENT '翻译值',
+ `lang` varchar(64) NOT NULL COMMENT '语言',
+ `remark` varchar(512) NOT NULL DEFAULT '' COMMENT '备注',
+ `uid` varchar(64) NOT NULL COMMENT '更新人',
+ `uts` bigint(20) NOT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_lang_code`(`lang`, `code`) USING BTREE
+) ENGINE=InnoDB ROW_FORMAT=Dynamic DEFAULT CHARSET=utf8mb4;
+
+
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (1, '999', 'ERROR', 'error', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (3, '999', 'ERROR', '错误', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (5, '100001', 'SYS_USER_PWD_ERROR', 'username or password error', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (7, '100001', 'SYS_USER_PWD_ERROR', '用户名或密码错误', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (9, '100002', 'SYS_DUPLICATE_RECORD', 'duplicate record', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (11, '100002', 'SYS_DUPLICATE_RECORD', '重复记录', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (13, '100003', 'SYS_NO_AUTH', 'Permission denied', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (15, '100003', 'SYS_NO_AUTH', '没有权限', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (17, '100004', 'ID_CANNOT_EMPTY', 'id cannot be empty', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (19, '100004', 'ID_CANNOT_EMPTY', 'id不能为空', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (21, '100005', 'NAME_CANNOT_EMPTY', 'name cannot be empty', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (23, '100005', 'NAME_CANNOT_EMPTY', '名称不能为空', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (25, '100006', 'PARAM_CANNOT_EMPTY', 'parameter cannot be empty', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (27, '100006', 'PARAM_CANNOT_EMPTY', '参数不能为空', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (29, '100007', 'USER_NO_LOGIN', 'user not login', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (31, '100007', 'USER_NO_LOGIN', '用户未登录', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (33, '100008', 'SYS_RECORD_NOT_FOUND', 'record not found', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (35, '100008', 'SYS_RECORD_NOT_FOUND', '找不到记录', 'zh', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (37, '200', 'SUCCESS', 'success', 'en', '', 'admin', 1719280800000);
+INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `uid`, `uts`) VALUES (39, '200', 'SUCCESS', '成功', 'zh', '', 'admin', 1719280800000);
+
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql
index c46f34d..fb2a4c6 100644
--- a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql
+++ b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql
@@ -56,8 +56,7 @@ CREATE TABLE `sys_menu` (
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`user_id` varchar(64) NOT NULL,
- `role_id` varchar(64) NOT NULL,
- PRIMARY KEY (`user_id`) USING BTREE
+ `role_id` varchar(64) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
DROP TABLE IF EXISTS `sys_role_menu`;