refactor(CharacterDetail): 重构角色详情页面布局和功能

- 更新页面布局,将头像和导航栏移到左侧,主要内容移到右侧- 添加页面滚动重置功能,确保每次打开详情页时从顶部开始
- 优化各个部分内容的样式和间距,提升可读性和美观度
- 更新角色列表页面中的角色图片链接
- 在导航栏中添加角色列表页面的链接
This commit is contained in:
hu xiaotong
2025-05-06 17:12:47 +08:00
parent e4de238018
commit 916a0d1de1
15 changed files with 121 additions and 130 deletions

BIN
public/pic/element/dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
public/pic/element/fire.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

BIN
public/pic/role/knight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
public/pic/role/mage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
public/pic/role/ranger.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
public/pic/role/thief.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/pic/role/warrior.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
public/pic/star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -13,7 +13,7 @@ interface NavItem {
const navItems: NavItem[] = [ const navItems: NavItem[] = [
{ path: "/", label: "对战阵容" }, { path: "/", label: "对战阵容" },
// { path: "/home", label: "主页" }, // { path: "/home", label: "主页" },
// { path: "/characters", label: "角色列表" }, { path: "/characters", label: "角色列表" },
// { path: "/builds", label: "配装攻略" }, // { path: "/builds", label: "配装攻略" },
// { path: "/battles", label: "对战信息" }, // { path: "/battles", label: "对战信息" },
// { path: "/news", label: "资讯中心" }, // { path: "/news", label: "资讯中心" },

View File

@@ -1,4 +1,4 @@
import React from 'react'; import React, { useEffect } from 'react';
export interface Skill { export interface Skill {
name: string; name: string;
@@ -42,6 +42,10 @@ interface CharacterDetailProps {
} }
const CharacterDetail: React.FC<CharacterDetailProps> = ({ character }) => { const CharacterDetail: React.FC<CharacterDetailProps> = ({ character }) => {
useEffect(() => {
window.scrollTo({ top: 0, behavior: 'auto' });
}, []);
const renderStars = (count: number) => { const renderStars = (count: number) => {
return Array(count) return Array(count)
.fill(0) .fill(0)
@@ -74,141 +78,128 @@ const CharacterDetail: React.FC<CharacterDetailProps> = ({ character }) => {
return ( return (
<div className="min-h-screen bg-[#1A1412] text-white font-sans"> <div className="min-h-screen bg-[#1A1412] text-white font-sans">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex">
{/* 角色基本信息 */} {/* 左侧:头像+导航 */}
<div className="bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 mb-8 border border-[#C17F59]/30"> <aside className="w-80 flex-shrink-0 pr-6 flex flex-col pt-12">
<div className="flex items-start space-x-6"> {/* 头像卡片 */}
<div className="w-32 h-32 rounded-full overflow-hidden border-4 border-[#C17F59]"> <div className="bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 mb-12 border border-[#C17F59]/30 flex flex-col items-center">
<img <div className="w-28 h-28 rounded-full overflow-hidden border-4 border-[#C17F59] mb-3">
src={character.imageUrl} <img src={character.imageUrl} alt={character.name} className="w-full h-full object-cover" />
alt={character.name}
className="w-full h-full object-cover"
/>
</div> </div>
<div> <h1 className="text-2xl font-bold text-[#E6B17E] mb-1">{character.name}</h1>
<h1 className="text-3xl font-bold text-[#E6B17E] mb-2"> <div className="flex mb-1">{renderStars(character.stars)}</div>
{character.name} <span className="text-[#9B8579] mb-2">{character.class}</span>
</h1> </div>
<div className="flex items-center space-x-4 mb-4"> {/* 导航卡片 */}
<div className="flex"> <nav className="sticky top-12 z-30">
{renderStars(character.stars)} <div className="bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 border border-[#C17F59]/30">
</div> <h2 className="text-lg font-bold mb-3 text-white">Table of Contents</h2>
<span className="text-[#9B8579]">{character.class}</span> <ul className="space-y-2">
<li>
<a href="#base-stats" className="hover:text-[#E6B17E] transition">Base Stats</a>
</li>
<li>
<a href="#skills" className="hover:text-[#E6B17E] transition">Skills</a>
</li>
<li>
<a href="#imprint" className="hover:text-[#E6B17E] transition">Imprint Concentration</a>
</li>
</ul>
</div>
</nav>
</aside>
{/* 右侧:详细内容 */}
<main className="flex-1 max-w-4xl mx-auto space-y-8">
{/* 基础属性 */}
<section id="base-stats" className="scroll-mt-24 bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 border border-[#C17F59]/30 mt-12">
<h2 className="text-xl font-bold text-[#E6B17E] mb-4">Base Stats</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="flex items-center space-x-2">
<i className="fas fa-sword text-[#C17F59]"></i>
<span>Attack: {character.baseStats.attack}</span>
</div>
<div className="flex items-center space-x-2">
<i className="fas fa-heart text-[#C17F59]"></i>
<span>Health: {character.baseStats.health}</span>
</div>
<div className="flex items-center space-x-2">
<i className="fas fa-shield-alt text-[#C17F59]"></i>
<span>Defense: {character.baseStats.defense}</span>
</div>
<div className="flex items-center space-x-2">
<i className="fas fa-wind text-[#C17F59]"></i>
<span>Speed: {character.baseStats.speed}</span>
</div> </div>
</div> </div>
</div> </section>
</div>
{/* 基础属性 */} {/* 技能列表 */}
<div className="bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 mb-8 border border-[#C17F59]/30"> <section id="skills" className="scroll-mt-24 space-y-6">
<h2 className="text-xl font-bold text-[#E6B17E] mb-4">Base Stats</h2> {character.skills.map((skill, index) => (
<div className="grid grid-cols-2 md:grid-cols-4 gap-4"> <div
<div className="flex items-center space-x-2"> key={index}
<i className="fas fa-sword text-[#C17F59]"></i> className="bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 border border-[#C17F59]/30"
<span>Attack: {character.baseStats.attack}</span> >
</div> <div className="flex items-center justify-between mb-4">
<div className="flex items-center space-x-2"> <h3 className="text-xl font-bold text-[#E6B17E]">{skill.name}</h3>
<i className="fas fa-heart text-[#C17F59]"></i> <div className="flex items-center">
<span>Health: {character.baseStats.health}</span> {renderSkillType(skill.type)}
</div> {renderSoulBurn(skill.soulBurn)}
<div className="flex items-center space-x-2">
<i className="fas fa-shield-alt text-[#C17F59]"></i>
<span>Defense: {character.baseStats.defense}</span>
</div>
<div className="flex items-center space-x-2">
<i className="fas fa-wind text-[#C17F59]"></i>
<span>Speed: {character.baseStats.speed}</span>
</div>
</div>
</div>
{/* 技能列表 */}
<div className="space-y-6">
{character.skills.map((skill, index) => (
<div
key={index}
className="bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 border border-[#C17F59]/30"
>
<div className="flex items-center justify-between mb-4">
<h3 className="text-xl font-bold text-[#E6B17E]">
{skill.name}
</h3>
<div className="flex items-center">
{renderSkillType(skill.type)}
{renderSoulBurn(skill.soulBurn)}
</div>
</div>
<p className="text-[#9B8579] mb-4">{skill.description}</p>
{skill.enhancements && skill.enhancements.length > 0 && (
<div className="mt-4">
<h4 className="text-lg font-semibold text-[#E6B17E] mb-2">
Skill Enhancements
</h4>
<div className="space-y-2">
{skill.enhancements.map((enhancement, idx) => (
<div
key={idx}
className="flex items-center space-x-4 text-sm"
>
<div className="flex">
{renderStars(enhancement.stars)}
</div>
<div className="flex flex-wrap gap-2">
{enhancement.attack && (
<span className="text-[#9B8579]">
Attack {enhancement.attack}
</span>
)}
{enhancement.health && (
<span className="text-[#9B8579]">
Health {enhancement.health}
</span>
)}
{enhancement.defense && (
<span className="text-[#9B8579]">
Defense {enhancement.defense}
</span>
)}
{enhancement.effectiveness && (
<span className="text-[#9B8579]">
Effectiveness {enhancement.effectiveness}
</span>
)}
</div>
</div>
))}
</div> </div>
</div> </div>
)} <p className="text-[#9B8579] mb-4">{skill.description}</p>
</div> {skill.enhancements && skill.enhancements.length > 0 && (
))} <div className="mt-4">
</div> <h4 className="text-lg font-semibold text-[#E6B17E] mb-2">Skill Enhancements</h4>
<div className="space-y-2">
{/* 印记集中 */} {skill.enhancements.map((enhancement, idx) => (
<div className="bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 mt-8 border border-[#C17F59]/30"> <div key={idx} className="flex items-center space-x-4 text-sm">
<h2 className="text-xl font-bold text-[#E6B17E] mb-4"> <div className="flex">{renderStars(enhancement.stars)}</div>
Imprint Concentration <div className="flex flex-wrap gap-2">
</h2> {enhancement.attack && (
{character.imprintConcentration.map((imprint, index) => ( <span className="text-[#9B8579]">Attack {enhancement.attack}</span>
<div key={index} className="mb-4"> )}
<h3 className="text-lg font-semibold text-[#C17F59] mb-2"> {enhancement.health && (
{imprint.type} <span className="text-[#9B8579]">Health {enhancement.health}</span>
</h3> )}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4"> {enhancement.defense && (
{imprint.values.map((value, idx) => ( <span className="text-[#9B8579]">Defense {enhancement.defense}</span>
<div )}
key={idx} {enhancement.effectiveness && (
className="flex items-center justify-between bg-[#1A1412] p-2 rounded border border-[#C17F59]/30" <span className="text-[#9B8579]">Effectiveness {enhancement.effectiveness}</span>
> )}
<span className="text-[#E6B17E]">{value.rank}</span> </div>
<span className="text-[#9B8579]">{value.value}</span> </div>
))}
</div>
</div> </div>
))} )}
</div> </div>
</div> ))}
))} </section>
</div>
{/* 印记集中 */}
<section id="imprint" className="scroll-mt-24 bg-gradient-to-br from-[#2A211E] to-[#1A1412] rounded-lg p-6 border border-[#C17F59]/30">
<h2 className="text-xl font-bold text-[#E6B17E] mb-4">Imprint Concentration</h2>
{character.imprintConcentration.map((imprint, index) => (
<div key={index} className="mb-4">
<h3 className="text-lg font-semibold text-[#C17F59] mb-2">{imprint.type}</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{imprint.values.map((value, idx) => (
<div
key={idx}
className="flex items-center justify-between bg-[#1A1412] p-2 rounded border border-[#C17F59]/30"
>
<span className="text-[#E6B17E]">{value.rank}</span>
<span className="text-[#9B8579]">{value.value}</span>
</div>
))}
</div>
</div>
))}
</section>
</main>
</div> </div>
</div> </div>
); );

View File

@@ -51,7 +51,7 @@ const Characters: React.FC = () => {
element: "fire", element: "fire",
class: "Fire Warrior", class: "Fire Warrior",
imageUrl: imageUrl:
"https://readdy.ai/api/search-image?query=anime%20style%20game%20character%20portrait%20of%20a%20female%20warrior%20with%20pink%20hair%20and%20red%20eyes%2C%20fantasy%20RPG%20character%20icon%2C%20detailed%20face%2C%20high%20quality%2C%20digital%20art&width=100&height=100&seq=1&orientation=squarish", "https://epic7db.com/images/heroes/abigail.webp",
}, },
{ {
id: 2, id: 2,