feat: 简化通道组顺序调整并过滤不可选通道
This commit is contained in:
@@ -3,7 +3,7 @@ import { CheckCircle2, Info, Search } from 'lucide-react';
|
||||
import type { AdminChannel } from '@/api/adminApi';
|
||||
import { Button, CarrierTag, Input, Modal, Select, Tag } from '@/components/ui';
|
||||
import { formatRateAmount, MONEY_UNITS_PER_YUAN } from '@/utils/currency';
|
||||
import { isValidPriority, normalizeRegion, type NationalRoute, type ProvinceRoute } from './model';
|
||||
import { normalizeRegion, type NationalRoute, type ProvinceRoute } from './model';
|
||||
import './RouteConfigModal.css';
|
||||
|
||||
type Carrier = 'mobile' | 'unicom' | 'telecom';
|
||||
@@ -46,7 +46,6 @@ export function RouteConfigModal({
|
||||
carrier,
|
||||
modal,
|
||||
occupiedChannelIds,
|
||||
nextPriority,
|
||||
onClose,
|
||||
onSubmit,
|
||||
}: {
|
||||
@@ -54,26 +53,25 @@ export function RouteConfigModal({
|
||||
carrier: Carrier;
|
||||
modal: RouteModalState;
|
||||
occupiedChannelIds: string[];
|
||||
nextPriority: number;
|
||||
onClose: () => void;
|
||||
onSubmit: (route: ProvinceRoute | NationalRoute) => string | null;
|
||||
}) {
|
||||
const provinceRoute = modal.type === 'province' ? (modal.route as ProvinceRoute | undefined) : undefined;
|
||||
const nationalRoute = modal.type === 'national' ? (modal.route as NationalRoute | undefined) : undefined;
|
||||
const initialPriority = String(nationalRoute?.priority ?? nextPriority);
|
||||
const [province, setProvince] = useState(provinceRoute?.province ?? '');
|
||||
const [priority, setPriority] = useState(initialPriority);
|
||||
const [channelId, setChannelId] = useState(modal.route?.channelId ?? '');
|
||||
const [keyword, setKeyword] = useState('');
|
||||
const [error, setError] = useState('');
|
||||
const selectionName = useId();
|
||||
const selected = channels.find((channel) => channel.id === channelId);
|
||||
const dirty =
|
||||
province !== (provinceRoute?.province ?? '') ||
|
||||
priority !== initialPriority ||
|
||||
channelId !== (modal.route?.channelId ?? '');
|
||||
const dirty = province !== (provinceRoute?.province ?? '') || channelId !== (modal.route?.channelId ?? '');
|
||||
const provinces = channels
|
||||
.filter((channel) => isCarrierCompatible(channel, carrier))
|
||||
.filter(
|
||||
(channel) =>
|
||||
channel.status !== 'deleted' &&
|
||||
isCarrierCompatible(channel, carrier) &&
|
||||
(channel.id === modal.route?.channelId || !occupiedChannelIds.includes(channel.id)),
|
||||
)
|
||||
.map((channel) => channel.sendRegion)
|
||||
.filter((region): region is string => Boolean(region && normalizeRegion(region) !== '全国'));
|
||||
if (provinceRoute?.province) provinces.push(provinceRoute.province);
|
||||
@@ -96,10 +94,11 @@ export function RouteConfigModal({
|
||||
}
|
||||
|
||||
const query = keyword.trim().toLocaleLowerCase();
|
||||
const visibleChannels = channels.filter((channel) =>
|
||||
`${channel.name} ${channel.code} ${channel.sendRegion ?? '全国'}`.toLocaleLowerCase().includes(query),
|
||||
const visibleChannels = channels.filter(
|
||||
(channel) =>
|
||||
!unavailableReason(channel) &&
|
||||
`${channel.name} ${channel.code} ${channel.sendRegion ?? '全国'}`.toLocaleLowerCase().includes(query),
|
||||
);
|
||||
const availableCount = visibleChannels.filter((channel) => !unavailableReason(channel)).length;
|
||||
|
||||
function submit() {
|
||||
if (modal.type === 'province' && !province) {
|
||||
@@ -115,14 +114,10 @@ export function RouteConfigModal({
|
||||
setError(reason);
|
||||
return;
|
||||
}
|
||||
if (modal.type === 'national' && (!priority.trim() || !isValidPriority(Number(priority)))) {
|
||||
setError('优先级需为 -2147483648 到 2147483647 的整数');
|
||||
return;
|
||||
}
|
||||
const route =
|
||||
modal.type === 'province'
|
||||
? { id: provinceRoute?.id ?? `p-${selectionName}`, province, channelId }
|
||||
: { id: nationalRoute?.id ?? `n-${selectionName}`, priority: Number(priority), channelId };
|
||||
: { id: nationalRoute?.id ?? `n-${selectionName}`, priority: nationalRoute?.priority ?? 0, channelId };
|
||||
setError(onSubmit(route) ?? '');
|
||||
}
|
||||
|
||||
@@ -156,22 +151,7 @@ export function RouteConfigModal({
|
||||
options={provinceOptions}
|
||||
value={province}
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
label="优先级"
|
||||
required
|
||||
type="number"
|
||||
step="1"
|
||||
min="-2147483648"
|
||||
max="2147483647"
|
||||
onChange={(event) => {
|
||||
setPriority(event.target.value);
|
||||
setError('');
|
||||
}}
|
||||
value={priority}
|
||||
hint="数值越小越先使用;失败补发会跳到下一优先级。"
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
<Input
|
||||
label="搜索通道"
|
||||
onChange={(event) => setKeyword(event.target.value)}
|
||||
@@ -184,9 +164,7 @@ export function RouteConfigModal({
|
||||
<span>连接状态来自最近一次真实回写;暂时断连不影响配置,实际发送仍受可用性校验。</span>
|
||||
</p>
|
||||
<fieldset className="channel-route-editor__choices">
|
||||
<legend>
|
||||
选择通道 · {visibleChannels.length} 个结果,{availableCount} 个可选
|
||||
</legend>
|
||||
<legend>选择通道 · {visibleChannels.length} 个可选</legend>
|
||||
{visibleChannels.map((channel) => {
|
||||
const reason = unavailableReason(channel);
|
||||
const connection = connectionLabel(channel);
|
||||
@@ -235,7 +213,11 @@ export function RouteConfigModal({
|
||||
})}
|
||||
{visibleChannels.length === 0 ? (
|
||||
<p className="channel-route-editor__empty">
|
||||
{channels.length ? '没有匹配的通道,请调整搜索条件' : '暂无通道数据'}
|
||||
{modal.type === 'province' && !province
|
||||
? '请先选择省份'
|
||||
: query
|
||||
? '没有匹配的可选通道,请调整搜索条件'
|
||||
: '暂无可添加的通道'}
|
||||
</p>
|
||||
) : null}
|
||||
</fieldset>
|
||||
|
||||
Reference in New Issue
Block a user