feat: enrich task record details
This commit is contained in:
@@ -2,7 +2,6 @@ import type { FormEvent, ReactNode } from 'react';
|
||||
import { CreditCard, KeyRound, ListChecks, UserRound } from 'lucide-react';
|
||||
import type { ConsoleData } from '../app-state';
|
||||
import { EntityTable } from '../components/EntityTable';
|
||||
import { PageHeader } from '../components/PageHeader';
|
||||
import { Badge, Button, Card, CardContent, CardHeader, CardTitle, Input, Label, Tabs } from '../components/ui';
|
||||
import type { ApiKeyForm, LoadState, WorkspaceSection } from '../types';
|
||||
|
||||
@@ -22,10 +21,10 @@ export function WorkspacePage(props: {
|
||||
onApiKeyFormChange: (value: ApiKeyForm) => void;
|
||||
onSectionChange: (value: WorkspaceSection) => void;
|
||||
onSubmitApiKey: (event: FormEvent<HTMLFormElement>) => void;
|
||||
onUseApiKeyForPlayground: (apiKeyId?: string) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="pageStack">
|
||||
<PageHeader eyebrow="Workspace" title="用户工作台" description="个人资产、API Key 和任务记录。" />
|
||||
<div className="subPageLayout">
|
||||
<Tabs className="sideTabs" value={props.section} tabs={tabs} onValueChange={props.onSectionChange} />
|
||||
<div className="subPageContent">
|
||||
@@ -106,7 +105,9 @@ function ApiKeyPanel(props: {
|
||||
state: LoadState;
|
||||
onApiKeyFormChange: (value: ApiKeyForm) => void;
|
||||
onSubmitApiKey: (event: FormEvent<HTMLFormElement>) => void;
|
||||
onUseApiKeyForPlayground: (apiKeyId?: string) => void;
|
||||
}) {
|
||||
const latestUsableKey = props.apiKeySecret ? props.data.apiKeys[0] : undefined;
|
||||
return (
|
||||
<section className="contentGrid two">
|
||||
<Card>
|
||||
@@ -123,7 +124,14 @@ function ApiKeyPanel(props: {
|
||||
<KeyRound size={15} />
|
||||
创建
|
||||
</Button>
|
||||
{props.apiKeySecret && <code className="secretBox">{props.apiKeySecret}</code>}
|
||||
{props.apiKeySecret && (
|
||||
<div className="createdApiKeyBox">
|
||||
<code className="secretBox">{props.apiKeySecret}</code>
|
||||
<Button type="button" variant="secondary" onClick={() => props.onUseApiKeyForPlayground(latestUsableKey?.id)}>
|
||||
使用测试
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@@ -145,6 +153,9 @@ function ApiKeyPanel(props: {
|
||||
|
||||
function TaskPanel(props: { data: ConsoleData }) {
|
||||
const task = props.data.taskResult;
|
||||
const usage = task?.usage ?? {};
|
||||
const tokenText = usage.totalTokens ? `${usage.totalTokens}` : '-';
|
||||
const chargeText = task?.finalChargeAmount ? `${task.finalChargeAmount}` : '-';
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@@ -156,7 +167,15 @@ function TaskPanel(props: { data: ConsoleData }) {
|
||||
<Badge variant={task.status === 'succeeded' ? 'success' : 'secondary'}>{task.status}</Badge>
|
||||
<strong>{task.kind}</strong>
|
||||
<span>{task.model}</span>
|
||||
<pre>{JSON.stringify(task.result ?? {}, null, 2)}</pre>
|
||||
<div className="infoGrid compact">
|
||||
<InfoItem label="API Key" value={task.apiKeyName || task.apiKeyId || '-'} />
|
||||
<InfoItem label="RequestID" value={task.requestId || '-'} />
|
||||
<InfoItem label="实际模型" value={task.resolvedModel || task.model} />
|
||||
<InfoItem label="Token" value={tokenText} />
|
||||
<InfoItem label="扣费" value={chargeText} />
|
||||
<InfoItem label="响应耗时" value={task.responseDurationMs ? `${task.responseDurationMs}ms` : '-'} />
|
||||
</div>
|
||||
<pre>{JSON.stringify({ result: task.result, usage: task.usage, billings: task.billings, billingSummary: task.billingSummary, metrics: task.metrics }, null, 2)}</pre>
|
||||
</div>
|
||||
) : (
|
||||
<div className="emptyState">
|
||||
|
||||
@@ -407,6 +407,16 @@ strong {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.infoGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.infoGrid.compact .infoItem {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.spanTwo {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user