index.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  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 { resourceTypeArray } 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. selectItem.value = {};
  48. }
  49. );
  50. return () => (
  51. <>
  52. {activeRow.value?.id && (
  53. <>
  54. <NFormItem label={activeRow.value.columnName + ':'}>
  55. <NSpace class={styles.spaceSection}>
  56. {activeRow.value?.children.map((subject: any) => (
  57. <span
  58. class={[
  59. styles.textBtn,
  60. (activeRow.value.activeIndex || '') == subject.id &&
  61. styles.textBtnActive
  62. ]}
  63. onClick={() => {
  64. activeRow.value.activeIndex = subject.id;
  65. let children: any;
  66. let columnName = '';
  67. if (subject.children) {
  68. children = [
  69. {
  70. columnName: subject.children[0].columnName,
  71. name: '全部',
  72. id: ''
  73. },
  74. ...subject.children
  75. ];
  76. columnName = subject.children[0].columnName;
  77. selectItem.value = {
  78. ...subject,
  79. columnName,
  80. activeIndex: '',
  81. children
  82. };
  83. } else {
  84. selectItem.value = {};
  85. }
  86. emit('selectChildTag', activeRow.value.activeIndex);
  87. }}>
  88. {subject.name}
  89. </span>
  90. ))}
  91. </NSpace>
  92. </NFormItem>
  93. <ChildNodeSearch
  94. activeRow={selectItem.value}
  95. onSelectChildTag={(item: any) => {
  96. emit('selectChildTag', item || activeRow.value.activeIndex);
  97. }}
  98. />
  99. </>
  100. )}
  101. </>
  102. );
  103. }
  104. });
  105. export default defineComponent({
  106. name: 'resource-search-group',
  107. props: {
  108. type: {
  109. type: String as PropType<
  110. 'relateResources' | 'shareResources' | 'myResources' | 'myCollect'
  111. >,
  112. default: 'shareResources'
  113. },
  114. subjectId: {
  115. type: String,
  116. default: null
  117. }
  118. },
  119. emits: ['search'],
  120. setup(props, { emit }) {
  121. const subjectId = toRef(props.subjectId);
  122. const catchStore = useCatchStore();
  123. const forms = reactive({
  124. type: 'MUSIC', //
  125. name: '',
  126. subjectId: subjectId.value as any,
  127. // grade: null as any,
  128. audioPlayTypes: props.type == 'myResources' ? 'PLAY' : '',
  129. bookVersionId: null as any
  130. // musicSheetCategoriesId: null as any
  131. });
  132. const state = reactive({
  133. tempSubjectId: null,
  134. gradeList: [] as any[],
  135. musicCategory: [] as any
  136. });
  137. const data = reactive({
  138. selectParents: {}, // 选中的数据
  139. tags: [] as any[],
  140. tagActiveId: '' as any,
  141. tagActive: {} as any,
  142. childSelectId: null as any
  143. });
  144. const resourceType = ref([] as any);
  145. const audioPlayTypeList = ref([] as any);
  146. const onSearch = (type?: string) => {
  147. emit(
  148. 'search',
  149. {
  150. ...forms,
  151. subjectId: forms.audioPlayTypes !== 'SING' ? forms.subjectId : null,
  152. audioPlayTypes: forms.audioPlayTypes
  153. ? forms.audioPlayTypes === 'PLAY_SING'
  154. ? ['PLAY', 'SING']
  155. : [forms.audioPlayTypes]
  156. : [],
  157. bookVersionId: data.childSelectId || data.tagActiveId
  158. },
  159. type
  160. );
  161. };
  162. const throttleFn = useThrottleFn(() => onSearch(), 500);
  163. const collapseWrapRef = ref();
  164. const divDomList = ref([] as any);
  165. const orginHeight = ref(0);
  166. const hiddenHeight = ref(0);
  167. const line = ref(0);
  168. const isCollapse = ref(false);
  169. const loadingCollapse = ref(false); // 是否加载完成
  170. const musicCateRef = (el: any) => {
  171. if (el?.selfElRef) {
  172. divDomList.value.push(el.selfElRef.parentNode);
  173. }
  174. };
  175. const setCollapse = (flag: boolean) => {
  176. isCollapse.value = flag;
  177. getLive();
  178. };
  179. const getLive = () => {
  180. try {
  181. divDomList.value = [...new Set(divDomList.value)];
  182. let offsetLeft = -1;
  183. divDomList.value.forEach((item: any, index: number) => {
  184. if (index === 0) {
  185. line.value = 1;
  186. offsetLeft = item.offsetLeft;
  187. } else if (item.offsetLeft === offsetLeft && index != 0) {
  188. // 如果某个标签的offsetLeft和第一个标签的offsetLeft相等 说明增加了一行
  189. line.value++;
  190. }
  191. if (!isCollapse.value) {
  192. if (line.value > 1) {
  193. //从第3行开始 隐藏标签
  194. item.style.display = 'none';
  195. // 显示展开按钮 class名chu是在前面动态添加的
  196. } else {
  197. item.style.display = 'block';
  198. }
  199. } else {
  200. item.style.display = 'block';
  201. }
  202. });
  203. loadingCollapse.value = true;
  204. } catch {
  205. //
  206. }
  207. };
  208. const selectChildObj = (item: any) => {
  209. const obj: any = {};
  210. item?.forEach((child: any) => {
  211. if (child.id === forms.subjectId) {
  212. obj.selected = true;
  213. obj.name = child.name;
  214. }
  215. });
  216. return obj;
  217. };
  218. const _initTags = () => {
  219. const tags = catchStore.getMusicTagTree;
  220. data.tags = [
  221. {
  222. columnName: tags[0].columnName,
  223. name: '全部',
  224. id: ''
  225. },
  226. ...tags
  227. ];
  228. data.tagActiveId = data.tags[0].id;
  229. };
  230. const changeTag = (item: any) => {
  231. data.tagActiveId = item.id;
  232. data.childSelectId = null;
  233. let children: any;
  234. let columnName = '';
  235. if (item.children) {
  236. children = [
  237. {
  238. columnName: item.children[0].columnName,
  239. name: '全部',
  240. id: ''
  241. },
  242. ...item.children
  243. ];
  244. columnName = item.children[0].columnName;
  245. data.selectParents = {
  246. ...item,
  247. columnName,
  248. activeIndex: '',
  249. children
  250. };
  251. } else {
  252. data.selectParents = {};
  253. }
  254. onSearch();
  255. };
  256. /** 默认选中第一个声部 */
  257. const formatFirstSubject = () => {
  258. const tempSubjects = catchStore.getSubjectInstrumentOnly;
  259. if (tempSubjects.length > 0) {
  260. const firstSubject = tempSubjects[0];
  261. if (firstSubject.instruments && firstSubject.instruments.length > 1) {
  262. state.tempSubjectId = firstSubject.instruments[0]?.value;
  263. forms.subjectId = firstSubject.instruments[0]?.value;
  264. } else {
  265. forms.subjectId = firstSubject.value;
  266. }
  267. }
  268. };
  269. onMounted(async () => {
  270. // 场景
  271. const tempAudio = Object.keys(audioPlayType).map(key => {
  272. return {
  273. value: key,
  274. name: audioPlayType[key]
  275. };
  276. });
  277. audioPlayTypeList.value = [{ name: '全部', value: '' }, ...tempAudio];
  278. resourceTypeArray.forEach((item: any) => {
  279. resourceType.value.push(item);
  280. });
  281. // // 获取教材分类列表
  282. // await catchStore.getMusicSheetCategory();
  283. await catchStore.getMusicTagTreeApi();
  284. _initTags();
  285. // 获取声部
  286. await catchStore.getSubjects();
  287. forms.subjectId = null;
  288. // 这里开始
  289. // musicCateRef
  290. if (forms.type === 'MUSIC') {
  291. orginHeight.value = collapseWrapRef.value?.offsetHeight;
  292. hiddenHeight.value = collapseWrapRef.value?.offsetHeight / line.value;
  293. // 默认隐藏
  294. getLive();
  295. }
  296. formatFirstSubject();
  297. onSearch('timer');
  298. });
  299. return () => (
  300. <div class={styles.searchGroup}>
  301. <div class={styles.searchCatatory}>
  302. <NSpace size="small" class={styles.btnType}>
  303. {resourceType.value.map((item: any) => (
  304. <NButton
  305. type={forms.type === item.value ? 'primary' : 'default'}
  306. secondary={forms.type === item.value ? false : true}
  307. round
  308. size="small"
  309. focusable={false}
  310. onClick={() => {
  311. forms.type = item.value;
  312. forms.subjectId = null;
  313. data.tagActiveId = '';
  314. data.childSelectId = null;
  315. data.selectParents = {};
  316. forms.audioPlayTypes =
  317. props.type === 'myResources' ? 'PLAY' : '';
  318. formatFirstSubject();
  319. onSearch();
  320. try {
  321. nextTick(() => {
  322. if (forms.type === 'MUSIC') {
  323. orginHeight.value = collapseWrapRef.value?.offsetHeight;
  324. hiddenHeight.value =
  325. collapseWrapRef.value?.offsetHeight / line.value;
  326. // 默认隐藏
  327. getLive();
  328. } else {
  329. divDomList.value = [];
  330. }
  331. });
  332. } catch {
  333. //
  334. }
  335. }}>
  336. {item.label}
  337. </NButton>
  338. ))}
  339. </NSpace>
  340. <TheSearch
  341. class={styles.inputSearch}
  342. round
  343. onSearch={(val: string) => {
  344. forms.name = val;
  345. throttleFn();
  346. }}
  347. />
  348. </div>
  349. <NForm
  350. labelAlign="left"
  351. labelPlacement="left"
  352. class={styles.searchForm}>
  353. {forms.type === 'MUSIC' && props.type === 'shareResources' && (
  354. <>
  355. <NFormItem label={data.tags[0]?.columnName + ':'}>
  356. <NSpace class={styles.spaceSection}>
  357. {data.tags.map((subject: any) => (
  358. <span
  359. class={[
  360. styles.textBtn,
  361. data.tagActiveId === subject.id && styles.textBtnActive
  362. ]}
  363. onClick={() => {
  364. changeTag(subject);
  365. }}>
  366. {subject.name}
  367. </span>
  368. ))}
  369. </NSpace>
  370. </NFormItem>
  371. <ChildNodeSearch
  372. activeRow={data.selectParents}
  373. onSelectChildTag={(val: any) => {
  374. data.childSelectId = val;
  375. onSearch();
  376. }}
  377. />
  378. </>
  379. )}
  380. {props.type !== 'myResources' && forms.type === 'MUSIC' && (
  381. <NFormItem label="场景:">
  382. <NSpace class={styles.spaceSection}>
  383. {audioPlayTypeList.value.map((subject: any) => (
  384. <span
  385. class={[
  386. styles.textBtn,
  387. forms.audioPlayTypes === subject.value &&
  388. styles.textBtnActive
  389. ]}
  390. onClick={() => {
  391. forms.audioPlayTypes = subject.value;
  392. // if (subject.value === 'SING') {
  393. // state.tempSubjectId = null;
  394. // forms.subjectId = null;
  395. // } else {
  396. // formatFirstSubject();
  397. // }
  398. onSearch();
  399. }}>
  400. {subject.name}
  401. </span>
  402. ))}
  403. </NSpace>
  404. </NFormItem>
  405. )}
  406. {forms.audioPlayTypes !== 'SING' && (
  407. <NFormItem label="乐器:">
  408. <NSpace class={styles.spaceSection2}>
  409. {catchStore.getSubjectInstrumentOnly.map((subject: any) =>
  410. subject.instruments && subject.instruments.length > 1 ? (
  411. <NPopselect
  412. options={subject.instruments}
  413. trigger="hover"
  414. scrollable
  415. v-model:value={state.tempSubjectId}
  416. onUpdate:value={() => {
  417. forms.subjectId = state.tempSubjectId;
  418. onSearch();
  419. }}
  420. key={subject.value}
  421. class={[styles.popSelect]}>
  422. <span
  423. class={[
  424. styles.textBtn,
  425. selectChildObj(subject.instruments).selected &&
  426. styles.textBtnActive
  427. ]}>
  428. {selectChildObj(subject.instruments).name ||
  429. subject.name}
  430. <i class={styles.iconArrow}></i>
  431. </span>
  432. </NPopselect>
  433. ) : (
  434. <span
  435. class={[
  436. styles.textBtn,
  437. forms.subjectId === subject.value &&
  438. styles.textBtnActive
  439. ]}
  440. onClick={() => {
  441. forms.subjectId = subject.value;
  442. state.tempSubjectId = null;
  443. onSearch();
  444. }}>
  445. {subject.name}
  446. </span>
  447. )
  448. )}
  449. </NSpace>
  450. </NFormItem>
  451. )}
  452. </NForm>
  453. </div>
  454. );
  455. }
  456. });