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

View File

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

View File

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

View File

@ -107,9 +107,42 @@ class TenantManager:
def get_all_tenants(): def get_all_tenants():
"""获取所有租户信息""" """获取所有租户信息"""
try: 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) tenants = execute_query(query, cursor_factory=RealDictCursor)
if not tenants:
return []
# 确保返回字段名正确
return tenants return tenants
except Exception as e: except Exception as e:
logger.error(f"获取所有租户信息失败: {e}") logger.error(f"获取所有租户信息失败: {e}")
return [] 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>> { export function getTenantModels(tenantId: string): Promise<ApiResponse<TenantModelResponse>> {
console.log('请求模型列表API路径:', `/api/models/${tenantId}`)
return request({ return request({
url: `/api/models/${tenantId}`, url: `/api/models/${tenantId}`,
method: 'get' method: 'get'

View File

@ -23,8 +23,31 @@ export interface ModelResponse {
created_at: string 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 { export interface TenantModelResponse {
tenant_id: string tenant_id: string
tenant_name: string models: {
models: ModelResponse[] models: ModelItem[]
}
} }

View File

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

View File

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

View File

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