fix: 租户模型列表问题未解决,待进一步调试

This commit is contained in:
Xin 2025-05-08 19:32:37 +08:00
parent b5fa1b0d63
commit f52f3b27aa
9 changed files with 164 additions and 48 deletions

View File

@ -1,5 +1,6 @@
import uuid
from datetime import datetime, timedelta, timezone
from typing import List
from fastapi import FastAPI, Depends, HTTPException, status, Request, Body, Response, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
@ -116,7 +117,9 @@ async def get_current_user(token: str = Depends(oauth2_scheme)):
# 打印接收到的token用于调试
logger.info(f"Received token: {token[:10]}...{token[-10:]}")
print(f"Full token: {token}") # 调试日志
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
print(f"Decoded payload: {payload}") # 调试日志
username: str = payload.get("sub")
if username is None:
raise credentials_exception
@ -424,19 +427,21 @@ async def create_tenant(tenant: TenantCreate, current_user: dict = Depends(get_c
logger.error(f"创建租户失败: {e}")
raise HTTPException(status_code=400, detail="创建租户失败")
@app.get("/api/tenants/")
async def list_tenants(current_user: dict = Depends(get_current_user)):
@app.get("/api/tenants/", response_model=List[TenantResponse])
async def list_tenants(
search: str = None,
current_user: dict = Depends(get_current_user)
):
"""查询租户列表"""
try:
tenants = TenantManager.get_all_tenants()
return {
"tenants": [{
"id": str(t["id"]),
"name": t["name"],
"description": t.get("description", ""),
"created_at": t.get("created_at", datetime.now(timezone.utc))
} for t in tenants]
}
logger.info(f"Current user accessing tenants: {current_user['username']}")
tenants = TenantManager.search_tenants(search) if search else TenantManager.get_all_tenants()
if not tenants:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="未找到匹配的租户"
)
return tenants
except Exception as e:
logger.error(f"查询租户列表失败: {e}")
raise HTTPException(status_code=400, detail="查询租户列表失败")
@ -445,6 +450,7 @@ async def list_tenants(current_user: dict = Depends(get_current_user)):
async def get_tenant(name: str, current_user: dict = Depends(get_current_user)):
"""查询特定租户"""
try:
logger.info(f"Current user accessing tenant {name}: {current_user['username']}")
tenant = TenantManager.get_tenant_by_name(name)
if not tenant:
raise HTTPException(

View File

@ -61,7 +61,9 @@ class ModelManager:
cursor.execute(query, (tenant_id,))
models = cursor.fetchall()
return [{
return {
"tenant_id": tenant_id,
"models": [{
"id": str(model[0]),
"provider_name": model[1],
"model_name": model[2],
@ -71,6 +73,7 @@ class ModelManager:
"created_at": model[6],
"updated_at": model[7]
} for model in models]
}
except Exception as e:
logger.error(f"获取租户模型失败: {e}")
raise

View File

@ -54,5 +54,5 @@ class TenantResponse(BaseModel):
"""租户响应模型"""
id: str
name: str
description: str
description: Optional[str] = None
created_at: datetime

View File

@ -107,9 +107,42 @@ class TenantManager:
def get_all_tenants():
"""获取所有租户信息"""
try:
query = "SELECT id, encrypt_public_key FROM tenants;"
query = """
SELECT
id::text,
name,
encrypt_public_key,
created_at
FROM tenants;
"""
tenants = execute_query(query, cursor_factory=RealDictCursor)
if not tenants:
return []
# 确保返回字段名正确
return tenants
except Exception as e:
logger.error(f"获取所有租户信息失败: {e}")
return []
@staticmethod
def search_tenants(search_term: str):
"""根据名称搜索租户"""
try:
query = """
SELECT
id::text,
name,
encrypt_public_key,
created_at
FROM tenants
WHERE name ILIKE %s;
"""
tenants = execute_query(query, (f"%{search_term}%",), cursor_factory=RealDictCursor)
if not tenants:
return []
return tenants
except Exception as e:
logger.error(f"搜索租户失败: {e}")
return []

View File

@ -29,6 +29,7 @@ export function assignModelToTenant(
}
export function getTenantModels(tenantId: string): Promise<ApiResponse<TenantModelResponse>> {
console.log('请求模型列表API路径:', `/api/models/${tenantId}`)
return request({
url: `/api/models/${tenantId}`,
method: 'get'

View File

@ -23,8 +23,31 @@ export interface ModelResponse {
created_at: string
}
export interface ModelItem {
id: string
model_name: string
provider_name: string
model_type: string
encrypted_config: any
is_valid: boolean
created_at: string
updated_at: string
}
export interface ModelItem {
id: string
provider_name: string
model_name: string
model_type: string
encrypted_config: any
is_valid: boolean
created_at: string
updated_at: string
}
export interface TenantModelResponse {
tenant_id: string
tenant_name: string
models: ModelResponse[]
models: {
models: ModelItem[]
}
}

View File

@ -7,17 +7,15 @@ import type {
CreateTenantResponse
} from './types'
export const fetchTenants = (params: { page?: number; pageSize?: number }) =>
export const fetchTenants = (params: { search?: string; page?: number; pageSize?: number }) =>
request<{
tenants: {
id: string
name: string
description: string
createdAt: string
}[]
}>({
}[]>({
method: 'GET',
url: '/api/tenants',
url: '/api/tenants/',
params
})

View File

@ -8,11 +8,14 @@ const service = createAxios()
service.interceptors.request.use(
(config) => {
const token = localStorage.getItem('access_token')
console.log('Request interceptor - token:', token) // 调试日志
if (token) {
config.headers.Authorization = `Bearer ${token}`
console.log('Authorization header set:', config.headers.Authorization) // 调试日志
}
config.headers['Content-Type'] = 'application/json'
config.withCredentials = true
console.log('Final request config:', config) // 调试日志
return config
},
(error) => {

View File

@ -107,7 +107,7 @@ import {
} from '@/api/model'
import { fetchTenants } from '@/api/tenant'
import { ElMessage } from 'element-plus'
import type { ModelResponse } from '@/api/model/types'
import type { ModelResponse, ModelItem } from '@/api/model/types'
interface Tenant {
id: string
@ -130,27 +130,67 @@ const assignForm = ref({
const searchTenants = async () => {
try {
const res = await fetchTenants({ search: searchQuery.value })
searchedTenants.value = res.tenants
} catch (error) {
const tenants = await fetchTenants({ search: searchQuery.value })
searchedTenants.value = tenants
if (tenants.length === 0) {
ElMessage.warning('未找到匹配的租户')
}
} catch (error: any) {
if (error.response?.status === 404) {
searchedTenants.value = []
ElMessage.warning('未找到匹配的租户')
} else {
ElMessage.error('查询租户失败')
}
}
}
const showTenantModels = async (tenantId: string) => {
try {
const res = await getTenantModels(tenantId)
models.value = res.data.models
console.log('开始请求模型列表租户ID:', tenantId)
const res = await getTenantModels(tenantId).catch(err => {
console.error('获取模型列表失败:', err)
console.error('错误详情:', err.response?.data || err.message)
throw err
})
console.log('完整API响应:', JSON.stringify(res, null, 2))
console.log('响应数据:', res.data)
console.log('响应数据.models:', res.data?.models)
if (res?.data?.models?.models) {
models.value = res.data.models.models.map((m: ModelItem) => ({
id: m.id,
model_name: m.model_name,
provider_name: m.provider_name,
model_type: m.model_type,
created_at: m.created_at,
updated_at: m.updated_at
}))
modelDialogVisible.value = true
} catch (error) {
ElMessage.error('加载模型列表失败')
} else {
ElMessage.error('获取模型列表失败: 返回数据格式不正确')
}
} catch (error: any) {
ElMessage.error('加载模型列表失败: ' +
(error.response?.data?.message ||
error.message ||
'未知错误'))
}
}
const handleTenantChange = async (tenantId: string) => {
try {
const res = await getTenantModels(tenantId)
models.value = res.data.models
if (res?.data?.models?.models) {
models.value = res.data.models.models.map((m: ModelItem) => ({
id: m.id,
model_name: m.model_name,
provider_name: m.provider_name,
model_type: m.model_type,
created_at: m.created_at
}))
} else {
ElMessage.error('获取模型列表失败: 返回数据格式不正确')
}
} catch (error) {
ElMessage.error('加载模型列表失败')
}
@ -182,7 +222,17 @@ const loadModels = async () => {
return
}
const res = await getTenantModels(currentTenantId)
models.value = res.data.models
if (res?.data?.models?.models) {
models.value = res.data.models.models.map((m: ModelItem) => ({
id: m.id,
model_name: m.model_name,
provider_name: m.provider_name,
model_type: m.model_type,
created_at: m.created_at
}))
} else {
ElMessage.error('获取模型列表失败: 返回数据格式不正确')
}
} catch (error) {
ElMessage.error('加载模型列表失败')
}
@ -190,8 +240,7 @@ const loadModels = async () => {
const loadTenants = async () => {
try {
const res = await fetchTenants({})
tenants.value = res.tenants
tenants.value = await fetchTenants({})
} catch (error) {
ElMessage.error('加载租户列表失败')
}