feat: improve model price error UX with role-aware messages and cleaner UI
- Backend: differentiate error messages for admin vs regular users in price.go - Backend: include error_code in channel test response for structured error handling - Frontend: render model_price_error as a styled card in Playground with admin nav button - Frontend: show inline error details and settings link in channel test modal - Frontend: parse error codes from both SSE and non-streaming API responses - i18n: remove redundant "Settings" suffix from setting tab translations (en/fr/ru/ja/vi) - i18n: update "Group & Model Pricing" translations across all locales
This commit is contained in:
@@ -21,8 +21,9 @@ import React, { useRef, useEffect } from 'react';
|
||||
import { Typography, TextArea, Button } from '@douyinfe/semi-ui';
|
||||
import MarkdownRenderer from '../common/markdown/MarkdownRenderer';
|
||||
import ThinkingContent from './ThinkingContent';
|
||||
import { Loader2, Check, X } from 'lucide-react';
|
||||
import { Loader2, Check, X, Settings, AlertTriangle } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isAdmin } from '../../helpers/utils';
|
||||
|
||||
const MessageContent = ({
|
||||
message,
|
||||
@@ -64,6 +65,44 @@ const MessageContent = ({
|
||||
errorText = t('请求发生错误');
|
||||
}
|
||||
|
||||
if (message.errorCode === 'model_price_error') {
|
||||
return (
|
||||
<div className={`${className}`}>
|
||||
<div
|
||||
className='rounded-lg p-3 space-y-2'
|
||||
style={{
|
||||
background: 'var(--semi-color-bg-0)',
|
||||
border: '1px solid var(--semi-color-border)',
|
||||
}}
|
||||
>
|
||||
<div className='flex items-center gap-2'>
|
||||
<AlertTriangle size={16} className='text-orange-500 shrink-0' />
|
||||
<Typography.Text strong className='!text-[var(--semi-color-text-0)]'>
|
||||
{t('模型价格未配置')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Typography.Paragraph
|
||||
className='!text-[var(--semi-color-text-1)] !text-sm !mb-0'
|
||||
style={{ wordBreak: 'break-word' }}
|
||||
>
|
||||
{errorText}
|
||||
</Typography.Paragraph>
|
||||
{isAdmin() && (
|
||||
<Button
|
||||
size='small'
|
||||
theme='light'
|
||||
type='warning'
|
||||
icon={<Settings size={14} />}
|
||||
onClick={() => window.open('/console/setting?tab=ratio', '_blank')}
|
||||
>
|
||||
{t('前往设置')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${className}`}>
|
||||
<Typography.Text className='text-white'>{errorText}</Typography.Text>
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
Banner,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { IconSearch, IconInfoCircle } from '@douyinfe/semi-icons';
|
||||
import { Settings } from 'lucide-react';
|
||||
import { copy, showError, showInfo, showSuccess } from '../../../../helpers';
|
||||
import { MODEL_TABLE_PAGE_SIZE } from '../../../../constants';
|
||||
|
||||
@@ -168,17 +169,43 @@ const ModelTestModal = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex items-center gap-2'>
|
||||
<Tag color={testResult.success ? 'green' : 'red'} shape='circle'>
|
||||
{testResult.success ? t('成功') : t('失败')}
|
||||
</Tag>
|
||||
{testResult.success && (
|
||||
<Typography.Text type='tertiary'>
|
||||
{t('请求时长: ${time}s').replace(
|
||||
'${time}',
|
||||
testResult.time.toFixed(2),
|
||||
<div className='flex flex-col gap-1'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Tag color={testResult.success ? 'green' : 'red'} shape='circle'>
|
||||
{testResult.success ? t('成功') : t('失败')}
|
||||
</Tag>
|
||||
{testResult.success && (
|
||||
<Typography.Text type='tertiary'>
|
||||
{t('请求时长: ${time}s').replace(
|
||||
'${time}',
|
||||
testResult.time.toFixed(2),
|
||||
)}
|
||||
</Typography.Text>
|
||||
)}
|
||||
</div>
|
||||
{!testResult.success && testResult.message && (
|
||||
<div className='flex flex-col gap-1'>
|
||||
<Typography.Text
|
||||
type='danger'
|
||||
size='small'
|
||||
className='break-all'
|
||||
style={{ maxWidth: '400px', fontSize: '12px' }}
|
||||
>
|
||||
{testResult.message}
|
||||
</Typography.Text>
|
||||
{testResult.errorCode === 'model_price_error' && (
|
||||
<Button
|
||||
size='small'
|
||||
theme='light'
|
||||
type='warning'
|
||||
icon={<Settings size={12} />}
|
||||
onClick={() => window.open('/console/setting?tab=ratio', '_blank')}
|
||||
style={{ width: 'fit-content' }}
|
||||
>
|
||||
{t('前往设置')}
|
||||
</Button>
|
||||
)}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user