| @@ -75,7 +75,6 @@ export const OptimizedSettingsPanel = React.memo( | |||||
| JSON.stringify(prevProps.previewPayload) === | JSON.stringify(prevProps.previewPayload) === | ||||
| JSON.stringify(nextProps.previewPayload) && | JSON.stringify(nextProps.previewPayload) && | ||||
| JSON.stringify(prevProps.messages) === JSON.stringify(nextProps.messages) && | JSON.stringify(prevProps.messages) === JSON.stringify(nextProps.messages) && | ||||
| JSON.stringify(prevProps.channels) === JSON.stringify(nextProps.channels) && | |||||
| prevProps.mutualExclusive === nextProps.mutualExclusive | prevProps.mutualExclusive === nextProps.mutualExclusive | ||||
| ); | ); | ||||
| }, | }, | ||||
| @@ -46,7 +46,6 @@ const SettingsPanel = ({ | |||||
| onCustomRequestBodyChange, | onCustomRequestBodyChange, | ||||
| previewPayload, | previewPayload, | ||||
| messages, | messages, | ||||
| channels = [], | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| @@ -179,38 +178,6 @@ const SettingsPanel = ({ | |||||
| /> | /> | ||||
| </div> | </div> | ||||
| {/* 通道选择 */} | |||||
| <div className={customRequestMode ? 'opacity-50' : ''}> | |||||
| <div className='flex items-center gap-2 mb-2'> | |||||
| <Typography.Text strong className='text-sm'> | |||||
| {t('通道')} | |||||
| </Typography.Text> | |||||
| {customRequestMode && ( | |||||
| <Typography.Text className='text-xs text-orange-600'> | |||||
| ({t('已在自定义模式中忽略')}) | |||||
| </Typography.Text> | |||||
| )} | |||||
| </div> | |||||
| <Select | |||||
| placeholder={t('请选择通道')} | |||||
| name='channelId' | |||||
| selection | |||||
| filter={selectFilter} | |||||
| autoClearSearchValue={false} | |||||
| onChange={(value) => onInputChange('channelId', value)} | |||||
| value={inputs.channelId} | |||||
| autoComplete='new-password' | |||||
| optionList={channels.map((ch) => ({ | |||||
| value: ch.id, | |||||
| label: ch.public_name || ch.name, | |||||
| }))} | |||||
| style={{ width: '100%' }} | |||||
| dropdownStyle={{ width: '100%', maxWidth: '100%' }} | |||||
| className='!rounded-lg' | |||||
| disabled={customRequestMode || channels.length === 0} | |||||
| /> | |||||
| </div> | |||||
| {/* 图片URL输入 */} | {/* 图片URL输入 */} | ||||
| <div className={customRequestMode ? 'opacity-50' : ''}> | <div className={customRequestMode ? 'opacity-50' : ''}> | ||||
| <ImageUrlInput | <ImageUrlInput | ||||
| @@ -103,7 +103,6 @@ const ChannelPricingCard = ({ | |||||
| hasCustomPricing: item.has_custom_pricing, | hasCustomPricing: item.has_custom_pricing, | ||||
| cacheRatio: item.cache_ratio, | cacheRatio: item.cache_ratio, | ||||
| cacheCreationRatio: item.cache_creation_ratio, | cacheCreationRatio: item.cache_creation_ratio, | ||||
| isDefault: item.is_default || false, | |||||
| userRatio: item.user_ratio ?? 1.0, | userRatio: item.user_ratio ?? 1.0, | ||||
| })); | })); | ||||
| @@ -147,11 +146,6 @@ const ChannelPricingCard = ({ | |||||
| {tag.name} | {tag.name} | ||||
| </Tag> | </Tag> | ||||
| ))} | ))} | ||||
| {record.isDefault && ( | |||||
| <Tag color='amber' size='small' shape='circle'> | |||||
| {t('默认')} | |||||
| </Tag> | |||||
| )} | |||||
| </div> | </div> | ||||
| ), | ), | ||||
| }, | }, | ||||
| @@ -298,18 +298,6 @@ const PricingCardView = ({ | |||||
| {/* 标签区域 */} | {/* 标签区域 */} | ||||
| {renderTags(model)} | {renderTags(model)} | ||||
| {/* 默认通道标识 */} | |||||
| {model.default_channel_name && ( | |||||
| <Tag | |||||
| color='amber' | |||||
| size='small' | |||||
| shape='circle' | |||||
| style={{ marginTop: 4 }} | |||||
| > | |||||
| {t('默认')}: {model.default_channel_name} | |||||
| </Tag> | |||||
| )} | |||||
| {/* 去体验按钮 */} | {/* 去体验按钮 */} | ||||
| {showTryButton && ( | {showTryButton && ( | ||||
| <Button | <Button | ||||
| @@ -64,7 +64,6 @@ const EditTokenModal = (props) => { | |||||
| const formApiRef = useRef(null); | const formApiRef = useRef(null); | ||||
| const [models, setModels] = useState([]); | const [models, setModels] = useState([]); | ||||
| const [groups, setGroups] = useState([]); | const [groups, setGroups] = useState([]); | ||||
| const [channels, setChannels] = useState([]); | |||||
| const isEdit = props.editingToken.id !== undefined; | const isEdit = props.editingToken.id !== undefined; | ||||
| const getInitValues = () => ({ | const getInitValues = () => ({ | ||||
| @@ -152,22 +151,6 @@ const EditTokenModal = (props) => { | |||||
| } | } | ||||
| }; | }; | ||||
| const loadChannels = async () => { | |||||
| let res = await API.get(`/api/user/channels`); | |||||
| const { success, message, data } = res.data; | |||||
| if (success) { | |||||
| let localChannelOptions = (data || []).map((channel) => ({ | |||||
| label: channel.remark | |||||
| ? `${channel.name} (${channel.remark})` | |||||
| : channel.name, | |||||
| value: channel.id, | |||||
| })); | |||||
| setChannels(localChannelOptions); | |||||
| } else { | |||||
| showError(t(message)); | |||||
| } | |||||
| }; | |||||
| const loadToken = async () => { | const loadToken = async () => { | ||||
| setLoading(true); | setLoading(true); | ||||
| let res = await API.get(`/api/token/${props.editingToken.id}`); | let res = await API.get(`/api/token/${props.editingToken.id}`); | ||||
| @@ -198,7 +181,6 @@ const EditTokenModal = (props) => { | |||||
| } | } | ||||
| loadModels(); | loadModels(); | ||||
| loadGroups(); | loadGroups(); | ||||
| loadChannels(); | |||||
| }, [props.editingToken.id]); | }, [props.editingToken.id]); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| @@ -85,7 +85,6 @@ export const DEFAULT_CONFIG = { | |||||
| inputs: { | inputs: { | ||||
| model: 'gpt-4o', | model: 'gpt-4o', | ||||
| group: '', | group: '', | ||||
| channelId: 0, | |||||
| temperature: 0.7, | temperature: 0.7, | ||||
| top_p: 1, | top_p: 1, | ||||
| max_tokens: 4096, | max_tokens: 4096, | ||||
| @@ -401,14 +401,6 @@ export const channelPricingApi = { | |||||
| // 复制全局定价 | // 复制全局定价 | ||||
| copyGlobal: (channelId, overwrite = false) => | copyGlobal: (channelId, overwrite = false) => | ||||
| API.post(`/api/channel_pricing/copy_global/${channelId}`, { overwrite }), | API.post(`/api/channel_pricing/copy_global/${channelId}`, { overwrite }), | ||||
| // 设置默认通道 | |||||
| setDefault: (modelName, channelId) => | |||||
| API.post('/api/channel_pricing/set_default', { model_name: modelName, channel_id: channelId }), | |||||
| // 清除默认通道 | |||||
| clearDefault: (modelName) => | |||||
| API.delete(`/api/channel_pricing/default/${encodeURIComponent(modelName)}`), | |||||
| }; | }; | ||||
| // 定价标签 API | // 定价标签 API | ||||
| @@ -83,7 +83,6 @@ export const usePlaygroundState = () => { | |||||
| const [showSettings, setShowSettings] = useState(false); | const [showSettings, setShowSettings] = useState(false); | ||||
| const [models, setModels] = useState([]); | const [models, setModels] = useState([]); | ||||
| const [groups, setGroups] = useState([]); | const [groups, setGroups] = useState([]); | ||||
| const [channels, setChannels] = useState([]); | |||||
| const [status, setStatus] = useState({}); | const [status, setStatus] = useState({}); | ||||
| // 消息相关状态 - 使用加载的消息或默认消息初始化 | // 消息相关状态 - 使用加载的消息或默认消息初始化 | ||||
| @@ -353,8 +352,6 @@ export const usePlaygroundState = () => { | |||||
| setShowSettings, | setShowSettings, | ||||
| setModels, | setModels, | ||||
| setGroups, | setGroups, | ||||
| channels, | |||||
| setChannels, | |||||
| setStatus, | setStatus, | ||||
| setMessage, | setMessage, | ||||
| setDebugData, | setDebugData, | ||||
| @@ -113,8 +113,6 @@ const Playground = () => { | |||||
| setShowSettings, | setShowSettings, | ||||
| setModels, | setModels, | ||||
| setGroups, | setGroups, | ||||
| channels, | |||||
| setChannels, | |||||
| setStatus, | setStatus, | ||||
| setMessage, | setMessage, | ||||
| setDebugData, | setDebugData, | ||||
| @@ -137,37 +135,6 @@ const Playground = () => { | |||||
| // 数据加载 | // 数据加载 | ||||
| useDataLoader(userState, inputs, handleInputChange, setModels, setGroups, searchParams); | useDataLoader(userState, inputs, handleInputChange, setModels, setGroups, searchParams); | ||||
| // Load channels for the selected model | |||||
| useEffect(() => { | |||||
| if (!inputs.model) { | |||||
| setChannels([]); | |||||
| return; | |||||
| } | |||||
| let cancelled = false; | |||||
| const loadChannels = async () => { | |||||
| try { | |||||
| const res = await API.get( | |||||
| `/api/user/model_channels?model=${encodeURIComponent(inputs.model)}` | |||||
| ); | |||||
| if (cancelled) return; | |||||
| const { success, data } = res.data; | |||||
| if (success && data) { | |||||
| const channelList = data.channels || []; | |||||
| setChannels(channelList); | |||||
| const channelId = (data.default_channel_id && data.default_channel_id > 0) | |||||
| ? data.default_channel_id | |||||
| : (channelList.length > 0 ? channelList[0].id : 0); | |||||
| if (channelId !== inputs.channelId) { | |||||
| handleInputChange('channelId', channelId); | |||||
| } | |||||
| } | |||||
| } catch { | |||||
| setChannels([]); | |||||
| } | |||||
| }; | |||||
| loadChannels(); | |||||
| return () => { cancelled = true; }; | |||||
| }, [inputs.model]); | |||||
| // 消息编辑 | // 消息编辑 | ||||
| const { | const { | ||||
| @@ -290,14 +257,10 @@ const Playground = () => { | |||||
| // 自定义请求体也通过 header 传递网关字段 | // 自定义请求体也通过 header 传递网关字段 | ||||
| const customHeaders = {}; | const customHeaders = {}; | ||||
| if (inputs.channelId && inputs.channelId > 0) { | |||||
| customHeaders['X-Channel-Id'] = String(inputs.channelId); | |||||
| } | |||||
| if (customPayload.group) { | if (customPayload.group) { | ||||
| customHeaders['X-Group'] = customPayload.group; | customHeaders['X-Group'] = customPayload.group; | ||||
| delete customPayload.group; | delete customPayload.group; | ||||
| } | } | ||||
| delete customPayload.channel_id; | |||||
| sendRequest(customPayload, customPayload.stream !== false, customHeaders); | sendRequest(customPayload, customPayload.stream !== false, customHeaders); | ||||
| // 发送消息后保存,传入新消息列表 | // 发送消息后保存,传入新消息列表 | ||||
| @@ -335,14 +298,10 @@ const Playground = () => { | |||||
| parameterEnabled, | parameterEnabled, | ||||
| ); | ); | ||||
| const extraHeaders = {}; | const extraHeaders = {}; | ||||
| if (inputs.channelId && inputs.channelId > 0) { | |||||
| extraHeaders['X-Channel-Id'] = String(inputs.channelId); | |||||
| } | |||||
| if (payload.group) { | if (payload.group) { | ||||
| extraHeaders['X-Group'] = payload.group; | extraHeaders['X-Group'] = payload.group; | ||||
| delete payload.group; | delete payload.group; | ||||
| } | } | ||||
| delete payload.channel_id; | |||||
| sendRequest(payload, inputs.stream, extraHeaders); | sendRequest(payload, inputs.stream, extraHeaders); | ||||
| // 禁用图片模式 | // 禁用图片模式 | ||||
| @@ -533,7 +492,6 @@ const Playground = () => { | |||||
| parameterEnabled={parameterEnabled} | parameterEnabled={parameterEnabled} | ||||
| models={models} | models={models} | ||||
| groups={groups} | groups={groups} | ||||
| channels={channels} | |||||
| styleState={styleState} | styleState={styleState} | ||||
| showSettings={showSettings} | showSettings={showSettings} | ||||
| showDebugPanel={showDebugPanel} | showDebugPanel={showDebugPanel} | ||||
| @@ -99,7 +99,6 @@ const CONTEXT_KEY_PRESETS = [ | |||||
| { key: 'username', label: 'username' }, | { key: 'username', label: 'username' }, | ||||
| { key: 'user_group', label: 'user_group' }, | { key: 'user_group', label: 'user_group' }, | ||||
| { key: 'user_email', label: 'user_email' }, | { key: 'user_email', label: 'user_email' }, | ||||
| { key: 'specific_channel_id', label: 'specific_channel_id' }, | |||||
| ]; | ]; | ||||
| const RULES_JSON_PLACEHOLDER = `[ | const RULES_JSON_PLACEHOLDER = `[ | ||||
| @@ -33,7 +33,6 @@ import { | |||||
| RadioGroup, | RadioGroup, | ||||
| Radio, | Radio, | ||||
| TreeSelect, | TreeSelect, | ||||
| Tooltip, | |||||
| } from '@douyinfe/semi-ui'; | } from '@douyinfe/semi-ui'; | ||||
| import { | import { | ||||
| IconEdit, | IconEdit, | ||||
| @@ -41,7 +40,6 @@ import { | |||||
| IconChevronDown, | IconChevronDown, | ||||
| IconChevronRight, | IconChevronRight, | ||||
| IconSearch, | IconSearch, | ||||
| IconStar, | |||||
| } from '@douyinfe/semi-icons'; | } from '@douyinfe/semi-icons'; | ||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import { channelPricingApi } from '../../../helpers/api'; | import { channelPricingApi } from '../../../helpers/api'; | ||||
| @@ -317,43 +315,6 @@ const ChannelPricingView = ({ channels, channelPricings, tags, onRefresh }) => { | |||||
| )); | )); | ||||
| }, | }, | ||||
| }, | }, | ||||
| { | |||||
| title: t('默认'), | |||||
| key: 'isDefault', | |||||
| width: 70, | |||||
| render: (_, record) => { | |||||
| const isDefault = record.pricing?.is_default === true; | |||||
| return ( | |||||
| <Tooltip content={isDefault ? t('此为该模型的默认通道') : t('设为默认通道')}> | |||||
| <div className="flex items-center gap-1"> | |||||
| <Button | |||||
| size="small" | |||||
| type={isDefault ? 'warning' : 'tertiary'} | |||||
| icon={<IconStar />} | |||||
| onClick={async () => { | |||||
| try { | |||||
| const res = isDefault | |||||
| ? await channelPricingApi.clearDefault(record.modelName) | |||||
| : await channelPricingApi.setDefault(record.modelName, record.channelId); | |||||
| if (res.data?.success === false) { | |||||
| showError(res.data.message || t('操作失败')); | |||||
| return; | |||||
| } | |||||
| showSuccess(isDefault ? t('已取消默认通道') : t('已设为默认通道')); | |||||
| onRefresh(); | |||||
| } catch (e) { | |||||
| showError(e); | |||||
| } | |||||
| }} | |||||
| /> | |||||
| {isDefault && ( | |||||
| <span className="text-xs text-amber-500 font-medium">{t('默认')}</span> | |||||
| )} | |||||
| </div> | |||||
| </Tooltip> | |||||
| ); | |||||
| }, | |||||
| }, | |||||
| { | { | ||||
| title: t('操作'), | title: t('操作'), | ||||
| key: 'action', | key: 'action', | ||||