release: prepare RealeseV2.3

This commit is contained in:
hectorzhao
2026-08-06 10:48:36 +08:00
parent 57b58f1c40
commit 8ad8e61793
37 changed files with 997 additions and 64 deletions
+4 -1
View File
@@ -1,9 +1,10 @@
import { request, requestBlob, requestForm, withQuery } from '../core/httpClient';
import type { BatchRequeueResponse, BatchTaskMessagePage, DailyProfitReport, DailyQualityReport, DailyReconciliationReport, DashboardResponse, DownstreamDeliveryDashboard, DownstreamDeliveryRecord, DownstreamRecoveryStatusExportQuery, DownstreamRecoveryStatusResponse, GatewayDownstreamRecoveryStatus, GatewaySubmitException, GatewaySubmitExceptionResponse, OperationLogResponse, PagedResponse, PagedResult, ProtocolInteractionLogResponse, SendQualityResponse, SignatureChannelQualityResponse, SmsBatchTask, SmsMessageRecord, SmsMessageSegmentAudit, SmsUplinkMessage, SystemLogExportResult } from '../types';
import type { BatchRequeueResponse, BatchTaskMessagePage, DailyProfitReport, DailyQualityReport, DailyReconciliationReport, DashboardResponse, DownstreamDeliveryDashboard, DownstreamDeliveryRecord, DownstreamRecoveryStatusExportQuery, DownstreamRecoveryStatusResponse, GatewayDownstreamRecoveryStatus, GatewaySubmitException, GatewaySubmitExceptionResponse, OperationLogResponse, PagedResponse, PagedResult, PendingAuditCounts, ProtocolInteractionLogResponse, ReceiptAnomalyResponse, SendQualityResponse, SignatureChannelQualityResponse, SmsBatchTask, SmsMessageRecord, SmsMessageSegmentAudit, SmsUplinkMessage, SystemLogExportResult } from '../types';
// Read-heavy operations endpoints are isolated from configuration mutations.
export const adminOperationsApi = {
getDashboard: (tenantId?: string) => request<DashboardResponse>(withQuery('/admin/operations/dashboard/statistics', { tenantId })),
getPendingAudits: (tenantId?: string) => request<PendingAuditCounts>(withQuery('/admin/operations/pending-audits', { tenantId })),
getSendQuality: (date?: string) => request<SendQualityResponse>(withQuery('/admin/operations/send-quality', { date })),
getSignatureQuality: (query: { date?: string; keyword?: string; page?: number; pageSize?: number } = {}) =>
request<SignatureChannelQualityResponse>(withQuery('/admin/operations/signature-quality', query)),
@@ -52,6 +53,8 @@ export const adminOperationsApi = {
request<GatewaySubmitExceptionResponse>(withQuery('/admin/operations/gateway-submit-dead-letters', query)),
requeueGatewaySubmitException: (id: string, body: { confirmedNotSubmitted: boolean; reason: string }) =>
request<GatewaySubmitException>(`/admin/operations/gateway-submit-dead-letters/${id}/requeue`, { method: 'POST', body: JSON.stringify(body) }),
listReceiptAnomalies: (query: { tenantId?: string; applicationId?: string; channelId?: string; anomalyType?: string; status?: string; keyword?: string; page?: number; pageSize?: number } = {}) =>
request<ReceiptAnomalyResponse>(withQuery('/admin/operations/receipt-anomalies', query)),
listStatistics: (query: { tenantId?: string; groupBy?: string } = {}) => request<Array<Record<string, unknown>>>(withQuery('/admin/operations/statistics', query)),
getDownstreamDeliveryDashboard: (query: { tenantId?: string; applicationId?: string; deliveryType?: string; createdAtFrom?: string; createdAtTo?: string } = {}) =>
request<DownstreamDeliveryDashboard>(withQuery('/admin/operations/downstream-deliveries/dashboard', query)),
+1 -1
View File
@@ -17,7 +17,7 @@ export type AdminChannel = {
rateLimitPerSecond: number;
unitPrice: number;
status: string;
config?: { desiredConnections?: number; windowSize?: number; extensionDigits?: number; heartbeatIntervalSeconds?: number; heartbeatMissThreshold?: number; [key: string]: unknown } | null;
config?: { desiredConnections?: number; windowSize?: number; extensionDigits?: number; heartbeatIntervalSeconds?: number; heartbeatMissThreshold?: number; longMessageReceiptMode?: 'per_segment' | 'message_level'; [key: string]: unknown } | null;
connectionStates?: CmppConnectionState[];
};
+11 -2
View File
@@ -127,6 +127,15 @@ export type UserPayload = {
operatorId?: string;
};
export type PendingAuditCounts = {
enterpriseCertifications: number;
smsAudits: number;
templates: number;
signatures: number;
drainageInfos: number;
total: number;
};
export type DashboardResponse = {
taskCount: number;
messageStatus: Array<{ status: string; _count: { _all: number }; _sum: { amountCents?: number | null; billingUnits?: number | null } }>;
@@ -136,7 +145,7 @@ export type DashboardResponse = {
transactions: { _count: { _all: number }; _sum: { amountCents?: number | null } };
gatewayConnections: Array<{ status: string; _count: { _all: number }; _sum: { currentConnections?: number | null; desiredConnections?: number | null } }>;
pendingAuditCount: number;
pendingAudits: { enterpriseCertifications: number; smsAudits: number; templates: number; signatures: number; drainageInfos: number; total: number };
pendingAudits: PendingAuditCounts;
hourlySendTrend: Array<{ hour: number; label: string; submittedCount: number; successCount: number }>;
auditProcessingSpeed: Array<{ category: string; label: string; count: number; averageProcessingMs: number | null }>;
downstreamDeliverySummary?: {
@@ -382,7 +391,7 @@ export type HttpApiConfig = {
allowClientTest: boolean;
};
export type HttpApiConfigResponse = { applicationId: string; applicationName?: string; config: HttpApiConfig | null; ipAllowlist: string[] };
export type HttpApiConfigResponse = { applicationId: string; applicationName?: string; publicOrigin?: string; config: HttpApiConfig | null; ipAllowlist: string[] };
export type HttpApiCredential = { id: string; name: string; accessKey: string; secretLast4: string; secret?: string; secretShownOnce?: boolean; status: string; expiresAt?: string | null; lastUsedAt?: string | null; lastUsedIp?: string | null; createdAt: string };
+32
View File
@@ -571,6 +571,38 @@ export type GatewaySubmitExceptionResponse = PagedResponse<GatewaySubmitExceptio
};
};
export type ReceiptAnomaly = {
id: string;
anomalyKey: string;
anomalyType: 'aggregate_success_then_failure' | string;
status: 'pending' | 'resolved' | 'ignored' | string;
previousStatus?: string | null;
incomingStatus?: string | null;
rawStatus?: string | null;
errorCode?: string | null;
detail?: Record<string, unknown> | null;
occurrenceCount: number;
firstOccurredAt: string;
lastOccurredAt: string;
resolvedAt?: string | null;
resolutionNote?: string | null;
tenant?: Pick<TenantOption, 'id' | 'name' | 'code' | 'status'> | null;
application?: Pick<EnterpriseApplication, 'id' | 'tenantId' | 'name' | 'status'> | null;
channel?: Pick<AdminChannel, 'id' | 'code' | 'name' | 'status'> | null;
messageRecord?: { messageId: string; phoneNumber: string; status: string } | null;
submitRecord?: { submitId: string; submitStatus: string } | null;
receiptRecord?: { gatewayMessageId: string; receiptStatus: string; rawStatus: string; deliveredAt: string } | null;
};
export type ReceiptAnomalyResponse = PagedResponse<ReceiptAnomaly> & {
summary: {
pending: number;
resolved: number;
ignored: number;
oldestPendingAt?: string | null;
};
};
export type DownstreamRecoveryStatusResponse = PagedResponse<GatewayDownstreamRecoveryStatus> & {
summary: {
total: number;