From 4df670d1c946565d8b67cd788f4e6363593d500d 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, 20 Oct 2025 15:04:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=B5=81=E9=87=8F=E6=B1=A0?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E7=BB=84=E4=BB=B6=EF=BC=9A=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=A2=84=E8=AE=BE=E6=96=B9=E6=A1=88=E9=80=89=E6=8B=A9=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E4=BC=98=E5=8C=96=E7=94=A8=E6=88=B7=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=94=9F=E6=88=90=E9=80=BB=E8=BE=91=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=BC=BA=E6=8F=90=E4=BA=A4=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E5=8D=87=E7=94=A8=E6=88=B7=E4=BD=93=E9=AA=8C?= =?UTF-8?q?=E5=92=8C=E4=BB=A3=E7=A0=81=E5=8F=AF=E7=BB=B4=E6=8A=A4=E6=80=A7?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mobile/mine/traffic-pool/form/api.ts | 57 ++++- .../components/AudienceFilter.module.scss | 12 +- .../form/components/AudienceFilter.tsx | 239 +++++++++--------- .../mobile/mine/traffic-pool/form/index.tsx | 67 ++++- .../pages/mobile/scenarios/plan/new/index.tsx | 31 ++- 5 files changed, 266 insertions(+), 140 deletions(-) diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/form/api.ts b/Cunkebao/src/pages/mobile/mine/traffic-pool/form/api.ts index 398ab200..781ebe28 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/form/api.ts +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/form/api.ts @@ -61,7 +61,62 @@ export interface PresetScheme { } export async function getPresetSchemes(): Promise { - return request("/v1/traffic/pool/schemes", {}, "GET"); + // 模拟数据 + return new Promise(resolve => { + setTimeout(() => { + resolve([ + { + id: "scheme_1", + name: "高价值客户方案", + description: "针对高消费、高活跃度的客户群体", + conditions: [ + { id: "rfm_high", type: "rfm", label: "RFM评分", value: "high" }, + { + id: "consumption_high", + type: "consumption", + label: "消费能力", + value: "high", + }, + ], + userCount: 1250, + color: "#ff4d4f", + }, + { + id: "scheme_2", + name: "新用户激活方案", + description: "针对新注册用户的激活策略", + conditions: [ + { id: "new_user", type: "tag", label: "新用户", value: true }, + { + id: "low_activity", + type: "activity", + label: "活跃度", + value: "low", + }, + ], + userCount: 890, + color: "#52c41a", + }, + { + id: "scheme_3", + name: "流失挽回方案", + description: "针对流失风险用户的挽回策略", + conditions: [ + { id: "churn_risk", type: "tag", label: "流失风险", value: true }, + { + id: "last_active", + type: "time", + label: "最后活跃", + value: "30天前", + }, + ], + userCount: 567, + color: "#faad14", + }, + ]); + }, 500); + }); + // return request("/v1/traffic/pool/schemes", {}, "GET"); } // 获取行业选项(固定筛选项) diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.module.scss b/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.module.scss index 75c1e09e..c1c7e292 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.module.scss +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.module.scss @@ -20,13 +20,21 @@ color: #333; } -.schemeBtn { +.schemeRow { + display: flex; + gap: 12px; + align-items: center; +} + +.addSchemeBtn { display: flex; align-items: center; gap: 4px; font-size: 12px; padding: 4px 8px; - height: 28px; + height: 32px; + white-space: nowrap; + flex-shrink: 0; } .section { diff --git a/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.tsx b/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.tsx index 6cc023fe..c126041c 100644 --- a/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.tsx +++ b/Cunkebao/src/pages/mobile/mine/traffic-pool/form/components/AudienceFilter.tsx @@ -1,12 +1,16 @@ import React, { useEffect, useState } from "react"; import { Card, Button } from "antd-mobile"; import { Select } from "antd"; -import { EditSOutline } from "antd-mobile-icons"; +import { PlusOutlined } from "@ant-design/icons"; import CustomConditionModal from "./CustomConditionModal"; -import SchemeRecommendation from "./SchemeRecommendation"; import ConditionList from "./ConditionList"; import styles from "./AudienceFilter.module.scss"; -import { getIndustryOptions, IndustryOption } from "../api"; +import { + getIndustryOptions, + getPresetSchemes, + IndustryOption, + PresetScheme, +} from "../api"; interface FilterCondition { id: string; @@ -19,26 +23,31 @@ interface FilterCondition { interface AudienceFilterProps { conditions: FilterCondition[]; onChange: (conditions: FilterCondition[]) => void; - onGenerate: (users: any[]) => void; } const AudienceFilter: React.FC = ({ conditions, onChange, - onGenerate, }) => { const [showCustomModal, setShowCustomModal] = useState(false); - const [showSchemeModal, setShowSchemeModal] = useState(false); const [industryOptions, setIndustryOptions] = useState([]); + const [presetSchemes, setPresetSchemes] = useState([]); const [selectedIndustry, setSelectedIndustry] = useState< string | number | undefined >(undefined); + const [selectedScheme, setSelectedScheme] = useState( + undefined, + ); - // 加载行业选项(固定筛选项) + // 加载行业选项和方案列表 useEffect(() => { getIndustryOptions() .then(res => setIndustryOptions(res || [])) .catch(() => setIndustryOptions([])); + + getPresetSchemes() + .then(res => setPresetSchemes(res || [])) + .catch(() => setPresetSchemes([])); }, []); const handleAddCondition = (condition: FilterCondition) => { @@ -58,15 +67,23 @@ const AudienceFilter: React.FC = ({ onChange(newConditions); }; - const handleApplyScheme = (schemeConditions: FilterCondition[]) => { - onChange(schemeConditions); - setShowSchemeModal(false); + const handleSchemeChange = (schemeId: string) => { + setSelectedScheme(schemeId); + if (schemeId) { + // 找到选中的方案并应用其条件 + const scheme = presetSchemes.find(s => s.id === schemeId); + if (scheme) { + onChange(scheme.conditions); + } + } else { + // 清空方案选择时,清空条件 + onChange([]); + } }; - const handleGenerate = () => { - // 模拟生成用户数据 - const mockUsers = generateMockUsers(conditions); - onGenerate(mockUsers); + const handleAddScheme = () => { + // 这里可以打开添加方案的弹窗或跳转到方案管理页面 + console.log("添加新方案"); }; return ( @@ -74,99 +91,96 @@ const AudienceFilter: React.FC = ({
人群筛选
-
- {/* 行业筛选(固定项,接口获取选项) */} + {/* 方案推荐选择 */}
-
行业
- ({ + label: `${scheme.name} (${scheme.userCount}人)`, + value: scheme.id, + }))} + allowClear + /> +
- {/* 自定义条件列表 */} - + {/* 条件筛选区域 - 当未选择方案时显示 */} + {!selectedScheme && ( + <> + {/* 行业筛选(固定项,接口获取选项) */} +
+
行业
+