mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
feat: 用户创建和注册时使用系统配置的默认配额
- 新增 /api/admin/users/defaults/quota 接口获取默认配额 - 用户注册时从系统配置读取默认配额 - 管理员创建用户时自动获取并使用系统默认配额
This commit is contained in:
@@ -98,6 +98,11 @@ export const usersApi = {
|
|||||||
await apiClient.patch(`/api/admin/users/${userId}/quota`)
|
await apiClient.patch(`/api/admin/users/${userId}/quota`)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async getDefaultQuota(): Promise<{ default_quota_usd: number }> {
|
||||||
|
const response = await apiClient.get<{ default_quota_usd: number }>('/api/admin/users/defaults/quota')
|
||||||
|
return response.data
|
||||||
|
},
|
||||||
|
|
||||||
// 管理员统计
|
// 管理员统计
|
||||||
async getUsageStats(): Promise<any> {
|
async getUsageStats(): Promise<any> {
|
||||||
const response = await apiClient.get('/api/admin/usage/stats')
|
const response = await apiClient.get('/api/admin/usage/stats')
|
||||||
|
|||||||
@@ -363,6 +363,7 @@ import { ModelMultiSelect } from '@/components/common'
|
|||||||
import { getProvidersSummary } from '@/api/endpoints/providers'
|
import { getProvidersSummary } from '@/api/endpoints/providers'
|
||||||
import { getGlobalModels } from '@/api/global-models'
|
import { getGlobalModels } from '@/api/global-models'
|
||||||
import { adminApi } from '@/api/admin'
|
import { adminApi } from '@/api/admin'
|
||||||
|
import { usersApi } from '@/api/users'
|
||||||
import { log } from '@/utils/logger'
|
import { log } from '@/utils/logger'
|
||||||
import type { ProviderWithEndpointsSummary, GlobalModelResponse } from '@/api/endpoints/types'
|
import type { ProviderWithEndpointsSummary, GlobalModelResponse } from '@/api/endpoints/types'
|
||||||
|
|
||||||
@@ -402,6 +403,7 @@ const endpointDropdownOpen = ref(false)
|
|||||||
const providers = ref<ProviderWithEndpointsSummary[]>([])
|
const providers = ref<ProviderWithEndpointsSummary[]>([])
|
||||||
const globalModels = ref<GlobalModelResponse[]>([])
|
const globalModels = ref<GlobalModelResponse[]>([])
|
||||||
const apiFormats = ref<Array<{ value: string; label: string }>>([])
|
const apiFormats = ref<Array<{ value: string; label: string }>>([])
|
||||||
|
const defaultQuota = ref<number>(10)
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const form = ref({
|
const form = ref({
|
||||||
@@ -430,7 +432,7 @@ function resetForm() {
|
|||||||
password: '',
|
password: '',
|
||||||
confirmPassword: '',
|
confirmPassword: '',
|
||||||
email: '',
|
email: '',
|
||||||
quota: 10,
|
quota: defaultQuota.value,
|
||||||
role: 'user',
|
role: 'user',
|
||||||
unlimited: false,
|
unlimited: false,
|
||||||
is_active: true,
|
is_active: true,
|
||||||
@@ -479,18 +481,22 @@ const isFormValid = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 加载访问控制选项
|
// 加载访问控制选项
|
||||||
async function loadAccessControlOptions() {
|
async function loadAccessControlOptions(): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const [providersData, modelsData, formatsData] = await Promise.all([
|
const [providersData, modelsData, formatsData, quotaData] = await Promise.all([
|
||||||
getProvidersSummary(),
|
getProvidersSummary(),
|
||||||
getGlobalModels({ limit: 1000, is_active: true }),
|
getGlobalModels({ limit: 1000, is_active: true }),
|
||||||
adminApi.getApiFormats()
|
adminApi.getApiFormats(),
|
||||||
|
usersApi.getDefaultQuota()
|
||||||
])
|
])
|
||||||
providers.value = providersData
|
providers.value = providersData
|
||||||
globalModels.value = modelsData.models || []
|
globalModels.value = modelsData.models || []
|
||||||
apiFormats.value = formatsData.formats || []
|
apiFormats.value = formatsData.formats || []
|
||||||
|
defaultQuota.value = quotaData.default_quota_usd
|
||||||
|
return true
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error('加载访问限制选项失败:', err)
|
log.error('加载访问限制选项失败:', err)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,9 +557,13 @@ function setSaving(value: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 监听打开状态,加载选项数据
|
// 监听打开状态,加载选项数据
|
||||||
watch(isOpen, (val) => {
|
watch(isOpen, async (val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
loadAccessControlOptions()
|
const success = await loadAccessControlOptions()
|
||||||
|
// 创建模式下,仅在加载成功时更新表单配额
|
||||||
|
if (!isEditMode.value && success) {
|
||||||
|
form.value.quota = defaultQuota.value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from src.database import get_db
|
|||||||
from src.models.admin_requests import UpdateUserRequest
|
from src.models.admin_requests import UpdateUserRequest
|
||||||
from src.models.api import CreateApiKeyRequest, CreateUserRequest
|
from src.models.api import CreateApiKeyRequest, CreateUserRequest
|
||||||
from src.models.database import ApiKey, User, UserRole
|
from src.models.database import ApiKey, User, UserRole
|
||||||
|
from src.services.system.config import SystemConfigService
|
||||||
from src.services.user.apikey import ApiKeyService
|
from src.services.user.apikey import ApiKeyService
|
||||||
from src.services.user.service import UserService
|
from src.services.user.service import UserService
|
||||||
|
|
||||||
@@ -197,6 +198,20 @@ async def delete_user_api_key(
|
|||||||
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/defaults/quota")
|
||||||
|
async def get_default_quota(request: Request, db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
获取默认用户配额
|
||||||
|
|
||||||
|
获取系统配置的默认用户配额值,用于创建用户时的默认值。
|
||||||
|
|
||||||
|
**返回字段**:
|
||||||
|
- `default_quota_usd`: 默认配额(USD)
|
||||||
|
"""
|
||||||
|
adapter = AdminGetDefaultQuotaAdapter()
|
||||||
|
return await pipeline.run(adapter=adapter, http_request=request, db=db, mode=adapter.mode)
|
||||||
|
|
||||||
|
|
||||||
# ============== 管理员适配器实现 ==============
|
# ============== 管理员适配器实现 ==============
|
||||||
|
|
||||||
|
|
||||||
@@ -586,3 +601,15 @@ class AdminDeleteUserKeyAdapter(AdminApiAdapter):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return {"message": "API Key已删除"}
|
return {"message": "API Key已删除"}
|
||||||
|
|
||||||
|
|
||||||
|
class AdminGetDefaultQuotaAdapter(AdminApiAdapter):
|
||||||
|
"""获取系统默认用户配额"""
|
||||||
|
|
||||||
|
async def handle(self, context): # type: ignore[override]
|
||||||
|
db = context.db
|
||||||
|
default_quota = SystemConfigService.get_config(db, "default_user_quota_usd", default=10.0)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"default_quota_usd": float(default_quota),
|
||||||
|
}
|
||||||
|
|||||||
@@ -470,12 +470,16 @@ class AuthRegisterAdapter(AuthPublicAdapter):
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# 读取系统配置的默认配额
|
||||||
|
default_quota = SystemConfigService.get_config(db, "default_user_quota_usd", default=10.0)
|
||||||
|
|
||||||
user = UserService.create_user(
|
user = UserService.create_user(
|
||||||
db=db,
|
db=db,
|
||||||
email=register_request.email,
|
email=register_request.email,
|
||||||
username=register_request.username,
|
username=register_request.username,
|
||||||
password=register_request.password,
|
password=register_request.password,
|
||||||
role=UserRole.USER,
|
role=UserRole.USER,
|
||||||
|
quota_usd=default_quota,
|
||||||
)
|
)
|
||||||
AuditService.log_event(
|
AuditService.log_event(
|
||||||
db=db,
|
db=db,
|
||||||
|
|||||||
Reference in New Issue
Block a user