feat(ui): 设置页重设计 + 全站表格配色统一为亮色变量
- 设置页:移除暗色残留,统一页头/卡片/图标块/按钮样式 - 模型管理:照 vivid 重排——模型名等宽显示,子行展示渠道名+权重, 定价胶囊「档位+普通价+代理价」,配置列统一灰色等宽标签, 操作列加宽修复删除按钮被挤 - 后端 ModelsView 返回每个模型绑定的渠道名列表(channel_models JOIN) - 全站 scoped 样式里的硬编码白值(rgb(255 255 255/white)批量替换为 主题变量,修复亮色模式下表头/开关/操作按钮不可见(如渠道表头) - 关于页:联系卡片统一等高布局,链接/非链接卡片对齐一致 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -10,24 +10,31 @@ const powers = [
|
||||
{ icon: 't2v', title: '文字生视频', desc: '一段描述生成短片,时长分辨率可选。', tint: 'linear-gradient(135deg,#38bdf8,#52525b)' },
|
||||
{ icon: 'i2v', title: '图生视频', desc: '给张参考图,让静态画面动起来。', tint: 'linear-gradient(135deg,#18181b,#3f3f46)' },
|
||||
]
|
||||
|
||||
const contactCards = computed(() => {
|
||||
const c = contact.value || {}
|
||||
const list = []
|
||||
if (c.shop) list.push({ label: '商店', value: '前往商店', href: c.shop })
|
||||
if (c.email) list.push({ label: '邮箱', value: c.email, href: `mailto:${c.email}` })
|
||||
if (c.qq) list.push({ label: 'QQ', value: c.qq, href: c.qq_link || '' })
|
||||
if (c.qq_group) list.push({ label: 'QQ 群', value: c.qq_group, href: c.qq_group_link || '' })
|
||||
return list
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-16 pb-8">
|
||||
<div class="space-y-14 pb-8">
|
||||
<!-- ===== hero ===== -->
|
||||
<section class="relative overflow-hidden rounded-[1.4rem] anime-card px-6 py-10 md:px-12 md:py-14">
|
||||
<div class="memphis-dots absolute inset-0 opacity-40 pointer-events-none"></div>
|
||||
<section class="ab-hero">
|
||||
<div class="relative grid md:grid-cols-[1.1fr_0.9fr] gap-8 items-center">
|
||||
<div>
|
||||
<span class="sticker">✦ 关于我们</span>
|
||||
<h1 class="mt-4 text-4xl md:text-5xl font-black tracking-tight text-[color:var(--fg)]">
|
||||
把创作交给 <span class="anime-grad-text">{{ site.title }}</span>
|
||||
</h1>
|
||||
<p class="text-[color:var(--fg-2)] mt-5 text-base md:text-lg leading-relaxed max-w-xl">
|
||||
{{ site.title }} 是一个聚合 GPT、Gemini、Firefly、Flux 等顶级模型的 AI 生图与生视频平台。
|
||||
<span class="ab-eyebrow">✦ 关于我们</span>
|
||||
<h1 class="ab-title">把创作交给 <span class="ab-brand">{{ site.title }}</span></h1>
|
||||
<p class="ab-lead">
|
||||
{{ site.title }} 是一个 AI 生图与生视频平台,汇集多家顶级模型,按实际生成量计费。
|
||||
把脑海里的画面写成一句话,剩下的交给我们变成图像与视频。
|
||||
</p>
|
||||
<router-link to="/user" class="bubble-btn mt-7">开始创作 →</router-link>
|
||||
<router-link to="/user" class="btn-primary ab-cta">开始创作 <span aria-hidden="true">→</span></router-link>
|
||||
</div>
|
||||
<!-- floating glass tile cluster standing in for a mascot illustration -->
|
||||
<div class="ab-cluster" aria-hidden="true">
|
||||
@@ -42,9 +49,9 @@ const powers = [
|
||||
|
||||
<!-- ===== powers ===== -->
|
||||
<section>
|
||||
<div class="anime-eyebrow text-[var(--m-orange)]">能做什么</div>
|
||||
<h2 class="mt-3 text-2xl md:text-3xl font-black tracking-tight text-[color:var(--fg)]">四种方式,把想象变成画面</h2>
|
||||
<div class="mt-7 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<div class="ab-eyebrow">能做什么</div>
|
||||
<h2 class="ab-h2">四种方式,把想象变成画面</h2>
|
||||
<div class="mt-6 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<div v-for="p in powers" :key="p.title" class="power-card p-5">
|
||||
<div class="power-ico" :style="{ background: p.tint }">
|
||||
<svg v-if="p.icon === 't2i'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5h16v14H4z"/><path d="M4 15l4.5-4.5 3 3L15 10l5 5"/><circle cx="9" cy="9" r="1.3"/></svg>
|
||||
@@ -60,60 +67,45 @@ const powers = [
|
||||
|
||||
<!-- ===== contact ===== -->
|
||||
<section>
|
||||
<div class="anime-eyebrow text-sky-600">联系我们</div>
|
||||
<h2 class="mt-3 text-2xl md:text-3xl font-black tracking-tight text-[color:var(--fg)]">有问题?来找我们玩~</h2>
|
||||
<p class="text-[color:var(--fg-3)] mt-2 mb-6">合作、反馈,或想加入交流群,随时招呼。</p>
|
||||
<div class="ab-eyebrow">联系我们</div>
|
||||
<h2 class="ab-h2">有问题?来找我们玩~</h2>
|
||||
<p class="ab-sub">合作、反馈,或想加入交流群,随时招呼。</p>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-3xl">
|
||||
<a v-if="contact.shop" :href="contact.shop" target="_blank" rel="noopener"
|
||||
class="group anime-card flex items-center justify-between gap-3 p-5">
|
||||
<div>
|
||||
<div class="sticker">商店</div>
|
||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 group-hover:text-[var(--m-orange)] transition-colors">前往商店</div>
|
||||
<div class="mt-6 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||
<component :is="c.href ? 'a' : 'div'" v-for="c in contactCards" :key="c.label"
|
||||
:href="c.href || undefined" :target="c.href ? '_blank' : undefined" rel="noopener"
|
||||
class="ct-card" :class="c.href && 'ct-link'">
|
||||
<div class="ct-top">
|
||||
<span class="ct-label">{{ c.label }}</span>
|
||||
<span v-if="c.href" class="ct-arrow" aria-hidden="true">↗</span>
|
||||
</div>
|
||||
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
||||
</a>
|
||||
|
||||
<a v-if="contact.email" :href="`mailto:${contact.email}`"
|
||||
class="group anime-card p-5">
|
||||
<div class="sticker">邮箱</div>
|
||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 break-all group-hover:text-sky-600 transition-colors">{{ contact.email }}</div>
|
||||
</a>
|
||||
|
||||
<a v-if="contact.qq && contact.qq_link" :href="contact.qq_link" target="_blank" rel="noopener"
|
||||
class="group anime-card flex items-center justify-between gap-3 p-5">
|
||||
<div>
|
||||
<div class="sticker">QQ</div>
|
||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all group-hover:text-sky-600 transition-colors">{{ contact.qq }}</div>
|
||||
</div>
|
||||
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
||||
</a>
|
||||
<div v-else-if="contact.qq" class="anime-card p-5">
|
||||
<div class="sticker">QQ</div>
|
||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all">{{ contact.qq }}</div>
|
||||
</div>
|
||||
|
||||
<a v-if="contact.qq_group && contact.qq_group_link" :href="contact.qq_group_link" target="_blank" rel="noopener"
|
||||
class="group anime-card flex items-center justify-between gap-3 p-5">
|
||||
<div>
|
||||
<div class="sticker">QQ 群</div>
|
||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all group-hover:text-emerald-600 transition-colors">{{ contact.qq_group }}</div>
|
||||
</div>
|
||||
<span class="text-[color:var(--fg-faint)] group-hover:translate-x-1 transition-transform">→</span>
|
||||
</a>
|
||||
<div v-else-if="contact.qq_group" class="anime-card p-5">
|
||||
<div class="sticker">QQ 群</div>
|
||||
<div class="text-base font-semibold text-[color:var(--fg)] mt-2 tabular-nums break-all">{{ contact.qq_group }}</div>
|
||||
</div>
|
||||
<div class="ct-value">{{ c.value }}</div>
|
||||
</component>
|
||||
</div>
|
||||
|
||||
<p v-if="!contact.shop && !contact.email && !contact.qq && !contact.qq_group"
|
||||
class="text-sm text-[color:var(--fg-3)]">管理员尚未配置联系方式。</p>
|
||||
<p v-if="!contactCards.length" class="ab-sub">管理员尚未配置联系方式。</p>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.ab-hero { position: relative; overflow: hidden; border-radius: 24px; padding: 48px 52px; background: var(--surface-solid); border: 1px solid rgb(24 24 27 / .07); box-shadow: 0 1px 2px rgb(24 24 27 / .03), 0 18px 40px -22px rgb(24 24 27 / .16); }
|
||||
.ab-hero::before { content: ''; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(520px 300px at 92% 0%, rgba(251, 146, 60, .1), transparent 70%); }
|
||||
.ab-eyebrow { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 800; letter-spacing: .08em; color: var(--fg-3); }
|
||||
.ab-title { margin-top: 14px; font-size: clamp(32px, 4vw, 48px); font-weight: 800; line-height: 1.15; letter-spacing: -0.04em; color: var(--fg); }
|
||||
.ab-brand { background: linear-gradient(100deg, #18181b, #71717a); -webkit-background-clip: text; background-clip: text; color: transparent; }
|
||||
.ab-lead { margin-top: 18px; max-width: 34em; font-size: 16px; line-height: 1.8; color: var(--fg-2); }
|
||||
.ab-cta { margin-top: 26px; height: 44px; padding: 0 24px !important; font-size: 14px !important; border-radius: 999px !important; }
|
||||
.ab-h2 { margin-top: 8px; font-size: 26px; font-weight: 800; letter-spacing: -0.03em; color: var(--fg); }
|
||||
.ab-sub { margin-top: 6px; font-size: 14px; color: var(--fg-3); }
|
||||
.ct-card { display: flex; flex-direction: column; justify-content: space-between; gap: 18px; min-height: 108px; padding: 18px 20px; border-radius: 16px; background: var(--surface-solid); border: 1px solid rgb(24 24 27 / .07); text-decoration: none; transition: transform .18s ease, border-color .18s ease, box-shadow .18s ease; }
|
||||
.ct-link:hover { transform: translateY(-3px); border-color: rgb(24 24 27 / .3); box-shadow: 0 14px 30px -16px rgb(24 24 27 / .25); }
|
||||
.ct-top { display: flex; align-items: center; justify-content: space-between; }
|
||||
.ct-label { font-size: 12px; font-weight: 800; letter-spacing: .06em; color: var(--fg-3); }
|
||||
.ct-arrow { font-size: 15px; color: var(--fg-faint); transition: transform .18s ease, color .18s ease; }
|
||||
.ct-link:hover .ct-arrow { transform: translate(2px, -2px); color: var(--fg); }
|
||||
.ct-value { font-size: 17px; font-weight: 800; letter-spacing: -0.01em; color: var(--fg); font-variant-numeric: tabular-nums; word-break: break-all; }
|
||||
@media (max-width: 640px) { .ab-hero { padding: 30px 22px; } }
|
||||
/* Floating glass tile cluster — a loose collage of rotated frosted squares. */
|
||||
.ab-cluster {
|
||||
position: relative;
|
||||
@@ -125,19 +117,17 @@ const powers = [
|
||||
place-items: center;
|
||||
width: 5.5rem;
|
||||
height: 5.5rem;
|
||||
border: 1px solid var(--glass-border);
|
||||
border: 1px solid rgb(24 24 27 / .07);
|
||||
border-radius: 1.2rem;
|
||||
background: var(--surface);
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
backdrop-filter: blur(14px);
|
||||
box-shadow: var(--glass-shadow-lg);
|
||||
background: var(--surface-solid);
|
||||
box-shadow: 0 14px 30px -14px rgb(24 24 27 / .25);
|
||||
color: var(--m-orange);
|
||||
}
|
||||
.ab-tile svg { width: 2.3rem; height: 2.3rem; }
|
||||
.ab-1 { left: 12%; top: 6%; transform: rotate(-9deg); animation: memphis-float 6s ease-in-out infinite; }
|
||||
.ab-2 { right: 14%; top: 0; color: var(--m-orange-2); transform: rotate(7deg); animation: memphis-float 7s ease-in-out infinite reverse; }
|
||||
.ab-3 { left: 26%; bottom: 4%; color: var(--m-pink); transform: rotate(5deg); animation: memphis-bounce 4.5s ease-in-out infinite; }
|
||||
.ab-4 { right: 8%; bottom: 14%; color: var(--m-mint); transform: rotate(-6deg); animation: memphis-float 5.5s ease-in-out infinite; }
|
||||
.ab-2 { right: 14%; top: 0; color: #18181b; transform: rotate(7deg); animation: memphis-float 7s ease-in-out infinite reverse; }
|
||||
.ab-3 { left: 26%; bottom: 4%; color: #52525b; transform: rotate(5deg); animation: memphis-bounce 4.5s ease-in-out infinite; }
|
||||
.ab-4 { right: 8%; bottom: 14%; color: #18181b; transform: rotate(-6deg); animation: memphis-float 5.5s ease-in-out infinite; }
|
||||
.ab-star {
|
||||
position: absolute;
|
||||
left: 50%; top: 44%;
|
||||
@@ -146,12 +136,10 @@ const powers = [
|
||||
animation: memphis-wiggle 3.5s ease-in-out infinite;
|
||||
}
|
||||
.power-card {
|
||||
border: 1px solid var(--glass-border);
|
||||
border: 1px solid rgb(24 24 27 / .07);
|
||||
border-radius: 1.1rem;
|
||||
background: var(--surface);
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
backdrop-filter: blur(14px);
|
||||
box-shadow: var(--glass-shadow);
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 2px rgb(24 24 27 / .03), 0 10px 28px -16px rgb(24 24 27 / .12);
|
||||
transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
|
||||
}
|
||||
.power-card:hover { transform: translateY(-3px); border-color: rgb(24 24 27 / 0.45); box-shadow: var(--glass-shadow-lg); }
|
||||
|
||||
Reference in New Issue
Block a user