search-group.tsx 15 KB

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