fix some bug
This commit is contained in:
@@ -1,18 +1,17 @@
|
||||
<template>
|
||||
<a-tooltip placement="top" :overlay-inner-style="{ maxWidth: '300px', direction: 'rtl' }">
|
||||
<template #title>
|
||||
<div class="space-y-1.5 text-xs leading-5">
|
||||
<p>{{ help.description }}</p>
|
||||
<p v-if="help.formula" class="border-t border-white/20 pt-1.5 text-white/90">
|
||||
<span class="font-semibold">فرمول:</span> {{ help.formula }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<a-tooltip
|
||||
placement="top"
|
||||
:title="tooltipText"
|
||||
overlay-class-name="dashboard-help-tooltip"
|
||||
:overlay-style="{ zIndex: TOOLTIP_ABOVE_MODAL_Z_INDEX }"
|
||||
:overlay-inner-style="{ maxWidth: '26rem', direction: 'rtl', textAlign: 'right', whiteSpace: 'pre-line' }"
|
||||
:mouse-enter-delay="0.15"
|
||||
>
|
||||
<span
|
||||
class="dashboard-help-trigger inline-flex shrink-0 items-center justify-center"
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
@click.stop
|
||||
role="img"
|
||||
:aria-label="tooltipText"
|
||||
tabindex="0"
|
||||
>
|
||||
<IosInfoBadge :size="badgeSize" />
|
||||
</span>
|
||||
@@ -22,6 +21,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { DashboardHelp } from '@/pages/dashboard/dashboardSectionCopy'
|
||||
import IosInfoBadge from '@/pages/dashboard/components/IosInfoBadge.vue'
|
||||
import { TOOLTIP_ABOVE_MODAL_Z_INDEX } from '@/constants/overlayZIndex'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -34,6 +34,14 @@ const props = withDefaults(
|
||||
)
|
||||
|
||||
const badgeSize = computed(() => props.size)
|
||||
|
||||
const tooltipText = computed(() => {
|
||||
const blocks = [props.help.description?.trim()].filter(Boolean)
|
||||
if (props.help.formula?.trim()) {
|
||||
blocks.push(props.help.formula.trim())
|
||||
}
|
||||
return blocks.join('\n\n')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -42,3 +50,10 @@ const badgeSize = computed(() => props.size)
|
||||
cursor: help;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.ant-tooltip.dashboard-help-tooltip {
|
||||
z-index: 1250 !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="dashboard-stat-card flex h-full min-h-[4.25rem] items-center gap-2 rounded-xl px-2.5 py-2">
|
||||
<div class="dashboard-stat-card flex h-full min-h-0 items-start gap-1.5 rounded-lg px-2 py-1.5">
|
||||
<div
|
||||
class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg"
|
||||
class="flex h-7 w-7 shrink-0 items-center justify-center rounded-md"
|
||||
:class="iconBgClass"
|
||||
>
|
||||
<BaseIcon :icon="icon" size="17" :class="iconTextClass" />
|
||||
<BaseIcon :icon="icon" size="15" :class="iconTextClass" />
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<DashboardLabelWithHelp
|
||||
@@ -13,8 +13,10 @@
|
||||
size="xs"
|
||||
label-class="dashboard-text-muted font-medium"
|
||||
/>
|
||||
<p class="dashboard-text truncate text-[15px] font-bold leading-snug">
|
||||
{{ value }}
|
||||
<p v-if="subtitle" class="dashboard-stat-card__subtitle">{{ subtitle }}</p>
|
||||
<p class="dashboard-stat-card__value dashboard-text leading-snug">
|
||||
<span class="font-bold">{{ value }}</span>
|
||||
<span v-if="unit" class="dashboard-stat-card__unit">{{ unit }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,6 +32,8 @@ const props = withDefaults(
|
||||
defineProps<{
|
||||
title: string
|
||||
value: string
|
||||
subtitle?: string
|
||||
unit?: string
|
||||
help?: DashboardHelp
|
||||
icon?: string
|
||||
tone?: Tone
|
||||
@@ -37,6 +41,7 @@ const props = withDefaults(
|
||||
{
|
||||
icon: 'vuesax-linear:chart-2',
|
||||
tone: 'blue',
|
||||
unit: '',
|
||||
},
|
||||
)
|
||||
|
||||
@@ -109,6 +114,26 @@ const iconTextClass = computed(() => toneMap[props.tone].iconText)
|
||||
.dashboard-stat-card__icon--orange {
|
||||
background: rgba(249, 115, 22, 0.14);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__subtitle {
|
||||
margin-top: 2px;
|
||||
font-size: 10px;
|
||||
line-height: 1.35;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-stat-card__value {
|
||||
margin-top: 2px;
|
||||
font-size: 13px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.dashboard-stat-card__unit {
|
||||
margin-right: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<section class="dashboard-income-summary">
|
||||
<DashboardSectionHeader title="خلاصه درآمد معاملات" :help="help" />
|
||||
<p class="dashboard-income-summary__intro">
|
||||
سود اسپرد (اختلاف قیمت) و کارمزد جدا محاسبه میشوند. جمع = هر دو. همه مبالغ
|
||||
<strong>ریال</strong> هستند (نه تومان).
|
||||
</p>
|
||||
|
||||
<div class="dashboard-income-summary__grid">
|
||||
<article
|
||||
v-for="row in rows"
|
||||
:key="row.key"
|
||||
class="dashboard-income-summary__card"
|
||||
:class="{ 'dashboard-income-summary__card--total': row.isTotal }"
|
||||
>
|
||||
<DashboardLabelWithHelp
|
||||
v-if="row.help"
|
||||
:label="row.label"
|
||||
:help="row.help"
|
||||
size="xs"
|
||||
label-class="dashboard-income-summary__card-title"
|
||||
/>
|
||||
<span v-else class="dashboard-income-summary__card-title">{{ row.label }}</span>
|
||||
<p class="dashboard-income-summary__hint">{{ row.hint }}</p>
|
||||
<p class="dashboard-income-summary__value">
|
||||
<span class="dashboard-income-summary__amount">{{ row.amount }}</span>
|
||||
<span class="dashboard-income-summary__unit">{{ unit }}</span>
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import DashboardSectionHeader from '@/pages/dashboard/components/DashboardSectionHeader.vue'
|
||||
import DashboardLabelWithHelp from '@/pages/dashboard/components/DashboardLabelWithHelp.vue'
|
||||
import {
|
||||
dashboardTradingIncomeSummary,
|
||||
dashboardKpi,
|
||||
} from '@/pages/dashboard/dashboardSectionCopy'
|
||||
import { DASHBOARD_RIAL_UNIT, formatDashboardAmount } from '@/pages/dashboard/dashboardFormat'
|
||||
import type { DashboardFinance } from '@/model/dashboard'
|
||||
|
||||
const props = defineProps<{
|
||||
finance?: DashboardFinance | null
|
||||
}>()
|
||||
|
||||
const help = dashboardTradingIncomeSummary
|
||||
const unit = DASHBOARD_RIAL_UNIT
|
||||
|
||||
const spreadRial = computed(() => Number(props.finance?.fullPriceSood ?? 0))
|
||||
const commissionRial = computed(() =>
|
||||
Number(props.finance?.fullPriceKarmozd ?? props.finance?.fullPriceKaermozd ?? 0)
|
||||
)
|
||||
const totalRial = computed(() =>
|
||||
Number(props.finance?.totalTradingProfit ?? spreadRial.value + commissionRial.value)
|
||||
)
|
||||
|
||||
const rows = computed(() => [
|
||||
{
|
||||
key: 'spread',
|
||||
label: 'سود اسپرد',
|
||||
hint: 'اختلاف قیمت پایه و قیمت مشتری',
|
||||
amount: formatDashboardAmount(spreadRial.value),
|
||||
help: dashboardKpi.spreadProfit,
|
||||
isTotal: false,
|
||||
},
|
||||
{
|
||||
key: 'commission',
|
||||
label: 'کارمزد',
|
||||
hint: 'درصد یا وزن کارمزد، به ریال',
|
||||
amount: formatDashboardAmount(commissionRial.value),
|
||||
help: dashboardKpi.commission,
|
||||
isTotal: false,
|
||||
},
|
||||
{
|
||||
key: 'total',
|
||||
label: 'جمع سود',
|
||||
hint: 'اسپرد + کارمزد',
|
||||
amount: formatDashboardAmount(totalRial.value),
|
||||
help: dashboardKpi.totalTradingProfit,
|
||||
isTotal: true,
|
||||
},
|
||||
])
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.dashboard-income-summary {
|
||||
margin-top: 0.5rem;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--admin-border);
|
||||
background: var(--admin-bg-elevated);
|
||||
padding: 0.65rem 0.75rem 0.75rem;
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.dashboard-income-summary__intro {
|
||||
margin: 0 0 0.5rem;
|
||||
font-size: 0.6875rem;
|
||||
line-height: 1.55;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-income-summary__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.dashboard-income-summary__grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-income-summary__card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.15rem;
|
||||
min-height: 4.75rem;
|
||||
padding: 0.5rem 0.6rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid var(--admin-border);
|
||||
background: var(--admin-bg-muted);
|
||||
}
|
||||
|
||||
.dashboard-income-summary__card--total {
|
||||
border-color: rgba(245, 158, 11, 0.4);
|
||||
background: rgba(245, 158, 11, 0.1);
|
||||
}
|
||||
|
||||
.dashboard-income-summary__card-title {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--admin-text);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.dashboard-income-summary__hint {
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
font-size: 0.625rem;
|
||||
line-height: 1.45;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-income-summary__value {
|
||||
margin: 0.15rem 0 0;
|
||||
direction: ltr;
|
||||
text-align: right;
|
||||
unicode-bidi: isolate;
|
||||
}
|
||||
|
||||
.dashboard-income-summary__amount {
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 800;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.dashboard-income-summary__card--total .dashboard-income-summary__amount {
|
||||
font-size: 1rem;
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.dashboard-income-summary__unit {
|
||||
margin-right: 3px;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
html.is-dark {
|
||||
.dashboard-income-summary__card--total {
|
||||
border-color: rgba(245, 158, 11, 0.45);
|
||||
background: rgba(245, 158, 11, 0.14);
|
||||
}
|
||||
|
||||
.dashboard-income-summary__card--total .dashboard-income-summary__amount {
|
||||
color: #fcd34d;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -23,6 +23,7 @@ import type {
|
||||
import type { Order } from '@/model/order'
|
||||
import type { Balance } from '@/model/product'
|
||||
import { usePrice } from '@core/utils/usePrice'
|
||||
import { DASHBOARD_RIAL_UNIT, formatDashboardAmount } from '@/pages/dashboard/dashboardFormat'
|
||||
import { toJalali } from '@core/utils/useDataTime'
|
||||
import { metalLabel } from '@/utils/adminMetalLabels'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
@@ -278,11 +279,12 @@ export function useDashboardPage() {
|
||||
const sood = finance.value?.fullPriceSood ?? 0
|
||||
const karmozd = finance.value?.fullPriceKarmozd ?? finance.value?.fullPriceKaermozd ?? 0
|
||||
const gifts = finance.value?.GiftsPrise ?? 0
|
||||
const total = finance.value?.totalTradingProfit ?? sood + karmozd
|
||||
|
||||
return {
|
||||
...chartSurfaceOptions(),
|
||||
chart: { type: 'donut', fontFamily: 'inherit', offsetY: 4, foreColor: chartSurfaceOptions().chart.foreColor },
|
||||
labels: ['سود معامله', metalLabel.goldCommission(), metalLabel.goldGifts()],
|
||||
labels: ['سود اسپرد', 'کارمزد معامله', 'ارزش هدایا (گرم)'],
|
||||
colors: ['#10b981', '#f59e0b', '#8b5cf6'],
|
||||
legend: {
|
||||
position: 'bottom',
|
||||
@@ -300,15 +302,15 @@ export function useDashboardPage() {
|
||||
show: true,
|
||||
total: {
|
||||
show: true,
|
||||
label: 'درآمد خالص',
|
||||
formatter: () => usePrice(finance.value?.sumAll ?? 0, true, ''),
|
||||
label: 'جمع سود معاملات',
|
||||
formatter: () => `${formatDashboardAmount(total)} ${DASHBOARD_RIAL_UNIT}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
y: { formatter: (v: number) => usePrice(v, true, '') },
|
||||
y: { formatter: (v: number) => `${formatDashboardAmount(v)} ${DASHBOARD_RIAL_UNIT}` },
|
||||
},
|
||||
series: [sood, karmozd, gifts],
|
||||
}
|
||||
@@ -409,7 +411,7 @@ export function useDashboardPage() {
|
||||
},
|
||||
tooltip: {
|
||||
x: { format: tooltipDateFormat },
|
||||
y: { formatter: (v: number) => usePrice(v, true, '') },
|
||||
y: { formatter: (v: number) => `${formatDashboardAmount(v)} ${DASHBOARD_RIAL_UNIT}` },
|
||||
},
|
||||
series: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/** مبلغ بدون واحد — برای نمایش جدا از «ریال» در کارتهای داشبورد */
|
||||
export function formatDashboardAmount(value: number | string | null | undefined): string {
|
||||
const n = Number(value ?? 0)
|
||||
if (Number.isNaN(n)) return '0'
|
||||
return Math.round(n)
|
||||
.toString()
|
||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
}
|
||||
|
||||
export const DASHBOARD_RIAL_UNIT = 'ریال'
|
||||
@@ -27,13 +27,17 @@ export const dashboardGateway = help(
|
||||
)
|
||||
|
||||
export const dashboardKpi = {
|
||||
profit: help(
|
||||
'مجموع سود اسپرد (تفاوت قیمت خرید/فروش با مشتری) روی همه سفارشهای ثبتشده در بازه.',
|
||||
'سود کل = جمع «سود هر سفارش»'
|
||||
spreadProfit: help(
|
||||
'مجموع سود اسپرد (اختلاف قیمت پایه و قیمت مشتری) — فقط از تفاوت buy/sell price. کارمزد جداگانه در کارت «کارمزد معامله» است.',
|
||||
'سود اسپرد = جمع «سود کل» (total_fee) هر سفارش در بازه'
|
||||
),
|
||||
commission: help(
|
||||
'مجموع کارمزد طلایی محصول که روی همان سفارشها محاسبه شده.',
|
||||
'کارمزد کل = جمع «کارمزد هر سفارش»'
|
||||
'مجموع کارمزد ریالی معاملات (درصد/وزن کارمزد) — جدا از سود اسپرد.',
|
||||
'کارمزد = جمع service_charge_price هر سفارش در بازه'
|
||||
),
|
||||
totalTradingProfit: help(
|
||||
'مجموع سود اسپرد و کارمزد — همان ردیف «جمع» در خلاصه درآمد.',
|
||||
'جمع = سود اسپرد + کارمزد معاملات'
|
||||
),
|
||||
orderCount: help(
|
||||
'تعداد همه سفارشهایی که در بازه انتخابی ثبت شدهاند (هر وضعیتی).',
|
||||
@@ -53,6 +57,11 @@ export const dashboardKpi = {
|
||||
),
|
||||
} as const satisfies Record<string, DashboardHelp>
|
||||
|
||||
export const dashboardTradingIncomeSummary = help(
|
||||
'تفکیک درآمد از معاملات در بازه انتخابی: سود اسپرد (اختلاف قیمت) و کارمزد ریالی جدا، و جمع هر دو.',
|
||||
'جمع سود معاملات = سود اسپرد + کارمزد معاملات'
|
||||
)
|
||||
|
||||
export const dashboardDateRange = help(
|
||||
'تاریخ شروع و پایان برای محاسبه کارتها، تراز و نمودارها.',
|
||||
'گزارش = از تاریخ … تا تاریخ …'
|
||||
@@ -64,8 +73,12 @@ export const dashboardDateMetrics = {
|
||||
'جمع مبلغ واریزهای تأییدشده از درگاه'
|
||||
),
|
||||
netIncome: help(
|
||||
'درآمد پس از کسر ارزش طلای هدیهدادهشده.',
|
||||
'درآمد خالص = (اختلاف قیمت اصلی و پرداختی) − (گرم هدیه × مظنه)'
|
||||
'شاخص قدیمی: اختلاف قیمت اصلی و پرداختی منهای ارزش هدایا — با «جمع سود معاملات» یکی نیست.',
|
||||
'تراز قیمت−پرداخت = جمع |قیمت اصلی − پرداختی| − (گرم هدیه × مظنه)'
|
||||
),
|
||||
totalTradingProfit: help(
|
||||
'همان «جمع سود معاملات» در خلاصه بالا — اسپرد + کارمزد.',
|
||||
'جمع = fullPriceSood + fullPriceKarmozd'
|
||||
),
|
||||
gifts: help(
|
||||
'طلایی که ادمین به مشتریان هدیه داده در همین بازه.',
|
||||
@@ -75,8 +88,8 @@ export const dashboardDateMetrics = {
|
||||
|
||||
export const dashboardCharts = {
|
||||
incomeMix: help(
|
||||
'نشان میدهد سود معامله، کارمزد و هدایا چقدر از درآمد کل را تشکیل میدهند.',
|
||||
'درآمد = سود معامله + کارمزد + (گرم هدیه × مظنه)'
|
||||
'تفکیک درآمد: سود اسپرد (اختلاف قیمت)، کارمزد ریالی، و ارزش هدایا.',
|
||||
'درآمد = سود اسپرد + کارمزد + (گرم هدیه × مظنه)'
|
||||
),
|
||||
buySellVolume: help(
|
||||
'مقدار طلای خرید و فروش مشتری در هر روز (فقط سفارش موفق).',
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
label-class="text-white/80"
|
||||
/>
|
||||
<span class="text-[11px] text-white/80">/گرم</span>
|
||||
<span class="text-lg font-bold leading-none">{{ usePrice(master?.price ?? 0, true, '') }}</span>
|
||||
<span class="text-lg font-bold leading-none">{{ usePrice(master?.price ?? 0, true, 'ریال') }}</span>
|
||||
<span class="text-white/35">·</span>
|
||||
<span class="text-[11px] text-white/80">مثقال</span>
|
||||
<span class="text-sm font-semibold leading-none">{{ usePrice(master?.pricem ?? 0, true, '') }}</span>
|
||||
<span class="text-sm font-semibold leading-none">{{ usePrice(master?.pricem ?? 0, true, 'ریال') }}</span>
|
||||
</div>
|
||||
<p v-if="master?.update_date" class="mt-1 text-[10px] leading-none text-white/55">
|
||||
{{ toJalali(master.update_date) }}
|
||||
@@ -45,45 +45,33 @@
|
||||
|
||||
<DashboardQuickWalletModal v-model:visible="showQuickWallet" />
|
||||
|
||||
<!-- KPI -->
|
||||
<section class="mt-2 grid grid-cols-2 items-stretch gap-2 md:grid-cols-3 xl:grid-cols-6">
|
||||
<DashboardStatCard
|
||||
tone="gold"
|
||||
icon="vuesax-linear:money-receive"
|
||||
title="سود معاملات"
|
||||
:value="usePrice(finance?.fullPriceSood ?? 0, true, '')"
|
||||
:help="copy.kpi.profit"
|
||||
/>
|
||||
<DashboardStatCard
|
||||
tone="amber"
|
||||
icon="vuesax-linear:coin"
|
||||
:title="metalLabel.goldCommission()"
|
||||
:value="usePrice(finance?.fullPriceKarmozd ?? finance?.fullPriceKaermozd ?? 0, true, '')"
|
||||
:help="copy.kpi.commission"
|
||||
/>
|
||||
<DashboardTradingIncomeSummary :finance="finance" />
|
||||
|
||||
<!-- تراز و آمار — ۴ کارت در یک ردیف -->
|
||||
<section class="dashboard-metrics-row mt-2">
|
||||
<DashboardStatCard
|
||||
tone="green"
|
||||
icon="vuesax-linear:receipt-2"
|
||||
title="تعداد سفارش"
|
||||
subtitle="ثبتشده در بازه"
|
||||
:value="String(finance?.orderCount ?? 0)"
|
||||
:help="copy.kpi.orderCount"
|
||||
/>
|
||||
<template v-if="metalBalanceItems.length">
|
||||
<DashboardStatCard
|
||||
v-for="item in metalBalanceItems"
|
||||
:key="item.metal_id"
|
||||
tone="blue"
|
||||
icon="vuesax-linear:empty-wallet"
|
||||
:title="metalBalanceTitle(item.metal_id, item.label)"
|
||||
:value="formatGram(item.goldBalance, item.metal_id)"
|
||||
:help="copy.kpi.goldBalance"
|
||||
/>
|
||||
</template>
|
||||
<DashboardStatCard
|
||||
v-if="metalBalanceItems.length === 1"
|
||||
tone="blue"
|
||||
icon="vuesax-linear:empty-wallet"
|
||||
:title="metalBalanceTitle(metalBalanceItems[0].metal_id, metalBalanceItems[0].label)"
|
||||
subtitle="تراز وزن — سفارش موفق"
|
||||
:value="formatGram(metalBalanceItems[0].goldBalance, metalBalanceItems[0].metal_id)"
|
||||
:help="copy.kpi.goldBalance"
|
||||
/>
|
||||
<DashboardStatCard
|
||||
v-else
|
||||
tone="blue"
|
||||
icon="vuesax-linear:empty-wallet"
|
||||
:title="metalLabel.goldBalance()"
|
||||
subtitle="تراز وزن — سفارش موفق"
|
||||
:value="formatGram(balance?.goldBalance)"
|
||||
:help="copy.kpi.goldBalance"
|
||||
/>
|
||||
@@ -91,22 +79,26 @@
|
||||
tone="rose"
|
||||
icon="vuesax-linear:dollar-circle"
|
||||
title="تراز ریالی"
|
||||
:value="usePrice(balance?.cashBalance ?? 0, true, '')"
|
||||
subtitle="ورود/خروج نقد"
|
||||
:value="formatDashboardAmount(balance?.cashBalance)"
|
||||
:unit="DASHBOARD_RIAL_UNIT"
|
||||
:help="copy.kpi.cashBalance"
|
||||
/>
|
||||
<DashboardStatCard
|
||||
tone="violet"
|
||||
icon="vuesax-linear:chart-2"
|
||||
title="تراز مظنه"
|
||||
:value="usePrice(balance?.mazanehBalance ?? 0, true, '')"
|
||||
subtitle="میانگین موزون"
|
||||
:value="formatDashboardAmount(balance?.mazanehBalance)"
|
||||
:unit="DASHBOARD_RIAL_UNIT"
|
||||
:help="copy.kpi.mazanehBalance"
|
||||
/>
|
||||
</section>
|
||||
|
||||
<!-- Date filter -->
|
||||
<!-- بازه گزارش -->
|
||||
<section class="dashboard-panel mt-2">
|
||||
<DashboardSectionHeader title="بازه گزارش" :help="copy.dateRange" />
|
||||
<div class="mb-2 grid grid-cols-1 gap-2 sm:grid-cols-3">
|
||||
<div class="dashboard-metrics-row mb-2">
|
||||
<div
|
||||
v-for="metric in dateRangeMetrics"
|
||||
:key="metric.label"
|
||||
@@ -149,7 +141,7 @@
|
||||
<DashboardSectionHeader title="ترکیب درآمد" :help="copy.charts.incomeMix" />
|
||||
<div class="dashboard-chart-wrap">
|
||||
<apexchart
|
||||
v-if="(finance?.fullPriceSood ?? 0) + (finance?.fullPriceKarmozd ?? 0) > 0"
|
||||
v-if="(finance?.fullPriceSood ?? 0) + (finance?.fullPriceKarmozd ?? 0) + (finance?.GiftsPrise ?? 0) > 0"
|
||||
type="donut"
|
||||
height="220"
|
||||
:options="financeChartOptions"
|
||||
@@ -349,8 +341,9 @@
|
||||
<th class="px-2 py-2 text-right">مقدار</th>
|
||||
<th class="px-2 py-2 text-right">مظنه/گرم</th>
|
||||
<th class="px-2 py-2 text-right">قیمت مشتری</th>
|
||||
<th class="px-2 py-2 text-right">سود/گرم</th>
|
||||
<th class="px-2 py-2 text-right">سود کل</th>
|
||||
<th class="px-2 py-2 text-right">سود اسپرد/گرم</th>
|
||||
<th class="px-2 py-2 text-right">سود اسپرد کل</th>
|
||||
<th class="px-2 py-2 text-right">کارمزد (ریال)</th>
|
||||
<th class="px-2 py-2 text-right">وضعیت</th>
|
||||
<th class="px-2 py-2 text-right">تاریخ</th>
|
||||
</tr>
|
||||
@@ -369,13 +362,16 @@
|
||||
</td>
|
||||
<td class="max-w-[8rem] truncate px-2 py-2.5">{{ order.customer?.name ?? '—' }}</td>
|
||||
<td class="px-2 py-2.5">{{ formatGram(order.amount) }}</td>
|
||||
<td class="px-2 py-2.5">{{ usePrice(order.price_original ?? 0, true, '') }}</td>
|
||||
<td class="px-2 py-2.5">{{ usePrice(order.price ?? 0, true, '') }}</td>
|
||||
<td class="px-2 py-2.5">{{ usePrice(order.price_original ?? 0, true, 'ریال') }}</td>
|
||||
<td class="px-2 py-2.5">{{ usePrice(order.price ?? 0, true, 'ریال') }}</td>
|
||||
<td class="dashboard-profit px-2 py-2.5">
|
||||
{{ usePrice(order.fee ?? 0, true, '') }}
|
||||
{{ usePrice(order.fee ?? 0, true, 'ریال') }}
|
||||
</td>
|
||||
<td class="dashboard-profit px-2 py-2.5 font-semibold">
|
||||
{{ usePrice(order.total_fee ?? 0, true, '') }}
|
||||
{{ usePrice(order.total_fee ?? 0, true, 'ریال') }}
|
||||
</td>
|
||||
<td class="px-2 py-2.5">
|
||||
{{ usePrice(order.service_charge_price ?? 0, true, 'ریال') }}
|
||||
</td>
|
||||
<td class="px-2 py-2.5">
|
||||
<span class="rounded-md px-2 py-0.5 text-xs" :class="stsClass(order.sts)">
|
||||
@@ -449,6 +445,7 @@ import DashboardQuickActionsBar from '@/pages/dashboard/components/DashboardQuic
|
||||
import DashboardQuickWalletModal from '@/pages/dashboard/components/DashboardQuickWalletModal.vue'
|
||||
import DashboardSectionHeader from '@/pages/dashboard/components/DashboardSectionHeader.vue'
|
||||
import DashboardStatCard from '@/pages/dashboard/components/DashboardStatCard.vue'
|
||||
import DashboardTradingIncomeSummary from '@/pages/dashboard/components/DashboardTradingIncomeSummary.vue'
|
||||
import {
|
||||
dashboardCharts,
|
||||
dashboardCustomerMetrics,
|
||||
@@ -462,6 +459,7 @@ import {
|
||||
dashboardWallet,
|
||||
dashboardWalletMetrics,
|
||||
} from '@/pages/dashboard/dashboardSectionCopy'
|
||||
import { DASHBOARD_RIAL_UNIT, formatDashboardAmount } from '@/pages/dashboard/dashboardFormat'
|
||||
import { useDashboardPage } from '@/pages/dashboard/composables/useDashboardPage'
|
||||
import { useDashboardQuickActions } from '@/pages/dashboard/composables/useDashboardQuickActions'
|
||||
import { metalBalanceTitle, metalLabel } from '@/utils/adminMetalLabels'
|
||||
@@ -523,6 +521,12 @@ const {
|
||||
customerStats,
|
||||
} = useDashboardPage()
|
||||
|
||||
const tradingProfitTotal = computed(() => {
|
||||
const spread = Number(finance.value?.fullPriceSood ?? 0)
|
||||
const commission = Number(finance.value?.fullPriceKarmozd ?? finance.value?.fullPriceKaermozd ?? 0)
|
||||
return Number(finance.value?.totalTradingProfit ?? spread + commission)
|
||||
})
|
||||
|
||||
const {
|
||||
quickActionLoading,
|
||||
hasProductSnapshot,
|
||||
@@ -543,16 +547,21 @@ void loadSnapshotStatus()
|
||||
const dateRangeMetrics = computed(() => [
|
||||
{
|
||||
label: 'واریز بانکی',
|
||||
value: usePrice(balance.value?.income_money ?? 0),
|
||||
value: `${formatDashboardAmount(balance.value?.income_money)} ${DASHBOARD_RIAL_UNIT}`,
|
||||
help: dashboardDateMetrics.bankDeposit,
|
||||
},
|
||||
{
|
||||
label: 'درآمد خالص',
|
||||
value: usePrice(finance.value?.sumAll ?? 0),
|
||||
label: 'جمع سود معاملات',
|
||||
value: `${formatDashboardAmount(tradingProfitTotal.value)} ${DASHBOARD_RIAL_UNIT}`,
|
||||
help: dashboardDateMetrics.totalTradingProfit,
|
||||
},
|
||||
{
|
||||
label: 'تراز قیمت−پرداخت (پس از هدیه)',
|
||||
value: `${formatDashboardAmount(finance.value?.sumAll)} ${DASHBOARD_RIAL_UNIT}`,
|
||||
help: dashboardDateMetrics.netIncome,
|
||||
},
|
||||
{
|
||||
label: 'هدایا',
|
||||
label: 'هدایا (گرم)',
|
||||
value: `${finance.value?.Gifts ?? '0'} گرم`,
|
||||
help: dashboardDateMetrics.gifts,
|
||||
},
|
||||
@@ -594,13 +603,13 @@ const walletMetricItems = computed(() => [
|
||||
},
|
||||
{
|
||||
label: 'ریال مشتریان',
|
||||
value: usePrice(walletSums.value?.cash ?? 0, true, ''),
|
||||
value: `${formatDashboardAmount(walletSums.value?.cash)} ${DASHBOARD_RIAL_UNIT}`,
|
||||
help: dashboardWalletMetrics.cash,
|
||||
variant: 'sky',
|
||||
},
|
||||
{
|
||||
label: metalLabel.goldValueInRial(),
|
||||
value: usePrice(walletSums.value?.goldToCash ?? 0, true, ''),
|
||||
value: `${formatDashboardAmount(walletSums.value?.goldToCash)} ${DASHBOARD_RIAL_UNIT}`,
|
||||
help: dashboardWalletMetrics.goldToCash,
|
||||
variant: 'violet',
|
||||
},
|
||||
@@ -616,6 +625,24 @@ const walletMetricItems = computed(() => [
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.dashboard-metrics-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.dashboard-metrics-row {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.dashboard-metrics-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-text {
|
||||
color: var(--admin-text);
|
||||
}
|
||||
@@ -630,6 +657,10 @@ const walletMetricItems = computed(() => [
|
||||
|
||||
.dashboard-inline-metric {
|
||||
background: var(--admin-bg-muted);
|
||||
min-height: 3.75rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dashboard-profit {
|
||||
|
||||
Reference in New Issue
Block a user