added charge for all products 2
This commit is contained in:
Vendored
+3
@@ -10,6 +10,7 @@ export {}
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
_index: typeof import('./src/core/components/_sample/_index.vue')['default']
|
||||
AAlert: typeof import('ant-design-vue/es')['Alert']
|
||||
AAvatar: typeof import('ant-design-vue/es')['Avatar']
|
||||
ABadge: typeof import('ant-design-vue/es')['Badge']
|
||||
AButton: typeof import('ant-design-vue/es')['Button']
|
||||
@@ -42,6 +43,7 @@ declare module '@vue/runtime-core' {
|
||||
APagination: typeof import('ant-design-vue/es')['Pagination']
|
||||
APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
|
||||
APopover: typeof import('ant-design-vue/es')['Popover']
|
||||
ARadio: typeof import('ant-design-vue/es')['Radio']
|
||||
ARadioButton: typeof import('ant-design-vue/es')['RadioButton']
|
||||
ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup']
|
||||
ARow: typeof import('ant-design-vue/es')['Row']
|
||||
@@ -56,6 +58,7 @@ declare module '@vue/runtime-core' {
|
||||
ATextarea: typeof import('ant-design-vue/es')['Textarea']
|
||||
ATimePicker: typeof import('ant-design-vue/es')['TimePicker']
|
||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||
AUpload: typeof import('ant-design-vue/es')['Upload']
|
||||
BaseButton: typeof import('./src/core/components/BaseButton/index.ts')['default']
|
||||
BaseCard: typeof import('./src/core/components/BaseCard/index.ts')['default']
|
||||
BaseCollapse: typeof import('./src/components/BaseCollapse.vue')['default']
|
||||
|
||||
@@ -60,6 +60,9 @@
|
||||
<div class="flex cursor-pointer justify-center pt-2" @click="visibleProxy = false">
|
||||
<span class="w-12 rounded-sm border-t-2 border-t-solid border-t-gray-500"></span>
|
||||
</div>
|
||||
<div v-if="title" class="basic-action-sheet__header">
|
||||
<h3 class="basic-action-sheet__title">{{ title }}</h3>
|
||||
</div>
|
||||
<div class="basic-action-sheet__content">
|
||||
<slot />
|
||||
</div>
|
||||
@@ -167,7 +170,8 @@ function handleOk() {
|
||||
.basic-action-sheet {
|
||||
.ant-drawer-content {
|
||||
border-radius: 16px 16px 0 0;
|
||||
overflow: hidden;
|
||||
overflow-x: visible;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.ant-drawer-body {
|
||||
@@ -185,10 +189,27 @@ function handleOk() {
|
||||
|
||||
.basic-action-sheet__content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-y: auto;
|
||||
padding: 0 16px 12px;
|
||||
}
|
||||
|
||||
.basic-action-sheet__header {
|
||||
flex: 0 0 auto;
|
||||
padding: 8px 16px 12px;
|
||||
border-bottom: 1px solid var(--admin-border);
|
||||
background: var(--admin-bg-elevated);
|
||||
}
|
||||
|
||||
.basic-action-sheet__title {
|
||||
margin: 0;
|
||||
color: var(--admin-text);
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.6;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.basic-action-sheet--compact {
|
||||
.ant-drawer-content-wrapper {
|
||||
height: auto !important;
|
||||
@@ -209,7 +230,7 @@ function handleOk() {
|
||||
|
||||
.basic-action-sheet__container--compact .basic-action-sheet__content {
|
||||
flex: 0 1 auto;
|
||||
max-height: calc(88vh - 40px);
|
||||
max-height: calc(88vh - 92px);
|
||||
}
|
||||
|
||||
.basic-action-sheet__footer {
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<template>
|
||||
<div class="customer-wallet-balance" :class="compact ? 'space-y-1.5' : 'space-y-3'">
|
||||
<div
|
||||
class="customer-wallet-balance"
|
||||
:class="[
|
||||
compact ? 'customer-wallet-balance--compact space-y-1.5' : 'space-y-3',
|
||||
layout === 'sidebar' ? 'customer-wallet-balance--sidebar' : '',
|
||||
]"
|
||||
>
|
||||
<div
|
||||
v-if="loading"
|
||||
class="rounded-xl border border-gray-200 bg-gray-50 text-center text-sm text-gray-500"
|
||||
class="customer-wallet-balance__placeholder rounded-xl text-center text-sm"
|
||||
:class="compact ? 'px-3 py-3' : 'px-4 py-6'"
|
||||
>
|
||||
در حال بارگذاری موجودی…
|
||||
@@ -16,24 +22,30 @@
|
||||
{{ error }}
|
||||
</div>
|
||||
|
||||
<div v-else-if="summary && compact" class="customer-wallet-balance__minimal">
|
||||
<div
|
||||
v-else-if="summary && compact"
|
||||
ref="minimalTrackRef"
|
||||
class="customer-wallet-balance__minimal-track"
|
||||
>
|
||||
<div class="customer-wallet-balance__minimal">
|
||||
<template v-if="chargeTargets.length">
|
||||
<button
|
||||
<component
|
||||
:is="interactive ? 'button' : 'div'"
|
||||
v-for="target in chargeTargets"
|
||||
:key="target.key"
|
||||
type="button"
|
||||
:type="interactive ? 'button' : undefined"
|
||||
class="customer-wallet-balance__minimal-item"
|
||||
:class="[
|
||||
targetToneClass(target),
|
||||
{ 'customer-wallet-balance__minimal-item--inactive': target.active === false },
|
||||
{ 'customer-wallet-balance__minimal-item--selected': target.key === selectedChargeKey },
|
||||
{ 'customer-wallet-balance__minimal-item--selected': interactive && target.key === selectedChargeKey },
|
||||
]"
|
||||
:title="target.label"
|
||||
@click="emit('selectChargeTarget', target.key)"
|
||||
@click="interactive ? emit('selectChargeTarget', target.key) : undefined"
|
||||
>
|
||||
<span class="customer-wallet-balance__minimal-label">{{ minimalTargetLabel(target) }}</span>
|
||||
<span class="customer-wallet-balance__minimal-value">{{ balanceForTarget(target) }}</span>
|
||||
</button>
|
||||
</component>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div
|
||||
@@ -50,68 +62,83 @@
|
||||
<span class="customer-wallet-balance__minimal-value">{{ usePrice(summary.cash_wallet ?? 0, true, '') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-else-if="summary">
|
||||
<div
|
||||
v-for="metal in summary.metal_totals"
|
||||
:key="metal.metal_id"
|
||||
class="overflow-hidden rounded-xl border border-gray-200"
|
||||
>
|
||||
<div class="flex items-center justify-between gap-3 bg-emerald-50 px-4 py-3">
|
||||
<div class="flex min-w-0 items-center gap-2">
|
||||
<BaseIcon icon="vuesax-linear:coin" size="18" color="#15803d" />
|
||||
<span class="truncate font-700 text-emerald-900">{{ metal.label }}</span>
|
||||
</div>
|
||||
<span class="shrink-0 font-800 text-emerald-800">{{ formatMetalTotal(metal) }}</span>
|
||||
</div>
|
||||
<div v-else-if="summary" class="customer-wallet-balance__full">
|
||||
<p v-if="layout === 'sidebar'" class="customer-wallet-balance__sidebar-title">موجودی داراییها</p>
|
||||
<div class="customer-wallet-balance__overview">
|
||||
<article
|
||||
v-for="metal in summary.metal_totals"
|
||||
:key="metal.metal_id"
|
||||
class="customer-wallet-balance__summary-card"
|
||||
:class="groupToneClass(metal.metal_id)"
|
||||
>
|
||||
<span class="customer-wallet-balance__summary-label">{{ minimalMetalLabel(metal) }}</span>
|
||||
<span class="customer-wallet-balance__summary-value">{{ formatMetalTotal(metal) }}</span>
|
||||
</article>
|
||||
|
||||
<div v-if="linesForMetal(metal.metal_id).length" class="divide-y divide-gray-100 bg-white">
|
||||
<div
|
||||
v-for="line in linesForMetal(metal.metal_id)"
|
||||
:key="line.key"
|
||||
class="flex items-center justify-between gap-3 px-4 py-2.5 text-sm"
|
||||
>
|
||||
<span class="min-w-0 truncate text-gray-600">{{ line.label }}</span>
|
||||
<span class="shrink-0 font-600 text-gray-900">{{ line.value }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<article class="customer-wallet-balance__summary-card customer-wallet-balance__group--cash">
|
||||
<span class="customer-wallet-balance__summary-label">ریالی</span>
|
||||
<span class="customer-wallet-balance__summary-value">{{ usePrice(summary.total_rial_value ?? 0, true, '') }}</span>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden rounded-xl border border-gray-200">
|
||||
<div class="flex items-center justify-between gap-3 bg-sky-50 px-4 py-3">
|
||||
<div class="flex items-center gap-2">
|
||||
<BaseIcon icon="vuesax-linear:empty-wallet" size="18" color="#0369a1" />
|
||||
<span class="font-700 text-sky-900">کل دارایی ریالی</span>
|
||||
</div>
|
||||
<span class="font-800 text-sky-800">{{ usePrice(summary.total_rial_value ?? 0, true, '') }}</span>
|
||||
</div>
|
||||
<div class="customer-wallet-balance__details">
|
||||
<div class="customer-wallet-balance__details-title">جزئیات موجودی</div>
|
||||
|
||||
<div class="divide-y divide-gray-100 bg-white">
|
||||
<div class="flex items-center justify-between gap-3 px-4 py-2.5 text-sm">
|
||||
<span class="text-gray-600">کیف پول ریالی</span>
|
||||
<span class="font-600">{{ usePrice(summary.cash_wallet ?? 0, true, '') }}</span>
|
||||
<template v-for="metal in summary.metal_totals" :key="`detail-${metal.metal_id}`">
|
||||
<section
|
||||
v-if="linesForMetal(metal.metal_id).length"
|
||||
class="customer-wallet-balance__detail-group"
|
||||
:class="groupToneClass(metal.metal_id)"
|
||||
>
|
||||
<div class="customer-wallet-balance__detail-group-title">
|
||||
<span class="customer-wallet-balance__group-dot" aria-hidden="true" />
|
||||
<span>{{ metal.label }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-for="line in linesForMetal(metal.metal_id)"
|
||||
:key="line.key"
|
||||
class="customer-wallet-balance__detail-row"
|
||||
:class="{ 'customer-wallet-balance__detail-row--strong': line.key === 'total' }"
|
||||
>
|
||||
<span class="customer-wallet-balance__detail-label">{{ line.label }}</span>
|
||||
<span class="customer-wallet-balance__detail-value">{{ line.value }}</span>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<section class="customer-wallet-balance__detail-group customer-wallet-balance__group--cash">
|
||||
<div class="customer-wallet-balance__detail-group-title">
|
||||
<span class="customer-wallet-balance__group-dot" aria-hidden="true" />
|
||||
<span>دارایی ریالی</span>
|
||||
</div>
|
||||
<div class="customer-wallet-balance__detail-row">
|
||||
<span class="customer-wallet-balance__detail-label">کیف پول ریالی</span>
|
||||
<span class="customer-wallet-balance__detail-value">{{ usePrice(summary.cash_wallet ?? 0, true, '') }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="Number(summary.assets_rial_value ?? 0) > 0"
|
||||
class="flex items-center justify-between gap-3 px-4 py-2.5 text-sm"
|
||||
class="customer-wallet-balance__detail-row"
|
||||
>
|
||||
<span class="text-gray-600">ارزش ریالی فلزات</span>
|
||||
<span class="font-600">{{ usePrice(summary.assets_rial_value ?? 0, true, '') }}</span>
|
||||
<span class="customer-wallet-balance__detail-label">ارزش ریالی فلزات</span>
|
||||
<span class="customer-wallet-balance__detail-value">{{ usePrice(summary.assets_rial_value ?? 0, true, '') }}</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-3 px-4 py-2.5 text-sm font-700">
|
||||
<span>مجموع کل</span>
|
||||
<span>{{ usePrice(summary.total_rial_value ?? 0, true, '') }}</span>
|
||||
<div class="customer-wallet-balance__detail-row customer-wallet-balance__detail-row--strong">
|
||||
<span class="customer-wallet-balance__detail-label">مجموع کل</span>
|
||||
<span class="customer-wallet-balance__detail-value">{{ usePrice(summary.total_rial_value ?? 0, true, '') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { getCustomerAssetsSummary } from '@/api/customer'
|
||||
import { useHorizontalTouchScroll } from '@/components/mobile/composables/useHorizontalTouchScroll'
|
||||
import type { ChargeTarget } from '@/model/wallet'
|
||||
import type { WalletAssetsSummary, WalletInventoryCard, WalletMetalTotal } from '@/model/walletAssets'
|
||||
import { usePrice } from '@core/utils/usePrice'
|
||||
@@ -122,14 +149,20 @@ const props = withDefaults(
|
||||
customerId?: number | null
|
||||
/** نمایش مینیمال برای مودالها */
|
||||
compact?: boolean
|
||||
/** چیدمان ستون کناری در اطلاعات کاربر */
|
||||
layout?: 'default' | 'sidebar'
|
||||
/** گزینههای شارژ — برای نمایش موجودی هر محصول */
|
||||
chargeTargets?: ChargeTarget[]
|
||||
selectedChargeKey?: string
|
||||
/** false = فقط نمایش، بدون کلیک */
|
||||
interactive?: boolean
|
||||
}>(),
|
||||
{
|
||||
compact: false,
|
||||
layout: 'default',
|
||||
chargeTargets: () => [],
|
||||
selectedChargeKey: '',
|
||||
interactive: true,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -167,9 +200,23 @@ function minimalMetalToneClass(metal: WalletMetalTotal) {
|
||||
|
||||
function minimalTargetLabel(target: ChargeTarget) {
|
||||
if (target.kind === 'money') return 'نقدی'
|
||||
const label = target.label.replace(/\s*\(کیف اصلی\)\s*$/u, '').trim()
|
||||
if (label.length <= 14) return label
|
||||
return `${label.slice(0, 13)}…`
|
||||
return target.label
|
||||
.replace(/\s*\(کیف اصلی\)\s*$/u, '')
|
||||
.replace(/\s*\(غیرفعال\)\s*$/u, '')
|
||||
.trim()
|
||||
}
|
||||
|
||||
function groupToneClass(metalId: number | string | undefined) {
|
||||
switch (Number(metalId)) {
|
||||
case 1:
|
||||
return 'customer-wallet-balance__group--gold'
|
||||
case 2:
|
||||
return 'customer-wallet-balance__group--silver'
|
||||
case 3:
|
||||
return 'customer-wallet-balance__group--copper'
|
||||
default:
|
||||
return 'customer-wallet-balance__group--product'
|
||||
}
|
||||
}
|
||||
|
||||
function targetToneClass(target: ChargeTarget) {
|
||||
@@ -210,6 +257,9 @@ function balanceForTarget(target: ChargeTarget) {
|
||||
const loading = ref(false)
|
||||
const error = ref<string | null>(null)
|
||||
const summary = ref<WalletAssetsSummary | null>(null)
|
||||
const minimalTrackRef = ref<HTMLElement | null>(null)
|
||||
|
||||
useHorizontalTouchScroll(minimalTrackRef)
|
||||
|
||||
watch(
|
||||
() => props.customerId,
|
||||
@@ -287,36 +337,262 @@ defineExpose({ reload: () => props.customerId && load(props.customerId) })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.customer-wallet-balance__minimal {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(4.75rem, 1fr));
|
||||
gap: 0.35rem;
|
||||
padding: 0.45rem;
|
||||
border-radius: 0.6rem;
|
||||
border: 1px solid #e2e8f0;
|
||||
background: #f8fafc;
|
||||
max-height: 14rem;
|
||||
.customer-wallet-balance--compact {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__placeholder {
|
||||
border: 1px solid var(--admin-border, #e2e8f0);
|
||||
background: var(--admin-bg-muted, #f8fafc);
|
||||
color: var(--admin-text-secondary, #64748b);
|
||||
}
|
||||
|
||||
/* ---------- نمای کامل (خلاصه + جزئیات) ---------- */
|
||||
|
||||
.customer-wallet-balance__full {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.customer-wallet-balance--sidebar .customer-wallet-balance__full {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__sidebar-title {
|
||||
margin: 0;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 700;
|
||||
color: var(--admin-text-secondary, #64748b);
|
||||
}
|
||||
|
||||
.customer-wallet-balance--sidebar .customer-wallet-balance__overview {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.customer-wallet-balance--sidebar .customer-wallet-balance__details {
|
||||
max-height: min(52vh, 26rem);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item {
|
||||
.customer-wallet-balance__overview {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__summary-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.1rem;
|
||||
min-width: 0;
|
||||
padding: 0.35rem 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.6rem;
|
||||
border-radius: 0.65rem;
|
||||
border: 1px solid color-mix(in srgb, var(--wallet-accent, #94a3b8) 28%, transparent);
|
||||
background: color-mix(in srgb, var(--wallet-accent, #94a3b8) 10%, var(--admin-bg-elevated, #fff));
|
||||
padding: 0.55rem 0.7rem;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__summary-label {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--admin-text-secondary, #64748b);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__summary-value {
|
||||
flex: 0 0 auto;
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 800;
|
||||
color: var(--wallet-accent-strong, var(--admin-text, #0f172a));
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__details {
|
||||
margin-top: 0.6rem;
|
||||
overflow: hidden;
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid var(--admin-border, #e2e8f0);
|
||||
background: var(--admin-bg-elevated, #fff);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__details-title {
|
||||
padding: 0.55rem 0.8rem;
|
||||
border-bottom: 1px solid var(--admin-border, #e2e8f0);
|
||||
color: var(--admin-text-secondary, #64748b);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-group + .customer-wallet-balance__detail-group {
|
||||
border-top: 1px solid var(--admin-border, #e2e8f0);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-group-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
padding: 0.55rem 0.8rem 0.25rem;
|
||||
color: var(--admin-text, #0f172a);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__group-dot {
|
||||
width: 0.45rem;
|
||||
height: 0.45rem;
|
||||
flex: 0 0 auto;
|
||||
border-radius: 9999px;
|
||||
background: var(--wallet-accent, var(--admin-text-secondary, #94a3b8));
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.45rem 0.8rem;
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-row + .customer-wallet-balance__detail-row {
|
||||
border-top: 1px solid color-mix(in srgb, var(--admin-border, #e2e8f0) 70%, transparent);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-label {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--admin-text-secondary, #64748b);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-value {
|
||||
font-weight: 600;
|
||||
color: var(--admin-text, #0f172a);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-row--strong {
|
||||
background: color-mix(in srgb, var(--wallet-accent, #94a3b8) 8%, transparent);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__detail-row--strong .customer-wallet-balance__detail-label,
|
||||
.customer-wallet-balance__detail-row--strong .customer-wallet-balance__detail-value {
|
||||
font-weight: 800;
|
||||
color: var(--admin-text, #0f172a);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__group--gold {
|
||||
--wallet-accent: #d97706;
|
||||
--wallet-accent-strong: #b45309;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__group--silver {
|
||||
--wallet-accent: #64748b;
|
||||
--wallet-accent-strong: #475569;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__group--copper {
|
||||
--wallet-accent: #ea580c;
|
||||
--wallet-accent-strong: #c2410c;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__group--cash {
|
||||
--wallet-accent: #0284c7;
|
||||
--wallet-accent-strong: #0369a1;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__group--product {
|
||||
--wallet-accent: var(--admin-text-secondary, #64748b);
|
||||
--wallet-accent-strong: var(--admin-text, #0f172a);
|
||||
}
|
||||
|
||||
:global(html.is-dark) .customer-wallet-balance__group--gold {
|
||||
--wallet-accent: #fbbf24;
|
||||
--wallet-accent-strong: #fcd34d;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .customer-wallet-balance__group--silver {
|
||||
--wallet-accent: #94a3b8;
|
||||
--wallet-accent-strong: #cbd5e1;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .customer-wallet-balance__group--copper {
|
||||
--wallet-accent: #fb923c;
|
||||
--wallet-accent-strong: #fdba74;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .customer-wallet-balance__group--cash {
|
||||
--wallet-accent: #60a5fa;
|
||||
--wallet-accent-strong: #93c5fd;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-track {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overscroll-behavior-x: contain;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--admin-border-strong, #cbd5e1) transparent;
|
||||
padding: 0.45rem 0.35rem;
|
||||
border-radius: 0.6rem;
|
||||
border: 1px solid var(--admin-border, #e2e8f0);
|
||||
background: var(--admin-bg-muted, #f8fafc);
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-track::-webkit-scrollbar {
|
||||
height: 0.35rem;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-track::-webkit-scrollbar-thumb {
|
||||
border-radius: 9999px;
|
||||
background: var(--admin-border-strong, #cbd5e1);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: stretch;
|
||||
gap: 0.35rem;
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item {
|
||||
display: grid;
|
||||
grid-template-rows: minmax(0, 1fr) auto;
|
||||
flex: 0 0 6.25rem;
|
||||
width: 6.25rem;
|
||||
min-width: 6.25rem;
|
||||
min-height: 4rem;
|
||||
gap: 0.25rem;
|
||||
padding: 0.45rem 0.35rem;
|
||||
border-radius: 0.45rem;
|
||||
background: #fff;
|
||||
background: var(--wallet-tile-bg, var(--admin-bg-elevated, #fff));
|
||||
text-align: center;
|
||||
border: 1px solid transparent;
|
||||
border: 1px solid var(--wallet-tile-border, var(--admin-border, #e2e8f0));
|
||||
cursor: default;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button.customer-wallet-balance__minimal-item {
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.15s ease, transform 0.15s ease;
|
||||
transition: box-shadow 0.15s ease, transform 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
button.customer-wallet-balance__minimal-item:hover {
|
||||
@@ -324,7 +600,9 @@ button.customer-wallet-balance__minimal-item:hover {
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--selected {
|
||||
box-shadow: 0 0 0 2px #2563eb;
|
||||
border-width: 2px;
|
||||
padding: calc(0.45rem - 1px) calc(0.35rem - 1px);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--inactive {
|
||||
@@ -332,84 +610,98 @@ button.customer-wallet-balance__minimal-item:hover {
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--gold {
|
||||
background: #fffbeb;
|
||||
border-color: #fde68a;
|
||||
--wallet-tile-bg: #fffbeb;
|
||||
--wallet-tile-border: #fde68a;
|
||||
--wallet-tile-label: #92400e;
|
||||
--wallet-tile-value: #b45309;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--silver {
|
||||
background: #f8fafc;
|
||||
border-color: #cbd5e1;
|
||||
--wallet-tile-bg: #f8fafc;
|
||||
--wallet-tile-border: #cbd5e1;
|
||||
--wallet-tile-label: #64748b;
|
||||
--wallet-tile-value: #334155;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--copper {
|
||||
background: #fff7ed;
|
||||
border-color: #fdba74;
|
||||
--wallet-tile-bg: #fff7ed;
|
||||
--wallet-tile-border: #fdba74;
|
||||
--wallet-tile-label: #c2410c;
|
||||
--wallet-tile-value: #9a3412;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--cash {
|
||||
background: #eff6ff;
|
||||
border-color: #93c5fd;
|
||||
--wallet-tile-bg: #eff6ff;
|
||||
--wallet-tile-border: #93c5fd;
|
||||
--wallet-tile-label: #0369a1;
|
||||
--wallet-tile-value: #0284c7;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--product {
|
||||
background: #f8fafc;
|
||||
border-color: #e2e8f0;
|
||||
--wallet-tile-bg: var(--admin-bg-elevated, #fff);
|
||||
--wallet-tile-border: var(--admin-border, #e2e8f0);
|
||||
--wallet-tile-label: #475569;
|
||||
--wallet-tile-value: #1e293b;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-label {
|
||||
font-size: 0.6875rem;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
align-self: start;
|
||||
min-height: 0;
|
||||
max-height: 2.45em;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
max-width: 100%;
|
||||
line-height: 1.25;
|
||||
color: var(--wallet-tile-label, var(--admin-text-secondary, #64748b));
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-value {
|
||||
font-size: 0.75rem;
|
||||
align-self: end;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
line-height: 1.25;
|
||||
color: var(--wallet-tile-value, var(--admin-text, #0f172a));
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--gold .customer-wallet-balance__minimal-label {
|
||||
color: #92400e;
|
||||
:global(html.is-dark) .customer-wallet-balance__minimal-item--gold {
|
||||
--wallet-tile-bg: rgba(245, 158, 11, 0.14);
|
||||
--wallet-tile-border: rgba(251, 191, 36, 0.28);
|
||||
--wallet-tile-label: #fbbf24;
|
||||
--wallet-tile-value: #fcd34d;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--gold .customer-wallet-balance__minimal-value {
|
||||
color: #b45309;
|
||||
:global(html.is-dark) .customer-wallet-balance__minimal-item--silver {
|
||||
--wallet-tile-bg: rgba(148, 163, 184, 0.12);
|
||||
--wallet-tile-border: rgba(148, 163, 184, 0.28);
|
||||
--wallet-tile-label: #94a3b8;
|
||||
--wallet-tile-value: #cbd5e1;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--silver .customer-wallet-balance__minimal-label {
|
||||
color: #64748b;
|
||||
:global(html.is-dark) .customer-wallet-balance__minimal-item--copper {
|
||||
--wallet-tile-bg: rgba(249, 115, 22, 0.14);
|
||||
--wallet-tile-border: rgba(251, 146, 60, 0.28);
|
||||
--wallet-tile-label: #fb923c;
|
||||
--wallet-tile-value: #fdba74;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--silver .customer-wallet-balance__minimal-value {
|
||||
color: #334155;
|
||||
:global(html.is-dark) .customer-wallet-balance__minimal-item--cash {
|
||||
--wallet-tile-bg: rgba(59, 130, 246, 0.14);
|
||||
--wallet-tile-border: rgba(96, 165, 250, 0.32);
|
||||
--wallet-tile-label: #60a5fa;
|
||||
--wallet-tile-value: #93c5fd;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--copper .customer-wallet-balance__minimal-label {
|
||||
color: #c2410c;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--copper .customer-wallet-balance__minimal-value {
|
||||
color: #9a3412;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--cash .customer-wallet-balance__minimal-label {
|
||||
color: #0369a1;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--cash .customer-wallet-balance__minimal-value {
|
||||
color: #0284c7;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--product .customer-wallet-balance__minimal-label {
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--product .customer-wallet-balance__minimal-value {
|
||||
color: #1e293b;
|
||||
:global(html.is-dark) .customer-wallet-balance__minimal-item--product {
|
||||
--wallet-tile-bg: rgba(255, 255, 255, 0.04);
|
||||
--wallet-tile-border: var(--admin-border);
|
||||
--wallet-tile-label: var(--admin-text-secondary);
|
||||
--wallet-tile-value: var(--admin-text);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<BasicActionSheet
|
||||
v-model:visible="visibleModel"
|
||||
:title="''"
|
||||
:title="title"
|
||||
:showButton="false"
|
||||
:compact="true"
|
||||
:drawerHeight="drawerHeight"
|
||||
>
|
||||
<div v-if="item" class="space-y-3 pb-2">
|
||||
<div v-if="item" class="mobile-detail-sheet__body space-y-3 pb-2">
|
||||
<slot :item="item" />
|
||||
</div>
|
||||
</BasicActionSheet>
|
||||
@@ -36,3 +36,11 @@ const visibleModel = computed({
|
||||
set: (value: boolean) => emit('update:visible', value)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mobile-detail-sheet__body {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { onBeforeUnmount, watch, type Ref } from 'vue'
|
||||
|
||||
function bindHorizontalTouchScroll(el: HTMLElement) {
|
||||
let startX = 0
|
||||
let startY = 0
|
||||
let scrollStart = 0
|
||||
let axis: 'x' | 'y' | null = null
|
||||
|
||||
const onTouchStart = (event: TouchEvent) => {
|
||||
if (event.touches.length !== 1) return
|
||||
startX = event.touches[0].clientX
|
||||
startY = event.touches[0].clientY
|
||||
scrollStart = el.scrollLeft
|
||||
axis = null
|
||||
}
|
||||
|
||||
const onTouchMove = (event: TouchEvent) => {
|
||||
if (event.touches.length !== 1) return
|
||||
|
||||
const dx = event.touches[0].clientX - startX
|
||||
const dy = event.touches[0].clientY - startY
|
||||
|
||||
if (!axis) {
|
||||
if (Math.abs(dx) < 4 && Math.abs(dy) < 4) return
|
||||
axis = Math.abs(dx) > Math.abs(dy) ? 'x' : 'y'
|
||||
}
|
||||
|
||||
if (axis !== 'x') return
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
el.scrollLeft = scrollStart - dx
|
||||
}
|
||||
|
||||
el.addEventListener('touchstart', onTouchStart, { passive: true })
|
||||
el.addEventListener('touchmove', onTouchMove, { passive: false })
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
const max = el.scrollWidth - el.clientWidth
|
||||
if (max > 0) el.scrollLeft = max
|
||||
})
|
||||
|
||||
return () => {
|
||||
el.removeEventListener('touchstart', onTouchStart)
|
||||
el.removeEventListener('touchmove', onTouchMove)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reliable horizontal swipe inside RTL pages and nested vertical scroll areas.
|
||||
*/
|
||||
export function useHorizontalTouchScroll(trackRef: Ref<HTMLElement | null>) {
|
||||
let cleanup: (() => void) | undefined
|
||||
|
||||
watch(
|
||||
trackRef,
|
||||
(el) => {
|
||||
cleanup?.()
|
||||
cleanup = undefined
|
||||
if (!el) return
|
||||
cleanup = bindHorizontalTouchScroll(el)
|
||||
},
|
||||
{ flush: 'post' },
|
||||
)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
cleanup?.()
|
||||
})
|
||||
}
|
||||
@@ -49,7 +49,8 @@
|
||||
|
||||
.ant-drawer-bottom .ant-drawer-content {
|
||||
border-radius: 16px 16px 0 0;
|
||||
overflow: hidden;
|
||||
overflow-x: visible;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.ant-card-body{
|
||||
|
||||
@@ -428,4 +428,164 @@ html.is-dark {
|
||||
border-color: var(--admin-gold-light) !important;
|
||||
box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.18) !important;
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction.ant-radio-group-solid {
|
||||
.ant-radio-button-wrapper {
|
||||
background: var(--admin-bg-muted) !important;
|
||||
border-color: var(--admin-border-strong) !important;
|
||||
color: var(--admin-text) !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper:hover {
|
||||
color: var(--admin-text) !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:hover,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:active {
|
||||
background: #16a34a !important;
|
||||
border-color: #16a34a !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:hover::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:active::before {
|
||||
background-color: #16a34a !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:hover,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:active {
|
||||
background: #dc2626 !important;
|
||||
border-color: #dc2626 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:hover::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:active::before {
|
||||
background-color: #dc2626 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction.ant-radio-group-solid {
|
||||
.ant-radio-button-wrapper {
|
||||
background: var(--admin-bg-muted) !important;
|
||||
border-color: var(--admin-border-strong) !important;
|
||||
color: var(--admin-text) !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:hover,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:active {
|
||||
background: #15803d !important;
|
||||
border-color: #15803d !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:hover::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge:active::before {
|
||||
background-color: #15803d !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:hover,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:active {
|
||||
background: #b91c1c !important;
|
||||
border-color: #b91c1c !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:hover::before,
|
||||
.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge:active::before {
|
||||
background-color: #b91c1c !important;
|
||||
}
|
||||
}
|
||||
|
||||
html.is-dark {
|
||||
.customer-wallet-balance__minimal {
|
||||
background: var(--admin-bg-muted);
|
||||
border-color: var(--admin-border);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--gold {
|
||||
background: rgba(245, 158, 11, 0.14);
|
||||
border-color: rgba(251, 191, 36, 0.28);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--gold .customer-wallet-balance__minimal-label {
|
||||
color: #fbbf24;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--gold .customer-wallet-balance__minimal-value {
|
||||
color: #fcd34d;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--silver {
|
||||
background: rgba(148, 163, 184, 0.12);
|
||||
border-color: rgba(148, 163, 184, 0.28);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--silver .customer-wallet-balance__minimal-label {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--silver .customer-wallet-balance__minimal-value {
|
||||
color: #cbd5e1;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--copper {
|
||||
background: rgba(249, 115, 22, 0.14);
|
||||
border-color: rgba(251, 146, 60, 0.28);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--copper .customer-wallet-balance__minimal-label {
|
||||
color: #fb923c;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--copper .customer-wallet-balance__minimal-value {
|
||||
color: #fdba74;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--cash {
|
||||
background: rgba(59, 130, 246, 0.14);
|
||||
border-color: rgba(96, 165, 250, 0.32);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--cash .customer-wallet-balance__minimal-label {
|
||||
color: #60a5fa;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--cash .customer-wallet-balance__minimal-value {
|
||||
color: #93c5fd;
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--product {
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border-color: var(--admin-border);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--product .customer-wallet-balance__minimal-label {
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.customer-wallet-balance__minimal-item--product .customer-wallet-balance__minimal-value {
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.wallet-charge-form__preview--charge {
|
||||
background: rgba(34, 197, 94, 0.14);
|
||||
border-color: rgba(34, 197, 94, 0.32);
|
||||
color: #86efac;
|
||||
}
|
||||
|
||||
.wallet-charge-form__preview--discharge {
|
||||
background: rgba(239, 68, 68, 0.14);
|
||||
border-color: rgba(239, 68, 68, 0.32);
|
||||
color: #fca5a5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,14 @@ export interface DashboardFinance {
|
||||
profitGoldGrams?: number
|
||||
/** سود ریالی: مجموع کارمزدهای کسرشده از ریال */
|
||||
profitRial?: number
|
||||
/** سود ریالی قبل از کسر سندهای تبدیل */
|
||||
profitRialGross?: number
|
||||
/** سود طلایی قبل از افزودن سندهای تبدیل */
|
||||
profitGoldGramsGross?: number
|
||||
/** جمع ریالی تبدیلشده به طلا در بازه */
|
||||
profitRialConverted?: number
|
||||
/** جمع گرم تبدیلشده از سود ریالی در بازه */
|
||||
profitGoldConvertedGram?: number
|
||||
/** ارزش ریالی سود طلایی با قیمت روز */
|
||||
profitGoldValueRial?: number
|
||||
/** تفکیک روزانهٔ سود طلایی/ریالی */
|
||||
|
||||
@@ -55,6 +55,9 @@
|
||||
<span class="dashboard-profit-split__unit">گرم</span>
|
||||
</p>
|
||||
<p class="dashboard-profit-split__sub">≈ {{ formatDashboardAmount(profitGoldValueRial) }} ریال</p>
|
||||
<p v-if="profitGoldConvertedGram > 0" class="dashboard-profit-split__note">
|
||||
شامل {{ formatGram(profitGoldConvertedGram) }} گرم از تبدیل سود ریالی
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article class="dashboard-profit-split__card dashboard-profit-split__card--rial">
|
||||
@@ -69,7 +72,14 @@
|
||||
<span class="dashboard-profit-split__amount">{{ formatDashboardAmount(profitRial) }}</span>
|
||||
<span class="dashboard-profit-split__unit">ریال</span>
|
||||
</p>
|
||||
<p class="dashboard-profit-split__sub">{{ dailyRows.length }} روز دارای معامله</p>
|
||||
<p class="dashboard-profit-split__sub">
|
||||
<template v-if="profitRialConverted > 0">
|
||||
{{ formatGram(profitGoldConvertedGram) }} گرم تبدیلشده به طلا
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ dailyRows.length }} روز دارای معامله
|
||||
</template>
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -291,15 +301,15 @@ const activeEnd = ref(rangeEnd.value)
|
||||
const sectionHelp: DashboardHelp = {
|
||||
description:
|
||||
'کارمزد معاملات بر اساس فیلدی که مشتری وارد میکند تفکیک میشود: وقتی مشتری «مبلغ ریالی» ثابت میزند کارمزد از طلا کسر میشود (سود طلایی)، و وقتی «وزن» ثابت میزند کارمزد از ریال کسر میشود (سود ریالی). اعداد بر اساس بازهٔ انتخابی همین بخش محاسبه میشوند.',
|
||||
formula: 'سود طلایی = جمع کارمزدِ کسرشده از طلا (گرم) | سود ریالی = جمع کارمزدِ کسرشده از ریال (ریال)',
|
||||
formula: 'سود طلایی = جمع کارمزدِ کسرشده از طلا (گرم) + گرم سندهای تبدیل سود ریالی | سود ریالی = جمع کارمزدِ کسرشده از ریال − ریال تبدیلشده به طلا',
|
||||
}
|
||||
const goldHelp: DashboardHelp = {
|
||||
description: 'مجموع کارمزدهایی که در معاملههای «مبلغمحور» (مشتری مبلغ ریالی ثابت زده) از طلا کسر شده است.',
|
||||
formula: 'مجموع کارمزد طلا (گرم) × قیمت روز = ارزش ریالی تقریبی',
|
||||
description: 'مجموع کارمزدهای کسرشده از طلا بهعلاوهٔ گرم سندهای «تبدیل سود ریالی به طلا» در همین بازه.',
|
||||
formula: 'کارمزد طلا (گرم) + گرم تبدیلشده از سود ریالی',
|
||||
}
|
||||
const rialHelp: DashboardHelp = {
|
||||
description: 'مجموع کارمزدهایی که در معاملههای «وزنمحور» (مشتری وزن ثابت زده) از ریال کسر شده است.',
|
||||
formula: 'مجموع کارمزد ریالی معاملههای وزنمحور',
|
||||
description: 'سود ریالی باقیمانده پس از کسر سندهای تبدیل به طلا در همین بازه.',
|
||||
formula: 'کارمزد ریالی − ریال تبدیلشده به طلا',
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
@@ -308,6 +318,8 @@ const finance = ref<DashboardFinance | null>(null)
|
||||
const profitGoldGrams = computed(() => Number(finance.value?.profitGoldGrams ?? 0))
|
||||
const profitRial = computed(() => Number(finance.value?.profitRial ?? 0))
|
||||
const profitGoldValueRial = computed(() => Number(finance.value?.profitGoldValueRial ?? 0))
|
||||
const profitRialConverted = computed(() => Number(finance.value?.profitRialConverted ?? 0))
|
||||
const profitGoldConvertedGram = computed(() => Number(finance.value?.profitGoldConvertedGram ?? 0))
|
||||
const dailyRows = computed(() => finance.value?.daily ?? [])
|
||||
|
||||
// صفحهبندی جدول روزانه
|
||||
@@ -467,7 +479,7 @@ async function submitSanad() {
|
||||
})
|
||||
message.success('سند تبدیل سود ثبت شد')
|
||||
closeSanad()
|
||||
await loadConversions()
|
||||
reloadAll()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
message.error('خطا در ثبت سند')
|
||||
@@ -480,7 +492,7 @@ async function removeConversion(id: number) {
|
||||
try {
|
||||
await deleteProfitConversion(id)
|
||||
message.success('سند حذف شد')
|
||||
await loadConversions()
|
||||
reloadAll()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
message.error('خطا در حذف سند')
|
||||
@@ -595,6 +607,12 @@ reloadAll()
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-profit-split__note {
|
||||
margin: 0.2rem 0 0;
|
||||
font-size: 0.6875rem;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.dashboard-profit-split__sanad {
|
||||
border-top: 1px solid var(--admin-border);
|
||||
padding-top: 0.75rem;
|
||||
|
||||
@@ -1,78 +1,96 @@
|
||||
<template>
|
||||
<MobileDetailSheet v-model:visible="visibleProxy" :item="item" title="">
|
||||
<MobileDetailSheet v-model:visible="visibleProxy" :item="item" :title="sheetTitle">
|
||||
<template #default="{ item: row }">
|
||||
<h2 class="text-base font-700 leading-relaxed text-gray-900">{{ row.name || '-' }}</h2>
|
||||
<p v-if="row.mobile" class="text-sm text-gray-500" dir="ltr">{{ row.mobile }}</p>
|
||||
<div class="customer-mobile-sheet">
|
||||
<p v-if="row.mobile" class="customer-mobile-sheet__mobile" dir="ltr">{{ row.mobile }}</p>
|
||||
|
||||
<div class="customer-mobile-sheet__chips">
|
||||
<span class="customer-mobile-sheet__chip" :class="row.active ? 'is-success' : 'is-danger'">
|
||||
{{ row.active ? 'فعال' : 'غیرفعال' }}
|
||||
</span>
|
||||
<span
|
||||
class="customer-mobile-sheet__chip"
|
||||
:class="row.trade_active === 1 ? 'is-success' : 'is-danger'"
|
||||
>
|
||||
{{ row.trade_active === 1 ? 'سفارش مجاز' : 'سفارش ممنوع' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<section class="customer-mobile-sheet__section">
|
||||
<h4 class="customer-mobile-sheet__section-title">موجودی</h4>
|
||||
<CustomerWalletBalancePanel
|
||||
:customer-id="row.id"
|
||||
:charge-targets="chargeTargets"
|
||||
:interactive="false"
|
||||
compact
|
||||
/>
|
||||
</section>
|
||||
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<BaseButton class="w-full col-span-2" size="middle" type="primary" icon="vuesax-linear:wallet-add" @click="closeAndEmit('chargeWallet', row)">
|
||||
شارژ کیف پول
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="!row.is_legal"
|
||||
class="w-full"
|
||||
class="customer-mobile-sheet__charge-btn"
|
||||
size="middle"
|
||||
type="default"
|
||||
icon="vuesax-linear:user-search"
|
||||
@click="closeAndEmit('confirmUser', row)"
|
||||
type="primary"
|
||||
icon="vuesax-linear:wallet-add"
|
||||
@click="closeAndEmit('chargeWallet', row)"
|
||||
>
|
||||
تایید کاربر
|
||||
</BaseButton>
|
||||
<BaseButton class="w-full" size="middle" type="default" icon="vuesax-linear:stickynote" @click="closeAndEmit('info', row)">
|
||||
مشخصات کامل
|
||||
</BaseButton>
|
||||
<BaseButton class="w-full" size="middle" type="default" icon="vuesax-linear:edit" @click="closeAndEmit('edit', row)">
|
||||
ویرایش
|
||||
</BaseButton>
|
||||
<BaseButton class="w-full" size="middle" type="default" icon="vuesax-linear:archive-tick" @click="closeAndEmit('archive', row)">
|
||||
بایگانی
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
class="w-full"
|
||||
size="middle"
|
||||
:type="row.active ? 'default' : 'primary'"
|
||||
:icon="row.active ? 'vuesax-linear:user-remove' : 'vuesax-linear:user-tick'"
|
||||
@click="confirmToggleActive(row)"
|
||||
>
|
||||
{{ row.active ? 'غیرفعال کردن' : 'فعال کردن' }}
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
class="w-full"
|
||||
size="middle"
|
||||
:type="row.trade_active === 1 ? 'default' : 'primary'"
|
||||
:icon="row.trade_active === 1 ? 'vuesax-linear:box-remove' : 'vuesax-linear:box-tick'"
|
||||
@click="confirmToggleTrade(row)"
|
||||
>
|
||||
{{ row.trade_active === 1 ? 'ممنوعیت سفارش' : 'مجاز کردن سفارش' }}
|
||||
شارژ / دشارژ کیف پول
|
||||
</BaseButton>
|
||||
|
||||
<div class="customer-mobile-sheet__actions">
|
||||
<BaseButton size="small" type="default" icon="vuesax-linear:stickynote" @click="closeAndEmit('info', row)">
|
||||
مشخصات
|
||||
</BaseButton>
|
||||
<BaseButton size="small" type="default" icon="vuesax-linear:edit" @click="closeAndEmit('edit', row)">
|
||||
ویرایش
|
||||
</BaseButton>
|
||||
<BaseButton size="small" type="default" icon="vuesax-linear:archive-tick" @click="closeAndEmit('archive', row)">
|
||||
بایگانی
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
v-if="!row.is_legal"
|
||||
size="small"
|
||||
type="default"
|
||||
icon="vuesax-linear:user-search"
|
||||
@click="closeAndEmit('confirmUser', row)"
|
||||
>
|
||||
تایید
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
size="small"
|
||||
:type="row.active ? 'default' : 'primary'"
|
||||
:icon="row.active ? 'vuesax-linear:user-remove' : 'vuesax-linear:user-tick'"
|
||||
@click="confirmToggleActive(row)"
|
||||
>
|
||||
{{ row.active ? 'غیرفعال' : 'فعال' }}
|
||||
</BaseButton>
|
||||
<BaseButton
|
||||
size="small"
|
||||
:type="row.trade_active === 1 ? 'default' : 'primary'"
|
||||
:icon="row.trade_active === 1 ? 'vuesax-linear:box-remove' : 'vuesax-linear:box-tick'"
|
||||
@click="confirmToggleTrade(row)"
|
||||
>
|
||||
{{ row.trade_active === 1 ? 'ممنوعیت' : 'مجاز سفارش' }}
|
||||
</BaseButton>
|
||||
</div>
|
||||
|
||||
<MobileInfoGrid>
|
||||
<MobileDetailRow label="کد کاربری" :value="row.id ?? '-'" />
|
||||
<MobileDetailRow label="نوع کاربر" :value="row.type_str || '-'" />
|
||||
<MobileDetailRow label="کد معرف" :value="row.referral_id ?? '-'" />
|
||||
<MobileDetailRow label="نام معرف" :value="row.referral?.name ?? '-'" />
|
||||
<MobileDetailRow label="آخرین بازدید" :value="lastSeen(row)" value-class="text-xs" />
|
||||
</MobileInfoGrid>
|
||||
</div>
|
||||
|
||||
<CustomerWalletBalancePanel :customer-id="row?.id" />
|
||||
|
||||
<MobileInfoGrid>
|
||||
<MobileDetailRow label="وضعیت کاربر" full-width :value-class="row.active ? 'text-green-700' : 'text-red-600'">
|
||||
{{ row.active ? 'فعال' : 'غیرفعال' }}
|
||||
</MobileDetailRow>
|
||||
<MobileDetailRow
|
||||
label="وضعیت سفارش دهی"
|
||||
full-width
|
||||
:value-class="row.trade_active === 1 ? 'text-green-700' : 'text-red-600'"
|
||||
>
|
||||
{{ row.trade_active === 1 ? 'مجاز' : 'غیر مجاز' }}
|
||||
</MobileDetailRow>
|
||||
<MobileDetailRow label="کد کاربری" :value="row.id ?? '-'" />
|
||||
<MobileDetailRow label="نوع کاربر" :value="row.type_str || '-'" />
|
||||
<MobileDetailRow label="کد معرف" :value="row.referral_id ?? '-'" />
|
||||
<MobileDetailRow label="نام معرف کاربر" :value="row.referral?.name ?? '-'" />
|
||||
<MobileDetailRow label="آخرین بازدید" :value="lastSeen(row)" value-class="text-xs" />
|
||||
</MobileInfoGrid>
|
||||
</template>
|
||||
</MobileDetailSheet>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { Modal } from 'ant-design-vue'
|
||||
import type { Customer } from '@/model/customer'
|
||||
import type { ChargeTarget } from '@/model/wallet'
|
||||
import { getChargeTargets } from '@/api/wallet'
|
||||
import { MODAL_ABOVE_ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
|
||||
import MobileDetailRow from '@/components/mobile/MobileDetailRow.vue'
|
||||
import MobileDetailSheet from '@/components/mobile/MobileDetailSheet.vue'
|
||||
@@ -96,11 +114,15 @@ const emit = defineEmits<{
|
||||
(e: 'confirmUser', item: Customer): void
|
||||
}>()
|
||||
|
||||
const chargeTargets = ref<ChargeTarget[]>([])
|
||||
|
||||
const visibleProxy = computed({
|
||||
get: () => props.visible,
|
||||
set: (value: boolean) => emit('update:visible', value)
|
||||
set: (value: boolean) => emit('update:visible', value),
|
||||
})
|
||||
|
||||
const sheetTitle = computed(() => props.item?.name?.trim() || 'مشتری')
|
||||
|
||||
type SheetEmit = 'archive' | 'chargeWallet' | 'info' | 'confirmUser' | 'edit'
|
||||
|
||||
function closeAndEmit(event: SheetEmit, row: Customer) {
|
||||
@@ -115,7 +137,7 @@ function confirmToggleActive(row: Customer) {
|
||||
cancelText: 'رد',
|
||||
centered: true,
|
||||
zIndex: MODAL_ABOVE_ACTION_SHEET_Z_INDEX,
|
||||
onOk: () => emit('toggleActive', row)
|
||||
onOk: () => emit('toggleActive', row),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -126,11 +148,98 @@ function confirmToggleTrade(row: Customer) {
|
||||
cancelText: 'رد',
|
||||
centered: true,
|
||||
zIndex: MODAL_ABOVE_ACTION_SHEET_Z_INDEX,
|
||||
onOk: () => emit('toggleTrade', row)
|
||||
onOk: () => emit('toggleTrade', row),
|
||||
})
|
||||
}
|
||||
|
||||
function lastSeen(row: Customer) {
|
||||
return row.last_seen_at ? toJalali(row.last_seen_at) : '-'
|
||||
}
|
||||
|
||||
async function loadChargeTargets() {
|
||||
try {
|
||||
const res = await getChargeTargets()
|
||||
chargeTargets.value = res?.targets ?? []
|
||||
} catch {
|
||||
chargeTargets.value = []
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [props.visible, props.item?.id] as const,
|
||||
([open]) => {
|
||||
if (open) void loadChargeTargets()
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.customer-mobile-sheet {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__mobile {
|
||||
margin: 0;
|
||||
font-size: 0.8125rem;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__chips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__chip {
|
||||
padding: 0.2rem 0.55rem;
|
||||
border-radius: 9999px;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__chip.is-success {
|
||||
background: rgba(34, 197, 94, 0.14);
|
||||
color: #15803d;
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__chip.is-danger {
|
||||
background: rgba(239, 68, 68, 0.14);
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__section {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__section-title {
|
||||
margin: 0 0 0.35rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
color: var(--admin-text-secondary);
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__charge-btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.customer-mobile-sheet__actions {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .customer-mobile-sheet__chip.is-success {
|
||||
color: #4ade80;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .customer-mobile-sheet__chip.is-danger {
|
||||
color: #f87171;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -138,12 +138,27 @@ defineExpose({
|
||||
margin-bottom: 0.65rem;
|
||||
}
|
||||
|
||||
.wallet-charge-form :deep(.ant-form-item-label > label) {
|
||||
color: var(--admin-text, rgba(0, 0, 0, 0.88));
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper) {
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
height: 2.35rem;
|
||||
line-height: 2.25rem;
|
||||
font-weight: 700;
|
||||
background: var(--admin-bg-muted, #fafafa) !important;
|
||||
border-color: var(--admin-border-strong, #d9d9d9) !important;
|
||||
color: var(--admin-text, rgba(0, 0, 0, 0.88)) !important;
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper:not(:first-child)::before) {
|
||||
background-color: var(--admin-border-strong, #d9d9d9) !important;
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper:hover) {
|
||||
color: var(--admin-text, rgba(0, 0, 0, 0.88)) !important;
|
||||
}
|
||||
|
||||
.wallet-charge-form__radio-icon {
|
||||
@@ -180,29 +195,29 @@ defineExpose({
|
||||
.wallet-charge-form__preview--charge {
|
||||
background: rgba(34, 197, 94, 0.12);
|
||||
border-color: rgba(34, 197, 94, 0.35);
|
||||
color: #86efac;
|
||||
color: #15803d;
|
||||
}
|
||||
|
||||
.wallet-charge-form__preview--charge .wallet-charge-form__preview-sign {
|
||||
background: rgba(34, 197, 94, 0.2);
|
||||
color: #4ade80;
|
||||
color: #16a34a;
|
||||
}
|
||||
|
||||
.wallet-charge-form__preview--discharge {
|
||||
background: rgba(239, 68, 68, 0.12);
|
||||
border-color: rgba(239, 68, 68, 0.35);
|
||||
color: #fca5a5;
|
||||
color: #b91c1c;
|
||||
}
|
||||
|
||||
.wallet-charge-form__preview--discharge .wallet-charge-form__preview-sign {
|
||||
background: rgba(239, 68, 68, 0.2);
|
||||
color: #f87171;
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.wallet-charge-form__hint {
|
||||
margin-top: 0.35rem;
|
||||
font-size: 0.75rem;
|
||||
opacity: 0.75;
|
||||
color: var(--admin-text-secondary, rgba(0, 0, 0, 0.45));
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge) {
|
||||
@@ -211,9 +226,59 @@ defineExpose({
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge::before) {
|
||||
background-color: #15803d !important;
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge) {
|
||||
background: #b91c1c !important;
|
||||
border-color: #b91c1c !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge::before) {
|
||||
background-color: #b91c1c !important;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__preview--charge {
|
||||
background: rgba(34, 197, 94, 0.14);
|
||||
border-color: rgba(34, 197, 94, 0.32);
|
||||
color: #86efac;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__preview--charge .wallet-charge-form__preview-sign {
|
||||
background: rgba(34, 197, 94, 0.22);
|
||||
color: #4ade80;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__preview--discharge {
|
||||
background: rgba(239, 68, 68, 0.14);
|
||||
border-color: rgba(239, 68, 68, 0.32);
|
||||
color: #fca5a5;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__preview--discharge .wallet-charge-form__preview-sign {
|
||||
background: rgba(239, 68, 68, 0.22);
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge) {
|
||||
background: #16a34a !important;
|
||||
border-color: #16a34a !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--charge::before) {
|
||||
background-color: #16a34a !important;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge) {
|
||||
background: #dc2626 !important;
|
||||
border-color: #dc2626 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
:global(html.is-dark) .wallet-charge-form__direction :deep(.ant-radio-button-wrapper-checked.wallet-charge-form__radio--discharge::before) {
|
||||
background-color: #dc2626 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<CustomerWalletBalancePanel
|
||||
v-if="resolvedCustomerId && !targetsLoading"
|
||||
:customer-id="resolvedCustomerId"
|
||||
:charge-targets="targets"
|
||||
:selected-charge-key="selectedTargetKey"
|
||||
compact
|
||||
@select-charge-target="selectedTargetKeyProxy = $event"
|
||||
/>
|
||||
<div v-if="resolvedCustomerId && !targetsLoading" class="wallet-charge-modal-body__assets">
|
||||
<CustomerWalletBalancePanel
|
||||
:customer-id="resolvedCustomerId"
|
||||
:charge-targets="targets"
|
||||
:selected-charge-key="selectedTargetKey"
|
||||
compact
|
||||
@select-charge-target="selectedTargetKeyProxy = $event"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="wallet-charge-modal-body__section">
|
||||
<label class="wallet-charge-modal-body__label">محصول / کیف پول</label>
|
||||
@@ -151,6 +152,13 @@ defineExpose({
|
||||
padding: 0 0.75rem 0.25rem;
|
||||
}
|
||||
|
||||
.wallet-charge-modal-body__assets {
|
||||
margin-bottom: 0.75rem;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.wallet-charge-modal-body__section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -132,10 +132,12 @@
|
||||
:showButton="false"
|
||||
@close="userInfoVisible = false"
|
||||
>
|
||||
<div v-if="isMobile" class="mb-3 text-base font-700">اطلاعات کاربر</div>
|
||||
<a-tabs v-if="userInfo" v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="اطلاعات جامع" tab="اطلاعات جامع">
|
||||
<div class="space-y-2">
|
||||
<div
|
||||
class="grid min-w-0 grid-cols-1 items-start gap-3 lg:grid-cols-[minmax(17rem,21rem)_minmax(0,1fr)] xl:grid-cols-[minmax(18rem,23rem)_minmax(0,1fr)]"
|
||||
>
|
||||
<div class="min-w-0 space-y-2 lg:order-2">
|
||||
<div class="admin-stat-muted rounded-lg w-full flex flex-col gap-3 p-3 md:flex-row md:justify-between">
|
||||
<div>
|
||||
<div class="font-bold">{{ userInfo.name }}</div>
|
||||
@@ -172,7 +174,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-2 gap-2 md:grid-cols-4">
|
||||
<div class="grid min-w-0 grid-cols-2 gap-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
|
||||
<BasicInfoItem title="کد کاربری" :value="userInfo?.id" />
|
||||
<BasicInfoItem title="نوع کاربر" :value="userInfo?.type_str" />
|
||||
<BasicInfoItem
|
||||
@@ -215,7 +217,26 @@
|
||||
</BasicInfoItem>
|
||||
</div>
|
||||
|
||||
<CustomerWalletBalancePanel v-if="userInfo?.id" :customer-id="userInfo.id" class="mt-2" />
|
||||
<CustomerWalletBalancePanel
|
||||
v-if="userInfo?.id && isMobile"
|
||||
:customer-id="userInfo.id"
|
||||
compact
|
||||
:charge-targets="infoChargeTargets"
|
||||
:interactive="false"
|
||||
class="mt-2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<aside
|
||||
v-if="userInfo?.id && !isMobile"
|
||||
class="surface-muted min-w-0 rounded-xl border border-base p-2.5 lg:order-1 lg:sticky lg:top-0"
|
||||
>
|
||||
<CustomerWalletBalancePanel
|
||||
:customer-id="userInfo.id"
|
||||
layout="sidebar"
|
||||
:interactive="false"
|
||||
/>
|
||||
</aside>
|
||||
</div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="لیست سفارشات" tab="لیست سفارشات">
|
||||
@@ -283,6 +304,8 @@ import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
import WalletChargeModal from './components/WalletChargeModal.vue'
|
||||
import CustomerWalletBalancePanel from '@/components/customer/CustomerWalletBalancePanel.vue'
|
||||
import { getChargeTargets } from '@/api/wallet'
|
||||
import type { ChargeTarget } from '@/model/wallet'
|
||||
import { metalLabel } from '@/utils/adminMetalLabels'
|
||||
import type { DashboardHelp } from '@/pages/dashboard/dashboardSectionCopy'
|
||||
import DashboardLabelWithHelp from '@/pages/dashboard/components/DashboardLabelWithHelp.vue'
|
||||
@@ -482,6 +505,7 @@ async function info(val: Customer) {
|
||||
activeKey.value = 'اطلاعات جامع'
|
||||
userInfo.value = cloneDeep(val)
|
||||
userInfoVisible.value = true
|
||||
void loadInfoChargeTargets()
|
||||
await nextTick(() => {
|
||||
loading.value = true
|
||||
refreshFundTable()
|
||||
@@ -551,6 +575,17 @@ onMounted(async () => {
|
||||
//add project modal
|
||||
const addUserVisible = ref<boolean>(false)
|
||||
const userInfoVisible = ref<boolean>(false)
|
||||
const infoChargeTargets = ref<ChargeTarget[]>([])
|
||||
|
||||
async function loadInfoChargeTargets() {
|
||||
if (!isMobile.value) return
|
||||
try {
|
||||
const res = await getChargeTargets()
|
||||
infoChargeTargets.value = res?.targets ?? []
|
||||
} catch {
|
||||
infoChargeTargets.value = []
|
||||
}
|
||||
}
|
||||
const userInfo = ref<Customer>()
|
||||
|
||||
//submit user
|
||||
|
||||
Reference in New Issue
Block a user