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