addCourseware.tsx 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. import {
  2. defineComponent,
  3. nextTick,
  4. onMounted,
  5. onUnmounted,
  6. reactive,
  7. watch
  8. } from 'vue';
  9. import styles from './addCourseware.module.less';
  10. import {
  11. NButton,
  12. NModal,
  13. NScrollbar,
  14. NSelect,
  15. NSpace,
  16. NSpin,
  17. useMessage,
  18. useDialog,
  19. NSwitch,
  20. NInput,
  21. NTooltip,
  22. NImage,
  23. NIcon
  24. } from 'naive-ui';
  25. import CardType from '/src/components/card-type';
  26. // import AttendClass from '/src/views/prepare-lessons/model/attend-class';
  27. import { usePrepareStore } from '/src/store/modules/prepareLessons';
  28. import { useCatchStore } from '/src/store/modules/catchData';
  29. // import TheEmpty from '/src/components/TheEmpty';
  30. import {
  31. api_teacherChapterLessonCoursewareAdd,
  32. api_teacherChapterLessonCoursewareUpdate,
  33. api_teacherChapterLessonCoursewareDetail,
  34. // courseScheduleStart,
  35. // queryCourseware,
  36. saveCourseware
  37. } from '../../../api';
  38. import Draggable from 'vuedraggable';
  39. import iconDelete from '../../../images/icon-delete.png';
  40. import iconAddMusic from '../../../images/icon-add-music.png';
  41. import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
  42. // import deepClone from '/src/helpers/deep-clone';
  43. import CardPreview from '/src/components/card-preview';
  44. import PreviewWindow from '/src/views/preview-window';
  45. // import { state } from '/src/state';
  46. import SubjectSync from '../../../model/subject-sync';
  47. import { eventGlobal } from '/src/utils';
  48. // import iconTips from '../../../images/icon-tips.png';
  49. import TheMessageDialog from '/src/components/TheMessageDialog';
  50. import AddItemModel from '../../../model/add-item-model';
  51. import AddOtherSource from '../../../model/add-other-source';
  52. export default defineComponent({
  53. name: 'courseware-modal',
  54. props: {
  55. groupItem: {
  56. type: Object,
  57. default: () => ({})
  58. }
  59. },
  60. emits: ['change'],
  61. setup(props, { emit }) {
  62. const catchStore = useCatchStore();
  63. const prepareStore = usePrepareStore();
  64. // const route = useRoute();
  65. const router = useRouter();
  66. // const dialog = useDialog();
  67. const message = useMessage();
  68. const forms = reactive({
  69. subjects: [] as any,
  70. openFlagEnable: true, // 是否支持修改公开状态
  71. name: '',
  72. openFlag: false,
  73. coursewareList: [
  74. {
  75. name: '',
  76. id: null,
  77. list: [] as any
  78. }
  79. ] as any,
  80. loadingStatus: false,
  81. showAttendClass: false,
  82. attendClassType: 'change', //
  83. removeIds: [] as any, // 临时删除的编号
  84. editSubjectIds: '', // 声部编号
  85. addCoursewareVisiable: false,
  86. addCoursewareItem: {} as any,
  87. messageCallBack: null as any,
  88. messageOperation: {
  89. visiable: false,
  90. loading: false, // 是否显示加载
  91. type: 'delete' as 'delete' | 'addItem' | 'save' | 'pageLive',
  92. contentDirection: 'center' as 'left' | 'center' | 'right',
  93. title: '删除知识点',
  94. content: '请确认是否删除该知识点,删除知识点后将同步删除知识点下的资源',
  95. cancelButtonText: '取消',
  96. confirmButtonText: '确认',
  97. index: 0
  98. },
  99. subjectSyncVisiable: false, // 同步声部
  100. show: false,
  101. item: {} as any,
  102. previewModal: false,
  103. previewParams: {
  104. type: '',
  105. subjectId: '',
  106. detailId: ''
  107. } as any,
  108. addOtherSource: false
  109. });
  110. // 获取列表
  111. const getList = async () => {
  112. forms.loadingStatus = true;
  113. try {
  114. if (!props.groupItem.id) return (forms.loadingStatus = false);
  115. const { data } = await api_teacherChapterLessonCoursewareDetail(
  116. props.groupItem.id
  117. );
  118. const tempRows = data.chapterKnowledgeList || [];
  119. forms.name = data.name;
  120. forms.subjects = data.subjectIds
  121. ? data.subjectIds.split(',').map((s: any) => {
  122. return Number(s);
  123. })
  124. : [];
  125. forms.openFlag = data.openFlag;
  126. forms.openFlagEnable = data.openFlagEnable;
  127. const temp: any = [];
  128. tempRows.forEach((row: any) => {
  129. const child: any = row.chapterKnowledgeMaterialList;
  130. const childList: any[] = [];
  131. if (Array.isArray(child) && child.length > 0) {
  132. child.forEach((sub: any) => {
  133. childList.push({
  134. id: sub.id,
  135. materialId: sub.bizId,
  136. coverImg: sub.bizInfo.coverImg,
  137. type: sub.type,
  138. title: sub.bizInfo.name,
  139. // isCollect: !!sub.favoriteFlag,
  140. isSelected: sub.source === 'PLATFORM' ? true : false,
  141. content: sub.bizInfo.content,
  142. removeFlag: sub.removeFlag
  143. });
  144. });
  145. }
  146. temp.push({
  147. name: row.name,
  148. id: row.id,
  149. list: [...childList]
  150. });
  151. });
  152. forms.coursewareList = temp;
  153. } catch (e) {
  154. //
  155. console.log(e);
  156. }
  157. forms.loadingStatus = false;
  158. };
  159. // 删除
  160. const onDelete = (item: any, index: number) => {
  161. const coursewareItem = forms.coursewareList[index];
  162. if (!coursewareItem) return;
  163. const childIndex = coursewareItem.list.findIndex(
  164. (c: any) => c.id === item.id
  165. );
  166. coursewareItem.list.splice(childIndex, 1);
  167. };
  168. // 完成编辑
  169. const onOverEdit = async () => {
  170. try {
  171. const temp: any = [];
  172. forms.coursewareList.forEach((item: any) => {
  173. temp.push({
  174. materialName: item.name,
  175. materialType: item.type,
  176. materialId: item.materialId,
  177. id: item.id
  178. });
  179. });
  180. // 保存课件
  181. // 判断是否编辑,如果编辑则取选择的声部
  182. await saveCourseware({
  183. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  184. lessonCoursewareId: prepareStore.getLessonCoursewareId,
  185. lessonCoursewareDetailId: prepareStore.getLessonCoursewareDetailId,
  186. // subjectId: forms.isEdit
  187. // ? forms.editSubjectIds
  188. // : prepareStore.getSubjectId,
  189. materialList: [...temp]
  190. });
  191. message.success('编辑成功');
  192. // forms.removeVisiable = false;
  193. prepareStore.setIsEditResource(false);
  194. // 重置临时删除编号
  195. forms.removeIds = [];
  196. await getList();
  197. } catch {
  198. //
  199. }
  200. };
  201. const isPointInsideElement = (element: any, x: number, y: number) => {
  202. const rect = element.getBoundingClientRect();
  203. return (
  204. x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom
  205. );
  206. };
  207. const isPointOnLeft = (element: any, x: number) => {
  208. const rect = element.getBoundingClientRect();
  209. const elementCenterX = rect.left + rect.width / 2;
  210. return x < elementCenterX;
  211. };
  212. // 操作
  213. const onChangePoint = (type: string, index: number) => {
  214. if (type === 'up') {
  215. // 向上移动
  216. if (index === 0) return;
  217. const temp = forms.coursewareList[index - 1];
  218. forms.coursewareList[index - 1] = forms.coursewareList[index];
  219. forms.coursewareList[index] = temp;
  220. } else if (type === 'down') {
  221. // 向下移动
  222. if (index >= forms.coursewareList.length - 1) return;
  223. const temp = forms.coursewareList[index + 1];
  224. forms.coursewareList[index + 1] = forms.coursewareList[index];
  225. forms.coursewareList[index] = temp;
  226. } else if (type === 'remove') {
  227. forms.messageOperation = {
  228. visiable: true,
  229. type: 'delete',
  230. contentDirection: 'left',
  231. title: '删除知识点',
  232. loading: false,
  233. content:
  234. '请确认是否删除该知识点,删除知识点后将同步删除知识点下的资源',
  235. cancelButtonText: '取消',
  236. confirmButtonText: '确认',
  237. index
  238. };
  239. }
  240. };
  241. //
  242. const onMessageConfirm = async () => {
  243. const type = forms.messageOperation.type;
  244. if (type === 'delete') {
  245. forms.coursewareList.splice(forms.messageOperation.index, 1);
  246. } else if (type === 'addItem') {
  247. forms.coursewareList.push({ name: '', list: [] });
  248. addCoursewareItem(forms.addCoursewareItem);
  249. } else if (type === 'save' || type === 'pageLive') {
  250. if (forms.messageOperation.loading) return;
  251. forms.messageOperation.loading = true;
  252. await onSaveCourseWare();
  253. forms.messageOperation.loading = false;
  254. if (
  255. type === 'pageLive' &&
  256. typeof forms.messageCallBack === 'function'
  257. ) {
  258. forms.messageCallBack();
  259. }
  260. emit('change', { status: false });
  261. eventGlobal.emit('teacher-slideshow', false);
  262. }
  263. forms.messageOperation.visiable = false;
  264. };
  265. const addCoursewareItem = (item: any, point?: any) => {
  266. nextTick(() => {
  267. if (point) {
  268. const dom = document.querySelectorAll('.row-nav');
  269. let isAdd = false;
  270. dom.forEach((child: any) => {
  271. // console.log(child);
  272. const status = isPointInsideElement(child, point.x, point.y);
  273. if (status) {
  274. const array: any =
  275. forms.coursewareList[item.index || 0].list || [];
  276. const left = isPointOnLeft(child, point.x);
  277. if (!left) {
  278. array.splice(item.index + 1, 0, item);
  279. } else {
  280. array.splice(item.index, 0, item);
  281. }
  282. isAdd = true;
  283. forms.coursewareList[item.index || 0].list = array;
  284. }
  285. });
  286. if (!isAdd) {
  287. forms.coursewareList[item.index || 0].list.push(item);
  288. }
  289. } else {
  290. forms.coursewareList[item.index || 0].list.push(item);
  291. message.success('添加成功');
  292. }
  293. });
  294. };
  295. // 提交
  296. const onSubmit = async () => {
  297. try {
  298. if (!forms.name) {
  299. message.error('请输入课件标题');
  300. return;
  301. }
  302. if (forms.subjects.length <= 0) {
  303. message.error('请选择声部');
  304. return;
  305. }
  306. let isNotAdd = false;
  307. for (const item of forms.coursewareList) {
  308. if (!item.name) {
  309. message.error('请输入知识点名称');
  310. return;
  311. }
  312. if (Array.isArray(item.list) && item.list.length <= 0) {
  313. isNotAdd = true;
  314. }
  315. }
  316. if (isNotAdd) {
  317. message.error('请至少添加一个资源');
  318. return;
  319. }
  320. forms.messageOperation = {
  321. visiable: true,
  322. type: 'save',
  323. loading: false,
  324. contentDirection: 'center',
  325. title: '保存课件',
  326. content: '当前课件暂未保存,是否保存?',
  327. cancelButtonText: '不保存',
  328. confirmButtonText: '保存',
  329. index: 0
  330. };
  331. } catch {
  332. //
  333. }
  334. };
  335. const onSaveCourseWare = async () => {
  336. try {
  337. const params = {
  338. name: forms.name,
  339. subjectIds: forms.subjects.join(','),
  340. openFlag: forms.openFlag,
  341. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  342. chapterKnowledgeList: [] as any
  343. };
  344. forms.coursewareList.forEach((item: any) => {
  345. let tempItem: any = [];
  346. if (Array.isArray(item.list) && item.list.length > 0) {
  347. tempItem = item.list.map((child: any) => {
  348. return {
  349. bizId: child.materialId,
  350. type: child.type,
  351. dataJson: ''
  352. };
  353. });
  354. }
  355. params.chapterKnowledgeList.push({
  356. name: item.name,
  357. chapterKnowledgeMaterialList: tempItem
  358. });
  359. });
  360. if (props.groupItem?.id) {
  361. await api_teacherChapterLessonCoursewareUpdate({
  362. id: props.groupItem.id,
  363. ...params
  364. });
  365. message.success('修改成功');
  366. } else {
  367. await api_teacherChapterLessonCoursewareAdd(params);
  368. message.success('添加成功');
  369. }
  370. } catch {
  371. //
  372. }
  373. };
  374. const addItem = (item: any, point?: any) => {
  375. if (forms.coursewareList.length <= 0) {
  376. // 添加到临时对象
  377. forms.addCoursewareItem = item;
  378. forms.messageOperation = {
  379. visiable: true,
  380. type: 'addItem',
  381. contentDirection: 'center',
  382. title: '添加到知识点',
  383. loading: false,
  384. content: '当前课件暂无知识点,请添加知识点后操作',
  385. cancelButtonText: '取消',
  386. confirmButtonText: '添加知识点',
  387. index: 0
  388. };
  389. } else if (forms.coursewareList.length > 1 && item.addType !== 'drag') {
  390. forms.addCoursewareVisiable = true;
  391. forms.addCoursewareItem = item;
  392. } else {
  393. addCoursewareItem(item, point);
  394. }
  395. };
  396. // 当页面离开时
  397. const onPageBeforeLeave = (event: any) => {
  398. console.log(event, typeof event);
  399. forms.messageCallBack = event;
  400. forms.messageOperation = {
  401. visiable: true,
  402. type: 'pageLive',
  403. loading: false,
  404. contentDirection: 'center',
  405. title: '保存课件',
  406. content: '当前课件暂未保存,是否保存?',
  407. cancelButtonText: '不保存',
  408. confirmButtonText: '保存',
  409. index: 0
  410. };
  411. };
  412. onMounted(async () => {
  413. await getList();
  414. // 动态添加数据
  415. eventGlobal.on('onPrepareAddItem', addItem);
  416. eventGlobal.on('pageBeforeLeave', onPageBeforeLeave);
  417. });
  418. onUnmounted(() => {
  419. eventGlobal.off('onPrepareAddItem', addItem);
  420. });
  421. // 当列表数据更新时同步缓存数据
  422. watch(
  423. () => forms.coursewareList,
  424. () => {
  425. prepareStore.setCoursewareList = forms.coursewareList;
  426. },
  427. {
  428. deep: true
  429. }
  430. );
  431. return () => (
  432. <div class={styles.coursewareModal}>
  433. <div class={styles.btnGroup}>
  434. <NSpace>
  435. <div class={styles.btnItem}>
  436. <span class={styles.btnTitle}>
  437. <span>*</span>标题:
  438. </span>
  439. <NInput
  440. placeholder="请输入课件标题"
  441. v-model:value={forms.name}
  442. maxlength={15}
  443. clearable
  444. />
  445. </div>
  446. <div class={styles.btnItem}>
  447. <span class={styles.btnTitle}>
  448. <span>*</span>声部:
  449. </span>
  450. <NSelect
  451. placeholder="请选择声部(可多选)"
  452. class={styles.btnSubjectList}
  453. options={prepareStore.getSubjectList}
  454. labelField="name"
  455. valueField="id"
  456. multiple
  457. maxTagCount={1}
  458. size="small"
  459. v-model:value={forms.subjects}
  460. clearable
  461. />
  462. </div>
  463. <div class={styles.btnItem}>
  464. <span class={styles.btnTitle}>公开:</span>
  465. {!forms.openFlagEnable ? (
  466. <NTooltip style={{ maxWidth: '200px' }} showArrow={false}>
  467. {{
  468. trigger: () => (
  469. <NSwitch
  470. v-model:value={forms.openFlag}
  471. disabled={!forms.openFlagEnable}
  472. />
  473. ),
  474. default: () =>
  475. '为尊重课件原作者,在“相关课件”中添加的课件不支持公开'
  476. }}
  477. </NTooltip>
  478. ) : (
  479. <NSwitch
  480. v-model:value={forms.openFlag}
  481. disabled={!forms.openFlagEnable}
  482. />
  483. )}
  484. </div>
  485. </NSpace>
  486. {/* 编辑 */}
  487. <NSpace>
  488. <NButton
  489. type="error"
  490. onClick={() => {
  491. emit('change', { status: false });
  492. eventGlobal.emit('teacher-slideshow', false);
  493. }}>
  494. 取消
  495. </NButton>
  496. <NButton type="primary" onClick={onSubmit}>
  497. 保存课件
  498. </NButton>
  499. {/* <NButton
  500. type="primary"
  501. onClick={() => {
  502. forms.coursewareList = [{ name: '', list: [] }];
  503. }}>
  504. 请空
  505. </NButton> */}
  506. </NSpace>
  507. </div>
  508. <NScrollbar class={[styles.listContainer]} {...{ id: 'lessons-2' }}>
  509. <NSpin show={forms.loadingStatus}>
  510. <div class={[styles.listSection]}>
  511. {forms.coursewareList.map((item: any, index: number) => (
  512. <div
  513. class={styles.listItems}
  514. onDragenter={(e: any) => {
  515. e.preventDefault();
  516. }}
  517. onDragover={(e: any) => {
  518. e.preventDefault();
  519. }}
  520. onDrop={(e: any) => {
  521. let dropItem = e.dataTransfer.getData('text');
  522. dropItem =
  523. dropItem && e.dataTransfer.effectAllowed === 'all'
  524. ? JSON.parse(dropItem)
  525. : {};
  526. // 判断是否有数据
  527. if (dropItem.id) {
  528. // 获取拖拽的目标元素
  529. eventGlobal.emit(
  530. 'onPrepareAddItem',
  531. {
  532. materialId: dropItem.id,
  533. coverImg: dropItem.coverImg,
  534. type: dropItem.type,
  535. title: dropItem.title,
  536. isCollect: dropItem.isCollect,
  537. isSelected: dropItem.isSelected,
  538. content: dropItem.content,
  539. removeFlag: false,
  540. index,
  541. addType: 'drag'
  542. },
  543. {
  544. x: e.clientX,
  545. y: e.clientY
  546. }
  547. );
  548. }
  549. }}>
  550. <div class={styles.knowledgePoint}>
  551. <div class={styles.btnItem}>
  552. <span class={styles.btnTitle}>
  553. <span>*</span>知识点名称:
  554. </span>
  555. <NInput
  556. placeholder="未命名知识点"
  557. v-model:value={item.name}
  558. maxlength={15}
  559. clearable
  560. />
  561. </div>
  562. </div>
  563. <NSpace class={styles.operationGroup}>
  564. {index > 0 && (
  565. <NTooltip>
  566. {{
  567. trigger: () => (
  568. <i
  569. class={styles.iconCUp}
  570. onClick={() => onChangePoint('up', index)}></i>
  571. ),
  572. default: () => '上移知识点'
  573. }}
  574. </NTooltip>
  575. )}
  576. {forms.coursewareList.length > 1 && (
  577. <NTooltip>
  578. {{
  579. trigger: () => (
  580. <i
  581. class={styles.iconCDown}
  582. onClick={() => onChangePoint('down', index)}></i>
  583. ),
  584. default: () => '下移知识点'
  585. }}
  586. </NTooltip>
  587. )}
  588. <NTooltip>
  589. {{
  590. trigger: () => (
  591. <i
  592. class={styles.iconCRemove}
  593. onClick={() => onChangePoint('remove', index)}></i>
  594. ),
  595. default: () => '删除知识点'
  596. }}
  597. </NTooltip>
  598. </NSpace>
  599. {item.list.length > 0 && (
  600. <Draggable
  601. v-model:modelValue={item.list}
  602. itemKey="id"
  603. componentData={{
  604. itemKey: 'id',
  605. tag: 'div',
  606. animation: 200,
  607. group: 'description',
  608. disabled: false
  609. }}
  610. class={styles.list}>
  611. {{
  612. item: (element: any) => {
  613. const item = element.element;
  614. return (
  615. <div
  616. data-id={item.id}
  617. class={[
  618. styles.itemWrap,
  619. styles.itemBlock,
  620. 'row-nav'
  621. ]}>
  622. <div class={styles.itemWrapBox}>
  623. <CardType
  624. class={[styles.itemContent]}
  625. isShowCollect={false}
  626. offShelf={item.removeFlag ? true : false}
  627. // onOffShelf={() => onRemove(item)}
  628. item={item}
  629. disabledMouseHover={false}
  630. onClick={() => {
  631. if (item.type === 'IMG') return;
  632. forms.show = true;
  633. forms.item = item;
  634. }}
  635. />
  636. <div class={styles.itemOperation}>
  637. <img
  638. src={iconDelete}
  639. class={styles.iconDelete}
  640. onClick={(e: MouseEvent) => {
  641. e.stopPropagation();
  642. onDelete(item, index);
  643. }}
  644. />
  645. </div>
  646. </div>
  647. </div>
  648. );
  649. },
  650. footer: () => (
  651. <div class={styles.itemWrap}>
  652. <div class={styles.itemWrapBox}>
  653. <div
  654. class={[
  655. styles.itemContent,
  656. styles.addMusicItem,
  657. 'handle'
  658. ]}
  659. onClick={() => {
  660. forms.addOtherSource = true;
  661. }}>
  662. <img src={iconAddMusic} />
  663. <p class={styles.addMusicName}>添加功能</p>
  664. </div>
  665. </div>
  666. </div>
  667. )
  668. }}
  669. </Draggable>
  670. )}
  671. {item.list <= 0 && (
  672. <div class={styles.list}>
  673. <div class={styles.itemWrap}>
  674. <div class={styles.itemWrapBox}>
  675. <div
  676. class={[
  677. styles.itemContent,
  678. styles.addMusicItem,
  679. 'handle'
  680. ]}
  681. onClick={() => {
  682. forms.addOtherSource = true;
  683. }}>
  684. <img src={iconAddMusic} />
  685. <p class={styles.addMusicName}>添加功能</p>
  686. </div>
  687. </div>
  688. </div>
  689. </div>
  690. )}
  691. </div>
  692. ))}
  693. <NButton
  694. block
  695. type="primary"
  696. secondary
  697. class={styles.addKnowledgePoint}
  698. onClick={() => {
  699. forms.coursewareList.push({
  700. name: '',
  701. list: []
  702. });
  703. }}>
  704. <i class={styles.iconCAdd}></i>
  705. 添加知识点
  706. </NButton>
  707. </div>
  708. </NSpin>
  709. </NScrollbar>
  710. {/* 弹窗查看 */}
  711. <CardPreview v-model:show={forms.show} item={forms.item} />
  712. <NModal
  713. v-model:show={forms.addCoursewareVisiable}
  714. preset="card"
  715. class={['modalTitle', styles.addCourseware]}
  716. title={'添加知识点'}>
  717. <AddItemModel
  718. coursewareList={forms.coursewareList}
  719. onClose={() => (forms.addCoursewareVisiable = false)}
  720. onConfirm={(selects: number[]) => {
  721. if (Array.isArray(selects) && selects.length > 0) {
  722. selects.forEach(select => {
  723. addCoursewareItem({
  724. ...forms.addCoursewareItem,
  725. index: select
  726. });
  727. });
  728. forms.addCoursewareVisiable = false;
  729. }
  730. }}
  731. />
  732. </NModal>
  733. <NModal
  734. v-model:show={forms.messageOperation.visiable}
  735. preset="card"
  736. class={['modalTitle', styles.removeVisiable1]}
  737. title={forms.messageOperation.title}>
  738. <TheMessageDialog
  739. content={forms.messageOperation.content}
  740. contentDirection={forms.messageOperation.contentDirection}
  741. cancelButtonText={forms.messageOperation.cancelButtonText}
  742. confirmButtonText={forms.messageOperation.confirmButtonText}
  743. loading={forms.messageOperation.loading}
  744. onClose={() => {
  745. forms.messageOperation.visiable = false;
  746. if (
  747. forms.messageOperation.type === 'save' ||
  748. forms.messageOperation.type === 'pageLive'
  749. ) {
  750. emit('change', { status: false });
  751. eventGlobal.emit('teacher-slideshow', false);
  752. if (
  753. forms.messageOperation.type === 'pageLive' &&
  754. typeof forms.messageCallBack === 'function'
  755. ) {
  756. forms.messageCallBack();
  757. }
  758. }
  759. }}
  760. onConfirm={() => onMessageConfirm()}
  761. />
  762. </NModal>
  763. <PreviewWindow
  764. v-model:show={forms.previewModal}
  765. type="attend"
  766. params={forms.previewParams}
  767. />
  768. {/* 完成编辑时,选择声部 */}
  769. <NModal
  770. v-model:show={forms.subjectSyncVisiable}
  771. preset="card"
  772. class={['modalTitle background', styles.subjectSyncModal]}
  773. title={'同步声部'}>
  774. <SubjectSync
  775. subjectId={prepareStore.getSubjectId as any}
  776. onClose={() => (forms.subjectSyncVisiable = false)}
  777. onConfirm={async (subjectIds: any) => {
  778. //
  779. try {
  780. forms.editSubjectIds = subjectIds.join(',');
  781. await onOverEdit();
  782. forms.subjectSyncVisiable = false;
  783. } catch {
  784. //
  785. }
  786. }}
  787. />
  788. </NModal>
  789. {/* 添加其它类型的资源 */}
  790. <NModal
  791. v-model:show={forms.addOtherSource}
  792. preset="card"
  793. class={['modalTitle background', styles.addOtherSource]}
  794. title={'添加功能'}>
  795. <AddOtherSource />
  796. </NModal>
  797. </div>
  798. );
  799. }
  800. });