index.tsx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. import { defineComponent, onMounted, reactive, ref } from 'vue';
  2. import styles from './index.module.less';
  3. import {
  4. NImage,
  5. NButton,
  6. NPopselect,
  7. NModal,
  8. useMessage,
  9. NSpin
  10. } from 'naive-ui';
  11. import headerD from './images/headerD.png';
  12. import defultHeade from '@/components/layout/images/teacherIcon.png';
  13. import blackBoardBg from './images/blackboard_bg.png';
  14. import teacherMan from './images/teacher_man.png';
  15. import teacherWoman from './images/teacher_woman.png';
  16. import homeText1 from './images/home/home-text-1.png';
  17. import homeText2 from './images/home/home-text-2.png';
  18. import iconTo from './images/icon-to.png';
  19. import t1 from './images/t1.png';
  20. import t2 from './images/t2.png';
  21. import t3 from './images/t3.png';
  22. import { useRouter } from 'vue-router';
  23. import { useUserStore } from '/src/store/modules/users';
  24. import SelectClass from './modals/selectClass';
  25. import dayjs from 'dayjs';
  26. import { gradeToCN, weekToCN } from '/src/utils/contants';
  27. import { useCatchStore } from '/src/store/modules/catchData';
  28. import TeachGroup from './modals/teachGroup';
  29. import { classGroupList, courseSchedulePage } from './api';
  30. import TheEmpty from '/src/components/TheEmpty';
  31. import HomeGuide from '/src/custom-plugins/guide-page/home-guide';
  32. import TimerMeter from '/src/components/timerMeter';
  33. import { vaildUrl } from '/src/utils/urlUtils';
  34. import { px2vw } from '/src/utils';
  35. import PlaceholderTone from '@/components/layout/modals/placeholderTone';
  36. import PreviewWindow from '../preview-window';
  37. import UpdatePassword from '/src/components/layout/modals/update-password';
  38. import AttendClass from '../prepare-lessons/model/attend-class';
  39. import { state } from '/src/state';
  40. export const formatDateToDay = () => {
  41. const hours = dayjs().hour();
  42. if (hours < 12) {
  43. return '早上好'; //如果小时数小于12则输出“早上好!”
  44. } else if (hours > 12 && hours < 18) {
  45. return '下午好'; //如果小时数大于12并且小于18,输入“下午好!”
  46. } else {
  47. return '晚上好'; //如果上面两个条件都不符合,则输出“晚上好!”
  48. }
  49. };
  50. export default defineComponent({
  51. name: 'home-page',
  52. setup() {
  53. const catchStore = useCatchStore();
  54. const message = useMessage();
  55. const router = useRouter();
  56. const userStore = useUserStore();
  57. const showUpdatePassword = ref(false);
  58. const showModalBeat = ref(false);
  59. const showModalTone = ref(false);
  60. const showModalTime = ref(false);
  61. const forms = reactive({
  62. showAttendClass: false,
  63. useStatus: false,
  64. studentList: [] as any,
  65. bookVersionId: null,
  66. classGroupId: null,
  67. category: null,
  68. subjectId: null,
  69. musicTagList: [] as any,
  70. loading: false,
  71. list: [] as any,
  72. unit: null,
  73. unitList: [],
  74. subjectList: [] as any,
  75. gradeList: [] as any,
  76. classLoading: false,
  77. total: 0, // 上课数量
  78. classSelect: {
  79. currentGradeNum: null,
  80. currentClass: null,
  81. name: ''
  82. } as any,
  83. popSelectOptions: [] as any,
  84. showGuide: false,
  85. showPreview: false,
  86. itemPreview: {} as any
  87. });
  88. const teachList = ref({} as any);
  89. // 学生列表
  90. // getStdentList
  91. const onUseConfirm = (item: any) => {
  92. forms.classSelect = {
  93. currentGradeNum: item.currentGradeNum,
  94. currentClass: item.classGroupId,
  95. name: item.name
  96. };
  97. getCourseSchedulePage();
  98. };
  99. // 获取年级班级
  100. const getClassList = async () => {
  101. try {
  102. const { data } = await classGroupList({ removeZeroClass: true });
  103. const cList = data || [];
  104. const gradeList: any = [];
  105. const popSelectOptions: any = [];
  106. cList.forEach((item: any, index: number) => {
  107. if (index === 0) {
  108. const temp = item.classGroupList[0];
  109. forms.classSelect = {
  110. currentGradeNum: item.currentGradeNum,
  111. currentClass: temp.id,
  112. name: temp.name
  113. };
  114. }
  115. const classList: any = [];
  116. item.classGroupList.forEach((i: any) => {
  117. classList.push({
  118. label: i.currentClass + '班',
  119. value: i.id,
  120. lastStudy: i.lastStudy
  121. });
  122. popSelectOptions.push({
  123. label: i.name,
  124. value: i.id,
  125. currentGradeNum: item.currentGradeNum,
  126. lastStudy: i.lastStudy
  127. });
  128. });
  129. gradeList.push({
  130. label: gradeToCN[item.currentGradeNum],
  131. value: item.currentGradeNum,
  132. childrens: classList
  133. });
  134. });
  135. forms.popSelectOptions = popSelectOptions;
  136. forms.gradeList = gradeList;
  137. } catch {
  138. //
  139. }
  140. };
  141. const getCourseSchedulePage = async () => {
  142. forms.classLoading = true;
  143. try {
  144. const { data } = await courseSchedulePage({
  145. classGroupId: forms.classSelect.currentClass,
  146. page: 1,
  147. rows: 4,
  148. teacherId: userStore.getUserInfo.id
  149. });
  150. const result = data.rows || [];
  151. forms.total = data.total || 0;
  152. const dateTime: any = {};
  153. result.forEach((item: any) => {
  154. const tempTime = dayjs(item.classDate).format('MM-DD');
  155. if (!dateTime[tempTime]) {
  156. dateTime[tempTime] = [];
  157. }
  158. const lessonCourseware = item.lessonCoursewareJson
  159. ? JSON.parse(item.lessonCoursewareJson)
  160. : {};
  161. dateTime[tempTime].push({
  162. classGroup: forms.classSelect.name,
  163. teacherName: item.teacherName,
  164. conent:
  165. lessonCourseware.lessonCoursewareName +
  166. ' | ' +
  167. lessonCourseware.lessonCoursewareDetailName +
  168. ' | ' +
  169. lessonCourseware.lessonCoursewareKnowledgeDetailName,
  170. image: item.teacherAvatar
  171. });
  172. });
  173. teachList.value = dateTime;
  174. } catch (e: any) {
  175. //
  176. console.log(e);
  177. }
  178. forms.classLoading = false;
  179. };
  180. onMounted(async () => {
  181. await getClassList();
  182. await catchStore.getSubjects();
  183. await getCourseSchedulePage();
  184. forms.subjectList = catchStore.getSubjectList.map((item: any) => {
  185. return {
  186. label: item.name,
  187. value: item.id
  188. };
  189. });
  190. if (!userStore.getUserInfo.account.updatePasswordFlag) {
  191. showUpdatePassword.value = true;
  192. } else {
  193. forms.showGuide = true;
  194. }
  195. });
  196. // const formsRef = ref();
  197. // const gotoClassPage = () => {
  198. // formsRef.value.validate(async (error: any) => {
  199. // if (error) return;
  200. // try {
  201. // const { data } = await queryCourseware({
  202. // coursewareDetailKnowledgeId: forms.unit,
  203. // subjectId: forms.subjectId,
  204. // page: 1,
  205. // rows: 99
  206. // });
  207. // if (data.rows && data.rows.length > 0) {
  208. // await courseScheduleStart({
  209. // lessonCoursewareKnowledgeDetailId: forms.unit,
  210. // classGroupId: forms.applyClassItem?.classGroupId
  211. // });
  212. // if (window.matchMedia('(display-mode: standalone)').matches) {
  213. // forms.showPreview = true;
  214. // forms.itemPreview = {
  215. // type: 'class',
  216. // classGroupId: forms.applyClassItem?.classGroupId,
  217. // subjectId: forms.subjectId,
  218. // detailId: forms.unit
  219. // };
  220. // globalState.application = window.matchMedia(
  221. // '(display-mode: standalone)'
  222. // ).matches;
  223. // // 加全屏
  224. // fscreen();
  225. // } else {
  226. // const { href } = router.resolve({
  227. // path: '/attend-class',
  228. // query: {
  229. // type: 'class',
  230. // classGroupId: forms.applyClassItem?.classGroupId,
  231. // subjectId: forms.subjectId,
  232. // detailId: forms.unit
  233. // }
  234. // });
  235. // window.open(href, +new Date() + '');
  236. // }
  237. // } else {
  238. // message.error('当前章节暂无课件,请重新选择');
  239. // }
  240. // } catch {
  241. // //
  242. // }
  243. // });
  244. // };
  245. const clearStorng = () => {
  246. localStorage.removeItem('teacher-guideInfo');
  247. forms.showGuide = false;
  248. setTimeout(() => {
  249. forms.showGuide = true;
  250. }, 500);
  251. };
  252. return () => (
  253. <div class={styles.homeWrap}>
  254. <div class={styles.homeInfoLeft}>
  255. <div class={styles.homeBanner}>
  256. <div class={styles.applyInfo} id="home-1">
  257. <div class={styles.centerInfo} id="home-0"></div>
  258. <div class={styles.userInfo}>
  259. <div class={styles.userName}>
  260. Hi,{userStore.getUserInfo?.nickname} {formatDateToDay()}~
  261. </div>
  262. </div>
  263. {userStore.getUserInfo.gender === 1 ? (
  264. <img src={teacherMan} class={styles.teacherMan} />
  265. ) : (
  266. <img src={teacherWoman} class={styles.teacherWoman} />
  267. )}
  268. <div class={styles.blackborad}>
  269. <img src={blackBoardBg} class={styles.blackBoardBg} />
  270. </div>
  271. <div class={styles.applyContainer}>
  272. <div class={[styles.applyItem, styles.applyItem1]}>
  273. <p>可根据声部进行备课,更好的规划教学</p>
  274. <div
  275. class={[styles.applyBtn, styles.applyBtn1]}
  276. onClick={() => {
  277. // 备课
  278. router.push({
  279. path: '/prepare-lessons'
  280. });
  281. }}>
  282. <img src={homeText1} />
  283. </div>
  284. </div>
  285. <div class={[styles.applyItem, styles.applyItem2]}>
  286. <p>点击这里,选择班级快速进入备课区域</p>
  287. <div
  288. class={[styles.applyBtn, styles.applyBtn2]}
  289. onClick={() => {
  290. forms.showAttendClass = true;
  291. }}>
  292. <img src={homeText2} />
  293. </div>
  294. </div>
  295. </div>
  296. </div>
  297. </div>
  298. <div class={styles.toolContainer}>
  299. <div class={styles.toolTips}>
  300. <div class={styles.toolTitle}>工具箱</div>
  301. <div class={styles.toolContent}>
  302. 这里是常用的教学辅助工具,可帮助学生集中注意力、提高演奏效率,使演奏更完整平稳。让您在课堂上完成更好的教学。
  303. </div>
  304. </div>
  305. <img src={iconTo} class={styles.iconTo} />
  306. <div class={styles.toolFunction} id="home-3">
  307. <div class={[styles.toolItem, styles.item1]}>
  308. <img src={t1} />
  309. {/* <p class={styles.toolMemo}>提升效率,练习好节奏</p> */}
  310. <NButton
  311. class={styles.btn1}
  312. onClick={() => {
  313. showModalBeat.value = true;
  314. }}>
  315. 节拍器
  316. </NButton>
  317. </div>
  318. <div class={[styles.toolItem, styles.item2]}>
  319. <img src={t2} />
  320. {/* <p class={styles.toolMemo}>精准调音,一劳永逸</p> */}
  321. <NButton
  322. class={styles.btn2}
  323. onClick={() => {
  324. showModalTone.value = true;
  325. }}>
  326. 调音器
  327. </NButton>
  328. </div>
  329. <div class={[styles.toolItem, styles.item3]}>
  330. <img src={t3} />
  331. {/* <p class={styles.toolMemo}>创造时间,集中注意力</p> */}
  332. <NButton
  333. class={styles.btn3}
  334. onClick={() => {
  335. showModalTime.value = true;
  336. }}>
  337. 计时器
  338. </NButton>
  339. </div>
  340. </div>
  341. </div>
  342. </div>
  343. <div class={styles.homeInfoRight}>
  344. <div class={styles.rightTeachingWrap}>
  345. <div class={styles.headerContainer}>
  346. <div
  347. class={styles.HeaderWrap}
  348. onClick={() => router.push('/setting')}>
  349. <NImage
  350. previewDisabled
  351. class={styles.headerD}
  352. src={headerD}></NImage>
  353. <NImage
  354. previewDisabled
  355. class={styles.defultHeade}
  356. src={userStore.getUserInfo.avatar || defultHeade}></NImage>
  357. </div>
  358. </div>
  359. <div class={styles.headerInfo}>
  360. <p class={styles.headerTitle}>{userStore.getUserInfo.nickname}</p>
  361. {userStore.getUserInfo.schoolInfos &&
  362. userStore.getUserInfo.schoolInfos.length > 0 && (
  363. <p class={styles.headerSubTitle}>
  364. {userStore.getUserInfo.schoolInfos[0].name}
  365. {/* | 音乐老师 */}
  366. </p>
  367. )}
  368. </div>
  369. <div class={styles.rightTeachingWrapTitle}>
  370. <h3 class={styles.rightTitle}>
  371. <div class={styles.titleDot}></div>上课记录
  372. </h3>
  373. {forms.classSelect.name && (
  374. <NPopselect
  375. v-model:value={forms.classSelect.currentClass}
  376. options={forms.popSelectOptions}
  377. trigger="click"
  378. onUpdate:value={(val: any) => {
  379. console.log(val, '1212');
  380. forms.popSelectOptions.forEach((item: any) => {
  381. if (item.value === val) {
  382. forms.classSelect = {
  383. currentGradeNum: item.currentGradeNum,
  384. currentClass: item.value,
  385. name: item.label
  386. };
  387. getCourseSchedulePage();
  388. }
  389. });
  390. }}>
  391. <div
  392. class={styles.lookMore}
  393. // onClick={() => (forms.useStatus = true)}
  394. >
  395. {forms.classSelect.name}
  396. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  397. <path
  398. d="M6 9l6 6l6-6"
  399. fill="none"
  400. stroke="currentColor"
  401. stroke-width="2"
  402. stroke-linecap="round"
  403. stroke-linejoin="round"></path>
  404. </svg>
  405. </div>
  406. </NPopselect>
  407. )}
  408. </div>
  409. <NSpin show={forms.classLoading} style={{ minHeight: '40vh' }}>
  410. {Object.keys(teachList.value).length > 0 && (
  411. <div class={styles.teachListWrap}>
  412. {Object.keys(teachList.value).map(key => (
  413. <TeachGroup
  414. list={teachList.value[key]}
  415. keys={key}></TeachGroup>
  416. ))}
  417. {forms.total > 4 && (
  418. <div class={styles.teachListWrapWall}>
  419. <span
  420. onClick={() => {
  421. // setTabsCaches('attendclass', 'tabName', {
  422. // path: '/classDetail'
  423. // });
  424. sessionStorage.setItem(
  425. 'classDetailTabs',
  426. 'attendclass'
  427. );
  428. router.push({
  429. path: '/classDetail',
  430. query: {
  431. name: forms.classSelect.name,
  432. id: forms.classSelect.currentClass
  433. }
  434. });
  435. }}>
  436. 查看全部
  437. </span>
  438. </div>
  439. )}
  440. </div>
  441. )}
  442. {Object.keys(teachList.value).length <= 0 &&
  443. !forms.classLoading && <TheEmpty />}
  444. </NSpin>
  445. </div>
  446. </div>
  447. <NModal
  448. v-model:show={forms.useStatus}
  449. preset="card"
  450. showIcon={false}
  451. class={['modalTitle background', styles.assignHomework]}
  452. title={'选择班级'}
  453. blockScroll={false}>
  454. <SelectClass
  455. useDetail={{
  456. currentGradeNum: forms.classSelect.currentGradeNum,
  457. classGroupId: forms.classSelect.currentClass
  458. }}
  459. gradeList={forms.gradeList}
  460. onConfirm={(item: any) => onUseConfirm(item)}
  461. onClose={() => (forms.useStatus = false)}
  462. />
  463. </NModal>
  464. <NModal
  465. class={['modalTitle background']}
  466. title={'节拍器'}
  467. preset="card"
  468. v-model:show={showModalBeat.value}
  469. style={{ width: '687px' }}>
  470. <div class={styles.modeWrap}>
  471. <iframe
  472. src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
  473. scrolling="no"
  474. frameborder="0"
  475. width="100%"
  476. height={'650px'}></iframe>
  477. </div>
  478. </NModal>
  479. <NModal
  480. v-model:show={showModalTime.value}
  481. class={['modalTitle background']}
  482. title={'计时器'}
  483. preset="card"
  484. style={{ width: px2vw(772) }}>
  485. <div>
  486. <TimerMeter></TimerMeter>
  487. </div>
  488. </NModal>
  489. <NModal class={['background']} v-model:show={showModalTone.value}>
  490. <div>
  491. <PlaceholderTone
  492. onClose={() => {
  493. showModalTone.value = false;
  494. }}></PlaceholderTone>
  495. </div>
  496. </NModal>
  497. {/* 弹窗查看 */}
  498. <PreviewWindow
  499. v-model:show={forms.showPreview}
  500. type="attend"
  501. params={forms.itemPreview}
  502. />
  503. {forms.showGuide ? <HomeGuide></HomeGuide> : null}
  504. <NModal
  505. v-model:show={showUpdatePassword.value}
  506. class={['modalTitle', styles.showUpdatePassword]}
  507. style="--n-title-font-weight: 600;"
  508. preset="card"
  509. title={'修改密码'}
  510. closable={false}
  511. maskClosable={false}
  512. closeOnEsc={false}>
  513. <UpdatePassword
  514. onSubmit={() => {
  515. // 密码更新成功
  516. showUpdatePassword.value = true;
  517. forms.showGuide = true;
  518. userStore.logout().then(() => {
  519. // 移除标签页
  520. router
  521. .replace({
  522. name: 'login'
  523. })
  524. .finally(() => location.reload());
  525. });
  526. }}
  527. />
  528. </NModal>
  529. <NModal
  530. v-model:show={forms.showAttendClass}
  531. preset="card"
  532. showIcon={false}
  533. class={['modalTitle background', styles.attendClassModal]}
  534. title={'选择班级'}
  535. blockScroll={false}>
  536. <AttendClass
  537. onClose={() => (forms.showAttendClass = false)}
  538. type="change"
  539. onConfirm={(item: any) => {
  540. router.push({
  541. path: '/prepare-lessons',
  542. query: {
  543. ...item
  544. }
  545. });
  546. }}
  547. />
  548. </NModal>
  549. </div>
  550. );
  551. }
  552. });