Files
secrets/apps/desktop/dist/index.html
agent 57c3efb70e feat(auth): 服务端托管 Google OAuth;修复未解锁 vault 时 bootstrap
- API:桌面登录 session、Google 托管回调与轮询
- Desktop:轮询登录;bootstrap 在 vault 未解锁时不返回 shell,避免跳过主密码
- 文档与 deploy/.env.example 对齐 GOOGLE_OAUTH_* 与 SECRETS_PUBLIC_BASE_URL
2026-04-14 22:05:11 +08:00

280 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Secrets</title>
<link rel="stylesheet" href="./styles.css" />
<script src="./disable-features.js"></script>
</head>
<body>
<div id="login-view" class="login-screen hidden">
<div class="window-titlebar login-titlebar" data-tauri-drag-region aria-hidden="true"></div>
<div class="login-card">
<div class="login-main">
<div class="login-emblem" aria-hidden="true">
<svg class="login-lock-icon" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<circle cx="12" cy="16" r="1"></circle>
<rect x="3" y="10" width="18" height="12" rx="2"></rect>
<path d="M7 10V7a5 5 0 0 1 10 0v3"></path>
</svg>
</div>
<div class="login-title-block">
<h1>Secrets</h1>
<p class="login-subtle">用 AI 安全地管理和使用密钥</p>
</div>
<div class="login-actions">
<button id="login-button" class="primary login-google-button">
<svg class="login-google-mark" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" />
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" />
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" />
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" />
</svg>
<span>前往浏览器登录</span>
</button>
</div>
<p id="login-error" class="error-text hidden"></p>
</div>
</div>
</div>
<div id="vault-modal" class="modal hidden">
<div class="modal-card">
<div class="modal-header">
<h3 id="vault-modal-title">解锁本地 Vault</h3>
</div>
<p id="vault-modal-copy" class="subtle modal-copy">请输入本地 vault 主密码。</p>
<div class="modal-form">
<label class="field-label">
<span>主密码</span>
<input id="vault-password-input" type="password" class="detail-input" placeholder="输入主密码" />
</label>
</div>
<p id="vault-modal-error" class="error-text hidden"></p>
<div class="modal-actions">
<button id="vault-modal-save" class="primary small">继续</button>
</div>
</div>
</div>
<div id="app-shell" class="shell hidden">
<div class="window-titlebar shell-titlebar" data-tauri-drag-region aria-hidden="true"></div>
<aside class="sidebar">
<div class="user-block">
<button id="user-trigger" class="user-trigger">
<div class="avatar">V</div>
<div class="user-copy">
<div id="user-name" class="user-name">-</div>
<div id="user-email" class="user-email">-</div>
</div>
<span class="caret"></span>
</button>
<div id="user-menu" class="user-menu hidden">
<button id="manage-devices" class="menu-item">管理设备</button>
</div>
</div>
<div id="folder-list" class="folder-list"></div>
<div class="sidebar-spacer"></div>
<div class="sidebar-footer">
<button id="open-mcp-modal" class="sidebar-utility">
<span class="sidebar-utility-icon" aria-hidden="true"></span>
<span>MCP</span>
</button>
<button id="logout-button" class="sidebar-utility">
<span class="sidebar-utility-icon" aria-hidden="true"></span>
<span>退出登录</span>
</button>
</div>
</aside>
<main class="main-shell">
<section class="list-column">
<div class="searchbar-shell">
<input id="search-input" class="search-input global-search" placeholder="按名称模糊搜索" />
</div>
<section class="list-pane">
<div class="toolbar">
<button id="new-entry-button" class="secondary-button small">
<span class="button-icon" aria-hidden="true"></span>
<span class="button-label">新建条目</span>
</button>
<select id="type-filter" class="filter-select">
<option value="">全部类型</option>
</select>
</div>
<div id="entry-list" class="entry-list"></div>
</section>
</section>
<section class="detail-pane">
<div class="detail-header">
<div class="detail-title-stack">
<div id="detail-folder-label" class="detail-folder-label">-</div>
<div class="detail-title-block">
<h2 id="entry-title">-</h2>
<div id="detail-badge" class="detail-badge hidden">最近删除</div>
</div>
</div>
<div class="detail-actions">
<button id="edit-entry-button" class="secondary-button small action-button">
<span class="button-icon" aria-hidden="true"></span>
<span class="button-label">编辑</span>
</button>
<button id="delete-entry-button" class="secondary-button small danger action-button hidden">
<span class="button-icon" aria-hidden="true"></span>
<span class="button-label">删除</span>
</button>
<button id="restore-entry-button" class="secondary-button small action-button hidden">
<span class="button-icon" aria-hidden="true"></span>
<span class="button-label">恢复</span>
</button>
<button id="save-entry-button" class="primary small action-button hidden">
<span class="button-icon" aria-hidden="true"></span>
<span class="button-label">保存</span>
</button>
<button id="cancel-edit-button" class="secondary-button small action-button hidden">
<span class="button-icon" aria-hidden="true">×</span>
<span class="button-label">取消</span>
</button>
</div>
</div>
<div id="name-section" class="detail-section detail-edit-section hidden">
<h3>名称</h3>
<div id="name-view" class="detail-inline-value">-</div>
<input id="name-input" class="detail-input hidden" />
</div>
<div class="detail-section">
<h3>元数据</h3>
<div id="metadata-list" class="detail-fields"></div>
<div id="metadata-editor" class="metadata-editor hidden"></div>
<button id="add-metadata-button" class="secondary-button small hidden">新增元数据</button>
</div>
<div class="detail-section">
<div class="section-header-row">
<h3>密钥</h3>
<button id="add-secret-button" class="secondary-button small hidden">
<span class="button-icon" aria-hidden="true"></span>
<span class="button-label">新增密钥</span>
</button>
</div>
<div id="secret-list" class="secret-list"></div>
</div>
</section>
</main>
<div id="device-modal" class="modal hidden">
<div class="modal-card">
<div class="modal-header">
<h3>设备在线列表</h3>
<button id="close-device-modal" class="icon-button">×</button>
</div>
<p class="subtle modal-copy">查看已登录设备的在线情况与最近活动。</p>
<div id="device-list" class="device-list"></div>
</div>
</div>
<div id="mcp-modal" class="modal hidden">
<div class="modal-card wide">
<div class="modal-header">
<h3>MCP 集成</h3>
<button id="close-mcp-modal" class="icon-button">×</button>
</div>
<p class="subtle modal-copy">查看当前 AI 工具的 MCP 集成情况,并一键写入本地 daemon 配置。</p>
<section class="modal-section">
<div id="mcp-integration-list" class="integration-list"></div>
<p class="modal-footnote">启动 Secrets 桌面端时,可按选择自动为上述工具写入 MCP 配置。</p>
</section>
<section class="detail-section compact modal-section">
<div class="mcp-json-header">
<h4>自定义 MCP 配置</h4>
<button id="copy-mcp-config" class="secondary-button small">
<span class="button-icon" aria-hidden="true"></span>
<span class="button-label">复制</span>
</button>
</div>
<pre id="mcp-config" class="mcp-config"></pre>
</section>
</div>
</div>
<div id="entry-modal" class="modal hidden">
<div class="modal-card">
<div class="modal-header">
<h3>新建条目</h3>
<button id="close-entry-modal" class="icon-button">×</button>
</div>
<div class="modal-form">
<label class="field-label">
<span>项目</span>
<input id="entry-modal-folder" class="detail-input" placeholder="例如Refining" />
</label>
<label class="field-label">
<span>名称</span>
<input id="entry-modal-title" class="detail-input" placeholder="例如secrets-local" />
</label>
<label class="field-label">
<span>类型</span>
<input id="entry-modal-type" class="detail-input" placeholder="例如service" />
</label>
</div>
<div class="modal-actions">
<button id="entry-modal-cancel" class="secondary-button small">取消</button>
<button id="entry-modal-save" class="primary small">创建</button>
</div>
</div>
</div>
<div id="secret-modal" class="modal hidden">
<div class="modal-card">
<div class="modal-header">
<h3 id="secret-modal-title">新增密钥</h3>
<button id="close-secret-modal" class="icon-button">×</button>
</div>
<div class="modal-form">
<label class="field-label">
<span>名称</span>
<input id="secret-name-input" class="detail-input" placeholder="例如token" />
</label>
<label class="field-label">
<span>类型</span>
<select id="secret-type-input" class="filter-select">
<option value="text">text</option>
<option value="password">password</option>
<option value="key">key</option>
</select>
</label>
<label class="field-label">
<span>内容</span>
<textarea id="secret-value-input" class="detail-input detail-textarea" placeholder="输入密钥内容"></textarea>
</label>
</div>
<div class="modal-actions">
<button id="secret-modal-cancel" class="secondary-button small">取消</button>
<button id="secret-modal-save" class="primary small">保存</button>
</div>
</div>
</div>
<div id="history-modal" class="modal hidden">
<div class="modal-card wide">
<div class="modal-header">
<h3>密钥历史</h3>
<button id="close-history-modal" class="icon-button">×</button>
</div>
<p id="history-modal-copy" class="subtle modal-copy">查看版本历史并回滚到指定版本。</p>
<div id="history-list" class="history-list"></div>
</div>
</div>
</div>
<script src="./main.js"></script>
</body>
</html>