diff --git a/src/App.tsx b/src/App.tsx index 8b89c82..8a096e3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,12 +5,86 @@ import Navbar from "./components/Navbar"; import Footer from "./components/Footer"; import Home from "./pages/Home"; import Characters from "./pages/Characters"; +import CharacterDetail from "./pages/CharacterDetail"; import Builds from "./pages/Builds"; import Battles from "./pages/Battles"; import News from "./pages/News"; import Community from "./pages/Community"; import LoginModal from "./components/LoginModal"; +// 导入类型定义 +import { Skill, ImprintConcentration } from './pages/CharacterDetail'; + +// 示例数据 +const mockCharacterData = { + id: 1, + name: "Boss Arunka", + stars: 5, + class: "Light Knight", + element: "light", + baseStats: { + attack: 821, + health: 6751, + defense: 648, + speed: 106 + }, + skills: [ + { + name: "Road Sign Smash", + type: "Active" as const, + soulBurn: 1, + description: "Attacks the enemy with a road sign, with a 65% chance to decrease Defense for 2 turns.", + enhancements: [ + { + stars: 2, + attack: "+5%", + effectiveness: "+10%" + }, + { + stars: 3, + attack: "+10%", + effectiveness: "+15%" + } + ] + }, + { + name: "Vanguard of the Silent Expanse", + type: "Passive" as const, + description: "At the start of battle and at the end of the turn, when the caster is in the front row, increases Attack of all allies for 2 turns.", + enhancements: [ + { + stars: 3, + attack: "+20%", + health: "+60" + } + ] + } + ] as Skill[], + imprintConcentration: [ + { + type: "Attack Concentration", + values: [ + { rank: "SSS", value: "10.8%" }, + { rank: "SS", value: "9.0%" }, + { rank: "S", value: "7.2%" }, + { rank: "A", value: "5.4%" }, + { rank: "B", value: "3.6%" } + ] + }, + { + type: "Defense Concentration", + values: [ + { rank: "SSS", value: "18%" }, + { rank: "SS", value: "15%" }, + { rank: "S", value: "12%" }, + { rank: "A", value: "9%" }, + { rank: "B", value: "6%" } + ] + } + ] as ImprintConcentration[], + 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" +}; + const App: React.FC = () => { const [isMenuOpen, setIsMenuOpen] = useState(false); const [isLoginModalOpen, setIsLoginModalOpen] = useState(false); @@ -51,9 +125,13 @@ const App: React.FC = () => { } /> } /> + } + /> + } /> } /> } /> - } /> } /> diff --git a/src/pages/CharacterDetail.tsx b/src/pages/CharacterDetail.tsx new file mode 100644 index 0000000..098afe2 --- /dev/null +++ b/src/pages/CharacterDetail.tsx @@ -0,0 +1,217 @@ +import React from 'react'; + +export interface Skill { + name: string; + type: 'None' | 'Passive' | 'Active'; + soulBurn?: number; + description: string; + enhancements?: { + stars: number; + attack?: string; + health?: string; + defense?: string; + effectiveness?: string; + }[]; +} + +export interface ImprintConcentration { + type: string; + values: { + rank: string; + value: string; + }[]; +} + +interface CharacterDetailProps { + character: { + id: number; + name: string; + stars: number; + class: string; + element: string; + baseStats: { + attack: number; + health: number; + defense: number; + speed: number; + }; + skills: Skill[]; + imprintConcentration: ImprintConcentration[]; + imageUrl: string; + }; +} + +const CharacterDetail: React.FC = ({ character }) => { + const renderStars = (count: number) => { + return Array(count) + .fill(0) + .map((_, index) => ( + + )); + }; + + const renderSkillType = (type: string) => { + switch (type) { + case 'None': + return None; + case 'Passive': + return Passive; + case 'Active': + return Active; + default: + return null; + } + }; + + const renderSoulBurn = (souls?: number) => { + if (!souls) return null; + return ( + + +{souls} souls + + ); + }; + + return ( +
+
+ {/* 角色基本信息 */} +
+
+
+ {character.name} +
+
+

+ {character.name} +

+
+
+ {renderStars(character.stars)} +
+ {character.class} +
+
+
+
+ + {/* 基础属性 */} +
+

Base Stats

+
+
+ + Attack: {character.baseStats.attack} +
+
+ + Health: {character.baseStats.health} +
+
+ + Defense: {character.baseStats.defense} +
+
+ + Speed: {character.baseStats.speed} +
+
+
+ + {/* 技能列表 */} +
+ {character.skills.map((skill, index) => ( +
+
+

+ {skill.name} +

+
+ {renderSkillType(skill.type)} + {renderSoulBurn(skill.soulBurn)} +
+
+

{skill.description}

+ + {skill.enhancements && skill.enhancements.length > 0 && ( +
+

+ Skill Enhancements +

+
+ {skill.enhancements.map((enhancement, idx) => ( +
+
+ {renderStars(enhancement.stars)} +
+
+ {enhancement.attack && ( + + Attack {enhancement.attack} + + )} + {enhancement.health && ( + + Health {enhancement.health} + + )} + {enhancement.defense && ( + + Defense {enhancement.defense} + + )} + {enhancement.effectiveness && ( + + Effectiveness {enhancement.effectiveness} + + )} +
+
+ ))} +
+
+ )} +
+ ))} +
+ + {/* 印记集中 */} +
+

+ Imprint Concentration +

+ {character.imprintConcentration.map((imprint, index) => ( +
+

+ {imprint.type} +

+
+ {imprint.values.map((value, idx) => ( +
+ {value.rank} + {value.value} +
+ ))} +
+
+ ))} +
+
+
+ ); +}; + +export default CharacterDetail; \ No newline at end of file diff --git a/src/pages/Characters.tsx b/src/pages/Characters.tsx index 96112e5..855d40a 100644 --- a/src/pages/Characters.tsx +++ b/src/pages/Characters.tsx @@ -1,6 +1,7 @@ // The exported code uses Tailwind CSS. Install Tailwind CSS in your dev environment to ensure all styles work. import React, { useState, useEffect, useRef } from "react"; +import { useNavigate } from 'react-router-dom'; const Characters: React.FC = () => { const [selectedStars, setSelectedStars] = useState("All Stars"); @@ -40,6 +41,8 @@ const Characters: React.FC = () => { }; }, []); + const navigate = useNavigate(); + const heroes = [ { id: 1, @@ -606,6 +609,10 @@ const Characters: React.FC = () => { return true; }); + const handleCharacterClick = (heroId: number) => { + navigate(`/character/${heroId}`); + }; + return (
{/* 背景装饰 */} @@ -945,6 +952,7 @@ const Characters: React.FC = () => {
handleCharacterClick(hero.id)} >