feat: add carrier-aware signature retirement alerts
This commit is contained in:
@@ -81,9 +81,9 @@ export const adminChannelsReportsApi = {
|
||||
listReportTasks: (query: { tenantId?: string; status?: string; channelId?: string; reportType?: 'signature' | 'drainage' } = {}) => request<ReportTask[]>(withQuery('/admin/report-tasks', query)),
|
||||
listReportTasksPage: (query: { tenantId?: string; status?: string; channelId?: string; reportType?: 'signature' | 'drainage'; keyword?: string; createdAtFrom?: string; createdAtTo?: string; page: number; pageSize: number }) =>
|
||||
request<PagedResult<ReportTask>>(withQuery('/admin/report-tasks', query)),
|
||||
createReportTask: (body: { tenantId: string; signatureId: string; channelId: string; reportType?: 'signature' | 'drainage'; drainageItemId?: string; createdById?: string }) =>
|
||||
createReportTask: (body: { tenantId: string; signatureId: string; channelId: string; carrier?: 'mobile' | 'unicom' | 'telecom'; reportType?: 'signature' | 'drainage'; drainageItemId?: string; createdById?: string }) =>
|
||||
request<ReportTask>('/admin/report-tasks/generate', { method: 'POST', body: JSON.stringify(body) }),
|
||||
changeReportTaskStatuses: (body: { items: Array<{ signatureId: string; channelId: string; status: string; reportType?: 'signature' | 'drainage'; drainageItemId?: string }>; reason?: string; operatorId?: string; sourceEntry?: 'enterprise_signature' | 'report_task' | 'channel_report' }) =>
|
||||
changeReportTaskStatuses: (body: { items: Array<{ signatureId: string; channelId: string; carrier?: 'mobile' | 'unicom' | 'telecom'; status: string; reportType?: 'signature' | 'drainage'; drainageItemId?: string }>; reason?: string; operatorId?: string; sourceEntry?: 'enterprise_signature' | 'report_task' | 'channel_report' }) =>
|
||||
request<Array<{ signatureId: string; reportStatus: string; carrierReportSummary: Record<string, { status: string; approved: number; total: number }> }>>('/admin/report-tasks/status-change', { method: 'POST', body: JSON.stringify(body) }),
|
||||
createReportExport: (id: string, body: { fileObjectId?: string; fileName: string; rowCount?: number }) =>
|
||||
request<Record<string, unknown>>(`/admin/report-tasks/${id}/export`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { request, withQuery } from '../core/httpClient';
|
||||
import type {
|
||||
LegacySignatureReportTask,
|
||||
PagedResult,
|
||||
SignatureRetirementHeatmapItem,
|
||||
SignatureRetirementHeatmapDimension,
|
||||
SignatureRetirementMessage,
|
||||
SignatureRetirementRule,
|
||||
SignatureRetirementRuleType,
|
||||
SignatureRetirementSuppression,
|
||||
SignatureRetirementWebhook,
|
||||
UnreportedSignatureItem,
|
||||
} from '../types';
|
||||
|
||||
export const adminSignatureRetirementApi = {
|
||||
getSignatureRetirementConfiguration: () => request<{ rules: SignatureRetirementRule[]; webhooks: SignatureRetirementWebhook[] }>('/admin/signature-retirement/configuration'),
|
||||
saveSignatureRetirementRule: (body: {
|
||||
ruleType: SignatureRetirementRuleType; targetId?: string; enabled: boolean;
|
||||
mobileWindowDays: number; mobileThreshold: number; unicomWindowDays: number; unicomThreshold: number;
|
||||
telecomWindowDays: number; telecomThreshold: number; messageTemplate?: string;
|
||||
}) => request<SignatureRetirementRule>('/admin/signature-retirement/rules', { method: 'PUT', body: JSON.stringify(body) }),
|
||||
createSignatureRetirementWebhook: (body: { name: string; platform: 'wecom' | 'feishu'; url: string }) =>
|
||||
request<SignatureRetirementWebhook>('/admin/signature-retirement/webhooks', { method: 'POST', body: JSON.stringify(body) }),
|
||||
deleteSignatureRetirementWebhook: (id: string) => request<SignatureRetirementWebhook>(`/admin/signature-retirement/webhooks/${id}`, { method: 'DELETE' }),
|
||||
listSignatureRetirementMessages: (query: { dateFrom?: string; dateTo?: string; dimensionType?: string; tenantId?: string; applicationId?: string; signatureKeyword?: string; channelId?: string; page?: number; pageSize?: number } = {}) =>
|
||||
request<PagedResult<SignatureRetirementMessage>>(withQuery('/admin/signature-retirement/messages', query)),
|
||||
getSignatureRetirementUnreadCount: () => request<{ count: number }>('/admin/signature-retirement/unread-count'),
|
||||
readSignatureRetirementMessage: (id: string) => request<SignatureRetirementMessage>(`/admin/signature-retirement/messages/${id}/read`, { method: 'POST' }),
|
||||
readAllSignatureRetirementMessagesToday: () => request<{ count: number }>('/admin/signature-retirement/messages/read-all-today', { method: 'POST' }),
|
||||
suppressSignatureRetirementMessage: (id: string, body: { mode: 'temporary' | 'permanent'; days?: number; reason?: string }) =>
|
||||
request<SignatureRetirementSuppression>(`/admin/signature-retirement/messages/${id}/suppress`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
listSignatureRetirementSuppressions: () => request<SignatureRetirementSuppression[]>('/admin/signature-retirement/suppressions'),
|
||||
cancelSignatureRetirementSuppression: (id: string, reason: string) =>
|
||||
request<SignatureRetirementSuppression>(`/admin/signature-retirement/suppressions/${id}/cancel`, { method: 'POST', body: JSON.stringify({ reason }) }),
|
||||
getSignatureRetirementHeatmap: (date?: string) => request<{ date: string; dimensions: SignatureRetirementHeatmapDimension[]; items: SignatureRetirementHeatmapItem[] }>(withQuery('/admin/signature-retirement/heatmap', { date })),
|
||||
getUnreportedSignatures: (query: { date?: string; keyword?: string; page?: number; pageSize?: number } = {}) =>
|
||||
request<PagedResult<UnreportedSignatureItem> & { date: string }>(withQuery('/admin/signature-retirement/unreported-signatures', query)),
|
||||
listLegacySignatureReportTasks: () => request<LegacySignatureReportTask[]>('/admin/signature-retirement/legacy-report-tasks'),
|
||||
confirmLegacySignatureReportTask: (id: string, body: { results: Array<{ carrier: 'mobile' | 'unicom' | 'telecom'; status: string; approvedAt?: string }>; reason?: string }) =>
|
||||
request<{ legacyTaskId: string }>(`/admin/signature-retirement/legacy-report-tasks/${id}/confirm`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
};
|
||||
@@ -9,6 +9,7 @@ import { adminChannelsReportsApi } from './admin/channels-reports.api';
|
||||
import { adminOperationsApi } from './admin/operations.api';
|
||||
import { adminGovernanceApi } from './admin/governance.api';
|
||||
import { adminFilesApi } from './admin/files.api';
|
||||
import { adminSignatureRetirementApi } from './admin/signature-retirement.api';
|
||||
|
||||
export const adminApi = {
|
||||
...adminIdentityApi,
|
||||
@@ -16,4 +17,5 @@ export const adminApi = {
|
||||
...adminOperationsApi,
|
||||
...adminGovernanceApi,
|
||||
...adminFilesApi,
|
||||
...adminSignatureRetirementApi,
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ export type AdminChannel = {
|
||||
code: string;
|
||||
name: string;
|
||||
carrier?: string | null;
|
||||
carriers?: Array<'mobile' | 'unicom' | 'telecom'>;
|
||||
sendRegion?: string | null;
|
||||
gatewayHost: string;
|
||||
gatewayPort: number;
|
||||
@@ -261,6 +262,9 @@ export type ReportTask = DictionaryItem & {
|
||||
tenantId: string;
|
||||
signatureId: string;
|
||||
channelId: string;
|
||||
carrier?: 'mobile' | 'unicom' | 'telecom' | null;
|
||||
approvedAt?: string | null;
|
||||
approvalScope?: 'carrier_specific' | 'legacy_channel';
|
||||
reportType?: 'signature' | 'drainage';
|
||||
drainageItemId?: string | null;
|
||||
status: string;
|
||||
@@ -273,7 +277,7 @@ export type ReportTask = DictionaryItem & {
|
||||
application?: { id: string; name: string } | null;
|
||||
};
|
||||
drainageInfo?: SmsDrainageInfo | null;
|
||||
channel?: { id: string; name: string; code: string };
|
||||
channel?: { id: string; name: string; code: string; carrier?: string | null; carriers?: Array<'mobile' | 'unicom' | 'telecom'> };
|
||||
reason?: string | null;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
|
||||
@@ -238,7 +238,7 @@ export type ClientSmsSignature = {
|
||||
application?: ClientSmsApplication | null;
|
||||
reportStatus?: string;
|
||||
reportTasks?: Array<ReportTask & { channel?: AdminChannel }>;
|
||||
reportTargets?: Array<{ channel: AdminChannel; channelId: string; status: string; taskId?: string }>;
|
||||
reportTargets?: Array<{ channel: AdminChannel; channelId: string; carrier: 'mobile' | 'unicom' | 'telecom'; status: string; taskId?: string; approvedAt?: string | null; approvalScope?: 'carrier_specific' | 'legacy_channel' }>;
|
||||
carrierReportSummary?: Record<'mobile' | 'unicom' | 'telecom', { status: string; approved: number; total: number }>;
|
||||
drainageReportTargets?: Record<string, Array<{ channel: AdminChannel; channelId: string; status: string; taskId?: string }>>;
|
||||
drainageCarrierReportSummary?: Record<string, Record<'mobile' | 'unicom' | 'telecom', { status: string; approved: number; total: number }>>;
|
||||
|
||||
@@ -3,3 +3,4 @@ export * from './identity-config';
|
||||
export * from './channels-reports';
|
||||
export * from './operations';
|
||||
export * from './governance';
|
||||
export * from './signature-retirement';
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import type { AdminChannel, ReportTask } from './channels-reports';
|
||||
|
||||
export type SignatureRetirementRuleType = 'enterprise_global' | 'enterprise_application' | 'channel_global' | 'channel';
|
||||
export type SignatureRetirementCarrier = 'mobile' | 'unicom' | 'telecom';
|
||||
|
||||
export type SignatureRetirementRule = {
|
||||
id: string;
|
||||
ruleType: SignatureRetirementRuleType;
|
||||
targetId?: string | null;
|
||||
targetKey: string;
|
||||
enabled: boolean;
|
||||
mobileWindowDays: number;
|
||||
mobileThreshold: number;
|
||||
unicomWindowDays: number;
|
||||
unicomThreshold: number;
|
||||
telecomWindowDays: number;
|
||||
telecomThreshold: number;
|
||||
messageTemplate?: string | null;
|
||||
version: number;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type SignatureRetirementWebhook = {
|
||||
id: string;
|
||||
name: string;
|
||||
platform: 'wecom' | 'feishu';
|
||||
urlMasked: string;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export type SignatureRetirementDetection = {
|
||||
id: string;
|
||||
detectionDate: string;
|
||||
dimensionType: 'enterprise' | 'channel';
|
||||
tenantId: string;
|
||||
applicationId?: string | null;
|
||||
signatureId: string;
|
||||
channelId?: string | null;
|
||||
carrier: SignatureRetirementCarrier;
|
||||
windowDays: number;
|
||||
threshold: number;
|
||||
submittedAttempts: number;
|
||||
acceptedBusinessCount: number;
|
||||
deliveredBusinessCount: number;
|
||||
approvedAt: string;
|
||||
status: 'alert' | 'healthy';
|
||||
suppressed: boolean;
|
||||
};
|
||||
|
||||
export type SignatureRetirementMessage = {
|
||||
id: string;
|
||||
detectionId: string;
|
||||
cycleId: string;
|
||||
tenantId: string;
|
||||
title: string;
|
||||
content: string;
|
||||
isRead: boolean;
|
||||
suppressed: boolean;
|
||||
createdAt: string;
|
||||
detection?: SignatureRetirementDetection;
|
||||
signatureName?: string;
|
||||
channelName?: string | null;
|
||||
tenantName?: string;
|
||||
applicationName?: string;
|
||||
};
|
||||
|
||||
export type SignatureRetirementSuppression = {
|
||||
id: string;
|
||||
dimensionType: 'enterprise' | 'channel';
|
||||
signatureId: string;
|
||||
channelId?: string | null;
|
||||
carrier: SignatureRetirementCarrier;
|
||||
mode: 'temporary' | 'permanent';
|
||||
muteUntil?: string | null;
|
||||
reason?: string | null;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type SignatureRetirementHeatmapItem = SignatureRetirementDetection & {
|
||||
signatureName?: string;
|
||||
channelName?: string | null;
|
||||
tenantName?: string;
|
||||
};
|
||||
|
||||
export type SignatureRetirementHeatmapDimension = {
|
||||
dimensionType: 'enterprise' | 'channel';
|
||||
signatureId: string;
|
||||
channelId: string | null;
|
||||
carrier: SignatureRetirementCarrier;
|
||||
approvedAt: string;
|
||||
signatureName: string;
|
||||
channelName: string | null;
|
||||
tenantName: string;
|
||||
applicationName?: string | null;
|
||||
};
|
||||
|
||||
export type UnreportedSignatureItem = {
|
||||
signatureId: string;
|
||||
signatureName: string;
|
||||
tenantId: string;
|
||||
tenantName: string;
|
||||
applicationId?: string | null;
|
||||
applicationName?: string | null;
|
||||
messageCount: number;
|
||||
};
|
||||
|
||||
export type LegacySignatureReportTask = ReportTask & { channel: AdminChannel };
|
||||
Reference in New Issue
Block a user