AddPrivatePocketModal.tsx 6.8 KB
import {
  postCanrdApiUserList,
  postCanrdPrivatePocketSave,
  postServiceOrderQuerySalesCode,
} from '@/services';
import { getUserInfo } from '@/utils/user';
import { Form, Modal, Select, message } from 'antd';
import React, { useEffect, useRef, useState } from 'react';

interface AddPrivatePocketModalProps {
  visible: boolean;
  onCancel: () => void;
  onSuccess: () => void;
}

interface SalesCodeItem {
  number: string | null;
  userName: string;
}

interface UserItem {
  uid: string;
  realName: string;
  institution?: string;
  nowMoney?: string | number;
  phone: string;
  [key: string]: any;
}

const AddPrivatePocketModal: React.FC<AddPrivatePocketModalProps> = ({
  visible,
  onCancel,
  onSuccess,
}) => {
  const [form] = Form.useForm();
  const [salesCodeList, setSalesCodeList] = useState<SalesCodeItem[]>([]);
  const [loading, setLoading] = useState<boolean>(false);
  const [userList, setUserList] = useState<any[]>([]);
  const [searchKeywords, setSearchKeywords] = useState<string>('');
  const userInfo = getUserInfo();
  const userName = userInfo?.username || '';
  const searchTimerRef = useRef<any>(null);

  const fetchSalesCodeList = async () => {
    try {
      const res = await postServiceOrderQuerySalesCode();
      if (res?.data) {
        setSalesCodeList(res.data);
      }
    } catch (error) {
      console.error('获取销售编码列表失败:', error);
      message.error('获取销售编码列表失败');
    }
  };

  // Define a function to fetch user list that can be called from multiple places
  const fetchUserList = async (keywords: string) => {
    try {
      if (!keywords || keywords.trim() === '') {
        return [];
      }

      const res = await postCanrdApiUserList({
        data: { keywords: keywords, pageSize: 1000000 },
      });

      if (res?.data?.data) {
        setUserList(res.data.data);
      }
      return res?.data?.data || [];
    } catch (error) {
      console.error('获取用户列表失败:', error);
      return [];
    }
  };

  // Initial fetch when component mounts
  useEffect(() => {
    if (visible) {
      fetchUserList('');
    }
  }, [visible]);

  useEffect(() => {
    if (visible) {
      fetchSalesCodeList();
      form.resetFields();
    }
  }, [visible, form]);

  const handleSubmit = async () => {
    try {
      const values = await form.validateFields();
      setLoading(true);

      const res = await postCanrdPrivatePocketSave({
        data: {
          account: values.account,
          salesCode: values.salesCode,
          createByName: userName,
        },
      });

      if (res?.result === 0 || res?.code === 200 || res?.success) {
        message.success('添加隐私钱包成功');
        onSuccess();
      } else {
        message.error(res?.message || '添加失败');
      }
    } catch (error) {
      console.error('添加隐私钱包失败:', error);
    } finally {
      setLoading(false);
    }
  };

  // Function to handle search with debounce
  const handleSearch = (value: string) => {
    setSearchKeywords(value);

    // Clear any existing timer
    if (searchTimerRef.current) {
      clearTimeout(searchTimerRef.current);
    }

    // Set a new timer to fetch users after 1000ms of inactivity
    searchTimerRef.current = setTimeout(() => {
      fetchUserList(value);
    }, 1000);
  };

  return (
    <Modal
      title="添加隐私钱包"
      open={visible}
      onCancel={onCancel}
      onOk={handleSubmit}
      confirmLoading={loading}
      destroyOnClose
    >
      <Form form={form} layout="vertical">
        <Form.Item
          name="account"
          label="绑定普通账户"
          rules={[{ required: true, message: '请选择账户' }]}
        >
          <Select
            showSearch
            placeholder="请选择账户"
            optionFilterProp="children"
            defaultActiveFirstOption={false}
            notFoundContent={null}
            filterOption={false} // Disable built-in filtering to use server-side search
            onSearch={handleSearch} // Use the debounced search handler
            onChange={(value) => {
              // When a value is selected, find the corresponding phone from userList
              // or use the value directly if it's a custom entry

              // Check if this is a custom entry (value is the same as searchKeywords)
              if (value === searchKeywords && searchKeywords.trim() !== '') {
                form.setFieldsValue({ account: searchKeywords });
                return;
              }

              // Find the selected user from userList to get their phone
              const selectedUser = userList.find((user) => user.uid === value);
              if (selectedUser && selectedUser.phone) {
                form.setFieldsValue({ account: selectedUser.phone });
              }
            }}
            dropdownRender={(menu) => (
              <div>
                {menu}
                {searchKeywords.trim() !== '' && (
                  <div
                    style={{
                      padding: '8px',
                      cursor: 'pointer',
                      borderTop: '1px solid #e8e8e8',
                    }}
                    onClick={() => {
                      form.setFieldsValue({ account: searchKeywords });
                    }}
                  >
                    <span style={{ color: '#333333' }}>{searchKeywords}</span>
                    {' | '}
                    <span style={{ color: 'orange' }}>自定义</span>
                  </div>
                )}
              </div>
            )}
          >
            {userList.map((user: UserItem) => {
              const displayText = `${user.realName || '-'} | ${
                user.institution || '-'
              } | ${user.nowMoney || '0'}¥ | ${user.phone || '-'}`;
              return (
                <Select.Option
                  key={user.uid}
                  value={user.uid}
                  title={displayText}
                >
                  <div>
                    <span>{displayText}</span>
                  </div>
                </Select.Option>
              );
            })}
          </Select>
        </Form.Item>
        <Form.Item
          name="salesCode"
          label="负责销售"
          rules={[{ required: true, message: '请选择负责销售' }]}
        >
          <Select
            placeholder="请选择负责销售"
            showSearch
            optionFilterProp="children"
            filterOption={(input, option) =>
              (option?.label?.toString() || '')
                .toLowerCase()
                .includes(input.toLowerCase())
            }
            options={salesCodeList.map((item) => ({
              value: item.userName,
              label: item.userName,
            }))}
          />
        </Form.Item>
      </Form>
    </Modal>
  );
};

export default AddPrivatePocketModal;