|
25 | 25 | {{ $t('all.private') }} |
26 | 26 | </div> |
27 | 27 | <div |
28 | | - class="flex cursor-pointer gap-1 border border-gray-300 bg-white px-2 pr-1 py-[3px] text-center text-xs text-gray-700 font-normal rounded-sm hover:bg-gray-50 active:ring-4 active:ring-gray-400 active:ring-opacity-25 active:bg-white" |
29 | | - :class=" |
30 | | - repoDetailStore.userLikes === true |
31 | | - ? 'text-gray-400 border-gray-200' |
32 | | - : '' |
33 | | - " |
| 28 | + class="flex gap-1 border border-gray-300 bg-white px-2 pr-1 py-[3px] text-center text-xs text-gray-700 font-normal rounded-sm hover:bg-gray-50 active:ring-4 active:ring-gray-400 active:ring-opacity-25 active:bg-white" |
| 29 | + :class="[ |
| 30 | + repoDetailStore.userLikes === true ? 'text-gray-400 border-gray-200' : '', |
| 31 | + isLikeLoading ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer' |
| 32 | + ]" |
34 | 33 | @click="clickLike"> |
35 | 34 | {{ |
36 | 35 | repoDetailStore.userLikes === false |
|
136 | 135 | {{ $t('all.private') }} |
137 | 136 | </div> |
138 | 137 | <div |
139 | | - class="flex cursor-pointer gap-1 border border-gray-300 bg-white px-2 pr-1 py-[3px] text-center text-xs text-gray-700 font-normal rounded-sm hover:bg-gray-50 active:ring-4 active:ring-gray-400 active:ring-opacity-25 active:bg-white" |
140 | | - :class=" |
141 | | - repoDetailStore.userLikes === true |
142 | | - ? 'text-gray-400 border-gray-200' |
143 | | - : '' |
144 | | - " |
| 138 | + class="flex gap-1 border border-gray-300 bg-white px-2 pr-1 py-[3px] text-center text-xs text-gray-700 font-normal rounded-sm hover:bg-gray-50 active:ring-4 active:ring-gray-400 active:ring-opacity-25 active:bg-white" |
| 139 | + :class="[ |
| 140 | + repoDetailStore.userLikes === true ? 'text-gray-400 border-gray-200' : '', |
| 141 | + isLikeLoading ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer' |
| 142 | + ]" |
145 | 143 | @click="clickLike"> |
146 | 144 | {{ |
147 | 145 | repoDetailStore.userLikes === false |
|
294 | 292 |
|
295 | 293 | const emit = defineEmits(['toggleSpaceLogsDrawer']) |
296 | 294 |
|
| 295 | + const isLikeLoading = ref(false) |
| 296 | +
|
297 | 297 | const props = defineProps({ |
298 | 298 | avatar: String, |
299 | 299 | name: String, |
|
358 | 358 | } |
359 | 359 | }) |
360 | 360 |
|
361 | | - const clickLike = () => { |
362 | | - repoDetailStore.userLikes === true ? removeLike() : addLike() |
| 361 | + const clickLike = async () => { |
| 362 | + // 如果正在加载中,直接返回,防止重复点击 |
| 363 | + if (isLikeLoading.value) { |
| 364 | + return |
| 365 | + } |
| 366 | + |
| 367 | + isLikeLoading.value = true |
| 368 | + |
| 369 | + try { |
| 370 | + if (repoDetailStore.userLikes === true) { |
| 371 | + await removeLike() |
| 372 | + } else { |
| 373 | + await addLike() |
| 374 | + } |
| 375 | + } finally { |
| 376 | + // 确保无论成功还是失败都要重置加载状态 |
| 377 | + isLikeLoading.value = false |
| 378 | + } |
363 | 379 | } |
364 | 380 |
|
365 | 381 | const addLike = async () => { |
366 | | - const { error } = await useFetchApi(likeUrl.value).put().json() |
367 | | - if (error.value) { |
368 | | - ElMessage({ |
369 | | - type: 'warning', |
370 | | - message: error.value.msg |
371 | | - }) |
372 | | - } else { |
373 | | - repoDetailStore.updateLikes(repoDetailStore.likes + 1) |
374 | | - repoDetailStore.updateUserLikes(true) |
| 382 | + const { error, response } = await useFetchApi(likeUrl.value).put().json() |
| 383 | + |
| 384 | + // 检查是否有错误或者响应状态码不是2xx |
| 385 | + if (error.value || (response.value && response.value?.status >= 400)) { |
| 386 | + // 如果是401状态码,不需要显示错误消息,因为会自动弹出登录对话框 |
| 387 | + if (response.value && response.value?.status !== 401) { |
| 388 | + ElMessage({ |
| 389 | + type: 'warning', |
| 390 | + message: error.value?.msg || '请求失败' |
| 391 | + }) |
| 392 | + } |
| 393 | + return |
375 | 394 | } |
| 395 | + |
| 396 | + repoDetailStore.updateLikes(repoDetailStore.likes + 1) |
| 397 | + repoDetailStore.updateUserLikes(true) |
376 | 398 | } |
377 | 399 |
|
378 | 400 | const removeLike = async () => { |
379 | | - const { error } = await useFetchApi(likeUrl.value).delete().json() |
380 | | - if (error.value) { |
381 | | - ElMessage({ |
382 | | - type: 'warning', |
383 | | - message: error.value.msg |
384 | | - }) |
385 | | - } else { |
386 | | - repoDetailStore.updateLikes(repoDetailStore.likes - 1) |
387 | | - repoDetailStore.updateUserLikes(false) |
| 401 | + const { error, response } = await useFetchApi(likeUrl.value).delete().json() |
| 402 | + |
| 403 | + // 检查是否有错误或者响应状态码不是2xx |
| 404 | + if (error.value || (response.value && response.value?.status >= 400)) { |
| 405 | + // 如果是401状态码,不需要显示错误消息,因为会自动弹出登录对话框 |
| 406 | + if (response.value && response.value?.status !== 401) { |
| 407 | + ElMessage({ |
| 408 | + type: 'warning', |
| 409 | + message: error.value?.msg || '请求失败' |
| 410 | + }) |
| 411 | + } |
| 412 | + return |
388 | 413 | } |
| 414 | + |
| 415 | + repoDetailStore.updateLikes(repoDetailStore.likes - 1) |
| 416 | + repoDetailStore.updateUserLikes(false) |
389 | 417 | } |
390 | 418 |
|
391 | 419 | const repoUrl = computed(() => { |
|
0 commit comments