From 874ecc5625c55354d12dfaf0fb8922f3882af468 Mon Sep 17 00:00:00 2001 From: xiaomai Date: Sat, 2 May 2026 21:15:48 +0800 Subject: [PATCH] feat(pokemon): redesign image display with side thumbnail and modal Move image thumbnail to the right of base stats Display detailed image information in a modal --- DESIGN.md | 4 +- frontend/src/styles/main.css | 55 +++++++++++++++++++++++++++ frontend/src/views/PokemonDetail.vue | 56 ++++++++++++++++++++-------- 3 files changed, 98 insertions(+), 17 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index acb9da2..226361b 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -277,11 +277,11 @@ Pokemon 列表功能: Pokemon 详情页展示: - 基本信息 -- 已配置图片时,详情主内容顶部展示 Pokédex 风格图片区,包含大图和图片版本说明;未配置图片时不显示图片区。 +- 已配置图片时,详情主内容在六维 Stats 右侧展示正方形居中的 Pokédex 风格图片;页面内不直接展示图片版本、状态或描述,用户可通过图片 Modal 查看详情;未配置图片时不显示图片区。 - 主内容顶部按以下布局展示: - 左上:Genus & Details;无区块标题;如有 Genus,先展示 Genus,再以分割线连接 Details 内容 - 左下:Height / Weight 与 Types 按 2:1 比例并排;Height / Weight 无区块标题,在 Dimension 区内左右并排展示并以中间分割线隔开,每组按英制、分割线、公制、标签上下排列;Types 不显示 Type 1 / Type 2 文案,上下布局并居中展示 - - 右侧:六维 Stats + - 右侧:六维 Stats;已配置图片时图片展示在 Stats 右侧 - 六维使用 ProgressBar 展示,最大值按 150 计算。 - 特长 - 特长掉落物品 diff --git a/frontend/src/styles/main.css b/frontend/src/styles/main.css index 05dd43c..c25f9b6 100644 --- a/frontend/src/styles/main.css +++ b/frontend/src/styles/main.css @@ -3379,6 +3379,21 @@ button:disabled, align-items: stretch; } +.pokemon-profile-grid--with-image { + grid-template-columns: minmax(0, 1fr) minmax(430px, 560px); +} + +.pokemon-profile-side { + display: grid; + gap: 16px; + align-items: stretch; + min-width: 0; +} + +.pokemon-profile-side--with-image { + grid-template-columns: minmax(0, 1fr) clamp(112px, 12vw, 164px); +} + .pokemon-profile-main, .pokemon-profile-row { display: grid; @@ -3400,6 +3415,36 @@ button:disabled, align-self: stretch; } +.pokemon-profile-image { + width: clamp(112px, 12vw, 164px); + aspect-ratio: 1 / 1; + align-self: center; + justify-self: center; + display: grid; + place-items: center; + padding: 10px; + border: 4px solid #172036; + border-radius: var(--radius-card); + background: + linear-gradient(90deg, rgba(42, 117, 187, 0.08) 1px, transparent 1px) 0 0 / 18px 18px, + linear-gradient(rgba(42, 117, 187, 0.08) 1px, transparent 1px) 0 0 / 18px 18px, + #eef9ff; + box-shadow: var(--shadow-soft); + cursor: pointer; +} + +.pokemon-profile-image:hover, +.pokemon-profile-image:focus-visible { + border-color: var(--pokemon-blue); +} + +.pokemon-profile-image img { + width: 100%; + height: 100%; + object-fit: contain; + object-position: center; +} + .pokemon-types-card { align-content: center; justify-items: center; @@ -4137,6 +4182,16 @@ button:disabled, justify-content: flex-start; } + .pokemon-profile-side--with-image { + grid-template-columns: minmax(0, 1fr) clamp(96px, 21vw, 132px); + gap: 10px; + } + + .pokemon-profile-image { + width: clamp(96px, 21vw, 132px); + padding: 8px; + } + .coming-soon-panel { grid-template-columns: 1fr; padding: 18px; diff --git a/frontend/src/views/PokemonDetail.vue b/frontend/src/views/PokemonDetail.vue index 9e818f4..0699fe4 100644 --- a/frontend/src/views/PokemonDetail.vue +++ b/frontend/src/views/PokemonDetail.vue @@ -7,6 +7,7 @@ import DetailSection from '../components/DetailSection.vue'; import EditHistoryPanel from '../components/EditHistoryPanel.vue'; import EntityDiscussionPanel from '../components/EntityDiscussionPanel.vue'; import EntityChips from '../components/EntityChips.vue'; +import Modal from '../components/Modal.vue'; import PageHeader from '../components/PageHeader.vue'; import PokemonStatsPanel from '../components/PokemonStatsPanel.vue'; import Skeleton from '../components/Skeleton.vue'; @@ -21,6 +22,7 @@ const pokemon = ref(null); const itemCategoryTab = ref(''); const relatedHabitatTab = ref(''); const detailTab = ref('details'); +const imageModalOpen = ref(false); const timeOfDays = ['早晨', '中午', '傍晚', '晚上']; const weathers = ['晴天', '阴天', '雨天']; const relatedPokemonLimit = 6; @@ -192,6 +194,14 @@ function pokemonImageLabel() { return pokemon.value?.image ? `${pokemon.value.image.version} - ${pokemon.value.image.variant}` : ''; } +function openImageModal() { + imageModalOpen.value = true; +} + +function closeImageModal() { + imageModalOpen.value = false; +} + async function loadPokemonDetail() { const nextPokemon = await api.pokemonDetail(String(route.params.id)); pokemon.value = nextPokemon; @@ -217,6 +227,7 @@ watch( pokemon.value = null; relatedHabitatTab.value = ''; detailTab.value = 'details'; + imageModalOpen.value = false; void loadPokemonDetail(); } ); @@ -298,18 +309,7 @@ watch(
-
-
- -
-
- {{ pokemonImageLabel() }} - {{ pokemon.image.style }} -

{{ pokemon.image.description }}

-
-
- -
+

{{ pokemon.genus }}

@@ -352,9 +352,15 @@ watch(
- - - +
+ + + + + +
@@ -482,5 +488,25 @@ watch(
+ +
+
+ +
+
+ {{ pokemonImageLabel() }} + {{ pokemon.image.style }} +

{{ pokemon.image.description }}

+
+
+
+