feat: add phone frequency controls and modularize codebase
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
import { request, requestBlob, requestForm, withQuery } from '../core/httpClient';
|
||||
import type { AuditRecord, ClientSmsSignature, ClientSmsTemplate, CommonReportField, DictionaryItem, 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 = {
|
||||
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 }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (query.keyword) params.set('keyword', query.keyword);
|
||||
if (query.status && query.status !== 'all') params.set('status', query.status);
|
||||
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 } = {}) =>
|
||||
request<ClientSmsSignature[]>(withQuery('/admin/enterprise-signatures', query)),
|
||||
listEnterpriseSignaturesPage: (query: { tenantId?: string; keyword?: string; status?: string; enterpriseKeyword?: string; applicationKeyword?: string; signatureKeyword?: string; drainageKeyword?: string; page: number; pageSize: number }) =>
|
||||
request<PagedResult<ClientSmsSignature>>(withQuery('/admin/enterprise-signatures', query)),
|
||||
listEnterpriseSignatureOptions: (query: { tenantId?: string } = {}) =>
|
||||
request<ClientSmsSignature[]>(withQuery('/admin/enterprise-signature-options', query)),
|
||||
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 } = {}) =>
|
||||
request<SmsDrainageInfo[]>(withQuery('/admin/drainage-infos', query)),
|
||||
listAuditRecords: (query: { targetType?: string; targetId?: string } = {}) =>
|
||||
request<AuditRecord[]>(withQuery('/admin/audit-records', query)),
|
||||
createDrainageInfo: (signatureId: string, body: { siteName: string; 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: { siteName?: string; 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 }) => {
|
||||
const params = new URLSearchParams();
|
||||
if (query.keyword) params.set('keyword', query.keyword);
|
||||
if (query.status && query.status !== 'all') params.set('status', query.status);
|
||||
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 } = {}) => 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' }),
|
||||
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' }),
|
||||
};
|
||||
Reference in New Issue
Block a user