/* 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 from 'react'; import { Button, Dropdown, InputNumber, Modal, Space, SplitButtonGroup, Tag, Tooltip, Typography, } from '@douyinfe/semi-ui'; import { timestamp2string, renderGroup, renderQuota, getChannelIcon, renderQuotaWithAmount, showSuccess, showError, } from '../../../helpers'; import { CHANNEL_OPTIONS } from '../../../constants'; import { IconTreeTriangleDown, IconMore } from '@douyinfe/semi-icons'; import { FaRandom } from 'react-icons/fa'; // Render functions const renderType = (type, channelInfo = undefined, t) => { let type2label = new Map(); for (let i = 0; i < CHANNEL_OPTIONS.length; i++) { type2label[CHANNEL_OPTIONS[i].value] = CHANNEL_OPTIONS[i]; } type2label[0] = { value: 0, label: t('未知类型'), color: 'grey' }; let icon = getChannelIcon(type); if (channelInfo?.is_multi_key) { icon = channelInfo?.multi_key_mode === 'random' ? (
{icon}
) : (
{icon}
); } return ( {type2label[type]?.label} ); }; const renderTagType = (t) => { return ( {t('标签聚合')} ); }; const renderStatus = (status, channelInfo = undefined, t) => { if (channelInfo) { if (channelInfo.is_multi_key) { let keySize = channelInfo.multi_key_size; let enabledKeySize = keySize; if (channelInfo.multi_key_status_list) { enabledKeySize = keySize - Object.keys(channelInfo.multi_key_status_list).length; } return renderMultiKeyStatus(status, keySize, enabledKeySize, t); } } switch (status) { case 1: return ( {t('已启用')} ); case 2: return ( {t('已禁用')} ); case 3: return ( {t('自动禁用')} ); default: return ( {t('未知状态')} ); } }; const renderMultiKeyStatus = (status, keySize, enabledKeySize, t) => { switch (status) { case 1: return ( {t('已启用')} {enabledKeySize}/{keySize} ); case 2: return ( {t('已禁用')} {enabledKeySize}/{keySize} ); case 3: return ( {t('自动禁用')} {enabledKeySize}/{keySize} ); default: return ( {t('未知状态')} {enabledKeySize}/{keySize} ); } }; const renderResponseTime = (responseTime, t) => { let time = responseTime / 1000; time = time.toFixed(2) + t(' 秒'); if (responseTime === 0) { return ( {t('未测试')} ); } else if (responseTime <= 1000) { return ( {time} ); } else if (responseTime <= 3000) { return ( {time} ); } else if (responseTime <= 5000) { return ( {time} ); } else { return ( {time} ); } }; export const getChannelsColumns = ({ t, COLUMN_KEYS, updateChannelBalance, manageChannel, manageTag, submitTagEdit, testChannel, setCurrentTestChannel, setShowModelTestModal, setEditingChannel, setShowEdit, setShowEditTag, setEditingTag, copySelectedChannel, refresh, activePage, channels, setShowMultiKeyManageModal, setCurrentMultiKeyChannel, }) => { return [ { key: COLUMN_KEYS.ID, title: t('ID'), dataIndex: 'id', }, { key: COLUMN_KEYS.NAME, title: t('名称'), dataIndex: 'name', render: (text, record, index) => { if (record.remark && record.remark.trim() !== '') { return (
{record.remark}
} trigger='hover' position='topLeft' > {text}
); } return text; }, }, { key: COLUMN_KEYS.GROUP, title: t('分组'), dataIndex: 'group', render: (text, record, index) => (
{text ?.split(',') .sort((a, b) => { if (a === 'default') return -1; if (b === 'default') return 1; return a.localeCompare(b); }) .map((item, index) => renderGroup(item))}
), }, { key: COLUMN_KEYS.TYPE, title: t('类型'), dataIndex: 'type', render: (text, record, index) => { if (record.children === undefined) { if (record.channel_info) { if (record.channel_info.is_multi_key) { return <>{renderType(text, record.channel_info, t)}; } } return <>{renderType(text, undefined, t)}; } else { return <>{renderTagType(t)}; } }, }, { key: COLUMN_KEYS.STATUS, title: t('状态'), dataIndex: 'status', render: (text, record, index) => { if (text === 3) { if (record.other_info === '') { record.other_info = '{}'; } let otherInfo = JSON.parse(record.other_info); let reason = otherInfo['status_reason']; let time = otherInfo['status_time']; return (
{renderStatus(text, record.channel_info, t)}
); } else { return renderStatus(text, record.channel_info, t); } }, }, { key: COLUMN_KEYS.RESPONSE_TIME, title: t('响应时间'), dataIndex: 'response_time', render: (text, record, index) =>
{renderResponseTime(text, t)}
, }, { key: COLUMN_KEYS.BALANCE, title: t('已用/剩余'), dataIndex: 'expired_time', render: (text, record, index) => { if (record.children === undefined) { return (
{renderQuota(record.used_quota)} updateChannelBalance(record)} > {renderQuotaWithAmount(record.balance)}
); } else { return ( {renderQuota(record.used_quota)} ); } }, }, { key: COLUMN_KEYS.PRIORITY, title: t('优先级'), dataIndex: 'priority', render: (text, record, index) => { if (record.children === undefined) { return (
{ manageChannel(record.id, 'priority', record, e.target.value); }} keepFocus={true} innerButtons defaultValue={record.priority} min={-999} size='small' />
); } else { return ( { Modal.warning({ title: t('修改子渠道优先级'), content: t('确定要修改所有子渠道优先级为 ') + e.target.value + t(' 吗?'), onOk: () => { if (e.target.value === '') { return; } submitTagEdit('priority', { tag: record.key, priority: e.target.value, }); }, }); }} innerButtons defaultValue={record.priority} min={-999} size='small' /> ); } }, }, { key: COLUMN_KEYS.WEIGHT, title: t('权重'), dataIndex: 'weight', render: (text, record, index) => { if (record.children === undefined) { return (
{ manageChannel(record.id, 'weight', record, e.target.value); }} keepFocus={true} innerButtons defaultValue={record.weight} min={0} size='small' />
); } else { return ( { Modal.warning({ title: t('修改子渠道权重'), content: t('确定要修改所有子渠道权重为 ') + e.target.value + t(' 吗?'), onOk: () => { if (e.target.value === '') { return; } submitTagEdit('weight', { tag: record.key, weight: e.target.value, }); }, }); }} innerButtons defaultValue={record.weight} min={-999} size='small' /> ); } }, }, { key: COLUMN_KEYS.OPERATE, title: '', dataIndex: 'operate', fixed: 'right', render: (text, record, index) => { if (record.children === undefined) { const moreMenuItems = [ { node: 'item', name: t('删除'), type: 'danger', onClick: () => { Modal.confirm({ title: t('确定是否要删除此渠道?'), content: t('此修改将不可逆'), onOk: () => { (async () => { await manageChannel(record.id, 'delete', record); await refresh(); setTimeout(() => { if (channels.length === 0 && activePage > 1) { refresh(activePage - 1); } }, 100); })(); }, }); }, }, { node: 'item', name: t('复制'), type: 'tertiary', onClick: () => { Modal.confirm({ title: t('确定是否要复制此渠道?'), content: t('复制渠道的所有信息'), onOk: () => copySelectedChannel(record), }); }, }, ]; return ( ) : ( )} {record.channel_info?.is_multi_key ? ( { setCurrentMultiKeyChannel(record); setShowMultiKeyManageModal(true); }, }, ]} > )} ); } }, }, ]; };