package com.ruoyi.system.service.impl; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.system.domain.CjFormConfig; import com.ruoyi.system.mapper.CjFillTaskMapper; import com.ruoyi.system.mapper.CjFormConfigMapper; import com.ruoyi.system.service.ICjFormConfigService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; /** * 填表配置Service业务层处理 * * @author ruoyi * @date 2026-09-09 */ @Service public class CjFormConfigServiceImpl implements ICjFormConfigService { private static final Logger log = LoggerFactory.getLogger(CjFormConfigServiceImpl.class); /** 内置35字段定义资源(classpath) */ private static final String BUILTIN_RESOURCE = "form/builtinDefault.json"; @Autowired private CjFormConfigMapper cjFormConfigMapper; @Autowired private CjFillTaskMapper cjFillTaskMapper; private final ObjectMapper objectMapper = new ObjectMapper(); /** * 查询填表配置 * * @param configId 填表配置主键 * @return 填表配置 */ @Override public CjFormConfig selectCjFormConfigByConfigId(Long configId) { return cjFormConfigMapper.selectCjFormConfigByConfigId(configId); } /** * 查询填表配置列表 * * @param cjFormConfig 填表配置 * @return 填表配置集合 */ @Override public List selectCjFormConfigList(CjFormConfig cjFormConfig) { return cjFormConfigMapper.selectCjFormConfigList(cjFormConfig); } /** * 新增填表配置 * * @param cjFormConfig 填表配置 * @return 结果 */ @Override public int insertCjFormConfig(CjFormConfig cjFormConfig) { if (cjFormConfig.getConfigName() == null || cjFormConfig.getConfigName().trim().isEmpty()) { throw new ServiceException("请填写配置名称"); } // groups 为空则自动载入内置35字段;attachments 缺省为空数组 String groups = cjFormConfig.getGroupsJson(); if (groups == null || groups.trim().isEmpty()) { try { JsonNode root = readBuiltin(); groups = objectMapper.writeValueAsString(root.path("groups")); cjFormConfig.setGroupsJson(groups); if (cjFormConfig.getAttachmentsJson() == null || cjFormConfig.getAttachmentsJson().trim().isEmpty()) { cjFormConfig.setAttachmentsJson(objectMapper.writeValueAsString(root.path("attachments"))); } } catch (Exception e) { throw new ServiceException("读取内置字段库失败: " + e.getMessage()); } } cjFormConfig.setFieldCount(countFields(cjFormConfig.getGroupsJson())); if (cjFormConfig.getVersion() == null) { cjFormConfig.setVersion(1L); } if (cjFormConfig.getStatus() == null || cjFormConfig.getStatus().isEmpty()) { cjFormConfig.setStatus("0"); } cjFormConfig.setCreateBy(username()); cjFormConfig.setCreateTime(DateUtils.getNowDate()); return cjFormConfigMapper.insertCjFormConfig(cjFormConfig); } /** * 修改填表配置 * * @param cjFormConfig 填表配置 * @return 结果 */ @Override public int updateCjFormConfig(CjFormConfig cjFormConfig) { CjFormConfig old = cjFormConfigMapper.selectCjFormConfigByConfigId(cjFormConfig.getConfigId()); if (old == null) { throw new ServiceException("填表配置不存在"); } if (cjFormConfig.getGroupsJson() != null && !cjFormConfig.getGroupsJson().trim().isEmpty()) { cjFormConfig.setFieldCount(countFields(cjFormConfig.getGroupsJson())); } cjFormConfig.setVersion(old.getVersion() == null ? 2L : old.getVersion() + 1); cjFormConfig.setUpdateBy(username()); cjFormConfig.setUpdateTime(DateUtils.getNowDate()); return cjFormConfigMapper.updateCjFormConfig(cjFormConfig); } /** * 批量删除填表配置(被填表任务引用时拒绝) * * @param configIds 需要删除的填表配置主键 * @return 结果 */ @Override public int deleteCjFormConfigByConfigIds(Long[] configIds) { if (configIds == null || configIds.length == 0) { return 0; } if (cjFillTaskMapper.countByConfigIds(configIds) > 0) { throw new ServiceException("所选配置已被填表任务引用,禁止删除(任务会保留表单快照)"); } return cjFormConfigMapper.deleteCjFormConfigByConfigIds(configIds); } /** * 获取内置默认表单定义({configName, groups, attachments}) * * @return 内置表单 Map */ @Override public Map getBuiltin() { try { return objectMapper.convertValue(readBuiltin(), new TypeReference>() { }); } catch (Exception e) { throw new ServiceException("读取内置字段库失败: " + e.getMessage()); } } // ========== 私有工具 ========== /** 读取 classpath 内置字段库根节点 */ private JsonNode readBuiltin() throws Exception { ClassPathResource resource = new ClassPathResource(BUILTIN_RESOURCE); return objectMapper.readTree(resource.getInputStream()); } /** 统计 groups 数组内字段总数 */ private Long countFields(String groupsJson) { if (groupsJson == null || groupsJson.trim().isEmpty()) { return 0L; } try { JsonNode groups = objectMapper.readTree(groupsJson); long n = 0; if (groups.isArray()) { for (JsonNode group : groups) { JsonNode fields = group.path("fields"); if (fields.isArray()) { n += fields.size(); } } } return n; } catch (Exception e) { log.warn("解析 groups_json 统计字段数失败,按 0 计: {}", e.getMessage()); return 0L; } } /** 当前登录用户名(无上下文时返回 null) */ private String username() { try { return SecurityUtils.getUsername(); } catch (Exception e) { return null; } } }