/* Copyright (C) 2025 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import { useIsMobile } from '../../hooks/common/useIsMobile.js'; import { Modal, Table, Input, Space, Highlight, Select, Tag, } from '@douyinfe/semi-ui'; import { IconSearch } from '@douyinfe/semi-icons'; import { CheckCircle, XCircle, AlertCircle, HelpCircle } from 'lucide-react'; const ChannelSelectorModal = forwardRef(({ visible, onCancel, onOk, allChannels, selectedChannelIds, setSelectedChannelIds, channelEndpoints, updateChannelEndpoint, t, }, ref) => { const [searchText, setSearchText] = useState(''); const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); const isMobile = useIsMobile(); const [filteredData, setFilteredData] = useState([]); useImperativeHandle(ref, () => ({ resetPagination: () => { setCurrentPage(1); setSearchText(''); }, })); useEffect(() => { if (!allChannels) return; const searchLower = searchText.trim().toLowerCase(); const matched = searchLower ? allChannels.filter((item) => { const name = (item.label || '').toLowerCase(); const baseUrl = (item._originalData?.base_url || '').toLowerCase(); return name.includes(searchLower) || baseUrl.includes(searchLower); }) : allChannels; setFilteredData(matched); }, [allChannels, searchText]); const total = filteredData.length; const paginatedData = filteredData.slice( (currentPage - 1) * pageSize, currentPage * pageSize, ); const updateEndpoint = (channelId, endpoint) => { if (typeof updateChannelEndpoint === 'function') { updateChannelEndpoint(channelId, endpoint); } }; const renderEndpointCell = (text, record) => { const channelId = record.key || record.value; const currentEndpoint = channelEndpoints[channelId] || ''; const getEndpointType = (ep) => { if (ep === '/api/ratio_config') return 'ratio_config'; if (ep === '/api/pricing') return 'pricing'; return 'custom'; }; const currentType = getEndpointType(currentEndpoint); const handleTypeChange = (val) => { if (val === 'ratio_config') { updateEndpoint(channelId, '/api/ratio_config'); } else if (val === 'pricing') { updateEndpoint(channelId, '/api/pricing'); } else { if (currentType !== 'custom') { updateEndpoint(channelId, ''); } } }; return (
updateEndpoint(channelId, val)} placeholder="/your/endpoint" style={{ width: 160, fontSize: 12 }} /> )}
); }; const renderStatusCell = (status) => { switch (status) { case 1: return ( }> {t('已启用')} ); case 2: return ( }> {t('已禁用')} ); case 3: return ( }> {t('自动禁用')} ); default: return ( }> {t('未知状态')} ); } }; const renderNameCell = (text) => ( ); const renderBaseUrlCell = (text) => ( ); const columns = [ { title: t('名称'), dataIndex: 'label', render: renderNameCell, }, { title: t('源地址'), dataIndex: '_originalData.base_url', render: (_, record) => renderBaseUrlCell(record._originalData?.base_url || ''), }, { title: t('状态'), dataIndex: '_originalData.status', render: (_, record) => renderStatusCell(record._originalData?.status || 0), }, { title: t('同步接口'), dataIndex: 'endpoint', fixed: 'right', render: renderEndpointCell, }, ]; const rowSelection = { selectedRowKeys: selectedChannelIds, onChange: (keys) => setSelectedChannelIds(keys), }; return ( {t('选择同步渠道')}} size={isMobile ? 'full-width' : 'large'} keepDOM lazyRender={false} > } placeholder={t('搜索渠道名称或地址')} value={searchText} onChange={setSearchText} showClear /> { setCurrentPage(page); setPageSize(size); }, onShowSizeChange: (curr, size) => { setCurrentPage(1); setPageSize(size); }, }} size="small" /> ); }); export default ChannelSelectorModal;