From a9c41aa9c3f7e2c3627d12069ea2e25c9ce43e37 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: Mon, 22 Sep 2025 10:37:11 +0800 Subject: [PATCH 01/26] =?UTF-8?q?feat(=E6=89=B9=E9=87=8F=E5=8A=A0=E5=85=A5?= =?UTF-8?q?=E5=88=86=E7=BB=84):=20=E6=9B=B4=E6=96=B0BatchAddModal=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E4=BB=A5=E6=94=AF=E6=8C=81=E7=A1=AE=E8=AE=A4=E6=93=8D?= =?UTF-8?q?=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在BatchAddModal组件中新增了确认按钮,优化了用户体验。更新onConfirm函数以接收选项参数,并调整了组件结构以提升可读性。同时,移除了未使用的Toast提示逻辑,简化了批量加入的处理逻辑。 --- .../mine/traffic-pool/list/BatchAddModal.tsx | 72 ++++++++++--------- .../mine/traffic-pool/list/dataAnyx.tsx | 29 ++++---- 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx index 86dda2024..19ffcae4a 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Popup, Selector } from "antd-mobile"; +import { Popup, Selector, Button } from "antd-mobile"; import type { PackageOption } from "./data"; interface BatchAddModalProps { @@ -9,7 +9,7 @@ interface BatchAddModalProps { batchTarget: string; setBatchTarget: (v: string) => void; selectedCount: number; - onConfirm: () => void; + onConfirm: (options) => void; } const BatchAddModal: React.FC = ({ @@ -20,38 +20,40 @@ const BatchAddModal: React.FC = ({ setBatchTarget, selectedCount, onConfirm, -}) => ( - // - //
- //
选择目标分组
- // ({ label: p.name, value: p.id }))} - // value={[batchTarget]} - // onChange={v => setBatchTarget(v[0])} - // /> - //
- //
- // 将选中的{selectedCount}个用户加入所选分组 - //
- //
- onClose()} - position="bottom" - bodyStyle={{ height: "80vh" }} - > -
-
选择目标分组
- ({ label: p.name, value: p.id }))} - value={[batchTarget]} - onChange={v => setBatchTarget(v[0])} - /> -
-
- 将选中的{selectedCount}个用户加入所选分组 -
-
-); +}) => { + const handSubmit = () => { + onConfirm(packageOptions); + }; + return ( + onClose()} + position="bottom" + bodyStyle={{ height: "80vh" }} + > +
+
选择目标分组
+ ({ label: p.name, value: p.id }))} + value={[batchTarget]} + onChange={v => setBatchTarget(v[0])} + /> +
+ 将选中的{selectedCount}个用户加入所选分组 +
+ +
+
+ ); +}; export default BatchAddModal; diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/dataAnyx.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/dataAnyx.tsx index 8a5f7edc3..ad4fc0379 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/dataAnyx.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/dataAnyx.tsx @@ -5,7 +5,6 @@ import { fetchScenarioOptions, } from "./api"; import type { TrafficPoolUser, PackageOption, ScenarioOption } from "./data"; -import { Toast } from "antd-mobile"; export function useTrafficPoolListLogic() { const [loading, setLoading] = useState(false); @@ -116,19 +115,21 @@ export function useTrafficPoolListLogic() { }; // 批量加入分组/流量池 - const handleBatchAdd = () => { - if (!batchTarget) { - Toast.show({ content: "请选择目标分组", position: "top" }); - return; - } - // TODO: 调用后端批量接口,这里仅模拟 - Toast.show({ - content: `已将${selectedIds.length}个用户加入${packageOptions.find(p => p.id === batchTarget)?.name || ""}`, - position: "top", - }); - setBatchModal(false); - setSelectedIds([]); - setBatchTarget(""); + const handleBatchAdd = options => { + console.log("批量加入分组", options); + + // if (!batchTarget) { + // Toast.show({ content: "请选择目标分组", position: "top" }); + // return; + // } + // // TODO: 调用后端批量接口,这里仅模拟 + // Toast.show({ + // content: `已将${selectedIds.length}个用户加入${packageOptions.find(p => p.id === batchTarget)?.name || ""}`, + // position: "top", + // }); + // setBatchModal(false); + // setSelectedIds([]); + // setBatchTarget(""); // 可刷新列表 }; From ce1eddad6866b02310fdfe7d88d076eb8862639d 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: Mon, 22 Sep 2025 10:49:21 +0800 Subject: [PATCH 02/26] =?UTF-8?q?FEAT=20=3D>=20=E6=9C=AC=E6=AC=A1=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E9=A1=B9=E7=9B=AE=E4=B8=BA=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mine/traffic-pool/list/BatchAddModal.tsx | 67 +++++-- .../traffic-pool/list/DataAnalysisPanel.tsx | 149 +++++++++----- .../mine/traffic-pool/list/FilterModal.tsx | 18 +- .../mine/traffic-pool/list/dataAnyx.tsx | 183 ------------------ .../mobile/mine/traffic-pool/list/index.tsx | 152 +++++++++++---- 5 files changed, 279 insertions(+), 290 deletions(-) delete mode 100644 Cunkebao/src/pages/mobile/mine/traffic-pool/list/dataAnyx.tsx diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx index 19ffcae4a..5feee1593 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/BatchAddModal.tsx @@ -1,28 +1,54 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import { Popup, Selector, Button } from "antd-mobile"; +import { fetchPackageOptions } from "./api"; import type { PackageOption } from "./data"; interface BatchAddModalProps { visible: boolean; onClose: () => void; - packageOptions: PackageOption[]; - batchTarget: string; - setBatchTarget: (v: string) => void; selectedCount: number; - onConfirm: (options) => void; + onConfirm: (data: { + packageOptions: PackageOption[]; + selectedPackageId: string; + }) => void; } const BatchAddModal: React.FC = ({ visible, onClose, - packageOptions = [], - batchTarget, - setBatchTarget, selectedCount, onConfirm, }) => { - const handSubmit = () => { - onConfirm(packageOptions); + const [packageOptions, setPackageOptions] = useState([]); + const [selectedPackageId, setSelectedPackageId] = useState(""); + const [loading, setLoading] = useState(false); + + // 获取分组选项 + useEffect(() => { + if (visible) { + setLoading(true); + fetchPackageOptions() + .then(res => { + setPackageOptions(res.list || []); + }) + .catch(error => { + console.error("获取分组选项失败:", error); + }) + .finally(() => { + setLoading(false); + }); + } + }, [visible]); + + const handleSubmit = () => { + if (!selectedPackageId) { + // 可以添加提示 + return; + } + onConfirm({ + packageOptions, + selectedPackageId, + }); }; return ( = ({ >
选择目标分组
- ({ label: p.name, value: p.id }))} - value={[batchTarget]} - onChange={v => setBatchTarget(v[0])} - /> + {loading ? ( +
加载中...
+ ) : ( + ({ label: p.name, value: p.id }))} + value={[selectedPackageId]} + onChange={v => setSelectedPackageId(v[0])} + /> + )}
= ({ > 将选中的{selectedCount}个用户加入所选分组
-
diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx index 395d7b512..5256de31e 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/DataAnalysisPanel.tsx @@ -1,24 +1,77 @@ -import React from "react"; +import React, { useState, useEffect, useMemo } from "react"; import { Card, Button } from "antd-mobile"; +import { fetchTrafficPoolList } from "./api"; +import type { TrafficPoolUser } from "./data"; interface DataAnalysisPanelProps { - stats: { + showStats: boolean; + setShowStats: (v: boolean) => void; + onConfirm: (stats: { total: number; highValue: number; added: number; pending: number; failed: number; addSuccessRate: number; - }; - showStats: boolean; - setShowStats: (v: boolean) => void; + }) => void; } const DataAnalysisPanel: React.FC = ({ - stats, showStats, setShowStats, + onConfirm, }) => { + const [list, setList] = useState([]); + const [loading, setLoading] = useState(false); + + // 计算统计数据 + const stats = useMemo(() => { + const total = list.length; + const highValue = list.filter( + u => u.tags && u.tags.includes("高价值客户池"), + ).length; + const added = list.filter(u => u.status === 1).length; + const pending = list.filter(u => u.status === 0).length; + const failed = list.filter(u => u.status === -1).length; + const addSuccessRate = total ? Math.round((added / total) * 100) : 0; + return { total, highValue, added, pending, failed, addSuccessRate }; + }, [list]); + + // 获取数据 + useEffect(() => { + if (showStats) { + setLoading(true); + fetchTrafficPoolList({ page: 1, pageSize: 1000 }) // 获取所有数据进行统计 + .then(res => { + setList(res.list || []); + // 通过 onConfirm 抛出统计数据 + const total = res.list?.length || 0; + const highValue = + res.list?.filter(u => u.tags && u.tags.includes("高价值客户池")) + .length || 0; + const added = res.list?.filter(u => u.status === 1).length || 0; + const pending = res.list?.filter(u => u.status === 0).length || 0; + const failed = res.list?.filter(u => u.status === -1).length || 0; + const addSuccessRate = total ? Math.round((added / total) * 100) : 0; + + onConfirm({ + total, + highValue, + added, + pending, + failed, + addSuccessRate, + }); + }) + .catch(error => { + console.error("获取统计数据失败:", error); + }) + .finally(() => { + setLoading(false); + }); + } + }, [showStats, onConfirm]); + if (!showStats) return null; return (
= ({ boxShadow: "0 2px 8px rgba(0,0,0,0.04)", }} > -
- -
- {stats.total} + {loading ? ( +
+ 加载统计数据中... +
+ ) : ( + <> +
+ +
+ {stats.total} +
+
总用户数
+
+ +
+ {stats.highValue} +
+
高价值用户
+
-
总用户数
- - -
- {stats.highValue} +
+ +
+ {stats.addSuccessRate}% +
+
添加成功率
+
+ +
+ {stats.added} +
+
已添加
+
+ +
+ {stats.pending} +
+
待添加
+
+ +
+ {stats.failed} +
+
添加失败
+
-
高价值用户
- -
-
- -
- {stats.addSuccessRate}% -
-
添加成功率
-
- -
- {stats.added} -
-
已添加
-
- -
- {stats.pending} -
-
待添加
-
- -
- {stats.failed} -
-
添加失败
-
-
+ + )}
{/* 数据分析面板 */} { + // 可以在这里处理统计数据,比如更新本地状态或发送到父组件 + console.log("收到统计数据:", statsData); + }} /> {/* 批量操作栏 */} @@ -167,11 +242,12 @@ const TrafficPoolList: React.FC = () => { setBatchModal(false)} - packageOptions={packageOptions} - batchTarget={batchTarget} - setBatchTarget={setBatchTarget} selectedCount={selectedIds.length} - onConfirm={handleBatchAdd} + onConfirm={data => { + console.log("收到批量操作数据:", data); + // 处理批量加入逻辑 + handleBatchAdd(data); + }} /> {/* 筛选弹窗 */} { onConfirm={filters => { // 更新筛选条件 setSelectedDevices( - filters.deviceIds.map(id => ({ + filters.deviceld.map(id => ({ id: parseInt(id), memo: "", imei: "", @@ -188,10 +264,10 @@ const TrafficPoolList: React.FC = () => { status: "offline" as const, })), ); - setPackageId(filters.packageId ? parseInt(filters.packageId) : 0); - setScenarioId(filters.scenarioId ? parseInt(filters.scenarioId) : 0); + setPackageId(filters.packageld ? parseInt(filters.packageld) : 0); + setScenarioId(filters.taskId ? parseInt(filters.taskId) : 0); setUserValue(filters.userValue); - setUserStatus(filters.userStatus); + setUserStatus(filters.addStatus); // 重新获取列表 getList(); }} From deb0eb85b5b70c7c28dcccba6378c65637d7cd70 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: Mon, 22 Sep 2025 11:51:37 +0800 Subject: [PATCH 03/26] =?UTF-8?q?feat(=E6=B5=81=E9=87=8F=E6=B1=A0=E7=AE=A1?= =?UTF-8?q?=E7=90=86):=20=E6=96=B0=E5=A2=9E=E6=B5=81=E9=87=8F=E6=B1=A0?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD=E5=8F=8A=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在流量池管理模块中,新增了添加流量池的API接口,并更新了筛选条件的结构,支持初始值的设置和状态的同步。优化了筛选条件的管理逻辑,提升了用户体验和代码可读性。 --- .../mine/traffic-pool/list/FilterModal.tsx | 50 ++++++--- .../mobile/mine/traffic-pool/list/api.ts | 17 +++ .../mobile/mine/traffic-pool/list/index.tsx | 102 +++++++++--------- 3 files changed, 106 insertions(+), 63 deletions(-) diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx index f1fb7d298..357cee53f 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx @@ -10,13 +10,21 @@ interface FilterModalProps { visible: boolean; onClose: () => void; onConfirm: (filters: { - deviceld: string[]; // 更新为 deviceld - packageld: string; // 更新为 packageld - taskId: string; // 更新为 taskId + selectedDevices: DeviceSelectionItem[]; // 更新为 deviceld + packageld: number; // 更新为 packageld + sceneId: number; // 更新为 sceneId userValue: number; addStatus: number; // 更新为 addStatus }) => void; scenarioOptions: ScenarioOption[]; + // 初始筛选值 + initialFilters?: { + selectedDevices: DeviceSelectionItem[]; + packageId: number; + scenarioId: number; + userValue: number; + userStatus: number; + }; } const valueLevelOptions = [ @@ -37,17 +45,35 @@ const FilterModal: React.FC = ({ visible, onClose, onConfirm, + initialFilters, }) => { const [selectedDevices, setSelectedDevices] = useState( - [], + initialFilters?.selectedDevices || [], + ); + const [packageId, setPackageId] = useState(initialFilters?.packageId); + const [scenarioId, setScenarioId] = useState( + initialFilters?.scenarioId, + ); + const [userValue, setUserValue] = useState( + initialFilters?.userValue || 0, + ); + const [userStatus, setUserStatus] = useState( + initialFilters?.userStatus || 0, ); - const [packageId, setPackageId] = useState(""); - const [scenarioId, setScenarioId] = useState(""); - const [userValue, setUserValue] = useState(0); - const [userStatus, setUserStatus] = useState(0); const [scenarioOptions, setScenarioOptions] = useState([]); const [packageOptions, setPackageOptions] = useState([]); + // 同步初始值变化 + useEffect(() => { + if (initialFilters) { + setSelectedDevices(initialFilters.selectedDevices || []); + setPackageId(initialFilters.packageId || 0); + setScenarioId(initialFilters.scenarioId || 0); + setUserValue(initialFilters.userValue || 0); + setUserStatus(initialFilters.userStatus || 0); + } + }, [initialFilters]); + useEffect(() => { if (visible) { fetchScenarioOptions() @@ -72,9 +98,9 @@ const FilterModal: React.FC = ({ const handleApply = () => { const params = { - deviceld: selectedDevices.map(d => d.id.toString()), // 更新为 deviceld + selectedDevices: selectedDevices, // 更新为 deviceld packageld: packageId, // 更新为 packageld - taskId: scenarioId, // 更新为 taskId + sceneId: scenarioId, // 更新为 sceneId userValue, addStatus: userStatus, // 更新为 addStatus }; @@ -119,7 +145,7 @@ const FilterModal: React.FC = ({ value={packageId} onChange={setPackageId} options={[ - { label: "全部流量池", value: "" }, + { label: "全部流量池", value: 0 }, ...packageOptions.map(p => ({ label: p.name, value: p.id })), ]} /> @@ -131,7 +157,7 @@ const FilterModal: React.FC = ({ value={scenarioId} onChange={setScenarioId} options={[ - { label: "全部场景", value: "" }, + { label: "全部场景", value: 0 }, ...scenarioOptions.map(s => ({ label: s.name, value: s.id })), ]} /> diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts index 5f1509e59..2116682bd 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts @@ -16,3 +16,20 @@ export async function fetchScenarioOptions() { export async function fetchPackageOptions() { return request("/v1/traffic/pool/getPackage", {}, "GET"); } + +export async function addPackage(params: { + type: string; // 类型 1搜索 2选择用户 3文件上传 + addPackageId?: string; + addStatus?: string; + deviceId?: string; + keyword?: string; + packageId?: string; + packageName?: string; // 添加的流量池名称 + tableFile?: string; + taskId?: string; // 任务id j及场景获客id + "userIds[]"?: string[]; + userValue?: string; + [property: string]: any; +}) { + return request("/v1/traffic/pool/addPackage", params, "POST"); +} diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx index d53bea0cc..2a5c0b864 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx @@ -15,7 +15,8 @@ import type { TrafficPoolUser, ScenarioOption } from "./data"; import DataAnalysisPanel from "./DataAnalysisPanel"; import FilterModal from "./FilterModal"; import BatchAddModal from "./BatchAddModal"; - +import { DeviceSelectionItem } from "@/components/DeviceSelection/data"; +import { join } from "path"; const defaultAvatar = "https://cdn.jsdelivr.net/gh/maokaka/static/avatar-default.png"; @@ -33,11 +34,15 @@ const TrafficPoolList: React.FC = () => { // 筛选相关 const [showFilter, setShowFilter] = useState(false); const [scenarioOptions, setScenarioOptions] = useState([]); - const [selectedDevices, setSelectedDevices] = useState([]); - const [packageId, setPackageId] = useState(0); - const [scenarioId, setScenarioId] = useState(0); - const [userValue, setUserValue] = useState(0); - const [userStatus, setUserStatus] = useState(0); + + // 公共筛选条件状态 + const [filterParams, setFilterParams] = useState({ + selectedDevices: [] as DeviceSelectionItem[], + packageId: 0, + scenarioId: 0, + userValue: 0, + userStatus: 0, + }); // 批量相关 const [selectedIds, setSelectedIds] = useState([]); @@ -47,23 +52,21 @@ const TrafficPoolList: React.FC = () => { const [showStats, setShowStats] = useState(false); // 获取列表 - const getList = async () => { + const getList = async (customParams?: any) => { setLoading(true); try { const params: any = { page, pageSize, keyword: search, - packageld: packageId, // 更新为 packageld - taskId: scenarioId, - userValue, - addStatus: userStatus, + packageld: filterParams.packageId, + sceneId: filterParams.scenarioId, + userValue: filterParams.userValue, + addStatus: filterParams.userStatus, + deviceld: filterParams.selectedDevices.map(d => d.id).join(), + ...customParams, // 允许传入自定义参数覆盖 }; - - // 添加筛选参数 - if (selectedDevices.length > 0) { - params.deviceld = selectedDevices.map(d => d.id).join(","); // 更新为 deviceld - } + console.log("搜索条件:", params); const res = await fetchTrafficPoolList(params); setList(res.list || []); @@ -85,20 +88,6 @@ const TrafficPoolList: React.FC = () => { }); }, []); - // 筛选条件变化时刷新列表 - useEffect(() => { - getList(); - // eslint-disable-next-line - }, [ - page, - search, - selectedDevices, - packageId, - scenarioId, - userValue, - userStatus, - ]); - // 全选/反选 const handleSelectAll = (checked: boolean) => { if (checked) { @@ -118,6 +107,7 @@ const TrafficPoolList: React.FC = () => { // 批量加入分组/流量池 const handleBatchAdd = options => { console.log("批量加入分组", options); + // TODO: 实现批量加入逻辑 setBatchModal(false); setSelectedIds([]); @@ -129,10 +119,13 @@ const TrafficPoolList: React.FC = () => { const debouncedSearch = useCallback(() => { const timer = setTimeout(() => { setSearch(searchInput); + // 搜索时重置到第一页并请求列表 + setPage(1); + getList({ keyword: searchInput, page: 1 }); }, 500); // 500ms 防抖延迟 return () => clearTimeout(timer); - }, [searchInput, setSearch]); + }, [searchInput]); useEffect(() => { const cleanup = debouncedSearch(); @@ -168,7 +161,7 @@ const TrafficPoolList: React.FC = () => { />
} @@ -244,7 +240,6 @@ const TrafficPoolList: React.FC = () => { onClose={() => setBatchModal(false)} selectedCount={selectedIds.length} onConfirm={data => { - console.log("收到批量操作数据:", data); // 处理批量加入逻辑 handleBatchAdd(data); }} @@ -254,24 +249,29 @@ const TrafficPoolList: React.FC = () => { visible={showFilter} onClose={() => setShowFilter(false)} onConfirm={filters => { - // 更新筛选条件 - setSelectedDevices( - filters.deviceld.map(id => ({ - id: parseInt(id), - memo: "", - imei: "", - wechatId: "", - status: "offline" as const, - })), - ); - setPackageId(filters.packageld ? parseInt(filters.packageld) : 0); - setScenarioId(filters.taskId ? parseInt(filters.taskId) : 0); - setUserValue(filters.userValue); - setUserStatus(filters.addStatus); - // 重新获取列表 - getList(); + // 更新公共筛选条件状态 + const newFilterParams = { + selectedDevices: filters.selectedDevices, + packageId: filters.packageld, + scenarioId: filters.sceneId, + userValue: filters.userValue, + userStatus: filters.addStatus, + }; + + setFilterParams(newFilterParams); + // 重置到第一页并请求列表 + setPage(1); + getList({ + page: 1, + packageld: newFilterParams.packageId, + sceneId: newFilterParams.scenarioId, + userValue: newFilterParams.userValue, + addStatus: newFilterParams.userStatus, + deviceld: newFilterParams.selectedDevices.map(d => d.id).join(), + }); }} scenarioOptions={scenarioOptions} + initialFilters={filterParams} />
{list.length === 0 && !loading ? ( From a9b769e51007c237b7ca08065608981a25f190d7 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: Mon, 22 Sep 2025 14:15:23 +0800 Subject: [PATCH 04/26] =?UTF-8?q?FEAT=20=3D>=20=E6=9C=AC=E6=AC=A1=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E9=A1=B9=E7=9B=AE=E4=B8=BA=EF=BC=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cunkebao/dist/.vite/manifest.json | 2 +- Cunkebao/dist/index.html | 2 +- .../mine/traffic-pool/list/FilterModal.tsx | 4 +- .../mobile/mine/traffic-pool/list/api.ts | 17 +++-- .../mobile/mine/traffic-pool/list/index.tsx | 70 ++++++++++++++++--- 5 files changed, 74 insertions(+), 21 deletions(-) diff --git a/Cunkebao/dist/.vite/manifest.json b/Cunkebao/dist/.vite/manifest.json index 84b250208..5aef74398 100644 --- a/Cunkebao/dist/.vite/manifest.json +++ b/Cunkebao/dist/.vite/manifest.json @@ -33,7 +33,7 @@ "name": "vendor" }, "index.html": { - "file": "assets/index-Czxez1-3.js", + "file": "assets/index-DSkLRL1o.js", "name": "index", "src": "index.html", "isEntry": true, diff --git a/Cunkebao/dist/index.html b/Cunkebao/dist/index.html index 6e11cb6ce..6e5939429 100644 --- a/Cunkebao/dist/index.html +++ b/Cunkebao/dist/index.html @@ -11,7 +11,7 @@ - + diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx index 357cee53f..4bf980234 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx @@ -112,8 +112,8 @@ const FilterModal: React.FC = ({ const handleReset = () => { setSelectedDevices([]); - setPackageId(""); - setScenarioId(""); + setPackageId(0); + setScenarioId(0); setUserValue(0); setUserStatus(0); }; diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts index 2116682bd..9b53c030a 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts @@ -19,17 +19,16 @@ export async function fetchPackageOptions() { export async function addPackage(params: { type: string; // 类型 1搜索 2选择用户 3文件上传 - addPackageId?: string; - addStatus?: string; + addPackageId?: number; + addStatus?: number; deviceId?: string; keyword?: string; - packageId?: string; - packageName?: string; // 添加的流量池名称 - tableFile?: string; - taskId?: string; // 任务id j及场景获客id - "userIds[]"?: string[]; - userValue?: string; - [property: string]: any; + packageId?: number; + packageName?: number; // 添加的流量池名称 + tableFile?: number; + taskId?: number; // 任务id j及场景获客id + userIds?: number[]; + userValue?: number; }) { return request("/v1/traffic/pool/addPackage", params, "POST"); } diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx index 2a5c0b864..fb1e6b0cc 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx @@ -5,18 +5,18 @@ import { ReloadOutlined, BarChartOutlined, } from "@ant-design/icons"; +import { Toast } from "antd-mobile"; import { Input, Button, Checkbox, Pagination } from "antd"; import styles from "./index.module.scss"; import { Empty, Avatar } from "antd-mobile"; import { useNavigate } from "react-router-dom"; import NavCommon from "@/components/NavCommon"; -import { fetchTrafficPoolList, fetchScenarioOptions } from "./api"; +import { fetchTrafficPoolList, fetchScenarioOptions, addPackage } from "./api"; import type { TrafficPoolUser, ScenarioOption } from "./data"; import DataAnalysisPanel from "./DataAnalysisPanel"; import FilterModal from "./FilterModal"; import BatchAddModal from "./BatchAddModal"; import { DeviceSelectionItem } from "@/components/DeviceSelection/data"; -import { join } from "path"; const defaultAvatar = "https://cdn.jsdelivr.net/gh/maokaka/static/avatar-default.png"; @@ -66,7 +66,6 @@ const TrafficPoolList: React.FC = () => { deviceld: filterParams.selectedDevices.map(d => d.id).join(), ...customParams, // 允许传入自定义参数覆盖 }; - console.log("搜索条件:", params); const res = await fetchTrafficPoolList(params); setList(res.list || []); @@ -105,12 +104,55 @@ const TrafficPoolList: React.FC = () => { }; // 批量加入分组/流量池 - const handleBatchAdd = options => { - console.log("批量加入分组", options); + const handleBatchAdd = async options => { + try { + // 构建请求参数 + const params = { + type: "2", // 2选择用户 + addPackageId: options.selectedPackageId, // 目标分组ID + userIds: selectedIds.map(id => id), // 选中的用户ID数组 + // 如果有当前筛选条件,也可以传递 + ...(filterParams.packageId && { + packageId: filterParams.packageId, + }), + ...(filterParams.scenarioId && { + taskId: filterParams.scenarioId, + }), + ...(filterParams.userValue && { + userValue: filterParams.userValue, + }), + ...(filterParams.userStatus && { + addStatus: filterParams.userStatus, + }), + ...(filterParams.selectedDevices.length > 0 && { + deviceId: filterParams.selectedDevices.map(d => d.id).join(","), + }), + ...(search && { keyword: search }), + }; - // TODO: 实现批量加入逻辑 - setBatchModal(false); - setSelectedIds([]); + console.log("批量加入请求参数:", params); + + // 调用接口 + const result = await addPackage(params); + console.log("批量加入结果:", result); + + // 成功后刷新列表 + getList(); + + // 关闭弹窗并清空选择 + setBatchModal(false); + setSelectedIds([]); + + // 可以添加成功提示 + Toast.show({ + content: `成功将${selectedIds.length}个用户加入分组`, + position: "top", + }); + } catch (error) { + console.error("批量加入失败:", error); + // 可以添加错误提示 + Toast.show({ content: "批量加入失败,请重试", position: "top" }); + } }; // 搜索防抖处理 @@ -208,6 +250,18 @@ const TrafficPoolList: React.FC = () => { )} + {searchInput.length > 0 && ( + <> + + + )}