fix: implement channel group routing failover
This commit is contained in:
@@ -4,13 +4,14 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { adminApi, type AdminChannel, type ChannelLinkLogResponse } from '@/api/adminApi';
|
||||
import { Breadcrumb, Button, Input, Modal, Select, Tag, Textarea } from '@/components/ui';
|
||||
|
||||
type Carrier = 'mobile' | 'unicom' | 'telecom';
|
||||
type Carrier = 'mobile' | 'unicom' | 'telecom' | 'all';
|
||||
type ChannelStatus = 'normal' | 'stopped' | 'connecting' | 'failed';
|
||||
|
||||
type SmsChannel = {
|
||||
id: string;
|
||||
name: string;
|
||||
carrier: Carrier;
|
||||
sendRegion: string;
|
||||
unitPrice: number;
|
||||
status: ChannelStatus;
|
||||
total: number;
|
||||
@@ -47,6 +48,7 @@ const carrierOptions = [
|
||||
{ label: '移动', value: 'mobile' },
|
||||
{ label: '联通', value: 'unicom' },
|
||||
{ label: '电信', value: 'telecom' },
|
||||
{ label: '三网', value: 'all' },
|
||||
];
|
||||
|
||||
const statusOptions = [
|
||||
@@ -65,9 +67,7 @@ const protocolOptions = [
|
||||
|
||||
const regionOptions = [
|
||||
{ label: '全国', value: '全国' },
|
||||
{ label: '华东', value: '华东' },
|
||||
{ label: '华南', value: '华南' },
|
||||
{ label: '华北', value: '华北' },
|
||||
...'北京,天津,河北,山西,内蒙古,辽宁,吉林,黑龙江,上海,江苏,浙江,安徽,福建,江西,山东,河南,湖北,湖南,广东,广西,海南,重庆,四川,贵州,云南,西藏,陕西,甘肃,青海,宁夏,新疆,香港,澳门,台湾'.split(',').map((province) => ({ label: province, value: province })),
|
||||
];
|
||||
|
||||
const extensionOptions = [
|
||||
@@ -81,12 +81,14 @@ const carrierLabelMap: Record<Carrier, string> = {
|
||||
mobile: '移动',
|
||||
unicom: '联通',
|
||||
telecom: '电信',
|
||||
all: '三网',
|
||||
};
|
||||
|
||||
const carrierToneMap: Record<Carrier, 'info' | 'danger' | 'success'> = {
|
||||
const carrierToneMap: Record<Carrier, 'info' | 'danger' | 'success' | 'neutral'> = {
|
||||
mobile: 'info',
|
||||
unicom: 'danger',
|
||||
telecom: 'success',
|
||||
all: 'neutral',
|
||||
};
|
||||
|
||||
const statusLabelMap: Record<ChannelStatus, string> = {
|
||||
@@ -114,7 +116,8 @@ function mapApiChannel(channel: AdminChannel): SmsChannel {
|
||||
return {
|
||||
id: channel.id,
|
||||
name: channel.name,
|
||||
carrier: channel.carrier === 'unicom' || channel.carrier === 'telecom' ? channel.carrier : 'mobile',
|
||||
carrier: channel.carrier === 'unicom' || channel.carrier === 'telecom' || channel.carrier === 'all' ? channel.carrier : 'mobile',
|
||||
sendRegion: channel.sendRegion ?? '全国',
|
||||
unitPrice: channel.unitPrice,
|
||||
status: statusMap[channel.status] ?? 'normal',
|
||||
total: 0,
|
||||
@@ -159,7 +162,7 @@ function ChannelFormModal({
|
||||
const [name, setName] = useState(channel?.name ?? '');
|
||||
const [carrier, setCarrier] = useState<Carrier>(channel?.carrier ?? 'mobile');
|
||||
const [unitPrice, setUnitPrice] = useState(channel ? String(channel.unitPrice / 100) : '0.0300');
|
||||
const [region, setRegion] = useState('全国');
|
||||
const [region, setRegion] = useState(channel?.sendRegion ?? '全国');
|
||||
const [protocol, setProtocol] = useState('CMPP');
|
||||
const [gatewayHost, setGatewayHost] = useState(channel?.gatewayHost ?? '');
|
||||
const [gatewayPort, setGatewayPort] = useState(channel?.gatewayPort ?? '17890');
|
||||
@@ -175,6 +178,7 @@ function ChannelFormModal({
|
||||
id: channel?.id ?? String(Math.floor(10000 + Math.random() * 80000)),
|
||||
name: name || '新建短信通道',
|
||||
carrier,
|
||||
sendRegion: region,
|
||||
unitPrice: Number(unitPrice || 0) * 100,
|
||||
status: channel?.status ?? 'connecting',
|
||||
total: channel?.total ?? 0,
|
||||
@@ -212,7 +216,7 @@ function ChannelFormModal({
|
||||
<Input label="* 通道名称" onChange={(event) => setName(event.target.value)} placeholder="请输入通道名称" value={name} />
|
||||
<div className="sms-channel-radio-row">
|
||||
<span>* 运营商</span>
|
||||
{(['mobile', 'unicom', 'telecom'] as const).map((item) => (
|
||||
{(['mobile', 'unicom', 'telecom', 'all'] as const).map((item) => (
|
||||
<label key={item}>
|
||||
<input checked={carrier === item} onChange={() => setCarrier(item)} type="radio" />
|
||||
{carrierLabelMap[item]}
|
||||
@@ -350,12 +354,33 @@ export function AdminChannelsPage() {
|
||||
[carrier, channels, keyword, status],
|
||||
);
|
||||
|
||||
function upsertChannel(nextChannel: SmsChannel) {
|
||||
setChannels((items) => {
|
||||
const exists = items.some((item) => item.id === nextChannel.id);
|
||||
return exists ? items.map((item) => (item.id === nextChannel.id ? nextChannel : item)) : [nextChannel, ...items];
|
||||
});
|
||||
setModal(null);
|
||||
async function upsertChannel(nextChannel: SmsChannel) {
|
||||
if (modal?.mode === 'edit') {
|
||||
setError('短信通道编辑接口待补,当前不做本地模拟保存');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const created = await adminApi.createChannel({
|
||||
code: `CH-${Date.now()}`,
|
||||
name: nextChannel.name,
|
||||
carrier: nextChannel.carrier,
|
||||
sendRegion: nextChannel.sendRegion,
|
||||
gatewayHost: nextChannel.gatewayHost,
|
||||
gatewayPort: Number(nextChannel.gatewayPort),
|
||||
enterpriseCode: nextChannel.corpCode,
|
||||
account: nextChannel.account,
|
||||
passwordCipher: 'secret',
|
||||
srcId: nextChannel.accessNo,
|
||||
rateLimitPerSecond: 100,
|
||||
unitPrice: Math.round(nextChannel.unitPrice),
|
||||
status: 'active',
|
||||
});
|
||||
setChannels((items) => [mapApiChannel(created), ...items]);
|
||||
setModal(null);
|
||||
setError('');
|
||||
} catch (failure) {
|
||||
setError(failure instanceof Error ? failure.message : '通道创建失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleChannel(channel: SmsChannel) {
|
||||
|
||||
Reference in New Issue
Block a user