index.tsx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  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. classGroupId: forms.applyClassItem?.classGroupId,
  326. subjectId: forms.subjectId,
  327. detailId: forms.unit
  328. };
  329. globalState.application = window.matchMedia(
  330. '(display-mode: standalone)'
  331. ).matches;
  332. // 加全屏
  333. fscreen();
  334. } else {
  335. const { href } = router.resolve({
  336. path: '/attend-class',
  337. query: {
  338. type: 'class',
  339. classGroupId: forms.applyClassItem?.classGroupId,
  340. subjectId: forms.subjectId,
  341. detailId: forms.unit
  342. }
  343. });
  344. window.open(href, +new Date() + '');
  345. }
  346. } else {
  347. message.error('当前章节暂无课件,请重新选择');
  348. }
  349. } catch {
  350. //
  351. }
  352. });
  353. };
  354. const clearStorng = () => {
  355. localStorage.removeItem('teacher-guideInfo');
  356. forms.showGuide = false;
  357. setTimeout(() => {
  358. forms.showGuide = true;
  359. }, 500);
  360. };
  361. return () => (
  362. <div class={styles.homeWrap}>
  363. <div class={styles.homeInfoLeft}>
  364. <div class={styles.homeBanner}>
  365. {/* <div class={styles.welcomeInfo}>
  366. <div class={styles.userInfo}>
  367. <div class={styles.userName}>
  368. Hi,{userStore.getUserInfo?.nickname} {formatDateToDay()}~
  369. </div>
  370. <div class={styles.userTime}>
  371. {dayjs().format('MM月DD日')},{weekToCN[dayjs().day()]}
  372. </div>
  373. </div>
  374. <div class={styles.userTips}>
  375. <span>欢迎您使用酷乐秀课堂乐器数字化教学平台!</span>
  376. <NButton color="#40A1FF" round class={styles.guide_btn} {...{id:'home-1'}} onClick={()=>clearStorng()}>
  377. 功能引导
  378. <i></i>
  379. </NButton>
  380. </div>
  381. </div> */}
  382. {/* <div class={styles.centerInfo}>11111</div> */}
  383. <div class={styles.applyInfo} id="home-1">
  384. <div class={styles.centerInfo} id="home-0"></div>
  385. <div class={styles.userInfo}>
  386. <div class={styles.userName}>
  387. Hi,{userStore.getUserInfo?.nickname} {formatDateToDay()}~
  388. </div>
  389. {/* <div class={styles.userTime}>
  390. {dayjs().format('MM月DD日')},{weekToCN[dayjs().day()]}
  391. </div> */}
  392. </div>
  393. {userStore.getUserInfo.gender === 1 ? (
  394. <img src={teacherMan} class={styles.teacherMan} />
  395. ) : (
  396. <img src={teacherWoman} class={styles.teacherWoman} />
  397. )}
  398. <div class={styles.blackborad}>
  399. <img src={blackBoardBg} class={styles.blackBoardBg} />
  400. </div>
  401. <div class={styles.applyContainer}>
  402. <div class={styles.applyTitle}>
  403. <span
  404. class={styles.className}
  405. onClick={() => (forms.applyStatus = true)}>
  406. {forms.applyClassItem.name || '请选择班级'}
  407. </span>
  408. <NAvatarGroup options={forms.studentList} max={5} />
  409. </div>
  410. <div class={styles.informations}>
  411. {forms.applyClassItem.lastStudy ? (
  412. <>
  413. <span style="flex-shrink: 0;">上次课程:</span>
  414. <TheNoticeBar text={forms.applyClassItem.lastStudy} />
  415. </>
  416. ) : (
  417. ''
  418. )}
  419. </div>
  420. <NForm showLabel={false} ref={formsRef} model={forms}>
  421. <NFormItem
  422. path="bookVersionId"
  423. rule={[
  424. {
  425. required: true,
  426. message: '',
  427. trigger: ['blur', 'change']
  428. }
  429. ]}>
  430. <div class={styles.selectContainer}>
  431. <img src={iconLession} />
  432. <NSelect
  433. placeholder="请选择教材版本"
  434. disabled={
  435. forms.applyClassItem?.currentGradeNum ? false : true
  436. }
  437. clearable
  438. options={[...forms.musicTagList]}
  439. labelField="name"
  440. valueField="id"
  441. v-model:value={forms.bookVersionId}
  442. onUpdate:value={() => throttledFn()}
  443. />
  444. </div>
  445. </NFormItem>
  446. <NFormItem
  447. path="category"
  448. rule={[
  449. {
  450. required: true,
  451. message: '',
  452. trigger: ['blur', 'change']
  453. }
  454. ]}>
  455. <div class={styles.selectContainer}>
  456. <img src={iconBook} />
  457. <NSelect
  458. placeholder="请选择册别"
  459. options={[...forms.list]}
  460. clearable
  461. disabled={!forms.bookVersionId}
  462. v-model:value={forms.category}
  463. onUpdate:value={() => getunitList()}
  464. />
  465. </div>
  466. </NFormItem>
  467. <NFormItem
  468. path="unit"
  469. rule={[
  470. {
  471. required: true,
  472. message: '',
  473. trigger: ['blur', 'change']
  474. }
  475. ]}>
  476. <div class={styles.selectContainer}>
  477. <img src={iconDetail} />
  478. <NCascader
  479. disabled={!forms.category}
  480. {...({
  481. options: [...forms.unitList],
  482. placeholder: '选择章节',
  483. clearable: true
  484. } as any)}
  485. childrenField="knowledgeList"
  486. valueField="id"
  487. labelField="name"
  488. v-model:value={forms.unit}
  489. checkStrategy="child"
  490. expandTrigger="hover"
  491. />
  492. </div>
  493. </NFormItem>
  494. <NFormItem
  495. path="subjectId"
  496. rule={[
  497. {
  498. required: true,
  499. message: '',
  500. trigger: ['blur', 'change'],
  501. type: 'number'
  502. }
  503. ]}>
  504. <div class={styles.selectContainer}>
  505. <img src={iconSubject} />
  506. <NSelect
  507. {...({
  508. options: [...forms.subjectList],
  509. placeholder: '选择乐器',
  510. clearable: true
  511. } as any)}
  512. v-model:value={forms.subjectId}
  513. />
  514. </div>
  515. </NFormItem>
  516. <NSpace class={styles.btnGroup} justify="center">
  517. <NButton
  518. round
  519. block
  520. class={styles.startClass}
  521. color="#FF6E4C"
  522. onClick={gotoClassPage}>
  523. 开始上课
  524. </NButton>
  525. <NButton
  526. round
  527. block
  528. class={styles.beforClass}
  529. color="#5B64D1"
  530. onClick={() => {
  531. // 携带默认数据显示
  532. formsRef.value.validate(async (error: any) => {
  533. if (error) return;
  534. router.push({
  535. path: '/prepare-lessons',
  536. query: {
  537. lastUseCoursewareId: forms.category,
  538. unit: forms.unit,
  539. subjectId: forms.subjectId
  540. }
  541. });
  542. });
  543. }}>
  544. 去备课
  545. </NButton>
  546. </NSpace>
  547. </NForm>
  548. </div>
  549. </div>
  550. </div>
  551. <div class={styles.toolContainer}>
  552. <div class={styles.toolTips}>
  553. <div class={styles.toolTitle}>工具箱</div>
  554. <div class={styles.toolContent}>
  555. 这里是常用的教学辅助工具,可帮助学生集中注意力、提高演奏效率,使演奏更完整平稳。让您在课堂上完成更好的教学。
  556. </div>
  557. </div>
  558. <img src={iconTo} class={styles.iconTo} />
  559. <div class={styles.toolFunction} id="home-3">
  560. <div
  561. class={[styles.toolItem, styles.item1]}
  562. onClick={() => {
  563. showModalBeat.value = true;
  564. }}>
  565. <img src={t1} />
  566. <p class={styles.toolMemo}>提升效率,练习好节奏</p>
  567. <NButton class={styles.btn1}>节拍器</NButton>
  568. </div>
  569. <div
  570. class={[styles.toolItem, styles.item2]}
  571. onClick={() => {
  572. showModalTone.value = true;
  573. }}>
  574. <img src={t2} />
  575. <p class={styles.toolMemo}>精准调音,一劳永逸</p>
  576. <NButton class={styles.btn2}>调音器</NButton>
  577. </div>
  578. <div
  579. class={[styles.toolItem, styles.item3]}
  580. onClick={() => {
  581. showModalTime.value = true;
  582. }}>
  583. <img src={t3} />
  584. <p class={styles.toolMemo}>创造时间,集中注意力</p>
  585. <NButton class={styles.btn3}>计时器</NButton>
  586. </div>
  587. </div>
  588. </div>
  589. </div>
  590. <div class={styles.homeInfoRight}>
  591. <div class={styles.rightTeachingWrap}>
  592. <div class={styles.headerContainer}>
  593. <div
  594. class={styles.HeaderWrap}
  595. onClick={() => router.push('/setting')}>
  596. <NImage
  597. previewDisabled
  598. class={styles.headerD}
  599. src={headerD}></NImage>
  600. <NImage
  601. previewDisabled
  602. class={styles.defultHeade}
  603. src={userStore.getUserInfo.avatar || defultHeade}></NImage>
  604. </div>
  605. </div>
  606. <div class={styles.headerInfo}>
  607. <p class={styles.headerTitle}>{userStore.getUserInfo.nickname}</p>
  608. {userStore.getUserInfo.schoolInfos &&
  609. userStore.getUserInfo.schoolInfos.length > 0 && (
  610. <p class={styles.headerSubTitle}>
  611. {userStore.getUserInfo.schoolInfos[0].name}
  612. {/* | 音乐老师 */}
  613. </p>
  614. )}
  615. </div>
  616. <div class={styles.rightTeachingWrapTitle}>
  617. <h3 class={styles.rightTitle}>
  618. <div class={styles.titleDot}></div>上课记录
  619. </h3>
  620. {forms.classSelect.name && (
  621. <NPopselect
  622. v-model:value={forms.classSelect.currentClass}
  623. options={forms.popSelectOptions}
  624. trigger="click"
  625. onUpdate:value={(val: any) => {
  626. console.log(val, '1212');
  627. forms.popSelectOptions.forEach((item: any) => {
  628. if (item.value === val) {
  629. forms.classSelect = {
  630. currentGradeNum: item.currentGradeNum,
  631. currentClass: item.value,
  632. name: item.label
  633. };
  634. getCourseSchedulePage();
  635. }
  636. });
  637. }}>
  638. <div
  639. class={styles.lookMore}
  640. // onClick={() => (forms.useStatus = true)}
  641. >
  642. {forms.classSelect.name}
  643. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  644. <path
  645. d="M6 9l6 6l6-6"
  646. fill="none"
  647. stroke="currentColor"
  648. stroke-width="2"
  649. stroke-linecap="round"
  650. stroke-linejoin="round"></path>
  651. </svg>
  652. </div>
  653. </NPopselect>
  654. )}
  655. </div>
  656. <NSpin show={forms.classLoading} style={{ minHeight: '40vh' }}>
  657. {Object.keys(teachList.value).length > 0 && (
  658. <div class={styles.teachListWrap}>
  659. {Object.keys(teachList.value).map(key => (
  660. <TeachGroup
  661. list={teachList.value[key]}
  662. keys={key}></TeachGroup>
  663. ))}
  664. {forms.total > 4 && (
  665. <div class={styles.teachListWrapWall}>
  666. <span
  667. onClick={() => {
  668. // setTabsCaches('attendclass', 'tabName', {
  669. // path: '/classDetail'
  670. // });
  671. sessionStorage.setItem(
  672. 'classDetailTabs',
  673. 'attendclass'
  674. );
  675. router.push({
  676. path: '/classDetail',
  677. query: {
  678. name: forms.classSelect.name,
  679. id: forms.classSelect.currentClass
  680. }
  681. });
  682. }}>
  683. 查看全部
  684. </span>
  685. </div>
  686. )}
  687. </div>
  688. )}
  689. {Object.keys(teachList.value).length <= 0 &&
  690. !forms.classLoading && <TheEmpty />}
  691. </NSpin>
  692. </div>
  693. </div>
  694. {/* 添加自定义教材 */}
  695. <NModal
  696. v-model:show={forms.applyStatus}
  697. preset="card"
  698. showIcon={false}
  699. class={['modalTitle background', styles.assignHomework]}
  700. title={'选择班级'}
  701. blockScroll={false}>
  702. <SelectClass
  703. useDetail={{
  704. currentGradeNum: forms.applyClassItem.currentGradeNum,
  705. classGroupId: forms.applyClassItem.classGroupId
  706. }}
  707. gradeList={forms.gradeList}
  708. onConfirm={(item: any) => onApplyConfirm(item)}
  709. onClose={() => (forms.applyStatus = false)}
  710. />
  711. </NModal>
  712. <NModal
  713. v-model:show={forms.useStatus}
  714. preset="card"
  715. showIcon={false}
  716. class={['modalTitle background', styles.assignHomework]}
  717. title={'选择班级'}
  718. blockScroll={false}>
  719. <SelectClass
  720. useDetail={{
  721. currentGradeNum: forms.classSelect.currentGradeNum,
  722. classGroupId: forms.classSelect.currentClass
  723. }}
  724. gradeList={forms.gradeList}
  725. onConfirm={(item: any) => onUseConfirm(item)}
  726. onClose={() => (forms.useStatus = false)}
  727. />
  728. </NModal>
  729. <NModal
  730. class={['modalTitle background']}
  731. title={'节拍器'}
  732. preset="card"
  733. v-model:show={showModalBeat.value}
  734. style={{ width: '687px' }}>
  735. <div class={styles.modeWrap}>
  736. <iframe
  737. src={`${vaildUrl()}/metronome/?id=${new Date().getTime()}`}
  738. scrolling="no"
  739. frameborder="0"
  740. width="100%"
  741. height={'650px'}></iframe>
  742. </div>
  743. </NModal>
  744. <NModal
  745. v-model:show={showModalTime.value}
  746. class={['modalTitle background']}
  747. title={'计时器'}
  748. preset="card"
  749. style={{ width: px2vw(772) }}>
  750. <div>
  751. <TimerMeter></TimerMeter>
  752. </div>
  753. </NModal>
  754. <NModal class={['background']} v-model:show={showModalTone.value}>
  755. <div>
  756. <PlaceholderTone
  757. onClose={() => {
  758. showModalTone.value = false;
  759. }}></PlaceholderTone>
  760. </div>
  761. </NModal>
  762. {/* 弹窗查看 */}
  763. <PreviewWindow
  764. v-model:show={forms.showPreview}
  765. type="attend"
  766. params={forms.itemPreview}
  767. />
  768. {forms.showGuide ? <HomeGuide></HomeGuide> : null}
  769. <NModal
  770. v-model:show={showUpdatePassword.value}
  771. class={['modalTitle', styles.showUpdatePassword]}
  772. preset="card"
  773. title={'修改密码'}
  774. closable={false}
  775. maskClosable={false}
  776. closeOnEsc={false}>
  777. <UpdatePassword
  778. onSubmit={() => {
  779. // 密码更新成功
  780. showUpdatePassword.value = true;
  781. forms.showGuide = true;
  782. userStore.logout().then(() => {
  783. // 移除标签页
  784. router
  785. .replace({
  786. name: 'login'
  787. })
  788. .finally(() => location.reload());
  789. });
  790. }}
  791. />
  792. </NModal>
  793. </div>
  794. );
  795. }
  796. });