merge:音色管理功能

音色管理功能
This commit is contained in:
欣南科技
2025-03-21 21:46:11 +08:00
committed by GitHub
15 changed files with 426 additions and 25 deletions
@@ -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<String> permsSet = shiroService.getUserPermissions(user);
Set<String> permsSet = new HashSet<>();
if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) {
permsSet.add("sys:role:superAdmin");
@@ -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<String> getUserPermissions(UserDetail user);
SysUserTokenEntity getByToken(String token);
@@ -19,22 +19,6 @@ public class ShiroServiceImpl implements ShiroService {
private final SysUserDao sysUserDao;
private final SysUserTokenDao sysUserTokenDao;
@Override
public Set<String> getUserPermissions(UserDetail user) {
//系统管理员,拥有最高权限
// TODO: 暂时写死,后续改成从数据库查询
List<String> permissionsList = new ArrayList<>();
//用户权限列表
Set<String> 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) {
@@ -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<PageData<TimbreDetailsVO>> page(
@Parameter(hidden = true) @RequestParam Map<String, Object> 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<TimbreDetailsVO> page = timbreService.page(dto);
return new Result<PageData<TimbreDetailsVO>>().ok(page);
}
@PostMapping
@Operation(summary = "音色保存")
@RequiresPermissions("sys:role:superAdmin")
public Result<Void> save(@RequestBody TimbreDataDTO dto) {
ValidatorUtils.validateEntity(dto);
timbreService.save(dto);
return new Result<>();
}
@PutMapping("/{id}")
@Operation(summary = "音色修改")
@RequiresPermissions("sys:role:superAdmin")
public Result<Void> 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<Void> delete(@PathVariable Long id) {
timbreService.delete(new Long[]{id});
return new Result<>();
}
}
@@ -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<TimbreEntity> {
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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<TimbreEntity> {
/**
* 分页获取音色指定tts的下的音色
* @param dto 分页查找参数
* @return 音色列表分页数据
*/
PageData<TimbreDetailsVO> 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);
}
@@ -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<TimbreDao, TimbreEntity> implements TimbreService {
@Override
public PageData<TimbreDetailsVO> page(TimbrePageDTO dto) {
Map<String, Object> params = new HashMap<String, Object>();
params.put(Constant.PAGE, dto.getPage());
params.put(Constant.LIMIT,dto.getLimit());
IPage<TimbreEntity> page = baseDao.selectPage(
getPage(params, "sort", true),
//定义查询条件
new QueryWrapper<TimbreEntity>()
//必须按照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){
//等模型配置那边写好调用方法判断
}
}
@@ -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;
}
@@ -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
@@ -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
@@ -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
@@ -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