feat: wire admin workflows to real APIs
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Trash2 } from 'lucide-react';
|
||||
import { Breadcrumb, Button, Table, type TableColumn } from '@/components/ui';
|
||||
import { Plus, Search, Trash2 } from 'lucide-react';
|
||||
import { Breadcrumb, Button, Input, Modal, Table, Textarea, type TableColumn } from '@/components/ui';
|
||||
|
||||
type EnterpriseBlacklistItem = {
|
||||
id: string;
|
||||
@@ -19,8 +19,24 @@ const initialItems: EnterpriseBlacklistItem[] = [
|
||||
{ id: 'EBL20260630004', enterprise: '重庆香惠慧', application: '客服应用', phone: '18800000555', createdAt: '2026-06-24 18:01:10', reason: '敏感投诉号码', expiredAt: '2026-07-24 23:59:59' },
|
||||
];
|
||||
|
||||
function nowText() {
|
||||
return new Date().toLocaleString('zh-CN', { hour12: false }).replace(/\//g, '-');
|
||||
}
|
||||
|
||||
export function AdminEnterpriseBlacklistPage() {
|
||||
const [items, setItems] = useState(initialItems);
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [enterprise, setEnterprise] = useState('');
|
||||
const [application, setApplication] = useState('');
|
||||
const [phone, setPhone] = useState('');
|
||||
const [reason, setReason] = useState('');
|
||||
const [expiredAt, setExpiredAt] = useState('');
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
|
||||
const filteredItems = useMemo(() => items.filter((item) => {
|
||||
const text = [item.enterprise, item.application, item.phone, item.reason].join(' ');
|
||||
return !keyword || text.includes(keyword);
|
||||
}), [items, keyword]);
|
||||
|
||||
const columns = useMemo<Array<TableColumn<EnterpriseBlacklistItem>>>(() => [
|
||||
{ key: 'enterprise', title: '企业名称', width: '180px', render: (record) => <strong>{record.enterprise}</strong> },
|
||||
@@ -42,6 +58,29 @@ export function AdminEnterpriseBlacklistPage() {
|
||||
},
|
||||
], []);
|
||||
|
||||
function resetForm() {
|
||||
setEnterprise('');
|
||||
setApplication('');
|
||||
setPhone('');
|
||||
setReason('');
|
||||
setExpiredAt('');
|
||||
}
|
||||
|
||||
function addItem() {
|
||||
const nextItem: EnterpriseBlacklistItem = {
|
||||
id: `EBL${Date.now()}`,
|
||||
enterprise: enterprise || '未命名企业',
|
||||
application: application || '默认应用',
|
||||
phone: phone || '待补充号码',
|
||||
createdAt: nowText(),
|
||||
reason: reason || '运营手动加入',
|
||||
expiredAt: expiredAt || '永久有效',
|
||||
};
|
||||
setItems((current) => [nextItem, ...current]);
|
||||
resetForm();
|
||||
setModalOpen(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="page-stack admin-security-page">
|
||||
<div className="page-heading">
|
||||
@@ -49,11 +88,46 @@ export function AdminEnterpriseBlacklistPage() {
|
||||
<Breadcrumb items={['安全控制', '企业黑名单']} />
|
||||
<h1>企业黑名单</h1>
|
||||
</div>
|
||||
<Button icon={<Plus size={16} />} onClick={() => setModalOpen(true)}>添加黑名单</Button>
|
||||
</div>
|
||||
|
||||
<div className="surface admin-security-filter">
|
||||
<Input
|
||||
label="搜索"
|
||||
onChange={(event) => setKeyword(event.target.value)}
|
||||
placeholder="搜索企业、应用、手机号或原因"
|
||||
prefix={<Search size={16} />}
|
||||
value={keyword}
|
||||
/>
|
||||
<div className="admin-security-filter__actions">
|
||||
<Button icon={<Search size={16} />}>查询</Button>
|
||||
<Button onClick={() => setKeyword('')} variant="ghost">重置</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="surface admin-security-table-card">
|
||||
<Table columns={columns} data={items} emptyText="暂无企业黑名单记录" rowKey="id" />
|
||||
<Table columns={columns} data={filteredItems} emptyText="暂无企业黑名单记录" rowKey="id" />
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
footer={(
|
||||
<>
|
||||
<Button onClick={() => setModalOpen(false)} variant="ghost">取消</Button>
|
||||
<Button onClick={addItem}>确认添加</Button>
|
||||
</>
|
||||
)}
|
||||
onClose={() => setModalOpen(false)}
|
||||
open={modalOpen}
|
||||
title="添加企业黑名单"
|
||||
>
|
||||
<div className="admin-security-form">
|
||||
<Input label="企业名称" onChange={(event) => setEnterprise(event.target.value)} placeholder="请输入企业名称" value={enterprise} />
|
||||
<Input label="应用名称" onChange={(event) => setApplication(event.target.value)} placeholder="请输入应用名称" value={application} />
|
||||
<Input label="手机号码" onChange={(event) => setPhone(event.target.value)} placeholder="请输入手机号码" value={phone} />
|
||||
<Input label="过期时间" onChange={(event) => setExpiredAt(event.target.value)} placeholder="例如 2026-12-31 23:59:59" value={expiredAt} />
|
||||
<Textarea label="入库原因" onChange={(event) => setReason(event.target.value)} placeholder="请输入入库原因" rows={3} value={reason} />
|
||||
</div>
|
||||
</Modal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user