Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 69 additions & 60 deletions web/src/components/table/usage-logs/UsageLogsColumnDefs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ For commercial licensing, please contact support@quantumnous.com
import React from 'react';
import {
Avatar,
Button,
Space,
Tag,
Tooltip,
Popover,
Typography,
Button
} from '@douyinfe/semi-ui';
import {
timestamp2string,
Expand All @@ -41,8 +41,8 @@ import {
renderClaudeModelPrice,
renderModelPrice,
} from '../../../helpers';
import { IconHelpCircle, IconStarStroked } from '@douyinfe/semi-icons';
import { Route } from 'lucide-react';
import { IconHelpCircle } from '@douyinfe/semi-icons';
import { Route, Sparkles } from 'lucide-react';

const colors = [
'amber',
Expand Down Expand Up @@ -307,28 +307,81 @@ export const getLogsColumns = ({
render: (text, record, index) => {
let isMultiKey = false;
let multiKeyIndex = -1;
let content = t('渠道') + `:${record.channel}`;
let affinity = null;
let showMarker = false;
let other = getLogOther(record.other);
if (other?.admin_info) {
let adminInfo = other.admin_info;
if (adminInfo?.is_multi_key) {
isMultiKey = true;
multiKeyIndex = adminInfo.multi_key_index;
}
if (
Array.isArray(adminInfo.use_channel) &&
adminInfo.use_channel.length > 0
) {
content = t('渠道') + `:${adminInfo.use_channel.join('->')}`;
}
if (adminInfo.channel_affinity) {
affinity = adminInfo.channel_affinity;
showMarker = true;
}
}

return isAdminUser &&
(record.type === 0 || record.type === 2 || record.type === 5) ? (
<Space>
<Tooltip content={record.channel_name || t('未知渠道')}>
<span>
<Tag
color={colors[parseInt(text) % colors.length]}
shape='circle'
<span style={{ position: 'relative', display: 'inline-block' }}>
<Tooltip content={record.channel_name || t('未知渠道')}>
<span>
<Tag
color={colors[parseInt(text) % colors.length]}
shape='circle'
>
{text}
</Tag>
</span>
</Tooltip>
{showMarker && (
<Tooltip
content={
<div style={{ lineHeight: 1.6 }}>
<div>{content}</div>
{affinity ? (
<div style={{ marginTop: 6 }}>
{buildChannelAffinityTooltip(affinity, t)}
</div>
) : null}
</div>
}
>
{text}
</Tag>
</span>
</Tooltip>
<span
style={{
position: 'absolute',
right: -4,
top: -4,
lineHeight: 1,
fontWeight: 600,
color: '#f59e0b',
cursor: 'pointer',
userSelect: 'none',
}}
onClick={(e) => {
e.stopPropagation();
openChannelAffinityUsageCacheModal?.(affinity);
}}
>
<Sparkles
size={14}
strokeWidth={2}
color='currentColor'
fill='currentColor'
/>
</span>
</Tooltip>
)}
</span>
{isMultiKey && (
<Tag color='white' shape='circle'>
{multiKeyIndex}
Expand Down Expand Up @@ -559,68 +612,24 @@ export const getLogsColumns = ({
return <></>;
}
let content = t('渠道') + `:${record.channel}`;
let affinity = null;
if (record.other !== '') {
let other = JSON.parse(record.other);
if (other === null) {
return <></>;
}
if (other.admin_info !== undefined) {
if (
other.admin_info.use_channel !== null &&
other.admin_info.use_channel !== undefined &&
other.admin_info.use_channel !== ''
other.admin_info.use_channel !== null &&
other.admin_info.use_channel !== undefined &&
other.admin_info.use_channel !== ''
) {
let useChannel = other.admin_info.use_channel;
let useChannelStr = useChannel.join('->');
content = t('渠道') + `:${useChannelStr}`;
Comment on lines 620 to 628

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent use_channel validation — .join() will throw on non-array values.

The channel column (line 321) now properly guards with Array.isArray(adminInfo.use_channel) && adminInfo.use_channel.length > 0, but this retry column still uses loose truthy checks. If use_channel is a non-array truthy value (e.g., a string), calling .join('->') on line 627 will throw a TypeError at runtime.

Proposed fix: align with channel column's validation
          if (
-                other.admin_info.use_channel !== null &&
-                other.admin_info.use_channel !== undefined &&
-                other.admin_info.use_channel !== ''
+                Array.isArray(other.admin_info.use_channel) &&
+                other.admin_info.use_channel.length > 0
           ) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (other.admin_info !== undefined) {
if (
other.admin_info.use_channel !== null &&
other.admin_info.use_channel !== undefined &&
other.admin_info.use_channel !== ''
other.admin_info.use_channel !== null &&
other.admin_info.use_channel !== undefined &&
other.admin_info.use_channel !== ''
) {
let useChannel = other.admin_info.use_channel;
let useChannelStr = useChannel.join('->');
content = t('渠道') + `:${useChannelStr}`;
if (other.admin_info !== undefined) {
if (
Array.isArray(other.admin_info.use_channel) &&
other.admin_info.use_channel.length > 0
) {
let useChannel = other.admin_info.use_channel;
let useChannelStr = useChannel.join('->');
content = t('渠道') + `:${useChannelStr}`;
🤖 Prompt for AI Agents
In `@web/src/components/table/usage-logs/UsageLogsColumnDefs.jsx` around lines 620
- 628, The retry-column logic uses other.admin_info.use_channel without ensuring
it's an array, so calling .join('->') on non-arrays will throw; update the block
that constructs useChannelStr (in UsageLogsColumnDefs.jsx where
other.admin_info/use_channel is referenced) to first check
Array.isArray(other.admin_info.use_channel) &&
other.admin_info.use_channel.length > 0 before calling .join, and fall back to
treating a string value as-is (or skip/empty) when use_channel is a non-array
truthy value; ensure the variable names referenced (useChannel, useChannelStr,
content) are adapted accordingly.

}
if (other.admin_info.channel_affinity) {
affinity = other.admin_info.channel_affinity;
}
}
}
return isAdminUser ? (
<Space>
<div>{content}</div>
{affinity ? (
<Tooltip
content={
<div>
{buildChannelAffinityTooltip(affinity, t)}
<div style={{ marginTop: 6 }}>
<Button
theme='borderless'
size='small'
onClick={(e) => {
e.stopPropagation();
openChannelAffinityUsageCacheModal?.(affinity);
}}
>
{t('查看详情')}
</Button>
</div>
</div>
}
>
<span>
<Tag
className='channel-affinity-tag'
color='cyan'
shape='circle'
>
<span className='channel-affinity-tag-content'>
<IconStarStroked style={{ fontSize: 13 }} />
{t('优选')}
</span>
</Tag>
</span>
</Tooltip>
) : null}
</Space>
) : (
<></>
);
return isAdminUser ? <div>{content}</div> : <></>;
},
},
{
Expand Down