123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- package com.xy.service;
- import cn.hutool.core.bean.BeanUtil;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.util.BooleanUtil;
- 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;
- import com.xy.collections.list.JList;
- 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.*;
- import io.swagger.annotations.Api;
- import io.swagger.annotations.ApiOperation;
- import lombok.AllArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.validation.annotation.Validated;
- 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;
- import static com.xy.utils.Beans.copy;
- import static com.xy.utils.PlusBeans.toIPage;
- import static com.xy.utils.PlusBeans.toPageBean;
- /**
- * <p>
- * 字典表 服务实现类
- * </p>
- *
- * @author lijin
- * @since 2022-12-09
- */
- @Slf4j
- @Service
- @AllArgsConstructor
- @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字典数据
- */
- @Async
- public void refreshAll() {
- List<SysDict> SysDicts = this.list();
- SysDicts.forEach(sysDict -> refuRedis(sysDict));
- }
- /**
- * 同步到生产环境,处理接收到的字典数据 nacos加白名单
- *
- * @param syncProd 目标字典数据
- * @return 响应结果
- */
- @ApiOperation("同步到生产环境-接收处理")
- @PostMapping("syncProd")
- public R syncProd(@RequestBody SysDictDto.SyncProd syncProd) {
- log.info("字典同步数据: {}", JSONUtil.toJsonPrettyStr(syncProd));
- String paterCode = syncProd.getPaterCode();
- String code = syncProd.getCode();
- Integer operateType = syncProd.getOperateType();
- if (!SysDictDto.SYNC_PWD.equals(syncProd.getPwd())) {
- throw new CommRuntimeException("非法请求!");
- }
- try {
- if (StrUtil.isEmpty(paterCode)) {
- //根字典
- handleRootDict(syncProd, code, operateType);
- } else {
- //子字典
- handleChildDict(syncProd, paterCode, operateType);
- }
- } catch (Exception e) {
- log.error("同步到生产环境失败", e);
- return R.fail("同步失败,请稍后重试");
- }
- 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("字典日志不存在");
- }
- Boolean isSync = sysDictLog.getIsSync();
- if (BooleanUtil.isTrue(isSync)) {
- return R.fail("已同步,请勿重复操作");
- }
- Integer sysDictId = sysDictLog.getSysDictId();
- SysDict sysDict = getById(sysDictId);
- SysDictDto.SyncProd syncProd = BeanUtil.copyProperties(sysDictLog, SysDictDto.SyncProd.class);
- syncProd.setValue(sysDictLog.getValue());
- if (sysDict != null) {
- //非删除
- syncProd.setCssClass(sysDict.getCssClass());
- syncProd.setListClass(sysDict.getListClass());
- syncProd.setOrders(sysDict.getOrders());
- }
- syncProd.setPwd(SysDictDto.SYNC_PWD);
- String body = JSONUtil.toJsonStr(syncProd);
- log.info("字典同步数据: {}", body);
- String res = sendPost(SYNC_DICT_URL, body);
- if ("fail".equals(res)) {
- return R.fail("同步失败,请稍后重试");
- } else {
- sysDictLog.setIsSync(true);
- sysDictLogService.updateById(sysDictLog);
- }
- return R.ok();
- }
- @ApiOperation("添加")
- @PostMapping("save")
- public R save(@RequestBody @Validated SysDictDto.Save save) {
- //添加字典
- long count = !Emptys.check(save.getPaterCode()) ? count(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, save.getCode()))
- : count(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, save.getCode()).eq(SysDict::getPaterCode, save.getPaterCode()));
- if (count > 0) {
- return R.fail("code已存在");
- }
- SysDict sysDict = copy(SysDict.class, save)
- .createUserTime(AuthorizeUtils.getLoginId(Long.class));
- save(sysDict);
- //日志
- SysDictLog sysDictLog = BeanUtil.copyProperties(sysDict, SysDictLog.class);
- sysDictLogService.handleLog(sysDict, sysDictLog, EnumSysDictOperateType.ADD);
- //刷新redis
- refuRedis(sysDict);
- return R.ok();
- }
- @ApiOperation("修改")
- @PostMapping("update")
- public R update(@RequestBody @Validated SysDictDto.Update update) {
- SysDict sysDict = getById(update.getId());
- if (!sysDict.getCode().equals(update.getCode())) {
- long count = !Emptys.check(update.getPaterCode()) ? count(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, update.getCode()))
- : count(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCode, update.getCode()).eq(SysDict::getPaterCode, update.getPaterCode()));
- if (count > 0) {
- 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(sysDict, 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(sysDict, sysDictLog, EnumSysDictOperateType.UPDATE);
- //刷新redis
- refuRedis(obj);
- return R.ok();
- }
- @ApiOperation("删除")
- @PostMapping("del")
- @Transactional(rollbackFor = Exception.class)
- public R del(@RequestBody @Validated SysDictDto.Del del) {
- //删除字典
- List<Integer> ids = del.getId();
- List<SysDict> list = list(new LambdaQueryWrapper<SysDict>().in(SysDict::getId, ids));
- removeBatchByIds(ids);
- //日志
- if (CollUtil.isNotEmpty(list)) {
- list.forEach(sysDict -> {
- SysDictLog sysDictLog = BeanUtil.copyProperties(sysDict, SysDictLog.class);
- sysDictLogService.handleLog(sysDict, sysDictLog, EnumSysDictOperateType.DEL);
- });
- }
- //删除子字典
- JList<SysDict> paters = new JArrayList<>(list).filter().isNull(SysDict::getPaterCode).list();
- JList<SysDict> paters2 = new JArrayList<>(list).filter().eq(SysDict::getPaterCode, "").list();
- if (Emptys.check(paters2)) {
- paters.addAll(paters2);
- }
- if (Emptys.check(paters)) {
- JList<String> codes = paters.getProperty(SysDict::getCode);
- LambdaQueryWrapper<SysDict> lqw = new LambdaQueryWrapper<SysDict>().in(SysDict::getPaterCode, codes);
- List<SysDict> sysDicts = list(lqw);
- if (CollUtil.isNotEmpty(sysDicts)) {
- removeBatchByIds(sysDicts);
- sysDicts.forEach(sysDict -> {
- SysDictLog sysDictLog = BeanUtil.copyProperties(sysDict, SysDictLog.class);
- sysDictLogService.handleLog(sysDict, sysDictLog, EnumSysDictOperateType.DEL);
- });
- }
- }
- //刷新redis
- list.forEach(sysDict -> refuRedis(sysDict));
- return R.ok();
- }
- @ApiOperation("分页查询")
- @PostMapping("page")
- public R<PageBean<SysDictDto.Vo>> page(@RequestBody SysDictDto.Page pageInfo) {
- PageBean<SysDict> page = pageInfo.getPage();
- LambdaQueryWrapper<SysDict> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(pageInfo, SysDict.class)
- .ge(SysDict::getCreateTime, pageInfo.getBeginCreateTime())
- .le(SysDict::getCreateTime, pageInfo.getEndCreateTime())
- .like(SysDict::getMsg)
- .like(SysDict::getValue)
- .build()
- .orderByAsc(!Emptys.check(page.getOrders()), SysDict::getOrders)
- .and(StringUtils.isEmpty(pageInfo.getPaterCode()), sysDictLambdaQueryWrapper -> sysDictLambdaQueryWrapper
- .isNull(SysDict::getPaterCode)
- .or()
- .eq(SysDict::getPaterCode, "")
- );
- IPage<SysDict> iPage = page(toIPage(page), lambdaQueryWrapper);
- return R.ok(toPageBean(SysDictDto.Vo.class, iPage));
- }
- @ApiOperation("集合查询")
- @PostMapping("list")
- public R<List<SysDictDto.Vo>> list(@RequestHeader(value = "lang", required = false) String lang, @RequestBody SysDictDto.SelectList selectList) {
- LambdaQueryWrapper<SysDict> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(selectList, SysDict.class)
- .in(SysDict::getId, selectList.getIds())
- .in(SysDict::getCode, selectList.getCodes())
- .in(SysDict::getPaterCode, selectList.getPaterCodes())
- .like(SysDict::getMsg)
- .like(SysDict::getValue)
- .build()
- .orderByAsc(SysDict::getOrders);
- List<SysDict> list = list(lambdaQueryWrapper);
- List<SysDictDto.Vo> voList = copy(SysDictDto.Vo.class, list);
- // if ("en".equals(lang)) {
- // //英文菜单
- // voList.forEach(v -> {
- // String enName = v.getEnMsg();
- // if (StrUtil.isNotEmpty(enName)) {
- // v.setMsg(enName);
- // }
- // });
- //
- // }
- return R.ok(voList);
- }
- @ApiOperation("集合查询(无需授权)")
- @PostMapping("list2")
- public R<List<SysDictDto.Vo>> list2(@RequestHeader(value = "lang", required = false) String lang, @RequestBody SysDictDto.SelectList selectList) {
- return list(lang, selectList);
- }
- /**
- * 刷新redis
- *
- * @param sysDict
- */
- public void refuRedis(SysDict sysDict) {
- List<SysDict> list;
- String key = sysDict.getPaterCode();
- if (!Emptys.check(key)) {
- //父字典
- list = list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getPaterCode, sysDict.getCode()).eq(SysDict::getStatus, true));
- key = sysDict.getCode();
- } else {
- //子字典
- list = list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getPaterCode, key).eq(SysDict::getStatus, true));
- }
- redisService.removeMap(SysDictUtils.getKey(key));
- for (SysDict dict : list) {
- redisService.setMap(SysDictUtils.getKey(key), dict.getCode(), copy(SysDictRedis.class, dict));
- }
- log.info("字典刷新redis完成~");
- }
- /**
- * 全量加载字典到redis
- */
- @Runners
- public void loadRedis() {
- List<SysDict> sysDicts = list(new LambdaQueryWrapper<SysDict>().eq(SysDict::getStatus, true));
- List<SysDictRedis> sysDictRedis = Beans.copy(SysDictRedis.class, sysDicts);
- JList<SysDictRedis> list = new JArrayList<>(sysDictRedis);
- //父字典
- JList<SysDictRedis> paters = list.filter().isNull(SysDictRedis::getPaterCode).list();
- JList<SysDictRedis> paters2 = list.filter().eq(SysDictRedis::getPaterCode, "").list();
- if (Emptys.check(paters2)) {
- paters.addAll(paters2);
- }
- redisService.removeLikeMap(SysDictUtils.SYS_DICT_REDIS_PREFIX);
- //[父code -> 子列表]数据结构写入redis
- paters.forEach(sysDict -> {
- JList<SysDictRedis> sysDictJList = list.filter().eq(SysDictRedis::getPaterCode, sysDict.getCode()).list();
- sysDictJList.forEach(sysDictRediss -> redisService.setMap(SysDictUtils.getKey(sysDict.getCode()), sysDictRediss.getCode(), sysDictRediss));
- });
- log.info("字典写入redis完成~");
- }
- }
|