chore: sync price monitor updates

This commit is contained in:
2026-09-28 18:04:49 +03:30
parent f778064aef
commit 9cb0979606
7 changed files with 88 additions and 112 deletions
+37 -19
View File
@@ -7,6 +7,9 @@ import {
priceSocketConnected,
priceStreamConnectingSince,
priceStreamLifecycle,
priceStreamList,
priceStreamProducts,
priceStreamServerUnix,
priceWssEnabled,
} from '@/utils/priceSocketState'
import {
@@ -282,28 +285,21 @@ export function notifyPriceLastFetchFailed() {
void maybeShowNetworkAlert()
}
function onTvBoard() {
if (typeof window === 'undefined') return false
const path = window.location.pathname.replace(/\/+$/, '') || '/'
return path === '/tv' || path.endsWith('/tv') || path === '/monitor' || path.endsWith('/monitor')
}
async function runFallbackPoll() {
if (onTvBoard() || tvStreamKey || !priceWssEnabled.value || priceSocketConnected.value) {
if (tvStreamKey || !priceWssEnabled.value || priceSocketConnected.value) {
return
}
try {
const { getLastPrices, hasRecentPriceFromSource } = await import('@/utils/price')
const jobs: Promise<unknown>[] = [getLastPrices()]
if (!tvStreamKey) {
const { refreshProductsPageData } = await import(
'@/views/base/products/composables/useProductsPageData'
)
jobs.push(refreshProductsPageData())
}
const { refreshProductsPageData } = await import(
'@/views/base/products/composables/useProductsPageData'
)
const [priceResult] = await Promise.allSettled(jobs)
const [priceResult] = await Promise.allSettled([
getLastPrices(),
refreshProductsPageData(),
])
const priceOk =
priceResult.status === 'fulfilled'
@@ -508,6 +504,7 @@ function handleListPayload(payload: unknown) {
}
touchStreamActivity()
priceStreamList.value = products as Array<Record<string, unknown>>
applyProductsListFromStream(products)
}
@@ -572,6 +569,31 @@ function bindStreamEvents(source: AuthPriceStream) {
}
})
source.addEventListener('products', (event) => {
try {
const rows = JSON.parse(event.data)
if (Array.isArray(rows) && rows.length) {
touchStreamActivity()
priceStreamProducts.value = rows
}
} catch (error) {
console.warn('Price SSE products parse failed', error)
}
})
source.addEventListener('time', (event) => {
try {
const payload = JSON.parse(event.data) as { unix?: number }
const unix = Number(payload?.unix)
if (unix > 0) {
touchStreamActivity()
priceStreamServerUnix.value = unix
}
} catch (error) {
console.warn('Price SSE time parse failed', error)
}
})
source.addEventListener('app_notification', (event) => {
try {
handleAppNotificationPayload(JSON.parse(event.data))
@@ -750,10 +772,6 @@ function unbindBrowserNetworkListeners() {
window.removeEventListener('offline', onBrowserOffline)
}
export function isTvStreamActive() {
return Boolean(tvStreamKey)
}
export function startTvPriceStream(
settingGetter: (key: string) => unknown,
key: string,
+9
View File
@@ -9,6 +9,15 @@ export const priceStreamLifecycle = ref<PriceStreamLifecycle>('idle')
export const priceStreamConnectingSince = ref(0)
/** آخرین رویداد list استریم */
export const priceStreamList = ref<Array<Record<string, unknown>>>([])
/** آخرین بدنهٔ tv/products که از SSE آمده */
export const priceStreamProducts = ref<Array<Record<string, unknown>>>([])
/** unix ساعت سرور از رویداد time استریم */
export const priceStreamServerUnix = ref(0)
const CONNECTING_POLL_AFTER_MS = 8000
export function shouldUsePricePolling(): boolean {
+6 -11
View File
@@ -61,15 +61,6 @@ function sellCashFee(product: Product, base: number) {
return resolveProductCashFeeSellRial(product, base, cashFeeOptions(product, 'sell'))
}
/** سمت خرید/فروش همکار؛ اگر سرور نفرستاده باشد همان قیمت وسط قبلی */
function colleagueSideUnit(product: Product, side: 'buy' | 'sell', live: number): number {
const sided = side === 'buy' ? Number(product.price_buy ?? 0) : Number(product.price_sell ?? 0)
if (sided > 0) {
return sided
}
return getColleagueSourcedUnitPrice(product, live)
}
/** قیمت منبع همکار؛ اگر خالی بود آبشده همان مظنهٔ صفحه اصلی را می‌گیرد */
function getColleagueSourcedUnitPrice(product: Product, live: number, apiPrice = Number(product.price ?? 0)): number {
if (apiPrice > 0) {
@@ -143,7 +134,7 @@ export function getProductBaseBuyPrice(product?: Product | null): number {
}
if (isColleaguePriceProduct(product)) {
return colleagueSideUnit(product, 'buy', getTradeBuyPrice(lastPrice.value))
return getColleagueSourcedUnitPrice(product, getTradeBuyPrice(lastPrice.value))
}
if (isMeltedProductUsingAppPrice(product) || isAppPriceProduct(product)) {
@@ -220,7 +211,11 @@ export function getProductBaseSellPrice(product?: Product | null): number {
}
if (isColleaguePriceProduct(product)) {
return colleagueSideUnit(product, 'sell', getTradeSellPrice(lastPrice.value))
return getColleagueSourcedUnitPrice(
product,
getTradeSellPrice(lastPrice.value),
Number(product.sellPrice ?? product.price ?? 0),
)
}
if (isMeltedProductUsingAppPrice(product) || isAppPriceProduct(product)) {