index.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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. export default defineComponent({
  9. name: 'XiaokuAi',
  10. setup() {
  11. const router = useRouter();
  12. const forms = reactive({
  13. musicTagIds: [] as any[],
  14. keyword: '',
  15. page: 1,
  16. rows: 9999
  17. });
  18. const data = reactive({
  19. tags: [] as any[],
  20. tagChildren: [] as any[],
  21. tagActiveId: '',
  22. tagActive: {} as any,
  23. list: [] as any,
  24. loading: false
  25. });
  26. const getTags = async () => {
  27. const res = await api_musicTagTree();
  28. if (Array.isArray(res?.data) && res.data.length) {
  29. data.tags = res.data;
  30. data.tagActiveId = res.data[0].id;
  31. const list: any[] = [];
  32. renderTag(res.data[0].children, list);
  33. data.tagChildren = list;
  34. }
  35. };
  36. const getList = async () => {
  37. data.loading = true;
  38. const res = await api_musicSheetCategoriesPage({
  39. ...forms,
  40. musicTagIds: [data.tagActiveId, ...forms.musicTagIds].filter(Boolean)
  41. });
  42. if (Array.isArray(res?.data?.rows)) {
  43. data.list = res.data.rows;
  44. }
  45. data.loading = false;
  46. };
  47. // 递归渲染标签
  48. const renderTag = (_data: any[], _list: any[]): any => {
  49. const item = {
  50. columnName: _data[0].columnName,
  51. list: [] as any[]
  52. };
  53. const childrens = [];
  54. for (let i = 0; i < _data.length; i++) {
  55. item.list.push({
  56. name: _data[i].name,
  57. id: _data[i].id,
  58. activeIndex: -1
  59. });
  60. if (_data[i].children) {
  61. childrens.push(..._data[i].children);
  62. }
  63. }
  64. _list.push(item);
  65. if (childrens.length) {
  66. renderTag(childrens, _list);
  67. }
  68. };
  69. onMounted(async () => {
  70. await getTags();
  71. getList();
  72. });
  73. /** 改变顶级分类 */
  74. const changeTag = (item: any, index: number) => {
  75. data.tagActiveId = item.id;
  76. forms.musicTagIds = [];
  77. const list: any[] = [];
  78. renderTag(data.tags[index].children, list);
  79. data.tagChildren = list;
  80. getList();
  81. };
  82. /** 选中子选项 */
  83. const selectChildTag = (columnIndex: number, index: number) => {
  84. const oldActiveItem =
  85. data.tagChildren[columnIndex].list[
  86. data.tagChildren[columnIndex].activeIndex
  87. ];
  88. const activeItem = data.tagChildren[columnIndex].list[index];
  89. if (oldActiveItem && oldActiveItem.id !== activeItem.id) {
  90. forms.musicTagIds = forms.musicTagIds.filter(
  91. item => item !== oldActiveItem.id
  92. );
  93. }
  94. if (forms.musicTagIds.includes(activeItem.id)) {
  95. forms.musicTagIds = forms.musicTagIds.filter(
  96. item => item !== activeItem.id
  97. );
  98. data.tagChildren[columnIndex].activeIndex = -1;
  99. } else {
  100. forms.musicTagIds.push(activeItem.id);
  101. data.tagChildren[columnIndex].activeIndex = index;
  102. }
  103. getList();
  104. };
  105. return () => (
  106. <div class={styles.container}>
  107. <div class={styles.tools}>
  108. <div class={styles.tagWrap}>
  109. <div class={styles.tags}>
  110. <NSpace size={[24, 12]}>
  111. <NButton quaternary disabled>
  112. 类型
  113. </NButton>
  114. {data.tags.map((item: any, index: number) => {
  115. return (
  116. <>
  117. <NButton
  118. round
  119. secondary={data.tagActiveId === item.id ? false : true}
  120. type={
  121. data.tagActiveId === item.id ? 'primary' : 'default'
  122. }
  123. onClick={() => changeTag(item, index)}>
  124. {item.name}
  125. </NButton>
  126. </>
  127. );
  128. })}
  129. </NSpace>
  130. </div>
  131. {data.tagChildren.map((column: any, columnIndex: number) => {
  132. return (
  133. <div class={styles.tags}>
  134. <NSpace size={[24, 12]}>
  135. <NButton quaternary disabled>
  136. {column.columnName}
  137. </NButton>
  138. {column.list.map((item: any, index: number) => {
  139. return (
  140. <>
  141. <NButton
  142. round
  143. secondary={
  144. column.activeIndex === index ? false : true
  145. }
  146. type={
  147. column.activeIndex === index
  148. ? 'primary'
  149. : 'default'
  150. }
  151. onClick={() => selectChildTag(columnIndex, index)}>
  152. {item.name}
  153. </NButton>
  154. </>
  155. );
  156. })}
  157. </NSpace>
  158. </div>
  159. );
  160. })}
  161. </div>
  162. <TheSearch
  163. round
  164. onSearch={val => {
  165. forms.keyword = val;
  166. getList();
  167. }}
  168. />
  169. </div>
  170. <NSpin show={data.loading}>
  171. <div class={styles.content}>
  172. {data.list.length > 0 ? <NSpace size={[50, 40]}>
  173. {data.list.map((item: any, index: number) => {
  174. return (
  175. <div
  176. class={styles.item}
  177. key={`item-${index}`}
  178. onClick={() =>
  179. router.push({
  180. path: '/xiaoku-music',
  181. query: {
  182. id: item.id,
  183. name: item.name
  184. }
  185. })
  186. }>
  187. <div class={styles.cover}>
  188. <div class={styles.itemImg}>
  189. <div class={styles.itemBg}></div>
  190. <NImage
  191. objectFit="cover"
  192. src={item.coverImg}
  193. lazy
  194. previewDisabled={true}
  195. onLoad={e => {
  196. (e.target as any).dataset.loaded = 'true';
  197. }}
  198. />
  199. </div>
  200. </div>
  201. <div class={styles.itemName}>{item.name}</div>
  202. </div>
  203. );
  204. })}
  205. </NSpace> : <TheEmpty></TheEmpty>}
  206. </div>
  207. </NSpin>
  208. </div>
  209. );
  210. }
  211. });