feat: densify enterprise signature management

This commit is contained in:
hectorzhao
2026-09-02 10:04:58 +08:00
parent 1f2dfb5caf
commit 9e34757d6f
14 changed files with 240 additions and 119 deletions
@@ -1,8 +1,8 @@
import type { Dispatch, SetStateAction } from 'react';
import { ChevronDown, ChevronRight, Edit3, FileText, Plus } from 'lucide-react';
import { ArrowDown, ArrowUp, ChevronDown, ChevronRight, Edit3, Plus } from 'lucide-react';
import type { ClientSmsSignature } from '@/api/adminApi';
import { Button, CarrierTag, DeleteRiskAction, Pagination } from '@/components/ui';
import { AuditStatusTag, CarrierReportTag, readDrainagePayload, signatureCardVisual } from './signature.helpers';
import { Button, DeleteRiskAction, Pagination } from '@/components/ui';
import { AuditStatusTag, CarrierReportCount, formatSignatureName, readDrainagePayload, signatureCardVisual } from './signature.helpers';
import type { DrainageInfo } from './signature.types';
type EnterpriseSignaturesTableProps = {
@@ -13,13 +13,13 @@ type EnterpriseSignaturesTableProps = {
loadData: () => Promise<void>;
setDeleteTarget: Dispatch<SetStateAction<{ kind: 'drainage'; signatureId: string; id: string; name: string } | null>>;
setDrainageModal: Dispatch<SetStateAction<{ signatureId: string; item?: DrainageInfo } | null>>;
setDrainageReport: Dispatch<SetStateAction<{ signature: ClientSmsSignature; item: DrainageInfo } | null>>;
setDrainageStatusTarget: Dispatch<SetStateAction<{ signature: ClientSmsSignature; item: DrainageInfo } | null>>;
setExpandedSignatureId: Dispatch<SetStateAction<string>>;
setPage: Dispatch<SetStateAction<number>>;
setSignatureSort: (sort: 'asc' | 'desc') => void;
setReportStatusTarget: Dispatch<SetStateAction<ClientSmsSignature | null>>;
setSignatureModal: Dispatch<SetStateAction<ClientSmsSignature | 'new' | null>>;
setSignatureReport: Dispatch<SetStateAction<ClientSmsSignature | null>>;
signatureSort: 'asc' | 'desc';
total: number;
totalPages: number;
visibleSignatures: ClientSmsSignature[];
@@ -33,19 +33,37 @@ export function EnterpriseSignaturesTable({
loadData,
setDeleteTarget,
setDrainageModal,
setDrainageReport,
setDrainageStatusTarget,
setExpandedSignatureId,
setPage,
setSignatureSort,
setReportStatusTarget,
setSignatureModal,
setSignatureReport,
signatureSort,
total,
totalPages,
visibleSignatures,
}: EnterpriseSignaturesTableProps) {
return (
<div className="signature-list admin-enterprise-signature-list">
<div className="enterprise-signature-table__head" role="row">
<span aria-hidden="true" />
<span className="enterprise-signature-table__sortable">
<span className="enterprise-signature-table__sort-actions">
<Button aria-pressed={signatureSort === 'asc'} icon={<ArrowUp size={13} />} iconOnly onClick={() => setSignatureSort('asc')} size="sm" variant={signatureSort === 'asc' ? 'secondary' : 'ghost'}></Button>
<Button aria-pressed={signatureSort === 'desc'} icon={<ArrowDown size={13} />} iconOnly onClick={() => setSignatureSort('desc')} size="sm" variant={signatureSort === 'desc' ? 'secondary' : 'ghost'}></Button>
</span>
</span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
{visibleSignatures.map((signature) => {
const payload = readDrainagePayload(signature);
const visibleDrainageLinks = appliedDrainageKeyword
@@ -59,16 +77,15 @@ export function EnterpriseSignaturesTable({
<button aria-label="展开签名" onClick={() => setExpandedSignatureId(expanded ? '' : signature.id)} type="button">
{expanded ? <ChevronDown size={18} /> : <ChevronRight size={18} />}
</button>
<div><span></span><strong>{signature.name}</strong></div>
<div><span></span><span className="signature-summary__regular-value">{signature.tenant?.name ?? signature.tenantId}</span></div>
<div><span></span><span className="signature-summary__regular-value">{signature.application?.name ?? '-'}</span></div>
<div><span></span><AuditStatusTag status={signature.auditStatus} /></div>
<div><CarrierTag carrier="mobile" /><CarrierReportTag summary={signature.carrierReportSummary?.mobile} /></div>
<div><CarrierTag carrier="unicom" /><CarrierReportTag summary={signature.carrierReportSummary?.unicom} /></div>
<div><CarrierTag carrier="telecom" /><CarrierReportTag summary={signature.carrierReportSummary?.telecom} /></div>
<div><span></span><strong>{payload.links.length} </strong></div>
<div className="enterprise-signature-table__signature" data-label="签名"><strong>{formatSignatureName(signature.name)}</strong></div>
<div data-label="企业"><span className="signature-summary__regular-value">{signature.tenant?.name ?? signature.tenantId}</span></div>
<div data-label="应用"><span className="signature-summary__regular-value">{signature.application?.name ?? '-'}</span></div>
<div data-label="审核状态"><AuditStatusTag status={signature.auditStatus} /></div>
<div data-label="移动"><CarrierReportCount summary={signature.carrierReportSummary?.mobile} /></div>
<div data-label="联通"><CarrierReportCount summary={signature.carrierReportSummary?.unicom} /></div>
<div data-label="电信"><CarrierReportCount summary={signature.carrierReportSummary?.telecom} /></div>
<div data-label="引流信息"><strong>{payload.links.length} </strong></div>
<div className="signature-actions">
<Button icon={<FileText size={16} />} onClick={() => setSignatureReport(signature)} size="sm" variant="ghost"></Button>
<Button icon={<Edit3 size={16} />} onClick={() => setReportStatusTarget(signature)} size="sm" variant="ghost"></Button>
<Button icon={<Edit3 size={16} />} onClick={() => setSignatureModal(signature)} size="sm" variant="ghost"></Button>
<DeleteRiskAction onCompleted={() => void loadData()} portal="admin" targetId={signature.id} targetType="signature" />
@@ -82,9 +99,9 @@ export function EnterpriseSignaturesTable({
<div className="drainage-table__head">
<span>url或号码</span>
<span></span>
<CarrierTag carrier="mobile" />
<CarrierTag carrier="unicom" />
<CarrierTag carrier="telecom" />
<span></span>
<span></span>
<span></span>
<span></span>
</div>
{visibleDrainageLinks.map((item) => {
@@ -93,11 +110,10 @@ export function EnterpriseSignaturesTable({
<div className="drainage-table__row" key={item.id}>
<span className="drainage-table__url" title={item.url}>{item.url}</span>
<AuditStatusTag status={item.auditStatus ?? 'pending'} />
<CarrierReportTag summary={summary?.mobile} />
<CarrierReportTag summary={summary?.unicom} />
<CarrierReportTag summary={summary?.telecom} />
<CarrierReportCount summary={summary?.mobile} />
<CarrierReportCount summary={summary?.unicom} />
<CarrierReportCount summary={summary?.telecom} />
<span className="drainage-row-actions">
<Button onClick={() => setDrainageReport({ signature, item })} size="sm" variant="ghost"></Button>
<Button disabled={item.auditStatus !== 'approved'} onClick={() => setDrainageStatusTarget({ signature, item })} size="sm" variant="ghost"></Button>
<Button onClick={() => setDrainageModal({ signatureId: signature.id, item })} size="sm" variant="ghost"></Button>
<Button onClick={() => setDeleteTarget({ kind: 'drainage', signatureId: signature.id, id: item.id, name: item.url })} size="sm" variant="danger"></Button>