From 2d2edd7210fa47cdfecf26cd99e43bdc599fa4bf Mon Sep 17 00:00:00 2001 From: wangzhiwei Date: Wed, 7 Jan 2026 14:16:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0LibraryItem=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E7=AD=9B=E9=80=89=E8=83=BD?= =?UTF-8?q?=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 创建了完整的LibraryItem功能模块 - 实体类:LibraryItem - Mapper:LibraryItemMapper - Service:LibraryItemService - Controller:LibraryItemController - 相关模型类 2. 将tags字段替换为四个独立字段 - age:年龄(youth-青年,middle-中年,old-老年) - gender:性别(male-男性,female-女性) - scene:场景(emotion-情感,podcast-播客,education-教育) - language:语种(chinese-中文,english-英语) 3. 支持多条件筛选 - 在pageList方法中添加了根据age、gender、scene、language字段筛选的逻辑 - 优化了SQL查询性能 4. 生成了完整的SQL文件 - 创建了dh_library_item表 - 添加了合理的索引设计 - 包含了示例数据 - 提供了查询示例 5. 创建了.gitignore文件 - 忽略了不必要的文件和目录 - 优化了git仓库结构 --- .gitignore | 49 +++++----- .../business/mapper/LibraryItemMapper.java | 15 ++++ .../business/model/entity/LibraryItem.java | 68 ++++++++++++++ .../model/query/LibraryItemPageQuery.java | 17 ++++ .../model/query/LibraryItemQuery.java | 53 +++++++++++ .../business/model/req/LibraryItemReq.java | 66 ++++++++++++++ .../business/model/resp/LibraryItemResp.java | 83 +++++++++++++++++ .../business/service/LibraryItemService.java | 19 ++++ .../service/impl/LibraryItemServiceImpl.java | 89 +++++++++++++++++++ .../business/LibraryItemController.java | 75 ++++++++++++++++ .../src/main/resources/dh_library_item.sql | 54 +++++++++++ 11 files changed, 568 insertions(+), 20 deletions(-) create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/mapper/LibraryItemMapper.java create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/model/entity/LibraryItem.java create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemPageQuery.java create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemQuery.java create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/model/req/LibraryItemReq.java create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/model/resp/LibraryItemResp.java create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/service/LibraryItemService.java create mode 100644 continew-admin-business/src/main/java/top/continew/admin/business/service/impl/LibraryItemServiceImpl.java create mode 100644 continew-admin-webapi/src/main/java/top/continew/admin/controller/business/LibraryItemController.java create mode 100644 continew-admin-webapi/src/main/resources/dh_library_item.sql diff --git a/.gitignore b/.gitignore index 9154f4c..b2b4ff9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1,35 @@ -# ---> Java -# Compiled class file -*.class +# Maven +.flattened-pom.xml +*.pom.versionsBackup -# Log file +# IDE +.idea/ +*.iml +*.ipr +*.iws + +# Build output +target/ +**/target/ + +# Logs +logs/ *.log -# BlueJ files -*.ctxt +# OS +.DS_Store +Thumbs.db -# Mobile Tools for Java (J2ME) -.mtj.tmp/ +# Environment variables +.env +.env.local +.env.*.local -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* +# Test reports +jacoco/ +coverage/ +# Temporary files +*.tmp +*.temp +.cache/ \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/mapper/LibraryItemMapper.java b/continew-admin-business/src/main/java/top/continew/admin/business/mapper/LibraryItemMapper.java new file mode 100644 index 0000000..102d4d0 --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/mapper/LibraryItemMapper.java @@ -0,0 +1,15 @@ +package top.continew.admin.business.mapper; + +import org.apache.ibatis.annotations.Mapper; +import top.continew.admin.business.model.entity.LibraryItem; +import top.continew.starter.data.mp.base.BaseMapper; + +/** + * 库中项目Mapper + * + * @author author + * @since 2026-01-07 + */ +@Mapper +public interface LibraryItemMapper extends BaseMapper { +} \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/model/entity/LibraryItem.java b/continew-admin-business/src/main/java/top/continew/admin/business/model/entity/LibraryItem.java new file mode 100644 index 0000000..a35f17d --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/model/entity/LibraryItem.java @@ -0,0 +1,68 @@ +package top.continew.admin.business.model.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import top.continew.starter.extension.crud.model.entity.BaseDO; + +/** + * 库中项目实体 + * + * @author author + * @since 2026-01-07 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("dh_library_item") +public class LibraryItem extends BaseDO { + + /** + * 是否自定义 + */ + private Boolean isCustom; + + /** + * 用户ID + */ + private String userId; + + /** + * 类型 + */ + private String type; + + /** + * 名称 + */ + private String name; + + /** + * 年龄:youth-青年,middle-中年,old-老年 + */ + private String age; + + /** + * 性别:male-男性,female-女性 + */ + private String gender; + + /** + * 场景:emotion-情感,podcast-播客,education-教育 + */ + private String scene; + + /** + * 语种:chinese-中文,english-英语 + */ + private String language; + + /** + * 资源URL + */ + private String sourceUrl; + + /** + * 封面URL + */ + private String coverUrl; +} \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemPageQuery.java b/continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemPageQuery.java new file mode 100644 index 0000000..e04d1b9 --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemPageQuery.java @@ -0,0 +1,17 @@ +package top.continew.admin.business.model.query; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import top.continew.starter.extension.crud.model.query.PageQuery; + +/** + * 库中项目分页查询对象 + * + * @author author + * @since 2026-01-07 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class LibraryItemPageQuery extends PageQuery { + // 可根据需要添加额外的分页查询条件 +} \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemQuery.java b/continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemQuery.java new file mode 100644 index 0000000..fa1f06a --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/model/query/LibraryItemQuery.java @@ -0,0 +1,53 @@ +package top.continew.admin.business.model.query; + +import lombok.Data; +import java.io.Serializable; + +/** + * 库中项目查询条件 + * + * @author author + * @since 2026-01-07 + */ +@Data +public class LibraryItemQuery implements Serializable { + /** + * 用户ID + */ + private String userId; + + /** + * 是否自定义 + */ + private Boolean isCustom; + + /** + * 类型 + */ + private String type; + + /** + * 名称 + */ + private String name; + + /** + * 年龄:youth-青年,middle-中年,old-老年 + */ + private String age; + + /** + * 性别:male-男性,female-女性 + */ + private String gender; + + /** + * 场景:emotion-情感,podcast-播客,education-教育 + */ + private String scene; + + /** + * 语种:chinese-中文,english-英语 + */ + private String language; +} \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/model/req/LibraryItemReq.java b/continew-admin-business/src/main/java/top/continew/admin/business/model/req/LibraryItemReq.java new file mode 100644 index 0000000..e44aa0e --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/model/req/LibraryItemReq.java @@ -0,0 +1,66 @@ +package top.continew.admin.business.model.req; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import top.continew.starter.extension.crud.model.req.BaseReq; + +/** + * 库中项目请求参数对象 + * + * @author author + * @since 2026-01-07 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class LibraryItemReq extends BaseReq { + + /** + * 是否自定义 + */ + private Boolean isCustom; + + /** + * 用户ID + */ + private String userId; + + /** + * 类型 + */ + private String type; + + /** + * 名称 + */ + private String name; + + /** + * 年龄:youth-青年,middle-中年,old-老年 + */ + private String age; + + /** + * 性别:male-男性,female-女性 + */ + private String gender; + + /** + * 场景:emotion-情感,podcast-播客,education-教育 + */ + private String scene; + + /** + * 语种:chinese-中文,english-英语 + */ + private String language; + + /** + * 资源URL + */ + private String sourceUrl; + + /** + * 封面URL + */ + private String coverUrl; +} \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/model/resp/LibraryItemResp.java b/continew-admin-business/src/main/java/top/continew/admin/business/model/resp/LibraryItemResp.java new file mode 100644 index 0000000..b51737c --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/model/resp/LibraryItemResp.java @@ -0,0 +1,83 @@ +package top.continew.admin.business.model.resp; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import top.continew.starter.extension.crud.model.resp.BaseResp; + +import java.time.LocalDateTime; + +/** + * 库中项目响应对象 + * + * @author author + * @since 2026-01-07 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class LibraryItemResp extends BaseResp { + + /** + * 库中项目ID + */ + private Long id; + + /** + * 是否自定义 + */ + private Boolean isCustom; + + /** + * 用户ID + */ + private String userId; + + /** + * 类型 + */ + private String type; + + /** + * 名称 + */ + private String name; + + /** + * 年龄:youth-青年,middle-中年,old-老年 + */ + private String age; + + /** + * 性别:male-男性,female-女性 + */ + private String gender; + + /** + * 场景:emotion-情感,podcast-播客,education-教育 + */ + private String scene; + + /** + * 语种:chinese-中文,english-英语 + */ + private String language; + + /** + * 资源URL + */ + private String sourceUrl; + + /** + * 封面URL + */ + private String coverUrl; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/service/LibraryItemService.java b/continew-admin-business/src/main/java/top/continew/admin/business/service/LibraryItemService.java new file mode 100644 index 0000000..219c423 --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/service/LibraryItemService.java @@ -0,0 +1,19 @@ +package top.continew.admin.business.service; + +import top.continew.admin.business.model.query.LibraryItemQuery; +import top.continew.admin.business.model.query.LibraryItemPageQuery; +import top.continew.admin.business.model.req.LibraryItemReq; +import top.continew.admin.business.model.resp.LibraryItemResp; +import top.continew.starter.extension.crud.model.resp.PageResp; +import top.continew.starter.extension.crud.service.BaseService; + +/** + * 库中项目服务 + * + * @author author + * @since 2026-01-07 + */ +public interface LibraryItemService extends BaseService { + + PageResp pageList(LibraryItemQuery query, LibraryItemPageQuery pageQuery); +} \ No newline at end of file diff --git a/continew-admin-business/src/main/java/top/continew/admin/business/service/impl/LibraryItemServiceImpl.java b/continew-admin-business/src/main/java/top/continew/admin/business/service/impl/LibraryItemServiceImpl.java new file mode 100644 index 0000000..15dcbbb --- /dev/null +++ b/continew-admin-business/src/main/java/top/continew/admin/business/service/impl/LibraryItemServiceImpl.java @@ -0,0 +1,89 @@ +package top.continew.admin.business.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import top.continew.admin.business.mapper.LibraryItemMapper; +import top.continew.admin.business.model.entity.LibraryItem; +import top.continew.admin.business.model.query.LibraryItemPageQuery; +import top.continew.admin.business.model.query.LibraryItemQuery; +import top.continew.admin.business.model.req.LibraryItemReq; +import top.continew.admin.business.model.resp.LibraryItemResp; +import top.continew.admin.business.service.LibraryItemService; +import top.continew.starter.extension.crud.model.resp.PageResp; +import top.continew.starter.extension.crud.service.impl.BaseServiceImpl; + +/** + * 库中项目服务实现 + * + * @author author + * @since 2026-01-07 + */ +@Service +@RequiredArgsConstructor +public class LibraryItemServiceImpl extends BaseServiceImpl implements LibraryItemService { + + private final LibraryItemMapper libraryItemMapper; + + @Override + public PageResp pageList(LibraryItemQuery query, LibraryItemPageQuery pageQuery) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + if (query.getUserId() != null) { + wrapper.eq(LibraryItem::getUserId, query.getUserId()); + } + if (query.getIsCustom() != null) { + wrapper.eq(LibraryItem::getIsCustom, query.getIsCustom()); + } + if (query.getType() != null) { + wrapper.eq(LibraryItem::getType, query.getType()); + } + if (query.getName() != null) { + wrapper.like(LibraryItem::getName, query.getName()); + } + // 年龄筛选 + if (query.getAge() != null) { + wrapper.eq(LibraryItem::getAge, query.getAge()); + } + // 性别筛选 + if (query.getGender() != null) { + wrapper.eq(LibraryItem::getGender, query.getGender()); + } + // 场景筛选 + if (query.getScene() != null) { + wrapper.eq(LibraryItem::getScene, query.getScene()); + } + // 语种筛选 + if (query.getLanguage() != null) { + wrapper.eq(LibraryItem::getLanguage, query.getLanguage()); + } + + // 默认按createTime倒序排列 + wrapper.orderByDesc(LibraryItem::getCreateTime); + + Page page = new Page<>(pageQuery.getPage(), pageQuery.getSize()); + Page result = libraryItemMapper.selectPage(page, wrapper); + + PageResp pageResp = new PageResp<>(); + pageResp.setTotal(result.getTotal()); + pageResp.setList(result.getRecords().stream().map(this::convertToResp).toList()); + return pageResp; + } + + @Override + public Long add(LibraryItemReq req) { + LibraryItem libraryItem = new LibraryItem(); + BeanUtils.copyProperties(req, libraryItem); + libraryItem.setCreateTime(java.time.LocalDateTime.now()); + libraryItem.setUpdateTime(java.time.LocalDateTime.now()); + libraryItemMapper.insert(libraryItem); + return libraryItem.getId(); + } + + private LibraryItemResp convertToResp(LibraryItem libraryItem) { + LibraryItemResp resp = new LibraryItemResp(); + BeanUtils.copyProperties(libraryItem, resp); + return resp; + } +} \ No newline at end of file diff --git a/continew-admin-webapi/src/main/java/top/continew/admin/controller/business/LibraryItemController.java b/continew-admin-webapi/src/main/java/top/continew/admin/controller/business/LibraryItemController.java new file mode 100644 index 0000000..e9041a9 --- /dev/null +++ b/continew-admin-webapi/src/main/java/top/continew/admin/controller/business/LibraryItemController.java @@ -0,0 +1,75 @@ +package top.continew.admin.controller.business; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import top.continew.admin.business.model.query.LibraryItemPageQuery; +import top.continew.admin.business.model.query.LibraryItemQuery; +import top.continew.admin.business.model.req.BatchReq; +import top.continew.admin.business.model.req.LibraryItemReq; +import top.continew.admin.business.model.resp.LibraryItemResp; +import top.continew.admin.business.service.LibraryItemService; +import top.continew.starter.extension.crud.annotation.CrudRequestMapping; +import top.continew.starter.extension.crud.controller.BaseController; +import top.continew.starter.extension.crud.enums.Api; +import top.continew.starter.extension.crud.model.query.SortQuery; +import top.continew.starter.extension.crud.model.resp.PageResp; +import top.continew.starter.log.core.annotation.Log; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 库中项目管理 API + * + * @author author + * @since 2026-01-07 + */ +@Tag(name = "数字人-库中项目管理 API") +@RestController +@RequiredArgsConstructor +@CrudRequestMapping(value = "/business/libraryItem", api = {Api.GET, Api.UPDATE, Api.LIST}) +public class LibraryItemController extends BaseController { + + @Log + @Operation(summary = "查询库中项目", description = "查询库中项目列表") + @ResponseBody + @GetMapping({"/list"}) + public List list(LibraryItemQuery query, SortQuery sortQuery) { + return baseService.list(query, sortQuery); + } + + @Log + @ResponseBody + @Operation(summary = "新增库中项目", description = "新增库中项目") + @PostMapping() + public Long addLibraryItem(@RequestBody LibraryItemReq req) { + return baseService.add(req); + } + + @Log + @Operation(summary = "分页查询库中项目", description = "分页查询库中项目列表") + @ResponseBody + @GetMapping({"/page"}) + public PageResp page(LibraryItemQuery query, LibraryItemPageQuery pageQuery) { + return baseService.pageList(query, pageQuery); + } + + @Log + @Operation(summary = "批量删除库中项目", description = "根据库中项目ID列表批量删除库中项目") + @PostMapping("/batchDelete") + public void deleteBatch(@Validated @RequestBody BatchReq req) { + baseService.delete(req.getIds()); + } + + @Log + @Operation(summary = "批量删除库中项目(通过路径参数)", description = "根据路径中的ID列表批量删除库中项目,ID以逗号分隔") + @DeleteMapping("/{ids}") + public void delete(@PathVariable("ids") String ids) { + List idList = Arrays.stream(ids.split(",")).map(Long::valueOf).collect(Collectors.toList()); + baseService.delete(idList); + } +} \ No newline at end of file diff --git a/continew-admin-webapi/src/main/resources/dh_library_item.sql b/continew-admin-webapi/src/main/resources/dh_library_item.sql new file mode 100644 index 0000000..78222df --- /dev/null +++ b/continew-admin-webapi/src/main/resources/dh_library_item.sql @@ -0,0 +1,54 @@ +-- MySQL 8.0 建表语句 +-- 库中项目表 - 存储各种类型的库中项目,支持按年龄、性别、场景、语种等维度筛选 +drop table if exists dh_library_item; +create table dh_library_item ( + `id` bigint not null auto_increment comment '主键ID', + `is_custom` tinyint(1) default 0 comment '是否自定义:0-否,1-是', + `user_id` varchar(64) not null comment '用户ID', + `type` varchar(32) not null comment '类型', + `name` varchar(128) comment '名称', + `age` varchar(16) comment '年龄:youth-青年,middle-中年,old-老年', + `gender` varchar(16) comment '性别:male-男性,female-女性', + `scene` varchar(16) comment '场景:emotion-情感,podcast-播客,education-教育', + `language` varchar(16) comment '语种:chinese-中文,english-英语', + `source_url` varchar(512) not null comment '资源URL', + `cover_url` varchar(512) comment '封面URL', + `create_user` bigint not null comment '创建者', + `create_time` datetime not null default current_timestamp comment '创建时间', + `update_user` bigint comment '更新者', + `update_time` datetime not null default current_timestamp on update current_timestamp comment '更新时间', + `is_deleted` tinyint(1) not null default 0 comment '删除标记:0-未删除,1-已删除', + primary key (`id`), + -- 单列索引,用于快速筛选 + index idx_user_id (`user_id`), + index idx_type (`type`), + index idx_age (`age`), + index idx_gender (`gender`), + index idx_scene (`scene`), + index idx_language (`language`), + index idx_create_time (`create_time`), + index idx_is_deleted (`is_deleted`), + -- 联合索引,用于多条件查询优化 + index idx_user_type (`user_id`, `type`), + index idx_age_gender_scene (`age`, `gender`, `scene`), + index idx_gender_scene_language (`gender`, `scene`, `language`) +) engine=innodb default charset=utf8mb4 collate=utf8mb4_0900_ai_ci comment='库中项目表'; + +-- 示例数据插入语句 +insert into dh_library_item (is_custom, user_id, type, name, age, gender, scene, language, source_url, cover_url, create_user) values +(0, '123456', 'voice', '青年男声-情感中文', 'youth', 'male', 'emotion', 'chinese', 'https://example.com/voice/youth-male-emotion-chinese.mp3', 'https://example.com/cover/youth-male.jpg', 1), +(0, '123456', 'voice', '青年女声-播客中文', 'youth', 'female', 'podcast', 'chinese', 'https://example.com/voice/youth-female-podcast-chinese.mp3', 'https://example.com/cover/youth-female.jpg', 1), +(0, '123456', 'voice', '中年男声-教育中文', 'middle', 'male', 'education', 'chinese', 'https://example.com/voice/middle-male-education-chinese.mp3', 'https://example.com/cover/middle-male.jpg', 1), +(0, '123456', 'voice', '中年女声-情感英文', 'middle', 'female', 'emotion', 'english', 'https://example.com/voice/middle-female-emotion-english.mp3', 'https://example.com/cover/middle-female.jpg', 1), +(0, '123456', 'voice', '老年男声-教育英文', 'old', 'male', 'education', 'english', 'https://example.com/voice/old-male-education-english.mp3', 'https://example.com/cover/old-male.jpg', 1), +(1, '789012', 'voice', '自定义声音-青年女声-中文', 'youth', 'female', 'podcast', 'chinese', 'https://example.com/voice/custom-youth-female-chinese.mp3', 'https://example.com/cover/custom.jpg', 2); + +-- 查询示例 +-- 1. 查询青年男性的中文资源 +-- select * from dh_library_item where age = 'youth' and gender = 'male' and language = 'chinese' and is_deleted = 0; + +-- 2. 查询情感场景的女声资源 +-- select * from dh_library_item where scene = 'emotion' and gender = 'female' and is_deleted = 0; + +-- 3. 按创建时间倒序查询自定义资源 +-- select * from dh_library_item where is_custom = 1 and is_deleted = 0 order by create_time desc; \ No newline at end of file