合入:工作流可以改名(画布顶栏、工作流列表各一个入口;服务端拦空名、超长、重名,内置模板不改名)

This commit is contained in:
ThearchyHelios
2026-10-20 08:19:32 +08:00
4 changed files with 136 additions and 4 deletions
+35 -1
View File
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { Check, Copy, Layers, LayoutTemplate, Plus, Search, Trash2, Workflow as WorkflowIcon } from 'lucide-react'
import { Check, Copy, Layers, LayoutTemplate, Pencil, Plus, Search, Trash2, Workflow as WorkflowIcon } from 'lucide-react'
import clsx from 'clsx'
import { api } from '../api/client'
import { useCatalog } from '../store/catalog'
@@ -156,6 +156,35 @@ export async function createWorkflow(
}
}
/**
* 给工作流改名。只改名字:不加版本、不碰图,画布上还没保存的改动原样留着(改的正是画布上打开的这一张时,只换它的名字)。
* 同名、空名在这里先拦一道,服务端也拦(api/workflows._checked_name);内置模板不给改名入口(启动时按名字补内置模板,
* 服务端会拒),要改就「以此模板新建」。
*/
export async function renameWorkflow(w: Workflow, refresh: () => Promise<void> | void): Promise<Workflow | null> {
const names = new Set(useCatalog.getState().workflows.filter((x) => x.id !== w.id).map((x) => x.name))
const raw = await promptDialog({
title: `重命名「${w.name}」`,
label: '名称',
initial: w.name,
confirmLabel: '重命名',
validate: (v) => (!v.trim() ? '名称不能为空' : names.has(v.trim()) ? '已存在同名工作流,请使用其他名称' : null),
})
const name = raw?.trim()
if (!name || name === w.name) return null
try {
const updated = await api.workflows.update(w.id, { name })
const open = useStudio.getState().workflow
if (open?.id === w.id) useStudio.setState({ workflow: { ...open, name: updated.name } })
void refresh()
toast.ok(`已重命名为「${updated.name}」`)
return updated
} catch (e) {
toast.error(e)
return null
}
}
function StatusChip({ w }: { w: Workflow }) {
const p = w.published_version
// 当前发布版的级别看 published_level(同工具栏的版本标签):画布上改过之后 status 回到草稿,受管发布版照实写「受管」
@@ -370,6 +399,11 @@ export function WorkflowPicker({ open, onClose }: { open: boolean; onClose: () =
<Plus size={11} /> 以此模板新建
</button>
)}
{!w.is_template && (
<IconButton label={`重命名「${w.name}」`} title="重命名"
className="text-faint group-hover:text-dim"
onClick={() => void renameWorkflow(w, refresh)} icon={<Pencil size={11} />} />
)}
<IconButton label={`复制「${w.name}」`} title="复制"
className="text-faint group-hover:text-dim"
onClick={() => void duplicate(w)} icon={<Copy size={11} />} />
+7 -2
View File
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useId, useMemo, useRef, useState, type ReactNode } from 'react'
import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import {
AlertTriangle, Check, ChevronDown, History, LayoutGrid, MoreHorizontal, PanelRightClose, PanelRightOpen, Plus,
AlertTriangle, Check, ChevronDown, History, LayoutGrid, MoreHorizontal, PanelRightClose, PanelRightOpen, Pencil, Plus,
Redo2, RotateCw, Save, ShieldCheck, Square, Undo2, Variable, Wand2, XCircle,
} from 'lucide-react'
import clsx from 'clsx'
@@ -13,7 +13,7 @@ import { CanvasDock, type DockTab } from '../canvas/CanvasDock'
import { LineageLayer } from '../canvas/LineageLayer'
import { VersionsSheet } from '../canvas/VersionsSheet'
import { PublishDialog } from '../canvas/PublishDialog'
import { WorkflowPicker, confirmDiscard, createWorkflow, takeDiscarded } from '../canvas/WorkflowPicker'
import { WorkflowPicker, confirmDiscard, createWorkflow, renameWorkflow, takeDiscarded } from '../canvas/WorkflowPicker'
import { fieldOfIssue, problemsOf, type Problem } from '../canvas/issues'
import { STUDIO_SHORTCUTS, hintOf, studioShortcut, type StudioShortcutId } from '../canvas/shortcuts'
import { AssistantPanel } from '../run/AssistantPanel'
@@ -527,6 +527,11 @@ export function StudioPage() {
<span className="max-w-56 truncate font-medium @max-[1120px]:max-w-32">{workflow?.name ?? '选择工作流'}</span>
<ChevronDown size={12} className="shrink-0 text-faint" />
</button>
{/* 改名只改名字,画布上没保存的改动不受影响;内置模板不给改名(见 renameWorkflow) */}
{workflow && !workflow.is_template && (
<IconButton label={`重命名「${workflow.name}」`} title="重命名" className="-ml-1 shrink-0 text-faint hover:text-dim"
onClick={() => void renameWorkflow(workflow, refresh)} icon={<Pencil size={12} />} />
)}
{workflow && <VersionLabel workflow={workflow} />}
{dirty && (