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