diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java index b7d6c278..6b04bb08 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/oauth2/Oauth2Realm.java @@ -19,6 +19,7 @@ import xiaozhi.modules.security.service.ShiroService; import xiaozhi.modules.sys.entity.SysUserEntity; import xiaozhi.modules.sys.enums.SuperAdminEnum; +import java.util.HashSet; import java.util.Set; /** @@ -47,7 +48,7 @@ public class Oauth2Realm extends AuthorizingRealm { UserDetail user = (UserDetail) principals.getPrimaryPrincipal(); //用户权限列表 - Set permsSet = shiroService.getUserPermissions(user); + Set permsSet = new HashSet<>(); if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) { permsSet.add("sys:role:superAdmin"); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java b/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java index 980645d6..b9d18889 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/service/ShiroService.java @@ -1,22 +1,14 @@ package xiaozhi.modules.security.service; -import xiaozhi.common.user.UserDetail; import xiaozhi.modules.security.entity.SysUserTokenEntity; import xiaozhi.modules.sys.entity.SysUserEntity; -import java.util.List; -import java.util.Set; - /** * shiro相关接口 * Copyright (c) 人人开源 All rights reserved. * Website: https://www.renren.io */ public interface ShiroService { - /** - * 获取用户权限列表 - */ - Set getUserPermissions(UserDetail user); SysUserTokenEntity getByToken(String token); diff --git a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java index 128d9b9d..97d16eaa 100644 --- a/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java +++ b/main/manager-api/src/main/java/xiaozhi/modules/security/service/impl/ShiroServiceImpl.java @@ -19,22 +19,6 @@ public class ShiroServiceImpl implements ShiroService { private final SysUserDao sysUserDao; private final SysUserTokenDao sysUserTokenDao; - @Override - public Set getUserPermissions(UserDetail user) { - //系统管理员,拥有最高权限 - // TODO: 暂时写死,后续改成从数据库查询 - List permissionsList = new ArrayList<>(); - //用户权限列表 - Set permsSet = new HashSet<>(); - for (String permissions : permissionsList) { - if (StringUtils.isBlank(permissions)) { - continue; - } - permsSet.addAll(Arrays.asList(permissions.trim().split(","))); - } - - return permsSet; - } @Override public SysUserTokenEntity getByToken(String token) { diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java new file mode 100644 index 00000000..dc6ccca7 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/controller/TimbreController.java @@ -0,0 +1,85 @@ +package xiaozhi.modules.timbre.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.AllArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.web.bind.annotation.*; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.page.PageData; +import xiaozhi.common.utils.Result; +import xiaozhi.common.validator.ValidatorUtils; +import xiaozhi.modules.timbre.dto.TimbreDataDTO; +import xiaozhi.modules.timbre.dto.TimbrePageDTO; +import xiaozhi.modules.timbre.service.TimbreService; +import xiaozhi.modules.timbre.vo.TimbreDetailsVO; + +import java.util.Map; + +/** + * 音色控制层 + * + * @author zjy + * @since 2025-3-21 + */ +@AllArgsConstructor +@RestController +@RequestMapping("/ttsVoice") +@Tag(name = "音色管理") +public class TimbreController { + private final TimbreService timbreService; + + @GetMapping + @Operation(summary = "分页查找") + @RequiresPermissions("sys:role:superAdmin") + @Parameters({ + @Parameter(name = "ttsModelId", description = "对应 TTS 模型主键", required = true), + @Parameter(name = "name", description = "音色名称"), + @Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true), + @Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true), + }) + public Result> page( + @Parameter(hidden = true) @RequestParam Map params) { + TimbrePageDTO dto = new TimbrePageDTO(); + dto.setTtsModelId((String) params.get("ttsModelId")); + dto.setName((String) params.get("name")); + dto.setLimit((String) params.get(Constant.LIMIT)); + dto.setPage((String) params.get(Constant.PAGE)); + + ValidatorUtils.validateEntity(dto); + PageData page = timbreService.page(dto); + return new Result>().ok(page); + } + + @PostMapping + @Operation(summary = "音色保存") + @RequiresPermissions("sys:role:superAdmin") + public Result save(@RequestBody TimbreDataDTO dto) { + ValidatorUtils.validateEntity(dto); + timbreService.save(dto); + return new Result<>(); + } + + @PutMapping("/{id}") + @Operation(summary = "音色修改") + @RequiresPermissions("sys:role:superAdmin") + public Result update( + @PathVariable Long id, + @RequestBody TimbreDataDTO dto) { + ValidatorUtils.validateEntity(dto); + timbreService.update(id, dto); + return new Result<>(); + } + + @DeleteMapping("/{id}") + @Operation(summary = "音色删除") + @RequiresPermissions("sys:role:superAdmin") + public Result delete(@PathVariable Long id) { + timbreService.delete(new Long[]{id}); + return new Result<>(); + } + + +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dao/TimbreDao.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dao/TimbreDao.java new file mode 100644 index 00000000..62afa358 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dao/TimbreDao.java @@ -0,0 +1,14 @@ +package xiaozhi.modules.timbre.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import xiaozhi.modules.timbre.entity.TimbreEntity; + +/** + * 音色持久层定义 + * @author zjy + * @since 2025-3-21 + */ +@Mapper +public interface TimbreDao extends BaseMapper { +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java new file mode 100644 index 00000000..08ed9b18 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbreDataDTO.java @@ -0,0 +1,45 @@ +package xiaozhi.modules.timbre.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + + +/** + * 音色表数据DTO + * @author zjy + * @since 2025-3-21 + */ +@Data +@Schema(description = "音色表信息") +public class TimbreDataDTO { + + @Schema(description = "语言") + @NotBlank(message = "{timbre.languages.require}") + private String languages; + + @Schema(description = "音色名称") + @NotBlank(message = "{timbre.name.require}") + private String name; + + @Schema(description = "备注") + @NotBlank(message = "{timbre.remark.require}") + private String remark; + + @Schema(description = "排序") + @Min(value = 0, message = "{sort.number}") + private long sort; + + @Schema(description = "对应 TTS 模型主键") + @NotBlank(message = "{timbre.ttsModelId.require}") + private String ttsModelId; + + @Schema(description = "音色编码") + @NotBlank(message = "{timbre.ttsVoice.require}") + private String ttsVoice; + + @Schema(description = "音频播放地址") + @NotBlank(message = "{timbre.voiceDemo.require}") + private String voiceDemo; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbrePageDTO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbrePageDTO.java new file mode 100644 index 00000000..72ed68b1 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/dto/TimbrePageDTO.java @@ -0,0 +1,28 @@ +package xiaozhi.modules.timbre.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 音色分页参数DTO + * @author zjy + * @since 2025-3-21 + */ +@Data +@Schema(description = "音色分页参数") +public class TimbrePageDTO { + + @Schema(description = "对应 TTS 模型主键") + @NotBlank(message = "{timbre.ttsModelId.require}") + private String ttsModelId; + + @Schema(description = "音色名称") + private String name; + + @Schema(description = "页数") + private String page; + + @Schema(description = "显示列数") + private String limit; +} diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java new file mode 100644 index 00000000..71bd58a9 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/entity/TimbreEntity.java @@ -0,0 +1,48 @@ +package xiaozhi.modules.timbre.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import xiaozhi.common.entity.BaseEntity; + +import java.util.Date; + +/** + * 音色表实体类 + * @author zjy + * @since 2025-3-21 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("ai_tts_voice") +@Schema(description = "音色信息") +public class TimbreEntity extends BaseEntity { + + @Schema(description = "语言") + private String languages; + + @Schema(description = "音色名称") + private String name; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + private long sort; + + @Schema(description = "对应 TTS 模型主键") + private String ttsModelId; + + @Schema(description = "音色编码") + private String ttsVoice; + + @Schema(description = "音频播放地址") + private String voiceDemo; + + @Schema(description = "更新者") + private Long updater; + + @Schema(description = "更新时间") + private Date updateDate; +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/TimbreService.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/TimbreService.java new file mode 100644 index 00000000..9b6c73eb --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/TimbreService.java @@ -0,0 +1,49 @@ +package xiaozhi.modules.timbre.service; + +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.BaseService; +import xiaozhi.modules.timbre.dto.TimbreDataDTO; +import xiaozhi.modules.timbre.dto.TimbrePageDTO; +import xiaozhi.modules.timbre.entity.TimbreEntity; +import xiaozhi.modules.timbre.vo.TimbreDetailsVO; + + +/** + * 音色的业务层的定义 + * @author zjy + * @since 2025-3-21 + */ +public interface TimbreService extends BaseService { + /** + * 分页获取音色指定tts的下的音色 + * @param dto 分页查找参数 + * @return 音色列表分页数据 + */ + PageData page(TimbrePageDTO dto); + + /** + * 获取音色指定id的详情信息 + * @param timbreId 音色表id + * @return 音色信息 + */ + TimbreDetailsVO get(Long timbreId); + + /** + * 保存音色信息 + * @param dto 需要保存数据 + */ + void save(TimbreDataDTO dto); + + /** + * 保存音色信息 + * @param timbreId 需要修改的id + * @param dto 需要修改的数据 + */ + void update(Long timbreId,TimbreDataDTO dto); + + /** + * 批量删除音色 + * @param ids 需要被删除的音色id列表 + */ + void delete(Long[] ids); +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java new file mode 100644 index 00000000..ce3c2b7b --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/service/impl/TimbreServiceImpl.java @@ -0,0 +1,85 @@ +package xiaozhi.modules.timbre.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import xiaozhi.common.constant.Constant; +import xiaozhi.common.page.PageData; +import xiaozhi.common.service.impl.BaseServiceImpl; +import xiaozhi.common.utils.ConvertUtils; +import xiaozhi.modules.timbre.dao.TimbreDao; +import xiaozhi.modules.timbre.dto.TimbreDataDTO; +import xiaozhi.modules.timbre.dto.TimbrePageDTO; +import xiaozhi.modules.timbre.service.TimbreService; +import xiaozhi.modules.timbre.entity.TimbreEntity; +import xiaozhi.modules.timbre.vo.TimbreDetailsVO; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + * 音色的业务层的实现 + * @author zjy + * @since 2025-3-21 + */ +@Service +public class TimbreServiceImpl extends BaseServiceImpl implements TimbreService { + + + @Override + public PageData page(TimbrePageDTO dto) { + Map params = new HashMap(); + params.put(Constant.PAGE, dto.getPage()); + params.put(Constant.LIMIT,dto.getLimit()); + IPage page = baseDao.selectPage( + getPage(params, "sort", true), + //定义查询条件 + new QueryWrapper() + //必须按照ttsID查找 + .eq("tts_model_id",dto.getTtsModelId()) + //如果有音色名字,按照音色名模糊查找 + .like(StringUtils.isNotBlank(dto.getName()),"name",dto.getName()) + ); + + return getPageData(page, TimbreDetailsVO.class); + } + + @Override + public TimbreDetailsVO get(Long timbreId) { + TimbreEntity entity = baseDao.selectById(timbreId); + return ConvertUtils.sourceToTarget(entity, TimbreDetailsVO.class); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void save(TimbreDataDTO dto) { + isTtsModelId(dto.getTtsModelId()); + TimbreEntity timbreEntity = ConvertUtils.sourceToTarget(dto, TimbreEntity.class); + baseDao.insert(timbreEntity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Long timbreId, TimbreDataDTO dto) { + isTtsModelId(dto.getTtsModelId()); + TimbreEntity timbreEntity = ConvertUtils.sourceToTarget(dto, TimbreEntity.class); + timbreEntity.setId(timbreId); + baseDao.updateById(timbreEntity); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long[] ids) { + baseDao.deleteBatchIds(Arrays.asList(ids)); + } + + /** + * 处理是不是tts模型的id + */ + private void isTtsModelId(String ttsModelId){ + //等模型配置那边写好调用方法判断 + } +} \ No newline at end of file diff --git a/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java b/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java new file mode 100644 index 00000000..fc82a5d0 --- /dev/null +++ b/main/manager-api/src/main/java/xiaozhi/modules/timbre/vo/TimbreDetailsVO.java @@ -0,0 +1,39 @@ +package xiaozhi.modules.timbre.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 音色详情展示VO + * @author zjy + * @since 2025-3-21 + */ +@Data +public class TimbreDetailsVO implements Serializable { + @Schema(description = "音色id") + private Long id; + + @Schema(description = "语言") + private String languages; + + @Schema(description = "音色名称") + private String name; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + private long sort; + + @Schema(description = "对应 TTS 模型主键") + private String ttsModelId; + + @Schema(description = "音色编码") + private String ttsVoice; + + @Schema(description = "音频播放地址") + private String voiceDemo; + +} diff --git a/main/manager-api/src/main/resources/i18n/validation.properties b/main/manager-api/src/main/resources/i18n/validation.properties index 947f89cc..e7452e47 100644 --- a/main/manager-api/src/main/resources/i18n/validation.properties +++ b/main/manager-api/src/main/resources/i18n/validation.properties @@ -20,3 +20,12 @@ sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A + + +timbre.languages.require=\u97F3\u8272\u7684\u8BED\u8A00\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.name.require=\u97F3\u8272\u7684\u540D\u79F0\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.remark.require=\u97F3\u8272\u7684\u5907\u6CE8\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u952E\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsVoice.require=\u97F3\u8272\u7684\u7F16\u7801\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653EDemo\u4E0D\u53EF\u4EE5\u4E3A\u7A7A + diff --git a/main/manager-api/src/main/resources/i18n/validation_en_US.properties b/main/manager-api/src/main/resources/i18n/validation_en_US.properties index f8bb6e94..37bebf18 100644 --- a/main/manager-api/src/main/resources/i18n/validation_en_US.properties +++ b/main/manager-api/src/main/resources/i18n/validation_en_US.properties @@ -20,3 +20,11 @@ sysuser.deptId.require=Departments cannot be empty sysuser.status.range=State ranges from 0 to 1 sysuser.captcha.require=The captcha cannot be empty sysuser.uuid.require=The unique identifier cannot be empty + +timbre.languages.require=The language of the timbre cannot be empty +timbre.name.require=The name of the timbre cannot be empty +timbre.remark.require=The remark of the timbre cannot be empty +timbre.ttsModelId.require=The TTS model ID of the timbre cannot be empty +timbre.ttsVoice.require=The TTS voice of the timbre cannot be empty +timbre.voiceDemo.require=The voice demo of the timbre cannot be empty + diff --git a/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties b/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties index ba350d05..41bf1e69 100644 --- a/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties +++ b/main/manager-api/src/main/resources/i18n/validation_zh_CN.properties @@ -21,3 +21,10 @@ sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A +timbre.languages.require=\u97F3\u8272\u7684\u8A9E\u8A00\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.name.require=\u97F3\u8272\u7684\u540D\u7A31\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.remark.require=\u97F3\u8272\u7684\u5099\u6CE8\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u9375\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.ttsVoice.require=\u97F3\u8272\u7684\u7DE8\u78BC\u4E0D\u53EF\u4EE5\u70BA\u7A7A +timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653E\u5730\u5740\u4E0D\u53EF\u4EE5\u70BA\u7A7A + diff --git a/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties b/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties index 947f89cc..9241c97a 100644 --- a/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties +++ b/main/manager-api/src/main/resources/i18n/validation_zh_TW.properties @@ -20,3 +20,10 @@ sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1 sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A + +timbre.languages.require=\u97F3\u8272\u7684\u8BED\u8A00\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.name.require=\u97F3\u8272\u7684\u540D\u79F0\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.remark.require=\u97F3\u8272\u7684\u5907\u6CE8\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u952E\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.ttsVoice.require=\u97F3\u8272\u7684\u7F16\u7801\u4E0D\u53EF\u4EE5\u4E3A\u7A7A +timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653EDemo\u4E0D\u53EF\u4EE5\u4E3A\u7A7A