Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ backend-cf/.dev.vars

frontend/node_modules/
frontend/.nuxt/
frontend/.output/

# wrangler files
.wrangler
Expand Down
112 changes: 103 additions & 9 deletions frontend/app.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,125 @@
<template>
<div class="min-h-screen flex flex-col">
<header class="bg-white border-b border-gray-200 sticky top-0 z-50">
<header class="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800 sticky top-0 z-50">
<div class="max-w-6xl mx-auto px-4 h-14 flex items-center justify-between">
<NuxtLink to="/" class="text-lg font-bold text-primary-600 hover:text-primary-700">
<NuxtLink to="/" class="text-lg font-bold text-primary-600 hover:text-primary-700 shrink-0">
Trans‑Search
</NuxtLink>
<nav class="flex items-center gap-1">
<NuxtLink to="/" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100" active-class="bg-primary-50 text-primary-700 font-medium">

<!-- Desktop nav + dark toggle -->
<nav class="hidden md:flex items-center gap-1">
<NuxtLink to="/" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium">
搜索
</NuxtLink>
<NuxtLink to="/tree" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100" active-class="bg-primary-50 text-primary-700 font-medium">
<NuxtLink to="/tree" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium">
分类
</NuxtLink>
<NuxtLink to="/stats" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100" active-class="bg-primary-50 text-primary-700 font-medium">
<NuxtLink to="/stats" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium">
统计
</NuxtLink>
<NuxtLink to="/config" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100" active-class="bg-primary-50 text-primary-700 font-medium">
<NuxtLink to="/config" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium">
管理
</NuxtLink>
<NuxtLink to="/about" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100" active-class="bg-primary-50 text-primary-700 font-medium">
<NuxtLink to="/about" class="px-3 py-1.5 rounded-md text-sm hover:bg-gray-100 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium">
关于
</NuxtLink>

<!-- Dark mode toggle (desktop: inside nav) -->
<button
class="ml-1 p-1.5 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-500 dark:text-gray-400"
aria-label="切换暗色模式"
@click="toggleDark"
>
<svg v-if="isDark" class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
<svg v-else class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
</svg>
</button>
</nav>

<!-- Mobile: dark toggle + hamburger (only) -->
<div class="flex md:hidden items-center gap-1">
<button
class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-500 dark:text-gray-400"
aria-label="切换暗色模式"
@click="toggleDark"
>
<svg v-if="isDark" class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
<svg v-else class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
</svg>
</button>

<button
class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-600 dark:text-gray-300"
aria-label="菜单"
@click="mobileMenuOpen = !mobileMenuOpen"
>
<svg v-if="!mobileMenuOpen" class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<svg v-else class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>

<!-- Mobile slide-down menu -->
<Transition name="slide-down">
<nav v-if="mobileMenuOpen" class="md:hidden border-t border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900 px-4 py-2 flex flex-col gap-0.5">
<NuxtLink to="/" class="px-3 py-2.5 rounded-md text-sm hover:bg-gray-50 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium" @click="mobileMenuOpen = false">
搜索
</NuxtLink>
<NuxtLink to="/tree" class="px-3 py-2.5 rounded-md text-sm hover:bg-gray-50 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium" @click="mobileMenuOpen = false">
分类
</NuxtLink>
<NuxtLink to="/stats" class="px-3 py-2.5 rounded-md text-sm hover:bg-gray-50 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium" @click="mobileMenuOpen = false">
统计
</NuxtLink>
<NuxtLink to="/config" class="px-3 py-2.5 rounded-md text-sm hover:bg-gray-50 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium" @click="mobileMenuOpen = false">
管理
</NuxtLink>
<NuxtLink to="/about" class="px-3 py-2.5 rounded-md text-sm hover:bg-gray-50 dark:hover:bg-gray-800 dark:text-gray-300" active-class="bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 font-medium" @click="mobileMenuOpen = false">
关于
</NuxtLink>
</nav>
</Transition>
</header>
<main class="flex-1">
<main class="flex-1 bg-gray-50 dark:bg-gray-950">
<NuxtPage />
</main>
</div>
</template>

<script setup lang="ts">
const mobileMenuOpen = ref(false)
const { isDark, toggle: toggleDark } = useDarkMode()

// Close menu on route change
const router = useRouter()
router.afterEach(() => {
mobileMenuOpen.value = false
})
</script>

<style>
.slide-down-enter-active,
.slide-down-leave-active {
transition: all 0.2s ease;
}
.slide-down-enter-from,
.slide-down-leave-to {
opacity: 0;
max-height: 0;
}
.slide-down-enter-to,
.slide-down-leave-from {
opacity: 1;
max-height: 300px;
}
</style>
4 changes: 4 additions & 0 deletions frontend/assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
body {
@apply bg-gray-50 text-gray-900 min-h-screen;
}

html.dark body {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

只改了背景,没有改控件,会出现比如侧边滚动条还是亮色的情况

Suggested change
html.dark body {
html.dark { color-scheme: dark; }

@apply bg-gray-950 text-gray-100;
}
33 changes: 33 additions & 0 deletions frontend/composables/useDarkMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export function useDarkMode() {
const colorMode = useCookie<string>('dark-mode', {
default: () => '',
watch: true,
maxAge: 60 * 60 * 24 * 365, // 1 year
})

const isDark = computed({
get: () => colorMode.value === 'dark',
set: (val: boolean) => {
colorMode.value = val ? 'dark' : 'light'
},
})

// Sync cookie <-> <html> class
if (import.meta.client) {
watch(isDark, (val) => {
document.documentElement.classList.toggle('dark', val)
}, { immediate: true })
}

function toggle() {
isDark.value = !isDark.value
}

// If no cookie set yet, use system preference on client

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先通过CSS读浏览器深色偏好,优先跟随浏览器偏好,手动设置了再往cookie写

if (import.meta.client && !colorMode.value) {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
isDark.value = prefersDark
}

return { isDark, toggle }
}
5 changes: 5 additions & 0 deletions frontend/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ export default defineNuxtConfig({
compatibilityDate: "2026-07-14",
devtools: { enabled: true },
modules: ["@nuxtjs/tailwindcss"],
tailwindcss: {
config: {
darkMode: "class",
},
},
nitro: {
preset: "cloudflare_module",
devProxy: {
Expand Down
46 changes: 23 additions & 23 deletions frontend/pages/about.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<template>
<div class="max-w-3xl mx-auto px-4 py-8">
<h1 class="text-2xl font-bold mb-6">关于与致谢</h1>
<h1 class="text-2xl font-bold mb-6 dark:text-white">关于与致谢</h1>

<section class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
<h2 class="text-lg font-semibold mb-3">开源许可</h2>
<p class="text-sm text-gray-600 leading-relaxed mb-3">
Trans-Search 基于 <a href="https://www.gnu.org/licenses/gpl-3.0.html" target="_blank" class="text-primary-600 hover:underline">GNU General Public License v3.0 (GPL-3.0)</a> 开源。
<section class="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6 mb-6">
<h2 class="text-lg font-semibold mb-3 dark:text-gray-200">开源许可</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed mb-3">
Trans-Search 基于 <a href="https://www.gnu.org/licenses/gpl-3.0.html" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">GNU General Public License v3.0 (GPL-3.0)</a> 开源。
</p>
<pre v-pre class="bg-gray-50 border border-gray-200 rounded-lg p-4 text-xs text-gray-500 leading-relaxed overflow-x-auto">
<pre v-pre class="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-4 text-xs text-gray-500 dark:text-gray-400 leading-relaxed overflow-x-auto">
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

Expand All @@ -28,38 +28,38 @@ along with this program. If not, see https://www.gnu.org/licenses/.
</pre>
</section>

<section class="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
<h2 class="text-lg font-semibold mb-3">技术致谢</h2>
<div class="space-y-3 text-sm text-gray-600 leading-relaxed">
<section class="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6 mb-6">
<h2 class="text-lg font-semibold mb-3 dark:text-gray-200">技术致谢</h2>
<div class="space-y-3 text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
<div class="flex items-start gap-3">
<span class="shrink-0 w-20 text-xs text-gray-400 font-mono">搜索引擎</span>
<span><a href="https://qdrant.tech" target="_blank" class="text-primary-600 hover:underline">Qdrant</a> — 开源向量数据库,提供混合检索能力</span>
<span class="shrink-0 w-20 text-xs text-gray-400 dark:text-gray-500 font-mono">搜索引擎</span>
<span><a href="https://qdrant.tech" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Qdrant</a> — 开源向量数据库,提供混合检索能力</span>
</div>
<div class="flex items-start gap-3">
<span class="shrink-0 w-20 text-xs text-gray-400 font-mono">基础模型</span>
<span class="shrink-0 w-20 text-xs text-gray-400 dark:text-gray-500 font-mono">基础模型</span>
<span>
<a href="https://huggingface.co/Qwen" target="_blank" class="text-primary-600 hover:underline">Qwen</a> 系列模型(Qwen3-8B / Qwen3-Embedding-0.6B)—
<a href="https://www.siliconflow.cn" target="_blank" class="text-primary-600 hover:underline">硅基流动</a> 提供 API 服务
<a href="https://huggingface.co/Qwen" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Qwen</a> 系列模型(Qwen3-8B / Qwen3-Embedding-0.6B)—
<a href="https://www.siliconflow.cn" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">硅基流动</a> 提供 API 服务
</span>
</div>
<div class="flex items-start gap-3">
<span class="shrink-0 w-20 text-xs text-gray-400 font-mono">重排序</span>
<span><a href="https://huggingface.co/BAAI/bge-reranker-v2-m3" target="_blank" class="text-primary-600 hover:underline">BAAI/bge-reranker-v2-m3</a> — 北京智源人工智能研究院开源的交叉编码器重排序模型</span>
<span class="shrink-0 w-20 text-xs text-gray-400 dark:text-gray-500 font-mono">重排序</span>
<span><a href="https://huggingface.co/BAAI/bge-reranker-v2-m3" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">BAAI/bge-reranker-v2-m3</a> — 北京智源人工智能研究院开源的交叉编码器重排序模型</span>
</div>
<div class="flex items-start gap-3">
<span class="shrink-0 w-20 text-xs text-gray-400 font-mono">运行时</span>
<span><a href="https://workers.cloudflare.com" target="_blank" class="text-primary-600 hover:underline">Cloudflare Workers</a> — 边缘计算平台;<a href="https://hono.dev" target="_blank" class="text-primary-600 hover:underline">Hono</a> — 轻量级 Web 框架</span>
<span class="shrink-0 w-20 text-xs text-gray-400 dark:text-gray-500 font-mono">运行时</span>
<span><a href="https://workers.cloudflare.com" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Cloudflare Workers</a> — 边缘计算平台;<a href="https://hono.dev" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Hono</a> — 轻量级 Web 框架</span>
</div>
<div class="flex items-start gap-3">
<span class="shrink-0 w-20 text-xs text-gray-400 font-mono">前端</span>
<span><a href="https://nuxt.com" target="_blank" class="text-primary-600 hover:underline">Nuxt</a> / <a href="https://vuejs.org" target="_blank" class="text-primary-600 hover:underline">Vue</a> / <a href="https://tailwindcss.com" target="_blank" class="text-primary-600 hover:underline">Tailwind CSS</a></span>
<span class="shrink-0 w-20 text-xs text-gray-400 dark:text-gray-500 font-mono">前端</span>
<span><a href="https://nuxt.com" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Nuxt</a> / <a href="https://vuejs.org" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Vue</a> / <a href="https://tailwindcss.com" target="_blank" class="text-primary-600 dark:text-primary-400 hover:underline">Tailwind CSS</a></span>
</div>
</div>
</section>

<section class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
<h2 class="text-lg font-semibold mb-3">内容来源</h2>
<p class="text-sm text-gray-600 leading-relaxed">
<section class="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6">
<h2 class="text-lg font-semibold mb-3 dark:text-gray-200">内容来源</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 leading-relaxed">
本站聚合的跨性别相关信息来源于多个中文社区、医疗指南、法律文书及公益组织公开资料。
所有内容的版权归原作者或来源机构所有。如有版权问题,请联系我们处理。
</p>
Expand Down
Loading