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