index copy.tsx 22 KB

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