layoutTop.tsx 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import { defineComponent, ref, onMounted, onBeforeMount, nextTick } from 'vue';
  2. import styles from './index.module.less';
  3. import { NImage, NBadge, NPopover, NIcon, NModal, NTooltip } from 'naive-ui';
  4. import schoolIcon from './images/schoolIcon.png';
  5. import teacherIcon from './images/teacherIcon.png';
  6. import messageIcon from './images/messageIcon.png';
  7. import closeIcon from './images/closeIcon.png';
  8. import clockIcon from './images/clockIcon.png';
  9. import schoolDot from './images/schoolDot.png';
  10. import personIcon from './images/personIcon.png';
  11. import { useUserStore } from '@/store/modules/users';
  12. import { useRouter } from 'vue-router';
  13. import { storeToRefs } from 'pinia';
  14. import 'animate.css';
  15. import ForgotPassword from '/src/views/setting/modal/forgotPassword';
  16. import ImGroup from './imGroup';
  17. export default defineComponent({
  18. name: 'layoutTop',
  19. setup() {
  20. const router = useRouter();
  21. const noReadCount = ref(0); // 未读数
  22. const showHeadFlag = ref(false);
  23. const showImGroup = ref(false);
  24. const showImGroupLoading = ref(true);
  25. const users = useUserStore();
  26. const showWord = ref(false);
  27. const { info } = storeToRefs(users);
  28. const gotoPerson = () => {
  29. router.push({ path: '/setting', query: { activeTab: 'person' } });
  30. };
  31. const gotoSchool = () => {
  32. router.push({ path: '/setting', query: { activeTab: 'school' } });
  33. };
  34. const resetPwd = () => {
  35. showWord.value = true;
  36. };
  37. const body = document.querySelector('body');
  38. if (body) {
  39. body.className = 'myBody body';
  40. }
  41. onMounted(() => {
  42. window.addEventListener('message', onImMessage);
  43. showImGroup.value = true;
  44. nextTick(() => {
  45. setTimeout(() => {
  46. showImGroup.value = false;
  47. }, 50);
  48. setTimeout(() => {
  49. showImGroupLoading.value = false;
  50. if (body) {
  51. body.className = 'myBody';
  52. }
  53. }, 1000);
  54. });
  55. });
  56. const onImMessage = (evt: MessageEvent) => {
  57. if (evt.data.api === 'onImClose') {
  58. showImGroup.value = false;
  59. } else if (evt.data.api === 'getNoReadMessageCount') {
  60. // console.log(evt, 'onMessage');
  61. noReadCount.value = evt.data.count || 0;
  62. }
  63. };
  64. onBeforeMount(() => {
  65. window.removeEventListener('message', onImMessage);
  66. });
  67. return () => (
  68. <>
  69. <div class={styles.layoutTop}>
  70. <div class={styles.layoutLeft}>
  71. <NImage
  72. src={schoolIcon}
  73. class={styles.schoolIcon}
  74. previewDisabled></NImage>
  75. <p>
  76. {info.value.schoolInfos[0].tenantName} |{' '}
  77. {info.value.schoolInfos[0].name}
  78. </p>
  79. </div>
  80. <div class={styles.layoutRight}>
  81. <div onClick={() => (showImGroup.value = true)}>
  82. <NBadge
  83. value={noReadCount.value}
  84. max={99}
  85. class={[
  86. styles.messageBadge,
  87. noReadCount.value <= 0 ? styles.messageBadgeNo : ''
  88. ]}
  89. {...{ id: 'home-2' }}
  90. color={'#FF1036'}>
  91. <NImage
  92. class={[
  93. styles.messageIcon,
  94. noReadCount.value > 0 ? styles.animation : ''
  95. ]}
  96. preview-disabled
  97. src={messageIcon}></NImage>
  98. </NBadge>
  99. </div>
  100. <div class={styles.line}></div>
  101. <NPopover
  102. show-arrow={false}
  103. trigger="click"
  104. onUpdate:show={val => {
  105. showHeadFlag.value = val;
  106. }}
  107. class={styles.popoverHeader}
  108. placement="bottom-end"
  109. raw={true}
  110. v-slots={{
  111. trigger: () => (
  112. <div class={styles.mesgWrap}>
  113. <NImage
  114. preview-disabled
  115. class={styles.teacherIcon}
  116. src={
  117. info.value.avatar ? info.value.avatar : teacherIcon
  118. }></NImage>
  119. <NIcon
  120. class={
  121. showHeadFlag.value
  122. ? styles.rotueLeft
  123. : styles.rotueRight
  124. }>
  125. <svg
  126. xmlns="http://www.w3.org/2000/svg"
  127. viewBox="0 0 24 24">
  128. <path
  129. d="M7.38 21.01c.49.49 1.28.49 1.77 0l8.31-8.31a.996.996 0 0 0 0-1.41L9.15 2.98c-.49-.49-1.28-.49-1.77 0s-.49 1.28 0 1.77L14.62 12l-7.25 7.25c-.48.48-.48 1.28.01 1.76z"
  130. fill="currentColor"></path>
  131. </svg>
  132. </NIcon>
  133. </div>
  134. )
  135. }}>
  136. <div class={styles.propWrap}>
  137. <div class={styles.teacherInfo}>
  138. <NImage
  139. class={styles.teacherIcon}
  140. src={info.value.avatar ? info.value.avatar : teacherIcon}
  141. previewDisabled></NImage>
  142. <NTooltip class={styles.nameTool}>
  143. {{
  144. trigger: () => (
  145. <p class={styles.teacherName}>{info.value.nickname}</p>
  146. ),
  147. default: () => info.value.nickname
  148. }}
  149. </NTooltip>
  150. </div>
  151. <div class={styles.propWrapList}>
  152. <div class={styles.propWrapItem} onClick={() => gotoPerson()}>
  153. {' '}
  154. <NImage
  155. class={styles.smallIcon}
  156. src={personIcon}
  157. previewDisabled></NImage>
  158. <p class={styles.smallTitle}>个人信息</p>
  159. </div>
  160. {info.value.isSuperAdmin ? (
  161. <div
  162. class={styles.propWrapItem}
  163. onClick={() => {
  164. gotoSchool();
  165. }}>
  166. {' '}
  167. <NImage
  168. class={styles.smallIcon}
  169. src={schoolDot}
  170. previewDisabled></NImage>
  171. <p class={styles.smallTitle}>学校信息</p>
  172. </div>
  173. ) : null}
  174. <div class={styles.propWrapItem} onClick={() => resetPwd()}>
  175. {' '}
  176. <NImage
  177. class={styles.smallIcon}
  178. src={clockIcon}
  179. previewDisabled></NImage>
  180. <p class={styles.smallTitle}>修改密码</p>
  181. </div>
  182. </div>
  183. <div
  184. class={styles.logoutInfo}
  185. onClick={() => {
  186. users.logout();
  187. router.replace('/login');
  188. }}>
  189. <div class={styles.propWrapItem}>
  190. <NImage
  191. class={styles.smallIcon}
  192. src={closeIcon}
  193. previewDisabled></NImage>
  194. <p class={styles.smallTitle}>退出登录</p>
  195. </div>
  196. </div>
  197. </div>
  198. </NPopover>
  199. </div>
  200. <NModal
  201. class={styles.changePwdModal}
  202. v-model:show={showWord.value}
  203. preset="dialog"
  204. showIcon={false}
  205. title="修改密码">
  206. <ForgotPassword
  207. phone={info.value.phone}
  208. onClose={() => {
  209. showWord.value = false;
  210. }}
  211. />
  212. </NModal>
  213. <NModal
  214. v-model:show={showImGroup.value}
  215. showIcon={false}
  216. class={showImGroupLoading.value ? styles.hideModal : ''}
  217. {...{ id: 'imGroupDiv' }}
  218. displayDirective="show">
  219. <ImGroup />
  220. </NModal>
  221. </div>
  222. </>
  223. );
  224. }
  225. });