diff --git a/web/default/src/components/LogsTable.js b/web/default/src/components/LogsTable.js index 39bafc2e..1f528676 100644 --- a/web/default/src/components/LogsTable.js +++ b/web/default/src/components/LogsTable.js @@ -9,13 +9,34 @@ import { Select, Table, } from 'semantic-ui-react'; -import { API, isAdmin, showError, timestamp2string } from '../helpers'; +import { + API, + copy, + isAdmin, + showError, + showSuccess, + showWarning, + timestamp2string, +} from '../helpers'; import { ITEMS_PER_PAGE } from '../constants'; -import { renderQuota } from '../helpers/render'; +import { renderColorLabel, renderQuota } from '../helpers/render'; -function renderTimestamp(timestamp) { - return <>{timestamp2string(timestamp)}; +function renderTimestamp(timestamp, request_id) { + return ( + { + if (await copy(request_id)) { + showSuccess(`已复制请求 ID:${request_id}`); + } else { + showWarning(`请求 ID 复制失败:${request_id}`); + } + }} + style={{ cursor: 'pointer' }} + > + {timestamp2string(timestamp)} + + ); } const MODE_OPTIONS = [ @@ -103,8 +124,6 @@ function renderDetail(log) { )} -
- {log.request_id} ); } @@ -467,7 +486,9 @@ const LogsTable = () => { if (log.deleted) return <>; return ( - {renderTimestamp(log.created_at)} + + {renderTimestamp(log.created_at, log.request_id)} + {isAdminUser && ( {log.channel ? : ''} @@ -475,23 +496,21 @@ const LogsTable = () => { )} {isAdminUser && ( - {log.username ? : ''} + {log.username ? ( + + ) : ( + '' + )} )} - {log.token_name ? ( - - ) : ( - '' - )} + {log.token_name ? renderColorLabel(log.token_name) : ''} {renderType(log.type)} - {log.model_name ? ( - - ) : ( - '' - )} + {log.model_name ? renderColorLabel(log.model_name) : ''} {log.prompt_tokens ? log.prompt_tokens : ''} diff --git a/web/default/src/helpers/render.js b/web/default/src/helpers/render.js index a9c81cc1..b622f8a6 100644 --- a/web/default/src/helpers/render.js +++ b/web/default/src/helpers/render.js @@ -13,16 +13,18 @@ export function renderGroup(group) { } let groups = group.split(','); groups.sort(); - return <> - {groups.map((group) => { - if (group === 'vip' || group === 'pro') { - return ; - } else if (group === 'svip' || group === 'premium') { - return ; - } - return ; - })} - ; + return ( + <> + {groups.map((group) => { + if (group === 'vip' || group === 'pro') { + return ; + } else if (group === 'svip' || group === 'premium') { + return ; + } + return ; + })} + + ); } export function renderNumber(num) { @@ -55,4 +57,33 @@ export function renderQuotaWithPrompt(quota, digits) { return `(等价金额:${renderQuota(quota, digits)})`; } return ''; -} \ No newline at end of file +} + +const colors = [ + 'red', + 'orange', + 'yellow', + 'olive', + 'green', + 'teal', + 'blue', + 'violet', + 'purple', + 'pink', + 'brown', + 'grey', + 'black', +]; + +export function renderColorLabel(text) { + let hash = 0; + for (let i = 0; i < text.length; i++) { + hash = text.charCodeAt(i) + ((hash << 5) - hash); + } + let index = Math.abs(hash % colors.length); + return ( + + ); +}