fix: hide deleted signatures and fit uplink table
This commit is contained in:
@@ -142,6 +142,19 @@ describe('SignatureRetirementService dimensions', () => {
|
||||
page: 2,
|
||||
pageSize: 10,
|
||||
});
|
||||
const query = prisma.$queryRaw.mock.calls[0]?.[0] as { strings?: readonly string[] };
|
||||
expect(query.strings?.join('?')).toContain('signature."auditStatus" <> \'deleted\'');
|
||||
});
|
||||
|
||||
it('does not count deleted signatures as unread retirement warnings', async () => {
|
||||
const prisma = { $queryRaw: jest.fn().mockResolvedValue([{ count: 2 }]) };
|
||||
const unreadService = new SignatureRetirementService(prisma as never);
|
||||
|
||||
await expect(unreadService.unreadCount()).resolves.toEqual({ count: 2 });
|
||||
const query = prisma.$queryRaw.mock.calls[0]?.[0] as { strings?: readonly string[] };
|
||||
const sql = query.strings?.join('?') ?? '';
|
||||
expect(sql).toContain('JOIN "SmsSignature" signature ON signature.id = detection."signatureId"');
|
||||
expect(sql).toContain('signature."auditStatus" <> \'deleted\'');
|
||||
});
|
||||
|
||||
it('requires a reason for temporary and permanent suppression', async () => {
|
||||
|
||||
@@ -128,6 +128,7 @@ export class SignatureRetirementService implements OnModuleInit, OnModuleDestroy
|
||||
LEFT JOIN "SmsApplication" application ON application.id = detection."applicationId"
|
||||
WHERE message."createdAt" >= ${range?.gte}
|
||||
AND message."createdAt" <= ${range?.lte}
|
||||
AND signature."auditStatus" <> 'deleted'
|
||||
AND (${dimensionType}::text IS NULL OR detection."dimensionType" = ${dimensionType})
|
||||
AND (${tenantId}::text IS NULL OR detection."tenantId" = ${tenantId})
|
||||
AND (${applicationId}::text IS NULL OR application.id = ${applicationId})
|
||||
@@ -167,8 +168,18 @@ export class SignatureRetirementService implements OnModuleInit, OnModuleDestroy
|
||||
|
||||
async unreadCount() {
|
||||
const range = shanghaiDateRange(shanghaiDateKey(), shanghaiDateKey());
|
||||
const count = await this.prisma.signatureRetirementMessage.count({ where: { createdAt: range, isRead: false, suppressed: false } });
|
||||
return { count };
|
||||
const rows = await this.prisma.$queryRaw<Array<{ count: number }>>(Prisma.sql`
|
||||
SELECT COUNT(*)::integer AS count
|
||||
FROM "SignatureRetirementMessage" message
|
||||
JOIN "SignatureRetirementDetection" detection ON detection.id = message."detectionId"
|
||||
JOIN "SmsSignature" signature ON signature.id = detection."signatureId"
|
||||
WHERE message."createdAt" >= ${range?.gte}
|
||||
AND message."createdAt" <= ${range?.lte}
|
||||
AND message."isRead" = FALSE
|
||||
AND message.suppressed = FALSE
|
||||
AND signature."auditStatus" <> 'deleted'
|
||||
`);
|
||||
return { count: rows[0]?.count ?? 0 };
|
||||
}
|
||||
|
||||
async markRead(id: string) {
|
||||
|
||||
@@ -283,20 +283,20 @@ export function AdminSmsUplinkRecordsPage() {
|
||||
{
|
||||
key: 'select',
|
||||
title: '',
|
||||
width: '72px',
|
||||
width: '48px',
|
||||
align: 'center',
|
||||
render: () => <input aria-label="选择上行记录" className="admin-uplink-checkbox" type="checkbox" />,
|
||||
},
|
||||
{ key: 'phoneNumber', title: '手机号码', width: '170px', render: (record) => <strong>{record.phoneNumber}</strong> },
|
||||
{ key: 'receivedAt', title: '上行时间', width: '220px', render: (record) => <strong>{getTime(record.receivedAt)}</strong> },
|
||||
{ key: 'content', title: '上行内容', width: '360px', render: (record) => <span className="uplink-content" title={record.content}>{record.content}</span> },
|
||||
{ key: 'channel', title: '上行通道', width: '260px', render: (record) => <strong>{record.channel?.name ?? record.channelId}</strong> },
|
||||
{ key: 'accessNo', title: '上行接入号', width: '180px', render: (record) => <strong>{record.destId}</strong> },
|
||||
{ key: 'matchStatus', title: '匹配状态', width: '140px', render: (record) => <strong>{matchStatusText(record.matchStatus)}</strong> },
|
||||
{ key: 'phoneNumber', title: '手机号码', width: '120px', render: (record) => <strong>{record.phoneNumber}</strong> },
|
||||
{ key: 'receivedAt', title: '上行时间', width: '156px', render: (record) => <strong>{getTime(record.receivedAt)}</strong> },
|
||||
{ key: 'content', title: '上行内容', width: '260px', render: (record) => <span className="uplink-content" title={record.content}>{record.content}</span> },
|
||||
{ key: 'channel', title: '上行通道', width: '160px', render: (record) => <strong>{record.channel?.name ?? record.channelId}</strong> },
|
||||
{ key: 'accessNo', title: '上行接入号', width: '120px', render: (record) => <strong>{record.destId}</strong> },
|
||||
{ key: 'matchStatus', title: '匹配状态', width: '100px', render: (record) => <strong>{matchStatusText(record.matchStatus)}</strong> },
|
||||
{
|
||||
key: 'actions',
|
||||
title: '操作',
|
||||
width: '140px',
|
||||
width: '88px',
|
||||
align: 'center',
|
||||
render: (record) => (
|
||||
<button className="admin-uplink-detail-link" onClick={() => openDetail(record)} type="button">查看详情</button>
|
||||
|
||||
+11
-1
@@ -7791,7 +7791,17 @@
|
||||
}
|
||||
|
||||
.admin-uplink-table-card .ui-table {
|
||||
min-width: 1500px;
|
||||
min-width: 1052px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.admin-uplink-table-card .uplink-content {
|
||||
-webkit-line-clamp: 2;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.admin-uplink-table-card .ui-table td strong {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.gateway-exception-list-heading {
|
||||
|
||||
Reference in New Issue
Block a user