Commit 3d4fba61 by mm ven

feat: init

0 parents
Showing 64 changed files with 2121 additions and 0 deletions
# 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?
{
"recommendations": ["Vue.volar"]
}
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
Learn more about IDE Support for Vue in the [Vue Docs Scaling up Guide](https://vuejs.org/guide/scaling-up/tooling.html#ide-support).
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
{
"name": "yahabbi-web",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"pinia": "^3.0.3",
"swiper": "^11.2.8",
"vant": "^4.9.19",
"vue": "^3.5.13",
"vue-i18n": "^9.14.4",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.3",
"sass-embedded": "^1.89.2",
"vite": "^6.3.5"
}
}
<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>
\ No newline at end of file
<script setup>
// 只需要渲染路由页面
</script>
<template>
<router-view />
</template>
<style scoped>
</style>
This file is too large to display.
<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>
\ No newline at end of file
\ No newline at end of file
<template>
<header class="home-header" :class="{ 'rtl': currentLang === 'ar' }">
<img
src="@/assets/common/logo.png"
class="logo"
:alt="$t('nav.home')"
@click="goTab(0, tabs[0])"
:class="{ 'logo-rtl': currentLang === 'ar' }"
/>
<nav class="nav">
<a
v-for="(tab, idx) in tabs"
:key="tab.path"
class="nav-link"
:class="{ active: store.index === idx }"
@click="goTab(idx, tab)"
>{{ $t(tab.name) }}</a
>
</nav>
<div class="header-actions">
<!-- <button class="topup-btn">Top-Up</button> -->
<div class="lang-select">
<div class="lang-btn" @click="toggleLangDropdown">
<span class="lang-btn-label">{{
langList.find((l) => l.value === currentLang)?.label
}}</span>
</div>
<transition name="fade">
<div v-if="showLang" class="lang-dropdown">
<div
v-for="lang in langList"
:key="lang.value"
class="lang-item"
:class="{ active: currentLang === lang.value }"
@click="selectLang(lang.value)"
>
{{ lang.label }}
</div>
</div>
</transition>
</div>
</div>
</header>
</template>
<script setup>
import { useCommonStore } from "@/store/commonStore";
import { useRoute, useRouter } from "vue-router";
import { ref, watch, onMounted } from "vue";
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
const store = useCommonStore();
const route = useRoute();
const router = useRouter();
const tabs = [
{ name: "nav.home", path: "/" },
{ name: "nav.about", path: "/about" },
{ name: "nav.leadership", path: "/leadership" },
{ name: "nav.contact", path: "/contact" },
];
function goTab(idx, tab) {
store.setIndex(idx);
router.push(tab.path);
}
function updateIndexByRoute() {
const idx = tabs.findIndex((tab) => tab.path === route.path);
store.setIndex(idx === -1 ? 0 : idx);
}
watch(() => route.path, updateIndexByRoute, { immediate: true });
onMounted(updateIndexByRoute);
const langList = [
{ label: t('nav.english'), value: "en" },
{ label: t('nav.arabic'), value: "ar" },
];
const showLang = ref(false);
const currentLang = ref(locale.value);
function toggleLangDropdown() {
showLang.value = !showLang.value;
}
function selectLang(val) {
locale.value = val;
currentLang.value = val;
showLang.value = false;
document.dir = val === 'ar' ? 'rtl' : 'ltr';
localStorage.setItem('language', val);
}
watch(locale, (val) => {
currentLang.value = val;
});
</script>
<style scoped>
.home-header {
position: sticky;
top: 0;
display: flex;
align-items: center;
justify-content: space-between;
/* width: 100vw; */
height: 98px;
flex-shrink: 0;
padding-left: 500px;
padding-right: 98px;
background: #000;
z-index: 10;
}
.logo {
position: absolute;
left: 0;
bottom: 0;
height: 78px;
cursor: pointer;
transition: left 0.3s, right 0.3s;
}
/* RTL 适配 */
.home-header.rtl {
padding-left: 98px;
padding-right: 500px;
}
.logo-rtl {
left: auto !important;
right: 0;
}
.nav {
display: flex;
gap: 120px;
}
.nav-link {
color: #fff;
font-size: 20px;
font-weight: 500;
text-decoration: none;
padding-bottom: 4px;
border-bottom: 2px solid transparent;
transition: border-color 0.2s;
cursor: pointer;
}
.nav-link.active {
color: #fff;
border-bottom: 4px solid #a259ff;
}
.header-actions {
display: flex;
align-items: center;
gap: 16px;
transition: margin 0.3s;
}
.rtl .header-actions {
margin-right: auto;
margin-left: 0;
}
.topup-btn {
background: #a259ff;
color: #fff;
border: none;
border-radius: 20px;
padding: 8px 24px;
font-size: 18px;
font-weight: 600;
cursor: pointer;
margin-right: 8px;
}
.lang-select {
position: relative;
}
.lang-btn {
width: 142px;
height: 58px;
/* padding: 16px 0 15px 17px; */
padding-left: 17px;
padding-top: 13px;
background-image: url("@/assets/common/language.png");
background-repeat: no-repeat;
background-size: cover;
cursor: pointer;
text-align: left;
}
.rtl .lang-btn {
padding-left: 17px;
padding-right: 17px;
}
.lang-btn-label {
z-index: 1;
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: 600;
font-size: 20px;
color: #ffffff;
text-align: center;
font-style: normal;
text-transform: none;
background: linear-gradient(90deg, #c22fff 0%, #8b17ff 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-fill-color: transparent;
}
.lang-dropdown {
position: absolute;
top: 56px;
right: 0;
min-width: 160px;
background: #e9eef7;
border-radius: 16px;
box-shadow: 0 8px 32px 0 rgba(24, 31, 43, 0.18);
padding: 18px 0 10px 0;
display: flex;
flex-direction: column;
z-index: 100;
border: 1px solid #e0e0e0;
}
.rtl .lang-dropdown {
right: auto;
left: 0;
}
.lang-item {
font-size: 22px;
color: #181f2b;
font-weight: 500;
padding: 12px 32px;
cursor: pointer;
border-radius: 8px;
transition: background 0.2s;
text-align: left;
}
.lang-item.active,
.lang-item:hover {
background: #f3eaff;
color: #a259ff;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
\ No newline at end of file
\ No newline at end of file
<template>
<div class="lang-selector">
<van-dropdown-menu>
<van-dropdown-item v-model="lang" :options="options" @change="changeLang" />
</van-dropdown-menu>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
const lang = ref(locale.value)
const options = [
{ text: 'English', value: 'en' },
{ text: 'العربية', value: 'ar' }
]
function changeLang(val) {
locale.value = val
lang.value = val
document.dir = val === 'ar' ? 'rtl' : 'ltr'
}
</script>
<style scoped>
.lang-selector {
min-width: 100px;
}
</style>
\ No newline at end of file
export default {
nav: {
home: 'الرئيسية',
about: 'عن ياحبي',
leadership: 'قيادتنا',
contact: 'اتصل بنا',
topup: 'شحن الرصيد',
english: 'English',
arabic: 'العربية',
},
home: {
title: 'الأصوات تتحد<br />الحدود تشتعل!',
subtitle: 'الفرح يوحد الآن: ياحبي~',
desc: 'تعرف علينا واستمتع أكثر، تعرف علينا واستمتع أكثر، تعرف علينا واستمتع أكثر،',
google: 'جوجل بلاي',
appstore: 'آب ستور',
},
about: {
join: 'انضم إلينا معًا!',
slides: [
{
desc1: 'تعرف علينا واستمتع أكثر',
title: 'لوحة عالمية، ألوانك المحلية',
desc2: 'مجتمع ياحبي – حيث تتقاطع أنماط الحياة! كن راويًا ثقافيًا. شارك جواهر السوق المخفية، وصفات التمر بلمسة الجدة، أو غروب الشمس في وادي رم.'
},
{
desc1: 'تعرف علينا واستمتع أكثر',
title: 'البطاقات تجمع الثقافات',
desc2: 'منطقة الألعاب: حيث تنبض ألعاب المينا المفضلة بالحياة! ألعاب عربية أصيلة: تحد أصدقاءك في بطولات البلوت، وتفوق على منافسيك في تريكس بليتز أو ماراثونات الدومينو – التقاليد تلتقي التقنية!'
},
{
desc1: 'تعرف علينا واستمتع أكثر',
title: 'حيث يلتقي الشرق الأوسط',
desc2: 'ادخل غرف الصوت في ياحبي – بوابتك إلى العالم العربي! 🎧 دردش مباشرة مع مستخدمين من 22 دولة عربية، من حكايات المغرب إلى شبكات الأعمال الخليجية. اكتشف نبض المينا من خلال الأصوات!'
}
],
google: 'جوجل بلاي',
appstore: 'آب ستور',
},
leadership: {
title: 'فريق القيادة <span class="highlight">الخاصة بنا</span>',
name: 'الاسم',
position: 'المنصب',
team_intro: 'مقدمة الفريق',
team_desc1: 'تعرف علينا واستمتع أكثر، تعرف علينا واستمتع أكثر، تعرف علينا واستمتع أكثر، تعرف علينا واستمتع أكثر. لتعرف علينا واستمتع أكثر.',
team_desc2: 'تعرف علينا واستمتع أكثر، تعرف علينا واستمتع أكثر، تعرف علينا واستمتع أكثر',
},
contact: {
title: 'انضم إلى عائلتنا الكبيرة',
desc: 'كوّن صداقات جديدة هنا واختبر المزيد من طرق اللعب الجديدة',
google: 'جوجل بلاي',
appstore: 'آب ستور',
yahabbi: 'ياحبي',
focus: 'نحن نركز على الدردشة عبر الإنترنت!',
contactus: 'اتصل بنا',
email: '1234567@QQ.COM',
phone: '12345678912',
topup: 'شحن الرصيد',
recharge: 'مدخل الشحن',
download: 'تنزيل',
android: 'أندرويد',
apple: 'نظام أبل',
copyright: 'جميع الحقوق محفوظة..................',
aboutus: 'معلومات عنا',
terms: 'شروط الخدمة',
privacy: 'سياسة الخصوصية'
}
}
\ No newline at end of file
export default {
nav: {
home: 'Home',
about: 'About Yahabbi',
leadership: 'Our Leadership',
contact: 'Contact Us',
topup: 'Top-Up',
english: 'English',
arabic: 'العربية',
},
home: {
title: 'VOICES UNITE<br />BORDERS IGNITE!',
subtitle: 'Joy Unites Now: Yahabbi~',
desc: 'Get To Know Us And Have More Fun,Get To Know Us And Have More Fun,Get To Know Us And Have More Fun,',
google: 'GOOGLE PLAY',
appstore: 'APP STORE',
},
about: {
join: 'JOIN US TOGETHER!',
slides: [
{
desc1: 'Get To Know Us And Have More Fun',
title: 'GLOBAL CANVAS, YOUR LOCAL COLORS',
desc2: 'YAHABBI Community – Where Lifestyles Cross-Pollinate! Be A Cultural Storyteller. Share Hidden Souk Gems, Date Recipes With Grandma\'s Touch, Or That Sunset In Wadi Rum.'
},
{
desc1: 'Get To Know Us And Have More Fun',
title: 'CARDS CONNECT CULTURES',
desc2: 'Platform] Game Zone: Where MENA\'s Favorite Games Come Alive! Authentic Arab Games: Challenge Friends In Baloot Championships, Outsmart Rivals In Trix Blitz, Or Dominoes Marathons – Tradition Meets Tech!'
},
{
desc1: 'Get To Know Us And Have More Fun',
title: 'WHERE THE MIDDLE EAST CONNECTS',
desc2: 'Dive Into YAHABBI\'s Voice Rooms – Your Gateway To The Arab World! 🎧 Chat LIVE With Users Across 22 Arab Nations, From Maghreb Storytelling To Gulf Business Networking. Unlock The Heartbeat Of MENA Culture Through Voices!'
}
],
google: 'GOOGLE PLAY',
appstore: 'APP STORE',
},
leadership: {
title: 'OUR <span class="highlight">LEADERSHIP TEAM</span>',
name: 'NAME',
position: 'POSITION',
team_intro: 'TEAM INTRODUCTION',
team_desc1: 'Get To Know Us And Have More Fun,Get To Know Us And Have More Fun,Get To Know Us And Have More Fun,Get To Know Us And Have More Fun.To Know Us And Have More Fun.',
team_desc2: 'Get To Know Us And Have More Fun,Get To Know Us And Have More Fun,Get To Know Us And Have More Fun',
},
contact: {
title: 'COME AND <span class="highlight">JOIN OUR</span> <br />BIG FAMILY',
desc: 'Make More New Friends Here And Experience More Novel Gameplay',
google: 'GOOGLE PLAY',
appstore: 'APP STORE',
yahabbi: 'YAHABBI',
focus: 'We Focus On Online Chat !',
contactus: 'CONTACT US',
email: '1234567@QQ.COM',
phone: '12345678912',
topup: 'Top-Up',
recharge: 'RECHARGE ENTRY',
download: 'Download',
android: 'ANDROID',
apple: 'APPLE SYSTEM',
copyright: '版权所有信息..................',
aboutus: 'ABOUT US',
terms: 'TERMS OF SERVICE',
privacy: 'PRIVACY POLICY'
}
}
\ No newline at end of file
import en from './en'
import ar from './ar'
export default {
en,
ar
}
\ No newline at end of file
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { createI18n } from 'vue-i18n'
import Vant from 'vant'
import App from './App.vue'
import router from './router'
import messages from './locales'
import 'vant/lib/index.css'
import './style.css'
// Get saved language from localStorage or default to 'en'
const savedLanguage = localStorage.getItem('language') || 'en'
// Set document direction based on language
document.dir = savedLanguage === 'ar' ? 'rtl' : 'ltr'
const i18n = createI18n({
legacy: false,
locale: savedLanguage,
messages,
})
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(router)
app.use(i18n)
app.use(Vant)
app.mount('#app')
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/leadership',
name: 'Leadership',
component: () => import('../views/Leadership.vue')
},
{
path: '/contact',
name: 'Contact',
component: () => import('../views/Contact.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router
\ No newline at end of file
import { defineStore } from 'pinia'
export const useCommonStore = defineStore('common', {
state: () => ({
index: 0
}),
actions: {
setIndex(val) {
this.index = val
}
}
})
\ No newline at end of file
/* modern-css-reset v1.4.0 | MIT License | https://github.com/hankchizljaw/modern-css-reset */
/* Document
========================================================================== */
html {
box-sizing: border-box;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
*, *::before, *::after {
box-sizing: inherit;
}
/* Sections
========================================================================== */
body {
margin: 0;
padding: 0;
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
background: #fff;
color: #222;
}
main {
display: block;
}
/* Grouping content
========================================================================== */
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
pre {
font-family: monospace, monospace;
font-size: 1em;
}
/* Text-level semantics
========================================================================== */
a {
background-color: transparent;
color: inherit;
text-decoration: none;
}
abbr[title] {
border-bottom: none;
text-decoration: underline dotted;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
img {
border-style: none;
max-width: 100%;
display: block;
}
/* Forms
========================================================================== */
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
padding: 0.35em 0.75em 0.625em;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
progress {
vertical-align: baseline;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
/* Interactive
========================================================================== */
details {
display: block;
}
summary {
display: list-item;
}
/* Misc
========================================================================== */
template {
display: none;
}
[hidden] {
display: none;
}
/* Remove all animations and transitions for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
h1, h2, h3, h4, h5, h6 {
margin: 0;
padding: 0;
font-size: inherit;
font-weight: inherit;
line-height: inherit;
}
.container {
position: relative;
min-width: 100vw;
max-width: 100vw;
width: 100vw;
height: 100vh;
overflow-x: hidden;
overflow-y: auto;
}
<template>
<div class="container about-bg">
<AppHeader />
<img src="@/assets/icon1.png" alt="" class="about-icon1" />
<img src="@/assets/icon2.png" alt="" class="about-icon2" />
<div class="about-main" :class="{ 'rtl': $i18n.locale === 'ar' }" dir="ltr">
<div class="about-title">{{$t('about.join')}}</div>
<div class="about-swiper">
<swiper
:modules="modules"
:direction="'vertical'"
:slides-per-view="1"
:space-between="0"
:mousewheel="{ releaseOnEdges: true }"
:pagination="{
clickable: true,
el: '.about-bar',
bulletClass: 'about-bar-bullet',
bulletActiveClass: 'active',
renderBullet: (index, className) => {
return `<div class='${className}'></div>`
}
}"
class="swiper-container"
@swiper="onSwiper"
@slideChange="onSlideChange"
>
<swiper-slide v-for="(slide, index) in slides" :key="index">
<div class="about-content" :class="[`about-content-${index}`, { 'rtl': $i18n.locale === 'ar' }]">
<div class="about-left">
<div class="about-section">
<div class="about-h1">
ABOUT
<img src="@/assets/about/name.png" class="about-name" />
</div>
<div class="about-desc1">{{$t(`about.slides[${index}].desc1`)}}</div>
</div>
<div class="about-section">
<div class="about-h2">{{$t(`about.slides[${index}].title`)}}</div>
<div class="about-desc2" v-html="$t(`about.slides[${index}].desc2`)"></div>
</div>
<div class="about-buttons">
<div class="store-btn google-play">
<img src="@/assets/common/google.png" alt="{{$t('about.google')}}" />
</div>
<div class="store-btn app-store">
<img src="@/assets/common/appstore.png" alt="{{$t('about.appstore')}}" />
</div>
</div>
</div>
<div class="about-right">
<img class="about-phone" :src="slide.image" alt="phone" />
</div>
</div>
</swiper-slide>
</swiper>
<!-- Custom pagination outside swiper -->
<div class="about-bar"></div>
<img src="@/assets/about/icon2.png" alt="" class="about-icon3" />
<!-- Scroll indicator -->
<div class="scroll-indicator" v-if="currentIndex < slides.length - 1" @click="goToNextSlide">
<img class="about-up" src="@/assets/about/up.png" alt="up" />
</div>
</div>
<img src="@/assets/about/icon2.png" alt="" class="about-icon4" />
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import AppHeader from "@/components/AppHeader.vue";
import { Swiper, SwiperSlide } from "swiper/vue";
import { Mousewheel, Pagination } from 'swiper/modules';
import "swiper/css";
import "swiper/css/pagination";
import app1 from "@/assets/about/app1.png";
import app2 from "@/assets/about/app2.png";
import app3 from "@/assets/about/app3.png";
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
const modules = [Mousewheel, Pagination];
const slides = [
{
image: app1,
desc1: "Get To Know Us And Have More Fun",
title: "GLOBAL CANVAS, YOUR LOCAL COLORS",
desc2:
"YAHABBI Community – Where Lifestyles Cross-Pollinate! Be A Cultural Storyteller. Share Hidden Souk<br/> Gems, Date Recipes With Grandma's Touch, Or That Sunset In Wadi Rum.",
},
{
image: app2,
desc1: "Get To Know Us And Have More Fun",
title: "CARDS CONNECT CULTURES",
desc2:
"Platform] Game Zone: Where MENA's Favorite Games Come Alive! Authentic Arab Games:<br /> Challenge Friends In Baloot Championships, Outsmart Rivals In Trix Blitz, Or Dominoes<br /> Marathons – Tradition Meets Tech!",
},
{
image: app3,
desc1: "Get To Know Us And Have More Fun",
title: "WHERE THE MIDDLE EAST CONNECTS",
desc2: "Dive Into YAHABBI's Voice Rooms – Your Gateway To The Arab World! 🎧 Chat LIVE With Users Across 22<br /> Arab Nations, From Maghreb Storytelling To Gulf Business Networking. Unlock The Heartbeat Of MENA<br /> Culture Through Voices!",
},
];
const currentIndex = ref(0);
let swiperInstance = ref(null);
const onSwiper = (swiper) => {
swiperInstance.value = swiper;
};
const onSlideChange = (swiper) => {
currentIndex.value = swiper.activeIndex;
};
const goToSlide = (index) => {
if (swiperInstance.value) {
swiperInstance.value.slideTo(index);
}
};
const goToNextSlide = () => {
if (swiperInstance.value && currentIndex.value < slides.length - 1) {
swiperInstance.value.slideTo(currentIndex.value + 1);
}
};
</script>
<style scoped lang="scss">
.about-bg {
position: relative;
background: #000000;
min-height: 100vh;
overflow: hidden;
}
.about-icon1 {
position: absolute;
left: -698px;
top: -300px;
width: 1396px;
object-fit: cover;
z-index: 0;
}
.about-icon2 {
position: absolute;
right: -422px;
bottom: -478px;
width: 1396px;
object-fit: cover;
z-index: 0;
}
.about-icon3 {
position: absolute;
top: 131px;
left: 670px;
width: 85px;
height: 85px;
z-index: 10;
}
.about-icon4 {
position: absolute;
right: -54px;
top: 32px;
width: 107px;
height: 107px;
z-index: 10;
}
.about-main {
// margin: 0 64px;
// padding-top: 10px;
padding: 10px 64px 0;
position: relative;
z-index: 1;
}
.about-title {
margin-bottom: 41px;
text-align: center;
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: bold;
font-size: 54px;
color: #ffffff;
}
.about-swiper {
position: relative;
height: 660px;
margin: 0 auto;
border-radius: 30px;
overflow: hidden;
}
:deep(.swiper-container) {
width: 100%;
height: 100%;
.swiper-slide {
height: 100%;
width: 100%;
display: flex;
align-items: stretch;
justify-content: stretch;
background: none;
}
}
.about-content {
flex: 1;
display: flex;
justify-content: space-between;
padding: 56px 0 0 60px;
background-image: url(@/assets/about/content_bg.png);
background-size: 100% 100%;
background-repeat: no-repeat;
height: 100%;
border-radius: 30px;
box-sizing: border-box;
transition: all 0.3s;
}
.about-content.rtl {
flex-direction: row-reverse;
padding: 56px 60px 0 0;
}
.about-left {
flex: 1;
display: flex;
flex-direction: column;
padding-right: 100px;
padding-bottom: 60px;
transition: all 0.3s;
}
.rtl .about-left {
padding-right: 0;
padding-left: 100px;
}
.about-right {
position: relative;
display: flex;
justify-content: flex-end;
align-items: center;
height: 100%;
padding-right: 280px;
transition: all 0.3s;
}
.rtl .about-right {
justify-content: flex-start;
padding-right: 0;
padding-left: 280px;
}
.about-section {
margin-bottom: 90px;
width: 100%;
}
.about-h1 {
display: flex;
align-items: center;
font-size: 38px;
font-weight: 900;
color: #fff;
margin-bottom: 8px;
letter-spacing: 1px;
}
.rtl .about-h1 {
flex-direction: row-reverse;
}
.about-name {
width: auto;
height: 70px;
margin-left: 10px;
}
.rtl .about-name {
margin-left: 0;
margin-right: 10px;
}
.about-desc1 {
font-size: 22px;
color: #fff;
font-weight: 400;
text-align: left;
}
.rtl .about-desc1 {
text-align: right;
}
.about-h2 {
margin-bottom: 17px;
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: bold;
font-size: 32px;
color: #ffffff;
text-align: left;
}
.rtl .about-h2 {
text-align: right;
}
.about-desc2 {
font-family: Microsoft YaHei, Microsoft YaHei;
font-size: 18px;
color: #ffffff;
text-align: left;
}
.rtl .about-desc2 {
text-align: right;
}
.about-buttons {
display: flex;
gap: 40px;
margin-top: 20px;
}
.rtl .about-buttons {
flex-direction: row-reverse;
}
.store-btn {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
img {
height: 92px;
}
}
.about-phone {
max-height: 520px;
object-fit: contain;
border-radius: 40px;
box-shadow: 0 8px 32px 0 rgba(24, 31, 43, 0.18);
}
.scroll-indicator {
position: absolute;
right: 177px;
bottom: 57px;
display: flex;
justify-content: flex-end;
align-items: center;
cursor: pointer;
z-index: 10;
animation: bounce 2s infinite;
transition: all 0.3s;
}
.rtl .scroll-indicator {
right: auto;
left: 177px;
justify-content: flex-start;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(-50%) scale(1);
}
40% {
transform: translateY(-60%) scale(1.1);
}
60% {
transform: translateY(-55%) scale(1.05);
}
}
.about-up {
width: 36px;
height: 120px;
object-fit: contain;
}
.about-bar {
display: flex;
justify-content: center;
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
flex-direction: column;
gap: 10px;
z-index: 10;
transition: all 0.3s;
}
.rtl .about-bar {
right: auto;
left: 20px;
}
:deep(.about-bar-bullet) {
width: 10px;
height: 10px;
background-color: #EAEAEA;
border-radius: 50%;
cursor: pointer;
display: block;
transition: all 0.2s ease;
&:hover {
transform: scale(1.2);
}
}
:deep(.about-bar-bullet.active) {
width: 12px;
height: 22px;
background-image: url(@/assets/about/dot_active.png);
background-size: cover;
background-repeat: no-repeat;
border-radius: 0;
background-color: transparent;
margin-left: -2px;
}
@media (max-width: 1200px) {
.about-content {
padding: 40px;
}
.about-left {
max-width: 55%;
}
.about-phone {
max-height: 480px;
}
}
</style>
<template>
<div class="container contact-bg" :class="{ 'rtl': $i18n.locale === 'ar' }">
<AppHeader />
<img src="@/assets/icon1.png" alt="" class="contact-icon1" />
<img src="@/assets/icon2.png" alt="" class="contact-icon2" />
<img src="@/assets/icon2.png" alt="" class="contact-icon3" />
<div class="contact-main">
<div class="contact-content-wrapper">
<div class="contact-content">
<div class="contact-left">
<div class="phone-mockup">
<img src="@/assets/about/app3.png" alt="phone" />
</div>
</div>
<div class="contact-right">
<div class="contact-title" v-html="$t('contact.title')"></div>
<div class="contact-desc">{{$t('contact.desc')}}</div>
<img
class="contact-arrow"
src="@/assets/contact/down.png"
alt="arrow"
/>
<div class="contact-btns">
<img
src="@/assets/common/google.png"
class="store-btn"
:alt="$t('contact.google')"
/>
<img
src="@/assets/common/appstore.png"
class="store-btn"
:alt="$t('contact.appstore')"
/>
</div>
<img
class="star-deco"
src="@/assets/contact/icon3.png"
alt="star"
/>
</div>
</div>
</div>
</div>
<div class="footer-wrapper">
<img
class="footer-bg-curve"
src="@/assets/contact/bottom_bg.png"
alt="footer-bg"
/>
<div class="footer-content">
<div class="footer-main">
<div class="footer-brand">
<div class="footer-title">{{$t('contact.yahabbi')}}</div>
<div class="footer-subtitle">{{$t('contact.focus')}}</div>
</div>
<div class="footer-links-group">
<div class="footer-col">
<div class="footer-col-title">{{$t('contact.contactus')}}</div>
<div class="footer-col-item">{{$t('contact.email')}}</div>
<div class="footer-col-item">{{$t('contact.phone')}}</div>
</div>
<div class="footer-col">
<div class="footer-col-title">{{$t('contact.topup')}}</div>
<div class="footer-col-item">{{$t('contact.recharge')}}</div>
</div>
<div class="footer-col">
<div class="footer-col-title">{{$t('contact.download')}}</div>
<div class="footer-col-item">{{$t('contact.android')}}</div>
<div class="footer-col-item">{{$t('contact.apple')}}</div>
</div>
</div>
</div>
<div class="footer-bottom">
<div class="copyright">{{$t('contact.copyright')}}</div>
<div class="legal-links">
<span>{{$t('contact.aboutus')}}</span>
<span>{{$t('contact.terms')}}</span>
<span>{{$t('contact.privacy')}}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import AppHeader from "@/components/AppHeader.vue";
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
</script>
<style scoped lang="scss">
.contact-bg {
background-color: #000000;
position: relative;
overflow-x: hidden;
}
.contact-icon1 {
position: absolute;
left: -698px;
top: -300px;
width: 1396px;
object-fit: cover;
z-index: 0;
}
.contact-icon2 {
position: absolute;
right: -422px;
bottom: -308px;
width: 1396px;
object-fit: cover;
z-index: 0;
}
.contact-icon3 {
position: fixed;
left: 50%;
transform: translateX(-50%);
bottom: 0;
width: 648px;
height: 458px;
object-fit: cover;
z-index: 1;
}
.contact-main {
width: 100%;
padding: 34px 102px 39px;
box-sizing: border-box;
position: relative;
z-index: 2;
}
.contact-content-wrapper {
background-image: url("@/assets/contact/content_bg.png");
background-size: 100% 100%;
background-repeat: no-repeat;
}
.contact-content {
position: relative;
display: flex;
align-items: flex-end;
justify-content: space-between;
}
.contact-left {
position: absolute;
bottom: -107px;
left: 160px;
// flex: 1;
// transform: translateY(40px);
}
.rtl .contact-left {
left: auto;
right: 160px;
}
.phone-mockup img {
width: 415px;
height: auto;
object-fit: contain;
}
.contact-right {
flex: 1;
padding: 121px 0 60px 800px;
position: relative;
}
.rtl .contact-right {
padding: 121px 800px 60px 0;
}
.contact-title {
font-size: 64px;
font-weight: 900;
color: #fff;
line-height: 1.2;
margin-bottom: 24px;
}
.highlight {
position: relative;
display: inline-block;
background: linear-gradient(90deg, #c844ff 0%, #982fff 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
padding-bottom: 5px;
&::after {
content: "";
position: absolute;
bottom: -12px;
left: 0;
width: 100%;
height: 34px;
background: url(@/assets/leadership/name_desc.png);
background-size: cover;
background-repeat: no-repeat;
}
}
.highlight-underline {
position: absolute;
bottom: -5px;
left: 0;
width: 100%;
height: 20px;
object-fit: fill;
}
.contact-desc {
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: 600;
font-size: 16px;
color: #ffffff;
margin-bottom: 60px;
}
.contact-arrow {
width: 36px;
height: auto;
margin-bottom: 80px;
animation: arrow-down-bounce 1.5s infinite;
}
@keyframes arrow-down-bounce {
0%, 100% {
transform: translateY(0);
}
30% {
transform: translateY(18px);
}
60% {
transform: translateY(8px);
}
}
.contact-btns {
display: flex;
gap: 24px;
}
.store-btn {
display: flex;
align-items: center;
gap: 12px;
background: #fff;
border: none;
border-radius: 40px;
padding: 16px 36px;
font-size: 18px;
font-weight: 700;
color: #000;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(255, 255, 255, 0.2);
}
.store-btn:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(255, 255, 255, 0.3);
}
.main-buttons {
position: absolute;
right: 90px;
bottom: 120px;
display: flex;
gap: 74px;
}
.store-btn {
height: 98px;
display: flex;
align-items: center;
cursor: pointer;
}
.store-btn img {
height: 48px;
}
.store-btn img {
height: 28px;
}
.star-deco {
position: absolute;
top: 210px;
right: 120px;
width: 80px;
height: 80px;
}
.rtl .star-deco {
right: auto;
left: 120px;
}
.footer-wrapper {
width: 100%;
position: relative;
z-index: 1;
}
.footer-bg-curve {
width: 100%;
display: block;
position: absolute;
top: 0;
left: 0;
z-index: -1;
}
.footer-content {
padding-top: 200px;
padding-bottom: 24px;
color: #fff;
}
.footer-main {
width: 100%;
padding: 0 102px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
margin-bottom: 40px;
}
.footer-brand {
flex-shrink: 0;
}
.footer-title {
font-size: 40px;
font-weight: 800;
margin-bottom: 8px;
}
.footer-subtitle {
font-size: 18px;
opacity: 0.8;
}
.footer-links-group {
display: flex;
gap: 80px;
padding-top: 10px;
}
.footer-col-title {
font-size: 20px;
font-weight: 700;
margin-bottom: 16px;
}
.footer-col-item {
font-size: 16px;
line-height: 1.8;
opacity: 0.8;
}
.footer-bottom {
width: 100%;
padding: 20px 102px 0 102px;
box-sizing: border-box;
border-top: 1px solid #fff;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
opacity: 0.7;
}
.legal-links {
display: flex;
gap: 40px;
}
</style>
<template>
<div class="container design-bg">
<AppHeader class="header-abs" />
<main class="main">
<div class="content">
<h1 class="main-title" v-html="$t('home.title')"></h1>
<div class="main-subtitle">{{$t('home.subtitle')}}</div>
<div class="main-desc">{{$t('home.desc')}}</div>
<div class="main-buttons">
<img
src="@/assets/common/google.png"
class="store-btn"
:alt="$t('home.google')"
/>
<img
src="@/assets/common/appstore.png"
class="store-btn"
:alt="$t('home.appstore')"
/>
</div>
</div>
</main>
</div>
</template>
<script setup>
import AppHeader from "@/components/AppHeader.vue";
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
</script>
<style scoped>
.design-bg {
display: flex;
flex-direction: column;
background: url("@/assets/home/bg.png") center top/1920px 1080px no-repeat;
}
.main {
position: relative;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.content {
position: relative;
margin: 0 80px;
padding: 82px 90px 120px 162px;
height: 787px;
background: rgba(0, 0, 0, 0.35);
border-radius: 36px 36px 36px 36px;
}
.main-title {
margin-bottom: 49px;
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: bold;
font-size: 72px;
color: #ffffff;
letter-spacing: 4px;
text-shadow: 0px 5px 15px rgba(0, 0, 0, 0.35);
}
.main-subtitle {
margin-bottom: 13px;
font-family: Microsoft YaHei, Microsoft YaHei;
font-size: 34px;
color: #ffffff;
text-shadow: 0px 4px 5px rgba(0, 0, 0, 0.35);
}
.main-desc {
font-family: Microsoft YaHei, Microsoft YaHei;
font-size: 18px;
color: #ffffff;
text-shadow: 0px 4px 5px rgba(0, 0, 0, 0.35);
}
.main-buttons {
position: absolute;
right: 90px;
bottom: 120px;
display: flex;
gap: 74px;
}
.store-btn {
height: 98px;
display: flex;
align-items: center;
cursor: pointer;
}
.store-btn img {
height: 48px;
}
.footer-abs {
position: absolute;
left: 0;
bottom: 0;
width: 1920px;
z-index: 10;
}
</style>
<template>
<div class="container leadership-bg" :class="{ rtl: $i18n.locale === 'ar' }">
<AppHeader />
<img src="@/assets/icon1.png" alt="" class="leadership-icon1" />
<img src="@/assets/icon2.png" alt="" class="leadership-icon2" />
<img src="@/assets/leadership/icon5.png" alt="" class="leadership-icon4" />
<div class="leadership-main">
<div class="leadership-title" v-html="$t('leadership.title')"></div>
<img
class="star star-left"
src="@/assets/leadership/icon3.png"
alt="star"
/>
<img
class="star star-right"
src="@/assets/leadership/icon4.png"
alt="star"
/>
<div class="leadership-slider-outer">
<div class="arrow-btn-outer">
<div class="arrow-btn left" @click="slidePrev">
<img src="@/assets/leadership/left.png" alt="left" />
</div>
<div class="arrow-btn right" @click="slideNext">
<img src="@/assets/leadership/right.png" alt="right" />
</div>
</div>
<div class="leadership-slider" :key="$i18n.locale">
<Swiper
:modules="modules"
:slides-per-view="4"
:space-between="71"
:navigation="false"
:loop="leaders.length > 4"
class="leader-swiper"
@swiper="onSwiper"
>
<SwiperSlide v-for="(leader, idx) in leaders" :key="idx">
<div class="leader-card">
<img class="leader-photo" :src="leader.photo" alt="leader" />
<span class="dot"></span>
<div class="leader-info-bar">
<div class="leader-name">{{ $t("leadership.name") }}</div>
<div class="leader-position">
{{ $t("leadership.position") }}
</div>
</div>
</div>
</SwiperSlide>
</Swiper>
</div>
</div>
<div class="team-intro-block">
<div class="team-intro-text">
<div class="team-intro-title">{{ $t("leadership.team_intro") }}</div>
<div class="team-intro-desc">{{ $t("leadership.team_desc1") }}</div>
<div class="team-intro-desc">{{ $t("leadership.team_desc2") }}</div>
</div>
<img
class="team-intro-img"
src="@/assets/leadership/name_desc.png"
alt="team"
/>
<img
src="@/assets/leadership/icon5.png"
alt=""
class="leadership-icon3"
/>
</div>
</div>
</div>
</template>
<script setup>
import AppHeader from "@/components/AppHeader.vue";
import { Swiper, SwiperSlide } from "swiper/vue";
import { Navigation } from "swiper/modules";
import "swiper/css";
import leader1 from "@/assets/leadership/icon1.png";
import leader2 from "@/assets/leadership/icon2.png";
import leader3 from "@/assets/leadership/icon3.png";
import leader4 from "@/assets/leadership/icon4.png";
import leader5 from "@/assets/leadership/icon5.png";
import { ref, watch } from "vue";
import { useI18n } from "vue-i18n";
const { t, locale } = useI18n();
const modules = [Navigation];
const leaders = [
{ photo: leader1 },
{ photo: leader2 },
{ photo: leader3 },
{ photo: leader4 },
{ photo: leader5 },
];
const swiperRef = ref(null);
const onSwiper = (swiper) => {
swiperRef.value = swiper;
};
const slidePrev = () => {
swiperRef.value && swiperRef.value.slidePrev();
};
const slideNext = () => {
swiperRef.value && swiperRef.value.slideNext();
};
// Watch for changes in the locale
watch(locale, (newLocale) => {
console.log("123 locale.value", newLocale);
if (swiperRef.value) {
console.log('123 11');
swiperRef.value.update(); // Update the Swiper instance
}
});
</script>
<style scoped lang="scss">
.leadership-bg {
background: #000000;
position: relative;
padding-bottom: 40px;
}
.leadership-icon1 {
position: absolute;
left: -698px;
top: -300px;
width: 1396px;
object-fit: cover;
z-index: 0;
}
.leadership-icon2 {
position: absolute;
right: -422px;
bottom: -308px;
width: 1396px;
object-fit: cover;
z-index: 0;
}
.leadership-icon3 {
width: 212px;
height: 212px;
position: absolute;
left: 222px;
bottom: -8px;
}
.leadership-icon4 {
width: 212px;
height: 212px;
position: absolute;
right: -24px;
top: 577px;
}
.leadership-main {
position: relative;
max-width: 1400px;
margin: 0 auto;
padding-top: 48px;
}
.leadership-title {
position: relative;
margin-bottom: 49px;
padding-left: 40px;
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: 800;
font-size: 52px;
color: #ffffff;
z-index: 2;
.highlight {
position: relative;
display: inline-block;
font-weight: 800;
background: linear-gradient(90deg, #c844ff 0%, #982fff 100%);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
-webkit-text-fill-color: transparent;
line-height: 1.1;
padding-bottom: 0;
&::after {
content: "";
position: absolute;
bottom: -8px;
left: 0;
width: 100%;
height: 34px;
background: url(@/assets/leadership/name_desc.png);
background-size: cover;
background-repeat: no-repeat;
z-index: -1;
}
}
}
.star-left {
position: absolute;
width: 60px;
top: 88px;
left: -61px;
width: 61px;
height: 60px;
}
.star-right {
position: absolute;
width: 60px;
top: 13px;
left: 50%;
transform: translateX(-50%);
width: 80px;
height: 80px;
}
.leadership-slider-outer {
width: 100%;
max-width: 1400px;
margin: 0 auto 69px auto;
position: relative;
}
.leadership-slider {
position: relative;
width: 100%;
padding: 28px 17px 28px 41px;
box-sizing: border-box;
overflow: hidden;
}
.arrow-btn-outer {
position: absolute;
right: -71px;
top: 50%;
transform: translateY(-50%);
display: flex;
align-items: center;
z-index: 10;
}
.rtl .arrow-btn-outer {
right: auto;
left: -71px;
flex-direction: row-reverse;
}
.arrow-btn {
width: 18px;
height: 26px;
cursor: pointer;
}
.leader-swiper {
width: 100%;
max-width: 1400px;
overflow: visible;
.swiper-wrapper {
align-items: stretch;
overflow: visible;
}
.swiper-slide {
overflow: visible;
}
}
.leadership-cards {
display: flex;
gap: 71px;
overflow: visible;
}
.leader-card {
background: #fff1;
border-radius: 8px;
overflow: visible;
width: 283px;
height: 341px;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
}
.leader-card:hover {
transform: scale(1.07) translateY(-8px);
z-index: 3;
}
.leader-photo {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 8px;
}
.dot {
position: absolute;
top: 15px;
right: 16px;
width: 12px;
height: 12px;
background: #fff;
border-radius: 50%;
border: 2px solid #eaeaea;
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.08);
z-index: 3;
}
.leader-info-bar {
position: absolute;
left: -23px;
bottom: 13px;
width: 262px;
height: 102px;
padding: 10px 22px 22px;
background: linear-gradient(90deg, #c22fff 0%, #8b17ff 100%), #b178ff;
border-radius: 8px;
box-sizing: border-box;
}
.leader-name {
margin-bottom: 5px;
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: 600;
font-size: 28px;
color: #ffffff;
}
.leader-position {
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: 600;
font-size: 20px;
color: #ffffff;
}
.team-intro-block {
display: flex;
align-items: center;
margin: 0 auto;
max-width: 1400px;
width: 100%;
height: 350px;
min-height: 350px;
padding: 32px 28px 37px 27px;
overflow: hidden;
background-image: url(@/assets/leadership/content_bg.png);
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
}
.team-intro-desc + .team-intro-desc {
margin-top: 12px;
}
.team-intro-text {
padding-top: 38px;
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
}
.team-intro-title {
margin-bottom: 20px;
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: 600;
font-size: 32px;
color: #ffffff;
}
.team-intro-desc {
font-family: Microsoft YaHei, Microsoft YaHei;
font-weight: 600;
font-size: 16px;
color: #ffffff;
}
.team-intro-img {
flex: 1;
object-fit: cover;
width: 834px;
height: 295px;
border-radius: 20px;
}
@media (max-width: 1200px) {
.leadership-main {
max-width: 98vw;
}
.leader-swiper {
width: 98vw;
}
.team-intro-block {
flex-direction: column;
min-height: 0;
}
.team-intro-img {
min-width: 0;
max-width: 100%;
border-radius: 0 0 20px 20px;
}
}
</style>
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'url'
// https://vite.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!