feat: build reporting workbench workflow
This commit is contained in:
@@ -1,5 +1,29 @@
|
||||
import { request, requestBlob, requestForm, withQuery } from '../core/httpClient';
|
||||
import type { AdminChannel, ChannelConnectionLogResponse, ChannelGroup, ChannelGroupDeletionImpact, ChannelReportField, ChannelTestResponse, CmppConnectionState, DeleteTargetRequest, DeletionPreflight, DeletionResult, DeletionTargetType, DictionaryItem, PagedResult, ReportImportMapping, ReportImportProfile, ReportImportReviewBatch, ReportMaterialBatch, ReportMaterialBatchPreflight, ReportMaterialBatchResult, ReportMaterialPendingItem, ReportRecord, ReportTask } from '../types';
|
||||
import type {
|
||||
AdminChannel,
|
||||
ChannelConnectionLogResponse,
|
||||
ChannelGroup,
|
||||
ChannelGroupDeletionImpact,
|
||||
ChannelReportField,
|
||||
ChannelTestResponse,
|
||||
CmppConnectionState,
|
||||
DeleteTargetRequest,
|
||||
DeletionPreflight,
|
||||
DeletionResult,
|
||||
DeletionTargetType,
|
||||
DictionaryItem,
|
||||
PagedResult,
|
||||
ReportImportMapping,
|
||||
ReportImportProfile,
|
||||
ReportImportReviewBatch,
|
||||
ReportMaterialBatch,
|
||||
ReportMaterialBatchPreflight,
|
||||
ReportMaterialBatchResult,
|
||||
ReportMaterialPendingItem,
|
||||
ReportRecord,
|
||||
ReportTask,
|
||||
SingleReportMaterialDetail,
|
||||
} from '../types';
|
||||
import { assertUploadFileSize } from '@/utils/fileUpload';
|
||||
|
||||
// Report generation consumes channel report fields, so these endpoints keep one
|
||||
@@ -8,88 +32,354 @@ export const adminChannelsReportsApi = {
|
||||
listChannels: () => request<AdminChannel[]>('/admin/channels'),
|
||||
listChannelsPage: (query: { keyword?: string; carrier?: string; status?: string; page: number; pageSize: number }) =>
|
||||
request<PagedResult<AdminChannel>>(withQuery('/admin/channels', query)),
|
||||
createChannel: (body: Partial<AdminChannel> & { passwordCipher?: string; desiredConnections?: number; windowSize?: number; heartbeatIntervalSeconds?: number; heartbeatMissThreshold?: number }) =>
|
||||
request<AdminChannel>('/admin/channels', { method: 'POST', body: JSON.stringify(body) }),
|
||||
updateChannel: (id: string, body: Partial<AdminChannel> & { passwordCipher?: string; desiredConnections?: number; windowSize?: number; heartbeatIntervalSeconds?: number; heartbeatMissThreshold?: number }) =>
|
||||
request<AdminChannel>(`/admin/channels/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
|
||||
copyChannel: (id: string, body: { operatorId?: string } = {}) => request<AdminChannel>(`/admin/channels/${id}/copy`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
testChannel: (id: string, body: { phoneNumber?: string; phones?: string[] | string; content: string; accessNo?: string }) =>
|
||||
request<ChannelTestResponse>(`/admin/channels/${id}/test`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
changeChannelStatus: (id: string, status: string, reason?: string) => request<AdminChannel>(`/admin/channels/${id}/status`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ status, reason }),
|
||||
}),
|
||||
deleteChannel: (id: string, reason?: string) => request<AdminChannel>(`/admin/channels/${id}`, {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify({ reason }),
|
||||
}),
|
||||
createChannel: (
|
||||
body: Partial<AdminChannel> & {
|
||||
passwordCipher?: string;
|
||||
desiredConnections?: number;
|
||||
windowSize?: number;
|
||||
heartbeatIntervalSeconds?: number;
|
||||
heartbeatMissThreshold?: number;
|
||||
},
|
||||
) => request<AdminChannel>('/admin/channels', { method: 'POST', body: JSON.stringify(body) }),
|
||||
updateChannel: (
|
||||
id: string,
|
||||
body: Partial<AdminChannel> & {
|
||||
passwordCipher?: string;
|
||||
desiredConnections?: number;
|
||||
windowSize?: number;
|
||||
heartbeatIntervalSeconds?: number;
|
||||
heartbeatMissThreshold?: number;
|
||||
},
|
||||
) => request<AdminChannel>(`/admin/channels/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
|
||||
copyChannel: (id: string, body: { operatorId?: string } = {}) =>
|
||||
request<AdminChannel>(`/admin/channels/${id}/copy`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
testChannel: (
|
||||
id: string,
|
||||
body: { phoneNumber?: string; phones?: string[] | string; content: string; accessNo?: string },
|
||||
) => request<ChannelTestResponse>(`/admin/channels/${id}/test`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
changeChannelStatus: (id: string, status: string, reason?: string) =>
|
||||
request<AdminChannel>(`/admin/channels/${id}/status`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ status, reason }),
|
||||
}),
|
||||
deleteChannel: (id: string, reason?: string) =>
|
||||
request<AdminChannel>(`/admin/channels/${id}`, {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify({ reason }),
|
||||
}),
|
||||
getDeletionPreflight: (type: DeletionTargetType, id: string) =>
|
||||
request<DeletionPreflight>(`/admin/deletions/${type}/${id}/preflight`),
|
||||
deleteGovernedTarget: (type: DeletionTargetType, id: string, body: DeleteTargetRequest) =>
|
||||
request<DeletionResult>(`/admin/deletions/${type}/${id}`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
listChannelConnectionLogs: (id: string) => request<ChannelConnectionLogResponse>(`/admin/channels/${id}/connection-logs`),
|
||||
listChannelConnectionLogs: (id: string) =>
|
||||
request<ChannelConnectionLogResponse>(`/admin/channels/${id}/connection-logs`),
|
||||
listChannelGroups: () => request<ChannelGroup[]>('/admin/channel-groups'),
|
||||
createChannelGroup: (body: { code: string; name: string; carrier: 'mobile' | 'unicom' | 'telecom'; description?: string; status?: string; retryEnabled?: boolean; retryTimeLimitHours?: number; retryTimeLimitMinutes?: number }) =>
|
||||
request<ChannelGroup>('/admin/channel-groups', { method: 'POST', body: JSON.stringify(body) }),
|
||||
updateChannelGroup: (id: string, body: { code?: string; name?: string; carrier?: 'mobile' | 'unicom' | 'telecom'; description?: string; status?: string; retryEnabled?: boolean; retryTimeLimitHours?: number; retryTimeLimitMinutes?: number; items?: Array<Record<string, unknown>> }) =>
|
||||
request<ChannelGroup>(`/admin/channel-groups/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
|
||||
createChannelGroup: (body: {
|
||||
code: string;
|
||||
name: string;
|
||||
carrier: 'mobile' | 'unicom' | 'telecom';
|
||||
description?: string;
|
||||
status?: string;
|
||||
retryEnabled?: boolean;
|
||||
retryTimeLimitHours?: number;
|
||||
retryTimeLimitMinutes?: number;
|
||||
}) => request<ChannelGroup>('/admin/channel-groups', { method: 'POST', body: JSON.stringify(body) }),
|
||||
updateChannelGroup: (
|
||||
id: string,
|
||||
body: {
|
||||
code?: string;
|
||||
name?: string;
|
||||
carrier?: 'mobile' | 'unicom' | 'telecom';
|
||||
description?: string;
|
||||
status?: string;
|
||||
retryEnabled?: boolean;
|
||||
retryTimeLimitHours?: number;
|
||||
retryTimeLimitMinutes?: number;
|
||||
items?: Array<Record<string, unknown>>;
|
||||
},
|
||||
) => request<ChannelGroup>(`/admin/channel-groups/${id}`, { method: 'PUT', body: JSON.stringify(body) }),
|
||||
getChannelGroupDeletionImpact: (id: string) =>
|
||||
request<ChannelGroupDeletionImpact>(`/admin/channel-groups/${id}/deletion-impact`),
|
||||
deleteChannelGroup: (id: string) =>
|
||||
request<ChannelGroup>(`/admin/channel-groups/${id}`, { method: 'DELETE' }),
|
||||
deleteChannelGroup: (id: string) => request<ChannelGroup>(`/admin/channel-groups/${id}`, { method: 'DELETE' }),
|
||||
addChannelGroupItem: (body: Record<string, unknown>) =>
|
||||
request<DictionaryItem>('/admin/channel-groups/items', { method: 'POST', body: JSON.stringify(body) }),
|
||||
listChannelRouteRules: () => request<DictionaryItem[]>('/admin/channel-route-rules'),
|
||||
createChannelRouteRule: (body: { tenantId?: string; applicationId: string; groupId: string; carrier: string; priority?: number; status?: string }) =>
|
||||
request<DictionaryItem>('/admin/channel-route-rules', { method: 'POST', body: JSON.stringify(body) }),
|
||||
createChannelRouteRule: (body: {
|
||||
tenantId?: string;
|
||||
applicationId: string;
|
||||
groupId: string;
|
||||
carrier: string;
|
||||
priority?: number;
|
||||
status?: string;
|
||||
}) => request<DictionaryItem>('/admin/channel-route-rules', { method: 'POST', body: JSON.stringify(body) }),
|
||||
listChannelConnections: (id: string) => request<CmppConnectionState[]>(`/admin/channels/${id}/connections`),
|
||||
replaceApplicationRouteRules: (applicationId: string, body: { routes: Array<{ carrier: 'mobile' | 'unicom' | 'telecom'; groupId: string; priority?: number; status?: string }> }) =>
|
||||
request<DictionaryItem[]>(`/admin/enterprise-applications/${applicationId}/route-rules`, { method: 'PUT', body: JSON.stringify(body) }),
|
||||
listChannelReportFields: (channelId?: string) => request<ChannelReportField[]>(withQuery('/admin/channel-report-fields', { channelId })),
|
||||
replaceApplicationRouteRules: (
|
||||
applicationId: string,
|
||||
body: {
|
||||
routes: Array<{ carrier: 'mobile' | 'unicom' | 'telecom'; groupId: string; priority?: number; status?: string }>;
|
||||
},
|
||||
) =>
|
||||
request<DictionaryItem[]>(`/admin/enterprise-applications/${applicationId}/route-rules`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
listChannelReportFields: (channelId?: string) =>
|
||||
request<ChannelReportField[]>(withQuery('/admin/channel-report-fields', { channelId })),
|
||||
createChannelReportField: (body: Record<string, unknown>) =>
|
||||
request<ChannelReportField>('/admin/channel-report-fields', { method: 'POST', body: JSON.stringify(body) }),
|
||||
replaceChannelReportFields: (channelId: string, reportType: 'signature' | 'drainage', fields: Array<Record<string, unknown>>) =>
|
||||
request<ChannelReportField[]>(`/admin/channels/${channelId}/report-fields/${reportType}`, { method: 'PUT', body: JSON.stringify({ fields }) }),
|
||||
listPendingReportMaterials: (query: { reportType?: 'signature' | 'drainage'; tenantId?: string; applicationId?: string; keyword?: string; startAt?: string; endAt?: string; page?: number; pageSize?: number } = {}) =>
|
||||
request<PagedResult<ReportMaterialPendingItem>>(withQuery('/admin/report-materials/pending', query)),
|
||||
replaceChannelReportFields: (
|
||||
channelId: string,
|
||||
reportType: 'signature' | 'drainage',
|
||||
fields: Array<Record<string, unknown>>,
|
||||
) =>
|
||||
request<ChannelReportField[]>(`/admin/channels/${channelId}/report-fields/${reportType}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ fields }),
|
||||
}),
|
||||
listPendingReportMaterials: (
|
||||
query: {
|
||||
reportType?: 'signature' | 'drainage';
|
||||
tenantId?: string;
|
||||
applicationId?: string;
|
||||
keyword?: string;
|
||||
startAt?: string;
|
||||
endAt?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
} = {},
|
||||
) => request<PagedResult<ReportMaterialPendingItem>>(withQuery('/admin/report-materials/pending', query)),
|
||||
listReportImportProfiles: (reportType?: 'signature' | 'drainage') =>
|
||||
request<ReportImportProfile[]>(withQuery('/admin/report-materials/import-profiles', { reportType })),
|
||||
saveReportImportProfile: (body: Omit<ReportImportProfile, 'id'> & { id?: string }) =>
|
||||
request<ReportImportProfile>('/admin/report-materials/import-profiles', { method: 'POST', body: JSON.stringify(body) }),
|
||||
analyzeReportMaterialImport: (file: File, body: { tenantId: string; applicationId?: string; reportType: 'signature' | 'drainage'; sheetName?: string; headerRowCount?: number; dataStartRow?: number; profileId?: string }) => {
|
||||
request<ReportImportProfile>('/admin/report-materials/import-profiles', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
analyzeReportMaterialImport: (
|
||||
file: File,
|
||||
body: {
|
||||
tenantId: string;
|
||||
applicationId?: string;
|
||||
reportType: 'signature' | 'drainage';
|
||||
sheetName?: string;
|
||||
headerRowCount?: number;
|
||||
dataStartRow?: number;
|
||||
profileId?: string;
|
||||
},
|
||||
) => {
|
||||
assertUploadFileSize(file);
|
||||
const form = new FormData();
|
||||
form.set('file', file);
|
||||
Object.entries(body).forEach(([key, value]) => { if (value !== undefined) form.set(key, String(value)); });
|
||||
return requestForm<Record<string, unknown> & { id: string; columns: Array<{ sourceColumnIndex: number; columnLetter: string; sourceHeader: string; sourceHeaderPath: string; imageCount: number }>; rows: Array<Record<string, unknown>>; suggestedMappings: ReportImportMapping[] }>('/admin/report-materials/imports/analyze', form);
|
||||
Object.entries(body).forEach(([key, value]) => {
|
||||
if (value !== undefined) form.set(key, String(value));
|
||||
});
|
||||
return requestForm<
|
||||
Record<string, unknown> & {
|
||||
id: string;
|
||||
columns: Array<{
|
||||
sourceColumnIndex: number;
|
||||
columnLetter: string;
|
||||
sourceHeader: string;
|
||||
sourceHeaderPath: string;
|
||||
imageCount: number;
|
||||
}>;
|
||||
rows: Array<Record<string, unknown>>;
|
||||
suggestedMappings: ReportImportMapping[];
|
||||
}
|
||||
>('/admin/report-materials/imports/analyze', form);
|
||||
},
|
||||
commitReportMaterialImport: (id: string, body: { mappings: ReportImportMapping[]; profile?: Omit<ReportImportProfile, 'id'> & { id?: string } }) =>
|
||||
request<Record<string, unknown>>(`/admin/report-materials/imports/${id}/commit`, { method: 'PUT', body: JSON.stringify(body) }),
|
||||
listReportImportReviewBatches: (query: { reportType?: 'signature' | 'drainage'; status?: string; keyword?: string; startAt?: string; endAt?: string; page?: number; pageSize?: number } = {}) =>
|
||||
commitReportMaterialImport: (
|
||||
id: string,
|
||||
body: { mappings: ReportImportMapping[]; profile?: Omit<ReportImportProfile, 'id'> & { id?: string } },
|
||||
) =>
|
||||
request<Record<string, unknown>>(`/admin/report-materials/imports/${id}/commit`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
listReportImportReviewBatches: (
|
||||
query: {
|
||||
reportType?: 'signature' | 'drainage';
|
||||
status?: string;
|
||||
keyword?: string;
|
||||
startAt?: string;
|
||||
endAt?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
} = {},
|
||||
) =>
|
||||
request<PagedResult<ReportImportReviewBatch>>(withQuery('/admin/report-materials/imports/review-batches', query)),
|
||||
reviewReportImportItems: (id: string, body: { decision: 'approve' | 'reject'; itemIds?: string[]; reason?: string }) =>
|
||||
request<{ batchId: string; status: string; approvedCount: number; rejectedCount: number; failedCount: number }>(`/admin/report-materials/imports/${id}/review`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
listReportMaterialBatches: (query: { keyword?: string; startAt?: string; endAt?: string; page?: number; pageSize?: number } = {}) =>
|
||||
request<PagedResult<ReportMaterialBatch>>(withQuery('/admin/report-materials/batches', query)),
|
||||
preflightReportMaterialBatch: (body: { items: Array<{ reportType: 'signature' | 'drainage'; signatureId: string; drainageItemId?: string; materialVersion?: number }> }) =>
|
||||
request<ReportMaterialBatchPreflight>('/admin/report-materials/batches/preflight', { method: 'POST', body: JSON.stringify(body) }),
|
||||
createReportMaterialBatch: (body: { idempotencyKey: string; items: Array<{ reportType: 'signature' | 'drainage'; signatureId: string; drainageItemId?: string; materialVersion: number }> }) =>
|
||||
request<ReportMaterialBatchResult>('/admin/report-materials/batches', { method: 'POST', body: JSON.stringify(body) }),
|
||||
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; 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; 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) }),
|
||||
reviewReportImportItems: (
|
||||
id: string,
|
||||
body: { decision: 'approve' | 'reject'; itemIds?: string[]; reason?: string },
|
||||
) =>
|
||||
request<{ batchId: string; status: string; approvedCount: number; rejectedCount: number; failedCount: number }>(
|
||||
`/admin/report-materials/imports/${id}/review`,
|
||||
{ method: 'POST', body: JSON.stringify(body) },
|
||||
),
|
||||
listReportMaterialBatches: (
|
||||
query: { keyword?: string; startAt?: string; endAt?: string; page?: number; pageSize?: number } = {},
|
||||
) => request<PagedResult<ReportMaterialBatch>>(withQuery('/admin/report-materials/batches', query)),
|
||||
getReportMaterialBatch: (id: string) => request<ReportMaterialBatch>(`/admin/report-materials/batches/${id}`),
|
||||
listReportMaterialBatchTasks: (
|
||||
id: string,
|
||||
query: {
|
||||
keyword?: string;
|
||||
reportType?: 'signature' | 'drainage';
|
||||
status?: string;
|
||||
channelId?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
} = {},
|
||||
) => request<PagedResult<ReportTask>>(withQuery(`/admin/report-materials/batches/${id}/tasks`, query)),
|
||||
preflightReportMaterialBatch: (body: {
|
||||
items: Array<{
|
||||
reportType: 'signature' | 'drainage';
|
||||
signatureId: string;
|
||||
drainageItemId?: string;
|
||||
materialVersion?: number;
|
||||
}>;
|
||||
}) =>
|
||||
request<ReportMaterialBatchPreflight>('/admin/report-materials/batches/preflight', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
createReportMaterialBatch: (body: {
|
||||
idempotencyKey: string;
|
||||
items: Array<{
|
||||
reportType: 'signature' | 'drainage';
|
||||
signatureId: string;
|
||||
drainageItemId?: string;
|
||||
materialVersion: number;
|
||||
}>;
|
||||
}) =>
|
||||
request<ReportMaterialBatchResult>('/admin/report-materials/batches', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
listReportTasks: (
|
||||
query: { tenantId?: string; status?: string; channelId?: string; reportType?: 'signature' | 'drainage' } = {},
|
||||
) => request<ReportTask[]>(withQuery('/admin/report-tasks', query)),
|
||||
listReportTasksPage: (query: {
|
||||
tenantId?: string;
|
||||
applicationId?: string;
|
||||
status?: string;
|
||||
channelId?: string;
|
||||
reportType?: 'signature' | 'drainage';
|
||||
keyword?: string;
|
||||
carrier?: string;
|
||||
todaySendMin?: number;
|
||||
todaySendMax?: number;
|
||||
sort?: string;
|
||||
createdAtFrom?: string;
|
||||
createdAtTo?: string;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}) => request<PagedResult<ReportTask>>(withQuery('/admin/report-tasks', query)),
|
||||
listReportDetailsPage: (query: {
|
||||
tenantId?: string;
|
||||
applicationId?: string;
|
||||
signatureId?: string;
|
||||
channelId?: string;
|
||||
carrier?: string;
|
||||
status?: string;
|
||||
reportType?: 'signature' | 'drainage';
|
||||
keyword?: string;
|
||||
createdAtFrom?: string;
|
||||
createdAtTo?: string;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}) => request<PagedResult<ReportTask>>(withQuery('/admin/report-details', query)),
|
||||
getSingleReportMaterialDetail: (body: {
|
||||
reportType?: 'signature' | 'drainage';
|
||||
signatureId: string;
|
||||
channelId: string;
|
||||
carrier?: 'mobile' | 'unicom' | 'telecom';
|
||||
drainageItemId?: string;
|
||||
batchItemId?: string;
|
||||
}) =>
|
||||
request<SingleReportMaterialDetail>('/admin/report-materials/single-detail', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
exportSingleReportMaterial: (body: {
|
||||
reportType?: 'signature' | 'drainage';
|
||||
signatureId: string;
|
||||
channelId: string;
|
||||
carrier?: 'mobile' | 'unicom' | 'telecom';
|
||||
drainageItemId?: string;
|
||||
batchItemId?: string;
|
||||
}) => requestBlob('/admin/report-materials/single-export', { method: 'POST', body: JSON.stringify(body) }),
|
||||
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;
|
||||
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) }),
|
||||
importReportReceipt: (id: string, body: { fileObjectId?: string; fileName: string; fileContent?: string; delimiter?: ',' | '\t'; rowCount?: number; successCount?: number; failedCount?: number; statusAfter?: string; reason?: string; result?: Record<string, unknown> }) =>
|
||||
request<Record<string, unknown>>(`/admin/report-tasks/${id}/receipt-import`, { method: 'POST', body: JSON.stringify(body) }),
|
||||
listReportRecords: (query: { taskId?: string; channelId?: string } = {}) => request<ReportRecord[]>(withQuery('/admin/report-records', query)),
|
||||
listReportRecordsPage: (query: { taskId?: string; channelId?: string; keyword?: string; reportType?: 'signature' | 'drainage'; createdAtFrom?: string; createdAtTo?: string; page: number; pageSize: number }) =>
|
||||
request<PagedResult<ReportRecord>>(withQuery('/admin/report-records', query)),
|
||||
request<Record<string, unknown>>(`/admin/report-tasks/${id}/export`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
importReportReceipt: (
|
||||
id: string,
|
||||
body: {
|
||||
fileObjectId?: string;
|
||||
fileName: string;
|
||||
fileContent?: string;
|
||||
delimiter?: ',' | '\t';
|
||||
rowCount?: number;
|
||||
successCount?: number;
|
||||
failedCount?: number;
|
||||
statusAfter?: string;
|
||||
reason?: string;
|
||||
result?: Record<string, unknown>;
|
||||
},
|
||||
) =>
|
||||
request<Record<string, unknown>>(`/admin/report-tasks/${id}/receipt-import`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
}),
|
||||
listReportRecords: (query: { taskId?: string; channelId?: string } = {}) =>
|
||||
request<ReportRecord[]>(withQuery('/admin/report-records', query)),
|
||||
listReportRecordsPage: (query: {
|
||||
taskId?: string;
|
||||
channelId?: string;
|
||||
batchNo?: string;
|
||||
statusAfter?: string;
|
||||
action?: string;
|
||||
sourceEntry?: string;
|
||||
operatorKeyword?: string;
|
||||
keyword?: string;
|
||||
reportType?: 'signature' | 'drainage';
|
||||
createdAtFrom?: string;
|
||||
createdAtTo?: string;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}) => request<PagedResult<ReportRecord>>(withQuery('/admin/report-records', query)),
|
||||
};
|
||||
|
||||
@@ -18,7 +18,15 @@ export type AdminChannel = {
|
||||
rateLimitPerSecond: number;
|
||||
unitPrice: number;
|
||||
status: string;
|
||||
config?: { desiredConnections?: number; windowSize?: number; extensionDigits?: number; heartbeatIntervalSeconds?: number; heartbeatMissThreshold?: number; longMessageReceiptMode?: 'per_segment' | 'message_level'; [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[];
|
||||
};
|
||||
|
||||
@@ -118,6 +126,14 @@ export type ReportMaterialPendingItem = {
|
||||
signatureName?: string;
|
||||
tenant?: TenantOption;
|
||||
application?: ClientSmsApplication | null;
|
||||
statusSummary?: {
|
||||
total: number;
|
||||
pending: number;
|
||||
reporting: number;
|
||||
approved: number;
|
||||
failed: number;
|
||||
abandoned: number;
|
||||
};
|
||||
};
|
||||
|
||||
export type ReportMaterialBatch = {
|
||||
@@ -132,7 +148,47 @@ export type ReportMaterialBatch = {
|
||||
successRate: number;
|
||||
createdAt: string;
|
||||
completedAt?: string | null;
|
||||
exportFiles: Array<{ id: string; fileObjectId?: string | null; fileName: string; rowCount: number; channelId?: string | null }>;
|
||||
exportFiles: Array<{
|
||||
id: string;
|
||||
fileObjectId?: string | null;
|
||||
fileName: string;
|
||||
rowCount: number;
|
||||
channelId?: string | null;
|
||||
}>;
|
||||
items?: Array<{
|
||||
id: string;
|
||||
reportType: 'signature' | 'drainage';
|
||||
signatureId: string;
|
||||
drainageItemId?: string | null;
|
||||
materialVersion: number;
|
||||
status: string;
|
||||
errorMessage?: string | null;
|
||||
}>;
|
||||
};
|
||||
|
||||
export type SingleReportMaterialDetail = {
|
||||
reportType: 'signature' | 'drainage';
|
||||
signatureId: string;
|
||||
signatureName: string;
|
||||
tenant: { id: string; name: string };
|
||||
application?: { id: string; name: string } | null;
|
||||
channel: { id: string; name: string; code: string };
|
||||
carrier?: 'mobile' | 'unicom' | 'telecom' | null;
|
||||
materialVersion: number;
|
||||
batchItemId?: string | null;
|
||||
fields: Array<{
|
||||
id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
exportName?: string | null;
|
||||
fieldType: string;
|
||||
required: boolean;
|
||||
value: unknown;
|
||||
submitted: boolean;
|
||||
missing: boolean;
|
||||
}>;
|
||||
historicalFields: Array<{ code: string; name: string; value: unknown }>;
|
||||
missingFields: string[];
|
||||
};
|
||||
|
||||
export type ReportImportReviewItem = {
|
||||
@@ -245,7 +301,16 @@ export type ApplicationReportField = {
|
||||
description?: string | null;
|
||||
reportTypes: string[];
|
||||
commonReportTypes?: Array<'signature' | 'drainage'>;
|
||||
channels: Array<{ id: string; code: string; name: string; groupId: string; groupName: string; required: boolean; reportType: 'signature' | 'drainage' | 'both'; source?: 'common' | 'channel' | 'both' }>;
|
||||
channels: Array<{
|
||||
id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
groupId: string;
|
||||
groupName: string;
|
||||
required: boolean;
|
||||
reportType: 'signature' | 'drainage' | 'both';
|
||||
source?: 'common' | 'channel' | 'both';
|
||||
}>;
|
||||
};
|
||||
|
||||
export type ClientApplicationReportField = Omit<ApplicationReportField, 'channels' | 'commonReportTypes'>;
|
||||
@@ -259,6 +324,7 @@ export type CommonReportField = DictionaryItem & {
|
||||
};
|
||||
|
||||
export type ReportTask = DictionaryItem & {
|
||||
virtual?: boolean;
|
||||
tenantId: string;
|
||||
signatureId: string;
|
||||
channelId: string;
|
||||
@@ -277,14 +343,26 @@ export type ReportTask = DictionaryItem & {
|
||||
application?: { id: string; name: string } | null;
|
||||
};
|
||||
drainageInfo?: SmsDrainageInfo | null;
|
||||
channel?: { id: string; name: string; code: string; carrier?: string | null; carriers?: Array<'mobile' | 'unicom' | 'telecom'> };
|
||||
channel?: {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
carrier?: string | null;
|
||||
carriers?: Array<'mobile' | 'unicom' | 'telecom'>;
|
||||
};
|
||||
reason?: string | null;
|
||||
createdAt?: string;
|
||||
updatedAt?: string;
|
||||
exportItems?: Array<{
|
||||
id: string;
|
||||
rowNumber: number;
|
||||
exportFile: { id: string; fileObjectId?: string | null; fileName: string; rowCount: number; batchId?: string | null };
|
||||
exportFile: {
|
||||
id: string;
|
||||
fileObjectId?: string | null;
|
||||
fileName: string;
|
||||
rowCount: number;
|
||||
batchId?: string | null;
|
||||
};
|
||||
batchItem: { id: string; materialVersion: number; batch: { id: string; batchNo: string; createdAt: string } };
|
||||
}>;
|
||||
records?: Array<{
|
||||
@@ -320,4 +398,5 @@ export type ReportRecord = DictionaryItem & {
|
||||
sourceEntry?: 'system' | 'legacy' | 'enterprise_signature' | 'report_task' | 'channel_report';
|
||||
channel?: AdminChannel;
|
||||
task?: ReportTask;
|
||||
operator?: { id: string; username: string; displayName: string };
|
||||
};
|
||||
|
||||
@@ -138,12 +138,29 @@ export type PendingAuditCounts = {
|
||||
|
||||
export type DashboardResponse = {
|
||||
taskCount: number;
|
||||
messageStatus: Array<{ status: string; _count: { _all: number }; _sum: { amountCents?: number | null; billingUnits?: number | null } }>;
|
||||
today: { sent: number; delivered: number; failed: number; unknown: number; successRate: number; spendCents: number; returnedCents: number; billingUnits: number };
|
||||
messageStatus: Array<{
|
||||
status: string;
|
||||
_count: { _all: number };
|
||||
_sum: { amountCents?: number | null; billingUnits?: number | null };
|
||||
}>;
|
||||
today: {
|
||||
sent: number;
|
||||
delivered: number;
|
||||
failed: number;
|
||||
unknown: number;
|
||||
successRate: number;
|
||||
spendCents: number;
|
||||
returnedCents: number;
|
||||
billingUnits: number;
|
||||
};
|
||||
uplinkCount: number;
|
||||
billing: { _count: { _all: number }; _sum: { amountCents?: number | null; billingUnits?: number | null } };
|
||||
transactions: { _count: { _all: number }; _sum: { amountCents?: number | null } };
|
||||
gatewayConnections: Array<{ status: string; _count: { _all: number }; _sum: { currentConnections?: number | null; desiredConnections?: number | null } }>;
|
||||
gatewayConnections: Array<{
|
||||
status: string;
|
||||
_count: { _all: number };
|
||||
_sum: { currentConnections?: number | null; desiredConnections?: number | null };
|
||||
}>;
|
||||
pendingAuditCount: number;
|
||||
pendingAudits: PendingAuditCounts;
|
||||
hourlySendTrend: Array<{ hour: number; label: string; submittedCount: number; successCount: number }>;
|
||||
@@ -157,8 +174,21 @@ export type DashboardResponse = {
|
||||
recentFailed: number;
|
||||
alertCount: number;
|
||||
};
|
||||
accounts: Array<{ id: string; tenantId: string; balanceCents: number; creditCents: number; status: string; tenant?: TenantOption }>;
|
||||
enterpriseSpendRanks: Array<{ tenantId: string; tenantName: string; todaySpendCents: number; balanceCents: number; creditCents: number }>;
|
||||
accounts: Array<{
|
||||
id: string;
|
||||
tenantId: string;
|
||||
balanceCents: number;
|
||||
creditCents: number;
|
||||
status: string;
|
||||
tenant?: TenantOption;
|
||||
}>;
|
||||
enterpriseSpendRanks: Array<{
|
||||
tenantId: string;
|
||||
tenantName: string;
|
||||
todaySpendCents: number;
|
||||
balanceCents: number;
|
||||
creditCents: number;
|
||||
}>;
|
||||
recentTasks: Array<Record<string, unknown>>;
|
||||
recentRecharges: Array<RechargeOrder>;
|
||||
clientOverview?: {
|
||||
@@ -239,34 +269,71 @@ export type ClientSmsSignature = {
|
||||
tenant?: TenantOption;
|
||||
application?: ClientSmsApplication | null;
|
||||
reportStatus?: string;
|
||||
materialVersion?: number;
|
||||
pendingReport?: boolean;
|
||||
reportChangedAt?: string;
|
||||
reportMaterialChanged?: boolean;
|
||||
reportPoolAvailableAfter?: 'immediate' | 'approval';
|
||||
pendingReportDetailCount?: number;
|
||||
pendingReportMaterialVersion?: number | null;
|
||||
pendingReportBlockedReason?: string | null;
|
||||
reportTasks?: Array<ReportTask & { channel?: AdminChannel }>;
|
||||
reportTargets?: Array<{ channel: AdminChannel; channelId: string; carrier: 'mobile' | 'unicom' | 'telecom'; status: string; taskId?: string; approvedAt?: string | null; approvalScope?: 'carrier_specific' | 'legacy_channel' }>;
|
||||
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 }>>;
|
||||
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 }>
|
||||
>;
|
||||
};
|
||||
|
||||
export type ClientSmsSignatureView = Pick<ClientSmsSignature,
|
||||
'id' | 'tenantId' | 'applicationId' | 'name' | 'purpose' | 'auditStatus' | 'reportStatus' | 'rejectReason' | 'createdAt' | 'updatedAt' | 'materials' | 'carrierReportSummary' | 'drainageCarrierReportSummary'
|
||||
export type ClientSmsSignatureView = Pick<
|
||||
ClientSmsSignature,
|
||||
| 'id'
|
||||
| 'tenantId'
|
||||
| 'applicationId'
|
||||
| 'name'
|
||||
| 'purpose'
|
||||
| 'auditStatus'
|
||||
| 'reportStatus'
|
||||
| 'rejectReason'
|
||||
| 'createdAt'
|
||||
| 'updatedAt'
|
||||
| 'materials'
|
||||
| 'carrierReportSummary'
|
||||
| 'drainageCarrierReportSummary'
|
||||
> & {
|
||||
pendingReport?: boolean;
|
||||
reportChangedAt?: string;
|
||||
application?: Pick<ClientSmsApplication, 'id' | 'name' | 'status'> | null;
|
||||
submittedMaterialCount: number;
|
||||
reportValues: Record<string, unknown>;
|
||||
drainageInfo: { links: Array<{
|
||||
id: string;
|
||||
siteName: string;
|
||||
url: string;
|
||||
remark?: string | null;
|
||||
reportValues: Record<string, unknown>;
|
||||
auditStatus: string;
|
||||
rejectReason?: string | null;
|
||||
submittedAt: string;
|
||||
reviewedAt?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}> };
|
||||
drainageInfo: {
|
||||
links: Array<{
|
||||
id: string;
|
||||
siteName: string;
|
||||
url: string;
|
||||
remark?: string | null;
|
||||
reportValues: Record<string, unknown>;
|
||||
auditStatus: string;
|
||||
rejectReason?: string | null;
|
||||
submittedAt: string;
|
||||
reviewedAt?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
|
||||
export type ClientSignatureWorkspace = {
|
||||
@@ -394,15 +461,64 @@ export type HttpApiConfig = {
|
||||
allowClientTest: boolean;
|
||||
};
|
||||
|
||||
export type HttpApiConfigResponse = { applicationId: string; applicationName?: string; publicOrigin?: 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 };
|
||||
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;
|
||||
};
|
||||
|
||||
export type HttpWebhookEndpoint = { id: string; eventType: 'receipt' | 'uplink'; url: string; secretLast4: string; secret?: string; secretShownOnce?: boolean; status: string; lastTestAt?: string | null; lastTestStatus?: string | null; updatedAt: string };
|
||||
export type HttpWebhookEndpoint = {
|
||||
id: string;
|
||||
eventType: 'receipt' | 'uplink';
|
||||
url: string;
|
||||
secretLast4: string;
|
||||
secret?: string;
|
||||
secretShownOnce?: boolean;
|
||||
status: string;
|
||||
lastTestAt?: string | null;
|
||||
lastTestStatus?: string | null;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type HttpApiRequestLog = { id: string; requestId: string; clientMessageId?: string | null; sourceIp?: string | null; httpStatus?: number | null; businessCode?: string | null; status: string; durationMs?: number | null; createdAt: string; completedAt?: string | null };
|
||||
export type HttpApiRequestLog = {
|
||||
id: string;
|
||||
requestId: string;
|
||||
clientMessageId?: string | null;
|
||||
sourceIp?: string | null;
|
||||
httpStatus?: number | null;
|
||||
businessCode?: string | null;
|
||||
status: string;
|
||||
durationMs?: number | null;
|
||||
createdAt: string;
|
||||
completedAt?: string | null;
|
||||
};
|
||||
|
||||
export type HttpWebhookDelivery = { id: string; status: string; attemptCount: number; lastHttpStatus?: number | null; lastError?: string | null; createdAt: string; event: { eventId: string; eventType: string; messageId?: string | null }; endpoint: { eventType: string; url: string } };
|
||||
export type HttpWebhookDelivery = {
|
||||
id: string;
|
||||
status: string;
|
||||
attemptCount: number;
|
||||
lastHttpStatus?: number | null;
|
||||
lastError?: string | null;
|
||||
createdAt: string;
|
||||
event: { eventId: string; eventType: string; messageId?: string | null };
|
||||
endpoint: { eventType: string; url: string };
|
||||
};
|
||||
|
||||
export type EnterpriseApplication = {
|
||||
id: string;
|
||||
|
||||
Reference in New Issue
Block a user