fix: implement channel group routing failover
This commit is contained in:
@@ -10,20 +10,35 @@ type PhoneSegment = DictionaryItem & {
|
||||
city?: string | null;
|
||||
};
|
||||
|
||||
type CarrierRule = DictionaryItem & {
|
||||
carrier?: string;
|
||||
pattern?: string;
|
||||
priority?: number;
|
||||
remark?: string | null;
|
||||
};
|
||||
|
||||
export function AdminPhoneSegmentsPage() {
|
||||
const [segments, setSegments] = useState<PhoneSegment[]>([]);
|
||||
const [rules, setRules] = useState<CarrierRule[]>([]);
|
||||
const [activeTab, setActiveTab] = useState<'segments' | 'rules'>('segments');
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [creatingRule, setCreatingRule] = useState(false);
|
||||
const [prefix, setPrefix] = useState('');
|
||||
const [carrier, setCarrier] = useState('中国移动');
|
||||
const [province, setProvince] = useState('');
|
||||
const [city, setCity] = useState('');
|
||||
const [ruleCarrier, setRuleCarrier] = useState('mobile');
|
||||
const [rulePattern, setRulePattern] = useState('');
|
||||
const [rulePriority, setRulePriority] = useState('100');
|
||||
const [ruleRemark, setRuleRemark] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
|
||||
function loadData() {
|
||||
adminApi.listPhoneSegments()
|
||||
.then((items) => {
|
||||
setSegments(items as PhoneSegment[]);
|
||||
Promise.all([adminApi.listPhoneSegments(), adminApi.listPhoneCarrierRules()])
|
||||
.then(([segmentItems, ruleItems]) => {
|
||||
setSegments(segmentItems as PhoneSegment[]);
|
||||
setRules(ruleItems as CarrierRule[]);
|
||||
setError('');
|
||||
})
|
||||
.catch((failure: Error) => setError(failure.message || '手机号段加载失败'));
|
||||
@@ -50,6 +65,17 @@ export function AdminPhoneSegmentsPage() {
|
||||
.catch((failure: Error) => setError(failure.message || '手机号段新增失败'));
|
||||
}
|
||||
|
||||
function createCarrierRule() {
|
||||
adminApi.createPhoneCarrierRule({ carrier: ruleCarrier, pattern: rulePattern, priority: Number(rulePriority) || 100, remark: ruleRemark })
|
||||
.then(() => {
|
||||
setRulePattern('');
|
||||
setRuleRemark('');
|
||||
setCreatingRule(false);
|
||||
loadData();
|
||||
})
|
||||
.catch((failure: Error) => setError(failure.message || '运营商区分规则新增失败'));
|
||||
}
|
||||
|
||||
const columns = useMemo<Array<TableColumn<PhoneSegment>>>(() => [
|
||||
{ key: 'segment', title: '手机号段(手机号码前7位)', width: '230px', render: (record) => <strong>{record.prefix}</strong> },
|
||||
{ key: 'carrier', title: '运营商', width: '150px', render: (record) => record.carrier ?? '-' },
|
||||
@@ -58,6 +84,13 @@ export function AdminPhoneSegmentsPage() {
|
||||
{ key: 'createdAt', title: '创建时间', width: '190px', render: (record) => record.createdAt ?? '-' },
|
||||
], []);
|
||||
|
||||
const ruleColumns = useMemo<Array<TableColumn<CarrierRule>>>(() => [
|
||||
{ key: 'carrier', title: '运营商', width: '140px', render: (record) => record.carrier ?? '-' },
|
||||
{ key: 'pattern', title: '号码前缀正则', render: (record) => <strong>{record.pattern}</strong> },
|
||||
{ key: 'priority', title: '优先级', width: '120px', render: (record) => record.priority ?? 100 },
|
||||
{ key: 'remark', title: '备注', render: (record) => record.remark ?? '-' },
|
||||
], []);
|
||||
|
||||
return (
|
||||
<section className="page-stack admin-system-page">
|
||||
<div className="page-heading">
|
||||
@@ -70,11 +103,19 @@ export function AdminPhoneSegmentsPage() {
|
||||
|
||||
<div className="surface admin-system-toolbar">
|
||||
<Input onChange={(event) => setKeyword(event.target.value)} placeholder="搜索手机号段、运营商、省份或城市" prefix={<Search size={16} />} value={keyword} />
|
||||
<Button icon={<Plus size={16} />} onClick={() => setCreating(true)}>新增号段</Button>
|
||||
<div className="segmented-control">
|
||||
<button className={activeTab === 'segments' ? 'is-active' : ''} onClick={() => setActiveTab('segments')} type="button">手机号段</button>
|
||||
<button className={activeTab === 'rules' ? 'is-active' : ''} onClick={() => setActiveTab('rules')} type="button">运营商区分规则</button>
|
||||
</div>
|
||||
<Button icon={<Plus size={16} />} onClick={() => activeTab === 'segments' ? setCreating(true) : setCreatingRule(true)}>
|
||||
{activeTab === 'segments' ? '新增号段' : '新增规则'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="surface admin-system-table-card">
|
||||
<Table columns={columns} data={filteredSegments} emptyText="暂无手机号段" rowKey="id" />
|
||||
{activeTab === 'segments'
|
||||
? <Table columns={columns} data={filteredSegments} emptyText="暂无手机号段" rowKey="id" />
|
||||
: <Table columns={ruleColumns} data={rules} emptyText="暂无运营商区分规则" rowKey="id" />}
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
@@ -104,6 +145,34 @@ export function AdminPhoneSegmentsPage() {
|
||||
<Input label="城市" onChange={(event) => setCity(event.target.value)} value={city} />
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
footer={(
|
||||
<>
|
||||
<Button onClick={() => setCreatingRule(false)} variant="ghost">取消</Button>
|
||||
<Button disabled={!rulePattern} onClick={createCarrierRule}>保存</Button>
|
||||
</>
|
||||
)}
|
||||
onClose={() => setCreatingRule(false)}
|
||||
open={creatingRule}
|
||||
title="新增运营商区分规则"
|
||||
>
|
||||
<div className="admin-system-modal-form">
|
||||
<Select
|
||||
label="运营商"
|
||||
onChange={(event) => setRuleCarrier(event.target.value)}
|
||||
options={[
|
||||
{ label: '移动', value: 'mobile' },
|
||||
{ label: '联通', value: 'unicom' },
|
||||
{ label: '电信', value: 'telecom' },
|
||||
]}
|
||||
value={ruleCarrier}
|
||||
/>
|
||||
<Input label="号码前缀正则" onChange={(event) => setRulePattern(event.target.value)} placeholder="例如 ^13[4-9]" value={rulePattern} />
|
||||
<Input label="优先级" onChange={(event) => setRulePriority(event.target.value)} value={rulePriority} />
|
||||
<Input label="备注" onChange={(event) => setRuleRemark(event.target.value)} value={ruleRemark} />
|
||||
</div>
|
||||
</Modal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user