@ -0,0 +1,24 @@ | |||||
# Logs | |||||
logs | |||||
*.log | |||||
npm-debug.log* | |||||
yarn-debug.log* | |||||
yarn-error.log* | |||||
pnpm-debug.log* | |||||
lerna-debug.log* | |||||
node_modules | |||||
dist | |||||
dist-ssr | |||||
*.local | |||||
# Editor directories and files | |||||
.vscode/* | |||||
!.vscode/extensions.json | |||||
.idea | |||||
.DS_Store | |||||
*.suo | |||||
*.ntvs* | |||||
*.njsproj | |||||
*.sln | |||||
*.sw? |
@ -0,0 +1,3 @@ | |||||
{ | |||||
"recommendations": ["Vue.volar"] | |||||
} |
@ -0,0 +1,65 @@ | |||||
# MOSE Web | |||||
MOSE Web 是一个基于 Vue 3 和 Tailwind CSS v4 的多语言区块链项目网站。 | |||||
## 特点 | |||||
- 使用 Vue 3 和 TypeScript 构建 | |||||
- 使用 Tailwind CSS v4 进行样式设计 | |||||
- 支持多语言(中文、英文、日语) | |||||
- 响应式设计,适配桌面、平板和移动端 | |||||
- 模块化组件结构 | |||||
## 页面 | |||||
- 首页:展示项目概览和核心特点 | |||||
- 生态系统:展示项目生态系统中的应用和合作伙伴 | |||||
- 关于我们:介绍项目团队和发展历程 | |||||
- 404页面:自定义错误页面 | |||||
## 技术栈 | |||||
- Vue 3:前端框架 | |||||
- Vue Router:路由管理 | |||||
- Vue I18n:国际化 | |||||
- Tailwind CSS v4:CSS 框架 | |||||
- Vite:构建工具 | |||||
## 开发 | |||||
```bash | |||||
# 安装依赖 | |||||
npm install | |||||
# 启动开发服务器 | |||||
npm run dev | |||||
# 构建生产版本 | |||||
npm run build | |||||
# 预览生产版本 | |||||
npm run preview | |||||
``` | |||||
## 项目结构 | |||||
``` | |||||
MOSE Web/ | |||||
├── public/ # 静态资源 | |||||
├── src/ | |||||
│ ├── assets/ # 项目资源文件 | |||||
│ ├── components/ # 组件 | |||||
│ │ └── layout/ # 布局组件 | |||||
│ ├── i18n/ # 国际化 | |||||
│ │ └── locales/ # 语言文件 | |||||
│ ├── router/ # 路由 | |||||
│ ├── views/ # 页面 | |||||
│ ├── App.vue # 根组件 | |||||
│ ├── main.ts # 入口文件 | |||||
│ └── style.css # 全局样式 | |||||
├── index.html # HTML 模板 | |||||
├── package.json # 项目配置 | |||||
├── tailwind.config.js # Tailwind 配置 | |||||
├── tsconfig.json # TypeScript 配置 | |||||
└── vite.config.ts # Vite 配置 | |||||
``` |
@ -0,0 +1,20 @@ | |||||
<!doctype html> | |||||
<html lang="en"> | |||||
<head> | |||||
<meta charset="UTF-8" /> | |||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | |||||
<link href="/src/style.css" rel="stylesheet"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||||
<meta name="description" content="MOSE Blockchain - Next-generation blockchain platform for high performance, security, and scalability" /> | |||||
<meta name="keywords" content="blockchain, crypto, MOSE, DeFi, NFT, DAO" /> | |||||
<title>MOSE Blockchain</title> | |||||
<!-- Google Fonts --> | |||||
<link rel="preconnect" href="https://fonts.googleapis.com"> | |||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Montserrat:wght@500;600;700;800&display=swap" rel="stylesheet"> | |||||
</head> | |||||
<body class="bg-background"> | |||||
<div id="app"></div> | |||||
<script type="module" src="/src/main.ts"></script> | |||||
</body> | |||||
</html> |
@ -0,0 +1,26 @@ | |||||
{ | |||||
"name": "mose-web", | |||||
"private": true, | |||||
"version": "0.0.0", | |||||
"type": "module", | |||||
"scripts": { | |||||
"dev": "vite", | |||||
"build": "vue-tsc -b && vite build", | |||||
"preview": "vite preview" | |||||
}, | |||||
"dependencies": { | |||||
"@tailwindcss/vite": "^4.1.11", | |||||
"tailwindcss": "^4.1.11", | |||||
"vue": "^3.5.13", | |||||
"vue-i18n": "^11.1.9", | |||||
"vue-router": "^4.5.1" | |||||
}, | |||||
"devDependencies": { | |||||
"@types/node": "^24.0.13", | |||||
"@vitejs/plugin-vue": "^5.2.1", | |||||
"@vue/tsconfig": "^0.7.0", | |||||
"typescript": "~5.7.2", | |||||
"vite": "^6.1.0", | |||||
"vue-tsc": "^2.2.0" | |||||
} | |||||
} |
@ -0,0 +1 @@ | |||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg> |
@ -0,0 +1,43 @@ | |||||
<script setup lang="ts"> | |||||
import { ref } from 'vue'; | |||||
import { useI18n } from 'vue-i18n'; | |||||
import NavBar from '@/components/layout/NavBar.vue'; | |||||
import Footer from '@/components/layout/Footer.vue'; | |||||
const { locale } = useI18n(); | |||||
// 切换语言 | |||||
const changeLanguage = (lang: string) => { | |||||
locale.value = lang; | |||||
localStorage.setItem('language', lang); | |||||
}; | |||||
</script> | |||||
<template> | |||||
<div class="min-h-screen flex flex-col bg-background text-text"> | |||||
<NavBar @change-language="changeLanguage" /> | |||||
<main class="flex-grow"> | |||||
<router-view v-slot="{ Component }"> | |||||
<transition name="fade" mode="out-in"> | |||||
<component :is="Component" /> | |||||
</transition> | |||||
</router-view> | |||||
</main> | |||||
<Footer /> | |||||
</div> | |||||
</template> | |||||
<style> | |||||
.fade-enter-active, | |||||
.fade-leave-active { | |||||
transition: opacity 0.3s ease; | |||||
} | |||||
.fade-enter-from, | |||||
.fade-leave-to { | |||||
opacity: 0; | |||||
} | |||||
</style> | |||||
@ -0,0 +1 @@ | |||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg> |
@ -0,0 +1,41 @@ | |||||
<script setup lang="ts"> | |||||
import { ref } from 'vue' | |||||
defineProps<{ msg: string }>() | |||||
const count = ref(0) | |||||
</script> | |||||
<template> | |||||
<h1>{{ msg }}</h1> | |||||
<div class="card"> | |||||
<button type="button" @click="count++">count is {{ count }}</button> | |||||
<p> | |||||
Edit | |||||
<code>components/HelloWorld.vue</code> to test HMR | |||||
</p> | |||||
</div> | |||||
<p> | |||||
Check out | |||||
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank" | |||||
>create-vue</a | |||||
>, the official Vue + Vite starter | |||||
</p> | |||||
<p> | |||||
Learn more about IDE Support for Vue in the | |||||
<a | |||||
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support" | |||||
target="_blank" | |||||
>Vue Docs Scaling up Guide</a | |||||
>. | |||||
</p> | |||||
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p> | |||||
</template> | |||||
<style scoped> | |||||
.read-the-docs { | |||||
color: #888; | |||||
} | |||||
</style> |
@ -0,0 +1,102 @@ | |||||
<script setup lang="ts"> | |||||
import { useI18n } from 'vue-i18n'; | |||||
const { t } = useI18n(); | |||||
// 社交媒体链接 | |||||
const socialLinks = [ | |||||
{ name: 'Twitter', icon: 'twitter', url: 'https://twitter.com/mose' }, | |||||
{ name: 'Discord', icon: 'discord', url: 'https://discord.gg/mose' }, | |||||
{ name: 'Telegram', icon: 'telegram', url: 'https://t.me/mose' }, | |||||
{ name: 'GitHub', icon: 'github', url: 'https://github.com/mose' }, | |||||
]; | |||||
// 当前年份 | |||||
const currentYear = new Date().getFullYear(); | |||||
</script> | |||||
<template> | |||||
<footer class="bg-background-dark text-text-secondary py-12 px-6 md:px-12 lg:px-24"> | |||||
<div class="container mx-auto"> | |||||
<!-- Footer Top Section --> | |||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12"> | |||||
<!-- Logo & Description --> | |||||
<div> | |||||
<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> | |||||
</div> | |||||
<p class="text-sm mb-6"> | |||||
MOSE is a next-generation blockchain platform designed for high performance, security, and scalability. | |||||
</p> | |||||
<!-- Social Links --> | |||||
<div class="flex space-x-4"> | |||||
<a | |||||
v-for="link in socialLinks" | |||||
:key="link.name" | |||||
:href="link.url" | |||||
target="_blank" | |||||
rel="noopener noreferrer" | |||||
class="text-text-secondary hover:text-primary-light transition-colors duration-200" | |||||
> | |||||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"> | |||||
<!-- Simplified SVG icons for demo purposes --> | |||||
<path v-if="link.icon === 'twitter'" d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path> | |||||
<path v-if="link.icon === 'discord'" d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.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"></path> | |||||
<path v-if="link.icon === 'telegram'" d="M24 12c0 6.627-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0s12 5.373 12 12zm-6.465-3.192c-.379-.12-1.68-.523-3.037-.763a9.45 9.45 0 0 0-.398-.053c-.813-.095-1.49.597-1.001 1.319.26.437.54.873.547 1.519a20.32 20.32 0 0 1-.172 2.313c-.19.256-.385.186-.53.074a22.813 22.813 0 0 1-1.287-1.048c-.145-.127-.349-.21-.571-.264-.782-.188-1.296.276-1.001.913.026.061.074.138.148.256a9.98 9.98 0 0 0 1.579 1.911c.947.933 2.422 2.153 3.134 2.612.932.593 2.16.638 2.504.695.485.067 1.284-.117 1.478-.491.112-.214.183-.492.22-.797.073-.594.128-1.344.107-2.116a2.24 2.24 0 0 0-.169-.868c-.098-.231-.382-.454-.753-.563z"></path> | |||||
<path v-if="link.icon === 'github'" d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path> | |||||
</svg> | |||||
</a> | |||||
</div> | |||||
</div> | |||||
<!-- Quick Links --> | |||||
<div> | |||||
<h3 class="text-lg font-medium text-text mb-4">{{ t('nav.ecosystem') }}</h3> | |||||
<ul class="space-y-2"> | |||||
<li><router-link to="/ecosystem/defi" class="hover:text-primary-light transition-colors duration-200">DeFi</router-link></li> | |||||
<li><router-link to="/ecosystem/nft" class="hover:text-primary-light transition-colors duration-200">NFT</router-link></li> | |||||
<li><router-link to="/ecosystem/dao" class="hover:text-primary-light transition-colors duration-200">DAO</router-link></li> | |||||
<li><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> | |||||
<h3 class="text-lg font-medium text-text mb-4">{{ t('nav.resources') }}</h3> | |||||
<ul class="space-y-2"> | |||||
<li><router-link to="/resources/docs" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.docs') }}</router-link></li> | |||||
<li><router-link to="/resources/github" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.github') }}</router-link></li> | |||||
<li><router-link to="/resources/grants" class="hover:text-primary-light transition-colors duration-200">{{ t('ecosystem.resources.grants') }}</router-link></li> | |||||
<li><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> | |||||
<h3 class="text-lg font-medium text-text mb-4">{{ t('nav.contact') }}</h3> | |||||
<ul class="space-y-2"> | |||||
<li><a href="mailto:info@mose.io" class="hover:text-primary-light transition-colors duration-200">info@mose.io</a></li> | |||||
<li><a href="mailto:support@mose.io" class="hover:text-primary-light transition-colors duration-200">support@mose.io</a></li> | |||||
<li><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"> | |||||
© {{ 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"> | |||||
{{ t('footer.privacy') }} | |||||
</router-link> | |||||
<router-link to="/terms" class="hover:text-primary-light transition-colors duration-200"> | |||||
{{ t('footer.terms') }} | |||||
</router-link> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</footer> | |||||
</template> |
@ -0,0 +1,171 @@ | |||||
<script setup lang="ts"> | |||||
import { ref, computed } from 'vue'; | |||||
import { useI18n } from 'vue-i18n'; | |||||
import { useRouter } from 'vue-router'; | |||||
const { t, locale } = useI18n(); | |||||
const router = useRouter(); | |||||
const isMenuOpen = ref(false); | |||||
// 切换菜单 | |||||
const toggleMenu = () => { | |||||
isMenuOpen.value = !isMenuOpen.value; | |||||
}; | |||||
// 切换语言 | |||||
const changeLanguage = (lang: string) => { | |||||
emit('changeLanguage', lang); | |||||
}; | |||||
// 语言选项 | |||||
const languages = [ | |||||
{ code: 'en', name: 'English' }, | |||||
{ code: 'zh', name: '中文' }, | |||||
{ code: 'ja', name: '日本語' } | |||||
]; | |||||
// 当前语言 | |||||
const currentLanguage = computed(() => { | |||||
return languages.find(lang => lang.code === locale.value)?.name || 'English'; | |||||
}); | |||||
// 导航菜单 | |||||
const navItems = [ | |||||
{ name: t('nav.home'), path: '/' }, | |||||
{ name: t('nav.ecosystem'), path: '/ecosystem' }, | |||||
{ name: t('nav.about'), path: '/about' }, | |||||
{ name: t('nav.resources'), path: '/resources' }, | |||||
{ name: t('nav.community'), path: '/community' }, | |||||
{ name: t('nav.faq'), path: '/faq' }, | |||||
{ name: t('nav.contact'), path: '/contact' } | |||||
]; | |||||
// 语言下拉菜单 | |||||
const isLangDropdownOpen = ref(false); | |||||
const toggleLangDropdown = () => { | |||||
isLangDropdownOpen.value = !isLangDropdownOpen.value; | |||||
}; | |||||
// 定义emit | |||||
const emit = defineEmits(['changeLanguage']); | |||||
</script> | |||||
<template> | |||||
<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"> | |||||
<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> | |||||
<!-- Desktop Navigation --> | |||||
<nav class="hidden md:flex items-center space-x-6"> | |||||
<router-link | |||||
v-for="item in navItems" | |||||
:key="item.path" | |||||
:to="item.path" | |||||
class="text-text-secondary hover:text-text transition-colors duration-200" | |||||
:class="{ 'text-primary-light font-medium': $route.path === item.path }" | |||||
> | |||||
{{ item.name }} | |||||
</router-link> | |||||
<!-- Language Selector --> | |||||
<div class="relative"> | |||||
<button | |||||
@click="toggleLangDropdown" | |||||
class="flex items-center text-text-secondary hover:text-text" | |||||
> | |||||
{{ currentLanguage }} | |||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 ml-1" 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="isLangDropdownOpen" | |||||
class="absolute right-0 mt-2 w-40 bg-background-light rounded-md shadow-lg py-1 z-10" | |||||
> | |||||
<button | |||||
v-for="lang in languages" | |||||
:key="lang.code" | |||||
@click="changeLanguage(lang.code); toggleLangDropdown()" | |||||
class="block w-full text-left px-4 py-2 text-text-secondary hover:bg-background hover:text-text" | |||||
:class="{ 'text-primary-light': locale === lang.code }" | |||||
> | |||||
{{ lang.name }} | |||||
</button> | |||||
</div> | |||||
</div> | |||||
</nav> | |||||
<!-- Mobile Menu Button --> | |||||
<button | |||||
@click="toggleMenu" | |||||
class="md:hidden text-text-secondary hover:text-text focus:outline-none" | |||||
> | |||||
<svg | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
class="h-6 w-6" | |||||
fill="none" | |||||
viewBox="0 0 24 24" | |||||
stroke="currentColor" | |||||
> | |||||
<path | |||||
v-if="!isMenuOpen" | |||||
stroke-linecap="round" | |||||
stroke-linejoin="round" | |||||
stroke-width="2" | |||||
d="M4 6h16M4 12h16M4 18h16" | |||||
/> | |||||
<path | |||||
v-else | |||||
stroke-linecap="round" | |||||
stroke-linejoin="round" | |||||
stroke-width="2" | |||||
d="M6 18L18 6M6 6l12 12" | |||||
/> | |||||
</svg> | |||||
</button> | |||||
</div> | |||||
<!-- Mobile Menu --> | |||||
<div | |||||
v-show="isMenuOpen" | |||||
class="md:hidden bg-background-light mt-4 rounded-lg py-4 px-6 shadow-lg" | |||||
> | |||||
<div class="flex flex-col space-y-4"> | |||||
<router-link | |||||
v-for="item in navItems" | |||||
:key="item.path" | |||||
:to="item.path" | |||||
class="text-text-secondary hover:text-text py-2" | |||||
:class="{ 'text-primary-light font-medium': $route.path === item.path }" | |||||
@click="isMenuOpen = false" | |||||
> | |||||
{{ item.name }} | |||||
</router-link> | |||||
<!-- Mobile Language Selector --> | |||||
<div class="py-2 border-t border-background"> | |||||
<p class="text-text-secondary mb-2">{{ t('language.en') }}</p> | |||||
<div class="flex flex-col space-y-2"> | |||||
<button | |||||
v-for="lang in languages" | |||||
:key="lang.code" | |||||
@click="changeLanguage(lang.code); isMenuOpen = false" | |||||
class="text-left text-text-secondary hover:text-text" | |||||
:class="{ 'text-primary-light': locale === lang.code }" | |||||
> | |||||
{{ lang.name }} | |||||
</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</header> | |||||
<!-- Spacer to prevent content from hiding under fixed header --> | |||||
<div class="h-16"></div> | |||||
</template> |
@ -0,0 +1,34 @@ | |||||
import { createI18n } from 'vue-i18n' | |||||
import en from './locales/en.json' | |||||
import zh from './locales/zh.json' | |||||
import ja from './locales/ja.json' | |||||
// 获取浏览器语言或从本地存储中获取 | |||||
const getBrowserLanguage = () => { | |||||
const storedLanguage = localStorage.getItem('language') | |||||
if (storedLanguage) { | |||||
return storedLanguage | |||||
} | |||||
const browserLanguage = navigator.language.toLowerCase() | |||||
if (browserLanguage.includes('zh')) { | |||||
return 'zh' | |||||
} else if (browserLanguage.includes('ja')) { | |||||
return 'ja' | |||||
} else { | |||||
return 'en' // 默认英语 | |||||
} | |||||
} | |||||
const i18n = createI18n({ | |||||
legacy: false, // 使用组合式API | |||||
locale: getBrowserLanguage(), | |||||
fallbackLocale: 'en', | |||||
messages: { | |||||
en, | |||||
zh, | |||||
ja | |||||
} | |||||
}) | |||||
export default i18n |
@ -0,0 +1,55 @@ | |||||
{ | |||||
"nav": { | |||||
"home": "Home", | |||||
"ecosystem": "Ecosystem", | |||||
"about": "About", | |||||
"resources": "Resources", | |||||
"community": "Community", | |||||
"faq": "FAQ", | |||||
"contact": "Contact" | |||||
}, | |||||
"ecosystem": { | |||||
"title": "Ecosystem", | |||||
"subtitle": "Explore the MOSE ecosystem and discover the various projects and applications built on our platform", | |||||
"categories": { | |||||
"all": "All", | |||||
"defi": "DeFi", | |||||
"nft": "NFT", | |||||
"dao": "DAO", | |||||
"gaming": "Gaming", | |||||
"infrastructure": "Infrastructure", | |||||
"social": "Social" | |||||
}, | |||||
"projects": { | |||||
"featured": "Featured Projects", | |||||
"viewAll": "View All", | |||||
"learnMore": "Learn More" | |||||
}, | |||||
"partners": { | |||||
"title": "Strategic Partners", | |||||
"subtitle": "Organizations and projects that work with us to expand the MOSE ecosystem" | |||||
}, | |||||
"join": { | |||||
"title": "Join Our Ecosystem", | |||||
"subtitle": "Build the next generation of decentralized applications on MOSE", | |||||
"cta": "Apply Now" | |||||
}, | |||||
"resources": { | |||||
"title": "Developer Resources", | |||||
"docs": "Documentation", | |||||
"github": "GitHub", | |||||
"grants": "Grants Program", | |||||
"community": "Developer Community" | |||||
} | |||||
}, | |||||
"footer": { | |||||
"rights": "All rights reserved", | |||||
"privacy": "Privacy Policy", | |||||
"terms": "Terms of Service" | |||||
}, | |||||
"language": { | |||||
"en": "English", | |||||
"zh": "中文", | |||||
"ja": "日本語" | |||||
} | |||||
} |
@ -0,0 +1,55 @@ | |||||
{ | |||||
"nav": { | |||||
"home": "ホーム", | |||||
"ecosystem": "エコシステム", | |||||
"about": "私たちについて", | |||||
"resources": "リソース", | |||||
"community": "コミュニティ", | |||||
"faq": "よくある質問", | |||||
"contact": "お問い合わせ" | |||||
}, | |||||
"ecosystem": { | |||||
"title": "エコシステム", | |||||
"subtitle": "MOSEエコシステムを探索し、プラットフォーム上に構築されたさまざまなプロジェクトとアプリケーションを発見しましょう", | |||||
"categories": { | |||||
"all": "すべて", | |||||
"defi": "DeFi", | |||||
"nft": "NFT", | |||||
"dao": "DAO", | |||||
"gaming": "ゲーム", | |||||
"infrastructure": "インフラストラクチャ", | |||||
"social": "ソーシャル" | |||||
}, | |||||
"projects": { | |||||
"featured": "注目のプロジェクト", | |||||
"viewAll": "すべて表示", | |||||
"learnMore": "詳細を見る" | |||||
}, | |||||
"partners": { | |||||
"title": "戦略的パートナー", | |||||
"subtitle": "MOSEエコシステムの拡大に協力する組織とプロジェクト" | |||||
}, | |||||
"join": { | |||||
"title": "エコシステムに参加する", | |||||
"subtitle": "MOSEで次世代の分散型アプリケーションを構築する", | |||||
"cta": "今すぐ申し込む" | |||||
}, | |||||
"resources": { | |||||
"title": "開発者リソース", | |||||
"docs": "ドキュメント", | |||||
"github": "GitHub", | |||||
"grants": "助成金プログラム", | |||||
"community": "開発者コミュニティ" | |||||
} | |||||
}, | |||||
"footer": { | |||||
"rights": "全著作権所有", | |||||
"privacy": "プライバシーポリシー", | |||||
"terms": "利用規約" | |||||
}, | |||||
"language": { | |||||
"en": "English", | |||||
"zh": "中文", | |||||
"ja": "日本語" | |||||
} | |||||
} |
@ -0,0 +1,55 @@ | |||||
{ | |||||
"nav": { | |||||
"home": "首页", | |||||
"ecosystem": "生态系统", | |||||
"about": "关于我们", | |||||
"resources": "资源", | |||||
"community": "社区", | |||||
"faq": "常见问题", | |||||
"contact": "联系我们" | |||||
}, | |||||
"ecosystem": { | |||||
"title": "生态系统", | |||||
"subtitle": "探索MOSE生态系统,发现在我们平台上构建的各种项目和应用", | |||||
"categories": { | |||||
"all": "全部", | |||||
"defi": "去中心化金融", | |||||
"nft": "非同质化代币", | |||||
"dao": "去中心化自治组织", | |||||
"gaming": "游戏", | |||||
"infrastructure": "基础设施", | |||||
"social": "社交" | |||||
}, | |||||
"projects": { | |||||
"featured": "精选项目", | |||||
"viewAll": "查看全部", | |||||
"learnMore": "了解更多" | |||||
}, | |||||
"partners": { | |||||
"title": "战略合作伙伴", | |||||
"subtitle": "与我们合作拓展MOSE生态系统的组织和项目" | |||||
}, | |||||
"join": { | |||||
"title": "加入我们的生态系统", | |||||
"subtitle": "在MOSE上构建下一代去中心化应用", | |||||
"cta": "立即申请" | |||||
}, | |||||
"resources": { | |||||
"title": "开发者资源", | |||||
"docs": "文档", | |||||
"github": "GitHub", | |||||
"grants": "资助计划", | |||||
"community": "开发者社区" | |||||
} | |||||
}, | |||||
"footer": { | |||||
"rights": "版权所有", | |||||
"privacy": "隐私政策", | |||||
"terms": "服务条款" | |||||
}, | |||||
"language": { | |||||
"en": "English", | |||||
"zh": "中文", | |||||
"ja": "日本語" | |||||
} | |||||
} |
@ -0,0 +1,12 @@ | |||||
import { createApp } from 'vue' | |||||
import './style.css' | |||||
import App from './App.vue' | |||||
import router from './router' | |||||
import i18n from './i18n' | |||||
const app = createApp(App) | |||||
app.use(router) | |||||
app.use(i18n) | |||||
app.mount('#app') |
@ -0,0 +1,34 @@ | |||||
import { createRouter, createWebHistory } from 'vue-router' | |||||
const routes = [ | |||||
{ | |||||
path: '/', | |||||
name: 'Home', | |||||
component: () => import('@/views/Home.vue') | |||||
}, | |||||
{ | |||||
path: '/ecosystem', | |||||
name: 'Ecosystem', | |||||
component: () => import('@/views/Ecosystem.vue') | |||||
}, | |||||
{ | |||||
path: '/about', | |||||
name: 'About', | |||||
component: () => import('@/views/About.vue') | |||||
}, | |||||
{ | |||||
path: '/:pathMatch(.*)*', | |||||
name: 'NotFound', | |||||
component: () => import('@/views/NotFound.vue') | |||||
} | |||||
] | |||||
const router = createRouter({ | |||||
history: createWebHistory(), | |||||
routes, | |||||
scrollBehavior() { | |||||
return { top: 0 } | |||||
} | |||||
}) | |||||
export default router |
@ -0,0 +1,213 @@ | |||||
@import "tailwindcss"; | |||||
@layer base { | |||||
:root { | |||||
--color-primary: #1E40AF; | |||||
--color-primary-light: #3B82F6; | |||||
--color-primary-dark: #1E3A8A; | |||||
--color-secondary: #10B981; | |||||
--color-secondary-light: #34D399; | |||||
--color-secondary-dark: #059669; | |||||
--color-background: #0F172A; | |||||
--color-background-light: #1E293B; | |||||
--color-background-dark: #020617; | |||||
--color-accent: #F59E0B; | |||||
--color-accent-light: #FBBF24; | |||||
--color-accent-dark: #D97706; | |||||
--color-text: #F8FAFC; | |||||
--color-text-secondary: #94A3B8; | |||||
--color-text-dark: #1E293B; | |||||
} | |||||
html { | |||||
scroll-behavior: smooth; | |||||
} | |||||
body { | |||||
font-family: 'Inter', system-ui, sans-serif; | |||||
line-height: 1.5; | |||||
-webkit-font-smoothing: antialiased; | |||||
-moz-osx-font-smoothing: grayscale; | |||||
background-color: var(--color-background); | |||||
color: var(--color-text); | |||||
} | |||||
h1, h2, h3, h4, h5, h6 { | |||||
font-family: 'Montserrat', sans-serif; | |||||
line-height: 1.2; | |||||
} | |||||
} | |||||
/* 自定义颜色类 */ | |||||
.bg-primary { | |||||
background-color: var(--color-primary); | |||||
} | |||||
.bg-primary-light { | |||||
background-color: var(--color-primary-light); | |||||
} | |||||
.bg-primary-dark { | |||||
background-color: var(--color-primary-dark); | |||||
} | |||||
.bg-secondary { | |||||
background-color: var(--color-secondary); | |||||
} | |||||
.bg-secondary-light { | |||||
background-color: var(--color-secondary-light); | |||||
} | |||||
.bg-secondary-dark { | |||||
background-color: var(--color-secondary-dark); | |||||
} | |||||
.bg-background { | |||||
background-color: var(--color-background); | |||||
} | |||||
.bg-background-light { | |||||
background-color: var(--color-background-light); | |||||
} | |||||
.bg-background-dark { | |||||
background-color: var(--color-background-dark); | |||||
} | |||||
.bg-accent { | |||||
background-color: var(--color-accent); | |||||
} | |||||
.bg-accent-light { | |||||
background-color: var(--color-accent-light); | |||||
} | |||||
.bg-accent-dark { | |||||
background-color: var(--color-accent-dark); | |||||
} | |||||
.text-primary { | |||||
color: var(--color-primary); | |||||
} | |||||
.text-primary-light { | |||||
color: var(--color-primary-light); | |||||
} | |||||
.text-primary-dark { | |||||
color: var(--color-primary-dark); | |||||
} | |||||
.text-secondary { | |||||
color: var(--color-secondary); | |||||
} | |||||
.text-text { | |||||
color: var(--color-text); | |||||
} | |||||
.text-text-secondary { | |||||
color: var(--color-text-secondary); | |||||
} | |||||
.text-text-dark { | |||||
color: var(--color-text-dark); | |||||
} | |||||
.border-primary { | |||||
border-color: var(--color-primary); | |||||
} | |||||
.border-primary-light { | |||||
border-color: var(--color-primary-light); | |||||
} | |||||
/* 自定义容器和按钮样式 */ | |||||
.container { | |||||
width: 100%; | |||||
margin-left: auto; | |||||
margin-right: auto; | |||||
padding-left: 1rem; | |||||
padding-right: 1rem; | |||||
} | |||||
@media (min-width: 640px) { | |||||
.container { | |||||
max-width: 640px; | |||||
} | |||||
} | |||||
@media (min-width: 768px) { | |||||
.container { | |||||
max-width: 768px; | |||||
padding-left: 1.5rem; | |||||
padding-right: 1.5rem; | |||||
} | |||||
} | |||||
@media (min-width: 1024px) { | |||||
.container { | |||||
max-width: 1024px; | |||||
padding-left: 2rem; | |||||
padding-right: 2rem; | |||||
} | |||||
} | |||||
@media (min-width: 1280px) { | |||||
.container { | |||||
max-width: 1280px; | |||||
} | |||||
} | |||||
.btn { | |||||
display: inline-block; | |||||
padding: 0.75rem 1.5rem; | |||||
border-radius: 0.5rem; | |||||
font-weight: 500; | |||||
transition-property: background-color, border-color, color; | |||||
transition-duration: 300ms; | |||||
} | |||||
.btn-primary { | |||||
background-color: var(--color-primary); | |||||
color: var(--color-text); | |||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |||||
} | |||||
.btn-primary:hover { | |||||
background-color: var(--color-primary-dark); | |||||
} | |||||
.btn-outline { | |||||
background-color: transparent; | |||||
border: 1px solid var(--color-primary-light); | |||||
color: var(--color-primary-light); | |||||
} | |||||
.btn-outline:hover { | |||||
background-color: var(--color-primary-light); | |||||
background-opacity: 0.1; | |||||
} | |||||
.shadow-card { | |||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); | |||||
} | |||||
.shadow-button { | |||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |||||
} | |||||
.blur-3xl { | |||||
--tw-blur: blur(64px); | |||||
filter: var(--tw-blur); | |||||
} | |||||
/* 自定义滚动条 */ | |||||
::-webkit-scrollbar { | |||||
width: 8px; | |||||
height: 8px; | |||||
} | |||||
::-webkit-scrollbar-track { | |||||
background: #1E293B; | |||||
} | |||||
::-webkit-scrollbar-thumb { | |||||
background: #3B82F6; | |||||
border-radius: 4px; | |||||
} | |||||
::-webkit-scrollbar-thumb:hover { | |||||
background: #2563EB; | |||||
} |
@ -0,0 +1,183 @@ | |||||
<script setup lang="ts"> | |||||
import { useI18n } from 'vue-i18n'; | |||||
const { t } = useI18n(); | |||||
// 团队成员数据 | |||||
const teamMembers = [ | |||||
{ | |||||
id: 1, | |||||
name: 'John Doe', | |||||
position: 'CEO & Founder', | |||||
image: '/public/images.png', | |||||
linkedin: 'https://linkedin.com' | |||||
}, | |||||
{ | |||||
id: 2, | |||||
name: 'Jane Smith', | |||||
position: 'CTO', | |||||
image: '/public/images.png', | |||||
linkedin: 'https://linkedin.com' | |||||
}, | |||||
{ | |||||
id: 3, | |||||
name: 'Mike Johnson', | |||||
position: 'Lead Developer', | |||||
image: '/public/images.png', | |||||
linkedin: 'https://linkedin.com' | |||||
}, | |||||
{ | |||||
id: 4, | |||||
name: 'Sarah Williams', | |||||
position: 'Marketing Director', | |||||
image: '/public/images.png', | |||||
linkedin: 'https://linkedin.com' | |||||
} | |||||
]; | |||||
// 里程碑数据 | |||||
const milestones = [ | |||||
{ | |||||
year: '2021', | |||||
title: 'MOSE Founded', | |||||
description: 'MOSE was founded with a vision to create a high-performance blockchain platform.' | |||||
}, | |||||
{ | |||||
year: '2022', | |||||
title: 'Testnet Launch', | |||||
description: 'Successfully launched our testnet with key features and functionalities.' | |||||
}, | |||||
{ | |||||
year: '2023', | |||||
title: 'Mainnet Beta', | |||||
description: 'Released the beta version of our mainnet with improved performance and security.' | |||||
}, | |||||
{ | |||||
year: '2024', | |||||
title: 'Ecosystem Growth', | |||||
description: 'Expanded our ecosystem with various projects and partnerships.' | |||||
} | |||||
]; | |||||
</script> | |||||
<template> | |||||
<div class="bg-background min-h-screen"> | |||||
<!-- Hero Section --> | |||||
<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"> | |||||
关于我们 | |||||
</h1> | |||||
<p class="text-lg md:text-xl text-text-secondary mb-8"> | |||||
了解MOSE的愿景、使命和团队 | |||||
</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-light blur-3xl"></div> | |||||
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl"></div> | |||||
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl"></div> | |||||
</div> | |||||
</section> | |||||
<!-- Our Story 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"> | |||||
<h2 class="text-2xl md:text-3xl font-bold text-text mb-6">我们的故事</h2> | |||||
<div class="space-y-6 text-text-secondary"> | |||||
<p> | |||||
MOSE是一个致力于构建高性能、安全和可扩展区块链平台的项目。我们的使命是为去中心化应用提供强大的基础设施,使开发者能够构建下一代的区块链应用。 | |||||
</p> | |||||
<p> | |||||
我们的团队由区块链技术专家、经验丰富的开发者和行业领导者组成,共同致力于推动区块链技术的发展和应用。 | |||||
</p> | |||||
<p> | |||||
MOSE的核心价值观包括去中心化、安全、可扩展性和社区驱动。我们相信通过这些价值观的指导,我们可以构建一个更加开放、公平和高效的区块链生态系统。 | |||||
</p> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<!-- 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"> | |||||
我们的团队 | |||||
</h2> | |||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"> | |||||
<div | |||||
v-for="member in teamMembers" | |||||
:key="member.id" | |||||
class="bg-background rounded-xl overflow-hidden shadow-card hover:shadow-lg transition-all duration-300" | |||||
> | |||||
<img :src="member.image" :alt="member.name" class="w-full h-48 object-cover" /> | |||||
<div class="p-5"> | |||||
<h3 class="text-lg font-bold text-text mb-1">{{ member.name }}</h3> | |||||
<p class="text-text-secondary text-sm mb-3">{{ member.position }}</p> | |||||
<a | |||||
:href="member.linkedin" | |||||
target="_blank" | |||||
rel="noopener noreferrer" | |||||
class="text-primary-light hover:text-primary-dark transition-colors duration-200 flex items-center text-sm" | |||||
> | |||||
<svg class="h-4 w-4 mr-1" 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"></path> | |||||
</svg> | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<!-- 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"> | |||||
发展历程 | |||||
</h2> | |||||
<div class="max-w-4xl mx-auto"> | |||||
<div class="relative"> | |||||
<!-- Timeline Line --> | |||||
<div class="absolute top-0 left-6 md:left-1/2 w-0.5 h-full bg-primary-light transform -translate-x-1/2"></div> | |||||
<!-- Timeline Items --> | |||||
<div class="space-y-12"> | |||||
<div | |||||
v-for="(milestone, index) in milestones" | |||||
:key="index" | |||||
class="relative" | |||||
> | |||||
<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" | |||||
> | |||||
<span class="text-text font-bold text-sm">{{ milestone.year }}</span> | |||||
</div> | |||||
<!-- Content --> | |||||
<div | |||||
class="ml-20 md:ml-0 md:w-1/2 md:pr-8 md:text-right" | |||||
:class="{ 'md:pl-8 md:pr-0 md:text-left md:order-2': index % 2 !== 0 }" | |||||
> | |||||
<h3 class="text-xl font-bold text-text mb-2">{{ milestone.title }}</h3> | |||||
<p class="text-text-secondary">{{ milestone.description }}</p> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
</div> | |||||
</template> |
@ -0,0 +1,396 @@ | |||||
<script setup lang="ts"> | |||||
import { ref, computed } from 'vue'; | |||||
import { useI18n } from 'vue-i18n'; | |||||
const { t } = useI18n(); | |||||
// 当前选中的分类 | |||||
const selectedCategory = ref('all'); | |||||
// 分类列表 | |||||
const categories = [ | |||||
{ id: 'all', name: t('ecosystem.categories.all') }, | |||||
{ id: 'defi', name: t('ecosystem.categories.defi') }, | |||||
{ id: 'nft', name: t('ecosystem.categories.nft') }, | |||||
{ id: 'dao', name: t('ecosystem.categories.dao') }, | |||||
{ id: 'gaming', name: t('ecosystem.categories.gaming') }, | |||||
{ id: 'infrastructure', name: t('ecosystem.categories.infrastructure') }, | |||||
{ id: 'social', name: t('ecosystem.categories.social') }, | |||||
]; | |||||
// 项目数据 | |||||
const projects = [ | |||||
{ | |||||
id: 1, | |||||
name: 'MOSE Swap', | |||||
description: 'Decentralized exchange with low fees and high liquidity', | |||||
category: 'defi', | |||||
image: '/public/images.png', | |||||
url: 'https://moseswap.io', | |||||
featured: true | |||||
}, | |||||
{ | |||||
id: 2, | |||||
name: 'MOSE NFT Marketplace', | |||||
description: 'Trade unique digital assets on the MOSE blockchain', | |||||
category: 'nft', | |||||
image: '/public/images.png', | |||||
url: 'https://mosenft.io', | |||||
featured: true | |||||
}, | |||||
{ | |||||
id: 3, | |||||
name: 'MOSE DAO', | |||||
description: 'Decentralized governance for the MOSE ecosystem', | |||||
category: 'dao', | |||||
image: '/public/images.png', | |||||
url: 'https://mosedao.io', | |||||
featured: true | |||||
}, | |||||
{ | |||||
id: 4, | |||||
name: 'MOSE Gaming', | |||||
description: 'Play-to-earn games built on MOSE', | |||||
category: 'gaming', | |||||
image: '/public/images.png', | |||||
url: 'https://mosegaming.io', | |||||
featured: false | |||||
}, | |||||
{ | |||||
id: 5, | |||||
name: 'MOSE Bridge', | |||||
description: 'Cross-chain bridge for MOSE assets', | |||||
category: 'infrastructure', | |||||
image: '/public/images.png', | |||||
url: 'https://mosebridge.io', | |||||
featured: true | |||||
}, | |||||
{ | |||||
id: 6, | |||||
name: 'MOSE Social', | |||||
description: 'Decentralized social network', | |||||
category: 'social', | |||||
image: '/public/images.png', | |||||
url: 'https://mosesocial.io', | |||||
featured: false | |||||
}, | |||||
{ | |||||
id: 7, | |||||
name: 'MOSE Lending', | |||||
description: 'Decentralized lending protocol', | |||||
category: 'defi', | |||||
image: '/public/images.png', | |||||
url: 'https://moselending.io', | |||||
featured: false | |||||
}, | |||||
{ | |||||
id: 8, | |||||
name: 'MOSE Staking', | |||||
description: 'Stake your MOSE tokens for rewards', | |||||
category: 'defi', | |||||
image: '/public/images.png', | |||||
url: 'https://mosestaking.io', | |||||
featured: false | |||||
} | |||||
]; | |||||
// 合作伙伴数据 | |||||
const partners = [ | |||||
{ | |||||
id: 1, | |||||
name: 'Partner 1', | |||||
logo: '/public/images.png', | |||||
url: 'https://partner1.com' | |||||
}, | |||||
{ | |||||
id: 2, | |||||
name: 'Partner 2', | |||||
logo: '/public/images.png', | |||||
url: 'https://partner2.com' | |||||
}, | |||||
{ | |||||
id: 3, | |||||
name: 'Partner 3', | |||||
logo: '/public/images.png', | |||||
url: 'https://partner3.com' | |||||
}, | |||||
{ | |||||
id: 4, | |||||
name: 'Partner 4', | |||||
logo: '/public/images.png', | |||||
url: 'https://partner4.com' | |||||
}, | |||||
{ | |||||
id: 5, | |||||
name: 'Partner 5', | |||||
logo: '/public/images.png', | |||||
url: 'https://partner5.com' | |||||
}, | |||||
{ | |||||
id: 6, | |||||
name: 'Partner 6', | |||||
logo: '/public/images.png', | |||||
url: 'https://partner6.com' | |||||
} | |||||
]; | |||||
// 筛选项目 | |||||
const filteredProjects = computed(() => { | |||||
if (selectedCategory.value === 'all') { | |||||
return projects; | |||||
} else { | |||||
return projects.filter(project => project.category === selectedCategory.value); | |||||
} | |||||
}); | |||||
// 特色项目 | |||||
const featuredProjects = computed(() => { | |||||
return projects.filter(project => project.featured); | |||||
}); | |||||
// 选择分类 | |||||
const selectCategory = (category: string) => { | |||||
selectedCategory.value = category; | |||||
}; | |||||
</script> | |||||
<template> | |||||
<div class="bg-background min-h-screen"> | |||||
<!-- Hero Section --> | |||||
<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"> | |||||
{{ t('ecosystem.title') }} | |||||
</h1> | |||||
<p class="text-lg md:text-xl text-text-secondary mb-8"> | |||||
{{ t('ecosystem.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-light blur-3xl"></div> | |||||
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl"></div> | |||||
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl"></div> | |||||
</div> | |||||
</section> | |||||
<!-- Featured Projects Section --> | |||||
<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"> | |||||
{{ t('ecosystem.projects.featured') }} | |||||
</h2> | |||||
<a href="#all-projects" class="text-primary-light hover:text-primary-dark transition-colors duration-200"> | |||||
{{ t('ecosystem.projects.viewAll') }} | |||||
</a> | |||||
</div> | |||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> | |||||
<div | |||||
v-for="project in featuredProjects" | |||||
:key="project.id" | |||||
class="bg-background-light rounded-xl overflow-hidden shadow-card hover:transform hover:scale-105 transition-all duration-300" | |||||
> | |||||
<img :src="project.image" :alt="project.name" class="w-full h-48 object-cover" /> | |||||
<div class="p-6"> | |||||
<h3 class="text-xl font-bold text-text mb-2">{{ project.name }}</h3> | |||||
<p class="text-text-secondary mb-4">{{ project.description }}</p> | |||||
<div class="flex justify-between items-center"> | |||||
<span class="px-3 py-1 bg-background text-primary-light text-xs rounded-full"> | |||||
{{ t(`ecosystem.categories.${project.category}`) }} | |||||
</span> | |||||
<a | |||||
:href="project.url" | |||||
target="_blank" | |||||
rel="noopener noreferrer" | |||||
class="text-primary-light hover:text-primary-dark transition-colors duration-200" | |||||
> | |||||
{{ t('ecosystem.projects.learnMore') }} | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<!-- 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"> | |||||
{{ t('ecosystem.title') }} | |||||
</h2> | |||||
<!-- Categories Filter --> | |||||
<div class="flex flex-wrap gap-2 mb-10"> | |||||
<button | |||||
v-for="category in categories" | |||||
:key="category.id" | |||||
@click="selectCategory(category.id)" | |||||
class="px-4 py-2 rounded-full text-sm transition-colors duration-200" | |||||
:class="selectedCategory === category.id | |||||
? 'bg-primary text-text' | |||||
: 'bg-background-dark text-text-secondary hover:bg-background hover:text-text'" | |||||
> | |||||
{{ category.name }} | |||||
</button> | |||||
</div> | |||||
<!-- Projects Grid --> | |||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6"> | |||||
<div | |||||
v-for="project in filteredProjects" | |||||
:key="project.id" | |||||
class="bg-background rounded-xl overflow-hidden shadow-card hover:shadow-lg transition-all duration-300" | |||||
> | |||||
<img :src="project.image" :alt="project.name" class="w-full h-40 object-cover" /> | |||||
<div class="p-5"> | |||||
<h3 class="text-lg font-bold text-text mb-2">{{ project.name }}</h3> | |||||
<p class="text-text-secondary text-sm mb-4">{{ project.description }}</p> | |||||
<div class="flex justify-between items-center"> | |||||
<span class="px-3 py-1 bg-background-dark text-primary-light text-xs rounded-full"> | |||||
{{ t(`ecosystem.categories.${project.category}`) }} | |||||
</span> | |||||
<a | |||||
:href="project.url" | |||||
target="_blank" | |||||
rel="noopener noreferrer" | |||||
class="text-primary-light hover:text-primary-dark transition-colors duration-200 text-sm" | |||||
> | |||||
{{ t('ecosystem.projects.learnMore') }} | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<!-- Partners Section --> | |||||
<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"> | |||||
{{ t('ecosystem.partners.title') }} | |||||
</h2> | |||||
<p class="text-text-secondary max-w-2xl mx-auto"> | |||||
{{ t('ecosystem.partners.subtitle') }} | |||||
</p> | |||||
</div> | |||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-8"> | |||||
<a | |||||
v-for="partner in partners" | |||||
:key="partner.id" | |||||
: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" | |||||
> | |||||
<img :src="partner.logo" :alt="partner.name" class="max-h-12 max-w-full" /> | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<!-- Join Ecosystem CTA --> | |||||
<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"> | |||||
{{ t('ecosystem.join.title') }} | |||||
</h2> | |||||
<p class="text-text-secondary mb-8"> | |||||
{{ 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" | |||||
> | |||||
{{ t('ecosystem.join.cta') }} | |||||
</a> | |||||
</div> | |||||
</div> | |||||
<!-- 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"></div> | |||||
<div class="absolute bottom-0 left-0 w-80 h-80 rounded-full bg-primary blur-3xl"></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"> | |||||
{{ 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" | |||||
> | |||||
<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" /> | |||||
</svg> | |||||
<h3 class="text-lg font-bold text-text mb-2">{{ t('ecosystem.resources.docs') }}</h3> | |||||
<p class="text-text-secondary text-sm"> | |||||
Comprehensive documentation for developers | |||||
</p> | |||||
</a> | |||||
<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" | |||||
> | |||||
<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" /> | |||||
</svg> | |||||
<h3 class="text-lg font-bold text-text mb-2">{{ t('ecosystem.resources.github') }}</h3> | |||||
<p class="text-text-secondary text-sm"> | |||||
Open source code repositories | |||||
</p> | |||||
</a> | |||||
<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" | |||||
> | |||||
<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" /> | |||||
</svg> | |||||
<h3 class="text-lg font-bold text-text mb-2">{{ t('ecosystem.resources.grants') }}</h3> | |||||
<p class="text-text-secondary text-sm"> | |||||
Funding for innovative projects | |||||
</p> | |||||
</a> | |||||
<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" | |||||
> | |||||
<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" /> | |||||
</svg> | |||||
<h3 class="text-lg font-bold text-text mb-2">{{ t('ecosystem.resources.community') }}</h3> | |||||
<p class="text-text-secondary text-sm"> | |||||
Join our developer community | |||||
</p> | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
</div> | |||||
</template> | |||||
<style scoped> | |||||
/* 添加一些额外的动画效果 */ | |||||
.hover\:transform:hover { | |||||
transform: translateY(-5px); | |||||
} | |||||
</style> |
@ -0,0 +1,90 @@ | |||||
<script setup lang="ts"> | |||||
import { useI18n } from 'vue-i18n'; | |||||
import { useRouter } from 'vue-router'; | |||||
const { t } = useI18n(); | |||||
const router = useRouter(); | |||||
const goToEcosystem = () => { | |||||
router.push('/ecosystem'); | |||||
}; | |||||
</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"> | |||||
MOSE Blockchain | |||||
</h1> | |||||
<p class="text-lg md:text-xl text-text-secondary mb-8"> | |||||
Next-generation blockchain platform for high performance, security, and scalability | |||||
</p> | |||||
<div class="flex flex-col sm:flex-row justify-center gap-4"> | |||||
<button | |||||
@click="goToEcosystem" | |||||
class="px-8 py-3 bg-primary text-text rounded-lg hover:bg-primary-dark transition-colors duration-300 shadow-button" | |||||
> | |||||
{{ t('ecosystem.title') }} | |||||
</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" | |||||
> | |||||
{{ t('ecosystem.resources.docs') }} | |||||
</a> | |||||
</div> | |||||
</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-light blur-3xl"></div> | |||||
<div class="absolute top-1/2 right-0 w-80 h-80 rounded-full bg-secondary blur-3xl"></div> | |||||
<div class="absolute -bottom-24 left-1/3 w-72 h-72 rounded-full bg-accent blur-3xl"></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"> | |||||
<video | |||||
src="/public/MOSEVideo.mp4" | |||||
controls | |||||
class="w-full h-auto" | |||||
poster="/public/images.png" | |||||
></video> | |||||
</div> | |||||
</div> | |||||
</section> | |||||
<!-- Call to Action --> | |||||
<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"> | |||||
{{ t('ecosystem.join.title') }} | |||||
</h2> | |||||
<p class="text-text-secondary mb-8"> | |||||
{{ 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" | |||||
> | |||||
{{ t('ecosystem.title') }} | |||||
</button> | |||||
</div> | |||||
</div> | |||||
<!-- 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"></div> | |||||
<div class="absolute bottom-0 left-0 w-80 h-80 rounded-full bg-primary blur-3xl"></div> | |||||
</div> | |||||
</section> | |||||
</div> | |||||
</template> |
@ -0,0 +1,27 @@ | |||||
<script setup lang="ts"> | |||||
import { useRouter } from 'vue-router'; | |||||
const router = useRouter(); | |||||
const goHome = () => { | |||||
router.push('/'); | |||||
}; | |||||
</script> | |||||
<template> | |||||
<div class="bg-background min-h-screen flex items-center justify-center px-6 py-24"> | |||||
<div class="text-center"> | |||||
<h1 class="text-6xl md:text-8xl font-bold text-primary-light mb-4">404</h1> | |||||
<h2 class="text-2xl md:text-3xl font-bold text-text mb-6">页面未找到</h2> | |||||
<p class="text-text-secondary mb-8 max-w-md mx-auto"> | |||||
您访问的页面不存在或已被移除。请检查URL或返回首页。 | |||||
</p> | |||||
<button | |||||
@click="goHome" | |||||
class="px-8 py-3 bg-primary text-text rounded-lg hover:bg-primary-dark transition-colors duration-300 shadow-button" | |||||
> | |||||
返回首页 | |||||
</button> | |||||
</div> | |||||
</div> | |||||
</template> |
@ -0,0 +1 @@ | |||||
/// <reference types="vite/client" /> |
@ -0,0 +1,20 @@ | |||||
{ | |||||
"extends": "@vue/tsconfig/tsconfig.dom.json", | |||||
"compilerOptions": { | |||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", | |||||
/* Linting */ | |||||
"strict": true, | |||||
"noUnusedLocals": true, | |||||
"noUnusedParameters": true, | |||||
"noFallthroughCasesInSwitch": true, | |||||
"noUncheckedSideEffectImports": true, | |||||
/* 路径别名 */ | |||||
"baseUrl": ".", | |||||
"paths": { | |||||
"@/*": ["./src/*"] | |||||
} | |||||
}, | |||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] | |||||
} |
@ -0,0 +1,7 @@ | |||||
{ | |||||
"files": [], | |||||
"references": [ | |||||
{ "path": "./tsconfig.app.json" }, | |||||
{ "path": "./tsconfig.node.json" } | |||||
] | |||||
} |
@ -0,0 +1,26 @@ | |||||
{ | |||||
"compilerOptions": { | |||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", | |||||
"target": "ES2022", | |||||
"lib": ["ES2023"], | |||||
"module": "ESNext", | |||||
"skipLibCheck": true, | |||||
/* Bundler mode */ | |||||
"moduleResolution": "bundler", | |||||
"allowImportingTsExtensions": true, | |||||
"isolatedModules": true, | |||||
"moduleDetection": "force", | |||||
"noEmit": true, | |||||
/* Linting */ | |||||
"strict": true, | |||||
"noUnusedLocals": true, | |||||
"noUnusedParameters": true, | |||||
"noFallthroughCasesInSwitch": true, | |||||
"noUncheckedSideEffectImports": true, | |||||
}, | |||||
"include": ["vite.config.ts"] | |||||
} |
@ -0,0 +1,20 @@ | |||||
import { defineConfig } from 'vite' | |||||
import vue from '@vitejs/plugin-vue' | |||||
import tailwindcss from '@tailwindcss/vite' | |||||
import path from 'path' | |||||
// https://vite.dev/config/ | |||||
export default defineConfig({ | |||||
plugins: [ | |||||
vue(), | |||||
tailwindcss(), | |||||
], | |||||
server: { | |||||
port: 3000, | |||||
}, | |||||
resolve: { | |||||
alias: { | |||||
'@': path.resolve(__dirname, './src'), | |||||
}, | |||||
}, | |||||
}) |