Commit f2bca12d by Apple\Apple

feat(ui): Enhance model tag rendering in logs table with icons

Improve the logs table by implementing brand-specific model icons and better
redirection visualization:

- Replace standard tags with `renderModelTag` to display appropriate brand
  icons for each model (OpenAI, Claude, Gemini, etc.)
- Fix background colors by explicitly passing color parameters
- Restore descriptive text for model redirection in popover
- Replace refresh icon with forward icon for better representation of model
  redirection
- Clean up unused imports

This change provides a more intuitive visual representation of models and
their relationships, making the logs table easier to understand at a glance.
parent 56491f4d
import React, { useContext, useEffect, useState } from 'react';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
API,
......@@ -19,7 +19,8 @@ import {
renderNumber,
renderQuota,
stringToColor,
getLogOther
getLogOther,
renderModelTag
} from '../../helpers';
import {
......@@ -39,18 +40,14 @@ import {
Typography,
Divider,
Input,
DatePicker,
DatePicker
} from '@douyinfe/semi-ui';
import { ITEMS_PER_PAGE } from '../../constants';
import Paragraph from '@douyinfe/semi-ui/lib/es/typography/paragraph';
import {
IconRefresh,
IconSetting,
IconEyeOpened,
IconSearch,
IconCoinMoneyStroked,
IconPulse,
IconTypograph,
IconForward
} from '@douyinfe/semi-icons';
const { Text } = Typography;
......@@ -202,19 +199,12 @@ const LogsTable = () => {
other?.upstream_model_name &&
other?.upstream_model_name !== '';
if (!modelMapped) {
return (
<Tag
color={stringToColor(record.model_name)}
size='large'
shape='circle'
onClick={(event) => {
copyText(event, record.model_name).then((r) => { });
}}
>
{' '}
{record.model_name}{' '}
</Tag>
);
return renderModelTag(record.model_name, {
color: stringToColor(record.model_name),
onClick: (event) => {
copyText(event, record.model_name).then((r) => { });
}
});
} else {
return (
<>
......@@ -223,48 +213,35 @@ const LogsTable = () => {
content={
<div style={{ padding: 10 }}>
<Space vertical align={'start'}>
<Tag
color={stringToColor(record.model_name)}
size='large'
shape='circle'
onClick={(event) => {
copyText(event, record.model_name).then((r) => { });
}}
>
{t('请求并计费模型')} {record.model_name}{' '}
</Tag>
<Tag
color={stringToColor(other.upstream_model_name)}
size='large'
shape='circle'
onClick={(event) => {
copyText(event, other.upstream_model_name).then(
(r) => { },
);
}}
>
{t('实际模型')} {other.upstream_model_name}{' '}
</Tag>
<div className="flex items-center">
<Text strong style={{ marginRight: 8 }}>{t('请求并计费模型')}:</Text>
{renderModelTag(record.model_name, {
color: stringToColor(record.model_name),
onClick: (event) => {
copyText(event, record.model_name).then((r) => { });
}
})}
</div>
<div className="flex items-center">
<Text strong style={{ marginRight: 8 }}>{t('实际模型')}:</Text>
{renderModelTag(other.upstream_model_name, {
color: stringToColor(other.upstream_model_name),
onClick: (event) => {
copyText(event, other.upstream_model_name).then((r) => { });
}
})}
</div>
</Space>
</div>
}
>
<Tag
color={stringToColor(record.model_name)}
size='large'
shape='circle'
onClick={(event) => {
{renderModelTag(record.model_name, {
color: stringToColor(record.model_name),
onClick: (event) => {
copyText(event, record.model_name).then((r) => { });
}}
suffixIcon={
<IconRefresh
style={{ width: '0.8em', height: '0.8em', opacity: 0.6 }}
/>
}
>
{' '}
{record.model_name}{' '}
</Tag>
},
suffixIcon: <IconForward style={{ width: '0.9em', height: '0.9em', opacity: 0.75 }} />
})}
</Popover>
</Space>
</>
......
import React, { useContext, useEffect, useRef, useMemo, useState } from 'react';
import { API, copy, showError, showInfo, showSuccess } from '../../helpers/index.js';
import { API, copy, showError, showInfo, showSuccess, getModelCategories } from '../../helpers/index.js';
import { useTranslation } from 'react-i18next';
import {
......@@ -28,7 +28,6 @@ import {
} from '@douyinfe/semi-icons';
import { UserContext } from '../../context/User/index.js';
import { AlertCircle } from 'lucide-react';
import { MODEL_CATEGORIES } from '../../constants/index.js';
const ModelPricing = () => {
const { t } = useTranslation();
......@@ -321,7 +320,7 @@ const ModelPricing = () => {
refresh().then();
}, []);
const modelCategories = MODEL_CATEGORIES(t);
const modelCategories = getModelCategories(t);
const renderArrow = (items, pos, handleArrowClick) => {
const style = {
......
......@@ -2,5 +2,4 @@ export * from './channel.constants';
export * from './user.constants';
export * from './toast.constants';
export * from './common.constant';
export * from './model.constants';
export * from './playground.constants';
import {
OpenAI,
Claude,
Gemini,
Moonshot,
Zhipu,
Qwen,
DeepSeek,
Minimax,
Wenxin,
Spark,
Midjourney,
Hunyuan,
Cohere,
Cloudflare,
Ai360,
Yi,
Jina,
Mistral,
XAI,
Ollama,
Doubao,
} from '@lobehub/icons';
export const MODEL_CATEGORIES = (t) => ({
all: {
label: t('全部模型'),
icon: null,
filter: () => true
},
openai: {
label: 'OpenAI',
icon: <OpenAI />,
filter: (model) => model.model_name.toLowerCase().includes('gpt') ||
model.model_name.toLowerCase().includes('dall-e') ||
model.model_name.toLowerCase().includes('whisper') ||
model.model_name.toLowerCase().includes('tts') ||
model.model_name.toLowerCase().includes('text-') ||
model.model_name.toLowerCase().includes('babbage') ||
model.model_name.toLowerCase().includes('davinci') ||
model.model_name.toLowerCase().includes('curie') ||
model.model_name.toLowerCase().includes('ada')
},
anthropic: {
label: 'Anthropic',
icon: <Claude.Color />,
filter: (model) => model.model_name.toLowerCase().includes('claude')
},
gemini: {
label: 'Gemini',
icon: <Gemini.Color />,
filter: (model) => model.model_name.toLowerCase().includes('gemini')
},
moonshot: {
label: 'Moonshot',
icon: <Moonshot />,
filter: (model) => model.model_name.toLowerCase().includes('moonshot')
},
zhipu: {
label: t('智谱'),
icon: <Zhipu.Color />,
filter: (model) => model.model_name.toLowerCase().includes('chatglm') ||
model.model_name.toLowerCase().includes('glm-')
},
qwen: {
label: t('通义千问'),
icon: <Qwen.Color />,
filter: (model) => model.model_name.toLowerCase().includes('qwen')
},
deepseek: {
label: 'DeepSeek',
icon: <DeepSeek.Color />,
filter: (model) => model.model_name.toLowerCase().includes('deepseek')
},
minimax: {
label: 'MiniMax',
icon: <Minimax.Color />,
filter: (model) => model.model_name.toLowerCase().includes('abab')
},
baidu: {
label: t('文心一言'),
icon: <Wenxin.Color />,
filter: (model) => model.model_name.toLowerCase().includes('ernie')
},
xunfei: {
label: t('讯飞星火'),
icon: <Spark.Color />,
filter: (model) => model.model_name.toLowerCase().includes('spark')
},
midjourney: {
label: 'Midjourney',
icon: <Midjourney />,
filter: (model) => model.model_name.toLowerCase().includes('mj_')
},
tencent: {
label: t('腾讯混元'),
icon: <Hunyuan.Color />,
filter: (model) => model.model_name.toLowerCase().includes('hunyuan')
},
cohere: {
label: 'Cohere',
icon: <Cohere.Color />,
filter: (model) => model.model_name.toLowerCase().includes('command')
},
cloudflare: {
label: 'Cloudflare',
icon: <Cloudflare.Color />,
filter: (model) => model.model_name.toLowerCase().includes('@cf/')
},
ai360: {
label: t('360智脑'),
icon: <Ai360.Color />,
filter: (model) => model.model_name.toLowerCase().includes('360')
},
yi: {
label: t('零一万物'),
icon: <Yi.Color />,
filter: (model) => model.model_name.toLowerCase().includes('yi')
},
jina: {
label: 'Jina',
icon: <Jina />,
filter: (model) => model.model_name.toLowerCase().includes('jina')
},
mistral: {
label: 'Mistral AI',
icon: <Mistral.Color />,
filter: (model) => model.model_name.toLowerCase().includes('mistral')
},
xai: {
label: 'xAI',
icon: <XAI />,
filter: (model) => model.model_name.toLowerCase().includes('grok')
},
llama: {
label: 'Llama',
icon: <Ollama />,
filter: (model) => model.model_name.toLowerCase().includes('llama')
},
doubao: {
label: t('豆包'),
icon: <Doubao.Color />,
filter: (model) => model.model_name.toLowerCase().includes('doubao')
}
});
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment