Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
ai-box
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
青山
ai-box
Commits
581157d2
Commit
581157d2
authored
Nov 09, 2024
by
fisherdaddy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: 优化移动端展示和SEO
parent
d44aafbd
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
624 additions
and
91 deletions
+624
-91
index.html
index.html
+1
-1
robots.txt
public/robots.txt
+14
-1
sitemap.xml
public/sitemap.xml
+33
-0
Header.jsx
src/components/Header.jsx
+78
-54
SEO.jsx
src/components/SEO.jsx
+45
-19
i18n.json
src/data/i18n.json
+5
-4
Home.jsx
src/pages/Home.jsx
+35
-12
Header.css
src/styles/Header.css
+345
-0
main.css
src/styles/main.css
+68
-0
No files found.
index.html
View file @
581157d2
...
...
@@ -2,7 +2,7 @@
<html
lang=
"zh-CN"
>
<head>
<meta
charset=
"UTF-8"
/>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
/>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0
, maximum-scale=1.0, user-scalable=no, viewport-fit=cover
"
/>
<meta
name=
"robots"
content=
"index, follow"
/>
<meta
name=
"author"
content=
"fisherdaddy"
/>
<link
rel=
"canonical"
href=
"https://fishersama.com"
/>
...
...
public/robots.txt
View file @
581157d2
User-agent: *
Disallow:
Allow: /
Disallow: /api/
Disallow: /admin/
Disallow: /private/
# Allow Google Images to index images
User-agent: Googlebot-Image
Allow: /assets/
Allow: /images/
# Allow Google Mobile to index mobile version
User-agent: Googlebot-Mobile
Allow: /
# Sitemap
Sitemap: https://fishersama.com/sitemap.xml
\ No newline at end of file
public/sitemap.xml
0 → 100644
View file @
581157d2
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns=
"http://www.sitemaps.org/schemas/sitemap/0.9"
>
<url>
<loc>
https://fishersama.com/
</loc>
<lastmod>
2024-01-01
</lastmod>
<changefreq>
daily
</changefreq>
<priority>
1.0
</priority>
</url>
<url>
<loc>
https://fishersama.com/dev-tools
</loc>
<lastmod>
2024-01-01
</lastmod>
<changefreq>
weekly
</changefreq>
<priority>
0.8
</priority>
</url>
<url>
<loc>
https://fishersama.com/image-tools
</loc>
<lastmod>
2024-01-01
</lastmod>
<changefreq>
weekly
</changefreq>
<priority>
0.8
</priority>
</url>
<url>
<loc>
https://fishersama.com/blog
</loc>
<lastmod>
2024-01-01
</lastmod>
<changefreq>
weekly
</changefreq>
<priority>
0.7
</priority>
</url>
<url>
<loc>
https://fishersama.com/ai-products
</loc>
<lastmod>
2024-01-01
</lastmod>
<changefreq>
weekly
</changefreq>
<priority>
0.8
</priority>
</url>
</urlset>
\ No newline at end of file
src/components/Header.jsx
View file @
581157d2
...
...
@@ -11,15 +11,11 @@ function Header() {
const
navigate
=
useNavigate
();
const
user
=
JSON
.
parse
(
localStorage
.
getItem
(
'user'
));
const
[
menuOpen
,
setMenuOpen
]
=
useState
(
false
);
const
[
mobileMenuOpen
,
setMobileMenuOpen
]
=
useState
(
false
);
const
menuRef
=
useRef
(
null
);
const
handleLogout
=
()
=>
{
localStorage
.
removeItem
(
'user'
);
navigate
(
'/login'
);
};
const
toggleMenu
=
()
=>
{
setMenuOpen
(
(
prev
)
=>
!
prev
);
setMenuOpen
(
!
menuOpen
);
};
useEffect
(()
=>
{
...
...
@@ -28,69 +24,97 @@ function Header() {
setMenuOpen
(
false
);
}
};
document
.
addEventListener
(
'mousedown'
,
handleClickOutside
);
return
()
=>
{
document
.
removeEventListener
(
'mousedown'
,
handleClickOutside
);
};
},
[]);
},
[
menuRef
]);
const
handleLogout
=
()
=>
{
localStorage
.
removeItem
(
'user'
);
navigate
(
'/login'
);
setMobileMenuOpen
(
false
);
};
const
toggleMobileMenu
=
()
=>
{
setMobileMenuOpen
(
!
mobileMenuOpen
);
};
const
handleNavClick
=
()
=>
{
setMobileMenuOpen
(
false
);
};
return
(
<
header
>
<
nav
>
<
div
className=
"logo-title-container"
>
<
NavLink
to=
"/"
className=
"title no-underline"
>
<
NavLink
to=
"/"
className=
"title no-underline"
onClick=
{
handleNavClick
}
>
<
img
src=
{
logo
}
alt=
"Logo"
className=
"logo"
/>
{
t
(
'title'
)
}
</
NavLink
>
</
div
>
<
div
className=
"menu-items"
>
<
NavLink
to=
"/dev-tools"
className=
{
({
isActive
})
=>
(
isActive
?
'active'
:
''
)
}
>
{
t
(
'dev-tools'
)
}
</
NavLink
>
<
NavLink
to=
"/image-tools"
className=
{
({
isActive
})
=>
(
isActive
?
'active'
:
''
)
}
>
{
t
(
'image-tools'
)
}
</
NavLink
>
<
NavLink
to=
"/blog"
className=
{
({
isActive
})
=>
(
isActive
?
'active'
:
''
)
}
>
{
t
(
'blog'
)
}
</
NavLink
>
<
NavLink
to=
"/ai-products"
className=
{
({
isActive
})
=>
(
isActive
?
'active'
:
''
)
}
>
{
t
(
'ai-products'
)
}
</
NavLink
>
</
div
>
<
div
className=
"right-container"
>
<
LanguageSelector
/>
<
div
className=
"auth-container"
>
{
user
?
(
<
div
className=
"user-info"
>
<
div
className=
"avatar-container"
ref=
{
menuRef
}
>
<
img
src=
{
user
.
picture
}
alt=
"User Avatar"
className=
"avatar"
onClick=
{
toggleMenu
}
/>
<
div
className=
{
`dropdown-menu ${menuOpen ? 'active' : ''}`
}
>
<
button
onClick=
{
handleLogout
}
>
<
svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
strokeWidth=
"2"
>
<
path
d=
"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"
/>
<
polyline
points=
"16 17 21 12 16 7"
/>
<
line
x1=
"21"
y1=
"12"
x2=
"9"
y2=
"12"
/>
</
svg
>
{
t
(
'logout'
)
}
</
button
>
</
div
>
</
div
>
</
div
>
<
button
className=
"mobile-menu-button"
onClick=
{
toggleMobileMenu
}
>
<
svg
width=
"24"
height=
"24"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
strokeWidth=
"2"
>
{
mobileMenuOpen
?
(
<
path
d=
"M6 18L18 6M6 6l12 12"
/>
)
:
(
<
NavLink
to=
"/login"
className=
"login-button"
>
<
svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
strokeWidth=
"2"
>
<
path
d=
"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"
/>
<
polyline
points=
"10 17 15 12 10 7"
/>
<
line
x1=
"15"
y1=
"12"
x2=
"3"
y2=
"12"
/>
</
svg
>
{
t
(
'login'
)
}
</
NavLink
>
<
path
d=
"M4 6h16M4 12h16M4 18h16"
/>
)
}
</
svg
>
</
button
>
<
div
className=
{
`menu-container ${mobileMenuOpen ? 'mobile-menu-open' : ''}`
}
>
<
div
className=
"menu-items"
>
<
NavLink
to=
"/dev-tools"
onClick=
{
handleNavClick
}
>
{
t
(
'dev-tools'
)
}
</
NavLink
>
<
NavLink
to=
"/image-tools"
onClick=
{
handleNavClick
}
>
{
t
(
'image-tools'
)
}
</
NavLink
>
<
NavLink
to=
"/blog"
onClick=
{
handleNavClick
}
>
{
t
(
'blog'
)
}
</
NavLink
>
<
NavLink
to=
"/ai-products"
onClick=
{
handleNavClick
}
>
{
t
(
'ai-products'
)
}
</
NavLink
>
</
div
>
<
div
className=
"right-container"
>
<
LanguageSelector
/>
<
div
className=
"auth-container"
>
{
user
?
(
<
div
className=
"user-info"
>
<
div
className=
"avatar-container"
ref=
{
menuRef
}
>
<
img
src=
{
user
.
picture
}
alt=
"User Avatar"
className=
"avatar"
onClick=
{
toggleMenu
}
/>
<
div
className=
{
`dropdown-menu ${menuOpen ? 'active' : ''}`
}
>
<
button
onClick=
{
handleLogout
}
>
<
svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
strokeWidth=
"2"
>
<
path
d=
"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"
/>
<
polyline
points=
"16 17 21 12 16 7"
/>
<
line
x1=
"21"
y1=
"12"
x2=
"9"
y2=
"12"
/>
</
svg
>
{
t
(
'logout'
)
}
</
button
>
</
div
>
</
div
>
</
div
>
)
:
(
<
NavLink
to=
"/login"
className=
"login-button"
>
<
svg
xmlns=
"http://www.w3.org/2000/svg"
width=
"16"
height=
"16"
viewBox=
"0 0 24 24"
fill=
"none"
stroke=
"currentColor"
strokeWidth=
"2"
>
<
path
d=
"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"
/>
<
polyline
points=
"10 17 15 12 10 7"
/>
<
line
x1=
"15"
y1=
"12"
x2=
"3"
y2=
"12"
/>
</
svg
>
{
t
(
'login'
)
}
</
NavLink
>
)
}
</
div
>
</
div
>
</
div
>
</
nav
>
...
...
src/components/SEO.jsx
View file @
581157d2
...
...
@@ -7,7 +7,8 @@ function SEO({ title, description, lang = 'en', meta = [] }) {
const
{
t
}
=
useTranslation
();
const
defaultTitle
=
t
(
'title'
);
const
defaultDescription
=
t
(
'description'
);
// 确保在i18n配置中添加'description'
const
defaultDescription
=
t
(
'description'
);
const
defaultKeywords
=
t
(
'keywords'
);
const
languages
=
[
'en'
,
'zh'
,
'ja'
,
'ko'
];
const
hostname
=
'https://fishersama.com'
;
// 替换为您的网站域名
...
...
@@ -20,20 +21,23 @@ function SEO({ title, description, lang = 'en', meta = [] }) {
const
structuredData
=
{
"@context"
:
"https://schema.org"
,
"@type"
:
"
Software
Application"
,
"@type"
:
"
Web
Application"
,
"name"
:
defaultTitle
,
"url"
:
"https://fishersama.com/"
,
// 请替换为您的网站URL
"url"
:
"https://fishersama.com/"
,
"description"
:
defaultDescription
,
"potentialAction"
:
{
"@type"
:
"SearchAction"
,
"target"
:
"https://fishersama.com/search?q={search_term}"
,
"query-input"
:
"required name=search_term"
},
"applicationCategory"
:
"AI Tools"
,
"operatingSystem"
:
"Web Browser"
,
"offers"
:
{
"@type"
:
"Offer"
,
"price"
:
"0"
,
"priceCurrency"
:
"USD"
}
},
"author"
:
{
"@type"
:
"Person"
,
"name"
:
"Fisher"
},
"datePublished"
:
"2024-01-01"
,
"dateModified"
:
new
Date
().
toISOString
().
split
(
'T'
)[
0
]
};
return
(
...
...
@@ -50,11 +54,7 @@ function SEO({ title, description, lang = 'en', meta = [] }) {
},
{
name
:
'keywords'
,
content
:
t
(
'keywords'
),
// 确保在 i18n 配置中添加 'keywords'
},
{
name
:
'viewport'
,
content
:
'width=device-width, initial-scale=1'
,
content
:
defaultKeywords
,
},
{
property
:
'og:title'
,
...
...
@@ -68,9 +68,17 @@ function SEO({ title, description, lang = 'en', meta = [] }) {
property
:
'og:type'
,
content
:
'website'
,
},
{
property
:
'og:image'
,
content
:
'https://fishersama.com/og-image.jpg'
,
},
{
name
:
'twitter:card'
,
content
:
'summary'
,
content
:
'summary_large_image'
,
},
{
name
:
'twitter:creator'
,
content
:
'@fun000001'
,
},
{
name
:
'twitter:title'
,
...
...
@@ -81,12 +89,30 @@ function SEO({ title, description, lang = 'en', meta = [] }) {
content
:
description
||
defaultDescription
,
},
{
name
:
'robots'
,
content
:
'index,follow'
,
name
:
'twitter:image'
,
content
:
'https://fishersama.com/twitter-card.jpg'
,
},
{
name
:
'application-name'
,
content
:
defaultTitle
,
},
{
name
:
'apple-mobile-web-app-title'
,
content
:
defaultTitle
,
},
{
name
:
'format-detection'
,
content
:
'telephone=no'
,
},
// 可以根据需要添加更多元数据
{
name
:
'theme-color'
,
content
:
'#6366F1'
,
}
].
concat
(
meta
)
}
link=
{
links
}
link=
{
[
...
links
,
{
rel
:
'canonical'
,
href
:
`https://fishersama.com${window.location.pathname}`
}
]
}
>
<
script
type=
"application/ld+json"
>
{
JSON
.
stringify
(
structuredData
)
}
...
...
src/data/i18n.json
View file @
581157d2
...
...
@@ -6,6 +6,7 @@
"keywords"
:
"AI Toolbox, AI tools, text cards, JSON formatter, URL decoder, OpenAI products, model price comparison, online tools, free tools"
,
"welcome"
:
"Welcome"
,
"login"
:
"Login"
,
"loginSubtitle"
:
"Welcome to AI Toolbox, please log in for the full experience"
,
"logout"
:
"Logout"
,
"dev-tools"
:
"Development Tools"
,
"image-tools"
:
"Image Tools"
,
...
...
@@ -231,6 +232,7 @@
"keywords"
:
"AI工具箱,AI 工具,文字卡片,JSON 格式化,URL 解码器,OpenAI 产品,模型价格对比,在线工具,免费工具"
,
"welcome"
:
"欢迎"
,
"login"
:
"登录"
,
"loginSubtitle"
:
"欢迎使用 AI 工具箱,请登录以获得完整体验"
,
"logout"
:
"退出登录"
,
"dev-tools"
:
"开发工具"
,
"image-tools"
:
"图片工具"
,
...
...
@@ -447,10 +449,7 @@
"Image"
:
"图像"
,
"AudioVideo"
:
"音视频"
,
"Productivity"
:
"效率办公"
},
"login"
:
"登录"
,
"loginSubtitle"
:
"欢迎使用 AI 工具箱,请登录以获得完整体验"
,
"or"
:
"或"
}
},
"ja"
:
{
"title"
:
"AIツールボックス"
,
...
...
@@ -459,6 +458,7 @@
"keywords"
:
"AIツールボックス、AIツール、テキストカード、JSONフォーマッター、URLデコーダー、OpenAI製品、モデル価格比較、オンラインツール、無料ツール"
,
"welcome"
:
"ようこそ"
,
"login"
:
"ログイン"
,
"loginSubtitle"
:
"AIツールボックスへようこそ。フル体験のためにログインしてください"
,
"logout"
:
"ログアウト"
,
"dev-tools"
:
"開発ツール"
,
"image-tools"
:
"画像ツール"
,
...
...
@@ -686,6 +686,7 @@
"keywords"
:
"AI 도구상자, AI 도구, 텍스트 카드, JSON 포매터, URL 디코더, OpenAI 제품, 모델 가격 비교, 온라인 도구, 무료 도구"
,
"welcome"
:
"환영합니다"
,
"login"
:
"로그인"
,
"loginSubtitle"
:
"AI 툴박스에 오신 것을 환영합니다. 전체 경험을 위해 로그인해 주세요"
,
"logout"
:
"로그아웃"
,
"dev-tools"
:
"개발 도구"
,
"image-tools"
:
"이미지 도구"
,
...
...
src/pages/Home.jsx
View file @
581157d2
...
...
@@ -18,6 +18,38 @@ const tools = [
const
Home
=
()
=>
{
const
{
t
}
=
useTranslation
();
const
renderToolLink
=
(
tool
)
=>
{
const
content
=
(
<>
<
img
src=
{
tool
.
icon
}
alt=
{
`${t(`
tools
.
$
{
tool
.
id
}.
title
`)} icon`
}
className=
"tool-icon"
loading=
"lazy"
/>
<
div
className=
"tool-content"
>
<
h3
className=
"tool-title"
>
{
t
(
`tools.${tool.id}.title`
)
}
</
h3
>
<
p
className=
"tool-description"
>
{
t
(
`tools.${tool.id}.description`
)
}
</
p
>
</
div
>
</>
);
return
tool
.
external
?
(
<
a
href=
{
tool
.
path
}
className=
"tool-card"
target=
"_blank"
rel=
"noopener noreferrer"
>
{
content
}
</
a
>
)
:
(
<
Link
to=
{
tool
.
path
}
className=
"tool-card"
>
{
content
}
</
Link
>
);
};
return
(
<>
<
SEO
...
...
@@ -28,18 +60,9 @@ const Home = () => {
<
section
className=
"tools-section"
>
<
div
className=
"tools-grid"
>
{
tools
.
map
(
tool
=>
(
<
Link
to=
{
tool
.
path
}
key=
{
tool
.
id
}
className=
"tool-card"
>
<
img
src=
{
tool
.
icon
}
alt=
{
`${t(`
tools
.
$
{
tool
.
id
}.
title
`)} icon`
}
className=
"tool-icon"
loading=
"lazy"
/>
<
div
className=
"tool-content"
>
<
h3
className=
"tool-title"
>
{
t
(
`tools.${tool.id}.title`
)
}
</
h3
>
<
p
className=
"tool-description"
>
{
t
(
`tools.${tool.id}.description`
)
}
</
p
>
</
div
>
</
Link
>
<
React
.
Fragment
key=
{
tool
.
id
}
>
{
renderToolLink
(
tool
)
}
</
React
.
Fragment
>
))
}
</
div
>
</
section
>
...
...
src/styles/Header.css
View file @
581157d2
...
...
@@ -432,3 +432,348 @@ header nav {
background
:
rgba
(
99
,
102
,
241
,
0.1
);
color
:
#6366F1
;
}
@media
screen
and
(
max-width
:
768px
)
{
header
{
height
:
auto
;
padding
:
0
;
}
header
nav
{
padding
:
0.6rem
1rem
;
}
.logo
{
width
:
30px
;
height
:
30px
;
}
.title
{
font-size
:
1.4rem
;
}
.menu-items
{
position
:
fixed
;
top
:
60px
;
left
:
0
;
right
:
0
;
background
:
rgba
(
255
,
255
,
255
,
0.95
);
backdrop-filter
:
blur
(
10px
);
padding
:
1rem
;
flex-direction
:
column
;
gap
:
1rem
;
border-bottom
:
1px
solid
rgba
(
99
,
102
,
241
,
0.1
);
display
:
none
;
}
.menu-items.active
{
display
:
flex
;
}
.menu-items
a
{
width
:
100%
;
text-align
:
center
;
padding
:
0.8rem
;
}
.right-container
{
gap
:
0.8rem
;
}
.auth-container
.login-button
{
padding
:
6px
12px
;
font-size
:
0.9rem
;
}
}
/* 移动端菜单按钮 */
.mobile-menu-button
{
display
:
none
;
background
:
none
;
border
:
none
;
padding
:
8px
;
cursor
:
pointer
;
color
:
#4B5563
;
transition
:
color
0.3s
ease
;
}
.mobile-menu-button
:hover
{
color
:
#6366F1
;
}
/* 移动端适配 */
@media
screen
and
(
max-width
:
768px
)
{
header
{
position
:
fixed
;
top
:
0
;
left
:
0
;
right
:
0
;
background
:
rgba
(
255
,
255
,
255
,
0.95
);
backdrop-filter
:
blur
(
10px
);
z-index
:
1000
;
}
header
nav
{
padding
:
0.8rem
1rem
;
justify-content
:
space-between
;
align-items
:
center
;
}
.mobile-menu-button
{
display
:
block
;
z-index
:
1001
;
}
.menu-container
{
position
:
fixed
;
top
:
60px
;
/* 导航栏高度 */
left
:
0
;
right
:
0
;
bottom
:
0
;
background
:
rgba
(
255
,
255
,
255
,
0.98
);
padding
:
1rem
;
transform
:
translateX
(
100%
);
transition
:
transform
0.3s
ease
;
overflow-y
:
auto
;
display
:
flex
;
flex-direction
:
column
;
gap
:
1rem
;
z-index
:
1000
;
}
.menu-container.mobile-menu-open
{
transform
:
translateX
(
0
);
}
.menu-items
{
display
:
flex
;
flex-direction
:
column
;
margin
:
0
;
width
:
100%
;
gap
:
0.5rem
;
}
.menu-items
a
{
width
:
100%
;
padding
:
1rem
;
text-align
:
center
;
}
.right-container
{
margin-top
:
1rem
;
width
:
100%
;
}
}
/* 横屏模式优化 */
@media
screen
and
(
max-width
:
768px
)
and
(
orientation
:
landscape
)
{
.menu-container
{
top
:
50px
;
}
.menu-items
{
flex-direction
:
row
;
flex-wrap
:
wrap
;
justify-content
:
center
;
}
.menu-items
a
{
width
:
auto
;
}
.right-container
{
flex-direction
:
row
;
justify-content
:
center
;
}
}
/* 移动端样式统一处理 */
@media
screen
and
(
max-width
:
768px
)
{
header
{
position
:
fixed
;
top
:
0
;
left
:
0
;
right
:
0
;
background
:
rgba
(
255
,
255
,
255
,
0.95
);
backdrop-filter
:
blur
(
10px
);
z-index
:
1000
;
}
header
nav
{
padding
:
0.8rem
1rem
;
justify-content
:
space-between
;
align-items
:
center
;
}
.mobile-menu-button
{
display
:
block
;
z-index
:
1001
;
background
:
none
;
border
:
none
;
padding
:
8px
;
cursor
:
pointer
;
color
:
#4B5563
;
transition
:
color
0.3s
ease
;
}
.mobile-menu-button
:hover
{
color
:
#6366F1
;
}
.menu-container
{
position
:
fixed
;
top
:
60px
;
left
:
0
;
right
:
0
;
bottom
:
0
;
background
:
rgba
(
255
,
255
,
255
,
0.98
);
backdrop-filter
:
blur
(
10px
);
padding
:
1rem
;
transform
:
translateX
(
100%
);
transition
:
transform
0.3s
ease
;
z-index
:
999
;
display
:
flex
;
flex-direction
:
column
;
overflow-y
:
auto
;
}
.menu-container.mobile-menu-open
{
transform
:
translateX
(
0
);
}
.menu-items
{
display
:
flex
;
flex-direction
:
column
;
margin
:
0
;
width
:
100%
;
gap
:
1rem
;
}
.menu-items
a
{
width
:
100%
;
text-align
:
center
;
padding
:
1rem
;
font-size
:
1.1rem
;
}
.right-container
{
margin-top
:
1rem
;
width
:
100%
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
gap
:
1rem
;
}
.auth-container
{
width
:
100%
;
display
:
flex
;
justify-content
:
center
;
}
.login-button
{
width
:
100%
;
justify-content
:
center
;
}
}
/* 横屏模式优化 */
@media
screen
and
(
max-width
:
768px
)
and
(
orientation
:
landscape
)
{
.menu-container
{
top
:
50px
;
}
.menu-items
{
flex-direction
:
row
;
flex-wrap
:
wrap
;
justify-content
:
center
;
}
.menu-items
a
{
width
:
auto
;
}
.right-container
{
flex-direction
:
row
;
justify-content
:
center
;
}
}
/* 移动端菜单按钮 */
.mobile-menu-button
{
display
:
none
;
background
:
none
;
border
:
none
;
padding
:
8px
;
cursor
:
pointer
;
color
:
#4B5563
;
transition
:
color
0.3s
ease
;
}
/* 移动端菜单容器 */
.menu-container
{
display
:
flex
;
align-items
:
center
;
flex
:
1
;
}
@media
screen
and
(
max-width
:
768px
)
{
.mobile-menu-button
{
display
:
block
;
}
.menu-container
{
position
:
fixed
;
top
:
60px
;
left
:
0
;
right
:
0
;
bottom
:
0
;
background
:
rgba
(
255
,
255
,
255
,
0.98
);
padding
:
1rem
;
transform
:
translateX
(
100%
);
transition
:
transform
0.3s
ease
;
z-index
:
999
;
display
:
flex
;
flex-direction
:
column
;
}
.menu-container.mobile-menu-open
{
transform
:
translateX
(
0
);
}
.menu-items
{
display
:
flex
!important
;
/* 覆盖之前的 display: none */
flex-direction
:
column
;
margin
:
0
;
width
:
100%
;
gap
:
1rem
;
}
.menu-items
a
{
width
:
100%
;
text-align
:
center
;
padding
:
1rem
;
}
.right-container
{
margin-top
:
1rem
;
width
:
100%
;
}
}
/* 横屏模式优化 */
@media
screen
and
(
max-width
:
768px
)
and
(
orientation
:
landscape
)
{
.menu-container
{
top
:
50px
;
}
.menu-items
{
flex-direction
:
row
;
flex-wrap
:
wrap
;
justify-content
:
center
;
}
.menu-items
a
{
width
:
auto
;
}
}
src/styles/main.css
View file @
581157d2
...
...
@@ -255,4 +255,72 @@ footer {
linear-gradient
(
90deg
,
rgba
(
99
,
102
,
241
,
0.05
)
1px
,
transparent
1px
),
linear-gradient
(
rgba
(
99
,
102
,
241
,
0.05
)
1px
,
transparent
1px
);
background-size
:
100%
100%
,
20px
20px
,
20px
20px
;
}
/* 移动端适配基础设置 */
@media
screen
and
(
max-width
:
768px
)
{
:root
{
font-size
:
14px
;
/* 调整基础字体大小 */
}
main
{
padding
:
1rem
;
margin-top
:
3.5rem
;
/* 为固定导航栏留出空间 */
}
.tools-section
{
padding
:
1rem
0
;
}
.tools-section
h2
{
font-size
:
2rem
;
margin-bottom
:
1.5rem
;
padding
:
0
1rem
;
}
.tools-grid
{
grid-template-columns
:
1
fr
;
gap
:
1rem
;
padding
:
0
1rem
;
}
.tool-card
{
padding
:
1.2rem
;
}
.tool-icon
{
width
:
35px
;
height
:
35px
;
}
.tool-title
{
font-size
:
1.2rem
;
}
.tool-description
{
font-size
:
0.95rem
;
}
}
/* 针对更小屏幕的优化 */
@media
screen
and
(
max-width
:
480px
)
{
.tools-section
h2
{
font-size
:
1.8rem
;
}
.tool-card
{
padding
:
1rem
;
}
.tool-icon
{
width
:
30px
;
height
:
30px
;
}
}
/* 针对横屏模式的优化 */
@media
screen
and
(
max-width
:
768px
)
and
(
orientation
:
landscape
)
{
.tools-grid
{
grid-template-columns
:
repeat
(
2
,
1
fr
);
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment