style: 优化一些css样式

This commit is contained in:
nap0o committed 2026-03-07 00:43:46 +08:00
1 parent 8b5b44363f
commit bfc3f089a8
5 files changed
+190 -32

No files matched your search

+42 -20
View File
@@ -11,12 +11,12 @@
[**Demo演示**](https://2fa.nezha.pp.ua) https://2fa.nezha.pp.ua
- 演示站配置了 `OAUTH_ALLOW_ALL=true`变量, 默认允许任何用户登录,正常部署切记 **不要配置OAUTH_ALLOW_ALL变量** | **不要配置OAUTH_ALLOW_ALL变量** | **不要配置OAUTH_ALLOW_ALL变量**
- 演示站配置了 `OAUTH_ALLOW_ALL=true`变量, 默认允许任何用户登录,正常部署切记 **不要主动配置OAUTH_ALLOW_ALL变量** | **不要主动配置OAUTH_ALLOW_ALL变量** | **不要主动配置OAUTH_ALLOW_ALL变量**
- 演示站数据可以任意修改、删除
---
**2FAuth Worker** 是一个轻量级、安全、无服务器的 TOTP 二步验证管理工具。它让你完全掌控自己的 2FA 数据,支持多端跨平台使用,无需购买任何服务器,**完全免费部署在 Cloudflare 边缘网络上**。
**2FAuth Worker** 是一个安全、轻量级、无服务器的 TOTP 二步验证管理工具。它让你完全掌控自己的 2FA 数据,支持多端跨平台使用,无需购买任何服务器,**完全免费部署在 Cloudflare 边缘网络上**。
## ✨ 核心优势与功能
@@ -51,17 +51,7 @@
---
## 🏗️ 全栈项目架构
本项目遵循现代化的 **Feature-based 垂直模块化架构**:
- **Frontend (Vue 3 + Vite)**:完全模块化,包含 `vault` (账户管理), `backup` (云端灾备), `auth` (身份验证), `tools` (工具箱) 等独立领域模块。状态管理由 Pinia 驱动。
- **Backend (Hono.js)**:极其轻量的边缘框架。配合 `Drizzle ORM` 丝滑读写 D1 数据库。
- **前后端天然一体**:由单代码库 (Monorepo) 管理,GitHub Actions 一次触发,同时构建前端产物并以 `Asset/SPA` 模式挂载至 Worker。
---
## 🚀 极速部署指南
## 🚀 详细部署指南
本项目设计为通过 **GitHub Actions** 自动化一键部署到你的 Cloudflare 账号下。只需几分钟即可获得你专属的 2FA 管理器。
@@ -69,23 +59,40 @@
1. 注册一个 [Cloudflare](https://dash.cloudflare.com/) 账号。
2. **Fork** 本仓库到你的 GitHub 账户。
### 第二步:配置 Cloudflare D1 数据库
### 第二步:获取 Cloudflare Worker部署令牌
1. 登录 Cloudflare Dashboard
2. [前往获取](https://dash.cloudflare.com/profile/api-tokens)
3. 点击“创建令牌”
4. 选择使用模版 “编辑 Cloudflare Workers”
5. 配置”帐户资源“和”区域资源“
6. 依次点击”继续以显示摘要“,点击”创建令牌“
7. 复制生成的令牌
<img width="500" alt="image" src="https://github.com/user-attachments/assets/6487aa6e-e505-4980-aef4-e08172116746" /><br />
<img width="800" alt="image" src="https://github.com/user-attachments/assets/d4c737f7-2d9f-4cfb-a712-b1af416c8ef6" />
### 第三步:配置 Cloudflare D1 数据库
1. 登录 Cloudflare Dashboard。
2. 依次点击左侧菜单的 **存储和数据库** -> **D1 SQL 数据库**。
3. 点击 **创建数据库**,命名为 `2fauth-db` (或自定义名称)。
4. 创建成功后,复制数据库详情页提供的 **`Database ID`**,备用。
### 第三步:配置第三方登录
*注:系统支持 6 种登录方式,你**至少需要配置一种***。
### 第四步:配置第三方登录
*注:系统支持 6 种登录方式,你**至少需要配置一种***。推荐使用 `GitHub登录`
#### 方案一:使用 GitHub 登录
#### 使用 GitHub 登录
1. 访问 GitHub `Settings` -> `Developer Settings` -> `OAuth Apps` -> **New OAuth App**。
2. 填写应用信息:
- **名称**: `2FAuth`
- **Homepage URL**: 填入你预期的站点域名,例如 `https://2fa.yourdomain.workers.dev` (部署后可绑定自定义域名)
- **Authorization callback URL**: 重点!必须填写 `https://<你的域名>/oauth/callback`
- **Authorization callback URL**: 重点!必须填写 `https://<Homepage URL>/oauth/callback`
3. 保存生成的 **`Client ID`** 和 **`Client Secret`**。
<img width="800" alt="image" src="https://github.com/user-attachments/assets/aa03b15f-deb2-4e48-bf4b-e57be342adbb" />
#### 方案二:使用 Telegram 登录
1. 在 Telegram 中搜索并添加官方机器人 **[@BotFather](https://t.me/BotFather)**。
2. 发送 `/newbot` 指令,按照提示为你的 2FAuth 创建一个机器人,并获取它的 **`Bot Token`**(如 `123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11`)。
@@ -96,14 +103,14 @@
curl "https://api.telegram.org/bot<你的BotToken>/setWebhook?url=https://<你设置的setdomain>/api/telegram/webhook"
```
### 第四步:配置 GitHub Actions Secrets
### 第五步:配置 GitHub Actions Secrets
前往你 Fork 的 GitHub 仓库的 **Settings** -> **Secrets and variables** -> **Actions** -> **New repository secret**,添加以下必填环境变量:
#### ☁️ 必填:Cloudflare 资源授权
| Secret Name | 说明 | 示例值 |
| :--- | :--- | :--- |
| `CLOUDFLARE_ACCOUNT_ID` | 你的 CF 账户 ID | `a1b2c3d4e5f6g7h8i9j0` (CF 面板的概述页右下角) |
| `CLOUDFLARE_API_TOKEN` | CF 部署令牌 [前往获取](https://dash.cloudflare.com/profile/api-tokens) <br> 点击“创建令牌” -> “创建自定义令牌” <br/> 权限 1: **账户** -> **D1** -> **编辑** <br/>权限 2: **账户** -> **Workers 脚本** -> **编辑** | `r4_xyz...` |
| `CLOUDFLARE_API_TOKEN` | CF 部署令牌 | `r4_xyz...` |
#### 🔐 必填:系统安全参数
@@ -136,6 +143,8 @@ curl "https://api.telegram.org/bot<你的BotToken>/setWebhook?url=https://<你
| **Gitee** | `OAUTH_GITEE_CLIENT_ID`<br>`bcd...` | `OAUTH_GITEE_CLIENT_SECRET`<br>`efg...` | `OAUTH_GITEE_REDIRECT_URI`<br>`https://xxx.workers.dev/oauth/callback` |
| **NodeLoc** | `OAUTH_NODELOC_CLIENT_ID`<br>`cde...` | `OAUTH_NODELOC_CLIENT_SECRET`<br>`fgh...` | `OAUTH_NODELOC_REDIRECT_URI`<br>`https://xxx.workers.dev/oauth/callback` |
<img width="800" alt="image" src="https://github.com/user-attachments/assets/ef907021-303d-4fd5-ba3e-913e8b0014a5" />
### 第五步:触发自动化部署
1. 进入你的 GitHub 仓库的 **Actions** 页面。
2. 找到 `Deploy to Cloudflare Workers` 工作流。
@@ -146,6 +155,9 @@ curl "https://api.telegram.org/bot<你的BotToken>/setWebhook?url=https://<你
- ⚡ 自动将带有静态前端的后端服务绑定至 Cloudflare 边缘节点。
5. 部署成功后,控制台会输出你的 `xxx.workers.dev` 链接。登录进去,开始你的私有化 2FA 之旅!
<img width="800" height="1350" alt="image" src="https://github.com/user-attachments/assets/b2891365-5c1a-4a46-83c6-5cd53dd4b895" />
---
## 💻 本地极客开发 (Local Development)
@@ -170,6 +182,16 @@ npx wrangler d1 execute 2fauth-db-dev --local --env dev --file=schema.sql
npm run dev
```
## 🏗️ 全栈项目架构
本项目遵循现代化的 **Feature-based 垂直模块化架构**:
- **Frontend (Vue 3 + Vite)**:完全模块化,包含 `vault` (账户管理), `backup` (云端灾备), `auth` (身份验证), `tools` (工具箱) 等独立领域模块。状态管理由 Pinia 驱动。
- **Backend (Hono.js)**:极其轻量的边缘框架。配合 `Drizzle ORM` 丝滑读写 D1 数据库。
- **前后端天然一体**:由单代码库 (Monorepo) 管理,GitHub Actions 一次触发,同时构建前端产物并以 `Asset/SPA` 模式挂载至 Worker。
---
---
## 🛡️ 安全性声明 (Security Policy)
+5 -1
View File
@@ -1,5 +1,9 @@
{
"name": "backend",
"name": "2FAuth Worker",
"version": "1.0.2",
"description": "A Secure 2FA Management Tool running on Cloudflare Workers",
"author": "nap0o",
"license": "AGPL-3.0",
"type": "module",
"scripts": {
"dev": "wrangler dev --config wrangler.dev.toml --host 0.0.0.0 --port 8787 --test-scheduled",
@@ -56,11 +56,29 @@
<el-drawer
v-model="layoutStore.showMobileMenu"
direction="ltr"
size="240px"
size="280px"
:with-header="false"
:lock-scroll="false"
>
<div class="drawer-content">
<!-- 移动端用户信息卡片 -->
<div class="user-info-card" v-if="authUserStore.userInfo">
<div class="user-card-content">
<el-avatar :size="40" :src="authUserStore.userInfo?.avatar" class="user-avatar">
{{ authUserStore.userInfo?.username?.charAt(0)?.toUpperCase() }}
</el-avatar>
<div class="user-detail">
<div class="user-name-row">
<span class="user-name">{{ authUserStore.userInfo?.username }}</span>
<i class="status-dot" :class="{ 'is-online': authUserStore.userInfo?.online !== false }"></i>
</div>
<div class="user-provider" v-if="authUserStore.userInfo?.provider">
{{ authUserStore.userInfo?.provider }}
</div>
</div>
</div>
</div>
<el-menu
:default-active="activeTab"
class="side-menu"
@@ -166,3 +184,67 @@ const handleLogout = async () => {
ElMessage.success(t('auth.logout_success'))
}
</script>
<style scoped>
.user-info-card {
margin: 0px 20px 0px 20px;
padding-bottom: 20px;
border-bottom: 0.2px solid var(--el-border-color-lighter);
}
.user-card-content {
display: flex;
align-items: center;
gap: 15px;
}
.user-avatar {
border: 2px solid var(--el-color-primary-light-8);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.user-detail {
display: flex;
flex-direction: column;
}
.user-name-row {
display: flex;
align-items: center;
gap: 6px;
margin-bottom: 2px;
}
.user-name {
font-size: 15px;
font-weight: 600;
color: var(--el-text-color-primary);
line-height: 1.2;
}
.status-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background-color: #909399; /* 默认灰色 */
display: inline-block;
flex-shrink: 0;
}
.status-dot.is-online {
background-color: #67C23A; /* 在线绿色 */
box-shadow: 0 0 4px rgba(103, 194, 58, 0.5);
}
.user-provider {
font-size: 11px;
color: var(--el-text-color-secondary);
background: var(--el-fill-color);
padding: 1px;
border-radius: 2px;
display: inline-block;
width: fit-content;
text-transform: uppercase;
letter-spacing: 0.5px;
}
</style>
@@ -1,7 +1,9 @@
<template>
<div class="vault-list-wrapper" style="min-height: 400px;">
<div class="vault-content">
<div class="toolbar" style="margin-bottom: 20px; display: flex; gap: 15px; align-items: center; justify-content: space-between; flex-wrap: wrap;">
<!-- 移动端偏移 45px (Header2), PC端偏移 61px (Header1) -->
<el-affix :offset="layoutStore.isMobile ? 45 : 61" @change="(val) => isToolbarFixed = val">
<div class="toolbar" :class="{ 'is-affixed': isToolbarFixed }" style="margin-bottom: 20px; display: flex; gap: 15px; align-items: center; justify-content: space-between; flex-wrap: wrap;">
<div style="display: flex; align-items: center; gap: 10px; flex: 1;">
<el-input
v-model="searchQuery"
@@ -27,6 +29,7 @@
<el-button v-else @click="selectAllLoaded" plain>{{ $t('common.select_all_loaded') }}</el-button>
</div>
</div>
</el-affix>
<!-- 1. 加载状态 -->
<div v-if="(isInitializing || isLoading || isFetching) && vault.length === 0" class="loading-state" style="display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 400px; color: var(--el-text-color-secondary);">
@@ -226,6 +229,7 @@ const {
// mount 到 handleUnlocked 完成前保持 true,确保本地缓存读取期间显示 loading 动画
const isInitializing = ref(true)
const isToolbarFixed = ref(false)
// --- 解锁回调:离线优先,秒开首屏 ---
const handleUnlocked = async () => {
@@ -248,3 +252,49 @@ defineExpose({ fetchVault })
onMounted(handleUnlocked)
</script>
<style scoped>
/* 搜索栏吸顶过渡动画 */
.toolbar {
transition: padding 0.3s ease, background-color 0.3s ease;
box-sizing: border-box;
}
/* 共有吸顶属性 */
.toolbar.is-affixed {
z-index: 2000;
margin-bottom: 0 !important;
}
/* 移动端吸顶效果:全屏、背景、边框 */
@media (max-width: 767px) {
.toolbar.is-affixed {
position: fixed !important;
left: 0 !important;
right: 0 !important;
width: 100vw !important;
background-color: var(--glass-card-bg, rgba(255, 255, 255, 0.95));
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--el-border-color-light);
padding: 10px 20px !important;
border-radius: 0 !important;
}
}
/* PC 端吸顶效果:保持原有宽度,无背景色和下边框 */
@media (min-width: 768px) {
.toolbar.is-affixed {
background-color: var(--el-bg-color-page) !important;
border-bottom: none !important;
padding: 10px 0px 20px 0px !important;
}
}
/* 适配暗黑模式 (仅移动端需要背景) */
@media (max-width: 767px) {
html.dark .toolbar.is-affixed {
background-color: rgba(30, 30, 30, 0.85);
border-bottom: 1px solid var(--el-border-color-dark);
}
}
</style>
+9 -9
View File
@@ -512,15 +512,15 @@
}
},
"suggestions": {
"encryption_key_suggestion": "请复制下方为您预生成的高强度随机密钥。随后前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将其填入 ENCRYPTION_KEY。",
"jwt_secret_suggestion": "请复制下方为您预生成的高强度随机密钥。前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密, 将其填入 JWT_SECRET",
"oauth_allow_all_suggestion": "请立刻前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将环境变量 OAUTH_ALLOW_ALL 删除,或将其值修改为 false。",
"allowed_users_suggestion": "请在 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密中添加 OAUTH_ALLOWED_USERS,并填入您在 GitHub(或其它平台)上对应的注册邮箱地址(多个以英文逗号分隔)。",
"github_config_suggestion": "请核对获取的 GitHub OAuth Apps 密钥信息,然后前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将环境变量 OAUTH_GITHUB_CLIENT_ID、OAUTH_GITHUB_CLIENT_SECRET、OAUTH_GITHUB_REDIRECT_URI 填入",
"telegram_config_suggestion": "请在 BotFather 检查机器人配置,确保信息填全,然后前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将环境变量 OAUTH_TELEGRAM_BOT_NAME、OAUTH_TELEGRAM_BOT_TOKEN、OAUTH_TELEGRAM_REDIRECT_URI 填入",
"google_config_suggestion": "请前往 Google Cloud Console 检查凭据配置,然后前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将环境变量 OAUTH_GOOGLE_CLIENT_ID、OAUTH_GOOGLE_CLIENT_SECRET、OAUTH_GOOGLE_REDIRECT_URI 填入",
"nodeloc_config_suggestion": "请前往 NodeLoc 面板检查您的开发者凭据,然后前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将环境变量 OAUTH_NODELOC_CLIENT_ID、OAUTH_NODELOC_CLIENT_SECRET、OAUTH_NODELOC_REDIRECT_URI 填入",
"gitee_config_suggestion": "请核对 Gitee 开发者凭据,然后前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将环境变量 OAUTH_GITEE_CLIENT_ID、OAUTH_GITEE_CLIENT_SECRET、OAUTH_GITEE_REDIRECT_URI 填入",
"encryption_key_suggestion": "请复制下方为您预生成的高强度随机密钥。请立刻前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions -> 将其填入 ENCRYPTION_KEY",
"jwt_secret_suggestion": "请复制下方为您预生成的高强度随机密钥。请立刻前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions -> 将其填入 JWT_SECRET",
"oauth_allow_all_suggestion": "请立刻前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions,将环境变量 OAUTH_ALLOW_ALL 删除,或将其值修改为 false。",
"allowed_users_suggestion": "请在 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions中添加 OAUTH_ALLOWED_USERS,并填入您在 GitHub(或其它平台)上对应的注册邮箱地址(多个以英文逗号分隔)。",
"github_config_suggestion": "请核对获取的 GitHub OAuth Apps 密钥信息,然后前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions,将环境变量 OAUTH_GITHUB_CLIENT_ID、OAUTH_GITHUB_CLIENT_SECRET、OAUTH_GITHUB_REDIRECT_URI 填入",
"telegram_config_suggestion": "请在 BotFather 检查机器人配置,确保信息填全,然后前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions,将环境变量 OAUTH_TELEGRAM_BOT_NAME、OAUTH_TELEGRAM_BOT_TOKEN、OAUTH_TELEGRAM_REDIRECT_URI 填入",
"google_config_suggestion": "请前往 Google Cloud Console 检查凭据配置,然后前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions,将环境变量 OAUTH_GOOGLE_CLIENT_ID、OAUTH_GOOGLE_CLIENT_SECRET、OAUTH_GOOGLE_REDIRECT_URI 填入",
"nodeloc_config_suggestion": "请前往 NodeLoc 面板检查您的开发者凭据,然后前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions,将环境变量 OAUTH_NODELOC_CLIENT_ID、OAUTH_NODELOC_CLIENT_SECRET、OAUTH_NODELOC_REDIRECT_URI 填入",
"gitee_config_suggestion": "请核对 Gitee 开发者凭据,然后前往 Fork的Github仓库 -> Settings -> Secrets and variables -> Actions,将环境变量 OAUTH_GITEE_CLIENT_ID、OAUTH_GITEE_CLIENT_SECRET、OAUTH_GITEE_REDIRECT_URI 填入",
"cloudflare_config_suggestion": "需要四位一体的参数:Client ID, Secret, Org Domain, Redirect URI,然后前往 Cloudflare 后台 -> Workers 和 Pages -> 2fauth-worker -> 设置 -> 变量和机密,将环境变量 OAUTH_CLOUDFLARE_CLIENT_ID、OAUTH_CLOUDFLARE_CLIENT_SECRET、OAUTH_CLOUDFLARE_REDIRECT_URI 填入",
"no_provider_suggestion": "阅读2Fauth Worker 的 README,挑选最适合您且配置最简单的一种登录方式,按照其说明获取 Client ID 与 Secret 并在云端配置。"
}