diff --git a/backend/app/models/tenant_app.py b/backend/app/models/tenant_app.py index 1e77a81..62e6ef5 100644 --- a/backend/app/models/tenant_app.py +++ b/backend/app/models/tenant_app.py @@ -23,6 +23,10 @@ class TenantApp(Base): # 功能权限 allowed_tools = Column(Text) # JSON 数组 + # 自定义配置(JSON 数组) + # [{"key": "industry", "value": "medical_beauty", "remark": "医美行业"}, ...] + custom_configs = Column(Text) + status = Column(SmallInteger, default=1) created_at = Column(TIMESTAMP, default=datetime.now) updated_at = Column(TIMESTAMP, default=datetime.now, onupdate=datetime.now) diff --git a/backend/app/routers/tenant_apps.py b/backend/app/routers/tenant_apps.py index db31e79..29be095 100644 --- a/backend/app/routers/tenant_apps.py +++ b/backend/app/routers/tenant_apps.py @@ -17,6 +17,13 @@ router = APIRouter(prefix="/tenant-apps", tags=["应用配置"]) # Schemas +class CustomConfigItem(BaseModel): + """自定义配置项""" + key: str # 配置键 + value: str # 配置值 + remark: Optional[str] = None # 备注说明 + + class TenantAppCreate(BaseModel): tenant_id: str app_code: str = "tools" @@ -25,6 +32,7 @@ class TenantAppCreate(BaseModel): access_token: Optional[str] = None # 如果不传则自动生成 allowed_origins: Optional[List[str]] = None allowed_tools: Optional[List[str]] = None + custom_configs: Optional[List[CustomConfigItem]] = None # 自定义配置 class TenantAppUpdate(BaseModel): @@ -33,6 +41,7 @@ class TenantAppUpdate(BaseModel): access_token: Optional[str] = None allowed_origins: Optional[List[str]] = None allowed_tools: Optional[List[str]] = None + custom_configs: Optional[List[CustomConfigItem]] = None # 自定义配置 status: Optional[int] = None @@ -111,6 +120,7 @@ async def create_tenant_app( access_token=access_token, allowed_origins=json.dumps(data.allowed_origins) if data.allowed_origins else None, allowed_tools=json.dumps(data.allowed_tools) if data.allowed_tools else None, + custom_configs=json.dumps([c.model_dump() for c in data.custom_configs], ensure_ascii=False) if data.custom_configs else None, status=1 ) db.add(app) @@ -139,6 +149,14 @@ async def update_tenant_app( update_data['allowed_origins'] = json.dumps(update_data['allowed_origins']) if update_data['allowed_origins'] else None if 'allowed_tools' in update_data: update_data['allowed_tools'] = json.dumps(update_data['allowed_tools']) if update_data['allowed_tools'] else None + if 'custom_configs' in update_data: + if update_data['custom_configs']: + update_data['custom_configs'] = json.dumps( + [c.model_dump() if hasattr(c, 'model_dump') else c for c in update_data['custom_configs']], + ensure_ascii=False + ) + else: + update_data['custom_configs'] = None for key, value in update_data.items(): setattr(app, key, value) @@ -164,6 +182,27 @@ async def delete_tenant_app( return {"success": True} +@router.get("/{app_id}/token") +async def get_token( + app_id: int, + user: User = Depends(require_operator), + db: Session = Depends(get_db) +): + """获取真实的 access_token(仅管理员可用)""" + app = db.query(TenantApp).filter(TenantApp.id == app_id).first() + if not app: + raise HTTPException(status_code=404, detail="应用配置不存在") + + # 获取应用的 base_url + app_info = db.query(App).filter(App.app_code == app.app_code).first() + base_url = app_info.base_url if app_info else "" + + return { + "access_token": app.access_token, + "base_url": base_url + } + + @router.post("/{app_id}/regenerate-token") async def regenerate_token( app_id: int, @@ -207,6 +246,7 @@ def format_tenant_app(app: TenantApp, mask_secret: bool = True, db: Session = No "access_token": "******" if mask_secret and app.access_token else app.access_token, "allowed_origins": json.loads(app.allowed_origins) if app.allowed_origins else [], "allowed_tools": json.loads(app.allowed_tools) if app.allowed_tools else [], + "custom_configs": json.loads(app.custom_configs) if app.custom_configs else [], "status": app.status, "created_at": app.created_at, "updated_at": app.updated_at