index.tsx 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. import { defineComponent, onMounted, reactive } from 'vue';
  2. import styles from './index.module.less';
  3. import TheSearch from '@/components/TheSearch';
  4. import { NButton, NImage, NSpace, NSpin } from 'naive-ui';
  5. import { useRouter } from 'vue-router';
  6. import { api_musicSheetCategoriesPage, api_musicTagTree } from './api';
  7. import TheEmpty from '/src/components/TheEmpty';
  8. import { useCatchStore } from '/src/store/modules/catchData';
  9. export default defineComponent({
  10. name: 'XiaokuAi',
  11. setup() {
  12. const catchStore = useCatchStore();
  13. const router = useRouter();
  14. const forms = reactive({
  15. musicTagIds: [] as any[],
  16. enable: true,
  17. subjectId: null,
  18. keyword: '',
  19. page: 1,
  20. rows: 9999
  21. });
  22. const data = reactive({
  23. tags: [] as any[],
  24. tagChildren: [] as any[],
  25. tagActiveId: '',
  26. tagActive: {} as any,
  27. list: [] as any,
  28. loading: false
  29. });
  30. const getTags = async () => {
  31. const res = await api_musicTagTree();
  32. if (Array.isArray(res?.data) && res.data.length) {
  33. data.tags = res.data;
  34. data.tagActiveId = res.data[0].id;
  35. const list: any[] = [];
  36. renderTag(res.data[0].children, list);
  37. data.tagChildren = list;
  38. }
  39. };
  40. const getList = async () => {
  41. data.loading = true;
  42. try {
  43. const res = await api_musicSheetCategoriesPage({
  44. ...forms,
  45. musicTagIds: [data.tagActiveId, ...forms.musicTagIds].filter(Boolean)
  46. });
  47. if (Array.isArray(res?.data?.rows)) {
  48. data.list = res.data.rows;
  49. }
  50. } catch {
  51. //
  52. }
  53. data.loading = false;
  54. };
  55. // 递归渲染标签
  56. const renderTag = (_data: any[], _list: any[]): any => {
  57. if (!_data?.length) return;
  58. const item = {
  59. columnName: _data[0].columnName,
  60. list: [] as any[]
  61. };
  62. const childrens = [];
  63. for (let i = 0; i < _data.length; i++) {
  64. item.list.push({
  65. name: _data[i].name,
  66. id: _data[i].id,
  67. activeIndex: -1
  68. });
  69. if (_data[i].children) {
  70. childrens.push(..._data[i].children);
  71. }
  72. }
  73. _list.push(item);
  74. if (childrens.length) {
  75. renderTag(childrens, _list);
  76. }
  77. };
  78. onMounted(async () => {
  79. data.loading = true;
  80. try {
  81. await getTags();
  82. await getList();
  83. // 获取教材分类列表
  84. await catchStore.getSubjects();
  85. } catch {
  86. //
  87. }
  88. data.loading = false;
  89. });
  90. /** 改变顶级分类 */
  91. const changeTag = (item: any, index: number) => {
  92. data.tagActiveId = item.id;
  93. forms.musicTagIds = [];
  94. const list: any[] = [];
  95. renderTag(data.tags[index].children, list);
  96. data.tagChildren = list;
  97. getList();
  98. };
  99. /** 选中子选项 */
  100. const selectChildTag = (columnIndex: number, index: number) => {
  101. const oldActiveItem =
  102. data.tagChildren[columnIndex].list[
  103. data.tagChildren[columnIndex].activeIndex
  104. ];
  105. const activeItem = data.tagChildren[columnIndex].list[index];
  106. if (oldActiveItem && oldActiveItem.id !== activeItem.id) {
  107. forms.musicTagIds = forms.musicTagIds.filter(
  108. item => item !== oldActiveItem.id
  109. );
  110. }
  111. if (forms.musicTagIds.includes(activeItem.id)) {
  112. forms.musicTagIds = forms.musicTagIds.filter(
  113. item => item !== activeItem.id
  114. );
  115. data.tagChildren[columnIndex].activeIndex = -1;
  116. } else {
  117. forms.musicTagIds.push(activeItem.id);
  118. data.tagChildren[columnIndex].activeIndex = index;
  119. }
  120. getList();
  121. };
  122. return () => (
  123. <div class={styles.container}>
  124. <div class={styles.tools}>
  125. <div class={styles.tagWrap}>
  126. <div class={styles.tags}>
  127. <NSpace size={[20, 12]}>
  128. <span class={styles.firstButton}>
  129. {data.tags?.[0]?.columnName}
  130. </span>
  131. {data.tags.map((item: any, index: number) => {
  132. return (
  133. <>
  134. <NButton
  135. round
  136. secondary={data.tagActiveId === item.id ? false : true}
  137. type={
  138. data.tagActiveId === item.id ? 'primary' : 'default'
  139. }
  140. onClick={() => changeTag(item, index)}>
  141. {item.name}
  142. </NButton>
  143. </>
  144. );
  145. })}
  146. </NSpace>
  147. </div>
  148. {data.tagChildren.map((column: any, columnIndex: number) => {
  149. return (
  150. <div class={styles.tags}>
  151. <NSpace size={[20, 12]}>
  152. <span class={styles.firstButton}>{column.columnName}</span>
  153. {column.list.map((item: any, index: number) => {
  154. return (
  155. <>
  156. <NButton
  157. round
  158. secondary={
  159. column.activeIndex === index ? false : true
  160. }
  161. type={
  162. column.activeIndex === index
  163. ? 'primary'
  164. : 'default'
  165. }
  166. onClick={() => selectChildTag(columnIndex, index)}>
  167. {item.name}
  168. </NButton>
  169. </>
  170. );
  171. })}
  172. </NSpace>
  173. </div>
  174. );
  175. })}
  176. <div class={styles.tags}>
  177. <NSpace size={[20, 12]}>
  178. <span class={styles.firstButton}>声部</span>
  179. {catchStore.getSubjectAllList.map((item: any) => {
  180. return (
  181. <>
  182. <NButton
  183. round
  184. secondary={item.id === forms.subjectId ? false : true}
  185. type={
  186. item.id === forms.subjectId ? 'primary' : 'default'
  187. }
  188. onClick={() => {
  189. forms.subjectId = item.id;
  190. getList();
  191. }}>
  192. {item.name}
  193. </NButton>
  194. </>
  195. );
  196. })}
  197. </NSpace>
  198. </div>
  199. </div>
  200. <TheSearch
  201. round
  202. onSearch={val => {
  203. forms.keyword = val;
  204. getList();
  205. }}
  206. />
  207. </div>
  208. <NSpin show={data.loading}>
  209. <div
  210. class={[styles.content, data.loading ? styles.loadingContent : '']}>
  211. {data.list.length > 0 ? (
  212. <NSpace size={[50, 40]}>
  213. {data.list.map((item: any, index: number) => {
  214. return (
  215. <div
  216. class={styles.item}
  217. key={`item-${index}`}
  218. onClick={() =>
  219. router.push({
  220. path: '/xiaoku-music',
  221. query: {
  222. id: item.id,
  223. name: item.name
  224. }
  225. })
  226. }>
  227. <div class={styles.cover}>
  228. <div class={styles.itemImg}>
  229. <div class={styles.itemBg}></div>
  230. <NImage
  231. objectFit="cover"
  232. src={item.coverImg}
  233. lazy
  234. previewDisabled={true}
  235. onLoad={e => {
  236. (e.target as any).dataset.loaded = 'true';
  237. }}
  238. />
  239. </div>
  240. </div>
  241. <div class={styles.itemName}>{item.name}</div>
  242. </div>
  243. );
  244. })}
  245. </NSpace>
  246. ) : (
  247. ''
  248. )}
  249. {!data.loading && data.list.length <= 0 && <TheEmpty></TheEmpty>}
  250. </div>
  251. </NSpin>
  252. </div>
  253. );
  254. }
  255. });