vp-menu-link.vue 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. <script lang="ts" setup>
  2. import { useRoute } from 'vitepress'
  3. import { useStorage } from '@vueuse/core'
  4. import VPLink from '../common/vp-link.vue'
  5. import { isActiveLink } from '../../utils'
  6. import type { Link } from '../../types'
  7. const USER_VISITED_NEW_RESOURCE_PAGE = 'USER_VISITED_NEW_RESOURCE_PAGE'
  8. defineProps<{
  9. item: Link
  10. }>()
  11. const route = useRoute()
  12. const isVisited = useStorage<boolean | string>(
  13. USER_VISITED_NEW_RESOURCE_PAGE,
  14. false
  15. )
  16. const isNewPage = (item: Link) => item.activeMatch === '/some_fake_path/'
  17. const onNavClick = (item: Link) => {
  18. if (isNewPage(item) && !isVisited.value) {
  19. isVisited.value = Date.now().toString()
  20. }
  21. }
  22. </script>
  23. <template>
  24. <VPLink
  25. :class="{
  26. 'is-menu-link': true,
  27. active: isActiveLink(
  28. route,
  29. item.activeMatch || item.link,
  30. !!item.activeMatch
  31. ),
  32. }"
  33. :href="item.link"
  34. :no-icon="true"
  35. @click="onNavClick(item)"
  36. >
  37. <el-badge v-if="isNewPage(item) && !isVisited" is-dot class="badge">
  38. {{ item.text }}</el-badge
  39. >
  40. <template v-else> {{ item.text }}</template>
  41. </VPLink>
  42. </template>
  43. <style scoped lang="scss">
  44. .is-menu-link {
  45. display: block;
  46. padding: 0 12px;
  47. line-height: calc(var(--nav-height) - 3px);
  48. font-size: 14px;
  49. font-weight: 500;
  50. color: var(--text-color);
  51. transition: color var(--el-transition-duration);
  52. border-bottom: 2px solid transparent;
  53. &.active {
  54. border-bottom-color: var(--brand-color);
  55. }
  56. &:hover {
  57. color: var(--brand-color);
  58. }
  59. .badge {
  60. display: inline;
  61. vertical-align: unset;
  62. }
  63. .badge:deep(.is-dot) {
  64. right: 0;
  65. }
  66. }
  67. </style>