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 styles2 from './suggestion-option.module.less';
  5. import schoolIcon from './images/schoolIcon.png';
  6. import teacherIcon from './images/teacherIcon.png';
  7. import messageIcon from './images/messageIcon.png';
  8. import closeIcon from './images/closeIcon.png';
  9. import clockIcon from './images/clockIcon.png';
  10. import schoolDot from './images/schoolDot.png';
  11. import personIcon from './images/personIcon.png';
  12. import { useUserStore } from '@/store/modules/users';
  13. import { useRouter } from 'vue-router';
  14. import { storeToRefs } from 'pinia';
  15. import opinionIcon from './images/opinionIcon.png';
  16. import 'animate.css';
  17. import ForgotPassword from '/src/views/setting/modal/forgotPassword';
  18. import ImGroup from './imGroup';
  19. import SuggestionOption from './modals/suggestion-option';
  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. </p>
  83. </div>
  84. <div class={styles.layoutRight}>
  85. <NTooltip>
  86. {{
  87. trigger: () => (
  88. <div
  89. class={styles.optons}
  90. onClick={() => (showSuggestionViseble.value = true)}>
  91. <NImage src={opinionIcon} previewDisabled></NImage>
  92. </div>
  93. ),
  94. default: '意见反馈'
  95. }}
  96. </NTooltip>
  97. {/* </div> */}
  98. <div onClick={() => (showImGroup.value = true)}>
  99. <NBadge
  100. value={noReadCount.value}
  101. max={99}
  102. class={[
  103. noReadCount.value > 0 ? '' : styles.messageBadgeHide,
  104. styles.messageBadge,
  105. noReadCount.value > 0 ? '' : styles.messageBadgeNo
  106. ]}
  107. {...{ id: 'home-2' }}
  108. color={'#FF1036'}>
  109. <NImage
  110. class={[
  111. styles.messageIcon,
  112. noReadCount.value > 0 ? styles.animation : ''
  113. ]}
  114. preview-disabled
  115. src={messageIcon}></NImage>
  116. </NBadge>
  117. </div>
  118. <div class={styles.line}></div>
  119. <NPopover
  120. show-arrow={false}
  121. trigger="click"
  122. onUpdate:show={val => {
  123. showHeadFlag.value = val;
  124. }}
  125. class={styles.popoverHeader}
  126. placement="bottom-end"
  127. raw={true}
  128. v-slots={{
  129. trigger: () => (
  130. <div class={styles.mesgWrap}>
  131. <NImage
  132. preview-disabled
  133. class={styles.teacherIcon}
  134. src={
  135. info.value.avatar ? info.value.avatar : teacherIcon
  136. }></NImage>
  137. <NIcon
  138. class={
  139. showHeadFlag.value
  140. ? styles.rotueLeft
  141. : styles.rotueRight
  142. }>
  143. <svg
  144. xmlns="http://www.w3.org/2000/svg"
  145. viewBox="0 0 24 24">
  146. <path
  147. 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"
  148. fill="currentColor"></path>
  149. </svg>
  150. </NIcon>
  151. </div>
  152. )
  153. }}>
  154. <div class={styles.propWrap}>
  155. <div class={styles.teacherInfo}>
  156. <NImage
  157. class={styles.teacherIcon}
  158. src={info.value.avatar ? info.value.avatar : teacherIcon}
  159. previewDisabled></NImage>
  160. <NTooltip class={styles.nameTool}>
  161. {{
  162. trigger: () => (
  163. <p class={styles.teacherName}>{info.value.nickname}</p>
  164. ),
  165. default: () => info.value.nickname
  166. }}
  167. </NTooltip>
  168. </div>
  169. <div class={styles.propWrapList}>
  170. <div class={styles.propWrapItem} onClick={() => gotoPerson()}>
  171. {' '}
  172. <NImage
  173. class={styles.smallIcon}
  174. src={personIcon}
  175. previewDisabled></NImage>
  176. <p class={styles.smallTitle}>个人信息</p>
  177. </div>
  178. {info.value.isSuperAdmin ? (
  179. <div
  180. class={styles.propWrapItem}
  181. onClick={() => {
  182. gotoSchool();
  183. }}>
  184. {' '}
  185. <NImage
  186. class={styles.smallIcon}
  187. src={schoolDot}
  188. previewDisabled></NImage>
  189. <p class={styles.smallTitle}>学校信息</p>
  190. </div>
  191. ) : null}
  192. <div class={styles.propWrapItem} onClick={() => resetPwd()}>
  193. {' '}
  194. <NImage
  195. class={styles.smallIcon}
  196. src={clockIcon}
  197. previewDisabled></NImage>
  198. <p class={styles.smallTitle}>修改密码</p>
  199. </div>
  200. </div>
  201. <div
  202. class={styles.logoutInfo}
  203. onClick={() => {
  204. users.logout();
  205. router.replace('/login');
  206. }}>
  207. <div class={styles.propWrapItem}>
  208. <NImage
  209. class={styles.smallIcon}
  210. src={closeIcon}
  211. previewDisabled></NImage>
  212. <p class={styles.smallTitle}>退出登录</p>
  213. </div>
  214. </div>
  215. </div>
  216. </NPopover>
  217. </div>
  218. <NModal
  219. class={styles.changePwdModal}
  220. v-model:show={showWord.value}
  221. preset="dialog"
  222. showIcon={false}
  223. title="修改密码">
  224. <ForgotPassword
  225. phone={info.value.phone}
  226. onClose={() => {
  227. showWord.value = false;
  228. }}
  229. />
  230. </NModal>
  231. <NModal
  232. v-model:show={showImGroup.value}
  233. showIcon={false}
  234. class={showImGroupLoading.value ? styles.hideModal : ''}
  235. {...{ id: 'imGroupDiv' }}
  236. displayDirective="show">
  237. <ImGroup />
  238. </NModal>
  239. <NModal
  240. class={['modalTitle', 'background', styles.suggestWrap]}
  241. v-model:show={showSuggestionViseble.value}
  242. preset="card"
  243. display-directive='show'
  244. showIcon={false}>
  245. <SuggestionOption
  246. onClose={() =>
  247. (showSuggestionViseble.value = false)
  248. }></SuggestionOption>
  249. </NModal>
  250. </div>
  251. </>
  252. );
  253. }
  254. });