basic.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <script lang="ts" setup>
  2. import type { NotificationItem } from '@vben/layouts';
  3. import { computed, ref, watch } from 'vue';
  4. import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
  5. import { VBEN_DOC_URL, VBEN_GITHUB_URL } from '@vben/constants';
  6. import { useWatermark } from '@vben/hooks';
  7. import { BookOpenText, CircleHelp, SvgGithubIcon } from '@vben/icons';
  8. import {
  9. BasicLayout,
  10. LockScreen,
  11. Notification,
  12. UserDropdown,
  13. } from '@vben/layouts';
  14. import { preferences } from '@vben/preferences';
  15. import { useAccessStore, useUserStore } from '@vben/stores';
  16. import { openWindow } from '@vben/utils';
  17. import { $t } from '#/locales';
  18. import { useAuthStore } from '#/store';
  19. import LoginForm from '#/views/_core/authentication/login.vue';
  20. const notifications = ref<NotificationItem[]>([
  21. {
  22. id: 1,
  23. avatar: 'https://avatar.vercel.sh/vercel.svg?text=VB',
  24. date: '3小时前',
  25. isRead: true,
  26. message: '描述信息描述信息描述信息',
  27. title: '收到了 14 份新周报',
  28. },
  29. {
  30. id: 2,
  31. avatar: 'https://avatar.vercel.sh/1',
  32. date: '刚刚',
  33. isRead: false,
  34. message: '描述信息描述信息描述信息',
  35. title: '朱偏右 回复了你',
  36. },
  37. {
  38. id: 3,
  39. avatar: 'https://avatar.vercel.sh/1',
  40. date: '2024-01-01',
  41. isRead: false,
  42. message: '描述信息描述信息描述信息',
  43. title: '曲丽丽 评论了你',
  44. },
  45. {
  46. id: 4,
  47. avatar: 'https://avatar.vercel.sh/satori',
  48. date: '1天前',
  49. isRead: false,
  50. message: '描述信息描述信息描述信息',
  51. title: '代办提醒',
  52. },
  53. ]);
  54. const userStore = useUserStore();
  55. const authStore = useAuthStore();
  56. const accessStore = useAccessStore();
  57. const { destroyWatermark, updateWatermark } = useWatermark();
  58. const showDot = computed(() =>
  59. notifications.value.some((item) => !item.isRead),
  60. );
  61. const menus = computed(() => [
  62. {
  63. handler: () => {
  64. openWindow(VBEN_DOC_URL, {
  65. target: '_blank',
  66. });
  67. },
  68. icon: BookOpenText,
  69. text: $t('ui.widgets.document'),
  70. },
  71. {
  72. handler: () => {
  73. openWindow(VBEN_GITHUB_URL, {
  74. target: '_blank',
  75. });
  76. },
  77. icon: SvgGithubIcon,
  78. text: 'GitHub',
  79. },
  80. {
  81. handler: () => {
  82. openWindow(`${VBEN_GITHUB_URL}/issues`, {
  83. target: '_blank',
  84. });
  85. },
  86. icon: CircleHelp,
  87. text: $t('ui.widgets.qa'),
  88. },
  89. ]);
  90. const avatar = computed(() => {
  91. return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
  92. });
  93. async function handleLogout() {
  94. await authStore.logout(false);
  95. }
  96. function handleNoticeClear() {
  97. notifications.value = [];
  98. }
  99. function markRead(id: number | string) {
  100. const item = notifications.value.find((item) => item.id === id);
  101. if (item) {
  102. item.isRead = true;
  103. }
  104. }
  105. function remove(id: number | string) {
  106. notifications.value = notifications.value.filter((item) => item.id !== id);
  107. }
  108. function handleMakeAll() {
  109. notifications.value.forEach((item) => (item.isRead = true));
  110. }
  111. watch(
  112. () => ({
  113. enable: preferences.app.watermark,
  114. content: preferences.app.watermarkContent,
  115. }),
  116. async ({ enable, content }) => {
  117. if (enable) {
  118. await updateWatermark({
  119. content:
  120. content ||
  121. `${userStore.userInfo?.username} - ${userStore.userInfo?.realName}`,
  122. });
  123. } else {
  124. destroyWatermark();
  125. }
  126. },
  127. {
  128. immediate: true,
  129. },
  130. );
  131. </script>
  132. <template>
  133. <BasicLayout @clear-preferences-and-logout="handleLogout">
  134. <template #user-dropdown>
  135. <UserDropdown
  136. :avatar
  137. :menus
  138. :text="userStore.userInfo?.realName"
  139. description="ann.vben@gmail.com"
  140. tag-text="Pro"
  141. @logout="handleLogout"
  142. />
  143. </template>
  144. <template #notification>
  145. <Notification
  146. :dot="showDot"
  147. :notifications="notifications"
  148. @clear="handleNoticeClear"
  149. @read="(item) => item.id && markRead(item.id)"
  150. @remove="(item) => item.id && remove(item.id)"
  151. @make-all="handleMakeAll"
  152. />
  153. </template>
  154. <template #extra>
  155. <AuthenticationLoginExpiredModal
  156. v-model:open="accessStore.loginExpired"
  157. :avatar
  158. >
  159. <LoginForm />
  160. </AuthenticationLoginExpiredModal>
  161. </template>
  162. <template #lock-screen>
  163. <LockScreen :avatar @to-login="handleLogout" />
  164. </template>
  165. </BasicLayout>
  166. </template>