# 模型参数配置功能 - 后端业务逻辑开发

## 任务概述

**任务编号:** 02
**任务名称:** 后端业务逻辑开发
**前置任务:** 01-后端实体类创建
**预计工时:** 2小时

## 任务目标

开发模型参数配置功能的 Mapper 层、Service 层和 Controller 层,实现查询模型列表、查询参数列表、保存参数配置三个核心接口。

---

## 开发步骤

### 1. 创建 Mapper 接口

#### 1.1 创建 Mapper 接口

**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiModelParamMapper.java`

```java
package com.ruoyi.ccdi.project.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.ccdi.project.domain.CcdiModelParam;
import org.apache.ibatis.annotations.Param;
import java.util.List;

/**
 * 模型参数Mapper
 */
public interface CcdiModelParamMapper extends BaseMapper<CcdiModelParam> {

    /**
     * 查询指定项目和模型的参数列表
     *
     * @param projectId 项目ID
     * @param modelCode 模型编码
     * @return 参数列表
     */
    List<CcdiModelParam> selectByProjectAndModel(
        @Param("projectId") Long projectId,
        @Param("modelCode") String modelCode
    );

    /**
     * 查询所有模型列表(去重)
     *
     * @param projectId 项目ID
     * @return 模型列表
     */
    List<CcdiModelParam> selectDistinctModels(@Param("projectId") Long projectId);

    /**
     * 批量更新参数值(只更新param_value字段)
     *
     * @param list 参数列表
     * @return 更新数量
     */
    int batchUpdateParamValues(@Param("list") List<CcdiModelParam> list);
}
```

---

### 2. 创建 Mapper XML

#### 2.1 创建资源目录

```
ccdi-project/src/main/resources/
└── mapper/
    └── ccdi/
        └── project/
```

#### 2.2 编写 Mapper XML

**文件路径:** `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiModelParamMapper.xml`

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.ccdi.project.mapper.CcdiModelParamMapper">

    <resultMap id="ModelParamResult" type="com.ruoyi.ccdi.project.domain.CcdiModelParam">
        <id property="id" column="id"/>
        <result property="projectId" column="project_id"/>
        <result property="modelCode" column="model_code"/>
        <result property="modelName" column="model_name"/>
        <result property="paramCode" column="param_code"/>
        <result property="paramName" column="param_name"/>
        <result property="paramDesc" column="param_desc"/>
        <result property="paramValue" column="param_value"/>
        <result property="paramUnit" column="param_unit"/>
        <result property="sortOrder" column="sort_order"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="remark" column="remark"/>
    </resultMap>

    <sql id="selectModelParamVo">
        select id, project_id, model_code, model_name, param_code, param_name, param_desc,
               param_value, param_unit, sort_order, create_by, create_time, update_by, update_time, remark
        from ccdi_model_param
    </sql>

    <select id="selectByProjectAndModel" resultMap="ModelParamResult">
        <include refid="selectModelParamVo"/>
        where project_id = #{projectId} and model_code = #{modelCode}
        order by sort_order asc
    </select>

    <select id="selectDistinctModels" resultMap="ModelParamResult">
        select distinct model_code, model_name
        from ccdi_model_param
        where project_id = #{projectId}
        order by model_code
    </select>

    <!-- 关键:只更新 param_value 字段 -->
    <update id="batchUpdateParamValues">
        <foreach collection="list" item="item" separator=";">
            update ccdi_model_param
            set param_value = #{item.paramValue},
                update_by = #{item.updateBy},
                update_time = sysdate()
            where id = #{item.id}
        </foreach>
    </update>

</mapper>
```

---

### 3. 创建 Service 接口

**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiModelParamService.java`

```java
package com.ruoyi.ccdi.project.service;

import com.ruoyi.ccdi.project.domain.dto.ModelParamQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveDTO;
import com.ruoyi.ccdi.project.domain.vo.ModelListVO;
import com.ruoyi.ccdi.project.domain.vo.ModelParamVO;
import java.util.List;

/**
 * 模型参数Service
 */
public interface ICcdiModelParamService {

    /**
     * 查询模型列表
     *
     * @param projectId 项目ID
     * @return 模型列表
     */
    List<ModelListVO> selectModelList(Long projectId);

    /**
     * 查询模型参数列表
     *
     * @param queryDTO 查询条件
     * @return 参数列表
     */
    List<ModelParamVO> selectParamList(ModelParamQueryDTO queryDTO);

    /**
     * 保存模型参数(只更新阈值)
     *
     * @param saveDTO 保存参数
     */
    void saveParams(ModelParamSaveDTO saveDTO);
}
```

---

### 4. 创建 Service 实现

#### 4.1 创建实现类目录

```
ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/
└── impl/
```

#### 4.2 编写 Service 实现

**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiModelParamServiceImpl.java`

```java
package com.ruoyi.ccdi.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.ccdi.project.domain.CcdiModelParam;
import com.ruoyi.ccdi.project.domain.dto.ModelParamQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveDTO;
import com.ruoyi.ccdi.project.domain.vo.ModelListVO;
import com.ruoyi.ccdi.project.domain.vo.ModelParamVO;
import com.ruoyi.ccdi.project.mapper.CcdiModelParamMapper;
import com.ruoyi.ccdi.project.service.ICcdiModelParamService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 模型参数Service实现
 */
@Service
public class CcdiModelParamServiceImpl implements ICcdiModelParamService {

    @Resource
    private CcdiModelParamMapper modelParamMapper;

    @Override
    public List<ModelListVO> selectModelList(Long projectId) {
        if (projectId == null) {
            projectId = 0L; // 默认查询系统级参数
        }

        List<ModelListVO> result = new ArrayList<>();
        List<CcdiModelParam> params = modelParamMapper.selectDistinctModels(projectId);

        params.forEach(param -> {
            ModelListVO vo = new ModelListVO();
            vo.setModelCode(param.getModelCode());
            vo.setModelName(param.getModelName());
            result.add(vo);
        });

        return result;
    }

    @Override
    public List<ModelParamVO> selectParamList(ModelParamQueryDTO queryDTO) {
        Long projectId = queryDTO.getProjectId();
        if (projectId == null) {
            projectId = 0L;
        }

        List<CcdiModelParam> params = modelParamMapper.selectByProjectAndModel(
            projectId,
            queryDTO.getModelCode()
        );

        List<ModelParamVO> result = new ArrayList<>();
        params.forEach(param -> {
            ModelParamVO vo = new ModelParamVO();
            BeanUtils.copyProperties(param, vo);
            result.add(vo);
        });

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveParams(ModelParamSaveDTO saveDTO) {
        Long projectId = saveDTO.getProjectId();
        if (projectId == null) {
            projectId = 0L;
        }

        String username = SecurityUtils.getUsername();
        Date now = new Date();

        // 查询现有参数
        List<CcdiModelParam> existingParams = modelParamMapper.selectByProjectAndModel(
            projectId,
            saveDTO.getModelCode()
        );

        if (existingParams.isEmpty()) {
            throw new ServiceException("未找到模型参数配置");
        }

        // 准备更新列表 - 只更新 param_value 字段
        List<CcdiModelParam> updateList = new ArrayList<>();
        for (ModelParamSaveDTO.ParamItem item : saveDTO.getParams()) {
            CcdiModelParam existing = existingParams.stream()
                .filter(p -> p.getParamCode().equals(item.getParamCode()))
                .findFirst()
                .orElse(null);

            if (existing != null) {
                // ⚠️ 关键:只修改 param_value 字段
                CcdiModelParam updateParam = new CcdiModelParam();
                updateParam.setId(existing.getId());
                updateParam.setParamValue(item.getParamValue()); // 只更新阈值
                updateParam.setUpdateBy(username);
                updateParam.setUpdateTime(now);
                updateList.add(updateParam);
            }
        }

        if (!updateList.isEmpty()) {
            modelParamMapper.batchUpdateParamValues(updateList);
        }
    }
}
```

---

### 5. 创建 Controller

**文件路径:** `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiModelParamController.java`

```java
package com.ruoyi.ccdi.project.controller;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.ccdi.project.domain.dto.ModelParamQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.ModelParamSaveDTO;
import com.ruoyi.ccdi.project.domain.vo.ModelListVO;
import com.ruoyi.ccdi.project.domain.vo.ModelParamVO;
import com.ruoyi.ccdi.project.service.ICcdiModelParamService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.annotation.Resource;
import java.util.List;

/**
 * 模型参数配置Controller
 */
@Tag(name = "模型参数配置")
@RestController
@RequestMapping("/ccdi/modelParam")
public class CcdiModelParamController extends BaseController {

    @Resource
    private ICcdiModelParamService modelParamService;

    /**
     * 查询模型列表
     */
    @Operation(summary = "查询模型列表")
    @GetMapping("/modelList")
    public AjaxResult listModels(@RequestParam(required = false) Long projectId) {
        List<ModelListVO> list = modelParamService.selectModelList(projectId);
        return success(list);
    }

    /**
     * 查询模型参数列表
     */
    @Operation(summary = "查询模型参数列表")
    @GetMapping("/list")
    public AjaxResult list(@Validated ModelParamQueryDTO queryDTO) {
        List<ModelParamVO> list = modelParamService.selectParamList(queryDTO);
        return success(list);
    }

    /**
     * 保存模型参数(只更新阈值)
     */
    @Operation(summary = "保存模型参数")
    @Log(title = "模型参数配置", businessType = BusinessType.UPDATE)
    @PostMapping("/save")
    public AjaxResult save(@Validated @RequestBody ModelParamSaveDTO saveDTO) {
        modelParamService.saveParams(saveDTO);
        return success("保存成功");
    }
}
```

---

## 验证清单

完成以下验证后,本任务才算完成:

- [ ] CcdiModelParamMapper 接口创建完成
- [ ] CcdiModelParamMapper.xml 创建完成
- [ ] ICcdiModelParamService 接口创建完成
- [ ] CcdiModelParamServiceImpl 实现类创建完成
- [ ] CcdiModelParamController 创建完成
- [ ] 所有类使用 import 导入,无全限定类名
- [ ] Service 使用 @Resource 注入
- [ ] Controller 添加了 Swagger 注解
- [ ] 项目编译无错误: `mvn clean compile`

---

## 注意事项

1. **Mapper XML 位置**: 必须放在 `resources/mapper/ccdi/project/` 目录下
2. **批量更新**: 使用 `separator=";"` 实现批量更新
3. **只更新阈值**: UPDATE 语句只更新 `param_value` 字段
4. **事务管理**: Service 实现类必须添加 `@Transactional` 注解
5. **异常处理**: 使用 `ServiceException` 抛出业务异常
6. **Swagger 文档**: Controller 必须添加 `@Tag` 和 `@Operation` 注解

---

## 下一步

完成本任务后,进入下一个任务: **03-后端功能测试.md**
