Wave 2: 五件套打通全链路(安装/检测/配置/授权/诊断)
- 五个适配器 YAML 全字段补齐(codex/claude-code/gemini/kimi/opencode) - agentdock-config:TOML/JSON 编解码 + 原子写 + 自动备份 - agentdock-diag:PATH/依赖版本/版本冲突/配置损坏四类规则 - agentdock-core:detectCli/previewAction/runAction 流式/readConfig/writeConfig/authStatus/diagnose - Tauri IPC 命令 + CLI 详情页/安装确认弹窗/配置表单/诊断页 - cargo test 75 项通过(含 4 项真机 ignored 自测),前端 build 通过
This commit is contained in:
@@ -1173,3 +1173,645 @@ button {
|
||||
[data-fx-tier="low"] .kpi-card:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Wave 2:CLI 详情页 / 安装确认弹窗 / 配置表单 / 诊断结果
|
||||
* 全部颜色/辉光/时长来自 tokens/(视觉规范 v1.2 §3.3–3.5 + v1.3)
|
||||
* ============================================================ */
|
||||
|
||||
/* 授权状态点(未授权 = 紫,静态,不发光不呼吸,§3.3) */
|
||||
.status-dot.auth {
|
||||
background: var(--ad-attention);
|
||||
}
|
||||
|
||||
/* ---------- CLI 详情页 ---------- */
|
||||
.cli-detail {
|
||||
max-width: var(--ad-frame-max);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.detail-back {
|
||||
margin-bottom: var(--ad-space-4);
|
||||
}
|
||||
|
||||
.cli-head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: var(--ad-space-6);
|
||||
padding: var(--ad-space-6);
|
||||
margin-bottom: var(--ad-space-5);
|
||||
}
|
||||
|
||||
.cli-head-main {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--ad-space-4);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.cli-head-info {
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.cli-head-name {
|
||||
font-size: var(--ad-text-xl-size);
|
||||
font-weight: var(--ad-text-xl-weight);
|
||||
}
|
||||
|
||||
.cli-head-vendor {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-s-size);
|
||||
}
|
||||
|
||||
.cli-head-license {
|
||||
color: var(--ad-text-3);
|
||||
}
|
||||
|
||||
.cli-head-meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--ad-space-2);
|
||||
margin-top: var(--ad-space-1);
|
||||
}
|
||||
|
||||
.status-badge-mini {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.cli-head-path {
|
||||
max-width: 420px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cli-head-unconfirmed {
|
||||
color: var(--ad-text-3);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.cli-head-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: var(--ad-space-3);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.auth-light {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.auth-light-text {
|
||||
color: var(--ad-text-1);
|
||||
font-size: var(--ad-text-s-size);
|
||||
}
|
||||
|
||||
.cli-head-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-3);
|
||||
}
|
||||
|
||||
/* 危险文字按钮(§3.3:卸载 = 文字按钮,悬停变红) */
|
||||
.btn-text-danger {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-2);
|
||||
height: 36px;
|
||||
padding: 0 var(--ad-space-2);
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-m-size);
|
||||
cursor: pointer;
|
||||
transition: color var(--ad-dur-fast) var(--ad-ease-out);
|
||||
}
|
||||
|
||||
.btn-text-danger:hover:not(:disabled) {
|
||||
color: var(--ad-danger);
|
||||
}
|
||||
|
||||
.btn-text-danger:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* ---------- 标签页(§3.3:底部 2px 青条 + 青色文字) ---------- */
|
||||
.tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-5);
|
||||
border-bottom: 1px solid var(--ad-border);
|
||||
margin-bottom: var(--ad-space-5);
|
||||
}
|
||||
|
||||
.tab {
|
||||
position: relative;
|
||||
height: 40px;
|
||||
padding: 0 var(--ad-space-2);
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-m-size);
|
||||
cursor: pointer;
|
||||
transition: color var(--ad-dur-fast) var(--ad-ease-out);
|
||||
}
|
||||
|
||||
.tab:hover {
|
||||
color: var(--ad-text-1);
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
color: var(--ad-primary);
|
||||
}
|
||||
|
||||
.tab.active::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -1px;
|
||||
height: 2px;
|
||||
background: var(--ad-primary);
|
||||
}
|
||||
|
||||
.cli-detail-body {
|
||||
max-width: 720px;
|
||||
}
|
||||
|
||||
/* ---------- 概览 / 文档块 ---------- */
|
||||
.detail-block {
|
||||
margin-bottom: var(--ad-space-5);
|
||||
}
|
||||
|
||||
.detail-block-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-2);
|
||||
font-size: var(--ad-text-l-size);
|
||||
font-weight: var(--ad-text-l-weight);
|
||||
margin-bottom: var(--ad-space-3);
|
||||
}
|
||||
|
||||
.detail-block-text {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-m-size);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.detail-channels {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.detail-channel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.detail-channel-pkg {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.detail-note {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--ad-space-2);
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-s-size);
|
||||
padding: var(--ad-space-4);
|
||||
border: 1px solid var(--ad-border);
|
||||
border-radius: var(--ad-radius-m);
|
||||
background: var(--ad-bg-1);
|
||||
}
|
||||
|
||||
.detail-commands {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-3);
|
||||
}
|
||||
|
||||
.detail-command {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-3);
|
||||
}
|
||||
|
||||
.detail-command-desc {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-s-size);
|
||||
}
|
||||
|
||||
/* ---------- 诊断结果(§3.5) ---------- */
|
||||
.diag-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-3);
|
||||
padding: var(--ad-space-4);
|
||||
margin-bottom: var(--ad-space-4);
|
||||
background: var(--ad-bg-1);
|
||||
border: 1px solid var(--ad-border);
|
||||
border-radius: var(--ad-radius-m);
|
||||
font-size: var(--ad-text-m-size);
|
||||
}
|
||||
|
||||
.diag-finding {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
margin-bottom: var(--ad-space-3);
|
||||
background: var(--ad-bg-1);
|
||||
border: 1px solid var(--ad-border);
|
||||
border-radius: var(--ad-radius-m);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.diag-sev-bar {
|
||||
width: 3px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.diag-sev-bar.diag-sev-info,
|
||||
.diag-sev-tag.diag-sev-info {
|
||||
background: var(--ad-attention);
|
||||
color: var(--ad-attention);
|
||||
}
|
||||
|
||||
.diag-sev-bar.diag-sev-warn,
|
||||
.diag-sev-tag.diag-sev-warn {
|
||||
background: var(--ad-warning);
|
||||
color: var(--ad-warning);
|
||||
}
|
||||
|
||||
.diag-sev-bar.diag-sev-error,
|
||||
.diag-sev-tag.diag-sev-error {
|
||||
background: var(--ad-danger);
|
||||
color: var(--ad-danger);
|
||||
}
|
||||
|
||||
.diag-finding-body {
|
||||
flex: 1;
|
||||
padding: var(--ad-space-4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.diag-finding-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.diag-sev-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
padding: 0 var(--ad-space-2);
|
||||
border-radius: var(--ad-radius-s);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.diag-finding-rule {
|
||||
color: var(--ad-text-3);
|
||||
font-family: var(--ad-font-mono);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.diag-finding-msg {
|
||||
color: var(--ad-text-1);
|
||||
font-size: var(--ad-text-m-size);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.diag-evidence-toggle {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.diag-evidence {
|
||||
padding: var(--ad-space-3);
|
||||
background: var(--ad-bg-0);
|
||||
border: 1px solid var(--ad-border);
|
||||
border-radius: var(--ad-radius-s);
|
||||
font-family: var(--ad-font-mono);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
color: var(--ad-text-2);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* ---------- 弹窗(§3.6) ---------- */
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--ad-modal-mask);
|
||||
}
|
||||
|
||||
.modal {
|
||||
width: min(560px, calc(100vw - 48px));
|
||||
max-height: calc(100vh - 96px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--ad-bg-2);
|
||||
border-radius: var(--ad-radius-l);
|
||||
box-shadow: var(--ad-shadow-pop);
|
||||
border: 1px solid var(--ad-border);
|
||||
}
|
||||
|
||||
.modal-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: var(--ad-space-4) var(--ad-space-5);
|
||||
border-bottom: 1px solid var(--ad-border);
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: var(--ad-text-l-size);
|
||||
font-weight: var(--ad-text-l-weight);
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--ad-text-2);
|
||||
cursor: pointer;
|
||||
border-radius: var(--ad-radius-s);
|
||||
}
|
||||
|
||||
.modal-close:hover {
|
||||
color: var(--ad-text-1);
|
||||
background: var(--ad-bg-3);
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: var(--ad-space-5);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-foot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: var(--ad-space-3);
|
||||
padding: var(--ad-space-4) var(--ad-space-5);
|
||||
border-top: 1px solid var(--ad-border);
|
||||
}
|
||||
|
||||
/* ---------- 确认弹窗内容 ---------- */
|
||||
.confirm-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-4);
|
||||
}
|
||||
|
||||
.confirm-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.confirm-label {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.confirm-text {
|
||||
color: var(--ad-text-1);
|
||||
font-size: var(--ad-text-m-size);
|
||||
}
|
||||
|
||||
.confirm-empty {
|
||||
color: var(--ad-text-3);
|
||||
font-size: var(--ad-text-s-size);
|
||||
}
|
||||
|
||||
.confirm-cmd {
|
||||
padding: var(--ad-space-3);
|
||||
background: var(--ad-bg-0);
|
||||
border: 1px solid var(--ad-border);
|
||||
border-radius: var(--ad-radius-s);
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.confirm-files {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.confirm-note {
|
||||
color: var(--ad-warning);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
/* ---------- 流式执行日志 ---------- */
|
||||
.run-log {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-1);
|
||||
max-height: 320px;
|
||||
overflow-y: auto;
|
||||
font-family: var(--ad-font-mono);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.run-log-wait {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-2);
|
||||
color: var(--ad-text-2);
|
||||
}
|
||||
|
||||
.run-log-line {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--ad-space-2);
|
||||
color: var(--ad-text-2);
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.run-log-line.step {
|
||||
color: var(--ad-primary);
|
||||
}
|
||||
|
||||
.run-log-line.stderr {
|
||||
color: var(--ad-warning);
|
||||
}
|
||||
|
||||
.run-log-line.error {
|
||||
color: var(--ad-danger);
|
||||
}
|
||||
|
||||
.spin {
|
||||
animation: ad-spin 1.2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes ad-spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- 配置表单(§3.4) ---------- */
|
||||
.config-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-5);
|
||||
max-width: 640px;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-2);
|
||||
}
|
||||
|
||||
.field-label {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-s-size);
|
||||
}
|
||||
|
||||
.field-required {
|
||||
color: var(--ad-primary);
|
||||
}
|
||||
|
||||
.field-control {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.field-control input {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
padding: 0 var(--ad-space-3);
|
||||
border: 1px solid var(--ad-border);
|
||||
border-radius: var(--ad-radius-m);
|
||||
background: var(--ad-bg-0);
|
||||
color: var(--ad-text-1);
|
||||
font-size: var(--ad-text-m-size);
|
||||
outline: none;
|
||||
transition: border-color var(--ad-dur-micro) var(--ad-ease-out),
|
||||
box-shadow var(--ad-dur-micro) var(--ad-ease-out);
|
||||
}
|
||||
|
||||
.field-control input::placeholder {
|
||||
color: var(--ad-text-3);
|
||||
}
|
||||
|
||||
.field-control input:focus {
|
||||
border-color: var(--ad-primary);
|
||||
box-shadow: var(--ad-glow-primary);
|
||||
}
|
||||
|
||||
.field-control input[type="password"] {
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
.field-lock {
|
||||
position: absolute;
|
||||
left: var(--ad-space-3);
|
||||
color: var(--ad-text-2);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.field-control .field-lock + input {
|
||||
padding-left: 32px;
|
||||
}
|
||||
|
||||
.field-eye {
|
||||
position: absolute;
|
||||
right: var(--ad-space-2);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: none;
|
||||
background: none;
|
||||
color: var(--ad-text-2);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.field-eye:hover {
|
||||
color: var(--ad-text-1);
|
||||
}
|
||||
|
||||
.field-help {
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.field-keyring-note {
|
||||
color: var(--ad-attention);
|
||||
}
|
||||
|
||||
.config-file-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--ad-space-2);
|
||||
padding-top: var(--ad-space-4);
|
||||
border-top: 1px solid var(--ad-border);
|
||||
color: var(--ad-text-2);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.config-savebar {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--ad-space-4);
|
||||
padding: var(--ad-space-4) 0;
|
||||
background: linear-gradient(180deg, transparent, var(--ad-bg-0) 40%);
|
||||
}
|
||||
|
||||
.config-save-msg {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--ad-space-1);
|
||||
font-size: var(--ad-text-xs-size);
|
||||
}
|
||||
|
||||
.save-ok {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--ad-space-1);
|
||||
color: var(--ad-success);
|
||||
}
|
||||
|
||||
.save-detail {
|
||||
color: var(--ad-text-2);
|
||||
}
|
||||
|
||||
.save-error {
|
||||
color: var(--ad-danger);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user