index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. queryCourseware,
  20. saveCourseware,
  21. teacherKnowledgeMaterialDelete
  22. } from '../../../api';
  23. import Draggable from 'vuedraggable';
  24. import iconDelete from '../../../images/icon-delete.png';
  25. import { useRouter } from 'vue-router';
  26. export default defineComponent({
  27. name: 'courseware-modal',
  28. setup() {
  29. const catchStore = useCatchStore();
  30. const prepareStore = usePrepareStore();
  31. const router = useRouter();
  32. const dialog = useDialog();
  33. const message = useMessage();
  34. const forms = reactive({
  35. coursewareList: [] as any,
  36. loadingStatus: false,
  37. showAttendClass: false,
  38. removeIds: [] as any, // 临时删除的编号
  39. drag: false
  40. });
  41. // 获取列表
  42. const getList = async () => {
  43. forms.loadingStatus = true;
  44. try {
  45. // 判断是否有选择对应的课件 或声部
  46. if (!prepareStore.getSelectKey || !prepareStore.getSubjectId)
  47. return (forms.loadingStatus = false);
  48. const { data } = await queryCourseware({
  49. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  50. subjectId: prepareStore.getSubjectId,
  51. page: 1,
  52. rows: 99
  53. });
  54. const tempRows = data.rows || [];
  55. const temp: any = [];
  56. tempRows.forEach((row: any) => {
  57. temp.push({
  58. id: row.id,
  59. materialId: row.materialId,
  60. coverImg: row.coverImg,
  61. type: row.materialType,
  62. title: row.materialName,
  63. isCollect: !!row.favoriteFlag,
  64. isSelected: row.source === 'PLATFORM' ? true : false,
  65. content: row.content,
  66. removeFlag: row.removeFlag
  67. });
  68. });
  69. prepareStore.setCoursewareList(temp || []);
  70. console.log(forms.removeIds, 'remove', temp);
  71. forms.coursewareList =
  72. temp.map((item: any) => {
  73. if (!forms.removeIds.includes(item.id)) return item;
  74. }) || [];
  75. } catch {
  76. //
  77. }
  78. forms.loadingStatus = false;
  79. };
  80. // 监听选择的key 左侧选择了其它的课
  81. watch(
  82. () => prepareStore.getSelectKey,
  83. () => {
  84. getList();
  85. }
  86. );
  87. // 声部变化时
  88. watch(
  89. () => prepareStore.getSubjectId,
  90. () => {
  91. getList();
  92. }
  93. );
  94. watch(
  95. () => prepareStore.getIsAddResource,
  96. (val: boolean) => {
  97. if (val) {
  98. getList();
  99. prepareStore.setIsAddResource(false);
  100. }
  101. }
  102. );
  103. // 删除
  104. const onDelete = (item: any) => {
  105. //
  106. forms.removeIds.push(item.id);
  107. const index = forms.coursewareList.findIndex(
  108. (c: any) => c.id === item.id
  109. );
  110. forms.coursewareList.splice(index, 1);
  111. // prepareStore.setCoursewareList(forms.coursewareList);
  112. };
  113. // 完成编辑
  114. const onOverEdit = async () => {
  115. dialog.warning({
  116. title: '提示',
  117. content: `是否完成编辑?`,
  118. positiveText: '确定',
  119. negativeText: '取消',
  120. onPositiveClick: async () => {
  121. try {
  122. const temp: any = [];
  123. forms.coursewareList.forEach((item: any) => {
  124. temp.push({
  125. materialName: item.title,
  126. materialType: item.type,
  127. materialId: item.materialId,
  128. id: item.id
  129. });
  130. });
  131. // 保存课件
  132. await saveCourseware({
  133. coursewareDetailKnowledgeId: prepareStore.getSelectKey,
  134. lessonCoursewareId: prepareStore.getLessonCoursewareId,
  135. lessonCoursewareDetailId:
  136. prepareStore.getLessonCoursewareDetailId,
  137. materialList: [...temp]
  138. });
  139. forms.drag = false;
  140. message.success('编辑成功');
  141. prepareStore.setCoursewareList(forms.coursewareList);
  142. // 重置临时删除编号
  143. forms.removeIds = [];
  144. } catch {
  145. //
  146. }
  147. }
  148. });
  149. };
  150. // 预览上课
  151. const onPreviewAttend = () => {
  152. // 获取上架的数据
  153. let count = 0;
  154. forms.coursewareList.forEach((item: any) => {
  155. if (!item.removeFlag) {
  156. count++;
  157. }
  158. });
  159. if (count <= 0) {
  160. message.error('课件不能为空');
  161. return;
  162. }
  163. const { href } = router.resolve({
  164. path: '/attend-class',
  165. query: {
  166. type: 'preview',
  167. subjectId: prepareStore.getSubjectId,
  168. detailId: prepareStore.getSelectKey
  169. }
  170. });
  171. window.open(href, +new Date() + '');
  172. };
  173. // 单个删除
  174. const onRemove = async (item: any) => {
  175. try {
  176. dialog.warning({
  177. title: '提示',
  178. content: '该资源已下架,是否删除?',
  179. positiveText: '确定',
  180. negativeText: '取消',
  181. onPositiveClick: async () => {
  182. forms.removeIds.push(item.id);
  183. await teacherKnowledgeMaterialDelete({ ids: item.id });
  184. message.success('删除成功');
  185. getList();
  186. }
  187. });
  188. } catch {
  189. //
  190. }
  191. };
  192. onMounted(async () => {
  193. // 获取教材分类列表
  194. await catchStore.getSubjects();
  195. const subjectList = catchStore.getSubjectList;
  196. // 并且没有声部时才会更新
  197. if (subjectList.length > 0 && !prepareStore.getSubjectId) {
  198. prepareStore.setSubjectId(subjectList[0].id);
  199. }
  200. await getList();
  201. });
  202. return () => (
  203. <div class={styles.coursewareModal}>
  204. <div class={styles.btnGroup}>
  205. {forms.drag ? (
  206. <NSpace>
  207. <NButton type="default" onClick={onOverEdit}>
  208. 完成编辑
  209. </NButton>
  210. <NButton
  211. type="error"
  212. onClick={() => {
  213. forms.drag = false;
  214. forms.removeIds = [];
  215. getList();
  216. }}>
  217. 退出编辑
  218. </NButton>
  219. <NButton
  220. type="error"
  221. onClick={() => {
  222. forms.coursewareList.forEach((item: any) => {
  223. forms.removeIds.push(item.id);
  224. });
  225. forms.coursewareList = [];
  226. // prepareStore.setCoursewareList([]);
  227. }}>
  228. 清空资源
  229. </NButton>
  230. <span class={styles.tips}>拖动可将资源进行排序</span>
  231. </NSpace>
  232. ) : (
  233. <NSpace>
  234. <NSelect
  235. placeholder="选择声部"
  236. options={catchStore.getSubjectList}
  237. labelField="name"
  238. valueField="id"
  239. value={prepareStore.getSubjectId}
  240. onUpdate:value={(val: any) => {
  241. prepareStore.setSubjectId(val);
  242. getList();
  243. }}
  244. />
  245. <NButton type="default" onClick={() => (forms.drag = true)}>
  246. 编辑
  247. </NButton>
  248. </NSpace>
  249. )}
  250. <NSpace>
  251. <NButton type="default" onClick={onPreviewAttend}>
  252. 预览
  253. </NButton>
  254. <NButton
  255. {...{ id: 'lessons-3' }}
  256. type="primary"
  257. onClick={() => {
  258. let count = 0;
  259. forms.coursewareList.forEach((item: any) => {
  260. if (!item.removeFlag) {
  261. count++;
  262. }
  263. });
  264. if (count <= 0) {
  265. message.error('课件不能为空');
  266. return;
  267. }
  268. forms.showAttendClass = true;
  269. }}>
  270. 开始上课
  271. </NButton>
  272. </NSpace>
  273. </div>
  274. <NScrollbar class={styles.listContainer}{...{id:'lessons-2'}} >
  275. <NSpin show={forms.loadingStatus}>
  276. <div
  277. class={[
  278. styles.listSection,
  279. !forms.loadingStatus && forms.coursewareList.length <= 0
  280. ? styles.emptySection
  281. : ''
  282. ]}>
  283. {forms.coursewareList.length > 0 && (
  284. <>
  285. {forms.drag ? (
  286. <Draggable
  287. v-model:modelValue={forms.coursewareList}
  288. itemKey="id"
  289. componentData={{
  290. animation: 200,
  291. group: 'description'
  292. }}
  293. class={styles.list}>
  294. {{
  295. item: (element: any,index:number) => {
  296. const item = element.element;
  297. return (<>
  298. <div
  299. data-id={item.id}
  300. class={[styles.itemBlock, 'row-nav']}>
  301. <CardType
  302. class={[styles.itemContent, 'handle']}
  303. isShowCollect={false}
  304. offShelf={item.removeFlag ? true : false}
  305. onOffShelf={() => onRemove(item)}
  306. item={item}
  307. />
  308. <div class={styles.itemOperation}>
  309. <img
  310. src={iconDelete}
  311. class={styles.iconDelete}
  312. onClick={(e: MouseEvent) => {
  313. e.stopPropagation();
  314. onDelete(item);
  315. }}
  316. />
  317. </div>
  318. </div>
  319. </>
  320. );
  321. }
  322. }}
  323. </Draggable>
  324. ) : (
  325. <div class={styles.list}>
  326. {forms.coursewareList.map((item: any,index:number) => (
  327. <CardType
  328. class={[styles.itemContent, 'handle']}
  329. isShowCollect={false}
  330. item={item}
  331. offShelf={item.removeFlag ? true : false}
  332. onOffShelf={() => onRemove(item)}
  333. />
  334. ))}
  335. </div>
  336. )}
  337. </>
  338. )}
  339. {!forms.loadingStatus && forms.coursewareList.length <= 0 && (
  340. <TheEmpty description="暂无课件" />
  341. )}
  342. </div>
  343. </NSpin>
  344. </NScrollbar>
  345. <NModal
  346. v-model:show={forms.showAttendClass}
  347. preset="card"
  348. showIcon={false}
  349. class={['modalTitle background', styles.attendClassModal]}
  350. title={'选择班级'}
  351. blockScroll={false}>
  352. <AttendClass onClose={() => (forms.showAttendClass = false)} />
  353. </NModal>
  354. </div>
  355. );
  356. }
  357. });