layoutTop.tsx 9.1 KB

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