- 生信进度:后端新增 stage_progress 事件帧+进度解析白名单(rnaseq_qc/sample_qc), kernel 日志流式落盘(20行/1s flush+fsync),logs 分页端点(offset/limit/eof), 事件 seq 跨重启扫描续增(2026-09-17 断流修复);前端 FlowProgressCard 确定性/ 不确定两态进度条+点击定位到生信任务 TAB,BioJobsPane DAG 行展开滚动日志区 (3s 轮询),log_tail 4000 截断,重跑 stage_started 清零进度 - 图片注入:figures 三源重构(标准DOI图库主路径/遗留体系兜底/PMC兜底), [[FIG:]] 宽松归一化识别 PMC/PMID/DOI 三种形态,引文兜底扩展至 [PMCID:]/[DOI:] 且标记未满配额继续注入,注入预算 90s/10篇(175 实测校准), PMC graphic 无 content-type 宽松正则,空结果不缓存(176 冷连接三连败修复) - QA 启动自愈:start.sh 启动前等 Qdrant readyz(30min)+Neo4j TCP(10min); backend_guard 标签校验改子集判定 - 样本配对:同 inode 去重优先真实文件,R1/R2 归一配对一对一认领 - gitignore 新增 *.bak-*/*.before-*/bioflow_service/bioflow.db 测试:bioflow_service pytest 358/358,前端 bioflow vitest 205/205
352 lines
15 KiB
JavaScript
352 lines
15 KiB
JavaScript
// i18n/bioflow.js —— 生信流程编排(P2-P5)全部用户可见文案(dev3 A3 归属)
|
||
// 纪律:文案全部进本文件,不碰 labels.js(红线);类名遵循 UI_SPEC §8.7。
|
||
|
||
/** 工作台生信 TAB 定义(BenchPanel/AppShell 共用;探活失败时整个 TAB 隐藏) */
|
||
export const BIOFLOW_TABS = [
|
||
{ key: 'biojobs', label: '生信任务' },
|
||
{ key: 'bioarchive', label: '生信档案' },
|
||
];
|
||
|
||
export const BF = {
|
||
// ---- 生信入口(Composer 分流提示/意图错误兜底) ----
|
||
bioflowRouteError: '生信分析暂不可用,已按知识问答处理',
|
||
// ---- 块类型标识(消息持久化用) ----
|
||
// ---- FlowPathCard(FR-BIO-002/003/004) ----
|
||
pathCardTitle: '🧬 分析路径选择',
|
||
pathCandidatePurposeLabel: '用途',
|
||
pathAutoFilled: '已自动补全',
|
||
pathConfirm: '确认此路径',
|
||
pathEmpty: '暂无候选路径',
|
||
pathPlanning: '正在分析需求并规划分析路径…',
|
||
formConfirmed: '参数已确认',
|
||
pathCreated: '任务已创建',
|
||
pathConfirming: '确认中…',
|
||
pathFallback: '规划降级:',
|
||
pathReuseNote: '复用存档',
|
||
pathReuseNoteSuffix: '的方法',
|
||
pathStageChain: '阶段链',
|
||
pathStagePurpose: '用途',
|
||
pathStageEstimated: '预计耗时',
|
||
pathStageEstimatedUnknown: '视数据规模',
|
||
pathStageTitle: '🧬 确认分析路径',
|
||
pathStageHint: '以下阶段链将按顺序执行,确认后创建任务',
|
||
pathStageCreate: '确认创建任务',
|
||
pathStageCreating: '创建中…',
|
||
// ---- FlowFormCard(FR-BIO-008/009/010) ----
|
||
formTitle: '⚙ {stage} 步骤 · 可调整参数',
|
||
formPrefix: '{stage} 步骤,可调整参数如下,可按需调整,调整完毕后继续',
|
||
formSourceContract: '默认值来源:阶段契约文档',
|
||
formSourcePrefill: '默认值来源:参数预填',
|
||
formSourceArchive: '默认值来源:存档 {name}',
|
||
formSourceUser: '默认值来源:任务参数',
|
||
formSourceUnknown: '默认值来源:未知',
|
||
formContinue: '继续',
|
||
formSubmitting: '提交中…',
|
||
formAutoLabel: '自动连续执行',
|
||
formAutoHint: '开启后按推荐参数自动连续跑完全程',
|
||
formTypeError: '参数类型不合法',
|
||
formRangeError: '取值范围 {min} ~ {max}',
|
||
formRequiredError: '必填参数不能为空',
|
||
formSubmitError: '提交失败',
|
||
formKeyEnter: '按 Enter 继续',
|
||
// ---- FlowFileCard(FR-BIO-005/006/007) ----
|
||
fileCardTitle: '📁 数据文件引导',
|
||
fileDropHint: '将数据文件拖入此处上传,或点击选择文件',
|
||
fileDropBusy: '上传中…',
|
||
fileRequiredTitle: '请将 {files} 数据文件拖入窗口上传至服务器,或在聊天窗口中指定数据文件的具体路径',
|
||
fileSelect: '选择文件',
|
||
fileUploading: '上传中',
|
||
fileUploadDone: '已上传',
|
||
fileUploadError: '上传失败',
|
||
fileUploadRetry: '重试',
|
||
fileRegisterPlaceholder: '或输入服务器上的文件路径(如 /data/examples/SPL.fa)',
|
||
fileRegister: '登记路径',
|
||
fileRegistering: '登记中…',
|
||
fileRegistered: '已登记',
|
||
filePathError: '路径登记失败',
|
||
fileSizeBytes: 'B',
|
||
// ---- FlowProgressCard(FR-BIO-011/012/013) ----
|
||
progTitle: '⚙ 生信流程进度',
|
||
progBadgeRunning: '运行中',
|
||
progBadgeDone: '已完成',
|
||
progBadgeFailed: '失败',
|
||
progBadgePaused: '已暂停',
|
||
progBadgeCreated: '等待开始',
|
||
progBadgeArchived: '已存档',
|
||
stepWaiting: '等待',
|
||
stepAwaitFiles: '等待文件',
|
||
stepWaitingConfirm: '待确认',
|
||
stepQueued: '排队中',
|
||
stepRunning: '运行中',
|
||
stepDone: '已完成',
|
||
stepFailed: '失败',
|
||
stepSkipped: '已跳过',
|
||
progRerun: '重跑',
|
||
progSkip: '跳过',
|
||
progRerunWithParams: '改参数重跑',
|
||
progLogPlaceholder: '暂无日志',
|
||
progGroupMore: '个阶段',
|
||
progPause: '暂停',
|
||
progResume: '继续',
|
||
progPausing: '暂停中…',
|
||
progResuming: '继续中…',
|
||
progActionError: '操作失败',
|
||
progLocateHint: '点击定位到生信任务面板',
|
||
// ---- FlowArchiveCard(FR-BIO-020/021) ----
|
||
archiveTitle: '本次生信任务已完成,是否存档?可按你的要求命名并描述',
|
||
archiveNamePlaceholder: '存档名称(如:水稻 SPL 鉴定 2026-09)',
|
||
archiveDescPlaceholder: '存档描述(可选)',
|
||
archiveDo: '存档',
|
||
archiveDismiss: '放弃',
|
||
archiveArchiving: '存档中…',
|
||
archiveError: '存档失败',
|
||
archiveDonePrefix: '任务已存档:',
|
||
archiveLocationLabel: '位置',
|
||
archiveSizeLabel: '大小',
|
||
archiveSizeUnknown: '未知大小',
|
||
// ---- 失败表单(改参数重跑弹出) ----
|
||
rerunFormTitle: '⚙ {stage} 步骤 · 改参数重跑',
|
||
rerunFormSubmit: '重跑',
|
||
// ---- BioJobsPane(FR-BIO-024) ----
|
||
jobsEmpty: '暂无生信任务。在对话中提出生信分析需求(如「帮我跑水稻 SPL 家族鉴定」)即可创建任务。',
|
||
jobsLoading: '任务加载中…',
|
||
jobsLoadError: '任务列表加载失败',
|
||
jobsReload: '重新加载',
|
||
jobsSearchPlaceholder: '按标题/状态筛选(可选)',
|
||
jobsStageProgress: '进度',
|
||
jobsStagesTitle: '阶段链',
|
||
jobsManifestTitle: 'manifest',
|
||
jobsLogTitle: '日志尾',
|
||
jobsLogEmpty: '暂无日志',
|
||
jobsManifestEmpty: 'manifest 未产出',
|
||
jobsDelete: '删除',
|
||
jobsDeleteConfirm: '确定删除任务「{title}」?删除后不可恢复。',
|
||
jobsConfirmYes: '删除',
|
||
jobsConfirmNo: '取消',
|
||
jobsDeleteRunning: '运行中不可删除',
|
||
jobsStatusCreated: '等待开始',
|
||
jobsStatusAwaitInputs: '等待输入',
|
||
jobsStatusRunning: '运行中',
|
||
jobsStatusPaused: '已暂停',
|
||
jobsStatusDone: '已完成',
|
||
jobsStatusFailed: '失败',
|
||
jobsStatusArchiving: '存档中',
|
||
jobsStatusArchived: '已存档',
|
||
jobsRerun: '重跑失败阶段',
|
||
jobsRerunning: '重跑中…',
|
||
jobsManifestLoading: 'manifest 加载中…',
|
||
jobsManifestError: 'manifest 加载失败',
|
||
jobsDetailLoading: '详情加载中…',
|
||
// ---- BioArchivePane(FR-BIO-022/023) ----
|
||
archivePaneEmpty: '暂无生信档案。任务完成后在对话中存档,即可在此回看与复用。',
|
||
archivePaneLoading: '档案加载中…',
|
||
archivePaneLoadError: '档案列表加载失败',
|
||
archivePaneReload: '重新加载',
|
||
archivePaneDelete: '删除',
|
||
archivePaneDeleteConfirm: '确定删除档案「{name}」?磁盘目录将一并删除。',
|
||
archivePaneReuse: '复用发起',
|
||
archivePaneDownload: '下载打包',
|
||
archivePaneOpenReport: '查看报告',
|
||
archivePaneReusing: '发起中…',
|
||
archivePaneStages: '阶段链',
|
||
archivePaneParams: '参数',
|
||
archivePaneProducts: '产物文件',
|
||
archivePaneDescription: '描述',
|
||
archivePaneNoProducts: '无产物清单',
|
||
archivePaneNoReport: '该档案无报告',
|
||
archivePaneReportLoading: '报告加载中…',
|
||
archivePaneReportError: '报告加载失败',
|
||
archivePaneReuseSuccess: '复用任务已创建',
|
||
archivePaneReuseError: '复用发起失败',
|
||
archivePaneReusedCount: '已复用 {n} 次',
|
||
// ---- 复用预填表单(FR-BIO-023;聊天流内) ----
|
||
reuseFormTitle: '🧬 复用存档「{name}」发起新任务',
|
||
reuseFormHint: '阶段链与参数已按存档预填,可按需调整后创建任务',
|
||
reuseFormCreate: '创建任务',
|
||
reuseFormCreating: '创建中…',
|
||
reuseFormError: '创建任务失败',
|
||
// ---- 探活显隐(FR-BIO-025) ----
|
||
bioflowUnavailableNote: '生信服务不可用(探活失败)',
|
||
// ---- 流程知识库引用块(FR-BIO-026) ----
|
||
flowQaEmpty: '暂无引用',
|
||
// ---- 阶段状态文字(进度卡/面板共用) ----
|
||
stageStatusWaiting: '等待',
|
||
stageStatusAwaitFiles: '等待文件',
|
||
stageStatusWaitingConfirm: '待确认',
|
||
stageStatusQueued: '排队中',
|
||
stageStatusRunning: '运行中',
|
||
stageStatusDone: '已完成',
|
||
stageStatusFailed: '失败',
|
||
stageStatusSkipped: '已跳过',
|
||
stageStatusPaused: '已暂停',
|
||
stageStatusUnknown: '未知',
|
||
|
||
// ---- 用户自定义扩展分析(EXTENSION_CONTRACT.md §4 引导卡文案) ----
|
||
// 上传引导卡(extension_upload 块)
|
||
extUploadTitle: '🧩 扩展上传引导',
|
||
extUploadPrefix: '请上传扩展代码包:支持 zip / tar / tar.gz 文件,或直接拖入目录(目录内的文件将按相对路径上传)。',
|
||
extUploadDropHint: '将 zip/tar 文件或目录拖入此处上传,或点击选择文件',
|
||
extPickDir: '选择文件夹',
|
||
extArchive: '归档文件',
|
||
extDir: '目录',
|
||
extUploadEmpty: '未读取到任何文件',
|
||
extUploadBusy: '上传中…',
|
||
extUploadNameLabel: '名称',
|
||
extUploadNamePlaceholder: '如:测序质量统计',
|
||
extUploadCommandLabel: '运行命令',
|
||
extUploadCommandPlaceholder: '如:python quality_stats.py --fastq input.fastq --out results/',
|
||
extUploadImageLabel: '运行镜像',
|
||
extUploadImageHint: '8 个 base 镜像供选择(默认 bioflow-gf 工具链最全)',
|
||
extUploadGoldenLabel: '金标输出(可选)',
|
||
extUploadSubmit: '上传并创建',
|
||
extUploadSubmitting: '创建中…',
|
||
extUploadError: '上传失败',
|
||
extUploadCreated: '扩展已创建',
|
||
extUploadNoMatchPrefix: '没有匹配的已发布扩展,是否创建新扩展?',
|
||
extUploadNameRequired: '请填写名称',
|
||
extUploadCommandRequired: '请填写运行命令',
|
||
extUploadZipRequired: '请先选择 zip 包',
|
||
extUploadDone: '已上传',
|
||
// AI 转换卡(extension_build 块)
|
||
extBuildTitle: '🧩 AI 转换 · 命令模板与依赖',
|
||
extBuildStatus: '转换中…',
|
||
extBuildStatusFailed: '转换失败',
|
||
extBuildTemplateLabel: '命令模板',
|
||
extBuildTemplateHint: '占位符白名单:{code_dir} {input_dir} {input_file} {input_hmm} {input_fasta} {input_query_fasta} {input_reference_fasta} {input_pep_fasta} {input_cds_fasta} {input_id_file} {output_dir} {work_dir} + {param_<name>};{output_dir} 必含。',
|
||
extBuildDepsLabel: '依赖',
|
||
extBuildDepsEmpty: '纯标准库,无额外依赖',
|
||
extBuildPipLabel: 'pip',
|
||
extBuildAptLabel: 'apt',
|
||
extBuildImageLabel: '推荐镜像',
|
||
extBuildTriggersLabel: '自然语言触发词',
|
||
extBuildTriggersHint: '逗号分隔;发布后用户可用这些短语触发运行',
|
||
extBuildTypeLabel: '分析类型',
|
||
extBuildParamsLabel: '参数',
|
||
extBuildParamsEmpty: '无需参数',
|
||
extBuildSubmit: '提交修正',
|
||
extBuildSubmitting: '提交中…',
|
||
extBuildSkip: '跳过(使用 AI 结果)',
|
||
extBuildError: '提交失败',
|
||
extBuildFieldRequired: '必填不能为空',
|
||
// 试运行卡(extension_trial 块)
|
||
extTrialTitle: '🧩 试运行',
|
||
extTrialRunning: '试运行中…',
|
||
extTrialDone: '试运行通过',
|
||
extTrialFailed: '试运行失败',
|
||
extTrialRepairing: 'AI 修复中…',
|
||
extTrialLogLabel: '日志尾',
|
||
extTrialLogPlaceholder: '暂无日志',
|
||
extTrialRun: '运行试运行',
|
||
extTrialRerun: '重新试运行',
|
||
extTrialTestHint: '上传测试输入文件(可选:金标输出用于对比验证)',
|
||
extTrialRepairBtn: 'AI 修复',
|
||
extTrialRepairSuggestionLabel: '修复建议',
|
||
extTrialRepairCount: '已修复 {n} 轮',
|
||
extTrialRepairFailed: '修复失败',
|
||
extTrialExitCode: '退出码',
|
||
extTrialInputEmpty: '请先选择测试输入文件',
|
||
extTrialNoExtId: '扩展未创建,无法试运行',
|
||
// 金标/确认卡(extension_validate 块)
|
||
extValidateTitle: '🧩 金标验证 · 参数确认',
|
||
extValidateGoldenLabel: '金标对比结果',
|
||
extValidateGoldenNone: '未提供金标数据',
|
||
extValidateConfirm: '确认',
|
||
extValidateConfirming: '确认中…',
|
||
extValidateError: '确认失败',
|
||
// 发布卡(extension_publish 块)
|
||
extPublishTitle: '🧩 发布扩展',
|
||
extPublishHint: '发布后该扩展可被自然语言触发。触发词可编辑(逗号分隔)。',
|
||
extPublishTriggersLabel: '触发词',
|
||
extPublishDo: '确认发布',
|
||
extPublishPublishing: '发布中…',
|
||
extPublishError: '发布失败',
|
||
extPublishedTitle: '扩展已发布',
|
||
extPublishedHint: '之后可在对话中说「帮我用 {name} 分析…」触发运行',
|
||
// 候选卡(extension_candidates 块)
|
||
extCandidatesTitle: '🧩 匹配到多个扩展,请选择',
|
||
extCandidatesPurposeLabel: '用途',
|
||
extCandidatesEmpty: '暂无候选扩展',
|
||
// 参数确认卡(extension_confirm 块)
|
||
extConfirmTitle: '🧩 运行参数确认',
|
||
extConfirmHint: '将运行该扩展,请确认输入参数(可直接修改)',
|
||
extConfirmFilesLabel: '需要输入文件',
|
||
extConfirmRun: '确认运行',
|
||
extConfirmRunning: '运行请求中…',
|
||
extConfirmError: '运行请求失败',
|
||
// 运行卡(extension_run 块)
|
||
extRunTitle: '🧩 扩展运行进度',
|
||
extRunBadgeCreated: '等待开始',
|
||
extRunBadgeRunning: '运行中',
|
||
extRunBadgeDone: '已完成',
|
||
extRunBadgeFailed: '失败',
|
||
extRunLogLabel: '日志尾',
|
||
extRunLogPlaceholder: '暂无日志',
|
||
extRunOutputsLabel: '输出产物',
|
||
extRunOutputsEmpty: '无输出清单',
|
||
extRunExitCode: '退出码',
|
||
// 侧栏「扩展」入口(session 列表底部)
|
||
extRailTitle: '扩展',
|
||
extPaneTitle: '扩展管理',
|
||
extPaneEmpty: '暂无扩展。在对话中说「帮我创建一个扩展:统计 fastq 质量」即可创建。',
|
||
extPaneLoading: '扩展加载中…',
|
||
extPaneLoadError: '扩展列表加载失败',
|
||
extPaneReload: '重新加载',
|
||
extPaneDelete: '删除',
|
||
extPaneDeleteConfirm: '确定删除扩展「{name}」?删除后不可恢复。',
|
||
extPaneConfirmYes: '删除',
|
||
extPaneConfirmNo: '取消',
|
||
extPaneStatus: '状态',
|
||
extPaneStatusDraft: '草稿',
|
||
extPaneStatusPublished: '已发布',
|
||
extPaneRuns: '运行历史',
|
||
extPaneRunsLoading: '历史加载中…',
|
||
extPaneRunsEmpty: '暂无运行记录',
|
||
extPaneRunsError: '历史加载失败',
|
||
extPaneRunsReload: '重试',
|
||
extPaneRunsCount: '共 {n} 次运行',
|
||
};
|
||
|
||
/** 8 个 base 镜像(与 176 部署树 stage_image_map.json 一致;默认 bioflow-gf 工具链最全。
|
||
* 扩展上传卡下拉与 AI 转换卡推荐镜像共用此表。 */
|
||
export const EXT_BASE_IMAGES = [
|
||
{ value: 'bioflow-gf', label: 'bioflow-gf(默认,工具链最全)' },
|
||
{ value: 'bioflow-gfpy', label: 'bioflow-gfpy' },
|
||
{ value: 'bioflow-rnaseq', label: 'bioflow-rnaseq' },
|
||
{ value: 'bioflow-rnaR', label: 'bioflow-rnaR' },
|
||
{ value: 'bioflow-wgs', label: 'bioflow-wgs' },
|
||
{ value: 'bioflow-interproscan', label: 'bioflow-interproscan' },
|
||
{ value: 'bioflow-pan', label: 'bioflow-pan' },
|
||
{ value: 'bioflow-rde', label: 'bioflow-rde' },
|
||
];
|
||
|
||
/** 阶段状态 → 展示文字(进度卡与面板共用同一映射) */
|
||
export function stageStatusText(status) {
|
||
return {
|
||
waiting: BF.stageStatusWaiting,
|
||
await_files: BF.stageStatusAwaitFiles,
|
||
waiting_confirm: BF.stageStatusWaitingConfirm,
|
||
queued: BF.stageStatusQueued,
|
||
running: BF.stageStatusRunning,
|
||
done: BF.stageStatusDone,
|
||
failed: BF.stageStatusFailed,
|
||
skipped: BF.stageStatusSkipped,
|
||
paused: BF.stageStatusPaused,
|
||
}[status] || BF.stageStatusUnknown;
|
||
}
|
||
|
||
/** 任务状态 → 展示文字 */
|
||
export function jobStatusText(status) {
|
||
return {
|
||
created: BF.jobsStatusCreated,
|
||
await_inputs: BF.jobsStatusAwaitInputs,
|
||
running: BF.jobsStatusRunning,
|
||
paused: BF.jobsStatusPaused,
|
||
done: BF.jobsStatusDone,
|
||
failed: BF.jobsStatusFailed,
|
||
archiving: BF.jobsStatusArchiving,
|
||
archived: BF.jobsStatusArchived,
|
||
}[status] || status || BF.stageStatusUnknown;
|
||
}
|
||
|
||
export default BF;
|