UserInfo.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <script lang="ts" setup>
  2. import { ElMessageBox } from 'element-plus'
  3. import avatarImg from '@/assets/imgs/avatar.gif'
  4. import { useDesign } from '@/hooks/web/useDesign'
  5. import { useTagsViewStore } from '@/store/modules/tagsView'
  6. import { useUserStore } from '@/store/modules/user'
  7. import LockDialog from './components/LockDialog.vue'
  8. import LockPage from './components/LockPage.vue'
  9. import { useLockStore } from '@/store/modules/lock'
  10. defineOptions({ name: 'UserInfo' })
  11. const { t } = useI18n()
  12. const { push, replace } = useRouter()
  13. const userStore = useUserStore()
  14. const tagsViewStore = useTagsViewStore()
  15. const { getPrefixCls } = useDesign()
  16. const prefixCls = getPrefixCls('user-info')
  17. const avatar = computed(() => userStore.user.avatar || avatarImg)
  18. const userName = computed(() => userStore.user.nickname ?? 'Admin')
  19. // 锁定屏幕
  20. const lockStore = useLockStore()
  21. const getIsLock = computed(() => lockStore.getLockInfo?.isLock ?? false)
  22. const dialogVisible = ref<boolean>(false)
  23. const lockScreen = () => {
  24. dialogVisible.value = true
  25. }
  26. const loginOut = async () => {
  27. try {
  28. await ElMessageBox.confirm(t('common.loginOutMessage'), t('common.reminder'), {
  29. confirmButtonText: t('common.ok'),
  30. cancelButtonText: t('common.cancel'),
  31. type: 'warning'
  32. })
  33. await userStore.loginOut()
  34. tagsViewStore.delAllViews()
  35. replace('/login?redirect=/index')
  36. } catch {}
  37. }
  38. const toProfile = async () => {
  39. push('/user/profile')
  40. }
  41. const toDocument = () => {
  42. window.open('https://doc.iocoder.cn/')
  43. }
  44. </script>
  45. <template>
  46. <ElDropdown class="custom-hover" :class="prefixCls" trigger="click">
  47. <div class="flex items-center">
  48. <ElAvatar :src="avatar" alt="" class="w-[calc(var(--logo-height)-25px)] rounded-[50%]" />
  49. <span class="pl-[5px] text-14px text-[var(--top-header-text-color)] <lg:hidden">
  50. {{ userName }}
  51. </span>
  52. </div>
  53. <template #dropdown>
  54. <ElDropdownMenu>
  55. <ElDropdownItem>
  56. <Icon icon="ep:tools" />
  57. <div @click="toProfile">{{ t('common.profile') }}</div>
  58. </ElDropdownItem>
  59. <!-- <ElDropdownItem>
  60. <Icon icon="ep:menu" />
  61. <div @click="toDocument">{{ t('common.document') }}</div>
  62. </ElDropdownItem> -->
  63. <ElDropdownItem divided>
  64. <Icon icon="ep:lock" />
  65. <div @click="lockScreen">{{ t('lock.lockScreen') }}</div>
  66. </ElDropdownItem>
  67. <ElDropdownItem divided @click="loginOut">
  68. <Icon icon="ep:switch-button" />
  69. <div>{{ t('common.loginOut') }}</div>
  70. </ElDropdownItem>
  71. </ElDropdownMenu>
  72. </template>
  73. </ElDropdown>
  74. <LockDialog v-if="dialogVisible" v-model="dialogVisible" />
  75. <teleport to="body">
  76. <transition name="fade-bottom" mode="out-in">
  77. <LockPage v-if="getIsLock" />
  78. </transition>
  79. </teleport>
  80. </template>
  81. <style scoped lang="scss">
  82. .fade-bottom-enter-active,
  83. .fade-bottom-leave-active {
  84. transition:
  85. opacity 0.25s,
  86. transform 0.3s;
  87. }
  88. .fade-bottom-enter-from {
  89. opacity: 0;
  90. transform: translateY(-10%);
  91. }
  92. .fade-bottom-leave-to {
  93. opacity: 0;
  94. transform: translateY(10%);
  95. }
  96. </style>