2026-06-16 19:47:28 +03:30
|
|
|
import { loadAppConfig } from '@/config/load-config'
|
|
|
|
|
import { setAppConfig } from '@/config/app-config'
|
|
|
|
|
import { applyAppConfig } from '@/config/apply-config'
|
|
|
|
|
import { startPwaManifest } from '@/modules/pwa/manifest'
|
|
|
|
|
import { createVueApp } from '@/app/createApp'
|
|
|
|
|
import { setupRouterGuards } from '@/app/setupRouter'
|
2026-06-17 11:26:26 +03:30
|
|
|
import router from '@/router'
|
2026-06-16 19:47:28 +03:30
|
|
|
import { applyProjectTheme } from '@/utils/config'
|
|
|
|
|
import { useSettingsStore } from '@/store/settingsStore'
|
2026-06-17 17:39:41 +03:30
|
|
|
import { useUserStore } from '@/store/userStore'
|
2026-06-16 19:47:28 +03:30
|
|
|
import { getToken } from '@/utils'
|
|
|
|
|
|
|
|
|
|
type BootWindow = Window & {
|
|
|
|
|
__BOOT_TIMEOUT__?: number
|
|
|
|
|
__APP_BOOTSTRAPPED__?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function clearBootTimeout() {
|
|
|
|
|
const bootWindow = window as BootWindow
|
|
|
|
|
|
|
|
|
|
if (bootWindow.__BOOT_TIMEOUT__) {
|
|
|
|
|
window.clearTimeout(bootWindow.__BOOT_TIMEOUT__)
|
|
|
|
|
bootWindow.__BOOT_TIMEOUT__ = undefined
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function withTimeout<T>(promise: Promise<T>, ms: number, message: string): Promise<T> {
|
|
|
|
|
return Promise.race([
|
|
|
|
|
promise,
|
|
|
|
|
new Promise<T>((_, reject) => {
|
|
|
|
|
window.setTimeout(() => {
|
|
|
|
|
reject(new Error(message))
|
|
|
|
|
}, ms)
|
|
|
|
|
})
|
|
|
|
|
])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showBootstrapError(error: unknown) {
|
|
|
|
|
clearBootTimeout()
|
|
|
|
|
|
|
|
|
|
console.error('Bootstrap failed:', error)
|
|
|
|
|
|
|
|
|
|
const appRoot = document.querySelector('#app')
|
|
|
|
|
|
|
|
|
|
if (!appRoot) return
|
|
|
|
|
|
|
|
|
|
appRoot.innerHTML = `
|
|
|
|
|
<div style="min-height: 100vh; display: flex; align-items: center; justify-content: center; direction: rtl; font-family: sans-serif; padding: 24px; background: var(--boot-bg, #ffffff); color: var(--boot-text, #111827);">
|
|
|
|
|
<div style="width: min(420px, 100%); text-align: center; background: var(--boot-card, #fff); border: 1px solid var(--boot-border, rgba(15,23,42,0.08)); border-radius: 24px; padding: 28px 22px;">
|
|
|
|
|
<div style="font-size: 42px; margin-bottom: 12px;">⚠️</div>
|
|
|
|
|
<h2 style="margin: 0 0 12px; font-size: 20px;">خطا در راهاندازی برنامه</h2>
|
|
|
|
|
<p style="margin: 0 0 20px; color: var(--boot-muted, rgba(15,23,42,0.62)); line-height: 2; font-size: 14px;">
|
|
|
|
|
لطفاً اتصال اینترنت خود را بررسی کنید و دوباره تلاش کنید.
|
|
|
|
|
</p>
|
|
|
|
|
<button
|
|
|
|
|
onclick="location.reload()"
|
|
|
|
|
style="padding: 11px 22px; border: 0; border-radius: 12px; background: var(--boot-accent, #2563eb); color: white; cursor: pointer; font-weight: 700;"
|
|
|
|
|
>
|
|
|
|
|
تلاش مجدد
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyTenantThemeVars() {
|
|
|
|
|
applyProjectTheme()
|
|
|
|
|
|
|
|
|
|
const color = window.__APP_CONFIG__?.user?.color
|
|
|
|
|
const secondaryColor = window.__APP_CONFIG__?.user?.secondary_color
|
|
|
|
|
const backgroundColor = window.__APP_CONFIG__?.user?.background_color
|
|
|
|
|
|
|
|
|
|
if (color) {
|
|
|
|
|
document.documentElement.style.setProperty('--App-primary-color', color)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (secondaryColor) {
|
|
|
|
|
document.documentElement.style.setProperty('--App-secondary-color', secondaryColor)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (backgroundColor) {
|
|
|
|
|
document.documentElement.style.setProperty('--App-background-color', backgroundColor)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function bootstrapApp() {
|
|
|
|
|
try {
|
|
|
|
|
const config = await withTimeout(loadAppConfig(), 20000, 'Config loading timeout')
|
|
|
|
|
|
|
|
|
|
setAppConfig(config)
|
|
|
|
|
applyTenantThemeVars()
|
|
|
|
|
startPwaManifest(config)
|
|
|
|
|
applyAppConfig()
|
|
|
|
|
|
|
|
|
|
const { app } = createVueApp()
|
|
|
|
|
const settingsStore = useSettingsStore()
|
2026-06-17 17:39:41 +03:30
|
|
|
const userStore = useUserStore()
|
2026-06-16 19:47:28 +03:30
|
|
|
|
|
|
|
|
await withTimeout(settingsStore.fetchSettings(), 45000, 'Settings loading timeout')
|
|
|
|
|
|
2026-06-17 17:39:41 +03:30
|
|
|
if (getToken()) {
|
|
|
|
|
await withTimeout(userStore.getMyInfo(), 45000, 'User session loading timeout')
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 19:47:28 +03:30
|
|
|
setupRouterGuards()
|
|
|
|
|
|
|
|
|
|
app.mount('#app')
|
|
|
|
|
|
2026-06-17 11:26:26 +03:30
|
|
|
await router.isReady()
|
|
|
|
|
|
|
|
|
|
if (!getToken() && router.currentRoute.value.name !== 'login') {
|
|
|
|
|
await router.replace({ name: 'login' })
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-16 19:47:28 +03:30
|
|
|
;(window as BootWindow).__APP_BOOTSTRAPPED__ = true
|
|
|
|
|
clearBootTimeout()
|
|
|
|
|
sessionStorage.removeItem('__APP_BOOT_RECOVERY_DONE__')
|
|
|
|
|
sessionStorage.removeItem('__APP_BOOT_RETRY_CLICKED__')
|
|
|
|
|
} catch (error) {
|
|
|
|
|
showBootstrapError(error)
|
|
|
|
|
}
|
|
|
|
|
}
|