diff --git a/.cursor/skills/abshode-domain-lookup/learned-notes.md b/.cursor/skills/abshode-domain-lookup/learned-notes.md index 58b8530..1802d4c 100644 --- a/.cursor/skills/abshode-domain-lookup/learned-notes.md +++ b/.cursor/skills/abshode-domain-lookup/learned-notes.md @@ -28,8 +28,10 @@ - 2026-09-09 | ماشین حساب | `useUserPage.ts` + `GoldDayCalculatorModal.vue` | «قیمت روز طلا» → «ماشین حساب»؛ برچسب فلز/واحد از settingsStore (metalTypeLabel + tradeWeightUnit) نه هاردکد طلا/گرم - 2026-10-05 | ????? ????? ??????? | desktop/components/DesktopAuthShell.vue + desktop/styles/desktop-auth.less | ????? stretch? ??? ???????? bleed? tagline ? form-links ?? margin-top:auto ???????? support ??? ???? ?? __top - 2026-10-05 | نمای کلی پروژه | `boursecu/BOURSECU.md` | چهار ریپو: user:3100، admin:3600، server:8000، landing:3200؛ فلز مس از settings +- 2026-10-17 | کلیک کارت محصول دسکتاپ | `products/index.vue` + `DesktopProductCard.vue` + `useProductsPage.ts` | کاتد مس: `isMeltedTradeGroup` → indexGold در مدال؛ رویداد `select`؛ بسته بودن معامله با `shouldBlockStoreTrading` - 2026-10-05 | ???? ????? ????? | DesktopAuthShell.vue + desktop-auth.less | status ???? form-column__foot ??? ???????? body/top ?? margin-top:auto ???????? tagline ??????? foot - 2026-10-05 | ??? ????? ?????? | home/components/AppHeader.vue + guestHome.ts | ???? ????? ???? ?????login? ????????? ????? ?????/??/???? ?? guest ???? - 2026-10-05 | FAB ???????? ????? ?????? | DesktopAuthShell.vue + useDraggableFloatingButton | ??????: ????? ???? ????????? ??????: ???? inline ??? ???? - 2026-10-05 | ?????? ?? ??? ????? | boutUs/components/AboutUsContentPanel.vue | ??? ?????? ???? ??? ???? ?? ????? ???? ?? ??? ?? - 2026-10-06 | بیلد آموزش ENOENT 1.png | EducateContentPanel.vue + assets/img/1.png,2.png,4.png + banner1/2 | فایل‌ها در گیت بودند و از دیسک پاک شده بودند؛ git restore +- 2026-10-17 | باز/بسته خرید فروش محصول | `utils/productTradeOpen.ts` + `gold/index.vue` | `open_buy`/`open_sell`؛ بدون ProductItem هر دو باز diff --git a/src/assets/img/soroushgold-login-logo.png b/src/assets/img/soroushgold-login-logo.png deleted file mode 100644 index 3025dea..0000000 Binary files a/src/assets/img/soroushgold-login-logo.png and /dev/null differ diff --git a/src/store/configStore.ts b/src/store/configStore.ts index 7a7b650..9987d2a 100644 --- a/src/store/configStore.ts +++ b/src/store/configStore.ts @@ -14,7 +14,6 @@ export const useConfigStore = defineStore('config', () => { async function getConfigData() { config.value = window.__APP_CONFIG__?.user - console.log(config.value) } return { diff --git a/src/utils/productTradeOpen.ts b/src/utils/productTradeOpen.ts new file mode 100644 index 0000000..7e5699f --- /dev/null +++ b/src/utils/productTradeOpen.ts @@ -0,0 +1,21 @@ +import type { Product } from '@/models/products' + +type TradeOpenProduct = Pick | null | undefined + +function asBool(value: boolean | number | null | undefined) { + return value === true || Number(value) === 1 +} + +export function isProductBuyOpen(product: TradeOpenProduct) { + if (!product) return true + return asBool(product.open_buy) +} + +export function isProductSellOpen(product: TradeOpenProduct) { + if (!product) return true + return asBool(product.open_sell) +} + +export function isProductTradeOpen(product: TradeOpenProduct, isBuy: boolean) { + return isBuy ? isProductBuyOpen(product) : isProductSellOpen(product) +} diff --git a/src/views/base/gold/index.vue b/src/views/base/gold/index.vue index e01adc2..77f0221 100644 --- a/src/views/base/gold/index.vue +++ b/src/views/base/gold/index.vue @@ -308,6 +308,7 @@ import { productMaxOrderCash, productMinOrderCash } from '@/utils/productOrderLimit' +import { isProductBuyOpen, isProductSellOpen } from '@/utils/productTradeOpen' const infoVisible = ref(false) const walletStore = useWalletStore() @@ -689,6 +690,8 @@ function useStyle() { function setIsBuy(val: boolean) { + if (val && !isProductBuyOpen(props?.ProductItem)) return + if (!val && !isProductSellOpen(props?.ProductItem)) return isBuy.value = val form.value.goldValue = undefined form.value.goldCash = undefined diff --git a/src/views/base/products/composables/useProductsPage.ts b/src/views/base/products/composables/useProductsPage.ts index bb4cc22..b08cba1 100644 --- a/src/views/base/products/composables/useProductsPage.ts +++ b/src/views/base/products/composables/useProductsPage.ts @@ -1,5 +1,6 @@ import { inject, + nextTick, onMounted, onUnmounted, provide, @@ -8,12 +9,13 @@ import { computed, type InjectionKey, } from 'vue' +import { message } from 'ant-design-vue' import router from '@/router' import { loading } from '@/utils' import type { Product } from '@/models/products' import { cloneDeep } from 'lodash' import { isProductPriceInactive } from '@/utils/productPrice' -import { getStoreClosedHint, shouldBlockStoreTrading } from '@/utils/storeHours' +import { getStoreClosedHint, resolveStoreClosedNotice, shouldBlockStoreTrading } from '@/utils/storeHours' import { useUserStore } from '@/store/userStore' import { lastPrice } from '@/utils/price' import { @@ -61,10 +63,21 @@ export function useProductsPageProvider() { getStoreClosedHint(userStore.getValueByKey('closed_message')), ) + function openStoreClosedModal() { + showFilter.value = false + if (isAfterCloseTime.value) { + isAfterCloseTime.value = false + nextTick(() => { + isAfterCloseTime.value = true + }) + return + } + isAfterCloseTime.value = true + } + function syncStoreClosedState() { if (shouldBlockStoreTrading()) { - showFilter.value = false - isAfterCloseTime.value = true + openStoreClosedModal() } } @@ -78,8 +91,8 @@ export function useProductsPageProvider() { if (!item?.show) return if (shouldBlockStoreTrading()) { - showFilter.value = false - isAfterCloseTime.value = true + message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message'))) + openStoreClosedModal() return } @@ -100,8 +113,8 @@ export function useProductsPageProvider() { watch(showFilter, (open) => { if (open && shouldBlockStoreTrading()) { - showFilter.value = false - isAfterCloseTime.value = true + message.warning(resolveStoreClosedNotice(userStore.getValueByKey('closed_message'))) + openStoreClosedModal() return } if (!open) { diff --git a/src/views/base/products/desktop/DesktopProductsView.vue b/src/views/base/products/desktop/DesktopProductsView.vue index cfdfb6c..5c5830b 100644 --- a/src/views/base/products/desktop/DesktopProductsView.vue +++ b/src/views/base/products/desktop/DesktopProductsView.vue @@ -43,7 +43,7 @@ :product="item" :inactive="isProductPriceInactive(item)" :locked="storeClosed" - @click="clickProduct(item)" + @select="clickProduct(item)" />
محصولی برای نمایش وجود ندارد. @@ -58,7 +58,7 @@ import DesktopPageTopbar from '@/layouts/components/DesktopPageTopbar.vue' import DesktopProductCard from './components/DesktopProductCard.vue' import { useProductsPageContext } from '../composables/useProductsPage' -import { isStoreClosed, STORE_CLOSED_TITLE } from '@/utils/storeHours' +import { isStoreClosed, shouldBlockStoreTrading, STORE_CLOSED_TITLE } from '@/utils/storeHours' import { computed } from 'vue' const { @@ -72,7 +72,7 @@ const { storeClosedMessage, } = useProductsPageContext() -const storeClosed = computed(() => isStoreClosed()) +const storeClosed = computed(() => isStoreClosed() || shouldBlockStoreTrading()) diff --git a/src/views/base/products/desktop/components/DesktopProductCard.vue b/src/views/base/products/desktop/components/DesktopProductCard.vue index 77576aa..1684d93 100644 --- a/src/views/base/products/desktop/components/DesktopProductCard.vue +++ b/src/views/base/products/desktop/components/DesktopProductCard.vue @@ -7,7 +7,7 @@ 'dproducts-card--locked': locked, }" :disabled="!isClickable" - @click="$emit('click')" + @click="handleClick" >
@@ -48,12 +48,17 @@ const props = withDefaults( { inactive: false, locked: false }, ) -defineEmits<{ - click: [] +const emit = defineEmits<{ + select: [] }>() const isClickable = computed(() => props.product.show && !props.inactive && !props.locked) +function handleClick() { + if (!isClickable.value) return + emit('select') +} + const displayImage = computed(() => getProductDisplayImage(props.product)) const price = computed(() => getProductBuyPrice(props.product)) diff --git a/src/views/base/products/index.vue b/src/views/base/products/index.vue index 7096fe3..7e09c13 100644 --- a/src/views/base/products/index.vue +++ b/src/views/base/products/index.vue @@ -12,7 +12,7 @@
@@ -22,14 +22,14 @@
@@ -73,7 +73,12 @@ import DealProduct from '@/views/base/products/components/DealProduct.vue' import BasicModal from '@/components/BasicPacks/BasicModal.vue' import ResponsiveViewPair from '@/layouts/components/ResponsiveViewPair.vue' import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout' -import { usesQuantityTrade } from '@/utils/productCategories' +import type { Product } from '@/models/products' +import { isMeltedTradeGroup, usesQuantityTrade } from '@/utils/productCategories' + +function usesMeltedOrQuantityTrade(product?: Product) { + return usesQuantityTrade(product) || isMeltedTradeGroup(product?.group_type) +} import { STORE_CLOSED_TITLE } from '@/utils/storeHours' import { useProductsPageProvider } from './composables/useProductsPage' import MobileProductsView from './mobile/MobileProductsView.vue' diff --git a/src/views/login/assets/img/login-copper-hero.jpg b/src/views/login/assets/img/login-copper-hero.jpg deleted file mode 100644 index a338d62..0000000 Binary files a/src/views/login/assets/img/login-copper-hero.jpg and /dev/null differ diff --git a/src/views/login/assets/img/login-copper-hero.webp b/src/views/login/assets/img/login-copper-hero.webp new file mode 100644 index 0000000..65f3dd1 Binary files /dev/null and b/src/views/login/assets/img/login-copper-hero.webp differ diff --git a/src/views/login/desktop/components/DesktopAuthShell.vue b/src/views/login/desktop/components/DesktopAuthShell.vue index 8f99ef2..29b2bc2 100644 --- a/src/views/login/desktop/components/DesktopAuthShell.vue +++ b/src/views/login/desktop/components/DesktopAuthShell.vue @@ -106,7 +106,7 @@ import router from '@/router' import BasicIcon from '@/components/BasicPacks/BasicIcon.vue' import { getProjectLoginLogo } from '@/utils/config' import { useDraggableFloatingButton } from '@/utils/useDraggableFloatingButton' -import copperProducts from '../../assets/img/login-copper-hero.jpg' +import copperProducts from '../../assets/img/login-copper-hero.webp' const pageLogo = getProjectLoginLogo()