package com.ruoyi.system.service.impl;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
|
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.CjFillTask;
|
import com.ruoyi.system.domain.CjFormConfig;
|
import com.ruoyi.system.mapper.CjFillTaskMapper;
|
import com.ruoyi.system.mapper.CjFormConfigMapper;
|
import com.ruoyi.system.mapper.CjStudentMapper;
|
import com.ruoyi.system.service.ICjFillTaskService;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
/**
|
* 填表任务Service业务层处理
|
*
|
* @author ruoyi
|
* @date 2026-09-09
|
*/
|
@Service
|
public class CjFillTaskServiceImpl implements ICjFillTaskService
|
{
|
private static final Logger log = LoggerFactory.getLogger(CjFillTaskServiceImpl.class);
|
|
/** 默认“是否外省/境外=否”排除集(本省+直辖市,可按任务调整) */
|
private static final String DEFAULT_OUTSIDE_EXCLUDE = "北京市,天津市,上海市,重庆市,江苏省";
|
|
@Autowired
|
private CjFillTaskMapper cjFillTaskMapper;
|
@Autowired
|
private CjFormConfigMapper cjFormConfigMapper;
|
@Autowired
|
private CjStudentMapper cjStudentMapper;
|
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
/**
|
* 查询填表任务
|
*
|
* @param taskId 填表任务主键
|
* @return 填表任务
|
*/
|
@Override
|
public CjFillTask selectCjFillTaskByTaskId(Long taskId)
|
{
|
return cjFillTaskMapper.selectCjFillTaskByTaskId(taskId);
|
}
|
|
/**
|
* 查询填表任务列表
|
*
|
* @param cjFillTask 填表任务
|
* @return 填表任务集合
|
*/
|
@Override
|
public List<CjFillTask> selectCjFillTaskList(CjFillTask cjFillTask)
|
{
|
return cjFillTaskMapper.selectCjFillTaskList(cjFillTask);
|
}
|
|
/**
|
* 新增填表任务
|
*
|
* @param cjFillTask 填表任务
|
* @return 结果
|
*/
|
@Override
|
public int insertCjFillTask(CjFillTask cjFillTask)
|
{
|
if (cjFillTask.getTaskName() == null || cjFillTask.getTaskName().trim().isEmpty())
|
{
|
throw new ServiceException("请填写任务名称");
|
}
|
if (existSameName(cjFillTask.getTaskName(), null))
|
{
|
throw new ServiceException("任务名称已存在,请换一个");
|
}
|
// 默认参数
|
if (cjFillTask.getNeedApprove() == null || cjFillTask.getNeedApprove().isEmpty()) { cjFillTask.setNeedApprove("1"); }
|
if (cjFillTask.getOutsideExclude() == null || cjFillTask.getOutsideExclude().isEmpty()) { cjFillTask.setOutsideExclude(DEFAULT_OUTSIDE_EXCLUDE); }
|
if (cjFillTask.getTwhkAsOutside() == null || cjFillTask.getTwhkAsOutside().isEmpty()) { cjFillTask.setTwhkAsOutside("0"); }
|
if (cjFillTask.getEnableEnterpriseLib() == null || cjFillTask.getEnableEnterpriseLib().isEmpty()) { cjFillTask.setEnableEnterpriseLib("0"); }
|
if (cjFillTask.getStatus() == null || cjFillTask.getStatus().isEmpty()) { cjFillTask.setStatus("0"); }
|
// 表单快照(从引用的填表配置生成)
|
refreshSnapshot(cjFillTask);
|
// 填报范围人数
|
refreshScopeCount(cjFillTask);
|
cjFillTask.setCreateBy(username());
|
cjFillTask.setCreateTime(DateUtils.getNowDate());
|
return cjFillTaskMapper.insertCjFillTask(cjFillTask);
|
}
|
|
/**
|
* 修改填表任务(仅草稿状态可改)
|
*
|
* @param cjFillTask 填表任务
|
* @return 结果
|
*/
|
@Override
|
public int updateCjFillTask(CjFillTask cjFillTask)
|
{
|
CjFillTask old = cjFillTaskMapper.selectCjFillTaskByTaskId(cjFillTask.getTaskId());
|
if (old == null) { throw new ServiceException("填表任务不存在"); }
|
if (!"0".equals(old.getStatus())) { throw new ServiceException("任务已发布/截止,不可修改,请先取消发布或另建任务"); }
|
if (cjFillTask.getTaskName() != null && !cjFillTask.getTaskName().trim().isEmpty()
|
&& existSameName(cjFillTask.getTaskName(), cjFillTask.getTaskId()))
|
{
|
throw new ServiceException("任务名称已存在,请换一个");
|
}
|
// 合并:保留旧值,用本次提交覆盖非空字段
|
CjFillTask merged = new CjFillTask();
|
copy(merged, old);
|
copy(merged, cjFillTask);
|
refreshSnapshot(merged);
|
refreshScopeCount(merged);
|
merged.setUpdateBy(username());
|
merged.setUpdateTime(DateUtils.getNowDate());
|
return cjFillTaskMapper.updateCjFillTask(merged);
|
}
|
|
/**
|
* 批量删除填表任务(仅草稿)
|
*
|
* @param taskIds 需要删除的填表任务主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteCjFillTaskByTaskIds(Long[] taskIds)
|
{
|
if (taskIds == null || taskIds.length == 0) { return 0; }
|
for (Long taskId : taskIds)
|
{
|
CjFillTask old = cjFillTaskMapper.selectCjFillTaskByTaskId(taskId);
|
if (old == null) { continue; }
|
if (!"0".equals(old.getStatus()))
|
{
|
throw new ServiceException("仅“草稿”状态的任务可删除,请先取消发布/归档处理");
|
}
|
}
|
return cjFillTaskMapper.deleteCjFillTaskByTaskIds(taskIds);
|
}
|
|
/**
|
* 发布填表任务(草稿→填报中)
|
*
|
* @param taskId 任务主键
|
* @return 结果
|
*/
|
@Override
|
public int publish(Long taskId)
|
{
|
CjFillTask task = require(taskId);
|
if (!"0".equals(task.getStatus())) { throw new ServiceException("仅“草稿”状态的任务可发布"); }
|
if (task.getFillStartDate() == null || task.getFillEndDate() == null)
|
{
|
throw new ServiceException("发布前请先设置填报起止日期");
|
}
|
if (task.getFillStartDate().after(task.getFillEndDate()))
|
{
|
throw new ServiceException("填报开始日期不能晚于截止日期");
|
}
|
// 统一班级码注册制:范围以班级为准,学生随后可扫码注册建档填报,注册人数允许为 0
|
if (task.getScopeJson() == null || task.getScopeJson().trim().isEmpty())
|
{
|
throw new ServiceException("发布前请先选择填报范围(至少一个班级)");
|
}
|
if (task.getSchemaJson() == null || task.getSchemaJson().trim().isEmpty())
|
{
|
throw new ServiceException("发布前请先关联填表配置(生成表单快照)");
|
}
|
task.setStatus("1");
|
task.setPublishBy(username());
|
task.setPublishTime(DateUtils.getNowDate());
|
return save(task);
|
}
|
|
/**
|
* 取消发布(填报中→草稿)
|
*
|
* @param taskId 任务主键
|
* @return 结果
|
*/
|
@Override
|
public int unpublish(Long taskId)
|
{
|
CjFillTask task = require(taskId);
|
if (!"1".equals(task.getStatus())) { throw new ServiceException("仅“填报中”状态的任务可取消发布"); }
|
task.setStatus("0");
|
return save(task);
|
}
|
|
/**
|
* 截止(填报中/草稿→已截止)
|
*
|
* @param taskId 任务主键
|
* @return 结果
|
*/
|
@Override
|
public int close(Long taskId)
|
{
|
CjFillTask task = require(taskId);
|
if (!"1".equals(task.getStatus()) && !"0".equals(task.getStatus()))
|
{
|
throw new ServiceException("仅“草稿/填报中”状态的任务可截止");
|
}
|
task.setStatus("2");
|
return save(task);
|
}
|
|
/**
|
* 归档(已截止→已归档)
|
*
|
* @param taskId 任务主键
|
* @return 结果
|
*/
|
@Override
|
public int archive(Long taskId)
|
{
|
CjFillTask task = require(taskId);
|
if (!"2".equals(task.getStatus())) { throw new ServiceException("仅“已截止”状态的任务可归档"); }
|
task.setStatus("3");
|
return save(task);
|
}
|
|
// ========== 私有工具 ==========
|
|
private CjFillTask require(Long taskId)
|
{
|
CjFillTask task = cjFillTaskMapper.selectCjFillTaskByTaskId(taskId);
|
if (task == null) { throw new ServiceException("填表任务不存在"); }
|
return task;
|
}
|
|
private int save(CjFillTask task)
|
{
|
task.setUpdateBy(username());
|
task.setUpdateTime(DateUtils.getNowDate());
|
return cjFillTaskMapper.updateCjFillTask(task);
|
}
|
|
private void copy(CjFillTask dest, CjFillTask src)
|
{
|
if (src == null) { return; }
|
if (src.getTaskId() != null) { dest.setTaskId(src.getTaskId()); }
|
if (src.getTaskName() != null) { dest.setTaskName(src.getTaskName()); }
|
if (src.getSchoolYear() != null) { dest.setSchoolYear(src.getSchoolYear()); }
|
if (src.getSemester() != null) { dest.setSemester(src.getSemester()); }
|
if (src.getConfigId() != null) { dest.setConfigId(src.getConfigId()); }
|
if (src.getSchemaJson() != null) { dest.setSchemaJson(src.getSchemaJson()); }
|
if (src.getScopeJson() != null) { dest.setScopeJson(src.getScopeJson()); }
|
if (src.getScopeCount() != null) { dest.setScopeCount(src.getScopeCount()); }
|
if (src.getFillStartDate() != null) { dest.setFillStartDate(src.getFillStartDate()); }
|
if (src.getFillEndDate() != null) { dest.setFillEndDate(src.getFillEndDate()); }
|
if (src.getNeedApprove() != null) { dest.setNeedApprove(src.getNeedApprove()); }
|
if (src.getOutsideExclude() != null) { dest.setOutsideExclude(src.getOutsideExclude()); }
|
if (src.getTwhkAsOutside() != null) { dest.setTwhkAsOutside(src.getTwhkAsOutside()); }
|
if (src.getRangeMode() != null) { dest.setRangeMode(src.getRangeMode()); }
|
if (src.getEnableEnterpriseLib() != null) { dest.setEnableEnterpriseLib(src.getEnableEnterpriseLib()); }
|
if (src.getStatus() != null) { dest.setStatus(src.getStatus()); }
|
if (src.getPublishBy() != null) { dest.setPublishBy(src.getPublishBy()); }
|
if (src.getPublishTime() != null) { dest.setPublishTime(src.getPublishTime()); }
|
if (src.getDelFlag() != null) { dest.setDelFlag(src.getDelFlag()); }
|
if (src.getRemark() != null) { dest.setRemark(src.getRemark()); }
|
}
|
|
/** 由 configId 关联的填表配置生成表单快照 {configId, groups, attachments} */
|
private void refreshSnapshot(CjFillTask task)
|
{
|
Long configId = task.getConfigId();
|
if (configId == null)
|
{
|
if (task.getSchemaJson() == null || task.getSchemaJson().trim().isEmpty())
|
{
|
throw new ServiceException("请关联一张填表配置(作为本任务要收集的表单)");
|
}
|
return;
|
}
|
CjFormConfig config = cjFormConfigMapper.selectCjFormConfigByConfigId(configId);
|
if (config == null) { throw new ServiceException("引用的填表配置不存在"); }
|
try
|
{
|
ObjectNode snap = objectMapper.createObjectNode();
|
snap.put("configId", config.getConfigId());
|
snap.set("configName", objectMapper.getNodeFactory().textNode(config.getConfigName()));
|
snap.set("groups", objectMapper.readTree(config.getGroupsJson()));
|
String att = config.getAttachmentsJson();
|
snap.set("attachments", (att == null || att.trim().isEmpty())
|
? objectMapper.createArrayNode()
|
: objectMapper.readTree(att));
|
task.setSchemaJson(objectMapper.writeValueAsString(snap));
|
}
|
catch (Exception e)
|
{
|
throw new ServiceException("生成表单快照失败: " + e.getMessage());
|
}
|
}
|
|
/** 从 scopeJson.classIds 统计学生人数并回写 scopeCount */
|
private void refreshScopeCount(CjFillTask task)
|
{
|
String scope = task.getScopeJson();
|
if (scope == null || scope.trim().isEmpty())
|
{
|
if ("0".equals(task.getStatus()))
|
{
|
throw new ServiceException("请选择填报范围(至少一个班级)");
|
}
|
return;
|
}
|
Long[] ids;
|
try
|
{
|
JsonNode root = objectMapper.readTree(scope);
|
JsonNode arr = root.path("classIds");
|
if (!arr.isArray() || arr.size() == 0)
|
{
|
if ("0".equals(task.getStatus())) { throw new ServiceException("请选择填报范围(至少一个班级)"); }
|
return;
|
}
|
List<Long> list = new ArrayList<>();
|
for (JsonNode node : arr) { list.add(node.asLong()); }
|
ids = list.toArray(new Long[0]);
|
}
|
catch (Exception e)
|
{
|
throw new ServiceException("填报范围数据格式错误: " + e.getMessage());
|
}
|
task.setScopeCount((long) cjStudentMapper.countByClassIds(ids));
|
}
|
|
/** 名称唯一性检查(创建/编辑) */
|
private boolean existSameName(String taskName, Long excludeTaskId)
|
{
|
CjFillTask q = new CjFillTask();
|
q.setTaskName(taskName);
|
List<CjFillTask> list = cjFillTaskMapper.selectCjFillTaskList(q);
|
if (list != null)
|
{
|
for (CjFillTask t : list)
|
{
|
if (excludeTaskId == null || !excludeTaskId.equals(t.getTaskId()))
|
{
|
return true;
|
}
|
}
|
}
|
return false;
|
}
|
|
private String username()
|
{
|
try { return SecurityUtils.getUsername(); } catch (Exception e) { return null; }
|
}
|
}
|