refactor(ai): 重构AI模块文件处理和模型管理功能

- 修改AbstractFileClient移除域名拼接逻辑
- 将getModel接口改为getEnabledModels批量获取已启用模型
- 更新AiSampleMapper查询语句改用LEFT JOIN并添加筛选条件
- 移除application-local.yaml中的file-server配置项
- 添加ImgJsonSerializer组件处理图片URL序列化
- 优化AiSampleServiceImpl文件上传逻辑
- 调整分页参数验证注解格式
This commit is contained in:
2026-02-28 10:19:04 +08:00
parent 4fbe69062c
commit 2bd20404ba
13 changed files with 55 additions and 57 deletions

View File

@@ -26,7 +26,7 @@ public class PageParam implements Serializable {
/** /**
* 页码,从 1 开始", example = "1 * 页码,从 1 开始", example = "1
*/ */
@NotNull(message = "页码不能为空") @NotNull(message = "页码不能为空" )
@Min(value = 1, message = "页码最小值为 1") @Min(value = 1, message = "页码最小值为 1")
private Integer pageNo = 1; private Integer pageNo = 1;

View File

@@ -1,64 +1,50 @@
/* package com.tashow.cloud.common.serializer;
* Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
*
* https://www.mall4j.com/
*
* 未经允许不可做商业用途
*
* 版权所有侵权必究
*/
package com.tashow.cloud.common.util.serializer;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** /**
* @author lanhai * 图片URL序列化器
* 自动为相对路径的图片添加文件服务器前缀
*/ */
@Component @Component
public class ImgJsonSerializer extends JsonSerializer<String> { public class ImgJsonSerializer extends JsonSerializer<String> {
/* @Autowired @Value("${file-server}")
private Qiniu qiniu; private String fileServer;
@Autowired
private ImgUploadUtil imgUploadUtil;*/
@Override @Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
/*if (StrUtil.isBlank(value)) { if (StrUtil.isBlank(value)) {
gen.writeString(StrUtil.EMPTY); gen.writeString(StrUtil.EMPTY);
return; return;
} }
String[] imgs = value.split(StrUtil.COMMA); String[] imgs = value.split(StrUtil.COMMA);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
String resourceUrl = ""; String resourceUrl = "";
String rule="^((http[s]{0,1})://)"; String rule = "^((http[s]{0,1})://)";
Pattern pattern= Pattern.compile(rule); Pattern pattern = Pattern.compile(rule);
if (Objects.equals(imgUploadUtil.getUploadType(), 2)) {
resourceUrl = qiniu.getResourcesUrl(); resourceUrl = fileServer;
} else if (Objects.equals(imgUploadUtil.getUploadType(), 1)) {
resourceUrl = imgUploadUtil.getResourceUrl();
}
for (String img : imgs) { for (String img : imgs) {
Matcher matcher = pattern.matcher(img); Matcher matcher = pattern.matcher(img);
//若图片以http或https开头直接返回 //若图片以http或https开头直接返回
if (matcher.find()){ if (matcher.find()) {
sb.append(img).append(StrUtil.COMMA); sb.append(img).append(StrUtil.COMMA);
}else { } else {
sb.append(resourceUrl).append(img).append(StrUtil.COMMA); sb.append(resourceUrl).append(img).append(StrUtil.COMMA);
} }
} }
sb.deleteCharAt(sb.length()-1); sb.deleteCharAt(sb.length() - 1);
gen.writeString(sb.toString());*/ gen.writeString(sb.toString());
} }
} }

View File

@@ -1,6 +1,9 @@
package com.tashow.cloud.ai.controller.admin.aisample.vo; package com.tashow.cloud.ai.controller.admin.aisample.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tashow.cloud.common.serializer.ImgJsonSerializer;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -10,6 +13,7 @@ import lombok.Data;
public class AiSampleFileRespVO { public class AiSampleFileRespVO {
@Schema(description = "文件地址") @Schema(description = "文件地址")
@JsonSerialize(using = ImgJsonSerializer.class)
private String fileUrl; private String fileUrl;
@Schema(description = "文件名称") @Schema(description = "文件名称")

View File

@@ -12,10 +12,10 @@ import lombok.ToString;
@ToString(callSuper = true) @ToString(callSuper = true)
public class AiSamplePageReqVO extends PageParam { public class AiSamplePageReqVO extends PageParam {
@Schema(description = "标签ids", example = "25839") @Schema(description = "标签ids")
private String tagIds; private String tagIds;
@Schema(description = "样本名称", example = "张三") @Schema(description = "样本名称")
private String sampleName; private String sampleName;
@Schema(description = "样本格式", example = "1") @Schema(description = "样本格式", example = "1")

View File

@@ -1,8 +1,9 @@
package com.tashow.cloud.ai.controller.admin.aisample.vo; package com.tashow.cloud.ai.controller.admin.aisample.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO; import com.tashow.cloud.ai.dal.dataobject.aisample.AiSampleTagDO;
import com.tashow.cloud.common.serializer.ImgJsonSerializer;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -21,6 +22,7 @@ public class AiSampleRespVO {
private List<AiSampleTagDO> tags; private List<AiSampleTagDO> tags;
@Schema(description = "样本文件地址") @Schema(description = "样本文件地址")
@JsonSerialize(using = ImgJsonSerializer.class)
private String sampleFilePath; private String sampleFilePath;
@Schema(description = "样本名称", example = "张三") @Schema(description = "样本名称", example = "张三")

View File

@@ -17,6 +17,8 @@ import jakarta.validation.Valid;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
import static com.tashow.cloud.common.pojo.CommonResult.success; import static com.tashow.cloud.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - AI模型管理") @Tag(name = "管理后台 - AI模型管理")
@@ -53,12 +55,11 @@ public class AiModelController {
} }
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "模型") @Operation(summary = "取所有已启用的模型")
@Parameter(name = "id", description = "编号", required = true, example = "1")
@PermitAll @PermitAll
public CommonResult<AiModelRespVO> getModel(@RequestParam("id") Long id) { public CommonResult<List<AiModelRespVO>> getEnabledModels() {
AiModelDO model = modelService.getModel(id); List<AiModelDO> models = modelService.getEnabledModels();
return success(BeanUtils.toBean(model, AiModelRespVO.class)); return success(BeanUtils.toBean(models, AiModelRespVO.class));
} }
@GetMapping("/page") @GetMapping("/page")

View File

@@ -28,14 +28,18 @@ public interface AiSampleMapper extends BaseMapperX<AiSampleDO> {
",sample_mine_type sampleMineType ,sample_size sampleSize, remark,creator,updater,create_time createTime" + ",sample_mine_type sampleMineType ,sample_size sampleSize, remark,creator,updater,create_time createTime" +
",update_time updateTime,deleted,tenant_id tenantId " + ",update_time updateTime,deleted,tenant_id tenantId " +
"FROM tz_ai_sample t " + "FROM tz_ai_sample t " +
"INNER JOIN tz_ai_sample_tag_relate r ON t.id = r.sample_id " + "LEFt JOIN tz_ai_sample_tag_relate r ON t.id = r.sample_id " +
"<where>" + "<where>" +
"AND t.deleted =0"+
" <if test=\"pageReqVO.tagIds != null and pageReqVO.tagIds != ''\">" + " <if test=\"pageReqVO.tagIds != null and pageReqVO.tagIds != ''\">" +
" AND FIND_IN_SET(r.sample_tag_id,${pageReqVO.tagIds}) " + " AND FIND_IN_SET(r.sample_tag_id,${pageReqVO.tagIds}) " +
" </if>" + " </if>" +
" <if test=\"pageReqVO.sampleName != null and pageReqVO.sampleName != ''\">" + " <if test=\"pageReqVO.sampleName != null and pageReqVO.sampleName != ''\">" +
" AND t.sample_name LIKE CONCAT('%',#{pageReqVO.sampleName},'%')" + " AND t.sample_name LIKE CONCAT('%',#{pageReqVO.sampleName},'%')" +
" </if>" + " </if>" +
" <if test=\"pageReqVO.sampleMineType != null and pageReqVO.sampleMineType != ''\">" +
" AND t.sample_mine_type LIKE CONCAT('%',#{pageReqVO.sampleMineType},'%')" +
" </if>" +
"</where>" + "</where>" +
"GROUP BY t.id ORDER BY t.id DESC" + "GROUP BY t.id ORDER BY t.id DESC" +
"</script>") "</script>")

View File

@@ -44,8 +44,7 @@ public class AiSampleServiceImpl implements AiSampleService {
private AiSampleTagRelateMapper aiSampleTagRelateMapper; private AiSampleTagRelateMapper aiSampleTagRelateMapper;
@Resource @Resource
private FileApi fileApi; private FileApi fileApi;
@Value("${file-server}")
private String fileServer;
@Override @Override
@SneakyThrows @SneakyThrows
@@ -55,15 +54,15 @@ public class AiSampleServiceImpl implements AiSampleService {
/* 调用文件上传服务*/ /* 调用文件上传服务*/
for (MultipartFile file : uploadReqVO.getFiles()) { for (MultipartFile file : uploadReqVO.getFiles()) {
//返回上传结果 //返回上传结果
String file1 = fileServer + fileApi.createFile(file.getBytes()); String filePath=fileApi.createFile(file.getOriginalFilename(), "", file.getBytes());
//保存样本信息 //保存样本信息
AiSampleDO aiSampleDO = new AiSampleDO(); AiSampleDO aiSampleDO = new AiSampleDO();
aiSampleDO.setSampleFilePath(file1); aiSampleDO.setSampleFilePath(filePath);
aiSampleDO.setSampleName(file.getOriginalFilename()); aiSampleDO.setSampleName(file.getOriginalFilename());
aiSampleDO.setSampleMineType(file.getContentType()); aiSampleDO.setSampleMineType(file.getContentType());
aiSampleDO.setSampleSize(file.getSize()); aiSampleDO.setSampleSize(file.getSize());
aiSampleMapper.insert(aiSampleDO); aiSampleMapper.insert(aiSampleDO);
urls.add(new AiSampleFileRespVO().setFileUrl(file1).setFileName(file.getOriginalFilename())); urls.add(new AiSampleFileRespVO().setFileUrl(filePath).setFileName(file.getOriginalFilename()));
} }
// 返回 // 返回
return urls; return urls;
@@ -172,7 +171,6 @@ public class AiSampleServiceImpl implements AiSampleService {
Object[] tagsId = list.stream().map(AiSampleTagRelateDO::getSampleTagId).toArray(); Object[] tagsId = list.stream().map(AiSampleTagRelateDO::getSampleTagId).toArray();
List<AiSampleTagDO> list1 = aiSampleTagDOS.stream().filter(a -> ArrayUtil.containsAny(tagsId, a.getId())).toList(); List<AiSampleTagDO> list1 = aiSampleTagDOS.stream().filter(a -> ArrayUtil.containsAny(tagsId, a.getId())).toList();
aiSampleDO.setTags(list1); aiSampleDO.setTags(list1);
aiSampleDO.setSampleFilePath(aiSampleDO.getSampleFilePath());
} }
return new PageResult<>(aiSampleDOPageResult.getRecords(), aiSampleDOPageResult.getTotal()); return new PageResult<>(aiSampleDOPageResult.getRecords(), aiSampleDOPageResult.getTotal());
} }

View File

@@ -6,6 +6,8 @@ import com.tashow.cloud.ai.dal.dataobject.model.AiModelDO;
import com.tashow.cloud.common.pojo.PageResult; import com.tashow.cloud.common.pojo.PageResult;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.List;
/** /**
* AI模型管理 Service 接口 * AI模型管理 Service 接口
* *
@@ -36,12 +38,11 @@ public interface AiModelService {
void deleteModel(Long id); void deleteModel(Long id);
/** /**
* 获模型 * 获取所有已启用的模型
* *
* @param id 编号 * @return 已启用的模型列表
* @return 模型
*/ */
AiModelDO getModel(Long id); List<AiModelDO> getEnabledModels();
/** /**
* 获得模型分页 * 获得模型分页

View File

@@ -1,5 +1,6 @@
package com.tashow.cloud.ai.service.model; package com.tashow.cloud.ai.service.model;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tashow.cloud.ai.controller.admin.model.vo.AiModelPageReqVO; import com.tashow.cloud.ai.controller.admin.model.vo.AiModelPageReqVO;
import com.tashow.cloud.ai.controller.admin.model.vo.AiModelSaveReqVO; import com.tashow.cloud.ai.controller.admin.model.vo.AiModelSaveReqVO;
import com.tashow.cloud.ai.dal.dataobject.model.AiModelDO; import com.tashow.cloud.ai.dal.dataobject.model.AiModelDO;
@@ -10,6 +11,8 @@ import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.util.List;
/** /**
* AI模型管理 Service 实现类 * AI模型管理 Service 实现类
* *
@@ -42,8 +45,11 @@ public class AiModelServiceImpl implements AiModelService {
} }
@Override @Override
public AiModelDO getModel(Long id) { public List<AiModelDO> getEnabledModels() {
return modelMapper.selectById(id); return modelMapper.selectList(
new LambdaQueryWrapper<AiModelDO>()
.eq(AiModelDO::getStatus, 1)
);
} }
@Override @Override

View File

@@ -17,8 +17,5 @@ spring:
--- #################### 外部服务配置 #################### --- #################### 外部服务配置 ####################
# 文件服务URL前缀
file-server: http://localhost:48090/admin-api/file/file/get/
# AI翻译服务URL # AI翻译服务URL
translate-server: http://43.139.42.137:8000/analyze/audio translate-server: http://43.139.42.137:8000/analyze/audio

View File

@@ -63,7 +63,7 @@ public abstract class AbstractFileClient<Config extends FileClientConfig> implem
* @return URL 访问地址 * @return URL 访问地址
*/ */
protected String formatFileUrl(String domain, String path) { protected String formatFileUrl(String domain, String path) {
return StrUtil.format("{}/admin-api/file/{}/get/{}", domain, getId(), path); return StrUtil.format("/admin-api/file/{}/get/{}", getId(), path);
} }
} }

View File

@@ -14,4 +14,3 @@ spring:
config: # 【注册中心】配置项 config: # 【注册中心】配置项
namespace: 63caf548-313d-44bb-929c-531bf2f3b1a2 # 命名空间 namespace: 63caf548-313d-44bb-929c-531bf2f3b1a2 # 命名空间
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP