index.tsx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
  2. import { Sticky, List, Popup, Icon, Switch, Tabs, Tab } from 'vant'
  3. import Search from '@/components/col-search'
  4. import request from '@/helpers/request'
  5. // import Item from './item'
  6. import SelectTag from '../search/select-tag'
  7. import { useRoute, useRouter } from 'vue-router'
  8. import ColResult from '@/components/col-result'
  9. import styles from './index.module.less'
  10. import { getRandomKey } from '../music'
  11. import { state as baseState } from '@/state'
  12. import SelectSubject from '../search/select-subject'
  13. import { SubjectEnum, useSubjectId } from '@/helpers/hooks'
  14. import Song from '../component/song'
  15. import ColHeader from '@/components/col-header'
  16. import { useRect } from '@vant/use'
  17. import { useAsyncState } from '@vueuse/core'
  18. import bgImg from './icons/bgImg.png'
  19. import iconSearch from './icons/icon_search.png'
  20. const noop = () => {
  21. //
  22. }
  23. export default defineComponent({
  24. name: 'MusicList',
  25. props: {
  26. hideSearch: {
  27. type: Boolean,
  28. default: false
  29. },
  30. defauleParams: {
  31. type: Object,
  32. default: () => ({})
  33. },
  34. onItemClick: {
  35. type: Function,
  36. default: noop
  37. },
  38. teacherId: {
  39. type: String || Number,
  40. default: ''
  41. },
  42. myself: {
  43. type: Boolean,
  44. default: false
  45. }
  46. },
  47. setup(
  48. { hideSearch, defauleParams, onItemClick, teacherId, myself },
  49. { expose }
  50. ) {
  51. const { isLoading, state } = useAsyncState(
  52. request(baseState.platformApi + '/MusicTag/tree', {
  53. params: {
  54. type: 'MUSIC'
  55. }
  56. }),
  57. null
  58. )
  59. const subjects: any = useSubjectId(SubjectEnum.SEARCH)
  60. // 判断是否已有数据
  61. if (!subjects.id) {
  62. const users = baseState.user.data
  63. const subjectId = users.subjectId
  64. ? Number(users.subjectId.split(',')[0])
  65. : ''
  66. const subjectName = users.subjectName
  67. ? users.subjectName.split(',')[0]
  68. : ''
  69. if (subjectId) {
  70. useSubjectId(
  71. SubjectEnum.SEARCH,
  72. JSON.stringify({
  73. id: subjectId,
  74. name: subjectName
  75. }),
  76. 'set'
  77. )
  78. }
  79. }
  80. localStorage.setItem('behaviorId', getRandomKey())
  81. const route = useRoute()
  82. // const router = useRouter()
  83. const tempParams: any = {}
  84. if (baseState.version) {
  85. tempParams.version = baseState.version || '' // 处理ios审核版本
  86. tempParams.platform =
  87. baseState.platformType === 'STUDENT' ? 'ios-student' : 'ios-teacher'
  88. }
  89. // 判断是否在搜索页面用过
  90. if (!hideSearch) {
  91. const getSubject: any = useSubjectId(SubjectEnum.SEARCH)
  92. tempParams.subjectIds = getSubject.id
  93. }
  94. //
  95. const params = reactive({
  96. search: (route.query.search as string) || '',
  97. // exquisiteFlag: 1,
  98. musicTagIds: route.query.tagids || '',
  99. page: 1,
  100. ...defauleParams,
  101. ...tempParams
  102. })
  103. const data = ref<any>(null)
  104. const loading = ref(false)
  105. const finished = ref(false)
  106. const isError = ref(false)
  107. const tagVisibility = ref(false)
  108. const exquisiteFlag = ref(false)
  109. const apiSuffix = ref(
  110. baseState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
  111. )
  112. const onSearch = (value: string) => {
  113. params.page = 1
  114. params.search = value
  115. data.value = null
  116. FetchList()
  117. }
  118. const FetchList = async () => {
  119. if (loading.value) {
  120. return
  121. }
  122. loading.value = true
  123. isError.value = false
  124. const tempParams = {
  125. ...params,
  126. auditStatus: 'PASS',
  127. idAndName: params.search,
  128. createBy: teacherId
  129. }
  130. if (exquisiteFlag.value) {
  131. tempParams.exquisiteFlag = 1
  132. }
  133. if (myself) {
  134. tempParams.myself = true
  135. } else {
  136. tempParams.myself = false
  137. }
  138. try {
  139. const res = await request.post(`${apiSuffix.value}/music/sheet/list`, {
  140. data: tempParams
  141. })
  142. if (data.value) {
  143. const result = (data.value?.rows || []).concat(res.data.rows || [])
  144. data.value.rows = result
  145. }
  146. data.value = data.value || res.data
  147. params.page = res.data.pageNo + 1
  148. finished.value = res.data.pageNo >= res.data.totalPage
  149. } catch (error) {
  150. isError.value = true
  151. }
  152. loading.value = false
  153. }
  154. const onComfirm = tags => {
  155. const tempTags: any = {}
  156. // 单独处理乐谱类型
  157. for (const tag in tags) {
  158. if (Number(tag) === -1) {
  159. exquisiteFlag.value = tags[tag][0] ? true : false
  160. } else {
  161. tempTags[tag] = tags[tag]
  162. }
  163. }
  164. const d = Object.values(tempTags).flat().filter(Boolean).join(',')
  165. params.musicTagIds = d
  166. params.page = 1
  167. data.value = null
  168. FetchList()
  169. tagVisibility.value = false
  170. }
  171. const onComfirmSubject = item => {
  172. params.page = 1
  173. params.subjectIds = item.id
  174. subject.id = item.id
  175. subject.name = item.name
  176. data.value = null
  177. useSubjectId(
  178. SubjectEnum.SEARCH,
  179. JSON.stringify({
  180. id: item.id,
  181. name: item.name
  182. }),
  183. 'set'
  184. )
  185. FetchList()
  186. subject.show = false
  187. }
  188. const getSubject: any = useSubjectId(SubjectEnum.SEARCH)
  189. const subject = reactive({
  190. show: false,
  191. name: getSubject.id ? getSubject.name : '全部声部',
  192. id: getSubject.id || ''
  193. })
  194. expose({
  195. onSearch,
  196. onComfirm,
  197. onComfirmSubject
  198. })
  199. return () => {
  200. const tagList = ((state.value && state.value.data) as any) || []
  201. return (
  202. <>
  203. {!hideSearch && (
  204. <>
  205. {' '}
  206. <Sticky class={styles.sticky}>
  207. <ColHeader
  208. background="transparent"
  209. isFixed={false}
  210. border={false}
  211. backIconColor="white"
  212. color="#fff"
  213. v-slots={{
  214. right: () => (
  215. <span
  216. class={styles.fleg}
  217. onClick={() => {
  218. exquisiteFlag.value != exquisiteFlag.value
  219. data.value = null
  220. params.page = 1
  221. FetchList()
  222. }}
  223. >
  224. <span>精品</span>
  225. <Switch v-model={exquisiteFlag.value} size="20px" />
  226. </span>
  227. )
  228. }}
  229. />
  230. <Search
  231. onSearch={onSearch}
  232. background="transparent"
  233. inputBackground="transparent"
  234. leftIcon={iconSearch}
  235. v-slots={{
  236. left: () => (
  237. <div
  238. class={styles.label}
  239. onClick={() => (subject.show = true)}
  240. >
  241. {subject.name}
  242. <Icon
  243. classPrefix="iconfont"
  244. name="down"
  245. size={12}
  246. color="#fff"
  247. />
  248. </div>
  249. )
  250. }}
  251. />
  252. <Tabs
  253. shrink
  254. class={styles.tagTabs}
  255. lineHeight={0}
  256. onClick-tab={(obj: any) => {
  257. params.musicTagIds = obj.name
  258. data.value = null
  259. params.page = 1
  260. FetchList()
  261. }}
  262. >
  263. <Tab title="全部" name=""></Tab>
  264. {tagList.map((tag: any) => (
  265. <Tab title={tag.name} name={tag.id}></Tab>
  266. ))}
  267. </Tabs>
  268. </Sticky>
  269. <img class={styles.bgImg} src={bgImg} />
  270. </>
  271. )}
  272. <div class={styles.alumnList}>
  273. <List
  274. loading={loading.value}
  275. finished={finished.value}
  276. finished-text={data.value && data.value.rows.length ? '' : ''}
  277. onLoad={FetchList}
  278. error={isError.value}
  279. >
  280. {data.value && data.value.rows.length ? (
  281. <Song
  282. list={data.value.rows}
  283. onDetail={(item: any) => {
  284. if (onItemClick === noop) {
  285. router.push({
  286. path: '/music-detail',
  287. query: {
  288. id: item.id
  289. }
  290. })
  291. } else {
  292. onItemClick?.(item)
  293. }
  294. }}
  295. />
  296. ) : (
  297. !loading.value && (
  298. <ColResult
  299. tips="暂无曲目"
  300. classImgSize="SMALL"
  301. btnStatus={false}
  302. />
  303. )
  304. )}
  305. </List>
  306. </div>
  307. <Popup
  308. show={tagVisibility.value}
  309. round
  310. closeable
  311. position="bottom"
  312. style={{ height: '60%' }}
  313. teleport="body"
  314. onUpdate:show={val => (tagVisibility.value = val)}
  315. >
  316. <SelectTag
  317. exquisiteFlag
  318. onConfirm={onComfirm}
  319. onCancel={() => {
  320. //
  321. }}
  322. defaultValue={route.query.tagids as string}
  323. />
  324. </Popup>
  325. {/* 声部弹框 */}
  326. <Popup
  327. show={subject.show}
  328. position="bottom"
  329. round
  330. closeable
  331. safe-area-inset-bottom
  332. onClose={() => (subject.show = false)}
  333. onClosed={() => (subject.show = false)}
  334. >
  335. <SelectSubject
  336. type="MUSIC"
  337. searchParams={subject}
  338. onComfirm={onComfirmSubject}
  339. />
  340. </Popup>
  341. </>
  342. )
  343. }
  344. }
  345. })