Administrator
5 hours ago 29674c95a7c1f57233c4182a72d01917a0be9689
feat(ai): 添加产品问答标签功能

- 在AiProductQuestionController中新增updateLabel接口用于更新标签
- 在AiProductQuestionLabelController中新增listAll接口获取所有标签
- 实现AiProductQuestionLabelService的listAllByCompanyId方法
- 实现AiProductQuestionService的updateLabel方法支持批量标签更新
- 创建新的labelSet.html页面实现标签设置界面
- 在产品问答列表页面添加打标签按钮和相关功能
- 修改视图控制器在名称显示中加入标签信息
- 更新数据库查询逻辑支持按公司ID过滤标签列表
9 files modified
1 files added
196 ■■■■■ changed files
src/main/java/cc/mrbird/febs/ai/controller/product/ViewController.java 8 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/AiProductQuestionController.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/ViewController.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/productQuestionLabel/AiProductQuestionLabelController.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionLabelService.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionLabelServiceImpl.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionServiceImpl.java 14 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/ai/productQuestion/labelSet.html 105 ●●●●● patch | view | raw | blame | history
src/main/resources/templates/febs/views/modules/ai/productQuestion/list.html 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/ai/controller/product/ViewController.java
@@ -182,8 +182,14 @@
                vos = allList.stream().map(AiProductQuestion -> {
                    AdminMoveChooseInfoVo vo = new AdminMoveChooseInfoVo();
                    vo.setId(AiProductQuestion.getId());
                    String name = AiProductQuestion.getTitle();
                    String difficulty = AiProductQuestion.getDifficulty() == 1 ? "简单" : AiProductQuestion.getDifficulty() == 2 ? "中等" : "困难";
                    vo.setName(difficulty+"-"+AiProductQuestion.getTitle());
                    name = difficulty+"-"+name;
                    String label = AiProductQuestion.getLabel();
                    if (StrUtil.isNotEmpty(label)){
                        name = label+"-"+name;
                    }
                    vo.setName(name);
                    return vo;
                }).collect(Collectors.toList());
            }
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/AiProductQuestionController.java
@@ -146,4 +146,11 @@
    public FebsResponse importDeliver(@RequestBody MultipartFile file){
        return aiProductQuestionService.importDeliver(file);
    }
    @PostMapping("updateLabel")
    @ControllerEndpoint(operation = "更新标签", exceptionMessage = "操作失败")
    public FebsResponse updateLabel(@RequestBody @Valid AiProductQuestion dto) {
        return aiProductQuestionService.updateLabel(dto.getIds(), dto.getLabel());
    }
}
src/main/java/cc/mrbird/febs/ai/controller/productQuestion/ViewController.java
@@ -7,6 +7,7 @@
import cc.mrbird.febs.ai.service.AiProductQuestionService;
import cc.mrbird.febs.common.entity.FebsConstant;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.mall.entity.MallMember;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
@@ -17,7 +18,9 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author Administrator
@@ -72,4 +75,14 @@
        model.addAttribute("aiProductQuestion", entity);
        return FebsUtil.view("modules/ai/productQuestion/info");
    }
    @GetMapping("labelSet/{strIds}")
    @RequiresPermissions("productQuestionList:labelSet")
    public String vipLevelSetting(@PathVariable(value = "strIds") String strIds, Model model) {
        Map<String, Object> data = new HashMap<>();
        data.put("ids", strIds);
        model.addAttribute("labelSet", data);
        return FebsUtil.view("modules/ai/productQuestion/labelSet");
    }
}
src/main/java/cc/mrbird/febs/ai/controller/productQuestionLabel/AiProductQuestionLabelController.java
@@ -14,6 +14,7 @@
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
@@ -51,4 +52,12 @@
        return aiProductQuestionLabelService.update(dto);
    }
    @GetMapping("listAll")
    @ControllerEndpoint(operation = "获取所有标签", exceptionMessage = "获取标签失败")
    public FebsResponse listAll() {
        String companyId = getCurrentUserCompanyId();
        List<AiProductQuestionLabel> labels = aiProductQuestionLabelService.listAllByCompanyId(companyId);
        return new FebsResponse().success().data(labels);
    }
}
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionLabelService.java
@@ -6,6 +6,7 @@
import cc.mrbird.febs.common.entity.QueryRequest;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface AiProductQuestionLabelService extends IService<AiProductQuestionLabel> {
@@ -16,4 +17,6 @@
    FebsResponse add(AiProductQuestionLabel dto);
    FebsResponse update(AiProductQuestionLabel dto);
    List<AiProductQuestionLabel> listAllByCompanyId(String companyId);
}
src/main/java/cc/mrbird/febs/ai/service/AiProductQuestionService.java
@@ -58,4 +58,6 @@
    void exportProductQuestion(AiProductQuestion dto, HttpServletResponse response);
    FebsResponse importDeliver(MultipartFile file);
    FebsResponse updateLabel(String ids, String label);
}
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionLabelServiceImpl.java
@@ -19,6 +19,7 @@
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
@@ -72,4 +73,14 @@
        }
        return new FebsResponse().success().message("操作成功");
    }
    @Override
    public List<AiProductQuestionLabel> listAllByCompanyId(String companyId) {
        LambdaQueryWrapper<AiProductQuestionLabel> query = Wrappers.lambdaQuery(AiProductQuestionLabel.class);
        if (StrUtil.isNotEmpty(companyId)){
            query.eq(AiProductQuestionLabel::getCompanyId, companyId);
        }
        query.orderByDesc(AiProductQuestionLabel::getCreatedTime);
        return aiProductQuestionLabelMapper.selectList(query);
    }
}
src/main/java/cc/mrbird/febs/ai/service/impl/AiProductQuestionServiceImpl.java
@@ -640,4 +640,18 @@
    }
    @Override
    public FebsResponse updateLabel(String ids, String label) {
        if (StrUtil.isEmpty(ids)) {
            throw new FebsException("参数错误");
        }
        List<String> idList = StrUtil.split(ids, ',');
        this.update(null,
                Wrappers.lambdaUpdate(AiProductQuestion.class)
                        .set(AiProductQuestion::getLabel, label)
                        .set(AiProductQuestion::getUpdatedTime, new Date())
                        .in(AiProductQuestion::getId, idList));
        return new FebsResponse().success().message("操作成功");
    }
}
src/main/resources/templates/febs/views/modules/ai/productQuestion/labelSet.html
New file
@@ -0,0 +1,105 @@
<style>
    #labelSet {
        padding: 20px 25px 25px 0;
    }
    #labelSet .layui-treeSelect .ztree li a, .ztree li span {
        margin: 0 0 2px 3px !important;
    }
    #labelSet #data-permission-tree-block {
        border: 1px solid #eee;
        border-radius: 2px;
        padding: 3px 0;
    }
    #labelSet .layui-treeSelect .ztree li span.button.switch {
        top: 1px;
        left: 3px;
    }
</style>
<div class="layui-fluid" id="labelSet">
    <form class="layui-form" action="" lay-filter="labelSet-form">
        <div class="layui-form-item febs-hide">
            <label class="layui-form-label febs-form-item-require">id:</label>
            <div class="layui-input-block">
                <input type="text" name="ids">
            </div>
        </div>
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label">标签:</label>
                <div class="layui-input-inline">
                    <select lay-verify="required" name="label" class="labelSet-level" id="labelNameSet">
                        <option value="">请选择</option>
                    </select>
                </div>
            </div>
        </div>
        <div class="layui-form-item febs-hide">
            <button class="layui-btn" lay-submit="" lay-filter="labelSet-form-submit" id="submit"></button>
        </div>
    </form>
</div>
<script data-th-inline="javascript">
    layui.use(['febs', 'form', 'formSelects', 'validate', 'treeSelect', 'eleTree'], function () {
        var $ = layui.jquery,
            febs = layui.febs,
            layer = layui.layer,
            formSelects = layui.formSelects,
            treeSelect = layui.treeSelect,
            form = layui.form,
            eleTree = layui.eleTree,
            labelSet = [[${labelSet}]],
            $view = $('#labelSet'),
            validate = layui.validate,
            _deptTree;
        form.render();
        initLabelSetLevel();
        function initLabelSetLevel() {
            form.val("labelSet-form", {
                "ids": labelSet.ids
            });
        }
        //(下拉框)
        $.get(ctx + 'admin/aiProductQuestionLabel/listAll', function (res) {
            var data = res.data;
            for (var k in data)
            {
                $(".labelSet-level").append("<option value='" + data[k].name + "'>" + data[k].name + "</option>");
            }
            layui.use('form', function () {
                var form = layui.form;
                form.render();
            });
        });
        form.on('submit(labelSet-form-submit)', function (data) {
            $.ajax({
                'url':ctx + 'admin/productQuestion/updateLabel',
                'type':'post',
                'dataType':'json',
                'headers' : {'Content-Type' : 'application/json;charset=utf-8'}, //接口json格式
                'traditional': true,//ajax传递数组必须添加属性
                'data':JSON.stringify(data.field),
                'success':function (data) {
                    if(data.code==200){
                        layer.closeAll();
                        febs.alert.success(data.message);
                    }else{
                        febs.alert.warn(data.message);
                    }
                },
                'error':function () {
                    febs.alert.warn('服务器繁忙');
                }
            })
            return false;
        });
    });
</script>
src/main/resources/templates/febs/views/modules/ai/productQuestion/list.html
@@ -56,6 +56,7 @@
        <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain" shiro:hasPermission="productQuestionList:aiAdd" lay-event="productQuestionStateOpen">启用</button>
        <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain" shiro:hasPermission="productQuestionList:aiAdd" lay-event="productQuestionStateClose">禁用</button>
        <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain" shiro:hasPermission="productQuestionList:aiAdd" lay-event="productQuestionDelete">删除</button>
        <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain" shiro:hasPermission="productQuestionList:aiAdd" lay-event="productQuestionAddLabel">打标签</button>
        <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain" shiro:hasPermission="productQuestionList:aiAdd"  lay-event="exportProductQuestion">导出</button>
        <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain" shiro:hasPermission="productQuestionList:aiAdd" id="importProductQuestion"  lay-event="importProductQuestion">导入</button>
    </div>
@@ -267,6 +268,28 @@
                });
                window.location.href = ctx + "admin/productQuestion/exportProductQuestion?ids="+ids;
            }
            if (layEvent === 'productQuestionAddLabel') {
                var checkData = table.checkStatus('productQuestionTable').data;
                if (checkData.length <= 0) {
                    febs.alert.warn('请选择');
                    return;
                }
                var ids = [];
                layui.each(checkData, function (key, item) {
                    ids.push(item.id)
                });
                let strIds = ids.join(',');
                febs.modal.open('打标签', 'modules/ai/productQuestion/labelSet/' + strIds, {
                    btn: ['确定', '取消'],
                    area:['100%','100%'],
                    yes: function (index, layero) {
                        $('#labelSet').find('#submit').trigger('click');
                    },
                    btn2: function () {
                        layer.closeAll();
                    }
                });
            }
        });
        upload.render({
@@ -310,6 +333,7 @@
                    {field: 'state', title: '状态', templet: '#productQuestionStateSwitch', minWidth: 130,align:'center'},
                    {field: 'productCategoryName', title: '分类', minWidth: 100,align:'center'},
                    {field: 'title', title: '题目', minWidth: 100,align:'center'},
                    {field: 'label', title: '标签', minWidth: 100,align:'center'},
                    {templet:"#difficultyFormat",  title: '难度', minWidth: 140,align:'center'},
                    {field: 'companyId', title: '公司编码', minWidth: 150,align:'center'},
                ]]