update:1.切换数据库PostgreSQL
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
"""组织管理API"""
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, and_
|
||||
from typing import List, Optional
|
||||
@@ -31,6 +31,26 @@ router = APIRouter(prefix="/organizations", tags=["组织管理"])
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
async def verify_project_access(project_id: str, user_id: str, db: AsyncSession) -> Project:
|
||||
"""验证用户是否有权访问指定项目"""
|
||||
if not user_id:
|
||||
raise HTTPException(status_code=401, detail="未登录")
|
||||
|
||||
result = await db.execute(
|
||||
select(Project).where(
|
||||
Project.id == project_id,
|
||||
Project.user_id == user_id
|
||||
)
|
||||
)
|
||||
project = result.scalar_one_or_none()
|
||||
|
||||
if not project:
|
||||
logger.warning(f"项目访问被拒绝: project_id={project_id}, user_id={user_id}")
|
||||
raise HTTPException(status_code=404, detail="项目不存在或无权访问")
|
||||
|
||||
return project
|
||||
|
||||
|
||||
class OrganizationGenerateRequest(BaseModel):
|
||||
"""AI生成组织的请求模型"""
|
||||
project_id: str = Field(..., description="项目ID")
|
||||
@@ -44,8 +64,13 @@ class OrganizationGenerateRequest(BaseModel):
|
||||
@router.get("/project/{project_id}", response_model=List[OrganizationDetailResponse], summary="获取项目的所有组织")
|
||||
async def get_project_organizations(
|
||||
project_id: str,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(project_id, user_id, db)
|
||||
|
||||
"""
|
||||
获取项目中的所有组织及其详情
|
||||
|
||||
@@ -85,6 +110,7 @@ async def get_project_organizations(
|
||||
@router.get("/{org_id}", response_model=OrganizationResponse, summary="获取组织详情")
|
||||
async def get_organization(
|
||||
org_id: str,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""获取组织的详细信息"""
|
||||
@@ -96,12 +122,17 @@ async def get_organization(
|
||||
if not org:
|
||||
raise HTTPException(status_code=404, detail="组织不存在")
|
||||
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(org.project_id, user_id, db)
|
||||
|
||||
return org
|
||||
|
||||
|
||||
@router.post("/", response_model=OrganizationResponse, summary="创建组织")
|
||||
async def create_organization(
|
||||
organization: OrganizationCreate,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
@@ -110,6 +141,10 @@ async def create_organization(
|
||||
- 需要关联到一个已存在的角色记录(is_organization=True)
|
||||
- 可以设置父组织、势力等级等属性
|
||||
"""
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(organization.project_id, user_id, db)
|
||||
|
||||
# 验证角色是否存在且是组织
|
||||
char_result = await db.execute(
|
||||
select(Character).where(Character.id == organization.character_id)
|
||||
@@ -142,6 +177,7 @@ async def create_organization(
|
||||
async def update_organization(
|
||||
org_id: str,
|
||||
organization: OrganizationUpdate,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""更新组织的属性"""
|
||||
@@ -153,6 +189,10 @@ async def update_organization(
|
||||
if not db_org:
|
||||
raise HTTPException(status_code=404, detail="组织不存在")
|
||||
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(db_org.project_id, user_id, db)
|
||||
|
||||
# 更新字段
|
||||
update_data = organization.model_dump(exclude_unset=True)
|
||||
for field, value in update_data.items():
|
||||
@@ -168,6 +208,7 @@ async def update_organization(
|
||||
@router.delete("/{org_id}", summary="删除组织")
|
||||
async def delete_organization(
|
||||
org_id: str,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""删除组织(会级联删除所有成员关系)"""
|
||||
@@ -179,6 +220,10 @@ async def delete_organization(
|
||||
if not db_org:
|
||||
raise HTTPException(status_code=404, detail="组织不存在")
|
||||
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(db_org.project_id, user_id, db)
|
||||
|
||||
await db.delete(db_org)
|
||||
await db.commit()
|
||||
|
||||
@@ -191,6 +236,7 @@ async def delete_organization(
|
||||
@router.get("/{org_id}/members", response_model=List[OrganizationMemberDetailResponse], summary="获取组织成员")
|
||||
async def get_organization_members(
|
||||
org_id: str,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
@@ -202,9 +248,14 @@ async def get_organization_members(
|
||||
org_result = await db.execute(
|
||||
select(Organization).where(Organization.id == org_id)
|
||||
)
|
||||
if not org_result.scalar_one_or_none():
|
||||
org = org_result.scalar_one_or_none()
|
||||
if not org:
|
||||
raise HTTPException(status_code=404, detail="组织不存在")
|
||||
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(org.project_id, user_id, db)
|
||||
|
||||
# 获取成员列表
|
||||
result = await db.execute(
|
||||
select(OrganizationMember)
|
||||
@@ -244,6 +295,7 @@ async def get_organization_members(
|
||||
async def add_organization_member(
|
||||
org_id: str,
|
||||
member: OrganizationMemberCreate,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
@@ -260,6 +312,10 @@ async def add_organization_member(
|
||||
if not org:
|
||||
raise HTTPException(status_code=404, detail="组织不存在")
|
||||
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(org.project_id, user_id, db)
|
||||
|
||||
# 验证角色存在
|
||||
char_result = await db.execute(
|
||||
select(Character).where(Character.id == member.character_id)
|
||||
@@ -304,6 +360,7 @@ async def add_organization_member(
|
||||
async def update_organization_member(
|
||||
member_id: str,
|
||||
member: OrganizationMemberUpdate,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""更新组织成员的职位、忠诚度等信息"""
|
||||
@@ -315,6 +372,14 @@ async def update_organization_member(
|
||||
if not db_member:
|
||||
raise HTTPException(status_code=404, detail="成员记录不存在")
|
||||
|
||||
# 通过成员所属的组织验证用户权限
|
||||
org_result = await db.execute(
|
||||
select(Organization).where(Organization.id == db_member.organization_id)
|
||||
)
|
||||
org = org_result.scalar_one()
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(org.project_id, user_id, db)
|
||||
|
||||
# 更新字段
|
||||
update_data = member.model_dump(exclude_unset=True)
|
||||
for field, value in update_data.items():
|
||||
@@ -330,6 +395,7 @@ async def update_organization_member(
|
||||
@router.delete("/members/{member_id}", summary="移除组织成员")
|
||||
async def remove_organization_member(
|
||||
member_id: str,
|
||||
request: Request,
|
||||
db: AsyncSession = Depends(get_db)
|
||||
):
|
||||
"""
|
||||
@@ -350,6 +416,10 @@ async def remove_organization_member(
|
||||
select(Organization).where(Organization.id == db_member.organization_id)
|
||||
)
|
||||
org = org_result.scalar_one()
|
||||
|
||||
# 验证用户权限
|
||||
user_id = getattr(request.state, 'user_id', None)
|
||||
await verify_project_access(org.project_id, user_id, db)
|
||||
org.member_count = max(0, org.member_count - 1)
|
||||
|
||||
await db.delete(db_member)
|
||||
@@ -360,7 +430,8 @@ async def remove_organization_member(
|
||||
|
||||
@router.post("/generate", response_model=CharacterResponse, summary="AI生成组织")
|
||||
async def generate_organization(
|
||||
request: OrganizationGenerateRequest,
|
||||
gen_request: OrganizationGenerateRequest,
|
||||
http_request: Request,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
user_ai_service: AIService = Depends(get_user_ai_service)
|
||||
):
|
||||
@@ -372,19 +443,15 @@ async def generate_organization(
|
||||
|
||||
生成内容包括:组织名称、类型、特性、背景、目的、势力等级等
|
||||
"""
|
||||
# 验证项目是否存在并获取项目信息
|
||||
result = await db.execute(
|
||||
select(Project).where(Project.id == request.project_id)
|
||||
)
|
||||
project = result.scalar_one_or_none()
|
||||
if not project:
|
||||
raise HTTPException(status_code=404, detail="项目不存在")
|
||||
# 验证用户权限
|
||||
user_id = getattr(http_request.state, 'user_id', None)
|
||||
project = await verify_project_access(gen_request.project_id, user_id, db)
|
||||
|
||||
try:
|
||||
# 获取已存在的角色和组织列表
|
||||
existing_chars_result = await db.execute(
|
||||
select(Character)
|
||||
.where(Character.project_id == request.project_id)
|
||||
.where(Character.project_id == gen_request.project_id)
|
||||
.order_by(Character.created_at.desc())
|
||||
)
|
||||
existing_characters = existing_chars_result.scalars().all()
|
||||
@@ -422,10 +489,10 @@ async def generate_organization(
|
||||
# 构建用户输入信息
|
||||
user_input = f"""
|
||||
用户要求:
|
||||
- 组织名称:{request.name or '请AI生成'}
|
||||
- 组织类型:{request.organization_type or '请AI根据世界观决定'}
|
||||
- 背景设定:{request.background or '无特殊要求'}
|
||||
- 其他要求:{request.requirements or '无'}
|
||||
- 组织名称:{gen_request.name or '请AI生成'}
|
||||
- 组织类型:{gen_request.organization_type or '请AI根据世界观决定'}
|
||||
- 背景设定:{gen_request.background or '无特殊要求'}
|
||||
- 其他要求:{gen_request.requirements or '无'}
|
||||
"""
|
||||
|
||||
# 使用统一的提示词服务
|
||||
@@ -435,10 +502,10 @@ async def generate_organization(
|
||||
)
|
||||
|
||||
# 调用AI生成组织
|
||||
logger.info(f"🎯 开始为项目 {request.project_id} 生成组织")
|
||||
logger.info(f" - 组织名:{request.name or 'AI生成'}")
|
||||
logger.info(f" - 组织类型:{request.organization_type or 'AI决定'}")
|
||||
logger.info(f" - 背景设定:{request.background or '无'}")
|
||||
logger.info(f"🎯 开始为项目 {gen_request.project_id} 生成组织")
|
||||
logger.info(f" - 组织名:{gen_request.name or 'AI生成'}")
|
||||
logger.info(f" - 组织类型:{gen_request.organization_type or 'AI决定'}")
|
||||
logger.info(f" - 背景设定:{gen_request.background or '无'}")
|
||||
logger.info(f" - AI提供商:{user_ai_service.api_provider}")
|
||||
logger.info(f" - AI模型:{user_ai_service.default_model}")
|
||||
logger.info(f" - Prompt长度:{len(prompt)} 字符")
|
||||
@@ -492,8 +559,8 @@ async def generate_organization(
|
||||
|
||||
# 创建角色记录(组织也是角色的一种)
|
||||
character = Character(
|
||||
project_id=request.project_id,
|
||||
name=organization_data.get("name", request.name or "未命名组织"),
|
||||
project_id=gen_request.project_id,
|
||||
name=organization_data.get("name", gen_request.name or "未命名组织"),
|
||||
is_organization=True,
|
||||
role_type="supporting", # 组织通常作为配角
|
||||
personality=organization_data.get("personality", ""),
|
||||
@@ -518,7 +585,7 @@ async def generate_organization(
|
||||
# 自动创建Organization详情记录
|
||||
organization = Organization(
|
||||
character_id=character.id,
|
||||
project_id=request.project_id,
|
||||
project_id=gen_request.project_id,
|
||||
member_count=0,
|
||||
power_level=organization_data.get("power_level", 50),
|
||||
location=organization_data.get("location"),
|
||||
@@ -532,7 +599,7 @@ async def generate_organization(
|
||||
|
||||
# 记录生成历史
|
||||
history = GenerationHistory(
|
||||
project_id=request.project_id,
|
||||
project_id=gen_request.project_id,
|
||||
prompt=prompt,
|
||||
generated_content=ai_content,
|
||||
model=user_ai_service.default_model
|
||||
@@ -542,7 +609,7 @@ async def generate_organization(
|
||||
await db.commit()
|
||||
await db.refresh(character)
|
||||
|
||||
logger.info(f"🎉 成功为项目 {request.project_id} 生成组织: {character.name}")
|
||||
logger.info(f"🎉 成功为项目 {gen_request.project_id} 生成组织: {character.name}")
|
||||
|
||||
return character
|
||||
|
||||
|
||||
Reference in New Issue
Block a user