Administrator
2026-02-12 e89b46eccadc107be6b6cb54e7b257a8ccb8455e
feat(ai): 添加AI产品题目任务详情功能

- 新增AdminQuestionInfoVo数据传输对象
- 在AiProductQuestionItem实体中添加jobId字段
- 实现jobChild分页查询接口和映射器方法
- 在控制器中添加jobChild查询接口
- 创建任务详情页面模板jobInfoList.html
- 在任务列表页面添加详情按钮和弹窗功能
- 实现任务子项分页查询SQL映射
- 在创建题目项时设置jobId关联关系
2 files added
8 files modified
116 ■■■■■ changed files
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/AiProductQuestionController.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/ViewController.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/entity/AiProductQuestionItem.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/mapper/AiProductQuestionMapper.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/res/AdminQuestionInfoVo.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionService.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionServiceImpl.java 11 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/AiProductQuestionMapper.xml 8 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/ai/productQuestion/jobInfoList.html 37 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/ai/productQuestion/jobList.html 18 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/AiProductQuestionController.java
@@ -67,6 +67,12 @@
        Map<String, Object> data = getDataTable(aiProductQuestionService.listJobInPage(dto, request));
        return new FebsResponse().success().data(data);
    }
    @GetMapping("/jobChild")
    public FebsResponse jobChild(QueryRequest request, AiProductQuestionJob dto, String jobId) {
        dto.setId(jobId);
        Map<String, Object> dataTable = getDataTable(aiProductQuestionService.jobChild(request, dto));
        return new FebsResponse().success().data(dataTable);
    }
    @GetMapping("changeState/{id}/{state}")
    @ControllerEndpoint(operation = "状态操作", exceptionMessage = "操作失败")
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/ViewController.java
@@ -76,7 +76,17 @@
        return FebsUtil.view("modules/ai/productQuestion/info");
    }
    /**
     * @param id
     * @param model
     * @return
     */
    @GetMapping("jobInfoList/{id}")
    @RequiresPermissions("jobInfoList:update")
    public String jobInfoList(@PathVariable String id, Model model) {
        model.addAttribute("jobId", id);
        return FebsUtil.view("modules/ai/productQuestion/jobInfoList");
    }
    @GetMapping("labelSet/{strIds}")
    @RequiresPermissions("productQuestionList:labelSet")
    public String vipLevelSetting(@PathVariable(value = "strIds") String strIds, Model model) {
src/main/java/cc/mrbird/febs/ai/entity/AiProductQuestionItem.java
@@ -30,6 +30,11 @@
    private String title;
    /**
     * AI添加任务ID
     */
    private String jobId;
    /**
     * 答案
     */
    private String answer;
src/main/java/cc/mrbird/febs/ai/mapper/AiProductQuestionMapper.java
@@ -1,7 +1,12 @@
package cc.mrbird.febs.ai.mapper;
import cc.mrbird.febs.ai.entity.AiProductQuestion;
import cc.mrbird.febs.ai.entity.AiProductQuestionJob;
import cc.mrbird.febs.ai.res.AdminQuestionInfoVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
/**
 * AI产品题目 Mapper接口
@@ -11,4 +16,5 @@
 */
public interface AiProductQuestionMapper extends BaseMapper<AiProductQuestion> {
    IPage<AdminQuestionInfoVo> selectJobChildPage(Page<AdminQuestionInfoVo> page, @Param("record")AiProductQuestionJob dto);
}
src/main/java/cc/mrbird/febs/ai/res/AdminQuestionInfoVo.java
New file
@@ -0,0 +1,10 @@
package cc.mrbird.febs.ai.res;
import lombok.Data;
@Data
public class AdminQuestionInfoVo {
    private String id;
}
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionService.java
@@ -4,6 +4,7 @@
import cc.mrbird.febs.ai.entity.AiProductQuestionJob;
import cc.mrbird.febs.ai.entity.AiProductRole;
import cc.mrbird.febs.ai.req.AiProductQuestionAiDto;
import cc.mrbird.febs.ai.res.AdminQuestionInfoVo;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -66,4 +67,6 @@
    void exportNewProductQuestion(AiProductQuestion dto, HttpServletResponse response);
    FebsResponse importNewProductQuestion(MultipartFile file, String categoryId, String companyId, Integer difficulty);
    IPage<AdminQuestionInfoVo> jobChild(QueryRequest request, AiProductQuestionJob dto);
}
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionServiceImpl.java
@@ -4,6 +4,7 @@
import cc.mrbird.febs.ai.mapper.AiProductQuestionJobMapper;
import cc.mrbird.febs.ai.mapper.AiProductQuestionMapper;
import cc.mrbird.febs.ai.req.AiProductQuestionAiDto;
import cc.mrbird.febs.ai.res.AdminQuestionInfoVo;
import cc.mrbird.febs.ai.service.AiProductCategoryService;
import cc.mrbird.febs.ai.service.AiProductQuestionItemService;
import cc.mrbird.febs.ai.service.AiProductQuestionService;
@@ -20,6 +21,7 @@
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.mall.entity.MallOrderItem;
import cc.mrbird.febs.mall.vo.AdminAgentMemberVo;
import cc.mrbird.febs.rabbit.producter.AgentProducer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
@@ -48,6 +50,7 @@
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
@@ -425,6 +428,7 @@
                        aiProductQuestionItem.setAnswer(answer.getStr("answer"));
                        aiProductQuestionItem.setCorrectAnswer(answer.getInt("type") == 2 ? 1 : 0);
                        aiProductQuestionItem.setAnswerAnalysis(answer.getStr("analysis"));
                        aiProductQuestionItem.setJobId( id);
                        aiProductQuestionItem.setCreatedTime(createdTime);
                        aiProductQuestionItemService.getBaseMapper().insert(aiProductQuestionItem);
                    }
@@ -899,6 +903,13 @@
        }
    }
    @Override
    public IPage<AdminQuestionInfoVo> jobChild(QueryRequest request, AiProductQuestionJob dto) {
        Page<AdminQuestionInfoVo> page = new Page<>(request.getPageNum(), request.getPageSize());
        return aiProductQuestionMapper.selectJobChildPage(page, dto);
    }
    private void saveQuestionWithItems(AiProductQuestion question, List<AiProductQuestionItem> items) {
        // 保存题目(新增一次)
        this.save(question);
src/main/resources/mapper/modules/AiProductQuestionMapper.xml
@@ -1,4 +1,12 @@
<?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="cc.mrbird.febs.ai.mapper.AiProductQuestionMapper">
    <select id="selectJobChildPage" resultType="cc.mrbird.febs.ai.res.AdminQuestionInfoVo">
        select a.id
        from ai_product_question_item a
        where a.job_id = #{record.id}
        ORDER BY a.title DESC
    </select>
</mapper>
src/main/resources/templates/febs/views/modules/ai/productQuestion/jobInfoList.html
New file
@@ -0,0 +1,37 @@
<div className="layui-fluid layui-anim febs-anim" id="febs-job-child" lay-title="全部成员">
    <div className="layui-row febs-container">
        <div className="layui-col-md12">
            <div className="layui-card">
                <div className="layui-card-body febs-table-full">
                    <table lay-filter="jobChild" lay-data="{id: 'jobChild'}"></table>
                </div>
            </div>
        </div>
    </div>
</div>
<script data-th-inline="javascript" type="text/javascript">
    layui.use(['jquery', 'form', 'table', 'febs'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            form = layui.form,
            table = layui.table,
            $view = $('#febs-job-child'),
            jobId = [[${jobId}]],  // 确保Thymeleaf传递正确
            tableIns;
        form.render();
        initJobChildTable();
        function initJobChildTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
                id: 'jobChild',
                url: ctx + 'admin/productQuestion/jobChild?jobId=' + jobId,
                cols: [[
                    {field: 'id', title: 'ID', minWidth: 150, align: 'center'},
                    // 添加更多列定义...
                ]]
            });
        }
    });
</script>
src/main/resources/templates/febs/views/modules/ai/productQuestion/jobList.html
@@ -55,6 +55,10 @@
    </div>
</script>
<script type="text/html" id="productQuestionJobOption">
    <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="jobInfoList:update" lay-event="productQuestionJobInfoEvent">详情</button>
</script>
<script type="text/html" id="difficultyFormat">
    {{# if(d.difficulty == 1) { }}
    <span>简单</span>
@@ -160,6 +164,19 @@
            });
        }
        // 初始化表格操作栏各个按钮功能
        table.on('tool(productQuestionJobTable)', function (obj) {
            console.log("触发事件:", obj.event); // 调试信息
            var data = obj.data,
                layEvent = obj.event;
            if (layEvent === 'productQuestionJobInfoEvent') {
                console.log("触发事件-ID:", data.id)
                febs.modal.open( '详情', 'modules/ai/productQuestion/jobInfoList/' + data.id, {
                    maxmin: true,
                });
            }
        });
        function initproductQuestionJobTable() {
            tableIns = febs.table.init({
                elem: $view.find('table'),
@@ -169,6 +186,7 @@
                defaultToolbar:[],
                cols: [[
                    {type: 'checkbox'},
                    {title: '操作', toolbar: '#productQuestionJobOption', minWidth: 200, align: 'center'},
                    {type: 'numbers', title: '', width: 80},
                    {field: 'title', title: '要求', minWidth: 100,align:'center'},
                    {field: 'questionCnt', title: '生成总数', minWidth: 100,align:'center'},