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
+32 -16
View File
@@ -2,7 +2,10 @@ import { getLastPrice, getPrice } from '@/api/home'
import type { Price, PriceUp } from '@/models/home'
import { ref } from 'vue'
let interval: ReturnType<typeof setInterval> | undefined
const LAST_INTERVAL_MS = 10000
let lastInterval: ReturnType<typeof setInterval> | undefined
let lastSubscribers = 0
/** @deprecated از lastPrice استفاده کنید — برای سازگاری با کد قدیمی sync می‌شود */
export const price = ref<Price>()
@@ -23,18 +26,38 @@ export function normalizePriceResponse(data: Price): Price {
return data
}
/** polling /api/price/last — فقط صفحه اصلی */
export function startLastPricePolling() {
lastSubscribers++
if (lastInterval) {
return
}
lastInterval = setInterval(() => {
void getLastPrices()
}, LAST_INTERVAL_MS)
}
/** @deprecated از startLastPricePolling استفاده کنید */
export async function setIntervalGetAllPrice() {
try {
interval = setInterval(async () => {
await getLastPrices()
}, 10000)
} catch (e) {
console.log(e)
startLastPricePolling()
}
/** @deprecated از startLastPricePolling استفاده کنید */
export async function setIntervalGetLastPrice() {
startLastPricePolling()
}
export function stopLastPricePolling() {
lastSubscribers = Math.max(0, lastSubscribers - 1)
if (lastSubscribers === 0 && lastInterval) {
clearInterval(lastInterval)
lastInterval = undefined
}
}
export async function setIntervalGetLastPrice() {
return setIntervalGetAllPrice()
/** @deprecated از stopLastPricePolling استفاده کنید */
export function stopPriceInterval() {
stopLastPricePolling()
}
/** @deprecated فقط getLastPrices را صدا بزنید */
@@ -79,13 +102,6 @@ export async function getLastPrices() {
}
}
export function stopPriceInterval() {
if (interval) {
clearInterval(interval)
interval = undefined
}
}
export function percentPriceChanged() {
if (!olderPrice.value) {
return 0
+84 -10
View File
@@ -1,8 +1,9 @@
import type { Product } from '@/models/products'
import type { UserWalletLine } from '@/models/wallet'
import type { ProductFile } from '@/utils/file'
import type { WalletInventoryCard, WalletMetalTotal } from '@/models/walletAssets'
import { getFileUrl } from '@/utils/file'
import { isCountBasedProduct, type ProductUnitSource } from '@/utils/productDealMethod'
import { isCountBasedProduct, getProductQuantityUnit, type ProductUnitSource } from '@/utils/productDealMethod'
import { isMeltedTradeGroup, normalizeProductGroupType, LEGACY_GROUP_KATOD } from '@/utils/productCategories'
import defaultImg from '@/assets/img/defaultAbshodeh.svg'
import goyImg from '@/assets/img/goyImg.svg'
@@ -54,16 +55,47 @@ export function sumInventoryCardsWeight(
.reduce((sum, card) => sum + Number(card.quantity ?? 0), 0)
}
export function resolveSummaryMetalWeight(
metal: { metal_id: number; total_weight: number },
cards: Array<{ metal_id?: number; quantity?: number }>
): number {
const cardWeight = sumInventoryCardsWeight(cards, metal.metal_id)
if (cardWeight > 0) {
return Number(cardWeight.toFixed(3))
}
/** ردیف‌های جزئی action sheet — فقط محصولاتی که show_in_assets روشن است. */
export function assetSheetInventoryCards<T extends { metal_id?: number; show_in_assets?: boolean }>(
cards: T[],
metalId?: number
): T[] {
return cards.filter((card) => {
if (!card.show_in_assets) {
return false
}
if (metalId == null) {
return true
}
return Number(card.metal_id) === metalId
})
}
return metal.total_weight
/** همه کارت‌های صفحه دارایی‌ها — بدون فیلتر show_in_assets. */
export function fundPageInventoryCards<T>(cards: T[]): T[] {
return cards.filter((card) => Number((card as { quantity?: number }).quantity ?? 0) > 0)
}
export function resolveSummaryMetalWeight(
metal: { total_weight: number },
_cards?: Array<{ metal_id?: number; quantity?: number }>
): number {
return Number(metal.total_weight ?? 0)
}
/** متن توضیح مودال دارایی فلزی — بر اساس metal_totals سرور، بدون هاردکد طلا */
export function formatMetalAssetsInfoText(metal: WalletMetalTotal): string {
const unit = metal.unit || 'گرم'
return `${metal.label}: مجموع کیف محصولات (${metal.product_weight} ${unit}) + موجودی کیف اصلی (${metal.melted_weight} ${unit})`
}
function formatRialNumber(value: number): string {
return Math.round(value).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
/** متن توضیح مودال دارایی ریالی — cash_wallet + assets_rial_value */
export function formatRialAssetsInfoText(cashWallet: number, assetsRialValue: number): string {
return `مجموع کیف پول ریالی (${formatRialNumber(cashWallet)} ریال) + معادل ریالی محصولات (${formatRialNumber(assetsRialValue)} ریال)`
}
export function formatInventoryCardValue(card: {
@@ -76,6 +108,48 @@ export function formatInventoryCardValue(card: {
return `${quantity} ${unit}`
}
export function findProductInventoryCard(
cards: WalletInventoryCard[],
productId?: number | null
): WalletInventoryCard | undefined {
if (!productId) {
return undefined
}
return cards.find((item) => Number(item.product_id) === Number(productId))
}
/**
* موجودی کیف یک محصول از inventory_cards.
* fallback: پروژه‌های ساختار قدیم (مثل گلد علی) کیف محصول ندارند و موجودی روی gold کیف اصلی است.
*/
export function getProductInventoryQuantity(
cards: WalletInventoryCard[],
productId?: number | null,
mainWalletGold?: number | null
): number {
const card = findProductInventoryCard(cards, productId)
if (card) {
return Number(card.quantity ?? 0)
}
return Number(mainWalletGold ?? 0)
}
/** برچسب موجودی کیف محصول — برای فرم خرید/فروش */
export function formatProductWalletBalanceText(
product: { id?: number; title?: string | null; unit?: string | null; group_type?: string | null } | null | undefined,
cards: WalletInventoryCard[] = [],
mainWalletGold?: number | null
): string {
const card = findProductInventoryCard(cards, product?.id)
const quantity = card ? Number(card.quantity ?? 0) : Number(mainWalletGold ?? 0)
const unit = card?.unit ?? getProductQuantityUnit(product)
const title = product?.title?.trim() || 'محصول'
return `موجودی کیف ${title}: ${quantity} ${unit}`
}
export function isSingleMetalCatalog(metalIds: number[]): boolean {
return metalIds.length === 1
}