Merge branch 'yongpxu-dev' into yongpxu-dev2
# Conflicts: # nkebao/src/pages/mobile/test/select.tsx resolved by yongpxu-dev version
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// 设备选择项接口
|
||||
export interface DeviceSelectionItem {
|
||||
id: string;
|
||||
id: number;
|
||||
name: string;
|
||||
imei: string;
|
||||
wechatId: string;
|
||||
@@ -12,8 +12,8 @@ export interface DeviceSelectionItem {
|
||||
|
||||
// 组件属性接口
|
||||
export interface DeviceSelectionProps {
|
||||
selectedOptions: string[];
|
||||
onSelect: (devices: string[]) => void;
|
||||
selectedOptions: DeviceSelectionItem[];
|
||||
onSelect: (devices: DeviceSelectionItem[]) => void;
|
||||
placeholder?: string;
|
||||
className?: string;
|
||||
mode?: "input" | "dialog"; // 新增,默认input
|
||||
|
||||
@@ -41,9 +41,9 @@ const DeviceSelection: React.FC<DeviceSelectionProps> = ({
|
||||
};
|
||||
|
||||
// 删除已选设备
|
||||
const handleRemoveDevice = (id: string) => {
|
||||
const handleRemoveDevice = (id: number) => {
|
||||
if (readonly) return;
|
||||
onSelect(selectedOptions.filter(d => d !== id));
|
||||
onSelect(selectedOptions.filter(v => v.id !== id));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -79,9 +79,9 @@ const DeviceSelection: React.FC<DeviceSelectionProps> = ({
|
||||
background: "#fff",
|
||||
}}
|
||||
>
|
||||
{selectedOptions.map(deviceId => (
|
||||
{selectedOptions.map(device => (
|
||||
<div
|
||||
key={deviceId}
|
||||
key={device.id}
|
||||
className={style.selectedListRow}
|
||||
style={{
|
||||
display: "flex",
|
||||
@@ -100,7 +100,7 @@ const DeviceSelection: React.FC<DeviceSelectionProps> = ({
|
||||
textOverflow: "ellipsis",
|
||||
}}
|
||||
>
|
||||
{deviceId}
|
||||
【 {device.name}】 - {device.wechatId}
|
||||
</div>
|
||||
{!readonly && (
|
||||
<Button
|
||||
@@ -118,7 +118,7 @@ const DeviceSelection: React.FC<DeviceSelectionProps> = ({
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
onClick={() => handleRemoveDevice(deviceId)}
|
||||
onClick={() => handleRemoveDevice(device.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -5,23 +5,13 @@ import style from "./index.module.scss";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import PopupHeader from "@/components/PopuLayout/header";
|
||||
import PopupFooter from "@/components/PopuLayout/footer";
|
||||
|
||||
interface DeviceSelectionItem {
|
||||
id: string;
|
||||
name: string;
|
||||
imei: string;
|
||||
wechatId: string;
|
||||
status: "online" | "offline";
|
||||
wxid?: string;
|
||||
nickname?: string;
|
||||
usedInPlans?: number;
|
||||
}
|
||||
import { DeviceSelectionItem } from "./data";
|
||||
|
||||
interface SelectionPopupProps {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
selectedOptions: string[];
|
||||
onSelect: (devices: string[]) => void;
|
||||
selectedOptions: DeviceSelectionItem[];
|
||||
onSelect: (devices: DeviceSelectionItem[]) => void;
|
||||
}
|
||||
|
||||
const PAGE_SIZE = 20;
|
||||
@@ -112,11 +102,12 @@ const SelectionPopup: React.FC<SelectionPopupProps> = ({
|
||||
const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
|
||||
|
||||
// 处理设备选择
|
||||
const handleDeviceToggle = (deviceId: string) => {
|
||||
if (selectedOptions.includes(deviceId)) {
|
||||
onSelect(selectedOptions.filter(id => id !== deviceId));
|
||||
const handleDeviceToggle = (device: DeviceSelectionItem) => {
|
||||
if (selectedOptions.some(v => v.id === device.id)) {
|
||||
onSelect(selectedOptions.filter(v => v.id !== device.id));
|
||||
} else {
|
||||
onSelect([...selectedOptions, deviceId]);
|
||||
const newSelectedOptions = [...selectedOptions, device];
|
||||
onSelect(newSelectedOptions);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -172,8 +163,8 @@ const SelectionPopup: React.FC<SelectionPopupProps> = ({
|
||||
{filteredDevices.map(device => (
|
||||
<label key={device.id} className={style.deviceItem}>
|
||||
<Checkbox
|
||||
checked={selectedOptions.includes(device.id)}
|
||||
onChange={() => handleDeviceToggle(device.id)}
|
||||
checked={selectedOptions.some(v => v.id === device.id)}
|
||||
onChange={() => handleDeviceToggle(device)}
|
||||
className={style.deviceCheckbox}
|
||||
/>
|
||||
<div className={style.deviceInfo}>
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
.inputWrapper {
|
||||
position: relative;
|
||||
}
|
||||
.selectedListRow {
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
font-size: 14px;
|
||||
}
|
||||
.selectedListRowContent {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
.selectedListRowContentText {
|
||||
flex: 1;
|
||||
}
|
||||
.inputIcon {
|
||||
position: absolute;
|
||||
left: 12px;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState } from "react";
|
||||
import { SearchOutlined, DeleteOutlined } from "@ant-design/icons";
|
||||
import { Popup } from "antd-mobile";
|
||||
import { Button, Input } from "antd";
|
||||
import { getFriendList } from "./api";
|
||||
import { Avatar } from "antd-mobile";
|
||||
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 { FriendSelectionProps, FriendSelectionItem } from "./data";
|
||||
import { FriendSelectionProps } from "./data";
|
||||
import SelectionPopup from "./selectionPopup";
|
||||
|
||||
export default function FriendSelection({
|
||||
selectedOptions,
|
||||
@@ -25,12 +22,7 @@ export default function FriendSelection({
|
||||
onConfirm,
|
||||
}: FriendSelectionProps) {
|
||||
const [popupVisible, setPopupVisible] = useState(false);
|
||||
const [friends, setFriends] = useState<FriendSelectionItem[]>([]);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [totalPages, setTotalPages] = useState(1);
|
||||
const [totalFriends, setTotalFriends] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// 内部弹窗交给 selectionPopup 处理
|
||||
|
||||
// 受控弹窗逻辑
|
||||
const realVisible = visible !== undefined ? visible : popupVisible;
|
||||
@@ -39,75 +31,10 @@ export default function FriendSelection({
|
||||
if (visible === undefined) setPopupVisible(v);
|
||||
};
|
||||
|
||||
// 打开弹窗并请求第一页好友
|
||||
// 打开弹窗
|
||||
const openPopup = () => {
|
||||
if (readonly) return;
|
||||
setCurrentPage(1);
|
||||
setSearchQuery("");
|
||||
setRealVisible(true);
|
||||
fetchFriends(1, "");
|
||||
};
|
||||
|
||||
// 当页码变化时,拉取对应页数据(弹窗已打开时)
|
||||
useEffect(() => {
|
||||
if (realVisible && currentPage !== 1) {
|
||||
fetchFriends(currentPage, searchQuery);
|
||||
}
|
||||
}, [currentPage, realVisible, searchQuery]);
|
||||
|
||||
// 搜索防抖
|
||||
useEffect(() => {
|
||||
if (!realVisible) return;
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setCurrentPage(1);
|
||||
fetchFriends(1, searchQuery);
|
||||
}, 500);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [searchQuery, realVisible]);
|
||||
|
||||
// 获取好友列表API - 添加 keyword 参数
|
||||
const fetchFriends = async (page: number, keyword: string = "") => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params: any = {
|
||||
page,
|
||||
limit: 20,
|
||||
};
|
||||
|
||||
if (keyword.trim()) {
|
||||
params.keyword = keyword.trim();
|
||||
}
|
||||
|
||||
if (enableDeviceFilter && deviceIds.length > 0) {
|
||||
params.deviceIds = deviceIds.join(",");
|
||||
}
|
||||
|
||||
const response = await getFriendList(params);
|
||||
if (response && response.list) {
|
||||
setFriends(response.list);
|
||||
setTotalFriends(response.total || 0);
|
||||
setTotalPages(Math.ceil((response.total || 0) / 20));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取好友列表失败:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理好友选择
|
||||
const handleFriendToggle = (friend: FriendSelectionItem) => {
|
||||
if (readonly) return;
|
||||
|
||||
const newSelectedFriends = selectedOptions
|
||||
.map(v => v.id)
|
||||
.includes(friend.id)
|
||||
? selectedOptions.filter(v => v.id !== friend.id)
|
||||
: selectedOptions.concat(friend);
|
||||
|
||||
onSelect(newSelectedFriends);
|
||||
};
|
||||
|
||||
// 获取显示文本
|
||||
@@ -122,14 +49,13 @@ export default function FriendSelection({
|
||||
onSelect(selectedOptions.filter(v => v.id !== id));
|
||||
};
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
if (onConfirm) {
|
||||
onConfirm(
|
||||
selectedOptions.map(v => v.id),
|
||||
selectedOptions,
|
||||
);
|
||||
}
|
||||
// 弹窗确认回调
|
||||
const handleConfirm = (
|
||||
selectedIds: number[],
|
||||
selectedItems: typeof selectedOptions,
|
||||
) => {
|
||||
onSelect(selectedItems);
|
||||
if (onConfirm) onConfirm(selectedIds, selectedItems);
|
||||
setRealVisible(false);
|
||||
};
|
||||
|
||||
@@ -167,151 +93,48 @@ export default function FriendSelection({
|
||||
}}
|
||||
>
|
||||
{selectedOptions.map(friend => (
|
||||
<div
|
||||
key={friend.id}
|
||||
className={style.selectedListRow}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "4px 8px",
|
||||
borderBottom: "1px solid #f0f0f0",
|
||||
fontSize: 14,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
minWidth: 0,
|
||||
whiteSpace: "nowrap",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
}}
|
||||
>
|
||||
{friend.nickname || friend.wechatId || friend.id}
|
||||
<div key={friend.id} className={style.selectedListRow}>
|
||||
<div className={style.selectedListRowContent}>
|
||||
<Avatar src={friend.avatar} />
|
||||
<div className={style.selectedListRowContentText}>
|
||||
<div>{friend.nickname}</div>
|
||||
<div>{friend.wechatId}</div>
|
||||
</div>
|
||||
{!readonly && (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<DeleteOutlined />}
|
||||
size="small"
|
||||
style={{
|
||||
marginLeft: 4,
|
||||
color: "#ff4d4f",
|
||||
border: "none",
|
||||
background: "none",
|
||||
minWidth: 24,
|
||||
height: 24,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
onClick={() => handleRemoveFriend(friend.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{!readonly && (
|
||||
<Button
|
||||
type="text"
|
||||
icon={<DeleteOutlined />}
|
||||
size="small"
|
||||
style={{
|
||||
marginLeft: 4,
|
||||
color: "#ff4d4f",
|
||||
border: "none",
|
||||
background: "none",
|
||||
minWidth: 24,
|
||||
height: 24,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
onClick={() => handleRemoveFriend(friend.id)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{/* 弹窗 */}
|
||||
<Popup
|
||||
<SelectionPopup
|
||||
visible={realVisible && !readonly}
|
||||
onMaskClick={() => setRealVisible(false)}
|
||||
position="bottom"
|
||||
bodyStyle={{ height: "100vh" }}
|
||||
>
|
||||
<Layout
|
||||
header={
|
||||
<PopupHeader
|
||||
title="选择微信好友"
|
||||
searchQuery={searchQuery}
|
||||
setSearchQuery={setSearchQuery}
|
||||
searchPlaceholder="搜索好友"
|
||||
loading={loading}
|
||||
onRefresh={() => fetchFriends(currentPage, searchQuery)}
|
||||
/>
|
||||
}
|
||||
footer={
|
||||
<PopupFooter
|
||||
total={totalFriends}
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
loading={loading}
|
||||
selectedCount={selectedOptions.length}
|
||||
onPageChange={setCurrentPage}
|
||||
onCancel={() => setRealVisible(false)}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className={style.friendList}>
|
||||
{loading ? (
|
||||
<div className={style.loadingBox}>
|
||||
<div className={style.loadingText}>加载中...</div>
|
||||
</div>
|
||||
) : friends.length > 0 ? (
|
||||
<div className={style.friendListInner}>
|
||||
{friends.map(friend => (
|
||||
<label
|
||||
key={friend.id}
|
||||
className={style.friendItem}
|
||||
onClick={() => !readonly && handleFriendToggle(friend)}
|
||||
>
|
||||
<div className={style.radioWrapper}>
|
||||
<div
|
||||
className={
|
||||
selectedOptions.map(v => v.id).includes(friend.id)
|
||||
? style.radioSelected
|
||||
: style.radioUnselected
|
||||
}
|
||||
>
|
||||
{selectedOptions.map(v => v.id).includes(friend.id) && (
|
||||
<div className={style.radioDot}></div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.friendInfo}>
|
||||
<div className={style.friendAvatar}>
|
||||
{friend.avatar ? (
|
||||
<img
|
||||
src={friend.avatar}
|
||||
alt={friend.nickname}
|
||||
className={style.avatarImg}
|
||||
/>
|
||||
) : (
|
||||
friend.nickname.charAt(0)
|
||||
)}
|
||||
</div>
|
||||
<div className={style.friendDetail}>
|
||||
<div className={style.friendName}>
|
||||
{friend.nickname}
|
||||
</div>
|
||||
<div className={style.friendId}>
|
||||
微信ID: {friend.wechatId}
|
||||
</div>
|
||||
{friend.customer && (
|
||||
<div className={style.friendCustomer}>
|
||||
归属客户: {friend.customer}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className={style.emptyBox}>
|
||||
<div className={style.emptyText}>
|
||||
{deviceIds.length === 0
|
||||
? "请先选择设备"
|
||||
: searchQuery
|
||||
? `没有找到包含"${searchQuery}"的好友`
|
||||
: "没有找到好友"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Layout>
|
||||
</Popup>
|
||||
onVisibleChange={setRealVisible}
|
||||
selectedOptions={selectedOptions}
|
||||
onSelect={onSelect}
|
||||
deviceIds={deviceIds}
|
||||
enableDeviceFilter={enableDeviceFilter}
|
||||
readonly={readonly}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
213
nkebao/src/components/FriendSelection/selectionPopup.tsx
Normal file
213
nkebao/src/components/FriendSelection/selectionPopup.tsx
Normal file
@@ -0,0 +1,213 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { Popup, Checkbox } from "antd-mobile";
|
||||
import Layout from "@/components/Layout/Layout";
|
||||
import PopupHeader from "@/components/PopuLayout/header";
|
||||
import PopupFooter from "@/components/PopuLayout/footer";
|
||||
import { getFriendList } from "./api";
|
||||
import style from "./index.module.scss";
|
||||
import type { FriendSelectionItem } from "./data";
|
||||
|
||||
interface SelectionPopupProps {
|
||||
visible: boolean;
|
||||
onVisibleChange: (visible: boolean) => void;
|
||||
selectedOptions: FriendSelectionItem[];
|
||||
onSelect: (friends: FriendSelectionItem[]) => void;
|
||||
deviceIds?: string[];
|
||||
enableDeviceFilter?: boolean;
|
||||
readonly?: boolean;
|
||||
onConfirm?: (
|
||||
selectedIds: number[],
|
||||
selectedItems: FriendSelectionItem[],
|
||||
) => void;
|
||||
}
|
||||
|
||||
const SelectionPopup: React.FC<SelectionPopupProps> = ({
|
||||
visible,
|
||||
onVisibleChange,
|
||||
selectedOptions,
|
||||
onSelect,
|
||||
deviceIds = [],
|
||||
enableDeviceFilter = true,
|
||||
readonly = false,
|
||||
onConfirm,
|
||||
}) => {
|
||||
const [friends, setFriends] = useState<FriendSelectionItem[]>([]);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [totalPages, setTotalPages] = useState(1);
|
||||
const [totalFriends, setTotalFriends] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// 获取好友列表API
|
||||
const fetchFriends = useCallback(
|
||||
async (page: number, keyword: string = "") => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const params: any = {
|
||||
page,
|
||||
limit: 20,
|
||||
};
|
||||
|
||||
if (keyword.trim()) {
|
||||
params.keyword = keyword.trim();
|
||||
}
|
||||
|
||||
if (enableDeviceFilter && deviceIds.length > 0) {
|
||||
params.deviceIds = deviceIds.join(",");
|
||||
}
|
||||
|
||||
const response = await getFriendList(params);
|
||||
if (response && response.list) {
|
||||
setFriends(response.list);
|
||||
setTotalFriends(response.total || 0);
|
||||
setTotalPages(Math.ceil((response.total || 0) / 20));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取好友列表失败:", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
[deviceIds, enableDeviceFilter],
|
||||
);
|
||||
|
||||
// 处理好友选择
|
||||
const handleFriendToggle = (friend: FriendSelectionItem) => {
|
||||
if (readonly) return;
|
||||
|
||||
const newSelectedFriends = selectedOptions.some(f => f.id === friend.id)
|
||||
? selectedOptions.filter(f => f.id !== friend.id)
|
||||
: selectedOptions.concat(friend);
|
||||
|
||||
onSelect(newSelectedFriends);
|
||||
};
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
if (onConfirm) {
|
||||
onConfirm(
|
||||
selectedOptions.map(v => v.id),
|
||||
selectedOptions,
|
||||
);
|
||||
}
|
||||
onVisibleChange(false);
|
||||
};
|
||||
|
||||
// 弹窗打开时初始化
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
setCurrentPage(1);
|
||||
setSearchQuery("");
|
||||
fetchFriends(1, "");
|
||||
}
|
||||
}, [visible]); // 只在弹窗开启时请求
|
||||
|
||||
// 搜索防抖(只在弹窗打开且搜索词变化时执行)
|
||||
useEffect(() => {
|
||||
if (!visible || searchQuery === "") return; // 弹窗关闭或搜索词为空时不请求
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setCurrentPage(1);
|
||||
fetchFriends(1, searchQuery);
|
||||
}, 500);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [searchQuery, visible]);
|
||||
|
||||
// 页码变化时请求数据(只在弹窗打开且页码不是1时执行)
|
||||
useEffect(() => {
|
||||
if (!visible || currentPage === 1) return; // 弹窗关闭或第一页时不请求
|
||||
fetchFriends(currentPage, searchQuery);
|
||||
}, [currentPage, visible, searchQuery]);
|
||||
|
||||
return (
|
||||
<Popup
|
||||
visible={visible && !readonly}
|
||||
onMaskClick={() => onVisibleChange(false)}
|
||||
position="bottom"
|
||||
bodyStyle={{ height: "100vh" }}
|
||||
>
|
||||
<Layout
|
||||
header={
|
||||
<PopupHeader
|
||||
title="选择微信好友"
|
||||
searchQuery={searchQuery}
|
||||
setSearchQuery={setSearchQuery}
|
||||
searchPlaceholder="搜索好友"
|
||||
loading={loading}
|
||||
onRefresh={() => fetchFriends(currentPage, searchQuery)}
|
||||
/>
|
||||
}
|
||||
footer={
|
||||
<PopupFooter
|
||||
total={totalFriends}
|
||||
currentPage={currentPage}
|
||||
totalPages={totalPages}
|
||||
loading={loading}
|
||||
selectedCount={selectedOptions.length}
|
||||
onPageChange={setCurrentPage}
|
||||
onCancel={() => onVisibleChange(false)}
|
||||
onConfirm={handleConfirm}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className={style.friendList}>
|
||||
{loading ? (
|
||||
<div className={style.loadingBox}>
|
||||
<div className={style.loadingText}>加载中...</div>
|
||||
</div>
|
||||
) : friends.length > 0 ? (
|
||||
<div className={style.friendListInner}>
|
||||
{friends.map(friend => (
|
||||
<div key={friend.id} className={style.friendItem}>
|
||||
<Checkbox
|
||||
checked={selectedOptions.some(f => f.id === friend.id)}
|
||||
onChange={() => !readonly && handleFriendToggle(friend)}
|
||||
disabled={readonly}
|
||||
style={{ marginRight: 12 }}
|
||||
/>
|
||||
<div className={style.friendInfo}>
|
||||
<div className={style.friendAvatar}>
|
||||
{friend.avatar ? (
|
||||
<img
|
||||
src={friend.avatar}
|
||||
alt={friend.nickname}
|
||||
className={style.avatarImg}
|
||||
/>
|
||||
) : (
|
||||
friend.nickname.charAt(0)
|
||||
)}
|
||||
</div>
|
||||
<div className={style.friendDetail}>
|
||||
<div className={style.friendName}>{friend.nickname}</div>
|
||||
<div className={style.friendId}>
|
||||
微信ID: {friend.wechatId}
|
||||
</div>
|
||||
{friend.customer && (
|
||||
<div className={style.friendCustomer}>
|
||||
归属客户: {friend.customer}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className={style.emptyBox}>
|
||||
<div className={style.emptyText}>
|
||||
{deviceIds.length === 0
|
||||
? "请先选择设备"
|
||||
: searchQuery
|
||||
? `没有找到包含"${searchQuery}"的好友`
|
||||
: "没有找到好友"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Layout>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectionPopup;
|
||||
@@ -11,12 +11,14 @@ import { isDevelopment } from "@/utils/env";
|
||||
import { GroupSelectionItem } from "@/components/GroupSelection/data";
|
||||
import { ContentItem } from "@/components/ContentSelection/data";
|
||||
import { FriendSelectionItem } from "@/components/FriendSelection/data";
|
||||
import { AccountItem } from "@/components/AccountSelection/data";
|
||||
import { DeviceSelectionItem } from "@/components/DeviceSelection/data";
|
||||
const ComponentTest: React.FC = () => {
|
||||
const [activeTab, setActiveTab] = useState("accounts");
|
||||
const [activeTab, setActiveTab] = useState("devices");
|
||||
|
||||
// 设备选择状态
|
||||
const [selectedDevices, setSelectedDevices] = useState<string[]>([]);
|
||||
const [selectedDevices, setSelectedDevices] = useState<DeviceSelectionItem[]>(
|
||||
[],
|
||||
);
|
||||
|
||||
// 群组选择状态
|
||||
const [selectedGroups, setSelectedGroups] = useState<GroupSelectionItem[]>(
|
||||
@@ -26,7 +28,8 @@ const ComponentTest: React.FC = () => {
|
||||
// 内容库选择状态
|
||||
const [selectedContent, setSelectedContent] = useState<ContentItem[]>([]);
|
||||
|
||||
const [selectedAccounts, setSelectedAccounts] = useState<AccountItem[]>([]);
|
||||
const [selectedAccounts, setSelectedAccounts] = useState<number[]>([]);
|
||||
// 好友选择状态
|
||||
const [selectedFriendsOptions, setSelectedFriendsOptions] = useState<
|
||||
FriendSelectionItem[]
|
||||
>([]);
|
||||
@@ -58,7 +61,7 @@ const ComponentTest: React.FC = () => {
|
||||
<div style={{ padding: "16px 0" }}>
|
||||
<h3 style={{ marginBottom: 16 }}>ContentSelection 组件测试</h3>
|
||||
<ContentSelection
|
||||
selectedOptions={selectedContent}
|
||||
selectedContent={selectedContent}
|
||||
onSelect={setSelectedContent}
|
||||
placeholder="请选择内容库"
|
||||
showSelectedList={true}
|
||||
@@ -84,7 +87,7 @@ const ComponentTest: React.FC = () => {
|
||||
<div style={{ padding: "16px 0" }}>
|
||||
<h3 style={{ marginBottom: 16 }}>GroupSelection 组件测试</h3>
|
||||
<GroupSelection
|
||||
selectedOptions={selectedGroups}
|
||||
selectedGroups={selectedGroups}
|
||||
onSelect={setSelectedGroups}
|
||||
placeholder="请选择微信群组"
|
||||
showSelectedList={true}
|
||||
@@ -126,7 +129,8 @@ const ComponentTest: React.FC = () => {
|
||||
>
|
||||
<strong>已选设备:</strong> {selectedDevices.length} 个
|
||||
<br />
|
||||
<strong>设备ID:</strong> {selectedDevices.join(", ") || "无"}
|
||||
<strong>设备ID:</strong>
|
||||
{selectedDevices.map(d => d.id).join(", ") || "无"}
|
||||
</div>
|
||||
</div>
|
||||
</Tabs.Tab>
|
||||
@@ -135,24 +139,15 @@ const ComponentTest: React.FC = () => {
|
||||
<div style={{ padding: "16px 0" }}>
|
||||
<h3 style={{ marginBottom: 16 }}>AccountSelection 组件测试</h3>
|
||||
<AccountSelection
|
||||
selectedOptions={selectedAccounts}
|
||||
onSelect={setSelectedAccounts}
|
||||
placeholder="请选择账号"
|
||||
showSelectedList={true}
|
||||
selectedListMaxHeight={300}
|
||||
value={selectedAccounts}
|
||||
onChange={setSelectedAccounts}
|
||||
// 可根据实际API和props补充其它参数
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
marginTop: 16,
|
||||
padding: 12,
|
||||
background: "#f5f5f5",
|
||||
borderRadius: 8,
|
||||
}}
|
||||
>
|
||||
<strong>已选账号:</strong> {selectedAccounts.length} 个
|
||||
<br />
|
||||
<strong>账号ID:</strong>{" "}
|
||||
{selectedAccounts.map(a => a.id).join(", ") || "无"}
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<strong>已选账号:</strong>
|
||||
{selectedAccounts.length > 0
|
||||
? selectedAccounts.join(", ")
|
||||
: "无"}
|
||||
</div>
|
||||
</div>
|
||||
</Tabs.Tab>
|
||||
|
||||
Reference in New Issue
Block a user