{{ title }} {{ verLabel }}
近 7 天任务量
| ID | 公司/账号 | 联系人 | 状态 | 余额 | 有效期至 | 任务数 | 授权 | 密钥 | 备注 | 密码 | 操作 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| {{ u.id }} | {{ u.company_name||u.username }} {{ u.username || '' }} |
{{ u.contact_person||'-' }} |
已删除
{{ u.status==1?'正常':'停用' }}
删于 {{ fmtDate(u.deleted_at) }}
|
{{ (u.quota_total||0)-(u.quota_used||0) }} | {{ fmtDate(u.plan_expire_at) }} | {{ u.job_count||0 }} | {{ u.grant_count||0 }} 个 | {{ u.key_count||0 }} | {{ (u.remark||'-').length>16 ? (u.remark.slice(0,16)+'…') : (u.remark||'-') }} |
{{ pwdReveal[u.id] }}
••••••••
|
|
{{ cDel ? '回收站是空的(没有已删除的大用户)' : '暂无大用户,点右上角开通' }} | |||||||||||
本页只读。要改天数或新增规则,请到 OSS 控制台操作 —— 原因是生命周期规则是「整份替换」语义, 后台一键改写有把「带过滤器的规则」写成「整桶规则」的风险(那会导致整桶被删),不值得为了省事冒这个险。
| 规则 ID | 管的目录(前缀) | 多少天后删 | 状态 | 范围类型 | 查看 |
|---|---|---|---|---|---|
| {{ r.id }} | {{ r.prefix || '(空前缀)' }} | {{ r.days==null ? (r.date||'—') : r.days+' 天' }} | {{ r.status=='Enabled'?'生效中':r.status }} | {{ r.has_filter ? '带过滤器' : '按前缀' }} · {{ r.filter_hint }} | |
{{ storeLoading?'加载中…':'没有读到清理规则(若接口报错见上方红字)' }} | |||||
目录统计:{{ storeStat.prefix || '(整桶)' }}
最老:{{ storeStat.oldest || '-' }} 最新:{{ storeStat.newest || '-' }}
① 权威源 = GPU 服务器本机盘 /data/comfyui/user/default/workflows/ ← ComfyUI 日常读写的就是这里
② OSS 副本 · 保存即同步(秒级) 完整原始 json,可原样还原
③ OSS 副本 · 每日 03:30 全量 与 ① 逐字节一致
④ NAS 历史快照 每 15 分钟一份、保留最近 120 份 ⇒ 可回到某个时间点的版本
⑤ 平台数据库 RDS workflow_drafts 表(记录路径 + 展平后的工作流)
换机器会丢吗?换镜像 / 重建容器 不会丢(工作流在挂载盘上,不在镜像里);换整台服务器时本机那份会没,但 ②③ 有完整原始文件,可以原样拉回。 (②③④ 的 OSS / NAS 精确目录不在此页写明:本页可被匿名读取,写明即等于对外给出直链线索。)
| ID | 名称 | 标题(内部) | 客户显示名 | 类型 | 点数 | 授权数 | 状态 | 源文件(服务器路径) | 更新 | 操作 |
|---|---|---|---|---|---|---|---|---|---|---|
| {{ w.id }} | {{ w.name }} | {{ w.title }} | {{ w.display_name }} ⚠️ 未设置 | {{ w.owner_id?('专属·'+(w.owner_name||('#'+w.owner_id))):'公有' }} | {{ w.cost_points }} | {{ w.grant_count||0 }} | {{ w.status==1?'服务中':'已下线' }} 有新改动 | {{ w.source_file }} 手动录入 | {{ fmt(w.updated_at) }} | |
暂无工作流,去「服务器发现」标签导入 | ||||||||||
公有工作流 = 自动授权给所有客户;专属工作流 = 仅授权指定客户。授权可在「大用户管理 → 独立管理」里按客户勾选调整。
关于「入库后能不能改」:入库 = 把当时的配置存成一份快照,此后它与 ComfyUI 里的文件各自独立,
你在 ComfyUI 里继续改不会自动影响这里。所以:
① 改工作流内容 → 在 ComfyUI 改好并保存 → 回来点「应用更新」(草稿每 10 分钟自动同步;状态列出现「有新改动」就表示新内容已同步到位)
② 改标题 / 点数等说明信息 → 目前没有编辑入口,需走「暂停服务 → 删除 → 到「服务器发现」重新导入」(⚠️ 删除会清空该工作流的客户授权,专属工作流要重新勾选)
③ 改归属客户(公有 / 专属)→ 只在导入时选一次,之后不可更改;客户授权可随时在「独立管理」里调整
| ID | 文件名(名称) | 节点数 | 源文件(服务器完整路径) | 同步时间 | 状态 | 操作 | |
|---|---|---|---|---|---|---|---|
| {{ d.id }} | {{ d.name }} | {{ d.node_count }} | {{ d.source_file }} — | {{ fmt(d.updated_at) }} |
已导入 #{{ d.imported_workflow_id }}
已导入 #{{ d.imported_workflow_id }} · 有更新
待导入
平台在用的仍是旧内容({{ d.wf_status==1?'服务中':'已下线' }})
|
{{ fmt(d.updated_at) }} | |
暂无同步到的工作流草稿(GPU 机 Agent 会自动上报) | |||||||
导入 = 存为平台正式工作流并上线;专属工作流 在导入时选择归属客户,只有该客户能调;公有 自动授权所有客户。
{{ testImgName || '点击上传测试图片(PNG/JPG/WebP ≤10MB)' }}
| 时间 | 操作人 | 动作 | 目标 | 详情 | IP |
|---|---|---|---|---|---|
| {{ fmt(a.created_at) }} | {{ a.username||('#'+a.admin_id) }} | {{ AUDIT_TEXT[a.action]||a.action }} | {{ a.target_type ? (a.target_type+(a.target_id?'#'+a.target_id:'')) : '-' }} | {{ a.ip||'-' }} | |
暂无操作记录 | |||||
CHANGELOG.md 是否存在、以及构建时是否随镜像带上。
| 时间 | 客户 | 方向 | 点数 | 类型 | 备注 | 操作 |
|---|---|---|---|---|---|---|
| {{ fmt(r.created_at) }} | {{ r.company_name||r.username||('#'+r.user_id) }} | {{ r.kind=='in'?'充值':'扣点' }} | {{ r.points>0?'+':'' }}{{ r.points }} | {{ REC_TEXT[r.action]||r.action }} | ||
暂无充值记录 | ||||||
默认全隐藏,勾选后仅共享该环节的名称和产物——不暴露节点类型、机器名、耗时、内部报错、OSS 桶名。
「最终产物」永远返回,不受此开关影响(业务必需)。
{{ shPreview() }}
Layer 3 · FC 巡检线程
| 心跳线程 | {{ m.layer1.hb_thread_alive?'运行中':'已停止' }} |
| 上次成功心跳 | {{ m.layer1.last_hb_ok?fmt(Date(m.layer1.last_hb_ok*1000)):'-' }} |
| 连续失败次数 | {{ m.layer1.hb_fail_count||0 }} |
| Agent 运行时长 | {{ wdUptime(m.layer1.agent_uptime) }} |
| 恢复事件总数 | {{ m.layer2.recovery_events||0 }} 次 |
| 日志最后更新 | {{ m.layer2.log_mtime?fmt(Date(m.layer2.log_mtime*1000)):'-' }} |
{{ m.layer2.watchdog_log }}
| ID | 名称 | 零件 | 版本 | 状态 | 扣点 | 创建时间 | 操作 | |
|---|---|---|---|---|---|---|---|---|
| {{ p.id }} | {{ p.name }} | {{ p.part_label }} | v{{ p.version }} | {{ {draft:'草稿',active:'上线',paused:'暂停',archived:'归档'}[p.status] }} | {{ p.total_cost_points }} | {{ p.node_count||'-' }} | {{ fmt(p.created_at) }} |
管道执行记录
| 任务ID | 状态 | 结果图 | 扣点 | 开始 | 完成 | 操作 |
|---|---|---|---|---|---|---|
| {{ j.id }} | {{ j.status }} |
|
{{ j.cost_points }} | {{ fmt(j.started_at) }} | {{ fmt(j.completed_at) }} |
已注册节点
| ID | 名称 | 分类 | 执行器 | 输入 | 输出 | 扣点 | 状态 |
|---|---|---|---|---|---|---|---|
| {{ n.id }} | {{ n.name }} | {{ {input:'输入',process:'处理',generate:'生成',output:'输出'}[n.category] }} | {{ n.executor_type }} | {{ n.input_type }} | {{ n.output_type }} | {{ n.is_active?'启用':'停用' }} |
节点耗时统计
| 节点类型 | 分辨率桶 | 样本数 | 中位数(ms) | P25 | P75 | P95 | 更新时间 |
|---|---|---|---|---|---|---|---|
| {{ s.node_type }} | {{ s.resolution_bucket }} | {{ s.sample_count }} | {{ s.median_ms }} | {{ s.p25_ms }} | {{ s.p75_ms }} | {{ s.p95_ms }} | {{ fmt(s.last_updated) }} |
| 时间 | 任务 ID | 来源 | 类型 | 用户 | 管道 | 全链路预览 | 总耗时 | 积分 | 状态 | 操作 |
|---|---|---|---|---|---|---|---|---|---|---|
| └{{ it.created_at }} | 管道 └ 机器执行 单流 | 🟢 生产 🔵 测试 | {{ it.user || '—' }} |
›
—
{{ c.icon }}
📝
❌
—
无
|
{{ it.elapsed_sec }}s — | {{ it.cost }} | {{ nfStatusText(it.status) }} |
| 任务 | 客户 | 工作流 | 状态 | 优先级 | 执行机器 | 等待/耗时 | 提交时间 |
|---|---|---|---|---|---|---|---|
| #{{ j.id }} | {{ j.company_name||j.user_id }} | {{ j.workflow_title||('#'+j.workflow_id) }} | {{ stText(j.status) }} | {{ j.priority }} | {{ j.assigned_agent||'-' }} | {{ j.status=='pending' ? '排队中' : (Math.floor((j.run_seconds||0)/60)+'分'+(j.run_seconds%60)+'秒') }} | {{ fmt(j.queue_at) }} |
当前无进行中任务 | |||||||
🧰 已注册函数({{ fcFns.length }} 个)
| ID | 名称 | 地址 | 参数 | 状态 | 操作 |
|---|---|---|---|---|---|
| {{ f.id }} | {{ f.title || f.name }}{{ f.name }} |
{{ (f.url||'').slice(0,60) }} | {{ (f.params_schema||[]).length }} 个 | 启用 停用 | |
| 还没注册函数。点右上角「+ 注册函数」开始。 | |||||
{{ fcEdit.id ? '✏️ 编辑函数' : '+ 注册函数' }}
参数模板(决定在方案里能填什么)
| 参数键 | 显示名 | 类型 | 默认值 | 说明 / 选项 | 操作 |
|---|---|---|---|---|---|
{{ fcTestResult.text }}
📜 执行记录(最近 {{ preRuns.length }} 条)
| ID | 方案 | 类型 | 状态 | 耗时 | 开始时间 | 操作 |
|---|---|---|---|---|---|---|
| {{ r.id }} | {{ r.plan_name || r.plan_id }} | 测试 整链 出图 | 完成 失败 {{ r.status }} | {{ r.elapsed_ms ? (r.elapsed_ms/1000).toFixed(1)+'s' : '-' }} | {{ r.started_at || r.created_at }} | |
| 还没有执行记录。去「预处理方案」里点「测试」试试。 | ||||||
🔍 执行 #{{ preRunDetail.id }} 详情
每一步明细
| 步 | 步骤 | 状态 | 耗时 | HTTP | 输出 |
|---|---|---|---|---|---|
| {{ s.seq }} |
{{ s.alias || s.step_type }} {{ s.step_type }} |
成功 失败 跳过 {{ s.status }} | {{ s.elapsed_ms ? s.elapsed_ms+'ms' : '-' }} | {{ s.http_status || '-' }} |
{{ s.output_text.slice(0,150) }}
{{ s.error }}
查看原始返回{{ s.response_json.slice(0,2000) }}
|
📦 {{ b.bucket }} {{ b.rule_count }} 条规则 ⚠️ {{ b.missing_count }} 个前缀没配清理
{{ b.endpoint_public }}内网:
{{ b.endpoint_internal }}(同地域走内网不计流量费)总占用:{{ sbFmtSize(b.storage_bytes) }} | 对象数:{{ b.object_count.toLocaleString() }}
| 目录前缀 | 用途 | 占用大小 | 保留天数 | 状态 | 备注(为什么保留/清理) | 操作 |
|---|---|---|---|---|---|---|
{{ p.prefix }} |
{{ p.purpose }} · {{ p.advice }} | {{ sbFmtSize(p._size) }} / {{ p._count }} 个 (估算) 计算中… 算一下 → | {{ p.rule_days }} 天 ∞ 永久 — 未配置 | ✅ 已配 📌 刻意保留 ⚠️ 漏配 |
|
{{ stTextView.text }}
📋 已有方案({{ prePlans.length }} 个)
| ID | 方案名 | 标题 | 步骤 | 状态 | 操作 |
|---|---|---|---|---|---|
| {{ p.id }} | {{ p.name }} |
{{ p.title || '-' }} | {{ p.step_count }} | ✅ 启用 ⏸ 停用 📝 草稿 | |
| 还没有方案。点右上角「+ 新建方案」开始。 | |||||
{{ preEdit.id ? '✏️ 编辑方案' : '+ 新建方案' }}
{{ preTestKey }}
✅ 用外部地址
未选择(跑方案前必须先有一张图)
一条线路里可以配多台机器,每台机器有自己的预处理流程:
· 物理机可能直接生图(流程在工作流里已完成)
· liblib 可能要先去背景、再缩放,然后才出图
调度时按 P1 → P2 顺序尝试,前一台失败自动换下一台。
{{ '{"effect":"' + rt.effect_key + '"}' }}
点「+ 新建线路」→ 填按钮名(如 玉雕)→ 加机器 → 每台机器配自己的预处理和工作流
🚀 真跑测试 · {{ runTestName }}
png / jpg / webp,≤15MB
会依次经过:上传 → 预处理 → 生图 → 交付,每一环都能看到输入和输出
{{ prettyJson(n.raw_json) }}
⚡ 线路检查:{{ checkRoute_name }}
· 改完配置后再点一次「⚡ 快速检查」确认
· 想验证真能出图 → 用「🚀 真跑测试」(会真调 GPU,约 6 分钟)
⚙ 出图平台管理
🗺 {{ topoRoute.display_name || topoRoute.name }} · 出图拓扑
{{ '{"effect":"' + (topoRoute.effect_key||'') + '"}' }}
→ 按 P1 优先 顺序尝试,前一条失败自动换下一条
· 点机器 → 换机器
· 点工作流/模板 → 换工作流
· 点预处理步骤 → 换预处理管道,或直接打开管道编辑器改流程
选一条管道后就能在这里改它的参数
{{ rtForm.pipeline_id ? '编辑出图线路' : '新建出图线路' }}
这样各台机器命名不规范也能对上:gpu 上叫「烫金专用」, liblib 上叫「TJ-24步」都没关系——只要在这里指名配好即可。
效果调用时按下面的顺序尝试,前一个失败自动换下一个。
点「+ 新建执行体」→ 填业务名 → 勾机器 → 每台机器配工作流
{{ pfForm.id ? '编辑执行体' : '新建出图执行体' }}
客户调
{"effect":"yudiao"}
→ 平台按你绑定的执行体顺序去试(P1 失败自动换 P2)。执行体决定「用哪台机器 + 哪个工作流」,在「🎬 出图执行体」页配好再来这里绑。
点「+ 新建效果」→ 选一条已上线的管道 → 填代号(如 yudiao)
{{ effForm.id ? '编辑效果' : '新建效果' }}
给效果「{{ bindEffect }}」绑定执行体
1. 点「+ 添加机器」,填名字(如 gpu-02)+ 选物理机
2. 列表里它显示「未接入」→ 点 🚀 部署
3. 复制命令 → 登到新服务器粘贴回车
4. 等 15–30 分钟(拉镜像+同步模型)→ 状态变「空闲」就接上单了
1. 模型放到
/data/comfyui/models/ 对应目录2. 不用管,每天凌晨 3:30 自动备份到 OSS
3. 后台 → 📦 出图环境 → 刷新,就会看到模型数变了
4. 其他机器点 🔗 同步命令 拉齐
1. 打开 📦 出图环境
2. 看哪台显示「⚠ 缺 N 个模型」
3. 点它的 🔗 同步命令 → 复制到那台机器执行
4. 只补缺的,不会删它多出来的
只在已经装好的机器上出现,用途是「重新装一遍」。
⚠️ 生成命令后执行会重启 ComfyUI 1–2 分钟。
🟢 但脚本会先检查:如果 ComfyUI 健康运行, 会问你「要不要重建」,答 N 就什么都不动。
ℹ️ 日常不需要点它。
点「删除」→ 要手打机器名才删得掉
删了进 🗑 回收站,30 天内点「↩ 恢复」能回来
「彻底删除」才是真删(要再输入一次机器名)
每天 凌晨 3:30 自动把「模型 + 节点 + 用户数据」增量备份到 OSS。
新加的模型最晚第二天 3:30 自动上传。
想立刻备份:在机器上执行
/root/scripts/backup_comfyui_all.sh
| ID | 机器名 | 类型 | GPU / 配置 | 地址 | 状态 | 当前任务 | 成功率 | 最后心跳 | 备注 | 操作 |
|---|---|---|---|---|---|---|---|---|---|---|
| {{ m.id }} | {{ m.name }} | ☁️ API 🖥️ 物理机 |
{{ m.gpu_info||'外部平台' }}
并发 {{ m.api_running }}/{{ m.api_concurrency||1 }}
· 模板:{{ m.api_template_id }}
{{ m.gpu_info||'-' }}
⚡{{ m.gpu_detail_obj.util }}%
🌡{{ m.gpu_detail_obj.temp }}°C
🎮{{ Math.round(Number(m.gpu_detail_obj.mem_used)/1024) }}/{{ Math.round(Number(m.gpu_detail_obj.mem_total)/1024) }}G
💾{{ m.gpu_detail_obj.disk_used_pct }}%(余 {{ m.gpu_detail_obj.disk_free_gb }}G)
🧠{{ m.gpu_detail_obj.mem_used_gb }}/{{ m.gpu_detail_obj.mem_total_gb }}G · 🖥{{ m.gpu_detail_obj.cpu_pct }}%({{ m.gpu_detail_obj.cpu_cores }}核)
--
|
{{ m._effective_status=='offline'?'离线(心跳超时)':stText(m.status) }} | {{ m.current_job_id?('#'+m.current_job_id+(m.job_workflow?' · '+m.job_workflow:'')):'-' }} | {{ m.task_done||0 }}/{{ m.task_failed||0 }} · {{ m.avg_seconds }}s | {{ fmt(m.last_heartbeat)||'-' }} | {{ m.remark||'-' }} | ||
暂无机器,点右上角「添加机器」登记,或等 GPU 机 Agent 启动自动注册 | ||||||||||
💡 以后在 gpu-01 上加了新模型 → 在 gpu-01 执行一次「上传备份」→ 把基准机设成 gpu-01 → 其他机器点「同步」即可。
| 机器 | 类型 | 模型 | 节点 | 与基准对比 | 最后上报 | 操作 |
|---|---|---|---|---|---|---|
| {{ m.name }} 基准 | {{ m.machine_type === 'api' ? '☁️ API' : '🖥️ 物理机' }} | {{ m.models.length }} 个 | {{ m.nodes.length }} 个 | {{ m.diff.note }} {{ m.diff.note }} ✅ 与基准一致 缺 {{ m.diff.missing.length }} 个模型 {{ m.diff.missing.length ? ' · ' : '' }}缺 {{ m.diff.nodes_missing.length }} 个节点 · 多 {{ m.diff.extra.length }} 个 | {{ m.reported_at || '—' }} |
{{ envDetailText() }}
· 机器上的 ComfyUI 环境和模型不会被删(还在那台服务器上)
· 但这台机器不再接单,正在跑的任务会被中断
· 删除后进回收站,30 天内可以恢复
| 机器名 | 类型 | 删除时间 | 剩余 | 操作 |
|---|---|---|---|---|
| {{ r.name }} | {{ r.machine_type === 'api' ? '☁️ API' : '🖥️ 物理机' }} | {{ r.deleted_at }} | {{ r.days_left }} 天 |
不满足也能装,但拉镜像/同步模型会失败——脚本会先体检并告诉你缺什么。
新机器会出现在上面表格里,状态从「未接入」→「空闲」(约 30 秒)。
全程约 15–30 分钟(主要是拉 16.5G 镜像 + 同步 37G 模型)。
机器列表会自动刷新,你也可以点右上「刷新」按钮。
生成部署命令后,在机器上执行会发生什么:
· ComfyUI 会重启 1-2 分钟,期间不能出图
· 模型和节点不会丢(在 /data/comfyui,不在容器里)
· Agent 会重新安装(不影响已有配置)
🟢 脚本自带保护:如果检测到 ComfyUI 正在健康运行, 会问你一句「要不要重建」,你答 N 就跳过,什么都不动。
· 机器重装系统了,要重新装一遍
· 令牌丢了 / Agent 起不来
· 换了新版本的 ComfyUI 镜像
· 只是想让 Agent 更新到最新 → 不用跑这个,它会自己更新
执行完回来看状态变成「空闲」就算接入成功。
不扣客户点数、不计入客户记录。
| 检查项 | 结果 | |
|---|---|---|
| {{ c.ok ? '✅' : '🔴' }} | {{ c.name }} |
{{ c.value }}
💡 {{ c.tip }}
|
| 目录 | 占用 | 建议 |
|---|---|---|
| {{ r.path || r.name }} | {{ r.human || r.size }} | {{ r.tip || '' }} |
物理机接入流程:添加机器 → 点「接入」复制一键命令 → 在新机器上执行(自动下载 Agent、写配置、开机自启)→ 状态变「空闲」即接入成功。
API 平台(如 liblib):添加机器时选「API 平台」,填接口地址+密钥+并发数+模板ID 即可,平台会自动探活、派发任务、轮询结果。机器台账保存在 RDS,删除仅移除台账,不影响 OSS 已生成图片。
| ID | 模板名 | templateUuid | 绑定机器 | 输入映射 | 状态 | 更新时间 | 备注 | 操作 |
|---|---|---|---|---|---|---|---|---|
| {{ t.id }} | {{ t.name }} 默认 | {{ t.agent_name||'全部API机器' }} | {{ t.status==1?'启用':'停用' }} | {{ fmt(t.updated_at)||'-' }} | {{ t.description||'-' }} | |||
暂无模板。添加 liblib 平台发布审核过的工作流 JSON 后,API 机器即可按模板直连出图 | ||||||||
使用方式:1️⃣ 在 liblib 平台发布工作流并通过审核 → 2️⃣ 复制返回的 templateUuid JSON 到这里新增模板 → 3️⃣ 输入映射配置"哪张输入图注入哪个节点"(如 image1→218 主图)→ 4️⃣ API 机器直连出图时自动使用默认模板。每个模板绑定某台机器后仅该机器可用,不绑则所有 API 机器可用。
{{ tplForm.id?'编辑模板':'新增模板' }}
实时任务(排队/生成中)
| 任务 | 工作流 | 状态 | 机器 | 排队时间 | 已跑 |
|---|---|---|---|---|---|
| #{{ j.id }} | {{ j.workflow_title||('#'+j.workflow_id) }} | {{ stText(j.status) }} | {{ j.assigned_agent||'-' }} | {{ fmt(j.queue_at) }} | {{ j.status=='running'?(Math.floor((j.run_seconds||0)/60)+'分'+(j.run_seconds||0)%60+'秒'):'-' }} |
当前无进行中任务 | |||||
| 任务 | 工作流 | 类型 | 状态 | 机器 | 点数 | 时间 | 结果 | 操作 |
|---|---|---|---|---|---|---|---|---|
| #{{ j.id }} | {{ j.workflow_title||('#'+j.workflow_id) }} | 测试— | {{ stText(j.status) }} | {{ j.assigned_agent||'-' }} | {{ (j.bill? j.bill.cost : j.cost_points) }}已补{{ j.bill.comp }}已返 | {{ fmt(j.created_at) }} |
|
— |
暂无记录 | ||||||||