2026-05-14 13:44:43 +03:30
|
|
|
<template>
|
2026-06-23 16:02:41 +03:30
|
|
|
<div
|
|
|
|
|
class="w-full relative mt-2 rounded-lg py-3 flex flex-col justify-center home_appear_fade_in transition-colors duration-300"
|
|
|
|
|
:class="containerClass"
|
|
|
|
|
>
|
|
|
|
|
<template v-if="isBoursecu && showStoreClosed">
|
|
|
|
|
<div class="boursecu-closed-box">
|
|
|
|
|
<div class="boursecu-closed-box__icon-wrap">
|
|
|
|
|
<Icon icon="vuesax-linear:lock" size="22" color="#ffffff" />
|
2026-05-14 13:44:43 +03:30
|
|
|
</div>
|
2026-06-23 16:02:41 +03:30
|
|
|
<div class="boursecu-closed-box__title">فروشگاه بسته است</div>
|
|
|
|
|
<div class="boursecu-closed-box__hint">{{ storeClosedHint }}</div>
|
2026-05-14 13:44:43 +03:30
|
|
|
</div>
|
2026-06-23 16:02:41 +03:30
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template v-else>
|
|
|
|
|
<div class="price-label" :class="isBoursecu ? 'price-label--boursecu' : 'text-gray-600 text-[12px] ml-2 w-full text-center'">
|
|
|
|
|
{{ priceLabel }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="w-full items-center flex justify-center">
|
|
|
|
|
<div v-if="price" class="flex gap-1 text-xs items-center">
|
|
|
|
|
<div
|
|
|
|
|
v-if="percentChange !== 0"
|
|
|
|
|
class="price-change-badge"
|
|
|
|
|
:class="percentChange > 0 ? 'price-change-badge--up' : 'price-change-badge--down'"
|
|
|
|
|
>
|
|
|
|
|
<Icon
|
|
|
|
|
:key="displayGoldVal"
|
|
|
|
|
:size="15"
|
|
|
|
|
:icon="percentChange > 0 ? 'vuesax-linear:send' : 'vuesax-linear:received'"
|
|
|
|
|
:color="percentChange > 0 ? 'green-600' : 'red-600'"
|
|
|
|
|
/>
|
|
|
|
|
<span class="price-change-badge__value">{{ formatSignedPercentChange(percentChange) }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<Vue3Odometer
|
|
|
|
|
:value="displayGoldVal"
|
|
|
|
|
class="o-text !text-xl font-bold"
|
|
|
|
|
:class="isBoursecu ? 'price-odometer--boursecu' : ''"
|
|
|
|
|
style="font-family: iran-sans; direction: ltr"
|
|
|
|
|
/>
|
|
|
|
|
<span :class="isBoursecu ? 'price-unit--boursecu' : ''">ریال</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
2026-05-14 13:44:43 +03:30
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-06-16 19:47:59 +03:30
|
|
|
import { computed } from 'vue'
|
2026-05-14 13:44:43 +03:30
|
|
|
import Icon from '@/components/BasicPacks/BasicIcon.vue'
|
|
|
|
|
import { useConfigStore } from '@/store/configStore'
|
2026-06-23 16:02:41 +03:30
|
|
|
import { useUserStore } from '@/store/userStore'
|
|
|
|
|
import { isBoursecuProject } from '@/utils/config'
|
2026-06-06 15:48:27 +03:30
|
|
|
import { getTradeBuyPrice, lastPrice, percentPriceChanged, price } from '@/utils/price'
|
2026-06-23 16:02:41 +03:30
|
|
|
import { getStoreClosedMessage, isStoreClosed } from '@/utils/storeHours'
|
2026-05-14 13:44:43 +03:30
|
|
|
import Vue3Odometer from 'vue3-odometer'
|
|
|
|
|
import 'odometer/themes/odometer-theme-default.css'
|
2026-06-16 19:47:59 +03:30
|
|
|
import { formatSignedPercentChange } from '@/utils/usePrice'
|
2026-05-14 13:44:43 +03:30
|
|
|
|
|
|
|
|
const config = useConfigStore()
|
2026-06-23 16:02:41 +03:30
|
|
|
const userStore = useUserStore()
|
|
|
|
|
const isBoursecu = isBoursecuProject()
|
|
|
|
|
|
|
|
|
|
const priceLabel = computed(() =>
|
|
|
|
|
isBoursecu ? 'قیمت لحظهای کاتد مس' : `قیمت خرید از ${config.config.name_fa}`
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const showStoreClosed = computed(() => {
|
|
|
|
|
if (isBoursecu) {
|
|
|
|
|
return isStoreClosed()
|
|
|
|
|
}
|
|
|
|
|
return lastPrice?.value?.goldir === 0 && getTradeBuyPrice(lastPrice.value) === 0
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const storeClosedHint = computed(() => {
|
|
|
|
|
const custom = userStore.getValueByKey('closed_message')
|
|
|
|
|
if (typeof custom === 'string' && custom.trim()) {
|
|
|
|
|
return custom.replace(/<[^>]*>/g, '').trim()
|
|
|
|
|
}
|
|
|
|
|
return getStoreClosedMessage()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const containerClass = computed(() => {
|
|
|
|
|
if (!isBoursecu) {
|
|
|
|
|
return 'border-gray-200 border-1'
|
|
|
|
|
}
|
|
|
|
|
if (showStoreClosed.value) {
|
|
|
|
|
return 'boursecu-price-box boursecu-price-box--closed'
|
|
|
|
|
}
|
|
|
|
|
return 'boursecu-price-box boursecu-price-box--open'
|
|
|
|
|
})
|
2026-05-14 13:44:43 +03:30
|
|
|
|
|
|
|
|
const percentChange = computed(() => {
|
2026-06-06 15:48:27 +03:30
|
|
|
if (!getTradeBuyPrice(lastPrice.value)) return 0
|
2026-05-14 13:44:43 +03:30
|
|
|
return percentPriceChanged()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const displayGoldVal = computed(() => {
|
2026-06-23 16:02:41 +03:30
|
|
|
if (showStoreClosed.value) return 0
|
2026-06-06 15:48:27 +03:30
|
|
|
return getTradeBuyPrice(lastPrice.value)
|
2026-05-14 13:44:43 +03:30
|
|
|
})
|
2026-06-23 16:02:41 +03:30
|
|
|
|
|
|
|
|
void price
|
2026-06-16 19:47:59 +03:30
|
|
|
</script>
|
2026-05-14 13:44:43 +03:30
|
|
|
|
2026-06-16 19:47:59 +03:30
|
|
|
<style scoped>
|
2026-06-23 16:02:41 +03:30
|
|
|
.boursecu-price-box {
|
|
|
|
|
border: none;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.boursecu-price-box--open {
|
|
|
|
|
background: linear-gradient(135deg, #c98a4a 0%, #a86528 100%);
|
|
|
|
|
box-shadow: 0 4px 14px rgba(168, 101, 40, 0.28);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.boursecu-price-box--closed {
|
|
|
|
|
background: linear-gradient(135deg, #4a5568 0%, #2d3748 100%);
|
|
|
|
|
box-shadow: 0 4px 14px rgba(45, 55, 72, 0.22);
|
|
|
|
|
min-height: 88px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-label--boursecu {
|
|
|
|
|
color: rgba(255, 255, 255, 0.92);
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
width: 100%;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-odometer--boursecu {
|
|
|
|
|
color: #ffffff !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-unit--boursecu {
|
|
|
|
|
color: rgba(255, 255, 255, 0.85);
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.boursecu-closed-box {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
gap: 6px;
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.boursecu-closed-box__icon-wrap {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
width: 40px;
|
|
|
|
|
height: 40px;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background: rgba(255, 255, 255, 0.12);
|
|
|
|
|
margin-bottom: 2px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.boursecu-closed-box__title {
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.boursecu-closed-box__hint {
|
|
|
|
|
color: rgba(255, 255, 255, 0.78);
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
max-width: 280px;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 19:47:59 +03:30
|
|
|
.price-change-badge {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 0.35rem;
|
|
|
|
|
padding: 0.2rem 0.65rem;
|
|
|
|
|
border-radius: 0.5rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-change-badge--up {
|
|
|
|
|
background: #dcfce7;
|
|
|
|
|
color: #16a34a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-change-badge--down {
|
|
|
|
|
background: #fee2e2;
|
|
|
|
|
color: #dc2626;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.price-change-badge__value {
|
|
|
|
|
direction: ltr;
|
|
|
|
|
unicode-bidi: isolate;
|
|
|
|
|
font-variant-numeric: tabular-nums;
|
|
|
|
|
letter-spacing: 0.01em;
|
|
|
|
|
}
|
|
|
|
|
</style>
|