index.tsx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. import {
  2. defineComponent,
  3. onBeforeUnmount,
  4. onMounted,
  5. reactive,
  6. ref
  7. } from 'vue';
  8. import styles from './index.module.less';
  9. import {
  10. NImage,
  11. NButton,
  12. NAvatarGroup,
  13. NForm,
  14. NFormItem,
  15. NSelect,
  16. NPopselect,
  17. NSpace,
  18. NModal,
  19. NCascader,
  20. useMessage,
  21. NSpin
  22. } from 'naive-ui';
  23. import headerD from './images/headerD.png';
  24. import defultHeade from '@/components/layout/images/teacherIcon.png';
  25. import blackBoardBg from './images/blackboard_bg.png';
  26. import teacherMan from './images/teacher_man.png';
  27. import teacherWoman from './images/teacher_woman.png';
  28. import iconLession from './images/icon-lession.png';
  29. import iconBook from './images/icon-book.png';
  30. import iconDetail from './images/icon-detail.png';
  31. import iconSubject from './images/icon-subject.png';
  32. import iconTo from './images/icon-to.png';
  33. import t1 from './images/t1.png';
  34. import t2 from './images/t2.png';
  35. import t3 from './images/t3.png';
  36. import { useRouter } from 'vue-router';
  37. import { useUserStore } from '/src/store/modules/users';
  38. import SelectClass from './modals/selectClass';
  39. import dayjs from 'dayjs';
  40. import { gradeToCN, weekToCN } from '/src/utils/contants';
  41. import { getCLassStudent, getCourseChapter } from '../classList/api';
  42. import { useCatchStore } from '/src/store/modules/catchData';
  43. import { useThrottleFn } from '@vueuse/core';
  44. import {
  45. bookVersionPage,
  46. courseScheduleStart,
  47. lessonCoursewarePage,
  48. queryCourseware
  49. } from '../prepare-lessons/api';
  50. import TheNoticeBar from '/src/components/TheNoticeBar';
  51. import TeachGroup from './modals/teachGroup';
  52. import { classGroupList, courseSchedulePage } from './api';
  53. import TheEmpty from '/src/components/TheEmpty';
  54. import { setTabsCaches } from '/src/hooks/use-async';
  55. import HomeGuide from '/src/custom-plugins/guide-page/home-guide';
  56. import TimerMeter from '/src/components/timerMeter';
  57. import { vaildUrl } from '/src/utils/urlUtils';
  58. import toneImage from '@/components/layout/images/toneImage.png';
  59. import { px2vw } from '/src/utils';
  60. import PlaceholderTone from '@/components/layout/modals/placeholderTone';
  61. import { state } from '/src/state';
  62. import { fscreen } from '@/utils/index';
  63. import PreviewWindow from '../preview-window';
  64. import UpdatePassword from '/src/components/layout/modals/update-password';
  65. import { state as globalState } from '/src/state';
  66. export const formatDateToDay = () => {
  67. const hours = dayjs().hour();
  68. if (hours < 12) {
  69. return '早上好'; //如果小时数小于12则输出“早上好!”
  70. } else if (hours > 12 && hours < 18) {
  71. return '下午好'; //如果小时数大于12并且小于18,输入“下午好!”
  72. } else {
  73. return '晚上好'; //如果上面两个条件都不符合,则输出“晚上好!”
  74. }
  75. };
  76. export default defineComponent({
  77. name: 'home-page',
  78. setup() {
  79. const catchStore = useCatchStore();
  80. const message = useMessage();
  81. const router = useRouter();
  82. const userStore = useUserStore();
  83. const showUpdatePassword = ref(false);
  84. const showModalBeat = ref(false);
  85. const showModalTone = ref(false);
  86. const showModalTime = ref(false);
  87. const forms = reactive({
  88. applyClassItem: {} as any, // 选择的内容
  89. applyStatus: false,
  90. useStatus: false,
  91. studentList: [] as any,
  92. bookVersionId: null,
  93. classGroupId: null,
  94. category: null,
  95. subjectId: null,
  96. musicTagList: [] as any,
  97. loading: false,
  98. list: [] as any,
  99. unit: null,
  100. unitList: [],
  101. subjectList: [] as any,
  102. gradeList: [] as any,
  103. classLoading: false,
  104. total: 0, // 上课数量
  105. classSelect: {
  106. currentGradeNum: null,
  107. currentClass: null,
  108. name: ''
  109. } as any,
  110. popSelectOptions: [] as any,
  111. showGuide: false,
  112. showPreview: false,
  113. itemPreview: {} as any
  114. });
  115. const teachList = ref({} as any);
  116. // 学生列表
  117. // getStdentList
  118. // 应用选择年级班级
  119. const onApplyConfirm = async (item: any) => {
  120. try {
  121. //
  122. const { data } = await getCLassStudent({
  123. page: 1,
  124. rows: 999,
  125. classGroupId: item.classGroupId
  126. });
  127. const temps = data.rows || [];
  128. temps.forEach((row: any) => {
  129. forms.studentList.push({
  130. name: row.nickname,
  131. src: row.avatar
  132. });
  133. });
  134. forms.applyClassItem = item;
  135. } catch {
  136. //
  137. }
  138. };
  139. const onUseConfirm = (item: any) => {
  140. forms.classSelect = {
  141. currentGradeNum: item.currentGradeNum,
  142. currentClass: item.classGroupId,
  143. name: item.name
  144. };
  145. getCourseSchedulePage();
  146. };
  147. const throttledFn = useThrottleFn(() => getLessonCourseware(), 500);
  148. const getLessonCourseware = async () => {
  149. forms.category = null;
  150. forms.unit = null;
  151. forms.category = null;
  152. forms.loading = true;
  153. try {
  154. const { data } = await lessonCoursewarePage({
  155. bookVersionId: forms.bookVersionId,
  156. enableFlag: 1,
  157. page: 1,
  158. rows: 99,
  159. type: 'COURSEWARE'
  160. // currentGradeNum: forms.applyClassItem.currentGradeNum
  161. });
  162. forms.list = data.rows.map((item: any) => {
  163. return {
  164. label: item.name,
  165. value: item.id
  166. };
  167. });
  168. } catch {
  169. //
  170. }
  171. forms.loading = false;
  172. };
  173. const getunitList = async () => {
  174. forms.unit = null;
  175. try {
  176. if (forms.category) {
  177. const res = await getCourseChapter(forms.category);
  178. forms.unitList = res.data.lessonList.map((item: any) => {
  179. return { ...item, label: item.name, value: item.id };
  180. });
  181. } else {
  182. forms.unitList = [];
  183. }
  184. } catch (e) {
  185. console.log(e);
  186. }
  187. };
  188. const getVersion = async () => {
  189. forms.unit = null;
  190. try {
  191. const { data } = await bookVersionPage({
  192. page: 1,
  193. rows: 99,
  194. type: 'COURSEWARE'
  195. });
  196. const temp = data.rows || [];
  197. temp.forEach((item: any) => {
  198. forms.musicTagList.push({
  199. id: item.id,
  200. name: item.name
  201. });
  202. });
  203. } catch {
  204. //
  205. }
  206. };
  207. // 获取年级班级
  208. const getClassList = async () => {
  209. try {
  210. const { data } = await classGroupList({ removeZeroClass: true });
  211. const cList = data || [];
  212. const gradeList: any = [];
  213. const popSelectOptions: any = [];
  214. cList.forEach((item: any, index: number) => {
  215. if (index === 0) {
  216. const temp = item.classGroupList[0];
  217. forms.classSelect = {
  218. currentGradeNum: item.currentGradeNum,
  219. currentClass: temp.id,
  220. name: temp.name
  221. };
  222. }
  223. const classList: any = [];
  224. item.classGroupList.forEach((i: any) => {
  225. classList.push({
  226. label: i.currentClass + '班',
  227. value: i.id,
  228. lastStudy: i.lastStudy
  229. });
  230. popSelectOptions.push({
  231. label: i.name,
  232. value: i.id,
  233. currentGradeNum: item.currentGradeNum,
  234. lastStudy: i.lastStudy
  235. });
  236. });
  237. gradeList.push({
  238. label: gradeToCN[item.currentGradeNum],
  239. value: item.currentGradeNum,
  240. childrens: classList
  241. });
  242. });
  243. forms.popSelectOptions = popSelectOptions;
  244. forms.gradeList = gradeList;
  245. } catch {
  246. //
  247. }
  248. };
  249. const getCourseSchedulePage = async () => {
  250. forms.classLoading = true;
  251. try {
  252. const { data } = await courseSchedulePage({
  253. classGroupId: forms.classSelect.currentClass,
  254. page: 1,
  255. rows: 4,
  256. teacherId: userStore.getUserInfo.id
  257. });
  258. const result = data.rows || [];
  259. forms.total = data.total || 0;
  260. const dateTime: any = {};
  261. result.forEach((item: any) => {
  262. const tempTime = dayjs(item.classDate).format('MM-DD');
  263. if (!dateTime[tempTime]) {
  264. dateTime[tempTime] = [];
  265. }
  266. const lessonCourseware = item.lessonCoursewareJson
  267. ? JSON.parse(item.lessonCoursewareJson)
  268. : {};
  269. dateTime[tempTime].push({
  270. classGroup: forms.classSelect.name,
  271. teacherName: item.teacherName,
  272. conent:
  273. lessonCourseware.lessonCoursewareName +
  274. ' | ' +
  275. lessonCourseware.lessonCoursewareDetailName +
  276. ' | ' +
  277. lessonCourseware.lessonCoursewareKnowledgeDetailName,
  278. image: item.teacherAvatar
  279. });
  280. });
  281. teachList.value = dateTime;
  282. } catch (e: any) {
  283. //
  284. console.log(e);
  285. }
  286. forms.classLoading = false;
  287. };
  288. onMounted(async () => {
  289. await getClassList();
  290. await catchStore.getSubjects();
  291. await getCourseSchedulePage();
  292. forms.subjectList = catchStore.getSubjectList.map((item: any) => {
  293. return {
  294. label: item.name,
  295. value: item.id
  296. };
  297. });
  298. getVersion();
  299. if (!userStore.getUserInfo.account.updatePasswordFlag) {
  300. showUpdatePassword.value = true;
  301. } else {
  302. forms.showGuide = true;
  303. }
  304. });
  305. const formsRef = ref();
  306. const gotoClassPage = () => {
  307. formsRef.value.validate(async (error: any) => {
  308. if (error) return;
  309. try {
  310. const { data } = await queryCourseware({
  311. coursewareDetailKnowledgeId: forms.unit,
  312. subjectId: forms.subjectId,
  313. page: 1,
  314. rows: 99
  315. });
  316. if (data.rows && data.rows.length > 0) {
  317. await courseScheduleStart({
  318. lessonCoursewareKnowledgeDetailId: forms.unit,
  319. classGroupId: forms.applyClassItem?.classGroupId
  320. });
  321. if (window.matchMedia('(display-mode: standalone)').matches) {
  322. forms.showPreview = true;
  323. forms.itemPreview = {
  324. type: 'class',
  325. lessonCourseId: forms.bookVersionId,
  326. classGroupId: forms.applyClassItem?.classGroupId,
  327. subjectId: forms.subjectId,
  328. detailId: forms.unit
  329. };
  330. globalState.application = window.matchMedia(
  331. '(display-mode: standalone)'
  332. ).matches;
  333. // 加全屏
  334. fscreen();
  335. } else {
  336. const { href } = router.resolve({
  337. path: '/attend-class',
  338. query: {
  339. type: 'class',
  340. lessonCourseId: forms.bookVersionId,
  341. classGroupId: forms.applyClassItem?.classGroupId,
  342. subjectId: forms.subjectId,
  343. detailId: forms.unit
  344. }
  345. });
  346. window.open(href, +new Date() + '');
  347. }
  348. } else {
  349. message.error('当前章节暂无课件,请重新选择');
  350. }
  351. } catch {
  352. //
  353. }
  354. });
  355. };
  356. const clearStorng = () => {
  357. localStorage.removeItem('teacher-guideInfo');
  358. forms.showGuide = false;
  359. setTimeout(() => {
  360. forms.showGuide = true;
  361. }, 500);
  362. };
  363. return () => (
  364. <div class={styles.homeWrap}>
  365. <div class={styles.homeInfoLeft}>
  366. <div class={styles.homeBanner}>
  367. {/* <div class={styles.welcomeInfo}>
  368. <div class={styles.userInfo}>
  369. <div class={styles.userName}>
  370. Hi,{userStore.getUserInfo?.nickname} {formatDateToDay()}~
  371. </div>
  372. <div class={styles.userTime}>
  373. {dayjs().format('MM月DD日')},{weekToCN[dayjs().day()]}
  374. </div>
  375. </div>
  376. <div class={styles.userTips}>
  377. <span>欢迎您使用酷乐秀课堂乐器数字化教学平台!</span>
  378. <NButton color="#40A1FF" round class={styles.guide_btn} {...{id:'home-1'}} onClick={()=>clearStorng()}>
  379. 功能引导
  380. <i></i>
  381. </NButton>
  382. </div>
  383. </div> */}
  384. {/* <div class={styles.centerInfo}>11111</div> */}
  385. <div class={styles.applyInfo} id="home-1">
  386. <div class={styles.centerInfo} id="home-0"></div>
  387. <div class={styles.userInfo}>
  388. <div class={styles.userName}>
  389. Hi,{userStore.getUserInfo?.nickname} {formatDateToDay()}~
  390. </div>
  391. {/* <div class={styles.userTime}>
  392. {dayjs().format('MM月DD日')},{weekToCN[dayjs().day()]}
  393. </div> */}
  394. </div>
  395. {userStore.getUserInfo.gender === 1 ? (
  396. <img src={teacherMan} class={styles.teacherMan} />
  397. ) : (
  398. <img src={teacherWoman} class={styles.teacherWoman} />
  399. )}
  400. <div class={styles.blackborad}>
  401. <img src={blackBoardBg} class={styles.blackBoardBg} />
  402. </div>
  403. <div class={styles.applyContainer}>
  404. <div class={styles.applyTitle}>
  405. <span
  406. class={styles.className}
  407. onClick={() => (forms.applyStatus = true)}>
  408. {forms.applyClassItem.name || '请选择班级'}
  409. </span>
  410. <NAvatarGroup options={forms.studentList} max={5} />
  411. </div>
  412. <div class={styles.informations}>
  413. {forms.applyClassItem.lastStudy ? (
  414. <>
  415. <span style="flex-shrink: 0;">上次课程:</span>
  416. <TheNoticeBar text={forms.applyClassItem.lastStudy} />
  417. </>
  418. ) : (
  419. ''
  420. )}
  421. </div>
  422. <NForm showLabel={false} ref={formsRef} model={forms}>
  423. <NFormItem
  424. path="bookVersionId"
  425. rule={[
  426. {
  427. required: true,
  428. message: '',
  429. trigger: ['blur', 'change']
  430. }
  431. ]}>
  432. <div class={styles.selectContainer}>
  433. <img src={iconLession} />
  434. <NSelect
  435. placeholder="请选择教材版本"
  436. disabled={
  437. forms.applyClassItem?.currentGradeNum ? false : true
  438. }
  439. clearable
  440. options={[...forms.musicTagList]}
  441. labelField="name"
  442. valueField="id"
  443. v-model:value={forms.bookVersionId}
  444. onUpdate:value={() => throttledFn()}
  445. />
  446. </div>
  447. </NFormItem>
  448. <NFormItem
  449. path="category"
  450. rule={[
  451. {
  452. required: true,
  453. message: '',
  454. trigger: ['blur', 'change']
  455. }
  456. ]}>
  457. <div class={styles.selectContainer}>
  458. <img src={iconBook} />
  459. <NSelect
  460. placeholder="请选择册别"
  461. options={[...forms.list]}
  462. clearable
  463. disabled={!forms.bookVersionId}
  464. v-model:value={forms.category}
  465. onUpdate:value={() => getunitList()}
  466. />
  467. </div>
  468. </NFormItem>
  469. <NFormItem
  470. path="unit"
  471. rule={[
  472. {
  473. required: true,
  474. message: '',
  475. trigger: ['blur', 'change']
  476. }
  477. ]}>
  478. <div class={styles.selectContainer}>
  479. <img src={iconDetail} />
  480. <NCascader
  481. disabled={!forms.category}
  482. {...({
  483. options: [...forms.unitList],
  484. placeholder: '选择章节',
  485. clearable: true
  486. } as any)}
  487. childrenField="knowledgeList"
  488. valueField="id"
  489. labelField="name"
  490. v-model:value={forms.unit}
  491. checkStrategy="child"
  492. expandTrigger="hover"
  493. />
  494. </div>
  495. </NFormItem>
  496. <NFormItem
  497. path="subjectId"
  498. rule={[
  499. {
  500. required: true,
  501. message: '',
  502. trigger: ['blur', 'change'],
  503. type: 'number'
  504. }
  505. ]}>
  506. <div class={styles.selectContainer}>
  507. <img src={iconSubject} />
  508. <NSelect
  509. {...({
  510. options: [...forms.subjectList],
  511. placeholder: '选择乐器',
  512. clearable: true
  513. } as any)}
  514. v-model:value={forms.subjectId}
  515. />
  516. </div>
  517. </NFormItem>
  518. <NSpace class={styles.btnGroup} justify="center">
  519. <NButton
  520. round
  521. block
  522. class={styles.startClass}
  523. color="#FF6E4C"
  524. onClick={gotoClassPage}>
  525. 开始上课
  526. </NButton>
  527. <NButton
  528. round
  529. block
  530. class={styles.beforClass}
  531. color="#5B64D1"
  532. onClick={() => {
  533. // 携带默认数据显示
  534. formsRef.value.validate(async (error: any) => {
  535. if (error) return;
  536. router.push({
  537. path: '/prepare-lessons',
  538. query: {
  539. lastUseCoursewareId: forms.category,
  540. unit: forms.unit,
  541. subjectId: forms.subjectId
  542. }
  543. });
  544. });
  545. }}>
  546. 去备课
  547. </NButton>
  548. </NSpace>
  549. </NForm>
  550. </div>
  551. </div>
  552. </div>
  553. <div class={styles.toolContainer}>
  554. <div class={styles.toolTips}>
  555. <div class={styles.toolTitle}>工具箱</div>
  556. <div class={styles.toolContent}>
  557. 这里是常用的教学辅助工具,可帮助学生集中注意力、提高演奏效率,使演奏更完整平稳。让您在课堂上完成更好的教学。
  558. </div>
  559. </div>
  560. <img src={iconTo} class={styles.iconTo} />
  561. <div class={styles.toolFunction} id="home-3">
  562. <div
  563. class={[styles.toolItem, styles.item1]}
  564. onClick={() => {
  565. showModalBeat.value = true;
  566. }}>
  567. <img src={t1} />
  568. <p class={styles.toolMemo}>提升效率,练习好节奏</p>
  569. <NButton class={styles.btn1}>节拍器</NButton>
  570. </div>
  571. <div
  572. class={[styles.toolItem, styles.item2]}
  573. onClick={() => {
  574. showModalTone.value = true;
  575. }}>
  576. <img src={t2} />
  577. <p class={styles.toolMemo}>精准调音,一劳永逸</p>
  578. <NButton class={styles.btn2}>调音器</NButton>
  579. </div>
  580. <div
  581. class={[styles.toolItem, styles.item3]}
  582. onClick={() => {
  583. showModalTime.value = true;
  584. }}>
  585. <img src={t3} />
  586. <p class={styles.toolMemo}>创造时间,集中注意力</p>
  587. <NButton class={styles.btn3}>计时器</NButton>
  588. </div>
  589. </div>
  590. </div>
  591. </div>
  592. <div class={styles.homeInfoRight}>
  593. <div class={styles.rightTeachingWrap}>
  594. <div class={styles.headerContainer}>
  595. <div
  596. class={styles.HeaderWrap}
  597. onClick={() => router.push('/setting')}>
  598. <NImage
  599. previewDisabled
  600. class={styles.headerD}
  601. src={headerD}></NImage>
  602. <NImage
  603. previewDisabled
  604. class={styles.defultHeade}
  605. src={userStore.getUserInfo.avatar || defultHeade}></NImage>
  606. </div>
  607. </div>
  608. <div class={styles.headerInfo}>
  609. <p class={styles.headerTitle}>{userStore.getUserInfo.nickname}</p>
  610. {userStore.getUserInfo.schoolInfos &&
  611. userStore.getUserInfo.schoolInfos.length > 0 && (
  612. <p class={styles.headerSubTitle}>
  613. {userStore.getUserInfo.schoolInfos[0].name}
  614. {/* | 音乐老师 */}
  615. </p>
  616. )}
  617. </div>
  618. <div class={styles.rightTeachingWrapTitle}>
  619. <h3 class={styles.rightTitle}>
  620. <div class={styles.titleDot}></div>上课记录
  621. </h3>
  622. {forms.classSelect.name && (
  623. <NPopselect
  624. v-model:value={forms.classSelect.currentClass}
  625. options={forms.popSelectOptions}
  626. trigger="click"
  627. onUpdate:value={(val: any) => {
  628. console.log(val, '1212');
  629. forms.popSelectOptions.forEach((item: any) => {
  630. if (item.value === val) {
  631. forms.classSelect = {
  632. currentGradeNum: item.currentGradeNum,
  633. currentClass: item.value,
  634. name: item.label
  635. };
  636. getCourseSchedulePage();
  637. }
  638. });
  639. }}>
  640. <div
  641. class={styles.lookMore}
  642. // onClick={() => (forms.useStatus = true)}
  643. >
  644. {forms.classSelect.name}
  645. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  646. <path
  647. d="M6 9l6 6l6-6"
  648. fill="none"
  649. stroke="currentColor"
  650. stroke-width="2"
  651. stroke-linecap="round"
  652. stroke-linejoin="round"></path>
  653. </svg>
  654. </div>
  655. </NPopselect>
  656. )}
  657. </div>
  658. <NSpin show={forms.classLoading} style={{ minHeight: '40vh' }}>
  659. {Object.keys(teachList.value).length > 0 && (
  660. <div class={styles.teachListWrap}>
  661. {Object.keys(teachList.value).map(key => (
  662. <TeachGroup
  663. list={teachList.value[key]}
  664. keys={key}></TeachGroup>
  665. ))}
  666. {forms.total > 4 && (
  667. <div class={styles.teachListWrapWall}>
  668. <span
  669. onClick={() => {
  670. // setTabsCaches('attendclass', 'tabName', {
  671. // path: '/classDetail'
  672. // });
  673. sessionStorage.setItem(
  674. 'classDetailTabs',
  675. 'attendclass'
  676. );
  677. router.push({
  678. path: '/classDetail',
  679. query: {
  680. name: forms.classSelect.name,
  681. id: forms.classSelect.currentClass
  682. }
  683. });
  684. }}>
  685. 查看全部
  686. </span>
  687. </div>
  688. )}
  689. </div>
  690. )}
  691. {Object.keys(teachList.value).length <= 0 &&
  692. !forms.classLoading && <TheEmpty />}
  693. </NSpin>
  694. </div>
  695. </div>
  696. {/* 添加自定义教材 */}
  697. <NModal
  698. v-model:show={forms.applyStatus}
  699. preset="card"
  700. showIcon={false}
  701. class={['modalTitle background', styles.assignHomework]}
  702. title={'选择班级'}
  703. blockScroll={false}>
  704. <SelectClass
  705. useDetail={{
  706. currentGradeNum: forms.applyClassItem.currentGradeNum,
  707. classGroupId: forms.applyClassItem.classGroupId
  708. }}
  709. gradeList={forms.gradeList}
  710. onConfirm={(item: any) => onApplyConfirm(item)}
  711. onClose={() => (forms.applyStatus = false)}
  712. />
  713. </NModal>
  714. <NModal
  715. v-model:show={forms.useStatus}
  716. preset="card"
  717. showIcon={false}
  718. class={['modalTitle background', styles.assignHomework]}
  719. title={'选择班级'}
  720. blockScroll={false}>
  721. <SelectClass
  722. useDetail={{
  723. currentGradeNum: forms.classSelect.currentGradeNum,
  724. classGroupId: forms.classSelect.currentClass
  725. }}
  726. gradeList={forms.gradeList}
  727. onConfirm={(item: any) => onUseConfirm(item)}
  728. onClose={() => (forms.useStatus = false)}
  729. />
  730. </NModal>
  731. <NModal
  732. class={['modalTitle background']}
  733. title={'节拍器'}
  734. preset="card"
  735. v-model:show={showModalBeat.value}
  736. style={{ width: '687px' }}>
  737. <div class={styles.modeWrap}>
  738. <iframe
  739. src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
  740. scrolling="no"
  741. frameborder="0"
  742. width="100%"
  743. height={'650px'}></iframe>
  744. </div>
  745. </NModal>
  746. <NModal
  747. v-model:show={showModalTime.value}
  748. class={['modalTitle background']}
  749. title={'计时器'}
  750. preset="card"
  751. style={{ width: px2vw(772) }}>
  752. <div>
  753. <TimerMeter></TimerMeter>
  754. </div>
  755. </NModal>
  756. <NModal class={['background']} v-model:show={showModalTone.value}>
  757. <div>
  758. <PlaceholderTone
  759. onClose={() => {
  760. showModalTone.value = false;
  761. }}></PlaceholderTone>
  762. </div>
  763. </NModal>
  764. {/* 弹窗查看 */}
  765. <PreviewWindow
  766. v-model:show={forms.showPreview}
  767. type="attend"
  768. params={forms.itemPreview}
  769. />
  770. {forms.showGuide ? <HomeGuide></HomeGuide> : null}
  771. <NModal
  772. v-model:show={showUpdatePassword.value}
  773. class={['modalTitle', styles.showUpdatePassword]}
  774. style="--n-title-font-weight: 600;"
  775. preset="card"
  776. title={'修改密码'}
  777. closable={false}
  778. maskClosable={false}
  779. closeOnEsc={false}>
  780. <UpdatePassword
  781. onSubmit={() => {
  782. // 密码更新成功
  783. showUpdatePassword.value = true;
  784. forms.showGuide = true;
  785. userStore.logout().then(() => {
  786. // 移除标签页
  787. router
  788. .replace({
  789. name: 'login'
  790. })
  791. .finally(() => location.reload());
  792. });
  793. }}
  794. />
  795. </NModal>
  796. </div>
  797. );
  798. }
  799. });