From 5586985d1e3021dfee6b107f27347a17aa46f956 Mon Sep 17 00:00:00 2001 From: adonis Date: Sun, 21 Jun 2026 20:27:13 +0330 Subject: [PATCH] fix chart --- src/api/configuration.ts | 9 +- src/api/dashboard.ts | 45 +- src/main.ts | 4 +- src/model/dashboard.ts | 79 +- .../dashboard/components/DashboardHelpTip.vue | 44 + .../components/DashboardLabelWithHelp.vue | 45 + .../components/DashboardSectionHeader.vue | 20 + .../components/DashboardStatCard.vue | 74 + .../dashboard/components/IosInfoBadge.vue | 36 + .../dashboard/composables/useDashboardPage.ts | 309 ++++ src/pages/dashboard/dashboardSectionCopy.ts | 139 ++ src/pages/dashboard/index.vue | 1359 ++++++----------- src/pages/login/components/LoginPanel.vue | 4 +- src/pages/menuPages/configuration/index.vue | 277 ++-- .../menuPages/configuration/settingGroups.ts | 158 ++ .../menuPages/configuration/settingTypes.ts | 11 + src/pages/menuPages/setting/index.vue | 17 +- src/router/index.ts | 129 +- src/router/routes/setting.ts | 93 +- src/store/userStore.ts | 5 +- src/utils/deployAdmin.ts | 17 + 21 files changed, 1727 insertions(+), 1147 deletions(-) create mode 100644 src/pages/dashboard/components/DashboardHelpTip.vue create mode 100644 src/pages/dashboard/components/DashboardLabelWithHelp.vue create mode 100644 src/pages/dashboard/components/DashboardSectionHeader.vue create mode 100644 src/pages/dashboard/components/DashboardStatCard.vue create mode 100644 src/pages/dashboard/components/IosInfoBadge.vue create mode 100644 src/pages/dashboard/composables/useDashboardPage.ts create mode 100644 src/pages/dashboard/dashboardSectionCopy.ts create mode 100644 src/pages/menuPages/configuration/settingGroups.ts create mode 100644 src/utils/deployAdmin.ts diff --git a/src/api/configuration.ts b/src/api/configuration.ts index 56fc76c..078e820 100644 --- a/src/api/configuration.ts +++ b/src/api/configuration.ts @@ -9,4 +9,11 @@ export const getConfiguration = async () => /** فقط تنظیمات قابل ویرایش — برای صفحه تنظیمات ادمین */ export const getEditableConfiguration = async () => - await useAxios.get>(`/admin/get_settings`, { params: { editable_only: 1 } }) \ No newline at end of file + await useAxios.get>(`/admin/get_settings`, { params: { editable_only: 1 } }) + +/** تنظیمات سیستمی (can_edit=0, is_active=1) — فقط ادمین دیپلوی */ +export const getSystemConfiguration = async () => + await useAxios.get>(`/admin/get_settings`, { params: { system_only: 1 } }) + +export const setSystemConfiguration = async (obj: Const & { system_deploy?: boolean }) => + await useAxios.post(`/admin/get_settings`, { ...obj, system_deploy: true }) \ No newline at end of file diff --git a/src/api/dashboard.ts b/src/api/dashboard.ts index 23ad20c..8cc8bfb 100644 --- a/src/api/dashboard.ts +++ b/src/api/dashboard.ts @@ -1,13 +1,46 @@ import useAxios from '@core/utils/useAxios' -import type { AddId, User } from '@/model/user' +import type { User } from '@/model/user' +import type { + DashboardFlowPoint, + DashboardFinance, + DashboardMaster, + PriceChartPoint, +} from '@/model/dashboard' +import type { Order } from '@/model/order' +import type { Balance } from '@/model/product' import type { TableInput } from '@core/type/baseTable' -import type {Dashboard} from '@/model/dashboard' -import type {PriceChart} from "@/model/priceChart"; -export const getDashboard = async () => await useAxios.get('/admin/dashboard') +export const getDashboard = async () => await useAxios.get('/admin/dashboard') export const updateMyInformation = async (val: User) => await useAxios.post('/admin/me/update', val) -//priceChart -export const getAllPrices = async () => await useAxios.post('/admin/prices') +export const getDashboardFinance = async (startDate: string, endDate: string) => + await useAxios.post('/admin/dashboard/finance', { startDate, endDate }) + +export const getDashboardBalance = async (startDate: string, endDate: string) => + await useAxios.post('/admin/getBalance', { startDate, endDate }) + +export const getDashboardFlow = async (type: 'week' | 'month') => + await useAxios.post('/admin/dashboard/customer/flow', { type }) + +export const getPriceChartData = async () => { + const res = await useAxios.post<{ + code?: number + data?: { prices?: Record<'DAILY' | 'WEEKLY' | 'MONTHLY', PriceChartPoint[]> } + }>('/admin/prices/chart') + + return res?.data?.prices ?? (res as unknown as { prices?: Record })?.prices +} + +export const getRecentOrders = async (limit = 10) => { + const res = await useAxios.post<{ rows?: Order[] }>('/admin/order/table', { + limit, + page: 1, + sort: { field: 'id', order: 'desc' }, + } as TableInput) + + return res?.rows ?? (Array.isArray(res) ? res : []) +} + +export const toggleGateway = async () => await useAxios.post('/admin/gateway') diff --git a/src/main.ts b/src/main.ts index 157c2d2..8074220 100644 --- a/src/main.ts +++ b/src/main.ts @@ -29,9 +29,9 @@ const init = async () => { if (token) { await userStore.getMyInfo() await initStoreModeFromSettings() - setupRoutes(['*']) + setupRoutes(['*'], undefined, userStore.userInfo?.mobile) const { refreshAppModeMenu } = await import('@/router') - refreshAppModeMenu() + refreshAppModeMenu(userStore.userInfo?.mobile) //setupRoutes(['project']) /*router.removeRoute('usersMain') router.removeRoute('users')*/ diff --git a/src/model/dashboard.ts b/src/model/dashboard.ts index 79d58a8..8e81273 100644 --- a/src/model/dashboard.ts +++ b/src/model/dashboard.ts @@ -1,4 +1,11 @@ -export interface Dashboard { +import type { Order } from '@/model/order' + +export interface DashboardMaster { + price?: number + pricem?: number + update_date?: string + is_gateway_open?: boolean + prices?: Array<{ id?: string | number; name?: string; price?: number; profit?: number }> new_customer_major?: number new_customer_single?: number all_customer_major?: number @@ -7,35 +14,51 @@ export interface Dashboard { archive_customer_single?: number all_gold?: number all_gold_single?: number - price?: Price -} -export interface Price { - id?: number - title_fa?: string - value?: number - created_at?: string - updated_at?: string - update_date?: string - value_json?: ValuePrice[] + await_order?: Order[] + best_customer?: Array<{ customer_id?: number; amount?: number; customer?: { name?: string; mobile?: string } }> + best_customer_single?: Array<{ gold?: number; customer?: { name?: string; mobile?: string } }> + GT_all_customers?: number + GT_no_login_customers?: number + GT_no_valid_customers?: number + GT_active_customers?: number + GT_deActive_customers?: number + GT_products_report?: Array<{ + id?: number + title?: string + transaction_sum_gold_buy?: number + total_negative_gold_sell?: number + total_gold?: number + }> } -export interface ValuePrice { - key?: number - low?: string - high?: string - price?: string - numbertitle?: string - change?: string - category?: string - created_at?: string +export interface DashboardFinance { + fullPriceM1?: number + fullPriceM2?: number + fullPriceSood?: number + fullPriceKarmozd?: number + fullPriceKaermozd?: number + orderCount?: number + Gifts?: string + GiftsPrise?: number + sumAll?: number } -export interface Charts { - buySellChart?: Chart - customerSellChart?: Chart - singleSellChart?: Chart +export interface DashboardFlowPoint { + date?: string + '1'?: number + '2'?: number + 1?: number + 2?: number +} + +export interface PriceChartPoint { + timestamp: number + value: number +} + +export interface DashboardWalletSums { + gold?: number + goldToCash?: number + cash?: number + cashToCash?: number } -export interface Chart { - price: number - obj: any[] -} \ No newline at end of file diff --git a/src/pages/dashboard/components/DashboardHelpTip.vue b/src/pages/dashboard/components/DashboardHelpTip.vue new file mode 100644 index 0000000..9a1db4d --- /dev/null +++ b/src/pages/dashboard/components/DashboardHelpTip.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/src/pages/dashboard/components/DashboardLabelWithHelp.vue b/src/pages/dashboard/components/DashboardLabelWithHelp.vue new file mode 100644 index 0000000..835c418 --- /dev/null +++ b/src/pages/dashboard/components/DashboardLabelWithHelp.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/pages/dashboard/components/DashboardSectionHeader.vue b/src/pages/dashboard/components/DashboardSectionHeader.vue new file mode 100644 index 0000000..ff9dc0d --- /dev/null +++ b/src/pages/dashboard/components/DashboardSectionHeader.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/pages/dashboard/components/DashboardStatCard.vue b/src/pages/dashboard/components/DashboardStatCard.vue new file mode 100644 index 0000000..d5a58bb --- /dev/null +++ b/src/pages/dashboard/components/DashboardStatCard.vue @@ -0,0 +1,74 @@ + + + diff --git a/src/pages/dashboard/components/IosInfoBadge.vue b/src/pages/dashboard/components/IosInfoBadge.vue new file mode 100644 index 0000000..d33420f --- /dev/null +++ b/src/pages/dashboard/components/IosInfoBadge.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/src/pages/dashboard/composables/useDashboardPage.ts b/src/pages/dashboard/composables/useDashboardPage.ts new file mode 100644 index 0000000..17d2935 --- /dev/null +++ b/src/pages/dashboard/composables/useDashboardPage.ts @@ -0,0 +1,309 @@ +//@ts-ignore +import moment from 'moment-jalaali' +import { ref, computed, onMounted } from 'vue' +import { + getDashboard, + getDashboardBalance, + getDashboardFinance, + getDashboardFlow, + getPriceChartData, + getRecentOrders, + toggleGateway, +} from '@/api/dashboard' +import { getWalletTable } from '@/api/wallet' +import type { + DashboardFlowPoint, + DashboardFinance, + DashboardMaster, + PriceChartPoint, +} from '@/model/dashboard' +import type { Order } from '@/model/order' +import type { Balance } from '@/model/product' +import { usePrice } from '@core/utils/usePrice' +import { toJalali } from '@core/utils/useDataTime' +import { isStoreApp } from '@/utils/config' + +const MESGHAL = 4.331802 + +export function useDashboardPage() { + const loading = ref(true) + const flowLoading = ref(false) + const priceRange = ref<'DAILY' | 'WEEKLY' | 'MONTHLY'>('DAILY') + const flowRange = ref<'week' | 'month'>('week') + + const startDate = ref(moment().subtract(30, 'days').startOf('day').format('YYYY-MM-DD HH:mm:ss')) + const endDate = ref(moment().endOf('day').format('YYYY-MM-DD HH:mm:ss')) + + const master = ref() + const finance = ref() + const balance = ref() + const walletSums = ref<{ gold?: number; cash?: number; goldToCash?: number; cashToCash?: number }>() + const recentOrders = ref([]) + const flowData = ref([]) + const priceSeries = ref([]) + + const isStore = computed(() => isStoreApp()) + + const pendingOrders = computed(() => master.value?.await_order ?? []) + + const customerStats = computed(() => ({ + newCount: isStore.value + ? master.value?.new_customer_major ?? 0 + : master.value?.new_customer_single ?? 0, + total: isStore.value + ? master.value?.all_customer_major ?? 0 + : master.value?.all_customer_single ?? 0, + active: master.value?.GT_active_customers ?? 0, + inactive: master.value?.GT_deActive_customers ?? 0, + notVerified: master.value?.GT_no_valid_customers ?? 0, + })) + + async function loadCore() { + const [dash, fin, bal, wallet, orders, prices] = await Promise.allSettled([ + getDashboard(), + getDashboardFinance(startDate.value, endDate.value), + getDashboardBalance(startDate.value, endDate.value), + getWalletTable({ limit: 1, page: 1 } as never), + getRecentOrders(12), + getPriceChartData(), + ]) + + if (dash.status === 'fulfilled') master.value = dash.value + if (fin.status === 'fulfilled') finance.value = fin.value + if (bal.status === 'fulfilled') balance.value = bal.value + if (wallet.status === 'fulfilled') walletSums.value = wallet.value?.sums + if (orders.status === 'fulfilled') recentOrders.value = orders.value + if (prices.status === 'fulfilled') { + priceSeries.value = prices.value?.DAILY ?? [] + } + } + + async function loadFlow() { + flowLoading.value = true + try { + flowData.value = (await getDashboardFlow(flowRange.value)) ?? [] + } catch (e) { + console.error(e) + flowData.value = [] + } finally { + flowLoading.value = false + } + } + + async function refreshAll() { + loading.value = true + try { + await Promise.all([loadCore(), loadFlow()]) + } finally { + loading.value = false + } + } + + async function applyDateRange() { + loading.value = true + try { + const [fin, bal] = await Promise.all([ + getDashboardFinance(startDate.value, endDate.value), + getDashboardBalance(startDate.value, endDate.value), + ]) + finance.value = fin + balance.value = bal + } finally { + loading.value = false + } + } + + async function switchPriceRange(range?: 'DAILY' | 'WEEKLY' | 'MONTHLY') { + const key = range ?? priceRange.value + priceRange.value = key + const prices = await getPriceChartData() + priceSeries.value = prices?.[key] ?? [] + } + + async function onToggleGateway() { + await toggleGateway() + master.value = await getDashboard() + } + + function formatGram(value?: number) { + return `${Number(value ?? 0).toLocaleString('fa-IR', { maximumFractionDigits: 3 })} گرم` + } + + function directionLabel(direction?: number) { + return direction === 1 ? 'خرید' : direction === 2 ? 'فروش' : '—' + } + + function directionClass(direction?: number) { + return direction === 1 + ? 'bg-emerald-100 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300' + : 'bg-rose-100 text-rose-700 dark:bg-rose-500/20 dark:text-rose-300' + } + + function stsClass(sts?: number) { + if (sts === 2) { + return 'bg-emerald-100 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-300' + } + if (sts === 1) { + return 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300' + } + return 'bg-rose-100 text-rose-700 dark:bg-rose-500/20 dark:text-rose-300' + } + + function stsLabel(order: Order) { + return (order as Order & { sts_str?: string }).sts_str + ?? (order.sts === 2 ? 'موفق' : order.sts === 1 ? 'باز' : 'ناموفق') + } + + const financeChartOptions = computed(() => { + const sood = finance.value?.fullPriceSood ?? 0 + const karmozd = finance.value?.fullPriceKarmozd ?? finance.value?.fullPriceKaermozd ?? 0 + const gifts = finance.value?.GiftsPrise ?? 0 + + return { + chart: { type: 'donut', fontFamily: 'inherit' }, + labels: ['سود معامله', 'کارمزد طلایی', 'هدایای طلا'], + colors: ['#10b981', '#f59e0b', '#8b5cf6'], + legend: { position: 'bottom', fontSize: '12px' }, + dataLabels: { enabled: false }, + plotOptions: { + pie: { + donut: { + size: '68%', + labels: { + show: true, + total: { + show: true, + label: 'درآمد خالص', + formatter: () => usePrice(finance.value?.sumAll ?? 0, true, ''), + }, + }, + }, + }, + }, + tooltip: { + y: { formatter: (v: number) => usePrice(v, true, '') }, + }, + series: [sood, karmozd, gifts], + } + }) + + const flowChartOptions = computed(() => { + const points = [...flowData.value].sort((a, b) => + String(a.date ?? '').localeCompare(String(b.date ?? '')), + ) + const categories = points.map((p) => { + const d = p.date ?? '' + return d ? toJalali(`${d} 12:00:00`, 'jMM/jDD') : d + }) + + return { + chart: { type: 'bar', stacked: true, toolbar: { show: false }, fontFamily: 'inherit' }, + plotOptions: { bar: { borderRadius: 4, columnWidth: '55%' } }, + colors: ['#10b981', '#f43f5e'], + xaxis: { categories, labels: { rotate: -35, style: { fontSize: '11px' } } }, + yaxis: { + labels: { + formatter: (v: number) => `${Number(v).toLocaleString('fa-IR')} گرم`, + }, + }, + legend: { position: 'top' }, + dataLabels: { enabled: false }, + series: [ + { name: 'خرید مشتری', data: points.map((p) => Number(p[1] ?? p['1'] ?? 0)) }, + { name: 'فروش مشتری', data: points.map((p) => Number(p[2] ?? p['2'] ?? 0)) }, + ], + } + }) + + const priceChartOptions = computed(() => ({ + chart: { type: 'area', toolbar: { show: false }, fontFamily: 'inherit', zoom: { enabled: false } }, + stroke: { curve: 'smooth', width: 2 }, + fill: { + type: 'gradient', + gradient: { shadeIntensity: 1, opacityFrom: 0.45, opacityTo: 0.05 }, + }, + colors: ['#2563eb'], + dataLabels: { enabled: false }, + xaxis: { + type: 'datetime', + labels: { datetimeUTC: false, style: { fontSize: '11px' } }, + }, + yaxis: { + labels: { + formatter: (v: number) => `${Math.round(v / 1_000_000).toLocaleString('fa-IR')}M`, + }, + }, + tooltip: { + x: { format: 'yyyy/MM/dd HH:mm' }, + y: { formatter: (v: number) => usePrice(v, true, '') }, + }, + series: [ + { + name: 'مظنه', + data: priceSeries.value.map((p) => [p.timestamp, p.value]), + }, + ], + })) + + const productChartOptions = computed(() => { + const items = (master.value?.GT_products_report ?? []).slice(0, 8) + return { + chart: { type: 'bar', toolbar: { show: false }, fontFamily: 'inherit' }, + plotOptions: { bar: { horizontal: true, borderRadius: 4 } }, + colors: ['#0ea5e9', '#f97316'], + dataLabels: { enabled: false }, + xaxis: { + categories: items.map((p) => p.title ?? `#${p.id}`), + labels: { style: { fontSize: '11px' } }, + }, + legend: { position: 'top' }, + series: [ + { name: 'خرید (گرم)', data: items.map((p) => p.transaction_sum_gold_buy ?? 0) }, + { + name: 'فروش (گرم)', + data: items.map((p) => Math.abs(p.total_negative_gold_sell ?? 0)), + }, + ], + } + }) + + onMounted(() => { + void refreshAll() + }) + + return { + loading, + flowLoading, + startDate, + endDate, + master, + finance, + balance, + walletSums, + recentOrders, + pendingOrders, + customerStats, + priceRange, + flowRange, + flowData, + priceSeries, + isStore, + MESGHAL, + refreshAll, + applyDateRange, + switchPriceRange, + loadFlow, + onToggleGateway, + formatGram, + directionLabel, + directionClass, + stsClass, + stsLabel, + financeChartOptions, + flowChartOptions, + priceChartOptions, + productChartOptions, + usePrice, + toJalali, + } +} diff --git a/src/pages/dashboard/dashboardSectionCopy.ts b/src/pages/dashboard/dashboardSectionCopy.ts new file mode 100644 index 0000000..b6adac7 --- /dev/null +++ b/src/pages/dashboard/dashboardSectionCopy.ts @@ -0,0 +1,139 @@ +/** توضیح و فرمول فارسی — برای tooltip آیکون راهنما */ + +export type DashboardHelp = { + description: string + formula: string +} + +export const MESGHAL_FACTOR = '۴.۳۳۱۸۰۲' + +export const dashboardHero: DashboardHelp = { + description: 'آخرین قیمت پایه هر گرم طلا در سیستم.', + formula: `قیمت هر مثقال = قیمت هر گرم × ${MESGHAL_FACTOR}`, +} + +export const dashboardGateway: DashboardHelp = { + description: 'وقتی فعال باشد مشتری می‌تواند از درگاه بانکی واریز کند؛ در حالت غیرفعال فقط واریز دستی ممکن است.', + formula: 'وضعیت: فعال یا غیرفعال', +} + +export const dashboardKpi = { + profit: { + description: 'مجموع سود اسپرد (تفاوت قیمت خرید/فروش با مشتری) روی همه سفارش‌های ثبت‌شده در بازه.', + formula: 'سود کل = جمع «سود هر سفارش»', + }, + commission: { + description: 'مجموع کارمزد طلایی محصول که روی همان سفارش‌ها محاسبه شده.', + formula: 'کارمزد کل = جمع «کارمزد هر سفارش»', + }, + orderCount: { + description: 'تعداد همه سفارش‌هایی که در بازه انتخابی ثبت شده‌اند (هر وضعیتی).', + formula: 'تعداد = شمارش سفارش‌ها بین دو تاریخ', + }, + goldBalance: { + description: 'تراز وزنی طلا از سفارشات موفق؛ مثبت یعنی به مشتری بیشتر فروخته‌اید.', + formula: 'تراز طلا = گرم فروش − گرم خرید (سفارش موفق)', + }, + cashBalance: { + description: 'تراز ریالی همان سفارشات موفق؛ ورود و خروج نقد از معاملات.', + formula: 'تراز ریال = مبلغ فروش − مبلغ خرید', + }, + mazanehBalance: { + description: 'میانگین موزون قیمت معاملات، تبدیل‌شده به مثقال.', + formula: `(جمع مبلغ معاملات ÷ جمع گرم) × ${MESGHAL_FACTOR}`, + }, +} as const satisfies Record + +export const dashboardDateRange: DashboardHelp = { + description: 'تاریخ شروع و پایان برای محاسبه کارت‌ها، تراز و نمودارها.', + formula: 'گزارش = از تاریخ … تا تاریخ …', +} + +export const dashboardDateMetrics = { + bankDeposit: { + description: 'کل واریزهای موفق مشتریان از درگاه آنلاین در این بازه.', + formula: 'جمع مبلغ واریزهای تأییدشده از درگاه', + }, + netIncome: { + description: 'درآمد پس از کسر ارزش طلای هدیه‌داده‌شده.', + formula: 'درآمد خالص = (اختلاف قیمت اصلی و پرداختی) − (گرم هدیه × مظنه)', + }, + gifts: { + description: 'طلایی که ادمین به مشتریان هدیه داده در همین بازه.', + formula: 'گرم هدیه = جمع طلای ثبت‌شده در تراکنش‌های ادمین', + }, +} as const satisfies Record + +export const dashboardCharts = { + incomeMix: { + description: 'نشان می‌دهد سود معامله، کارمزد و هدایا چقدر از درآمد کل را تشکیل می‌دهند.', + formula: 'درآمد = سود معامله + کارمزد + (گرم هدیه × مظنه)', + }, + buySellVolume: { + description: 'مقدار طلای خرید و فروش مشتری در هر روز (فقط سفارش موفق).', + formula: 'هر روز: گرم خرید مشتری و گرم فروش به مشتری', + }, + priceChart: { + description: 'روند تغییر قیمت پایه هر گرم در ۲۴ ساعت، هفته یا ماه.', + formula: 'نمودار = قیمت پایه در هر لحظه', + }, + productActivity: { + description: 'مقایسه حجم خرید و فروش هر محصول.', + formula: 'خرید = جمع گرم مثبت | فروش = جمع گرم منفی', + }, +} as const satisfies Record + +export const dashboardOrders = { + pending: { + description: 'سفارش‌هایی که هنوز تأیید نشده‌اند.', + formula: 'سود هر گرم × مقدار = سود کل سفارش', + }, + recent: { + description: '۱۲ سفارش آخر با جزئیات مظنه و سود.', + formula: 'مظنه = قیمت پایه | قیمت مشتری = مظنه ± اسپرد | سود/گرم = تفاوت اسپرد', + }, +} as const satisfies Record + +export const dashboardCustomers: DashboardHelp = { + description: 'آمار مشتریان خانگی ثبت‌شده در سیستم.', + formula: 'فعال = دارای کیف پول | بدون احراز = هویت تأیید نشده', +} + +export const dashboardCustomerMetrics = { + total: { + description: 'همه مشتریان خانگی ثبت‌شده.', + formula: 'شمارش کل مشتریان', + }, + new: { + description: 'مشتریانی که در ۳ ماه اخیر ثبت‌نام کرده‌اند.', + formula: 'ثبت‌نام در ۹۰ روز گذشته', + }, + active: { + description: 'مشتریانی که حداقل یک کیف پول دارند.', + formula: 'دارای موجودی در کیف', + }, + notVerified: { + description: 'مشتریانی که احراز هویت را تکمیل نکرده‌اند.', + formula: 'وضعیت احراز: ناقص', + }, +} as const satisfies Record + +export const dashboardWallet: DashboardHelp = { + description: 'مجموع موجودی طلا و ریال همه مشتریان.', + formula: 'ارزش طلا به ریال = جمع گرم × مظنه لحظه‌ای', +} + +export const dashboardWalletMetrics = { + gold: { + description: 'مجموع طلای موجود در کیف همه مشتریان.', + formula: 'جمع گرم طلا در کیف‌ها', + }, + cash: { + description: 'مجموع ریال موجود در کیف همه مشتریان.', + formula: 'جمع ریال در کیف‌ها', + }, + goldToCash: { + description: 'ارزش ریالی کل طلای مشتریان با مظنه فعلی.', + formula: 'جمع گرم × قیمت هر گرم', + }, +} as const satisfies Record diff --git a/src/pages/dashboard/index.vue b/src/pages/dashboard/index.vue index 1901738..d4ef7b4 100644 --- a/src/pages/dashboard/index.vue +++ b/src/pages/dashboard/index.vue @@ -1,914 +1,531 @@ - diff --git a/src/pages/login/components/LoginPanel.vue b/src/pages/login/components/LoginPanel.vue index 363e91f..7ddfb0f 100644 --- a/src/pages/login/components/LoginPanel.vue +++ b/src/pages/login/components/LoginPanel.vue @@ -161,9 +161,9 @@ const onUserPassFormFinish = async () => { } await userStore.getMyInfo() await initStoreModeFromSettings() - setupRoutes(['*'], router) + setupRoutes(['*'], router, userStore.userInfo?.mobile) const { refreshAppModeMenu } = await import('@/router') - refreshAppModeMenu() + refreshAppModeMenu(userStore.userInfo?.mobile) // const info = await getMyInformation() // await setMyInfo(JSON.stringify(info)) // emits('enter') diff --git a/src/pages/menuPages/configuration/index.vue b/src/pages/menuPages/configuration/index.vue index f5598f5..ab77019 100644 --- a/src/pages/menuPages/configuration/index.vue +++ b/src/pages/menuPages/configuration/index.vue @@ -1,6 +1,6 @@