fix: harden real backend admin workflows and ui
This commit is contained in:
@@ -1,177 +0,0 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Eye, Search } from 'lucide-react';
|
||||
import { Breadcrumb, Button, Input, Modal, Select, Table, Tag, type TableColumn } from '@/components/ui';
|
||||
|
||||
type MmsAuditStatus = 'pending' | 'approved' | 'rejected';
|
||||
|
||||
type MmsTemplateAudit = {
|
||||
id: string;
|
||||
name: string;
|
||||
application: string;
|
||||
subject: string;
|
||||
sizeKb: number;
|
||||
enterprise: string;
|
||||
submittedAt: string;
|
||||
status: MmsAuditStatus;
|
||||
image: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '全部状态', value: 'all' },
|
||||
{ label: '待审核', value: 'pending' },
|
||||
{ label: '已通过', value: 'approved' },
|
||||
{ label: '已拒绝', value: 'rejected' },
|
||||
];
|
||||
|
||||
const statusLabelMap: Record<MmsAuditStatus, string> = {
|
||||
pending: '待审核',
|
||||
approved: '已通过',
|
||||
rejected: '已拒绝',
|
||||
};
|
||||
|
||||
const statusToneMap: Record<MmsAuditStatus, 'warning' | 'success' | 'danger'> = {
|
||||
pending: 'warning',
|
||||
approved: 'success',
|
||||
rejected: 'danger',
|
||||
};
|
||||
|
||||
const initialMmsAudits: MmsTemplateAudit[] = [
|
||||
{
|
||||
id: 'MMS-TPL-20260319-001',
|
||||
name: '春季上新图文推广',
|
||||
application: '营销活动彩信',
|
||||
subject: '【星云科技】春季新品发布',
|
||||
sizeKb: 1450,
|
||||
enterprise: '北京星云科技有限公司',
|
||||
submittedAt: '2026-03-19 11:15:20',
|
||||
status: 'pending',
|
||||
image: 'https://images.unsplash.com/photo-1434494878577-86c23bcb06b9?auto=format&fit=crop&w=900&q=80',
|
||||
content: '春季新品重磅发布,限时优惠价299元起,前100名购买送精美礼品一份。',
|
||||
},
|
||||
{
|
||||
id: 'MMS-TPL-20260319-002',
|
||||
name: '端午节大促视频',
|
||||
application: '节日促销彩信',
|
||||
subject: '【蓝海科技】端午狂欢最高满减',
|
||||
sizeKb: 1850,
|
||||
enterprise: '上海蓝海科技有限公司',
|
||||
submittedAt: '2026-03-18 09:30:10',
|
||||
status: 'pending',
|
||||
image: 'https://images.unsplash.com/photo-1607083206968-13611e3d76db?auto=format&fit=crop&w=900&q=80',
|
||||
content: '端午节会员福利开启,精选商品满299减50,满599减120,数量有限。',
|
||||
},
|
||||
{
|
||||
id: 'MMS-TPL-20260318-001',
|
||||
name: '新用户欢迎礼包',
|
||||
application: '会员运营彩信',
|
||||
subject: '【飞跃传媒】新老用户专享福利',
|
||||
sizeKb: 850,
|
||||
enterprise: '广州飞跃文化传媒有限公司',
|
||||
submittedAt: '2026-03-17 14:20:05',
|
||||
status: 'approved',
|
||||
image: 'https://images.unsplash.com/photo-1567427017947-545c5f8d16ad?auto=format&fit=crop&w=900&q=80',
|
||||
content: '欢迎加入会员中心,新用户可领取专属礼包和本月优惠券。',
|
||||
},
|
||||
{
|
||||
id: 'MMS-TPL-20260317-001',
|
||||
name: '理财产品营销违规',
|
||||
application: '金融营销彩信',
|
||||
subject: '【理财通】高收益理财推荐',
|
||||
sizeKb: 1950,
|
||||
enterprise: '深圳前海贸易有限公司',
|
||||
submittedAt: '2026-03-16 16:45:30',
|
||||
status: 'rejected',
|
||||
image: 'https://images.unsplash.com/photo-1554224155-6726b3ff858f?auto=format&fit=crop&w=900&q=80',
|
||||
content: '精选高收益理财产品推荐,限时申购,活动名额有限。',
|
||||
},
|
||||
];
|
||||
|
||||
export function AdminSignatureAuditPage() {
|
||||
const [records, setRecords] = useState(initialMmsAudits);
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [status, setStatus] = useState('all');
|
||||
const [previewRecord, setPreviewRecord] = useState<MmsTemplateAudit | null>(null);
|
||||
|
||||
const filteredRecords = useMemo(
|
||||
() => records.filter((record) => {
|
||||
const matchesKeyword = !keyword || `${record.name}${record.enterprise}`.includes(keyword);
|
||||
const matchesStatus = status === 'all' || record.status === status;
|
||||
return matchesKeyword && matchesStatus;
|
||||
}),
|
||||
[keyword, records, status],
|
||||
);
|
||||
|
||||
function updateStatus(id: string, nextStatus: MmsAuditStatus) {
|
||||
setRecords((items) => items.map((item) => (item.id === id ? { ...item, status: nextStatus } : item)));
|
||||
}
|
||||
|
||||
const columns: Array<TableColumn<MmsTemplateAudit>> = [
|
||||
{ key: 'id', title: '模板编号', render: (record) => <span className="muted">{record.id}</span> },
|
||||
{ key: 'name', title: '模板名称', render: (record) => <strong>{record.name}</strong> },
|
||||
{ key: 'application', title: '彩信应用', render: (record) => record.application },
|
||||
{ key: 'subject', title: '彩信主题', render: (record) => record.subject },
|
||||
{ key: 'sizeKb', title: '大小(KB)', render: (record) => record.sizeKb },
|
||||
{ key: 'enterprise', title: '归属企业', render: (record) => record.enterprise },
|
||||
{ key: 'submittedAt', title: '提交时间', render: (record) => record.submittedAt },
|
||||
{ key: 'status', title: '状态', render: (record) => <Tag tone={statusToneMap[record.status]}>{statusLabelMap[record.status]}</Tag> },
|
||||
{
|
||||
key: 'actions',
|
||||
title: '操作',
|
||||
align: 'right',
|
||||
render: (record) => (
|
||||
<div className="audit-actions">
|
||||
<button className="audit-link" onClick={() => setPreviewRecord(record)} type="button"><Eye size={16} />预览</button>
|
||||
{record.status === 'pending' ? (
|
||||
<>
|
||||
<button className="audit-link audit-link--success" onClick={() => updateStatus(record.id, 'approved')} type="button">通过</button>
|
||||
<button className="audit-link audit-link--danger" onClick={() => updateStatus(record.id, 'rejected')} type="button">拒绝</button>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="page-stack admin-audit-page">
|
||||
<Breadcrumb items={['审核中心', '彩信模板审核']} />
|
||||
|
||||
<div className="surface audit-filter-card">
|
||||
<div className="audit-filter-grid audit-filter-grid--enterprise">
|
||||
<Input label="模板名称/企业名称" onChange={(event) => setKeyword(event.target.value)} placeholder="请输入模板名称或企业名称" value={keyword} />
|
||||
<Select label="审核状态" onChange={(event) => setStatus(event.target.value)} options={statusOptions} value={status} />
|
||||
<div className="audit-filter-actions">
|
||||
<Button icon={<Search size={17} />}>查询</Button>
|
||||
<Button onClick={() => { setKeyword(''); setStatus('all'); }} variant="ghost">重置</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="surface audit-table-card mms-audit-table">
|
||||
<Table columns={columns} data={filteredRecords} rowKey="id" />
|
||||
<div className="audit-pagination">
|
||||
<span>共 {filteredRecords.length} 条</span>
|
||||
<Button disabled size="sm" variant="ghost">上一页</Button>
|
||||
<Button size="sm" variant="secondary">1</Button>
|
||||
<Button disabled size="sm" variant="ghost">下一页</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
footer={<Button onClick={() => setPreviewRecord(null)}>关闭</Button>}
|
||||
onClose={() => setPreviewRecord(null)}
|
||||
open={Boolean(previewRecord)}
|
||||
title={<div className="template-modal-title"><h2>彩信预览</h2><p>{previewRecord?.name}</p></div>}
|
||||
>
|
||||
{previewRecord ? (
|
||||
<div className="mms-preview">
|
||||
<img alt={previewRecord.name} src={previewRecord.image} />
|
||||
<h3>{previewRecord.subject}</h3>
|
||||
<p>{previewRecord.content}</p>
|
||||
</div>
|
||||
) : null}
|
||||
</Modal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user