Split desktop and mobile layouts with shared page data so APIs fetch once per context.

Add layout shells, desktop views, module-level page caches, and UI fixes for auth, home, wallet, transactions, address, and related pages.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-14 10:08:46 +03:30
co-authored by Cursor
parent 4404b4cb92
commit a5e458ed25
234 changed files with 18425 additions and 5503 deletions
@@ -0,0 +1,103 @@
<template>
<div
:class="variant === 'desktop'
? 'deducate-content'
: 'mt-5 text-5 border-solid border-2 border-[#093D51] text-[#093D51] rounded-[12px] p-4'"
>
<div
v-if="variant === 'desktop'"
class="deducate-content__avatar-wrap"
>
<img :src="config.config.avatar" alt="" class="deducate-content__avatar" />
</div>
<div
v-else
class="h-20vh flex justify-center"
>
<img :src="config.config.avatar" alt="" class="mb-20 h-15vh mt-5" />
</div>
<div :class="variant === 'desktop' ? 'deducate-content__body' : ''">
<div
:class="variant === 'desktop' ? 'deducate-content__section-title' : 'font-bold text-sm text-[#093D51]'"
>
شیوهٔ ورود و ثبت ‌نام در گروسی گالری
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• برای ثبت‌نام در گروسی گالری، اگر قبلاً حساب کاربری دارید می‌توانید از طریق پیامک وارد شوید.<br />
• اگر حساب کاربری ندارید، "از این قسمت" وارد صفحه ثبت نام شده و با وارد کردن نام و شماره تلفنی که با کد ملی شما مطابقت دارد، حساب کاربری بسازید.<br />
• الزامی به وارد کردن کد معرف نیست.
</div>
<img :src="img1" :class="variant === 'desktop' ? 'deducate-content__image' : ''" />
<div :class="variant === 'desktop' ? 'deducate-content__divider' : 'w-full h-1px my-3 bg-secondary'"></div>
<div :class="variant === 'desktop' ? 'deducate-content__section-title' : 'font-bold mt-4 text-sm text-[#093D51]'">
شارژ کیف پول
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• ابتدا کیف پول را در منو انتخاب کرده، مبلغ مورد نظر را وارد نموده و دکمه واریز را انتخاب کنید تا کیف پول شما شارژ شود.<br />
</div>
<img :src="img2" :class="variant === 'desktop' ? 'deducate-content__image' : ''" />
<div :class="variant === 'desktop' ? 'deducate-content__divider' : 'w-full h-1px my-3 bg-secondary'"></div>
<div :class="variant === 'desktop' ? 'deducate-content__section-title' : 'font-bold mt-4 text-sm text-[#093D51]'">
شیوهٔ خرید از گروسی گالری
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• سپس از بخش «خرید و فروش» انتخاب کنید که طلای آب‌شده می‌خواهید یا محصولات دیگر (شامل گوی، شمش یا مکعب).<br />
• توجه داشته باشید کارمزد طلای آب‌شده حدود ۲٪ است و کارمزد ریالی محصولات دیگر در پایین صفحه قیمت درج شده است.
</div>
<img :src="img4" :class="variant === 'desktop' ? 'deducate-content__image' : ''" />
<div :class="variant === 'desktop' ? 'deducate-content__divider' : 'w-full h-1px my-3 bg-secondary'"></div>
<div :class="variant === 'desktop' ? 'deducate-content__section-title' : 'font-bold mt-4 text-sm text-[#093D51]'">
شیوهٔ فروش در گروسی گالری
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• برای فروش محصولاتی که خریداری کرده‌اید، به بخش «خرید و فروش» مراجعه کرده، محصول موردنظر را انتخاب و گزینه فروش را بزنید تا مبلغ قابل دریافت نمایش داده شود.<br />
• مبلغ به کیف پول شما واریز می‌شود و از طریق پیام پشتیبانی می‌توانید درخواست برداشت دهید.<br />
• اگر موجودی کیف پول بیش از ۱۰ میلیون تومان باشد، مبلغ تا پایان روز کاری بعد به حساب اعلام‌شده شما واریز خواهد شد.
</div>
<div :class="variant === 'desktop' ? 'deducate-content__divider' : 'w-full h-1px my-3 bg-secondary'"></div>
<div :class="variant === 'desktop' ? 'deducate-content__section-title' : 'font-bold mt-4 text-sm text-[#093D51]'">
شیوهٔ دریافت فیزیکی طلا (ارسال)
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• ابتدا موجودی محصول موردنظر را با پشتیبانی در واتساپ هماهنگ کنید.<br />
• سپس روی لوگو کلیک کرده، گزینه «برداشت فیزیکی» و بعد «درخواست جدید» را انتخاب کنید.<br />
• محصولات خریداری‌شده و تعداد آن‌ها را مشخص کرده و آدرس خود را ثبت نمایید.<br />
• پشتیبانی عکس و وزن محصول را برای شما ارسال می‌کند.<br />
• ارسال به‌صورت پس‌کرایه و بیمه‌شده انجام می‌شود.<br />
</div>
<div :class="variant === 'desktop' ? 'deducate-content__divider' : 'w-full h-1px my-3 bg-secondary'"></div>
<div :class="variant === 'desktop' ? 'deducate-content__section-title' : 'font-bold mt-4 text-sm text-[#093D51]'">
پاداش معرفی
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• در صفحه اصلی روی "تنظیمات" کلیک کرده و وارد حساب کاربری خود شوید.
</div>
<div :class="variant === 'desktop' ? 'deducate-content__text' : 'mt-5 text-xs leading-5'">
• سپس گزینه «اشتراک‌گذاری» یا «کپی لینک» را انتخاب کرده و لینک دعوت را برای دوستانتان ارسال کنید.<br />
• در صورتی که دوستان شما از طریق لینک شما ثبت‌نام کنند، به‌صورت خودکار ۱ سوت طلا به‌عنوان پاداش دریافت خواهید کرد.
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import img1 from '@/assets/img/1.png'
import img2 from '@/assets/img/2.png'
import img4 from '@/assets/img/4.png'
import { useEducatePageContext } from '../composables/useEducatePage'
withDefaults(
defineProps<{
variant?: 'mobile' | 'desktop'
}>(),
{ variant: 'mobile' },
)
const { config } = useEducatePageContext()
</script>
@@ -0,0 +1,43 @@
<template>
<div
v-if="config.config.name === 'garoosi'"
:class="variant === 'desktop' ? 'deducate-support' : 'wrap-fix bottom-0 px-10 py-6 flex gap-2 bg-white'"
>
<a class="w-full" href="tel:09031265925">
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
</a>
<a href="https://ble.ir/garoosigallery">
<img
src="@/assets/img/bale.png"
alt=""
:class="variant === 'desktop' ? 'deducate-support__bale' : 'h-10 w-10'"
/>
</a>
</div>
<div
v-else
:class="variant === 'desktop' ? 'deducate-support' : 'wrap-fix bottom-0 px-10 py-5 flex gap-2 bg-white'"
>
<a class="w-full" href="tel:09306612518">
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
</a>
<a href="">
<BasicButton icon="vuesax-linear:whatsapp" />
</a>
</div>
</template>
<script lang="ts" setup>
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
import { useEducatePageContext } from '../composables/useEducatePage'
withDefaults(
defineProps<{
variant?: 'mobile' | 'desktop'
}>(),
{ variant: 'mobile' },
)
const { config } = useEducatePageContext()
</script>
@@ -0,0 +1,105 @@
import { inject, onMounted, provide, ref, type InjectionKey } from 'vue'
import type { FormInstance } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { updateMe } from '@/api/me'
import type { User } from '@/models/login'
import { useConfigStore } from '@/store/configStore'
import { useUserStore } from '@/store/userStore'
import { loading } from '@/utils'
export interface EducatePageContext {
config: ReturnType<typeof useConfigStore>
userFormState: ReturnType<typeof ref<User>>
formRef: ReturnType<typeof ref<FormInstance | undefined>>
editPassVisible: ReturnType<typeof ref<boolean>>
setForm: () => void
copyCode: () => void
resetData: () => void
ok: () => void
}
export const EDUCATE_PAGE_CONTEXT_KEY: InjectionKey<EducatePageContext> = Symbol('educatePageContext')
export function useEducatePage() {
const config = useConfigStore()
const userStore = useUserStore()
const userFormState = ref<User>({
fname: '',
lname: '',
mobile: undefined,
birth_date: '',
phone_number: '',
province: '',
city: '',
n_code: undefined,
})
const formRef = ref<FormInstance>()
const editPassVisible = ref<boolean>(false)
function setForm() {
userFormState.value = userStore.userInfo
}
function copyCode() {
const val = userStore.userInfo?.referral_id
navigator.clipboard.writeText(val)
message.info('کد رونوشت شد')
}
const resetData = () => {
formRef.value?.resetFields()
userFormState.value = {
fname: '',
lname: '',
mobile: undefined,
birth_date: '',
phone_number: '',
province: '',
city: '',
n_code: undefined,
}
}
function ok() {
formRef.value?.validateFields().then(async () => {
try {
loading.value = true
await updateMe(userFormState.value)
await userStore.getMyInfo()
editPassVisible.value = false
message.success('اطلاعات شما با موفقیت به روز رسانی شد')
} catch (e) {
console.log(e)
} finally {
loading.value = false
}
})
}
onMounted(() => {
setForm()
})
const context: EducatePageContext = {
config,
userFormState,
formRef,
editPassVisible,
setForm,
copyCode,
resetData,
ok,
}
provide(EDUCATE_PAGE_CONTEXT_KEY, context)
return context
}
export function useEducatePageContext() {
const context = inject(EDUCATE_PAGE_CONTEXT_KEY)
if (!context) {
throw new Error('useEducatePageContext must be used within a page that calls useEducatePage()')
}
return context
}
@@ -0,0 +1,52 @@
<template>
<div class="deducate">
<div class="deducate__container">
<header class="deducate-topbar">
<button type="button" class="deducate-topbar__back" @click="router.back()">
<BasicIcon icon="vuesax-linear:arrow-right-1" size="18" />
<span>بازگشت</span>
</button>
<div class="deducate-topbar__meta">
<p class="deducate-topbar__eyebrow">راهنما</p>
<h1 class="deducate-topbar__title">آموزش نرم افزار</h1>
</div>
</header>
<div class="deducate-layout">
<section class="deducate-surface deducate-main">
<div class="deducate-main__intro">
<div class="deducate-main__logo">
<BasicIcon icon="vuesax-linear:book" size="28" />
</div>
<div>
<h2 class="deducate-main__project">{{ config.config.name_fa }}</h2>
<p class="deducate-main__tagline">آموزش گام‌به‌گام استفاده از خدمات</p>
</div>
</div>
<div class="deducate-main__scroll">
<EducateContentPanel variant="desktop" />
</div>
</section>
<aside class="deducate-surface deducate-side">
<h3 class="deducate-side__title">پشتیبانی و ارتباط</h3>
<p class="deducate-side__text">
در صورت نیاز به راهنمایی بیشتر، با پشتیبانی تماس بگیرید.
</p>
<EducateSupportActions variant="desktop" />
</aside>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import router from '@/router'
import EducateContentPanel from '../components/EducateContentPanel.vue'
import EducateSupportActions from '../components/EducateSupportActions.vue'
import { useEducatePageContext } from '../composables/useEducatePage'
const { config } = useEducatePageContext()
</script>
@@ -0,0 +1,231 @@
/* Premium desktop educate page */
.deducate {
min-height: 100%;
background: #f6f7f9;
color: #111827;
}
.deducate__container {
max-width: 1080px;
margin: 0 auto;
padding: 28px 36px 40px;
}
.deducate-topbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 28px;
padding-bottom: 24px;
border-bottom: 1px solid rgba(15, 23, 42, 0.06);
&__back {
display: inline-flex;
align-items: center;
gap: 8px;
border: none;
background: transparent;
color: #6b7280;
font-size: 13px;
font-weight: 500;
font-family: inherit;
cursor: pointer;
padding: 8px 0;
&:hover {
color: #111827;
}
}
&__meta {
flex: 1;
min-width: 0;
}
&__eyebrow {
font-size: 12px;
font-weight: 500;
color: #9ca3af;
margin: 0 0 4px;
}
&__title {
font-size: 26px;
font-weight: 600;
letter-spacing: -0.03em;
color: #111827;
margin: 0;
line-height: 1.2;
}
}
.deducate-layout {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
gap: 20px;
align-items: start;
}
.deducate-surface {
background: #fff;
border: 1px solid rgba(15, 23, 42, 0.06);
border-radius: 16px;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}
.deducate-main {
padding: 28px;
display: flex;
flex-direction: column;
min-height: 0;
max-height: calc(100vh - 180px);
&__intro {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 24px;
padding-bottom: 20px;
border-bottom: 1px solid #eef0f3;
flex-shrink: 0;
}
&__logo {
display: flex;
align-items: center;
justify-content: center;
width: 56px;
height: 56px;
border-radius: 14px;
background: rgba(9, 61, 81, 0.08);
color: @App-primary-color;
flex-shrink: 0;
}
&__project {
font-size: 18px;
font-weight: 700;
color: #111827;
margin: 0 0 4px;
}
&__tagline {
font-size: 13px;
color: #6b7280;
margin: 0;
}
&__scroll {
flex: 1;
min-height: 0;
overflow-y: auto;
padding-left: 4px;
margin-left: -4px;
}
}
.deducate-content {
padding: 20px;
border: 1px solid rgba(9, 61, 81, 0.15);
border-radius: 12px;
background: rgba(9, 61, 81, 0.03);
color: @App-primary-color;
&__avatar-wrap {
display: flex;
justify-content: center;
margin-bottom: 20px;
}
&__avatar {
max-height: 120px;
width: auto;
object-fit: contain;
}
&__section-title {
font-size: 15px;
font-weight: 700;
color: inherit;
margin: 0 0 10px;
}
&__text {
font-size: 13px;
line-height: 1.8;
color: inherit;
text-align: justify;
margin: 0 0 12px;
}
&__image {
display: block;
width: 100%;
max-width: 100%;
height: auto;
margin: 12px 0 4px;
border-radius: 8px;
}
&__divider {
width: 100%;
height: 1px;
background: rgba(9, 61, 81, 0.12);
margin: 16px 0;
}
}
.deducate-side {
padding: 24px;
position: sticky;
top: 24px;
&__title {
font-size: 15px;
font-weight: 600;
color: #111827;
margin: 0 0 8px;
}
&__text {
font-size: 13px;
line-height: 1.7;
color: #6b7280;
margin: 0 0 20px;
}
}
.deducate-support {
display: flex;
flex-direction: row;
align-items: center;
gap: 8px;
> a:first-child {
flex: 1;
min-width: 0;
}
&__bale {
width: 40px;
height: 40px;
object-fit: contain;
flex-shrink: 0;
}
}
@media (max-width: 1023.98px) {
.deducate-layout {
grid-template-columns: 1fr;
}
.deducate-side {
position: static;
}
.deducate-main {
max-height: none;
}
}
+12 -196
View File
@@ -1,208 +1,24 @@
<template>
<div>
<div class="wrap-fix z-1 bg-white py-3 px-3 text-black font-bold drop-shadow flex">
<div @click="router.back()" class="cursor-pointer">
<BasicIcon icon="vuesax-linear:arrow-right-1" />
</div>
<div class="mr-2">آموزش نرم افزار</div>
</div>
<div class="pt-10">
<div>
<!-- <img :src="img" alt="" class="mt-2 w-full absolute bottom-0" />-->
<!-- <img :src="config.config.avatar" alt="" class="mt-2 w-full absolute bottom-0">-->
</div>
<div class="text-justify text-base z-200000 relative">
<div class="px-10">
<div class="h-20vh flex justify-center">
<img :src="config.config.avatar" alt="" class="mb-20 h-15vh mt-5">
</div>
<div class="overflow-y-auto h-60vh pb-10 border-[#093D51]">
<div
class="mt-5 text-5 border-solid border-2 border-[#093D51] text-[#093D51] rounded-[12px] p-4"
>
<div class="font-bold text-sm text-[#093D51]">
شیوهٔ ورود و ثبت ‌نام در گروسی گالری
</div>
<div class="mt-5 text-xs leading-5">
• برای ثبت‌نام در گروسی گالری، اگر قبلاً حساب کاربری دارید می‌توانید از طریق پیامک وارد شوید.<br />
• اگر حساب کاربری ندارید، "از این قسمت" وارد صفحه ثبت نام شده و با وارد کردن نام و شماره تلفنی که با کد ملی شما مطابقت دارد، حساب کاربری بسازید.<br />
• الزامی به وارد کردن کد معرف نیست.
</div>
<img :src="img1" />
<div class="w-full h-1px my-3 bg-secondary"></div>
<div class="font-bold mt-4 text-sm text-[#093D51]">
شارژ کیف پول
</div>
<div class="mt-5 text-xs leading-5">
• ابتدا کیف پول را در منو انتخاب کرده، مبلغ مورد نظر را وارد نموده و دکمه واریز را انتخاب کنید تا کیف پول شما شارژ شود.<br />
</div>
<img :src="img2" />
<div class="w-full h-1px my-3 bg-secondary"></div>
<div class="font-bold mt-4 text-sm text-[#093D51]">
شیوهٔ خرید از گروسی گالری
</div>
<div class="mt-5 text-xs leading-5">
• سپس از بخش «خرید و فروش» انتخاب کنید که طلای آب‌شده می‌خواهید یا محصولات دیگر (شامل گوی، شمش یا مکعب).<br />
• توجه داشته باشید کارمزد طلای آب‌شده حدود ۲٪ است و کارمزد ریالی محصولات دیگر در پایین صفحه قیمت درج شده است.
</div>
<img :src="img4" />
<div class="w-full h-1px my-3 bg-secondary"></div>
<div class="font-bold mt-4 text-sm text-[#093D51]">
شیوهٔ فروش در گروسی گالری
</div>
<div class="mt-5 text-xs leading-5">
• برای فروش محصولاتی که خریداری کرده‌اید، به بخش «خرید و فروش» مراجعه کرده، محصول موردنظر را انتخاب و گزینه فروش را بزنید تا مبلغ قابل دریافت نمایش داده شود.<br />
• مبلغ به کیف پول شما واریز می‌شود و از طریق پیام پشتیبانی می‌توانید درخواست برداشت دهید.<br />
• اگر موجودی کیف پول بیش از ۱۰ میلیون تومان باشد، مبلغ تا پایان روز کاری بعد به حساب اعلام‌شده شما واریز خواهد شد.
</div>
<div class="w-full h-1px my-3 bg-secondary"></div>
<div class="font-bold mt-4 text-sm text-[#093D51]">
شیوهٔ دریافت فیزیکی طلا (ارسال)
</div>
<div class="mt-5 text-xs leading-5">
• ابتدا موجودی محصول موردنظر را با پشتیبانی در واتساپ هماهنگ کنید.<br />
• سپس روی لوگو کلیک کرده، گزینه «برداشت فیزیکی» و بعد «درخواست جدید» را انتخاب کنید.<br />
• محصولات خریداری‌شده و تعداد آن‌ها را مشخص کرده و آدرس خود را ثبت نمایید.<br />
• پشتیبانی عکس و وزن محصول را برای شما ارسال می‌کند.<br />
• ارسال به‌صورت پس‌کرایه و بیمه‌شده انجام می‌شود.<br />
</div>
<div class="w-full h-1px my-3 bg-secondary"></div>
<div class="font-bold mt-4 text-sm text-[#093D51]">
پاداش معرفی
</div>
<div class="mt-5 text-xs leading-5">
• در صفحه اصلی روی "تنظیمات" کلیک کرده و وارد حساب کاربری خود شوید.
</div>
<!-- <img :src="img2" />-->
<div class="mt-5 text-xs leading-5">
• سپس گزینه «اشتراک‌گذاری» یا «کپی لینک» را انتخاب کرده و لینک دعوت را برای دوستانتان ارسال کنید.<br />
• در صورتی که دوستان شما از طریق لینک شما ثبت‌نام کنند، به‌صورت خودکار ۱ سوت طلا به‌عنوان پاداش دریافت خواهید کرد.
</div>
<!-- <img :src="img3" />-->
</div>
</div>
</div>
<div v-if="config.config.name === 'garoosi'" class="wrap-fix bottom-0 px-10 py-6 flex gap-2 bg-white">
<a class="w-full" href="tel:09031265925">
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
</a>
<a href="https://ble.ir/garoosigallery">
<img src="@/assets/img/bale.png" alt="" class="h-10 w-10"/>
</a>
</div>
<div v-else class="wrap-fix bottom-0 px-10 py-5 flex gap-2 bg-white">
<a class="w-full" href="tel:09306612518">
<BasicButton class="w-full" type="primary">تماس با پشتیبانی</BasicButton>
</a>
<a href="">
<BasicButton icon="vuesax-linear:whatsapp" />
</a>
</div>
</div>
</div>
<!-- <ActionSheet v-model:show="editPassVisible">salam</ActionSheet>-->
<div class="educate-page-root">
<DesktopEducateView v-show="isDesktop" />
<MobileEducateView v-show="!isDesktop" />
</div>
</template>
<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue'
import img from '@/assets/img/user_ly1.svg'
import img1 from '@/assets/img/1.png'
import img2 from '@/assets/img/2.png'
import img4 from '@/assets/img/4.png'
import { loading } from '@/utils'
import BasicButton from '@/components/BasicPacks/BasicButton.vue'
import type { User } from '@/models/login'
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import router from '@/router'
import type { FormInstance } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import { updateMe } from '@/api/me'
import { useUserStore } from '@/store/userStore'
import {useConfigStore} from "@/store/configStore";
const config=useConfigStore()
const userFormState = ref<User>({
fname: '',
lname: '',
mobile: undefined,
birth_date: '',
phone_number: '',
province: '',
city: '',
n_code: undefined
})
const formRef = ref<FormInstance>()
const userStore = useUserStore()
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
import { useEducatePage } from './composables/useEducatePage'
import DesktopEducateView from './desktop/DesktopEducateView.vue'
import MobileEducateView from './mobile/MobileEducateView.vue'
// const editPassVisible = ref<boolean>(false)
const editPassVisible = ref<boolean>(false)
const isDesktop = useDesktopBreakpoint()
function setForm() {
userFormState.value = userStore.userInfo
}
function copyCode() {
// nextTick(() => {
const val = userStore.userInfo?.referral_id
navigator.clipboard.writeText(val)
message.info('کد رونوشت شد')
// })
}
const resetData = () => {
formRef.value?.resetFields()
userFormState.value = {
fname: '',
lname: '',
mobile: undefined,
birth_date: '',
phone_number: '',
province: '',
city: '',
n_code: undefined
}
}
onMounted(() => {
setForm()
})
function ok() {
formRef.value?.validateFields().then(async () => {
try {
loading.value = true
await updateMe(userFormState.value)
await userStore.getMyInfo()
editPassVisible.value = false
message.success('اطلاعات شما با موفقیت به روز رسانی شد')
} catch (e) {
console.log(e)
} finally {
loading.value = false
}
})
}
useEducatePage()
</script>
<style scoped>
/*.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease;
.educate-page-root {
min-height: 100%;
height: 100%;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}*/
/*.trans{
transition: height 1s;
}*/
</style>
@@ -0,0 +1,27 @@
<template>
<div>
<div class="wrap-fix z-1 bg-white py-3 px-3 text-black font-bold drop-shadow flex">
<div class="cursor-pointer" @click="router.back()">
<BasicIcon icon="vuesax-linear:arrow-right-1" />
</div>
<div class="mr-2">آموزش نرم افزار</div>
</div>
<div class="pt-10">
<div class="text-justify text-base z-200000 relative">
<div class="px-10">
<div class="overflow-y-auto h-60vh pb-10 border-[#093D51]">
<EducateContentPanel variant="mobile" />
</div>
</div>
<EducateSupportActions variant="mobile" />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
import router from '@/router'
import EducateContentPanel from '../components/EducateContentPanel.vue'
import EducateSupportActions from '../components/EducateSupportActions.vue'
</script>