React - 编写选择礼物组件

发布于:2025-05-15 ⋅ 阅读:(14) ⋅ 点赞:(0)

GiftSelector.tsx 

import React, { useState, useEffect } from 'react';
import { Modal, Image, message, Spin, Form, Input, Button } from 'antd';
import './GiftSelector.css';
import fetchGiftListWithCache from "@/pages/AnchorLive/LiveMatchGiftPk/components/saveGiftDataToLocalStorage";

type GiftItem = {
  propId: number;
  propName: string;
  propHYB: number;
  propGreenBean: number;
  propIconUrl: string;
};

type GiftSelectorProps = {
  visible: boolean;
  prefix: 'opt1' | 'opt2';
  uid: string;
  gameId: number;
  disabledGifts: number[]; // 已选择的礼物ID列表
  onSelect: (selectedGift: GiftItem) => void;
  onClose: () => void;
};

const GiftSelector: React.FC<GiftSelectorProps> = ({ visible, prefix, uid, gameId, disabledGifts, onSelect, onClose }) => {
  const [giftList, setGiftList] = useState<GiftItem[]>([]);
  const [filteredGiftList, setFilteredGiftList] = useState<GiftItem[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
  const [selectedGiftId, setSelectedGiftId] = useState<number | null>(null);
  const [form] = Form.useForm();

  const fetchGiftList = async () => {
    setLoading(true);
    try {
      const giftList = await fetchGiftListWithCache(uid, gameId);
      setGiftList(giftList);
      setFilteredGiftList(giftList);
    } catch (error) {
      console.error('加载礼物数据失败:', error);
      message.error('加载礼物数据失败');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (visible) {
      fetchGiftList();
    }
  }, [visible]);

  const handleSearch = () => {
    const { nameSearch, idSearch } = form.getFieldsValue();
    const filteredList = giftList.filter((gift) => {
      const matchesName = nameSearch ? gift.propName.includes(nameSearch) : true;
      const matchesId = idSearch ? String(gift.propId).includes(idSearch) : true;
      return matchesName && matchesId;
    });
    setFilteredGiftList(filteredList);
  };

  const handleReset = () => {
    form.resetFields();
    setFilteredGiftList(giftList);
  };

  const handleConfirm = () => {
    const selectedGift = filteredGiftList.find((gift) => gift.propId === selectedGiftId);
    if (selectedGift) {
      onSelect(selectedGift);
      onClose();
    } else {
      message.warning('请选择一个礼物');
    }
  };

  return (
    <Modal
      visible={visible}
      title="选择礼物"
      onCancel={onClose}
      footer={null}
      width={600}
    >
      {loading ? (
        <div className="loading-container">
          <Spin tip="加载中..." />
        </div>
      ) : (
        <>
          <Form form={form} layout="inline" style={{ marginBottom: '16px', marginLeft: '20px' }}>
            <Form.Item name="nameSearch">
              <Input placeholder="请输入礼物名称" style={{ width: '165px' }} />
            </Form.Item>
            <Form.Item name="idSearch">
              <Input placeholder="请输入礼物ID" style={{ width: '165px' }} />
            </Form.Item>
            <Form.Item>
              <Button type="primary" onClick={handleSearch}>
                查询
              </Button>
              <Button onClick={handleReset} style={{ marginLeft: '5px' }}>
                重置
              </Button>
            </Form.Item>
          </Form>

          <div className="gift-container">
            <div className="gift-grid">
              {filteredGiftList.map((gift) => (
                <div
                  key={gift.propId}
                  className={`gift-item ${selectedGiftId === gift.propId ? 'selected' : ''} ${
                    disabledGifts.includes(gift.propId) ? 'disabled' : ''
                  }`}
                  onClick={() => !disabledGifts.includes(gift.propId) && setSelectedGiftId(gift.propId)}
                >
                  <Image src={gift.propIconUrl} alt={gift.propName} width={46} height={46} preview={false} />
                  <div className="gift-name">{gift.propName}</div>
                  <div className="gift-price">{gift.propGreenBean} 虎牙币</div>
                </div>
              ))}
            </div>
          </div>
          <div className="gift-footer">
            <button className="confirm-button" onClick={handleConfirm} disabled={!selectedGiftId}>
              确定
            </button>
          </div>
        </>
      )}
    </Modal>
  );
};

export default GiftSelector;

GiftSelector.css

.loading-container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 300px;
}

.gift-container {
  max-height: 400px;
  overflow-y: auto;
  padding: 20px;
}

.gift-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 20px;
}

.gift-item {
  cursor: pointer;
  text-align: center;
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 10px;
  transition: all 0.3s ease;
}

.gift-item:hover {
  border-color: #1890ff;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.gift-item.selected {
  border-color: #1890ff;
  background-color: #f0f8ff;
}

.gift-footer {
  position: sticky;
  bottom: 0;
  text-align: center;
  background-color: #fff;
  padding: 10px;
}

.confirm-button {
  background-color: #1890ff;
  color: white;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.confirm-button:hover {
  background-color: #40a9ff;
}

.gift-price {
  font-size: 12px;
  color: #666;
  margin-top: 5px;
}

.gift-item.disabled {
  opacity: 0.5;
  pointer-events: none;
}

.confirm-button:disabled {
  background-color: #d9d9d9;
  color: #a6a6a6;
  cursor: not-allowed;
}


网站公告

今日签到

点亮在社区的每一天
去签到