feat: 新增作品和动态详情页
✨ Work 详情页 (/work/[slug]): - Hero 大图 + 渐变遮罩 - 项目概述、挑战、解决方案 - 项目截图画廊 - 右侧信息卡片(客户、年份、周期、服务) - 访问项目按钮 - 相关项目推荐 - 返回列表按钮 - 完整中英文内容 ✨ News 详情页 (/news/[slug]): - Hero 大图 + 渐变遮罩 - 分类标签 + 日期 + 阅读时间 + 作者 - 文章正文(多段落 + 引用 + 图片) - 分享按钮(Twitter、LinkedIn、复制链接) - 相关文章推荐 - 返回列表按钮 - 完整中英文内容 🔧 列表页更新: - work.vue → work/index.vue - news.vue → news/index.vue - 卡片链接改为 NuxtLink 到详情页 🌍 国际化: - 6 个作品详情(中文 + 英文) - 6 篇文章详情(中文 + 英文) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,236 @@
|
|||||||
|
<template>
|
||||||
|
<main class="min-h-screen">
|
||||||
|
<!-- 返回按钮 -->
|
||||||
|
<div class="fixed top-28 left-4 md:left-8 z-30">
|
||||||
|
<NuxtLink
|
||||||
|
to="/news"
|
||||||
|
class="inline-flex items-center gap-2 px-4 py-2.5 rounded-full bg-white/90 backdrop-blur-sm shadow-lg hover:shadow-xl transition-all duration-300 text-sm font-semibold text-black hover:-translate-x-1"
|
||||||
|
>
|
||||||
|
<Icon name="ph:arrow-left" class="w-5 h-5" />
|
||||||
|
{{ t('news.backToList') }}
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 文章 Hero -->
|
||||||
|
<section class="relative h-[50vh] md:h-[60vh] overflow-hidden">
|
||||||
|
<img
|
||||||
|
:src="article.image"
|
||||||
|
:alt="article.title"
|
||||||
|
class="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
||||||
|
<div class="absolute bottom-0 left-0 right-0 p-8 md:p-16">
|
||||||
|
<div class="max-w-[800px] mx-auto">
|
||||||
|
<span
|
||||||
|
class="inline-block px-3 py-1.5 text-xs md:text-sm font-semibold rounded-full mb-4"
|
||||||
|
:class="article.badge"
|
||||||
|
>
|
||||||
|
{{ article.category }}
|
||||||
|
</span>
|
||||||
|
<h1 class="text-3xl md:text-5xl lg:text-6xl font-bold text-white mb-4 tracking-tight">
|
||||||
|
{{ article.title }}
|
||||||
|
</h1>
|
||||||
|
<div class="flex items-center gap-4 text-white/80 text-sm md:text-base">
|
||||||
|
<span class="flex items-center gap-1.5">
|
||||||
|
<Icon name="ph:calendar-blank" class="w-4 h-4" />
|
||||||
|
{{ article.date }}
|
||||||
|
</span>
|
||||||
|
<span class="flex items-center gap-1.5">
|
||||||
|
<Icon name="ph:clock" class="w-4 h-4" />
|
||||||
|
{{ article.readTime }}
|
||||||
|
</span>
|
||||||
|
<span class="flex items-center gap-1.5">
|
||||||
|
<Icon name="ph:user" class="w-4 h-4" />
|
||||||
|
{{ article.author }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 文章内容 -->
|
||||||
|
<section class="max-w-[800px] mx-auto px-6 md:px-10 py-16 md:py-24">
|
||||||
|
<article class="prose prose-lg max-w-none">
|
||||||
|
<p class="text-gray-700 text-lg leading-relaxed mb-8">
|
||||||
|
{{ t(`news.detail.items.${slug}.content`) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-6 mt-12">
|
||||||
|
{{ t(`news.detail.items.${slug}.section1Title`) }}
|
||||||
|
</h2>
|
||||||
|
<p class="text-gray-700 text-lg leading-relaxed mb-8">
|
||||||
|
{{ t(`news.detail.items.${slug}.section1Content`) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 引用 -->
|
||||||
|
<blockquote class="border-l-4 border-black pl-6 my-10 italic text-gray-600 text-lg">
|
||||||
|
"{{ t(`news.detail.items.${slug}.quote`) }}"
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-6 mt-12">
|
||||||
|
{{ t(`news.detail.items.${slug}.section2Title`) }}
|
||||||
|
</h2>
|
||||||
|
<p class="text-gray-700 text-lg leading-relaxed mb-8">
|
||||||
|
{{ t(`news.detail.items.${slug}.section2Content`) }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 文章内图片 -->
|
||||||
|
<div class="my-10 rounded-2xl overflow-hidden">
|
||||||
|
<img :src="article.image" :alt="article.title" class="w-full h-auto" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-6 mt-12">
|
||||||
|
{{ t(`news.detail.items.${slug}.section3Title`) }}
|
||||||
|
</h2>
|
||||||
|
<p class="text-gray-700 text-lg leading-relaxed mb-8">
|
||||||
|
{{ t(`news.detail.items.${slug}.section3Content`) }}
|
||||||
|
</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<!-- 分享按钮 -->
|
||||||
|
<div class="mt-16 pt-8 border-t border-gray-200">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<p class="text-sm text-gray-500">{{ t('news.detail.shareArticle') }}</p>
|
||||||
|
<div class="flex gap-3">
|
||||||
|
<button class="w-10 h-10 rounded-full bg-gray-100 hover:bg-black hover:text-white flex items-center justify-center transition-all duration-300">
|
||||||
|
<Icon name="ph:x-logo" class="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
<button class="w-10 h-10 rounded-full bg-gray-100 hover:bg-black hover:text-white flex items-center justify-center transition-all duration-300">
|
||||||
|
<Icon name="ph:linkedin-logo" class="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
<button class="w-10 h-10 rounded-full bg-gray-100 hover:bg-black hover:text-white flex items-center justify-center transition-all duration-300">
|
||||||
|
<Icon name="ph:link" class="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 相关文章 -->
|
||||||
|
<section class="bg-gray-50 py-16 md:py-24">
|
||||||
|
<div class="max-w-[1200px] mx-auto px-6 md:px-10">
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-10 text-center">{{ t('news.detail.relatedArticles') }}</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
|
<NuxtLink
|
||||||
|
v-for="related in relatedArticles"
|
||||||
|
:key="related.id"
|
||||||
|
:to="`/news/${related.id}`"
|
||||||
|
class="group block rounded-2xl overflow-hidden bg-white shadow-lg hover:shadow-xl transition-all duration-300 hover:-translate-y-1"
|
||||||
|
>
|
||||||
|
<div class="relative aspect-[16/10] overflow-hidden">
|
||||||
|
<img :src="related.image" :alt="related.title" class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" />
|
||||||
|
</div>
|
||||||
|
<div class="p-5">
|
||||||
|
<span class="text-xs text-gray-500">{{ related.date }}</span>
|
||||||
|
<h3 class="text-lg font-bold text-black group-hover:text-gray-600 transition-colors mt-1 line-clamp-2">
|
||||||
|
{{ related.title }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useSeoMeta, createError } from '#imports'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const route = useRoute()
|
||||||
|
const slug = route.params.slug as string
|
||||||
|
|
||||||
|
interface NewsItem {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
image: string
|
||||||
|
category: string
|
||||||
|
badge: string
|
||||||
|
date: string
|
||||||
|
readTime: string
|
||||||
|
author: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const newsData: Record<string, NewsItem> = {
|
||||||
|
'design-trends-2026': {
|
||||||
|
id: 'design-trends-2026',
|
||||||
|
title: 'Design Trends Shaping 2026',
|
||||||
|
image: 'https://picsum.photos/id/1/1200/800',
|
||||||
|
category: 'Insights',
|
||||||
|
badge: 'bg-purple-100 text-purple-700',
|
||||||
|
date: 'May 28, 2026',
|
||||||
|
readTime: '5 min',
|
||||||
|
author: 'ArcticNewOne Team'
|
||||||
|
},
|
||||||
|
'forma-digital-launch': {
|
||||||
|
id: 'forma-digital-launch',
|
||||||
|
title: 'Forma Digital Platform Launch',
|
||||||
|
image: 'https://picsum.photos/id/201/1200/800',
|
||||||
|
category: 'Projects',
|
||||||
|
badge: 'bg-blue-100 text-blue-700',
|
||||||
|
date: 'May 15, 2026',
|
||||||
|
readTime: '3 min',
|
||||||
|
author: 'ArcticNewOne Team'
|
||||||
|
},
|
||||||
|
'studio-expansion': {
|
||||||
|
id: 'studio-expansion',
|
||||||
|
title: 'Studio Expansion Announcement',
|
||||||
|
image: 'https://picsum.photos/id/164/1200/800',
|
||||||
|
category: 'Announcements',
|
||||||
|
badge: 'bg-green-100 text-green-700',
|
||||||
|
date: 'May 10, 2026',
|
||||||
|
readTime: '2 min',
|
||||||
|
author: 'ArcticNewOne Team'
|
||||||
|
},
|
||||||
|
'ux-research-methods': {
|
||||||
|
id: 'ux-research-methods',
|
||||||
|
title: 'Modern UX Research Methods',
|
||||||
|
image: 'https://picsum.photos/id/180/1200/800',
|
||||||
|
category: 'Insights',
|
||||||
|
badge: 'bg-purple-100 text-purple-700',
|
||||||
|
date: 'Apr 28, 2026',
|
||||||
|
readTime: '7 min',
|
||||||
|
author: 'ArcticNewOne Team'
|
||||||
|
},
|
||||||
|
'bold-moves-case-study': {
|
||||||
|
id: 'bold-moves-case-study',
|
||||||
|
title: 'Bold Moves: A Case Study',
|
||||||
|
image: 'https://picsum.photos/id/119/1200/800',
|
||||||
|
category: 'Projects',
|
||||||
|
badge: 'bg-blue-100 text-blue-700',
|
||||||
|
date: 'Apr 20, 2026',
|
||||||
|
readTime: '6 min',
|
||||||
|
author: 'ArcticNewOne Team'
|
||||||
|
},
|
||||||
|
'new-tools-integration': {
|
||||||
|
id: 'new-tools-integration',
|
||||||
|
title: 'New Tools Added to Our Platform',
|
||||||
|
image: 'https://picsum.photos/id/326/1200/800',
|
||||||
|
category: 'Announcements',
|
||||||
|
badge: 'bg-green-100 text-green-700',
|
||||||
|
date: 'Apr 12, 2026',
|
||||||
|
readTime: '4 min',
|
||||||
|
author: 'ArcticNewOne Team'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const article = newsData[slug]
|
||||||
|
|
||||||
|
if (!article) {
|
||||||
|
throw createError({ statusCode: 404, statusMessage: 'Article not found' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedArticles = computed(() => {
|
||||||
|
return Object.values(newsData)
|
||||||
|
.filter(a => a.id !== slug)
|
||||||
|
.slice(0, 3)
|
||||||
|
})
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
title: () => `${article.title} - ${t('news.title')}`,
|
||||||
|
description: () => article.title,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
Executable → Regular
+19
-82
@@ -3,7 +3,6 @@
|
|||||||
<div
|
<div
|
||||||
ref="headerWrapRef"
|
ref="headerWrapRef"
|
||||||
class="flex flex-col items-center justify-center text-center mb-10 md:mb-16"
|
class="flex flex-col items-center justify-center text-center mb-10 md:mb-16"
|
||||||
style="opacity: 0; visibility: hidden;"
|
|
||||||
>
|
>
|
||||||
<h1 ref="titleRef" class="text-3xl md:text-5xl font-bold mb-4 md:mb-6 tracking-tight text-black">{{ t('news.title') }}</h1>
|
<h1 ref="titleRef" class="text-3xl md:text-5xl font-bold mb-4 md:mb-6 tracking-tight text-black">{{ t('news.title') }}</h1>
|
||||||
<p ref="descRef" class="text-base md:text-lg text-gray-600 max-w-2xl">{{ t('news.description') }}</p>
|
<p ref="descRef" class="text-base md:text-lg text-gray-600 max-w-2xl">{{ t('news.description') }}</p>
|
||||||
@@ -12,7 +11,6 @@
|
|||||||
<div
|
<div
|
||||||
ref="filterWrapRef"
|
ref="filterWrapRef"
|
||||||
class="flex justify-center gap-3 md:gap-4 mb-10 md:mb-14 flex-wrap"
|
class="flex justify-center gap-3 md:gap-4 mb-10 md:mb-14 flex-wrap"
|
||||||
style="opacity: 0; visibility: hidden;"
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-for="category in categories"
|
v-for="category in categories"
|
||||||
@@ -30,11 +28,11 @@
|
|||||||
<div
|
<div
|
||||||
ref="articlesWrapRef"
|
ref="articlesWrapRef"
|
||||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8"
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8"
|
||||||
style="opacity: 0; visibility: hidden;"
|
|
||||||
>
|
>
|
||||||
<article
|
<NuxtLink
|
||||||
v-for="article in filteredNewsData"
|
v-for="article in filteredNewsData"
|
||||||
:key="article.id"
|
:key="article.id"
|
||||||
|
:to="`/news/${article.id}`"
|
||||||
class="news-card group relative flex flex-col rounded-2xl md:rounded-3xl overflow-hidden bg-white border border-gray-100 hover:shadow-xl transition-all duration-500 cursor-pointer hover:-translate-y-2"
|
class="news-card group relative flex flex-col rounded-2xl md:rounded-3xl overflow-hidden bg-white border border-gray-100 hover:shadow-xl transition-all duration-500 cursor-pointer hover:-translate-y-2"
|
||||||
>
|
>
|
||||||
<div class="relative aspect-[16/10] overflow-hidden bg-gray-100">
|
<div class="relative aspect-[16/10] overflow-hidden bg-gray-100">
|
||||||
@@ -82,13 +80,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { nextTick, onBeforeUnmount, onMounted, ref, computed } from 'vue'
|
import { nextTick, onMounted, ref, computed } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useSeoMeta } from '#imports'
|
import { useSeoMeta } from '#imports'
|
||||||
import gsap from 'gsap'
|
import gsap from 'gsap'
|
||||||
@@ -103,11 +101,9 @@ const descRef = ref<HTMLElement | null>(null)
|
|||||||
const filterWrapRef = ref<HTMLElement | null>(null)
|
const filterWrapRef = ref<HTMLElement | null>(null)
|
||||||
const articlesWrapRef = ref<HTMLElement | null>(null)
|
const articlesWrapRef = ref<HTMLElement | null>(null)
|
||||||
const activeCategory = ref('all')
|
const activeCategory = ref('all')
|
||||||
let articlesCtx: gsap.Context | null = null
|
|
||||||
|
|
||||||
const categories = ['all', 'insights', 'projects', 'announcements']
|
const categories = ['all', 'insights', 'projects', 'announcements']
|
||||||
|
|
||||||
// 计算属性:根据选中的分类过滤文章
|
|
||||||
const filteredNewsData = computed(() => {
|
const filteredNewsData = computed(() => {
|
||||||
if (activeCategory.value === 'all') {
|
if (activeCategory.value === 'all') {
|
||||||
return newsData
|
return newsData
|
||||||
@@ -124,74 +120,24 @@ const playPageIntro = async () => {
|
|||||||
await nextTick()
|
await nextTick()
|
||||||
if (!headerWrapRef.value || !titleRef.value || !descRef.value || !filterWrapRef.value || !articlesWrapRef.value) return
|
if (!headerWrapRef.value || !titleRef.value || !descRef.value || !filterWrapRef.value || !articlesWrapRef.value) return
|
||||||
|
|
||||||
articlesCtx?.revert()
|
|
||||||
|
|
||||||
articlesCtx = gsap.context(() => {
|
|
||||||
const filterButtons = gsap.utils.toArray<HTMLElement>('button', filterWrapRef.value!)
|
|
||||||
const newsCards = gsap.utils.toArray<HTMLElement>('.news-card', articlesWrapRef.value!)
|
|
||||||
|
|
||||||
gsap.delayedCall(0, () => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
const tl = gsap.timeline({ defaults: { ease: 'power3.out' } })
|
const tl = gsap.timeline({ defaults: { ease: 'power3.out' } })
|
||||||
|
|
||||||
tl.set(headerWrapRef.value!, { autoAlpha: 1 })
|
tl.fromTo(titleRef.value, { autoAlpha: 0, y: 20 }, { autoAlpha: 1, y: 0, duration: 0.85, ease: 'power4.out', clearProps: 'transform' })
|
||||||
tl.fromTo(titleRef.value!, { autoAlpha: 0, y: 20 }, { autoAlpha: 1, y: 0, duration: 0.85, ease: 'power4.out', clearProps: 'transform' })
|
tl.fromTo(descRef.value, { autoAlpha: 0, y: 16 }, { autoAlpha: 1, y: 0, duration: 0.7, ease: 'power4.out', clearProps: 'transform' }, '-=0.45')
|
||||||
tl.fromTo(descRef.value!, { autoAlpha: 0, y: 16 }, { autoAlpha: 1, y: 0, duration: 0.7, ease: 'power4.out', clearProps: 'transform' }, '-=0.45')
|
|
||||||
|
|
||||||
tl.set(filterWrapRef.value!, { autoAlpha: 1 }, '-=0.2')
|
const filterButtons = gsap.utils.toArray<HTMLElement>('button', filterWrapRef.value!)
|
||||||
tl.fromTo(
|
tl.fromTo(filterButtons, { autoAlpha: 0, y: 20 }, { autoAlpha: 1, y: 0, duration: 0.7, stagger: 0.08, clearProps: 'transform' }, '-=0.3')
|
||||||
filterButtons,
|
|
||||||
{ autoAlpha: 0, y: 20 },
|
|
||||||
{
|
|
||||||
autoAlpha: 1,
|
|
||||||
y: 0,
|
|
||||||
duration: 0.7,
|
|
||||||
ease: 'power4.out',
|
|
||||||
stagger: { each: 0.08, from: 'start' },
|
|
||||||
clearProps: 'transform',
|
|
||||||
},
|
|
||||||
'-=0.3'
|
|
||||||
)
|
|
||||||
|
|
||||||
tl.set(articlesWrapRef.value!, { autoAlpha: 1 }, '-=0.05')
|
const newsCards = gsap.utils.toArray<HTMLElement>('.news-card', articlesWrapRef.value!)
|
||||||
tl.fromTo(
|
tl.fromTo(newsCards, { autoAlpha: 0, y: 34, scale: 0.965 }, { autoAlpha: 1, y: 0, scale: 1, duration: 0.95, stagger: 0.11, clearProps: 'transform' }, '+=0.08')
|
||||||
newsCards,
|
|
||||||
{ autoAlpha: 0, y: 34, scale: 0.965 },
|
|
||||||
{
|
|
||||||
autoAlpha: 1,
|
|
||||||
y: 0,
|
|
||||||
scale: 1,
|
|
||||||
duration: 0.95,
|
|
||||||
ease: 'power4.out',
|
|
||||||
stagger: { each: 0.11, from: 'start' },
|
|
||||||
clearProps: 'transform',
|
|
||||||
},
|
|
||||||
'+=0.08'
|
|
||||||
)
|
|
||||||
|
|
||||||
tl.set([headerWrapRef.value!, filterWrapRef.value!, articlesWrapRef.value!], { clearProps: 'opacity,visibility' })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}, headerWrapRef.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const handleLoadingDone = () => {
|
|
||||||
playPageIntro()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!appStore.isAppLoading) {
|
if (!appStore.isAppLoading) {
|
||||||
playPageIntro()
|
playPageIntro()
|
||||||
return
|
} else {
|
||||||
|
window.addEventListener('app-loading-done', playPageIntro, { once: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('app-loading-done', handleLoadingDone, { once: true })
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
articlesCtx?.revert()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
interface NewsItem {
|
interface NewsItem {
|
||||||
@@ -203,7 +149,6 @@ interface NewsItem {
|
|||||||
badge: string
|
badge: string
|
||||||
date: string
|
date: string
|
||||||
readTime: string
|
readTime: string
|
||||||
url: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const newsData: NewsItem[] = [
|
const newsData: NewsItem[] = [
|
||||||
@@ -215,8 +160,7 @@ const newsData: NewsItem[] = [
|
|||||||
category: 'Insights',
|
category: 'Insights',
|
||||||
badge: 'bg-purple-100 text-purple-700',
|
badge: 'bg-purple-100 text-purple-700',
|
||||||
date: 'May 28, 2026',
|
date: 'May 28, 2026',
|
||||||
readTime: '5 min',
|
readTime: '5 min'
|
||||||
url: '#'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'forma-digital-launch',
|
id: 'forma-digital-launch',
|
||||||
@@ -226,8 +170,7 @@ const newsData: NewsItem[] = [
|
|||||||
category: 'Projects',
|
category: 'Projects',
|
||||||
badge: 'bg-blue-100 text-blue-700',
|
badge: 'bg-blue-100 text-blue-700',
|
||||||
date: 'May 15, 2026',
|
date: 'May 15, 2026',
|
||||||
readTime: '3 min',
|
readTime: '3 min'
|
||||||
url: '#'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'studio-expansion',
|
id: 'studio-expansion',
|
||||||
@@ -237,8 +180,7 @@ const newsData: NewsItem[] = [
|
|||||||
category: 'Announcements',
|
category: 'Announcements',
|
||||||
badge: 'bg-green-100 text-green-700',
|
badge: 'bg-green-100 text-green-700',
|
||||||
date: 'May 10, 2026',
|
date: 'May 10, 2026',
|
||||||
readTime: '2 min',
|
readTime: '2 min'
|
||||||
url: '#'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'ux-research-methods',
|
id: 'ux-research-methods',
|
||||||
@@ -248,8 +190,7 @@ const newsData: NewsItem[] = [
|
|||||||
category: 'Insights',
|
category: 'Insights',
|
||||||
badge: 'bg-purple-100 text-purple-700',
|
badge: 'bg-purple-100 text-purple-700',
|
||||||
date: 'Apr 28, 2026',
|
date: 'Apr 28, 2026',
|
||||||
readTime: '7 min',
|
readTime: '7 min'
|
||||||
url: '#'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'bold-moves-case-study',
|
id: 'bold-moves-case-study',
|
||||||
@@ -259,8 +200,7 @@ const newsData: NewsItem[] = [
|
|||||||
category: 'Projects',
|
category: 'Projects',
|
||||||
badge: 'bg-blue-100 text-blue-700',
|
badge: 'bg-blue-100 text-blue-700',
|
||||||
date: 'Apr 20, 2026',
|
date: 'Apr 20, 2026',
|
||||||
readTime: '6 min',
|
readTime: '6 min'
|
||||||
url: '#'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'new-tools-integration',
|
id: 'new-tools-integration',
|
||||||
@@ -270,14 +210,11 @@ const newsData: NewsItem[] = [
|
|||||||
category: 'Announcements',
|
category: 'Announcements',
|
||||||
badge: 'bg-green-100 text-green-700',
|
badge: 'bg-green-100 text-green-700',
|
||||||
date: 'Apr 12, 2026',
|
date: 'Apr 12, 2026',
|
||||||
readTime: '4 min',
|
readTime: '4 min'
|
||||||
url: '#'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
p {
|
p { word-break: break-word; }
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
<template>
|
||||||
|
<main class="min-h-screen">
|
||||||
|
<!-- 返回按钮 -->
|
||||||
|
<div class="fixed top-28 left-4 md:left-8 z-30">
|
||||||
|
<NuxtLink
|
||||||
|
to="/work"
|
||||||
|
class="inline-flex items-center gap-2 px-4 py-2.5 rounded-full bg-white/90 backdrop-blur-sm shadow-lg hover:shadow-xl transition-all duration-300 text-sm font-semibold text-black hover:-translate-x-1"
|
||||||
|
>
|
||||||
|
<Icon name="ph:arrow-left" class="w-5 h-5" />
|
||||||
|
{{ t('work.backToList') }}
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Hero 大图 -->
|
||||||
|
<section class="relative h-[60vh] md:h-[70vh] overflow-hidden">
|
||||||
|
<img
|
||||||
|
:src="project.image"
|
||||||
|
:alt="project.title"
|
||||||
|
class="w-full h-full object-cover"
|
||||||
|
/>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/40 to-transparent"></div>
|
||||||
|
<div class="absolute bottom-0 left-0 right-0 p-8 md:p-16">
|
||||||
|
<div class="max-w-[1200px] mx-auto">
|
||||||
|
<div class="flex flex-wrap gap-2 mb-4">
|
||||||
|
<span
|
||||||
|
v-for="tag in project.tags"
|
||||||
|
:key="tag"
|
||||||
|
class="px-3 py-1 text-xs md:text-sm bg-white/20 backdrop-blur-sm text-white rounded-full"
|
||||||
|
>
|
||||||
|
{{ tag }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-4xl md:text-6xl lg:text-7xl font-bold text-white mb-4 tracking-tight">
|
||||||
|
{{ project.title }}
|
||||||
|
</h1>
|
||||||
|
<p class="text-lg md:text-xl text-white/80 max-w-2xl">
|
||||||
|
{{ project.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 项目信息 -->
|
||||||
|
<section class="max-w-[1200px] mx-auto px-6 md:px-10 py-16 md:py-24">
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-12 lg:gap-16">
|
||||||
|
<!-- 左侧:项目详情 -->
|
||||||
|
<div class="lg:col-span-2 space-y-12">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-6">{{ t('work.detail.overview') }}</h2>
|
||||||
|
<p class="text-gray-700 text-base md:text-lg leading-relaxed">
|
||||||
|
{{ t(`work.detail.items.${slug}.overview`) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-6">{{ t('work.detail.challenge') }}</h2>
|
||||||
|
<p class="text-gray-700 text-base md:text-lg leading-relaxed">
|
||||||
|
{{ t(`work.detail.items.${slug}.challenge`) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-6">{{ t('work.detail.solution') }}</h2>
|
||||||
|
<p class="text-gray-700 text-base md:text-lg leading-relaxed">
|
||||||
|
{{ t(`work.detail.items.${slug}.solution`) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 项目截图 -->
|
||||||
|
<div class="space-y-6">
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black">{{ t('work.detail.gallery') }}</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div
|
||||||
|
v-for="(img, index) in project.gallery"
|
||||||
|
:key="index"
|
||||||
|
class="rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-shadow duration-300"
|
||||||
|
>
|
||||||
|
<img :src="img" :alt="`${project.title} screenshot ${index + 1}`" class="w-full h-auto" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧:项目信息卡片 -->
|
||||||
|
<div class="space-y-8">
|
||||||
|
<div class="bg-gray-50 rounded-2xl p-6 md:p-8 sticky top-32">
|
||||||
|
<h3 class="text-lg font-bold text-black mb-6">{{ t('work.detail.projectInfo') }}</h3>
|
||||||
|
|
||||||
|
<div class="space-y-5">
|
||||||
|
<div>
|
||||||
|
<p class="text-sm text-gray-500 mb-1">{{ t('work.detail.client') }}</p>
|
||||||
|
<p class="text-base font-semibold text-black">{{ t(`work.detail.items.${slug}.client`) }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm text-gray-500 mb-1">{{ t('work.detail.year') }}</p>
|
||||||
|
<p class="text-base font-semibold text-black">{{ project.year }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm text-gray-500 mb-1">{{ t('work.detail.duration') }}</p>
|
||||||
|
<p class="text-base font-semibold text-black">{{ t(`work.detail.items.${slug}.duration`) }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="text-sm text-gray-500 mb-1">{{ t('work.detail.services') }}</p>
|
||||||
|
<div class="flex flex-wrap gap-2 mt-2">
|
||||||
|
<span
|
||||||
|
v-for="tag in project.tags"
|
||||||
|
:key="tag"
|
||||||
|
class="px-3 py-1 text-xs bg-black text-white rounded-full"
|
||||||
|
>
|
||||||
|
{{ tag }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 访问项目按钮 -->
|
||||||
|
<a
|
||||||
|
v-if="project.url"
|
||||||
|
:href="project.url"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="mt-8 w-full inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-full bg-black text-white font-semibold hover:bg-gray-800 transition-colors duration-300"
|
||||||
|
>
|
||||||
|
{{ t('work.detail.visitProject') }}
|
||||||
|
<Icon name="ph:arrow-up-right" class="w-5 h-5" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 相关项目 -->
|
||||||
|
<section class="bg-gray-50 py-16 md:py-24">
|
||||||
|
<div class="max-w-[1200px] mx-auto px-6 md:px-10">
|
||||||
|
<h2 class="text-2xl md:text-3xl font-bold text-black mb-10 text-center">{{ t('work.detail.relatedProjects') }}</h2>
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
|
<NuxtLink
|
||||||
|
v-for="related in relatedProjects"
|
||||||
|
:key="related.id"
|
||||||
|
:to="`/work/${related.id}`"
|
||||||
|
class="group block rounded-2xl overflow-hidden bg-white shadow-lg hover:shadow-xl transition-all duration-300 hover:-translate-y-1"
|
||||||
|
>
|
||||||
|
<div class="relative aspect-[4/3] overflow-hidden">
|
||||||
|
<img :src="related.image" :alt="related.title" class="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105" />
|
||||||
|
</div>
|
||||||
|
<div class="p-5">
|
||||||
|
<h3 class="text-lg font-bold text-black group-hover:text-gray-600 transition-colors">{{ related.title }}</h3>
|
||||||
|
<p class="text-sm text-gray-500 mt-1">{{ related.tags[0] }}</p>
|
||||||
|
</div>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { useSeoMeta, createError } from '#imports'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const route = useRoute()
|
||||||
|
const slug = route.params.slug as string
|
||||||
|
|
||||||
|
interface WorkItem {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
image: string
|
||||||
|
tags: string[]
|
||||||
|
category: string
|
||||||
|
year: string
|
||||||
|
url?: string
|
||||||
|
gallery: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const workData: Record<string, WorkItem> = {
|
||||||
|
'forma-digital': {
|
||||||
|
id: 'forma-digital',
|
||||||
|
title: 'Forma Digital',
|
||||||
|
description: 'A modern e-commerce platform with seamless user experience and dynamic product showcases.',
|
||||||
|
image: 'https://picsum.photos/id/201/1200/800',
|
||||||
|
tags: ['Web Design', 'E-commerce', 'React'],
|
||||||
|
category: 'webDesign',
|
||||||
|
year: '2026',
|
||||||
|
url: '#',
|
||||||
|
gallery: [
|
||||||
|
'https://picsum.photos/id/201/800/600',
|
||||||
|
'https://picsum.photos/id/202/800/600',
|
||||||
|
'https://picsum.photos/id/203/800/600',
|
||||||
|
'https://picsum.photos/id/204/800/600',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'one-step': {
|
||||||
|
id: 'one-step',
|
||||||
|
title: 'One Step',
|
||||||
|
description: 'Brand identity and marketing campaign for a fitness app focused on sustainable habits.',
|
||||||
|
image: 'https://picsum.photos/id/180/1200/800',
|
||||||
|
tags: ['Branding', 'Marketing', 'UI/UX'],
|
||||||
|
category: 'branding',
|
||||||
|
year: '2024',
|
||||||
|
gallery: [
|
||||||
|
'https://picsum.photos/id/180/800/600',
|
||||||
|
'https://picsum.photos/id/181/800/600',
|
||||||
|
'https://picsum.photos/id/182/800/600',
|
||||||
|
'https://picsum.photos/id/183/800/600',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'nero-vision': {
|
||||||
|
id: 'nero-vision',
|
||||||
|
title: 'Nero Vision',
|
||||||
|
description: 'Full-stack web application for creative professionals to manage their portfolios.',
|
||||||
|
image: 'https://picsum.photos/id/119/1200/800',
|
||||||
|
tags: ['Development', 'Vue.js', 'Node.js'],
|
||||||
|
category: 'development',
|
||||||
|
year: '2025',
|
||||||
|
gallery: [
|
||||||
|
'https://picsum.photos/id/119/800/600',
|
||||||
|
'https://picsum.photos/id/120/800/600',
|
||||||
|
'https://picsum.photos/id/121/800/600',
|
||||||
|
'https://picsum.photos/id/122/800/600',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'bold-moves': {
|
||||||
|
id: 'bold-moves',
|
||||||
|
title: 'Bold Moves',
|
||||||
|
description: 'Interactive website showcasing innovative architectural designs with 3D visualizations.',
|
||||||
|
image: 'https://picsum.photos/id/164/1200/800',
|
||||||
|
tags: ['Web Design', '3D', 'Three.js'],
|
||||||
|
category: 'webDesign',
|
||||||
|
year: '2024',
|
||||||
|
gallery: [
|
||||||
|
'https://picsum.photos/id/164/800/600',
|
||||||
|
'https://picsum.photos/id/165/800/600',
|
||||||
|
'https://picsum.photos/id/166/800/600',
|
||||||
|
'https://picsum.photos/id/167/800/600',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'echo-labs': {
|
||||||
|
id: 'echo-labs',
|
||||||
|
title: 'Echo Labs',
|
||||||
|
description: 'Corporate branding and visual identity for a tech startup in the AI space.',
|
||||||
|
image: 'https://picsum.photos/id/101/1200/800',
|
||||||
|
tags: ['Branding', 'Visual Identity', 'Corporate'],
|
||||||
|
category: 'branding',
|
||||||
|
year: '2025',
|
||||||
|
gallery: [
|
||||||
|
'https://picsum.photos/id/101/800/600',
|
||||||
|
'https://picsum.photos/id/102/800/600',
|
||||||
|
'https://picsum.photos/id/103/800/600',
|
||||||
|
'https://picsum.photos/id/104/800/600',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'flux-api': {
|
||||||
|
id: 'flux-api',
|
||||||
|
title: 'Flux API',
|
||||||
|
description: 'Scalable REST API with comprehensive documentation and developer tools.',
|
||||||
|
image: 'https://picsum.photos/id/326/1200/800',
|
||||||
|
tags: ['Development', 'API', 'Python'],
|
||||||
|
category: 'development',
|
||||||
|
year: '2025',
|
||||||
|
gallery: [
|
||||||
|
'https://picsum.photos/id/326/800/600',
|
||||||
|
'https://picsum.photos/id/327/800/600',
|
||||||
|
'https://picsum.photos/id/328/800/600',
|
||||||
|
'https://picsum.photos/id/329/800/600',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const project = workData[slug]
|
||||||
|
|
||||||
|
if (!project) {
|
||||||
|
throw createError({ statusCode: 404, statusMessage: 'Project not found' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedProjects = computed(() => {
|
||||||
|
return Object.values(workData)
|
||||||
|
.filter(p => p.id !== slug)
|
||||||
|
.slice(0, 3)
|
||||||
|
})
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
title: () => `${project.title} - ${t('work.title')}`,
|
||||||
|
description: () => project.description,
|
||||||
|
})
|
||||||
|
</script>
|
||||||
Executable → Regular
+13
-77
@@ -3,7 +3,6 @@
|
|||||||
<div
|
<div
|
||||||
ref="headerWrapRef"
|
ref="headerWrapRef"
|
||||||
class="flex flex-col items-center justify-center text-center mb-10 md:mb-16"
|
class="flex flex-col items-center justify-center text-center mb-10 md:mb-16"
|
||||||
style="opacity: 0; visibility: hidden;"
|
|
||||||
>
|
>
|
||||||
<h1 ref="titleRef" class="text-3xl md:text-5xl font-bold mb-4 md:mb-6 tracking-tight text-black">{{ t('work.title') }}</h1>
|
<h1 ref="titleRef" class="text-3xl md:text-5xl font-bold mb-4 md:mb-6 tracking-tight text-black">{{ t('work.title') }}</h1>
|
||||||
<p ref="descRef" class="text-base md:text-lg text-gray-600 max-w-2xl">{{ t('work.description') }}</p>
|
<p ref="descRef" class="text-base md:text-lg text-gray-600 max-w-2xl">{{ t('work.description') }}</p>
|
||||||
@@ -12,7 +11,6 @@
|
|||||||
<div
|
<div
|
||||||
ref="filterWrapRef"
|
ref="filterWrapRef"
|
||||||
class="flex justify-center gap-3 md:gap-4 mb-10 md:mb-14 flex-wrap"
|
class="flex justify-center gap-3 md:gap-4 mb-10 md:mb-14 flex-wrap"
|
||||||
style="opacity: 0; visibility: hidden;"
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-for="category in categories"
|
v-for="category in categories"
|
||||||
@@ -30,12 +28,11 @@
|
|||||||
<div
|
<div
|
||||||
ref="projectsWrapRef"
|
ref="projectsWrapRef"
|
||||||
class="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8"
|
class="grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-8"
|
||||||
style="opacity: 0; visibility: hidden;"
|
|
||||||
>
|
>
|
||||||
<a
|
<NuxtLink
|
||||||
v-for="project in filteredWorkData"
|
v-for="project in filteredWorkData"
|
||||||
:key="project.id"
|
:key="project.id"
|
||||||
:href="project.url"
|
:to="`/work/${project.id}`"
|
||||||
class="work-card group relative block rounded-2xl md:rounded-3xl overflow-hidden cursor-pointer hover:shadow-2xl transition-all duration-500"
|
class="work-card group relative block rounded-2xl md:rounded-3xl overflow-hidden cursor-pointer hover:shadow-2xl transition-all duration-500"
|
||||||
>
|
>
|
||||||
<div class="relative aspect-[4/3] overflow-hidden bg-gray-100">
|
<div class="relative aspect-[4/3] overflow-hidden bg-gray-100">
|
||||||
@@ -65,13 +62,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { nextTick, onBeforeUnmount, onMounted, ref, computed } from 'vue'
|
import { nextTick, onMounted, ref, computed } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useSeoMeta } from '#imports'
|
import { useSeoMeta } from '#imports'
|
||||||
import gsap from 'gsap'
|
import gsap from 'gsap'
|
||||||
@@ -86,11 +83,9 @@ const descRef = ref<HTMLElement | null>(null)
|
|||||||
const filterWrapRef = ref<HTMLElement | null>(null)
|
const filterWrapRef = ref<HTMLElement | null>(null)
|
||||||
const projectsWrapRef = ref<HTMLElement | null>(null)
|
const projectsWrapRef = ref<HTMLElement | null>(null)
|
||||||
const activeCategory = ref('all')
|
const activeCategory = ref('all')
|
||||||
let projectsCtx: gsap.Context | null = null
|
|
||||||
|
|
||||||
const categories = ['all', 'webDesign', 'branding', 'development']
|
const categories = ['all', 'webDesign', 'branding', 'development']
|
||||||
|
|
||||||
// 计算属性:根据选中的分类过滤项目
|
|
||||||
const filteredWorkData = computed(() => {
|
const filteredWorkData = computed(() => {
|
||||||
if (activeCategory.value === 'all') {
|
if (activeCategory.value === 'all') {
|
||||||
return workData
|
return workData
|
||||||
@@ -107,74 +102,24 @@ const playPageIntro = async () => {
|
|||||||
await nextTick()
|
await nextTick()
|
||||||
if (!headerWrapRef.value || !titleRef.value || !descRef.value || !filterWrapRef.value || !projectsWrapRef.value) return
|
if (!headerWrapRef.value || !titleRef.value || !descRef.value || !filterWrapRef.value || !projectsWrapRef.value) return
|
||||||
|
|
||||||
projectsCtx?.revert()
|
|
||||||
|
|
||||||
projectsCtx = gsap.context(() => {
|
|
||||||
const filterButtons = gsap.utils.toArray<HTMLElement>('button', filterWrapRef.value!)
|
|
||||||
const projectCards = gsap.utils.toArray<HTMLElement>('.work-card', projectsWrapRef.value!)
|
|
||||||
|
|
||||||
gsap.delayedCall(0, () => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
const tl = gsap.timeline({ defaults: { ease: 'power3.out' } })
|
const tl = gsap.timeline({ defaults: { ease: 'power3.out' } })
|
||||||
|
|
||||||
tl.set(headerWrapRef.value!, { autoAlpha: 1 })
|
tl.fromTo(titleRef.value, { autoAlpha: 0, y: 20 }, { autoAlpha: 1, y: 0, duration: 0.85, ease: 'power4.out', clearProps: 'transform' })
|
||||||
tl.fromTo(titleRef.value!, { autoAlpha: 0, y: 20 }, { autoAlpha: 1, y: 0, duration: 0.85, ease: 'power4.out', clearProps: 'transform' })
|
tl.fromTo(descRef.value, { autoAlpha: 0, y: 16 }, { autoAlpha: 1, y: 0, duration: 0.7, ease: 'power4.out', clearProps: 'transform' }, '-=0.45')
|
||||||
tl.fromTo(descRef.value!, { autoAlpha: 0, y: 16 }, { autoAlpha: 1, y: 0, duration: 0.7, ease: 'power4.out', clearProps: 'transform' }, '-=0.45')
|
|
||||||
|
|
||||||
tl.set(filterWrapRef.value!, { autoAlpha: 1 }, '-=0.2')
|
const filterButtons = gsap.utils.toArray<HTMLElement>('button', filterWrapRef.value!)
|
||||||
tl.fromTo(
|
tl.fromTo(filterButtons, { autoAlpha: 0, y: 20 }, { autoAlpha: 1, y: 0, duration: 0.7, stagger: 0.08, clearProps: 'transform' }, '-=0.3')
|
||||||
filterButtons,
|
|
||||||
{ autoAlpha: 0, y: 20 },
|
|
||||||
{
|
|
||||||
autoAlpha: 1,
|
|
||||||
y: 0,
|
|
||||||
duration: 0.7,
|
|
||||||
ease: 'power4.out',
|
|
||||||
stagger: { each: 0.08, from: 'start' },
|
|
||||||
clearProps: 'transform',
|
|
||||||
},
|
|
||||||
'-=0.3'
|
|
||||||
)
|
|
||||||
|
|
||||||
tl.set(projectsWrapRef.value!, { autoAlpha: 1 }, '-=0.05')
|
const projectCards = gsap.utils.toArray<HTMLElement>('.work-card', projectsWrapRef.value!)
|
||||||
tl.fromTo(
|
tl.fromTo(projectCards, { autoAlpha: 0, y: 34, scale: 0.965 }, { autoAlpha: 1, y: 0, scale: 1, duration: 0.95, stagger: 0.13, clearProps: 'transform' }, '+=0.08')
|
||||||
projectCards,
|
|
||||||
{ autoAlpha: 0, y: 34, scale: 0.965 },
|
|
||||||
{
|
|
||||||
autoAlpha: 1,
|
|
||||||
y: 0,
|
|
||||||
scale: 1,
|
|
||||||
duration: 0.95,
|
|
||||||
ease: 'power4.out',
|
|
||||||
stagger: { each: 0.13, from: 'start' },
|
|
||||||
clearProps: 'transform',
|
|
||||||
},
|
|
||||||
'+=0.08'
|
|
||||||
)
|
|
||||||
|
|
||||||
tl.set([headerWrapRef.value!, filterWrapRef.value!, projectsWrapRef.value!], { clearProps: 'opacity,visibility' })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}, headerWrapRef.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const handleLoadingDone = () => {
|
|
||||||
playPageIntro()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!appStore.isAppLoading) {
|
if (!appStore.isAppLoading) {
|
||||||
playPageIntro()
|
playPageIntro()
|
||||||
return
|
} else {
|
||||||
|
window.addEventListener('app-loading-done', playPageIntro, { once: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('app-loading-done', handleLoadingDone, { once: true })
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
projectsCtx?.revert()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
interface WorkItem {
|
interface WorkItem {
|
||||||
@@ -182,7 +127,6 @@ interface WorkItem {
|
|||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
image: string
|
image: string
|
||||||
url: string
|
|
||||||
tags: string[]
|
tags: string[]
|
||||||
category: string
|
category: string
|
||||||
}
|
}
|
||||||
@@ -193,7 +137,6 @@ const workData: WorkItem[] = [
|
|||||||
title: 'Forma Digital',
|
title: 'Forma Digital',
|
||||||
description: 'A modern e-commerce platform with seamless user experience and dynamic product showcases.',
|
description: 'A modern e-commerce platform with seamless user experience and dynamic product showcases.',
|
||||||
image: 'https://picsum.photos/id/201/800/600',
|
image: 'https://picsum.photos/id/201/800/600',
|
||||||
url: '#',
|
|
||||||
tags: ['Web Design', 'E-commerce', 'React'],
|
tags: ['Web Design', 'E-commerce', 'React'],
|
||||||
category: 'webDesign'
|
category: 'webDesign'
|
||||||
},
|
},
|
||||||
@@ -202,7 +145,6 @@ const workData: WorkItem[] = [
|
|||||||
title: 'One Step',
|
title: 'One Step',
|
||||||
description: 'Brand identity and marketing campaign for a fitness app focused on sustainable habits.',
|
description: 'Brand identity and marketing campaign for a fitness app focused on sustainable habits.',
|
||||||
image: 'https://picsum.photos/id/180/800/600',
|
image: 'https://picsum.photos/id/180/800/600',
|
||||||
url: '#',
|
|
||||||
tags: ['Branding', 'Marketing', 'UI/UX'],
|
tags: ['Branding', 'Marketing', 'UI/UX'],
|
||||||
category: 'branding'
|
category: 'branding'
|
||||||
},
|
},
|
||||||
@@ -211,7 +153,6 @@ const workData: WorkItem[] = [
|
|||||||
title: 'Nero Vision',
|
title: 'Nero Vision',
|
||||||
description: 'Full-stack web application for creative professionals to manage their portfolios.',
|
description: 'Full-stack web application for creative professionals to manage their portfolios.',
|
||||||
image: 'https://picsum.photos/id/119/800/600',
|
image: 'https://picsum.photos/id/119/800/600',
|
||||||
url: '#',
|
|
||||||
tags: ['Development', 'Vue.js', 'Node.js'],
|
tags: ['Development', 'Vue.js', 'Node.js'],
|
||||||
category: 'development'
|
category: 'development'
|
||||||
},
|
},
|
||||||
@@ -220,7 +161,6 @@ const workData: WorkItem[] = [
|
|||||||
title: 'Bold Moves',
|
title: 'Bold Moves',
|
||||||
description: 'Interactive website showcasing innovative architectural designs with 3D visualizations.',
|
description: 'Interactive website showcasing innovative architectural designs with 3D visualizations.',
|
||||||
image: 'https://picsum.photos/id/164/800/600',
|
image: 'https://picsum.photos/id/164/800/600',
|
||||||
url: '#',
|
|
||||||
tags: ['Web Design', '3D', 'Three.js'],
|
tags: ['Web Design', '3D', 'Three.js'],
|
||||||
category: 'webDesign'
|
category: 'webDesign'
|
||||||
},
|
},
|
||||||
@@ -229,7 +169,6 @@ const workData: WorkItem[] = [
|
|||||||
title: 'Echo Labs',
|
title: 'Echo Labs',
|
||||||
description: 'Corporate branding and visual identity for a tech startup in the AI space.',
|
description: 'Corporate branding and visual identity for a tech startup in the AI space.',
|
||||||
image: 'https://picsum.photos/id/101/800/600',
|
image: 'https://picsum.photos/id/101/800/600',
|
||||||
url: '#',
|
|
||||||
tags: ['Branding', 'Visual Identity', 'Corporate'],
|
tags: ['Branding', 'Visual Identity', 'Corporate'],
|
||||||
category: 'branding'
|
category: 'branding'
|
||||||
},
|
},
|
||||||
@@ -238,7 +177,6 @@ const workData: WorkItem[] = [
|
|||||||
title: 'Flux API',
|
title: 'Flux API',
|
||||||
description: 'Scalable REST API with comprehensive documentation and developer tools.',
|
description: 'Scalable REST API with comprehensive documentation and developer tools.',
|
||||||
image: 'https://picsum.photos/id/326/800/600',
|
image: 'https://picsum.photos/id/326/800/600',
|
||||||
url: '#',
|
|
||||||
tags: ['Development', 'API', 'Python'],
|
tags: ['Development', 'API', 'Python'],
|
||||||
category: 'development'
|
category: 'development'
|
||||||
}
|
}
|
||||||
@@ -246,7 +184,5 @@ const workData: WorkItem[] = [
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
p {
|
p { word-break: break-word; }
|
||||||
word-break: break-word;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
+126
-1
@@ -308,7 +308,65 @@
|
|||||||
"branding": "Branding",
|
"branding": "Branding",
|
||||||
"development": "Development"
|
"development": "Development"
|
||||||
},
|
},
|
||||||
"cta": "View Project"
|
"cta": "View Project",
|
||||||
|
"backToList": "Back to Work",
|
||||||
|
"detail": {
|
||||||
|
"overview": "Overview",
|
||||||
|
"challenge": "Challenge",
|
||||||
|
"solution": "Solution",
|
||||||
|
"gallery": "Gallery",
|
||||||
|
"projectInfo": "Project Info",
|
||||||
|
"client": "Client",
|
||||||
|
"year": "Year",
|
||||||
|
"duration": "Duration",
|
||||||
|
"services": "Services",
|
||||||
|
"visitProject": "Visit Project",
|
||||||
|
"relatedProjects": "Related Projects",
|
||||||
|
"items": {
|
||||||
|
"forma-digital": {
|
||||||
|
"overview": "Forma Digital is a modern e-commerce platform designed to provide a seamless shopping experience. We redesigned the entire user interface with a minimalist design approach, focusing on product showcase and conversion optimization.",
|
||||||
|
"challenge": "The client needed a platform that could both showcase premium products and deliver a smooth shopping experience. The existing website was slow, had poor mobile experience, and low conversion rates.",
|
||||||
|
"solution": "We built the platform with React + Next.js, implementing server-side rendering and static generation for blazing fast load times. The product pages feature immersive large-format imagery with smooth animation transitions.",
|
||||||
|
"client": "Forma Digital Inc.",
|
||||||
|
"duration": "3 months"
|
||||||
|
},
|
||||||
|
"one-step": {
|
||||||
|
"overview": "One Step is a fitness app focused on building healthy habits. We created a complete brand visual identity system including logo design, UI interface, and marketing materials.",
|
||||||
|
"challenge": "In the competitive fitness app market, how to stand out through brand design and establish unique brand recognition.",
|
||||||
|
"solution": "With the core concept of 'one step at a time', we designed a clean and powerful brand identity. Using gradient colors and rounded graphic language to convey health, positivity, and progress.",
|
||||||
|
"client": "One Step Fitness",
|
||||||
|
"duration": "2 months"
|
||||||
|
},
|
||||||
|
"nero-vision": {
|
||||||
|
"overview": "Nero Vision is a portfolio management platform for creative professionals, helping designers and artists showcase and manage their work.",
|
||||||
|
"challenge": "Creative professionals need a platform that can perfectly showcase work while being easy to manage. Existing solutions are either too complex or have poor display quality.",
|
||||||
|
"solution": "We developed a full-stack application with Vue.js + Node.js, designing an intuitive drag-and-drop portfolio management interface with beautiful display templates.",
|
||||||
|
"client": "Nero Studio",
|
||||||
|
"duration": "4 months"
|
||||||
|
},
|
||||||
|
"bold-moves": {
|
||||||
|
"overview": "Bold Moves is an interactive website showcasing innovative architectural designs through 3D visualization technology, letting users experience architecture immersively.",
|
||||||
|
"challenge": "How to present complex architectural designs in an intuitive and engaging way to general users while maintaining professionalism.",
|
||||||
|
"solution": "We used Three.js for high-quality 3D rendering with smooth interactive design, allowing users to appreciate architectural details from any angle, with lighting effects and material displays.",
|
||||||
|
"client": "Bold Moves Architecture",
|
||||||
|
"duration": "5 months"
|
||||||
|
},
|
||||||
|
"echo-labs": {
|
||||||
|
"overview": "Echo Labs is an AI tech startup. We created a complete brand visual identity system and corporate website for them.",
|
||||||
|
"challenge": "AI brands need to convey both technology and humanity, avoiding being too cold or technical.",
|
||||||
|
"solution": "With the concept of 'echo', we designed a dynamic brand identity. Using dark themes with gradient colors for a tech feel, while rounded graphic language adds approachability.",
|
||||||
|
"client": "Echo Labs AI",
|
||||||
|
"duration": "3 months"
|
||||||
|
},
|
||||||
|
"flux-api": {
|
||||||
|
"overview": "Flux API is a scalable REST API service platform with comprehensive documentation and developer tools to help developers integrate quickly.",
|
||||||
|
"challenge": "API documentation and developer experience are core competitive advantages. How to make complex APIs easy to understand and use.",
|
||||||
|
"solution": "We designed interactive API documentation with online testing and code generation. Multi-language SDKs and detailed tutorials significantly reduce the learning curve for developers.",
|
||||||
|
"client": "Flux Technologies",
|
||||||
|
"duration": "6 months"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"studio": {
|
"studio": {
|
||||||
"title": "About Studio",
|
"title": "About Studio",
|
||||||
@@ -360,11 +418,78 @@
|
|||||||
"title": "News & Updates",
|
"title": "News & Updates",
|
||||||
"description": "Stay informed with our latest insights, project updates, and industry trends.",
|
"description": "Stay informed with our latest insights, project updates, and industry trends.",
|
||||||
"readMore": "Read More",
|
"readMore": "Read More",
|
||||||
|
"backToList": "Back to News",
|
||||||
"categories": {
|
"categories": {
|
||||||
"all": "All Posts",
|
"all": "All Posts",
|
||||||
"insights": "Insights",
|
"insights": "Insights",
|
||||||
"projects": "Projects",
|
"projects": "Projects",
|
||||||
"announcements": "Announcements"
|
"announcements": "Announcements"
|
||||||
|
},
|
||||||
|
"detail": {
|
||||||
|
"shareArticle": "Share Article",
|
||||||
|
"relatedArticles": "Related Articles",
|
||||||
|
"items": {
|
||||||
|
"design-trends-2026": {
|
||||||
|
"content": "In 2026, the design industry is undergoing a profound transformation. From the return of minimalism to the rise of bold typography, from the普及 of 3D elements to the maturity of AI-assisted design, these trends are redefining the boundaries of digital experiences.",
|
||||||
|
"section1Title": "The Return of Minimalism",
|
||||||
|
"section1Content": "In an age of information overload, users increasingly渴望 clean, clear interfaces. 2026's minimalism isn't just 'less is more' — it's about delivering more value in limited space through careful information architecture and visual hierarchy.",
|
||||||
|
"quote": "Good design isn't about adding more, it's about removing the unnecessary. In 2026, this matters more than ever.",
|
||||||
|
"section2Title": "Bold Typography & Dynamic Text",
|
||||||
|
"section2Content": "Typography is moving from supporting actor to leading role. Large, high-contrast font designs are becoming important brand expression tools. Dynamic text effects are making typography a living, interactive element rather than static decoration.",
|
||||||
|
"section3Title": "Maturity of AI-Assisted Design",
|
||||||
|
"section3Content": "AI tools are shifting from 'replacing designers' to 'empowering designers.' Smart layout suggestions, automated color schemes, and real-time design feedback let designers focus on creativity and strategy rather than repetitive execution."
|
||||||
|
},
|
||||||
|
"forma-digital-launch": {
|
||||||
|
"content": "After three months of careful crafting, we're excited to announce the official launch of the Forma Digital e-commerce platform! This project is one of our team's most challenging works to date.",
|
||||||
|
"section1Title": "Project Background",
|
||||||
|
"section1Content": "Forma Digital is an e-commerce brand focusing on premium home goods. They needed a platform that could perfectly showcase product quality while delivering a smooth shopping experience.",
|
||||||
|
"quote": "The ArcticNewOne team not only understood our needs but exceeded our expectations. After the new platform launched, our conversion rate increased by 45%.",
|
||||||
|
"section2Title": "Technical Highlights",
|
||||||
|
"section2Content": "We used React + Next.js for server-side rendering and static generation. Through lazy loading, code splitting, and CDN acceleration, we reduced first load time from 4.5s to 1.2s.",
|
||||||
|
"section3Title": "Results",
|
||||||
|
"section3Content": "After launch, user停留 time increased by 60%, bounce rate decreased by 35%, and conversion rate improved by 45%."
|
||||||
|
},
|
||||||
|
"studio-expansion": {
|
||||||
|
"content": "With continued business growth and increasing client demand, we're excited to announce the official expansion of ArcticNewOne Studio!",
|
||||||
|
"section1Title": "Team Growth",
|
||||||
|
"section1Content": "We're adding 5 senior designers and 3 senior developers covering frontend, backend, UI/UX, and more. All new members have extensive industry experience.",
|
||||||
|
"quote": "Talent is our most valuable asset. By expanding our team, we can take on more projects while maintaining consistent high-quality delivery.",
|
||||||
|
"section2Title": "Service Upgrade",
|
||||||
|
"section2Content": "In addition to existing services, we're adding data visualization, AI application development, AR/VR experience design, and other cutting-edge services.",
|
||||||
|
"section3Title": "Looking Ahead",
|
||||||
|
"section3Content": "We plan to complete 50+ projects and serve 30+ new clients in the coming year while continuing to explore new possibilities."
|
||||||
|
},
|
||||||
|
"ux-research-methods": {
|
||||||
|
"content": "UX research is the foundation of design decisions. In 2026, as technology evolves and user behaviors change, UX research methods continue to advance.",
|
||||||
|
"section1Title": "Remote User Testing",
|
||||||
|
"section1Content": "Remote user testing has become mainstream. Through professional platforms, we can recruit test users globally and gather broader feedback in less time.",
|
||||||
|
"quote": "Remote testing not only reduces costs but more importantly lets us access more authentic user scenarios.",
|
||||||
|
"section2Title": "Behavioral Data Analysis",
|
||||||
|
"section2Content": "Through heatmaps, scroll depth, click streams, and other behavioral data, we can objectively understand how users interact with products.",
|
||||||
|
"section3Title": "AI-Assisted Analysis",
|
||||||
|
"section3Content": "AI tools help us analyze user feedback more efficiently. Sentiment analysis, topic clustering, and trend prediction help extract valuable insights from massive data."
|
||||||
|
},
|
||||||
|
"bold-moves-case-study": {
|
||||||
|
"content": "Bold Moves is an interactive website showcasing innovative architectural designs. This article provides an in-depth look at the design思路, technical implementation, and final results.",
|
||||||
|
"section1Title": "Design Philosophy",
|
||||||
|
"section1Content": "Bold Moves wanted to showcase architectural beauty digitally. We decided to use 3D visualization to let users appreciate architectural details from any angle.",
|
||||||
|
"quote": "We didn't just want a showcase website — we wanted a digital space where users could 'walk into' the architecture.",
|
||||||
|
"section2Title": "Technical Challenges",
|
||||||
|
"section2Content": "High-quality 3D rendering requires significant computing power, but web performance is limited. We achieved smooth interactions through model optimization, LOD techniques, and WebGL rendering.",
|
||||||
|
"section3Title": "Final Results",
|
||||||
|
"section3Content": "The project received widespread acclaim and won multiple design awards. Average user停留 time exceeded 5 minutes, well above industry average."
|
||||||
|
},
|
||||||
|
"new-tools-integration": {
|
||||||
|
"content": "To better serve our clients, we continuously expand and improve our toolbox. Recently, we've added several practical tools covering design, development, collaboration, and more.",
|
||||||
|
"section1Title": "Design Tool Upgrades",
|
||||||
|
"section1Content": "We've引入 the latest design collaboration platform supporting real-time multi-person editing, version management, and design system integration.",
|
||||||
|
"quote": "Good tools significantly boost team efficiency. The right toolchain is key to delivering quality work.",
|
||||||
|
"section2Title": "Development Tool Enhancements",
|
||||||
|
"section2Content": "Added automated testing frameworks, performance monitoring tools, and code quality checks to help identify and resolve issues during development.",
|
||||||
|
"section3Title": "Collaboration Tool Optimization",
|
||||||
|
"section3Content": "We upgraded our project management platform with new Kanban views, time tracking, and resource allocation features for better project oversight."
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
|
|||||||
+126
-1
@@ -308,7 +308,65 @@
|
|||||||
"branding": "品牌设计",
|
"branding": "品牌设计",
|
||||||
"development": "程序开发"
|
"development": "程序开发"
|
||||||
},
|
},
|
||||||
"cta": "查看项目"
|
"cta": "查看项目",
|
||||||
|
"backToList": "返回作品列表",
|
||||||
|
"detail": {
|
||||||
|
"overview": "项目概述",
|
||||||
|
"challenge": "项目挑战",
|
||||||
|
"solution": "解决方案",
|
||||||
|
"gallery": "项目展示",
|
||||||
|
"projectInfo": "项目信息",
|
||||||
|
"client": "客户",
|
||||||
|
"year": "年份",
|
||||||
|
"duration": "周期",
|
||||||
|
"services": "服务内容",
|
||||||
|
"visitProject": "访问项目",
|
||||||
|
"relatedProjects": "相关项目",
|
||||||
|
"items": {
|
||||||
|
"forma-digital": {
|
||||||
|
"overview": "Forma Digital 是一个现代化的电商平台,致力于为用户提供无缝的购物体验。我们重新设计了整个用户界面,采用极简主义设计风格,突出产品展示,提升转化率。",
|
||||||
|
"challenge": "客户需要一个既能展示高端产品,又能提供流畅购物体验的平台。原有的网站加载缓慢,用户体验差,转化率低下。",
|
||||||
|
"solution": "我们采用了 React + Next.js 技术栈,实现了服务端渲染和静态生成,大幅提升加载速度。同时重新设计了产品展示页面,采用沉浸式大图展示,配合流畅的动画过渡。",
|
||||||
|
"client": "Forma Digital Inc.",
|
||||||
|
"duration": "3 个月"
|
||||||
|
},
|
||||||
|
"one-step": {
|
||||||
|
"overview": "One Step 是一款专注于健康习惯养成的健身应用。我们为其打造了完整的品牌视觉识别系统,包括 Logo 设计、UI 界面和营销物料。",
|
||||||
|
"challenge": "在竞争激烈的健身应用市场中,如何通过品牌设计脱颖而出,建立独特的品牌认知。",
|
||||||
|
"solution": "我们以「一步一个脚印」为核心理念,设计了简洁有力的品牌标识。采用渐变色彩和圆润的图形语言,传达健康、积极、向上的品牌调性。",
|
||||||
|
"client": "One Step Fitness",
|
||||||
|
"duration": "2 个月"
|
||||||
|
},
|
||||||
|
"nero-vision": {
|
||||||
|
"overview": "Nero Vision 是一个面向创意专业人士的作品集管理平台,帮助设计师和艺术家展示和管理他们的创作。",
|
||||||
|
"challenge": "创意人士需要一个既能完美展示作品,又能方便管理的平台。现有解决方案要么太复杂,要么展示效果不佳。",
|
||||||
|
"solution": "我们采用 Vue.js + Node.js 全栈开发,设计了直观的拖拽式作品管理界面,配合精美的展示模板,让创意人士轻松打造个人品牌。",
|
||||||
|
"client": "Nero Studio",
|
||||||
|
"duration": "4 个月"
|
||||||
|
},
|
||||||
|
"bold-moves": {
|
||||||
|
"overview": "Bold Moves 是一个展示创新建筑设计的交互式网站,通过 3D 可视化技术,让用户身临其境地体验建筑之美。",
|
||||||
|
"challenge": "如何将复杂的建筑设计以直观、吸引人的方式展示给普通用户,同时保持专业性。",
|
||||||
|
"solution": "我们使用 Three.js 实现了高质量的 3D 渲染,配合流畅的交互设计,用户可以从任意角度欣赏建筑细节。同时加入了光影效果和材质展示,提升视觉冲击力。",
|
||||||
|
"client": "Bold Moves Architecture",
|
||||||
|
"duration": "5 个月"
|
||||||
|
},
|
||||||
|
"echo-labs": {
|
||||||
|
"overview": "Echo Labs 是一家 AI 领域的科技创业公司,我们为其打造了完整的品牌视觉识别系统和企业官网。",
|
||||||
|
"challenge": "AI 领域的品牌需要既体现科技感,又要有人文温度,避免过于冷冰冰的技术感。",
|
||||||
|
"solution": "我们以「回声」为概念,设计了富有动感的品牌标识。采用深色主题配合渐变色彩,营造科技感的同时,通过圆润的图形语言增添亲和力。",
|
||||||
|
"client": "Echo Labs AI",
|
||||||
|
"duration": "3 个月"
|
||||||
|
},
|
||||||
|
"flux-api": {
|
||||||
|
"overview": "Flux API 是一个可扩展的 REST API 服务平台,提供全面的文档和开发者工具,帮助开发者快速集成。",
|
||||||
|
"challenge": "API 文档和开发者体验是技术产品的核心竞争力,如何让复杂的 API 变得易于理解和使用。",
|
||||||
|
"solution": "我们设计了交互式 API 文档,支持在线测试和代码生成。同时提供了多语言 SDK 和详细的教程,大幅降低开发者的学习成本。",
|
||||||
|
"client": "Flux Technologies",
|
||||||
|
"duration": "6 个月"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"studio": {
|
"studio": {
|
||||||
"title": "关于工作室",
|
"title": "关于工作室",
|
||||||
@@ -360,11 +418,78 @@
|
|||||||
"title": "新闻动态",
|
"title": "新闻动态",
|
||||||
"description": "获取我们的最新见解、项目更新和行业趋势。",
|
"description": "获取我们的最新见解、项目更新和行业趋势。",
|
||||||
"readMore": "阅读更多",
|
"readMore": "阅读更多",
|
||||||
|
"backToList": "返回文章列表",
|
||||||
"categories": {
|
"categories": {
|
||||||
"all": "全部文章",
|
"all": "全部文章",
|
||||||
"insights": "行业洞察",
|
"insights": "行业洞察",
|
||||||
"projects": "项目动态",
|
"projects": "项目动态",
|
||||||
"announcements": "公告通知"
|
"announcements": "公告通知"
|
||||||
|
},
|
||||||
|
"detail": {
|
||||||
|
"shareArticle": "分享文章",
|
||||||
|
"relatedArticles": "相关文章",
|
||||||
|
"items": {
|
||||||
|
"design-trends-2026": {
|
||||||
|
"content": "2026 年,设计行业正在经历一场深刻的变革。从极简主义的回归到大胆排版的兴起,从 3D 元素的普及到 AI 辅助设计的成熟,这些趋势正在重新定义数字体验的边界。作为设计从业者,我们需要紧跟这些变化,才能为客户创造更具竞争力的作品。",
|
||||||
|
"section1Title": "极简主义的回归",
|
||||||
|
"section1Content": "在信息过载的时代,用户越来越渴望简洁、清晰的界面。2026 年的极简主义不再是简单的「少即是多」,而是通过精心的信息架构和视觉层次,在有限的空间内传达更多价值。留白不再是空白,而是一种有意为之的设计语言。",
|
||||||
|
"quote": "好的设计不是添加更多,而是去除不必要的。在 2026 年,这一点比以往任何时候都更加重要。",
|
||||||
|
"section2Title": "大胆排版与动态文字",
|
||||||
|
"section2Content": "排版正在从配角变成主角。大尺寸、高对比度的字体设计正在成为品牌表达的重要手段。动态文字效果的普及,让排版不再是静态的装饰,而是能够与用户互动的活元素。",
|
||||||
|
"section3Title": "AI 辅助设计的成熟",
|
||||||
|
"section3Content": "AI 工具正在从「替代设计师」转向「增强设计师」。智能布局建议、自动化配色方案、实时设计反馈等功能,让设计师能够专注于创意和策略,而非重复性的执行工作。"
|
||||||
|
},
|
||||||
|
"forma-digital-launch": {
|
||||||
|
"content": "经过三个月的精心打造,我们很高兴地宣布 Forma Digital 电商平台正式上线!这个项目是我们团队迄今为止最具挑战性的作品之一,也是我们技术实力和设计能力的集中体现。",
|
||||||
|
"section1Title": "项目背景",
|
||||||
|
"section1Content": "Forma Digital 是一家专注于高端家居用品的电商品牌。他们需要一个能够完美展示产品质感、提供流畅购物体验的平台。原有的网站存在加载缓慢、移动端体验差、转化率低等问题。",
|
||||||
|
"quote": "北极新一团队不仅理解我们的需求,更超越了我们的期望。新平台上线后,我们的转化率提升了 45%。",
|
||||||
|
"section2Title": "技术亮点",
|
||||||
|
"section2Content": "我们采用了 React + Next.js 技术栈,实现了服务端渲染和静态生成。通过图片懒加载、代码分割、CDN 加速等技术手段,将首屏加载时间从 4.5 秒降低到 1.2 秒。",
|
||||||
|
"section3Title": "成果展示",
|
||||||
|
"section3Content": "新平台上线后,用户停留时间增加了 60%,跳出率降低了 35%,转化率提升了 45%。客户对新平台的设计和性能都非常满意。"
|
||||||
|
},
|
||||||
|
"studio-expansion": {
|
||||||
|
"content": "随着业务的持续增长和客户需求的不断增加,我们很高兴地宣布 ArcticNewOne 工作室正式扩展!我们将增加新的团队成员,拓展服务能力,为客户提供更优质的数字化解决方案。",
|
||||||
|
"section1Title": "团队扩展",
|
||||||
|
"section1Content": "我们将新增 5 名资深设计师和 3 名高级开发工程师,覆盖前端、后端、UI/UX 等多个领域。这些新成员都拥有丰富的行业经验,曾服务于多家知名企业。",
|
||||||
|
"quote": "人才是我们最宝贵的资产。通过扩展团队,我们能够承接更多项目,同时保持一贯的高品质交付。",
|
||||||
|
"section2Title": "服务升级",
|
||||||
|
"section2Content": "除了现有的网页设计、品牌设计、程序开发等服务,我们还将新增数据可视化、AI 应用开发、AR/VR 体验设计等前沿服务。",
|
||||||
|
"section3Title": "展望未来",
|
||||||
|
"section3Content": "我们计划在未来一年内完成 50+ 项目,服务 30+ 新客户。同时,我们将继续深耕技术创新,探索更多可能性,为客户创造更大价值。"
|
||||||
|
},
|
||||||
|
"ux-research-methods": {
|
||||||
|
"content": "用户体验研究是设计决策的基础。在 2026 年,随着技术的发展和用户行为的变化,UX 研究方法也在不断演进。本文将介绍几种最有效的现代 UX 研究方法。",
|
||||||
|
"section1Title": "远程用户测试",
|
||||||
|
"section1Content": "远程用户测试已经成为 UX 研究的主流方法。通过专业的远程测试平台,我们可以在短时间内招募到全球各地的测试用户,获取更广泛的反馈。",
|
||||||
|
"quote": "远程测试不仅降低了成本,更重要的是让我们能够接触到更真实的用户场景。",
|
||||||
|
"section2Title": "行为数据分析",
|
||||||
|
"section2Content": "通过热力图、滚动深度、点击流等行为数据,我们可以客观地了解用户如何与产品互动。这些数据弥补了传统访谈和问卷的不足,提供了更真实的用户行为洞察。",
|
||||||
|
"section3Title": "AI 辅助分析",
|
||||||
|
"section3Content": "AI 工具正在帮助我们更高效地分析用户反馈。情感分析、主题聚类、趋势预测等功能,让我们能够从海量数据中快速提取有价值的洞察。"
|
||||||
|
},
|
||||||
|
"bold-moves-case-study": {
|
||||||
|
"content": "Bold Moves 是一个展示创新建筑设计的交互式网站项目。本文将深入介绍这个项目的设计思路、技术实现和最终成果。",
|
||||||
|
"section1Title": "设计理念",
|
||||||
|
"section1Content": "Bold Moves 希望通过数字方式展示建筑设计的魅力。我们决定采用 3D 可视化技术,让用户能够从任意角度欣赏建筑细节,获得沉浸式的体验。",
|
||||||
|
"quote": "我们想要的不只是一个展示网站,而是一个能够让用户「走进」建筑的数字空间。",
|
||||||
|
"section2Title": "技术挑战",
|
||||||
|
"section2Content": "高质量的 3D 渲染需要强大的计算能力,而网页端的性能有限。我们通过模型优化、LOD 技术、WebGL 渲染等手段,在保证视觉质量的同时,实现了流畅的交互体验。",
|
||||||
|
"section3Title": "最终成果",
|
||||||
|
"section3Content": "项目上线后获得了广泛好评,赢得了多个设计奖项。用户平均停留时间超过 5 分钟,远高于行业平均水平。"
|
||||||
|
},
|
||||||
|
"new-tools-integration": {
|
||||||
|
"content": "为了更好地服务客户,我们不断扩充和完善我们的工具箱。最近,我们新增了多款实用工具,涵盖设计、开发、协作等多个领域。",
|
||||||
|
"section1Title": "设计工具升级",
|
||||||
|
"section1Content": "我们引入了最新的设计协作平台,支持实时多人编辑、版本管理、设计系统集成等功能。设计师和开发者可以在同一个平台上无缝协作。",
|
||||||
|
"quote": "工欲善其事,必先利其器。好的工具能够大幅提升团队效率。",
|
||||||
|
"section2Title": "开发工具增强",
|
||||||
|
"section2Content": "新增了自动化测试框架、性能监控工具、代码质量检查等开发工具。这些工具帮助我们在开发过程中及时发现和解决问题,保证代码质量。",
|
||||||
|
"section3Title": "协作工具优化",
|
||||||
|
"section3Content": "我们升级了项目管理平台,新增了看板视图、时间追踪、资源分配等功能。项目经理可以更直观地掌控项目进度,团队成员可以更高效地协作。"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
|
|||||||
Reference in New Issue
Block a user