- server/db: 拆 4929 行 db.rs 单体为 db/ 目录,migrations.rs 引入 PRAGMA user_version
版本化迁移运行器(M1~M13)
- 任务引擎 Phase 6/7b/7c 改名收敛:EngineStageConfig→PhaseConfig、StagePolicy→ResumePolicy、
Converged→Completed、删除 task_type 列、success_method 拆 tlusty_/synspec_ 双列、
新增 tlusty_status/synspec_status 半失败阶段守卫
- 科学正确性加固:conv_check 任意行 NaN/Inf/溢出判无效(0 行容忍)、新增 spec_is_valid
校验 SYNSPEC 脏谱、itek_history 逐次迭代全量保真、fmt_abn powf 溢出饱和
- 用户配置真正接通:tlusty_chain/tlusty_input 由死字段经 调度器→TaskSpec→executor→runner
透传生效;config 加载期 validate + deny_unknown_fields + 解析失败记 warn
- 调度修复:H1 活锁(pending_strategies 跳过已失败策略)、种子查找错误不再静默降级冷启动
- dashboard: 阶段配置面板 tlusty_stage/synspec_stage、"已完成"标签、迭代诊断展示
- docs: 新增 database_refactor_design.md,同步 database/api/PIPELINE/workflow_detail
325 lines
19 KiB
HTML
325 lines
19 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>DCTS — 分布式恒星大气网格计算控制台</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||
<!-- 字重精简:Inter 去掉未使用的 300,Space Grotesk 去掉未使用的 500(仅 600/700 用于标题),
|
||
减少 2 个字体文件下载。display=swap 避免 FOIT。 -->
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&family=Space+Grotesk:wght@600;700&display=swap" rel="stylesheet">
|
||
<!-- 主题初始化移为外链(public/theme-init.js):使 CSP 可移除 script-src 'unsafe-inline'。
|
||
同步脚本在首帧前执行,保持防 FOUC 语义。 -->
|
||
<script src="/theme-init.js"></script>
|
||
<link rel="stylesheet" href="/src/style.css" />
|
||
</head>
|
||
<body>
|
||
<a href="#view-root" class="skip-link">跳到主内容</a>
|
||
<div id="app">
|
||
<!-- ===== 登录遮罩(鉴权) ===== -->
|
||
<div id="login-overlay" class="login-overlay" role="dialog" aria-modal="true" aria-labelledby="login-title" aria-describedby="login-subtitle">
|
||
<div class="login-card card">
|
||
<div class="login-header">
|
||
<h2 id="login-title">DCTS 控制台登录</h2>
|
||
<p id="login-subtitle">请输入管理员密码以访问管理控制台</p>
|
||
</div>
|
||
<form id="form-login" class="stack-col stack-col-md">
|
||
<div class="form-group">
|
||
<label for="input-admin-token">管理员密码</label>
|
||
<div class="input-with-toggle">
|
||
<input type="password" id="input-admin-token" class="form-input" placeholder="输入管理员密码..." required autocomplete="current-password" />
|
||
<button type="button" class="btn-toggle-password" aria-label="显示密码" title="显示/隐藏密码">
|
||
<svg class="icon-eye-open" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
||
<svg class="icon-eye-closed hidden" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/><path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div id="login-error-msg" class="login-error-msg alert-error hidden"></div>
|
||
<button type="submit" id="btn-submit-login" class="btn btn-primary">登录</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 顶部导航栏 (Header) -->
|
||
<header class="header">
|
||
<div class="logo-container">
|
||
<div class="logo-icon">
|
||
<svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
||
<!-- 恒星大气星核 (TLUSTY Stellar Core) -->
|
||
<path d="M12 3c0 4.5-4.5 9-9 9 4.5 0 9 4.5 9 9 0-4.5 4.5-9 9-9-4.5 0-9-4.5-9-9z" fill="currentColor" fill-opacity="0.35" stroke-width="1.5" />
|
||
<!-- 分布式计算集群网格轨道与算力节点 (Distributed Computing Grid Nodes) -->
|
||
<circle cx="12" cy="12" r="9.5" stroke-width="1.4" stroke-dasharray="4 2.5" />
|
||
<circle cx="12" cy="2.5" r="1.5" fill="currentColor" />
|
||
<circle cx="21.5" cy="12" r="1.5" fill="currentColor" />
|
||
<circle cx="12" cy="21.5" r="1.5" fill="currentColor" />
|
||
<circle cx="2.5" cy="12" r="1.5" fill="currentColor" />
|
||
</svg>
|
||
</div>
|
||
<div>
|
||
<h1 class="logo-title">DCTS 集群控制台</h1>
|
||
<p class="logo-subtitle">Distributed Computing TLUSTY / SYNSPEC Grid System</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="header-status">
|
||
<div class="status-indicator online" id="status-indicator-box" role="status" aria-live="polite">
|
||
<span class="status-dot"></span>
|
||
<span id="server-status-text">服务端正常运行</span>
|
||
</div>
|
||
<button id="btn-create-wf" class="btn btn-primary">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||
</svg>
|
||
创建工作流
|
||
</button>
|
||
<button id="refresh-btn" class="btn btn-secondary">
|
||
<svg class="icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M23 4v6h-6M1 20v-6h6"/>
|
||
<path d="M3.51 9a9 9 0 0114.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0020.49 15"/>
|
||
</svg>
|
||
刷新
|
||
</button>
|
||
<button id="btn-theme-toggle" class="btn btn-secondary" title="切换主题模式" aria-label="切换主题模式">
|
||
<svg class="icon-theme-sun hidden" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<circle cx="12" cy="12" r="5"></circle>
|
||
<line x1="12" y1="1" x2="12" y2="3"></line>
|
||
<line x1="12" y1="21" x2="12" y2="23"></line>
|
||
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
||
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
||
<line x1="1" y1="12" x2="3" y2="12"></line>
|
||
<line x1="21" y1="12" x2="23" y2="12"></line>
|
||
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
||
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
||
</svg>
|
||
<svg class="icon-theme-moon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||
</svg>
|
||
</button>
|
||
<button id="btn-logout" class="btn btn-secondary hidden" title="登出并清除 Token">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||
<polyline points="16 17 21 12 16 7"></polyline>
|
||
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||
</svg>
|
||
登出
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- 主内容区(视图由 src/router.js 挂载到 #view-root:首页 / 工作流详情页) -->
|
||
<main class="main-container">
|
||
<div id="view-root"></div>
|
||
</main>
|
||
|
||
|
||
<!-- 创建 / 编辑工作流 模态弹窗 -->
|
||
<div id="modal-create-wf" class="modal-backdrop hidden" role="dialog" aria-modal="true" aria-labelledby="modal-title">
|
||
<div class="modal-card">
|
||
<div class="modal-header">
|
||
<h3 id="modal-title">注册新的计算工作流</h3>
|
||
<button id="close-create-wf" class="modal-close" aria-label="关闭">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||
</button>
|
||
</div>
|
||
<form id="form-create-wf" class="stack-col stack-col-md">
|
||
<div class="form-group">
|
||
<label for="input-wf-name">工作流名称 (Identifier) <span class="req-mark" aria-hidden="true">*</span></label>
|
||
<input type="text" id="input-wf-name" class="form-input" placeholder="例如: sdB_cno" required
|
||
pattern="[A-Za-z0-9._\-]+" maxlength="64" autocomplete="off"
|
||
aria-describedby="wf-name-hint" />
|
||
<small id="wf-name-hint" class="field-hint">仅支持字母、数字、点、下划线与连字符,最长 64 字符</small>
|
||
<small id="wf-name-error" class="field-error hidden" role="alert"></small>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="input-wf-desc">描述信息</label>
|
||
<input type="text" id="input-wf-desc" class="form-input" placeholder="例如: sdB 6维恒星大气模型计算网格" />
|
||
</div>
|
||
<div class="form-group">
|
||
<div class="row-wrap" style="justify-content: space-between; align-items: center;">
|
||
<label for="input-wf-yaml">YAML 配置内容 (GridConfig) <span class="req-mark" aria-hidden="true">*</span></label>
|
||
<button type="button" id="btn-load-preset-yaml" class="btn btn-secondary btn-sm">填入默认示例</button>
|
||
</div>
|
||
<textarea id="input-wf-yaml" class="form-textarea" required placeholder="请粘贴工作流 YAML 参数网格定义..." aria-describedby="wf-yaml-hint"></textarea>
|
||
<small id="wf-yaml-hint" class="field-hint">定义 grid 参数网格与 chain 计算链,保存前服务端会校验 YAML 结构</small>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" id="cancel-create-wf" class="btn btn-secondary">取消</button>
|
||
<button type="submit" class="btn btn-primary">提交保存</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 工作流 YAML 配置编辑器(查看/编辑双模式,逻辑见 src/components/yamlEditor.js) -->
|
||
<div id="modal-view-wf" class="modal-backdrop hidden" role="dialog" aria-modal="true" aria-labelledby="view-wf-title">
|
||
<div class="modal-card modal-wide yaml-editor">
|
||
<div class="modal-header">
|
||
<div class="yaml-editor-head">
|
||
<h3 id="view-wf-title">工作流配置</h3>
|
||
<span id="yaml-editor-status"></span>
|
||
<span id="yaml-editor-dirty" class="dirty-dot hidden" title="有未保存的修改" aria-label="有未保存的修改"></span>
|
||
</div>
|
||
<button id="close-view-wf" class="modal-close" aria-label="关闭">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 查看模式:语法高亮 + 行号 -->
|
||
<div id="yaml-view-pane" class="yaml-view-pane">
|
||
<div class="yaml-scroll"><pre id="view-wf-yaml" class="yaml-highlight"></pre></div>
|
||
</div>
|
||
|
||
<!-- 编辑模式:等宽编辑区 + 校验错误/状态重置提示 -->
|
||
<div id="yaml-edit-pane" class="yaml-edit-pane hidden">
|
||
<div id="yaml-edit-error" class="yaml-edit-error hidden" role="alert"></div>
|
||
<div id="yaml-reset-warn" class="yaml-reset-warn hidden">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||
<span>保存后工作流状态将重置为「闲置」,需重新启动才能使新配置生效</span>
|
||
</div>
|
||
<textarea id="yaml-edit-area" class="yaml-edit-area" spellcheck="false" aria-label="YAML 配置编辑区"></textarea>
|
||
</div>
|
||
|
||
<div class="modal-footer yaml-editor-footer">
|
||
<span id="yaml-editor-meta" class="yaml-editor-meta tabular-num"></span>
|
||
<span id="yaml-editor-lock" class="yaml-editor-lock hidden"></span>
|
||
<button type="button" id="btn-export-yaml" class="btn btn-secondary btn-sm" title="下载导出当前 YAML 配置文件">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||
导出配置
|
||
</button>
|
||
<button type="button" id="btn-edit-yaml" class="btn btn-primary btn-sm">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></svg>
|
||
编辑
|
||
</button>
|
||
<button type="button" id="btn-cancel-edit-yaml" class="btn btn-secondary btn-sm hidden">取消</button>
|
||
<button type="button" id="btn-save-yaml" class="btn btn-primary btn-sm hidden">
|
||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
|
||
保存配置
|
||
</button>
|
||
<button type="button" id="btn-close-view-wf" class="btn btn-secondary btn-sm">关闭</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 重发 Token 结果展示模态弹窗 -->
|
||
<div id="modal-reissue-token" class="modal-backdrop hidden" role="dialog" aria-modal="true" aria-labelledby="reissue-modal-title">
|
||
<div class="modal-card">
|
||
<div class="modal-header">
|
||
<h3 id="reissue-modal-title">节点专属 Token 已重新颁发</h3>
|
||
<button id="reissue-close-btn" class="modal-close" aria-label="关闭">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p class="text-hint-mb">
|
||
旧 Token 已立即失效。请复制下方新 Token 并同步到该节点的本地 <code>.node_token</code> 文件后重启节点:
|
||
</p>
|
||
<pre id="reissue-token-content" class="code-pre-wrap"></pre>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" id="btn-copy-token" class="btn btn-primary">复制 Token</button>
|
||
<button type="button" id="btn-close-reissue-modal" class="btn btn-secondary">关闭</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 节点详情与管理模态弹窗(三点菜单入口:配额调整 / 启停 / 重发 Token) -->
|
||
<div id="modal-node-manage" class="modal-backdrop hidden" role="dialog" aria-modal="true" aria-labelledby="node-manage-title">
|
||
<div class="modal-card">
|
||
<div class="modal-header">
|
||
<h3 id="node-manage-title">节点详情与管理</h3>
|
||
<button id="node-manage-close-btn" class="modal-close" aria-label="关闭">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<!-- 基础信息 + 槽位展示 -->
|
||
<div id="node-manage-overview" class="node-manage-section">
|
||
<div class="form-group">
|
||
<label>节点 ID</label>
|
||
<div id="node-manage-id" class="node-manage-value mono"></div>
|
||
</div>
|
||
<div class="node-manage-grid">
|
||
<div class="form-group">
|
||
<label>节点状态</label>
|
||
<div id="node-manage-status"></div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>CPU 槽位 (占用/配额/最大)</label>
|
||
<div id="node-manage-slots" class="node-manage-value tabular-num"></div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>CPU / 内存</label>
|
||
<div id="node-manage-usage" class="node-manage-value tabular-num"></div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>心跳时间</label>
|
||
<div id="node-manage-heartbeat" class="node-manage-value"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 修改配额 (CPU 核数) -->
|
||
<div class="node-manage-section">
|
||
<h4 class="node-manage-section-title">并发槽位配额</h4>
|
||
<p class="text-hint-mb">限制该节点最大并发领用的任务数(CPU 核数)。正在运行的任务不会被中断,等其结束后自然回落到新配额以下;设为 0 可暂停接收新任务,留空清除限制恢复物理上限。</p>
|
||
<div class="row-wrap" style="gap: 0.5rem; align-items: flex-end;">
|
||
<div class="form-group" style="flex: 1; min-width: 120px;">
|
||
<label for="node-manage-quota-input">配额上限</label>
|
||
<input type="number" id="node-manage-quota-input" class="form-input" min="0" step="1" placeholder="留空 = 无限制" />
|
||
</div>
|
||
<button type="button" id="btn-node-save-quota" class="btn btn-primary btn-sm">保存配额</button>
|
||
<button type="button" id="btn-node-clear-quota" class="btn btn-secondary btn-sm">清除配额</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 节点调度控制 -->
|
||
<div class="node-manage-section">
|
||
<h4 class="node-manage-section-title">调度控制</h4>
|
||
<div class="row-wrap" style="gap: 0.5rem;">
|
||
<button type="button" id="btn-node-disable" class="btn btn-secondary btn-sm">停用节点(暂停分发)</button>
|
||
<button type="button" id="btn-node-enable" class="btn btn-primary btn-sm">启用节点(恢复分发)</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 安全管理 -->
|
||
<div class="node-manage-section">
|
||
<h4 class="node-manage-section-title">安全管理</h4>
|
||
<p class="text-hint-mb">重发后旧 Token 立即失效,该节点下次心跳/领用将 401 退出。请随后把新 Token 同步到节点。</p>
|
||
<button type="button" id="btn-node-reissue" class="btn btn-secondary btn-sm">重新颁发专属 Token</button>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" id="btn-close-node-manage" class="btn btn-secondary">关闭</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 页脚 -->
|
||
<footer class="footer">
|
||
<p>DCTS 分布式恒星大气计算系统 © 2026 TLUSTY/SYNSPEC Project</p>
|
||
</footer>
|
||
|
||
<!-- ===== 全局 Toast 提示容器 ===== -->
|
||
<div id="toast-container" class="toast-container" aria-live="polite" aria-atomic="true"></div>
|
||
|
||
<!-- ===== 通用自定义 Confirm 模态弹窗 ===== -->
|
||
<div id="modal-confirm" class="modal-backdrop hidden" role="dialog" aria-modal="true" aria-labelledby="confirm-modal-title" aria-describedby="confirm-modal-msg">
|
||
<div class="login-card card modal-card">
|
||
<div class="login-header">
|
||
<h3 id="confirm-modal-title" class="confirm-modal-title">确认操作</h3>
|
||
<p id="confirm-modal-msg" class="confirm-modal-msg">您确定要执行此操作吗?</p>
|
||
</div>
|
||
<div class="modal-footer confirm-modal-footer">
|
||
<button type="button" id="btn-confirm-cancel" class="btn btn-secondary">取消</button>
|
||
<button type="button" id="btn-confirm-ok" class="btn btn-primary">确定</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script type="module" src="/src/main.js"></script>
|
||
</body>
|
||
</html>
|