From a9922b33efb3d060e67b2df4a1904f0970e92785 Mon Sep 17 00:00:00 2001 From: MojtabaSoumi Date: Thu, 11 Jun 2026 11:02:50 +0330 Subject: [PATCH] 1405/03/21-fix bug in ghatreh --- components.d.ts | 5 +- src/router/index.ts | 20 +-- src/store/cartStore.ts | 59 +++++++- src/views/base/cart/index.vue | 142 ++++++++---------- src/views/base/index.vue | 13 +- .../base/transactions/components/Item.vue | 73 +++++++-- 6 files changed, 202 insertions(+), 110 deletions(-) diff --git a/components.d.ts b/components.d.ts index 62272de..6741a93 100644 --- a/components.d.ts +++ b/components.d.ts @@ -7,6 +7,7 @@ export {} declare module 'vue' { export interface GlobalComponents { + ABadge: typeof import('ant-design-vue/es')['Badge'] AButton: typeof import('ant-design-vue/es')['Button'] AConfigProvider: typeof import('ant-design-vue/es')['ConfigProvider'] ADivider: typeof import('ant-design-vue/es')['Divider'] @@ -15,16 +16,13 @@ declare module 'vue' { AInput: typeof import('ant-design-vue/es')['Input'] AInputPassword: typeof import('ant-design-vue/es')['InputPassword'] AModal: typeof import('ant-design-vue/es')['Modal'] - ARadio: typeof import('ant-design-vue/es')['Radio'] ARadioButton: typeof import('ant-design-vue/es')['RadioButton'] ARadioGroup: typeof import('ant-design-vue/es')['RadioGroup'] ASelect: typeof import('ant-design-vue/es')['Select'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASlider: typeof import('ant-design-vue/es')['Slider'] ASpin: typeof import('ant-design-vue/es')['Spin'] - ASwitch: typeof import('ant-design-vue/es')['Switch'] ATag: typeof import('ant-design-vue/es')['Tag'] - ATextarea: typeof import('ant-design-vue/es')['Textarea'] ATooltip: typeof import('ant-design-vue/es')['Tooltip'] BaseDatePicker: typeof import('./src/components/BasicPacks/BaseDatePicker/src/BaseDatePicker.vue')['default'] Basic: typeof import('./src/components/BasicPacks/BaseDatePicker/src/datePick/demo/basic.vue')['default'] @@ -68,6 +66,5 @@ declare module 'vue' { TransactionSkeleton: typeof import('./src/components/TransactionSkeleton.vue')['default'] VanActionSheet: typeof import('vant/es')['ActionSheet'] VanDialog: typeof import('vant/es')['Dialog'] - VanField: typeof import('vant/es')['Field'] } } diff --git a/src/router/index.ts b/src/router/index.ts index 3bbb0f2..e0327f5 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -20,16 +20,16 @@ const router = createRouter({ redirect: {name: 'buyProduct'}, component: () => import('../views/base/index.vue'), children: [ - { - path: 'home', - name: 'home', - component: () => import('../views/base/home/index.vue') - }, - { - path: 'gold', - name: 'gold', - component: () => import('@/views/base/gold/index.vue') - }, + // { + // path: 'home', + // name: 'home', + // component: () => import('../views/base/home/index.vue') + // }, + // { + // path: 'gold', + // name: 'gold', + // component: () => import('@/views/base/gold/index.vue') + // }, { path: 'buyProduct', name: 'buyProduct', diff --git a/src/store/cartStore.ts b/src/store/cartStore.ts index 1197394..fb2e463 100644 --- a/src/store/cartStore.ts +++ b/src/store/cartStore.ts @@ -2,6 +2,8 @@ import { computed, ref } from 'vue' import { defineStore } from 'pinia' import type { CartItem } from '@/models/cart' import type { Product } from '@/models/products' +import type { Price } from '@/models/home' +import { getProducts } from '@/api/products' const CART_STORAGE_KEY = 'ghatre_cart' @@ -93,6 +95,58 @@ export const useCartStore = defineStore('cart', () => { return cartItems.value.length }) + function syncProductsFromServer(serverProducts: Product[]): number { + const productMap = new Map(serverProducts.map(p => [p.id, p])) + const beforeCount = cartItems.value.length + + cartItems.value = cartItems.value + .filter(item => productMap.has(item.product.id)) + .map(item => ({ + ...item, + product: { ...productMap.get(item.product.id)! } + })) + + if (cartItems.value.length > 0 || beforeCount > 0) { + saveCartToStorage() + } + + return beforeCount - cartItems.value.length + } + + function recalculateCartPrices(lastPrice: Price) { + if (!lastPrice || cartItems.value.length === 0) return + + cartItems.value.forEach((item) => { + const product = item.product + let newPrice = 0 + + if (product.group_type == 'آبشده') { + newPrice = lastPrice.price_last ?? 0 + } else { + newPrice = product.amount * (lastPrice.price_last ?? 0) + } + + product.price = newPrice + product.sellPrice = product.amount * (lastPrice.sell ?? 0) + item.price = newPrice + (product.cash_fee_buy ?? 0) + item.totalPrice = parseInt(String(item.price * item.quantity)) + }) + + saveCartToStorage() + } + + async function refreshCartFromServer(): Promise { + if (cartItems.value.length === 0) return 0 + + try { + const serverProducts: Product[] = await getProducts() + return syncProductsFromServer(serverProducts) + } catch (e) { + console.error('Error refreshing cart from server:', e) + return 0 + } + } + return { cartItems, addToCart, @@ -102,7 +156,10 @@ export const useCartStore = defineStore('cart', () => { totalPrice, itemCount, loadCartFromStorage, - saveCartToStorage + saveCartToStorage, + syncProductsFromServer, + recalculateCartPrices, + refreshCartFromServer } }) diff --git a/src/views/base/cart/index.vue b/src/views/base/cart/index.vue index 2223f15..d9b219a 100644 --- a/src/views/base/cart/index.vue +++ b/src/views/base/cart/index.vue @@ -15,7 +15,11 @@ -
+
+ +
lastPrice.value ?? 0) // Watch for price updates and update cart items watch(lastPrice, () => { - if (lastPrice.value && cartStore.cartItems.length > 0) { - cartStore.cartItems.forEach((item) => { - const product = item.product - let newPrice = 0 - - if (product.group_type == 'آبشده') { - newPrice = lastPrice.value?.price_last ?? 0 - } else { - newPrice = product.amount * (lastPrice.value?.price_last ?? 0) - } - - // Update product price - product.price = newPrice - product.sellPrice = product.amount * (lastPrice.value?.sell ?? 0) - - // Update item price and total price - item.price = newPrice + (product.cash_fee_buy ?? 0) - item.totalPrice = parseInt(item.price * item.quantity) - }) - - // Save updated prices to storage - cartStore.saveCartToStorage() + if (lastPrice.value) { + cartStore.recalculateCartPrices(lastPrice.value) } }, {deep: true, immediate: false}) @@ -313,8 +302,8 @@ async function handleCheckout() { if (cashItemsTotal > 0) { // Ensure wallet info is loaded - if (discountInfo.value.amount>0){ - cashItemsTotal=cashItemsTotal-cashItemsTotal*discountInfo.value.amount + if (discountInfo.value?.amount && discountInfo.value?.amount>0){ + cashItemsTotal=cashItemsTotal-cashItemsTotal*discountInfo.value?.amount } if (!walletStore.walletInfo) { await walletStore.getMyWallet() @@ -370,7 +359,7 @@ async function handleCheckout() { product_id: product.id, method: item.method, number: item.quantity, - discount_code:discountInfo.value.code + discount_code:discountInfo.value?.code } }) @@ -413,40 +402,37 @@ async function initPrice() { try { await getLastPrices() await setIntervalGetLastPrice() - - // Update prices for all cart items - if (lastPrice.value && cartStore.cartItems.length > 0) { - cartStore.cartItems.forEach((item) => { - const product = item.product - let newPrice = 0 - - if (product.group_type == 'آبشده') { - newPrice = lastPrice.value?.price_last ?? 0 - } else { - newPrice = product.amount * (lastPrice.value?.price_last ?? 0) - } - - // Update product price - product.price = newPrice - product.sellPrice = product.amount * (lastPrice.value?.sell ?? 0) - - // Update item price and total price - item.price = newPrice + (product.cash_fee_buy ?? 0) - item.totalPrice = parseInt(item.price * item.quantity) - }) - - // Save updated prices to storage - cartStore.saveCartToStorage() + if (lastPrice.value) { + cartStore.recalculateCartPrices(lastPrice.value) } } catch (e: any) { console.log(e) } } +async function refreshCart() { + const removedCount = await cartStore.refreshCartFromServer() + if (removedCount > 0) { + message.warning(`${removedCount} محصول از سبد خرید حذف شد (دیگر در دسترس نیست)`) + } + if (lastPrice.value) { + cartStore.recalculateCartPrices(lastPrice.value) + } +} + onMounted(async () => { - // Load cart from storage if needed cartStore.loadCartFromStorage() - await initPrice() + loading.value = true + try { + await initPrice() + await refreshCart() + const refreshCartInfo=setInterval(async () => { + await refreshCart() + // await getUpPrice() + }, 10000) + } finally { + loading.value = false + } }) onUnmounted(() => { diff --git a/src/views/base/index.vue b/src/views/base/index.vue index 339fea7..f7b67a0 100644 --- a/src/views/base/index.vue +++ b/src/views/base/index.vue @@ -144,7 +144,9 @@
- + + +
سبد خرید
@@ -180,7 +182,9 @@
خرید محصول
-->
- + + +
سبد خرید
@@ -205,11 +209,14 @@ import BasicButton from '@/components/BasicPacks/BasicButton.vue' import type { Transaction } from '@/models/transaction' import BasicIcon from '@/components/BasicPacks/BasicIcon.vue' import {isToken} from "@/utils"; +import { useCartStore } from '@/store/cartStore' -const currentRoute = computed(() => router.currentRoute.value.name) +const cartStore = useCartStore() const popVisible = ref(false) +const currentRoute = computed(() => router.currentRoute.value.name) + function setNavColor(val: string) { if (currentRoute.value === val) { return 'text-primary' diff --git a/src/views/base/transactions/components/Item.vue b/src/views/base/transactions/components/Item.vue index 404d965..f53cfd8 100644 --- a/src/views/base/transactions/components/Item.vue +++ b/src/views/base/transactions/components/Item.vue @@ -16,7 +16,7 @@ class="text-gray-500 text-xs number-ltr">{{ item.gold }}
{{item.unit}}
-
+
{{ usePriceWithoutType(item.cash?? 0) }}
@@ -25,7 +25,27 @@
-
+ +
قیمت معامله:
@@ -60,20 +80,44 @@ ریال
-
-
قیمت هر گرم طلا حین معامله:
-
-
{{ usePriceWithoutType(item.order?.price?? 0) }}
- ریال + +
موجودی کیف پول:
@@ -156,6 +200,7 @@ interface Prop { const props = withDefaults(defineProps(), {}) const isUp = computed(() => props.item.type === 3 || props.item.type === 1 || props.item.type === 8 || props.item.type === 9) const isGold = computed(() => props.item.type === 1 || props.item.type === 2 || props.item.type === 10) +const isShopProduct = computed(() => !!props.item?.product_id) /*const title = computed(() => { if (isUp.value) { if (isGold.value) {