index.tsx 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. import { defineComponent, nextTick, onMounted, reactive, watch } from 'vue';
  2. import styles from './index.module.less';
  3. import {
  4. NButton,
  5. NModal,
  6. NScrollbar,
  7. NSelect,
  8. NSpace,
  9. NSpin,
  10. useMessage,
  11. useDialog
  12. } from 'naive-ui';
  13. import CardType from '/src/components/card-type';
  14. import AttendClass from '/src/views/prepare-lessons/model/attend-class';
  15. import { usePrepareStore } from '/src/store/modules/prepareLessons';
  16. import { useCatchStore } from '/src/store/modules/catchData';
  17. import TheEmpty from '/src/components/TheEmpty';
  18. import {
  19. courseScheduleStart,
  20. queryCourseware,
  21. saveCourseware,
  22. teacherKnowledgeMaterialDelete
  23. } from '../../../api';
  24. import Draggable from 'vuedraggable';
  25. import iconDelete from '../../../images/icon-delete.png';
  26. import iconAddMusic from '../../../images/icon-add-music.png';
  27. import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
  28. import deepClone from '/src/helpers/deep-clone';
  29. import CardPreview from '/src/components/card-preview';
  30. import PreviewWindow from '/src/views/preview-window';
  31. import { state } from '/src/state';
  32. import SubjectSync from '../../../model/subject-sync';
  33. import { eventGlobal } from '/src/utils';
  34. import iconTips from '../../../images/icon-tips.png';
  35. import { useElementBounding } from '@vueuse/core';
  36. export default defineComponent({
  37. name: 'courseware-modal',
  38. setup() {
  39. const catchStore = useCatchStore();
  40. const prepareStore = usePrepareStore();
  41. const route = useRoute();
  42. const router = useRouter();
  43. const dialog = useDialog();
  44. const message = useMessage();
  45. const localStorageSubjectId = localStorage.getItem(
  46. 'prepareLessonSubjectId'
  47. );
  48. const forms = reactive({
  49. tipsStatus: localStorage.getItem('prepare-lesson-courseware-tip')
  50. ? true
  51. : false,
  52. className: route.query.name as any,
  53. classGroupId: route.query.classGroupId,
  54. preStudentNum: route.query.preStudentNum,
  55. courseScheduleSubjectId: route.query.courseScheduleSubjectId,
  56. // 选取参数带的,后取缓存
  57. subjectId: route.query.subjectId
  58. ? Number(route.query.subjectId)
  59. : localStorageSubjectId
  60. ? Number(localStorageSubjectId)
  61. : null,
  62. coursewareList: [] as any,
  63. loadingStatus: false,
  64. showAttendClass: false,
  65. attendClassType: 'change', //
  66. removeIds: [] as any, // 临时删除的编号
  67. drag: false,
  68. isEdit: false, // 是否更新数据
  69. editSubjectIds: '', // 声部编号
  70. removeVisiable: false,
  71. removeVisiable1: false,
  72. subjectSyncVisiable: false, // 同步声部
  73. show: false,
  74. item: {} as any,
  75. previewModal: false,
  76. previewParams: {
  77. type: '',
  78. subjectId: '',
  79. detailId: ''
  80. } as any
  81. });
  82. // 获取列表
  83. const getList = async () => {
  84. forms.loadingStatus = true;
  85. try {
  86. // 判断是否有选择对应的课件 或声部
  87. if (!prepareStore.getSelectKey || !prepareStore.getSubjectId)
  88. return (forms.loadingStatus = false);
  89. const { data } = await queryCourseware({
  90. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  91. subjectId: prepareStore.getSubjectId,
  92. page: 1,
  93. rows: 99
  94. });
  95. const tempRows = data.rows || [];
  96. const temp: any = [];
  97. tempRows.forEach((row: any) => {
  98. temp.push({
  99. id: row.id,
  100. materialId: row.materialId,
  101. coverImg: row.coverImg,
  102. type: row.materialType,
  103. title: row.materialName,
  104. isCollect: !!row.favoriteFlag,
  105. isSelected: row.source === 'PLATFORM' ? true : false,
  106. content: row.content,
  107. removeFlag: row.removeFlag
  108. });
  109. });
  110. prepareStore.setCoursewareList(temp || []);
  111. const tempCourse: any = [];
  112. temp.forEach((item: any) => {
  113. if (!forms.removeIds.includes(item.id)) {
  114. tempCourse.push(item);
  115. }
  116. });
  117. forms.coursewareList = tempCourse;
  118. } catch {
  119. //
  120. }
  121. forms.loadingStatus = false;
  122. };
  123. // 监听选择的key 左侧选择了其它的课
  124. watch(
  125. () => prepareStore.getSelectKey,
  126. () => {
  127. forms.drag = false;
  128. prepareStore.setIsEditResource(false);
  129. getList();
  130. }
  131. );
  132. // 声部变化时
  133. watch(
  134. () => prepareStore.getSubjectId,
  135. () => {
  136. getList();
  137. }
  138. );
  139. watch(
  140. () => prepareStore.getIsAddResource,
  141. (val: boolean) => {
  142. if (val) {
  143. getList();
  144. prepareStore.setIsAddResource(false);
  145. }
  146. }
  147. );
  148. // 监听列表变化,如果变化了,则弹选择声部的
  149. watch(
  150. () => forms.coursewareList,
  151. () => {
  152. if (forms.drag) {
  153. forms.isEdit = true;
  154. }
  155. },
  156. {
  157. deep: true
  158. }
  159. );
  160. // 删除
  161. const onDelete = (item: any) => {
  162. //
  163. forms.removeIds.push(item.id);
  164. const index = forms.coursewareList.findIndex(
  165. (c: any) => c.id === item.id
  166. );
  167. forms.coursewareList.splice(index, 1);
  168. forms.isEdit = true;
  169. // prepareStore.setCoursewareList(forms.coursewareList);
  170. // console.log(prepareStore.getCoursewareList, 'getCourseware');
  171. };
  172. // 完成编辑
  173. const onOverEdit = async () => {
  174. try {
  175. const temp: any = [];
  176. forms.coursewareList.forEach((item: any) => {
  177. temp.push({
  178. materialName: item.title,
  179. materialType: item.type,
  180. materialId: item.materialId,
  181. id: item.id
  182. });
  183. });
  184. // 保存课件
  185. // 判断是否编辑,如果编辑则取选择的声部
  186. await saveCourseware({
  187. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  188. lessonCoursewareId: prepareStore.getLessonCoursewareId,
  189. lessonCoursewareDetailId: prepareStore.getLessonCoursewareDetailId,
  190. subjectId: forms.isEdit
  191. ? forms.editSubjectIds
  192. : prepareStore.getSubjectId,
  193. materialList: [...temp]
  194. });
  195. forms.drag = false;
  196. message.success('编辑成功');
  197. forms.removeVisiable = false;
  198. prepareStore.setIsEditResource(false);
  199. // 重置临时删除编号
  200. forms.removeIds = [];
  201. await getList();
  202. } catch {
  203. //
  204. }
  205. };
  206. // 预览上课
  207. const onPreviewAttend = () => {
  208. // 获取上架的数据
  209. let count = 0;
  210. forms.coursewareList.forEach((item: any) => {
  211. if (!item.removeFlag) {
  212. count++;
  213. }
  214. });
  215. if (count <= 0) {
  216. message.error('课件不能为空');
  217. return;
  218. }
  219. // 判断是否在应用里面
  220. if (window.matchMedia('(display-mode: standalone)').matches) {
  221. state.application = window.matchMedia(
  222. '(display-mode: standalone)'
  223. ).matches;
  224. forms.previewModal = true;
  225. fscreen();
  226. forms.previewParams = {
  227. type: 'preview',
  228. instrumentId: prepareStore.getInstrumentId,
  229. detailId: prepareStore.getSelectKey,
  230. lessonCourseId: prepareStore.getBaseCourseware.id
  231. };
  232. } else {
  233. const { href } = router.resolve({
  234. path: '/attend-class',
  235. query: {
  236. type: 'preview',
  237. instrumentId: prepareStore.getInstrumentId,
  238. detailId: prepareStore.getSelectKey,
  239. lessonCourseId: prepareStore.getBaseCourseware.id
  240. }
  241. });
  242. window.open(href, +new Date() + '');
  243. }
  244. };
  245. const fscreen = () => {
  246. const el: any = document.documentElement;
  247. const documentDom: any = document;
  248. const isFullscreen =
  249. documentDom.fullScreen ||
  250. documentDom.mozFullScreen ||
  251. documentDom.webkitIsFullScreen;
  252. if (!isFullscreen) {
  253. //进入全屏
  254. (el.requestFullscreen && el.requestFullscreen()) ||
  255. (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
  256. (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
  257. (el.msRequestFullscreen && el.msRequestFullscreen());
  258. }
  259. };
  260. // 单个删除
  261. const onRemove = async (item: any) => {
  262. try {
  263. dialog.warning({
  264. title: '提示',
  265. content: '该资源已下架,是否删除?',
  266. positiveText: '确定',
  267. negativeText: '取消',
  268. onPositiveClick: async () => {
  269. forms.removeIds.push(item.id);
  270. await teacherKnowledgeMaterialDelete({ ids: item.id });
  271. message.success('删除成功');
  272. getList();
  273. }
  274. });
  275. } catch {
  276. //
  277. }
  278. };
  279. watch(
  280. () => prepareStore.getSubjectList,
  281. () => {
  282. checkSubjectIds();
  283. }
  284. );
  285. const checkSubjectIds = () => {
  286. const subjectList = prepareStore.getSubjectList;
  287. // 并且没有声部时才会更新
  288. if (subjectList.length > 0) {
  289. // 并且声部在列表中
  290. const localStorageSubjectId = localStorage.getItem(
  291. 'prepareLessonSubjectId'
  292. );
  293. // // 先取 上次上课声部,在取班级声部 最后取缓存
  294. let subjectId = null;
  295. let index = -1;
  296. if (forms.courseScheduleSubjectId) {
  297. // 判断浏览器上面是否有
  298. index = subjectList.findIndex(
  299. (subject: any) => subject.id == forms.courseScheduleSubjectId
  300. );
  301. if (index >= 0) {
  302. subjectId = Number(forms.courseScheduleSubjectId);
  303. }
  304. }
  305. // 判断班级上面声部 & 还没有声部
  306. if (forms.subjectId && !subjectId) {
  307. // 判断浏览器上面是否有
  308. index = subjectList.findIndex(
  309. (subject: any) => subject.id == forms.subjectId
  310. );
  311. if (index >= 0) {
  312. subjectId = Number(forms.subjectId);
  313. }
  314. }
  315. // 缓存声部 & 还没有声部
  316. if (localStorageSubjectId && !subjectId) {
  317. // 判断浏览器上面是否有
  318. index = subjectList.findIndex(
  319. (subject: any) => subject.id == localStorageSubjectId
  320. );
  321. if (index >= 0) {
  322. subjectId = Number(localStorageSubjectId);
  323. }
  324. }
  325. if (subjectId && index >= 0) {
  326. prepareStore.setSubjectId(subjectId);
  327. } else {
  328. // 判断是否有缓存
  329. prepareStore.setSubjectId(subjectList[0].id);
  330. }
  331. // 保存
  332. localStorage.setItem(
  333. 'prepareLessonSubjectId',
  334. prepareStore.getSubjectId as any
  335. );
  336. }
  337. };
  338. watch(
  339. () => route.query,
  340. async () => {
  341. forms.className = route.query.name as any;
  342. forms.classGroupId = route.query.classGroupId as any;
  343. forms.preStudentNum = route.query.preStudentNum as any;
  344. forms.subjectId = route.query.subjectId
  345. ? Number(route.query.subjectId)
  346. : null;
  347. prepareStore.setClassGroupId(forms.classGroupId as any);
  348. checkSubjectIds();
  349. await getList();
  350. }
  351. );
  352. const isPointInsideElement = (element: any, x: number, y: number) => {
  353. const rect = element.getBoundingClientRect();
  354. return (
  355. x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
  356. );
  357. };
  358. const isPointOnLeft = (element: any, x: number) => {
  359. const rect = element.getBoundingClientRect();
  360. const elementCenterX = rect.left + rect.width / 2;
  361. return x < elementCenterX;
  362. };
  363. onMounted(async () => {
  364. prepareStore.setClassGroupId(route.query.classGroupId as any);
  365. // 获取教材分类列表
  366. checkSubjectIds();
  367. await getList();
  368. // 动态添加数据
  369. eventGlobal.on('onPrepareAddItem', (item: any, point?: any) => {
  370. forms.drag = true;
  371. forms.isEdit = true;
  372. nextTick(() => {
  373. if (point) {
  374. const dom = document.querySelectorAll('.row-nav');
  375. let isAdd = false;
  376. dom.forEach((child: any, index: number) => {
  377. const status = isPointInsideElement(child, point.x, point.y);
  378. if (status) {
  379. const array: any = forms.coursewareList;
  380. const left = isPointOnLeft(child, point.x);
  381. if (!left) {
  382. array.splice(index + 1, 0, item);
  383. } else {
  384. array.splice(index, 0, item);
  385. }
  386. isAdd = true;
  387. forms.coursewareList = array;
  388. prepareStore.setCoursewareList(forms.coursewareList);
  389. }
  390. });
  391. if (!isAdd) {
  392. forms.coursewareList.push(item);
  393. prepareStore.setCoursewareList(forms.coursewareList);
  394. }
  395. } else {
  396. forms.coursewareList.push(item);
  397. prepareStore.setCoursewareList(forms.coursewareList);
  398. }
  399. });
  400. });
  401. });
  402. return () => (
  403. <div class={styles.coursewareModal}>
  404. <div class={styles.btnGroup}>
  405. {forms.drag ? (
  406. !forms.tipsStatus ? (
  407. <div class={styles.tipsContainer}>
  408. <div class={styles.tipsLeft}>
  409. <img src={iconTips} class={styles.iconTips} />
  410. <span class={styles.tips}>可以拖动资源排序哦</span>
  411. </div>
  412. <span
  413. class={styles.btnNoTips}
  414. onClick={() => {
  415. localStorage.setItem('prepare-lesson-courseware-tip', '1');
  416. forms.tipsStatus = true;
  417. }}>
  418. 不再提醒
  419. </span>
  420. </div>
  421. ) : (
  422. <span></span>
  423. )
  424. ) : (
  425. <NSpace>
  426. {forms.classGroupId && (
  427. <div class={styles.btnItem}>
  428. <span class={styles.btnTitle}>上课班级:</span>
  429. <div
  430. onClick={() => {
  431. forms.showAttendClass = true;
  432. forms.attendClassType = 'change';
  433. }}>
  434. <NSelect
  435. placeholder="选择班级"
  436. labelField="name"
  437. valueField="id"
  438. class={styles.btnClassList}
  439. value={forms.className}
  440. disabled
  441. />
  442. </div>
  443. </div>
  444. )}
  445. <div class={styles.btnItem}>
  446. <span class={styles.btnTitle}>声部:</span>
  447. <NSelect
  448. placeholder="选择声部"
  449. class={styles.btnSubjectList}
  450. options={prepareStore.getSubjectList}
  451. labelField="name"
  452. valueField="id"
  453. value={prepareStore.getSubjectId}
  454. onUpdate:value={(val: any) => {
  455. prepareStore.setSubjectId(val);
  456. // 保存
  457. localStorage.setItem('prepareLessonSubjectId', val);
  458. getList();
  459. }}
  460. />
  461. </div>
  462. </NSpace>
  463. )}
  464. {/* 编辑 */}
  465. {!forms.drag ? (
  466. <NSpace>
  467. <NButton
  468. type="default"
  469. onClick={() => {
  470. forms.drag = true;
  471. prepareStore.setIsEditResource(true);
  472. // forms.subjectSyncVisiable = true;
  473. }}>
  474. 编辑
  475. </NButton>
  476. </NSpace>
  477. ) : (
  478. <NSpace>
  479. <NButton
  480. type="error"
  481. onClick={() => {
  482. forms.removeVisiable1 = true;
  483. }}>
  484. 清空资源
  485. </NButton>
  486. <NButton
  487. type="error"
  488. onClick={() => {
  489. forms.drag = false;
  490. forms.isEdit = false;
  491. prepareStore.setIsEditResource(false);
  492. forms.removeIds = [];
  493. getList();
  494. }}>
  495. 取消编辑
  496. </NButton>
  497. <NButton
  498. type="default"
  499. onClick={() => {
  500. if (forms.isEdit) {
  501. forms.subjectSyncVisiable = true;
  502. } else {
  503. forms.removeVisiable = true;
  504. }
  505. }}>
  506. 完成编辑
  507. </NButton>
  508. </NSpace>
  509. )}
  510. </div>
  511. <NScrollbar
  512. class={[
  513. styles.listContainer,
  514. forms.drag ? styles.listContainerDrag : ''
  515. ]}
  516. {...{ id: 'lessonsIn-1' }}>
  517. <NSpin show={forms.loadingStatus}>
  518. <div
  519. class={[
  520. styles.listSection
  521. // !forms.loadingStatus && forms.coursewareList.length <= 0
  522. // ? styles.emptySection
  523. // : ''
  524. ]}
  525. onDragenter={(e: any) => {
  526. e.preventDefault();
  527. }}
  528. onDragover={(e: any) => {
  529. e.preventDefault();
  530. }}
  531. onDrop={(e: any) => {
  532. console.log(e, 'event');
  533. let dropItem = e.dataTransfer.getData('text');
  534. dropItem = dropItem ? JSON.parse(dropItem) : {};
  535. // 判断是否有数据
  536. if (dropItem.id) {
  537. // 获取拖拽的目标元素
  538. eventGlobal.emit(
  539. 'onPrepareAddItem',
  540. {
  541. materialId: dropItem.id,
  542. coverImg: dropItem.coverImg,
  543. type: dropItem.type,
  544. title: dropItem.title,
  545. isCollect: dropItem.isCollect,
  546. isSelected: dropItem.isSelected,
  547. content: dropItem.content,
  548. removeFlag: false
  549. },
  550. {
  551. x: e.clientX,
  552. y: e.clientY
  553. }
  554. );
  555. }
  556. }}>
  557. {forms.coursewareList.length > 0 && (
  558. <>
  559. {forms.drag ? (
  560. <Draggable
  561. v-model:modelValue={forms.coursewareList}
  562. itemKey="id"
  563. componentData={{
  564. itemKey: 'id',
  565. tag: 'div',
  566. animation: 200,
  567. group: 'description',
  568. disabled: false
  569. }}
  570. class={styles.list}>
  571. {{
  572. item: (element: any) => {
  573. const item = element.element;
  574. return (
  575. <div
  576. data-id={item.id}
  577. class={[
  578. styles.itemWrap,
  579. styles.itemBlock,
  580. 'row-nav'
  581. ]}>
  582. <div class={styles.itemWrapBox}>
  583. <CardType
  584. class={[styles.itemContent]}
  585. isShowCollect={false}
  586. offShelf={item.removeFlag ? true : false}
  587. onOffShelf={() => onRemove(item)}
  588. item={item}
  589. />
  590. <div class={styles.itemOperation}>
  591. <img
  592. src={iconDelete}
  593. class={styles.iconDelete}
  594. onClick={(e: MouseEvent) => {
  595. e.stopPropagation();
  596. onDelete(item);
  597. }}
  598. />
  599. </div>
  600. </div>
  601. </div>
  602. );
  603. }
  604. }}
  605. </Draggable>
  606. ) : (
  607. <div class={styles.list}>
  608. {forms.coursewareList.map((item: any) => (
  609. <div class={styles.itemWrap}>
  610. <div class={styles.itemWrapBox}>
  611. <CardType
  612. class={[styles.itemContent, 'handle']}
  613. isShowCollect={false}
  614. item={item}
  615. offShelf={item.removeFlag ? true : false}
  616. onOffShelf={() => onRemove(item)}
  617. disabledMouseHover={false}
  618. onClick={() => {
  619. if (item.type === 'IMG') return;
  620. forms.show = true;
  621. forms.item = item;
  622. }}
  623. />
  624. </div>
  625. </div>
  626. ))}
  627. <div class={styles.itemWrap}>
  628. <div class={styles.itemWrapBox}>
  629. <div
  630. class={[
  631. styles.itemContent,
  632. styles.addMusicItem,
  633. 'handle'
  634. ]}
  635. onClick={() => {
  636. // 直接跳转到制谱页面 (临时存储数据)
  637. sessionStorage.setItem(
  638. 'notation-open-create',
  639. '1'
  640. );
  641. router.push('/notation');
  642. }}>
  643. <img src={iconAddMusic} />
  644. <p class={styles.addMusicName}>开始制谱</p>
  645. </div>
  646. </div>
  647. </div>
  648. </div>
  649. )}
  650. </>
  651. )}
  652. {/* {!forms.loadingStatus && forms.coursewareList.length <= 0 && (
  653. <TheEmpty description="暂无课件" />
  654. )} */}
  655. {forms.coursewareList.length <= 0 && (
  656. <div class={styles.list}>
  657. <div class={styles.itemWrap}>
  658. <div class={styles.itemWrapBox}>
  659. <div
  660. class={[
  661. styles.itemContent,
  662. styles.addMusicItem,
  663. 'handle'
  664. ]}
  665. onClick={() => {
  666. // 直接跳转到制谱页面 (临时存储数据)
  667. sessionStorage.setItem('notation-open-create', '1');
  668. router.push('/notation');
  669. }}>
  670. <img src={iconAddMusic} />
  671. <p class={styles.addMusicName}>开始制谱</p>
  672. </div>
  673. </div>
  674. </div>
  675. </div>
  676. )}
  677. </div>
  678. </NSpin>
  679. </NScrollbar>
  680. {!forms.drag ? (
  681. <div
  682. class={[styles.btnGroup, styles.btnGroupClass]}
  683. style={{ justifyContent: 'flex-end' }}>
  684. <NSpace justify="end">
  685. <NButton type="primary" onClick={onPreviewAttend}>
  686. 预览课件
  687. </NButton>
  688. <NButton
  689. type="error"
  690. class={styles.btnClassStart}
  691. onClick={async () => {
  692. let count = 0;
  693. forms.coursewareList.forEach((item: any) => {
  694. if (!item.removeFlag) {
  695. count++;
  696. }
  697. });
  698. if (count <= 0) {
  699. message.error('课件不能为空');
  700. return;
  701. }
  702. if (forms.classGroupId) {
  703. // 开始上课
  704. const res = await courseScheduleStart({
  705. lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
  706. classGroupId: forms.classGroupId,
  707. subjectId: prepareStore.getSubjectId
  708. });
  709. if (
  710. window.matchMedia('(display-mode: standalone)').matches
  711. ) {
  712. state.application = window.matchMedia(
  713. '(display-mode: standalone)'
  714. ).matches;
  715. forms.previewModal = true;
  716. fscreen();
  717. forms.previewParams = {
  718. type: 'class',
  719. classGroupId: forms.classGroupId,
  720. instrumentId: prepareStore.getInstrumentId,
  721. detailId: prepareStore.getSelectKey,
  722. classId: res.data,
  723. lessonCourseId: prepareStore.getBaseCourseware.id,
  724. preStudentNum: forms.preStudentNum
  725. };
  726. } else {
  727. const { href } = router.resolve({
  728. path: '/attend-class',
  729. query: {
  730. type: 'class',
  731. classGroupId: forms.classGroupId,
  732. instrumentId: prepareStore.getInstrumentId,
  733. detailId: prepareStore.getSelectKey,
  734. classId: res.data,
  735. lessonCourseId: prepareStore.getBaseCourseware.id,
  736. preStudentNum: forms.preStudentNum
  737. }
  738. });
  739. window.open(href, +new Date() + '');
  740. }
  741. } else {
  742. forms.showAttendClass = true;
  743. forms.attendClassType = 'change';
  744. }
  745. }}>
  746. 开始上课
  747. </NButton>
  748. </NSpace>
  749. </div>
  750. ) : (
  751. ''
  752. )}
  753. <NModal
  754. v-model:show={forms.showAttendClass}
  755. preset="card"
  756. showIcon={false}
  757. class={['modalTitle background', styles.attendClassModal]}
  758. title={'选择班级'}
  759. blockScroll={false}>
  760. <AttendClass
  761. onClose={() => (forms.showAttendClass = false)}
  762. type={forms.attendClassType}
  763. onPreview={(item: any) => {
  764. if (window.matchMedia('(display-mode: standalone)').matches) {
  765. state.application = window.matchMedia(
  766. '(display-mode: standalone)'
  767. ).matches;
  768. forms.previewModal = true;
  769. forms.previewParams = {
  770. ...item
  771. };
  772. } else {
  773. const { href } = router.resolve({
  774. path: '/attend-class',
  775. query: {
  776. ...item
  777. }
  778. });
  779. window.open(href, +new Date() + '');
  780. }
  781. }}
  782. onConfirm={async (item: any) => {
  783. if (forms.classGroupId) {
  784. forms.className = item.name;
  785. forms.classGroupId = item.classGroupId;
  786. forms.preStudentNum = item.preStudentNum;
  787. forms.subjectId = item.subjectId;
  788. forms.courseScheduleSubjectId = item.courseScheduleSubjectId;
  789. forms.showAttendClass = false;
  790. prepareStore.setClassGroupId(item.classGroupId);
  791. console.log(forms, 'forms', item);
  792. checkSubjectIds();
  793. // 声部切换时
  794. eventGlobal.emit('onChangeClass', {
  795. lastUseCoursewareId: item.lastUseCoursewareId,
  796. unit: item.unit
  797. });
  798. } else {
  799. const res = await courseScheduleStart({
  800. lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
  801. classGroupId: item.classGroupId,
  802. subjectId: prepareStore.getSubjectId
  803. });
  804. forms.showAttendClass = false;
  805. if (window.matchMedia('(display-mode: standalone)').matches) {
  806. state.application = window.matchMedia(
  807. '(display-mode: standalone)'
  808. ).matches;
  809. forms.previewModal = true;
  810. forms.previewParams = {
  811. type: 'class',
  812. classId: res.data, // 上课编号
  813. classGroupId: item.classGroupId,
  814. preStudentNum: item.preStudentNum,
  815. subjectId: prepareStore.getSubjectId,
  816. detailId: prepareStore.getSelectKey,
  817. lessonCourseId: prepareStore.getBaseCourseware.id
  818. };
  819. setTimeout(() => {
  820. fscreen();
  821. }, 200);
  822. } else {
  823. const { href } = router.resolve({
  824. path: '/attend-class',
  825. query: {
  826. type: 'class',
  827. classId: res.data, // 上课编号
  828. classGroupId: item.classGroupId,
  829. preStudentNum: item.preStudentNum,
  830. subjectId: prepareStore.getSubjectId,
  831. detailId: prepareStore.getSelectKey,
  832. lessonCourseId: prepareStore.getBaseCourseware.id
  833. }
  834. });
  835. window.open(href, +new Date() + '');
  836. }
  837. }
  838. }}
  839. />
  840. </NModal>
  841. {/* 弹窗查看 */}
  842. <CardPreview v-model:show={forms.show} item={forms.item} />
  843. <NModal
  844. v-model:show={forms.removeVisiable}
  845. preset="card"
  846. class={['modalTitle', styles.removeVisiable]}
  847. title={'提示'}>
  848. <div class={styles.studentRemove}>
  849. <p>是否完成编辑?</p>
  850. <NSpace class={styles.btnGroupModal} justify="center">
  851. <NButton round type="primary" onClick={onOverEdit}>
  852. 确定
  853. </NButton>
  854. <NButton round onClick={() => (forms.removeVisiable = false)}>
  855. 取消
  856. </NButton>
  857. </NSpace>
  858. </div>
  859. </NModal>
  860. <NModal
  861. v-model:show={forms.removeVisiable1}
  862. preset="card"
  863. class={['modalTitle', styles.removeVisiable1]}
  864. title={'清空资源'}>
  865. <div class={styles.studentRemove}>
  866. <p>
  867. 请确认是否要清空资源?
  868. <span>点击确认后所有的素材内容 将被清空掉。</span>
  869. </p>
  870. <NSpace class={styles.btnGroupModal} justify="center">
  871. <NButton
  872. round
  873. type="primary"
  874. onClick={() => {
  875. forms.coursewareList.forEach((item: any) => {
  876. forms.removeIds.push(item.id);
  877. });
  878. forms.coursewareList = [];
  879. forms.removeVisiable1 = false;
  880. forms.isEdit = true;
  881. // prepareStore.setCoursewareList([]);
  882. }}>
  883. 确定
  884. </NButton>
  885. <NButton round onClick={() => (forms.removeVisiable1 = false)}>
  886. 取消
  887. </NButton>
  888. </NSpace>
  889. </div>
  890. </NModal>
  891. <PreviewWindow
  892. v-model:show={forms.previewModal}
  893. type="attend"
  894. params={forms.previewParams}
  895. />
  896. {/* 完成编辑时,选择声部 */}
  897. <NModal
  898. v-model:show={forms.subjectSyncVisiable}
  899. preset="card"
  900. class={['modalTitle background', styles.subjectSyncModal]}
  901. title={'同步声部'}>
  902. <SubjectSync
  903. subjectId={prepareStore.getSubjectId as any}
  904. onClose={() => (forms.subjectSyncVisiable = false)}
  905. onConfirm={async (subjectIds: any) => {
  906. //
  907. try {
  908. forms.editSubjectIds = subjectIds.join(',');
  909. await onOverEdit();
  910. forms.subjectSyncVisiable = false;
  911. } catch {
  912. //
  913. }
  914. }}
  915. />
  916. </NModal>
  917. </div>
  918. );
  919. }
  920. });