fix: 优化鱼字典新增修改
This commit is contained in:
parent
57403df980
commit
cca46d159e
@ -20,10 +20,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -88,9 +85,14 @@ public class SdFishDictoryBController {
|
||||
if (entity == null) {
|
||||
return ResponseResult.error("数据不能为空");
|
||||
}
|
||||
entity.setId(IdUtil.simpleUUID());
|
||||
entity.setId(IdUtil.fastUUID());
|
||||
entity.setCode(entity.getId());
|
||||
|
||||
// 名称重名校验
|
||||
if (sdFishDictoryBService.existsByName(entity.getName())) {
|
||||
return ResponseResult.error("该鱼类名称已存在");
|
||||
}
|
||||
|
||||
// 上传文件并设置附件ID到实体
|
||||
applyUploadedFiles(entity, files);
|
||||
|
||||
@ -109,23 +111,35 @@ public class SdFishDictoryBController {
|
||||
@RequestParam(value = "files", required = false) List<MultipartFile> files) {
|
||||
try {
|
||||
SdEngInfoBHOperateRequest request = objectMapper.readValue(dataStr, SdEngInfoBHOperateRequest.class);
|
||||
SdFishDictoryB entity = request == null || request.getEngInfo() == null ? null
|
||||
: objectMapper.convertValue(request.getEngInfo(), SdFishDictoryB.class);
|
||||
if (entity == null || entity.getId() == null) {
|
||||
Map<String, Object> engInfo = request == null ? null : request.getEngInfo();
|
||||
if (engInfo == null || engInfo.get("id") == null) {
|
||||
return ResponseResult.error("数据或ID不能为空");
|
||||
}
|
||||
|
||||
// 名称重名校验(仅当本次修改了名称时校验)
|
||||
Object newName = engInfo.get("name");
|
||||
if (newName != null && StrUtil.isNotBlank(newName.toString())) {
|
||||
String name = newName.toString();
|
||||
if (sdFishDictoryBService.existsByNameExcludeId(name, (String) engInfo.get("id"))) {
|
||||
return ResponseResult.error("该鱼类名称已存在");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取修改前的实体,用于后续清理旧文件
|
||||
SdFishDictoryB before = sdFishDictoryBService.getById(entity.getId());
|
||||
SdFishDictoryB before = sdFishDictoryBService.getById((String) engInfo.get("id"));
|
||||
List<String> oldAttachmentIds = before != null ? collectAttachmentIds(before) : Collections.emptyList();
|
||||
|
||||
// 上传新文件并设置附件ID
|
||||
applyUploadedFiles(entity, files);
|
||||
SdFishDictoryB tempEntity = objectMapper.convertValue(engInfo, SdFishDictoryB.class);
|
||||
applyUploadedFiles(tempEntity, files);
|
||||
// 将文件处理后 inffile 合并回 patch map
|
||||
engInfo.put("inffile", tempEntity.getInffile());
|
||||
|
||||
boolean result = sdFishDictoryBService.update(entity, request.getSource());
|
||||
boolean result = sdFishDictoryBService.update(engInfo, request.getSource());
|
||||
if (result) {
|
||||
// 清理被替换的旧文件
|
||||
deleteReplacedFiles(oldAttachmentIds, collectAttachmentIds(entity));
|
||||
SdFishDictoryB after = sdFishDictoryBService.getById((String) engInfo.get("id"));
|
||||
deleteReplacedFiles(oldAttachmentIds, collectAttachmentIds(after));
|
||||
}
|
||||
return result ? ResponseResult.success("修改成功") : ResponseResult.error("修改失败");
|
||||
} catch (Exception e) {
|
||||
|
||||
@ -21,7 +21,7 @@ public class SdFishDictoryB implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 主键 */
|
||||
@TableId(type = IdType.ASSIGN_UUID)
|
||||
@TableId(type = IdType.INPUT)
|
||||
@FieldChinese("主键")
|
||||
private String id;
|
||||
|
||||
@ -105,6 +105,9 @@ public class SdFishDictoryB implements Serializable {
|
||||
@FieldChinese("所属流域")
|
||||
private String rvcd;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String rvcdName;
|
||||
|
||||
/** 洄游习性 */
|
||||
@FieldChinese("洄游习性")
|
||||
private String habitMigrat;
|
||||
|
||||
@ -6,6 +6,7 @@ import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.qgc_base.domain.SdFishDictoryB;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ISdFishDictoryBService extends IService<SdFishDictoryB> {
|
||||
|
||||
@ -16,10 +17,21 @@ public interface ISdFishDictoryBService extends IService<SdFishDictoryB> {
|
||||
boolean add(SdFishDictoryB entity, String source);
|
||||
|
||||
boolean update(SdFishDictoryB entity, String source);
|
||||
boolean update(Map<String, Object> patchMap, String source) throws Exception;
|
||||
|
||||
boolean delete(List<String> ids, String source);
|
||||
|
||||
SdFishDictoryB getById(String id);
|
||||
|
||||
/**
|
||||
* 检查名称是否已存在(不过滤IS_DELETED,因为唯一约束不区分软删除)
|
||||
*/
|
||||
boolean existsByName(String name);
|
||||
|
||||
/**
|
||||
* 检查名称是否已被其他记录占用(排除指定ID)
|
||||
*/
|
||||
boolean existsByNameExcludeId(String name, String excludeId);
|
||||
|
||||
List<SdFishDictoryB> findSimilarFish(String name, Integer limit);
|
||||
}
|
||||
|
||||
@ -49,6 +49,22 @@ public class PatchUpdateHelper {
|
||||
@Resource
|
||||
private DictCodeToNameConverter dictCodeToNameConverter;
|
||||
|
||||
/**
|
||||
* 执行 patch 更新(默认主键字段为 "stcd")。
|
||||
*
|
||||
* @see #execute(IService, Map, String, String, Class, Set, List, String)
|
||||
*/
|
||||
public <T> boolean execute(
|
||||
IService<T> service,
|
||||
Map<String, Object> engInfoPatch,
|
||||
String source,
|
||||
String tableName,
|
||||
Class<T> entityClass,
|
||||
Set<String> transientFields,
|
||||
List<CodeToNameMetadataBo> codeToNameMetaList) throws Exception {
|
||||
return execute(service, engInfoPatch, source, tableName, entityClass, transientFields, codeToNameMetaList, "stcd");
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行 patch 更新:仅更新前端显式传入的字段(包括 null 值),未传入的字段保持原值。
|
||||
*
|
||||
@ -59,6 +75,7 @@ public class PatchUpdateHelper {
|
||||
* @param entityClass 实体类
|
||||
* @param transientFields 需跳过的瞬态字段集合(如 @TableField(exist=false)、serialVersionUID)
|
||||
* @param codeToNameMetaList 字典代码转名称配置(用于操作日志)
|
||||
* @param pkFieldName 主键 Java 字段名(如 "stcd"、"id")
|
||||
* @param <T> 实体类型
|
||||
* @return true=更新成功
|
||||
* @throws Exception Jackson 类型转换异常等
|
||||
@ -70,27 +87,29 @@ public class PatchUpdateHelper {
|
||||
String tableName,
|
||||
Class<T> entityClass,
|
||||
Set<String> transientFields,
|
||||
List<CodeToNameMetadataBo> codeToNameMetaList) throws Exception {
|
||||
List<CodeToNameMetadataBo> codeToNameMetaList,
|
||||
String pkFieldName) throws Exception {
|
||||
|
||||
String stcd = engInfoPatch == null ? null : (String) engInfoPatch.get("stcd");
|
||||
if (StrUtil.isBlank(stcd)) {
|
||||
throw new BizException("站点编码不能为空");
|
||||
Object pkValue = engInfoPatch == null ? null : engInfoPatch.get(pkFieldName);
|
||||
if (isEmptyPk(pkValue)) {
|
||||
throw new BizException("主键不能为空");
|
||||
}
|
||||
T before = service.getById(stcd);
|
||||
T before = service.getById((String) pkValue);
|
||||
if (before == null) {
|
||||
throw new BizException("测站不存在: " + stcd);
|
||||
throw new BizException("记录不存在: " + pkValue);
|
||||
}
|
||||
|
||||
T after = entityClass.getDeclaredConstructor().newInstance();
|
||||
BeanUtil.copyProperties(before, after);
|
||||
objectMapper.updateValue(after, engInfoPatch);
|
||||
|
||||
String pkColumn = StrUtil.toUnderlineCase(pkFieldName).toUpperCase();
|
||||
UpdateWrapper<T> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("STCD", stcd);
|
||||
updateWrapper.eq(pkColumn, pkValue);
|
||||
boolean hasUpdate = false;
|
||||
for (Field field : entityClass.getDeclaredFields()) {
|
||||
String fieldName = field.getName();
|
||||
if (transientFields.contains(fieldName) || "stcd".equals(fieldName)) {
|
||||
if (transientFields.contains(fieldName) || pkFieldName.equals(fieldName)) {
|
||||
continue;
|
||||
}
|
||||
if (!engInfoPatch.containsKey(fieldName)) {
|
||||
@ -114,8 +133,14 @@ public class PatchUpdateHelper {
|
||||
if (result) {
|
||||
dictCodeToNameConverter.convertCodeToName(before, codeToNameMetaList);
|
||||
dictCodeToNameConverter.convertCodeToName(after, codeToNameMetaList);
|
||||
msOperationLogService.recordModifyDetailLog(stcd, tableName, before, after, source, codeToNameMetaList);
|
||||
msOperationLogService.recordModifyDetailLog(String.valueOf(pkValue), tableName, before, after, source, codeToNameMetaList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isEmptyPk(Object value) {
|
||||
if (value == null) return true;
|
||||
if (value instanceof String) return StrUtil.isBlank((String) value);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.yfd.platform.qgc_base.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@ -36,6 +37,14 @@ public class SdFishDictoryBServiceImpl extends ServiceImpl<SdFishDictoryBMapper,
|
||||
|
||||
@Resource
|
||||
private DictCodeToNameConverter dictCodeToNameConverter;
|
||||
@Resource
|
||||
private PatchUpdateHelper patchUpdateHelper;
|
||||
|
||||
/** SdFishDictoryB 中 @TableField(exist = false) 的字段名 + serialVersionUID */
|
||||
private static final Set<String> TRANSIENT_FIELDS = Set.of(
|
||||
"typeName", "rareName", "specOriginName", "ptypeName",
|
||||
"habitatName", "situationName", "resourceTypeName", "serialVersionUID"
|
||||
);
|
||||
|
||||
/**
|
||||
* 代码转名称元数据配置列表(静态初始化)
|
||||
@ -95,6 +104,14 @@ public class SdFishDictoryBServiceImpl extends ServiceImpl<SdFishDictoryBMapper,
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean update(Map<String, Object> patchMap, String source) throws Exception {
|
||||
return patchUpdateHelper.execute(
|
||||
this, patchMap, source, TABLE_NAME, SdFishDictoryB.class,
|
||||
TRANSIENT_FIELDS, CODE_TO_NAME_META_LIST, "id");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean delete(List<String> ids, String source) {
|
||||
@ -116,6 +133,29 @@ public class SdFishDictoryBServiceImpl extends ServiceImpl<SdFishDictoryBMapper,
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByName(String name) {
|
||||
if (!StringUtils.hasText(name)) {
|
||||
return false;
|
||||
}
|
||||
LambdaQueryWrapper<SdFishDictoryB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SdFishDictoryB::getName, name);
|
||||
return count(wrapper) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByNameExcludeId(String name, String excludeId) {
|
||||
if (!StringUtils.hasText(name)) {
|
||||
return false;
|
||||
}
|
||||
LambdaQueryWrapper<SdFishDictoryB> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SdFishDictoryB::getName, name);
|
||||
if (StringUtils.hasText(excludeId)) {
|
||||
wrapper.ne(SdFishDictoryB::getId, excludeId);
|
||||
}
|
||||
return count(wrapper) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SdFishDictoryB getById(String id) {
|
||||
LambdaQueryWrapper<SdFishDictoryB> wrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user