feat: complete reporting and filing workflows
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Check, Eye, Search, X } from 'lucide-react';
|
||||
import { adminApi, type FileRef, type SmsDrainageInfo } from '@/api/adminApi';
|
||||
import { Breadcrumb, Button, FileActions, Input, Modal, Select, Table, Tag, Textarea, type TableColumn } from '@/components/ui';
|
||||
import { AuditReviewInfo, Breadcrumb, Button, FileActions, Input, Modal, Select, Table, Tabs, Tag, Textarea, type TableColumn } from '@/components/ui';
|
||||
import { formatDateTime } from '@/utils/dateTime';
|
||||
import { ReportImportAuditPanel } from './ReportImportAuditPanel';
|
||||
|
||||
const statusMeta: Record<string, { label: string; tone: 'neutral' | 'info' | 'success' | 'danger' }> = {
|
||||
pending: { label: '待审核', tone: 'info' },
|
||||
@@ -32,6 +33,7 @@ function DrainageDetail({ item, onClose }: { item: SmsDrainageInfo; onClose: ()
|
||||
<div><span>站名称</span><strong>{item.siteName}</strong></div>
|
||||
<div><span>引流地址</span><strong>{item.url}</strong></div>
|
||||
<div><span>提交时间</span><strong>{formatDateTime(item.submittedAt)}</strong></div>
|
||||
<AuditReviewInfo targetId={item.id} targetType="sms_drainage_info" />
|
||||
<div className="detail-grid__wide"><span>备注</span><strong>{item.remark || '-'}</strong></div>
|
||||
{item.rejectReason ? <div className="detail-grid__wide"><span>驳回原因</span><strong>{item.rejectReason}</strong></div> : null}
|
||||
</div>
|
||||
@@ -86,8 +88,10 @@ export function AdminDrainageAuditPage() {
|
||||
return <section className="page-stack admin-template-audit-page">
|
||||
<div className="page-heading"><div><Breadcrumb items={['审核中心', '引流信息审核']} /><h1>引流信息审核</h1></div></div>
|
||||
{error ? <p className="form-error">{error}</p> : null}
|
||||
<div className="surface audit-filter-card"><div className="audit-filter-grid audit-filter-grid--template"><Input label="搜索" onChange={(event) => setKeyword(event.target.value)} placeholder="搜索企业、应用、签名、站点或网址" prefix={<Search size={16} />} value={keyword} /><Select label="审核状态" onChange={(event) => setStatus(event.target.value)} options={[{ label: '全部状态', value: 'all' }, { label: '待审核', value: 'pending' }, { label: '已通过', value: 'approved' }, { label: '已驳回', value: 'rejected' }]} value={status} /><div className="audit-filter-actions"><Button icon={<Search size={17} />} onClick={loadData}>查询</Button><Button onClick={() => { setKeyword(''); setStatus('pending'); }} variant="ghost">重置</Button></div></div></div>
|
||||
<div className="surface"><Table columns={columns} data={items} emptyText="暂无引流信息审核记录" rowKey="id" /></div>
|
||||
<Tabs items={[
|
||||
{ label: '单条引流信息审核', value: 'single', content: <div className="page-stack"><div className="surface audit-filter-card"><div className="audit-filter-grid audit-filter-grid--template"><Input label="搜索" onChange={(event) => setKeyword(event.target.value)} placeholder="搜索企业、应用、签名、站点或网址" prefix={<Search size={16} />} value={keyword} /><Select label="审核状态" onChange={(event) => setStatus(event.target.value)} options={[{ label: '全部状态', value: 'all' }, { label: '待审核', value: 'pending' }, { label: '已通过', value: 'approved' }, { label: '已驳回', value: 'rejected' }]} value={status} /><div className="audit-filter-actions"><Button icon={<Search size={17} />} onClick={loadData}>查询</Button><Button onClick={() => { setKeyword(''); setStatus('pending'); }} variant="ghost">重置</Button></div></div></div><div className="surface"><Table columns={columns} data={items} emptyText="暂无引流信息审核记录" rowKey="id" /></div></div> },
|
||||
{ label: '导入批次审核', value: 'import', content: <ReportImportAuditPanel reportType="drainage" /> },
|
||||
]} />
|
||||
{detail ? <DrainageDetail item={detail} onClose={() => setDetail(undefined)} /> : null}
|
||||
<Modal footer={<><Button onClick={() => setRejectTarget(undefined)} variant="ghost">取消</Button><Button disabled={!reason.trim()} onClick={() => void reject()} variant="danger">确认驳回</Button></>} onClose={() => setRejectTarget(undefined)} open={Boolean(rejectTarget)} title="驳回引流信息"><Textarea label="驳回原因" onChange={(event) => setReason(event.target.value)} rows={4} value={reason} /></Modal>
|
||||
</section>;
|
||||
|
||||
Reference in New Issue
Block a user