Browse Source

'补充另外几个页面完毕'

main
hflllll 3 months ago
parent
commit
48894053f4
15 changed files with 2041 additions and 132 deletions
  1. +223
    -0
      package-lock.json
  2. +2
    -0
      package.json
  3. +149
    -14
      src/assets/animations.css
  4. +22
    -22
      src/components/layout/Footer.vue
  5. +16
    -20
      src/components/layout/NavBar.vue
  6. +138
    -1
      src/i18n/locales/en.json
  7. +138
    -1
      src/i18n/locales/ja.json
  8. +138
    -1
      src/i18n/locales/zh.json
  9. +15
    -0
      src/router/index.ts
  10. +22
    -22
      src/views/About.vue
  11. +293
    -0
      src/views/Community.vue
  12. +286
    -0
      src/views/Contact.vue
  13. +31
    -32
      src/views/Ecosystem.vue
  14. +267
    -0
      src/views/FAQ.vue
  15. +301
    -19
      src/views/Home.vue

+ 223
- 0
package-lock.json View File

@ -9,8 +9,10 @@
"version": "0.0.0",
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"@videojs-player/vue": "^1.0.0",
"animate.css": "^4.1.1",
"tailwindcss": "^4.1.11",
"video.js": "^8.23.3",
"vue": "^3.5.13",
"vue-i18n": "^11.1.9",
"vue-router": "^4.5.1",
@ -69,6 +71,14 @@
"node": ">=6.0.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.27.6",
"resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.27.6.tgz",
"integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
"version": "7.28.0",
"resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.28.0.tgz",
@ -1090,6 +1100,67 @@
"undici-types": "~7.8.0"
}
},
"node_modules/@types/video.js": {
"version": "7.3.58",
"resolved": "https://registry.npmmirror.com/@types/video.js/-/video.js-7.3.58.tgz",
"integrity": "sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ==",
"peer": true
},
"node_modules/@videojs-player/vue": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/@videojs-player/vue/-/vue-1.0.0.tgz",
"integrity": "sha512-WonTezRfKu3fYdQLt/ta+nuKH6gMZUv8l40Jke/j4Lae7IqeO/+lLAmBnh3ni88bwR+vkFXIlZ2Ci7VKInIYJg==",
"peerDependencies": {
"@types/video.js": "7.x",
"video.js": "7.x",
"vue": "3.x"
}
},
"node_modules/@videojs/http-streaming": {
"version": "3.17.0",
"resolved": "https://registry.npmmirror.com/@videojs/http-streaming/-/http-streaming-3.17.0.tgz",
"integrity": "sha512-Ch1P3tvvIEezeZXyK11UfWgp4cWKX4vIhZ30baN/lRinqdbakZ5hiAI3pGjRy3d+q/Epyc8Csz5xMdKNNGYpcw==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^4.1.1",
"aes-decrypter": "^4.0.2",
"global": "^4.4.0",
"m3u8-parser": "^7.2.0",
"mpd-parser": "^1.3.1",
"mux.js": "7.1.0",
"video.js": "^7 || ^8"
},
"engines": {
"node": ">=8",
"npm": ">=5"
},
"peerDependencies": {
"video.js": "^8.19.0"
}
},
"node_modules/@videojs/vhs-utils": {
"version": "4.1.1",
"resolved": "https://registry.npmmirror.com/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz",
"integrity": "sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"global": "^4.4.0"
},
"engines": {
"node": ">=8",
"npm": ">=5"
}
},
"node_modules/@videojs/xhr": {
"version": "2.7.0",
"resolved": "https://registry.npmmirror.com/@videojs/xhr/-/xhr-2.7.0.tgz",
"integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"global": "~4.4.0",
"is-function": "^1.0.1"
}
},
"node_modules/@vitejs/plugin-vue": {
"version": "5.2.4",
"resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
@ -1277,6 +1348,25 @@
}
}
},
"node_modules/@xmldom/xmldom": {
"version": "0.8.10",
"resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
"integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/aes-decrypter": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/aes-decrypter/-/aes-decrypter-4.0.2.tgz",
"integrity": "sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^4.1.1",
"global": "^4.4.0",
"pkcs7": "^1.0.4"
}
},
"node_modules/alien-signals": {
"version": "1.0.13",
"resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz",
@ -1384,6 +1474,11 @@
"node": ">=8"
}
},
"node_modules/dom-walk": {
"version": "0.1.2",
"resolved": "https://registry.npmmirror.com/dom-walk/-/dom-walk-0.1.2.tgz",
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
},
"node_modules/email-addresses": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/email-addresses/-/email-addresses-5.0.0.tgz",
@ -1634,6 +1729,15 @@
"node": ">= 6"
}
},
"node_modules/global": {
"version": "4.4.0",
"resolved": "https://registry.npmmirror.com/global/-/global-4.4.0.tgz",
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
"dependencies": {
"min-document": "^2.19.0",
"process": "^0.11.10"
}
},
"node_modules/globby": {
"version": "11.1.0",
"resolved": "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz",
@ -1686,6 +1790,11 @@
"node": ">=0.10.0"
}
},
"node_modules/is-function": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/is-function/-/is-function-1.0.2.tgz",
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
@ -1956,6 +2065,16 @@
"node": ">=8"
}
},
"node_modules/m3u8-parser": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/m3u8-parser/-/m3u8-parser-7.2.0.tgz",
"integrity": "sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^4.1.1",
"global": "^4.4.0"
}
},
"node_modules/magic-string": {
"version": "0.30.17",
"resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
@ -2013,6 +2132,14 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/min-document": {
"version": "2.19.0",
"resolved": "https://registry.npmmirror.com/min-document/-/min-document-2.19.0.tgz",
"integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
"dependencies": {
"dom-walk": "^0.1.0"
}
},
"node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
@ -2061,12 +2188,42 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mpd-parser": {
"version": "1.3.1",
"resolved": "https://registry.npmmirror.com/mpd-parser/-/mpd-parser-1.3.1.tgz",
"integrity": "sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/vhs-utils": "^4.0.0",
"@xmldom/xmldom": "^0.8.3",
"global": "^4.4.0"
},
"bin": {
"mpd-to-m3u8-json": "bin/parse.js"
}
},
"node_modules/muggle-string": {
"version": "0.4.1",
"resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz",
"integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
"dev": true
},
"node_modules/mux.js": {
"version": "7.1.0",
"resolved": "https://registry.npmmirror.com/mux.js/-/mux.js-7.1.0.tgz",
"integrity": "sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==",
"dependencies": {
"@babel/runtime": "^7.11.2",
"global": "^4.4.0"
},
"bin": {
"muxjs-transmux": "bin/transmux.js"
},
"engines": {
"node": ">=8",
"npm": ">=5"
}
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
@ -2160,6 +2317,17 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pkcs7": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/pkcs7/-/pkcs7-1.0.4.tgz",
"integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
"dependencies": {
"@babel/runtime": "^7.5.5"
},
"bin": {
"pkcs7": "bin/cli.js"
}
},
"node_modules/pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz",
@ -2199,6 +2367,14 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmmirror.com/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
@ -2424,6 +2600,53 @@
"node": ">= 10.0.0"
}
},
"node_modules/video.js": {
"version": "8.23.3",
"resolved": "https://registry.npmmirror.com/video.js/-/video.js-8.23.3.tgz",
"integrity": "sha512-Toe0VLlDZcUhiaWfcePS1OEdT3ATfktm0hk/PELfD7zUoPDHeT+cJf/wZmCy5M5eGVwtGUg25RWPCj1L/1XufA==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@videojs/http-streaming": "^3.17.0",
"@videojs/vhs-utils": "^4.1.1",
"@videojs/xhr": "2.7.0",
"aes-decrypter": "^4.0.2",
"global": "4.4.0",
"m3u8-parser": "^7.2.0",
"mpd-parser": "^1.3.1",
"mux.js": "^7.0.1",
"videojs-contrib-quality-levels": "4.1.0",
"videojs-font": "4.2.0",
"videojs-vtt.js": "0.15.5"
}
},
"node_modules/videojs-contrib-quality-levels": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz",
"integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==",
"dependencies": {
"global": "^4.4.0"
},
"engines": {
"node": ">=16",
"npm": ">=8"
},
"peerDependencies": {
"video.js": "^8"
}
},
"node_modules/videojs-font": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/videojs-font/-/videojs-font-4.2.0.tgz",
"integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ=="
},
"node_modules/videojs-vtt.js": {
"version": "0.15.5",
"resolved": "https://registry.npmmirror.com/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz",
"integrity": "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==",
"dependencies": {
"global": "^4.3.1"
}
},
"node_modules/vite": {
"version": "6.3.5",
"resolved": "https://registry.npmmirror.com/vite/-/vite-6.3.5.tgz",


+ 2
- 0
package.json View File

@ -11,8 +11,10 @@
},
"dependencies": {
"@tailwindcss/vite": "^4.1.11",
"@videojs-player/vue": "^1.0.0",
"animate.css": "^4.1.1",
"tailwindcss": "^4.1.11",
"video.js": "^8.23.3",
"vue": "^3.5.13",
"vue-i18n": "^11.1.9",
"vue-router": "^4.5.1",


+ 149
- 14
src/assets/animations.css View File

@ -1,38 +1,66 @@
/* 全局动画样式 */
:root {
--animation-speed-slow: 1.5s; /* 慢速 */
--animation-speed-normal: 0.8s; /* 正常速度 */
--animation-speed-fast: 0.5s; /* 快速 */
--animation-speed-very-fast: 0.3s; /* 非常快 */
--animation-delay-xs: 0.1s; /* 极短延迟 */
--animation-delay-sm: 0.2s; /* 短延迟 */
--animation-delay-md: 0.3s; /* 中等延迟 */
--animation-delay-lg: 0.5s; /* 长延迟 */
/* 按钮动画变量 */
--btn-hover-transition: 0.3s;
--btn-scale-amount: 1.05;
--btn-pulse-scale: 1.03;
--btn-pulse-duration: 1.5s;
--btn-glow-color: rgba(255, 255, 255, 0.2);
--btn-glow-spread: 10px;
}
/* 使WOW元素在加载前不可见 */
.wow {
visibility: hidden;
}
/* 自定义动画持续时间 */
.animate__animated.animate__duration-1s {
animation-duration: 1s;
.animate__animated {
animation-duration: var(--animation-speed-normal) !important;
}
.animate__animated.animate__duration-slow {
animation-duration: var(--animation-speed-slow) !important;
}
.animate__animated.animate__duration-normal {
animation-duration: var(--animation-speed-normal) !important;
}
.animate__animated.animate__duration-2s {
animation-duration: 2s;
.animate__animated.animate__duration-fast {
animation-duration: var(--animation-speed-fast) !important;
}
.animate__animated.animate__duration-3s {
animation-duration: 3s;
.animate__animated.animate__duration-very-fast {
animation-duration: var(--animation-speed-very-fast) !important;
}
/* 自定义动画延迟 */
.animate__animated.animate__delay-0-5s {
animation-delay: 0.5s;
.animate__animated.animate__delay-xs {
animation-delay: var(--animation-delay-xs) !important;
}
.animate__animated.animate__delay-1s {
animation-delay: 1s;
.animate__animated.animate__delay-sm {
animation-delay: var(--animation-delay-sm) !important;
}
.animate__animated.animate__delay-1-5s {
animation-delay: 1.5s;
.animate__animated.animate__delay-md {
animation-delay: var(--animation-delay-md) !important;
}
.animate__animated.animate__delay-2s {
animation-delay: 2s;
.animate__animated.animate__delay-lg {
animation-delay: var(--animation-delay-lg) !important;
}
/* 自定义动画重复次数 */
@ -46,4 +74,111 @@
.animate__animated.animate__infinite {
animation-iteration-count: infinite;
}
/* 按钮悬停动画效果 */
.btn-hover-scale {
transition: transform var(--btn-hover-transition) ease;
}
.btn-hover-scale:hover {
transform: scale(var(--btn-scale-amount));
}
.btn-hover-float {
transition: transform var(--btn-hover-transition) ease;
}
.btn-hover-float:hover {
transform: translateY(-5px);
}
.btn-hover-glow {
position: relative;
overflow: hidden;
transition: all var(--btn-hover-transition) ease;
}
.btn-hover-glow:hover {
box-shadow: 0 0 var(--btn-glow-spread) var(--btn-glow-color);
}
.btn-hover-glow:hover::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(120deg, transparent, var(--btn-glow-color), transparent);
transform: translateX(-100%);
animation: btn-glow-animation 1.5s infinite;
}
@keyframes btn-glow-animation {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
.btn-hover-pulse {
animation: none;
}
.btn-hover-pulse:hover {
animation: btn-pulse var(--btn-pulse-duration) infinite;
}
@keyframes btn-pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(var(--btn-pulse-scale));
}
100% {
transform: scale(1);
}
}
.btn-hover-rotate {
transition: transform var(--btn-hover-transition) ease;
}
.btn-hover-rotate:hover {
transform: rotate(5deg);
}
.btn-hover-shadow {
transition: box-shadow var(--btn-hover-transition) ease, transform var(--btn-hover-transition) ease;
}
.btn-hover-shadow:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
transform: translateY(-3px);
}
.btn-hover-border {
position: relative;
z-index: 1;
transition: all var(--btn-hover-transition) ease;
}
.btn-hover-border::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background-color: currentColor;
transition: width var(--btn-hover-transition) ease;
z-index: -1;
}
.btn-hover-border:hover::after {
width: 100%;
}

+ 22
- 22
src/components/layout/Footer.vue View File

@ -21,7 +21,7 @@ const currentYear = new Date().getFullYear();
<!-- Footer Top Section -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
<!-- Logo & Description -->
<div class="wow animate__animated animate__fadeIn">
<div class="wow animate__animated animate__fadeIn animate__duration-fast">
<div class="flex items-center mb-4">
<img src="/public/vite.svg" alt="MOSE Logo" class="h-8 w-auto mr-2" />
<span class="text-xl font-bold text-primary-light">MOSE</span>
@ -37,11 +37,11 @@ const currentYear = new Date().getFullYear();
:href="link.url"
target="_blank"
rel="noopener noreferrer"
class="text-text-secondary hover:text-primary-light transition-colors duration-200 wow animate__animated animate__fadeIn"
class="text-text-secondary hover:text-primary-light transition-colors duration-200 wow animate__animated animate__fadeIn animate__duration-fast"
:class="{
'animate__delay-0-5s': index === 1,
'animate__delay-1s': index === 2,
'animate__delay-1-5s': index === 3
'animate__delay-xs': index === 1,
'animate__delay-sm': index === 2,
'animate__delay-md': index === 3
}"
>
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
@ -56,48 +56,48 @@ const currentYear = new Date().getFullYear();
</div>
<!-- Quick Links -->
<div class="wow animate__animated animate__fadeIn animate__delay-0-5s">
<div class="wow animate__animated animate__fadeIn animate__delay-xs animate__duration-fast">
<h3 class="text-lg font-medium text-text mb-4">{{ t('nav.ecosystem') }}</h3>
<ul class="space-y-2">
<li class="wow animate__animated animate__fadeInUp"><router-link to="/ecosystem/defi" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.defi') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-0-5s"><router-link to="/ecosystem/nft" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.nft') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-1s"><router-link to="/ecosystem/dao" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.dao') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-1-5s"><router-link to="/ecosystem/gaming" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.gaming') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__duration-fast"><router-link to="/ecosystem/defi" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.defi') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast"><router-link to="/ecosystem/nft" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.nft') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-sm animate__duration-fast"><router-link to="/ecosystem/dao" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.dao') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-md animate__duration-fast"><router-link to="/ecosystem/gaming" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.categories.gaming') }}</router-link></li>
</ul>
</div>
<!-- Resources -->
<div class="wow animate__animated animate__fadeIn animate__delay-1s">
<div class="wow animate__animated animate__fadeIn animate__delay-sm animate__duration-fast">
<h3 class="text-lg font-medium text-text mb-4">{{ t('nav.resources') }}</h3>
<ul class="space-y-2">
<li class="wow animate__animated animate__fadeInUp"><router-link to="/resources/docs" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.docs') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-0-5s"><router-link to="/resources/github" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.github') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-1s"><router-link to="/resources/grants" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.grants') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-1-5s"><router-link to="/resources/community" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.community') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__duration-fast"><router-link to="/resources/docs" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.docs') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast"><router-link to="/resources/github" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.github') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-sm animate__duration-fast"><router-link to="/resources/grants" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.grants') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-md animate__duration-fast"><router-link to="/resources/community" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.community') }}</router-link></li>
</ul>
</div>
<!-- Contact -->
<div class="wow animate__animated animate__fadeIn animate__delay-1-5s">
<div class="wow animate__animated animate__fadeIn animate__delay-md animate__duration-fast">
<h3 class="text-lg font-medium text-text mb-4">{{ t('nav.contact') }}</h3>
<ul class="space-y-2">
<li class="wow animate__animated animate__fadeInUp"><a href="mailto:info@mose.io" class="hover:text-primary-light transition-colors duration-200">{{ t('contact.email.info') }}</a></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-0-5s"><a href="mailto:support@mose.io" class="hover:text-primary-light transition-colors duration-200">{{ t('contact.email.support') }}</a></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-1s"><router-link to="/contact" class="hover:text-primary-light transition-colors duration-200">{{ t('nav.contact') }}</router-link></li>
<li class="wow animate__animated animate__fadeInUp animate__duration-fast"><a href="mailto:info@mose.io" class="hover:text-primary-light transition-colors duration-200">{{ t('contact.email.info') }}</a></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast"><a href="mailto:support@mose.io" class="hover:text-primary-light transition-colors duration-200">{{ t('contact.email.support') }}</a></li>
<li class="wow animate__animated animate__fadeInUp animate__delay-sm animate__duration-fast"><router-link to="/contact" class="hover:text-primary-light transition-colors duration-200">{{ t('nav.contact') }}</router-link></li>
</ul>
</div>
</div>
<!-- Footer Bottom -->
<div class="pt-8 border-t border-background-light flex flex-col md:flex-row justify-between items-center">
<p class="text-sm mb-4 md:mb-0 wow animate__animated animate__fadeIn">
<p class="text-sm mb-4 md:mb-0 wow animate__animated animate__fadeIn animate__duration-fast">
&copy; {{ currentYear }} MOSE. {{ t('footer.rights') }}.
</p>
<div class="flex space-x-6 text-sm">
<router-link to="/privacy" class="hover:text-primary-light transition-colors duration-200 wow animate__animated animate__fadeIn animate__delay-0-5s">
<router-link to="/privacy" class="hover:text-primary-light transition-colors duration-200 wow animate__animated animate__fadeIn animate__delay-xs animate__duration-fast">
{{ t('footer.privacy') }}
</router-link>
<router-link to="/terms" class="hover:text-primary-light transition-colors duration-200 wow animate__animated animate__fadeIn animate__delay-1s">
<router-link to="/terms" class="hover:text-primary-light transition-colors duration-200 wow animate__animated animate__fadeIn animate__delay-sm animate__duration-fast">
{{ t('footer.terms') }}
</router-link>
</div>


+ 16
- 20
src/components/layout/NavBar.vue View File

@ -54,7 +54,7 @@ const emit = defineEmits(['changeLanguage']);
<header class="bg-background-dark text-text py-4 px-6 md:px-12 lg:px-24 fixed w-full z-50">
<div class="container mx-auto flex justify-between items-center">
<!-- Logo -->
<router-link to="/" class="flex items-center animate__animated animate__fadeIn">
<router-link to="/" class="flex items-center animate__animated animate__fadeIn animate__duration-fast">
<img src="/public/vite.svg" alt="MOSE Logo" class="h-8 w-auto mr-2" />
<span class="text-xl font-bold text-primary-light">MOSE</span>
</router-link>
@ -65,22 +65,20 @@ const emit = defineEmits(['changeLanguage']);
v-for="(item, index) in navItems"
:key="item.path"
:to="item.path"
class="text-text-secondary hover:text-text transition-colors duration-200 animate__animated animate__fadeInDown"
class="text-text-secondary hover:text-text transition-colors duration-200 animate__animated animate__fadeInDown animate__duration-fast"
:class="{
'text-primary-light font-medium': $route.path === item.path,
'animate__delay-0-5s': index === 1,
'animate__delay-1s': index === 2,
'animate__delay-1-5s': index === 3,
'animate__delay-2s': index === 4,
'animate__delay-2-5s': index === 5,
'animate__delay-3s': index === 6
'animate__delay-xs': index === 1,
'animate__delay-sm': index === 2,
'animate__delay-md': index === 3,
'animate__delay-lg': index === 4
}"
>
{{ item.name }}
</router-link>
<!-- Language Selector -->
<div class="relative animate__animated animate__fadeInDown animate__delay-3-5s">
<div class="relative animate__animated animate__fadeInDown animate__delay-lg animate__duration-fast">
<button
@click="toggleLangDropdown"
class="flex items-center text-text-secondary hover:text-text"
@ -93,7 +91,7 @@ const emit = defineEmits(['changeLanguage']);
<div
v-show="isLangDropdownOpen"
class="absolute right-0 mt-2 w-40 bg-background-light rounded-md shadow-lg py-1 z-10 animate__animated animate__fadeIn animate__faster"
class="absolute right-0 mt-2 w-40 bg-background-light rounded-md shadow-lg py-1 z-10 animate__animated animate__fadeIn animate__duration-very-fast"
>
<button
v-for="lang in languages"
@ -111,7 +109,7 @@ const emit = defineEmits(['changeLanguage']);
<!-- Mobile Menu Button -->
<button
@click="toggleMenu"
class="md:hidden text-text-secondary hover:text-text focus:outline-none animate__animated animate__fadeIn"
class="md:hidden text-text-secondary hover:text-text focus:outline-none animate__animated animate__fadeIn animate__duration-fast"
>
<svg
xmlns="http://www.w3.org/2000/svg"
@ -141,7 +139,7 @@ const emit = defineEmits(['changeLanguage']);
<!-- Mobile Menu -->
<div
v-show="isMenuOpen"
class="md:hidden bg-background-light mt-4 rounded-lg py-4 px-6 shadow-lg animate__animated"
class="md:hidden bg-background-light mt-4 rounded-lg py-4 px-6 shadow-lg animate__animated animate__duration-fast"
:class="{'animate__fadeIn': isMenuOpen, 'animate__fadeOut': !isMenuOpen}"
>
<div class="flex flex-col space-y-4">
@ -149,15 +147,13 @@ const emit = defineEmits(['changeLanguage']);
v-for="(item, index) in navItems"
:key="item.path"
:to="item.path"
class="text-text-secondary hover:text-text py-2 animate__animated animate__fadeInRight"
class="text-text-secondary hover:text-text py-2 animate__animated animate__fadeInRight animate__duration-fast"
:class="{
'text-primary-light font-medium': $route.path === item.path,
'animate__delay-0-5s': index === 1,
'animate__delay-1s': index === 2,
'animate__delay-1-5s': index === 3,
'animate__delay-2s': index === 4,
'animate__delay-2-5s': index === 5,
'animate__delay-3s': index === 6
'animate__delay-xs': index === 1,
'animate__delay-sm': index === 2,
'animate__delay-md': index === 3,
'animate__delay-lg': index === 4
}"
@click="isMenuOpen = false"
>
@ -165,7 +161,7 @@ const emit = defineEmits(['changeLanguage']);
</router-link>
<!-- Mobile Language Selector -->
<div class="py-2 border-t border-background animate__animated animate__fadeInUp animate__delay-3-5s">
<div class="py-2 border-t border-background animate__animated animate__fadeInUp animate__delay-lg animate__duration-fast">
<p class="text-text-secondary mb-2">{{ t('language.en') }}</p>
<div class="flex flex-col space-y-2">
<button


+ 138
- 1
src/i18n/locales/en.json View File

@ -111,12 +111,149 @@
"email": {
"info": "info@mose.io",
"support": "support@mose.io"
},
"hero": {
"title": "Contact Us",
"subtitle": "Have questions or suggestions? We'd love to hear from you"
},
"form": {
"name": "Your Name",
"email": "Email Address",
"subject": "Subject",
"message": "Message",
"submit": "Send Message",
"success": "Your message has been sent. We'll get back to you soon!",
"error": "There was an error sending your message. Please try again later."
},
"info": {
"title": "Contact Information",
"address": "Address",
"address_value": "1 Century Avenue, Pudong, Shanghai, China",
"phone": "Phone",
"phone_value": "+86 123 4567 8910",
"hours": "Working Hours",
"hours_value": "Monday - Friday: 9:00 AM - 6:00 PM"
},
"social": {
"title": "Social Media",
"follow": "Follow Us"
}
},
"community": {
"hero": {
"title": "MOSE Community",
"subtitle": "Join our vibrant community and help build the future of blockchain"
},
"join": {
"title": "Join Our Community",
"subtitle": "Connect and learn with developers, users, and enthusiasts from around the world"
},
"channels": {
"title": "Community Channels",
"discord": {
"title": "Discord",
"description": "Join our Discord server for real-time discussions with developers and community members",
"button": "Join Discord"
},
"telegram": {
"title": "Telegram",
"description": "Get the latest news and announcements through our Telegram channel",
"button": "Join Telegram"
},
"twitter": {
"title": "Twitter",
"description": "Follow us on Twitter for updates and industry insights",
"button": "Follow on Twitter"
},
"forum": {
"title": "Forum",
"description": "Participate in in-depth discussions, share ideas, and make proposals",
"button": "Visit Forum"
}
},
"events": {
"title": "Community Events",
"upcoming": "Upcoming Events",
"past": "Past Events",
"virtual": "Virtual",
"inperson": "In-person",
"register": "Register",
"watch": "Watch Recording"
},
"contributors": {
"title": "Community Contributors",
"description": "Thank you to all the community members who have contributed to the MOSE ecosystem",
"become": "Become a Contributor"
}
},
"faq": {
"hero": {
"title": "Frequently Asked Questions",
"subtitle": "Find answers to common questions about the MOSE platform"
},
"search": {
"placeholder": "Search questions...",
"button": "Search",
"noresults": "No results found. Try different keywords."
},
"categories": {
"all": "All",
"general": "General",
"technical": "Technical",
"ecosystem": "Ecosystem",
"token": "Token",
"development": "Development"
},
"questions": {
"general": {
"what_is_mose": {
"question": "What is MOSE?",
"answer": "MOSE is a high-performance, secure, and scalable blockchain platform designed to provide powerful infrastructure for decentralized applications. It features high throughput, low latency, and strong security, enabling developers to build next-generation blockchain applications."
},
"how_started": {
"question": "How did the MOSE project start?",
"answer": "The MOSE project was founded in 2021 by a group of blockchain technology experts and industry leaders who saw the limitations of existing blockchain technologies and wanted to create a more efficient and secure solution."
}
},
"technical": {
"consensus": {
"question": "What consensus mechanism does MOSE use?",
"answer": "MOSE uses an innovative hybrid consensus mechanism that combines the benefits of Proof of Stake (PoS) and Practical Byzantine Fault Tolerance (PBFT) to provide high throughput and fast finality."
},
"tps": {
"question": "What is MOSE's transaction processing capacity?",
"answer": "MOSE can process thousands of transactions per second (TPS) while maintaining low latency and high security, making it ideal for high-performance blockchain applications."
}
},
"ecosystem": {
"projects": {
"question": "What projects are currently building on MOSE?",
"answer": "The MOSE ecosystem includes various projects, including DeFi protocols, NFT platforms, gaming applications, and social networks. You can view all projects on our Ecosystem page."
},
"partners": {
"question": "Who are MOSE's partners?",
"answer": "MOSE has established strategic partnerships with leading blockchain companies, research institutions, and enterprises to advance the development and application of blockchain technology."
}
}
},
"more": {
"title": "Still have questions?",
"contact": "Contact Us",
"community": "Join the Community"
}
},
"common": {
"loading": "Loading...",
"error": "An error occurred",
"success": "Success!",
"linkedin": "LinkedIn"
"linkedin": "LinkedIn",
"readMore": "Read More",
"viewAll": "View All",
"learnMore": "Learn More",
"comingSoon": "Coming Soon",
"submit": "Submit",
"cancel": "Cancel",
"back": "Back",
"next": "Next"
}
}

+ 138
- 1
src/i18n/locales/ja.json View File

@ -111,12 +111,149 @@
"email": {
"info": "info@mose.io",
"support": "support@mose.io"
},
"hero": {
"title": "お問い合わせ",
"subtitle": "ご質問やご提案がありますか?お気軽にお問い合わせください"
},
"form": {
"name": "お名前",
"email": "メールアドレス",
"subject": "件名",
"message": "メッセージ",
"submit": "送信する",
"success": "メッセージが送信されました。近日中にご連絡いたします。",
"error": "メッセージの送信中にエラーが発生しました。後ほど再試行してください。"
},
"info": {
"title": "連絡先情報",
"address": "住所",
"address_value": "中国上海市浦東新区世紀大道1号",
"phone": "電話番号",
"phone_value": "+86 123 4567 8910",
"hours": "営業時間",
"hours_value": "月曜日〜金曜日:9:00 - 18:00"
},
"social": {
"title": "ソーシャルメディア",
"follow": "フォローする"
}
},
"community": {
"hero": {
"title": "MOSEコミュニティ",
"subtitle": "活気あるコミュニティに参加して、ブロックチェーンの未来を一緒に構築しましょう"
},
"join": {
"title": "コミュニティに参加する",
"subtitle": "世界中の開発者、ユーザー、愛好家とつながり、学びましょう"
},
"channels": {
"title": "コミュニティチャネル",
"discord": {
"title": "Discord",
"description": "開発者やコミュニティメンバーとリアルタイムでディスカッションするためにDiscordサーバーに参加しましょう",
"button": "Discordに参加"
},
"telegram": {
"title": "Telegram",
"description": "Telegramチャンネルを通じて最新ニュースとお知らせを入手しましょう",
"button": "Telegramに参加"
},
"twitter": {
"title": "Twitter",
"description": "最新情報や業界の洞察を得るためにTwitterをフォローしましょう",
"button": "Twitterでフォロー"
},
"forum": {
"title": "フォーラム",
"description": "深い議論に参加し、アイデアを共有し、提案を行いましょう",
"button": "フォーラムを訪問"
}
},
"events": {
"title": "コミュニティイベント",
"upcoming": "今後のイベント",
"past": "過去のイベント",
"virtual": "オンライン",
"inperson": "対面",
"register": "登録",
"watch": "録画を見る"
},
"contributors": {
"title": "コミュニティ貢献者",
"description": "MOSEエコシステムに貢献してくださったすべてのコミュニティメンバーに感謝します",
"become": "貢献者になる"
}
},
"faq": {
"hero": {
"title": "よくある質問",
"subtitle": "MOSEプラットフォームに関するよくある質問への回答を見つけましょう"
},
"search": {
"placeholder": "質問を検索...",
"button": "検索",
"noresults": "結果が見つかりません。別のキーワードをお試しください。"
},
"categories": {
"all": "すべて",
"general": "一般",
"technical": "技術",
"ecosystem": "エコシステム",
"token": "トークン",
"development": "開発"
},
"questions": {
"general": {
"what_is_mose": {
"question": "MOSEとは何ですか?",
"answer": "MOSEは、分散型アプリケーションのための強力なインフラストラクチャを提供するために設計された、高性能、セキュア、スケーラブルなブロックチェーンプラットフォームです。高いスループット、低レイテンシー、強力なセキュリティを特徴とし、開発者が次世代のブロックチェーンアプリケーションを構築できるようにします。"
},
"how_started": {
"question": "MOSEプロジェクトはどのように始まりましたか?",
"answer": "MOSEプロジェクトは、既存のブロックチェーン技術の限界を見て、より効率的で安全なソリューションを作りたいと考えたブロックチェーン技術の専門家と業界リーダーのグループによって2021年に設立されました。"
}
},
"technical": {
"consensus": {
"question": "MOSEはどのようなコンセンサスメカニズムを使用していますか?",
"answer": "MOSEは、高いスループットと高速な確定性を提供するために、プルーフオブステーク(PoS)と実用的ビザンチン障害耐性(PBFT)の利点を組み合わせた革新的なハイブリッドコンセンサスメカニズムを使用しています。"
},
"tps": {
"question": "MOSEのトランザクション処理能力はどのくらいですか?",
"answer": "MOSEは低レイテンシーと高いセキュリティを維持しながら、毎秒数千のトランザクション(TPS)を処理することができ、高性能なブロックチェーンアプリケーションに最適です。"
}
},
"ecosystem": {
"projects": {
"question": "現在MOSEで構築されているプロジェクトは何ですか?",
"answer": "MOSEエコシステムには、DeFiプロトコル、NFTプラットフォーム、ゲームアプリケーション、ソーシャルネットワークなど、さまざまなプロジェクトが含まれています。エコシステムページですべてのプロジェクトを見ることができます。"
},
"partners": {
"question": "MOSEのパートナーは誰ですか?",
"answer": "MOSEは、ブロックチェーン技術の開発と応用を促進するために、主要なブロックチェーン企業、研究機関、企業と戦略的パートナーシップを確立しています。"
}
}
},
"more": {
"title": "まだ質問がありますか?",
"contact": "お問い合わせ",
"community": "コミュニティに参加"
}
},
"common": {
"loading": "読み込み中...",
"error": "エラーが発生しました",
"success": "成功!",
"linkedin": "LinkedIn"
"linkedin": "LinkedIn",
"readMore": "もっと読む",
"viewAll": "すべて表示",
"learnMore": "詳細を見る",
"comingSoon": "近日公開",
"submit": "送信",
"cancel": "キャンセル",
"back": "戻る",
"next": "次へ"
}
}

+ 138
- 1
src/i18n/locales/zh.json View File

@ -111,12 +111,149 @@
"email": {
"info": "info@mose.io",
"support": "support@mose.io"
},
"hero": {
"title": "联系我们",
"subtitle": "有任何问题或建议?我们很乐意听取您的意见"
},
"form": {
"name": "您的姓名",
"email": "电子邮箱",
"subject": "主题",
"message": "消息内容",
"submit": "发送消息",
"success": "您的消息已发送,我们将尽快回复您",
"error": "发送消息时出错,请稍后再试"
},
"info": {
"title": "联系方式",
"address": "地址",
"address_value": "中国上海市浦东新区世纪大道1号",
"phone": "电话",
"phone_value": "+86 123 4567 8910",
"hours": "工作时间",
"hours_value": "周一至周五: 9:00 - 18:00"
},
"social": {
"title": "社交媒体",
"follow": "关注我们"
}
},
"community": {
"hero": {
"title": "MOSE社区",
"subtitle": "加入我们充满活力的社区,共同构建区块链的未来"
},
"join": {
"title": "加入我们的社区",
"subtitle": "与全球开发者、用户和爱好者一起交流和学习"
},
"channels": {
"title": "社区渠道",
"discord": {
"title": "Discord",
"description": "加入我们的Discord服务器,与开发者和社区成员实时交流",
"button": "加入Discord"
},
"telegram": {
"title": "Telegram",
"description": "通过Telegram获取最新消息和公告",
"button": "加入Telegram"
},
"twitter": {
"title": "Twitter",
"description": "关注我们的Twitter账号,了解最新动态和行业见解",
"button": "关注Twitter"
},
"forum": {
"title": "论坛",
"description": "参与深度讨论,分享想法和提出建议",
"button": "访问论坛"
}
},
"events": {
"title": "社区活动",
"upcoming": "即将举行的活动",
"past": "往期活动",
"virtual": "线上",
"inperson": "线下",
"register": "注册",
"watch": "观看回放"
},
"contributors": {
"title": "社区贡献者",
"description": "感谢所有为MOSE生态系统做出贡献的社区成员",
"become": "成为贡献者"
}
},
"faq": {
"hero": {
"title": "常见问题",
"subtitle": "查找有关MOSE平台的常见问题解答"
},
"search": {
"placeholder": "搜索问题...",
"button": "搜索",
"noresults": "未找到结果,请尝试其他关键词"
},
"categories": {
"all": "全部",
"general": "一般问题",
"technical": "技术问题",
"ecosystem": "生态系统",
"token": "代币相关",
"development": "开发相关"
},
"questions": {
"general": {
"what_is_mose": {
"question": "什么是MOSE?",
"answer": "MOSE是一个高性能、安全和可扩展的区块链平台,旨在为去中心化应用提供强大的基础设施。它具有高吞吐量、低延迟和强大的安全性,使开发者能够构建下一代的区块链应用。"
},
"how_started": {
"question": "MOSE项目是如何开始的?",
"answer": "MOSE项目由一群区块链技术专家和行业领导者于2021年创立,他们看到了当前区块链技术的局限性,并希望创建一个更高效、更安全的解决方案。"
}
},
"technical": {
"consensus": {
"question": "MOSE使用什么共识机制?",
"answer": "MOSE使用一种创新的混合共识机制,结合了权益证明(PoS)和实用拜占庭容错(PBFT)的优点,提供高吞吐量和快速最终确定性。"
},
"tps": {
"question": "MOSE的交易处理能力如何?",
"answer": "MOSE能够处理每秒数千笔交易(TPS),同时保持低延迟和高安全性,这使其成为高性能区块链应用的理想平台。"
}
},
"ecosystem": {
"projects": {
"question": "目前有哪些项目在MOSE上构建?",
"answer": "MOSE生态系统包括各种项目,包括DeFi协议、NFT平台、游戏应用和社交网络等。您可以在我们的生态系统页面查看所有项目。"
},
"partners": {
"question": "MOSE有哪些合作伙伴?",
"answer": "MOSE与多家领先的区块链公司、研究机构和企业建立了战略合作伙伴关系,共同推动区块链技术的发展和应用。"
}
}
},
"more": {
"title": "还有其他问题?",
"contact": "联系我们",
"community": "加入社区"
}
},
"common": {
"loading": "加载中...",
"error": "发生错误",
"success": "成功!",
"linkedin": "领英"
"linkedin": "领英",
"readMore": "阅读更多",
"viewAll": "查看全部",
"learnMore": "了解更多",
"comingSoon": "即将推出",
"submit": "提交",
"cancel": "取消",
"back": "返回",
"next": "下一步"
}
}

+ 15
- 0
src/router/index.ts View File

@ -16,6 +16,21 @@ const routes = [
name: 'About',
component: () => import('@/views/About.vue')
},
{
path: '/community',
name: 'Community',
component: () => import('@/views/Community.vue')
},
{
path: '/faq',
name: 'FAQ',
component: () => import('@/views/FAQ.vue')
},
{
path: '/contact',
name: 'Contact',
component: () => import('@/views/Contact.vue')
},
{
path: '/:pathMatch(.*)*',
name: 'NotFound',


+ 22
- 22
src/views/About.vue View File

@ -66,10 +66,10 @@ const milestones = [
<section class="relative py-24 px-6 md:px-12 lg:px-24 bg-background-dark overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown animate__duration-fast">
{{ t('about.hero.title') }}
</h1>
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-0-5s">
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-xs animate__duration-fast">
{{ t('about.hero.subtitle') }}
</p>
</div>
@ -78,8 +78,8 @@ const milestones = [
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-10">
<div class="absolute -top-24 -left-24 w-64 h-64 rounded-full bg-primary-light blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-1s"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-2s"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-md"></div>
</div>
</section>
@ -87,15 +87,15 @@ const milestones = [
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="max-w-3xl mx-auto">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-6 wow animate__animated animate__fadeInUp">{{ t('about.story.title') }}</h2>
<h2 class="text-2xl md:text-3xl font-bold text-text mb-6 wow animate__animated animate__fadeInUp animate__duration-fast">{{ t('about.story.title') }}</h2>
<div class="space-y-6 text-text-secondary">
<p class="wow animate__animated animate__fadeInUp">
<p class="wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('about.story.paragraph1') }}
</p>
<p class="wow animate__animated animate__fadeInUp animate__delay-0-5s">
<p class="wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast">
{{ t('about.story.paragraph2') }}
</p>
<p class="wow animate__animated animate__fadeInUp animate__delay-1s">
<p class="wow animate__animated animate__fadeInUp animate__delay-sm animate__duration-fast">
{{ t('about.story.paragraph3') }}
</p>
</div>
@ -106,7 +106,7 @@ const milestones = [
<!-- Team Section -->
<section class="py-16 px-6 md:px-12 lg:px-24 bg-background-light">
<div class="container mx-auto">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 text-center wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 text-center wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('about.team.title') }}
</h2>
@ -114,11 +114,11 @@ const milestones = [
<div
v-for="(member, index) in teamMembers"
:key="member.id"
class="bg-background rounded-xl overflow-hidden shadow-card hover:shadow-lg transition-all duration-300 wow animate__animated animate__fadeInUp"
class="bg-background rounded-xl overflow-hidden shadow-card hover:shadow-lg transition-all duration-300 wow animate__animated animate__fadeInUp animate__duration-fast"
:class="{
'animate__delay-0-5s': index === 1,
'animate__delay-1s': index === 2,
'animate__delay-1-5s': index === 3
'animate__delay-xs': index === 1,
'animate__delay-sm': index === 2,
'animate__delay-md': index === 3
}"
>
<img :src="member.image" :alt="member.name" class="w-full h-48 object-cover" />
@ -145,7 +145,7 @@ const milestones = [
<!-- Milestones Section -->
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 text-center wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 text-center wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('about.milestones.title') }}
</h2>
@ -159,23 +159,23 @@ const milestones = [
<div
v-for="(milestone, index) in milestones"
:key="index"
class="relative wow animate__animated"
class="relative wow animate__animated animate__duration-fast"
:class="{
'animate__fadeInLeft': index % 2 === 0,
'animate__fadeInRight': index % 2 !== 0,
'animate__delay-0-5s': index === 1,
'animate__delay-1s': index === 2,
'animate__delay-1-5s': index === 3
'animate__delay-xs': index === 1,
'animate__delay-sm': index === 2,
'animate__delay-md': index === 3
}"
>
<div class="flex flex-col md:flex-row items-center">
<!-- Year Bubble -->
<div
class="absolute left-6 md:left-1/2 w-12 h-12 bg-primary rounded-full flex items-center justify-center transform -translate-x-1/2 z-10 wow animate__animated animate__zoomIn"
class="absolute left-6 md:left-1/2 w-12 h-12 bg-primary rounded-full flex items-center justify-center transform -translate-x-1/2 z-10 wow animate__animated animate__zoomIn animate__duration-fast"
:class="{
'animate__delay-0-5s': index === 1,
'animate__delay-1s': index === 2,
'animate__delay-1-5s': index === 3
'animate__delay-xs': index === 1,
'animate__delay-sm': index === 2,
'animate__delay-md': index === 3
}"
>
<span class="text-text font-bold text-sm">{{ milestone.year }}</span>


+ 293
- 0
src/views/Community.vue View File

@ -0,0 +1,293 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { ref } from 'vue';
const { t } = useI18n();
//
const upcomingEvents = ref([
{
id: 1,
title: 'MOSE 开发者大会',
date: '2023-12-15',
type: 'virtual',
image: '/public/images.png'
},
{
id: 2,
title: 'MOSE 区块链峰会',
date: '2024-01-20',
type: 'inperson',
image: '/public/images.png'
},
{
id: 3,
title: 'MOSE 黑客松',
date: '2024-02-10',
type: 'virtual',
image: '/public/images.png'
}
]);
const pastEvents = ref([
{
id: 4,
title: 'MOSE 生态系统发布会',
date: '2023-06-05',
type: 'virtual',
image: '/public/images.png',
recording: '#'
},
{
id: 5,
title: 'MOSE 技术研讨会',
date: '2023-08-12',
type: 'inperson',
image: '/public/images.png',
recording: '#'
}
]);
//
const contributors = ref([
{
id: 1,
name: 'Alex Johnson',
role: 'Core Developer',
image: '/public/vite.svg',
github: 'https://github.com'
},
{
id: 2,
name: 'Sarah Chen',
role: 'UI/UX Designer',
image: '/public/vite.svg',
github: 'https://github.com'
},
{
id: 3,
name: 'David Kim',
role: 'Community Manager',
image: '/public/vite.svg',
github: 'https://github.com'
},
{
id: 4,
name: 'Maria Rodriguez',
role: 'Documentation',
image: '/public/vite.svg',
github: 'https://github.com'
}
]);
</script>
<template>
<div class="bg-background min-h-screen">
<!-- Hero Section -->
<section class="relative py-32 px-6 md:px-12 lg:px-24 bg-background-dark overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown animate__duration-fast">
{{ t('community.hero.title') }}
</h1>
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-sm">
{{ t('community.hero.subtitle') }}
</p>
</div>
</div>
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-10">
<div class="absolute -top-24 -left-24 w-64 h-64 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-md"></div>
</div>
</section>
<!-- Community Channels Section -->
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="max-w-3xl mx-auto text-center mb-16">
<h2 class="text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp">
{{ t('community.join.title') }}
</h2>
<p class="text-text-secondary wow animate__animated animate__fadeInUp animate__delay-xs">
{{ t('community.join.subtitle') }}
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Discord -->
<div class="bg-background-light rounded-xl p-6 shadow-card wow animate__animated animate__fadeInUp">
<div class="h-16 w-16 bg-primary/20 rounded-full flex items-center justify-center mb-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-primary-light" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.608 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1634-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/>
</svg>
</div>
<h3 class="text-xl font-bold text-text mb-2">{{ t('community.channels.discord.title') }}</h3>
<p class="text-text-secondary mb-4">{{ t('community.channels.discord.description') }}</p>
<a href="#" class="inline-block px-6 py-2 bg-primary text-text rounded-lg btn-hover-float">
{{ t('community.channels.discord.button') }}
</a>
</div>
<!-- Telegram -->
<div class="bg-background-light rounded-xl p-6 shadow-card wow animate__animated animate__fadeInUp animate__delay-xs">
<div class="h-16 w-16 bg-primary/20 rounded-full flex items-center justify-center mb-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-primary-light" fill="currentColor" viewBox="0 0 24 24">
<path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.96 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/>
</svg>
</div>
<h3 class="text-xl font-bold text-text mb-2">{{ t('community.channels.telegram.title') }}</h3>
<p class="text-text-secondary mb-4">{{ t('community.channels.telegram.description') }}</p>
<a href="#" class="inline-block px-6 py-2 bg-primary text-text rounded-lg btn-hover-float">
{{ t('community.channels.telegram.button') }}
</a>
</div>
<!-- Twitter -->
<div class="bg-background-light rounded-xl p-6 shadow-card wow animate__animated animate__fadeInUp animate__delay-sm">
<div class="h-16 w-16 bg-primary/20 rounded-full flex items-center justify-center mb-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-primary-light" fill="currentColor" viewBox="0 0 24 24">
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
</svg>
</div>
<h3 class="text-xl font-bold text-text mb-2">{{ t('community.channels.twitter.title') }}</h3>
<p class="text-text-secondary mb-4">{{ t('community.channels.twitter.description') }}</p>
<a href="#" class="inline-block px-6 py-2 bg-primary text-text rounded-lg btn-hover-float">
{{ t('community.channels.twitter.button') }}
</a>
</div>
<!-- Forum -->
<div class="bg-background-light rounded-xl p-6 shadow-card wow animate__animated animate__fadeInUp animate__delay-md">
<div class="h-16 w-16 bg-primary/20 rounded-full flex items-center justify-center mb-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-primary-light" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z" />
</svg>
</div>
<h3 class="text-xl font-bold text-text mb-2">{{ t('community.channels.forum.title') }}</h3>
<p class="text-text-secondary mb-4">{{ t('community.channels.forum.description') }}</p>
<a href="#" class="inline-block px-6 py-2 bg-primary text-text rounded-lg btn-hover-float">
{{ t('community.channels.forum.button') }}
</a>
</div>
</div>
</div>
</section>
<!-- Community Events Section -->
<section class="py-16 px-6 md:px-12 lg:px-24 bg-background-light">
<div class="container mx-auto">
<h2 class="text-3xl font-bold text-text mb-12 text-center wow animate__animated animate__fadeInUp">
{{ t('community.events.title') }}
</h2>
<!-- Upcoming Events -->
<div class="mb-16">
<h3 class="text-2xl font-bold text-text mb-6 wow animate__animated animate__fadeInUp">
{{ t('community.events.upcoming') }}
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div v-for="event in upcomingEvents" :key="event.id" class="bg-background rounded-xl overflow-hidden shadow-card wow animate__animated animate__fadeInUp">
<div class="relative h-48 overflow-hidden">
<img :src="event.image" :alt="event.title" class="w-full h-full object-cover" />
<div class="absolute top-4 right-4 px-3 py-1 rounded-full" :class="event.type === 'virtual' ? 'bg-secondary' : 'bg-accent'">
<span class="text-xs font-medium text-text">
{{ t(`community.events.${event.type}`) }}
</span>
</div>
</div>
<div class="p-6">
<h4 class="text-xl font-bold text-text mb-2">{{ event.title }}</h4>
<p class="text-text-secondary mb-4">{{ event.date }}</p>
<button class="px-6 py-2 bg-primary text-text rounded-lg w-full btn-hover-glow">
{{ t('community.events.register') }}
</button>
</div>
</div>
</div>
</div>
<!-- Past Events -->
<div>
<h3 class="text-2xl font-bold text-text mb-6 wow animate__animated animate__fadeInUp">
{{ t('community.events.past') }}
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div v-for="event in pastEvents" :key="event.id" class="bg-background rounded-xl overflow-hidden shadow-card wow animate__animated animate__fadeInUp">
<div class="relative h-48 overflow-hidden">
<img :src="event.image" :alt="event.title" class="w-full h-full object-cover opacity-70" />
<div class="absolute top-4 right-4 px-3 py-1 rounded-full" :class="event.type === 'virtual' ? 'bg-secondary' : 'bg-accent'">
<span class="text-xs font-medium text-text">
{{ t(`community.events.${event.type}`) }}
</span>
</div>
</div>
<div class="p-6">
<h4 class="text-xl font-bold text-text mb-2">{{ event.title }}</h4>
<p class="text-text-secondary mb-4">{{ event.date }}</p>
<a :href="event.recording" class="px-6 py-2 bg-transparent border border-primary-light text-primary-light rounded-lg flex items-center justify-center btn-hover-shadow">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
{{ t('community.events.watch') }}
</a>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Community Contributors Section -->
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="max-w-3xl mx-auto text-center mb-12">
<h2 class="text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp">
{{ t('community.contributors.title') }}
</h2>
<p class="text-text-secondary wow animate__animated animate__fadeInUp animate__delay-xs">
{{ t('community.contributors.description') }}
</p>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
<div v-for="contributor in contributors" :key="contributor.id" class="bg-background-light rounded-xl p-6 text-center shadow-card wow animate__animated animate__fadeInUp">
<div class="w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden">
<img :src="contributor.image" :alt="contributor.name" class="w-full h-full object-cover" />
</div>
<h4 class="text-xl font-bold text-text mb-1">{{ contributor.name }}</h4>
<p class="text-text-secondary mb-4">{{ contributor.role }}</p>
<a :href="contributor.github" class="text-primary-light hover:text-primary flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
</svg>
GitHub
</a>
</div>
</div>
<div class="text-center">
<a href="#" class="inline-block px-8 py-3 bg-primary text-text rounded-lg btn-hover-scale">
{{ t('community.contributors.become') }}
</a>
</div>
</div>
</section>
</div>
</template>
<style scoped>
.shadow-card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.shadow-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
}
</style>

+ 286
- 0
src/views/Contact.vue View File

@ -0,0 +1,286 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { ref } from 'vue';
const { t } = useI18n();
//
const formData = ref({
name: '',
email: '',
subject: '',
message: ''
});
//
const isSubmitting = ref(false);
const formSubmitted = ref(false);
const formError = ref(false);
//
const submitForm = () => {
isSubmitting.value = true;
// API
setTimeout(() => {
isSubmitting.value = false;
formSubmitted.value = true;
//
formData.value = {
name: '',
email: '',
subject: '',
message: ''
};
// 3
setTimeout(() => {
formSubmitted.value = false;
}, 3000);
}, 1000);
};
</script>
<template>
<div class="bg-background min-h-screen">
<!-- Hero Section -->
<section class="relative py-32 px-6 md:px-12 lg:px-24 bg-background-dark overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown animate__duration-fast">
{{ t('contact.hero.title') }}
</h1>
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-sm">
{{ t('contact.hero.subtitle') }}
</p>
</div>
</div>
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-10">
<div class="absolute -top-24 -left-24 w-64 h-64 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-md"></div>
</div>
</section>
<!-- Contact Form Section -->
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="grid grid-cols-1 lg:grid-cols-5 gap-12">
<!-- Contact Form -->
<div class="lg:col-span-3 wow animate__animated animate__fadeInLeft">
<div class="bg-background-light rounded-xl p-8 shadow-card">
<h2 class="text-2xl font-bold text-text mb-6">{{ t('contact.hero.title') }}</h2>
<!-- Success Message -->
<div v-if="formSubmitted" class="mb-6 p-4 bg-secondary bg-opacity-20 rounded-lg border border-secondary">
<p class="text-secondary">{{ t('contact.form.success') }}</p>
</div>
<!-- Error Message -->
<div v-if="formError" class="mb-6 p-4 bg-red-500 bg-opacity-20 rounded-lg border border-red-500">
<p class="text-red-500">{{ t('contact.form.error') }}</p>
</div>
<!-- Form -->
<form @submit.prevent="submitForm">
<div class="mb-4">
<label for="name" class="block text-text-secondary mb-2">{{ t('contact.form.name') }}</label>
<input
type="text"
id="name"
v-model="formData.name"
class="w-full px-4 py-3 bg-background rounded-lg text-text focus:outline-none focus:ring-2 focus:ring-primary"
required
/>
</div>
<div class="mb-4">
<label for="email" class="block text-text-secondary mb-2">{{ t('contact.form.email') }}</label>
<input
type="email"
id="email"
v-model="formData.email"
class="w-full px-4 py-3 bg-background rounded-lg text-text focus:outline-none focus:ring-2 focus:ring-primary"
required
/>
</div>
<div class="mb-4">
<label for="subject" class="block text-text-secondary mb-2">{{ t('contact.form.subject') }}</label>
<input
type="text"
id="subject"
v-model="formData.subject"
class="w-full px-4 py-3 bg-background rounded-lg text-text focus:outline-none focus:ring-2 focus:ring-primary"
required
/>
</div>
<div class="mb-6">
<label for="message" class="block text-text-secondary mb-2">{{ t('contact.form.message') }}</label>
<textarea
id="message"
v-model="formData.message"
rows="5"
class="w-full px-4 py-3 bg-background rounded-lg text-text focus:outline-none focus:ring-2 focus:ring-primary"
required
></textarea>
</div>
<button
type="submit"
class="w-full px-6 py-3 bg-primary text-text rounded-lg shadow-button btn-hover-glow"
:disabled="isSubmitting"
>
<span v-if="isSubmitting">{{ t('common.loading') }}</span>
<span v-else>{{ t('contact.form.submit') }}</span>
</button>
</form>
</div>
</div>
<!-- Contact Info -->
<div class="lg:col-span-2 wow animate__animated animate__fadeInRight">
<div class="bg-background-light rounded-xl p-8 shadow-card mb-8">
<h3 class="text-xl font-bold text-text mb-6">{{ t('contact.info.title') }}</h3>
<div class="space-y-6">
<div class="flex items-start">
<div class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center mr-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-primary-light" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</div>
<div>
<h4 class="text-text font-medium mb-1">{{ t('contact.info.address') }}</h4>
<p class="text-text-secondary">{{ t('contact.info.address_value') }}</p>
</div>
</div>
<div class="flex items-start">
<div class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center mr-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-primary-light" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
<div>
<h4 class="text-text font-medium mb-1">Email</h4>
<p class="text-text-secondary">{{ t('contact.email.info') }}</p>
<p class="text-text-secondary">{{ t('contact.email.support') }}</p>
</div>
</div>
<div class="flex items-start">
<div class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center mr-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-primary-light" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
</svg>
</div>
<div>
<h4 class="text-text font-medium mb-1">{{ t('contact.info.phone') }}</h4>
<p class="text-text-secondary">{{ t('contact.info.phone_value') }}</p>
</div>
</div>
<div class="flex items-start">
<div class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center mr-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-primary-light" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div>
<h4 class="text-text font-medium mb-1">{{ t('contact.info.hours') }}</h4>
<p class="text-text-secondary">{{ t('contact.info.hours_value') }}</p>
</div>
</div>
</div>
</div>
<!-- Social Media -->
<div class="bg-background-light rounded-xl p-8 shadow-card">
<h3 class="text-xl font-bold text-text mb-6">{{ t('contact.social.title') }}</h3>
<p class="text-text-secondary mb-4">{{ t('contact.social.follow') }}</p>
<div class="flex space-x-4">
<a href="#" class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center text-primary-light hover:bg-primary hover:text-text transition-colors btn-hover-scale">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/>
</svg>
</a>
<a href="#" class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center text-primary-light hover:bg-primary hover:text-text transition-colors btn-hover-scale">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0C5.373 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.6.113.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/>
</svg>
</a>
<a href="#" class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center text-primary-light hover:bg-primary hover:text-text transition-colors btn-hover-scale">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
</svg>
</a>
<a href="#" class="h-10 w-10 bg-primary/20 rounded-full flex items-center justify-center text-primary-light hover:bg-primary hover:text-text transition-colors btn-hover-scale">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.608 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1634-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/>
</svg>
</a>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Map Section -->
<section class="py-16 px-6 md:px-12 lg:px-24 bg-background-light">
<div class="container mx-auto">
<div class="max-w-5xl mx-auto">
<div class="bg-background rounded-xl overflow-hidden shadow-card h-96 wow animate__animated animate__fadeIn">
<!-- Map Placeholder (in a real app, you'd use a real map API) -->
<div class="w-full h-full bg-background-dark flex items-center justify-center">
<div class="text-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-text-secondary mx-auto mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<p class="text-text-secondary">{{ t('contact.info.address_value') }}</p>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</template>
<style scoped>
input, textarea {
transition: box-shadow 0.3s ease;
}
input:focus, textarea:focus {
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3);
}
.btn-hover-scale {
transition: transform 0.3s ease;
}
.btn-hover-scale:hover {
transform: scale(1.1);
}
.shadow-card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.shadow-card:hover {
transform: translateY(-5px);
box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2);
}
</style>

+ 31
- 32
src/views/Ecosystem.vue View File

@ -160,10 +160,10 @@ const selectCategory = (category: string) => {
<section class="relative py-24 px-6 md:px-12 lg:px-24 bg-background-dark overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown animate__duration-fast">
{{ t('ecosystem.title') }}
</h1>
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-0-5s">
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-xs animate__duration-fast">
{{ t('ecosystem.subtitle') }}
</p>
</div>
@ -172,8 +172,8 @@ const selectCategory = (category: string) => {
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-10">
<div class="absolute -top-24 -left-24 w-64 h-64 rounded-full bg-primary-light blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-1s"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-2s"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-md"></div>
</div>
</section>
@ -181,10 +181,10 @@ const selectCategory = (category: string) => {
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="flex justify-between items-center mb-10">
<h2 class="text-2xl md:text-3xl font-bold text-text wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('ecosystem.projects.featured') }}
</h2>
<a href="#all-projects" class="text-primary-light hover:text-primary-dark transition-colors duration-200 wow animate__animated animate__fadeInUp">
<a href="#all-projects" class="text-primary-light hover:text-primary-dark transition-colors duration-200 wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('ecosystem.projects.viewAll') }}
</a>
</div>
@ -193,10 +193,10 @@ const selectCategory = (category: string) => {
<div
v-for="(project, index) in featuredProjects"
:key="project.id"
class="bg-background-light rounded-xl overflow-hidden shadow-card hover:transform hover:scale-105 transition-all duration-300 wow animate__animated animate__fadeInUp"
class="bg-background-light rounded-xl overflow-hidden shadow-card hover:transform hover:scale-105 transition-all duration-300 wow animate__animated animate__fadeInUp animate__duration-fast"
:class="{
'animate__delay-0-5s': index === 1,
'animate__delay-1s': index === 2
'animate__delay-xs': index === 1,
'animate__delay-sm': index === 2
}"
>
<img :src="project.image" :alt="project.name" class="w-full h-48 object-cover" />
@ -225,12 +225,12 @@ const selectCategory = (category: string) => {
<!-- All Projects Section -->
<section id="all-projects" class="py-16 px-6 md:px-12 lg:px-24 bg-background-light">
<div class="container mx-auto">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('ecosystem.title') }}
</h2>
<!-- Categories Filter -->
<div class="flex flex-wrap gap-2 mb-10 wow animate__animated animate__fadeInUp animate__delay-0-5s">
<div class="flex flex-wrap gap-2 mb-10 wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast">
<button
v-for="category in categories"
:key="category.id"
@ -249,11 +249,11 @@ const selectCategory = (category: string) => {
<div
v-for="(project, index) in filteredProjects"
:key="project.id"
class="bg-background rounded-xl overflow-hidden shadow-card hover:shadow-lg transition-all duration-300 wow animate__animated animate__fadeIn"
class="bg-background rounded-xl overflow-hidden shadow-card hover:shadow-lg transition-all duration-300 wow animate__animated animate__fadeIn animate__duration-fast"
:class="{
'animate__delay-0-5s': index % 4 === 1,
'animate__delay-1s': index % 4 === 2,
'animate__delay-1-5s': index % 4 === 3
'animate__delay-xs': index % 4 === 1,
'animate__delay-sm': index % 4 === 2,
'animate__delay-md': index % 4 === 3
}"
>
<img :src="project.image" :alt="project.name" class="w-full h-40 object-cover" />
@ -283,10 +283,10 @@ const selectCategory = (category: string) => {
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="text-center mb-12">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('ecosystem.partners.title') }}
</h2>
<p class="text-text-secondary max-w-2xl mx-auto wow animate__animated animate__fadeInUp animate__delay-0-5s">
<p class="text-text-secondary max-w-2xl mx-auto wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast">
{{ t('ecosystem.partners.subtitle') }}
</p>
</div>
@ -298,13 +298,12 @@ const selectCategory = (category: string) => {
:href="partner.url"
target="_blank"
rel="noopener noreferrer"
class="flex items-center justify-center p-6 bg-background-light rounded-lg hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__fadeIn"
class="flex items-center justify-center p-6 bg-background-light rounded-lg hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__fadeIn animate__duration-fast"
:class="{
'animate__delay-0-5s': index % 6 === 1,
'animate__delay-1s': index % 6 === 2,
'animate__delay-1-5s': index % 6 === 3,
'animate__delay-2s': index % 6 === 4,
'animate__delay-2-5s': index % 6 === 5
'animate__delay-xs': index % 6 === 1,
'animate__delay-sm': index % 6 === 2,
'animate__delay-md': index % 6 === 3,
'animate__delay-lg': index % 6 === 4
}"
>
<img :src="partner.logo" :alt="partner.name" class="max-h-12 max-w-full" />
@ -317,15 +316,15 @@ const selectCategory = (category: string) => {
<section class="py-20 px-6 md:px-12 lg:px-24 bg-primary bg-opacity-10 relative overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('ecosystem.join.title') }}
</h2>
<p class="text-text-secondary mb-8 wow animate__animated animate__fadeInUp animate__delay-0-5s">
<p class="text-text-secondary mb-8 wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast">
{{ t('ecosystem.join.subtitle') }}
</p>
<a
href="#"
class="inline-block px-8 py-3 bg-primary text-text rounded-lg hover:bg-primary-dark transition-colors duration-300 shadow-button wow animate__animated animate__fadeInUp animate__delay-1s"
class="inline-block px-8 py-3 bg-primary text-text rounded-lg hover:bg-primary-dark transition-colors duration-300 shadow-button wow animate__animated animate__fadeInUp animate__delay-sm animate__duration-fast"
>
{{ t('ecosystem.join.cta') }}
</a>
@ -335,21 +334,21 @@ const selectCategory = (category: string) => {
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-30">
<div class="absolute top-0 right-0 w-64 h-64 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute bottom-0 left-0 w-80 h-80 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-1s"></div>
<div class="absolute bottom-0 left-0 w-80 h-80 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
</div>
</section>
<!-- Developer Resources -->
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-10 wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('ecosystem.resources.title') }}
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<a
href="#"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn animate__duration-fast"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-primary-light mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
@ -362,7 +361,7 @@ const selectCategory = (category: string) => {
<a
href="#"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn animate__delay-0-5s"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn animate__delay-xs animate__duration-fast"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-primary-light mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
@ -375,7 +374,7 @@ const selectCategory = (category: string) => {
<a
href="#"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn animate__delay-1s"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn animate__delay-sm animate__duration-fast"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-primary-light mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
@ -388,7 +387,7 @@ const selectCategory = (category: string) => {
<a
href="#"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn animate__delay-1-5s"
class="bg-background-light p-6 rounded-xl flex flex-col items-center text-center hover:bg-background-dark transition-colors duration-300 wow animate__animated animate__zoomIn animate__delay-md animate__duration-fast"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 text-primary-light mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />


+ 267
- 0
src/views/FAQ.vue View File

@ -0,0 +1,267 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { ref, computed } from 'vue';
const { t } = useI18n();
//
const selectedCategory = ref('all');
//
const searchQuery = ref('');
//
const allQuestions = computed(() => {
return [
{
id: 'what_is_mose',
category: 'general',
question: t('faq.questions.general.what_is_mose.question'),
answer: t('faq.questions.general.what_is_mose.answer')
},
{
id: 'how_started',
category: 'general',
question: t('faq.questions.general.how_started.question'),
answer: t('faq.questions.general.how_started.answer')
},
{
id: 'consensus',
category: 'technical',
question: t('faq.questions.technical.consensus.question'),
answer: t('faq.questions.technical.consensus.answer')
},
{
id: 'tps',
category: 'technical',
question: t('faq.questions.technical.tps.question'),
answer: t('faq.questions.technical.tps.answer')
},
{
id: 'projects',
category: 'ecosystem',
question: t('faq.questions.ecosystem.projects.question'),
answer: t('faq.questions.ecosystem.projects.answer')
},
{
id: 'partners',
category: 'ecosystem',
question: t('faq.questions.ecosystem.partners.question'),
answer: t('faq.questions.ecosystem.partners.answer')
}
];
});
//
const filteredQuestions = computed(() => {
let questions = allQuestions.value;
//
if (selectedCategory.value !== 'all') {
questions = questions.filter(q => q.category === selectedCategory.value);
}
//
if (searchQuery.value) {
const query = searchQuery.value.toLowerCase();
questions = questions.filter(q =>
q.question.toLowerCase().includes(query) ||
q.answer.toLowerCase().includes(query)
);
}
return questions;
});
//
const setCategory = (category: string) => {
selectedCategory.value = category;
};
// /
const expandedQuestions = ref<string[]>([]);
const toggleQuestion = (id: string) => {
const index = expandedQuestions.value.indexOf(id);
if (index === -1) {
expandedQuestions.value.push(id);
} else {
expandedQuestions.value.splice(index, 1);
}
};
const isExpanded = (id: string) => {
return expandedQuestions.value.includes(id);
};
</script>
<template>
<div class="bg-background min-h-screen">
<!-- Hero Section -->
<section class="relative py-32 px-6 md:px-12 lg:px-24 bg-background-dark overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown animate__duration-fast">
{{ t('faq.hero.title') }}
</h1>
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-sm">
{{ t('faq.hero.subtitle') }}
</p>
</div>
</div>
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-10">
<div class="absolute -top-24 -left-24 w-64 h-64 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-md"></div>
</div>
</section>
<!-- Search and Filter Section -->
<section class="py-12 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="max-w-3xl mx-auto mb-12">
<!-- Search Bar -->
<div class="relative mb-8 wow animate__animated animate__fadeIn">
<input
type="text"
v-model="searchQuery"
:placeholder="t('faq.search.placeholder')"
class="w-full py-4 px-6 pr-12 bg-background-light text-text rounded-xl focus:outline-none focus:ring-2 focus:ring-primary"
/>
<button class="absolute right-4 top-1/2 transform -translate-y-1/2 text-text-secondary hover:text-primary transition-colors btn-hover-scale">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</button>
</div>
<!-- Categories -->
<div class="flex flex-wrap gap-3 justify-center wow animate__animated animate__fadeIn animate__delay-sm">
<button
@click="setCategory('all')"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors btn-hover-float"
:class="selectedCategory === 'all' ? 'bg-primary text-text' : 'bg-background-light text-text-secondary hover:bg-background-light/80'"
>
{{ t('faq.categories.all') }}
</button>
<button
@click="setCategory('general')"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors btn-hover-float"
:class="selectedCategory === 'general' ? 'bg-primary text-text' : 'bg-background-light text-text-secondary hover:bg-background-light/80'"
>
{{ t('faq.categories.general') }}
</button>
<button
@click="setCategory('technical')"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors btn-hover-float"
:class="selectedCategory === 'technical' ? 'bg-primary text-text' : 'bg-background-light text-text-secondary hover:bg-background-light/80'"
>
{{ t('faq.categories.technical') }}
</button>
<button
@click="setCategory('ecosystem')"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors btn-hover-float"
:class="selectedCategory === 'ecosystem' ? 'bg-primary text-text' : 'bg-background-light text-text-secondary hover:bg-background-light/80'"
>
{{ t('faq.categories.ecosystem') }}
</button>
<button
@click="setCategory('token')"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors btn-hover-float"
:class="selectedCategory === 'token' ? 'bg-primary text-text' : 'bg-background-light text-text-secondary hover:bg-background-light/80'"
>
{{ t('faq.categories.token') }}
</button>
<button
@click="setCategory('development')"
class="px-4 py-2 rounded-lg text-sm font-medium transition-colors btn-hover-float"
:class="selectedCategory === 'development' ? 'bg-primary text-text' : 'bg-background-light text-text-secondary hover:bg-background-light/80'"
>
{{ t('faq.categories.development') }}
</button>
</div>
</div>
<!-- FAQ Questions -->
<div class="max-w-3xl mx-auto">
<div v-if="filteredQuestions.length === 0" class="text-center py-8 text-text-secondary wow animate__animated animate__fadeIn">
{{ t('faq.search.noresults') }}
</div>
<div v-else class="space-y-4">
<div
v-for="question in filteredQuestions"
:key="question.id"
class="bg-background-light rounded-xl overflow-hidden wow animate__animated animate__fadeIn"
>
<button
@click="toggleQuestion(question.id)"
class="w-full px-6 py-4 flex justify-between items-center text-left hover:bg-background-light/80 transition-colors"
>
<h3 class="text-lg font-medium text-text">{{ question.question }}</h3>
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 text-text-secondary transition-transform duration-300"
:class="{ 'transform rotate-180': isExpanded(question.id) }"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
<div
v-show="isExpanded(question.id)"
class="px-6 py-4 border-t border-background"
>
<p class="text-text-secondary">{{ question.answer }}</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- More Questions Section -->
<section class="py-16 px-6 md:px-12 lg:px-24 bg-background-light">
<div class="container mx-auto">
<div class="max-w-3xl mx-auto text-center">
<h2 class="text-2xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp">
{{ t('faq.more.title') }}
</h2>
<div class="flex flex-col sm:flex-row justify-center gap-4 mt-8 wow animate__animated animate__fadeInUp animate__delay-sm">
<router-link
to="/contact"
class="px-8 py-3 bg-primary text-text rounded-lg hover:bg-primary-dark transition-colors duration-300 shadow-button btn-hover-glow"
>
{{ t('faq.more.contact') }}
</router-link>
<router-link
to="/community"
class="px-8 py-3 bg-transparent border border-primary-light text-primary-light rounded-lg hover:bg-primary-light hover:bg-opacity-10 transition-colors duration-300 btn-hover-shadow"
>
{{ t('faq.more.community') }}
</router-link>
</div>
</div>
</div>
</section>
</div>
</template>
<style scoped>
button {
outline: none;
}
.btn-hover-float {
transition: transform 0.3s ease;
}
.btn-hover-float:hover {
transform: translateY(-3px);
}
</style>

+ 301
- 19
src/views/Home.vue View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import { ref } from 'vue';
const { t } = useI18n();
const router = useRouter();
@ -8,6 +9,90 @@ const router = useRouter();
const goToEcosystem = () => {
router.push('/ecosystem');
};
//
const videoRef = ref<HTMLVideoElement | null>(null);
const isPlaying = ref(false);
const currentTime = ref(0);
const duration = ref(0);
const volume = ref(1);
const isMuted = ref(false);
const isFullscreen = ref(false);
// /
const togglePlay = () => {
const video = videoRef.value;
if (!video) return;
if (video.paused) {
video.play();
isPlaying.value = true;
} else {
video.pause();
isPlaying.value = false;
}
};
//
const updateProgress = () => {
const video = videoRef.value;
if (!video) return;
currentTime.value = video.currentTime;
duration.value = video.duration;
};
//
const setVideoProgress = (event: MouseEvent) => {
const video = videoRef.value;
if (!video) return;
const progressBar = event.target as HTMLElement;
const clickPosition = (event.offsetX / progressBar.offsetWidth);
video.currentTime = clickPosition * video.duration;
};
//
const setVolume = (event: Event) => {
const video = videoRef.value;
if (!video) return;
volume.value = parseFloat((event.target as HTMLInputElement).value);
video.volume = volume.value;
isMuted.value = volume.value === 0;
};
//
const toggleMute = () => {
const video = videoRef.value;
if (!video) return;
isMuted.value = !isMuted.value;
video.muted = isMuted.value;
};
//
const toggleFullscreen = () => {
const videoContainer = document.querySelector('.video-container');
if (!videoContainer) return;
if (!document.fullscreenElement) {
videoContainer.requestFullscreen().catch(err => {
console.error(`Error attempting to enable fullscreen: ${err.message}`);
});
isFullscreen.value = true;
} else {
document.exitFullscreen();
isFullscreen.value = false;
}
};
//
const formatTime = (timeInSeconds: number) => {
const minutes = Math.floor(timeInSeconds / 60);
const seconds = Math.floor(timeInSeconds % 60);
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
};
</script>
<template>
@ -16,22 +101,22 @@ const goToEcosystem = () => {
<section class="relative py-32 px-6 md:px-12 lg:px-24 bg-background-dark overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown">
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text mb-6 wow animate__animated animate__fadeInDown animate__duration-fast">
{{ t('home.hero.title') }}
</h1>
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-1s">
<p class="text-lg md:text-xl text-text-secondary mb-8 wow animate__animated animate__fadeIn animate__delay-sm">
{{ t('home.hero.subtitle') }}
</p>
<div class="flex flex-col sm:flex-row justify-center gap-4 wow animate__animated animate__fadeInUp animate__delay-1-5s">
<div class="flex flex-col sm:flex-row justify-center gap-4 wow animate__animated animate__fadeInUp animate__delay-md">
<button
@click="goToEcosystem"
class="px-8 py-3 bg-primary text-text rounded-lg hover:bg-primary-dark transition-colors duration-300 shadow-button"
class="px-8 py-3 bg-primary text-text rounded-lg transition-colors duration-300 shadow-button btn-hover-shadow"
>
{{ t('home.cta.explore') }}
</button>
<a
href="#"
class="px-8 py-3 bg-transparent border border-primary-light text-primary-light rounded-lg hover:bg-primary-light hover:bg-opacity-10 transition-colors duration-300"
class="px-8 py-3 bg-transparent border border-primary-light text-primary-light rounded-lg hover:bg-primary-light hover:bg-opacity-10 transition-colors duration-300 btn-hover-glow"
>
{{ t('home.cta.docs') }}
</a>
@ -42,21 +127,109 @@ const goToEcosystem = () => {
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-10">
<div class="absolute -top-24 -left-24 w-64 h-64 rounded-full bg-primary-light blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-1s"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-2s"></div>
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-md"></div>
</div>
</section>
<!-- Video Section -->
<section class="py-16 px-6 md:px-12 lg:px-24">
<div class="container mx-auto">
<div class="max-w-4xl mx-auto bg-background-light rounded-2xl overflow-hidden shadow-card wow animate__animated animate__fadeIn animate__duration-2s">
<video
src="/public/MOSEVideo.mp4"
controls
class="w-full h-auto"
poster="/public/images.png"
></video>
<div class="max-w-4xl mx-auto wow animate__animated animate__fadeIn animate__duration-normal">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-6 text-center">{{ t('home.video.title') }}</h2>
<!-- Custom Video Player -->
<div class="video-container bg-background-dark rounded-2xl overflow-hidden shadow-card relative">
<!-- Video Element -->
<video
ref="videoRef"
src="/public/MOSEVideo.mp4"
class="w-full h-auto"
poster="/public/images.png"
@timeupdate="updateProgress"
@click="togglePlay"
></video>
<!-- Video Controls -->
<div class="video-controls absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-4 transition-opacity duration-300 opacity-0 hover:opacity-100">
<!-- Progress Bar -->
<div
class="progress-bar h-1 bg-gray-600 rounded-full mb-3 cursor-pointer"
@click="setVideoProgress"
>
<div
class="progress bg-primary h-full rounded-full"
:style="{ width: `${(currentTime / duration) * 100 || 0}%` }"
></div>
</div>
<!-- Control Buttons -->
<div class="flex justify-between items-center">
<div class="flex items-center space-x-3">
<!-- Play/Pause Button -->
<button @click.stop="togglePlay" class="text-white hover:text-primary-light transition-colors btn-hover-scale">
<svg v-if="!isPlaying" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 9v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</button>
<!-- Volume Control -->
<div class="flex items-center space-x-1">
<button @click.stop="toggleMute" class="text-white hover:text-primary-light transition-colors btn-hover-scale">
<svg v-if="!isMuted" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
</svg>
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z" />
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2" />
</svg>
</button>
<input
type="range"
min="0"
max="1"
step="0.01"
:value="volume"
@input="setVolume"
class="w-16 accent-primary-light"
/>
</div>
<!-- Time Display -->
<div class="text-white text-sm">
{{ formatTime(currentTime) }} / {{ formatTime(duration) }}
</div>
</div>
<!-- Fullscreen Button -->
<button @click.stop="toggleFullscreen" class="text-white hover:text-primary-light transition-colors btn-hover-scale">
<svg v-if="!isFullscreen" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5v-4m0 4h-4m4 0l-5-5" />
</svg>
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
<!-- Play Button Overlay (visible when video is paused) -->
<div
v-if="!isPlaying"
class="absolute inset-0 flex items-center justify-center bg-black/30"
@click="togglePlay"
>
<div class="w-20 h-20 bg-primary/80 rounded-full flex items-center justify-center cursor-pointer hover:bg-primary transition-colors btn-hover-pulse">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
</svg>
</div>
</div>
</div>
</div>
</div>
</section>
@ -65,15 +238,15 @@ const goToEcosystem = () => {
<section class="py-20 px-6 md:px-12 lg:px-24 bg-primary bg-opacity-10 relative overflow-hidden">
<div class="container mx-auto relative z-10">
<div class="max-w-3xl mx-auto text-center">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp">
<h2 class="text-2xl md:text-3xl font-bold text-text mb-4 wow animate__animated animate__fadeInUp animate__duration-fast">
{{ t('ecosystem.join.title') }}
</h2>
<p class="text-text-secondary mb-8 wow animate__animated animate__fadeInUp animate__delay-0-5s">
<p class="text-text-secondary mb-8 wow animate__animated animate__fadeInUp animate__delay-xs animate__duration-fast">
{{ t('ecosystem.join.subtitle') }}
</p>
<button
@click="goToEcosystem"
class="inline-block px-8 py-3 bg-primary text-text rounded-lg hover:bg-primary-dark transition-colors duration-300 shadow-button wow animate__animated animate__fadeInUp animate__delay-1s"
class="inline-block px-8 py-3 bg-primary text-text rounded-lg transition-colors duration-300 shadow-button wow animate__animated animate__fadeInUp animate__delay-sm animate__duration-fast btn-hover-float"
>
{{ t('ecosystem.title') }}
</button>
@ -83,8 +256,117 @@ const goToEcosystem = () => {
<!-- Background Decoration -->
<div class="absolute top-0 left-0 w-full h-full overflow-hidden opacity-30">
<div class="absolute top-0 right-0 w-64 h-64 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite"></div>
<div class="absolute bottom-0 left-0 w-80 h-80 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-1s"></div>
<div class="absolute bottom-0 left-0 w-80 h-80 rounded-full bg-primary blur-3xl wow animate__animated animate__pulse animate__infinite animate__delay-sm"></div>
</div>
</section>
</div>
</template>
</template>
<style scoped>
.video-container {
position: relative;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.video-container:hover {
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.3);
}
.video-container:hover .video-controls {
opacity: 1;
}
.progress-bar {
position: relative;
cursor: pointer;
transition: height 0.2s ease;
}
.progress-bar:hover {
height: 4px;
}
input[type=range] {
-webkit-appearance: none;
height: 4px;
background: rgba(255, 255, 255, 0.3);
border-radius: 5px;
outline: none;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--primary-light, #64B5F6);
cursor: pointer;
}
input[type=range]::-moz-range-thumb {
width: 12px;
height: 12px;
border-radius: 50%;
background: var(--primary-light, #64B5F6);
cursor: pointer;
border: none;
}
/* 按钮悬停效果 */
.btn-hover-scale {
transition: transform var(--btn-hover-transition) ease;
}
.btn-hover-scale:hover {
transform: scale(var(--btn-scale-amount));
}
.btn-hover-float {
transition: transform var(--btn-hover-transition) ease;
}
.btn-hover-float:hover {
transform: translateY(-5px);
}
.btn-hover-shadow {
transition: box-shadow var(--btn-hover-transition) ease, transform var(--btn-hover-transition) ease;
}
.btn-hover-shadow:hover {
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
transform: translateY(-3px);
}
.btn-hover-glow {
position: relative;
overflow: hidden;
transition: all var(--btn-hover-transition) ease;
}
.btn-hover-glow:hover {
box-shadow: 0 0 var(--btn-glow-spread) var(--btn-glow-color);
}
.btn-hover-pulse {
animation: none;
}
.btn-hover-pulse:hover {
animation: btn-pulse var(--btn-pulse-duration) infinite;
}
@keyframes btn-pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(var(--btn-pulse-scale));
}
100% {
transform: scale(1);
}
}
</style>

Loading…
Cancel
Save