<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { siteConfig } from '~/config/site'

useHead({ title: `封面制作 - ${siteConfig.siteName}` })

// 文字
const leftText = ref('标题')
const rightText = ref('副标题')
const fontSize = ref(80)
const fontWeight = ref(700)
const gap = ref(20)

// 图标
const showIcon = ref(true)
const iconName = ref('mdi:star')
const iconSvg = ref('')
const localIcon = ref<string | null>(null)
const iconSize = ref(64)
const iconColor = ref('#000000')
const useOriginalIconColor = ref(false)
const iconRadius = ref(0)
const iconPosition = ref<'before' | 'middle' | 'after'>('before')
const searchQuery = ref('')
const searchResults = ref<string[]>([])
let searchTimer: ReturnType<typeof setTimeout> | null = null

// 背景
const bgImage = ref<string | null>(null)
const bgColor = ref('#ffffff')
const bgColorOpacity = ref(1)
const bgBlur = ref(0)
const bgOpacity = ref(1)
const isBgDragOver = ref(false)

// 颜色
const textColor = ref('#000000')
const linkColor = ref(true)

// 阴影
const textShadow = reactive({ x: 0, y: 0, blur: 0, color: '#000000', alpha: 0 })
const iconShadow = reactive({ x: 0, y: 0, blur: 0, color: '#000000', alpha: 0 })

// 图标背景
const iconBgEnabled = ref(false)
const iconBgColor = ref('#000000')
const iconBgOpacity = ref(0.2)
const iconBgPadding = ref(10)
const iconBgRadius = ref(20)
const iconBgBlur = ref(0)

// 画布
const canvasWidth = ref(1067)
const canvasHeight = ref(600)
const ratios = reactive([
  { label: '16:9', w: 16, h: 9, checked: true },
  { label: '4:3', w: 4, h: 3, checked: false },
  { label: '1:1', w: 1, h: 1, checked: false },
  { label: '21:9', w: 21, h: 9, checked: false },
])
const linkScale = ref(true)

// 导出
const exportFormat = ref<'png' | 'svg'>('png')
const exportScales = ref([1])
const exportFilename = ref('cover')
const exportTransparentBg = ref(false)

// 背景图拖拽
const bgX = ref(0)
const bgY = ref(0)
const bgScale = ref(1)
const isDragging = ref(false)
let dragStartX = 0
let dragStartY = 0
let dragStartBgX = 0
let dragStartBgY = 0

const svgRef = ref<SVGSVGElement | null>(null)

// 计算
const activeRatios = computed(() => ratios.filter(r => r.checked))
const maxRatio = computed(() => activeRatios.value.reduce((max, r) => Math.max(max, r.w / r.h), 0))
const computedWidth = computed(() => Math.round(canvasHeight.value * maxRatio.value))

// 颜色转换
function hexToRgba(hex: string, alpha: number) {
  const r = parseInt(hex.slice(1, 3), 16)
  const g = parseInt(hex.slice(3, 5), 16)
  const b = parseInt(hex.slice(5, 7), 16)
  return `rgba(${r}, ${g}, ${b}, ${alpha})`
}

// 图标搜索
function onSearchInput(e: Event) {
  const val = (e.target as HTMLInputElement).value
  searchQuery.value = val
  if (searchTimer) clearTimeout(searchTimer)
  if (!val.trim()) { searchResults.value = []; return }
  searchTimer = setTimeout(async () => {
    try {
      const res = await fetch(`https://api.iconify.design/search?query=${encodeURIComponent(val)}&limit=20`)
      const data = await res.json()
      searchResults.value = data.icons || []
    } catch { searchResults.value = [] }
  }, 500)
}

function selectIcon(name: string) {
  iconName.value = name
  localIcon.value = null
}

// 加载图标 SVG
watch(iconName, async (name) => {
  if (!name || !name.includes(':') || localIcon.value) { iconSvg.value = ''; return }
  try {
    const res = await fetch(`https://api.iconify.design/${name.split(':')[0]}/${name.split(':')[1]}.svg`)
    if (!res.ok) throw Error()
    let svg = await res.text()
    svg = svg
      .replace(/\s(width|height)="[^"]*"/g, '')
      .replace(/<svg\b([^>]*)>/, '<svg$1 width="100%" height="100%" preserveAspectRatio="xMidYMid meet">')
      .replace(/currentColor/gi, iconColor.value)
    iconSvg.value = svg
  } catch { iconSvg.value = '' }
}, { immediate: true })

// 颜色同步
watch(linkColor, (v) => { if (v) iconColor.value = textColor.value })
watch(textColor, (v) => { if (linkColor.value) iconColor.value = v })

// 本地图标上传
function onLocalIconUpload(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (!file) return
  const reader = new FileReader()
  reader.onload = (ev) => {
    localIcon.value = ev.target?.result as string
    iconName.value = '本地图片'
    iconSvg.value = ''
  }
  reader.readAsDataURL(file)
}

// 背景图上传
function onBgUpload(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0]
  if (!file || !file.type.startsWith('image/')) return
  const reader = new FileReader()
  reader.onload = (ev) => {
    bgImage.value = ev.target?.result as string
    bgX.value = 0; bgY.value = 0; bgScale.value = 1
  }
  reader.readAsDataURL(file)
}

function onBgDragOver(e: DragEvent) { e.preventDefault(); isBgDragOver.value = true }
function onBgDragLeave() { isBgDragOver.value = false }
function onBgDrop(e: DragEvent) {
  e.preventDefault(); isBgDragOver.value = false
  const file = e.dataTransfer?.files?.[0]
  if (file) onBgUpload({ target: { files: [file] } } as any)
}

// 画布拖拽
function onPointerDown(e: PointerEvent) {
  if (!bgImage.value) return
  e.preventDefault()
  ;(e.currentTarget as Element).setPointerCapture(e.pointerId)
  isDragging.value = true
  dragStartX = e.clientX; dragStartY = e.clientY
  dragStartBgX = bgX.value; dragStartBgY = bgY.value
}

function onPointerMove(e: PointerEvent) {
  if (!isDragging.value) return
  bgX.value = dragStartBgX + (e.clientX - dragStartX) / bgScale.value
  bgY.value = dragStartBgY + (e.clientY - dragStartY) / bgScale.value
}

function onPointerUp() { isDragging.value = false }

function onWheel(e: WheelEvent) {
  if (!bgImage.value) return
  e.preventDefault()
  const factor = 1.1
  bgScale.value = e.deltaY < 0
    ? Math.min(bgScale.value * factor, 10)
    : Math.max(bgScale.value / factor, 0.1)
}

// 比例联动
function updateWidth() {
  if (linkScale.value) canvasWidth.value = computedWidth.value
}

watch(() => ratios.map(r => r.checked), updateWidth, { deep: true })
watch(maxRatio, updateWidth)

// 导出
async function onExport() {
  const svgEl = svgRef.value
  if (!svgEl) return

  // 隐藏辅助线
  const guides = svgEl.querySelectorAll('.ratio-guide')
  guides.forEach(g => (g as SVGElement).style.display = 'none')
  const border = svgEl.querySelector('.canvas-border') as SVGElement | null
  if (border) border.style.display = 'none'

  const clone = svgEl.cloneNode(true) as SVGSVGElement

  // 恢复
  guides.forEach(g => (g as SVGElement).style.display = '')
  if (border) border.style.display = ''

  const exportRatios = activeRatios.value.length > 0 ? activeRatios.value : [ratios[0]]

  for (const ratio of exportRatios) {
    const w = Math.round(canvasHeight.value * (ratio.w / ratio.h))
    const offsetX = (computedWidth.value - w) / 2

    const c = clone.cloneNode(true) as SVGSVGElement
    c.setAttribute('width', w.toString())
    c.setAttribute('height', canvasHeight.value.toString())
    c.setAttribute('viewBox', `${offsetX} 0 ${w} ${canvasHeight.value}`)

    const svgStr = new XMLSerializer().serializeToString(c)
    const fname = exportRatios.length > 1
      ? `${exportFilename.value}-${ratio.label.replace(':', '-')}`
      : exportFilename.value

    if (exportFormat.value === 'svg') {
      downloadBlob(new Blob([svgStr], { type: 'image/svg+xml;charset=utf-8' }), `${fname}.svg`)
    } else {
      const img = new Image()
      img.src = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svgStr)))}`
      await new Promise<void>(r => { img.onload = () => r() })

      const scales = exportScales.value.length > 0 ? exportScales.value : [1]
      for (const s of scales) {
        const canvas = document.createElement('canvas')
        canvas.width = w * s; canvas.height = canvasHeight.value * s
        const ctx = canvas.getContext('2d')!
        ctx.imageSmoothingEnabled = true
        ctx.imageSmoothingQuality = 'high'
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
        const suffix = scales.length > 1 ? `@${s}x` : ''
        downloadDataURL(canvas.toDataURL('image/png'), `${fname}${suffix}.png`)
      }
    }
  }
}

function downloadBlob(blob: Blob, name: string) {
  const a = document.createElement('a')
  a.href = URL.createObjectURL(blob)
  a.download = name
  document.body.appendChild(a); a.click()
  document.body.removeChild(a)
}

function downloadDataURL(url: string, name: string) {
  const a = document.createElement('a')
  a.href = url; a.download = name
  document.body.appendChild(a); a.click()
  document.body.removeChild(a)
}

// 移动端 tab
const activeTab = ref<'content' | 'style' | 'export'>('content')
</script>

<template>
  <div class="container mx-auto max-w-[1920px] px-4 py-8">
    <div class="mb-6">
      <h1 class="text-3xl font-bold mb-2">封面制作</h1>
      <p class="text-muted-foreground">在线生成精美的封面图片</p>
    </div>

    <div class="flex flex-col lg:flex-row gap-6 w-full">
      <!-- 画布 -->
      <div class="flex-1 lg:max-w-[55%]">
        <div class="lg:sticky lg:top-20">
          <div
            class="w-full overflow-hidden flex justify-center rounded-xl select-none touch-none"
            style="background-color: var(--color-bg-card); padding: 1rem;"
            role="button" tabindex="0"
            @pointerdown="onPointerDown"
            @pointermove="onPointerMove"
            @pointerup="onPointerUp"
            @pointercancel="onPointerUp"
            @pointerleave="onPointerUp"
            @wheel="onWheel"
          >
            <svg
              ref="svgRef"
              xmlns="http://www.w3.org/2000/svg"
              :width="computedWidth"
              :height="canvasHeight"
              :viewBox="`0 0 ${computedWidth} ${canvasHeight}`"
              style="max-width: 100%; height: auto;"
              :style="{ cursor: bgImage ? (isDragging ? 'grabbing' : 'grab') : 'default' }"
            >
              <!-- 棋盘格 -->
              <defs>
                <pattern id="checkerboard" width="20" height="20" patternUnits="userSpaceOnUse">
                  <rect width="10" height="10" fill="#e0e0e0"/>
                  <rect x="10" y="0" width="10" height="10" fill="#ffffff"/>
                  <rect x="0" y="10" width="10" height="10" fill="#ffffff"/>
                  <rect x="10" y="10" width="10" height="10" fill="#e0e0e0"/>
                </pattern>
              </defs>
              <rect width="100%" height="100%" fill="url(#checkerboard)"/>

              <!-- 背景色 -->
              <rect
                width="100%" height="100%"
                :fill="hexToRgba(bgColor, bgColorOpacity)"
              />

              <!-- 背景图 -->
              <image
                v-if="bgImage"
                :href="bgImage"
                :x="bgX" :y="bgY"
                :width="computedWidth" :height="canvasHeight"
                preserveAspectRatio="xMidYMid meet"
                :transform="`scale(${bgScale})`"
                :style="`transform-origin: 50% 50%; filter: blur(${bgBlur}px); opacity: ${bgOpacity};`"
              />

              <!-- 内容区 -->
              <foreignObject x="0" y="0" width="100%" height="100%" style="pointer-events: none;">
                <div
                  xmlns="http://www.w3.org/1999/xhtml"
                  :style="`
                    width: 100%; height: 100%;
                    display: flex; align-items: center; justify-content: center;
                    gap: ${gap}px;
                    font-family: sans-serif;
                    font-weight: ${fontWeight};
                  `"
                >
                  <!-- 图标 -->
                  <div
                    v-if="showIcon && (iconSvg || localIcon)"
                    :style="`
                      order: ${iconPosition === 'before' ? 0 : iconPosition === 'middle' ? 1 : 2};
                      width: ${iconSize + iconBgPadding * 2}px;
                      height: ${iconSize + iconBgPadding * 2}px;
                      display: flex; align-items: center; justify-content: center;
                      background-color: ${iconBgEnabled ? hexToRgba(iconBgColor, iconBgOpacity) : 'transparent'};
                      backdrop-filter: ${iconBgEnabled && iconBgBlur > 0 ? `blur(${iconBgBlur}px)` : 'none'};
                      border-radius: ${iconBgEnabled ? iconBgRadius + '%' : '0'};
                    `"
                  >
                    <img
                      v-if="localIcon"
                      :src="localIcon"
                      alt="Icon"
                      :style="`
                        max-width: ${iconSize}px; max-height: ${iconSize}px;
                        flex-shrink: 0; border-radius: ${iconRadius}%;
                        overflow: hidden;
                        filter: drop-shadow(${iconShadow.x}px ${iconShadow.y}px ${iconShadow.blur}px ${hexToRgba(iconShadow.color, iconShadow.alpha)});
                      `"
                    />
                    <div
                      v-else
                      v-html="iconSvg"
                      :style="`
                        max-width: ${iconSize}px; max-height: ${iconSize}px;
                        flex-shrink: 0;
                        color: ${useOriginalIconColor ? 'inherit' : iconColor};
                        filter: drop-shadow(${iconShadow.x}px ${iconShadow.y}px ${iconShadow.blur}px ${hexToRgba(iconShadow.color, iconShadow.alpha)});
                        display: flex; align-items: center; justify-content: center;
                        border-radius: ${iconRadius}%; overflow: hidden;
                      `"
                    />
                  </div>

                  <!-- 左侧文字 -->
                  <span
                    :style="`
                      order: ${iconPosition === 'before' ? 1 : 0};
                      font-size: ${fontSize}px; color: ${textColor};
                      text-shadow: ${textShadow.x}px ${textShadow.y}px ${textShadow.blur}px ${hexToRgba(textShadow.color, textShadow.alpha)};
                      line-height: 1; white-space: nowrap;
                    `"
                  >{{ leftText }}</span>

                  <!-- 右侧文字 -->
                  <span
                    :style="`
                      order: ${iconPosition === 'after' ? 1 : 2};
                      font-size: ${fontSize}px; color: ${textColor};
                      text-shadow: ${textShadow.x}px ${textShadow.y}px ${textShadow.blur}px ${hexToRgba(textShadow.color, textShadow.alpha)};
                      line-height: 1; white-space: nowrap;
                    `"
                  >{{ rightText }}</span>
                </div>
              </foreignObject>

              <!-- 比例参考线 -->
              <g
                v-for="r in activeRatios" :key="r.label"
                class="ratio-guide"
              >
                <rect
                  v-if="canvasHeight * (r.w / r.h) < computedWidth"
                  :x="(computedWidth - canvasHeight * (r.w / r.h)) / 2"
                  y="0"
                  :width="canvasHeight * (r.w / r.h)"
                  :height="canvasHeight"
                  fill="none" stroke="rgba(255,0,0,0.5)" stroke-width="2" stroke-dasharray="10 5"
                />
                <text
                  v-if="canvasHeight * (r.w / r.h) < computedWidth"
                  :x="(computedWidth - canvasHeight * (r.w / r.h)) / 2 + 10"
                  y="30"
                  fill="rgba(255,0,0,0.5)" font-size="20"
                >{{ r.label }}</text>
              </g>

              <!-- 画布边框 -->
              <rect x="0" y="0" width="100%" height="100%" fill="none" stroke="rgba(255,0,0,0.8)" stroke-width="2" class="canvas-border"/>
            </svg>
          </div>
        </div>
      </div>

      <!-- 控制面板 -->
      <div class="w-full lg:flex-1">
        <!-- 移动端 tab -->
        <div class="lg:hidden mb-4">
          <div class="flex gap-1 border rounded-lg p-1">
            <button
              v-for="tab in (['content', 'style', 'export'] as const)"
              :key="tab"
              class="flex-1 px-3 py-1.5 rounded text-sm font-medium transition-colors"
              :class="activeTab === tab ? '' : 'text-muted-foreground'"
              :style="activeTab === tab ? 'background: var(--color-primary); color: white;' : ''"
              @click="activeTab = tab"
            >
              {{ { content: '内容', style: '样式', export: '导出' }[tab] }}
            </button>
          </div>
        </div>

        <!-- 桌面端三列 -->
        <div class="hidden lg:grid lg:grid-cols-3 gap-6">
          <!-- 内容列 -->
          <div class="space-y-6">
            <h2 class="text-lg font-semibold mb-4">内容</h2>

            <!-- 文本设置 -->
            <div class="space-y-4">
              <h3 class="font-medium">文本设置</h3>
              <div>
                <label class="text-sm text-muted-foreground">左侧文字</label>
                <input v-model="leftText" class="w-full h-9 rounded-lg border bg-transparent px-3 text-sm mt-1" style="border-color: var(--color-border);" />
              </div>
              <div>
                <label class="text-sm text-muted-foreground">右侧文字</label>
                <input v-model="rightText" class="w-full h-9 rounded-lg border bg-transparent px-3 text-sm mt-1" style="border-color: var(--color-border);" />
              </div>
              <div>
                <label class="text-sm text-muted-foreground">字体粗细: {{ fontWeight }}</label>
                <input type="range" v-model.number="fontWeight" min="100" max="900" step="100" class="w-full mt-1" />
              </div>
            </div>

            <!-- 图标设置 -->
            <div class="space-y-4">
              <div class="flex items-center justify-between">
                <h3 class="font-medium">图标设置</h3>
                <label class="flex items-center gap-2 cursor-pointer text-sm">
                  <input type="checkbox" v-model="showIcon" />
                  <span>显示图标</span>
                </label>
              </div>
              <div class="grid grid-cols-2 gap-2">
                <div>
                  <input type="file" accept="image/*" class="hidden" id="icon-upload" @change="onLocalIconUpload" />
                  <label for="icon-upload" class="flex items-center justify-center h-10 border-2 border-dashed rounded-lg cursor-pointer hover:border-primary text-sm" style="border-color: var(--color-border);">
                    {{ localIcon ? '更换图片' : '上传图标' }}
                  </label>
                </div>
                <div>
                  <input
                    :value="searchQuery"
                    @input="onSearchInput"
                    placeholder="搜索图标库..."
                    class="w-full h-10 rounded-lg border bg-transparent px-3 text-sm"
                    style="border-color: var(--color-border);"
                  />
                </div>
              </div>
              <div v-if="searchResults.length > 0" class="max-h-48 overflow-y-auto border rounded-lg p-2" style="border-color: var(--color-border);">
                <div class="grid gap-2" style="grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));">
                  <button
                    v-for="icon in searchResults" :key="icon"
                    class="aspect-square flex items-center justify-center p-1.5 rounded-md border hover:bg-accent transition-colors"
                    :class="icon === iconName ? 'border-primary' : ''"
                    :style="{ borderColor: icon === iconName ? 'var(--color-primary)' : 'var(--color-border)' }"
                    :title="icon"
                    @click="selectIcon(icon)"
                  >
                    <img :src="`https://api.iconify.design/${icon.split(':')[0]}/${icon.split(':')[1]}.svg`" class="w-full h-full" />
                  </button>
                </div>
              </div>
              <p class="text-xs text-muted-foreground">
                当前: {{ iconName }}
                <a href="https://icon-sets.iconify.design/" target="_blank" rel="noopener noreferrer" style="border-bottom: 1px solid var(--color-text-secondary); padding-bottom: 1px;" class="hover:opacity-70">浏览图标库</a>
              </p>
            </div>

            <!-- 背景图片 -->
            <div class="space-y-4">
              <h3 class="font-medium">背景图片</h3>
              <div>
                <input type="file" accept="image/*" class="hidden" id="bg-upload" @change="onBgUpload" />
                <label
                  for="bg-upload"
                  class="flex items-center justify-center w-full h-24 border-2 border-dashed rounded-lg cursor-pointer hover:border-primary transition-colors"
                  :class="isBgDragOver ? 'border-primary' : ''"
                  :style="{ borderColor: isBgDragOver ? 'var(--color-primary)' : 'var(--color-border)' }"
                  @dragover="onBgDragOver"
                  @dragleave="onBgDragLeave"
                  @drop="onBgDrop"
                >
                  <div class="flex flex-col items-center gap-1 text-muted-foreground">
                    <span class="text-xs">{{ isBgDragOver ? '松开上传' : bgImage ? '点击或拖拽更换' : '点击或拖拽上传' }}</span>
                  </div>
                </label>
              </div>
              <div v-if="bgImage" class="space-y-2">
                <div class="flex items-center justify-between">
                  <span class="text-sm text-muted-foreground">模糊: {{ bgBlur }}px</span>
                  <button class="text-red-500 text-sm" @click="bgImage = null">删除</button>
                </div>
                <input type="range" v-model.number="bgBlur" min="0" max="20" class="w-full" />
                <span class="text-sm text-muted-foreground">不透明度: {{ Math.round(bgOpacity * 100) }}%</span>
                <input type="range" v-model.number="bgOpacity" min="0" max="1" step="0.01" class="w-full" />
                <p class="text-xs text-muted-foreground">提示: 拖拽移动位置，滚轮缩放大小</p>
              </div>
            </div>
          </div>

          <!-- 样式列 -->
          <div class="space-y-6">
            <h2 class="text-lg font-semibold mb-4">样式</h2>

            <!-- 尺寸设置 -->
            <div class="space-y-4">
              <h3 class="font-medium">尺寸设置</h3>
              <div>
                <label class="text-sm text-muted-foreground">字体大小: {{ fontSize }}px</label>
                <input type="range" v-model.number="fontSize" min="20" max="700" class="w-full mt-1" />
              </div>
              <div>
                <label class="text-sm text-muted-foreground">图标大小: {{ iconSize }}px</label>
                <input type="range" v-model.number="iconSize" min="20" max="700" class="w-full mt-1" />
              </div>
              <div>
                <label class="text-sm text-muted-foreground">图标圆角: {{ iconRadius }}%</label>
                <input type="range" v-model.number="iconRadius" min="0" max="50" class="w-full mt-1" />
              </div>
              <div>
                <label class="text-sm text-muted-foreground">图标位置</label>
                <div class="flex gap-1 border rounded-lg p-1 mt-1" style="border-color: var(--color-border);">
                  <button
                    v-for="pos in ([{ v: 'before', l: '前面' }, { v: 'middle', l: '中间' }, { v: 'after', l: '后面' }] as const)"
                    :key="pos.v"
                    class="flex-1 px-2 py-1 rounded text-sm font-medium transition-colors"
                    :style="iconPosition === pos.v ? 'background: var(--color-primary); color: white;' : ''"
                    @click="iconPosition = pos.v"
                  >{{ pos.l }}</button>
                </div>
              </div>
              <div>
                <label class="text-sm text-muted-foreground">间距: {{ gap }}px</label>
                <input type="range" v-model.number="gap" min="0" max="200" class="w-full mt-1" />
              </div>
            </div>

            <!-- 颜色设置 -->
            <div class="space-y-4">
              <div class="flex items-center justify-between">
                <h3 class="font-medium">颜色设置</h3>
                <label class="flex items-center gap-2 cursor-pointer text-sm">
                  <input type="checkbox" v-model="linkColor" />
                  <span>颜色同步</span>
                </label>
              </div>
              <div class="flex items-center justify-between">
                <span class="text-sm text-muted-foreground">文字颜色</span>
                <div class="flex items-center gap-2">
                  <input v-model="textColor" class="w-24 h-8 text-xs rounded border bg-transparent px-2" style="border-color: var(--color-border);" />
                  <input type="color" v-model="textColor" class="w-8 h-8 rounded cursor-pointer" />
                </div>
              </div>
              <div class="flex items-center justify-between">
                <span class="text-sm text-muted-foreground">图标颜色</span>
                <div class="flex items-center gap-2">
                  <input v-model="iconColor" :disabled="useOriginalIconColor" class="w-24 h-8 text-xs rounded border bg-transparent px-2" style="border-color: var(--color-border);" />
                  <input type="color" v-model="iconColor" :disabled="useOriginalIconColor" class="w-8 h-8 rounded cursor-pointer" />
                </div>
              </div>
              <div class="flex items-center justify-between">
                <span class="text-sm text-muted-foreground">背景颜色</span>
                <div class="flex items-center gap-2">
                  <input v-model="bgColor" class="w-24 h-8 text-xs rounded border bg-transparent px-2" style="border-color: var(--color-border);" />
                  <input type="color" v-model="bgColor" class="w-8 h-8 rounded cursor-pointer" />
                </div>
              </div>
              <div>
                <label class="text-sm text-muted-foreground">背景不透明度: {{ Math.round(bgColorOpacity * 100) }}%</label>
                <input type="range" v-model.number="bgColorOpacity" min="0" max="1" step="0.01" class="w-full mt-1" />
              </div>
            </div>

            <!-- 图标背景 -->
            <div class="space-y-4 pt-4" style="border-top: 1px solid var(--color-border);">
              <h3 class="font-medium">图标背景</h3>
              <label class="flex items-center justify-between cursor-pointer text-sm">
                <span>启用图标背景</span>
                <input type="checkbox" v-model="iconBgEnabled" />
              </label>
              <div v-if="iconBgEnabled" class="space-y-3">
                <div class="flex items-center justify-between">
                  <span class="text-sm text-muted-foreground">背景颜色</span>
                  <input type="color" v-model="iconBgColor" class="w-6 h-6 rounded cursor-pointer" />
                </div>
                <div>
                  <label class="text-sm text-muted-foreground">不透明度: {{ Math.round(iconBgOpacity * 100) }}%</label>
                  <input type="range" v-model.number="iconBgOpacity" min="0" max="1" step="0.01" class="w-full mt-1" />
                </div>
                <div>
                  <label class="text-sm text-muted-foreground">内边距: {{ iconBgPadding }}px</label>
                  <input type="range" v-model.number="iconBgPadding" min="0" max="100" class="w-full mt-1" />
                </div>
                <div>
                  <label class="text-sm text-muted-foreground">圆角: {{ iconBgRadius }}%</label>
                  <input type="range" v-model.number="iconBgRadius" min="0" max="50" class="w-full mt-1" />
                </div>
              </div>
            </div>

            <!-- 阴影设置 -->
            <div class="space-y-4">
              <h3 class="font-medium">阴影设置</h3>
              <div class="space-y-3">
                <div class="flex items-center justify-between">
                  <span class="text-sm text-muted-foreground">颜色</span>
                  <input type="color" v-model="textShadow.color" class="w-8 h-8 rounded cursor-pointer" />
                </div>
                <div class="grid grid-cols-3 gap-2">
                  <div>
                    <label class="text-xs text-muted-foreground">模糊</label>
                    <input type="number" v-model.number="textShadow.blur" class="w-full h-8 rounded border bg-transparent px-2 text-sm mt-1" style="border-color: var(--color-border);" />
                  </div>
                  <div>
                    <label class="text-xs text-muted-foreground">水平</label>
                    <input type="number" v-model.number="textShadow.x" class="w-full h-8 rounded border bg-transparent px-2 text-sm mt-1" style="border-color: var(--color-border);" />
                  </div>
                  <div>
                    <label class="text-xs text-muted-foreground">垂直</label>
                    <input type="number" v-model.number="textShadow.y" class="w-full h-8 rounded border bg-transparent px-2 text-sm mt-1" style="border-color: var(--color-border);" />
                  </div>
                </div>
                <div>
                  <label class="text-sm text-muted-foreground">不透明度: {{ Math.round(textShadow.alpha * 100) }}%</label>
                  <input type="range" v-model.number="textShadow.alpha" min="0" max="1" step="0.01" class="w-full mt-1" />
                </div>
              </div>
            </div>
          </div>

          <!-- 导出列 -->
          <div class="space-y-6">
            <h2 class="text-lg font-semibold mb-4">导出</h2>

            <!-- 画板比例 -->
            <div class="space-y-2">
              <h3 class="font-medium">画板比例</h3>
              <div class="grid grid-cols-2 gap-2">
                <label
                  v-for="r in ratios" :key="r.label"
                  class="flex items-center gap-2 p-2 border rounded-lg cursor-pointer hover:bg-accent"
                  :style="{ borderColor: 'var(--color-border)' }"
                >
                  <input type="checkbox" v-model="r.checked" />
                  <span class="font-mono text-sm">{{ r.label }}</span>
                </label>
              </div>
            </div>

            <!-- 导出设置 -->
            <div class="space-y-4">
              <h3 class="font-medium">导出设置</h3>
              <div>
                <label class="text-sm text-muted-foreground">文件名</label>
                <input v-model="exportFilename" class="w-full h-9 rounded-lg border bg-transparent px-3 text-sm mt-1" style="border-color: var(--color-border);" />
              </div>
              <div>
                <label class="text-sm text-muted-foreground">格式</label>
                <div class="flex gap-1 border rounded-lg p-1 mt-1" style="border-color: var(--color-border);">
                  <button
                    class="flex-1 px-3 py-1 rounded text-sm font-bold transition-colors"
                    :style="exportFormat === 'png' ? 'background: var(--color-primary); color: white;' : ''"
                    @click="exportFormat = 'png'"
                  >PNG</button>
                  <button
                    class="flex-1 px-3 py-1 rounded text-sm font-bold transition-colors"
                    :style="exportFormat === 'svg' ? 'background: var(--color-primary); color: white;' : ''"
                    @click="exportFormat = 'svg'"
                  >SVG</button>
                </div>
              </div>
              <div v-if="exportFormat === 'png'">
                <h4 class="text-sm text-muted-foreground mb-2">缩放倍率</h4>
                <div class="grid grid-cols-2 gap-2">
                  <label
                    v-for="s in [1, 2, 3, 4]" :key="s"
                    class="flex items-center gap-2 p-2 border rounded-lg cursor-pointer hover:bg-accent"
                    :style="{ borderColor: 'var(--color-border)' }"
                  >
                    <input
                      type="checkbox"
                      :checked="exportScales.includes(s)"
                      @change="exportScales = exportScales.includes(s) ? exportScales.filter(x => x !== s) : [...exportScales, s].sort()"
                    />
                    <span class="font-mono text-sm">{{ s }}x</span>
                  </label>
                </div>
                <p class="text-xs text-muted-foreground mt-2">{{ computedWidth }}x{{ canvasHeight }} px</p>
              </div>
              <button
                class="btn-pill btn-primary w-full justify-center"
                :disabled="activeRatios.length === 0"
                @click="onExport"
              >
                导出图片
              </button>
            </div>
          </div>
        </div>

        <!-- 移动端内容 -->
        <div class="lg:hidden">
          <div v-if="activeTab === 'content'" class="space-y-6">
            <!-- 同上"内容列"的全部内容 -->
            <div class="space-y-4">
              <h3 class="font-medium">文本设置</h3>
              <div><label class="text-sm text-muted-foreground">左侧文字</label><input v-model="leftText" class="w-full h-9 rounded-lg border bg-transparent px-3 text-sm mt-1" style="border-color: var(--color-border);" /></div>
              <div><label class="text-sm text-muted-foreground">右侧文字</label><input v-model="rightText" class="w-full h-9 rounded-lg border bg-transparent px-3 text-sm mt-1" style="border-color: var(--color-border);" /></div>
              <div><label class="text-sm text-muted-foreground">字体粗细: {{ fontWeight }}</label><input type="range" v-model.number="fontWeight" min="100" max="900" step="100" class="w-full mt-1" /></div>
            </div>
            <div class="space-y-4">
              <h3 class="font-medium">图标设置</h3>
              <input type="file" accept="image/*" class="hidden" id="icon-upload-mobile" @change="onLocalIconUpload" />
              <label for="icon-upload-mobile" class="flex items-center justify-center h-10 border-2 border-dashed rounded-lg cursor-pointer text-sm" style="border-color: var(--color-border);">{{ localIcon ? '更换图片' : '上传图标' }}</label>
              <input :value="searchQuery" @input="onSearchInput" placeholder="搜索图标库..." class="w-full h-9 rounded-lg border bg-transparent px-3 text-sm" style="border-color: var(--color-border);" />
              <p class="text-xs text-muted-foreground">
                当前: {{ iconName }}
                <a href="https://icon-sets.iconify.design/" target="_blank" rel="noopener noreferrer" style="border-bottom: 1px solid var(--color-text-secondary); padding-bottom: 1px;" class="hover:opacity-70">浏览图标库</a>
              </p>
            </div>
            <div class="space-y-4">
              <h3 class="font-medium">背景图片</h3>
              <input type="file" accept="image/*" class="hidden" id="bg-upload-mobile" @change="onBgUpload" />
              <label for="bg-upload-mobile" class="flex items-center justify-center w-full h-24 border-2 border-dashed rounded-lg cursor-pointer text-sm" style="border-color: var(--color-border);">{{ bgImage ? '更换背景' : '上传背景' }}</label>
            </div>
          </div>
          <div v-else-if="activeTab === 'style'" class="space-y-6">
            <div class="space-y-4">
              <h3 class="font-medium">尺寸设置</h3>
              <div><label class="text-sm text-muted-foreground">字体大小: {{ fontSize }}px</label><input type="range" v-model.number="fontSize" min="20" max="700" class="w-full mt-1" /></div>
              <div><label class="text-sm text-muted-foreground">图标大小: {{ iconSize }}px</label><input type="range" v-model.number="iconSize" min="20" max="700" class="w-full mt-1" /></div>
              <div><label class="text-sm text-muted-foreground">间距: {{ gap }}px</label><input type="range" v-model.number="gap" min="0" max="200" class="w-full mt-1" /></div>
            </div>
            <div class="space-y-4">
              <h3 class="font-medium">颜色设置</h3>
              <div class="flex items-center justify-between"><span class="text-sm text-muted-foreground">文字颜色</span><input type="color" v-model="textColor" class="w-8 h-8 rounded cursor-pointer" /></div>
              <div class="flex items-center justify-between"><span class="text-sm text-muted-foreground">背景颜色</span><input type="color" v-model="bgColor" class="w-8 h-8 rounded cursor-pointer" /></div>
            </div>
          </div>
          <div v-else class="space-y-6">
            <div class="space-y-2">
              <h3 class="font-medium">画板比例</h3>
              <div class="grid grid-cols-2 gap-2">
                <label v-for="r in ratios" :key="r.label" class="flex items-center gap-2 p-2 border rounded-lg cursor-pointer" style="border-color: var(--color-border);">
                  <input type="checkbox" v-model="r.checked" /><span class="font-mono text-sm">{{ r.label }}</span>
                </label>
              </div>
            </div>
            <button class="btn-pill btn-primary w-full justify-center" @click="onExport">导出图片</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
