package org.jeecg.common.util; import cn.hutool.core.collection.CollectionUtil; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.jeecg.common.api.CommonAPI; import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.system.vo.DictModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Component @Slf4j public class TranslateDictTextUtils { @Lazy @Autowired private CommonAPI commonApi; @Autowired private RedisTemplate redisTemplate; public String translateField(String field, String value, String dictCode) { if (StringUtils.isBlank(value)) { return ""; } // 字典数据列表, key = 字典code,value=数据列表 Map> dataListMap = new HashMap<>(5); dataListMap.put(dictCode, this.listAddAllDeduplicate(new ArrayList<>(), Arrays.asList(value.split(",")))); //step.2 调用翻译方法,一次性翻译 Map> translText = this.translateAllDict(dataListMap); //翻译 List dictModels = translText.get(dictCode); if (CollectionUtil.isEmpty(dictModels)) { return ""; } return this.translDictText(dictModels, value); } public void translateField(String field, String value, JSONObject item, String dictCode) { if (StringUtils.isBlank(value)) { item.put(field + CommonConstant.DICT_TEXT_SUFFIX, null); return; } // 字典数据列表, key = 字典code,value=数据列表 Map> dataListMap = new HashMap<>(5); dataListMap.put(dictCode, this.listAddAllDeduplicate(new ArrayList<>(), Arrays.asList(value.split(",")))); //step.2 调用翻译方法,一次性翻译 Map> translText = this.translateAllDict(dataListMap); //翻译 List dictModels = translText.get(dictCode); if (CollectionUtil.isEmpty(dictModels)) { item.put(field + CommonConstant.DICT_TEXT_SUFFIX, null); return; } String textValue = this.translDictText(dictModels, value); item.put(field + CommonConstant.DICT_TEXT_SUFFIX, textValue); } /** * 字典值替换文本 * * @param dictModels * @param values * @return */ private String translDictText(List dictModels, String values) { List result = new ArrayList<>(); // 允许多个逗号分隔,允许传数组对象 String[] splitVal = values.split(","); for (String val : splitVal) { String dictText = val; for (DictModel dict : dictModels) { if (val.equals(dict.getValue())) { dictText = dict.getText(); break; } } if(StringUtils.isNotBlank(dictText)) { result.add(dictText); } } if(CollectionUtil.isEmpty(result)) { return ""; } return String.join(",", result); } /** * list 去重添加 */ private List listAddAllDeduplicate(List dataList, List addList) { // 筛选出dataList中没有的数据 List filterList = addList.stream().filter(i -> !dataList.contains(i)).collect(Collectors.toList()); dataList.addAll(filterList); return dataList; } /** * 一次性把所有的字典都翻译了 * 1. 所有的普通数据字典的所有数据只执行一次SQL * 2. 表字典相同的所有数据只执行一次SQL * * @param dataListMap * @return */ private Map> translateAllDict(Map> dataListMap) { // 翻译后的字典文本,key=dictCode Map> translText = new HashMap<>(5); // 需要翻译的数据(有些可以从redis缓存中获取,就不走数据库查询) List needTranslData = new ArrayList<>(); //step.1 先通过redis中获取缓存字典数据 for (String dictCode : dataListMap.keySet()) { List dataList = dataListMap.get(dictCode); if (dataList.size() == 0) { continue; } // 表字典需要翻译的数据 List needTranslDataTable = new ArrayList<>(); for (String s : dataList) { String data = s.trim(); if (data.length() == 0) { continue; //跳过循环 } if (dictCode.contains(",")) { String keyString = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, data); if (redisTemplate.hasKey(keyString)) { try { String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); list.add(new DictModel(data, text)); } catch (Exception e) { log.warn(e.getMessage()); } } else if (!needTranslDataTable.contains(data)) { // 去重添加 needTranslDataTable.add(data); } } else { String keyString = String.format("sys:cache:dict::%s:%s", dictCode, data); if (redisTemplate.hasKey(keyString)) { try { String text = oConvertUtils.getString(redisTemplate.opsForValue().get(keyString)); List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); list.add(new DictModel(data, text)); } catch (Exception e) { log.warn(e.getMessage()); } } else if (!needTranslData.contains(data)) { // 去重添加 needTranslData.add(data); } } } //step.2 调用数据库翻译表字典 if (needTranslDataTable.size() > 0) { String[] arr = dictCode.split(","); String table = arr[0], text = arr[1], code = arr[2]; String values = String.join(",", needTranslDataTable); log.debug("translateDictFromTableByKeys.dictCode:" + dictCode); log.debug("translateDictFromTableByKeys.values:" + values); List texts = commonApi.translateDictFromTableByKeys(table, text, code, values); log.debug("translateDictFromTableByKeys.result:" + texts); List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); list.addAll(texts); // 做 redis 缓存 for (DictModel dict : texts) { String redisKey = String.format("sys:cache:dictTable::SimpleKey [%s,%s]", dictCode, dict.getValue()); try { // update-begin-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061 // 保留5分钟 redisTemplate.opsForValue().set(redisKey, dict.getText(), 300, TimeUnit.SECONDS); // update-end-author:taoyan date:20211012 for: 字典表翻译注解缓存未更新 issues/3061 } catch (Exception e) { log.warn(e.getMessage(), e); } } } } //step.3 调用数据库进行翻译普通字典 if (needTranslData.size() > 0) { List dictCodeList = Arrays.asList(dataListMap.keySet().toArray(new String[]{})); // 将不包含逗号的字典code筛选出来,因为带逗号的是表字典,而不是普通的数据字典 List filterDictCodes = dictCodeList.stream().filter(key -> !key.contains(",")).collect(Collectors.toList()); String dictCodes = String.join(",", filterDictCodes); String values = String.join(",", needTranslData); log.debug("translateManyDict.dictCodes:" + dictCodes); log.debug("translateManyDict.values:" + values); Map> manyDict = commonApi.translateManyDict(dictCodes, values); log.debug("translateManyDict.result:" + manyDict); for (String dictCode : manyDict.keySet()) { List list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>()); List newList = manyDict.get(dictCode); list.addAll(newList); // 做 redis 缓存 for (DictModel dict : newList) { String redisKey = String.format("sys:cache:dict::%s:%s", dictCode, dict.getValue()); try { redisTemplate.opsForValue().set(redisKey, dict.getText()); } catch (Exception e) { log.warn(e.getMessage(), e); } } } } return translText; } }