Initial SuperAdmin web panel (Vue 3)

This commit is contained in:
SuperAdmin
2026-07-23 10:24:50 +03:30
commit 0f94a49b8d
63 changed files with 4762 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import {
MessageOutlined,
CloudServerOutlined,
TeamOutlined,
HomeOutlined,
} from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import api from '@/api/http'
type Tenant = { id: string; product: 'hamkar' | 'khanegi' }
const router = useRouter()
const loading = ref(true)
const tenants = ref<Tenant[]>([])
const hamkarCount = computed(() => tenants.value.filter((t) => t.product === 'hamkar').length)
const khanegiCount = computed(() => tenants.value.filter((t) => t.product === 'khanegi').length)
const modules = computed(() => [
{
key: 'sms',
className: 'sms',
title: 'پنل پیامکی',
desc: 'ارسال و مدیریت پیامک مشترک برای همکار و خانگی در یکجا',
meta: 'مرکزی',
icon: MessageOutlined,
to: { name: 'sms-panel' as const },
},
{
key: 'server',
className: 'server',
title: 'پنل سرور',
desc: 'شارژ، تمدید و پیگیری وضعیت سرورهای نسخه‌های فروشی',
meta: 'جدید',
icon: CloudServerOutlined,
to: { name: 'server-panel' as const },
},
{
key: 'hamkar',
className: 'hamkar',
title: 'همکار',
desc: 'مدیریت نسخه‌های فروشی پروژه همکار',
meta: `${hamkarCount.value} نسخه`,
icon: TeamOutlined,
to: { name: 'product-versions' as const, params: { product: 'hamkar' } },
},
{
key: 'khanegi',
className: 'khanegi',
title: 'خانگی',
desc: 'مدیریت نسخه‌های فروشی و ظاهر اپ خانگی',
meta: `${khanegiCount.value} نسخه`,
icon: HomeOutlined,
to: { name: 'product-versions' as const, params: { product: 'khanegi' } },
},
])
async function load() {
loading.value = true
try {
const { data } = await api.get('/tenants')
tenants.value = data
} catch (e: any) {
message.error(e?.response?.data?.message || 'خطا در دریافت آمار')
} finally {
loading.value = false
}
}
onMounted(load)
</script>
<template>
<div class="page-shell">
<div class="login-kicker">داشبورد کنترل</div>
<h1 class="page-title">سلام، خوش آمدید</h1>
<p class="page-sub">
از اینجا به پنل پیامکی، پنل سرور و نسخه‌های همکار / خانگی دسترسی دارید.
</p>
<a-spin :spinning="loading">
<div class="dash-modules">
<button
v-for="item in modules"
:key="item.key"
type="button"
class="module-card"
:class="item.className"
@click="router.push(item.to)"
>
<div>
<div class="icon-wrap">
<component :is="item.icon" />
</div>
<h3>{{ item.title }}</h3>
<p>{{ item.desc }}</p>
</div>
<div>
<div class="progress"><span /></div>
<div class="module-meta">
<span>{{ item.meta }}</span>
<span>ورود ←</span>
</div>
</div>
</button>
</div>
</a-spin>
</div>
</template>