some trigger handled

This commit is contained in:
2026-06-10 18:40:29 +03:30
parent 5b525bd2c7
commit 84db7b013d
13 changed files with 264 additions and 117 deletions
+2 -9
View File
@@ -204,7 +204,7 @@
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import img1 from '@/assets/img/home_ly2.svg'
import { usePrice, usePriceWithoutType } from '@/utils/usePrice'
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
@@ -232,7 +232,7 @@ import type { Transaction } from '@/models/transaction'
import type { TableEngineInput, TableOutput } from '@/models/table'
import { useInfiniteScroll } from '@vueuse/core'
import { getTransactionTable } from '@/api/transaction'
import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice, setIntervalGetAllPrice, stopPriceInterval } from '@/utils/price'
import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@/utils/price'
import type { Product } from '@/models/products'
import { useFundUserStore } from '@/store/fundStore'
import {useConfigStore} from "@/store/configStore";
@@ -434,10 +434,6 @@ onMounted(async () => {
await initBuyTable()*/
})
onUnmounted(() => {
stopPriceInterval()
})
const form = ref<Gold>({
goldCash: undefined,
goldValue: undefined,
@@ -630,15 +626,12 @@ const goldPriceValue = computed(() => {
async function initPrice() {
try {
// chartLoading.value = true
await getLastPrices()
await setIntervalGetAllPrice()
loading.value = true
} catch (e) {
console.log(e)
} finally {
loading.value = false
// chartLoading.value = false
}
}
+2 -2
View File
@@ -82,13 +82,13 @@ import { usePriceWithoutType } from '@/utils/usePrice'
import { useConfigStore } from '@/store/configStore'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
import { resolveSummaryMetalWeight } from '@/utils/productAssets'
import { resolveSummaryMetalWeight, fundPageInventoryCards } from '@/utils/productAssets'
const nameProject = useConfigStore().config.name
const { assetsSummary, loadWalletAssets } = useWalletAssets()
const meta = computed(() => assetsSummary.value?.meta)
const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? [])
const inventoryCards = computed(() => fundPageInventoryCards(assetsSummary.value?.inventory_cards ?? []))
const metalTotals = computed(() => assetsSummary.value?.metal_totals ?? [])
const primaryMetalTotal = computed(() => metalTotals.value[0])
const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
+29 -18
View File
@@ -64,7 +64,7 @@
<!-- {{walletStore?.walletInfo?.gold}}-->
<Transition mode="out-in" name="fade">
<div v-if="!isBuy" class="font-bold text-xs">
<div>{{ formatGoldWalletBalanceText(walletStore?.walletInfo?.gold ?? 0, props?.ProductItem?.group_type) }}</div>
<div>{{ productWalletBalanceText }}</div>
<!-- <div v-if="walletStore?.walletInfo?.gold_block !== 0">
{{ `موجودی قابل برداشت طلا: ${walletStore?.walletInfo?.gold_block ?? 0} گرم` }}
</div>-->
@@ -116,10 +116,10 @@
<div v-else>{{ !isBuy ? 'فروش' : 'خرید' }}</div>
</div>
</BasicButton>
<div v-if="!isBuy && form.goldValue > walletStore?.walletInfo?.gold"
<div v-if="!isBuy && form.goldValue > productWalletBalance"
class="text-red-700 text-xs font-bold mt-2">
مقدار گرم طلای وارد شده جهت فروش ({{ form.goldValue }}گرم) بیشتر از مقدار موجودی شما
({{ walletStore?.walletInfo?.gold }}گرم) می باشد.
مقدار {{ weightUnit }} وارد شده جهت فروش ({{ form.goldValue }}{{ weightUnit }}) بیشتر از مقدار موجودی شما
({{ productWalletBalance }}{{ weightUnit }}) می باشد.
</div>
<!-- <div>{{form?.goldValue? true: false}}</div>-->
<div v-if="isBuy ? (form?.goldCash > walletStore?.walletInfo?.cash) : false"
@@ -202,7 +202,7 @@
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import img1 from '@/assets/img/home_ly2.svg'
import { usePrice, usePriceWithoutType } from '@/utils/usePrice'
import BasicInput from '@/components/BasicPacks/BasicInput.vue'
@@ -231,12 +231,14 @@ import type { TableEngineInput, TableOutput } from '@/models/table'
import { useInfiniteScroll } from '@vueuse/core'
import { getTransactionTable } from '@/api/transaction'
import { getProductBuyPrice, getProductSellPrice } from '@/utils/productPrice'
import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice, setIntervalGetAllPrice, stopPriceInterval } from '@/utils/price'
import { getLastPrices, getTradeBuyPrice, getTradeSellPrice, lastPrice } from '@/utils/price'
import type { Product } from '@/models/products'
import { useFundUserStore } from '@/store/fundStore'
import {useConfigStore} from "@/store/configStore";
import { calcFeeInGrams, loadServiceFeeFromSettings } from '@/utils/serviceFee'
import { formatCashWalletBalanceText, formatGoldWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
import { formatCashWalletBalanceText, getWeightUnit } from '@/utils/productDealMethod'
import { formatProductWalletBalanceText, getProductInventoryQuantity } from '@/utils/productAssets'
import { useWalletAssets } from '@/composables/useWalletAssets'
import { isMeltedTradeGroup } from '@/utils/productCategories'
import { useSettingsStore } from '@/store/settingsStore'
import { storeToRefs } from 'pinia'
@@ -253,6 +255,7 @@ const settingsStore = useSettingsStore()
const { meltedGoldLabel } = storeToRefs(settingsStore)
const weightUnit = computed(() => getWeightUnit())
const fundStore = useFundUserStore()
const { assetsSummary, loadWalletAssets } = useWalletAssets()
const confirmAction = ref<boolean>(false)
const noCompleteVisible = ref<boolean>(false)
const buyItems = ref<Transaction[]>([])
@@ -275,6 +278,22 @@ const tradeProductLabel = computed(() => {
})
const amountFieldLabel = computed(() => `مقدار ${tradeProductLabel.value}`)
const productWalletBalance = computed(() =>
getProductInventoryQuantity(
assetsSummary.value?.inventory_cards ?? [],
props.ProductItem?.id,
walletStore?.walletInfo?.gold
)
)
const productWalletBalanceText = computed(() =>
formatProductWalletBalanceText(
props.ProductItem,
assetsSummary.value?.inventory_cards ?? [],
walletStore?.walletInfo?.gold
)
)
const buyPagination = ref<TableEngineInput>({
filters: [{
field: 'type',
@@ -441,10 +460,6 @@ onMounted(async () => {
await initBuyTable()*/
})
onUnmounted(() => {
stopPriceInterval()
})
const form = ref<Gold>({
goldCash: undefined,
goldValue: undefined,
@@ -471,6 +486,7 @@ watch(form.value, () => {
})
onMounted(() => {
void loadWalletAssets()
console.log(userStore.userInfo?.is_legal === 2)
if (userStore.userInfo?.is_legal === 0) {
noCompleteVisible.value = true
@@ -495,10 +511,7 @@ function percentChange(val: number) {
}
}
const unitGoldCalculator = computed(() => {
// console.log(walletStore?.walletInfo?.gold / 100)
return (walletStore?.walletInfo?.gold ?? 0) / 100
})
const unitGoldCalculator = computed(() => productWalletBalance.value / 100)
const unitCashCalculator = computed(() => {
return (walletStore?.walletInfo?.cash ?? 0) / 100
@@ -607,15 +620,12 @@ const goldPriceValue = computed(() => unitPrice.value)
async function initPrice() {
try {
// chartLoading.value = true
await getLastPrices()
await setIntervalGetAllPrice()
loading.value = true
} catch (e) {
console.log(e)
} finally {
loading.value = false
// chartLoading.value = false
}
}
@@ -639,6 +649,7 @@ async function ok() {
})
confirmAction.value = false
await walletStore.getMyWallet()
await loadWalletAssets(true)
await router.push({ name: 'transactions' })
form.value = {
goldValue: undefined,
@@ -12,7 +12,7 @@
icon="vuesax-linear:info-circle"
size="18"
color="tertiary"
@click="$emit('openGoldModal')"
@click="$emit('openGoldModal', primaryMetalTotal)"
/>
</div>
</template>
@@ -29,13 +29,13 @@
icon="vuesax-linear:info-circle"
size="18"
color="tertiary"
@click="$emit('openGoldModal')"
@click="$emit('openGoldModal', metal)"
/>
</div>
</template>
<div class="flex mt-2 justify-center text-tertiary w-full z-20">
دارایی ریالی:
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(cashWallet) }} ریال</div>
<div class="text-l mr-2 font-bold">{{ usePriceWithoutType(totalRialValue) }} ریال</div>
<BasicIcon @click="$emit('openRialModal')" icon="vuesax-linear:info-circle" size="18" color="tertiary" />
</div>
</div>
@@ -52,14 +52,14 @@ import { resolveSummaryMetalWeight } from '@/utils/productAssets'
const { assetsSummary, loadWalletAssets } = useWalletAssets()
defineEmits<{
openGoldModal: []
openGoldModal: [metal: WalletMetalTotal]
openRialModal: []
}>()
const meta = computed(() => assetsSummary.value?.meta)
const metalTotals = computed(() => assetsSummary.value?.metal_totals ?? [])
const primaryMetalTotal = computed(() => metalTotals.value[0])
const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
const totalRialValue = computed(() => assetsSummary.value?.total_rial_value ?? 0)
const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? [])
const countBasedInventory = computed(() =>
(assetsSummary.value?.count_products ?? []).reduce((sum, item) => sum + Number(item.quantity ?? 0), 0)
@@ -31,7 +31,14 @@
<a-divider class="!my-1" />
<BasicInfoItem
class="flex justify-between"
title="معادل ریالی مجموع دارایی ها"
title="معادل ریالی محصولات"
is-line
:value="usePrice(assetsRialValue)"
/>
<a-divider class="!my-1" />
<BasicInfoItem
class="flex justify-between"
title="مجموع دارایی ریالی"
is-line
:value="usePrice(totalRialValue)"
/>
@@ -49,7 +56,7 @@ import BasicInfoItem from '@/components/BasicPacks/BasicInfoItem.vue'
import { usePrice } from '@/utils/usePrice'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
import { formatInventoryCardValue } from '@/utils/productAssets'
import { formatInventoryCardValue, assetSheetInventoryCards } from '@/utils/productAssets'
const props = defineProps<{
show: boolean
@@ -71,6 +78,7 @@ const visible = computed({
const inventoryCards = computed(() => assetsSummary.value?.inventory_cards ?? [])
const metalTotals = computed(() => assetsSummary.value?.metal_totals ?? [])
const cashWallet = computed(() => assetsSummary.value?.cash_wallet ?? 0)
const assetsRialValue = computed(() => assetsSummary.value?.assets_rial_value ?? 0)
const totalRialValue = computed(() => assetsSummary.value?.total_rial_value ?? 0)
onMounted(() => {
@@ -87,7 +95,7 @@ watch(
)
function cardsByMetal(metalId: number) {
return inventoryCards.value.filter((card) => Number(card.metal_id) === metalId)
return assetSheetInventoryCards(inventoryCards.value, metalId)
}
function formatMetalTotal(metal: WalletMetalTotal) {
+15 -11
View File
@@ -83,10 +83,12 @@ import {loading, removeToken} from '@/utils'
import {useUserStore} from '@/store/userStore'
import {useWalletStore} from '@/store/walletStore'
import { useWalletAssets } from '@/composables/useWalletAssets'
import type { WalletMetalTotal } from '@/models/walletAssets'
import { formatMetalAssetsInfoText, formatRialAssetsInfoText } from '@/utils/productAssets'
import {useConfigStore} from '@/store/configStore'
import {useFundUserStore} from '@/store/fundStore'
import {usePrice, usePriceWithoutType} from '../../../utils/usePrice'
import {getLastPrices, lastPrice, price, setIntervalGetAllPrice, stopPriceInterval} from '@/utils/price'
import {usePriceWithoutType} from '../../../utils/usePrice'
import {getLastPrices, lastPrice, price, startLastPricePolling, stopLastPricePolling} from '@/utils/price'
import {getConstByKey} from '@/api/const'
import {message, Modal} from 'ant-design-vue'
@@ -119,6 +121,7 @@ const userStore = useUserStore()
const walletStore = useWalletStore()
const configStore = useConfigStore()
const fundStore = useFundUserStore()
const { assetsSummary, loadWalletAssets } = useWalletAssets()
// Config
const isGaroosi = computed(() => configStore.config.name === 'garoosi')
@@ -211,11 +214,9 @@ async function logout() {
window.location.reload()
}
function openGoldModal() {
const goldAmount = (walletStore.walletInfo?.gold ?? 0).toFixed(3)
const walletsAmount = (walletStore.walletInfo?.count_gold_wallets ?? 0).toFixed(3)
function openGoldModal(metal: WalletMetalTotal) {
Modal.confirm({
title: `مجموع کل وزن طلای آبشده (${goldAmount}) + ارزش دارایی ها (${walletsAmount}) گرم`,
title: formatMetalAssetsInfoText(metal),
okText: 'متوجه شدم',
centered: true,
cancelButtonProps: {style: {display: 'none'}}
@@ -223,10 +224,12 @@ function openGoldModal() {
}
function openRialModal() {
const cashWallet = usePrice(walletStore?.walletInfo?.count_cash_wallet ?? 0)
const cashWallets = usePrice(walletStore?.walletInfo?.count_cash_wallets ?? 0)
const summary = assetsSummary.value
Modal.confirm({
title: `مجموع کیف پول ریالی (${cashWallet}) + معادل ریالی محصولات (${cashWallets}) ریال`,
title: formatRialAssetsInfoText(
summary?.cash_wallet ?? 0,
summary?.assets_rial_value ?? 0
),
okText: 'متوجه شدم',
centered: true,
cancelButtonProps: {style: {display: 'none'}}
@@ -261,9 +264,10 @@ onMounted(async () => {
loading.value = true
await Promise.all([
loadFunds(),
loadWalletAssets(),
getLastPrices(),
fetchPrices(),
setIntervalGetAllPrice(),
startLastPricePolling(),
loadBanners()
])
@@ -274,7 +278,7 @@ onMounted(async () => {
onUnmounted(() => {
clearInterval(updateInterval)
stopPriceInterval()
stopLastPricePolling()
})
} catch (error) {
console.error('Initialization error:', error)
@@ -67,7 +67,7 @@
size="large" type="text" inputmode="numeric" @onchange="handleGoldValueChange" />
</a-form-item>
<a-form-item v-else name="goldValue"
:rules="[justNumber3(props?.ProductItem?.sellPrice, productNum ,false)]">
:rules="[justNumber3(props?.ProductItem?.sellPrice, productNum.value ,false)]">
<BasicInput v-model:value="form.goldValue" addon-before="تعداد" addon-bg-color="#000000FF"
addon-text-color="white"
place-holder="تعداد"
@@ -104,8 +104,7 @@
{{ cashWalletBalanceText }}
</div>
<div class="font-bold text-xs" v-else>
<div>{{ `موجودی محصول: ${getInventoryById(props?.ProductItem?.id)} ${getProductQuantityUnit(props?.ProductItem)}` }}</div>
<div v-if="isMetalReceiveDeal" class="mt-1">{{ sellMetalWalletBalanceText }}</div>
<div>{{ productWalletBalanceText }}</div>
</div>
</Transition>
<Transition mode="out-in" name="fade">
@@ -296,6 +295,8 @@ import {
productMaxOrderCash,
productMinOrderCash
} from '@/utils/productOrderLimit'
import { useWalletAssets } from '@/composables/useWalletAssets'
import { formatProductWalletBalanceText, getProductInventoryQuantity } from '@/utils/productAssets'
const typeDeal = computed(() => getProductDealMethodOptions(props?.ProductItem?.group_type, isBuy.value))
@@ -329,16 +330,28 @@ const goldWalletBalanceText = computed(() =>
formatGoldWalletBalanceText(walletStore?.walletInfo?.gold ?? 0, productGroupType.value)
)
const productWalletBalance = computed(() =>
getProductInventoryQuantity(
assetsSummary.value?.inventory_cards ?? [],
props?.ProductItem?.id,
walletStore?.walletInfo?.gold
)
)
const productWalletBalanceText = computed(() =>
formatProductWalletBalanceText(
props?.ProductItem,
assetsSummary.value?.inventory_cards ?? [],
walletStore?.walletInfo?.gold
)
)
const buyMetalWalletBalanceText = computed(() =>
form.value.method === 'katod'
? formatMainMetalWalletBalanceText(walletStore?.walletInfo?.gold ?? 0)
: goldWalletBalanceText.value
)
const sellMetalWalletBalanceText = computed(() =>
formatMainMetalWalletBalanceText(walletStore?.walletInfo?.gold ?? 0)
)
const cashWalletBalanceText = computed(() =>
formatCashWalletBalanceText(
usePriceWithoutType(walletStore?.walletInfo?.cash ?? 0),
@@ -347,6 +360,7 @@ const cashWalletBalanceText = computed(() =>
)
const infoVisible = ref(false)
const walletStore = useWalletStore()
const { assetsSummary, loadWalletAssets } = useWalletAssets()
const userStore = useUserStore()
const confirmAction = ref<boolean>(false)
const noCompleteVisible = ref<boolean>(false)
@@ -525,6 +539,7 @@ async function initSellTable() {
// }
onMounted(async () => {
void loadWalletAssets()
switch (router.currentRoute.value.query.state) {
case 'sell':
isBuy.value = false
@@ -581,15 +596,7 @@ onMounted(() => {
noCompleteVisible.value = true
}
})
const productNum = ref<number>(0)
const getInventoryById = (id: number) => {
userStore?.productWallet?.forEach((val) => {
if (val.product_id == id)
productNum.value = val.gold
})
return productNum.value ?? 0
}
const productNum = computed(() => productWalletBalance.value)
/*function percentChange(val: number) {
if (val !== 0)
@@ -802,6 +809,7 @@ async function ok() {
emit('ordered')
await userStore.getMyInfo()
await walletStore.getMyWallet()
await loadWalletAssets(true)
await fundStore.getMyFund()
message.success('سفارش شما با موفقیت انجام شد')
await router.push({ name: 'transactions' })
+56 -27
View File
@@ -89,13 +89,7 @@ import { onMounted, onUnmounted, ref, watch } from 'vue'
import router from '@/router'
import ProductItem from '@/views/base/products/components/ProductItem.vue'
import { getProducts } from '@/api/products'
import {
getLastPrices,
lastPrice,
stopPriceInterval
} from '@/utils/price'
import { loading } from '@/utils'
import { Price } from '@/models/home'
import type { Product } from '@/models/products'
import BasicActionSheet from '@/components/BasicPacks/BasicActionSheet.vue'
import indexGold from '@/views/base/gold/index.vue'
@@ -162,9 +156,57 @@ function changeTab() {
}
const firstItems = ref<Product[]>()
const price = ref<Price>()
const items = ref<Product[]>()
const typeItems = ref([])
let productListInterval: ReturnType<typeof setInterval> | undefined
/**
* رفرش بی‌صدای لیست محصولات (هر ۱۰ ثانیه تا وقتی در این صفحه‌ایم).
* آپدیت درجا انجام می‌شود تا لیست re-render کامل نشود و نپرد؛
* فقط اگر محصولی اضافه/حذف شده باشد ساختار لیست عوض می‌شود.
*/
async function refreshProducts() {
try {
const fresh = await getProducts()
if (!fresh?.length) {
return
}
fresh.forEach((val) => {
if (!typeItems.value.includes(val.group_type)) {
typeItems.value.push(val.group_type)
}
})
const freshById = new Map(fresh.map((p) => [p.id, p]))
const current = firstItems.value
if (!current?.length) {
firstItems.value = fresh
changeTab()
return
}
// آپدیت فیلدهای محصولات موجود روی همان آبجکت‌ها (items همین رفرنس‌ها را دارد)
current.forEach((item) => {
const updated = freshById.get(item.id)
if (updated) {
Object.assign(item, updated)
}
})
const currentIds = new Set(current.map((p) => p.id))
const hasAdded = fresh.some((p) => !currentIds.has(p.id))
const hasRemoved = current.some((p) => !freshById.has(p.id))
if (hasAdded || hasRemoved) {
firstItems.value = fresh
changeTab()
}
} catch (e) {
console.log(e)
}
}
onMounted(async () => {
try {
loading.value = true
@@ -182,9 +224,9 @@ onMounted(async () => {
// typeItems.value[index] = val.group_type
})
firstItems.value = items.value
await Promise.all([initPrice(), loadServiceFeeFromSettings()])
// await setIntervalGetLastPrice()
// console.log('run product')
await loadServiceFeeFromSettings()
// فقط لیست محصولات هر ۱۰ ثانیه — last فقط در صفحه اصلی poll می‌شود
productListInterval = setInterval(refreshProducts, 10000)
} catch (e) {
console.log(e)
@@ -205,10 +247,10 @@ onMounted(async () => {
}
})
onUnmounted(() => {
stopPriceInterval()
// console.log('stop product')
// console.log('okgold')
if (productListInterval) {
clearInterval(productListInterval)
productListInterval = undefined
}
})
// watch(lastPrice, async () => {
// // console.log(items);
@@ -226,19 +268,6 @@ onUnmounted(() => {
//
// })
// })
async function initPrice() {
try {
// chartLoading.value = true
await getLastPrices()
loading.value = true
} catch (e) {
console.log(e)
} finally {
loading.value = false
// chartLoading.value = false
}
}
</script>
<style lang="less">