index.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. import { defineComponent, 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 { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
  27. import deepClone from '/src/helpers/deep-clone';
  28. import CardPreview from '/src/components/card-preview';
  29. import PreviewWindow from '/src/views/preview-window';
  30. import { state } from '/src/state';
  31. import SubjectSync from '../../../model/subject-sync';
  32. import { eventGlobal } from '/src/utils';
  33. export default defineComponent({
  34. name: 'courseware-modal',
  35. setup() {
  36. const catchStore = useCatchStore();
  37. const prepareStore = usePrepareStore();
  38. const route = useRoute();
  39. const router = useRouter();
  40. const dialog = useDialog();
  41. const message = useMessage();
  42. const forms = reactive({
  43. className: route.query.name as any,
  44. classGroupId: route.query.classGroupId,
  45. subjectId: route.query.subjectId ? Number(route.query.subjectId) : null,
  46. coursewareList: [] as any,
  47. loadingStatus: false,
  48. showAttendClass: false,
  49. attendClassType: 'change', //
  50. removeIds: [] as any, // 临时删除的编号
  51. drag: false,
  52. isEdit: false, // 是否更新数据
  53. editSubjectIds: '', // 声部编号
  54. removeVisiable: false,
  55. removeVisiable1: false,
  56. subjectSyncVisiable: false, // 同步声部
  57. show: false,
  58. item: {} as any,
  59. previewModal: false,
  60. previewParams: {
  61. type: '',
  62. subjectId: '',
  63. detailId: ''
  64. } as any
  65. });
  66. // 获取列表
  67. const getList = async () => {
  68. forms.loadingStatus = true;
  69. try {
  70. // 判断是否有选择对应的课件 或声部
  71. if (!prepareStore.getSelectKey || !prepareStore.getSubjectId)
  72. return (forms.loadingStatus = false);
  73. const { data } = await queryCourseware({
  74. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  75. subjectId: prepareStore.getSubjectId,
  76. page: 1,
  77. rows: 99
  78. });
  79. const tempRows = data.rows || [];
  80. const temp: any = [];
  81. tempRows.forEach((row: any) => {
  82. temp.push({
  83. id: row.id,
  84. materialId: row.materialId,
  85. coverImg: row.coverImg,
  86. type: row.materialType,
  87. title: row.materialName,
  88. isCollect: !!row.favoriteFlag,
  89. isSelected: row.source === 'PLATFORM' ? true : false,
  90. content: row.content,
  91. removeFlag: row.removeFlag
  92. });
  93. });
  94. prepareStore.setCoursewareList(temp || []);
  95. const tempCourse: any = [];
  96. temp.forEach((item: any) => {
  97. if (!forms.removeIds.includes(item.id)) {
  98. tempCourse.push(item);
  99. }
  100. });
  101. forms.coursewareList = tempCourse;
  102. } catch {
  103. //
  104. }
  105. forms.loadingStatus = false;
  106. };
  107. // 监听选择的key 左侧选择了其它的课
  108. watch(
  109. () => prepareStore.getSelectKey,
  110. () => {
  111. forms.drag = false;
  112. prepareStore.setIsEditResource(false);
  113. getList();
  114. }
  115. );
  116. // 声部变化时
  117. watch(
  118. () => prepareStore.getSubjectId,
  119. () => {
  120. getList();
  121. }
  122. );
  123. watch(
  124. () => prepareStore.getIsAddResource,
  125. (val: boolean) => {
  126. if (val) {
  127. getList();
  128. prepareStore.setIsAddResource(false);
  129. }
  130. }
  131. );
  132. // 监听列表变化,如果变化了,则弹选择声部的
  133. watch(
  134. () => forms.coursewareList,
  135. () => {
  136. if (forms.drag) {
  137. forms.isEdit = true;
  138. }
  139. },
  140. {
  141. deep: true
  142. }
  143. );
  144. // 删除
  145. const onDelete = (item: any) => {
  146. //
  147. forms.removeIds.push(item.id);
  148. const index = forms.coursewareList.findIndex(
  149. (c: any) => c.id === item.id
  150. );
  151. forms.coursewareList.splice(index, 1);
  152. forms.isEdit = true;
  153. // prepareStore.setCoursewareList(forms.coursewareList);
  154. // console.log(prepareStore.getCoursewareList, 'getCourseware');
  155. };
  156. // 完成编辑
  157. const onOverEdit = async () => {
  158. try {
  159. const temp: any = [];
  160. forms.coursewareList.forEach((item: any) => {
  161. temp.push({
  162. materialName: item.title,
  163. materialType: item.type,
  164. materialId: item.materialId,
  165. id: item.id
  166. });
  167. });
  168. // 保存课件
  169. // 判断是否编辑,如果编辑则取选择的声部
  170. await saveCourseware({
  171. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  172. lessonCoursewareId: prepareStore.getLessonCoursewareId,
  173. lessonCoursewareDetailId: prepareStore.getLessonCoursewareDetailId,
  174. subjectId: forms.isEdit
  175. ? forms.editSubjectIds
  176. : prepareStore.getSubjectId,
  177. materialList: [...temp]
  178. });
  179. forms.drag = false;
  180. message.success('编辑成功');
  181. forms.removeVisiable = false;
  182. prepareStore.setIsEditResource(false);
  183. // 重置临时删除编号
  184. forms.removeIds = [];
  185. await getList();
  186. } catch {
  187. //
  188. }
  189. };
  190. // 预览上课
  191. const onPreviewAttend = () => {
  192. // 获取上架的数据
  193. let count = 0;
  194. forms.coursewareList.forEach((item: any) => {
  195. if (!item.removeFlag) {
  196. count++;
  197. }
  198. });
  199. if (count <= 0) {
  200. message.error('课件不能为空');
  201. return;
  202. }
  203. // 判断是否在应用里面
  204. if (window.matchMedia('(display-mode: standalone)').matches) {
  205. state.application = window.matchMedia(
  206. '(display-mode: standalone)'
  207. ).matches;
  208. forms.previewModal = true;
  209. fscreen();
  210. forms.previewParams = {
  211. type: 'preview',
  212. subjectId: prepareStore.getSubjectId,
  213. detailId: prepareStore.getSelectKey,
  214. lessonCourseId: prepareStore.getBaseCourseware.id
  215. };
  216. } else {
  217. const { href } = router.resolve({
  218. path: '/attend-class',
  219. query: {
  220. type: 'preview',
  221. subjectId: prepareStore.getSubjectId,
  222. detailId: prepareStore.getSelectKey,
  223. lessonCourseId: prepareStore.getBaseCourseware.id
  224. }
  225. });
  226. window.open(href, +new Date() + '');
  227. }
  228. };
  229. const fscreen = () => {
  230. const el = document.documentElement;
  231. const isFullscreen =
  232. document.fullScreen ||
  233. document.mozFullScreen ||
  234. document.webkitIsFullScreen;
  235. if (!isFullscreen) {
  236. //进入全屏
  237. (el.requestFullscreen && el.requestFullscreen()) ||
  238. (el.mozRequestFullScreen && el.mozRequestFullScreen()) ||
  239. (el.webkitRequestFullscreen && el.webkitRequestFullscreen()) ||
  240. (el.msRequestFullscreen && el.msRequestFullscreen());
  241. }
  242. };
  243. // 单个删除
  244. const onRemove = async (item: any) => {
  245. try {
  246. dialog.warning({
  247. title: '提示',
  248. content: '该资源已下架,是否删除?',
  249. positiveText: '确定',
  250. negativeText: '取消',
  251. onPositiveClick: async () => {
  252. forms.removeIds.push(item.id);
  253. await teacherKnowledgeMaterialDelete({ ids: item.id });
  254. message.success('删除成功');
  255. getList();
  256. }
  257. });
  258. } catch {
  259. //
  260. }
  261. };
  262. watch(
  263. () => prepareStore.getSubjectList,
  264. () => {
  265. checkSubjectIds();
  266. }
  267. );
  268. const checkSubjectIds = () => {
  269. const subjectList = prepareStore.getSubjectList;
  270. // 并且没有声部时才会更新
  271. if (subjectList.length > 0) {
  272. // 判断浏览器上面是否有
  273. const index = subjectList.findIndex(
  274. (subject: any) => subject.id == forms.subjectId
  275. );
  276. // 并且声部在列表中
  277. if (forms.subjectId && index >= 0) {
  278. prepareStore.setSubjectId(forms.subjectId);
  279. } else {
  280. // 判断是否有缓存
  281. prepareStore.setSubjectId(subjectList[0].id);
  282. }
  283. // console.log(prepareStore.getSubjectId, 'getSubjectId');
  284. }
  285. // 保存
  286. localStorage.setItem(
  287. 'prepareLessonSubjectId',
  288. prepareStore.getSubjectId as any
  289. );
  290. };
  291. watch(
  292. () => route.query,
  293. async () => {
  294. forms.className = route.query.name as any;
  295. forms.classGroupId = route.query.classGroupId as any;
  296. forms.subjectId = route.query.subjectId
  297. ? Number(route.query.subjectId)
  298. : null;
  299. checkSubjectIds();
  300. await getList();
  301. }
  302. );
  303. onMounted(async () => {
  304. // 获取教材分类列表
  305. checkSubjectIds();
  306. await getList();
  307. // 动态添加数据
  308. eventGlobal.on('onPrepareAddItem', (item: any) => {
  309. forms.coursewareList.push(item);
  310. prepareStore.setCoursewareList(forms.coursewareList);
  311. forms.isEdit = true;
  312. });
  313. });
  314. return () => (
  315. <div class={styles.coursewareModal}>
  316. <div class={styles.btnGroup}>
  317. {forms.drag ? (
  318. <NSpace>
  319. <span class={styles.tips}>拖动可将资源进行排序哦~</span>
  320. </NSpace>
  321. ) : (
  322. <NSpace>
  323. {forms.classGroupId && (
  324. <div class={styles.btnItem}>
  325. <span class={styles.btnTitle}>上课班级:</span>
  326. <div
  327. onClick={() => {
  328. forms.showAttendClass = true;
  329. forms.attendClassType = 'change';
  330. }}>
  331. <NSelect
  332. placeholder="选择声部"
  333. labelField="name"
  334. valueField="id"
  335. class={styles.btnClassList}
  336. value={forms.className}
  337. disabled
  338. />
  339. </div>
  340. </div>
  341. )}
  342. <div class={styles.btnItem}>
  343. <span class={styles.btnTitle}>声部:</span>
  344. <NSelect
  345. placeholder="选择声部"
  346. class={styles.btnSubjectList}
  347. options={prepareStore.getSubjectList}
  348. labelField="name"
  349. valueField="id"
  350. value={prepareStore.getSubjectId}
  351. onUpdate:value={(val: any) => {
  352. prepareStore.setSubjectId(val);
  353. // 保存
  354. localStorage.setItem('prepareLessonSubjectId', val);
  355. getList();
  356. }}
  357. />
  358. </div>
  359. </NSpace>
  360. )}
  361. {/* 编辑 */}
  362. {!forms.drag ? (
  363. <NSpace>
  364. <NButton
  365. type="default"
  366. onClick={() => {
  367. forms.drag = true;
  368. prepareStore.setIsEditResource(true);
  369. // forms.subjectSyncVisiable = true;
  370. }}>
  371. 编辑
  372. </NButton>
  373. </NSpace>
  374. ) : (
  375. <NSpace>
  376. <NButton
  377. type="error"
  378. onClick={() => {
  379. forms.removeVisiable1 = true;
  380. }}>
  381. 清空资源
  382. </NButton>
  383. <NButton
  384. type="error"
  385. onClick={() => {
  386. forms.drag = false;
  387. forms.isEdit = false;
  388. prepareStore.setIsEditResource(false);
  389. forms.removeIds = [];
  390. getList();
  391. }}>
  392. 取消编辑
  393. </NButton>
  394. <NButton
  395. type="default"
  396. onClick={() => {
  397. if (forms.isEdit) {
  398. forms.subjectSyncVisiable = true;
  399. } else {
  400. forms.removeVisiable = true;
  401. }
  402. }}>
  403. 完成编辑
  404. </NButton>
  405. </NSpace>
  406. )}
  407. </div>
  408. <NScrollbar
  409. class={[
  410. styles.listContainer,
  411. forms.drag ? styles.listContainerDrag : ''
  412. ]}
  413. {...{ id: 'lessons-2' }}>
  414. <NSpin show={forms.loadingStatus}>
  415. <div
  416. class={[
  417. styles.listSection,
  418. !forms.loadingStatus && forms.coursewareList.length <= 0
  419. ? styles.emptySection
  420. : ''
  421. ]}>
  422. {forms.coursewareList.length > 0 && (
  423. <>
  424. {forms.drag ? (
  425. <Draggable
  426. v-model:modelValue={forms.coursewareList}
  427. itemKey="id"
  428. componentData={{
  429. itemKey: 'id',
  430. tag: 'div',
  431. animation: 200,
  432. group: 'description',
  433. disabled: false
  434. }}
  435. class={styles.list}>
  436. {{
  437. item: (element: any) => {
  438. const item = element.element;
  439. return (
  440. <div
  441. data-id={item.id}
  442. class={[styles.itemBlock, 'row-nav']}>
  443. <CardType
  444. class={[styles.itemContent]}
  445. isShowCollect={false}
  446. offShelf={item.removeFlag ? true : false}
  447. onOffShelf={() => onRemove(item)}
  448. item={item}
  449. />
  450. <div class={styles.itemOperation}>
  451. <img
  452. src={iconDelete}
  453. class={styles.iconDelete}
  454. onClick={(e: MouseEvent) => {
  455. e.stopPropagation();
  456. onDelete(item);
  457. }}
  458. />
  459. </div>
  460. </div>
  461. );
  462. }
  463. }}
  464. </Draggable>
  465. ) : (
  466. <div class={styles.list}>
  467. {forms.coursewareList.map((item: any) => (
  468. <CardType
  469. class={[styles.itemContent, 'handle']}
  470. isShowCollect={false}
  471. item={item}
  472. offShelf={item.removeFlag ? true : false}
  473. onOffShelf={() => onRemove(item)}
  474. disabledMouseHover={false}
  475. onClick={() => {
  476. if (item.type === 'IMG') return;
  477. forms.show = true;
  478. forms.item = item;
  479. }}
  480. />
  481. ))}
  482. </div>
  483. )}
  484. </>
  485. )}
  486. {!forms.loadingStatus && forms.coursewareList.length <= 0 && (
  487. <TheEmpty description="暂无课件" />
  488. )}
  489. </div>
  490. </NSpin>
  491. </NScrollbar>
  492. {!forms.drag ? (
  493. <div class={styles.btnGroup} style={{ justifyContent: 'flex-end' }}>
  494. <NSpace justify="end">
  495. <NButton type="primary" onClick={onPreviewAttend}>
  496. 预览课件
  497. </NButton>
  498. <NButton
  499. {...{ id: 'lessons-3' }}
  500. type="error"
  501. class={styles.btnClassStart}
  502. onClick={async () => {
  503. let count = 0;
  504. forms.coursewareList.forEach((item: any) => {
  505. if (!item.removeFlag) {
  506. count++;
  507. }
  508. });
  509. if (count <= 0) {
  510. message.error('课件不能为空');
  511. return;
  512. }
  513. if (forms.classGroupId) {
  514. // 开始上课
  515. const res = await courseScheduleStart({
  516. lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
  517. classGroupId: forms.classGroupId
  518. });
  519. if (
  520. window.matchMedia('(display-mode: standalone)').matches
  521. ) {
  522. state.application = window.matchMedia(
  523. '(display-mode: standalone)'
  524. ).matches;
  525. forms.previewModal = true;
  526. fscreen();
  527. forms.previewParams = {
  528. type: 'class',
  529. classGroupId: forms.classGroupId,
  530. subjectId: prepareStore.getSubjectId,
  531. detailId: prepareStore.getSelectKey,
  532. classId: res.data,
  533. lessonCourseId: prepareStore.getBaseCourseware.id
  534. };
  535. } else {
  536. const { href } = router.resolve({
  537. path: '/attend-class',
  538. query: {
  539. type: 'class',
  540. classGroupId: forms.classGroupId,
  541. subjectId: prepareStore.getSubjectId,
  542. detailId: prepareStore.getSelectKey,
  543. classId: res.data,
  544. lessonCourseId: prepareStore.getBaseCourseware.id
  545. }
  546. });
  547. window.open(href, +new Date() + '');
  548. }
  549. } else {
  550. forms.showAttendClass = true;
  551. forms.attendClassType = 'change';
  552. }
  553. }}>
  554. 开始上课
  555. </NButton>
  556. </NSpace>
  557. </div>
  558. ) : (
  559. ''
  560. )}
  561. <NModal
  562. v-model:show={forms.showAttendClass}
  563. preset="card"
  564. showIcon={false}
  565. class={['modalTitle background', styles.attendClassModal]}
  566. title={'选择班级'}
  567. blockScroll={false}>
  568. <AttendClass
  569. onClose={() => (forms.showAttendClass = false)}
  570. type={forms.attendClassType}
  571. onPreview={(item: any) => {
  572. if (window.matchMedia('(display-mode: standalone)').matches) {
  573. state.application = window.matchMedia(
  574. '(display-mode: standalone)'
  575. ).matches;
  576. forms.previewModal = true;
  577. forms.previewParams = {
  578. ...item
  579. };
  580. } else {
  581. const { href } = router.resolve({
  582. path: '/attend-class',
  583. query: {
  584. ...item
  585. }
  586. });
  587. window.open(href, +new Date() + '');
  588. }
  589. }}
  590. onConfirm={async (item: any) => {
  591. if (forms.classGroupId) {
  592. forms.className = item.name;
  593. forms.classGroupId = item.classGroupId;
  594. forms.subjectId = item.subjectId;
  595. forms.showAttendClass = false;
  596. checkSubjectIds();
  597. // 声部切换时
  598. eventGlobal.emit('onChangeClass', {
  599. lastUseCoursewareId: item.lastUseCoursewareId,
  600. unit: item.unit
  601. });
  602. } else {
  603. const res = await courseScheduleStart({
  604. lessonCoursewareKnowledgeDetailId: prepareStore.selectKey,
  605. classGroupId: item.classGroupId
  606. });
  607. forms.showAttendClass = false;
  608. if (window.matchMedia('(display-mode: standalone)').matches) {
  609. state.application = window.matchMedia(
  610. '(display-mode: standalone)'
  611. ).matches;
  612. forms.previewModal = true;
  613. forms.previewParams = {
  614. type: 'class',
  615. classId: res.data, // 上课编号
  616. classGroupId: item.classGroupId,
  617. subjectId: prepareStore.getSubjectId,
  618. detailId: prepareStore.getSelectKey,
  619. lessonCourseId: prepareStore.getBaseCourseware.id
  620. };
  621. setTimeout(() => {
  622. fscreen();
  623. }, 200);
  624. } else {
  625. const { href } = router.resolve({
  626. path: '/attend-class',
  627. query: {
  628. type: 'class',
  629. classId: res.data, // 上课编号
  630. classGroupId: item.classGroupId,
  631. subjectId: prepareStore.getSubjectId,
  632. detailId: prepareStore.getSelectKey,
  633. lessonCourseId: prepareStore.getBaseCourseware.id
  634. }
  635. });
  636. window.open(href, +new Date() + '');
  637. }
  638. }
  639. }}
  640. />
  641. </NModal>
  642. {/* 弹窗查看 */}
  643. <CardPreview v-model:show={forms.show} item={forms.item} />
  644. <NModal
  645. v-model:show={forms.removeVisiable}
  646. preset="card"
  647. class={['modalTitle', styles.removeVisiable]}
  648. title={'提示'}>
  649. <div class={styles.studentRemove}>
  650. <p>是否完成编辑?</p>
  651. <NSpace class={styles.btnGroupModal} justify="center">
  652. <NButton round type="primary" onClick={onOverEdit}>
  653. 确定
  654. </NButton>
  655. <NButton round onClick={() => (forms.removeVisiable = false)}>
  656. 取消
  657. </NButton>
  658. </NSpace>
  659. </div>
  660. </NModal>
  661. <NModal
  662. v-model:show={forms.removeVisiable1}
  663. preset="card"
  664. class={['modalTitle', styles.removeVisiable1]}
  665. title={'清空资源'}>
  666. <div class={styles.studentRemove}>
  667. <p>
  668. 请确认是否要清空资源?
  669. <span>点击确认后所有的素材内容 将被清空掉。</span>
  670. </p>
  671. <NSpace class={styles.btnGroupModal} justify="center">
  672. <NButton
  673. round
  674. type="primary"
  675. onClick={() => {
  676. forms.coursewareList.forEach((item: any) => {
  677. forms.removeIds.push(item.id);
  678. });
  679. forms.coursewareList = [];
  680. forms.removeVisiable1 = false;
  681. forms.isEdit = true;
  682. // prepareStore.setCoursewareList([]);
  683. console.log(prepareStore.getCoursewareList, 'getCourseware1');
  684. }}>
  685. 确定
  686. </NButton>
  687. <NButton round onClick={() => (forms.removeVisiable1 = false)}>
  688. 取消
  689. </NButton>
  690. </NSpace>
  691. </div>
  692. </NModal>
  693. <PreviewWindow
  694. v-model:show={forms.previewModal}
  695. type="attend"
  696. params={forms.previewParams}
  697. />
  698. {/* 完成编辑时,选择声部 */}
  699. <NModal
  700. v-model:show={forms.subjectSyncVisiable}
  701. preset="card"
  702. class={['modalTitle background', styles.subjectSyncModal]}
  703. title={'同步声部'}>
  704. <SubjectSync
  705. subjectId={prepareStore.getSubjectId as any}
  706. onClose={() => (forms.subjectSyncVisiable = false)}
  707. onConfirm={async (subjectIds: any) => {
  708. //
  709. try {
  710. forms.editSubjectIds = subjectIds.join(',');
  711. await onOverEdit();
  712. forms.subjectSyncVisiable = false;
  713. } catch {
  714. //
  715. }
  716. }}
  717. />
  718. </NModal>
  719. </div>
  720. );
  721. }
  722. });