This commit is contained in:
2026-06-14 22:00:59 +03:30
parent dad6b0b82c
commit aec64397aa
6 changed files with 91 additions and 21 deletions
+47 -3
View File
@@ -7,6 +7,14 @@ export interface StoreTradingHours {
closePriceEnabled: boolean closePriceEnabled: boolean
} }
export interface EffectiveTradingHours {
start: string
end: string
enforced: boolean
}
let productTradingHours: { start: string; end: string } | null = null
function parseTimeToSeconds(time: string): number { function parseTimeToSeconds(time: string): number {
const parts = time.trim().split(':').map(Number) const parts = time.trim().split(':').map(Number)
const [hours = 0, minutes = 0, seconds = 0] = parts const [hours = 0, minutes = 0, seconds = 0] = parts
@@ -24,6 +32,12 @@ export function formatTradingTimeDisplay(time: string): string {
return time return time
} }
export function setProductTradingHours(start?: string | null, end?: string | null) {
if (start && end) {
productTradingHours = { start, end }
}
}
export function getStoreTradingHours(): StoreTradingHours { export function getStoreTradingHours(): StoreTradingHours {
const settings = useSettingsStore() const settings = useSettingsStore()
const closeRaw = settings.getSettingByKey('close_price') const closeRaw = settings.getSettingByKey('close_price')
@@ -39,9 +53,34 @@ export function getStoreTradingHours(): StoreTradingHours {
} }
} }
export function getEffectiveTradingHours(): EffectiveTradingHours {
const settings = getStoreTradingHours()
if (settings.closePriceEnabled) {
return {
start: settings.start,
end: settings.end,
enforced: true,
}
}
if (productTradingHours?.start && productTradingHours?.end) {
return {
start: productTradingHours.start,
end: productTradingHours.end,
enforced: true,
}
}
return {
start: settings.start,
end: settings.end,
enforced: false,
}
}
export function isStoreClosedBySchedule(now = new Date()): boolean { export function isStoreClosedBySchedule(now = new Date()): boolean {
const { start, end, closePriceEnabled } = getStoreTradingHours() const { start, end, enforced } = getEffectiveTradingHours()
if (!closePriceEnabled) { if (!enforced) {
return false return false
} }
@@ -60,4 +99,9 @@ export function isStoreClosed(): boolean {
return isStoreClosedBySchedule() return isStoreClosedBySchedule()
} }
export const STORE_CLOSED_MESSAGE = 'فروشگاه در حال حاضر بسته است.' export function getStoreClosedMessage(): string {
const { start, end } = getEffectiveTradingHours()
const open = formatTradingTimeDisplay(start)
const close = formatTradingTimeDisplay(end)
return `فروشگاه در حال حاضر بسته است. ساعت کاری از ${open} تا ${close} می‌باشد.`
}
+3 -3
View File
@@ -239,7 +239,7 @@ import {useConfigStore} from "@/store/configStore";
import { calcFeeInGrams } from '@/utils/serviceFee' import { calcFeeInGrams } from '@/utils/serviceFee'
import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod' import { formatCashWalletBalanceText, formatGoldWalletBalanceText } from '@/utils/productDealMethod'
import { getCashWalletBalance } from '@/utils/productAssets' import { getCashWalletBalance } from '@/utils/productAssets'
import { isStoreClosed, STORE_CLOSED_MESSAGE } from '@/utils/storeHours' import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
const infoVisible = ref(false) const infoVisible = ref(false)
const walletStore = useWalletStore() const walletStore = useWalletStore()
@@ -643,7 +643,7 @@ async function initPrice() {
function okConfirm() { function okConfirm() {
if (isStoreClosed()) { if (isStoreClosed()) {
message.warning(STORE_CLOSED_MESSAGE) message.warning(getStoreClosedMessage())
return return
} }
confirmAction.value = true confirmAction.value = true
@@ -651,7 +651,7 @@ function okConfirm() {
async function ok() { async function ok() {
if (isStoreClosed()) { if (isStoreClosed()) {
message.warning(STORE_CLOSED_MESSAGE) message.warning(getStoreClosedMessage())
return return
} }
try { try {
+3 -3
View File
@@ -236,7 +236,7 @@ import type { Product } from '@/models/products'
import { useFundUserStore } from '@/store/fundStore' import { useFundUserStore } from '@/store/fundStore'
import {useConfigStore} from "@/store/configStore"; import {useConfigStore} from "@/store/configStore";
import { calcFeeInGrams, loadServiceFeeFromSettings } from '@/utils/serviceFee' import { calcFeeInGrams, loadServiceFeeFromSettings } from '@/utils/serviceFee'
import { isStoreClosed, STORE_CLOSED_MESSAGE } from '@/utils/storeHours' import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod' import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets' import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
import { useWalletAssets } from '@/composables/useWalletAssets' import { useWalletAssets } from '@/composables/useWalletAssets'
@@ -636,7 +636,7 @@ async function initPrice() {
function okConfirm() { function okConfirm() {
if (isStoreClosed()) { if (isStoreClosed()) {
message.warning(STORE_CLOSED_MESSAGE) message.warning(getStoreClosedMessage())
return return
} }
if (cashValidationMessage.value) { if (cashValidationMessage.value) {
@@ -648,7 +648,7 @@ function okConfirm() {
async function ok() { async function ok() {
if (isStoreClosed()) { if (isStoreClosed()) {
message.warning(STORE_CLOSED_MESSAGE) message.warning(getStoreClosedMessage())
return return
} }
try { try {
+7 -4
View File
@@ -38,7 +38,7 @@
<AssetsSection v-else @openGoldModal="openGoldModal" @openRialModal="openRialModal"/> <AssetsSection v-else @openGoldModal="openGoldModal" @openRialModal="openRialModal"/>
<!-- پیام بسته بودن بازار --> <!-- پیام بسته بودن بازار -->
<MarketClosedMessage v-if="showClosedMessage" :message="closedMessage"/> <MarketClosedMessage v-if="showClosedMessage" :message="marketClosedText"/>
<!-- قیمت فعلی --> <!-- قیمت فعلی -->
<CurrentPrice/> <CurrentPrice/>
@@ -89,6 +89,7 @@ import {useConfigStore} from '@/store/configStore'
import {useFundUserStore} from '@/store/fundStore' import {useFundUserStore} from '@/store/fundStore'
import {usePriceWithoutType} from '../../../utils/usePrice' import {usePriceWithoutType} from '../../../utils/usePrice'
import {getLastPrices, lastPrice, price, startLastPricePolling, stopLastPricePolling} from '@/utils/price' import {getLastPrices, lastPrice, price, startLastPricePolling, stopLastPricePolling} from '@/utils/price'
import { getStoreClosedMessage, isStoreClosed } from '@/utils/storeHours'
import {getConstByKey} from '@/api/const' import {getConstByKey} from '@/api/const'
import {message, Modal} from 'ant-design-vue' import {message, Modal} from 'ant-design-vue'
@@ -126,9 +127,11 @@ const { assetsSummary, loadWalletAssets } = useWalletAssets()
// Config // Config
const isGaroosi = computed(() => configStore.config.name === 'garoosi') const isGaroosi = computed(() => configStore.config.name === 'garoosi')
const closedMessage = computed(() => userStore.getValueByKey('closed_message')) const closedMessage = computed(() => userStore.getValueByKey('closed_message'))
const showClosedMessage = computed(() => const marketClosedText = computed(() => {
closedMessage.value && if (!isStoreClosed()) return ''
lastPrice?.value?.price_last === 0) return closedMessage.value || getStoreClosedMessage()
})
const showClosedMessage = computed(() => !!marketClosedText.value)
// State // State
@@ -297,7 +297,7 @@ import {
} from '@/utils/productOrderLimit' } from '@/utils/productOrderLimit'
import { useWalletAssets } from '@/composables/useWalletAssets' import { useWalletAssets } from '@/composables/useWalletAssets'
import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets' import { formatProductWalletBalanceText, getCashWalletBalance, getProductInventoryQuantity } from '@/utils/productAssets'
import { isStoreClosed, STORE_CLOSED_MESSAGE } from '@/utils/storeHours' import { isStoreClosed, getStoreClosedMessage } from '@/utils/storeHours'
const typeDeal = computed(() => getProductDealMethodOptions(props?.ProductItem?.group_type, isBuy.value)) const typeDeal = computed(() => getProductDealMethodOptions(props?.ProductItem?.group_type, isBuy.value))
@@ -798,7 +798,7 @@ async function initPrice() {
function okConfirm() { function okConfirm() {
if (isStoreClosed()) { if (isStoreClosed()) {
message.warning(STORE_CLOSED_MESSAGE) message.warning(getStoreClosedMessage())
return return
} }
confirmAction.value = true confirmAction.value = true
@@ -807,7 +807,7 @@ function okConfirm() {
async function ok() { async function ok() {
if (isStoreClosed()) { if (isStoreClosed()) {
message.warning(STORE_CLOSED_MESSAGE) message.warning(getStoreClosedMessage())
return return
} }
try { try {
+28 -5
View File
@@ -13,6 +13,15 @@
</ARadioGroup> </ARadioGroup>
</div> </div>
<div
v-if="storeIsClosed"
class="mx-5 mb-3 rounded-lg bg-red-50 px-3 py-4 text-center text-red-600"
>
<div class="font-bold">مشتریان گرامی</div>
<p class="mt-2 leading-relaxed">{{ storeClosedMessage }}</p>
<p class="mt-2">از همراهی و اعتماد شما سپاسگزاریم.🤍</p>
</div>
<div class="mx-5 pb-30 pt-2" style="color: #1b2b07"> <div class="mx-5 pb-30 pt-2" style="color: #1b2b07">
<div class="mt-3" v-for="item in items" :key="item.id"> <div class="mt-3" v-for="item in items" :key="item.id">
<ProductItem <ProductItem
@@ -70,8 +79,7 @@
<div class="text-center"> <div class="text-center">
<div class="font-bold text-red-600">مشتریان گرامی</div> <div class="font-bold text-red-600">مشتریان گرامی</div>
<div class="mt-2 leading-relaxed"> <div class="mt-2 leading-relaxed">
<p>فروشگاه در حال حاضر بسته است.</p> <p>{{ storeClosedMessage }}</p>
<p>ساعت کاری فروشگاه از {{ openTime }} تا {{ closeTime }} می‌باشد.</p>
<p>از همراهی و اعتماد شما سپاسگزاریم.🤍</p> <p>از همراهی و اعتماد شما سپاسگزاریم.🤍</p>
</div> </div>
</div> </div>
@@ -106,10 +114,12 @@ import { loadProductCategoryTabNames } from '@/utils/categoryTabs'
import { getLastPrices, lastPrice, startLastPricePolling, stopLastPricePolling } from '@/utils/price' import { getLastPrices, lastPrice, startLastPricePolling, stopLastPricePolling } from '@/utils/price'
import { import {
formatTradingTimeDisplay, formatTradingTimeDisplay,
getStoreTradingHours, getEffectiveTradingHours,
getStoreClosedMessage,
isStoreClosed, isStoreClosed,
STORE_CLOSED_MESSAGE setProductTradingHours
} from '@/utils/storeHours' } from '@/utils/storeHours'
import { useSettingsStore } from '@/store/settingsStore'
const activekey = ref('طلا' ||'آبشده') const activekey = ref('طلا' ||'آبشده')
const showFilter = ref(false) const showFilter = ref(false)
@@ -119,6 +129,8 @@ const closeTime = ref<string>('')
const openTime = ref<string>('') const openTime = ref<string>('')
const isAfterCloseTime = ref<boolean>(false) const isAfterCloseTime = ref<boolean>(false)
const isProductInactive = ref<boolean>(false) const isProductInactive = ref<boolean>(false)
const storeIsClosed = computed(() => isStoreClosed())
const storeClosedMessage = computed(() => getStoreClosedMessage())
watch([openTime, closeTime], () => { watch([openTime, closeTime], () => {
syncStoreClosedState() syncStoreClosedState()
@@ -178,6 +190,7 @@ const firstItems = ref<Product[]>()
const items = ref<Product[]>() const items = ref<Product[]>()
const typeItems = ref<string[]>([]) const typeItems = ref<string[]>([])
let productListInterval: ReturnType<typeof setInterval> | undefined let productListInterval: ReturnType<typeof setInterval> | undefined
let storeHoursInterval: ReturnType<typeof setInterval> | undefined
async function loadCategoryTabs() { async function loadCategoryTabs() {
try { try {
@@ -234,11 +247,16 @@ watch(() => lastPrice.value?.closed, syncStoreClosedState)
onMounted(async () => { onMounted(async () => {
try { try {
loading.value = true loading.value = true
await useSettingsStore().fetchSettings()
await getLastPrices() await getLastPrices()
startLastPricePolling() startLastPricePolling()
items.value = await getProducts() items.value = await getProducts()
const hours = getStoreTradingHours() if (items.value?.length) {
setProductTradingHours(items.value[0].auto_open_at, items.value[0].auto_close_at)
}
const hours = getEffectiveTradingHours()
openTime.value = formatTradingTimeDisplay(hours.start) openTime.value = formatTradingTimeDisplay(hours.start)
closeTime.value = formatTradingTimeDisplay(hours.end) closeTime.value = formatTradingTimeDisplay(hours.end)
syncStoreClosedState() syncStoreClosedState()
@@ -247,6 +265,7 @@ onMounted(async () => {
firstItems.value = items.value firstItems.value = items.value
await loadServiceFeeFromSettings() await loadServiceFeeFromSettings()
productListInterval = setInterval(refreshProducts, 10000) productListInterval = setInterval(refreshProducts, 10000)
storeHoursInterval = setInterval(syncStoreClosedState, 30000)
} catch (e) { } catch (e) {
console.log(e) console.log(e)
@@ -274,6 +293,10 @@ onUnmounted(() => {
clearInterval(productListInterval) clearInterval(productListInterval)
productListInterval = undefined productListInterval = undefined
} }
if (storeHoursInterval) {
clearInterval(storeHoursInterval)
storeHoursInterval = undefined
}
}) })
// watch(lastPrice, async () => { // watch(lastPrice, async () => {
// // console.log(items); // // console.log(items);