Files
gongxue-base/apps/taro/src/services/tenantAdmin.ts
2026-06-29 20:51:24 +08:00

1107 lines
31 KiB
TypeScript

import { apiRequest } from './api';
export interface TenantDashboard {
scope?: Record<string, unknown>;
cards?: {
students?: Record<string, number>;
learning?: Record<string, number>;
content?: Record<string, number>;
activationCodes?: Record<string, number>;
feedback?: Record<string, number>;
};
paymentStats?: Record<string, number>;
trends?: Record<string, unknown>[];
activeHours?: Record<string, unknown>[];
questionDistribution?: Record<string, unknown>[];
subjectTop?: Record<string, unknown>[];
regionStats?: Record<string, unknown>[];
planSales?: Record<string, unknown>[];
recentActivities?: Record<string, unknown>[];
}
export interface TenantClassItem {
id: string;
name: string;
code?: string | null;
status?: string;
regionName?: string | null;
studentCount?: number;
teacherCount?: number;
}
export interface TenantStudentItem {
membershipId?: string;
userId: string;
username?: string | null;
name?: string | null;
phone?: string | null;
email?: string | null;
status?: string;
profileId?: string;
regionId?: string | null;
regionName?: string | null;
selectedSchoolId?: string | null;
selectedSchoolName?: string | null;
selectedMajorId?: string | null;
selectedMajorName?: string | null;
questionsAnsweredToday?: number;
masteredWordsCount?: number;
lastSeenAt?: string | null;
classes?: Record<string, unknown>[];
}
export interface TenantStudentInput {
userId?: string;
username?: string | null;
name?: string | null;
phone?: string | null;
email?: string | null;
regionId?: string | null;
selectedSchoolId?: string | null;
selectedMajorId?: string | null;
status?: string;
stats?: Record<string, unknown>;
progress?: Record<string, unknown>;
moduleSelections?: Record<string, unknown>;
}
export interface TenantTeacherItem {
membershipId?: string;
userId: string;
username?: string | null;
name?: string | null;
phone?: string | null;
email?: string | null;
status?: string;
classCount?: number;
}
export interface BulkOperationResult {
total?: number;
successCount?: number;
errorCount?: number;
items?: Record<string, unknown>[];
errors?: Array<{
index?: number;
code?: string;
message?: string;
}>;
}
export interface TenantStudentNoteItem {
id: string;
studentUserId?: string;
noteType?: string;
content?: string;
visibility?: string;
isPinned?: boolean;
metadata?: Record<string, unknown>;
createdByName?: string | null;
createdByUsername?: string | null;
createdAt?: string;
updatedAt?: string;
}
export interface TenantStudentFollowupItem {
id: string;
studentUserId?: string;
studentName?: string | null;
studentPhone?: string | null;
assignedToUserId?: string | null;
assignedToName?: string | null;
classId?: string | null;
className?: string | null;
title?: string;
description?: string | null;
followupType?: string;
priority?: string;
status?: string;
dueAt?: string | null;
completedAt?: string | null;
completedBy?: string | null;
metadata?: Record<string, unknown>;
createdAt?: string;
updatedAt?: string;
}
export interface ImportJobItem {
id: string;
importType?: string;
sourceFormat?: string;
status?: string;
sourceName?: string | null;
totalCount?: number;
validCount?: number;
successCount?: number;
errorCount?: number;
warningCount?: number;
insertedCount?: number;
updatedCount?: number;
skippedCount?: number;
executionMode?: string;
queuedAt?: string | null;
lockedAt?: string | null;
lockedBy?: string | null;
attemptCount?: number;
maxAttempts?: number;
nextAttemptAt?: string | null;
errorMessage?: string | null;
createdAt?: string;
updatedAt?: string;
finishedAt?: string | null;
summary?: Record<string, unknown>;
}
export interface ImportJobDetail {
item?: ImportJobItem;
issueSummary?: Record<string, number>;
itemStatusSummary?: Record<string, number>;
recentIssues?: ImportIssueItem[];
importPostCheck?: Record<string, unknown> | null;
worker?: {
executionMode?: string;
queuedAt?: string | null;
lockedAt?: string | null;
lockedBy?: string | null;
attemptCount?: number;
maxAttempts?: number;
nextAttemptAt?: string | null;
lastWorkerError?: Record<string, unknown>;
};
}
export interface ContentEntryAdminItem {
id: string;
name: string;
entryType?: string;
visibility?: string;
isActive?: boolean;
regionName?: string | null;
}
export interface PublicQuestionBankItem {
grantId?: string;
sourceQuestionBankId?: string;
sourceQuestionBankName?: string;
sourceRegionName?: string | null;
name?: string;
regionName?: string | null;
grantScope?: string;
questionCount?: number;
adoptedId?: string | null;
adoptionStatus?: string | null;
syncStatus?: string | null;
targetEntryId?: string | null;
targetCollectionId?: string | null;
copiedQuestionCount?: number;
lastSyncedAt?: string | null;
adoption?: Record<string, unknown> | null;
}
export interface PublicQuestionBankConflictItem {
sourceQuestionId?: string;
targetQuestionId?: string | null;
action?: string;
sourceHash?: string;
previousSourceHash?: string | null;
targetHash?: string | null;
}
export interface PublicQuestionBankConflictsResult {
adoptionId?: string;
syncStatus?: string;
status?: string;
lastSyncedAt?: string | null;
updatedAt?: string;
conflictCount?: number;
counts?: Record<string, unknown>;
conflicts?: PublicQuestionBankConflictItem[];
}
export interface TenantContentNotificationItem {
id: string;
notificationType?: string;
status?: 'unread' | 'read' | 'dismissed' | 'resolved';
severity?: 'info' | 'success' | 'warning' | 'error';
adoptionId?: string | null;
sourceQuestionBankId?: string | null;
title?: string;
message?: string;
actionLabel?: string | null;
actionPath?: string | null;
metadata?: Record<string, unknown>;
createdAt?: string;
updatedAt?: string;
readAt?: string | null;
resolvedAt?: string | null;
}
export interface ImportIssueItem {
id: string;
rowNo?: number | null;
severity?: string;
code?: string;
fieldPath?: string | null;
message?: string;
externalId?: string | null;
itemStatus?: string | null;
createdAt?: string;
}
export interface ImportFieldMapping {
importType?: string;
title?: string;
description?: string;
fields?: Array<{
field?: string;
label?: string;
required?: boolean;
aliases?: string[];
description?: string;
example?: unknown;
}>;
requiredFields?: string[];
}
export interface ImportTemplateItem {
importType?: string;
format?: string;
fileName?: string;
mimeType?: string;
contentBase64?: string;
contentPreview?: string;
fields?: Record<string, unknown>[];
}
export interface MediaAnalyticsSummary {
scope?: Record<string, unknown>;
assetAccess?: {
totalEvents?: number;
grantedEvents?: number;
deniedEvents?: number;
downloads?: number;
previews?: number;
uploadSigns?: number;
uploadConfirms?: number;
uniqueUsers?: number;
watermarkEvents?: number;
};
videoPlay?: {
totalEvents?: number;
issuedEvents?: number;
startedEvents?: number;
completedEvents?: number;
freePlays?: number;
svipPlays?: number;
quotaPlays?: number;
consumedQuota?: number;
watchedSeconds?: number;
avgCompletionRate?: number;
uniqueUsers?: number;
watermarkEvents?: number;
};
assetTop?: Record<string, unknown>[];
videoTop?: Record<string, unknown>[];
daily?: Record<string, number | string>[];
traceMatches?: { assets?: number; videos?: number } | null;
}
export interface MediaAssetAccessEvent {
id: string;
assetId?: string | null;
assetTitle?: string | null;
assetType?: string | null;
userId?: string | null;
userLabel?: string | null;
actorRole?: string;
accessType?: string;
visibility?: string | null;
storageProvider?: string | null;
disposition?: string | null;
expiresInSec?: number | null;
signatureMode?: string | null;
result?: string;
denyCode?: string | null;
ipAddress?: string | null;
userAgent?: string | null;
watermarkTraceId?: string | null;
watermark?: Record<string, unknown> | null;
createdAt?: string;
}
export interface MediaVideoPlayEvent {
id: string;
videoId?: string;
videoTitle?: string | null;
assetId?: string | null;
questionId?: string | null;
userId?: string;
userLabel?: string | null;
status?: string;
accessMode?: string;
consumedQuota?: number;
playback?: Record<string, unknown> | null;
signedUrlExpiresAt?: string | null;
ipAddress?: string | null;
userAgent?: string | null;
signatureMode?: string | null;
provider?: string | null;
watermarkTraceId?: string | null;
watermark?: Record<string, unknown> | null;
createdAt?: string;
updatedAt?: string;
}
export interface ImportPreviewResult {
job?: {
id: string;
status?: string;
totalCount?: number;
validCount?: number;
errorCount?: number;
warningCount?: number;
};
items?: Array<{
rowNo?: number;
status?: string;
externalId?: string | null;
normalized?: Record<string, unknown> | null;
issues?: ImportIssueItem[];
}>;
issues?: ImportIssueItem[];
}
export type ImportType = 'questions' | 'vocabulary' | 'handbook' | 'scoreline' | 'videos';
export type ImportSourceFormat = 'json' | 'csv' | 'excel';
export interface ImportRequestBody {
sourceFormat?: ImportSourceFormat;
sourceName?: string;
payload?: unknown;
items?: unknown[];
csvText?: string;
fileBase64?: string;
allowPartial?: boolean;
executionMode?: 'sync' | 'async';
previewJobId?: string;
jobId?: string;
regionId?: string;
entryId?: string;
contentNodeId?: string;
collectionId?: string;
fieldMappingOverrides?: Record<string, string[]>;
fieldMappingPreset?: ImportFieldMapping | null;
}
export interface CouponItem {
id: string;
code: string;
status?: string;
discountType?: string | null;
discountValue?: number | string | null;
usedCount?: number;
maxUses?: number | null;
}
export interface CodeBatchItem {
id: string;
name?: string | null;
batchNo?: string | null;
totalCount?: number;
usedCount?: number;
status?: string;
}
export interface CrmConfigItem {
id?: string;
enabled?: boolean;
url?: string | null;
secretRef?: string | null;
formName?: string | null;
examType?: string | null;
timeoutSec?: number;
delaySec?: number;
assignmentMode?: 'none' | 'direct' | 'round_robin' | 'referrer';
assignmentPool?: string[];
assignmentCursor?: number;
assignmentConfig?: Record<string, unknown>;
updatedAt?: string;
}
export interface CrmQueueItem {
id: string;
recordId?: string | null;
status?: string;
scheduledAt?: string | null;
attempts?: number;
nextAttemptAt?: string | null;
lastError?: string | null;
lastHttpCode?: number | null;
leadId?: string | null;
sentAt?: string | null;
source?: string | null;
targetUrl?: string | null;
payload?: Record<string, unknown>;
createdAt?: string;
}
export interface CommissionSettingsItem {
defaultRate?: number | string;
minSettlementCents?: number;
settlementCycle?: string;
config?: Record<string, unknown>;
updatedAt?: string;
}
export interface CommissionSummaryItem {
tenantId?: string;
startDate?: string;
endDate?: string;
referrerUserId?: string | null;
defaultRate?: number | string;
minSettlementCents?: number;
sourceCount?: number;
paidUserCount?: number;
grossAmountCents?: number;
commissionAmountCents?: number;
byReferrer?: Record<string, unknown>[];
}
export interface CommissionOrderItem {
sourceType?: string;
sourceId?: string;
sourceNo?: string | null;
referrerUserId?: string;
referrerName?: string | null;
referrerPhone?: string | null;
studentUserId?: string | null;
studentName?: string | null;
grossAmountCents?: number;
commissionRate?: number | string;
commissionAmountCents?: number;
rateSource?: string;
settlementId?: string | null;
sourcePaidAt?: string | null;
}
export interface CommissionSettlementItem {
id: string;
settlementNo?: string;
referrerUserId?: string;
referrerName?: string | null;
referrerPhone?: string | null;
status?: string;
periodStart?: string;
periodEnd?: string;
sourceCount?: number;
paidUserCount?: number;
grossAmountCents?: number;
commissionAmountCents?: number;
defaultRate?: number | string;
effectiveRate?: number | string;
reviewedBy?: string | null;
reviewedAt?: string | null;
paidBy?: string | null;
paidAt?: string | null;
paymentMethod?: string | null;
paymentAccount?: string | null;
remark?: string | null;
metadata?: Record<string, unknown>;
createdAt?: string;
updatedAt?: string;
}
export interface TenantOverview {
id?: string;
name?: string;
slug?: string;
status?: string;
brandName?: string;
shortName?: string;
slogan?: string | null;
logoUrl?: string | null;
theme?: Record<string, unknown>;
featureFlags?: Record<string, unknown>;
adminFeatureFlags?: Record<string, unknown>;
publicConfig?: Record<string, unknown>;
}
export interface TenantThemeTemplateItem {
code: string;
name: string;
description?: string | null;
previewImageUrl?: string | null;
theme?: Record<string, unknown>;
publicAssets?: Record<string, unknown>;
sortOrder?: number;
status?: string;
updatedAt?: string;
}
export interface TenantThemeConfigItem {
tenantId?: string;
activeTemplateCode?: string | null;
activeTemplateName?: string | null;
activeTheme?: Record<string, unknown>;
activePublicAssets?: Record<string, unknown>;
draftTemplateCode?: string | null;
draftTemplateName?: string | null;
draftTheme?: Record<string, unknown>;
draftPublicAssets?: Record<string, unknown>;
status?: string;
publishedAt?: string | null;
updatedAt?: string | null;
brandingTheme?: Record<string, unknown>;
brandingPublicAssets?: Record<string, unknown>;
}
export interface TenantThemeDraftInput {
templateCode: string;
theme?: Record<string, unknown>;
publicAssets?: Record<string, unknown>;
}
export interface TenantPermissionCatalogItem {
key: string;
label?: string;
description?: string;
}
export interface TenantPermissionsPayload {
current?: Record<string, unknown>;
permissions?: TenantPermissionCatalogItem[];
menuGroups?: TenantPermissionCatalogItem[];
fieldGroups?: TenantPermissionCatalogItem[];
fieldCatalog?: TenantPermissionCatalogItem[];
roleDefaults?: Record<string, string[]>;
}
export interface TenantRoleTemplateItem {
id: string;
code: string;
name: string;
description?: string | null;
baseRole?: string;
status?: string;
permissions?: Record<string, boolean>;
menuPermissions?: Record<string, boolean>;
modulePermissions?: Record<string, boolean>;
fieldPermissions?: Record<string, boolean>;
dataScope?: Record<string, unknown>;
isSystem?: boolean;
sortOrder?: number;
createdAt?: string;
updatedAt?: string;
}
export interface TenantRoleTemplateInput {
id?: string;
code: string;
name: string;
description?: string | null;
baseRole: string;
status?: string;
permissions?: Record<string, boolean>;
menuPermissions?: Record<string, boolean>;
modulePermissions?: Record<string, boolean>;
fieldPermissions?: Record<string, boolean>;
dataScope?: Record<string, unknown>;
sortOrder?: number;
}
export interface TenantMemberItem {
id: string;
userId: string;
username?: string | null;
name?: string | null;
phone?: string | null;
email?: string | null;
avatarUrl?: string | null;
primaryRole?: string | null;
role: string;
status?: string;
permissions?: Record<string, boolean>;
roleTemplateId?: string | null;
roleTemplateCode?: string | null;
roleTemplateName?: string | null;
menuPermissions?: Record<string, boolean>;
modulePermissions?: Record<string, boolean>;
fieldPermissions?: Record<string, boolean>;
dataScope?: Record<string, unknown>;
legacyRole?: string | null;
lastSeenAt?: string | null;
createdAt?: string;
updatedAt?: string;
}
export interface TenantMemberInput {
membershipId?: string;
userId?: string;
username?: string | null;
name?: string | null;
phone?: string | null;
email?: string | null;
primaryRole?: string | null;
role: string;
status?: string;
permissions?: Record<string, boolean>;
roleTemplateId?: string | null;
}
export async function loadTenantDashboard(timeRange = '30d') {
return apiRequest<{ item?: TenantDashboard }>('/api/tenant-admin/dashboard', { query: { timeRange } });
}
export async function loadTenantOverview() {
return apiRequest<{ item?: TenantOverview }>('/api/tenant-admin/overview');
}
export async function loadThemeTemplates() {
return apiRequest<{ items?: TenantThemeTemplateItem[] }>('/api/tenant-admin/theme-templates');
}
export async function loadTenantTheme() {
return apiRequest<{ item?: TenantThemeConfigItem }>('/api/tenant-admin/theme');
}
export async function previewTenantTheme(input: TenantThemeDraftInput) {
return apiRequest<{ item?: TenantThemeConfigItem & { templateName?: string | null } }>('/api/tenant-admin/theme/preview', {
method: 'POST',
body: input,
});
}
export async function publishTenantTheme(input: { useDraft?: boolean; templateCode?: string; theme?: Record<string, unknown>; publicAssets?: Record<string, unknown> } = {}) {
return apiRequest<{ item?: TenantThemeConfigItem & { templateName?: string | null } }>('/api/tenant-admin/theme/publish', {
method: 'POST',
body: { useDraft: input.useDraft ?? true, ...input },
});
}
export async function loadTenantPermissions() {
return apiRequest<TenantPermissionsPayload>('/api/tenant-admin/permissions');
}
export async function loadTenantClasses(limit = 50) {
return apiRequest<{ items?: TenantClassItem[]; scoped?: boolean }>('/api/tenant-admin/classes', { query: { limit } });
}
export async function loadTenantStudents(query: { keyword?: string; classId?: string; status?: string; limit?: number } = {}) {
return apiRequest<{ items?: TenantStudentItem[]; scoped?: boolean }>('/api/tenant-admin/students', {
query: { ...query, limit: query.limit || 50 },
});
}
export async function upsertTenantStudent(input: TenantStudentInput) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-admin/students', {
method: 'PUT',
body: input,
});
}
export async function bulkUpsertTenantStudents(students: TenantStudentInput[]) {
return apiRequest<BulkOperationResult>('/api/tenant-admin/students/bulk-upsert', {
method: 'POST',
body: { students },
});
}
export async function updateTenantStudentStatus(input: { userId: string; status: string; reason?: string | null }) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-admin/students/status', {
method: 'POST',
body: input,
});
}
export async function bulkAssignTenantClassMembers(input: {
classId: string;
assignments: Array<{
userId?: string;
username?: string | null;
name?: string | null;
phone?: string | null;
email?: string | null;
memberType?: string;
status?: string;
metadata?: Record<string, unknown>;
}>;
}) {
return apiRequest<BulkOperationResult>('/api/tenant-admin/classes/members/bulk-assign', {
method: 'POST',
body: input,
});
}
export async function loadTenantTeachers(query: { keyword?: string; limit?: number } = {}) {
return apiRequest<{ items?: TenantTeacherItem[] }>('/api/tenant-admin/teachers', {
query: { ...query, limit: query.limit || 50 },
});
}
export async function loadTenantStudentNotes(studentUserId: string, limit = 20) {
return apiRequest<{ items?: TenantStudentNoteItem[] }>('/api/tenant-admin/students/notes', {
query: { studentUserId, limit },
});
}
export async function upsertTenantStudentNote(input: {
id?: string;
studentUserId: string;
noteType?: string;
content: string;
visibility?: string;
isPinned?: boolean;
metadata?: Record<string, unknown>;
}) {
return apiRequest<{ item?: TenantStudentNoteItem }>('/api/tenant-admin/students/notes', {
method: 'PUT',
body: input,
});
}
export async function loadTenantStudentFollowups(query: {
studentUserId?: string;
status?: string;
assignedToUserId?: string;
limit?: number;
} = {}) {
return apiRequest<{ items?: TenantStudentFollowupItem[] }>('/api/tenant-admin/students/followups', {
query: { ...query, limit: query.limit || 50 },
});
}
export async function upsertTenantStudentFollowup(input: {
id?: string;
studentUserId: string;
assignedToUserId?: string | null;
classId?: string | null;
title: string;
description?: string | null;
followupType?: string;
priority?: string;
status?: string;
dueAt?: string | null;
metadata?: Record<string, unknown>;
}) {
return apiRequest<{ item?: TenantStudentFollowupItem }>('/api/tenant-admin/students/followups', {
method: 'PUT',
body: input,
});
}
export async function loadContentEntriesAdmin() {
return apiRequest<{ items?: ContentEntryAdminItem[] }>('/api/tenant-content/content-entries');
}
export async function loadImportJobs(limit = 20) {
return apiRequest<{ items?: ImportJobItem[] }>('/api/tenant-content/imports', { query: { limit } });
}
export async function loadImportJobDetail(jobId: string) {
return apiRequest<ImportJobDetail>('/api/tenant-content/imports/detail', { query: { jobId } });
}
export async function loadImportIssues(jobId: string) {
return apiRequest<{ items?: ImportIssueItem[] }>('/api/tenant-content/imports/issues', { query: { jobId } });
}
export async function loadPublicQuestionBanks() {
return apiRequest<{ items?: PublicQuestionBankItem[] }>('/api/tenant-content/public-question-banks');
}
export async function loadTenantContentNotifications(input: {
status?: 'unread' | 'read' | 'dismissed' | 'resolved';
notificationType?: string;
adoptionId?: string;
limit?: number;
} = {}) {
return apiRequest<{ items?: TenantContentNotificationItem[]; summary?: Record<string, number> }>('/api/tenant-content/notifications', {
query: input,
});
}
export async function updateTenantContentNotificationStatus(input: {
notificationIds: string[];
status: 'read' | 'dismissed' | 'resolved';
}) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-content/notifications/status', {
method: 'POST',
body: input,
});
}
export async function adoptPublicQuestionBank(input: { grantId: string; entryName?: string; collectionName?: string; copyLimit?: number }) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-content/public-question-banks/adopt', {
method: 'POST',
body: input,
});
}
export async function syncPublicQuestionBank(input: { adoptionId: string; copyLimit?: number }) {
return apiRequest<{ item?: Record<string, unknown>; sync?: Record<string, unknown> }>('/api/tenant-content/public-question-banks/sync', {
method: 'POST',
body: input,
});
}
export async function loadPublicQuestionBankConflicts(adoptionId: string) {
return apiRequest<{ item?: PublicQuestionBankConflictsResult }>('/api/tenant-content/public-question-banks/conflicts', {
query: { adoptionId },
});
}
export async function resolvePublicQuestionBankConflict(input: { adoptionId: string; sourceQuestionId: string; resolution: 'accept_platform' | 'keep_local' }) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-content/public-question-banks/conflicts/resolve', {
method: 'POST',
body: input,
});
}
export async function resolvePublicQuestionBankConflicts(input: {
adoptionId: string;
sourceQuestionIds: string[];
resolution: 'accept_platform' | 'keep_local';
limit?: number;
}) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-content/public-question-banks/conflicts/resolve-batch', {
method: 'POST',
body: input,
});
}
export async function runImportPostCheck(jobId: string) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-content/imports/post-check', {
method: 'POST',
body: { jobId },
});
}
export async function loadImportPostCheck(jobId: string) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/tenant-content/imports/post-check', {
query: { jobId },
});
}
export async function loadImportFieldMapping(importType: string) {
return apiRequest<{ item?: ImportFieldMapping }>('/api/tenant-content/imports/field-mapping', {
query: { importType },
});
}
export async function loadImportTemplate(importType: string, format: 'json' | 'csv' = 'json') {
return apiRequest<{ item?: ImportTemplateItem }>('/api/tenant-content/imports/templates', {
query: { importType, format },
});
}
export async function loadMediaAnalyticsSummary(query: {
timeRange?: '7d' | '30d' | '90d';
assetId?: string;
videoId?: string;
userId?: string;
traceId?: string;
limit?: number;
} = {}) {
return apiRequest<MediaAnalyticsSummary>('/api/tenant-content/media-analytics/summary', { query });
}
export async function loadMediaAssetAccessEvents(query: {
timeRange?: '7d' | '30d' | '90d';
assetId?: string;
userId?: string;
accessType?: string;
result?: 'granted' | 'denied';
traceId?: string;
limit?: number;
} = {}) {
return apiRequest<{ scope?: Record<string, unknown>; items?: MediaAssetAccessEvent[] }>('/api/tenant-content/media-analytics/asset-events', {
query: { ...query, limit: query.limit || 100 },
});
}
export async function loadMediaVideoPlayEvents(query: {
timeRange?: '7d' | '30d' | '90d';
videoId?: string;
userId?: string;
accessMode?: 'free' | 'svip' | 'video_quota';
status?: 'issued' | 'started' | 'completed' | 'expired' | 'revoked';
traceId?: string;
limit?: number;
} = {}) {
return apiRequest<{ scope?: Record<string, unknown>; items?: MediaVideoPlayEvent[] }>('/api/tenant-content/media-analytics/video-events', {
query: { ...query, limit: query.limit || 100 },
});
}
export async function previewContentImport(importType: ImportType, body: ImportRequestBody) {
return apiRequest<ImportPreviewResult>(`/api/tenant-content/imports/preview/${importType}`, {
method: 'POST',
body,
});
}
export async function executeContentImport(importType: ImportType, body: ImportRequestBody) {
return apiRequest<{ item?: Record<string, unknown>; preview?: ImportPreviewResult }>(`/api/tenant-content/imports/${importType}`, {
method: 'POST',
body,
});
}
export async function loadCoupons() {
return apiRequest<{ items?: CouponItem[] }>('/api/tenant-admin/coupons');
}
export async function loadCodeBatches() {
return apiRequest<{ items?: CodeBatchItem[] }>('/api/tenant-admin/code-batches');
}
export async function loadActivationCodes(limit = 20) {
return apiRequest<{ items?: Record<string, unknown>[] }>('/api/tenant-admin/activation-codes', { query: { limit } });
}
export async function loadTenantDomains() {
return apiRequest<{ items?: Record<string, unknown>[] }>('/api/tenant-admin/domains');
}
export async function loadPaymentAccounts() {
return apiRequest<{ items?: Record<string, unknown>[] }>('/api/tenant-admin/payment-accounts');
}
export async function loadAuthProviders() {
return apiRequest<{ items?: Record<string, unknown>[] }>('/api/tenant-admin/auth-providers');
}
export async function loadRoleTemplates() {
return apiRequest<{ items?: TenantRoleTemplateItem[] }>('/api/tenant-admin/role-templates');
}
export async function upsertRoleTemplate(input: TenantRoleTemplateInput) {
return apiRequest<{ item?: TenantRoleTemplateItem }>('/api/tenant-admin/role-templates', {
method: 'PUT',
body: input,
});
}
export async function disableRoleTemplate(roleTemplateId: string) {
return apiRequest<{ item?: TenantRoleTemplateItem }>('/api/tenant-admin/role-templates/disable', {
method: 'POST',
body: { roleTemplateId },
});
}
export async function loadTenantMembers(query: { keyword?: string; role?: string; status?: string; limit?: number } = {}) {
return apiRequest<{ items?: TenantMemberItem[] }>('/api/tenant-admin/members', {
query: { ...query, limit: query.limit || 50 },
});
}
export async function upsertTenantMember(input: TenantMemberInput) {
return apiRequest<{ item?: TenantMemberItem }>('/api/tenant-admin/members', {
method: 'PUT',
body: input,
});
}
export async function disableTenantMember(membershipId: string) {
return apiRequest<{ item?: TenantMemberItem }>('/api/tenant-admin/members/disable', {
method: 'POST',
body: { membershipId },
});
}
export async function loadCrmConfig() {
return apiRequest<{ item?: CrmConfigItem | null }>('/api/crm/config');
}
export async function upsertCrmConfig(input: {
enabled?: boolean;
url?: string | null;
secretRef?: string | null;
formName?: string | null;
examType?: string | null;
timeoutSec?: number;
delaySec?: number;
assignmentMode?: 'none' | 'direct' | 'round_robin' | 'referrer';
assignmentPool?: string[];
assignmentConfig?: Record<string, unknown>;
}) {
return apiRequest<{ item?: CrmConfigItem }>('/api/crm/config', {
method: 'PUT',
body: input,
});
}
export async function loadCrmQueue(limit = 20, status?: string) {
return apiRequest<{ items?: CrmQueueItem[] }>('/api/crm/queue', { query: { limit, status } });
}
export async function loadCommissionSettings() {
return apiRequest<{ item?: CommissionSettingsItem }>('/api/commission/settings');
}
export async function updateCommissionSettings(input: {
defaultRate: number;
minSettlementCents?: number;
settlementCycle?: string;
config?: Record<string, unknown>;
}) {
return apiRequest<{ item?: CommissionSettingsItem }>('/api/commission/settings', {
method: 'PUT',
body: input,
});
}
export async function updateMemberCommissionRate(input: {
userId: string;
commissionRate?: number | null;
commissionConfig?: Record<string, unknown>;
}) {
return apiRequest<{ item?: Record<string, unknown> }>('/api/commission/member-rate', {
method: 'PUT',
body: input,
});
}
export async function loadCommissionSummary(query: { startDate?: string; endDate?: string; referrerUserId?: string } = {}) {
return apiRequest<{ item?: CommissionSummaryItem }>('/api/commission/summary', { query });
}
export async function loadCommissionOrders(query: { startDate?: string; endDate?: string; referrerUserId?: string; limit?: number } = {}) {
return apiRequest<{ items?: CommissionOrderItem[]; scope?: Record<string, unknown> }>('/api/commission/orders', {
query: { ...query, limit: query.limit || 50 },
});
}
export async function loadCommissionSettlements(query: { status?: string; referrerUserId?: string; limit?: number } = {}) {
return apiRequest<{ items?: CommissionSettlementItem[] }>('/api/commission/settlements', {
query: { ...query, limit: query.limit || 50 },
});
}
export async function generateCommissionSettlement(input: {
referrerUserId: string;
startDate: string;
endDate: string;
status?: string;
remark?: string | null;
}) {
return apiRequest<{ item?: CommissionSettlementItem & { items?: CommissionOrderItem[] } }>('/api/commission/settlements/generate', {
method: 'POST',
body: input,
});
}
export async function updateCommissionSettlementStatus(input: {
settlementId: string;
status: string;
paymentMethod?: string | null;
paymentAccount?: string | null;
remark?: string | null;
metadata?: Record<string, unknown>;
}) {
return apiRequest<{ item?: CommissionSettlementItem }>('/api/commission/settlements/status', {
method: 'POST',
body: input,
});
}