fix bug of main-page for guest
This commit is contained in:
@@ -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
@@ -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')
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="variant === 'desktop' && !isRegister"
|
||||
v-if="isRegister && variant === 'desktop'"
|
||||
class="dauth-switch"
|
||||
>
|
||||
<span>حساب کاربری ندارید؟</span>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user