index.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. import { defineComponent, onMounted, reactive, watch } from 'vue';
  2. import styles from './index.module.less';
  3. import {
  4. NButton,
  5. NCarousel,
  6. NIcon,
  7. NImage,
  8. NInput,
  9. NModal,
  10. NScrollbar,
  11. NSelect,
  12. NSpace,
  13. NSpin,
  14. useMessage
  15. } from 'naive-ui';
  16. import { usePrepareStore } from '/src/store/modules/prepareLessons';
  17. import add from '@/views/studentList/images/add.png';
  18. import iconSlideRight from '../../../images/icon-slide-right.png';
  19. import CoursewareType from '../../../model/courseware-type';
  20. import TheEmpty from '/src/components/TheEmpty';
  21. import RelatedClass from '../../../model/related-class';
  22. import { useResizeObserver } from '@vueuse/core';
  23. import {
  24. api_addByOpenCourseware,
  25. api_eacherChapterLessonCoursewareRemove,
  26. api_queryOpenCoursewareByPage,
  27. api_updateCoursewareInfo,
  28. teacherChapterLessonCoursewareList
  29. } from '../../../api';
  30. import { useRoute } from 'vue-router';
  31. import TheMessageDialog from '/src/components/TheMessageDialog';
  32. import { eventGlobal } from '/src/utils';
  33. export default defineComponent({
  34. name: 'courseware-presets',
  35. emits: ['change'],
  36. setup(props, { emit }) {
  37. const prepareStore = usePrepareStore();
  38. const message = useMessage();
  39. const route = useRoute();
  40. const localStorageSubjectId = localStorage.getItem(
  41. 'prepareLessonSubjectId'
  42. );
  43. const forms = reactive({
  44. // 选取参数带的,后取缓存
  45. messageLoading: false,
  46. subjectId: route.query.subjectId
  47. ? Number(route.query.subjectId)
  48. : localStorageSubjectId
  49. ? Number(localStorageSubjectId)
  50. : null,
  51. courseScheduleSubjectId: route.query.courseScheduleSubjectId,
  52. bodyWidth: '100%',
  53. loading: false,
  54. openLoading: false,
  55. showRelatedClass: false,
  56. tableList: [] as any,
  57. openTableList: [] as any,
  58. selectItem: {} as any,
  59. editTitleVisiable: false,
  60. editTitle: null,
  61. editBtnLoading: false,
  62. preRemoveVisiable: false,
  63. carouselIndex: 0
  64. });
  65. const getCoursewareList = async () => {
  66. forms.loading = true;
  67. try {
  68. // 判断是否有选择对应的课件 或声部
  69. if (!prepareStore.getSelectKey) return (forms.loading = false);
  70. const { data } = await teacherChapterLessonCoursewareList({
  71. subjectId: prepareStore.getSubjectId,
  72. coursewareDetailKnowledgeId: prepareStore.getSelectKey
  73. });
  74. if (!Array.isArray(data)) {
  75. return;
  76. }
  77. const tempList: any = [];
  78. data.forEach((item: any) => {
  79. const firstItem: any =
  80. item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
  81. tempList.push({
  82. id: item.id,
  83. openFlag: item.openFlag,
  84. openFlagEnable: item.openFlagEnable,
  85. subjectNames: item.subjectNames,
  86. fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
  87. name: item.name,
  88. coverImg: firstItem?.bizInfo.coverImg,
  89. type: firstItem?.bizInfo.type
  90. });
  91. });
  92. forms.tableList = tempList;
  93. } catch {
  94. //
  95. }
  96. forms.loading = false;
  97. };
  98. const getOpenCoursewareList = async () => {
  99. // 查询公开课件列表
  100. forms.openLoading = true;
  101. try {
  102. // 判断是否有选择对应的课件 或声部
  103. if (!prepareStore.getSelectKey) return (forms.openLoading = false);
  104. const { data } = await api_queryOpenCoursewareByPage({
  105. subjectId: prepareStore.getSubjectId,
  106. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  107. page: 1,
  108. rows: 20
  109. });
  110. const result = data.rows || [];
  111. const tempList: any = [];
  112. result.forEach((item: any) => {
  113. const index = forms.tableList.findIndex(
  114. (i: any) => i.fromChapterLessonCoursewareId === item.id
  115. );
  116. const firstItem: any =
  117. item.chapterKnowledgeList[0]?.chapterKnowledgeMaterialList[0];
  118. tempList.push({
  119. id: item.id,
  120. openFlag: item.openFlag,
  121. openFlagEnable: item.openFlagEnable,
  122. subjectNames: item.subjectNames,
  123. fromChapterLessonCoursewareId: item.fromChapterLessonCoursewareId,
  124. name: item.name,
  125. coverImg: firstItem?.bizInfo.coverImg,
  126. type: firstItem?.bizInfo.type,
  127. isAdd: index !== -1 ? true : false
  128. });
  129. });
  130. forms.openTableList = tempList;
  131. } catch {
  132. //
  133. }
  134. forms.openLoading = false;
  135. };
  136. // 监听选择的key 左侧选择了其它的课
  137. watch(
  138. () => [prepareStore.getSelectKey, prepareStore.getSubjectId],
  139. async () => {
  140. await getCoursewareList();
  141. await getOpenCoursewareList();
  142. }
  143. );
  144. // 检测数据是否存在
  145. watch(
  146. () => forms.tableList,
  147. () => {
  148. // fromChapterLessonCoursewareId;
  149. forms.openTableList.forEach((item: any) => {
  150. const index = forms.tableList.findIndex(
  151. (i: any) => i.fromChapterLessonCoursewareId === item.id
  152. );
  153. item.isAdd = index !== -1 ? true : false;
  154. });
  155. }
  156. );
  157. const checkSubjectIds = () => {
  158. const subjectList = prepareStore.getSubjectList;
  159. // 并且没有声部时才会更新
  160. if (subjectList.length > 0) {
  161. // 并且声部在列表中
  162. const localStorageSubjectId = localStorage.getItem(
  163. 'prepareLessonSubjectId'
  164. );
  165. // // 先取 上次上课声部,在取班级声部 最后取缓存
  166. let subjectId = null;
  167. let index = -1;
  168. if (forms.courseScheduleSubjectId) {
  169. // 判断浏览器上面是否有
  170. index = subjectList.findIndex(
  171. (subject: any) => subject.id == forms.courseScheduleSubjectId
  172. );
  173. if (index >= 0) {
  174. subjectId = Number(forms.courseScheduleSubjectId);
  175. }
  176. }
  177. // 判断班级上面声部 & 还没有声部
  178. if (forms.subjectId && !subjectId) {
  179. // 判断浏览器上面是否有
  180. index = subjectList.findIndex(
  181. (subject: any) => subject.id == forms.subjectId
  182. );
  183. if (index >= 0) {
  184. subjectId = Number(forms.subjectId);
  185. }
  186. }
  187. // 缓存声部 & 还没有声部
  188. if (localStorageSubjectId && !subjectId) {
  189. // 判断浏览器上面是否有
  190. index = subjectList.findIndex(
  191. (subject: any) => subject.id == localStorageSubjectId
  192. );
  193. if (index >= 0) {
  194. subjectId = Number(localStorageSubjectId);
  195. }
  196. }
  197. if (subjectId && index >= 0) {
  198. prepareStore.setSubjectId(subjectId);
  199. } else {
  200. // 判断是否有缓存
  201. prepareStore.setSubjectId(subjectList[0].id);
  202. }
  203. // 保存
  204. localStorage.setItem(
  205. 'prepareLessonSubjectId',
  206. prepareStore.getSubjectId as any
  207. );
  208. }
  209. };
  210. onMounted(async () => {
  211. prepareStore.setClassGroupId(route.query.classGroupId as any);
  212. // 获取教材分类列表
  213. checkSubjectIds();
  214. useResizeObserver(
  215. document.querySelector('#coursewarePresets') as HTMLElement,
  216. (entries: any) => {
  217. const entry = entries[0];
  218. const { width } = entry.contentRect;
  219. forms.bodyWidth = width + 'px';
  220. }
  221. );
  222. await getCoursewareList();
  223. await getOpenCoursewareList();
  224. });
  225. // 重命名
  226. const onEditTitleSubmit = async () => {
  227. try {
  228. await api_updateCoursewareInfo({
  229. id: forms.selectItem.id,
  230. name: forms.editTitle
  231. });
  232. message.success('修改成功');
  233. getCoursewareList();
  234. forms.editTitleVisiable = false;
  235. } catch {
  236. //
  237. }
  238. };
  239. // 删除
  240. const onRemove = async () => {
  241. forms.messageLoading = true;
  242. try {
  243. await api_eacherChapterLessonCoursewareRemove({
  244. id: forms.selectItem.id
  245. });
  246. message.success('删除成功');
  247. getCoursewareList();
  248. forms.preRemoveVisiable = false;
  249. } catch {
  250. //
  251. }
  252. setTimeout(() => {
  253. forms.messageLoading = false;
  254. }, 100);
  255. };
  256. // 添加课件
  257. const onAddCourseware = async (item: any) => {
  258. if (forms.messageLoading) return;
  259. forms.messageLoading = true;
  260. try {
  261. await api_addByOpenCourseware({ id: item.id });
  262. message.success('添加成功');
  263. getCoursewareList();
  264. } catch {
  265. //
  266. }
  267. setTimeout(() => {
  268. forms.messageLoading = false;
  269. }, 100);
  270. };
  271. return () => (
  272. <div class={styles.coursewarePresetsContainer}>
  273. <NScrollbar class={styles.coursewarePresets}>
  274. <div class={styles.title} id="coursewarePresets">
  275. <div class={styles.titleLeft}>
  276. <i class={[styles.icon, styles.iconWork]}></i>
  277. 我的课件
  278. </div>
  279. </div>
  280. <NSpace>
  281. <NSelect
  282. placeholder="选择声部"
  283. class={styles.btnSubjectList}
  284. options={[
  285. { name: '全部声部', id: '' },
  286. ...prepareStore.getSubjectList
  287. ]}
  288. labelField="name"
  289. valueField="id"
  290. value={prepareStore.getSubjectId}
  291. onUpdate:value={(val: any) => {
  292. prepareStore.setSubjectId(val);
  293. // 保存
  294. }}
  295. />
  296. <NButton
  297. class={styles.addBtn}
  298. type="primary"
  299. onClick={() => {
  300. eventGlobal.emit('teacher-slideshow', true);
  301. emit('change', { status: true });
  302. }}>
  303. <NImage
  304. class={styles.addBtnIcon}
  305. previewDisabled
  306. src={add}></NImage>
  307. 添加课件
  308. </NButton>
  309. </NSpace>
  310. <div style={{ overflow: 'hidden' }}>
  311. <NSpin show={forms.loading}>
  312. <div class={styles.list}>
  313. {forms.tableList.map((item: any) => (
  314. <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
  315. <div class={styles.itemWrapBox}>
  316. <CoursewareType
  317. operate
  318. isEditName
  319. item={item}
  320. onEditName={() => {
  321. forms.selectItem = item;
  322. forms.editTitle = item.name;
  323. forms.editTitleVisiable = true;
  324. }}
  325. onDelete={() => {
  326. forms.selectItem = item;
  327. forms.preRemoveVisiable = true;
  328. }}
  329. />
  330. </div>
  331. </div>
  332. ))}
  333. {!forms.loading && forms.tableList.length <= 0 && <TheEmpty />}
  334. </div>
  335. </NSpin>
  336. </div>
  337. <div class={[styles.title, styles.line]}>
  338. <div class={styles.titleLeft}>
  339. <i class={[styles.icon, styles.iconCourseware]}></i>
  340. 相关课件
  341. {forms.openTableList.length > 4 && (
  342. <span
  343. class={styles.more}
  344. onClick={() => (forms.showRelatedClass = true)}>
  345. 查看更多
  346. <NIcon>
  347. <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  348. <path
  349. d="M8.59 16.59L13.17 12L8.59 7.41L10 6l6 6l-6 6l-1.41-1.41z"
  350. fill="currentColor"></path>
  351. </svg>
  352. </NIcon>
  353. </span>
  354. )}
  355. </div>
  356. {forms.openTableList.length > 4 && (
  357. <NSpace class={styles.swipeControll}>
  358. <div>
  359. <NImage
  360. previewDisabled
  361. class={[styles.leftIcon]}
  362. src={iconSlideRight}
  363. />
  364. </div>
  365. <div>
  366. <NImage previewDisabled src={iconSlideRight} />
  367. </div>
  368. </NSpace>
  369. )}
  370. </div>
  371. <NSpin show={forms.openLoading} class={styles.openLoading}>
  372. <NCarousel
  373. slidesPerView={4}
  374. loop={false}
  375. style={{ width: forms.bodyWidth }}
  376. v-model:currentIndex={forms.carouselIndex}>
  377. {forms.openTableList.map((item: any) => (
  378. <div class={[styles.itemWrap, styles.itemBlock, 'row-nav']}>
  379. <div class={styles.itemWrapBox}>
  380. <CoursewareType
  381. isShowAdd
  382. item={item}
  383. onAdd={() => onAddCourseware(item)}
  384. />
  385. </div>
  386. </div>
  387. ))}
  388. </NCarousel>
  389. </NSpin>
  390. </NScrollbar>
  391. <NModal
  392. v-model:show={forms.showRelatedClass}
  393. preset="card"
  394. showIcon={false}
  395. class={['modalTitle background', styles.attendClassModal]}
  396. title={'相关课件'}
  397. blockScroll={false}>
  398. <RelatedClass
  399. tableList={forms.tableList}
  400. subjectList={prepareStore.getSubjectList}
  401. subjectId={prepareStore.getSubjectId as any}
  402. coursewareDetailKnowledgeId={prepareStore.getSelectKey}
  403. onClose={() => (forms.showRelatedClass = false)}
  404. onAdd={(item: any) => onAddCourseware(item)}
  405. />
  406. </NModal>
  407. <NModal
  408. v-model:show={forms.editTitleVisiable}
  409. preset="card"
  410. class={['modalTitle', styles.removeVisiable1]}
  411. title={'课件重命名'}>
  412. <div class={styles.studentRemove}>
  413. <NInput
  414. placeholder="请输入课件名称"
  415. v-model:value={forms.editTitle}
  416. maxlength={15}
  417. onKeyup={(e: any) => {
  418. if (e.code === 'ArrowLeft' || e.code === 'ArrowRight') {
  419. e.stopPropagation();
  420. }
  421. }}
  422. />
  423. <NSpace class={styles.btnGroupModal} justify="center">
  424. <NButton round onClick={() => (forms.editTitleVisiable = false)}>
  425. 取消
  426. </NButton>
  427. <NButton
  428. round
  429. type="primary"
  430. onClick={onEditTitleSubmit}
  431. loading={forms.editBtnLoading}>
  432. 确定
  433. </NButton>
  434. </NSpace>
  435. </div>
  436. </NModal>
  437. <NModal
  438. v-model:show={forms.preRemoveVisiable}
  439. preset="card"
  440. class={['modalTitle', styles.removeVisiable1]}
  441. title={'保存预设'}>
  442. <TheMessageDialog
  443. content={`<p style="text-align: left;">请确认是否删除【${forms.selectItem.name}】,删除后不可恢复</p>`}
  444. cancelButtonText="取消"
  445. confirmButtonText="确认"
  446. loading={forms.messageLoading}
  447. onClose={() => (forms.preRemoveVisiable = false)}
  448. onConfirm={() => onRemove()}
  449. />
  450. </NModal>
  451. </div>
  452. );
  453. }
  454. });