feat(流量池选择): 新增流量池包选择功能并保留原接口兼容

- 添加流量池包相关接口和类型定义
- 修改选择弹窗组件以支持流量池包选择
- 保留原有流量池接口和类型以兼容现有代码
- 更新UI展示以适应流量池包数据结构
This commit is contained in:
超级老白兔
2025-08-20 17:31:22 +08:00
parent 3d944770f1
commit 87aea20056
3 changed files with 74 additions and 61 deletions

View File

@@ -1,6 +1,25 @@
import request from "@/api/request";
// 获取流量池列表
// 请求参数接口
export interface Request {
keyword: string;
/**
* 条数
*/
limit: string;
/**
* 分页
*/
page: string;
[property: string]: any;
}
// 获取流量池包列表
export function getPoolPackages(params: Request) {
return request("/v1/traffic/pool/getPackage", params, "GET");
}
// 保留原接口以兼容现有代码
export function getPoolList(params: {
page?: string;
pageSize?: string;

View File

@@ -1,4 +1,13 @@
// 流量池接口类型
// 流量池接口类型
export interface PoolPackageItem {
id: number;
name: string;
description: string;
createTime: string;
num: number;
}
// 原流量池接口类型(保留以兼容现有代码)
export interface PoolItem {
id: number;
identifier: string;
@@ -21,12 +30,14 @@ export interface PoolItem {
export interface GroupSelectionItem {
id: string;
avatar: string;
avatar?: string;
name: string;
wechatId?: string;
mobile?: string;
nickname?: string;
createTime?: string;
description?: string;
num?: number;
[key: string]: any;
}
@@ -34,7 +45,7 @@ export interface GroupSelectionItem {
export interface GroupSelectionProps {
selectedOptions: GroupSelectionItem[];
onSelect: (groups: GroupSelectionItem[]) => void;
onSelectDetail?: (groups: PoolItem[]) => void;
onSelectDetail?: (groups: PoolPackageItem[]) => void;
placeholder?: string;
className?: string;
visible?: boolean;

View File

@@ -1,12 +1,12 @@
import React, { useState, useEffect } from "react";
import { Popup, Checkbox } from "antd-mobile";
import { getPoolList } from "./api";
import { getPoolPackages, Request } from "./api";
import style from "./index.module.scss";
import Layout from "@/components/Layout/Layout";
import PopupHeader from "@/components/PopuLayout/header";
import PopupFooter from "@/components/PopuLayout/footer";
import { GroupSelectionItem, PoolItem } from "./data";
import { GroupSelectionItem, PoolPackageItem } from "./data";
// 弹窗属性接口
interface SelectionPopupProps {
@@ -14,7 +14,7 @@ interface SelectionPopupProps {
onVisibleChange: (visible: boolean) => void;
selectedOptions: GroupSelectionItem[];
onSelect: (items: GroupSelectionItem[]) => void;
onSelectDetail?: (items: PoolItem[]) => void;
onSelectDetail?: (items: PoolPackageItem[]) => void;
readonly?: boolean;
onConfirm?: (
selectedIds: string[],
@@ -31,52 +31,47 @@ export default function SelectionPopup({
readonly = false,
onConfirm,
}: SelectionPopupProps) {
const [poolItems, setPoolItems] = useState<PoolItem[]>([]);
const [poolPackages, setPoolPackages] = useState<PoolPackageItem[]>([]);
const [searchQuery, setSearchQuery] = useState("");
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [totalItems, setTotalItems] = useState(0);
const [loading, setLoading] = useState(false);
// 获取流量池列表API
const fetchPoolItems = async (page: number, keyword: string = "") => {
// 获取流量池列表API
const fetchPoolPackages = async (page: number, keyword: string = "") => {
setLoading(true);
try {
const params: any = {
const params: Request = {
page: String(page),
pageSize: "20",
limit: "20",
keyword: keyword.trim(),
};
if (keyword.trim()) {
params.keyword = keyword.trim();
}
const response = await getPoolList(params);
const response = await getPoolPackages(params);
if (response && response.list) {
setPoolItems(response.list);
setPoolPackages(response.list);
setTotalItems(response.total || 0);
setTotalPages(Math.ceil((response.total || 0) / 20));
}
} catch (error) {
console.error("获取流量池列表失败:", error);
console.error("获取流量池列表失败:", error);
} finally {
setLoading(false);
}
};
// 处理流量池选择
const handleItemToggle = (item: PoolItem) => {
// 处理流量池选择
const handlePackageToggle = (item: PoolPackageItem) => {
if (readonly) return;
// 将PoolItem转换为GroupSelectionItem格式
// 将PoolPackageItem转换为GroupSelectionItem格式
const selectionItem: GroupSelectionItem = {
id: String(item.id),
name: item.nickname || item.wechatId,
avatar: item.avatar,
wechatId: item.wechatId,
mobile: item.mobile,
nickname: item.nickname,
name: item.name,
description: item.description,
createTime: item.createTime,
num: item.num,
// 保留原始数据
originalData: item,
};
@@ -87,10 +82,10 @@ export default function SelectionPopup({
onSelect(newSelectedItems);
// 如果有 onSelectDetail 回调,传递完整的流量池对象
// 如果有 onSelectDetail 回调,传递完整的流量池对象
if (onSelectDetail) {
const selectedItemObjs = poolItems.filter(poolItem =>
newSelectedItems.some(g => g.id === String(poolItem.id)),
const selectedItemObjs = poolPackages.filter(packageItem =>
newSelectedItems.some(g => g.id === String(packageItem.id)),
);
onSelectDetail(selectedItemObjs);
}
@@ -112,7 +107,7 @@ export default function SelectionPopup({
if (visible) {
setCurrentPage(1);
setSearchQuery("");
fetchPoolItems(1, "");
fetchPoolPackages(1, "");
}
}, [visible]);
@@ -122,7 +117,7 @@ export default function SelectionPopup({
const timer = setTimeout(() => {
setCurrentPage(1);
fetchPoolItems(1, searchQuery);
fetchPoolPackages(1, searchQuery);
}, 500);
return () => clearTimeout(timer);
@@ -131,7 +126,7 @@ export default function SelectionPopup({
// 页码变化时请求数据只在弹窗打开且页码不是1时执行
useEffect(() => {
if (!visible || currentPage === 1) return;
fetchPoolItems(currentPage, searchQuery);
fetchPoolPackages(currentPage, searchQuery);
}, [currentPage, visible, searchQuery]);
return (
@@ -144,12 +139,12 @@ export default function SelectionPopup({
<Layout
header={
<PopupHeader
title="选择流量池"
title="选择流量池"
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
searchPlaceholder="搜索流量池"
searchPlaceholder="搜索流量池"
loading={loading}
onRefresh={() => fetchPoolItems(currentPage, searchQuery)}
onRefresh={() => fetchPoolPackages(currentPage, searchQuery)}
/>
}
footer={
@@ -170,42 +165,30 @@ export default function SelectionPopup({
<div className={style.loadingBox}>
<div className={style.loadingText}>...</div>
</div>
) : poolItems.length > 0 ? (
) : poolPackages.length > 0 ? (
<div className={style.groupListInner}>
{poolItems.map(item => (
{poolPackages.map(item => (
<div key={item.id} className={style.groupItem}>
<Checkbox
checked={selectedOptions.some(
g => g.id === String(item.id),
)}
onChange={() => !readonly && handleItemToggle(item)}
onChange={() => !readonly && handlePackageToggle(item)}
disabled={readonly}
style={{ marginRight: 12 }}
/>
<div className={style.groupInfo}>
<div className={style.groupAvatar}>
{item.avatar ? (
<img
src={item.avatar}
alt={item.nickname || item.wechatId}
className={style.avatarImg}
/>
) : (
(item.nickname || item.wechatId || "").charAt(0)
)}
</div>
<div className={style.groupDetail}>
<div className={style.groupName}>
{item.nickname || item.wechatId}
</div>
<div className={style.groupName}>{item.name}</div>
<div className={style.groupId}>
ID: {item.wechatId}
: {item.description || "无描述"}
</div>
<div className={style.groupOwner}>
: {item.createTime}
</div>
<div className={style.groupOwner}>
: {item.num}
</div>
{item.mobile && (
<div className={style.groupOwner}>
: {item.mobile}
</div>
)}
</div>
</div>
</div>
@@ -215,8 +198,8 @@ export default function SelectionPopup({
<div className={style.emptyBox}>
<div className={style.emptyText}>
{searchQuery
? `没有找到包含"${searchQuery}"的流量池`
: "没有找到流量池"}
? `没有找到包含"${searchQuery}"的流量池`
: "没有找到流量池"}
</div>
</div>
)}