production runtime and mock removal
This commit is contained in:
1 parent
2ef3da7af5
commit
6480e503eb
55 files changed
+581
-540
No files matched your search
@@ -52,6 +52,7 @@ export function AssetManager({ initialView = "assets", initialTaskId }: AssetMan
|
||||
}
|
||||
return map;
|
||||
}, [jobs]);
|
||||
const outputAssetIds = useMemo(() => new Set(assets.map((asset) => asset.id)), [assets]);
|
||||
|
||||
const visibleAssets = pageItems(assets, assetPage, ASSET_PAGE_SIZE);
|
||||
const visibleJobs = pageItems(jobs, jobPage, TASK_PAGE_SIZE);
|
||||
@@ -262,10 +263,10 @@ export function AssetManager({ initialView = "assets", initialTaskId }: AssetMan
|
||||
<div className="job-summary">
|
||||
<h3>{job.prompt?.slice(0, 90) || capabilityLabel(job.capability)}</h3>
|
||||
<p className="muted">{capabilityLabel(job.capability)} / {job.reqKey}</p>
|
||||
<p className="muted compact-hint">{durationLabel(job, durationNow)} / 输入 {job.inputAssetIds.length || job.inputUrls.length} 个,输出 {job.outputAssetIds.length} 个 / {billingLabel(job)}</p>
|
||||
<p className="muted compact-hint">{durationLabel(job, durationNow)} / 输入 {job.inputAssetIds.length || job.inputUrls.length} 个,输出 {resolvedOutputCount(job, outputAssetIds)} 个 / {billingLabel(job)}</p>
|
||||
</div>
|
||||
<div className="toolbar job-actions">
|
||||
<span className={`status ${job.status}`}>{statusLabel(job.status)}</span>
|
||||
<span className={`status ${taskStatusClass(job, outputAssetIds)}`}>{statusLabel(job.status, hasResolvedOutput(job, outputAssetIds))}</span>
|
||||
<button className="button mini-button" type="button" aria-expanded={expandedJobId === job.id} onClick={() => setExpandedJobId(expandedJobId === job.id ? null : job.id)}>
|
||||
<Info size={15} />
|
||||
{expandedJobId === job.id ? "收起" : "详情"}
|
||||
@@ -278,7 +279,7 @@ export function AssetManager({ initialView = "assets", initialTaskId }: AssetMan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{expandedJobId === job.id ? <JobDetails job={job} now={durationNow} /> : null}
|
||||
{expandedJobId === job.id ? <JobDetails job={job} now={durationNow} outputAssetIds={outputAssetIds} /> : null}
|
||||
</article>
|
||||
))}
|
||||
{!jobs.length ? <div className="callout">暂无生成任务。提交图片或视频生成后会保留任务历史。</div> : null}
|
||||
@@ -314,13 +315,13 @@ export function AssetManager({ initialView = "assets", initialTaskId }: AssetMan
|
||||
);
|
||||
}
|
||||
|
||||
function JobDetails({ job, now }: { job: GenerationJob; now: number }) {
|
||||
function JobDetails({ job, now, outputAssetIds }: { job: GenerationJob; now: number; outputAssetIds: Set<string> }) {
|
||||
return (
|
||||
<div className="job-detail-panel">
|
||||
<dl className="job-detail-grid">
|
||||
<div>
|
||||
<dt>状态</dt>
|
||||
<dd><span className={`status ${job.status}`}>{statusLabel(job.status)}</span></dd>
|
||||
<dd><span className={`status ${taskStatusClass(job, outputAssetIds)}`}>{statusLabel(job.status, hasResolvedOutput(job, outputAssetIds))}</span></dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>耗时</dt>
|
||||
@@ -352,7 +353,7 @@ function JobDetails({ job, now }: { job: GenerationJob; now: number }) {
|
||||
</div>
|
||||
<div>
|
||||
<dt>输入/输出</dt>
|
||||
<dd>{job.inputAssetIds.length || job.inputUrls.length} / {job.outputAssetIds.length}</dd>
|
||||
<dd>{job.inputAssetIds.length || job.inputUrls.length} / {resolvedOutputCount(job, outputAssetIds)}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>扣费</dt>
|
||||
@@ -456,10 +457,22 @@ function sourceLabel(source: Asset["source"]) {
|
||||
return "外部";
|
||||
}
|
||||
|
||||
function statusLabel(status: GenerationJob["status"]) {
|
||||
function hasResolvedOutput(job: GenerationJob, outputAssetIds: Set<string>) {
|
||||
return job.outputAssetIds.some((assetId) => outputAssetIds.has(assetId));
|
||||
}
|
||||
|
||||
function resolvedOutputCount(job: GenerationJob, outputAssetIds: Set<string>) {
|
||||
return job.outputAssetIds.filter((assetId) => outputAssetIds.has(assetId)).length;
|
||||
}
|
||||
|
||||
function taskStatusClass(job: GenerationJob, outputAssetIds: Set<string>) {
|
||||
return job.status === "succeeded" && !hasResolvedOutput(job, outputAssetIds) ? "syncing" : job.status;
|
||||
}
|
||||
|
||||
function statusLabel(status: GenerationJob["status"], hasOutput = true) {
|
||||
if (status === "queued") return "排队中";
|
||||
if (status === "running") return "生成中";
|
||||
if (status === "succeeded") return "已完成";
|
||||
if (status === "succeeded") return hasOutput ? "已完成" : "结果同步中";
|
||||
if (status === "failed") return "失败";
|
||||
if (status === "expired") return "已过期";
|
||||
if (status === "cancelled") return "已取消";
|
||||
@@ -485,7 +498,7 @@ function capabilityLabel(capability?: GenerationJob["capability"]) {
|
||||
}
|
||||
|
||||
function billingLabel(job: GenerationJob) {
|
||||
if (!job.billing) return job.provider === "mock" ? "免计费" : "未计费";
|
||||
if (!job.billing) return job.provider === "mock" ? "历史任务(未计费)" : "未计费";
|
||||
if (job.billing.quotaExempt) return `超管费用 ${formatBillingAmount(job.billing.amountFen)}(不计额度)`;
|
||||
if (job.billing.status === "refunded") return `已退款 ${formatBillingAmount(job.billing.amountFen)}`;
|
||||
if (job.billing.status === "pending") return `预计 ${formatBillingAmount(job.billing.amountFen)}`;
|
||||
|
||||
Reference in new issue
Block a user