Spaces:
Sleeping
Sleeping
refactor(HistoryDatabase): simplify CTA button positioning and adjust layout for improved responsiveness
Browse files- Removed dynamic offset calculation for the CTA button, fixing its position.
- Updated card layout logic to ensure proper stacking and alignment.
- Increased minimum heights for both collapsed and expanded states to enhance visual consistency.
frontend/src/components/HistoryDatabase.vue
CHANGED
|
@@ -10,10 +10,9 @@
|
|
| 10 |
<div class="gradient-overlay"></div>
|
| 11 |
</div>
|
| 12 |
|
| 13 |
-
<!-- CTA 按钮 -->
|
| 14 |
<div
|
| 15 |
class="cta-button"
|
| 16 |
-
:style="{ transform: `translateY(${ctaOffset}px)` }"
|
| 17 |
@click="toggleExpand"
|
| 18 |
>
|
| 19 |
<div class="cta-inner">
|
|
@@ -101,7 +100,6 @@ const projects = ref([])
|
|
| 101 |
const loading = ref(true)
|
| 102 |
const isExpanded = ref(false)
|
| 103 |
const hoveringCard = ref(null)
|
| 104 |
-
const ctaOffset = ref(0)
|
| 105 |
const imageErrors = ref({}) // 追踪图片加载错误
|
| 106 |
|
| 107 |
// 卡片布局配置 - 调整为更宽的比例
|
|
@@ -135,18 +133,6 @@ const handleImageError = (event, index) => {
|
|
| 135 |
event.target.style.display = 'none'
|
| 136 |
}
|
| 137 |
|
| 138 |
-
// 计算 CTA 按钮偏移
|
| 139 |
-
const calculateCtaOffset = () => {
|
| 140 |
-
if (!isExpanded.value) {
|
| 141 |
-
ctaOffset.value = 0
|
| 142 |
-
return
|
| 143 |
-
}
|
| 144 |
-
|
| 145 |
-
const rowCount = Math.ceil(projects.value.length / CARDS_PER_ROW)
|
| 146 |
-
// 调整 CTA 偏移量以适应网格高度
|
| 147 |
-
ctaOffset.value = -(rowCount * EXPANDED_ROW_HEIGHT + 100)
|
| 148 |
-
}
|
| 149 |
-
|
| 150 |
// 获取卡片样式
|
| 151 |
const getCardStyle = (index) => {
|
| 152 |
const total = projects.value.length
|
|
@@ -187,14 +173,9 @@ const getCardStyle = (index) => {
|
|
| 187 |
const colInRow = index % CARDS_PER_ROW
|
| 188 |
const x = startX + colInRow * (CARD_WIDTH + CARD_GAP)
|
| 189 |
|
| 190 |
-
// translateY: 向
|
| 191 |
-
// Row 0
|
| 192 |
-
|
| 193 |
-
// In CSS translate Y, negative is up.
|
| 194 |
-
// So row 0 should have the most negative Y? Or row 0 is at the bottom and subsequent rows stack up?
|
| 195 |
-
// "向上生长:如果卡片超过4个,生成的第二行应该在第一行上方" -> Row 1 is above Row 0.
|
| 196 |
-
// So Row 0 is at y=0 (or base), Row 1 is at y = -230px, etc.
|
| 197 |
-
const y = -(row * EXPANDED_ROW_HEIGHT)
|
| 198 |
|
| 199 |
return {
|
| 200 |
transform: `translate(${x}px, ${y}px) rotate(0deg) scale(1)`,
|
|
@@ -277,17 +258,14 @@ const truncateText = (text, maxLength) => {
|
|
| 277 |
// 事件处理
|
| 278 |
const handleMouseEnter = () => {
|
| 279 |
isExpanded.value = true
|
| 280 |
-
calculateCtaOffset()
|
| 281 |
}
|
| 282 |
|
| 283 |
const handleMouseLeave = () => {
|
| 284 |
isExpanded.value = false
|
| 285 |
-
ctaOffset.value = 0
|
| 286 |
}
|
| 287 |
|
| 288 |
const toggleExpand = () => {
|
| 289 |
isExpanded.value = !isExpanded.value
|
| 290 |
-
calculateCtaOffset()
|
| 291 |
}
|
| 292 |
|
| 293 |
// 导航到项目
|
|
@@ -376,14 +354,13 @@ onMounted(() => {
|
|
| 376 |
pointer-events: none;
|
| 377 |
}
|
| 378 |
|
| 379 |
-
/* CTA 按钮 */
|
| 380 |
.cta-button {
|
| 381 |
position: relative;
|
| 382 |
z-index: 100;
|
| 383 |
display: flex;
|
| 384 |
justify-content: center;
|
| 385 |
margin-bottom: 48px;
|
| 386 |
-
transition: transform 700ms cubic-bezier(0.23, 1, 0.32, 1); /* Match card duration */
|
| 387 |
cursor: pointer;
|
| 388 |
}
|
| 389 |
|
|
@@ -430,14 +407,14 @@ onMounted(() => {
|
|
| 430 |
position: relative;
|
| 431 |
display: flex;
|
| 432 |
justify-content: center;
|
| 433 |
-
align-items: flex-
|
| 434 |
-
min-height:
|
| 435 |
padding: 0 40px;
|
| 436 |
transition: min-height 700ms cubic-bezier(0.23, 1, 0.32, 1); /* Match card duration */
|
| 437 |
}
|
| 438 |
|
| 439 |
.cards-container.expanded {
|
| 440 |
-
min-height:
|
| 441 |
}
|
| 442 |
|
| 443 |
/* 项目卡片 - 完全参照参考图 */
|
|
|
|
| 10 |
<div class="gradient-overlay"></div>
|
| 11 |
</div>
|
| 12 |
|
| 13 |
+
<!-- CTA 按钮 - 位置固定不变 -->
|
| 14 |
<div
|
| 15 |
class="cta-button"
|
|
|
|
| 16 |
@click="toggleExpand"
|
| 17 |
>
|
| 18 |
<div class="cta-inner">
|
|
|
|
| 100 |
const loading = ref(true)
|
| 101 |
const isExpanded = ref(false)
|
| 102 |
const hoveringCard = ref(null)
|
|
|
|
| 103 |
const imageErrors = ref({}) // 追踪图片加载错误
|
| 104 |
|
| 105 |
// 卡片布局配置 - 调整为更宽的比例
|
|
|
|
| 133 |
event.target.style.display = 'none'
|
| 134 |
}
|
| 135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
// 获取卡片样式
|
| 137 |
const getCardStyle = (index) => {
|
| 138 |
const total = projects.value.length
|
|
|
|
| 173 |
const colInRow = index % CARDS_PER_ROW
|
| 174 |
const x = startX + colInRow * (CARD_WIDTH + CARD_GAP)
|
| 175 |
|
| 176 |
+
// translateY: 向下展开逻辑. 行高 300px (包含卡片高度280+间距).
|
| 177 |
+
// Row 0 在顶部,后续行向下排列
|
| 178 |
+
const y = row * (CARD_HEIGHT + CARD_GAP)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
return {
|
| 181 |
transform: `translate(${x}px, ${y}px) rotate(0deg) scale(1)`,
|
|
|
|
| 258 |
// 事件处理
|
| 259 |
const handleMouseEnter = () => {
|
| 260 |
isExpanded.value = true
|
|
|
|
| 261 |
}
|
| 262 |
|
| 263 |
const handleMouseLeave = () => {
|
| 264 |
isExpanded.value = false
|
|
|
|
| 265 |
}
|
| 266 |
|
| 267 |
const toggleExpand = () => {
|
| 268 |
isExpanded.value = !isExpanded.value
|
|
|
|
| 269 |
}
|
| 270 |
|
| 271 |
// 导航到项目
|
|
|
|
| 354 |
pointer-events: none;
|
| 355 |
}
|
| 356 |
|
| 357 |
+
/* CTA 按钮 - 位置固定不变 */
|
| 358 |
.cta-button {
|
| 359 |
position: relative;
|
| 360 |
z-index: 100;
|
| 361 |
display: flex;
|
| 362 |
justify-content: center;
|
| 363 |
margin-bottom: 48px;
|
|
|
|
| 364 |
cursor: pointer;
|
| 365 |
}
|
| 366 |
|
|
|
|
| 407 |
position: relative;
|
| 408 |
display: flex;
|
| 409 |
justify-content: center;
|
| 410 |
+
align-items: flex-start; /* 从顶部开始排列 */
|
| 411 |
+
min-height: 420px; /* 折叠时的最小高度 */
|
| 412 |
padding: 0 40px;
|
| 413 |
transition: min-height 700ms cubic-bezier(0.23, 1, 0.32, 1); /* Match card duration */
|
| 414 |
}
|
| 415 |
|
| 416 |
.cards-container.expanded {
|
| 417 |
+
min-height: 620px; /* 展开时增加高度,页面自动向下延长 */
|
| 418 |
}
|
| 419 |
|
| 420 |
/* 项目卡片 - 完全参照参考图 */
|