fix bug of main-page for guest

This commit is contained in:
2026-10-17 14:12:18 +03:30
parent 9487490981
commit 5e181fdae9
7 changed files with 39 additions and 30 deletions
@@ -35,3 +35,5 @@
- 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 هر دو باز
- 2026-10-17 | نمودار مهمان ۴۰۱ | `usePriceChart.ts` + `api/home.ts` + سرور `routes/api.php` `POST /api/price/all` | مهمان product/list نمی‌زند؛ تاریخچه نمودار از `/api/price/all` (همان priceData)
- 2026-10-17 | قیمت زنده مهمان | `bootstrap.ts` + `priceSocket.ts` + سرور `/api/price/stream` بدون auth | SSE بدون توکن؛ polling پشتیبان product/list فقط با توکن
+4 -1
View File
@@ -8,4 +8,7 @@ export const getPrice = async () => await useAxios.get<Price>(`/api/price/up`)
export const getLastPrice = async () => await useAxios.get<Price>(`/api/price/last`)
export const getAllPrices = async () => await useAxios.post('/customer/prices/all')
export const getAllPrices = async () => await useAxios.post('/customer/prices/all')
/** نمودار مهمان — همان بدنهٔ prices/all، بدون توکن مشتری */
export const getPublicChartPrices = async () => await useAxios.post('/api/price/all')
+1 -3
View File
@@ -117,9 +117,7 @@ export async function bootstrapApp() {
await withTimeout(settingsStore.fetchSettings(), 45000, 'Settings loading timeout')
if (getToken()) {
initPriceRealtimeChannel((key) => settingsStore.getSettingByKey(key))
}
initPriceRealtimeChannel((key) => settingsStore.getSettingByKey(key))
if (getToken()) {
await withTimeout(userStore.getMyInfo(), 45000, 'User session loading timeout')
+20 -21
View File
@@ -38,7 +38,7 @@ const STREAM_CONNECTING = 0
const STREAM_OPEN = 1
const STREAM_CLOSED = 2
/** EventSource نمی‌تواند Authorization بفرستد؛ استریم همچنان auth:customer می‌خواهد. */
/** fetch + ReadableStream — با توکن اختلاف قیمت ویژه؛ بدون توکن همان مظنهٔ عمومی (مهمان). */
class AuthPriceStream extends EventTarget {
readyState = STREAM_CONNECTING
onopen: (() => void) | null = null
@@ -46,7 +46,7 @@ class AuthPriceStream extends EventTarget {
onmessage: (() => void) | null = null
private abort = new AbortController()
constructor(url: string, token: string) {
constructor(url: string, token?: string) {
super()
void this.start(url, token)
}
@@ -56,13 +56,18 @@ class AuthPriceStream extends EventTarget {
this.abort.abort()
}
private async start(url: string, token: string) {
private async start(url: string, token?: string) {
try {
const headers: Record<string, string> = {
Accept: 'text/event-stream',
}
const bearer = String(token ?? '').trim()
if (bearer) {
headers.Authorization = `Bearer ${bearer}`
}
const response = await fetch(url, {
headers: {
Accept: 'text/event-stream',
Authorization: `Bearer ${token}`,
},
headers,
cache: 'no-store',
signal: this.abort.signal,
})
@@ -191,10 +196,6 @@ function resolveStreamUrl(): string | null {
return null
}
if (!findStoredAuthToken()) {
return null
}
const base = String(getConfigApp('node_server') || window.location.origin).replace(/\/$/, '')
return `${base}${resolveStreamPath()}`
}
@@ -301,10 +302,12 @@ async function runFallbackPoll() {
'@/views/base/products/composables/useProductsPageData'
)
const [priceResult] = await Promise.allSettled([
getLastPrices(),
refreshProductsPageData(),
])
const pollTasks: Promise<unknown>[] = [getLastPrices()]
if (findStoredAuthToken()) {
pollTasks.push(refreshProductsPageData())
}
const [priceResult] = await Promise.allSettled(pollTasks)
const priceOk =
priceResult.status === 'fulfilled'
@@ -643,7 +646,7 @@ function connect() {
const url = resolveStreamUrl()
const token = findStoredAuthToken()
if (!url || !token) {
if (!url) {
priceSocketConnected.value = false
priceStreamLifecycle.value = 'closed'
clearConnectingLifecycle()
@@ -661,7 +664,7 @@ function connect() {
markConnectingLifecycle()
try {
eventSource = new AuthPriceStream(url, token)
eventSource = new AuthPriceStream(url, token ?? undefined)
} catch (error) {
console.warn('Price SSE connect failed', error)
handleStreamLost()
@@ -824,10 +827,6 @@ export function isPriceWebSocketEnabled(settingGetter: (key: string) => unknown)
return false
}
if (!findStoredAuthToken()) {
return false
}
return resolveStreamUrl() !== null
}
@@ -1,6 +1,7 @@
import { computed, ref, watch } from 'vue'
import { getAllPrices } from '@/api/home'
import { getAllPrices, getPublicChartPrices } from '@/api/home'
import { getProductsCatalog, getProductsCatalogRef } from '@/composables/useProductsCatalog'
import { getToken } from '@/utils'
import { getTradeBuyPrice, getTradeSellPrice } from '@/utils/price'
export type ChartMetalType = 'katod' | 'maftol' | 'shamsh'
@@ -132,7 +133,7 @@ async function fetchPrices(force = false) {
chartFetchPromise = (async () => {
try {
chartLoading.value = true
const response = await getAllPrices()
const response = await (getToken() ? getAllPrices() : getPublicChartPrices())
const data = resolvePricesMap(response)
cachedPrices.value = data
applyTimelineFromCache()
@@ -149,6 +150,14 @@ async function fetchPrices(force = false) {
}
async function loadMetalChartOffsets(force = false) {
if (!getToken()) {
if (!metalOffsetLoaded) {
syncChartSeries()
metalOffsetLoaded = true
}
return
}
if (!force && metalOffsetLoaded && catalogProducts.value.length > 0) {
return
}
+1 -1
View File
@@ -221,7 +221,7 @@
</div>
<div
v-if="variant === 'desktop' && !isRegister"
v-if="isRegister && variant === 'desktop'"
class="dauth-switch"
>
<span>حساب کاربری ندارید؟</span>
-2
View File
@@ -8,9 +8,7 @@
<p class="dauth-card__subtitle">برای ادامه، رمز ورود خود را انتخاب کنید.</p>
</header>
<header v-else class="dauth-card__header">
<p class="dauth-card__eyebrow">حساب جدید</p>
<h2 class="dauth-card__title">ثبت نام</h2>
<p class="dauth-card__subtitle">اطلاعات خود را برای ایجاد حساب وارد کنید</p>
</header>
<Login