fix: polish parameter preprocessing details
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState, type FormEvent, type ReactNode } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState, type FormEvent, type ReactNode } from 'react';
|
||||
import { Popover as AntPopover } from 'antd';
|
||||
import { ChevronLeft, ChevronRight, Copy, CreditCard, Eye, KeyRound, ListChecks, Plus, ReceiptText, RotateCcw, Search, ShieldCheck, SlidersHorizontal, Trash2, UserRound } from 'lucide-react';
|
||||
import type { GatewayAccessRuleBatchRequest, GatewayApiKey, GatewayTask, GatewayTaskParamPreprocessingLog, GatewayWalletAccount, GatewayWalletTransaction, IntegrationPlatform, PlatformModel } from '@easyai-ai-gateway/contracts';
|
||||
@@ -838,27 +838,46 @@ function TaskParamConversionCell(props: { task: GatewayTask; token: string }) {
|
||||
const [logs, setLogs] = useState<GatewayTaskParamPreprocessingLog[] | null>(null);
|
||||
const [loadState, setLoadState] = useState<'idle' | 'loading' | 'ready' | 'error'>('idle');
|
||||
const [error, setError] = useState('');
|
||||
const logsRef = useRef<GatewayTaskParamPreprocessingLog[] | null>(null);
|
||||
const loadingRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !summary.changed || logs || loadState === 'loading' || !props.token) return;
|
||||
logsRef.current = null;
|
||||
loadingRef.current = false;
|
||||
setLogs(null);
|
||||
setLoadState('idle');
|
||||
setError('');
|
||||
}, [props.task.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !summary.changed || logsRef.current || loadingRef.current || !props.token) return;
|
||||
let cancelled = false;
|
||||
loadingRef.current = true;
|
||||
setLoadState('loading');
|
||||
setError('');
|
||||
listTaskParamPreprocessing(props.token, props.task.id)
|
||||
.then((response) => {
|
||||
if (cancelled) return;
|
||||
setLogs(response.items ?? []);
|
||||
const items = response.items ?? [];
|
||||
logsRef.current = items;
|
||||
setLogs(items);
|
||||
setLoadState('ready');
|
||||
})
|
||||
.catch((err) => {
|
||||
if (cancelled) return;
|
||||
setError(err instanceof Error ? err.message : '参数转换明细加载失败');
|
||||
setLoadState('error');
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) {
|
||||
loadingRef.current = false;
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
loadingRef.current = false;
|
||||
};
|
||||
}, [loadState, logs, open, props.task.id, props.token, summary.changed]);
|
||||
}, [open, props.task.id, props.token, summary.changed]);
|
||||
|
||||
if (!summary.changed) {
|
||||
return <span className="taskParamConversionEmpty">无转换</span>;
|
||||
@@ -900,8 +919,11 @@ function TaskParamConversionPopover(props: {
|
||||
{logs.map((log) => (
|
||||
<span key={log.id} className="taskParamConversionLog">
|
||||
<span className="taskParamConversionLogHeader">
|
||||
<strong>{taskParamLogTitle(log)}</strong>
|
||||
<Badge variant={log.changed ? 'secondary' : 'outline'}>{log.changeCount} 项</Badge>
|
||||
<span className="taskParamConversionLogTitleBlock">
|
||||
<strong>{taskParamLogTitle(log)}</strong>
|
||||
<small title={log.clientId || undefined}>{taskParamLogSubtitle(log)}</small>
|
||||
</span>
|
||||
<Badge className="taskParamConversionCountBadge" variant={log.changed ? 'secondary' : 'outline'}>{log.changeCount} 项</Badge>
|
||||
</span>
|
||||
{(log.changes ?? []).slice(0, 8).map((change, index) => (
|
||||
<span key={`${log.id}-change-${index}`} className="taskParamConversionChange">
|
||||
@@ -1116,9 +1138,16 @@ function taskParamConversionSummary(task: GatewayTask): TaskParamConversionSumma
|
||||
paths: [],
|
||||
capabilityPaths: [],
|
||||
};
|
||||
mergeTaskParamSummary(summary, metadataObject(task.metrics, 'parameterPreprocessingSummary'));
|
||||
let mergedAttemptSummary = false;
|
||||
for (const attempt of task.attempts ?? []) {
|
||||
mergeTaskParamSummary(summary, metadataObject(attempt.metrics, 'parameterPreprocessingSummary'));
|
||||
const attemptSummary = metadataObject(attempt.metrics, 'parameterPreprocessingSummary');
|
||||
if (Object.keys(attemptSummary).length) {
|
||||
mergedAttemptSummary = true;
|
||||
mergeTaskParamSummary(summary, attemptSummary);
|
||||
}
|
||||
}
|
||||
if (!mergedAttemptSummary) {
|
||||
mergeTaskParamSummary(summary, metadataObject(task.metrics, 'parameterPreprocessingSummary'));
|
||||
}
|
||||
return summary;
|
||||
}
|
||||
@@ -1147,11 +1176,30 @@ function taskParamLogTitle(log: GatewayTaskParamPreprocessingLog) {
|
||||
const parts = [
|
||||
log.attemptNo ? `#${log.attemptNo}` : '',
|
||||
log.modelType || '',
|
||||
log.clientId || '',
|
||||
].filter(Boolean);
|
||||
return parts.join(' · ') || '预处理记录';
|
||||
}
|
||||
|
||||
function taskParamLogSubtitle(log: GatewayTaskParamPreprocessingLog) {
|
||||
const model = log.model ?? {};
|
||||
const modelLabel = firstNonEmptyText(
|
||||
objectString(model, 'modelAlias'),
|
||||
objectString(model, 'providerModelName'),
|
||||
objectString(model, 'modelName'),
|
||||
);
|
||||
const provider = objectString(model, 'provider');
|
||||
const parts = [
|
||||
provider,
|
||||
modelLabel,
|
||||
].filter(Boolean);
|
||||
if (parts.length) return parts.join(' · ');
|
||||
return log.clientId || '候选模型';
|
||||
}
|
||||
|
||||
function firstNonEmptyText(...values: string[]) {
|
||||
return values.find((value) => value.trim()) ?? '';
|
||||
}
|
||||
|
||||
function taskParamActionLabel(action: string) {
|
||||
if (action === 'remove') return '移除';
|
||||
if (action === 'adjust') return '调整';
|
||||
|
||||
@@ -521,6 +521,36 @@ strong {
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.taskParamConversionLogHeader {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.taskParamConversionLogTitleBlock {
|
||||
display: grid;
|
||||
min-width: 0;
|
||||
gap: 0.15rem;
|
||||
}
|
||||
|
||||
.taskParamConversionLogTitleBlock strong {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.taskParamConversionLogTitleBlock small {
|
||||
max-width: 32rem;
|
||||
overflow: hidden;
|
||||
color: var(--text-soft);
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--font-size-xs);
|
||||
line-height: 1.35;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.taskParamConversionCountBadge {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.taskParamConversionChange {
|
||||
display: grid;
|
||||
gap: 0.28rem;
|
||||
|
||||
Reference in New Issue
Block a user