58
58
<div class =" dropdown" >
59
59
<button class =" btn dropdown-toggle d-flex align-items-center flex-row "
60
60
:class =" { 'btn-outline-light': isDarkMode, 'btn-dark': !isDarkMode }" type =" button"
61
- data-bs-toggle =" dropdown" :data-bs-theme =" isDarkMode ? 'dark' : ''" aria-expanded =" false" >
61
+ data-bs-toggle =" dropdown" :data-bs-theme =" isDarkMode ? 'dark' : ''" aria-expanded =" false"
62
+ @click =" getUserInfo" >
62
63
<span v-if =" !store.user" >
63
64
{{ t('user.SignIn') }}
64
65
</span >
70
71
</span >
71
72
</button >
72
73
<ul class =" dropdown-menu dropdown-menu-end" :data-bs-theme =" isDarkMode ? 'dark' : ''" >
74
+ <li v-if =" store.user" class =" dropdown-header d-flex flex-column" >
75
+ <span >{{ t('user.Fields.User') }} : {{store.user.displayName}}</span >
76
+ <span >{{ t('user.Fields.CreatedAt') }} : {{ unixToDateTime(store.user.metadata.createdAt) }}</span >
77
+ <span >{{ t('user.Fields.Level') }} :  ;
78
+ <span v-if =" userInfoFetched" >{{ t('user.Level.' + userInfo.userLevel)}}</span >
79
+ <span v-else >{{ t('user.Fields.Fetching') }}</span >
80
+ </span >
81
+ <span >{{ t('user.Fields.FunctionUses') }} :  ;
82
+ <span v-if =" userInfoFetched" >{{ userInfo.functionUses.total }}
83
+ {{ t('user.Fields.Times') }}
84
+ </span >
85
+ <span v-else >{{ t('user.Fields.Fetching') }}</span >
86
+ </span >
87
+ </li >
88
+ <li v-if =" store.user" >
89
+ <hr class =" dropdown-divider" />
90
+ </li >
73
91
<li v-if =" !store.user" ><a type =" button" class =" dropdown-item" @click =" store.signInWithGoogle" ><i
74
92
class =" bi bi-google" ></i > {{ t('user.SignInWithGoogle') }}</a ></li >
75
93
<li v-if =" !store.user" ><a type =" button" class =" dropdown-item" @click =" store.signInWithGithub" ><i
76
94
class =" bi bi-github" ></i > {{ t('user.SignInWithGithub') }}</a ></li >
77
- <li v-if =" store.user" ><a type =" button" class =" dropdown-item" @click =" store.signOut" ><i
78
- class =" bi bi-box-arrow-right" ></i > {{ t('user.SignOut')
79
- }}</a ></li >
80
- <li >
95
+ <li v-if =" !store.user" >
81
96
<hr class =" dropdown-divider" />
82
97
</li >
83
98
<li ><a type =" button" class =" dropdown-item" @click =" openUserBenefits" ><i class =" bi bi-award-fill" ></i > {{
84
99
t('user.Benefits.Title') }}</a ></li >
100
+ <li v-if =" store.user" >
101
+ <hr class =" dropdown-divider" />
102
+ </li >
103
+ <li v-if =" store.user" ><a type =" button" class =" dropdown-item" @click =" store.signOut" ><i
104
+ class =" bi bi-box-arrow-right" ></i > {{ t('user.SignOut')
105
+ }}</a >
106
+ </li >
85
107
</ul >
86
108
</div >
87
109
</div >
@@ -142,6 +164,7 @@ import { useMainStore } from '@/store';
142
164
import { useI18n } from ' vue-i18n' ;
143
165
import { trackEvent } from ' @/utils/use-analytics' ;
144
166
import { Offcanvas , Modal } from ' bootstrap' ;
167
+ import { authenticatedFetch } from ' @/utils/authenticated-fetch' ;
145
168
146
169
const { t } = useI18n ();
147
170
@@ -157,6 +180,9 @@ const loaded = ref(false);
157
180
const currentSection = computed (() => store .currentSection );
158
181
const isFireBaseSet = computed (() => store .isFireBaseSet );
159
182
183
+ const userInfo = ref ({});
184
+ const userInfoFetched = ref (false );
185
+
160
186
// 打开偏好设置
161
187
const OpenPreferences = () => {
162
188
const offcanvasElement = document .getElementById (' offcanvasPreferences' );
@@ -170,17 +196,6 @@ const OpenPreferences = () => {
170
196
trackEvent (' Nav' , ' NavClick' , ' Preferences' );
171
197
};
172
198
173
- // 打开 Modal
174
- const openUserBenefits = () => {
175
- const modalElement = document .getElementById (' Benefits' );
176
- const modalInstance = Modal .getOrCreateInstance (modalElement);
177
- if (modalInstance) {
178
- modalInstance .show ();
179
- }
180
-
181
- trackEvent (' Nav' , ' NavClick' , ' UserBenefits' );
182
- };
183
-
184
199
// 点击 Logo 事件处理
185
200
const handleLogoClick = () => {
186
201
if (window .scrollY === 0 ) {
@@ -197,6 +212,48 @@ const scrollToSection = (el, offset = 70) => {
197
212
window .scrollTo ({ top: y, behavior: " smooth" });
198
213
}
199
214
215
+ // 转换 Unix 时间
216
+ const unixToDateTime = (timestamp ) => {
217
+ timestamp = Number (timestamp);
218
+ const options = {
219
+ year: ' numeric' ,
220
+ month: ' long' ,
221
+ day: ' numeric' ,
222
+ };
223
+ const date = new Date (timestamp);
224
+ return date .toLocaleString (undefined , options);
225
+ }
226
+
227
+ // 打开 Modal
228
+ const openUserBenefits = () => {
229
+ const modalElement = document .getElementById (' Benefits' );
230
+ const modalInstance = Modal .getOrCreateInstance (modalElement);
231
+ if (modalInstance) {
232
+ modalInstance .show ();
233
+ }
234
+
235
+ trackEvent (' Nav' , ' NavClick' , ' UserBenefits' );
236
+ };
237
+
238
+ // 获取用户统计信息
239
+ const getUserInfo = async () => {
240
+ if (userInfoFetched .value ) {
241
+ return ;
242
+ }
243
+ if (! store .user ) {
244
+ return ;
245
+ }
246
+ try {
247
+ const response = await authenticatedFetch (` /api/getuserinfo` );
248
+ const data = response;
249
+ userInfo .value = data;
250
+ } catch (error) {
251
+ console .error (' Error fetching user info:' , error);
252
+ }
253
+
254
+ userInfoFetched .value = true ;
255
+ };
256
+
200
257
watch (() => store .allHasLoaded , (newValue ) => {
201
258
loaded .value = newValue;
202
259
});
0 commit comments