会员积分改版V1

This commit is contained in:
2026-08-11 09:24:18 +08:00
parent fe24e51b97
commit b9fd07f293
111 changed files with 9355 additions and 3900 deletions
+84 -1
View File
@@ -17,7 +17,7 @@ import type {
AdminTeam, AdminTeamListResponse, AdminTeamOption, AdminTeamPayload, AdminTeamQueryParams,
PrivatePortraitConfig, PrivatePortraitProjectListOut, PrivatePortraitAssetListOut,
AdminUploadFileResult, AdminUploadResourceType, AdminUploadScene,
VideoUpscaleConfigOut, VideoUpscaleConfigSavePayload,
VideoUpscaleConfigOut, VideoUpscaleConfigSavePayload, CreditProduct,
} from '../types';
import type {
@@ -1092,3 +1092,86 @@ export async function adminGetPrivatePortraitConfig(userId: string): Promise<Pri
export async function adminUpdatePrivatePortraitConfig(userId: string, limit: number): Promise<PrivatePortraitConfig> {
return api.put<PrivatePortraitConfig>(`/admin/private-portrait/users/${userId}/config`, { private_portrait_asset_limit: limit });
}
// ── Dynamic Credit Products ───────────────────────────────
function normalizeCreditProduct(raw: CreditProduct): CreditProduct {
return {
...raw,
renewalEnabled: raw.renewalEnabled === true,
tierRank: raw.tierRank == null ? null : Number(raw.tierRank),
monthlyGrantCredits: Number(raw.monthlyGrantCredits || 0),
firstPurchasePrice: Number(raw.firstPurchasePrice || 0),
regularPrice: Number(raw.regularPrice || 0),
activityPrice: raw.activityPrice == null ? null : Number(raw.activityPrice),
price: Number(raw.price || 0),
grantCredits: Number(raw.grantCredits || 0),
sortOrder: Number(raw.sortOrder || 0),
isActive: raw.isActive === true,
};
}
export async function getCreditProducts(productType?: 'subscription' | 'credit_addon'): Promise<CreditProduct[]> {
const query = productType ? `?product_type=${encodeURIComponent(productType)}` : '';
const products = await api.get<CreditProduct[]>(`/admin/credit-management/products${query}`);
return products.map(normalizeCreditProduct);
}
export async function createCreditProduct(payload: Record<string, unknown>): Promise<CreditProduct> {
return normalizeCreditProduct(await api.post<CreditProduct>('/admin/credit-management/products', payload));
}
export async function updateCreditProduct(id: string, payload: Record<string, unknown>): Promise<CreditProduct> {
return normalizeCreditProduct(await api.put<CreditProduct>(`/admin/credit-management/products/${id}`, payload));
}
export async function setCreditProductRenewal(id: string, renewalEnabled: boolean): Promise<CreditProduct> {
return normalizeCreditProduct(await api.put<CreditProduct>(
`/admin/credit-management/products/${id}/renewal`,
{ renewal_enabled: renewalEnabled },
));
}
export async function disableCreditProduct(id: string): Promise<void> {
await api.delete(`/admin/credit-management/products/${id}`);
}
export async function getAdminUserCreditSummary(userId: string): Promise<any> {
return api.get(`/admin/credit-management/users/${userId}/summary`);
}
export async function getAdminUserCreditBalances(userId: string, page = 1, pageSize = 50, status?: string): Promise<any[]> {
const params = new URLSearchParams({ page: String(page), page_size: String(pageSize) });
if (status) params.set('status', status);
return api.get(`/admin/credit-management/users/${userId}/balances?${params.toString()}`);
}
export async function adminGrantCredits(userId: string, payload: Record<string, unknown>): Promise<any> {
return api.post(`/admin/credit-management/users/${userId}/grant`, payload);
}
export async function adminDeductCredits(userId: string, payload: Record<string, unknown>): Promise<any> {
return api.post(`/admin/credit-management/users/${userId}/deduct`, payload);
}
// ── LLM Fixed Pre-deduct ──────────────────────────────────
export async function getLlmBillingPolicies(): Promise<import('../types').LlmBillingPolicy[]> {
return api.get('/admin/llm-billing/policies');
}
export async function createLlmBillingPolicy(payload: Record<string, unknown>): Promise<import('../types').LlmBillingPolicy> {
return api.post('/admin/llm-billing/policies', payload);
}
export async function updateLlmBillingPolicy(id: string, payload: Record<string, unknown>): Promise<import('../types').LlmBillingPolicy> {
return api.put(`/admin/llm-billing/policies/${id}`, payload);
}
export async function getLlmBillingExecutions(params?: { page?: number; pageSize?: number; sceneCode?: string; status?: string; userId?: string }): Promise<{ items: import('../types').LlmBillingExecution[]; total: number }> {
const query = new URLSearchParams();
query.set('page', String(params?.page || 1));
query.set('page_size', String(params?.pageSize || 20));
if (params?.sceneCode) query.set('scene_code', params.sceneCode);
if (params?.status) query.set('status', params.status);
if (params?.userId) query.set('user_id', params.userId);
return api.get(`/admin/llm-billing/executions?${query.toString()}`);
}