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;