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 93c5002e..67d4ba32 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/api.ts @@ -31,3 +31,13 @@ export function deleteDistributionRule(id: number): Promise { export function fetchDistributionRuleDetail(id: number): Promise { return request(`/v1/workbench/detail?id=${id}`, {}, "GET"); } + +//流量分发记录 +export function fetchTransferFriends(params: { + page?: number; + limit?: number; + keyword?: string; + workbenchId: number; +}) { + return request("/v1/workbench/transfer-friends", params, "GET"); +} diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/components/SendRcrodModal.tsx b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/components/SendRcrodModal.tsx new file mode 100644 index 00000000..e82d27e9 --- /dev/null +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/components/SendRcrodModal.tsx @@ -0,0 +1,232 @@ +import React, { useEffect, useState } from "react"; +import { Popup, Avatar, SpinLoading, Input } from "antd-mobile"; +import { Button, message, Pagination } from "antd"; +import { CloseOutlined, SearchOutlined } from "@ant-design/icons"; +import style from "../index.module.scss"; +import { fetchTransferFriends } from "../api"; + +interface SendRecordItem { + id: string | number; + nickname?: string; + wechatId?: string; + avatar?: string; + status?: string; + isRecycle?: number; + sendTime?: string; + sendCount?: number; +} + +interface SendRcrodModalProps { + visible: boolean; + onClose: () => void; + ruleId?: number; + ruleName?: string; +} + +const SendRcrodModal: React.FC = ({ + visible, + onClose, + ruleId, + ruleName, +}) => { + const [sendRecords, setSendRecords] = useState([]); + const [loading, setLoading] = useState(false); + const [searchQuery, setSearchQuery] = useState(""); + const [searchKeyword, setSearchKeyword] = useState(""); + const [currentPage, setCurrentPage] = useState(1); + const [total, setTotal] = useState(0); + const pageSize = 20; + + // 获取分发记录数据 + const fetchSendRecords = async (page = 1, keyword = "") => { + if (!ruleId || !visible) return; + + setLoading(true); + try { + const detailRes = await fetchTransferFriends({ + workbenchId: ruleId, + page, + limit: pageSize, + keyword, + }); + console.log(detailRes); + + const recordData = detailRes.list || []; + setSendRecords(recordData); + setTotal(detailRes.total || 0); + } catch (error) { + console.error("获取分发记录失败:", error); + message.error("获取分发记录失败"); + } finally { + setLoading(false); + } + }; + + // 当弹窗打开且有ruleId时,获取数据 + useEffect(() => { + if (visible && ruleId) { + setCurrentPage(1); + setSearchQuery(""); + setSearchKeyword(""); + fetchSendRecords(1, ""); + } + }, [visible, ruleId]); + + // 搜索关键词变化时触发搜索 + useEffect(() => { + if (!visible || !ruleId) return; + setCurrentPage(1); + fetchSendRecords(1, searchKeyword); + }, [searchKeyword, visible, ruleId]); + + // 页码变化 + useEffect(() => { + if (!visible || !ruleId || currentPage === 1) return; + fetchSendRecords(currentPage, searchKeyword); + }, [currentPage, visible, ruleId]); + + // 处理页码变化 + const handlePageChange = (page: number) => { + setCurrentPage(page); + }; + + // 处理搜索回车 + const handleSearchEnter = () => { + setSearchKeyword(searchQuery); + }; + + // 处理搜索输入 + const handleSearchChange = (value: string) => { + setSearchQuery(value); + }; + + const title = ruleName ? `${ruleName} - 分发统计` : "分发统计"; + const getRecycleColor = (isRecycle?: number) => { + switch (isRecycle) { + case 0: + return "#52c41a"; // 绿色 - 未回收 + case 1: + return "#ff4d4f"; // 红色 - 已回收 + default: + return "#d9d9d9"; // 灰色 - 未知状态 + } + }; + + const getRecycleText = (isRecycle?: number) => { + switch (isRecycle) { + case 0: + return "未回收"; + case 1: + return "已回收"; + default: + return "未知"; + } + }; + + return ( + +
+ {/* 头部 */} +
+

{title}

+
+ + {/* 搜索栏 */} +
+
+ + +
+
+ + {/* 分发记录列表 */} +
+ {loading ? ( +
+ +
+ 正在加载分发记录... +
+
+ ) : sendRecords.length > 0 ? ( + sendRecords.map((record, index) => ( +
+
+ +
+
+
+ {record.nickname || record.wechatId || `账号${record.id}`} +
+
+ {record.wechatId || "未绑定微信号"} +
+
+
+ + + {getRecycleText(record.isRecycle)} + +
+
+ )) + ) : ( +
+
暂无分发记录
+
+ )} +
+ + {/* 底部统计和分页 */} +
+
+ 共 {total} 条分发记录 +
+
+ +
+
+
+
+ ); +}; + +export default SendRcrodModal; diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.module.scss b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.module.scss index 9f5adc14..1415242c 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.module.scss +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.module.scss @@ -255,6 +255,9 @@ padding: 16px 20px; border-top: 1px solid #f0f0f0; background: #fff; + display: flex; + justify-content: space-between; + align-items: center; } .accountStats { @@ -263,6 +266,39 @@ color: #666; } +.searchBar { + padding: 16px 20px; + border-bottom: 1px solid #f0f0f0; + background: #fff; +} + +.searchInputWrapper { + position: relative; + display: flex; + align-items: center; +} + +.searchIcon { + position: absolute; + left: 12px; + top: 50%; + transform: translateY(-50%); + color: #999; + font-size: 16px; + z-index: 1; +} + +.searchInputWrapper :global(.adm-input) { + padding-left: 40px; + border-radius: 8px; + height: 40px; +} + +.paginationContainer { + display: flex; + justify-content: center; +} + // 设备列表弹窗样式 .deviceModal { height: 100%; diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx index b36a58ef..f94f54ba 100644 --- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx +++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx @@ -34,6 +34,7 @@ import { useNavigate } from "react-router-dom"; import AccountListModal from "./components/AccountListModal"; import DeviceListModal from "./components/DeviceListModal"; import PoolListModal from "./components/PoolListModal"; +import SendRcrodModal from "./components/SendRcrodModal"; const PAGE_SIZE = 10; @@ -57,6 +58,7 @@ const TrafficDistributionList: React.FC = () => { const [accountModalVisible, setAccountModalVisible] = useState(false); const [deviceModalVisible, setDeviceModalVisible] = useState(false); const [poolModalVisible, setPoolModalVisible] = useState(false); + const [sendRecordModalVisible, setSendRecordModalVisible] = useState(false); const [currentRule, setCurrentRule] = useState(null); const navigate = useNavigate(); @@ -153,6 +155,12 @@ const TrafficDistributionList: React.FC = () => { setPoolModalVisible(true); }; + // 显示分发统计弹窗 + const showSendRecord = (item: DistributionRule) => { + setCurrentRule(item); + setSendRecordModalVisible(true); + }; + const renderCard = (item: DistributionRule) => { const menu = ( handleMenuClick(key, item)}> @@ -287,7 +295,11 @@ const TrafficDistributionList: React.FC = () => { 总流量池数量 -
+
showSendRecord(item)} + > {item.config?.total?.totalUsers || 0} @@ -394,6 +406,14 @@ const TrafficDistributionList: React.FC = () => { ruleId={currentRule?.id} ruleName={currentRule?.name} /> + + {/* 分发统计弹窗 */} + setSendRecordModalVisible(false)} + ruleId={currentRule?.id} + ruleName={currentRule?.name} + /> ); };