diff --git a/nkebao/src/api/trafficDistribution.ts b/nkebao/src/api/trafficDistribution.ts index 0e7df24e5..9e05fe027 100644 --- a/nkebao/src/api/trafficDistribution.ts +++ b/nkebao/src/api/trafficDistribution.ts @@ -204,7 +204,7 @@ export const updateDistributionRule = async (id: string, params: any): Promise> => { - return del>(`/v1/workbench/delete/${id}`); + return del>(`/v1/workbench/delete?id=${id}`); }; /** diff --git a/nkebao/src/components/TrafficPoolSelection.tsx b/nkebao/src/components/TrafficPoolSelection.tsx index 779e41cdc..29f808c28 100644 --- a/nkebao/src/components/TrafficPoolSelection.tsx +++ b/nkebao/src/components/TrafficPoolSelection.tsx @@ -1,13 +1,11 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { Search, Database } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { ScrollArea } from '@/components/ui/scroll-area'; -import { Checkbox } from '@/components/ui/checkbox'; -import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog'; import { useToast } from '@/components/ui/toast'; -import { fetchDeviceLabels, type TrafficPool, type TrafficPoolListResponse } from '@/api/trafficDistribution'; -import type { ApiResponse } from '@/types/common'; +import { fetchDeviceLabels, type TrafficPool } from '@/api/trafficDistribution'; // 组件属性接口 interface TrafficPoolSelectionProps { @@ -34,34 +32,8 @@ export default function TrafficPoolSelection({ const [loading, setLoading] = useState(false); const { toast } = useToast(); - // 当弹窗打开时获取流量池列表 - useEffect(() => { - if (dialogOpen && deviceIds.length > 0) { - // 弹窗打开时重置搜索和页码,然后立即请求第一页数据 - setSearchQuery(''); - setCurrentPage(1); - fetchPools(1, ''); - } - }, [dialogOpen, deviceIds]); - - // 监听页码变化,重新请求数据 - useEffect(() => { - if (dialogOpen && deviceIds.length > 0 && currentPage > 1) { - fetchPools(currentPage, searchQuery); - } - }, [currentPage]); - - // 当设备ID变化时,清空已选择的流量池(如果需要的话) - useEffect(() => { - if (deviceIds.length === 0) { - setPools([]); - setTotalPools(0); - setTotalPages(1); - } - }, [deviceIds]); - // 获取流量池列表API - const fetchPools = async (page: number, keyword: string = '') => { + const fetchPools = useCallback(async (page: number, keyword: string = '') => { if (deviceIds.length === 0) return; setLoading(true); @@ -136,7 +108,33 @@ export default function TrafficPoolSelection({ } finally { setLoading(false); } - }; + }, [deviceIds, toast]); + + // 当弹窗打开时获取流量池列表 + useEffect(() => { + if (dialogOpen && deviceIds.length > 0) { + // 弹窗打开时重置搜索和页码,然后立即请求第一页数据 + setSearchQuery(''); + setCurrentPage(1); + fetchPools(1, ''); + } + }, [dialogOpen, deviceIds, fetchPools]); + + // 监听页码变化,重新请求数据 + useEffect(() => { + if (dialogOpen && deviceIds.length > 0 && currentPage > 1) { + fetchPools(currentPage, searchQuery); + } + }, [currentPage, dialogOpen, deviceIds.length, fetchPools, searchQuery]); + + // 当设备ID变化时,清空已选择的流量池(如果需要的话) + useEffect(() => { + if (deviceIds.length === 0) { + setPools([]); + setTotalPools(0); + setTotalPages(1); + } + }, [deviceIds]); // 处理搜索 const handleSearch = (keyword: string) => { @@ -167,16 +165,6 @@ export default function TrafficPoolSelection({ setDialogOpen(false); }; - // 处理弹窗关闭 - const handleDialogClose = (open: boolean) => { - setDialogOpen(open); - if (!open) { - // 弹窗关闭时可以选择性清理状态,这里保留搜索状态以便下次打开时使用 - // setSearchQuery(''); - // setCurrentPage(1); - } - }; - // 处理输入框点击 const handleInputClick = () => { if (deviceIds.length === 0) { @@ -207,9 +195,9 @@ export default function TrafficPoolSelection({ {/* 流量池选择弹窗 */} - + -
+
选择流量池
diff --git a/nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx b/nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx index 130fdaf0b..4c09dcccb 100644 --- a/nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx +++ b/nkebao/src/pages/workspace/traffic-distribution/NewDistribution.tsx @@ -4,7 +4,6 @@ import { Steps, StepItem } from 'tdesign-mobile-react'; import { Users, Search, - Database, X, } from 'lucide-react'; import { Button } from '@/components/ui/button'; @@ -17,7 +16,7 @@ import Layout from '@/components/Layout'; import PageHeader from '@/components/PageHeader'; import DeviceSelection from '@/components/DeviceSelection'; import { useToast } from '@/components/ui/toast'; -import { fetchAccountList, Account } from '@/api/trafficDistribution'; +import { fetchAccountList, Account, createDistributionRule } from '@/api/trafficDistribution'; import '@/components/Layout.css'; import TrafficPoolSelection from '@/components/TrafficPoolSelection'; @@ -45,13 +44,6 @@ interface FormData { trafficPool: Partial; } -interface TrafficPool { - id: string; - name: string; - count: number; - description: string; -} - // 账号选择对话框组件 const AccountSelectionDialog = ({ open, @@ -289,6 +281,20 @@ export default function NewDistribution() { return `流量分发 ${year}${month}${day} ${hour}${minute}`; }; + // 转换分配方式为后端需要的格式 + const getDistributeType = (distributionMethod: string | undefined) => { + switch (distributionMethod) { + case 'equal': + return 1; // 均分配 + case 'priority': + return 2; // 优先级分配 + case 'ratio': + return 3; // 比例分配 + default: + return 1; // 默认均分配 + } + }; + const handleBasicInfoNext = (data: BasicInfoData) => { setFormData(prev => ({ ...prev, basicInfo: data })); setCurrentStep(1); @@ -314,19 +320,48 @@ export default function NewDistribution() { }; try { - console.log('提交的数据:', finalData); + // 构造API请求参数 - 按照后端要求的格式 + const apiParams = { + type: 5, // 流量分发类型 + name: finalData.basicInfo.name || '', + distributeType: getDistributeType(finalData.basicInfo.distributionMethod), + maxPerDay: finalData.basicInfo.dailyLimit || 50, + timeType: finalData.basicInfo.timeRestriction === 'allDay' ? 1 : 2, + startTime: finalData.basicInfo.timeRestriction === 'custom' + ? (finalData.basicInfo.startTime || "09:00") + : "00:00", + endTime: finalData.basicInfo.timeRestriction === 'custom' + ? (finalData.basicInfo.endTime || "18:00") + : "23:59", + devices: finalData.targetSettings?.selectedDevices || [], + account: finalData.basicInfo?.selectedAccounts || [], + pools: finalData.trafficPool?.selectedPools || [], + enabled: true // 默认启用 + }; + + console.log('提交的数据:', apiParams); - toast({ - title: "创建成功", - description: "流量分发规则已成功创建" - }); + const response = await createDistributionRule(apiParams); - navigate('/workspace/traffic-distribution'); + if (response.code === 200) { + toast({ + title: "创建成功", + description: "流量分发规则已成功创建" + }); + + navigate('/workspace/traffic-distribution'); + } else { + toast({ + title: "创建失败", + description: response.msg || "请稍后重试", + variant: "destructive" + }); + } } catch (error) { console.error('提交失败:', error); toast({ title: "创建失败", - description: "请稍后重试", + description: "网络错误,请稍后重试", variant: "destructive" }); } @@ -589,14 +624,6 @@ export default function NewDistribution() { const [isSubmitting, setIsSubmitting] = useState(false); const handleSubmit = async () => { - if (selectedPools.length === 0) { - toast({ - title: "请选择至少一个流量池", - variant: "destructive" - }); - return; - } - setIsSubmitting(true); try { @@ -634,7 +661,7 @@ export default function NewDistribution() { -