style: 前端交互及样式优化

This commit is contained in:
nap0o committed 2026-03-01 01:10:35 +08:00
1 parent e9c97a42a5
commit 2afb8353ac
7 files changed
+72 -18

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@
<el-card class="login-card" shadow="hover">
<div class="logo-container">
<el-icon :size="54" color="#409EFC"><Lock /></el-icon>
<h2>2FAuth</h2>
<h2>2FAuth Worker</h2>
<p class="subtitle">您的专属云端双因素认证管家</p>
</div>
@@ -8,7 +8,7 @@
:collapse="isCollapse"
>
<el-menu-item index="vault">
<el-icon><Iphone /></el-icon>
<el-icon><CopyDocument /></el-icon>
<template #title><span>我的账户</span></template>
</el-menu-item>
@@ -66,7 +66,7 @@
style="border-right: none;"
>
<el-menu-item index="vault">
<el-icon><Iphone /></el-icon>
<el-icon><CopyDocument /></el-icon>
<span>我的账户</span>
</el-menu-item>
<el-sub-menu index="add-vault">
@@ -95,9 +95,9 @@
</el-menu-item>
</el-menu>
<div class="sidebar-footer">
<el-button circle :icon="themeStore.isDark ? Sunny : Moon" @click="themeStore.toggleTheme" />
<el-button circle @click="handleLogout" title="退出登录">
<div class="sidebar-footer" style="display: flex; gap: 15px; justify-content: center; padding: 20px 0;">
<el-button circle size="medium" :icon="themeStore.isDark ? Sunny : Moon" @click="themeStore.toggleTheme" />
<el-button circle size="medium" @click="handleLogout" title="退出登录">
<el-icon><SwitchButton /></el-icon>
</el-button>
</div>
@@ -110,7 +110,7 @@ import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import {
Iphone, Plus, Camera, Edit, Sort, Upload, Download,
CopyDocument, Plus, Camera, Edit, Sort, Upload, Download,
Cloudy, Sunny, Moon, SwitchButton, Fold, Expand, Tools
} from '@element-plus/icons-vue'
import { useLayoutStore } from '@/shared/stores/layoutStore'
@@ -47,6 +47,9 @@
<script setup>
import { ref, nextTick, defineAsyncComponent, watch } from 'vue'
import AppSidebar from '@/features/vault/components/appSidebar.vue'
import { useLayoutStore } from '@/shared/stores/layoutStore'
const layoutStore = useLayoutStore()
const VaultList = defineAsyncComponent(() => import('@/features/vault/components/vaultList.vue'))
const AddVaultScan = defineAsyncComponent(() => import('@/features/vault/components/addVaultScan.vue'))
@@ -78,4 +81,17 @@ watch(vaultListRef, (ref) => {
nextTick(() => ref.fetchVault())
}
})
// 监听头部 Logo 点击事件,无刷新跳回主列表
watch(() => layoutStore.homeTabReset, () => {
if (activeTab.value !== 'vault') {
activeTab.value = 'vault'
}
// 强制刷新一下列表数据
if (vaultListRef.value) {
nextTick(() => vaultListRef.value?.fetchVault())
} else {
pendingRefetch = true
}
})
</script>
+14 -4
View File
@@ -2,14 +2,24 @@
<footer class="global-footer">
<div class="footer-content">
<p>
&copy;{{ new Date().getFullYear() }} <a href="https://github.com/nap0o/2fauth-worker" target="_blank" rel="noopener noreferrer">2FAuth</a>
<span class="divider">|</span>
Serverless 2FA Manager
&copy;{{ new Date().getFullYear() }} <a href="https://github.com/nap0o/2fauth-worker" target="_blank" rel="noopener noreferrer">2FAuth Worker</a>
<span v-if="!layoutStore.isMobile">
<span class="divider">|</span>
Serverless 2FA Manager
</span>
<span v-if="commitHash && commitHash !== 'unknown'">
<span class="divider">|</span>
Hash-{{ commitHash }}
</span>
</p>
</div>
</footer>
</template>
<script setup>
// 这里可以添加页脚需要的逻辑,例如版本号显示等
import { useLayoutStore } from '@/shared/stores/layoutStore'
const layoutStore = useLayoutStore()
// 注入在 vite.config.js 中定义的全局构建环境变量
const commitHash = typeof __COMMIT_HASH__ !== 'undefined' ? __COMMIT_HASH__ : 'unknown'
</script>
+21 -6
View File
@@ -1,11 +1,17 @@
<template>
<header class="header">
<div class="logo">
<el-button v-if="layoutStore.isMobile && route.path !== '/login'" link @click="layoutStore.showMobileMenu = true" style="margin-right: 5px; padding: 0;">
<el-icon :size="24" class="menu-icon"><Menu /></el-icon>
<el-button v-if="layoutStore.isMobile && !!userStore.userInfo?.username" @click="layoutStore.showMobileMenu = true" style="margin-right: 10px; padding: 5px 8px; border: 1px solid var(--el-border-color); height: auto;">
<el-icon :size="14" class="menu-icon" style="color: var(--el-text-color-primary);">
<svg viewBox="0 0 16 16" version="1.1" width="100%" height="100%" aria-hidden="true" fill="currentColor">
<path d="M1 2.75A.75.75 0 0 1 1.75 2h12.5a.75.75 0 0 1 0 1.5H1.75A.75.75 0 0 1 1 2.75Zm0 5A.75.75 0 0 1 1.75 7h12.5a.75.75 0 0 1 0 1.5H1.75A.75.75 0 0 1 1 7.75ZM1.75 12h12.5a.75.75 0 0 1 0 1.5H1.75a.75.75 0 0 1 0-1.5Z"></path>
</svg>
</el-icon>
</el-button>
<el-icon :size="24" color="#409EFC" style="margin-right: 10px;"><Lock /></el-icon>
<h2>2FAuth</h2>
<a href="#" @click.prevent="goHome" style="display: flex; align-items: center; text-decoration: none; color: inherit;">
<el-icon :size="24" color="#409EFC" style="margin-right: 10px;"><Lock /></el-icon>
<h2>2FAuth Worker</h2>
</a>
</div>
<div class="user-actions" v-if="route.path !== '/login'">
<div class="user-profile" v-if="!layoutStore.isMobile">
@@ -20,12 +26,21 @@
<script setup>
import { ref } from 'vue'
import { useRoute } from 'vue-router'
import { Lock, Menu } from '@element-plus/icons-vue'
import { useRoute, useRouter } from 'vue-router'
import { Lock } from '@element-plus/icons-vue'
import { useLayoutStore } from '@/shared/stores/layoutStore'
import { useUserStore } from '@/features/auth/store/userStore'
const route = useRoute()
const router = useRouter()
const layoutStore = useLayoutStore()
const userStore = useUserStore()
const goHome = () => {
if (route.path === '/') {
layoutStore.homeTabReset++
} else {
router.push('/')
}
}
</script>
+3 -1
View File
@@ -4,9 +4,11 @@ import { ref } from 'vue'
export const useLayoutStore = defineStore('layout', () => {
const isMobile = ref(false)
const showMobileMenu = ref(false)
const homeTabReset = ref(0) // 触发返回统一的主账号视图
return {
isMobile,
showMobileMenu
showMobileMenu,
homeTabReset
}
})
+11
View File
@@ -6,6 +6,14 @@ import { VitePWA } from 'vite-plugin-pwa'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { execSync } from 'child_process'
let commitHash = ''
try {
commitHash = execSync('git rev-parse --short HEAD').toString().trim()
} catch (e) {
commitHash = 'unknown'
}
export default defineConfig({
plugins: [
@@ -61,6 +69,9 @@ export default defineConfig({
}
})
],
define: {
__COMMIT_HASH__: JSON.stringify(commitHash)
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))