import React, {useEffect, useState} from 'react'; import {Label} from 'semantic-ui-react'; import {API, isAdmin, showError, timestamp2string} from '../helpers'; import {Table, Avatar, Tag, Form, Button, Layout, Select} from '@douyinfe/semi-ui'; import {ITEMS_PER_PAGE} from '../constants'; import {renderQuota, stringToColor} from '../helpers/render'; import { IconAt, IconHistogram, IconGift, IconKey, IconUser, IconLayers, IconSetting, IconCreditCard, IconSemiLogo, IconHome, IconMore } from '@douyinfe/semi-icons'; const {Sider, Content, Header} = Layout; function renderTimestamp(timestamp) { return ( <> {timestamp2string(timestamp)} ); } const MODE_OPTIONS = [ {key: 'all', text: '全部用户', value: 'all'}, {key: 'self', text: '当前用户', value: 'self'} ]; const colors = ['amber', 'blue', 'cyan', 'green', 'grey', 'indigo', 'light-blue', 'lime', 'orange', 'pink', 'purple', 'red', 'teal', 'violet', 'yellow' ] function renderType(type) { switch (type) { case 1: return 充值 ; case 2: return 消费 ; case 3: return 管理 ; case 4: return 系统 ; default: return 未知 ; } } const LogsTable = () => { const columns = [ { title: '时间', dataIndex: 'timestamp2string', }, { title: '渠道', dataIndex: 'channel', render: (text, record, index) => { return ( isAdminUser ? logType === 0 || logType === 2 ?
{ {text} }
: <> : <> ); }, }, { title: '用户', dataIndex: 'username', render: (text, record, index) => { return ( isAdminUser ?
{typeof text === 'string' && text.slice(0, 1)} {text}
: <> ); }, }, { title: '令牌', dataIndex: 'token_name', render: (text, record, index) => { return ( logType === 0 || logType === 2 ?
{ {text} }
: <> ); }, }, { title: '类型', dataIndex: 'type', render: (text, record, index) => { return (
{renderType(text)}
); }, }, { title: '模型', dataIndex: 'model_name', render: (text, record, index) => { return ( logType === 0 || logType === 2 ?
{ {text} }
: <> ); }, }, { title: '提示', dataIndex: 'prompt_tokens', render: (text, record, index) => { return ( logType === 0 || logType === 2 ?
{ {text} }
: <> ); }, }, { title: '补全', dataIndex: 'completion_tokens', render: (text, record, index) => { return ( logType === 0 || logType === 2 ?
{ {text} }
: <> ); }, }, { title: '花费', dataIndex: 'quota', render: (text, record, index) => { return ( logType === 0 || logType === 2 ?
{ renderQuota(text, 6) }
: <> ); } }, { title: '详情', dataIndex: 'content', } ]; const [logs, setLogs] = useState([]); const [showStat, setShowStat] = useState(false); const [loading, setLoading] = useState(true); const [activePage, setActivePage] = useState(1); const [logCount, setLogCount] = useState(ITEMS_PER_PAGE); const [searchKeyword, setSearchKeyword] = useState(''); const [searching, setSearching] = useState(false); const [logType, setLogType] = useState(0); const isAdminUser = isAdmin(); let now = new Date(); const [inputs, setInputs] = useState({ username: '', token_name: '', model_name: '', start_timestamp: timestamp2string(0), end_timestamp: timestamp2string(now.getTime() / 1000 + 3600), channel: '' }); const {username, token_name, model_name, start_timestamp, end_timestamp, channel} = inputs; const [stat, setStat] = useState({ quota: 0, token: 0 }); const handleInputChange = (value, name) => { setInputs((inputs) => ({...inputs, [name]: value})); }; const getLogSelfStat = async () => { let localStartTimestamp = Date.parse(start_timestamp) / 1000; let localEndTimestamp = Date.parse(end_timestamp) / 1000; let res = await API.get(`/api/log/self/stat?type=${logType}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`); const {success, message, data} = res.data; if (success) { setStat(data); } else { showError(message); } }; const getLogStat = async () => { let localStartTimestamp = Date.parse(start_timestamp) / 1000; let localEndTimestamp = Date.parse(end_timestamp) / 1000; let res = await API.get(`/api/log/stat?type=${logType}&username=${username}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}&channel=${channel}`); const {success, message, data} = res.data; if (success) { setStat(data); } else { showError(message); } }; const handleEyeClick = async () => { if (!showStat) { if (isAdminUser) { await getLogStat(); } else { await getLogSelfStat(); } } setShowStat(!showStat); }; const setLogsFormat = (logs) => { for (let i = 0; i < logs.length; i++) { logs[i].timestamp2string = timestamp2string(logs[i].created_at); logs[i].key = '' + logs[i].id; } // data.key = '' + data.id setLogs(logs); setLogCount(logs.length + ITEMS_PER_PAGE); console.log(logCount); } const loadLogs = async (startIdx) => { setLoading(true); let url = ''; let localStartTimestamp = Date.parse(start_timestamp) / 1000; let localEndTimestamp = Date.parse(end_timestamp) / 1000; if (isAdminUser) { url = `/api/log/?p=${startIdx}&type=${logType}&username=${username}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}&channel=${channel}`; } else { url = `/api/log/self/?p=${startIdx}&type=${logType}&token_name=${token_name}&model_name=${model_name}&start_timestamp=${localStartTimestamp}&end_timestamp=${localEndTimestamp}`; } const res = await API.get(url); const {success, message, data} = res.data; if (success) { if (startIdx === 0) { setLogsFormat(data); } else { let newLogs = [...logs]; newLogs.splice(startIdx * ITEMS_PER_PAGE, data.length, ...data); setLogsFormat(newLogs); } } else { showError(message); } setLoading(false); }; const pageData = logs.slice((activePage - 1) * ITEMS_PER_PAGE, activePage * ITEMS_PER_PAGE); // const onPaginationChange = (e, { activePage }) => { // (async () => { // if (activePage === Math.ceil(logs.length / ITEMS_PER_PAGE) + 1) { // // In this case we have to load more data and then append them. // await loadLogs(activePage - 1); // } // setActivePage(activePage); // })(); // }; const handlePageChange = page => { setActivePage(page); if (page === Math.ceil(logs.length / ITEMS_PER_PAGE) + 1) { // In this case we have to load more data and then append them. loadLogs(page - 1).then(r => { }); } // setLoading(false); }; const refresh = async () => { // setLoading(true); setActivePage(1); await loadLogs(0); }; useEffect(() => { refresh().then(); }, [logType]); const searchLogs = async () => { if (searchKeyword === '') { // if keyword is blank, load files instead. await loadLogs(0); setActivePage(1); return; } setSearching(true); const res = await API.get(`/api/log/self/search?keyword=${searchKeyword}`); const {success, message, data} = res.data; if (success) { setLogs(data); setActivePage(1); } else { showError(message); } setSearching(false); }; const handleKeywordChange = async (e, {value}) => { setSearchKeyword(value.trim()); }; const sortLog = (key) => { if (logs.length === 0) return; setLoading(true); let sortedLogs = [...logs]; if (typeof sortedLogs[0][key] === 'string') { sortedLogs.sort((a, b) => { return ('' + a[key]).localeCompare(b[key]); }); } else { sortedLogs.sort((a, b) => { if (a[key] === b[key]) return 0; if (a[key] > b[key]) return -1; if (a[key] < b[key]) return 1; }); } if (sortedLogs[0].id === logs[0].id) { sortedLogs.reverse(); } setLogs(sortedLogs); setLoading(false); }; return ( <>

使用明细(总消耗额度: {showStat && renderQuota(stat.quota)} {!showStat && 点击查看} )

<> handleInputChange(value, 'token_name')}/> handlePageChange(value, 'model_name')}/> handleInputChange(value, 'start_timestamp')}/> handleInputChange(value, 'end_timestamp')}/> {/*查询*/} { isAdminUser && <> handleInputChange(value, 'channel')}/> handleInputChange(value, 'username')}/> } ); }; export default LogsTable;