|
@@ -2,9 +2,15 @@ package com.xy.service;
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.CharsetUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.http.HttpResponse;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.xy.annotate.Runners;
|
|
|
import com.xy.collections.list.JArrayList;
|
|
@@ -13,6 +19,7 @@ import com.xy.dto.SysDictDto;
|
|
|
import com.xy.entity.SysDict;
|
|
|
import com.xy.entity.SysDictLog;
|
|
|
import com.xy.entity.SysDictRedis;
|
|
|
+import com.xy.error.CommRuntimeException;
|
|
|
import com.xy.mapper.SysDictMapper;
|
|
|
import com.xy.sys.EnumSysDictOperateType;
|
|
|
import com.xy.utils.*;
|
|
@@ -28,6 +35,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
|
import org.springframework.web.bind.annotation.RequestHeader;
|
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
@@ -49,9 +57,33 @@ import static com.xy.utils.PlusBeans.toPageBean;
|
|
|
@Api(tags = "系统字典")
|
|
|
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {
|
|
|
|
|
|
+ private static final String SYNC_DICT_URL = "https://api.mxrvending.com/sys/sys-dict/syncProd";
|
|
|
+ // private static final String SYNC_DICT_URL = "http://119.96.194.20:9050/sys/sys-dict/syncProd";
|
|
|
private RedisService<SysDictRedis> redisService;
|
|
|
private SysDictLogServiceImpl sysDictLogService;
|
|
|
|
|
|
+ /**
|
|
|
+ * post请求
|
|
|
+ *
|
|
|
+ * @param url url
|
|
|
+ * @param body spi参数
|
|
|
+ * @return {@link String}
|
|
|
+ */
|
|
|
+ static String sendPost(String url, String body) {
|
|
|
+ HttpResponse resultStr = HttpRequest.post(url)
|
|
|
+ .header("Content-Type", "application/json") // 修改为 JSON 格式
|
|
|
+ .charset(CharsetUtil.UTF_8)
|
|
|
+ .body(body) // 使用 JSON 字符串作为请求体
|
|
|
+ .timeout(30 * 1000)
|
|
|
+ .execute();
|
|
|
+ String responseBody = resultStr.body();
|
|
|
+ if (resultStr.getStatus() != 200) {
|
|
|
+ log.error("字典同步到生产环境异常: 状态码: {}, 响应体: {},appId:{},notifyId:{}", resultStr.getStatus(), responseBody);
|
|
|
+ return "fail";
|
|
|
+ }
|
|
|
+ return responseBody;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* 全量刷新redis字典数据
|
|
@@ -62,26 +94,240 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|
|
SysDicts.forEach(sysDict -> refuRedis(sysDict));
|
|
|
}
|
|
|
|
|
|
- @ApiOperation("同步到生产环境")
|
|
|
+ /**
|
|
|
+ * 同步到生产环境,处理接收到的字典数据 nacos加白名单
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @return 响应结果
|
|
|
+ */
|
|
|
+ @ApiOperation("同步到生产环境-接收处理")
|
|
|
@PostMapping("syncProd")
|
|
|
- public R syncProd(@RequestBody @Validated SysDictDto.SyncProd syncProd) {
|
|
|
+ public R syncProd(@RequestBody SysDictDto.SyncProd syncProd) {
|
|
|
+ log.info("字典同步数据: {}", JSONUtil.toJsonPrettyStr(syncProd));
|
|
|
String paterCode = syncProd.getPaterCode();
|
|
|
- LambdaQueryWrapper<SysDict> lambdaQueryWrapper = new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, paterCode);
|
|
|
- SysDict sysDict = getOne(lambdaQueryWrapper);
|
|
|
- if (sysDict == null) {
|
|
|
- return R.ok();
|
|
|
+ String code = syncProd.getCode();
|
|
|
+ Integer operateType = syncProd.getOperateType();
|
|
|
+ if (SysDictDto.SYNC_PWD.equals(syncProd.getPwd())) {
|
|
|
+ throw new CommRuntimeException("非法请求!");
|
|
|
}
|
|
|
- List<SysDict> sysDictsAll = new ArrayList<>();
|
|
|
- sysDictsAll.add(sysDict);
|
|
|
- LambdaQueryWrapper<SysDict> lambdaQueryWrapperSub = new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, paterCode);
|
|
|
- List<SysDict> sysDicts = list(lambdaQueryWrapperSub);
|
|
|
- if (CollUtil.isNotEmpty(sysDicts)) {
|
|
|
- sysDictsAll.addAll(sysDicts);
|
|
|
+ try {
|
|
|
+ if (StrUtil.isEmpty(paterCode)) {
|
|
|
+ //根字典
|
|
|
+ handleRootDict(syncProd, code, operateType);
|
|
|
+ } else {
|
|
|
+ //子字典
|
|
|
+ handleChildDict(syncProd, paterCode, operateType);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("同步到生产环境失败", e);
|
|
|
+ return R.fail("同步失败,请稍后重试");
|
|
|
}
|
|
|
- //TODO 同步到生产环境
|
|
|
+
|
|
|
return R.ok();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 处理根字典的操作,根据操作类型决定增加、更新或删除
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @param code 字典代码
|
|
|
+ * @param operateType 操作类型
|
|
|
+ */
|
|
|
+ private void handleRootDict(SysDictDto.SyncProd syncProd, String code, Integer operateType) {
|
|
|
+ switch (operateType) {
|
|
|
+ case 1:
|
|
|
+ addRootDict(syncProd, code);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ updateRootDict(syncProd);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ deleteRootDict(syncProd.getCode());
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ log.warn("未知操作类型: {}", operateType);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理子字典的操作,根据操作类型决定增加、更新或删除
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @param paterCode 父级字典代码
|
|
|
+ * @param operateType 操作类型
|
|
|
+ */
|
|
|
+ private void handleChildDict(SysDictDto.SyncProd syncProd, String paterCode, Integer operateType) {
|
|
|
+ switch (operateType) {
|
|
|
+ case 1:
|
|
|
+ addChildDict(syncProd, paterCode);
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ updateChildDict(syncProd, paterCode);
|
|
|
+ break;
|
|
|
+ case 3:
|
|
|
+ deleteChildDict(syncProd, paterCode);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ log.warn("未知操作类型: {}", operateType);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加根字典,如果字典代码不存在则创建新的字典
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @param code 字典代码
|
|
|
+ */
|
|
|
+ private void addRootDict(SysDictDto.SyncProd syncProd, String code) {
|
|
|
+ long count = count(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, code));
|
|
|
+ if (count <= 0) {
|
|
|
+ SysDict sysDict = createSysDict(syncProd);
|
|
|
+ save(sysDict);
|
|
|
+ refuRedis(sysDict);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新根字典,若不存在则调用添加方法
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ */
|
|
|
+ private void updateRootDict(SysDictDto.SyncProd syncProd) {
|
|
|
+ SysDict sysP = getOne(Wrappers.lambdaQuery(SysDict.class).eq(SysDict::getCode, syncProd.getCode()));
|
|
|
+ if (sysP == null) {
|
|
|
+ addRootDict(syncProd, syncProd.getCode());
|
|
|
+ } else {
|
|
|
+ updateSysDict(sysP, syncProd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除根字典及其相关的子字典
|
|
|
+ *
|
|
|
+ * @param code 字典代码
|
|
|
+ */
|
|
|
+ private void deleteRootDict(String code) {
|
|
|
+ List<SysDict> sysDicts = getRelatedDicts(code);
|
|
|
+ remove(Wrappers.lambdaQuery(SysDict.class).eq(SysDict::getCode, code));
|
|
|
+ remove(Wrappers.lambdaQuery(SysDict.class).eq(SysDict::getPaterCode, code));
|
|
|
+ sysDicts.forEach(this::refuRedis);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加子字典,如果代码不存在则创建新的字典
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @param paterCode 父级字典代码
|
|
|
+ */
|
|
|
+ private void addChildDict(SysDictDto.SyncProd syncProd, String paterCode) {
|
|
|
+ long count = count(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, syncProd.getCode()).eq(SysDict::getPaterCode, paterCode));
|
|
|
+ if (count <= 0) {
|
|
|
+ SysDict sysDict = createSysDict(syncProd);
|
|
|
+ save(sysDict);
|
|
|
+ refuRedis(sysDict);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新子字典,若不存在则调用添加方法
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @param paterCode 父级字典代码
|
|
|
+ */
|
|
|
+ private void updateChildDict(SysDictDto.SyncProd syncProd, String paterCode) {
|
|
|
+ SysDict sysP = getOne(Wrappers.lambdaQuery(SysDict.class)
|
|
|
+ .eq(SysDict::getCode, syncProd.getCode())
|
|
|
+ .eq(SysDict::getPaterCode, paterCode));
|
|
|
+ if (sysP == null) {
|
|
|
+ addChildDict(syncProd, paterCode);
|
|
|
+ } else {
|
|
|
+ updateSysDict(sysP, syncProd);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除子字典
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @param paterCode 父级字典代码
|
|
|
+ */
|
|
|
+ private void deleteChildDict(SysDictDto.SyncProd syncProd, String paterCode) {
|
|
|
+ List<SysDict> list = new ArrayList<>();
|
|
|
+ SysDict sysDict = getOne(Wrappers.lambdaQuery(SysDict.class)
|
|
|
+ .eq(SysDict::getCode, syncProd.getCode())
|
|
|
+ .eq(SysDict::getPaterCode, paterCode));
|
|
|
+ if (sysDict != null) {
|
|
|
+ list.add(sysDict);
|
|
|
+ remove(Wrappers.lambdaQuery(SysDict.class).eq(SysDict::getPaterCode, syncProd.getCode()).eq(SysDict::getCode, syncProd.getCode()));
|
|
|
+ list.forEach(this::refuRedis);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建新的字典对象
|
|
|
+ *
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ * @return 新创建的字典对象
|
|
|
+ */
|
|
|
+ private SysDict createSysDict(SysDictDto.SyncProd syncProd) {
|
|
|
+ SysDict sysDict = BeanUtil.copyProperties(syncProd, SysDict.class);
|
|
|
+ sysDict.setCreateTime(LocalDateTime.now());
|
|
|
+ sysDict.setCreateUser(1L);
|
|
|
+ return sysDict;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新字典对象的属性
|
|
|
+ *
|
|
|
+ * @param sysDict 需要更新的字典对象
|
|
|
+ * @param syncProd 目标字典数据
|
|
|
+ */
|
|
|
+ private void updateSysDict(SysDict sysDict, SysDictDto.SyncProd syncProd) {
|
|
|
+ sysDict.setValue(syncProd.getValue());
|
|
|
+ sysDict.setMsg(syncProd.getMsg());
|
|
|
+ sysDict.setUpdateTime(LocalDateTime.now());
|
|
|
+ updateById(sysDict);
|
|
|
+ refuRedis(sysDict);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据字典代码获取相关的字典
|
|
|
+ *
|
|
|
+ * @param code 字典代码
|
|
|
+ * @return 相关字典列表
|
|
|
+ */
|
|
|
+ private List<SysDict> getRelatedDicts(String code) {
|
|
|
+ List<SysDict> list = new ArrayList<>();
|
|
|
+ SysDict sysDict = getOne(Wrappers.lambdaQuery(SysDict.class).eq(SysDict::getCode, code));
|
|
|
+ if (sysDict != null) {
|
|
|
+ list.add(sysDict);
|
|
|
+ LambdaQueryWrapper<SysDict> lqw = Wrappers.lambdaQuery(SysDict.class).eq(SysDict::getPaterCode, code);
|
|
|
+ List<SysDict> sysDicts = list(lqw);
|
|
|
+ if (CollUtil.isNotEmpty(sysDicts)) {
|
|
|
+ list.addAll(sysDicts);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("手动同步到生产环境")
|
|
|
+ @PostMapping("syncToProd")
|
|
|
+ public R syncToProd(@RequestBody @Validated SysDictDto.SyncToProd syncToProd) {
|
|
|
+ Long id = syncToProd.getId();
|
|
|
+ SysDictLog sysDictLog = sysDictLogService.getById(id);
|
|
|
+ // 确保获取到的字典日志不为空
|
|
|
+ if (sysDictLog == null) {
|
|
|
+ return R.fail("字典日志不存在");
|
|
|
+ }
|
|
|
+ SysDictDto.SyncProd syncProd = BeanUtil.copyProperties(sysDictLog, SysDictDto.SyncProd.class);
|
|
|
+ String res = sendPost(SYNC_DICT_URL, JSONUtil.toJsonStr(syncProd));
|
|
|
+ if ("fail".equals(res)) {
|
|
|
+ return R.fail("同步失败,请稍后重试");
|
|
|
+ }
|
|
|
+ return R.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
@ApiOperation("添加")
|
|
|
@PostMapping("save")
|
|
|
public R save(@RequestBody @Validated SysDictDto.Save save) {
|
|
@@ -113,15 +359,30 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
|
|
|
return R.fail("code已存在");
|
|
|
}
|
|
|
}
|
|
|
+ //如果根字典code修改,则 子字典也要记录日志(作为新增)
|
|
|
+ if (StrUtil.isEmpty(sysDict.getPaterCode()) && !sysDict.getCode().equals(update.getCode())) {
|
|
|
+ LambdaQueryWrapper<SysDict> lambdaQueryWrapper = new LambdaQueryWrapper<SysDict>().eq(SysDict::getPaterCode, sysDict.getCode());
|
|
|
+ List<SysDict> sysDicts = list(lambdaQueryWrapper);
|
|
|
+ if (CollUtil.isNotEmpty(sysDicts)) {
|
|
|
+ //存在子字典,修改日志记录
|
|
|
+ sysDicts.forEach(sd -> {
|
|
|
+ sd.setPaterCode(update.getCode());
|
|
|
+ SysDictLog sysDictLog = BeanUtil.copyProperties(sd, SysDictLog.class);
|
|
|
+ sysDictLogService.handleLog(sysDictLog, EnumSysDictOperateType.ADD);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
//修改字典
|
|
|
SysDict obj = copy(SysDict.class, update)
|
|
|
.update(AuthorizeUtils.getLoginId(Long.class));
|
|
|
updateById(obj);
|
|
|
+
|
|
|
//修改子字典
|
|
|
update(new SysDict().setPaterCode(obj.getCode()), new LambdaQueryWrapper<SysDict>().eq(SysDict::getPaterCode, sysDict.getCode()));
|
|
|
//日志
|
|
|
SysDictLog sysDictLog = BeanUtil.copyProperties(sysDict, SysDictLog.class);
|
|
|
sysDictLogService.handleLog(sysDictLog, EnumSysDictOperateType.UPDATE);
|
|
|
+
|
|
|
//刷新redis
|
|
|
refuRedis(obj);
|
|
|
return R.ok();
|