Commit f08b3fdc authored by shrabbit's avatar shrabbit
Browse files

fix: 修复 CharacterCard 交互问题与 sExt 成品展示区塌缩

- CharacterCard:整张卡片可点击翻转,添加键盘支持(Enter/Space)
- CharacterCard:右上角 FLIP/BACK 角标提示,hover 时图标旋转
- CharacterCard:底部按钮改为纯文字提示,避免冒泡触发双重翻转
- CharacterCard:修复 SVG 内 v-else 必须紧邻 v-if 的编译错误(用 template 包裹)
- sext-parse:修复 output-grid 首列 auto 导致卡片塌缩为 0x0 的问题,改为 minmax(0, 380px)
parent d043f2f2
Loading
Loading
Loading
Loading
+128 −20
Original line number Diff line number Diff line
<template>
  <div class="char-card" :class="{ 'is-flipped': showBack }">
  <div
    class="char-card"
    :class="{ 'is-flipped': showBack }"
    role="button"
    tabindex="0"
    :aria-label="showBack ? '点击返回渲染成品' : '点击查看原始 sExt 字符串'"
    @click="flip"
    @keydown.enter="flip"
    @keydown.space.prevent="flip"
  >
    <!-- 翻转提示角标 -->
    <div class="char-card__flip-hint" aria-hidden="true">
      <svg
        class="char-card__flip-hint-icon"
        width="14"
        height="14"
        viewBox="0 0 24 24"
        fill="none"
      >
        <template v-if="!showBack">
          <path
            d="M3 12a9 9 0 1 0 9-9"
            stroke="currentColor"
            stroke-width="1.8"
            stroke-linecap="round"
          />
          <path
            d="M3 4v5h5"
            stroke="currentColor"
            stroke-width="1.8"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
        </template>
        <template v-else>
          <path
            d="M21 12a9 9 0 1 1-9 9"
            stroke="currentColor"
            stroke-width="1.8"
            stroke-linecap="round"
          />
          <path
            d="M21 20v-5h-5"
            stroke="currentColor"
            stroke-width="1.8"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
        </template>
      </svg>
      <span class="char-card__flip-hint-text">{{ showBack ? 'BACK' : 'FLIP' }}</span>
    </div>

    <!-- ============ 正面 ============ -->
    <article class="char-card__face char-card__face--front">
      <div class="char-card__bg">
@@ -51,7 +103,7 @@
              :key="i"
              class="char-card__lang"
              :class="{ 'is-active': activeLang === i }"
              @click="activeLang = i"
              @click.stop="activeLang = i"
            >{{ l }}</span>
          </div>
        </div>
@@ -72,7 +124,7 @@
            class="char-card__voice-btn"
            :class="{ 'is-playing': playingIdx === i }"
            type="button"
            @click="togglePlay(i, url)"
            @click.stop="togglePlay(i, url)"
          >
            <svg v-if="playingIdx !== i" width="12" height="12" viewBox="0 0 24 24" fill="none" aria-hidden="true">
              <path d="M5 3l14 9-14 9V3z" fill="currentColor"/>
@@ -88,13 +140,13 @@

      <footer class="char-card__foot">
        <span class="char-card__foot-tag">Parsed · from sExt</span>
        <button class="char-card__flip" type="button" @click="flip">
          <span>查看原始 sExt</span>
        <span class="char-card__flip-hint-bottom">
          <span>{{ showBack ? '点击空白处返回' : '点击查看原始 sExt' }}</span>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" aria-hidden="true">
            <path d="M3 12a9 9 0 1 0 9-9" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
            <path d="M3 4v5h5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
          </svg>
        </button>
        </span>
      </footer>
    </article>

@@ -111,13 +163,13 @@

      <footer class="char-card__foot">
        <span class="char-card__foot-tag">JSON string · 17 keys</span>
        <button class="char-card__flip" type="button" @click="flip">
        <span class="char-card__flip-hint-bottom">
          <span>点击返回渲染成品</span>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" aria-hidden="true">
            <path d="M21 12a9 9 0 1 1-9-9" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
            <path d="M21 12a9 9 0 1 1-9 9" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
            <path d="M21 4v5h-5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
          </svg>
          <span>返回卡片</span>
        </button>
        </span>
      </footer>
    </article>
  </div>
@@ -191,6 +243,55 @@ onBeforeUnmount(() => {
  max-width: 380px;
  perspective: 1600px;
  font-family: var(--font-sans);
  cursor: pointer;
  outline: none;
}

.char-card:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 4px;
  border-radius: var(--radius-lg);
}

/* ============ 翻转提示角标 ============ */
.char-card__flip-hint {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 10;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  background: rgba(10, 14, 12, 0.7);
  backdrop-filter: blur(8px);
  border: 1px solid var(--color-line);
  border-radius: 2px;
  font-family: var(--font-mono);
  font-size: 0.5625rem;
  letter-spacing: 0.15em;
  color: var(--color-accent);
  pointer-events: none;
  opacity: 0.7;
  transition: opacity var(--duration-base) var(--ease-out-quint),
              transform var(--duration-base) var(--ease-out-quint);
}

.char-card__flip-hint-icon {
  transition: transform var(--duration-base) var(--ease-out-quint);
}

.char-card:hover .char-card__flip-hint {
  opacity: 1;
  transform: translateY(0);
}

.char-card:hover .char-card__flip-hint-icon {
  transform: rotate(180deg);
}

.char-card.is-flipped .char-card__flip-hint {
  background: rgba(10, 14, 12, 0.85);
}

.char-card__face {
@@ -465,31 +566,38 @@ onBeforeUnmount(() => {
  text-transform: uppercase;
}

.char-card__flip {
/* 底部翻转提示(纯文字,整张卡片可点) */
.char-card__flip-hint-bottom {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: none;
  color: var(--color-accent);
  font-family: var(--font-mono);
  font-size: 0.6875rem;
  letter-spacing: 0.05em;
  cursor: pointer;
  padding: 4px 6px;
  transition: opacity var(--duration-fast) var(--ease-out-quint);
  color: var(--color-accent);
  pointer-events: none;
  opacity: 0.6;
  transition: opacity var(--duration-base) var(--ease-out-quint),
              gap var(--duration-base) var(--ease-out-quint);
}

.char-card__flip:hover { opacity: 0.7; }
.char-card:hover .char-card__flip-hint-bottom {
  opacity: 1;
  gap: 8px;
}

.char-card__flip svg {
.char-card__flip-hint-bottom svg {
  transition: transform var(--duration-base) var(--ease-out-quint);
}

.char-card__flip:hover svg {
.char-card:hover .char-card__flip-hint-bottom svg {
  transform: rotate(-90deg);
}

.char-card.is-flipped .char-card__flip-hint-bottom svg {
  transform: rotate(180deg);
}

/* ============ 反面 ============ */
.char-card__back-head {
  padding: var(--space-5) var(--space-5) var(--space-3);
+1 −1
Original line number Diff line number Diff line
@@ -838,7 +838,7 @@ const onHoverField = (key: string) => {
/* —— 输出区 —— */
.output-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-columns: minmax(0, 380px) 1fr;
  gap: var(--space-10);
  align-items: center;
}