From ef839f65c11646a90c88b4b01c2150834873c7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E7=BA=A7=E8=80=81=E7=99=BD=E5=85=94?= Date: Fri, 19 Sep 2025 16:58:40 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=B5=81=E9=87=8F=E5=88=86=E5=8F=91?= =?UTF-8?q?=E8=A1=A8=E5=8D=95):=20=E4=BC=98=E5=8C=96=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=92=8C=E6=95=B0=E6=8D=AE=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构流量分发表单组件,使用Form管理字段并引入useWatch以简化状态管理。移除未使用的状态和函数,优化了获取详情数据的逻辑。同时,更新了API请求方法以符合RESTful标准,确保删除计划时使用DELETE请求。 --- .../traffic-distribution/form/index.tsx | 277 +++++++++--------- .../traffic-distribution/list/api.ts | 2 +- 2 files changed, 132 insertions(+), 147 deletions(-) diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx index 7d6f21b1..bef94887 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/form/index.tsx @@ -1,15 +1,5 @@ -import React, { useState, useEffect } from "react"; -import { - Form, - Input, - Button, - Radio, - Slider, - TimePicker, - message, - Checkbox, -} from "antd"; -import { SearchOutlined } from "@ant-design/icons"; +import React, { useState, useEffect, useCallback } from "react"; +import { Form, Input, Button, Radio, Slider, TimePicker, message } from "antd"; import { useNavigate, useParams } from "react-router-dom"; import style from "./index.module.scss"; import StepIndicator from "@/components/StepIndicator"; @@ -24,22 +14,10 @@ import { updateTrafficDistribution, createTrafficDistribution, } from "./api"; -import type { - TrafficDistributionDetail, - TrafficDistributionFormData, -} from "./data"; +import type { TrafficDistributionFormData } from "./data"; import dayjs from "dayjs"; -const scenarioList = [ - { label: "海报获客", value: "poster" }, - { label: "电话获客", value: "phone" }, - { label: "抖音获客", value: "douyin" }, - { label: "小红书获客", value: "xiaohongshu" }, - { label: "微信群获客", value: "weixinqun" }, - { label: "API获客", value: "api" }, - { label: "订单获客", value: "order" }, - { label: "付款码获客", value: "payment" }, -]; +// const scenarioList = [...]; const poolList = [ { id: "pool-1", @@ -73,10 +51,7 @@ const TrafficDistributionForm: React.FC = () => { const [deviceGroupsOptions, setDeviceGroupsOptions] = useState([]); const [accountGroups, setAccountGroups] = useState([]); const [accountGroupsOptions, setAccountGroupsOptions] = useState([]); - const [distributeType, setDistributeType] = useState(1); - const [maxPerDay, setMaxPerDay] = useState(50); - const [timeType, setTimeType] = useState(1); - const [timeRange, setTimeRange] = useState(null); + // 使用 Form 管理字段,配合 useWatch 读取值 const [loading, setLoading] = useState(false); const [detailLoading, setDetailLoading] = useState(false); @@ -86,9 +61,12 @@ const TrafficDistributionForm: React.FC = () => { "device" | "account" >("device"); - // 编辑时的详情数据 - const [detailData, setDetailData] = - useState(null); + // 编辑时的详情数据(不需要保存整份数据,仅回填表单与本地状态) + + // 监听表单字段变化(antd v5 推荐) + const maxPerDay = Form.useWatch("maxPerDay", form); + const timeType = Form.useWatch("timeType", form); + // const timeRange = Form.useWatch("timeRange", form); // 生成默认名称 const generateDefaultName = () => { @@ -98,20 +76,12 @@ const TrafficDistributionForm: React.FC = () => { return `流量分发 ${dateStr} ${timeStr}`; }; - // 获取详情数据 - useEffect(() => { - if (isEdit && id) { - fetchDetail(); - } - }, [isEdit, id]); - - const fetchDetail = async () => { + const fetchDetail = useCallback(async () => { if (!id) return; setDetailLoading(true); try { const detail = await getTrafficDistributionDetail(id); - setDetailData(detail); // 回填表单数据 const config = detail.config; @@ -122,11 +92,6 @@ const TrafficDistributionForm: React.FC = () => { timeType: config.timeType, }); - // 设置状态 - setDistributeType(config.distributeType); - setMaxPerDay(config.maxPerDay); - setTimeType(config.timeType); - // 设置账号组数据 setAccountGroups(config.accountGroups || []); setAccountGroupsOptions(config.accountGroupsOptions || []); @@ -147,7 +112,7 @@ const TrafficDistributionForm: React.FC = () => { // 使用dayjs创建时间对象 const startTime = dayjs().hour(startHour).minute(startMinute).second(0); const endTime = dayjs().hour(endHour).minute(endMinute).second(0); - setTimeRange([startTime, endTime]); + form.setFieldsValue({ timeRange: [startTime, endTime] }); } // 设置流量池 @@ -158,9 +123,21 @@ const TrafficDistributionForm: React.FC = () => { } finally { setDetailLoading(false); } + }, [id, form]); + + // 获取详情数据 + useEffect(() => { + if (isEdit && id) { + fetchDetail(); + } + }, [isEdit, id, fetchDetail]); + const handleFinish = async () => { + form.submit(); }; - const handleFinish = async (values?: any) => { + // 移除未使用的 handleFinish3 + + const handleFinish2 = async (values?: any) => { setLoading(true); try { // 如果没有传递values参数,从表单中获取 @@ -173,13 +150,17 @@ const TrafficDistributionForm: React.FC = () => { source: "", sourceIcon: "", description: "", - distributeType: distributeType, - maxPerDay: maxPerDay, - timeType: timeType, + distributeType: formValues.distributeType, + maxPerDay: formValues.maxPerDay, + timeType: formValues.timeType, startTime: - timeType === 2 && timeRange?.[0] ? timeRange[0].format("HH:mm") : "", + formValues.timeType === 2 && formValues.timeRange?.[0] + ? formValues.timeRange[0].format("HH:mm") + : "", endTime: - timeType === 2 && timeRange?.[1] ? timeRange[1].format("HH:mm") : "", + formValues.timeType === 2 && formValues.timeRange?.[1] + ? formValues.timeRange[1].format("HH:mm") + : "", deviceGroups: deviceGroups, deviceGroupsOptions: deviceGroupsOptions, accountGroups: accountGroups, @@ -216,6 +197,17 @@ const TrafficDistributionForm: React.FC = () => { .catch(() => { // 验证失败,不进行下一步 }); + } else if (current === 1) { + // 第二步:目标设置至少需要选择设备或客服之一 + const hasDevice = + Array.isArray(selectedDevices) && selectedDevices.length > 0; + const hasAccount = + Array.isArray(selectedAccounts) && selectedAccounts.length > 0; + if (!hasDevice && !hasAccount) { + message.error("请至少选择一个设备或一个客服"); + return; + } + setCurrent(cur => cur + 1); } else { setCurrent(cur => cur + 1); } @@ -225,6 +217,7 @@ const TrafficDistributionForm: React.FC = () => { // 过滤流量池 const filteredPools = poolList.filter(pool => pool.name.includes(poolSearch)); + // 移除未使用的输入同步函数 return ( { >
- {current === 0 && ( -
+
基本信息
+ -
基本信息
+ +
+ + + + 均分配 + + (流量将均分分配给所有客服) + + + + 优先级分配 + + (按客服优先级顺序分配) + + + + 比例分配 + (按设置比例分配流量) + + + + +
+ 每日最大分配量 + + {maxPerDay || 0} 人/天 + +
- + - - setDistributeType(e.target.value)} - className={style.radioGroup} - > - - 均分配 - - (流量将均分分配给所有客服) - - - - 优先级分配 - - (按客服优先级顺序分配) - - - - 比例分配 - - (按设置比例分配流量) - - - - - -
- 每日最大分配量 - {maxPerDay} 人/天 -
- 限制每天最多分配的流量数量
+ + + + 全天分配 + 自定义时间段 + + + {timeType === 2 && ( + ({ + validator(_, value) { + if (getFieldValue("timeType") === 1) { + return Promise.resolve(); + } + if (value && value.length === 2) { + return Promise.resolve(); + } + return Promise.reject(new Error("请选择开始和结束时间")); + }, + }), + ]} + > + -
- 限制每天最多分配的流量数量 -
- - setTimeType(e.target.value)} - className={style.radioGroup} - > - 全天分配 - 自定义时间段 - - - {timeType === 2 && ( - -
-
- 开始时间 - setTimeRange([v, timeRange?.[1]])} - /> -
-
- 结束时间 - setTimeRange([timeRange?.[0], v])} - /> -
-
-
- )} - - )} + )} + {current === 1 && (
目标设置
diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts index 67d4ba32..fddb19bc 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts @@ -24,7 +24,7 @@ export function toggleDistributionRuleStatus( // 删除计划 export function deleteDistributionRule(id: number): Promise { - return request("/v1/workbench/delete", { id }, "POST"); + return request("/v1/workbench/delete", { id }, "DELETE"); } // 获取流量分发规则详情