2 Commits

Author SHA1 Message Date
fawney19
f6a6410626 feat: 添加 GitHub 仓库链接到页面头部
- 新增 GithubIcon 组件复用 GitHub 图标
- MainLayout 和 Home 页面头部添加 GitHub 链接按钮
- 重构 Home 页面 header 布局结构
2026-01-06 18:27:28 +08:00
fawney19
835be3d329 refactor: nginx 透传外层代理 IP 头并禁用审计日志页面的审计记录
- Dockerfile.app/local: 使用 map 指令智能处理 X-Real-IP 和 X-Forwarded-For,
  有外层代理头则透传,否则使用 remote_addr
- audit.py: 查看审计日志不再产生审计记录,避免刷新页面时产生大量无意义日志
2026-01-06 17:23:08 +08:00
6 changed files with 106 additions and 68 deletions

View File

@@ -39,7 +39,18 @@ COPY alembic.ini ./
COPY alembic/ ./alembic/ COPY alembic/ ./alembic/
# Nginx 配置模板 # Nginx 配置模板
# 智能处理 IP有外层代理头就透传没有就用直连 IP
RUN printf '%s\n' \ RUN printf '%s\n' \
'map $http_x_real_ip $real_ip {' \
' default $http_x_real_ip;' \
' "" $remote_addr;' \
'}' \
'' \
'map $http_x_forwarded_for $forwarded_for {' \
' default $http_x_forwarded_for;' \
' "" $remote_addr;' \
'}' \
'' \
'server {' \ 'server {' \
' listen 80;' \ ' listen 80;' \
' server_name _;' \ ' server_name _;' \
@@ -70,8 +81,8 @@ RUN printf '%s\n' \
' proxy_pass http://127.0.0.1:PORT_PLACEHOLDER;' \ ' proxy_pass http://127.0.0.1:PORT_PLACEHOLDER;' \
' proxy_http_version 1.1;' \ ' proxy_http_version 1.1;' \
' proxy_set_header Host $host;' \ ' proxy_set_header Host $host;' \
' proxy_set_header X-Real-IP $remote_addr;' \ ' proxy_set_header X-Real-IP $real_ip;' \
' proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;' \ ' proxy_set_header X-Forwarded-For $forwarded_for;' \
' proxy_set_header X-Forwarded-Proto $scheme;' \ ' proxy_set_header X-Forwarded-Proto $scheme;' \
' proxy_set_header Connection "";' \ ' proxy_set_header Connection "";' \
' proxy_set_header Accept $http_accept;' \ ' proxy_set_header Accept $http_accept;' \

View File

@@ -40,7 +40,18 @@ COPY alembic.ini ./
COPY alembic/ ./alembic/ COPY alembic/ ./alembic/
# Nginx 配置模板 # Nginx 配置模板
# 智能处理 IP有外层代理头就透传没有就用直连 IP
RUN printf '%s\n' \ RUN printf '%s\n' \
'map $http_x_real_ip $real_ip {' \
' default $http_x_real_ip;' \
' "" $remote_addr;' \
'}' \
'' \
'map $http_x_forwarded_for $forwarded_for {' \
' default $http_x_forwarded_for;' \
' "" $remote_addr;' \
'}' \
'' \
'server {' \ 'server {' \
' listen 80;' \ ' listen 80;' \
' server_name _;' \ ' server_name _;' \
@@ -71,8 +82,8 @@ RUN printf '%s\n' \
' proxy_pass http://127.0.0.1:PORT_PLACEHOLDER;' \ ' proxy_pass http://127.0.0.1:PORT_PLACEHOLDER;' \
' proxy_http_version 1.1;' \ ' proxy_http_version 1.1;' \
' proxy_set_header Host $host;' \ ' proxy_set_header Host $host;' \
' proxy_set_header X-Real-IP $remote_addr;' \ ' proxy_set_header X-Real-IP $real_ip;' \
' proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;' \ ' proxy_set_header X-Forwarded-For $forwarded_for;' \
' proxy_set_header X-Forwarded-Proto $scheme;' \ ' proxy_set_header X-Forwarded-Proto $scheme;' \
' proxy_set_header Connection "";' \ ' proxy_set_header Connection "";' \
' proxy_set_header Accept $http_accept;' \ ' proxy_set_header Accept $http_accept;' \

View File

@@ -0,0 +1,13 @@
<template>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4" />
<path d="M9 18c-4.51 2-5-2-7-2" />
</svg>
</template>

View File

@@ -280,6 +280,16 @@
class="h-4 w-4" class="h-4 w-4"
/> />
</button> </button>
<!-- GitHub Link -->
<a
href="https://github.com/fawney19/Aether"
target="_blank"
rel="noopener noreferrer"
class="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/50 transition"
title="GitHub 仓库"
>
<GithubIcon class="h-4 w-4" />
</a>
</div> </div>
</header> </header>
</template> </template>
@@ -322,6 +332,7 @@ import {
X, X,
Mail, Mail,
} from 'lucide-vue-next' } from 'lucide-vue-next'
import GithubIcon from '@/components/icons/GithubIcon.vue'
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()

View File

@@ -20,10 +20,11 @@
</nav> </nav>
<!-- Header --> <!-- Header -->
<header class="fixed top-0 left-0 right-0 z-50 border-b border-[#cc785c]/10 dark:border-[rgba(227,224,211,0.12)] bg-[#fafaf7]/90 dark:bg-[#191714]/95 backdrop-blur-xl transition-all"> <header class="sticky top-0 z-50 border-b border-[#cc785c]/10 dark:border-[rgba(227,224,211,0.12)] bg-[#fafaf7]/90 dark:bg-[#191714]/95 backdrop-blur-xl transition-all">
<div class="mx-auto max-w-7xl px-6 py-4"> <div class="h-16 flex items-center">
<div class="flex items-center justify-between"> <!-- Centered content container (max-w-7xl) -->
<!-- Logo & Brand --> <div class="mx-auto max-w-7xl w-full px-6 flex items-center justify-between">
<!-- Left: Logo & Brand -->
<div <div
class="flex items-center gap-3 group/logo cursor-pointer" class="flex items-center gap-3 group/logo cursor-pointer"
@click="scrollToSection(0)" @click="scrollToSection(0)"
@@ -40,7 +41,7 @@
</div> </div>
</div> </div>
<!-- Center Navigation --> <!-- Center: Navigation -->
<nav class="hidden md:flex items-center gap-2"> <nav class="hidden md:flex items-center gap-2">
<button <button
v-for="(section, index) in sections" v-for="(section, index) in sections"
@@ -59,42 +60,54 @@
</button> </button>
</nav> </nav>
<!-- Right Actions --> <!-- Right: Login/Dashboard Button -->
<div class="flex items-center gap-3"> <RouterLink
<button v-if="authStore.isAuthenticated"
class="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/50 transition" :to="dashboardPath"
:title="themeMode === 'system' ? '跟随系统' : themeMode === 'dark' ? '深色模式' : '浅色模式'" class="min-w-[72px] text-center rounded-xl bg-[#191919] dark:bg-[#cc785c] px-4 py-2 text-sm font-medium text-white shadow-sm transition hover:bg-[#262625] dark:hover:bg-[#b86d52] whitespace-nowrap"
@click="toggleDarkMode" >
> 控制台
<SunMoon </RouterLink>
v-if="themeMode === 'system'" <button
class="h-4 w-4" v-else
/> class="min-w-[72px] text-center rounded-xl bg-[#cc785c] px-4 py-2 text-sm font-medium text-white shadow-lg shadow-[#cc785c]/30 transition hover:bg-[#d4a27f] whitespace-nowrap"
<Sun @click="showLoginDialog = true"
v-else-if="themeMode === 'light'" >
class="h-4 w-4" 登录
/> </button>
<Moon </div>
v-else
class="h-4 w-4"
/>
</button>
<RouterLink <!-- Fixed right icons (px-8 to match dashboard) -->
v-if="authStore.isAuthenticated" <div class="absolute right-8 top-1/2 -translate-y-1/2 flex items-center gap-2">
:to="dashboardPath" <!-- Theme Toggle -->
class="rounded-xl bg-[#191919] dark:bg-[#cc785c] px-4 py-2 text-sm font-medium text-white shadow-sm transition hover:bg-[#262625] dark:hover:bg-[#b86d52]" <button
> class="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/50 transition"
控制台 :title="themeMode === 'system' ? '跟随系统' : themeMode === 'dark' ? '深色模式' : '浅色模式'"
</RouterLink> @click="toggleDarkMode"
<button >
<SunMoon
v-if="themeMode === 'system'"
class="h-4 w-4"
/>
<Sun
v-else-if="themeMode === 'light'"
class="h-4 w-4"
/>
<Moon
v-else v-else
class="rounded-xl bg-[#cc785c] px-4 py-2 text-sm font-medium text-white shadow-lg shadow-[#cc785c]/30 transition hover:bg-[#d4a27f]" class="h-4 w-4"
@click="showLoginDialog = true" />
> </button>
登录 <!-- GitHub Link -->
</button> <a
</div> href="https://github.com/fawney19/Aether"
target="_blank"
rel="noopener noreferrer"
class="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground hover:text-foreground hover:bg-muted/50 transition"
title="GitHub 仓库"
>
<GithubIcon class="h-4 w-4" />
</a>
</div> </div>
</div> </div>
</header> </header>
@@ -336,31 +349,6 @@
</section> </section>
</main> </main>
<!-- Footer -->
<footer class="relative z-10 border-t border-[#cc785c]/10 dark:border-[rgba(227,224,211,0.12)] bg-[#fafaf7]/90 dark:bg-[#191714]/95 backdrop-blur-md py-8">
<div class="mx-auto max-w-7xl px-6">
<div class="flex flex-col items-center justify-between gap-4 sm:flex-row">
<p class="text-sm text-[#91918d] dark:text-muted-foreground">
© 2025 Aether. 团队内部使用
</p>
<div class="flex items-center gap-6 text-sm text-[#91918d] dark:text-muted-foreground">
<a
href="#"
class="transition hover:text-[#191919] dark:hover:text-white"
>使用条款</a>
<a
href="#"
class="transition hover:text-[#191919] dark:hover:text-white"
>隐私政策</a>
<a
href="#"
class="transition hover:text-[#191919] dark:hover:text-white"
>技术支持</a>
</div>
</div>
</div>
</footer>
<LoginDialog v-model="showLoginDialog" /> <LoginDialog v-model="showLoginDialog" />
</div> </div>
</template> </template>
@@ -378,6 +366,7 @@ import {
SunMoon, SunMoon,
Terminal Terminal
} from 'lucide-vue-next' } from 'lucide-vue-next'
import GithubIcon from '@/components/icons/GithubIcon.vue'
import { useAuthStore } from '@/stores/auth' import { useAuthStore } from '@/stores/auth'
import { useDarkMode } from '@/composables/useDarkMode' import { useDarkMode } from '@/composables/useDarkMode'
import { useClipboard } from '@/composables/useClipboard' import { useClipboard } from '@/composables/useClipboard'

View File

@@ -107,6 +107,9 @@ class AdminGetAuditLogsAdapter(AdminApiAdapter):
limit: int limit: int
offset: int offset: int
# 查看审计日志本身不应该产生审计记录,避免刷新页面时产生大量无意义的日志
audit_log_enabled: bool = False
async def handle(self, context): # type: ignore[override] async def handle(self, context): # type: ignore[override]
db = context.db db = context.db
cutoff_time = datetime.now(timezone.utc) - timedelta(days=self.days) cutoff_time = datetime.now(timezone.utc) - timedelta(days=self.days)