FEAT => 本次更新项目为:
This commit is contained in:
@@ -31,4 +31,5 @@ export interface AccountSelectionProps {
|
||||
showSelectedList?: boolean;
|
||||
readonly?: boolean;
|
||||
onConfirm?: (selectedOptions: AccountItem[]) => void;
|
||||
accountGroups?: any[]; // 传递账号组数据
|
||||
}
|
||||
|
||||
@@ -25,4 +25,5 @@ export interface DeviceSelectionProps {
|
||||
showInput?: boolean; // 新增
|
||||
showSelectedList?: boolean; // 新增
|
||||
readonly?: boolean; // 新增
|
||||
deviceGroups?: any[]; // 传递设备组数据
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@ export interface TrafficDistributionConfig {
|
||||
timeType: number;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
account: (string | number)[];
|
||||
devices: string[];
|
||||
accountGroups: any[];
|
||||
accountGroupsOptions: any[];
|
||||
deviceGroups: any[];
|
||||
deviceGroupsOptions: any[];
|
||||
pools: any[];
|
||||
exp: number;
|
||||
createTime: string;
|
||||
@@ -52,8 +54,10 @@ export interface TrafficDistributionFormData {
|
||||
timeType: number;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
devices: string[];
|
||||
account: (string | number)[];
|
||||
deviceGroups: any[];
|
||||
deviceGroupsOptions: any[];
|
||||
accountGroups: any[];
|
||||
accountGroupsOptions: any[];
|
||||
pools: any[];
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,51 @@
|
||||
.accountSelectItem {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.deviceSelectItem {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.searchWrapper {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.tabWrapper {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.tabList {
|
||||
display: flex;
|
||||
background: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.tabItem {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 8px 16px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.tabItem:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.tabActive {
|
||||
background: #fff;
|
||||
color: #1890ff;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.tabContent {
|
||||
min-height: 200px;
|
||||
}
|
||||
.accountListWrap {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
message,
|
||||
Checkbox,
|
||||
} from "antd";
|
||||
import { SearchOutlined } from "@ant-design/icons";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import style from "./index.module.scss";
|
||||
import StepIndicator from "@/components/StepIndicator";
|
||||
@@ -16,6 +17,8 @@ import Layout from "@/components/Layout/Layout";
|
||||
import NavCommon from "@/components/NavCommon";
|
||||
import AccountSelection from "@/components/AccountSelection";
|
||||
import { AccountItem } from "@/components/AccountSelection/data";
|
||||
import DeviceSelection from "@/components/DeviceSelection";
|
||||
import { DeviceSelectionItem } from "@/components/DeviceSelection/data";
|
||||
import {
|
||||
getTrafficDistributionDetail,
|
||||
updateTrafficDistribution,
|
||||
@@ -62,6 +65,14 @@ const TrafficDistributionForm: React.FC = () => {
|
||||
|
||||
const [current, setCurrent] = useState(0);
|
||||
const [selectedAccounts, setSelectedAccounts] = useState<AccountItem[]>([]);
|
||||
const [selectedDevices, setSelectedDevices] = useState<DeviceSelectionItem[]>(
|
||||
[],
|
||||
);
|
||||
// 设备组和账号组数据
|
||||
const [deviceGroups, setDeviceGroups] = useState<any[]>([]);
|
||||
const [deviceGroupsOptions, setDeviceGroupsOptions] = useState<any[]>([]);
|
||||
const [accountGroups, setAccountGroups] = useState<any[]>([]);
|
||||
const [accountGroupsOptions, setAccountGroupsOptions] = useState<any[]>([]);
|
||||
const [distributeType, setDistributeType] = useState(1);
|
||||
const [maxPerDay, setMaxPerDay] = useState(50);
|
||||
const [timeType, setTimeType] = useState(1);
|
||||
@@ -69,11 +80,11 @@ const TrafficDistributionForm: React.FC = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [detailLoading, setDetailLoading] = useState(false);
|
||||
|
||||
const [targetUserCount, setTargetUserCount] = useState(100);
|
||||
const [targetTypes, setTargetTypes] = useState<string[]>([]);
|
||||
const [targetScenarios, setTargetScenarios] = useState<string[]>([]);
|
||||
const [selectedPools, setSelectedPools] = useState<string[]>([]);
|
||||
const [poolSearch, setPoolSearch] = useState("");
|
||||
const [targetSelectionTab, setTargetSelectionTab] = useState<
|
||||
"device" | "account"
|
||||
>("device");
|
||||
|
||||
// 编辑时的详情数据
|
||||
const [detailData, setDetailData] =
|
||||
@@ -116,7 +127,15 @@ const TrafficDistributionForm: React.FC = () => {
|
||||
setMaxPerDay(config.maxPerDay);
|
||||
setTimeType(config.timeType);
|
||||
|
||||
setSelectedAccounts(config.accountGroupsOptions);
|
||||
// 设置账号组数据
|
||||
setAccountGroups(config.accountGroups || []);
|
||||
setAccountGroupsOptions(config.accountGroupsOptions || []);
|
||||
setSelectedAccounts(config.accountGroupsOptions || []);
|
||||
|
||||
// 设置设备组数据
|
||||
setDeviceGroups(config.deviceGroups || []);
|
||||
setDeviceGroupsOptions(config.deviceGroupsOptions || []);
|
||||
setSelectedDevices(config.deviceGroupsOptions || []);
|
||||
|
||||
// 设置时间范围 - 使用dayjs格式
|
||||
if (config.timeType === 2 && config.startTime && config.endTime) {
|
||||
@@ -161,8 +180,10 @@ const TrafficDistributionForm: React.FC = () => {
|
||||
timeType === 2 && timeRange?.[0] ? timeRange[0].format("HH:mm") : "",
|
||||
endTime:
|
||||
timeType === 2 && timeRange?.[1] ? timeRange[1].format("HH:mm") : "",
|
||||
devices: detailData?.config.devices || [],
|
||||
account: selectedAccounts.map(acc => acc.id),
|
||||
deviceGroups: deviceGroups,
|
||||
deviceGroupsOptions: deviceGroupsOptions,
|
||||
accountGroups: accountGroups,
|
||||
accountGroupsOptions: accountGroupsOptions,
|
||||
pools: selectedPools,
|
||||
enabled: true,
|
||||
};
|
||||
@@ -261,19 +282,6 @@ const TrafficDistributionForm: React.FC = () => {
|
||||
>
|
||||
<Input placeholder="流量分发 20250724 1700" maxLength={30} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="选择账号"
|
||||
required
|
||||
className={style.accountSelectItem}
|
||||
>
|
||||
<AccountSelection
|
||||
selectedOptions={selectedAccounts}
|
||||
onSelect={setSelectedAccounts}
|
||||
placeholder="请选择账号"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={300}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="分配方式" name="distributeType" required>
|
||||
<Radio.Group
|
||||
value={distributeType}
|
||||
@@ -355,37 +363,61 @@ const TrafficDistributionForm: React.FC = () => {
|
||||
{current === 1 && (
|
||||
<div>
|
||||
<div className={style.sectionTitle}>目标设置</div>
|
||||
<div className={style.formBlock}>
|
||||
<div className={style.formLabel}>目标用户数</div>
|
||||
<Slider
|
||||
min={1}
|
||||
max={1000}
|
||||
value={targetUserCount}
|
||||
onChange={setTargetUserCount}
|
||||
className={style.slider}
|
||||
/>
|
||||
<div className={style.sliderValue}>{targetUserCount} 人</div>
|
||||
|
||||
{/* Tab 切换 */}
|
||||
<div className={style.tabWrapper}>
|
||||
<div className={style.tabList}>
|
||||
<div
|
||||
className={`${style.tabItem} ${
|
||||
targetSelectionTab === "device" ? style.tabActive : ""
|
||||
}`}
|
||||
onClick={() => setTargetSelectionTab("device")}
|
||||
>
|
||||
设备选择
|
||||
</div>
|
||||
<div
|
||||
className={`${style.tabItem} ${
|
||||
targetSelectionTab === "account" ? style.tabActive : ""
|
||||
}`}
|
||||
onClick={() => setTargetSelectionTab("account")}
|
||||
>
|
||||
客服选择
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.formBlock}>
|
||||
<div className={style.formLabel}>目标客户类型</div>
|
||||
<Checkbox.Group
|
||||
options={["高价值客户", "新用户", "潜在客户", "流失预警"]}
|
||||
value={targetTypes}
|
||||
onChange={setTargetTypes}
|
||||
className={style.checkboxGroup}
|
||||
/>
|
||||
</div>
|
||||
<div className={style.formBlock}>
|
||||
<div className={style.formLabel}>获客场景</div>
|
||||
<Checkbox.Group
|
||||
options={scenarioList.map(s => ({
|
||||
label: s.label,
|
||||
value: s.value,
|
||||
}))}
|
||||
value={targetScenarios}
|
||||
onChange={setTargetScenarios}
|
||||
className={style.checkboxGroup}
|
||||
/>
|
||||
|
||||
{/* Tab 内容 */}
|
||||
<div className={style.tabContent}>
|
||||
{targetSelectionTab === "device" && (
|
||||
<div className={style.formBlock}>
|
||||
<DeviceSelection
|
||||
selectedOptions={selectedDevices}
|
||||
onSelect={devices => {
|
||||
setSelectedDevices(devices);
|
||||
setDeviceGroupsOptions(devices);
|
||||
}}
|
||||
placeholder="请选择设备"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={300}
|
||||
deviceGroups={deviceGroups}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{targetSelectionTab === "account" && (
|
||||
<div className={style.formBlock}>
|
||||
<AccountSelection
|
||||
selectedOptions={selectedAccounts}
|
||||
onSelect={accounts => {
|
||||
setSelectedAccounts(accounts);
|
||||
setAccountGroupsOptions(accounts);
|
||||
}}
|
||||
placeholder="请选择客服"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={300}
|
||||
accountGroups={accountGroups}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -343,7 +343,7 @@ const TrafficDistributionList: React.FC = () => {
|
||||
}
|
||||
loading={loading}
|
||||
footer={
|
||||
<div className={style.pagination}>
|
||||
<div className="pagination-container">
|
||||
<Pagination
|
||||
current={page}
|
||||
pageSize={PAGE_SIZE}
|
||||
|
||||
Reference in New Issue
Block a user