index.tsx 23 KB

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