会员积分改版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
+35 -5
View File
@@ -280,10 +280,29 @@ export async function retryGeneration(recordId: string): Promise<GenerationRecor
return api.post<GenerationRecord>(`/generation-records/${recordId}/retry`);
}
// ── Credits ───────────────────────────────────────────────
export async function getCredits(page = 1, pageSize = 20): Promise<{ credits: number; records: CreditRecord[]; total: number }> {
export async function getCredits(page = 1, pageSize = 20): Promise<{ credits: number; availableCredits: number; nextExpiringCredits: number; nextExpiresAt?: string | null; nextLastUsableAt?: string | null; totalGranted: number; totalConsumed: number; totalRefunded: number; totalExpired: number; records: CreditRecord[]; total: number }> {
if (USE_MOCK) {
const data = await mock.mockGetCredits();
return data;
const records = data.records || [];
const totalGranted = records
.filter((record) => record.type === 'recharge' || record.type === 'refund')
.reduce((sum, record) => sum + Math.max(0, Number(record.amount || 0)), 0);
const totalConsumed = records
.filter((record) => record.type === 'consume')
.reduce((sum, record) => sum + Math.abs(Number(record.amount || 0)), 0);
return {
credits: data.credits,
availableCredits: data.credits,
nextExpiringCredits: 0,
nextExpiresAt: null,
nextLastUsableAt: null,
totalGranted,
totalConsumed,
totalRefunded: 0,
totalExpired: 0,
records,
total: data.total,
};
}
const params = new URLSearchParams();
params.set('page', String(page));
@@ -301,7 +320,7 @@ export async function verifyCaptcha(captchaId: string, x: number): Promise<strin
return res.token;
}
// ── Site Info ─────────────────────────────────────────────
export async function getSiteInfo(): Promise<{ siteName: string; siteLogo: string; userAgreementPrivacyUrl: string; siteCopyright: string; operationManual: string; loginBgVideo: string; optimizeHoldCredits?: number }> {
export async function getSiteInfo(): Promise<{ siteName: string; siteLogo: string; userAgreementPrivacyUrl: string; siteCopyright: string; operationManual: string; loginBgVideo: string }> {
if (USE_MOCK) return { siteName: '智创', siteLogo: '', userAgreementPrivacyUrl: '', siteCopyright: '© 2026 智创 版权所有', operationManual: '', loginBgVideo: '' };
return api.get('/auth/site-info', false);
}
@@ -542,7 +561,7 @@ export async function getone(projectId: string, stepId: string): Promise<any> {
export async function updateImagePrompt(projectId: string, stepId: string, params: any): Promise<any> {
return api.put(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/image-prompt`, params);
}
// 第二步,生成图片
export async function gettwo(projectId: string, stepId: string ,params: any): Promise<any> {
return api.post(`/hot-opening-replications/tasks/${projectId}/steps/${stepId}/generate-image`, params);
@@ -915,7 +934,7 @@ export async function deleteOAuthAccount(params: DeleteOAuthAccountParams): Prom
export async function getAllOAuthAccountList(): Promise<any> {
return api.post(`/upload-material/oauth_account_list`);
}
// 获取用户全部授权账户列表 resources_material_ids pre_test_template_id
// 获取用户全部授权账户列表 resources_material_ids pre_test_template_id
export async function submitPreTest(params: { resources_material_ids: any[]; pre_test_template_id: string }): Promise<any> {
return api.post(`/resources-material/pre-commit`, params);
}
@@ -1263,3 +1282,14 @@ export function getTeamCreditExportUrl(params: {
const base = (import.meta as any).env?.VITE_API_BASE || 'http://localhost:8000';
return `${base}/api/team/credit-records/export?${p.toString()}`;
}
// ── Dynamic credit products ───────────────────────────────
export async function getCreditProductCatalog(): Promise<import('../types').CreditProductCatalog> {
return api.get('/credit-products/catalog');
}
export async function getCreditBalances(page = 1, pageSize = 20, status?: string): Promise<any[]> {
const params = new URLSearchParams({ page: String(page), page_size: String(pageSize) });
if (status) params.set('status', status);
return api.get(`/credits/balances?${params.toString()}`);
}
+11 -3
View File
@@ -207,10 +207,14 @@ export async function mockOptimizePrompt(
await delay(1500);
const project = MOCK_PROJECTS.find((p) => p.id === projectId);
const cost = Math.round(80 + params.prompt.length * 0.5 + (params.duration || 0) * 2);
// Mock 与正式接口保持一致:提示词优化按场景固定预扣,积分不足直接拦截。
const cost = 5;
if (currentUser) {
currentUser.credits -= cost;
if (currentUser.credits < cost) {
throw new Error('积分不足');
}
currentUser.credits = Math.round((currentUser.credits - cost) * 100) / 100;
}
const optimizedPromptMap: Record<string, string> = {
@@ -356,7 +360,11 @@ export async function mockGetAdminUsers(search?: string): Promise<AdminUser[]> {
export async function mockAdjustCredits(userId: string, amount: number, _description: string): Promise<void> {
await delay(500);
const user = MOCK_ADMIN_USERS.find(u => u.id === userId);
if (user) user.credits += amount;
if (user) {
const nextCredits = Math.round((user.credits + amount) * 100) / 100;
if (nextCredits < 0) throw new Error('有效积分不足');
user.credits = nextCredits;
}
}
export async function mockToggleUserStatus(userId: string, isActive: boolean): Promise<void> {