index.tsx 21 KB

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