index.tsx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. import {
  2. PropType,
  3. defineComponent,
  4. nextTick,
  5. onMounted,
  6. reactive,
  7. ref,
  8. toRef,
  9. toRefs,
  10. watch
  11. } from 'vue';
  12. import styles from './index.module.less';
  13. import {
  14. NButton,
  15. NForm,
  16. NFormItem,
  17. NImage,
  18. NPopselect,
  19. NSpace
  20. } from 'naive-ui';
  21. import { resourceTypeArray2 } from '/src/utils/searchArray';
  22. import { useCatchStore } from '/src/store/modules/catchData';
  23. import { useThrottleFn } from '@vueuse/core';
  24. import TheSearch from '/src/components/TheSearch';
  25. import isCollaose from '/src/views/natural-resources/images/isCollaose.png';
  26. import { audioPlayType } from '/src/utils/contants';
  27. const ChildNodeSearch = defineComponent({
  28. name: 'ChildNodeSearch',
  29. props: {
  30. activeRow: {
  31. type: Object,
  32. default: () => ({})
  33. },
  34. list: {
  35. type: Array,
  36. default: () => []
  37. }
  38. },
  39. emits: ['selectChildTag'],
  40. setup(props, { emit }) {
  41. const { activeRow } = toRefs(props);
  42. const selectItem = ref({});
  43. watch(
  44. () => props.activeRow,
  45. () => {
  46. activeRow.value = props.activeRow;
  47. initActiveRow();
  48. }
  49. );
  50. const initActiveRow = () => {
  51. if (activeRow.value.activeIndex) {
  52. const childList = activeRow.value.children || [];
  53. childList.forEach((subject: any) => {
  54. if (subject.id === activeRow.value.activeIndex) {
  55. let children: any;
  56. let columnName = '';
  57. if (subject.children) {
  58. children = [
  59. {
  60. columnName: subject.children[0].columnName,
  61. name: '全部',
  62. id: ''
  63. },
  64. ...subject.children
  65. ];
  66. columnName = subject.children[0].columnName;
  67. selectItem.value = {
  68. ...subject,
  69. columnName,
  70. activeIndex: subject.activeIndex,
  71. children
  72. };
  73. }
  74. }
  75. });
  76. } else {
  77. selectItem.value = {};
  78. }
  79. };
  80. onMounted(() => {
  81. initActiveRow();
  82. });
  83. return () => (
  84. <>
  85. {activeRow.value?.id && (
  86. <>
  87. <NFormItem label={activeRow.value.columnName + ':'}>
  88. <NSpace class={styles.spaceSection}>
  89. {activeRow.value?.children.map((subject: any) => (
  90. <span
  91. class={[
  92. styles.textBtn,
  93. (activeRow.value.activeIndex || '') == subject.id &&
  94. styles.textBtnActive
  95. ]}
  96. onClick={() => {
  97. activeRow.value.activeIndex = subject.id;
  98. let children: any;
  99. let columnName = '';
  100. if (subject.children) {
  101. children = [
  102. {
  103. columnName: subject.children[0].columnName,
  104. name: '全部',
  105. id: ''
  106. },
  107. ...subject.children
  108. ];
  109. columnName = subject.children[0].columnName;
  110. selectItem.value = {
  111. ...subject,
  112. columnName,
  113. activeIndex: '',
  114. children
  115. };
  116. } else {
  117. selectItem.value = {};
  118. }
  119. emit('selectChildTag', activeRow.value.activeIndex);
  120. }}>
  121. {subject.name}
  122. </span>
  123. ))}
  124. </NSpace>
  125. </NFormItem>
  126. <ChildNodeSearch
  127. activeRow={selectItem.value}
  128. onSelectChildTag={(item: any) => {
  129. emit('selectChildTag', item || activeRow.value.activeIndex);
  130. }}
  131. />
  132. </>
  133. )}
  134. </>
  135. );
  136. }
  137. });
  138. export default defineComponent({
  139. name: 'resource-search-group',
  140. props: {
  141. type: {
  142. type: String as PropType<
  143. 'relateResources' | 'shareResources' | 'myResources' | 'myCollect'
  144. >,
  145. default: 'shareResources'
  146. },
  147. searchGroup: {
  148. type: Object,
  149. default: () => ({})
  150. },
  151. subjectId: {
  152. type: String,
  153. default: null
  154. }
  155. },
  156. emits: ['search'],
  157. setup(props, { emit }) {
  158. const subjectId = toRef(props.subjectId);
  159. const catchStore = useCatchStore();
  160. const forms = reactive({
  161. type: 'IMG', //
  162. name: '',
  163. subjectId: subjectId.value as any,
  164. // grade: null as any,
  165. audioPlayTypes: props.type == 'myResources' ? 'PLAY' : '',
  166. bookVersionId: null as any,
  167. materialTagId: null
  168. // musicSheetCategoriesId: null as any
  169. });
  170. const state = reactive({
  171. tempSubjectId: null,
  172. gradeList: [] as any[],
  173. musicCategory: [] as any
  174. });
  175. const data = reactive({
  176. selectParents: {}, // 选中的数据
  177. tags: [] as any[],
  178. tagActiveId: '' as any,
  179. tagActive: {} as any,
  180. childSelectId: null as any
  181. });
  182. const resourceType = ref([] as any);
  183. const audioPlayTypeList = ref([] as any);
  184. const onSearch = (type?: string) => {
  185. emit(
  186. 'search',
  187. {
  188. ...forms,
  189. subjectId: forms.audioPlayTypes !== 'SING' ? forms.subjectId : null,
  190. audioPlayTypes: forms.audioPlayTypes
  191. ? forms.audioPlayTypes === 'PLAY_SING'
  192. ? ['PLAY', 'SING']
  193. : [forms.audioPlayTypes]
  194. : [],
  195. bookVersionId: data.childSelectId || data.tagActiveId
  196. },
  197. type
  198. );
  199. };
  200. const throttleFn = useThrottleFn(() => onSearch(), 500);
  201. const collapseWrapRef = ref();
  202. const divDomList = ref([] as any);
  203. const orginHeight = ref(0);
  204. const hiddenHeight = ref(0);
  205. const line = ref(0);
  206. const isCollapse = ref(false);
  207. const loadingCollapse = ref(false); // 是否加载完成
  208. // const musicCateRef = (el: any) => {
  209. // if (el?.selfElRef) {
  210. // divDomList.value.push(el.selfElRef.parentNode);
  211. // }
  212. // };
  213. // const setCollapse = (flag: boolean) => {
  214. // isCollapse.value = flag;
  215. // getLive();
  216. // };
  217. const getLive = () => {
  218. try {
  219. divDomList.value = [...new Set(divDomList.value)];
  220. let offsetLeft = -1;
  221. divDomList.value.forEach((item: any, index: number) => {
  222. if (index === 0) {
  223. line.value = 1;
  224. offsetLeft = item.offsetLeft;
  225. } else if (item.offsetLeft === offsetLeft && index != 0) {
  226. // 如果某个标签的offsetLeft和第一个标签的offsetLeft相等 说明增加了一行
  227. line.value++;
  228. }
  229. if (!isCollapse.value) {
  230. if (line.value > 1) {
  231. //从第3行开始 隐藏标签
  232. item.style.display = 'none';
  233. // 显示展开按钮 class名chu是在前面动态添加的
  234. } else {
  235. item.style.display = 'block';
  236. }
  237. } else {
  238. item.style.display = 'block';
  239. }
  240. });
  241. loadingCollapse.value = true;
  242. } catch {
  243. //
  244. }
  245. };
  246. const selectChildObj = (item: any) => {
  247. const obj: any = {};
  248. item?.forEach((child: any) => {
  249. if (child.id === forms.subjectId) {
  250. obj.selected = true;
  251. obj.name = child.name;
  252. }
  253. });
  254. return obj;
  255. };
  256. const _initTags = () => {
  257. const tags = catchStore.getMusicTagTree;
  258. data.tags = [
  259. {
  260. columnName: tags[0].columnName,
  261. name: '全部',
  262. id: ''
  263. },
  264. ...tags
  265. ];
  266. data.tagActiveId = data.tags[0].id;
  267. };
  268. const changeTag = (item: any) => {
  269. data.tagActiveId = item.id;
  270. data.childSelectId = null;
  271. let children: any;
  272. let columnName = '';
  273. if (item.children) {
  274. children = [
  275. {
  276. columnName: item.children[0].columnName,
  277. name: '全部',
  278. id: ''
  279. },
  280. ...item.children
  281. ];
  282. columnName = item.children[0].columnName;
  283. data.selectParents = {
  284. ...item,
  285. columnName,
  286. activeIndex: '',
  287. children
  288. };
  289. } else {
  290. data.selectParents = {};
  291. }
  292. onSearch();
  293. };
  294. /** 默认选中第一个声部 */
  295. const formatFirstSubject = () => {
  296. const tempSubjects = catchStore.getSubjectInstrumentOnly;
  297. if (tempSubjects.length > 0) {
  298. const firstSubject = tempSubjects[0];
  299. if (firstSubject.instruments && firstSubject.instruments.length > 1) {
  300. state.tempSubjectId = firstSubject.instruments[0]?.value;
  301. forms.subjectId = firstSubject.instruments[0]?.value;
  302. } else {
  303. forms.subjectId = firstSubject.value;
  304. }
  305. }
  306. };
  307. // const mapList: any = new Map();
  308. const formatParentId = (id: any, list: any, ids = [] as any) => {
  309. for (const item of list) {
  310. if (item.children && item.children.length > 0) {
  311. const cIds: any = formatParentId(id, item.children, [
  312. ...ids,
  313. item.id
  314. ]);
  315. if (cIds.includes(id)) {
  316. return cIds;
  317. }
  318. }
  319. if (item.id === id) {
  320. return [...ids, id];
  321. }
  322. // mapList[item.id] = item.parentTagId;
  323. // mapList.push()
  324. }
  325. return ids;
  326. };
  327. const formatParentCurrentValue = (ids: any, list: any) => {
  328. for (const item of list) {
  329. if (ids.includes(item.id)) {
  330. if (item.children && item.children.length > 0) {
  331. let lastId: any;
  332. item.children.forEach((child: any) => {
  333. if (ids.includes(child.id)) {
  334. lastId = child.id;
  335. }
  336. });
  337. item.activeIndex = lastId;
  338. }
  339. }
  340. if (item.children && item.children.length > 0) {
  341. formatParentCurrentValue(ids, item.children);
  342. }
  343. }
  344. };
  345. const formatParentresetValue = (list: any) => {
  346. for (const item of list) {
  347. if (item.children && item.children.length > 0) {
  348. // item.children.forEach(() => {
  349. // item.activeIndex = '';
  350. // });
  351. }
  352. item.activeIndex = '';
  353. if (item.children && item.children.length > 0) {
  354. formatParentresetValue(item.children);
  355. }
  356. }
  357. };
  358. onMounted(async () => {
  359. // 场景
  360. const tempAudio = Object.keys(audioPlayType).map(key => {
  361. return {
  362. value: key,
  363. name: audioPlayType[key]
  364. };
  365. });
  366. audioPlayTypeList.value = [{ name: '全部', value: '' }, ...tempAudio];
  367. resourceTypeArray2.forEach((item: any) => {
  368. resourceType.value.push(item);
  369. });
  370. // // 获取教材分类列表
  371. // await catchStore.getMusicSheetCategory();
  372. await catchStore.getMusicTagTreeApi();
  373. _initTags();
  374. // 获取声部
  375. await catchStore.getSubjects();
  376. await catchStore.getMaterialTagsApi();
  377. forms.subjectId = null;
  378. // 这里开始
  379. // musicCateRef
  380. if (forms.type === 'MUSIC') {
  381. orginHeight.value = collapseWrapRef.value?.offsetHeight;
  382. hiddenHeight.value = collapseWrapRef.value?.offsetHeight / line.value;
  383. // 默认隐藏
  384. getLive();
  385. }
  386. formatFirstSubject();
  387. console.log(props.searchGroup, 'searchGroup - parent');
  388. if (props.searchGroup.type) {
  389. const tempSearchGroup = props.searchGroup;
  390. forms.type = tempSearchGroup.type || 'MUSIC';
  391. forms.audioPlayTypes = tempSearchGroup?.audioPlayTypes
  392. ? tempSearchGroup.audioPlayTypes.join('_')
  393. : '';
  394. if (tempSearchGroup.musicalInstrumentId) {
  395. forms.subjectId = tempSearchGroup.musicalInstrumentId;
  396. }
  397. if (tempSearchGroup.bookVersionId) {
  398. // forms.bookVersionId = tempSearchGroup.bookVersionId || '';
  399. data.childSelectId = tempSearchGroup.bookVersionId;
  400. let ids = formatParentId(data.childSelectId, data.tags);
  401. console.log(ids, 'ids');
  402. data.tagActiveId = ids[0];
  403. const index = ids.findIndex((id: any) => id === data.childSelectId);
  404. // console.log(index, 'id');
  405. ids = ids.slice(0, index + 1);
  406. formatParentCurrentValue(ids, data.tags);
  407. data.tags.forEach((item: any) => {
  408. if (item.id === data.tagActiveId) {
  409. let children: any;
  410. let columnName = '';
  411. if (item.children) {
  412. children = [
  413. {
  414. columnName: item.children[0].columnName,
  415. name: '全部',
  416. id: ''
  417. },
  418. ...item.children
  419. ];
  420. columnName = item.children[0].columnName;
  421. let id: any;
  422. item.children.forEach((item: any) => {
  423. if (ids.includes(item.id)) {
  424. id = item.id;
  425. }
  426. });
  427. data.selectParents = {
  428. ...item,
  429. columnName,
  430. activeIndex: id || '',
  431. children
  432. };
  433. } else {
  434. data.selectParents = {};
  435. }
  436. }
  437. });
  438. }
  439. }
  440. onSearch('timer');
  441. });
  442. return () => (
  443. <div class={styles.searchGroup}>
  444. <div class={styles.searchCatatory}>
  445. <NSpace size="small" class={styles.btnType}>
  446. {resourceType.value.map((item: any) => (
  447. <NButton
  448. type={forms.type === item.value ? 'primary' : 'default'}
  449. secondary={forms.type === item.value ? false : true}
  450. round
  451. size="small"
  452. focusable={false}
  453. onClick={() => {
  454. forms.type = item.value;
  455. forms.subjectId = null;
  456. data.tagActiveId = '';
  457. data.childSelectId = null;
  458. data.selectParents = {};
  459. forms.audioPlayTypes =
  460. props.type === 'myResources' ? 'PLAY' : '';
  461. forms.materialTagId = null
  462. formatFirstSubject();
  463. onSearch();
  464. try {
  465. nextTick(() => {
  466. if (forms.type === 'MUSIC') {
  467. orginHeight.value = collapseWrapRef.value?.offsetHeight;
  468. hiddenHeight.value =
  469. collapseWrapRef.value?.offsetHeight / line.value;
  470. // 默认隐藏
  471. getLive();
  472. } else {
  473. divDomList.value = [];
  474. }
  475. });
  476. } catch {
  477. //
  478. }
  479. }}>
  480. {item.label}
  481. </NButton>
  482. ))}
  483. </NSpace>
  484. <TheSearch
  485. class={styles.inputSearch}
  486. round
  487. onSearch={(val: string) => {
  488. forms.name = val;
  489. throttleFn();
  490. }}
  491. />
  492. </div>
  493. <NForm
  494. labelAlign="left"
  495. labelPlacement="left"
  496. class={styles.searchForm}>
  497. {forms.type === 'MUSIC' && props.type === 'shareResources' && (
  498. <>
  499. <NFormItem label={data.tags[0]?.columnName + ':'}>
  500. <NSpace class={styles.spaceSection}>
  501. {data.tags.map((subject: any) => (
  502. <span
  503. class={[
  504. styles.textBtn,
  505. data.tagActiveId === subject.id && styles.textBtnActive
  506. ]}
  507. onClick={() => {
  508. changeTag(subject);
  509. }}>
  510. {subject.name}
  511. </span>
  512. ))}
  513. </NSpace>
  514. </NFormItem>
  515. <ChildNodeSearch
  516. activeRow={data.selectParents}
  517. onSelectChildTag={(val: any) => {
  518. data.childSelectId = val;
  519. onSearch();
  520. }}
  521. />
  522. </>
  523. )}
  524. {props.type !== 'myResources' && forms.type === 'MUSIC' && (
  525. <NFormItem label="场景:">
  526. <NSpace class={styles.spaceSection}>
  527. {audioPlayTypeList.value.map((subject: any) => (
  528. <span
  529. class={[
  530. styles.textBtn,
  531. forms.audioPlayTypes === subject.value &&
  532. styles.textBtnActive
  533. ]}
  534. onClick={() => {
  535. forms.audioPlayTypes = subject.value;
  536. // if (subject.value === 'SING') {
  537. // state.tempSubjectId = null;
  538. // forms.subjectId = null;
  539. // } else {
  540. // formatFirstSubject();
  541. // }
  542. onSearch();
  543. }}>
  544. {subject.name}
  545. </span>
  546. ))}
  547. </NSpace>
  548. </NFormItem>
  549. )}
  550. {forms.audioPlayTypes !== 'SING' && (
  551. <NFormItem label="乐器:">
  552. <NSpace class={styles.spaceSection2}>
  553. {catchStore.getSubjectInstrumentOnly.map((subject: any) =>
  554. subject.instruments && subject.instruments.length > 1 ? (
  555. <NPopselect
  556. options={subject.instruments}
  557. trigger="hover"
  558. scrollable
  559. v-model:value={state.tempSubjectId}
  560. onUpdate:value={() => {
  561. forms.subjectId = state.tempSubjectId;
  562. onSearch();
  563. }}
  564. key={subject.value}
  565. class={[styles.popSelect]}>
  566. <span
  567. class={[
  568. styles.textBtn,
  569. selectChildObj(subject.instruments).selected &&
  570. styles.textBtnActive
  571. ]}>
  572. {selectChildObj(subject.instruments).name ||
  573. subject.name}
  574. <i class={styles.iconArrow}></i>
  575. </span>
  576. </NPopselect>
  577. ) : (
  578. <span
  579. class={[
  580. styles.textBtn,
  581. forms.subjectId === subject.value &&
  582. styles.textBtnActive
  583. ]}
  584. onClick={() => {
  585. forms.subjectId = subject.value;
  586. state.tempSubjectId = null;
  587. onSearch();
  588. }}>
  589. {subject.name}
  590. </span>
  591. )
  592. )}
  593. </NSpace>
  594. </NFormItem>
  595. )}
  596. {forms.type !== 'MUSIC' && (
  597. <NFormItem label="标签:">
  598. <NSpace class={styles.spaceSection}>
  599. {catchStore.getAllMaterialTags.map((subject: any) => (
  600. <span
  601. class={[
  602. styles.textBtn,
  603. forms.materialTagId === subject.value &&
  604. styles.textBtnActive
  605. ]}
  606. onClick={() => {
  607. forms.materialTagId = subject.value;
  608. onSearch();
  609. }}>
  610. {subject.label}
  611. </span>
  612. ))}
  613. </NSpace>
  614. </NFormItem>
  615. )}
  616. </NForm>
  617. </div>
  618. );
  619. }
  620. });