feat: Implement voice design management with CRUD operations and integrate into frontend

This commit is contained in:
2026-02-04 13:57:20 +08:00
parent a694ead4b8
commit ddaa0abfc7
14 changed files with 542 additions and 31 deletions

View File

@@ -3,7 +3,7 @@ from typing import Optional, List, Dict, Any
from datetime import datetime
from sqlalchemy.orm import Session
from db.models import User, Job, VoiceCache, SystemSettings
from db.models import User, Job, VoiceCache, SystemSettings, VoiceDesign
def get_user_by_username(db: Session, username: str) -> Optional[User]:
return db.query(User).filter(User.username == username).first()
@@ -271,3 +271,83 @@ def update_system_setting(db: Session, key: str, value: dict) -> SystemSettings:
def can_user_use_local_model(user: User) -> bool:
return user.is_superuser or user.can_use_local_model
def create_voice_design(
db: Session,
user_id: int,
name: str,
instruct: str,
backend_type: str,
aliyun_voice_id: Optional[str] = None,
meta_data: Optional[Dict[str, Any]] = None,
preview_text: Optional[str] = None
) -> VoiceDesign:
design = VoiceDesign(
user_id=user_id,
name=name,
backend_type=backend_type,
instruct=instruct,
aliyun_voice_id=aliyun_voice_id,
meta_data=json.dumps(meta_data) if meta_data else None,
preview_text=preview_text,
created_at=datetime.utcnow(),
last_used=datetime.utcnow()
)
db.add(design)
db.commit()
db.refresh(design)
return design
def get_voice_design(db: Session, design_id: int, user_id: int) -> Optional[VoiceDesign]:
return db.query(VoiceDesign).filter(
VoiceDesign.id == design_id,
VoiceDesign.user_id == user_id,
VoiceDesign.is_active == True
).first()
def list_voice_designs(
db: Session,
user_id: int,
backend_type: Optional[str] = None,
skip: int = 0,
limit: int = 100
) -> List[VoiceDesign]:
query = db.query(VoiceDesign).filter(
VoiceDesign.user_id == user_id,
VoiceDesign.is_active == True
)
if backend_type:
query = query.filter(VoiceDesign.backend_type == backend_type)
return query.order_by(VoiceDesign.last_used.desc()).offset(skip).limit(limit).all()
def update_voice_design_usage(db: Session, design_id: int, user_id: int) -> Optional[VoiceDesign]:
design = get_voice_design(db, design_id, user_id)
if design:
design.last_used = datetime.utcnow()
design.use_count += 1
db.commit()
db.refresh(design)
return design
def update_voice_design(
db: Session,
design_id: int,
user_id: int,
name: Optional[str] = None
) -> Optional[VoiceDesign]:
design = get_voice_design(db, design_id, user_id)
if not design:
return None
if name is not None:
design.name = name
db.commit()
db.refresh(design)
return design
def delete_voice_design(db: Session, design_id: int, user_id: int) -> bool:
design = get_voice_design(db, design_id, user_id)
if not design:
return False
design.is_active = False
db.commit()
return True

View File

@@ -28,6 +28,7 @@ class User(Base):
jobs = relationship("Job", back_populates="user", cascade="all, delete-orphan")
voice_caches = relationship("VoiceCache", back_populates="user", cascade="all, delete-orphan")
voice_designs = relationship("VoiceDesign", back_populates="user", cascade="all, delete-orphan")
class Job(Base):
__tablename__ = "jobs"
@@ -77,3 +78,26 @@ class SystemSettings(Base):
key = Column(String(100), unique=True, nullable=False, index=True)
value = Column(JSON, nullable=False)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
class VoiceDesign(Base):
__tablename__ = "voice_designs"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
name = Column(String(100), nullable=False)
backend_type = Column(String(20), nullable=False, index=True)
instruct = Column(Text, nullable=False)
aliyun_voice_id = Column(String(255), nullable=True)
meta_data = Column(JSON, nullable=True)
preview_text = Column(Text, nullable=True)
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
last_used = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
use_count = Column(Integer, default=0, nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
user = relationship("User", back_populates="voice_designs")
__table_args__ = (
Index('idx_user_backend', 'user_id', 'backend_type'),
Index('idx_user_active', 'user_id', 'is_active'),
)