diff --git a/Cunkebao/dist/.vite/manifest.json b/Cunkebao/dist/.vite/manifest.json
index 5c1e7050..70d5d6b2 100644
--- a/Cunkebao/dist/.vite/manifest.json
+++ b/Cunkebao/dist/.vite/manifest.json
@@ -1,9 +1,9 @@
{
- "_charts-TuAbbBZ5.js": {
- "file": "assets/charts-TuAbbBZ5.js",
+ "_charts-D0fT04H8.js": {
+ "file": "assets/charts-D0fT04H8.js",
"name": "charts",
"imports": [
- "_ui-D1w-jetn.js",
+ "_ui-qLeQLv1F.js",
"_vendor-2vc8h_ct.js"
]
},
@@ -11,8 +11,8 @@
"file": "assets/ui-D0C0OGrH.css",
"src": "_ui-D0C0OGrH.css"
},
- "_ui-D1w-jetn.js": {
- "file": "assets/ui-D1w-jetn.js",
+ "_ui-qLeQLv1F.js": {
+ "file": "assets/ui-qLeQLv1F.js",
"name": "ui",
"imports": [
"_vendor-2vc8h_ct.js"
@@ -33,18 +33,18 @@
"name": "vendor"
},
"index.html": {
- "file": "assets/index-DTZ_ow5W.js",
+ "file": "assets/index-Cp05akVy.js",
"name": "index",
"src": "index.html",
"isEntry": true,
"imports": [
"_vendor-2vc8h_ct.js",
- "_ui-D1w-jetn.js",
+ "_ui-qLeQLv1F.js",
"_utils-6WF66_dS.js",
- "_charts-TuAbbBZ5.js"
+ "_charts-D0fT04H8.js"
],
"css": [
- "assets/index-B0SB167P.css"
+ "assets/index-Eg_DAu9e.css"
]
}
}
\ No newline at end of file
diff --git a/Cunkebao/dist/index.html b/Cunkebao/dist/index.html
index a3b55d54..6261e31e 100644
--- a/Cunkebao/dist/index.html
+++ b/Cunkebao/dist/index.html
@@ -10,14 +10,14 @@
}
-
-
+
+
-
+
-
+
-
+
diff --git a/Cunkebao/index.html b/Cunkebao/index.html
index 92ab92a7..16de6c67 100644
--- a/Cunkebao/index.html
+++ b/Cunkebao/index.html
@@ -10,7 +10,7 @@
}
-
+
diff --git a/Cunkebao/src/components/DeviceSelection/index.tsx b/Cunkebao/src/components/DeviceSelection/index.tsx
index 997c56f2..ba6952cd 100644
--- a/Cunkebao/src/components/DeviceSelection/index.tsx
+++ b/Cunkebao/src/components/DeviceSelection/index.tsx
@@ -46,6 +46,12 @@ const DeviceSelection: React.FC = ({
onSelect(selectedOptions.filter(v => v.id !== id));
};
+ // 清除所有已选设备
+ const handleClearAll = () => {
+ if (readonly) return;
+ onSelect([]);
+ };
+
return (
<>
{/* mode=input 显示输入框,mode=dialog不显示 */}
@@ -57,6 +63,7 @@ const DeviceSelection: React.FC = ({
onClick={openPopup}
prefix={}
allowClear={!readonly}
+ onClear={handleClearAll}
size="large"
readOnly={readonly}
disabled={readonly}
diff --git a/Cunkebao/src/pages/mobile/mine/main/index.tsx b/Cunkebao/src/pages/mobile/mine/main/index.tsx
index b3d44912..b6fd294f 100644
--- a/Cunkebao/src/pages/mobile/mine/main/index.tsx
+++ b/Cunkebao/src/pages/mobile/mine/main/index.tsx
@@ -64,7 +64,7 @@ const Mine: React.FC = () => {
description: "管理用户流量池和分组",
icon: ,
count: stats.traffic,
- path: "/traffic-pool",
+ path: "/mine/traffic-pool",
bgColor: "#f9f0ff",
iconColor: "#722ed1",
},
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 b36dedb0..baeb21c1 100644
--- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx
+++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/FilterModal.tsx
@@ -1,27 +1,28 @@
-import React from "react";
+import React, { useState } from "react";
import { Popup } from "antd-mobile";
import { Select, Button } from "antd";
+import DeviceSelection from "@/components/DeviceSelection";
import type {
- DeviceOption,
PackageOption,
ValueLevel,
UserStatus,
+ ScenarioOption,
} from "./data";
+import { DeviceSelectionItem } from "@/components/DeviceSelection/data";
+
interface FilterModalProps {
visible: boolean;
onClose: () => void;
- deviceOptions: DeviceOption[];
+ onConfirm: (filters: {
+ deviceIds: string[];
+ packageId: string;
+ scenarioId: string;
+ valueLevel: ValueLevel;
+ userStatus: UserStatus;
+ }) => void;
packageOptions: PackageOption[];
- deviceId: string;
- setDeviceId: (v: string) => void;
- packageId: string;
- setPackageId: (v: string) => void;
- valueLevel: ValueLevel;
- setValueLevel: (v: ValueLevel) => void;
- userStatus: UserStatus;
- setUserStatus: (v: UserStatus) => void;
- onReset: () => void;
+ scenarioOptions: ScenarioOption[];
}
const valueLevelOptions = [
@@ -41,78 +42,109 @@ const statusOptions = [
const FilterModal: React.FC = ({
visible,
onClose,
- deviceOptions,
packageOptions,
- deviceId,
- setDeviceId,
- packageId,
- setPackageId,
- valueLevel,
- setValueLevel,
- userStatus,
- setUserStatus,
- onReset,
-}) => (
-
-
- 筛选选项
-
-
-
设备
-
-
-
流量池
-
-
-
用户价值
-
-
-
添加状态
-
-
-
-
-
-
-);
+ scenarioOptions,
+ onConfirm,
+}) => {
+ const [selectedDevices, setSelectedDevices] = useState(
+ [],
+ );
+ const [packageId, setPackageId] = useState("all");
+ const [scenarioId, setScenarioId] = useState("all");
+ const [valueLevel, setValueLevel] = useState("all");
+ const [userStatus, setUserStatus] = useState("all");
+
+ const handleApply = () => {
+ onConfirm({
+ deviceIds: selectedDevices.map(d => d.id.toString()),
+ packageId,
+ scenarioId,
+ valueLevel,
+ userStatus,
+ });
+ onClose();
+ };
+
+ const handleReset = () => {
+ setSelectedDevices([]);
+ setPackageId("all");
+ setScenarioId("all");
+ setValueLevel("all");
+ setUserStatus("all");
+ };
+
+ return (
+
+
+ 筛选选项
+
+
+
+
流量池
+
+
+
获客场景
+
+
+
用户价值
+
+
+
添加状态
+
+
+
+
+
+
+ );
+};
export default FilterModal;
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 0a6162a8..de5bfff1 100644
--- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts
+++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/api.ts
@@ -17,3 +17,14 @@ export async function fetchPackageOptions(): Promise {
{ id: "pkg-2", name: "测试流量池" },
];
}
+
+// 获取获客场景列表
+export async function fetchScenarioOptions(): Promise {
+ // TODO: 替换为真实接口
+ return [
+ { id: "scenario-1", name: "朋友圈推广" },
+ { id: "scenario-2", name: "群聊引流" },
+ { id: "scenario-3", name: "公众号推广" },
+ { id: "scenario-4", name: "线下活动" },
+ ];
+}
diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/data.ts b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/data.ts
index f437b129..65ad7f55 100644
--- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/data.ts
+++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/data.ts
@@ -43,3 +43,9 @@ export type ValueLevel = "all" | "high" | "medium" | "low";
// 状态类型
export type UserStatus = "all" | "added" | "pending" | "failed" | "duplicate";
+
+// 获客场景类型
+export interface ScenarioOption {
+ id: string;
+ name: string;
+}
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 7a84040a..b0d3f8ee 100644
--- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/dataAnyx.tsx
+++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/dataAnyx.tsx
@@ -1,11 +1,16 @@
import { useState, useEffect, useMemo } from "react";
-import { fetchTrafficPoolList, fetchPackageOptions } from "./api";
+import {
+ fetchTrafficPoolList,
+ fetchPackageOptions,
+ fetchScenarioOptions,
+} from "./api";
import type {
TrafficPoolUser,
DeviceOption,
PackageOption,
ValueLevel,
UserStatus,
+ ScenarioOption,
} from "./data";
import { Toast } from "antd-mobile";
@@ -19,10 +24,11 @@ export function useTrafficPoolListLogic() {
// 筛选相关
const [showFilter, setShowFilter] = useState(false);
- const [deviceOptions, setDeviceOptions] = useState([]);
const [packageOptions, setPackageOptions] = useState([]);
- const [deviceId, setDeviceId] = useState("all");
+ const [scenarioOptions, setScenarioOptions] = useState([]);
+ const [selectedDevices, setSelectedDevices] = useState([]);
const [packageId, setPackageId] = useState("all");
+ const [scenarioId, setScenarioId] = useState("all");
const [valueLevel, setValueLevel] = useState("all");
const [userStatus, setUserStatus] = useState("all");
@@ -47,15 +53,38 @@ export function useTrafficPoolListLogic() {
const getList = async () => {
setLoading(true);
try {
- const res = await fetchTrafficPoolList({
+ const params: any = {
page,
pageSize,
keyword: search,
- // deviceId,
- // packageId,
- // valueLevel,
- // userStatus,
- });
+ };
+
+ // 添加筛选参数
+ if (selectedDevices.length > 0) {
+ params.deviceId = selectedDevices.map(d => d.id).join(",");
+ }
+ if (packageId !== "all") {
+ params.packageId = packageId;
+ }
+ if (scenarioId !== "all") {
+ params.taskId = scenarioId;
+ }
+ if (valueLevel !== "all") {
+ params.userValue =
+ valueLevel === "high" ? 3 : valueLevel === "medium" ? 2 : 1;
+ }
+ if (userStatus !== "all") {
+ params.addStatus =
+ userStatus === "added"
+ ? 1
+ : userStatus === "pending"
+ ? 0
+ : userStatus === "failed"
+ ? -1
+ : -2;
+ }
+
+ const res = await fetchTrafficPoolList(params);
setList(res.list || []);
setTotal(res.total || 0);
} finally {
@@ -66,13 +95,22 @@ export function useTrafficPoolListLogic() {
// 获取筛选项
useEffect(() => {
fetchPackageOptions().then(setPackageOptions);
+ fetchScenarioOptions().then(setScenarioOptions);
}, []);
// 筛选条件变化时刷新列表
useEffect(() => {
getList();
// eslint-disable-next-line
- }, [page, search /*, deviceId, packageId, valueLevel, userStatus*/]);
+ }, [
+ page,
+ search,
+ selectedDevices,
+ packageId,
+ scenarioId,
+ valueLevel,
+ userStatus,
+ ]);
// 全选/反选
const handleSelectAll = (checked: boolean) => {
@@ -108,8 +146,9 @@ export function useTrafficPoolListLogic() {
// 筛选重置
const resetFilter = () => {
- setDeviceId("all");
+ setSelectedDevices([]);
setPackageId("all");
+ setScenarioId("all");
setValueLevel("all");
setUserStatus("all");
};
@@ -125,12 +164,14 @@ export function useTrafficPoolListLogic() {
setSearch,
showFilter,
setShowFilter,
- deviceOptions,
packageOptions,
- deviceId,
- setDeviceId,
+ scenarioOptions,
+ selectedDevices,
+ setSelectedDevices,
packageId,
setPackageId,
+ scenarioId,
+ setScenarioId,
valueLevel,
setValueLevel,
userStatus,
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 7e000524..4702737d 100644
--- a/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx
+++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/list/index.tsx
@@ -7,7 +7,7 @@ import {
} from "@ant-design/icons";
import { Input, Button, Checkbox } from "antd";
import styles from "./index.module.scss";
-import { List, Empty, Avatar, Modal, Selector, Toast, Card } from "antd-mobile";
+import { Empty, Avatar } from "antd-mobile";
import { useNavigate } from "react-router-dom";
import NavCommon from "@/components/NavCommon";
import { useTrafficPoolListLogic } from "./dataAnyx";
@@ -18,20 +18,6 @@ import BatchAddModal from "./BatchAddModal";
const defaultAvatar =
"https://cdn.jsdelivr.net/gh/maokaka/static/avatar-default.png";
-const valueLevelOptions = [
- { label: "全部", value: "all" },
- { label: "高价值", value: "high" },
- { label: "中价值", value: "medium" },
- { label: "低价值", value: "low" },
-];
-const statusOptions = [
- { label: "全部", value: "all" },
- { label: "已添加", value: "added" },
- { label: "待添加", value: "pending" },
- { label: "添加失败", value: "failed" },
- { label: "重复", value: "duplicate" },
-];
-
const TrafficPoolList: React.FC = () => {
const navigate = useNavigate();
const {
@@ -45,12 +31,14 @@ const TrafficPoolList: React.FC = () => {
setSearch,
showFilter,
setShowFilter,
- deviceOptions,
packageOptions,
- deviceId,
- setDeviceId,
+ scenarioOptions,
+ selectedDevices,
+ setSelectedDevices,
packageId,
setPackageId,
+ scenarioId,
+ setScenarioId,
valueLevel,
setValueLevel,
userStatus,
@@ -169,17 +157,26 @@ const TrafficPoolList: React.FC = () => {
setShowFilter(false)}
- deviceOptions={deviceOptions}
+ onConfirm={filters => {
+ // 更新筛选条件
+ setSelectedDevices(
+ filters.deviceIds.map(id => ({
+ id: parseInt(id),
+ memo: "",
+ imei: "",
+ wechatId: "",
+ status: "offline" as const,
+ })),
+ );
+ setPackageId(filters.packageId);
+ setScenarioId(filters.scenarioId);
+ setValueLevel(filters.valueLevel);
+ setUserStatus(filters.userStatus);
+ // 重新获取列表
+ getList();
+ }}
packageOptions={packageOptions}
- deviceId={deviceId}
- setDeviceId={setDeviceId}
- packageId={packageId}
- setPackageId={setPackageId}
- valueLevel={valueLevel}
- setValueLevel={setValueLevel}
- userStatus={userStatus}
- setUserStatus={setUserStatus}
- onReset={resetFilter}
+ scenarioOptions={scenarioOptions}
/>
{list.length === 0 && !loading ? (
@@ -192,7 +189,9 @@ const TrafficPoolList: React.FC = () => {
className={styles.card}
style={{ cursor: "pointer" }}
onClick={() =>
- navigate(`/traffic-pool/detail/${item.sourceId}/${item.id}`)
+ navigate(
+ `/mine/traffic-pool/detail/${item.sourceId}/${item.id}`,
+ )
}
>
diff --git a/Cunkebao/src/router/module/mine.tsx b/Cunkebao/src/router/module/mine.tsx
index e41f455d..e5c33623 100644
--- a/Cunkebao/src/router/module/mine.tsx
+++ b/Cunkebao/src/router/module/mine.tsx
@@ -36,12 +36,12 @@ const routes = [
auth: true,
},
{
- path: "/traffic-pool",
+ path: "/mine/traffic-pool",
element: ,
auth: true,
},
{
- path: "/traffic-pool/detail/:wxid/:userId",
+ path: "/mine/traffic-pool/detail/:wxid/:userId",
element: ,
auth: true,
},