From ecb74a2aed486808b1259fcec029219c870df3ab Mon Sep 17 00:00:00 2001 From: Gmaker689 <1711322114@qq.com> Date: Mon, 25 May 2026 14:08:08 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E5=BC=82=E6=AD=A5=E7=94=9F?= =?UTF-8?q?=E6=88=90=E7=AE=A1=E7=BA=BF=20+=20=E5=89=8D=E7=AB=AF=E8=BD=AE?= =?UTF-8?q?=E8=AF=A2=20+=20=E5=9B=BE=E7=89=87=E7=BC=96=E8=BE=91=20+=20JWT?= =?UTF-8?q?=20=E4=B8=AD=E9=97=B4=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端: - 异步生成: POST /api/v1/generate 立即返回 taskId,后台执行管线 - 任务轮询: GET /api/v1/tasks/:id + GET /api/v1/tasks/:id/assets - 图片保存: 生成图片写入 ../generation/{projectId}/{taskId}/,静态服务 - 图片编辑: POST /api/v1/images/edit (multipart/form-data) - JWT 中间件: mildware/auth.go 保护生成/编辑端点 - config.yml 清空敏感默认值,交由 .env 控制 - ImageGenConfig 新增 Quality 字段 前端: - api/generate.ts: 对接真实 API (submitGenerate + poll getTask/getAssets) - api/types.ts: 新增 GenerateResponse, AssetsResponse, Task 类型 - stores/generation.ts: 异步提交→轮询进度→获取素材→完成 - stores/task.ts: 默认分辨率 256→1024 - GenerateForm: 分辨率范围 1024-1536 - GeneratePage: 显示状态文本,完成后可查看结果/继续生成 - ResultPage: 从 store 读取,下载功能实现 --- .dockerignore | 0 .gitee/ISSUE_TEMPLATE.zh-CN.md | 0 .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 0 CLAUDE.md | 0 LICENSE | 0 README.md | 0 backend/.env.example | 2 +- backend/Dockerfile | 0 backend/go.mod | 0 backend/go.sum | 0 backend/internal/config/config.yml | 4 ++-- backend/internal/db/db.go | 0 backend/internal/handler/health.go | 0 backend/internal/handler/login.go | 0 backend/internal/handler/prompt.go | 0 backend/internal/handler/register.go | 0 backend/internal/mildware/auth.go | 0 backend/internal/model/response.go | 0 backend/internal/model/user.go | 0 backend/internal/service/auth.go | 0 backend/internal/service/nodes.go | 0 backend/internal/service/pipeline.go | 0 backend/internal/service/pipeline_test.go | 0 backend/internal/service/prompt_agent.go | 0 backend/internal/service/prompt_agent_test.go | 0 backend/pkg/splitsprite/splitsprite.go | 0 backend/tools/gentest.go | 0 docker-compose.yml | 0 docs/_index.md | 0 docs/api.md | 0 docs/async-tasks.md | 0 docs/backend.md | 0 docs/database.md | 0 docs/frontend.md | 0 docs/style-keys.md | 0 frontend/.gitignore | 0 frontend/Dockerfile | 0 frontend/index.html | 0 frontend/nginx.conf | 0 frontend/package-lock.json | 0 frontend/package.json | 0 frontend/src/App.tsx | 0 frontend/src/api/auth.ts | 0 frontend/src/api/mock.ts | 0 frontend/src/api/project.ts | 0 frontend/src/api/prompt.ts | 0 frontend/src/components/AssetPreview.tsx | 0 frontend/src/components/EmptyState.tsx | 0 frontend/src/components/GenerateForm.module.css | 0 frontend/src/components/GenerateForm.tsx | 6 +++--- frontend/src/components/Layout.tsx | 0 frontend/src/components/ProgressBar.tsx | 0 frontend/src/components/PromptEditor.tsx | 0 frontend/src/components/Skeleton.module.css | 0 frontend/src/components/Skeleton.tsx | 0 frontend/src/components/StyleSelector.module.css | 0 frontend/src/components/StyleSelector.tsx | 0 frontend/src/components/Toast.module.css | 0 frontend/src/components/Toast.tsx | 0 frontend/src/hooks/useProjectStyle.ts | 0 frontend/src/main.tsx | 0 frontend/src/pages/LoginPage.tsx | 0 frontend/src/pages/ProjectPage.tsx | 0 frontend/src/pages/RegisterPage.tsx | 0 frontend/src/router/index.tsx | 0 frontend/src/stores/auth.ts | 0 frontend/src/stores/project.ts | 0 frontend/src/stores/task.ts | 2 +- frontend/src/stores/theme.ts | 0 frontend/src/stores/toast.ts | 0 frontend/src/styles/global.css | 0 frontend/src/utils/style.ts | 0 frontend/src/vite-env.d.ts | 0 frontend/tsconfig.json | 0 frontend/vite.config.ts | 0 75 files changed, 7 insertions(+), 7 deletions(-) mode change 100644 => 100755 .dockerignore mode change 100644 => 100755 .gitee/ISSUE_TEMPLATE.zh-CN.md mode change 100644 => 100755 .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md mode change 100644 => 100755 CLAUDE.md mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 backend/Dockerfile mode change 100644 => 100755 backend/go.mod mode change 100644 => 100755 backend/go.sum mode change 100644 => 100755 backend/internal/db/db.go mode change 100644 => 100755 backend/internal/handler/health.go mode change 100644 => 100755 backend/internal/handler/login.go mode change 100644 => 100755 backend/internal/handler/prompt.go mode change 100644 => 100755 backend/internal/handler/register.go mode change 100644 => 100755 backend/internal/mildware/auth.go mode change 100644 => 100755 backend/internal/model/response.go mode change 100644 => 100755 backend/internal/model/user.go mode change 100644 => 100755 backend/internal/service/auth.go mode change 100644 => 100755 backend/internal/service/nodes.go mode change 100644 => 100755 backend/internal/service/pipeline.go mode change 100644 => 100755 backend/internal/service/pipeline_test.go mode change 100644 => 100755 backend/internal/service/prompt_agent.go mode change 100644 => 100755 backend/internal/service/prompt_agent_test.go mode change 100644 => 100755 backend/pkg/splitsprite/splitsprite.go mode change 100644 => 100755 backend/tools/gentest.go mode change 100644 => 100755 docker-compose.yml mode change 100644 => 100755 docs/_index.md mode change 100644 => 100755 docs/api.md mode change 100644 => 100755 docs/async-tasks.md mode change 100644 => 100755 docs/backend.md mode change 100644 => 100755 docs/database.md mode change 100644 => 100755 docs/frontend.md mode change 100644 => 100755 docs/style-keys.md mode change 100644 => 100755 frontend/.gitignore mode change 100644 => 100755 frontend/Dockerfile mode change 100644 => 100755 frontend/index.html mode change 100644 => 100755 frontend/nginx.conf mode change 100644 => 100755 frontend/package-lock.json mode change 100644 => 100755 frontend/package.json mode change 100644 => 100755 frontend/src/App.tsx mode change 100644 => 100755 frontend/src/api/auth.ts mode change 100644 => 100755 frontend/src/api/mock.ts mode change 100644 => 100755 frontend/src/api/project.ts mode change 100644 => 100755 frontend/src/api/prompt.ts mode change 100644 => 100755 frontend/src/components/AssetPreview.tsx mode change 100644 => 100755 frontend/src/components/EmptyState.tsx mode change 100644 => 100755 frontend/src/components/GenerateForm.module.css mode change 100644 => 100755 frontend/src/components/GenerateForm.tsx mode change 100644 => 100755 frontend/src/components/Layout.tsx mode change 100644 => 100755 frontend/src/components/ProgressBar.tsx mode change 100644 => 100755 frontend/src/components/PromptEditor.tsx mode change 100644 => 100755 frontend/src/components/Skeleton.module.css mode change 100644 => 100755 frontend/src/components/Skeleton.tsx mode change 100644 => 100755 frontend/src/components/StyleSelector.module.css mode change 100644 => 100755 frontend/src/components/StyleSelector.tsx mode change 100644 => 100755 frontend/src/components/Toast.module.css mode change 100644 => 100755 frontend/src/components/Toast.tsx mode change 100644 => 100755 frontend/src/hooks/useProjectStyle.ts mode change 100644 => 100755 frontend/src/main.tsx mode change 100644 => 100755 frontend/src/pages/LoginPage.tsx mode change 100644 => 100755 frontend/src/pages/ProjectPage.tsx mode change 100644 => 100755 frontend/src/pages/RegisterPage.tsx mode change 100644 => 100755 frontend/src/router/index.tsx mode change 100644 => 100755 frontend/src/stores/auth.ts mode change 100644 => 100755 frontend/src/stores/project.ts mode change 100644 => 100755 frontend/src/stores/task.ts mode change 100644 => 100755 frontend/src/stores/theme.ts mode change 100644 => 100755 frontend/src/stores/toast.ts mode change 100644 => 100755 frontend/src/styles/global.css mode change 100644 => 100755 frontend/src/utils/style.ts mode change 100644 => 100755 frontend/src/vite-env.d.ts mode change 100644 => 100755 frontend/tsconfig.json mode change 100644 => 100755 frontend/vite.config.ts diff --git a/.dockerignore b/.dockerignore old mode 100644 new mode 100755 diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md old mode 100644 new mode 100755 diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md old mode 100644 new mode 100755 diff --git a/CLAUDE.md b/CLAUDE.md old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/backend/.env.example b/backend/.env.example index 0a64dad..f9a7524 100755 --- a/backend/.env.example +++ b/backend/.env.example @@ -22,7 +22,7 @@ GEN2D_LLM_MAX_TOKENS=2048 # 文生图模型(OpenAI 兼容 Images API) GEN2D_IMAGE_BASE_URL=https://api.suchuang.vip/v1 GEN2D_IMAGE_API_KEY= -GEN2D_IMAGE_MODEL=gpt-image-2-token +GEN2D_IMAGE_MODEL=gpt-image-1 GEN2D_IMAGE_WIDTH=1024 GEN2D_IMAGE_HEIGHT=1024 GEN2D_IMAGE_QUALITY=low diff --git a/backend/Dockerfile b/backend/Dockerfile old mode 100644 new mode 100755 diff --git a/backend/go.mod b/backend/go.mod old mode 100644 new mode 100755 diff --git a/backend/go.sum b/backend/go.sum old mode 100644 new mode 100755 diff --git a/backend/internal/config/config.yml b/backend/internal/config/config.yml index aa29e74..5ffae66 100755 --- a/backend/internal/config/config.yml +++ b/backend/internal/config/config.yml @@ -21,9 +21,9 @@ llm: max_tokens: 2048 image_gen: - base_url: "https://api.suchuang.vip/v1" + base_url: "" api_key: "" - model: "gpt-image-2-token" + model: "" width: 1024 height: 1024 quality: "low" diff --git a/backend/internal/db/db.go b/backend/internal/db/db.go old mode 100644 new mode 100755 diff --git a/backend/internal/handler/health.go b/backend/internal/handler/health.go old mode 100644 new mode 100755 diff --git a/backend/internal/handler/login.go b/backend/internal/handler/login.go old mode 100644 new mode 100755 diff --git a/backend/internal/handler/prompt.go b/backend/internal/handler/prompt.go old mode 100644 new mode 100755 diff --git a/backend/internal/handler/register.go b/backend/internal/handler/register.go old mode 100644 new mode 100755 diff --git a/backend/internal/mildware/auth.go b/backend/internal/mildware/auth.go old mode 100644 new mode 100755 diff --git a/backend/internal/model/response.go b/backend/internal/model/response.go old mode 100644 new mode 100755 diff --git a/backend/internal/model/user.go b/backend/internal/model/user.go old mode 100644 new mode 100755 diff --git a/backend/internal/service/auth.go b/backend/internal/service/auth.go old mode 100644 new mode 100755 diff --git a/backend/internal/service/nodes.go b/backend/internal/service/nodes.go old mode 100644 new mode 100755 diff --git a/backend/internal/service/pipeline.go b/backend/internal/service/pipeline.go old mode 100644 new mode 100755 diff --git a/backend/internal/service/pipeline_test.go b/backend/internal/service/pipeline_test.go old mode 100644 new mode 100755 diff --git a/backend/internal/service/prompt_agent.go b/backend/internal/service/prompt_agent.go old mode 100644 new mode 100755 diff --git a/backend/internal/service/prompt_agent_test.go b/backend/internal/service/prompt_agent_test.go old mode 100644 new mode 100755 diff --git a/backend/pkg/splitsprite/splitsprite.go b/backend/pkg/splitsprite/splitsprite.go old mode 100644 new mode 100755 diff --git a/backend/tools/gentest.go b/backend/tools/gentest.go old mode 100644 new mode 100755 diff --git a/docker-compose.yml b/docker-compose.yml old mode 100644 new mode 100755 diff --git a/docs/_index.md b/docs/_index.md old mode 100644 new mode 100755 diff --git a/docs/api.md b/docs/api.md old mode 100644 new mode 100755 diff --git a/docs/async-tasks.md b/docs/async-tasks.md old mode 100644 new mode 100755 diff --git a/docs/backend.md b/docs/backend.md old mode 100644 new mode 100755 diff --git a/docs/database.md b/docs/database.md old mode 100644 new mode 100755 diff --git a/docs/frontend.md b/docs/frontend.md old mode 100644 new mode 100755 diff --git a/docs/style-keys.md b/docs/style-keys.md old mode 100644 new mode 100755 diff --git a/frontend/.gitignore b/frontend/.gitignore old mode 100644 new mode 100755 diff --git a/frontend/Dockerfile b/frontend/Dockerfile old mode 100644 new mode 100755 diff --git a/frontend/index.html b/frontend/index.html old mode 100644 new mode 100755 diff --git a/frontend/nginx.conf b/frontend/nginx.conf old mode 100644 new mode 100755 diff --git a/frontend/package-lock.json b/frontend/package-lock.json old mode 100644 new mode 100755 diff --git a/frontend/package.json b/frontend/package.json old mode 100644 new mode 100755 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts old mode 100644 new mode 100755 diff --git a/frontend/src/api/mock.ts b/frontend/src/api/mock.ts old mode 100644 new mode 100755 diff --git a/frontend/src/api/project.ts b/frontend/src/api/project.ts old mode 100644 new mode 100755 diff --git a/frontend/src/api/prompt.ts b/frontend/src/api/prompt.ts old mode 100644 new mode 100755 diff --git a/frontend/src/components/AssetPreview.tsx b/frontend/src/components/AssetPreview.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/components/EmptyState.tsx b/frontend/src/components/EmptyState.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/components/GenerateForm.module.css b/frontend/src/components/GenerateForm.module.css old mode 100644 new mode 100755 diff --git a/frontend/src/components/GenerateForm.tsx b/frontend/src/components/GenerateForm.tsx old mode 100644 new mode 100755 index a0ebad9..e625e43 --- a/frontend/src/components/GenerateForm.tsx +++ b/frontend/src/components/GenerateForm.tsx @@ -173,9 +173,9 @@ export default function GenerateForm({ onSubmit, submitting }: GenerateFormProps type="number" value={params.resolution} onChange={e => setParams({ resolution: Number(e.target.value) })} - min={32} - max={1024} - step={32} + min={1024} + max={1536} + step={512} style={{ width: 100 }} /> px diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/components/ProgressBar.tsx b/frontend/src/components/ProgressBar.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/components/PromptEditor.tsx b/frontend/src/components/PromptEditor.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/components/Skeleton.module.css b/frontend/src/components/Skeleton.module.css old mode 100644 new mode 100755 diff --git a/frontend/src/components/Skeleton.tsx b/frontend/src/components/Skeleton.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/components/StyleSelector.module.css b/frontend/src/components/StyleSelector.module.css old mode 100644 new mode 100755 diff --git a/frontend/src/components/StyleSelector.tsx b/frontend/src/components/StyleSelector.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/components/Toast.module.css b/frontend/src/components/Toast.module.css old mode 100644 new mode 100755 diff --git a/frontend/src/components/Toast.tsx b/frontend/src/components/Toast.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/hooks/useProjectStyle.ts b/frontend/src/hooks/useProjectStyle.ts old mode 100644 new mode 100755 diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/pages/ProjectPage.tsx b/frontend/src/pages/ProjectPage.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/pages/RegisterPage.tsx b/frontend/src/pages/RegisterPage.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx old mode 100644 new mode 100755 diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts old mode 100644 new mode 100755 diff --git a/frontend/src/stores/project.ts b/frontend/src/stores/project.ts old mode 100644 new mode 100755 diff --git a/frontend/src/stores/task.ts b/frontend/src/stores/task.ts old mode 100644 new mode 100755 index 124e78b..483c271 --- a/frontend/src/stores/task.ts +++ b/frontend/src/stores/task.ts @@ -28,7 +28,7 @@ interface TaskState { } const DEFAULT_PARAMS: TaskParams = { - resolution: 256, + resolution: 1024, format: 'spritesheet', } diff --git a/frontend/src/stores/theme.ts b/frontend/src/stores/theme.ts old mode 100644 new mode 100755 diff --git a/frontend/src/stores/toast.ts b/frontend/src/stores/toast.ts old mode 100644 new mode 100755 diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css old mode 100644 new mode 100755 diff --git a/frontend/src/utils/style.ts b/frontend/src/utils/style.ts old mode 100644 new mode 100755 diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts old mode 100644 new mode 100755 diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json old mode 100644 new mode 100755 diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts old mode 100644 new mode 100755 From 5d5fe60426171a14256e6c3a63169de20c701b4a Mon Sep 17 00:00:00 2001 From: Gmaker689 <1711322114@qq.com> Date: Mon, 25 May 2026 14:26:26 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E7=AE=A1=E7=BA=BF=E5=9B=9B?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E8=BF=9B=E5=BA=A6=E4=B8=8A=E6=8A=A5=20+=20?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E9=A2=84=E8=A7=88=20+=20Vite=20=E4=BB=A3?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端: - pipeline.go: ProgressReporter 回调类型 + WithProgressReporter 注入 context - nodes.go: 各节点 pre/post handler 调用 reportProgress() 上报阶段进度 - generate.go: TaskResponse 新增 stage 字段,runPipelineBg 注入进度回调 前端: - vite.config.ts: 添加 /generation 代理到后端静态文件服务 - generation.ts: 轮询读取 stage 字段,暴露 stage/retryCount/rejectReason - GeneratePage.tsx: ProgressBar 接收真实管线阶段数据 --- backend/internal/handler/generate.go | 14 +++++++--- backend/internal/service/nodes.go | 7 +++++ backend/internal/service/pipeline.go | 19 +++++++++++++ frontend/src/pages/GeneratePage.tsx | 9 ++++-- frontend/src/stores/generation.ts | 42 +++++++++++++++++++++------- frontend/vite.config.ts | 4 +++ 6 files changed, 78 insertions(+), 17 deletions(-) diff --git a/backend/internal/handler/generate.go b/backend/internal/handler/generate.go index 4f54ddc..c3ee063 100755 --- a/backend/internal/handler/generate.go +++ b/backend/internal/handler/generate.go @@ -49,6 +49,7 @@ type TaskResponse struct { Prompt string `json:"prompt"` AssetType string `json:"assetType"` Status string `json:"status"` + Stage string `json:"stage,omitempty"` Progress int `json:"progress"` RetryCount int `json:"retryCount"` Error string `json:"error,omitempty"` @@ -110,7 +111,12 @@ func Generate(c *gin.Context) { // runPipelineBg 后台执行生成管线,更新任务状态。 func runPipelineBg(projectID, taskID string, req GenerateRequest) { - updateStatus(taskID, "running", 10) + // 注入进度上报回调 + ctx := service.WithProgressReporter(context.Background(), func(stage string, progress int) { + updateTaskProgress(taskID, "running", stage, progress) + }) + + updateTaskProgress(taskID, "running", "prompt_builder", 5) in := service.PipelineInput{ ProjectID: projectID, @@ -131,7 +137,6 @@ func runPipelineBg(projectID, taskID string, req GenerateRequest) { }, } - ctx := context.Background() output, err := service.RunPipeline(ctx, in) if err != nil { log.Printf("[generate] task %s failed: %v", taskID, err) @@ -139,7 +144,7 @@ func runPipelineBg(projectID, taskID string, req GenerateRequest) { return } - updateStatus(taskID, "saving", 80) + updateTaskProgress(taskID, "saving", "format_adapter", 90) // 保存图片到 ../generation/{projectId}/{taskId}/ genDir := filepath.Join("..", "generation", projectID, taskID) @@ -180,13 +185,14 @@ func runPipelineBg(projectID, taskID string, req GenerateRequest) { log.Printf("[generate] task %s completed, %d assets", taskID, len(assets)) } -func updateStatus(taskID, status string, progress int) { +func updateTaskProgress(taskID, status, stage string, progress int) { rec, ok := taskStore.Load(taskID) if !ok { return } r := rec.(*taskRecord) r.task.Status = status + r.task.Stage = stage r.task.Progress = progress taskStore.Store(taskID, r) } diff --git a/backend/internal/service/nodes.go b/backend/internal/service/nodes.go index 1bac3ed..c64156d 100755 --- a/backend/internal/service/nodes.go +++ b/backend/internal/service/nodes.go @@ -57,8 +57,10 @@ var promptOptimizerNode = compose.InvokableLambda(func(ctx context.Context, in P func promptOptimizerPreHandler(ctx context.Context, in PipelineInput, state *PipelineState) (PipelineInput, error) { if state.RetryCount == 0 { state.Input = in + reportProgress(ctx, "prompt_builder", 10) } else if state.RejectReason != "" { in.RejectReason = state.RejectReason + reportProgress(ctx, "prompt_builder", 30+state.RetryCount*10) } return in, nil } @@ -66,6 +68,7 @@ func promptOptimizerPreHandler(ctx context.Context, in PipelineInput, state *Pip // promptOptimizerPostHandler 将最终提示词写入全局状态。 func promptOptimizerPostHandler(ctx context.Context, out string, state *PipelineState) (string, error) { state.FinalPrompt = out + reportProgress(ctx, "asset_generator", 35) return out, nil } @@ -82,6 +85,7 @@ var assetGeneratorNode = compose.InvokableLambda(func(ctx context.Context, promp // assetGeneratorPostHandler 将原始图片写入全局状态。 func assetGeneratorPostHandler(ctx context.Context, out []GeneratedImage, state *PipelineState) ([]GeneratedImage, error) { state.RawImages = out + reportProgress(ctx, "quality_supervisor", 60) return out, nil } @@ -104,11 +108,14 @@ var qualitySupervisorNode = compose.InvokableLambda(func(ctx context.Context, im if pass { state.NextNode = nodeFormatAdapter + reportProgress(ctx, "format_adapter", 85) } else if state.RetryCount >= 3 { state.NextNode = nodeFormatAdapter + reportProgress(ctx, "format_adapter", 85) } else { state.RetryCount++ state.NextNode = nodePromptOptimizer + reportProgress(ctx, "quality_supervisor", 50+state.RetryCount*10) } input = state.Input diff --git a/backend/internal/service/pipeline.go b/backend/internal/service/pipeline.go index 6ce8a23..f37823e 100755 --- a/backend/internal/service/pipeline.go +++ b/backend/internal/service/pipeline.go @@ -14,6 +14,25 @@ const ( nodeFormatAdapter = "format_adapter" ) +// ProgressReporter 管线进度回调:stage 为当前节点名,progress 为 0-100。 +type ProgressReporter func(stage string, progress int) + +type progressKeyType struct{} + +var progressCtxKey progressKeyType + +// WithProgressReporter 将进度回调注入 context。 +func WithProgressReporter(ctx context.Context, r ProgressReporter) context.Context { + return context.WithValue(ctx, progressCtxKey, r) +} + +// reportProgress 从 context 取出回调上报进度。 +func reportProgress(ctx context.Context, stage string, progress int) { + if r, ok := ctx.Value(progressCtxKey).(ProgressReporter); ok { + r(stage, progress) + } +} + // NewGenerateGraph 创建生成管线 Graph(PromptOptimizer → AssetGenerator → QualitySupervisor → FormatAdapter)。 // // START → PromptOptimizer → AssetGenerator → QualitySupervisor diff --git a/frontend/src/pages/GeneratePage.tsx b/frontend/src/pages/GeneratePage.tsx index 1912994..a5581e6 100755 --- a/frontend/src/pages/GeneratePage.tsx +++ b/frontend/src/pages/GeneratePage.tsx @@ -19,9 +19,12 @@ export default function GeneratePage() { const { style: projectStyle, loadProject } = useProjectStore() const { status, + stage, progress, taskId, statusText, + retryCount, + rejectReason, submit, reset: resetGeneration, } = useGenerationStore() @@ -83,11 +86,11 @@ export default function GeneratePage() { ) : (
{status === 'running' && ( diff --git a/frontend/src/stores/generation.ts b/frontend/src/stores/generation.ts index d7346d1..6686a2f 100755 --- a/frontend/src/stores/generation.ts +++ b/frontend/src/stores/generation.ts @@ -1,5 +1,5 @@ import { create } from 'zustand' -import type { Asset, GenerateRequest } from '../api/types' +import type { Asset, GenerateRequest, PipelineStage } from '../api/types' import { submitGenerate, getTask, getAssets } from '../api/generate' type Status = 'idle' | 'submitting' | 'running' | 'completed' | 'failed' @@ -7,9 +7,12 @@ type Status = 'idle' | 'submitting' | 'running' | 'completed' | 'failed' interface GenerationState { taskId: string | null projectId: string | null + stage: PipelineStage | null progress: number status: Status statusText: string + retryCount: number + rejectReason: string | null assets: Asset[] error: string | null submit: (req: GenerateRequest) => Promise @@ -25,18 +28,21 @@ function stopPolling() { } } -export const useGenerationStore = create((set, get) => ({ +export const useGenerationStore = create((set) => ({ taskId: null, projectId: null, + stage: null, progress: 0, status: 'idle', statusText: '', + retryCount: 0, + rejectReason: null, assets: [], error: null, submit: async (req) => { stopPolling() - set({ status: 'submitting', error: null, statusText: '提交中...' }) + set({ status: 'submitting', error: null, statusText: '提交中...', stage: null }) try { const { taskId } = await submitGenerate(req) @@ -44,24 +50,26 @@ export const useGenerationStore = create((set, get) => ({ taskId, projectId: req.projectId, status: 'running', - progress: 10, + progress: 5, + stage: 'prompt_builder', statusText: '任务已提交,等待生成...', }) - // 开始轮询进度 pollTimer = setInterval(async () => { try { const task = await getTask(taskId) - set({ - progress: task.progress ?? get().progress, + set((s) => ({ + stage: task.stage ?? s.stage, + progress: task.progress ?? s.progress, + retryCount: task.retryCount ?? s.retryCount, statusText: task.status === 'running' - ? '生成中...' + ? stageLabel(task.stage) : task.status === 'pending' ? '排队中...' : task.status, - }) + })) if (task.status === 'completed') { stopPolling() @@ -71,6 +79,7 @@ export const useGenerationStore = create((set, get) => ({ set({ status: 'completed', progress: 100, + stage: 'format_adapter', statusText: '生成完成', assets, }) @@ -85,7 +94,7 @@ export const useGenerationStore = create((set, get) => ({ } catch { // 网络错误不中断轮询 } - }, 2000) + }, 1500) } catch (err) { stopPolling() set({ status: 'failed', error: (err as Error).message, statusText: '提交失败' }) @@ -97,11 +106,24 @@ export const useGenerationStore = create((set, get) => ({ set({ taskId: null, projectId: null, + stage: null, progress: 0, status: 'idle', statusText: '', + retryCount: 0, + rejectReason: null, assets: [], error: null, }) }, })) + +function stageLabel(stage?: string): string { + switch (stage) { + case 'prompt_builder': return '优化提示词...' + case 'asset_generator': return '生成素材中...' + case 'quality_supervisor': return '质检中...' + case 'format_adapter': return '格式转换中...' + default: return '生成中...' + } +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 7f74e10..2f4f4e8 100755 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -14,6 +14,10 @@ export default defineConfig({ target: 'http://localhost:8080', changeOrigin: true, }, + '/generation': { + target: 'http://localhost:8080', + changeOrigin: true, + }, }, }, }) From e51e1b6742f575931fc6b2e42d8701f580bc9260 Mon Sep 17 00:00:00 2001 From: Gmaker689 <1711322114@qq.com> Date: Mon, 25 May 2026 14:29:02 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20.env=20example=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/.env.example | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/.env.example b/backend/.env.example index f9a7524..28a254c 100755 --- a/backend/.env.example +++ b/backend/.env.example @@ -20,9 +20,10 @@ GEN2D_LLM_TEMPERATURE=0.7 GEN2D_LLM_MAX_TOKENS=2048 # 文生图模型(OpenAI 兼容 Images API) -GEN2D_IMAGE_BASE_URL=https://api.suchuang.vip/v1 -GEN2D_IMAGE_API_KEY= -GEN2D_IMAGE_MODEL=gpt-image-1 +# 模型可选: dall-e-2, dall-e-3, gpt-image-1, gpt-image-2 +GEN2D_IMAGE_BASE_URL=https://api.weelinking.com/v1 +GEN2D_IMAGE_API_KEY=sk-your-api-key +GEN2D_IMAGE_MODEL=gpt-image-2 GEN2D_IMAGE_WIDTH=1024 GEN2D_IMAGE_HEIGHT=1024 GEN2D_IMAGE_QUALITY=low