liding
8 小时以前 94509204d25f7c0ad213ae2322be2bd5bfd17424
1.初始化配煤计算器数据 2。配煤到待入库
已修改17个文件
399 ■■■■ 文件已修改
basic-server/src/main/java/com/ruoyi/basic/dto/CoalFieldDto.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/mapper/CoalFieldMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/mapper/CoalPlanMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/service/CoalFieldService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/service/CoalPlanService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/service/impl/CoalFieldServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/service/impl/CoalPlanServiceImpl.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/resources/mapper/CoalFieldMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/resources/mapper/CoalPlanMapper.xml 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/controller/OfficialInventoryController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/OfficialInventoryDto.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/OfficialInventoryService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/PendingInventoryService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/OfficialInventoryServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/PendingInventoryServiceImpl.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/init/MyStartupRunner.java 74 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/handler/MyMetaObjectHandler.java 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
basic-server/src/main/java/com/ruoyi/basic/dto/CoalFieldDto.java
@@ -6,15 +6,5 @@
@Data
public class CoalFieldDto extends CoalField {
    private String fieldName;
    public CoalFieldDto(String name) {
        this.fieldName = name;
    }
    public static CoalFieldDto from(String name) {
        return new CoalFieldDto(name);
    }
    private String searchAll;
}
basic-server/src/main/java/com/ruoyi/basic/mapper/CoalFieldMapper.java
@@ -4,6 +4,7 @@
import com.ruoyi.basic.entity.CoalField;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Set;
/**
@@ -18,4 +19,6 @@
public interface CoalFieldMapper extends BaseMapper<CoalField> {
    Set<String> getFieldNamesByNames(Set<String> fieldNames);
    List<CoalField> getFieldsByNames(Set<String> filteredNames);
}
basic-server/src/main/java/com/ruoyi/basic/mapper/CoalPlanMapper.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.basic.entity.CoalPlan;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
@@ -15,4 +16,5 @@
@Mapper
public interface CoalPlanMapper extends BaseMapper<CoalPlan> {
    int existsFieldIds(@Param("fieldIds") String fieldIds);
}
basic-server/src/main/java/com/ruoyi/basic/service/CoalFieldService.java
@@ -28,4 +28,6 @@
    List<CoalField> selectAllList(CoalFieldDto coalFieldDto);
    Set<String> getFieldNamesByNames(Set<String> collect);
    List<CoalFieldDto> getFieldsByNames(Set<String> fieldNames);
}
basic-server/src/main/java/com/ruoyi/basic/service/CoalPlanService.java
@@ -28,4 +28,6 @@
    List<CoalPlan> selectAllList();
    List<CoalFieldVo> selectCoalPlanById(Long id);
    boolean checkPlanExists(String fieldIds);
}
basic-server/src/main/java/com/ruoyi/basic/service/impl/CoalFieldServiceImpl.java
@@ -9,16 +9,19 @@
import com.ruoyi.basic.entity.CoalField;
import com.ruoyi.basic.mapper.CoalFieldMapper;
import com.ruoyi.basic.service.CoalFieldService;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.bean.BeanUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
 * <p>
@@ -82,6 +85,44 @@
    }
    @Override
    public List<CoalFieldDto> getFieldsByNames(Set<String> fieldNames) {
        // 1. 参数校验
        if (fieldNames == null || fieldNames.isEmpty()) {
            throw new IllegalArgumentException("字段名集合不能为空");
        }
        // 2. 过滤空值
        Set<String> filteredNames = fieldNames.stream()
                .filter(name -> name != null && !name.trim().isEmpty())
                .collect(Collectors.toSet());
        if (filteredNames.isEmpty()) {
            return Collections.emptyList();
        }
        // 3. 查询数据库
        try {
            List<CoalField> entities = coalFieldMapper.getFieldsByNames(filteredNames);
            // 4. 实体转DTO
            return entities.stream()
                    .map(this::convertToDto)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            throw new BaseException("查询煤质字段信息失败,请稍后重试");
        }
    }
    private CoalFieldDto convertToDto(CoalField entity) {
        CoalFieldDto dto = new CoalFieldDto();
        dto.setId(entity.getId());
        dto.setFields(entity.getFields());
        dto.setFieldName(entity.getFieldName());
        return dto;
    }
    @Override
    public Set<String> getFieldNamesByNames(Set<String> fieldNames) {
        return coalFieldMapper.getFieldNamesByNames(fieldNames);
    }
basic-server/src/main/java/com/ruoyi/basic/service/impl/CoalPlanServiceImpl.java
@@ -78,6 +78,16 @@
    }
    @Override
    public boolean checkPlanExists(String fieldIds) {
        if (StringUtils.isBlank(fieldIds)) {
            return false;
        }
        // 查询数据库
        return coalPlanMapper.existsFieldIds(fieldIds) > 0;
    }
    @Override
    public List<CoalFieldVo> selectCoalPlanById(Long id) {
        CoalPlan coalPlan = coalPlanMapper.selectById(id);
        LambdaQueryWrapper<CoalField> coalFieldLambdaQueryWrapper = new LambdaQueryWrapper<>();
basic-server/src/main/resources/mapper/CoalFieldMapper.xml
@@ -27,7 +27,20 @@
    <select id="getFieldNamesByNames" resultType="java.lang.String">
        SELECT field_name FROM coal_field WHERE field_name IN
        <foreach collection="fieldNames" item="name" open="(" separator="," close=")">
            #{fieldNames}
            #{name}
        </foreach>
    </select>
    <select id="getFieldsByNames" resultType="com.ruoyi.basic.entity.CoalField">
        SELECT
        id,
        field_name AS fieldName,
        fields AS fields
        FROM
        coal_field
        WHERE
        field_name IN
        <foreach collection="filteredNames" item="name" open="(" separator="," close=")">
            #{name}
        </foreach>
    </select>
basic-server/src/main/resources/mapper/CoalPlanMapper.xml
@@ -11,8 +11,9 @@
                <result column="update_by" property="updateBy" />
                <result column="update_time" property="updateTime" />
                    <result column="plan" property="plan" />
                    <result column="coal_field_id" property="coalFieldId" />
                    <result column="field_names" property="fieldNames" />
                    <result column="coal_fields" property="coalFields" />
                    <result column="field_ids" property="fieldIds" />
                    <result column="scheme_desc" property="schemeDesc" />
        </resultMap>
        <!-- 通用查询结果列 -->
@@ -24,5 +25,11 @@
                update_time,
            id, plan, coal_field_id, field_names
        </sql>
    <select id="existsFieldIds" resultType="java.lang.Integer">
        SELECT COUNT(1)
        FROM coal_plan
        WHERE field_ids = #{fieldIds}
          AND deleted = 0
    </select>
</mapper>
main-business/src/main/java/com/ruoyi/business/controller/OfficialInventoryController.java
@@ -69,4 +69,11 @@
        return R.ok(officialInventoryService.mergeAll(officialInventoryDto));
    }
    /**
     * 配煤计算器选择list
     */
    @GetMapping("/coalBlendingList")
    public R<List<OfficialInventoryDto>> coalBlendingList() {
        return R.ok(officialInventoryService.coalBlendingList());
    }
}
main-business/src/main/java/com/ruoyi/business/dto/OfficialInventoryDto.java
@@ -1,5 +1,6 @@
package com.ruoyi.business.dto;
import com.ruoyi.basic.entity.CoalValue;
import com.ruoyi.business.entity.OfficialInventory;
import lombok.Data;
@@ -17,4 +18,8 @@
    private String supplierName; //供应商
    private String supplierCoal; //供应商 + 煤种
    private List<CoalValue> coalValues; //媒质方案字段值
}
main-business/src/main/java/com/ruoyi/business/service/OfficialInventoryService.java
@@ -32,4 +32,6 @@
    List<OfficialInventory> selectOfficialAll();
    Map<String, BigDecimal> selectOfficialAllInfo();
    List<OfficialInventoryDto> coalBlendingList();
}
main-business/src/main/java/com/ruoyi/business/service/PendingInventoryService.java
@@ -24,5 +24,5 @@
    int addOrEditCoalValue(PendingInventoryDto pendingInventoryDto);
    int addPending(PendingInventoryDto pendingInventoryDto);
    boolean addPending(PendingInventoryDto pendingInventoryDto);
}
main-business/src/main/java/com/ruoyi/business/service/impl/OfficialInventoryServiceImpl.java
@@ -333,6 +333,47 @@
    }
    @Override
    public List<OfficialInventoryDto> coalBlendingList() {
        // 1. 查询基础库存数据
        List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(null);
        // 2. 收集所有需要查询的ID
        Set<Long> coalIds = new HashSet<>();
        Set<Long> supplierIds = new HashSet<>();
        Set<Long> planIds = new HashSet<>();
        officialInventories.forEach(inventory -> {
            coalIds.add(inventory.getCoalId());
            supplierIds.add(inventory.getSupplierId());
            planIds.add(inventory.getCoalPlanId());
        });
        // 3. 批量查询关联数据
        Map<Long, CoalInfo> coalInfoMap = coalInfoMapper.selectByIds(coalIds).stream()
                .collect(Collectors.toMap(CoalInfo::getId, Function.identity()));
        Map<Long, Supply> supplyMap = supplyMapper.selectByIds(supplierIds).stream()
                .collect(Collectors.toMap(Supply::getId, Function.identity()));
        List<CoalValue> coalValues = coalValueMapper.selectList(
                new LambdaQueryWrapper<CoalValue>().in(CoalValue::getPlanId, planIds));
        // 4. 组装DTO
        return officialInventories.stream()
                .map(inventory -> {
                    OfficialInventoryDto dto = new OfficialInventoryDto();
                    BeanUtils.copyProperties(inventory, dto);
                    // 设置煤种信息
                    CoalInfo coalInfo = coalInfoMap.get(inventory.getCoalId());
                    Supply supply = supplyMap.get(inventory.getSupplierId());
                    if (coalInfo != null && supply != null) {
                        dto.setSupplierCoal(supply.getSupplierName() + " - " + coalInfo.getCoal());
                    }
                    // 设置煤质数据
                    dto.setCoalValues(coalValues);
                    return dto;
                })
                .collect(Collectors.toList());
    }
    @Override
    public Map<String, BigDecimal> selectOfficialAllInfo() {
        // 1. 查询 official_inventory 表数据
        List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(null);
main-business/src/main/java/com/ruoyi/business/service/impl/PendingInventoryServiceImpl.java
@@ -6,9 +6,11 @@
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mchange.v2.lang.SystemUtils;
import com.ruoyi.basic.dto.CoalFieldDto;
import com.ruoyi.basic.entity.CoalField;
import com.ruoyi.basic.entity.CoalInfo;
import com.ruoyi.basic.entity.CoalPlan;
import com.ruoyi.basic.entity.CoalValue;
import com.ruoyi.basic.mapper.CoalFieldMapper;
import com.ruoyi.basic.mapper.CoalInfoMapper;
@@ -16,6 +18,7 @@
import com.ruoyi.basic.mapper.CoalValueMapper;
import com.ruoyi.basic.service.CoalFieldService;
import com.ruoyi.basic.service.CoalPlanService;
import com.ruoyi.basic.service.CoalValueService;
import com.ruoyi.business.dto.PendingInventoryDto;
import com.ruoyi.business.entity.OfficialInventory;
import com.ruoyi.business.entity.PendingInventory;
@@ -29,6 +32,7 @@
import com.ruoyi.business.service.PendingInventoryService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.mapper.SysUserMapper;
@@ -38,11 +42,13 @@
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
@@ -72,10 +78,8 @@
    private final InputInventoryRecordService inputInventoryRecordService;
    private final InventorySummaryService inventorySummaryService;
    private final CoalFieldService coalFieldService;
    private final CoalPlanService coalPlanService;
    private final CoalPlanMapper coalPlanMapper;
    private final CoalValueService coalValueService;
    @Override
    public IPage<PendingInventoryDto> selectPendingInventoryList(Page page, PendingInventoryDto pendingInventoryDto) {
@@ -297,7 +301,115 @@
    @Override
    @Transactional
    public int addPending(PendingInventoryDto pendingInventoryDto) {
      return 1;
    public boolean addPending(PendingInventoryDto pendingInventoryDto) {
        try {
            CoalPlan coalPlan = coalPlanMapper.selectOne(new LambdaQueryWrapper<CoalPlan>().eq(CoalPlan::getPlan, "配煤计算器方案"));
            if (coalPlan == null) {
                return false;
            }
            // 添加到待入库
            Long userId = SecurityUtils.getUserId();
            PendingInventory pendingInventory = new PendingInventory();
            pendingInventory.setUnit("t");
            pendingInventory.setRegistrantId(userId);
            pendingInventory.setRegistrationDate(LocalDate.now());
            for (Map<String, Object> map : pendingInventoryDto.getFieldsResultList()) {
                pendingInventory.setSupplierName("配煤计算器方案入库");
                // 处理煤炭ID
                if (map.get("coalId") == null) {
                    CoalInfo coalInfo = new CoalInfo();
                    coalInfo.setCoal((String) map.get("createCoal"));
                    coalInfo.setMaintainerId(userId);
                    coalInfo.setMaintenanceDate(LocalDate.now());
                    if (coalInfoMapper.insert(coalInfo) <= 0) {
                        return false;
                    }
                    pendingInventory.setCoalId(coalInfo.getId());
                } else {
                    pendingInventory.setCoalId((Long) map.get("coalId"));
                }
                // 设置价格和数量
                BigDecimal cost = BigDecimal.valueOf((Double) map.get("cost"));
                BigDecimal tonnage = BigDecimal.valueOf((Double) map.get("totalTonnage"));
                pendingInventory.setPriceIncludingTax(cost);
                pendingInventory.setInventoryQuantity(tonnage);
                pendingInventory.setTotalPriceIncludingTax(cost.multiply(tonnage));
                BigDecimal costExcludingTax = cost.divide(BigDecimal.valueOf(1.13), 2, RoundingMode.HALF_UP);
                pendingInventory.setPriceExcludingTax(costExcludingTax);
                pendingInventory.setTotalPriceExcludingTax(costExcludingTax.multiply(tonnage));
                pendingInventory.setCoalPlanId(coalPlan.getId());
                // 煤质字段值
                String coalFields = coalPlan.getCoalFields();
                List<String> coalFieldList = Arrays.asList(coalFields.split(","));
                for (String field : coalFieldList) {
                    CoalField coalField = coalFieldMapper.selectOne(
                            new LambdaQueryWrapper<CoalField>().eq(CoalField::getFields, field));
                    if (coalField == null) {
                        continue;
                    }
                    CoalValue coalValue = new CoalValue();
                    coalValue.setPlanId(coalPlan.getId());
                    coalValue.setFields(field);
                    coalValue.setFieldName(coalField.getFieldName());
                    coalValue.setType("1");
                    switch (coalField.getFieldName()) {
                        case "发热量":
                            coalValue.setCoalValue((String) map.get("cv"));
                            break;
                        case "硫分":
                            coalValue.setCoalValue((String) map.get("sulfur"));
                            break;
                        case "灰分":
                            coalValue.setCoalValue((String) map.get("ash"));
                            break;
                        case "水分":
                            coalValue.setCoalValue((String) map.get("moisture"));
                            break;
                    }
                    // 保存煤质值
                    if (coalValueMapper.insert(coalValue) <= 0) {
                        return false;
                    }
                }
            }
            // 插入待入库记录
            if (pendingInventoryMapper.insert(pendingInventory) <= 0) {
                return false;
            }
            // 更新正式库
            for (Map<String, Object> coalResult : pendingInventoryDto.getCoalResultList()) {
                Long officialId = (Long) coalResult.get("officialId");
                BigDecimal quantity = (BigDecimal) coalResult.get("quantity");
                OfficialInventory officialInventory = officialInventoryMapper.selectById(officialId);
                if (officialInventory == null || officialInventory.getInventoryQuantity().compareTo(quantity) < 0) {
                    throw new BaseException("库存数量不足,添加至待入库失败");
                }
                officialInventory.setInventoryQuantity(officialInventory.getInventoryQuantity().subtract(quantity));
                if (officialInventoryMapper.updateById(officialInventory) <= 0) {
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            // 记录日志
            log.error("添加待入库失败", e);
            throw new BaseException("添加待入库失败: " + e.getMessage());
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/init/MyStartupRunner.java
@@ -2,14 +2,14 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.basic.dto.CoalFieldDto;
import com.ruoyi.basic.dto.CoalPlanDto;
import com.ruoyi.basic.entity.City;
import com.ruoyi.basic.entity.CoalField;
import com.ruoyi.basic.entity.District;
import com.ruoyi.basic.entity.Province;
import com.ruoyi.basic.mapper.*;
import com.ruoyi.basic.service.CoalFieldService;
import com.ruoyi.basic.service.CoalPlanService;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.web.controller.init.dto.AreaDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,9 +18,9 @@
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -48,7 +48,7 @@
    public void run(String... args) throws Exception {
        // 初始化省市区
        initRegion();
        // 初始新增配煤计算器中的字段和方案
        // 初始新增配煤计算器中的煤种字段和方案
        initCoalFields();
    }
@@ -120,19 +120,63 @@
    }
    private void initCoalFields() {
        try {
            // 1. 初始化字段逻辑
            Supplier<CoalFieldDto> dtoSupplier = CoalFieldDto::new; // 假设存在无参构造函数
        List<CoalFieldDto> fields = Stream.of("发热量", "硫分", "灰分", "水分")
                .map(CoalFieldDto::from)
                .toList();
        // 批量获取已存在的 fieldNames
        Set<String> existingFieldNames = coalFieldService.getFieldNamesByNames(
                fields.stream().map(CoalFieldDto::getFieldName).collect(Collectors.toSet())
        );
            List<CoalFieldDto> fields = Stream.of("发热量", "硫分", "灰分", "水分")
                    .map(fieldName -> {
                        CoalFieldDto dto = dtoSupplier.get();
                        dto.setFieldName(fieldName); // 假设存在 setFieldName 方法
                        dto.setFieldDescription("配煤计算器媒质字段");
                        return dto;
                    })
                    .toList();
        fields.forEach(field -> {
            if (!existingFieldNames.contains(field.getFieldName())) {
                coalFieldService.addOrEditCoalField(field);
            // 2. 保存字段(如果不存在)
            Set<String> existingNames = coalFieldService.getFieldNamesByNames(
                    fields.stream().map(CoalFieldDto::getFieldName).collect(Collectors.toSet())
            );
            fields.forEach(field -> {
                if (!existingNames.contains(field.getFieldName())) {
                    coalFieldService.addOrEditCoalField(field);
                }
            });
            // 3. 查询所有字段ID
            List<CoalFieldDto> allFields = coalFieldService.getFieldsByNames(
                    fields.stream().map(CoalFieldDto::getFieldName).collect(Collectors.toSet())
            );
            // 4. 创建方案
            String planName = "配煤计算器方案";
            boolean planExists = coalPlanService.checkPlanExists(allFields.stream()
                    .map(f -> f.getId().toString())
                    .collect(Collectors.joining(",")));
            if (!planExists) {
                // 创建新方案
                CoalPlanDto planDto = new CoalPlanDto();
                planDto.setPlan(planName);
                planDto.setCoalFields(allFields.stream()
                        .map(CoalFieldDto::getFields)
                        .collect(Collectors.joining(",")));
                planDto.setFieldIds(allFields.stream()
                        .map(f -> f.getId().toString())
                        .collect(Collectors.joining(",")));
                planDto.setSchemeDesc("系统生成配煤计算器所需字段方案");
                coalPlanService.addOrEditCoalPlan(planDto);
                log.info("成功创建配煤计算器方案");
            } else {
                log.info("配煤计算器方案已存在,跳过创建");
            }
        });
        } catch (Exception e) {
            // 记录系统异常日志,并转换为业务异常抛出(触发回滚)
            log.error("配煤计算器初始化失败", e);
            throw new BaseException("初始化配煤方案失败,请稍后重试");
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/handler/MyMetaObjectHandler.java
@@ -10,27 +10,53 @@
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    private static final String SYSTEM_USER = "system";
    @Override
    public void insertFill(MetaObject meta) {
        LocalDateTime now = LocalDateTime.now();
        Long uid = SecurityUtils.getLoginUser().getUserId();
        if (uid != null) {
            strictInsertFill(meta, "createBy", String.class, uid.toString());
            strictInsertFill(meta, "updateBy", String.class, uid.toString());
        String userId = getUserId();
        if (hasField(meta, "createBy")) {
            strictInsertFill(meta, "createBy", String.class, userId);
        }
        strictInsertFill(meta, "createTime", LocalDateTime.class, now);
        strictInsertFill(meta, "updateTime", LocalDateTime.class, now);
        if (hasField(meta, "updateBy")) {
            strictInsertFill(meta, "updateBy", String.class, userId);
        }
        if (hasField(meta, "createTime")) {
            strictInsertFill(meta, "createTime", LocalDateTime.class, now);
        }
        if (hasField(meta, "updateTime")) {
            strictInsertFill(meta, "updateTime", LocalDateTime.class, now);
        }
    }
    @Override
    public void updateFill(MetaObject meta) {
        LocalDateTime now = LocalDateTime.now();
        Long uid = SecurityUtils.getLoginUser().getUserId();
        if (uid != null) {
            strictUpdateFill(meta, "updateBy", String.class, uid.toString());
        String userId = getUserId();
        if (hasField(meta, "updateBy")) {
            strictUpdateFill(meta, "updateBy", String.class, userId);
        }
        // 强制覆盖 updateTime
        setFieldValByName("updateTime", now, meta);
        if (hasField(meta, "updateTime")) {
            setFieldValByName("updateTime", now, meta);
        }
    }
    private String getUserId() {
        try {
            Long uid = SecurityUtils.getLoginUser().getUserId();
            return uid != null ? uid.toString() : SYSTEM_USER;
        } catch (Exception e) {
            return SYSTEM_USER;
        }
    }
    private boolean hasField(MetaObject meta, String fieldName) {
        if (meta == null || fieldName == null) {
            return false;
        }
        return meta.hasGetter(fieldName) || meta.hasSetter(fieldName);
    }
}