Files
lislgosms/src/api/admin/governance.api.ts
T

215 lines
19 KiB
TypeScript

import { request, requestBlob, requestForm, withQuery } from '../core/httpClient';
import type { AdministrativeRegion, AuditRecord, ClientSmsSignature, ClientSmsTemplate, CommonReportField, DictionaryItem, DrainageDetectionResult, DrainageDetectionRule, EnterpriseCertification, ManualRechargePreflight, ManualRechargeResult, PagedResult, PhoneFrequencyHit, PhoneFrequencyWhitelistItem, RechargeOrder, ReviewDecisionResult, ReviewPreflight, RiskReviewTask, RiskRuleItem, RiskTaskMessagePage, SmsDrainageInfo, SmsTemplateAudit, TenantAccount } from '../types';
// Review, risk and billing mutations keep their original URLs, payloads and
// response types behind one governance boundary.
export const adminGovernanceApi = {
listAdministrativeRegions: () => request<AdministrativeRegion[]>('/admin/dictionaries/administrative-regions'),
listAccounts: () => request<TenantAccount[]>('/admin/billing/accounts'),
updateCreditLimit: (tenantId: string, body: { creditCents: number; operatorId?: string; remark?: string }) =>
request<TenantAccount>(`/admin/billing/accounts/${tenantId}/credit-limit`, { method: 'POST', body: JSON.stringify(body) }),
listManualRecharges: (tenantId?: string) => request<RechargeOrder[]>(withQuery('/admin/billing/manual-recharges', { tenantId })),
listManualRechargesPage: (query: { enterpriseKeyword?: string; createdAtFrom?: string; createdAtTo?: string; page: number; pageSize: number }) =>
request<PagedResult<RechargeOrder>>(withQuery('/admin/billing/manual-recharges', query)),
preflightManualRecharge: (body: { tenantId: string; amountCents: number }) =>
request<ManualRechargePreflight>('/admin/billing/manual-recharges/preflight', { method: 'POST', body: JSON.stringify(body) }),
createManualRecharge: (body: { tenantId: string; amountCents: number; expectedAccountUpdatedAt: string; idempotencyKey: string; remark?: string }) =>
request<ManualRechargeResult>('/admin/billing/manual-recharges', { method: 'POST', body: JSON.stringify(body) }),
listTemplateAudits: (query: { keyword?: string; status?: string; submittedAtFrom?: string; submittedAtTo?: string }) => {
const params = new URLSearchParams();
if (query.keyword) params.set('keyword', query.keyword);
if (query.status && query.status !== 'all') params.set('status', query.status);
if (query.submittedAtFrom) params.set('submittedAtFrom', query.submittedAtFrom);
if (query.submittedAtTo) params.set('submittedAtTo', query.submittedAtTo);
const suffix = params.toString() ? `?${params}` : '';
return request<SmsTemplateAudit[]>(`/admin/enterprise-templates${suffix}`);
},
approveTemplate: (id: string) => request<SmsTemplateAudit>(`/admin/templates/${id}/approve`, { method: 'POST', body: JSON.stringify({}) }),
rejectTemplate: (id: string, reason = '运营审核驳回') => request<SmsTemplateAudit>(`/admin/templates/${id}/reject`, {
method: 'POST',
body: JSON.stringify({ reason }),
}),
approveSignature: (id: string) => request<ClientSmsSignature>(`/admin/signatures/${id}/approve`, { method: 'POST', body: JSON.stringify({}) }),
rejectSignature: (id: string, reason = '运营审核驳回') => request<ClientSmsSignature>(`/admin/signatures/${id}/reject`, {
method: 'POST',
body: JSON.stringify({ reason }),
}),
getReviewPreflight: (type: 'signature' | 'template', id: string) =>
request<ReviewPreflight>(`/admin/reviews/${type}/${id}/preflight`),
submitReviewDecision: (type: 'signature' | 'template', id: string, body: { decision: 'approve' | 'reject'; expectedUpdatedAt: string; idempotencyKey: string; reason?: string }) =>
request<ReviewDecisionResult>(`/admin/reviews/${type}/${id}/decision`, { method: 'POST', body: JSON.stringify(body) }),
listEnterpriseSignatures: (query: { tenantId?: string; keyword?: string; status?: string; enterpriseKeyword?: string; applicationKeyword?: string; signatureKeyword?: string; drainageKeyword?: string; submittedAtFrom?: string; submittedAtTo?: string } = {}) =>
request<ClientSmsSignature[]>(withQuery('/admin/enterprise-signatures', query)),
listEnterpriseSignaturesPage: (query: { tenantId?: string; keyword?: string; status?: string; enterpriseKeyword?: string; applicationKeyword?: string; signatureKeyword?: string; drainageKeyword?: string; signatureSort?: 'asc' | 'desc'; page: number; pageSize: number }) =>
request<PagedResult<ClientSmsSignature>>(withQuery('/admin/enterprise-signatures', query)),
listEnterpriseSignatureOptions: (query: { tenantId?: string } = {}) =>
request<ClientSmsSignature[]>(withQuery('/admin/enterprise-signature-options', query)),
getEnterpriseSignature: (id: string) => request<ClientSmsSignature>(`/admin/enterprise-signatures/${id}`),
getEnterpriseSignatureReportTargets: (id: string) => request<NonNullable<ClientSmsSignature['reportTargets']>>(`/admin/enterprise-signatures/${id}/report-targets`),
getDrainageInfoReportTargets: (id: string) => request<NonNullable<ClientSmsSignature['drainageReportTargets']>[string]>(`/admin/drainage-infos/${id}/report-targets`),
createEnterpriseSignature: (body: { tenantId: string; applicationId?: string; name: string; purpose?: string; drainageInfo?: Record<string, unknown> }) =>
request<ClientSmsSignature>('/admin/enterprise-signatures', { method: 'POST', body: JSON.stringify(body) }),
updateEnterpriseSignature: (id: string, body: { applicationId?: string | null; name?: string; purpose?: string; auditStatus?: string; drainageInfo?: Record<string, unknown> }) =>
request<ClientSmsSignature>(`/admin/enterprise-signatures/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
changeEnterpriseSignatureStatus: (id: string, status: string, reason?: string) =>
request<ClientSmsSignature>(`/admin/enterprise-signatures/${id}/status`, { method: 'POST', body: JSON.stringify({ status, reason }) }),
listDrainageInfos: (query: { tenantId?: string; signatureId?: string; keyword?: string; status?: string; submittedAtFrom?: string; submittedAtTo?: string } = {}) =>
request<SmsDrainageInfo[]>(withQuery('/admin/drainage-infos', query)),
listAuditRecords: (query: { targetType?: string; targetId?: string } = {}) =>
request<AuditRecord[]>(withQuery('/admin/audit-records', query)),
createDrainageInfo: (signatureId: string, body: { url: string; remark?: string; reportValues?: Record<string, unknown> }) =>
request<SmsDrainageInfo>(`/admin/enterprise-signatures/${signatureId}/drainage-infos`, { method: 'POST', body: JSON.stringify(body) }),
updateDrainageInfo: (id: string, body: { url?: string; remark?: string; reportValues?: Record<string, unknown> }) =>
request<SmsDrainageInfo>(`/admin/drainage-infos/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
approveDrainageInfo: (id: string) =>
request<SmsDrainageInfo>(`/admin/drainage-infos/${id}/approve`, { method: 'POST', body: JSON.stringify({}) }),
rejectDrainageInfo: (id: string, reason: string) =>
request<SmsDrainageInfo>(`/admin/drainage-infos/${id}/reject`, { method: 'POST', body: JSON.stringify({ reason }) }),
changeDrainageInfoStatus: (id: string, status: string, reason?: string) =>
request<SmsDrainageInfo>(`/admin/drainage-infos/${id}/status`, { method: 'POST', body: JSON.stringify({ status, reason }) }),
listEnterpriseTemplates: (query: { tenantId?: string; keyword?: string; status?: string; enterpriseKeyword?: string; applicationKeyword?: string; nameKeyword?: string; contentKeyword?: string } = {}) =>
request<ClientSmsTemplate[]>(withQuery('/admin/enterprise-templates', query)),
listEnterpriseTemplatesPage: (query: { tenantId?: string; keyword?: string; status?: string; enterpriseKeyword?: string; applicationKeyword?: string; nameKeyword?: string; contentKeyword?: string; page: number; pageSize: number }) =>
request<PagedResult<ClientSmsTemplate>>(withQuery('/admin/enterprise-templates', query)),
createEnterpriseTemplate: (body: { tenantId: string; applicationId: string; signatureId?: string; name: string; content: string; category?: string; variables?: Array<{ name: string; example?: string; required?: boolean }> }) =>
request<ClientSmsTemplate>('/admin/enterprise-templates', { method: 'POST', body: JSON.stringify(body) }),
updateEnterpriseTemplate: (id: string, body: { applicationId?: string; signatureId?: string | null; name?: string; content?: string; category?: string; auditStatus?: string; variables?: Array<{ name: string; example?: string; required?: boolean }> }) =>
request<ClientSmsTemplate>(`/admin/enterprise-templates/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
changeEnterpriseTemplateStatus: (id: string, status: string, reason?: string) =>
request<ClientSmsTemplate>(`/admin/enterprise-templates/${id}/status`, { method: 'POST', body: JSON.stringify({ status, reason }) }),
listEnterpriseCertifications: (query: { keyword?: string; status?: string; submittedAtFrom?: string; submittedAtTo?: string }) => {
const params = new URLSearchParams();
if (query.keyword) params.set('keyword', query.keyword);
if (query.status && query.status !== 'all') params.set('status', query.status);
if (query.submittedAtFrom) params.set('submittedAtFrom', query.submittedAtFrom);
if (query.submittedAtTo) params.set('submittedAtTo', query.submittedAtTo);
const suffix = params.toString() ? `?${params}` : '';
return request<EnterpriseCertification[]>(`/admin/enterprise-certifications${suffix}`);
},
getEnterpriseCertification: (id: string) => request<EnterpriseCertification>(`/admin/enterprise-certifications/${id}`),
approveEnterpriseCertification: (id: string) => request<EnterpriseCertification>(`/admin/enterprise-certifications/${id}/approve`, {
method: 'POST',
body: JSON.stringify({}),
}),
rejectEnterpriseCertification: (id: string, reason = '运营审核驳回') => request<EnterpriseCertification>(`/admin/enterprise-certifications/${id}/reject`, {
method: 'POST',
body: JSON.stringify({ reason }),
}),
listRiskReviewTasks: (query: { tenantId?: string; status?: string; submittedAtFrom?: string; submittedAtTo?: string } = {}) => request<RiskReviewTask[]>(withQuery('/admin/risk-review/tasks', query)),
listRiskRules: (applicationId?: string) =>
request<RiskRuleItem[]>(withQuery('/admin/risk-review/rules', { applicationId })),
createRiskRule: (body: {
applicationId?: string;
code: RiskRuleItem['code'];
thresholdValue: number;
action: RiskRuleItem['action'];
status: RiskRuleItem['status'];
priority?: number;
config?: RiskRuleItem['config'];
}) => request<RiskRuleItem>('/admin/risk-review/rules', { method: 'POST', body: JSON.stringify(body) }),
updateRiskRule: (id: string, body: {
thresholdValue?: number;
action?: RiskRuleItem['action'];
status?: RiskRuleItem['status'];
priority?: number;
config?: RiskRuleItem['config'];
}) => request<RiskRuleItem>(`/admin/risk-review/rules/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
listPhoneFrequencyHits: (query: {
tenantId?: string;
applicationId?: string;
phoneNumber?: string;
status?: 'active' | 'expired' | 'released';
createdAtFrom?: string;
createdAtTo?: string;
page?: number;
pageSize?: number;
} = {}) => request<PagedResult<PhoneFrequencyHit>>(withQuery('/admin/risk-review/phone-frequency-hits', query)),
releasePhoneFrequencyHit: (id: string, reason: string) =>
request<PhoneFrequencyHit>(`/admin/risk-review/phone-frequency-hits/${id}/release`, {
method: 'POST',
body: JSON.stringify({ reason }),
}),
listPhoneFrequencyWhitelist: (query: {
phoneNumber?: string;
keyword?: string;
status?: 'active' | 'inactive' | 'deleted';
updatedAtFrom?: string;
updatedAtTo?: string;
page?: number;
pageSize?: number;
} = {}) => request<PagedResult<PhoneFrequencyWhitelistItem>>(withQuery('/admin/risk-review/phone-frequency-whitelist', query)),
createPhoneFrequencyWhitelist: (body: {
phoneNumber: string;
reason: string;
remark?: string;
status?: 'active' | 'inactive';
}) => request<PhoneFrequencyWhitelistItem>('/admin/risk-review/phone-frequency-whitelist', {
method: 'POST',
body: JSON.stringify(body),
}),
updatePhoneFrequencyWhitelist: (id: string, body: {
phoneNumber?: string;
reason?: string;
remark?: string;
status?: 'active' | 'inactive';
}) => request<PhoneFrequencyWhitelistItem>(`/admin/risk-review/phone-frequency-whitelist/${id}`, {
method: 'PUT',
body: JSON.stringify(body),
}),
deletePhoneFrequencyWhitelist: (id: string, reason: string) =>
request<PhoneFrequencyWhitelistItem>(`/admin/risk-review/phone-frequency-whitelist/${id}`, {
method: 'DELETE',
body: JSON.stringify({ reason }),
}),
listRiskReviewTaskMessages: (id: string, query: { phone?: string; page?: number; pageSize?: number } = {}) =>
request<RiskTaskMessagePage>(withQuery(`/admin/risk-review/tasks/${id}/messages`, query)),
approveRiskReviewTask: (id: string, reason?: string) =>
request<RiskReviewTask>(`/admin/risk-review/tasks/${id}/approve`, { method: 'POST', body: JSON.stringify({ reason }) }),
rejectRiskReviewTask: (id: string, reason?: string) =>
request<RiskReviewTask>(`/admin/risk-review/tasks/${id}/reject`, { method: 'POST', body: JSON.stringify({ reason }) }),
rejectRiskReviewTasks: (ids: string[], reason: string) =>
request<RiskReviewTask[]>('/admin/risk-review/tasks/batch/reject', { method: 'POST', body: JSON.stringify({ ids, reason }) }),
listSensitiveWords: (query: { keyword?: string; status?: string } = {}) => request<DictionaryItem[]>(withQuery('/admin/dictionaries/sensitive-words', query)),
createSensitiveWord: (body: { word: string; level?: string; status?: string }) =>
request<DictionaryItem>('/admin/dictionaries/sensitive-words', { method: 'POST', body: JSON.stringify(body) }),
deleteSensitiveWord: (id: string) => request<DictionaryItem>(`/admin/dictionaries/sensitive-words/${id}`, { method: 'DELETE' }),
listGlobalBlacklist: (query: { keyword?: string; status?: string } = {}) => request<DictionaryItem[]>(withQuery('/admin/dictionaries/blacklists/global', query)),
createGlobalBlacklist: (body: { phoneNumber: string; reason?: string; status?: string; operatorId?: string }) =>
request<DictionaryItem>('/admin/dictionaries/blacklists/global', { method: 'POST', body: JSON.stringify(body) }),
deleteGlobalBlacklist: (id: string) => request<DictionaryItem>(`/admin/dictionaries/blacklists/global/${id}`, { method: 'DELETE' }),
listEnterpriseBlacklist: (query: { tenantId?: string; applicationId?: string; keyword?: string; status?: string; enterpriseKeyword?: string; applicationKeyword?: string; phoneNumber?: string; reasonKeyword?: string } = {}) => request<DictionaryItem[]>(withQuery('/admin/dictionaries/blacklists/enterprise', query)),
createEnterpriseBlacklist: (body: { tenantId: string; applicationId: string; phoneNumber: string; reason?: string; status?: string; operatorId?: string }) =>
request<DictionaryItem>('/admin/dictionaries/blacklists/enterprise', { method: 'POST', body: JSON.stringify(body) }),
deleteEnterpriseBlacklist: (id: string) => request<DictionaryItem>(`/admin/dictionaries/blacklists/enterprise/${id}`, { method: 'DELETE' }),
listPhoneSegments: (query: { keyword?: string; page?: number; pageSize?: number } = {}) =>
request<{ items: DictionaryItem[]; total: number; page: number; pageSize: number }>(withQuery('/admin/dictionaries/phone-segments', query)),
createPhoneSegment: (body: { prefix: string; carrier: string; province?: string; city?: string }) =>
request<DictionaryItem>('/admin/dictionaries/phone-segments', { method: 'POST', body: JSON.stringify(body) }),
deletePhoneSegment: (id: string) => request<DictionaryItem>(`/admin/dictionaries/phone-segments/${id}`, { method: 'DELETE' }),
listPhoneCarrierRules: (query: { keyword?: string; page?: number; pageSize?: number } = {}) =>
request<{ items: DictionaryItem[]; total: number; page: number; pageSize: number }>(withQuery('/admin/dictionaries/phone-carrier-rules', query)),
createPhoneCarrierRule: (body: { carrier: string; pattern: string; priority?: number; status?: string; remark?: string }) =>
request<DictionaryItem>('/admin/dictionaries/phone-carrier-rules', { method: 'POST', body: JSON.stringify(body) }),
deletePhoneCarrierRule: (id: string) => request<DictionaryItem>(`/admin/dictionaries/phone-carrier-rules/${id}`, { method: 'DELETE' }),
listDrainageFields: () => request<DictionaryItem[]>('/admin/dictionaries/drainage-fields'),
createDrainageField: (body: { code: string; name: string; fieldType: 'string' | 'image' | 'file'; required?: boolean; status?: string; description?: string }) =>
request<DictionaryItem>('/admin/dictionaries/drainage-fields', { method: 'POST', body: JSON.stringify(body) }),
deleteDrainageField: (id: string) => request<DictionaryItem>(`/admin/dictionaries/drainage-fields/${id}`, { method: 'DELETE' }),
listDrainageDetectionRules: (query: { keyword?: string; status?: string } = {}) =>
request<DrainageDetectionRule[]>(withQuery('/admin/dictionaries/drainage-detection-rules', query)),
createDrainageDetectionRule: (body: Omit<DrainageDetectionRule, 'id' | 'version' | 'createdAt' | 'updatedAt'>) =>
request<DrainageDetectionRule>('/admin/dictionaries/drainage-detection-rules', { method: 'POST', body: JSON.stringify(body) }),
updateDrainageDetectionRule: (id: string, body: Omit<DrainageDetectionRule, 'id' | 'version' | 'createdAt' | 'updatedAt'>) =>
request<DrainageDetectionRule>(`/admin/dictionaries/drainage-detection-rules/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
changeDrainageDetectionRuleStatus: (id: string, status: 'active' | 'inactive') =>
request<DrainageDetectionRule>(`/admin/dictionaries/drainage-detection-rules/${id}/status`, { method: 'POST', body: JSON.stringify({ status }) }),
testDrainageDetectionRule: (body: { content: string; rule?: Omit<DrainageDetectionRule, 'id' | 'version' | 'createdAt' | 'updatedAt'> }) =>
request<DrainageDetectionResult>('/admin/dictionaries/drainage-detection-rules/test', { method: 'POST', body: JSON.stringify(body) }),
listCommonReportFields: () => request<CommonReportField[]>('/admin/dictionaries/common-report-fields'),
createCommonReportField: (body: { drainageFieldId: string; reportType: 'signature' | 'drainage'; required: boolean; sortOrder?: number }) =>
request<CommonReportField>('/admin/dictionaries/common-report-fields', { method: 'POST', body: JSON.stringify(body) }),
deleteCommonReportField: (id: string) => request<CommonReportField>(`/admin/dictionaries/common-report-fields/${id}`, { method: 'DELETE' }),
updateCommonReportField: (id: string, body: { drainageFieldId: string; reportType: 'signature' | 'drainage'; required: boolean }) =>
request<CommonReportField>(`/admin/dictionaries/common-report-fields/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
};