Files
image-prompt-studio/public/prompt-builder.js
2026-04-25 11:26:33 +08:00

112 lines
3.1 KiB
JavaScript

export const STORAGE_KEY = "image-prompt-studio:simple-prompt:v1";
export const GENERATION_DEFAULTS = {
size: "1024x1024",
quality: "high",
outputFormat: "png",
background: "auto",
count: 1,
moderation: "auto",
outputCompression: 90,
};
export const EXAMPLE_PROMPTS = [
"一只白色陶瓷杯放在浅灰色窗边桌面上,晨光柔和,极简产品摄影,干净背景,苹果官网质感。",
"未来感电动车停在雾气很轻的海边公路,银色车身,阴天柔光,电影级写实海报。",
"一间现代风格客厅,浅木地板,奶油白沙发,大面积自然光,室内设计杂志封面感。",
"一款无线耳机悬浮在纯白背景中,蓝色柔和反射光,商业广告风,细节锐利。",
];
export const PROCESSING_STAGES = [
{
title: "整理 Prompt",
detail: "检查内容并准备发送到服务端。",
thresholdMs: 1400,
},
{
title: "连接 gpt-image-2",
detail: "向 OpenAI Images API 发起图片生成请求。",
thresholdMs: 5200,
},
{
title: "等待渲染",
detail: "模型正在生成高质量图片,这一步通常最耗时。",
thresholdMs: 15000,
},
{
title: "准备下载",
detail: "接收 base64 图片并整理成浏览器可下载文件。",
thresholdMs: 24000,
},
];
export function sanitizePrompt(input) {
return String(input ?? "")
.replace(/\r/g, "")
.replace(/[ \t]+\n/g, "\n")
.replace(/\n{3,}/g, "\n\n")
.split("\n")
.map((line) => line.trim())
.join("\n")
.trim();
}
export function buildPromptStats(prompt) {
const cleanPrompt = sanitizePrompt(prompt);
if (!cleanPrompt) {
return "输入一句清晰的画面描述即可开始。";
}
const lineCount = cleanPrompt.split("\n").length;
const charCount = cleanPrompt.length;
return `${charCount} 个字符 · ${lineCount}`;
}
export function buildDownloadStem(prompt) {
const normalized = sanitizePrompt(prompt)
.toLowerCase()
.replace(/[^a-z0-9\u4e00-\u9fa5\s-]/g, "")
.trim()
.replace(/\s+/g, "-")
.slice(0, 48);
return normalized || "generated-image";
}
export function createProcessingSnapshot(elapsedMs, isComplete = false) {
if (isComplete) {
return {
progress: 1,
activeStageIndex: PROCESSING_STAGES.length - 1,
lead: "图片已生成完成,可以预览和下载。",
};
}
const safeElapsed = Math.max(0, elapsedMs);
const finalThreshold =
PROCESSING_STAGES[PROCESSING_STAGES.length - 1]?.thresholdMs ?? 24000;
const progress = Math.min(0.92, safeElapsed / finalThreshold);
const activeStageIndex = resolveActiveStageIndex(safeElapsed);
const activeStage = PROCESSING_STAGES[activeStageIndex];
return {
progress,
activeStageIndex,
lead: activeStage
? `${activeStage.title}中... ${activeStage.detail}`
: "正在处理,请稍候。",
};
}
function resolveActiveStageIndex(elapsedMs) {
for (let index = PROCESSING_STAGES.length - 1; index >= 0; index -= 1) {
if (elapsedMs >= PROCESSING_STAGES[index].thresholdMs) {
return index;
}
}
return 0;
}