|
|
@ -2,6 +2,14 @@ |
|
|
|
import { ref, computed, onMounted, reactive } from 'vue'; |
|
|
|
import { useI18n } from 'vue-i18n'; |
|
|
|
import { queryEcosystemListForEcosystem } from '@/api/modules/ecosystem'; |
|
|
|
import type { EcosystemItem as ApiEcosystemItem } from '@/api/modules/ecosystem'; |
|
|
|
|
|
|
|
// 声明全局WOW类型 |
|
|
|
declare global { |
|
|
|
interface Window { |
|
|
|
WOW: any; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const { t, locale } = useI18n(); |
|
|
|
|
|
|
@ -10,7 +18,7 @@ const selectedEcosystem = ref(1); |
|
|
|
const totalEcosystems = 10; // 总共10个生态系统 |
|
|
|
|
|
|
|
// 生态系统数据加载状态 |
|
|
|
const loading = ref(true); |
|
|
|
const loading = ref(false); |
|
|
|
|
|
|
|
// 统一生态系统样式配置 |
|
|
|
const ecosystemStyles = [ |
|
|
@ -56,128 +64,119 @@ const ecosystemStyles = [ |
|
|
|
} |
|
|
|
]; |
|
|
|
|
|
|
|
// 生态系统图片数据 - 从API获取 |
|
|
|
const ecosystems = reactive([]); |
|
|
|
// 生态系统图片数据 - 使用i18n硬编码数据 |
|
|
|
interface EcosystemItem { |
|
|
|
id: string; |
|
|
|
image: string; |
|
|
|
title: string; |
|
|
|
description: string; |
|
|
|
overlayColor: string; |
|
|
|
bgColor: string; |
|
|
|
} |
|
|
|
|
|
|
|
// 获取生态系统数据 |
|
|
|
const ecosystems = ref<EcosystemItem[]>([]); |
|
|
|
// 存储API返回的图片数组 |
|
|
|
const apiImages = ref<string[]>([]); |
|
|
|
|
|
|
|
// 获取API数据 |
|
|
|
const fetchEcosystems = async () => { |
|
|
|
loading.value = true; |
|
|
|
try { |
|
|
|
const result = await queryEcosystemListForEcosystem({ |
|
|
|
pageSize: 10, |
|
|
|
pageNo: 1 |
|
|
|
}); |
|
|
|
|
|
|
|
if (result && result.length > 0) { |
|
|
|
// 将API返回的数据与样式配置合并 |
|
|
|
const ecosystemsData = result.map((item, index) => { |
|
|
|
return { |
|
|
|
...item, |
|
|
|
id: item.id || String(index + 1), |
|
|
|
// 使用API返回的图片,如果没有则使用默认图片 |
|
|
|
image: item.image || '/LOGO.png', |
|
|
|
// 使用对应索引的样式配置 |
|
|
|
...ecosystemStyles[index % ecosystemStyles.length] |
|
|
|
}; |
|
|
|
const response = await queryEcosystemListForEcosystem(); |
|
|
|
console.log('API Response:', response); |
|
|
|
if (response) { |
|
|
|
console.log('First API item structure:', response[0]); |
|
|
|
// 提取API返回的图片数组,去除前后空格 |
|
|
|
apiImages.value = response.map((item: ApiEcosystemItem) => { |
|
|
|
// console.log('Processing item:', item, 'image field:', item.image); |
|
|
|
const trimmedImage = (item.image || '').trim(); |
|
|
|
// console.log('Trimmed image:', trimmedImage); |
|
|
|
return trimmedImage; |
|
|
|
}).filter(url => { |
|
|
|
console.log('Filtering URL:', url, 'is valid:', Boolean(url)); |
|
|
|
return Boolean(url); |
|
|
|
}); |
|
|
|
|
|
|
|
// 更新生态系统数据 |
|
|
|
ecosystems.splice(0, ecosystems.length, ...ecosystemsData); |
|
|
|
} else { |
|
|
|
// 如果API没有返回数据,使用默认数据 |
|
|
|
const defaultEcosystems = [ |
|
|
|
{ |
|
|
|
id: '1', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.trading.title'), |
|
|
|
description: t('ecosystem.trading.description'), |
|
|
|
...ecosystemStyles[0] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '2', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.blockchain.title'), |
|
|
|
description: t('ecosystem.blockchain.description'), |
|
|
|
...ecosystemStyles[1] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '3', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.crosschain.title'), |
|
|
|
description: t('ecosystem.crosschain.description'), |
|
|
|
...ecosystemStyles[2] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '4', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.payment.title'), |
|
|
|
description: t('ecosystem.payment.description'), |
|
|
|
...ecosystemStyles[3] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '5', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.privacy.title'), |
|
|
|
description: t('ecosystem.privacy.description'), |
|
|
|
...ecosystemStyles[4] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '6', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.defi.title'), |
|
|
|
description: t('ecosystem.defi.description'), |
|
|
|
...ecosystemStyles[5] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '7', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.nft.title'), |
|
|
|
description: t('ecosystem.nft.description'), |
|
|
|
...ecosystemStyles[6] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '8', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.dao.title'), |
|
|
|
description: t('ecosystem.dao.description'), |
|
|
|
...ecosystemStyles[7] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '9', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.gaming.title'), |
|
|
|
description: t('ecosystem.gaming.description'), |
|
|
|
...ecosystemStyles[8] |
|
|
|
}, |
|
|
|
{ |
|
|
|
id: '10', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.social.title'), |
|
|
|
description: t('ecosystem.social.description'), |
|
|
|
...ecosystemStyles[9] |
|
|
|
} |
|
|
|
]; |
|
|
|
|
|
|
|
// 更新生态系统数据 |
|
|
|
ecosystems.splice(0, ecosystems.length, ...defaultEcosystems); |
|
|
|
console.log('Final API Images array:', apiImages.value); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error(t('common.error.loadEcosystemFailed'), error); |
|
|
|
// 发生错误时使用默认数据 |
|
|
|
const defaultEcosystems = [ |
|
|
|
{ |
|
|
|
id: '1', |
|
|
|
image: '/LOGO.png', |
|
|
|
title: t('ecosystem.trading.title'), |
|
|
|
description: t('ecosystem.trading.description'), |
|
|
|
...ecosystemStyles[0] |
|
|
|
}, |
|
|
|
// 其他默认数据... |
|
|
|
]; |
|
|
|
ecosystems.splice(0, ecosystems.length, ...defaultEcosystems.slice(0, 1)); |
|
|
|
} finally { |
|
|
|
loading.value = false; |
|
|
|
console.error('Failed to fetch ecosystems:', error); |
|
|
|
apiImages.value = []; |
|
|
|
} |
|
|
|
// 无论API是否成功,都初始化生态系统数据 |
|
|
|
initEcosystems(); |
|
|
|
}; |
|
|
|
|
|
|
|
// 初始化生态系统数据(图片使用API返回,其他内容使用i18n硬编码) |
|
|
|
const initEcosystems = () => { |
|
|
|
const i18nData = [ |
|
|
|
{ |
|
|
|
key: 'trading', |
|
|
|
title: t('ecosystem.trading.title'), |
|
|
|
description: t('ecosystem.trading.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'blockchain', |
|
|
|
title: t('ecosystem.blockchain.title'), |
|
|
|
description: t('ecosystem.blockchain.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'crosschain', |
|
|
|
title: t('ecosystem.crosschain.title'), |
|
|
|
description: t('ecosystem.crosschain.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'payment', |
|
|
|
title: t('ecosystem.payment.title'), |
|
|
|
description: t('ecosystem.payment.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'privacy', |
|
|
|
title: t('ecosystem.privacy.title'), |
|
|
|
description: t('ecosystem.privacy.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'defi', |
|
|
|
title: t('ecosystem.defi.title'), |
|
|
|
description: t('ecosystem.defi.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'nft', |
|
|
|
title: t('ecosystem.nft.title'), |
|
|
|
description: t('ecosystem.nft.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'dao', |
|
|
|
title: t('ecosystem.dao.title'), |
|
|
|
description: t('ecosystem.dao.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'gaming', |
|
|
|
title: t('ecosystem.gaming.title'), |
|
|
|
description: t('ecosystem.gaming.description') |
|
|
|
}, |
|
|
|
{ |
|
|
|
key: 'social', |
|
|
|
title: t('ecosystem.social.title'), |
|
|
|
description: t('ecosystem.social.description') |
|
|
|
} |
|
|
|
]; |
|
|
|
|
|
|
|
// 将API图片与i18n文本数据一一对应组合 |
|
|
|
const ecosystemsData = i18nData.map((item, index) => { |
|
|
|
const finalImage = apiImages.value[index] || `/images/ecosystem/${item.key}.jpg`; |
|
|
|
console.log(`Ecosystem ${index}: Using image ${finalImage}`); |
|
|
|
return { |
|
|
|
id: (index + 1).toString(), |
|
|
|
title: item.title, |
|
|
|
description: item.description, |
|
|
|
image: finalImage, |
|
|
|
orderNo: index + 1, |
|
|
|
...ecosystemStyles[index] |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
console.log('Final ecosystems data:', ecosystemsData); |
|
|
|
// 更新生态系统数据 |
|
|
|
ecosystems.value = ecosystemsData; |
|
|
|
}; |
|
|
|
|
|
|
|
// 使用字符串变量而不是计算属性 |
|
|
@ -219,7 +218,7 @@ const projects = computed(() => [ |
|
|
|
|
|
|
|
// 特色项目 |
|
|
|
const featuredProjects = computed(() => { |
|
|
|
return projects.value.filter(project => project.featured); |
|
|
|
return projects.value.filter((project: any) => project.featured); |
|
|
|
}); |
|
|
|
|
|
|
|
// 选择生态系统 |
|
|
@ -239,7 +238,7 @@ const prevEcosystem = () => { |
|
|
|
|
|
|
|
// 当前选中的生态系统 |
|
|
|
const currentEcosystem = computed(() => { |
|
|
|
return ecosystems.find((eco: any) => Number(eco.id) === selectedEcosystem.value) || ecosystems[0]; |
|
|
|
return ecosystems.value.find((eco: EcosystemItem) => Number(eco.id) === selectedEcosystem.value) || ecosystems.value[0]; |
|
|
|
}); |
|
|
|
|
|
|
|
// 滚动到下一个生态系统 |
|
|
@ -304,9 +303,8 @@ const handleMouseMove = (event: MouseEvent) => { |
|
|
|
onMounted(() => { |
|
|
|
// 初始化WOW.js动画 |
|
|
|
try { |
|
|
|
const WOW = window.WOW; |
|
|
|
if (WOW) { |
|
|
|
new WOW({ |
|
|
|
if (typeof window !== 'undefined' && window.WOW) { |
|
|
|
new (window.WOW as any)({ |
|
|
|
boxClass: 'wow', |
|
|
|
animateClass: 'animate__animated', |
|
|
|
offset: 100, |
|
|
@ -401,13 +399,13 @@ onMounted(() => { |
|
|
|
</div> --> |
|
|
|
|
|
|
|
<!-- 标题 - 统一样式 --> |
|
|
|
<h2 class="font-bold text-white mb-6 wow animate__animated animate__fadeInRight text-4xl md:text-5xl" v-html="ecosystem.title" /> |
|
|
|
<!-- {{ ecosystem.title }} --> |
|
|
|
<!-- </h2> --> |
|
|
|
<h2 class="font-bold text-white mb-6 wow animate__animated animate__fadeInRight text-4xl md:text-5xl"> |
|
|
|
{{ ecosystem.title }} |
|
|
|
</h2> |
|
|
|
|
|
|
|
<!-- 描述 - 统一样式 --> |
|
|
|
<p class="text-white/80 mb-8 wow animate__animated animate__fadeInRight animate__delay-xs text-base max-w-full" v-if="ecosystem.description" v-html="ecosystem.description"> |
|
|
|
|
|
|
|
<p class="text-white/80 mb-8 wow animate__animated animate__fadeInRight animate__delay-xs text-base max-w-full" v-if="ecosystem.description"> |
|
|
|
{{ ecosystem.description }} |
|
|
|
</p> |
|
|
|
<p class="text-white/80 mb-8 wow animate__animated animate__fadeInRight animate__delay-xs text-base" v-else> |
|
|
|
{{ t('ecosystem.default_description') }} |
|
|
@ -449,7 +447,7 @@ onMounted(() => { |
|
|
|
v-if="index < ecosystems.length - 1" |
|
|
|
class="absolute bottom-8 left-1/2 transform -translate-x-1/2 text-white/70 text-sm flex flex-col items-center cursor-pointer hover:text-white transition-colors duration-300" |
|
|
|
@click="scrollToNext(index)" |
|
|
|
> |
|
|
|
> |
|
|
|
<!-- <span class="mb-1">探索更多</span> |
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 animate-bounce-soft" fill="none" viewBox="0 0 24 24" stroke="currentColor"> |
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3" /> |
|
|
|