From 86fe7de029ea955658e7ea1834b43692381960bd Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Wed, 20 May 2026 02:01:10 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=8C=E6=9B=B4=E6=96=B0=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E5=92=8C=E7=BB=84=E4=BB=B6=EF=BC=8C=E4=BC=98=E5=8C=96=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E5=8A=A8=E7=94=BB=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PRODUCT.md | 36 ++++++++++ app/assets/css/main.css | 22 ++++++ app/components/index/WaterfallCard.vue | 18 ++--- app/components/index/WaterfallImageCard.vue | 28 +++++++- app/components/index/WaterfallPortfolioCard.vue | 12 ++-- app/components/index/WaterfallProjectCard.vue | 19 +++-- app/components/index/WaterfallTextCard.vue | 37 +++++----- app/pages/index/index.vue | 94 +++++++++++++++++-------- 8 files changed, 191 insertions(+), 75 deletions(-) create mode 100644 PRODUCT.md diff --git a/PRODUCT.md b/PRODUCT.md new file mode 100644 index 0000000..4425c52 --- /dev/null +++ b/PRODUCT.md @@ -0,0 +1,36 @@ +# Product + +## Register + +brand + +## Users + +个人用户在此策展和收藏灵感内容(图片、文字、项目),通过瀑布流浏览发现美学作品。同时也面向潜在客户或雇主,作为个人作品集的展示窗口——设计本身就是能力证明。 + +## Product Purpose + +一个个人灵感策展与作品展示平台。核心体验是浏览:用户在精心编排的视觉流中发现内容。设计在此不是装饰,是内容本身——前卫的视觉表达直接传达创作者的能力和品味。 + +## Brand Personality + +大胆、实验性、前卫。像一个独立设计师的作品集站点——强烈个性,不按模板出牌。拒绝安全的设计选择,愿意为视觉冲击力承担风险。字体、色彩、布局都是表达态度的工具,不是中性的容器。 + +参考方向:独立设计师作品集(Tobias van Schneider、Malika Favre 等),反传统编辑美学。 + +## Anti-references + +- 冷淡极简:纯黑白、瑞士国际主义风格、无色彩无温度的克制 +- 典型 SaaS 模板:蓝紫渐变 hero、玻璃卡片、大数字加小标签的 metrics 模式 +- 任何看起来像 "AI 生成的 landing page" 的东西 + +## Design Principles + +- **设计即内容**:视觉不是包装,视觉是信息本身。每个设计决策都在说 "这是谁做的" +- **宁可冒险也不平庸**:大胆的选择好过安全的平均。出格比无聊更接近目标 +- **内容优先,但不中立**:框架服务于内容,但框架本身也有态度。排版、间距、色彩都有自己的声音 +- **意外与连贯并存**:每个区域可以有自己的视觉世界,但整体仍是同一个声音 + +## Accessibility & Inclusion + +基础 WCAG AA 在长期计划中。当前阶段实验性优先,视觉探索不受限于合规要求。后续迭代再补。 diff --git a/app/assets/css/main.css b/app/assets/css/main.css index 7a43b22..64f1e42 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -1,4 +1,5 @@ @import "tailwindcss"; +@import url('https://fonts.googleapis.com/css2?family=Abril+Fatface&display=swap'); @theme { --color-canvas: #faf9f5; @@ -16,6 +17,10 @@ --color-muted-soft: #8e8b82; --color-hairline: #e6dfd8; --color-hairline-soft: #ebe6df; + --color-on-dark: #faf9f5; + --color-on-primary: #ffffff; + --color-accent-teal: #5db8a6; + --color-accent-amber: #e8a55a; } body { @@ -28,6 +33,23 @@ body { --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); + --font-display: "Abril Fatface", "Times New Roman", Georgia, Garamond, serif; + --font-body: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; +} + +.noise-texture { + position: relative; +} + +.noise-texture::before { + content: ""; + position: absolute; + inset: 0; + opacity: 0.025; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); + background-size: 128px 128px; + pointer-events: none; + z-index: 0; } @media (prefers-reduced-motion: reduce) { diff --git a/app/components/index/WaterfallCard.vue b/app/components/index/WaterfallCard.vue index 1c82456..e5706af 100644 --- a/app/components/index/WaterfallCard.vue +++ b/app/components/index/WaterfallCard.vue @@ -1,5 +1,5 @@ @@ -43,12 +46,15 @@ function onImgError() { border-radius: 12px; background: var(--color-surface-card); overflow: hidden; - transition: transform 0.3s ease, box-shadow 0.3s ease; + transition: transform 0.4s var(--ease-out-expo); } .card:hover { - transform: translateY(-3px); - box-shadow: 0 8px 30px rgba(20, 20, 19, 0.07); + transform: scale(1.015); +} + +.card:hover .card-label { + opacity: 1; } .img-placeholder { @@ -83,6 +89,22 @@ function onImgError() { opacity: 1; } +.card-label { + position: absolute; + bottom: 12px; + right: 12px; + background: var(--color-surface-dark); + color: var(--color-on-dark); + font-size: 12px; + font-weight: 500; + padding: 6px 12px; + border-radius: 6px; + letter-spacing: 0.03em; + opacity: 0; + transition: opacity 0.3s ease; + z-index: 2; +} + .img-fallback { position: absolute; inset: 0; diff --git a/app/components/index/WaterfallPortfolioCard.vue b/app/components/index/WaterfallPortfolioCard.vue index 685e283..17f46dc 100644 --- a/app/components/index/WaterfallPortfolioCard.vue +++ b/app/components/index/WaterfallPortfolioCard.vue @@ -56,12 +56,12 @@ const totalImages = computed(() => props.images.length) border-radius: 12px; background: var(--color-surface-card); overflow: hidden; - transition: transform 0.3s ease, box-shadow 0.3s ease; + transition: transform 0.4s var(--ease-out-expo), box-shadow 0.4s var(--ease-out-expo); } .card:hover { - transform: translateY(-3px); - box-shadow: 0 8px 30px rgba(20, 20, 19, 0.07); + transform: translateY(-5px) scale(1.01); + box-shadow: 0 16px 48px rgba(20, 20, 19, 0.12); } .img-grid { @@ -131,12 +131,12 @@ const totalImages = computed(() => props.images.length) .overlay h3 { color: #fff; - font-family: "Times New Roman", Georgia, serif; - font-size: 16px; + font-family: var(--font-display); + font-size: 18px; font-weight: 400; line-height: 1.3; margin: 0 0 4px; - letter-spacing: -0.2px; + letter-spacing: -0.01em; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3); } diff --git a/app/components/index/WaterfallProjectCard.vue b/app/components/index/WaterfallProjectCard.vue index f726775..fa56aab 100644 --- a/app/components/index/WaterfallProjectCard.vue +++ b/app/components/index/WaterfallProjectCard.vue @@ -53,12 +53,12 @@ function onImgError() { border-radius: 12px; background: var(--color-surface-card); overflow: hidden; - transition: transform 0.3s ease, box-shadow 0.3s ease; + transition: transform 0.4s var(--ease-out-expo), box-shadow 0.4s var(--ease-out-expo); } .card:hover { - transform: translateY(-3px); - box-shadow: 0 8px 30px rgba(20, 20, 19, 0.07); + transform: translateY(-5px) scale(1.01); + box-shadow: 0 16px 48px rgba(20, 20, 19, 0.12); } .img-placeholder { @@ -134,12 +134,12 @@ function onImgError() { .card-body h3 { color: #fff; - font-family: "Times New Roman", Georgia, serif; - font-size: 17px; + font-family: var(--font-display); + font-size: 18px; font-weight: 400; line-height: 1.3; margin: 0 0 5px; - letter-spacing: -0.2px; + letter-spacing: -0.01em; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); } @@ -162,11 +162,10 @@ function onImgError() { font-size: 11.5px; font-weight: 400; color: rgba(255, 255, 255, 0.82); - background: rgba(255, 255, 255, 0.12); - border: 1px solid rgba(255, 255, 255, 0.15); - padding: 4px 10px; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.18); + padding: 3px 10px; border-radius: 9999px; line-height: 1.3; - backdrop-filter: blur(4px); } diff --git a/app/components/index/WaterfallTextCard.vue b/app/components/index/WaterfallTextCard.vue index 3d8b6c4..b46bea2 100644 --- a/app/components/index/WaterfallTextCard.vue +++ b/app/components/index/WaterfallTextCard.vue @@ -9,7 +9,7 @@ defineProps<{