chore(desktop): 跟踪 apps/desktop/dist 静态资源并统一文档与忽略规则
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,9 +8,6 @@ client_secret_*.apps.googleusercontent.com.json
|
|||||||
node_modules/
|
node_modules/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
# Desktop: Tauri frontend bundle (tauri.conf.json build.frontendDist)
|
|
||||||
apps/desktop/dist/
|
|
||||||
|
|
||||||
# Tauri app icon pack: generated by `cargo tauri icon apps/desktop/src-tauri/icons/icon.png`
|
# Tauri app icon pack: generated by `cargo tauri icon apps/desktop/src-tauri/icons/icon.png`
|
||||||
# Version control only the 1024×1024 master; regenerate the rest locally or in release builds.
|
# Version control only the 1024×1024 master; regenerate the rest locally or in release builds.
|
||||||
apps/desktop/src-tauri/icons/**
|
apps/desktop/src-tauri/icons/**
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ http://127.0.0.1:9515/mcp
|
|||||||
|
|
||||||
### 图标与前端 dist(本地 / CI)
|
### 图标与前端 dist(本地 / CI)
|
||||||
|
|
||||||
版本库为减小噪音,**不提交** Tauri 生成的多尺寸图标包,以及 **`apps/desktop/dist/`** 前端打包目录(见根目录 `.gitignore`)。
|
版本库为减小噪音,**不提交** Tauri 生成的多尺寸图标包;但 **`apps/desktop/dist/`** 现在作为桌面端前端静态资源目录,**需要提交到版本库**,以保证新机器 clone 后可直接运行 Tauri desktop。
|
||||||
|
|
||||||
- **图标**:仅跟踪 `apps/desktop/src-tauri/icons/icon.png` 作为源图(建议 **1024×1024** PNG)。检出代码后,若需要完整 `icons/`(例如打包、验证窗口/托盘图标),在 **`apps/desktop/src-tauri`** 下执行:
|
- **图标**:仅跟踪 `apps/desktop/src-tauri/icons/icon.png` 作为源图(建议 **1024×1024** PNG)。检出代码后,若需要完整 `icons/`(例如打包、验证窗口/托盘图标),在 **`apps/desktop/src-tauri`** 下执行:
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ http://127.0.0.1:9515/mcp
|
|||||||
|
|
||||||
需已安装 **Tauri CLI**(例如 `cargo install tauri-cli`,或与项目一致的 `cargo-tauri` 版本)。
|
需已安装 **Tauri CLI**(例如 `cargo install tauri-cli`,或与项目一致的 `cargo-tauri` 版本)。
|
||||||
|
|
||||||
- **前端 dist**:`tauri.conf.json` 中 `build.frontendDist` 指向 `../dist`。本地或 CI 在运行 `cargo tauri dev` / `cargo tauri build` 前,需先按项目约定生成或同步 **`apps/desktop/dist/`** 内容;流水线构建桌面端时,在 Tauri 步骤之前加入对应的前端产物步骤即可。
|
- **前端 dist**:`tauri.conf.json` 中 `build.frontendDist` 指向 `../dist`。当前仓库直接跟踪 **`apps/desktop/dist/`** 下的静态页面资源,因此新机器 clone 后无需额外生成前端产物即可运行 `cargo run -p secrets-desktop`。若后续引入独立前端构建链,再单独把这部分切回构建产物管理。
|
||||||
|
|
||||||
## 代码规范
|
## 代码规范
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ cargo run -p secrets-desktop-daemon
|
|||||||
cargo run -p secrets-desktop
|
cargo run -p secrets-desktop
|
||||||
```
|
```
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
- `apps/desktop/src-tauri/tauri.conf.json` 中 `build.frontendDist` 指向 `apps/desktop/dist`
|
||||||
|
- 当前仓库会直接提交 `apps/desktop/dist/` 下的桌面端静态资源
|
||||||
|
- 因此新机器 clone 后,无需额外前端构建步骤即可启动 desktop
|
||||||
|
|
||||||
## 当前能力
|
## 当前能力
|
||||||
|
|
||||||
- 桌面端使用系统浏览器完成 Google Desktop OAuth 登录
|
- 桌面端使用系统浏览器完成 Google Desktop OAuth 登录
|
||||||
|
|||||||
41
apps/desktop/dist/disable-features.js
vendored
Normal file
41
apps/desktop/dist/disable-features.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
(() => {
|
||||||
|
const tauriInvoke = window.__TAURI_INTERNALS__?.invoke;
|
||||||
|
|
||||||
|
// Disable text selection globally, but keep inputs editable.
|
||||||
|
document.addEventListener("selectstart", (event) => {
|
||||||
|
const target = event.target;
|
||||||
|
if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function applyProductionGuards() {
|
||||||
|
if (!tauriInvoke) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isDebugBuild = false;
|
||||||
|
try {
|
||||||
|
isDebugBuild = await tauriInvoke("is_debug_build");
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDebugBuild) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("contextmenu", (event) => event.preventDefault());
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
if (event.key === "F12") {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
if ((event.ctrlKey || event.metaKey) && event.shiftKey && ["I", "C", "J"].includes(event.key.toUpperCase())) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyProductionGuards();
|
||||||
|
})();
|
||||||
BIN
apps/desktop/dist/favicon.png
vendored
Normal file
BIN
apps/desktop/dist/favicon.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
279
apps/desktop/dist/index.html
vendored
Normal file
279
apps/desktop/dist/index.html
vendored
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
<!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>使用 Google 登录</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>
|
||||||
1018
apps/desktop/dist/main.js
vendored
Normal file
1018
apps/desktop/dist/main.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1072
apps/desktop/dist/styles.css
vendored
Normal file
1072
apps/desktop/dist/styles.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user