index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. import {
  2. PropType,
  3. defineComponent,
  4. onMounted,
  5. onUnmounted,
  6. reactive,
  7. toRefs
  8. } from 'vue';
  9. import ResourceSearchGroup from './resource-search-group';
  10. import { NScrollbar, NSpin, useMessage } from 'naive-ui';
  11. import styles from './index.module.less';
  12. import CardType from '/src/components/card-type';
  13. import { favorite, materialQueryPage } from '/src/views/natural-resources/api';
  14. import TheEmpty from '/src/components/TheEmpty';
  15. import { usePrepareStore } from '/src/store/modules/prepareLessons';
  16. import { useDebounceFn, useResizeObserver } from '@vueuse/core';
  17. import CardPreview from '/src/components/card-preview';
  18. import { eventGlobal } from '/src/utils';
  19. import ClassSearchGroup from './class-search-group';
  20. import { useCatchStore } from '/src/store/modules/catchData';
  21. const formatType = (type: string) => {
  22. if (type === 'shareResources') {
  23. return 2;
  24. } else if (type === 'myResources') {
  25. return 3;
  26. } else if (type === 'myCollect') {
  27. return 4;
  28. } else if (type === 'relateResources') {
  29. return 5;
  30. }
  31. };
  32. export default defineComponent({
  33. name: 'share-resources',
  34. props: {
  35. type: {
  36. type: String as PropType<
  37. 'relateResources' | 'shareResources' | 'myResources' | 'myCollect'
  38. >,
  39. default: 'shareResources'
  40. },
  41. searchGroup: {
  42. type: Object,
  43. default: () => ({})
  44. },
  45. /** 从哪里使用 */
  46. from: {
  47. type: String,
  48. default: ''
  49. },
  50. instrumentId: {
  51. type: String,
  52. default: ''
  53. }
  54. },
  55. setup(props) {
  56. const prepareStore = usePrepareStore();
  57. const catchStore = useCatchStore();
  58. const { type } = toRefs(props);
  59. const className = 'resourceSearchGroup' + +new Date();
  60. const className2 = 'spinSearchGroup' + +new Date();
  61. const state = reactive({
  62. searchHeight: '0px',
  63. searchHeight2: '0px',
  64. loading: false,
  65. finshed: false, // 是否加载完
  66. pagination: {
  67. page: 1,
  68. rows: 20
  69. },
  70. searchGroup: {
  71. type: 'MUSIC', //
  72. name: '',
  73. bookVersionId: null,
  74. subjectId: null,
  75. audioPlayTypes: props.type === 'myResources' ? ['PLAY'] : [],
  76. sourceType: formatType(type.value),
  77. musicalInstrumentId: null as any,
  78. enableFlag: true
  79. },
  80. tableList: [] as any,
  81. show: false,
  82. item: {} as any
  83. });
  84. // 查询列表
  85. const getList = async () => {
  86. try {
  87. if (state.pagination.page === 1) {
  88. state.loading = true;
  89. }
  90. const { data } = await materialQueryPage({
  91. ...state.searchGroup,
  92. ...state.pagination,
  93. lessonCoursewareKnowledgeId:
  94. props.type === 'relateResources' || props.type === 'shareResources'
  95. ? prepareStore.getSelectKey
  96. : null,
  97. relateLessonCoursewareKnowledgeMaterialIds: getIds()
  98. });
  99. state.loading = false;
  100. const tempRows = data.rows || [];
  101. const temp: any = [];
  102. tempRows.forEach((row: any) => {
  103. temp.push({
  104. id: row.id,
  105. coverImg: row.coverImg,
  106. type: row.type,
  107. title: row.name,
  108. isCollect: !!row.favoriteFlag,
  109. isSelected: row.sourceFrom === 'PLATFORM' ? true : false,
  110. refFlag: row.refFlag,
  111. audioPlayTypeArray: row.audioPlayTypes
  112. ? row.audioPlayTypes.split(',')
  113. : [],
  114. containAccompaniment: row.containAccompaniment,
  115. content: row.content
  116. });
  117. });
  118. state.tableList.push(...temp);
  119. state.finshed = data.pages <= data.current ? true : false;
  120. } catch {
  121. state.loading = false;
  122. }
  123. };
  124. const onSearch = (item: any) => {
  125. state.pagination.page = 1;
  126. state.tableList = [];
  127. const { subjectId, ...res } = item;
  128. state.searchGroup = Object.assign(state.searchGroup, {
  129. ...res,
  130. musicalInstrumentId: subjectId,
  131. subjectId: null
  132. });
  133. getList();
  134. };
  135. const throttledFnSearch = useDebounceFn(item => {
  136. onSearch(item);
  137. }, 300);
  138. // 添加资源
  139. const onAdd = async (item: any) => {
  140. try {
  141. eventGlobal.emit('onPrepareAddItem', {
  142. materialId: item.id,
  143. coverImg: item.coverImg,
  144. type: item.type,
  145. title: item.title,
  146. refFlag: item.refFlag,
  147. isCollect: item.isCollect,
  148. isSelected: item.isSelected,
  149. content: item.content,
  150. removeFlag: false
  151. });
  152. } catch {
  153. //
  154. }
  155. };
  156. // 收藏
  157. const onCollect = async (item: any) => {
  158. try {
  159. await favorite({
  160. materialId: item.id,
  161. favoriteFlag: item.isCollect ? 0 : 1,
  162. type: item.type
  163. });
  164. item.isCollect = !item.isCollect;
  165. } catch {
  166. //
  167. }
  168. };
  169. const getIds = () => {
  170. let noRepeatIds: any = [];
  171. if (props.type === 'relateResources') {
  172. const materialIds: any = [];
  173. prepareStore.getCoursewareList.forEach((course: any) => {
  174. course.list?.forEach((item: any) => {
  175. materialIds.push(item.materialId);
  176. });
  177. });
  178. noRepeatIds = Array(...new Set(materialIds));
  179. }
  180. return noRepeatIds.join(',');
  181. };
  182. const onUpdate = () => {
  183. state.pagination.page = 1;
  184. state.tableList = [];
  185. getList();
  186. };
  187. onMounted(async () => {
  188. // 加载的时候判断是否有资源数据
  189. // 获取声部
  190. await catchStore.getSubjects();
  191. useResizeObserver(
  192. document.querySelector('.' + className) as HTMLElement,
  193. (entries: any) => {
  194. const entry = entries[0];
  195. const { height } = entry.contentRect;
  196. state.searchHeight = height + 'px';
  197. }
  198. );
  199. useResizeObserver(
  200. document.querySelector('.' + className2) as HTMLElement,
  201. (entries: any) => {
  202. const entry = entries[0];
  203. const { height } = entry.contentRect;
  204. state.searchHeight2 = height + 'px';
  205. }
  206. );
  207. // if (props.type !== 'shareResources' || props.from === 'class') {
  208. // getList();
  209. // }
  210. if (props.type === 'relateResources') {
  211. eventGlobal.on('onCoursewareUpdate', onUpdate);
  212. }
  213. });
  214. onUnmounted(() => {
  215. eventGlobal.off('onCoursewareUpdate', onUpdate);
  216. });
  217. return () => (
  218. <div>
  219. {/* <div class={className}>
  220. {props.from !== 'class' && (
  221. <ResourceSearchGroup
  222. type={props.type}
  223. onSearch={(item: any, type: any) => {
  224. if (type) {
  225. onSearch(item);
  226. return;
  227. }
  228. throttledFnSearch(item);
  229. }}
  230. />
  231. )}
  232. </div> */}
  233. <NScrollbar
  234. class={[styles.listContainer, 'list_container']}
  235. style={{
  236. 'max-height': `calc(var(--listContainerHeight) - var(--modal-lesson-tab-height) - ${state.searchHeight}) `
  237. }}
  238. onScroll={(e: any) => {
  239. const clientHeight = e.target?.clientHeight;
  240. const scrollTop = e.target?.scrollTop;
  241. const scrollHeight = e.target?.scrollHeight;
  242. // 是否到底,是否加载完
  243. if (
  244. clientHeight + scrollTop + 20 >= scrollHeight &&
  245. !state.finshed &&
  246. !state.loading
  247. ) {
  248. state.pagination.page = state.pagination.page + 1;
  249. getList();
  250. }
  251. }}>
  252. <div class={className2}>
  253. {props.from === 'class' ? (
  254. <ClassSearchGroup
  255. from={props.from}
  256. type={props.type}
  257. subjectId={
  258. (prepareStore.getSubjectId as any) || props.instrumentId
  259. }
  260. onSearch={(item: any, type: any) => {
  261. if (type) {
  262. onSearch(item);
  263. return;
  264. }
  265. throttledFnSearch(item);
  266. }}
  267. />
  268. ) : (
  269. <ResourceSearchGroup
  270. type={props.type}
  271. searchGroup={props.searchGroup}
  272. onSearch={(item: any, type: any) => {
  273. if (type) {
  274. onSearch(item);
  275. return;
  276. }
  277. throttledFnSearch(item);
  278. }}
  279. />
  280. )}
  281. </div>
  282. <NSpin show={state.loading} size={'small'}>
  283. <div
  284. style={{
  285. 'min-height': `calc(var(--listContainerHeight) - var(--modal-lesson-tab-height) - ${state.searchHeight} - ${state.searchHeight2})`
  286. }}
  287. class={[
  288. styles.listSection,
  289. !state.loading && state.tableList.length <= 0
  290. ? styles.emptySection
  291. : ''
  292. ]}>
  293. {state.tableList.length > 0 && (
  294. <div class={styles.list}>
  295. {state.tableList.map((item: any) => (
  296. <div class={[styles.itemWrap, 'selresources_item_Wrap']}>
  297. <div class={styles.itemWrapBox}>
  298. <CardType
  299. isShowAdd={props.from === 'class' ? false : true}
  300. item={item}
  301. isShowCollect={true}
  302. // isShowAddDisabled={!prepareStore.getIsEditResource}
  303. onAdd={(item: any) => onAdd(item)}
  304. disabledMouseHover={false}
  305. onCollect={(item: any) => onCollect(item)}
  306. onClick={() => {
  307. if (item.type === 'IMG') return;
  308. state.show = true;
  309. state.item = {
  310. instrumentId:
  311. state.searchGroup.musicalInstrumentId,
  312. ...item
  313. };
  314. }}
  315. />
  316. </div>
  317. </div>
  318. ))}
  319. </div>
  320. )}
  321. {!state.loading && state.tableList.length <= 0 && <TheEmpty />}
  322. </div>
  323. </NSpin>
  324. </NScrollbar>
  325. {/* 弹窗查看 */}
  326. <CardPreview
  327. size={props.from === 'class' ? 'large' : 'default'}
  328. v-model:show={state.show}
  329. from={props.from}
  330. item={state.item}
  331. isDownload={false}
  332. />
  333. </div>
  334. );
  335. }
  336. });