diff --git a/web/src/components/LogsTable.js b/web/src/components/LogsTable.js index 6cf7e844..985af15d 100644 --- a/web/src/components/LogsTable.js +++ b/web/src/components/LogsTable.js @@ -14,8 +14,6 @@ import { Avatar, Button, Descriptions, - Form, - Layout, Modal, Popover, Select, @@ -25,6 +23,11 @@ import { Tag, Tooltip, Checkbox, + Card, + Typography, + Divider, + Input, + DatePicker, } from '@douyinfe/semi-ui'; import { ITEMS_PER_PAGE } from '../constants'; import { @@ -43,9 +46,14 @@ import { import Paragraph from '@douyinfe/semi-ui/lib/es/typography/paragraph'; import { getLogOther } from '../helpers/other.js'; import { StyleContext } from '../context/Style/index.js'; -import { IconInherit, IconRefresh, IconSetting } from '@douyinfe/semi-icons'; +import { + IconRefresh, + IconSetting, + IconEyeOpened, + IconSearch, +} from '@douyinfe/semi-icons'; -const { Header } = Layout; +const { Text } = Typography; function renderTimestamp(timestamp) { return <>{timestamp2string(timestamp)}; @@ -81,37 +89,37 @@ const LogsTable = () => { switch (type) { case 1: return ( - + {t('充值')} ); case 2: return ( - + {t('消费')} ); case 3: return ( - + {t('管理')} ); case 4: return ( - + {t('系统')} ); case 5: return ( - + {t('错误')} ); default: return ( - + {t('未知')} ); @@ -121,13 +129,13 @@ const LogsTable = () => { function renderIsStream(bool) { if (bool) { return ( - + {t('流')} ); } else { return ( - + {t('非流')} ); @@ -138,21 +146,21 @@ const LogsTable = () => { const time = parseInt(type); if (time < 101) { return ( - + {' '} {time} s{' '} ); } else if (time < 300) { return ( - + {' '} {time} s{' '} ); } else { return ( - + {' '} {time} s{' '} @@ -165,21 +173,21 @@ const LogsTable = () => { time = time.toFixed(1); if (time < 3) { return ( - + {' '} {time} s{' '} ); } else if (time < 10) { return ( - + {' '} {time} s{' '} ); } else { return ( - + {' '} {time} s{' '} @@ -198,8 +206,9 @@ const LogsTable = () => { { - copyText(event, record.model_name).then((r) => {}); + copyText(event, record.model_name).then((r) => { }); }} > {' '} @@ -217,8 +226,9 @@ const LogsTable = () => { { - copyText(event, record.model_name).then((r) => {}); + copyText(event, record.model_name).then((r) => { }); }} > {t('请求并计费模型')} {record.model_name}{' '} @@ -226,9 +236,10 @@ const LogsTable = () => { { copyText(event, other.upstream_model_name).then( - (r) => {}, + (r) => { }, ); }} > @@ -241,8 +252,9 @@ const LogsTable = () => { { - copyText(event, record.model_name).then((r) => {}); + copyText(event, record.model_name).then((r) => { }); }} suffixIcon={ { {record.model_name}{' '} - {/**/} - {/* {*/} - {/* copyText(event, other.upstream_model_name).then(r => {});*/} - {/* }}*/} - {/* >*/} - {/* {' '}{other.upstream_model_name}{' '}*/} - {/* */} - {/**/} ); @@ -386,6 +387,7 @@ const LogsTable = () => { {' '} {text}{' '} @@ -437,6 +439,7 @@ const LogsTable = () => { { //cancel the row click event copyText(event, text); @@ -620,21 +623,21 @@ const LogsTable = () => { } let content = other?.claude ? renderClaudeModelPriceSimple( - other.model_ratio, - other.model_price, - other.group_ratio, - other.cache_tokens || 0, - other.cache_ratio || 1.0, - other.cache_creation_tokens || 0, - other.cache_creation_ratio || 1.0, - ) + other.model_ratio, + other.model_price, + other.group_ratio, + other.cache_tokens || 0, + other.cache_ratio || 1.0, + other.cache_creation_tokens || 0, + other.cache_creation_ratio || 1.0, + ) : renderModelPriceSimple( - other.model_ratio, - other.model_price, - other.group_ratio, - other.cache_tokens || 0, - other.cache_ratio || 1.0, - ); + other.model_ratio, + other.model_price, + other.group_ratio, + other.cache_tokens || 0, + other.cache_ratio || 1.0, + ); return ( { visible={showColumnSelector} onCancel={() => setShowColumnSelector(false)} footer={ - <> - - + - - + } >
@@ -697,15 +714,7 @@ const LogsTable = () => {
{allColumns.map((column) => { // Skip admin-only columns for non-admin users @@ -721,7 +730,7 @@ const LogsTable = () => { return (
{ key: t('日志详情'), value: other?.claude ? renderClaudeLogContent( - other?.model_ratio, - other.completion_ratio, - other.model_price, - other.group_ratio, - other.cache_ratio || 1.0, - other.cache_creation_ratio || 1.0, - ) + other?.model_ratio, + other.completion_ratio, + other.model_price, + other.group_ratio, + other.cache_ratio || 1.0, + other.cache_creation_ratio || 1.0, + ) : renderLogContent( - other?.model_ratio, - other.completion_ratio, - other.model_price, - other.group_ratio, - other?.user_group_ratio, - false, - 1.0, - undefined, - other.web_search || false, - other.web_search_call_count || 0, - other.file_search || false, - other.file_search_call_count || 0, - ), + other?.model_ratio, + other.completion_ratio, + other.model_price, + other.group_ratio, + other?.user_group_ratio, + false, + 1.0, + undefined, + other.web_search || false, + other.web_search_call_count || 0, + other.file_search || false, + other.file_search_call_count || 0, + ), }); } if (logs[i].type === 2) { @@ -1056,7 +1065,7 @@ const LogsTable = () => { const handlePageChange = (page) => { setActivePage(page); - loadLogs(page, pageSize, logType).then((r) => {}); + loadLogs(page, pageSize, logType).then((r) => { }); }; const handlePageSizeChange = async (size) => { @@ -1104,86 +1113,56 @@ const LogsTable = () => { return ( <> {renderColumnSelector()} - -
- - - - {t('消耗额度')}: {renderQuota(stat.quota)} - - - RPM: {stat.rpm} - - - TPM: {stat.tpm} - - - -
-
- <> - -
- {styleState.isMobile ? ( -
- { - console.log(value); - handleInputChange(value, 'start_timestamp'); - }} - /> - - handleInputChange(value, 'end_timestamp') - } - /> + +
+
+ + {t('日志记录帮助您了解使用情况和排查问题')} +
+ + +
+
+ 💰 +
+ {t('消耗额度')} +
{renderQuota(stat.quota)}
+
- ) : ( - + 📊 +
+ RPM +
{stat.rpm || 0}
+
+
+ +
+ +
+ TPM +
{stat.tpm || 0}
+
+
+
+ +
+ + + + {/* 搜索表单区域 */} +
+
+ {/* 时间选择器 */} +
+ { if (Array.isArray(value) && value.length === 2) { handleInputChange(value[0], 'start_timestamp'); @@ -1191,100 +1170,113 @@ const LogsTable = () => { } }} /> +
+ + {/* 日志类型选择器 */} + + + {/* 其他搜索字段 */} + } + placeholder={t('令牌名称')} + value={token_name} + onChange={(value) => handleInputChange(value, 'token_name')} + className="!rounded-full" + showClear + /> + + } + placeholder={t('模型名称')} + value={model_name} + onChange={(value) => handleInputChange(value, 'model_name')} + className="!rounded-full" + showClear + /> + + } + placeholder={t('分组')} + value={group} + onChange={(value) => handleInputChange(value, 'group')} + className="!rounded-full" + showClear + /> + + {isAdminUser && ( + <> + } + placeholder={t('渠道 ID')} + value={channel} + onChange={(value) => handleInputChange(value, 'channel')} + className="!rounded-full" + showClear + /> + } + placeholder={t('用户名称')} + value={username} + onChange={(value) => handleInputChange(value, 'username')} + className="!rounded-full" + showClear + /> + )}
- - handleInputChange(value, 'token_name')} - /> - handleInputChange(value, 'model_name')} - /> - handleInputChange(value, 'group')} - /> - {isAdminUser && ( - <> - handleInputChange(value, 'channel')} - /> - handleInputChange(value, 'username')} - /> - - )} - - - - -
- - -
+ + {/* 操作按钮区域 */} +
+
+
+ + +
+
+
+
+ } + shadows='hover' + > t('第 {{start}} - {{end}} 条,共 {{total}} 条', { @@ -1295,7 +1287,7 @@ const LogsTable = () => { currentPage: activePage, pageSize: pageSize, total: logCount, - pageSizeOpts: [10, 20, 50, 100], + pageSizeOptions: [10, 20, 50, 100], showSizeChanger: true, onPageSizeChange: (size) => { handlePageSizeChange(size); @@ -1303,7 +1295,7 @@ const LogsTable = () => { onPageChange: handlePageChange, }} /> - + ); }; diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index f95ec340..aff937c7 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -170,6 +170,7 @@ "充值": "Recharge", "用户": "Users", "日志": "Logs", + "日志记录帮助您了解使用情况和排查问题": "Log records help you understand usage and troubleshoot issues", "设置": "Settings", "关于": "About", "价格": "Pricing", diff --git a/web/src/index.css b/web/src/index.css index d6e6726c..87cc62e7 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -329,3 +329,7 @@ code { /* -moz-box-shadow: 0 1px 6px rgba(0, 0, 0, 0.08) !important;*/ /* min-height: 100%;*/ /*}*/ + +.semi-datepicker-range-input { + border-radius: 9999px; +}