fix: connect remaining sms pages to real backend
This commit is contained in:
@@ -1,130 +1,61 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Plus, Search, Trash2 } from 'lucide-react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Plus, Search } from 'lucide-react';
|
||||
import { Breadcrumb, Button, Input, Modal, Select, Table, type TableColumn } from '@/components/ui';
|
||||
import { adminApi, type DictionaryItem } from '@/api/adminApi';
|
||||
|
||||
type PhoneSegment = {
|
||||
id: string;
|
||||
segment: string;
|
||||
carrier: string;
|
||||
province: string;
|
||||
city: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
type PhoneSegment = DictionaryItem & {
|
||||
prefix?: string;
|
||||
carrier?: string;
|
||||
province?: string | null;
|
||||
city?: string | null;
|
||||
};
|
||||
|
||||
const initialSegments: PhoneSegment[] = [
|
||||
{ id: 'SEG20260630001', segment: '1367556', carrier: '中国移动', province: '四川省', city: '成都市', createdAt: '2026-06-11 09:30:12', updatedAt: '2026-06-28 15:40:00' },
|
||||
{ id: 'SEG20260630002', segment: '1860763', carrier: '中国联通', province: '重庆市', city: '重庆市', createdAt: '2026-06-12 10:18:44', updatedAt: '2026-06-27 11:22:13' },
|
||||
{ id: 'SEG20260630003', segment: '1525066', carrier: '中国电信', province: '江苏省', city: '南京市', createdAt: '2026-06-15 14:22:31', updatedAt: '2026-06-26 17:05:39' },
|
||||
{ id: 'SEG20260630004', segment: '1501234', carrier: '中国移动', province: '广东省', city: '深圳市', createdAt: '2026-06-18 16:10:25', updatedAt: '2026-06-24 09:15:26' },
|
||||
];
|
||||
|
||||
function createSegmentId() {
|
||||
return `SEG${Date.now()}`;
|
||||
}
|
||||
|
||||
type SegmentFormModalProps = {
|
||||
item?: PhoneSegment;
|
||||
onClose: () => void;
|
||||
onSubmit: (item: PhoneSegment) => void;
|
||||
};
|
||||
|
||||
function SegmentFormModal({ item, onClose, onSubmit }: SegmentFormModalProps) {
|
||||
const [form, setForm] = useState<PhoneSegment>(() => item ?? {
|
||||
id: createSegmentId(),
|
||||
segment: '',
|
||||
carrier: '中国移动',
|
||||
province: '',
|
||||
city: '',
|
||||
createdAt: '2026-06-30 10:00:00',
|
||||
updatedAt: '2026-06-30 10:00:00',
|
||||
});
|
||||
|
||||
function updateField<Key extends keyof PhoneSegment>(key: Key, value: PhoneSegment[Key]) {
|
||||
setForm((current) => ({ ...current, [key]: value }));
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
footer={(
|
||||
<>
|
||||
<Button onClick={onClose} variant="ghost">取消</Button>
|
||||
<Button onClick={() => onSubmit({ ...form, updatedAt: '2026-06-30 10:00:00' })}>保存</Button>
|
||||
</>
|
||||
)}
|
||||
onClose={onClose}
|
||||
open
|
||||
title={item ? '编辑手机号段' : '新增手机号段'}
|
||||
>
|
||||
<div className="admin-system-modal-form">
|
||||
<Input label="手机号段" maxLength={7} onChange={(event) => updateField('segment', event.target.value)} placeholder="手机号码前7位" value={form.segment} />
|
||||
<Select
|
||||
label="运营商"
|
||||
onChange={(event) => updateField('carrier', event.target.value)}
|
||||
options={[
|
||||
{ label: '中国移动', value: '中国移动' },
|
||||
{ label: '中国联通', value: '中国联通' },
|
||||
{ label: '中国电信', value: '中国电信' },
|
||||
]}
|
||||
value={form.carrier}
|
||||
/>
|
||||
<Input label="省份" onChange={(event) => updateField('province', event.target.value)} value={form.province} />
|
||||
<Input label="城市" onChange={(event) => updateField('city', event.target.value)} value={form.city} />
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export function AdminPhoneSegmentsPage() {
|
||||
const [segments, setSegments] = useState(initialSegments);
|
||||
const [segments, setSegments] = useState<PhoneSegment[]>([]);
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [editingSegment, setEditingSegment] = useState<PhoneSegment | null>(null);
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [prefix, setPrefix] = useState('');
|
||||
const [carrier, setCarrier] = useState('中国移动');
|
||||
const [province, setProvince] = useState('');
|
||||
const [city, setCity] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
function loadData() {
|
||||
adminApi.listPhoneSegments()
|
||||
.then((items) => {
|
||||
setSegments(items as PhoneSegment[]);
|
||||
setError('');
|
||||
})
|
||||
.catch((failure: Error) => setError(failure.message || '手机号段加载失败'));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, []);
|
||||
|
||||
const filteredSegments = useMemo(
|
||||
() => segments.filter((segment) => [segment.segment, segment.carrier, segment.province, segment.city].some((value) => value.includes(keyword))),
|
||||
() => segments.filter((segment) => [segment.prefix, segment.carrier, segment.province, segment.city].some((value) => String(value ?? '').includes(keyword))),
|
||||
[keyword, segments],
|
||||
);
|
||||
|
||||
function upsertSegment(nextSegment: PhoneSegment) {
|
||||
setSegments((current) => {
|
||||
const exists = current.some((item) => item.id === nextSegment.id);
|
||||
if (exists) {
|
||||
return current.map((item) => (item.id === nextSegment.id ? nextSegment : item));
|
||||
}
|
||||
|
||||
return [nextSegment, ...current];
|
||||
});
|
||||
setEditingSegment(null);
|
||||
setCreating(false);
|
||||
function createSegment() {
|
||||
adminApi.createPhoneSegment({ prefix, carrier, province, city })
|
||||
.then(() => {
|
||||
setPrefix('');
|
||||
setProvince('');
|
||||
setCity('');
|
||||
setCreating(false);
|
||||
loadData();
|
||||
})
|
||||
.catch((failure: Error) => setError(failure.message || '手机号段新增失败'));
|
||||
}
|
||||
|
||||
const columns = useMemo<Array<TableColumn<PhoneSegment>>>(() => [
|
||||
{ key: 'segment', title: '手机号段(手机号码前7位)', width: '230px', render: (record) => <strong>{record.segment}</strong> },
|
||||
{ key: 'carrier', title: '运营商', width: '150px', render: (record) => record.carrier },
|
||||
{ key: 'province', title: '省份', width: '140px', render: (record) => record.province },
|
||||
{ key: 'city', title: '城市', width: '140px', render: (record) => record.city },
|
||||
{ key: 'createdAt', title: '创建时间', width: '190px', render: (record) => record.createdAt },
|
||||
{ key: 'updatedAt', title: '更新时间', width: '190px', render: (record) => record.updatedAt },
|
||||
{
|
||||
key: 'actions',
|
||||
title: '操作',
|
||||
width: '150px',
|
||||
align: 'right',
|
||||
render: (record) => (
|
||||
<div className="admin-system-actions">
|
||||
<Button onClick={() => setEditingSegment(record)} size="sm" variant="ghost">编辑</Button>
|
||||
<Button
|
||||
icon={<Trash2 size={15} />}
|
||||
onClick={() => setSegments((current) => current.filter((item) => item.id !== record.id))}
|
||||
size="sm"
|
||||
variant="danger"
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{ key: 'segment', title: '手机号段(手机号码前7位)', width: '230px', render: (record) => <strong>{record.prefix}</strong> },
|
||||
{ key: 'carrier', title: '运营商', width: '150px', render: (record) => record.carrier ?? '-' },
|
||||
{ key: 'province', title: '省份', width: '140px', render: (record) => record.province ?? '-' },
|
||||
{ key: 'city', title: '城市', width: '140px', render: (record) => record.city ?? '-' },
|
||||
{ key: 'createdAt', title: '创建时间', width: '190px', render: (record) => record.createdAt ?? '-' },
|
||||
], []);
|
||||
|
||||
return (
|
||||
@@ -135,6 +66,7 @@ export function AdminPhoneSegmentsPage() {
|
||||
<h1>手机号段库</h1>
|
||||
</div>
|
||||
</div>
|
||||
{error ? <p className="form-error">{error}</p> : null}
|
||||
|
||||
<div className="surface admin-system-toolbar">
|
||||
<Input onChange={(event) => setKeyword(event.target.value)} placeholder="搜索手机号段、运营商、省份或城市" prefix={<Search size={16} />} value={keyword} />
|
||||
@@ -145,8 +77,33 @@ export function AdminPhoneSegmentsPage() {
|
||||
<Table columns={columns} data={filteredSegments} emptyText="暂无手机号段" rowKey="id" />
|
||||
</div>
|
||||
|
||||
{creating ? <SegmentFormModal onClose={() => setCreating(false)} onSubmit={upsertSegment} /> : null}
|
||||
{editingSegment ? <SegmentFormModal item={editingSegment} onClose={() => setEditingSegment(null)} onSubmit={upsertSegment} /> : null}
|
||||
<Modal
|
||||
footer={(
|
||||
<>
|
||||
<Button onClick={() => setCreating(false)} variant="ghost">取消</Button>
|
||||
<Button disabled={!prefix} onClick={createSegment}>保存</Button>
|
||||
</>
|
||||
)}
|
||||
onClose={() => setCreating(false)}
|
||||
open={creating}
|
||||
title="新增手机号段"
|
||||
>
|
||||
<div className="admin-system-modal-form">
|
||||
<Input label="手机号段" maxLength={7} onChange={(event) => setPrefix(event.target.value)} placeholder="手机号码前7位" value={prefix} />
|
||||
<Select
|
||||
label="运营商"
|
||||
onChange={(event) => setCarrier(event.target.value)}
|
||||
options={[
|
||||
{ label: '中国移动', value: '中国移动' },
|
||||
{ label: '中国联通', value: '中国联通' },
|
||||
{ label: '中国电信', value: '中国电信' },
|
||||
]}
|
||||
value={carrier}
|
||||
/>
|
||||
<Input label="省份" onChange={(event) => setProvince(event.target.value)} value={province} />
|
||||
<Input label="城市" onChange={(event) => setCity(event.target.value)} value={city} />
|
||||
</div>
|
||||
</Modal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user