feat: build reporting workbench workflow
This commit is contained in:
@@ -1,8 +1,15 @@
|
||||
import type { Dispatch, SetStateAction } from 'react';
|
||||
import { ChevronDown, ChevronRight, Edit3, Plus, Triangle } from 'lucide-react';
|
||||
import type { ClientSmsSignature } from '@/api/adminApi';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button, DeleteRiskAction, Pagination } from '@/components/ui';
|
||||
import { AuditStatusTag, CarrierReportCount, formatSignatureName, readDrainagePayload, signatureCardVisual } from './signature.helpers';
|
||||
import {
|
||||
AuditStatusTag,
|
||||
CarrierReportCount,
|
||||
formatSignatureName,
|
||||
readDrainagePayload,
|
||||
signatureCardVisual,
|
||||
} from './signature.helpers';
|
||||
import type { DrainageInfo } from './signature.types';
|
||||
|
||||
type EnterpriseSignaturesTableProps = {
|
||||
@@ -44,6 +51,7 @@ export function EnterpriseSignaturesTable({
|
||||
totalPages,
|
||||
visibleSignatures,
|
||||
}: EnterpriseSignaturesTableProps) {
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<div className="signature-list admin-enterprise-signature-list">
|
||||
<div className="enterprise-signature-table__head" role="row">
|
||||
@@ -51,8 +59,33 @@ export function EnterpriseSignaturesTable({
|
||||
<span className="enterprise-signature-table__sortable">
|
||||
签名
|
||||
<span className="enterprise-signature-table__sort-actions">
|
||||
<Button aria-pressed={signatureSort === 'asc'} icon={<Triangle aria-hidden="true" fill="currentColor" size={11} />} iconOnly onClick={() => setSignatureSort('asc')} size="sm" variant={signatureSort === 'asc' ? 'secondary' : 'ghost'}>签名升序</Button>
|
||||
<Button aria-pressed={signatureSort === 'desc'} icon={<Triangle aria-hidden="true" className="enterprise-signature-table__sort-triangle--down" fill="currentColor" size={11} />} iconOnly onClick={() => setSignatureSort('desc')} size="sm" variant={signatureSort === 'desc' ? 'secondary' : 'ghost'}>签名降序</Button>
|
||||
<Button
|
||||
aria-pressed={signatureSort === 'asc'}
|
||||
icon={<Triangle aria-hidden="true" fill="currentColor" size={11} />}
|
||||
iconOnly
|
||||
onClick={() => setSignatureSort('asc')}
|
||||
size="sm"
|
||||
variant={signatureSort === 'asc' ? 'secondary' : 'ghost'}
|
||||
>
|
||||
签名升序
|
||||
</Button>
|
||||
<Button
|
||||
aria-pressed={signatureSort === 'desc'}
|
||||
icon={
|
||||
<Triangle
|
||||
aria-hidden="true"
|
||||
className="enterprise-signature-table__sort-triangle--down"
|
||||
fill="currentColor"
|
||||
size={11}
|
||||
/>
|
||||
}
|
||||
iconOnly
|
||||
onClick={() => setSignatureSort('desc')}
|
||||
size="sm"
|
||||
variant={signatureSort === 'desc' ? 'secondary' : 'ghost'}
|
||||
>
|
||||
签名降序
|
||||
</Button>
|
||||
</span>
|
||||
</span>
|
||||
<span>企业</span>
|
||||
@@ -62,33 +95,92 @@ export function EnterpriseSignaturesTable({
|
||||
<span>联通</span>
|
||||
<span>电信</span>
|
||||
<span>引流信息</span>
|
||||
<span>待生成明细</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
{visibleSignatures.map((signature) => {
|
||||
const payload = readDrainagePayload(signature);
|
||||
const visibleDrainageLinks = appliedDrainageKeyword
|
||||
? payload.links.filter((item) => `${item.siteName} ${item.url} ${item.remark}`.includes(appliedDrainageKeyword))
|
||||
? payload.links.filter((item) =>
|
||||
`${item.siteName} ${item.url} ${item.remark}`.includes(appliedDrainageKeyword),
|
||||
)
|
||||
: payload.links;
|
||||
const cardVisual = signatureCardVisual(signature.auditStatus, signature.carrierReportSummary);
|
||||
const expanded = expandedSignatureId === signature.id || Boolean(appliedDrainageKeyword);
|
||||
return (
|
||||
<article aria-label={`签名总体状态:${cardVisual.label}`} className={`signature-card signature-card--${cardVisual.tone}`} key={signature.id} title={`总体状态:${cardVisual.label}`}>
|
||||
<article
|
||||
aria-label={`签名总体状态:${cardVisual.label}`}
|
||||
className={`signature-card signature-card--${cardVisual.tone}`}
|
||||
key={signature.id}
|
||||
title={`总体状态:${cardVisual.label}`}
|
||||
>
|
||||
<div className="signature-summary">
|
||||
<button aria-label="展开签名" onClick={() => setExpandedSignatureId(expanded ? '' : signature.id)} type="button">
|
||||
<button
|
||||
aria-label="展开签名"
|
||||
onClick={() => setExpandedSignatureId(expanded ? '' : signature.id)}
|
||||
type="button"
|
||||
>
|
||||
{expanded ? <ChevronDown size={18} /> : <ChevronRight size={18} />}
|
||||
</button>
|
||||
<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="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 data-label="待生成明细">
|
||||
<Button
|
||||
disabled={!signature.pendingReportDetailCount}
|
||||
onClick={() =>
|
||||
navigate(`/admin/report-tasks?signatureId=${encodeURIComponent(signature.id)}&scope=pending`)
|
||||
}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
{signature.pendingReportDetailCount ?? 0} 条
|
||||
</Button>
|
||||
</div>
|
||||
<div className="signature-actions">
|
||||
<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" />
|
||||
<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"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{expanded ? (
|
||||
@@ -107,25 +199,61 @@ export function EnterpriseSignaturesTable({
|
||||
{visibleDrainageLinks.map((item) => {
|
||||
const summary = signature.drainageCarrierReportSummary?.[item.id];
|
||||
return (
|
||||
<div className="drainage-table__row" key={item.id}>
|
||||
<span className="drainage-table__url" title={item.url}>{item.url}</span>
|
||||
<AuditStatusTag status={item.auditStatus ?? 'pending'} />
|
||||
<CarrierReportCount summary={summary?.mobile} />
|
||||
<CarrierReportCount summary={summary?.unicom} />
|
||||
<CarrierReportCount summary={summary?.telecom} />
|
||||
<span className="drainage-row-actions">
|
||||
<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>
|
||||
</span>
|
||||
</div>
|
||||
);})}
|
||||
<div className="drainage-table__row" key={item.id}>
|
||||
<span className="drainage-table__url" title={item.url}>
|
||||
{item.url}
|
||||
</span>
|
||||
<AuditStatusTag status={item.auditStatus ?? 'pending'} />
|
||||
<CarrierReportCount summary={summary?.mobile} />
|
||||
<CarrierReportCount summary={summary?.unicom} />
|
||||
<CarrierReportCount summary={summary?.telecom} />
|
||||
<span className="drainage-row-actions">
|
||||
<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>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<p className="muted">暂无引流信息</p>
|
||||
)}
|
||||
<div className="drainage-panel__footer">
|
||||
<Button icon={<Plus size={16} />} onClick={() => setDrainageModal({ signatureId: signature.id })} size="sm" variant="ghost">添加引流信息</Button>
|
||||
<Button
|
||||
icon={<Plus size={16} />}
|
||||
onClick={() => setDrainageModal({ signatureId: signature.id })}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
添加引流信息
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user