feat: optimize header and footer

This commit is contained in:
2026-02-26 22:23:54 +08:00
parent ca5c3c8d21
commit af270b3d6a
15 changed files with 126 additions and 76 deletions

4
components.d.ts vendored
View File

@@ -40,6 +40,8 @@ declare module 'vue' {
ElButton: typeof import('element-plus/es')['ElButton']
FooterBar: typeof import('./src/components/layout/FooterBar.vue')['default']
FooterBarV2: typeof import('./src/components/layout/FooterBarV2.vue')['default']
FooterBarV2Placeholder: typeof import('./src/components/layout/FooterBarV2Placeholder.vue')['default']
FooterBarV2Space: typeof import('./src/components/layout/FooterBarV2Space.vue')['default']
LogoIcon: typeof import('./src/components/icon/LogoIcon.vue')['default']
NativeSelect: typeof import('./src/components/ui/native-select/NativeSelect.vue')['default']
NativeSelectOptGroup: typeof import('./src/components/ui/native-select/NativeSelectOptGroup.vue')['default']
@@ -86,6 +88,8 @@ declare global {
const ElButton: typeof import('element-plus/es')['ElButton']
const FooterBar: typeof import('./src/components/layout/FooterBar.vue')['default']
const FooterBarV2: typeof import('./src/components/layout/FooterBarV2.vue')['default']
const FooterBarV2Placeholder: typeof import('./src/components/layout/FooterBarV2Placeholder.vue')['default']
const FooterBarV2Space: typeof import('./src/components/layout/FooterBarV2Space.vue')['default']
const LogoIcon: typeof import('./src/components/icon/LogoIcon.vue')['default']
const NativeSelect: typeof import('./src/components/ui/native-select/NativeSelect.vue')['default']
const NativeSelectOptGroup: typeof import('./src/components/ui/native-select/NativeSelectOptGroup.vue')['default']

View File

@@ -0,0 +1,13 @@
# 滚动
## 平滑滚动
Hucky 选择了 [Lenis](https://lenis.darkroom.engineering/) 为项目提供平滑滚动,您可以在 `App.vue` 中控制平滑滚动的开关。
## 滚动失效
如果您遇到了滚动失效的情况,这是因为 Lenis 和普通滚动冲突,您可以通过添加 `data-lenis-prevent` 属性来防止 lenis 平滑滚动。例如:
```html
<div data-lenis-prevent></div>
```

View File

@@ -4,7 +4,11 @@ import { useLanguageStore } from "./stores/LanguageStore";
import Lenis from "lenis";
// 开启 lenis 平滑滚动
const lenis = new Lenis();
const lenis = new Lenis({
// 通过添加 data-lenis-prevent 属性来防止 lenis 平滑滚动
prevent: (node) =>
node.tagName === "SELECT" || node.hasAttribute("data-lenis-prevent"),
});
function raf(time) {
lenis.raf(time);

View File

@@ -33,13 +33,10 @@ const onClickChangeLocal = (newLanguage: string) => {
d="M12 21a9 9 0 1 0 0-18m0 18a9 9 0 1 1 0-18m0 18c2.761 0 3.941-5.163 3.941-9S14.761 3 12 3m0 18c-2.761 0-3.941-5.163-3.941-9S9.239 3 12 3M3.5 9h17m-17 6h17"
/>
</svg>
<svg
class="mt-px hidden size-2 fill-current opacity-60 sm:inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 2048 2048"
>
<path d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z" />
</svg>
<span class="text-base-content/70">{{ t("nav.locale") }}</span>
<span
class="icon-[material-symbols--keyboard-arrow-down-rounded] text-lg text-base-content/70"
/>
</div>
<div
tabindex="0"

View File

@@ -1,6 +1,17 @@
<script setup lang="ts">
import { useGlobalThemeHook } from "@/hooks/globalThemeHook";
import { useI18n } from "vue-i18n";
import Lenis from "lenis";
// 开启 lenis 平滑滚动
const lenis = new Lenis();
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
const { t } = useI18n();
@@ -20,17 +31,13 @@ const { changeGlobalTheme, curGlobalTheme, optionalThemes } =
<div class="bg-secondary size-1 rounded-full" />
<div class="bg-accent size-1 rounded-full" />
</div>
<svg
class="mt-px hidden size-2 fill-current opacity-60 sm:inline-block"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 2048 2048"
>
<path
d="M1799 349l242 241-1017 1017L7 590l242-241 775 775 775-775z"
/>
</svg>
<span class="text-base-content/70">{{ t("nav.theme") }}</span>
<span
class="icon-[material-symbols--keyboard-arrow-down-rounded] text-lg text-base-content/70"
/>
</div>
<ul
data-lenis-prevent
tabindex="-1"
class="dropdown-content bg-base-300 rounded-box z-1 w-52 p-2 shadow-2xl max-h-84 overflow-auto mt-6"
>

View File

@@ -25,15 +25,16 @@ const handleLogout = () => {
<div
v-if="!userStore.checkUserLogin()"
role="button"
class="btn btn-circle btn-sm btn-ghost px-3 w-16"
class="btn btn-sm btn-primary px-3"
@click="
renderAuthDialog('login');
closeDropdown();
"
>
<span class="text-sm text-base-content/70">
<span>
{{ $t("nav.login") }}
</span>
<span class="icon-[material-symbols--login-rounded] text-sm" />
</div>
<div
v-else

View File

@@ -14,25 +14,6 @@
xmlns:svg="http://www.w3.org/2000/svg"
>
<defs id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="2.6914062"
inkscape:cx="127.81422"
inkscape:cy="128"
inkscape:window-width="1600"
inkscape:window-height="928"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g1"
/>
<g inkscape:groupmode="layer" inkscape:label="Image" id="g1">
<path
style="fill: #ff2842; stroke: none"

View File

@@ -7,7 +7,7 @@ import RedBookIcon from "../icon/RedBookIcon.vue";
<template>
<footer
class="fixed bottom-0 left-0 w-full z-[-1] pt-16 pb-10 px-6 md:px-12 lg:px-20 text-sm font-[LXGW] h-102"
class="fixed bottom-0 left-0 w-full z-1 pt-16 pb-10 px-6 md:px-12 lg:px-20 text-sm font-[LXGW] lg:h-102 md:h-122 h-154"
>
<!-- Background overlay -->
<div
@@ -106,8 +106,8 @@ import RedBookIcon from "../icon/RedBookIcon.vue";
</div>
<!-- Bottom legal line -->
<div class="mt-8 text-xs text-gray-500 text-center md:text-left">
<div class="max-w-7xl mx-auto px-6 md:px-0">
<div class="mt-8 text-xs text-gray-500 text-left">
<div class="max-w-7xl mx-auto">
Copyright © 2026 sunway.icu | 备案号浙ICP备2023010223号 |
增值电信业务经营许可证浙B2-20110004
</div>

View File

@@ -6,7 +6,6 @@ import { throttle } from "radash";
import { AnimatePresence, motion } from "motion-v";
import { navigateTo } from "@/utils/navigator";
import UserAuthNavButton from "../button/UserAuthNavButton.vue";
import LogoIcon from "../icon/LogoIcon.vue";
const { t } = useI18n();
@@ -29,6 +28,25 @@ const navPageByResetScroll = (path: string) => {
window.scrollTo({ top: 0, behavior: "smooth" });
navigateTo(path);
};
const menuItems = ref([
{
path: "/",
label: "nav.home",
},
{
path: "/about",
label: "nav.about",
},
{
path: "/demo",
label: "nav.demo",
},
{
path: "/join",
label: "nav.join",
},
]);
</script>
<template>
@@ -47,50 +65,29 @@ const navPageByResetScroll = (path: string) => {
<div class="navbar-start">
<div class="dropdown">
<div tabindex="0" role="button" class="btn btn-ghost lg:hidden">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h8m-8 6h16"
/>
</svg>
<span class="icon-[material-symbols--menu-rounded] text-2xl" />
</div>
<ul
tabindex="-1"
class="menu dropdown-content bg-base-100 rounded-box z-1 mt-5 w-52 p-2 shadow"
class="menu dropdown-content bg-base-100 rounded-box z-1 mt-5 w-48 p-2 shadow"
>
<li>
<a @click="navPageByResetScroll('/')">{{ t("nav.home") }}</a>
</li>
<li>
<a @click="navPageByResetScroll('/about')">{{
t("nav.about")
<li v-for="item in menuItems" :key="item.path">
<a @click="navPageByResetScroll(item.path)">{{
t(item.label)
}}</a>
</li>
</ul>
</div>
<a class="btn btn-ghost text-xl">Hucky</a>
</div>
<div class="navbar-center hidden lg:flex">
<ul class="menu menu-horizontal px-1">
<li>
<a @click="navPageByResetScroll('/')">{{ t("nav.home") }}</a>
</li>
<li>
<a @click="navPageByResetScroll('/about')">{{
t("nav.about")
<ul class="menu menu-horizontal pl-6 hidden lg:flex gap-3">
<li v-for="item in menuItems" :key="item.path">
<a @click="navPageByResetScroll(item.path)">{{
t(item.label)
}}</a>
</li>
</ul>
</div>
<div class="navbar-end">
<div class="navbar-end gap-2">
<ChangeThemeDropdownButton />
<ChangeLanguageDropdownButton />
<UserAuthNavButton />

View File

@@ -4,6 +4,8 @@ export const en_USMessages: messagesInterface = {
nav: {
home: "Home",
about: "About",
demo: "Demo",
join: "Join",
theme: "Theme",
locale: "Locale",
login: "Login",

View File

@@ -6,6 +6,8 @@ export interface messagesInterface {
nav: {
home: string;
about: string;
demo: string;
join: string;
theme: string;
locale: string;
login: string;

View File

@@ -4,6 +4,8 @@ export const zh_CNMessages: messagesInterface = {
nav: {
home: "首页",
about: "关于",
demo: "演示",
join: "加入",
theme: "主题",
locale: "语言",
login: "登录",

20
src/pages/demo.vue Normal file
View File

@@ -0,0 +1,20 @@
<script setup lang="ts">
import NavBar from "@/components/menu/NavBar.vue";
import FooterBarV2 from "@/components/layout/FooterBarV2.vue";
</script>
<template>
<div class="lg:pb-102 md:pb-122 pb-154">
<!-- 这里开 relative 形成 stack context -->
<div class="bg-base-200 relative z-2">
<div class="h-screen flex flex-col">
<NavBar class="fixed top-0 left-0 z-10" />
<!-- 同高度占位颜色叠加 -->
<div class="h-16 bg-base-300" />
</div>
</div>
<FooterBarV2 />
</div>
</template>
<style scoped></style>

View File

@@ -39,8 +39,9 @@ const progress = ref([
</script>
<template>
<div>
<div class="bg-base-200">
<div class="lg:pb-102 md:pb-122 pb-154">
<!-- 这里开 relative 形成 stack context -->
<div class="bg-base-200 relative z-2">
<div class="h-screen flex flex-col">
<NavBar class="fixed top-0 left-0 z-10" />
<!-- 同高度占位颜色叠加 -->
@@ -91,7 +92,6 @@ const progress = ref([
</div>
</div>
</div>
<div class="h-102 bg-transparent z-5" />
<FooterBarV2 />
</div>
</template>

20
src/pages/join.vue Normal file
View File

@@ -0,0 +1,20 @@
<script setup lang="ts">
import NavBar from "@/components/menu/NavBar.vue";
import FooterBarV2 from "@/components/layout/FooterBarV2.vue";
</script>
<template>
<div class="lg:pb-102 md:pb-122 pb-154">
<!-- 这里开 relative 形成 stack context -->
<div class="bg-base-200 relative z-2">
<div class="h-screen flex flex-col">
<NavBar class="fixed top-0 left-0 z-10" />
<!-- 同高度占位颜色叠加 -->
<div class="h-16 bg-base-300" />
</div>
</div>
<FooterBarV2 />
</div>
</template>
<style scoped></style>