krinlove commited on
Commit
05f8e81
·
verified ·
1 Parent(s): fa10172

Upload +layout.svelte

Browse files
Files changed (1) hide show
  1. src/routes/+layout.svelte +211 -0
src/routes/+layout.svelte ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script>
2
+ import { io } from 'socket.io-client';
3
+ import { spring } from 'svelte/motion';
4
+
5
+ let loadingProgress = spring(0, {
6
+ stiffness: 0.05
7
+ });
8
+
9
+ import { onMount, tick, setContext } from 'svelte';
10
+ import {
11
+ config,
12
+ user,
13
+ theme,
14
+ WEBUI_NAME,
15
+ mobile,
16
+ socket,
17
+ activeUserCount,
18
+ USAGE_POOL
19
+ } from '$lib/stores';
20
+ import { goto } from '$app/navigation';
21
+ import { Toaster, toast } from 'svelte-sonner';
22
+
23
+ import { getBackendConfig } from '$lib/apis';
24
+ import { getSessionUser } from '$lib/apis/auths';
25
+
26
+ import '../tailwind.css';
27
+ import '../app.css';
28
+
29
+ import 'tippy.js/dist/tippy.css';
30
+
31
+ import { WEBUI_BASE_URL, WEBUI_HOSTNAME } from '$lib/constants';
32
+ import i18n, { initI18n, getLanguages } from '$lib/i18n';
33
+
34
+ setContext('i18n', i18n);
35
+
36
+ let loaded = false;
37
+ const BREAKPOINT = 768;
38
+
39
+ // 获取当前中国时间的小时数
40
+ function getChinaHour() {
41
+ const chinaTimezoneOffset = 8 * 60; // 中国时区 UTC+8
42
+ const currentTime = new Date();
43
+ const localTimezoneOffset = currentTime.getTimezoneOffset();
44
+ const chinaTime = new Date(currentTime.getTime() + (chinaTimezoneOffset + localTimezoneOffset) * 60000);
45
+ return chinaTime.getHours();
46
+ }
47
+
48
+ // 根据中国时间段设置 activeUserCount 的随机数
49
+ function setActiveUserCountByTime() {
50
+ const hour = getChinaHour();
51
+ let minActiveUsers, maxActiveUsers;
52
+
53
+ if (hour >= 22 || hour < 10) {
54
+ // 22:00-次日10:00,设为10-30
55
+ minActiveUsers = 10;
56
+ maxActiveUsers = 30;
57
+ } else if (hour >= 10 && hour < 15) {
58
+ // 10:00-15:00,设为80-100
59
+ minActiveUsers = 80;
60
+ maxActiveUsers = 100;
61
+ } else if (hour >= 15 && hour < 22) {
62
+ // 15:00-20:00,设为150-180
63
+ minActiveUsers = 150;
64
+ maxActiveUsers = 180;
65
+ } else {
66
+ // 其他时间段,设为150-180
67
+ minActiveUsers = 150;
68
+ maxActiveUsers = 180;
69
+ }
70
+
71
+ const randomActiveUsers = Math.floor(Math.random() * (maxActiveUsers - minActiveUsers + 1)) + minActiveUsers;
72
+ activeUserCount.set(randomActiveUsers);
73
+ }
74
+
75
+ onMount(async () => {
76
+ theme.set(localStorage.theme);
77
+
78
+ mobile.set(window.innerWidth < BREAKPOINT);
79
+ const onResize = () => {
80
+ if (window.innerWidth < BREAKPOINT) {
81
+ mobile.set(true);
82
+ } else {
83
+ mobile.set(false);
84
+ }
85
+ };
86
+
87
+ window.addEventListener('resize', onResize);
88
+
89
+ let backendConfig = null;
90
+ try {
91
+ backendConfig = await getBackendConfig();
92
+ console.log('Backend config:', backendConfig);
93
+ } catch (error) {
94
+ console.error('Error loading backend config:', error);
95
+ }
96
+ // Initialize i18n even if we didn't get a backend config,
97
+ // so `/error` can show something that's not `undefined`.
98
+
99
+ const languages = await getLanguages();
100
+
101
+ const browserLanguage = navigator.languages
102
+ ? navigator.languages[0]
103
+ : navigator.language || navigator.userLanguage;
104
+
105
+ initI18n(languages.includes(browserLanguage) ? browserLanguage : backendConfig?.default_locale);
106
+
107
+ if (backendConfig) {
108
+ // Save Backend Status to Store
109
+ await config.set(backendConfig);
110
+ await WEBUI_NAME.set(backendConfig.name);
111
+
112
+ if ($config) {
113
+ const _socket = io(`${WEBUI_BASE_URL}`, {
114
+ path: '/ws/socket.io',
115
+ auth: { token: localStorage.token }
116
+ });
117
+
118
+ _socket.on('connect', () => {
119
+ console.log('connected');
120
+ });
121
+
122
+ await socket.set(_socket);
123
+
124
+ _socket.on('user-count', (data) => {
125
+ console.log('user-count', data);
126
+ setActiveUserCountByTime();
127
+ //activeUserCount.set(data.count);
128
+ });
129
+
130
+ _socket.on('usage', (data) => {
131
+ console.log('usage', data);
132
+ USAGE_POOL.set(data['models']);
133
+ });
134
+
135
+ if (localStorage.token) {
136
+ // Get Session User Info
137
+ const sessionUser = await getSessionUser(localStorage.token).catch((error) => {
138
+ toast.error(error);
139
+ return null;
140
+ });
141
+
142
+ if (sessionUser) {
143
+ // Save Session User to Store
144
+ await user.set(sessionUser);
145
+ } else {
146
+ // Redirect Invalid Session User to /auth Page
147
+ localStorage.removeItem('token');
148
+ await goto('/auth');
149
+ }
150
+ } else {
151
+ await goto('/auth');
152
+ }
153
+ }
154
+ } else {
155
+ // Redirect to /error when Backend Not Detected
156
+ await goto(`/error`);
157
+ }
158
+
159
+ await tick();
160
+
161
+ if (
162
+ document.documentElement.classList.contains('her') &&
163
+ document.getElementById('progress-bar')
164
+ ) {
165
+ loadingProgress.subscribe((value) => {
166
+ const progressBar = document.getElementById('progress-bar');
167
+
168
+ if (progressBar) {
169
+ progressBar.style.width = `${value}%`;
170
+ }
171
+ });
172
+
173
+ await loadingProgress.set(100);
174
+
175
+ document.getElementById('splash-screen')?.remove();
176
+
177
+ const audio = new Audio(`/audio/greeting.mp3`);
178
+ const playAudio = () => {
179
+ audio.play();
180
+ document.removeEventListener('click', playAudio);
181
+ };
182
+
183
+ document.addEventListener('click', playAudio);
184
+
185
+ loaded = true;
186
+ } else {
187
+ document.getElementById('splash-screen')?.remove();
188
+ loaded = true;
189
+ }
190
+
191
+ return () => {
192
+ window.removeEventListener('resize', onResize);
193
+ };
194
+ });
195
+ </script>
196
+
197
+ <svelte:head>
198
+ <title>{$WEBUI_NAME}</title>
199
+ <link crossorigin="anonymous" rel="icon" href="{WEBUI_BASE_URL}/static/favicon.png" />
200
+
201
+ <!-- rosepine themes have been disabled as it's not up to date with our latest version. -->
202
+ <!-- feel free to make a PR to fix if anyone wants to see it return -->
203
+ <!-- <link rel="stylesheet" type="text/css" href="/themes/rosepine.css" />
204
+ <link rel="stylesheet" type="text/css" href="/themes/rosepine-dawn.css" /> -->
205
+ </svelte:head>
206
+
207
+ {#if loaded}
208
+ <slot />
209
+ {/if}
210
+
211
+ <Toaster richColors position="top-center" />