feat: refine template deletion and channel group filters

This commit is contained in:
hectorzhao
2026-08-09 20:54:52 +08:00
parent 482d332f49
commit 78b839f468
11 changed files with 210 additions and 49 deletions
+38 -9
View File
@@ -1,8 +1,8 @@
import { useEffect, useMemo, useState } from 'react';
import { Clock3, Layers3, Pencil, Plus, RadioTower, Search, Trash2 } from 'lucide-react';
import { useNavigate } from 'react-router-dom';
import { Breadcrumb, Button, Input, Modal, Pagination, Tag } from '@/components/ui';
import { adminApi, type ChannelGroup, type ChannelGroupDeletionImpact } from '@/api/adminApi';
import { Breadcrumb, Button, Input, Modal, Pagination, Select, Tag } from '@/components/ui';
import { adminApi, type AdminChannel, type ChannelGroup, type ChannelGroupDeletionImpact } from '@/api/adminApi';
type GroupCarrier = 'mobile' | 'unicom' | 'telecom';
@@ -33,6 +33,8 @@ function getGroupSummary(group: ChannelGroup) {
export function AdminChannelGroupsPage() {
const navigate = useNavigate();
const [groupName, setGroupName] = useState('');
const [channelId, setChannelId] = useState('');
const [channels, setChannels] = useState<AdminChannel[]>([]);
const [groups, setGroups] = useState<ChannelGroup[]>([]);
const [deleteTarget, setDeleteTarget] = useState<ChannelGroup | null>(null);
const [deletionImpact, setDeletionImpact] = useState<ChannelGroupDeletionImpact | null>(null);
@@ -43,26 +45,42 @@ export function AdminChannelGroupsPage() {
const pageSize = 10;
function loadData() {
adminApi.listChannelGroups()
.then((items) => {
setGroups(items);
Promise.all([adminApi.listChannelGroups(), adminApi.listChannels()])
.then(([groupItems, channelItems]) => {
setGroups(groupItems);
setChannels(channelItems);
setError('');
})
.catch((failure: Error) => setError(failure.message || '通道组加载失败'));
.catch((failure: Error) => setError(failure.message || '通道组数据加载失败'));
}
useEffect(() => {
loadData();
}, []);
const filteredGroups = useMemo(() => groups.filter((group) => !groupName.trim() || group.name.includes(groupName.trim())), [groupName, groups]);
const channelOptions = useMemo(() => [
{ label: '全部通道', value: '' },
...channels
.map((channel) => {
const identity = `${channel.name}${channel.code}`;
return { label: channel.status === 'deleted' ? `${identity}(已删除)` : identity, value: channel.id };
})
.sort((left, right) => left.label.localeCompare(right.label, 'zh-CN')),
], [channels]);
const filteredGroups = useMemo(() => {
const keyword = groupName.trim();
return groups.filter((group) => (
(!keyword || group.name.includes(keyword))
&& (!channelId || (group.items ?? []).some((item) => item.channelId === channelId))
));
}, [channelId, groupName, groups]);
const totalPages = Math.max(1, Math.ceil(filteredGroups.length / pageSize));
const currentPage = Math.min(page, totalPages);
const visibleGroups = filteredGroups.slice((currentPage - 1) * pageSize, currentPage * pageSize);
useEffect(() => {
setPage(1);
}, [groupName, groups.length]);
}, [channelId, groupName, groups.length]);
function closeDeleteModal() {
if (deleting) return;
@@ -108,9 +126,20 @@ export function AdminChannelGroupsPage() {
<section className="surface channel-group-filter">
<Input label="通道组名称" onChange={(event) => setGroupName(event.target.value)} placeholder="请输入通道组名称" value={groupName} />
<Select
label="通道"
onChange={(event) => setChannelId(event.target.value)}
options={channelOptions}
searchable
searchPlaceholder="输入通道名称或编码搜索"
value={channelId}
/>
<div className="channel-group-filter__actions">
<Button icon={<Search size={16} />} onClick={loadData}></Button>
<Button onClick={() => setGroupName('')} variant="ghost"></Button>
<Button onClick={() => {
setGroupName('');
setChannelId('');
}} variant="ghost"></Button>
</div>
</section>