diff --git a/Cunkebao/dist/.vite/manifest.json b/Cunkebao/dist/.vite/manifest.json
index 70d5d6b2..70988547 100644
--- a/Cunkebao/dist/.vite/manifest.json
+++ b/Cunkebao/dist/.vite/manifest.json
@@ -33,7 +33,7 @@
"name": "vendor"
},
"index.html": {
- "file": "assets/index-Cp05akVy.js",
+ "file": "assets/index-AbKWTcUz.js",
"name": "index",
"src": "index.html",
"isEntry": true,
@@ -44,7 +44,7 @@
"_charts-D0fT04H8.js"
],
"css": [
- "assets/index-Eg_DAu9e.css"
+ "assets/index-V1Q-fxX3.css"
]
}
}
\ No newline at end of file
diff --git a/Cunkebao/dist/index.html b/Cunkebao/dist/index.html
index 6261e31e..16cb8970 100644
--- a/Cunkebao/dist/index.html
+++ b/Cunkebao/dist/index.html
@@ -11,13 +11,13 @@
-
+
-
+
diff --git a/Cunkebao/src/pages/mobile/scenarios/plan/new/steps/FriendRequestSettings.tsx b/Cunkebao/src/pages/mobile/scenarios/plan/new/steps/FriendRequestSettings.tsx
index 4734c615..5aa73aed 100644
--- a/Cunkebao/src/pages/mobile/scenarios/plan/new/steps/FriendRequestSettings.tsx
+++ b/Cunkebao/src/pages/mobile/scenarios/plan/new/steps/FriendRequestSettings.tsx
@@ -87,18 +87,14 @@ const FriendRequestSettings: React.FC = ({
return (
{/* 选择设备区块 */}
- {![7].includes(formData.scenario) && (
- <>
-
选择设备
-
-
-
- >
- )}
+
选择设备
+
+
+
{/* 好友备注区块 */}
好友备注
diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/AccountListModal.tsx b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/AccountListModal.tsx
new file mode 100644
index 00000000..79bc23a7
--- /dev/null
+++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/AccountListModal.tsx
@@ -0,0 +1,126 @@
+import React from "react";
+import { Popup, Avatar } from "antd-mobile";
+import { Button } from "antd";
+import { CloseOutlined } from "@ant-design/icons";
+import style from "./index.module.scss";
+
+interface AccountItem {
+ id: string | number;
+ nickname?: string;
+ wechatId?: string;
+ avatar?: string;
+ status?: string;
+}
+
+interface AccountListModalProps {
+ visible: boolean;
+ onClose: () => void;
+ accounts: AccountItem[];
+ title?: string;
+}
+
+const AccountListModal: React.FC
= ({
+ visible,
+ onClose,
+ accounts,
+ title = "分发账号列表",
+}) => {
+ const getStatusColor = (status?: string) => {
+ switch (status) {
+ case "normal":
+ return "#52c41a";
+ case "limited":
+ return "#faad14";
+ case "blocked":
+ return "#ff4d4f";
+ default:
+ return "#d9d9d9";
+ }
+ };
+
+ const getStatusText = (status?: string) => {
+ switch (status) {
+ case "normal":
+ return "正常";
+ case "limited":
+ return "受限";
+ case "blocked":
+ return "封禁";
+ default:
+ return "未知";
+ }
+ };
+
+ return (
+
+
+ {/* 头部 */}
+
+
{title}
+ }
+ onClick={onClose}
+ className={style.accountModalClose}
+ />
+
+
+ {/* 账号列表 */}
+
+ {accounts.length > 0 ? (
+ accounts.map((account, index) => (
+
+
+
+ {(account.nickname || account.wechatId || "账号")[0]}
+
+
+
+
+ {account.nickname ||
+ account.wechatId ||
+ `账号${account.id}`}
+
+
+ {account.wechatId || "未绑定微信号"}
+
+
+
+
+
+ {getStatusText(account.status)}
+
+
+
+ ))
+ ) : (
+
+ )}
+
+
+ {/* 底部统计 */}
+
+
+ 共 {accounts.length} 个账号
+
+
+
+
+ );
+};
+
+export default AccountListModal;
diff --git a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/DeviceListModal.tsx b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/DeviceListModal.tsx
new file mode 100644
index 00000000..ea26f58e
--- /dev/null
+++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/DeviceListModal.tsx
@@ -0,0 +1,141 @@
+import React from "react";
+import { Popup, Avatar } from "antd-mobile";
+import { Button } from "antd";
+import { CloseOutlined } from "@ant-design/icons";
+import style from "./index.module.scss";
+
+interface DeviceItem {
+ id: string | number;
+ memo?: string;
+ imei?: string;
+ wechatId?: string;
+ status?: "online" | "offline";
+ avatar?: string;
+ totalFriend?: number;
+}
+
+interface DeviceListModalProps {
+ visible: boolean;
+ onClose: () => void;
+ devices: DeviceItem[];
+ title?: string;
+}
+
+const DeviceListModal: React.FC = ({
+ visible,
+ onClose,
+ devices,
+ title = "分发设备列表",
+}) => {
+ const getStatusColor = (status?: string) => {
+ return status === "online" ? "#52c41a" : "#ff4d4f";
+ };
+
+ const getStatusText = (status?: string) => {
+ return status === "online" ? "在线" : "离线";
+ };
+
+ return (
+
+
+ {/* 头部 */}
+
+
{title}
+ }
+ onClick={onClose}
+ className={style.deviceModalClose}
+ />
+
+
+ {/* 设备列表 */}
+
+ {devices.length > 0 ? (
+ devices.map((device, index) => (
+
+ {/* 顶部行:IMEI */}
+
+
+ IMEI: {device.imei?.toUpperCase() || "-"}
+
+
+
+ {/* 主要内容区域:头像和详细信息 */}
+
+ {/* 头像 */}
+
+ {device.avatar ? (
+

+ ) : (
+
+ {(device.memo || device.wechatId || "设")[0]}
+
+ )}
+
+
+ {/* 设备信息 */}
+
+
+
+ {device.memo || "未命名设备"}
+
+
+ {getStatusText(device.status)}
+
+
+
+
+
+ 微信号:
+
+ {device.wechatId || "未绑定"}
+
+
+
+ 好友数:
+
+ {device.totalFriend ?? "-"}
+
+
+
+
+
+
+ ))
+ ) : (
+
+ )}
+
+
+ {/* 底部统计 */}
+
+
+ 共 {devices.length} 个设备
+
+
+
+
+ );
+};
+
+export default DeviceListModal;
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 a9770b88..f30dfa28 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
@@ -69,10 +69,15 @@
.ruleMetaItem {
flex: 1;
text-align: center;
+ transition: background-color 0.2s ease;
}
.ruleMetaItem:not(:last-child) {
border-right: 1px solid #f0f0f0;
}
+.ruleMetaItem:hover {
+ background-color: #f8f9fa;
+ border-radius: 6px;
+}
.ruleDivider {
border-top: 1px solid #f0f0f0;
@@ -124,3 +129,313 @@
padding: 16px 0;
background: #fff;
}
+
+// 账号列表弹窗样式
+.accountModal {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+.accountModalHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px 20px;
+ border-bottom: 1px solid #f0f0f0;
+ background: #fff;
+}
+
+.accountModalTitle {
+ margin: 0;
+ font-size: 18px;
+ font-weight: 600;
+ color: #222;
+}
+
+.accountModalClose {
+ border: none;
+ background: none;
+ color: #888;
+ font-size: 16px;
+}
+
+.accountList {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0 20px;
+}
+
+.accountItem {
+ display: flex;
+ align-items: center;
+ padding: 12px 0;
+ border-bottom: 1px solid #f5f5f5;
+}
+
+.accountItem:last-child {
+ border-bottom: none;
+}
+
+.accountAvatar {
+ margin-right: 12px;
+ flex-shrink: 0;
+}
+
+.accountInfo {
+ flex: 1;
+ min-width: 0;
+}
+
+.accountName {
+ font-size: 16px;
+ font-weight: 500;
+ color: #222;
+ margin-bottom: 4px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.accountWechatId {
+ font-size: 14px;
+ color: #888;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.accountStatus {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ flex-shrink: 0;
+}
+
+.statusDot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+}
+
+.statusText {
+ font-size: 13px;
+ color: #666;
+}
+
+.accountEmpty {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 200px;
+ color: #888;
+}
+
+.accountEmptyText {
+ font-size: 16px;
+}
+
+.accountModalFooter {
+ padding: 16px 20px;
+ border-top: 1px solid #f0f0f0;
+ background: #fff;
+}
+
+.accountStats {
+ text-align: center;
+ font-size: 14px;
+ color: #666;
+}
+
+// 设备列表弹窗样式
+.deviceModal {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+.deviceModalHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px 20px;
+ border-bottom: 1px solid #f0f0f0;
+ background: #fff;
+}
+
+.deviceModalTitle {
+ margin: 0;
+ font-size: 18px;
+ font-weight: 600;
+ color: #222;
+}
+
+.deviceModalClose {
+ border: none;
+ background: none;
+ color: #888;
+ font-size: 16px;
+}
+
+.deviceList {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0 20px;
+}
+
+.deviceItem {
+ background: #fff;
+ border-radius: 12px;
+ padding: 12px;
+ margin-bottom: 12px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+ border: 1px solid #ececec;
+ transition: all 0.2s ease;
+}
+
+.deviceItem:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
+}
+
+.deviceHeaderRow {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 8px;
+}
+
+.deviceImeiText {
+ font-size: 13px;
+ color: #888;
+ font-weight: 500;
+}
+
+.deviceMainContent {
+ display: flex;
+ align-items: center;
+}
+
+.deviceAvatar {
+ width: 48px;
+ height: 48px;
+ border-radius: 12px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 12px;
+ flex-shrink: 0;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+ overflow: hidden;
+}
+
+.deviceAvatar img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ border-radius: 12px;
+}
+
+.deviceAvatarText {
+ color: #fff;
+ font-size: 18px;
+ font-weight: 600;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
+}
+
+.deviceInfo {
+ flex: 1;
+ min-width: 0;
+}
+
+.deviceInfoHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 6px;
+}
+
+.deviceName {
+ margin: 0;
+ font-size: 16px;
+ font-weight: 600;
+ color: #222;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ flex: 1;
+ margin-right: 8px;
+}
+
+.deviceStatusBadge {
+ padding: 2px 8px;
+ border-radius: 10px;
+ font-size: 12px;
+ font-weight: 500;
+ flex-shrink: 0;
+}
+
+.deviceStatusOnline {
+ background: rgba(82, 196, 26, 0.1);
+ color: #52c41a;
+}
+
+.deviceStatusOffline {
+ background: rgba(255, 77, 79, 0.1);
+ color: #ff4d4f;
+}
+
+.deviceInfoList {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.deviceInfoItem {
+ display: flex;
+ align-items: center;
+ font-size: 13px;
+}
+
+.deviceInfoLabel {
+ color: #888;
+ margin-right: 6px;
+ min-width: 50px;
+}
+
+.deviceInfoValue {
+ color: #444;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.deviceFriendCount {
+ color: #1890ff;
+ font-weight: 500;
+}
+
+.deviceEmpty {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 200px;
+ color: #888;
+}
+
+.deviceEmptyText {
+ font-size: 16px;
+}
+
+.deviceModalFooter {
+ padding: 16px 20px;
+ border-top: 1px solid #f0f0f0;
+ background: #fff;
+}
+
+.deviceStats {
+ text-align: center;
+ font-size: 14px;
+ color: #666;
+}
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 940622a8..0b571ecf 100644
--- a/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx
+++ b/Cunkebao/src/pages/mobile/workspace/traffic-distribution/list/index.tsx
@@ -32,6 +32,8 @@ import {
} from "@ant-design/icons";
import style from "./index.module.scss";
import { useNavigate } from "react-router-dom";
+import AccountListModal from "./AccountListModal";
+import DeviceListModal from "./DeviceListModal";
const PAGE_SIZE = 10;
@@ -51,6 +53,14 @@ const TrafficDistributionList: React.FC = () => {
const [searchQuery, setSearchQuery] = useState("");
// 优化:用menuLoadingId标记当前操作的item
const [menuLoadingId, setMenuLoadingId] = useState(null);
+ // 账号列表弹窗
+ const [accountModalVisible, setAccountModalVisible] = useState(false);
+ const [currentAccounts, setCurrentAccounts] = useState([]);
+ const [currentRuleName, setCurrentRuleName] = useState("");
+ // 设备列表弹窗
+ const [deviceModalVisible, setDeviceModalVisible] = useState(false);
+ const [currentDevices, setCurrentDevices] = useState([]);
+ const [currentDeviceRuleName, setCurrentDeviceRuleName] = useState("");
const navigate = useNavigate();
useEffect(() => {
@@ -128,6 +138,44 @@ const TrafficDistributionList: React.FC = () => {
}
};
+ // 显示账号列表弹窗
+ const showAccountList = (item: DistributionRule) => {
+ // 这里需要根据实际的账号数据结构来转换
+ // 假设 item.config.account 是账号ID数组,需要转换为账号对象数组
+ const accounts = (item.config?.account || []).map(
+ (accountId: string | number) => ({
+ id: accountId,
+ nickname: `账号${accountId}`,
+ wechatId: `wx_${accountId}`,
+ avatar: "",
+ status: "normal",
+ }),
+ );
+
+ setCurrentAccounts(accounts);
+ setCurrentRuleName(item.name);
+ setAccountModalVisible(true);
+ };
+
+ // 显示设备列表弹窗
+ const showDeviceList = (item: DistributionRule) => {
+ // 这里需要根据实际的设备数据结构来转换
+ // 假设 item.config.devices 是设备ID数组,需要转换为设备对象数组
+ const devices = (item.config?.devices || []).map((deviceId: string) => ({
+ id: deviceId,
+ memo: `设备${deviceId}`,
+ imei: `IMEI${deviceId}`,
+ wechatId: `wx_${deviceId}`,
+ status: "online" as const,
+ avatar: "",
+ totalFriend: Math.floor(Math.random() * 1000) + 100,
+ }));
+
+ setCurrentDevices(devices);
+ setCurrentDeviceRuleName(item.name);
+ setDeviceModalVisible(true);
+ };
+
const renderCard = (item: DistributionRule) => {
const menu = (
-
+
showAccountList(item)}
+ >
{item.config?.account?.length || 0}
分发账号
-
+
showDeviceList(item)}
+ >
{item.config?.devices?.length || 0}
@@ -325,6 +381,22 @@ const TrafficDistributionList: React.FC = () => {
暂无数据
)}
+
+ {/* 账号列表弹窗 */}
+
setAccountModalVisible(false)}
+ accounts={currentAccounts}
+ title={`${currentRuleName} - 分发账号列表`}
+ />
+
+ {/* 设备列表弹窗 */}
+ setDeviceModalVisible(false)}
+ devices={currentDevices}
+ title={`${currentDeviceRuleName} - 分发设备列表`}
+ />
);
};