From 5a516b0b01cb06a8a92e01fbbc97e4222fe83b10 Mon Sep 17 00:00:00 2001 From: stream Date: Tue, 9 Sep 2025 16:57:25 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=20=E8=BF=9E=E7=BB=AD=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E6=8E=A5=E5=8F=A3=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/vi/ViCorpusController.java | 77 +++++++--- .../com/cmvr/vi/model/domain/ViCorpus.java | 5 +- .../vi/model/vo/ViContinuousCorpusVO.java | 3 + .../java/com/cmvr/vi/model/vo/ViCorpusVO.java | 3 + .../com/cmvr/vi/service/IViCorpusService.java | 18 ++- .../vi/service/impl/IViCorpusServiceImpl.java | 136 ++++++++++++++++-- 6 files changed, 209 insertions(+), 33 deletions(-) diff --git a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViCorpusController.java b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViCorpusController.java index 93c374e..0aaa339 100644 --- a/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViCorpusController.java +++ b/cmvr-iot-admin/src/main/java/com/cmvr/web/controller/vi/ViCorpusController.java @@ -38,6 +38,8 @@ public class ViCorpusController extends BaseController { return success(viCorpusService.selectViCorpusByCorpusId(corpusId)); } + // ----------------------- 单次对话语料/唤醒语料 -------------------------- + @ApiOperation("查询单次对话语料/唤醒语料列表") @PreAuthorize("@ss.hasPermi('vi:corpus:list')") @GetMapping("/single/list") @@ -47,6 +49,36 @@ public class ViCorpusController extends BaseController { return getDataTable(list); } + @ApiOperation("新增单次对话语料/唤醒语料") + @PreAuthorize("@ss.hasPermi('vi:corpus:add')") + @PostMapping + public AjaxResult add(@RequestBody ViCorpus viCorpus) { + return toAjax(viCorpusService.insertViCorpus(viCorpus)); + } + + @ApiOperation("批量新增单次对话语料/唤醒语料") + @PreAuthorize("@ss.hasPermi('vi:corpus:add')") + @PostMapping("/insertBatch") + public AjaxResult insertBatch(@RequestBody List data) { + return toAjax(viCorpusService.insertBatch(data)); + } + + @ApiOperation("删除单次对话语料/唤醒语料") + @PreAuthorize("@ss.hasPermi('vi:corpus:remove')") + @DeleteMapping("/{corpusIds}") + public AjaxResult remove(@PathVariable Long[] corpusIds) { + return toAjax(viCorpusService.deleteViCorpusByCorpusIds(corpusIds)); + } + + @ApiOperation("修改单次对话语料/唤醒语料") + @PreAuthorize("@ss.hasPermi('vi:corpus:edit')") + @PutMapping + public AjaxResult edit(@RequestBody ViCorpus viCorpus) { + return toAjax(viCorpusService.updateViCorpus(viCorpus)); + } + + // ----------------------- 连续对话 -------------------------- + @ApiOperation("查询连续对话列表") @PreAuthorize("@ss.hasPermi('vi:corpus:list')") @GetMapping("/continuous/list") @@ -56,31 +88,40 @@ public class ViCorpusController extends BaseController { return getDataTable(list); } - @ApiOperation("新增语料") + @ApiOperation("新增连续对话") @PreAuthorize("@ss.hasPermi('vi:corpus:add')") - @PostMapping - public AjaxResult add(@RequestBody ViCorpus viCorpus) { - return toAjax(viCorpusService.insertViCorpus(viCorpus)); + @PostMapping("/continuous/insert") + public AjaxResult add(@RequestBody ViContinuousCorpusVO viContinuousCorpusVO) { + return toAjax(viCorpusService.insertContinuousViCorpus(viContinuousCorpusVO)); } - @ApiOperation("批量新增/修改") + @ApiOperation("修改连续对话") @PreAuthorize("@ss.hasPermi('vi:corpus:add')") + @PostMapping("/continuous/update") + public AjaxResult update(@RequestBody ViContinuousCorpusVO viContinuousCorpusVO) { + return toAjax(viCorpusService.updateContinuousViCorpus(viContinuousCorpusVO)); + } + + @ApiOperation("删除连续对话") + @PreAuthorize("@ss.hasPermi('vi:corpus:remove')") + @DeleteMapping("/continuous") + public AjaxResult continuousRemove(@RequestBody String[] parentIds) { + return toAjax(viCorpusService.deleteViCorpusByParentIds(parentIds)); + } + +/* @ApiOperation("批量修改") + @PreAuthorize("@ss.hasPermi('vi:corpus:edit')") + @PostMapping("/updateBatch") + public AjaxResult updateBatch(@RequestBody List data) { + return toAjax(viCorpusService.updateBatch(data)); + }*/ + +/* @ApiOperation("批量新增/修改") + @PreAuthorize("@ss.hasPermi('vi:corpus:edit')") @PostMapping("/insertOrUpdateBatch") public AjaxResult insertOrUpdateBatch(@RequestBody List data) { return toAjax(viCorpusService.insertOrUpdateBatch(data)); - } + }*/ - @ApiOperation("修改语料") - @PreAuthorize("@ss.hasPermi('vi:corpus:edit')") - @PutMapping - public AjaxResult edit(@RequestBody ViCorpus viCorpus) { - return toAjax(viCorpusService.updateViCorpus(viCorpus)); - } - @ApiOperation("删除语料") - @PreAuthorize("@ss.hasPermi('vi:corpus:remove')") - @DeleteMapping("/{corpusIds}") - public AjaxResult remove(@PathVariable Long[] corpusIds) { - return toAjax(viCorpusService.deleteViCorpusByCorpusIds(corpusIds)); - } } diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/domain/ViCorpus.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/domain/ViCorpus.java index 77e6361..0af674e 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/domain/ViCorpus.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/domain/ViCorpus.java @@ -18,6 +18,9 @@ public class ViCorpus extends BaseEntity { @TableId(type = IdType.AUTO) private Long corpusId; + @ApiModelProperty("测试语料-连续对话的父ID") + private String parentId; + @Excel(name = "语料名称") @ApiModelProperty("语料名称") private String corpusName; @@ -42,7 +45,7 @@ public class ViCorpus extends BaseEntity { @ApiModelProperty("方言") private String dialect; -// @Excel(name = "预期结果(预留)") + // @Excel(name = "预期结果(预留)") @ApiModelProperty("预期结果(预留)") private String expectedResult; diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViContinuousCorpusVO.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViContinuousCorpusVO.java index 2ca2640..54c3ab1 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViContinuousCorpusVO.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViContinuousCorpusVO.java @@ -11,6 +11,9 @@ import java.util.List; @ApiModel("连续对话分组VO") public class ViContinuousCorpusVO { + @ApiModelProperty("测试语料-连续对话的父ID") + private String parentId; + @ApiModelProperty("语料名称") private String corpusName; diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViCorpusVO.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViCorpusVO.java index 6d72b8e..96973d9 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViCorpusVO.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/model/vo/ViCorpusVO.java @@ -10,6 +10,9 @@ import javax.validation.constraints.NotEmpty; @ApiModel("查询单次对话语料/唤醒语料VO") public class ViCorpusVO { + @ApiModelProperty("测试语料-连续对话的父ID") + private String parentId; + @ApiModelProperty("语料名称") private String corpusName; diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViCorpusService.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViCorpusService.java index 98e6fb1..61b5a2c 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViCorpusService.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/IViCorpusService.java @@ -51,7 +51,7 @@ public interface IViCorpusService extends IService { * @param viCorpus 语料库 * @return 结果 */ - public boolean insertOrUpdateBatch(List viCorpus); + public boolean insertBatch(List viCorpus); /** * 修改语料库 @@ -69,4 +69,20 @@ public interface IViCorpusService extends IService { */ public int deleteViCorpusByCorpusIds(Long[] corpusIds); + /** + * 批量新增/修改语料库 + */ + int insertOrUpdateBatch(List data); + + /** + * 新增连续对话 + */ + boolean insertContinuousViCorpus(ViContinuousCorpusVO viContinuousCorpusVO); + + /** + * 修改连续对话 + */ + int updateContinuousViCorpus(ViContinuousCorpusVO viContinuousCorpusVO); + + int deleteViCorpusByParentIds(String[] parentIds); } diff --git a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/IViCorpusServiceImpl.java b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/IViCorpusServiceImpl.java index 5600e6a..5980b08 100644 --- a/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/IViCorpusServiceImpl.java +++ b/cmvr-iot-vi/src/main/java/com/cmvr/vi/service/impl/IViCorpusServiceImpl.java @@ -1,9 +1,11 @@ package com.cmvr.vi.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.cmvr.common.utils.uuid.IdUtils; import com.cmvr.vi.enums.ViCorpusEnum; import com.cmvr.vi.mapper.ViCorpusMapper; import com.cmvr.vi.model.domain.ViCorpus; @@ -12,9 +14,14 @@ import com.cmvr.vi.model.vo.ViCorpusVO; import com.cmvr.vi.service.IViCorpusService; import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; /** * 语料库Service业务层处理 @@ -59,9 +66,10 @@ public class IViCorpusServiceImpl extends ServiceImpl @Override public List selectContinuousList(ViCorpus viCorpus) { - // 先查父级 + // 查询父级 MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>(); - wrapper.select(ViCorpus::getCorpusName) + wrapper.select(ViCorpus::getParentId) + .select(ViCorpus::getCorpusName) .select(ViCorpus::getVoiceType) .select(ViCorpus::getDialect) .eq(ViCorpus::getType, ViCorpusEnum.TEST) @@ -69,33 +77,36 @@ public class IViCorpusServiceImpl extends ServiceImpl .like(ObjUtil.isNotEmpty(viCorpus.getVoiceType()), ViCorpus::getVoiceType, viCorpus.getVoiceType()) .like(ObjUtil.isNotEmpty(viCorpus.getDialect()), ViCorpus::getDialect, viCorpus.getDialect()) .like(ObjUtil.isNotEmpty(viCorpus.getCorpusName()), ViCorpus::getCorpusName, viCorpus.getCorpusName()) - .groupBy(ViCorpus::getCorpusName, ViCorpus::getVoiceType, ViCorpus::getDialect); + .groupBy(ViCorpus::getParentId, ViCorpus::getVoiceType, ViCorpus::getDialect, ViCorpus::getCorpusName); List list = this.baseMapper.selectJoinList(ViContinuousCorpusVO.class, wrapper); - // 再查 children + // 查询 children 用 parentId 关联 for (ViContinuousCorpusVO vo : list) { - List children = this.list(Wrappers.lambdaQuery(ViCorpus.class) - .eq(ViCorpus::getCorpusName, vo.getCorpusName()) - .eq(ViCorpus::getVoiceType, vo.getVoiceType()) - .eq(ViCorpus::getDialect, vo.getDialect()) - .eq(ViCorpus::getContinuous, 0) - .eq(ViCorpus::getType, ViCorpusEnum.TEST) - .orderByAsc(ViCorpus::getSortOrder)); + List children = this.list( + Wrappers.lambdaQuery(ViCorpus.class) + .eq(ViCorpus::getParentId, vo.getParentId()) + .eq(ViCorpus::getContinuous, 0) + .eq(ViCorpus::getType, ViCorpusEnum.TEST) + .orderByAsc(ViCorpus::getSortOrder) + ); vo.setChildren(children); } return list; } + @Override public int insertViCorpus(ViCorpus viCorpus) { + viCorpus.setParentId(IdUtils.fastSimpleUUID()); return this.baseMapper.insert(viCorpus); } @Override - public boolean insertOrUpdateBatch(List data) { - return this.saveOrUpdateBatch(data); + public boolean insertBatch(List data) { + data.forEach(v -> v.setParentId(IdUtils.fastSimpleUUID())); + return this.saveBatch(data); } @Override @@ -108,4 +119,103 @@ public class IViCorpusServiceImpl extends ServiceImpl return this.baseMapper.deleteBatchIds(Arrays.asList(corpusIds)); } + @Override + public int insertOrUpdateBatch(List data) { + if (CollUtil.isEmpty(data)) { + throw new IllegalArgumentException("data must not be null"); + } + + // 非空 id → 更新 + List updateList = data.stream() + .filter(item -> item.getCorpusId() != null) + .collect(Collectors.toList()); + + // 空 id → 新增 + List insertList = data.stream() + .filter(item -> item.getCorpusId() == null) + .collect(Collectors.toList()); + + if (!insertList.isEmpty()) { + this.saveBatch(insertList); + } + + // 批量更新(自定义 XML,返回影响行数) + if (!updateList.isEmpty()) { + for (ViCorpus viCorpus : updateList) { + this.updateById(viCorpus); + } + } + return data.size(); + } + + @Override + public boolean insertContinuousViCorpus(ViContinuousCorpusVO viContinuousCorpusVO) { + String parentId = IdUtils.fastSimpleUUID(); + List children = viContinuousCorpusVO.getChildren(); + children.forEach(v -> v.setParentId(parentId)); + return this.insertBatch(children); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int updateContinuousViCorpus(ViContinuousCorpusVO viContinuousCorpusVO) { + String parentId = viContinuousCorpusVO.getParentId(); + + // parentId 下现有 corpusId + List dbIds = this.list(new LambdaQueryWrapper() + .select(ViCorpus::getCorpusId) + .eq(ViCorpus::getParentId, parentId)) + .stream() + .map(ViCorpus::getCorpusId) + .collect(Collectors.toList()); + + List children = viContinuousCorpusVO.getChildren(); + + // 新增、更新、保留 + List addList = new ArrayList<>(); + List updateList = new ArrayList<>(); + Set keepIds = new HashSet<>(); + + for (ViCorpus child : children) { + if (ObjUtil.isEmpty(child.getCorpusId())) { + // 新增 + child.setParentId(parentId); + addList.add(child); + } else { + // 更新 + updateList.add(child); + keepIds.add(child.getCorpusId()); + } + } + + // 要删除的 + List removeIds = dbIds.stream() + .filter(id -> !keepIds.contains(id)) + .collect(Collectors.toList()); + + if (!addList.isEmpty()) { + this.saveBatch(addList); + } + if (!updateList.isEmpty()) { + this.updateBatchById(updateList); + } + if (!removeIds.isEmpty()) { + this.removeByIds(removeIds); + } + + return addList.size() + updateList.size() + removeIds.size(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteViCorpusByParentIds(String[] parentIds) { + if (parentIds == null || parentIds.length == 0) { + return 0; + } + return this.baseMapper.delete( + new LambdaQueryWrapper() + .in(ViCorpus::getParentId, Arrays.asList(parentIds)) + ); + } + }