/*
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';
import {
Modal,
Table,
Input,
Space,
Highlight,
Select,
Tag,
} from '@douyinfe/semi-ui';
import { IconSearch } from '@douyinfe/semi-icons';
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('');
},
}));
// 官方渠道识别
const isOfficialChannel = (record) => {
const id = record?.key ?? record?.value ?? record?._originalData?.id;
const base = record?._originalData?.base_url || '';
const name = record?.label || '';
return (
id === -100 ||
base === 'https://basellm.github.io' ||
name === '官方倍率预设'
);
};
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;
const sorted = [...matched].sort((a, b) => {
const wa = isOfficialChannel(a) ? 0 : 1;
const wb = isOfficialChannel(b) ? 0 : 1;
return wa - wb;
});
setFilteredData(sorted);
}, [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 (