index.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue'
  2. import { List, DropdownMenu, DropdownItem, Tag, Sticky, Button } from 'vant'
  3. import Search from '@/components/col-search'
  4. import request from '@/helpers/request'
  5. import { useRoute, useRouter } from 'vue-router'
  6. import ColResult from '@/components/col-result'
  7. import styles from './index.module.less'
  8. import { getRandomKey } from '../music'
  9. import { openDefaultWebView, state as baseState } from '@/state'
  10. import { SubjectEnum, useSubjectId } from '@/helpers/hooks'
  11. import Song from '../component/song'
  12. import ColHeader from '@/components/col-header'
  13. import bgImg from '../../images/bg-image.png'
  14. import TheSticky from '@/components/the-sticky'
  15. const noop = () => {
  16. //
  17. }
  18. export default defineComponent({
  19. name: 'MusicList',
  20. props: {
  21. teacherId: {
  22. type: String || Number,
  23. default: ''
  24. },
  25. myself: {
  26. type: Boolean,
  27. default: false
  28. }
  29. },
  30. setup({ onItemClick }, { expose }) {
  31. localStorage.setItem('behaviorId', getRandomKey())
  32. const route = useRoute()
  33. const router = useRouter()
  34. //
  35. const subjectType = route.query.subjectType || ''
  36. let title = ''
  37. if (subjectType === 'SUBJECT') {
  38. title = '声部练习'
  39. } else if (subjectType === 'MUSIC') {
  40. title = '独奏曲目'
  41. } else if (subjectType === 'ENSEMBLE') {
  42. title = '合奏练习'
  43. }
  44. const params = reactive({
  45. keyword: (route.query.search as string) || '',
  46. subjectType: subjectType,
  47. page: 1,
  48. subjectId: null,
  49. level: '',
  50. type: '',
  51. title: title
  52. })
  53. const data = ref<any>(null)
  54. const loading = ref(false)
  55. const finished = ref(false)
  56. const isError = ref(false)
  57. const searchObj = ref<any>({})
  58. const searchRef = ref()
  59. const apiSuffix = ref(
  60. baseState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
  61. )
  62. const onSearch = (value: string) => {
  63. params.page = 1
  64. params.keyword = value
  65. data.value = null
  66. FetchList()
  67. }
  68. const FetchList = async () => {
  69. loading.value = true
  70. isError.value = false
  71. const tempParams = {
  72. ...params
  73. }
  74. try {
  75. const res = await request.post(
  76. `${apiSuffix.value}/tenantAlbumMusic/page`,
  77. {
  78. data: tempParams
  79. }
  80. )
  81. if (data.value) {
  82. const result = (data.value?.rows || []).concat(res.data.rows || [])
  83. data.value.rows = result
  84. }
  85. data.value = data.value || res.data
  86. params.page = res.data.pageNo + 1
  87. finished.value = res.data.pageNo >= res.data.totalPage
  88. } catch (error) {
  89. isError.value = true
  90. }
  91. loading.value = false
  92. }
  93. const getSelectCondition = async () => {
  94. const { data } = await request.post(
  95. `${apiSuffix.value}/tenantAlbumMusic/selectCondition`,
  96. {
  97. data: {
  98. subjectType: params.subjectType
  99. }
  100. }
  101. )
  102. searchObj.value = data || {}
  103. }
  104. onMounted(async () => {
  105. // SUBJECT: '声部练习',
  106. // MUSIC: '独奏曲目',
  107. // ENSEMBLE: '合奏练习'
  108. loading.value = true
  109. await getSelectCondition()
  110. await FetchList()
  111. })
  112. return () => {
  113. return (
  114. <>
  115. <div class={styles.sticky}>
  116. <TheSticky>
  117. <ColHeader
  118. background="transparent"
  119. isFixed={false}
  120. border={false}
  121. title={title}
  122. color="#131415"
  123. />
  124. <Search
  125. onSearch={onSearch}
  126. type="tenant"
  127. background="transparent"
  128. inputBackground="transparent"
  129. // leftIcon={iconSearch}
  130. v-slots={{
  131. left: () => (
  132. <DropdownMenu>
  133. <DropdownItem
  134. titleClass={
  135. params.subjectId || params.type || params.level
  136. ? styles.titleActive
  137. : ''
  138. }
  139. title="筛选"
  140. ref={searchRef}
  141. >
  142. <div
  143. class={styles.searchResult}
  144. style={{ maxHeight: '45vh', overflowY: 'auto' }}
  145. >
  146. {searchObj.value.subjects &&
  147. searchObj.value.subjects.length > 0 && (
  148. <>
  149. <div class={styles.searchTitle}>声部</div>
  150. <div
  151. class={[
  152. styles['radio-group'],
  153. styles.radio,
  154. styles['organ-radio']
  155. ]}
  156. >
  157. {searchObj.value.subjects.map(
  158. (subject: any) => {
  159. const isActive =
  160. subject.id === params.subjectId
  161. const type = isActive
  162. ? 'primary'
  163. : 'default'
  164. return (
  165. <Tag
  166. size="large"
  167. plain={isActive}
  168. type={type}
  169. round
  170. onClick={() => {
  171. params.subjectId = subject.id
  172. }}
  173. >
  174. {subject.name}
  175. </Tag>
  176. )
  177. }
  178. )}
  179. </div>
  180. </>
  181. )}
  182. {searchObj.value.levels &&
  183. searchObj.value.levels.length > 0 && (
  184. <>
  185. <div class={styles.searchTitle}>级别</div>
  186. <div
  187. class={[
  188. styles['radio-group'],
  189. styles.radio,
  190. styles['organ-radio']
  191. ]}
  192. >
  193. {searchObj.value.levels.map(
  194. (subject: any) => {
  195. const isActive = subject === params.level
  196. const type = isActive
  197. ? 'primary'
  198. : 'default'
  199. return (
  200. <Tag
  201. size="large"
  202. plain={isActive}
  203. type={type}
  204. round
  205. onClick={() => {
  206. params.level = subject
  207. }}
  208. >
  209. {subject}
  210. </Tag>
  211. )
  212. }
  213. )}
  214. </div>
  215. </>
  216. )}
  217. {searchObj.value.types &&
  218. searchObj.value.types.length > 0 && (
  219. <>
  220. <div class={styles.searchTitle}>类型</div>
  221. <div
  222. class={[
  223. styles['radio-group'],
  224. styles.radio,
  225. styles['organ-radio']
  226. ]}
  227. >
  228. {searchObj.value.types.map((subject: any) => {
  229. const isActive = subject === params.type
  230. const type = isActive
  231. ? 'primary'
  232. : 'default'
  233. return (
  234. <Tag
  235. size="large"
  236. plain={isActive}
  237. type={type}
  238. round
  239. onClick={() => {
  240. params.type = subject
  241. }}
  242. >
  243. {subject}
  244. </Tag>
  245. )
  246. })}
  247. </div>
  248. </>
  249. )}
  250. </div>
  251. <div class={['btnGroup', 'btnMore']}>
  252. <Button
  253. type="primary"
  254. plain
  255. round
  256. onClick={() => {
  257. params.subjectId = null
  258. params.level = ''
  259. params.type = ''
  260. }}
  261. >
  262. 重 置
  263. </Button>
  264. <Button
  265. type="primary"
  266. round
  267. block
  268. onClick={() => {
  269. onSearch('')
  270. searchRef.value?.toggle()
  271. }}
  272. >
  273. 确 认
  274. </Button>
  275. </div>
  276. </DropdownItem>
  277. </DropdownMenu>
  278. )
  279. }}
  280. />
  281. </TheSticky>
  282. <img class={styles.bgImg} src={bgImg} />
  283. </div>
  284. <div class={styles.alumnList}>
  285. <List
  286. // loading={loading.value}
  287. finished={finished.value}
  288. finished-text={data.value && data.value.rows.length ? '' : ''}
  289. onLoad={FetchList}
  290. error={isError.value}
  291. immediateCheck={false}
  292. >
  293. {data.value && data.value.rows.length ? (
  294. <Song
  295. showTitleImg
  296. list={data.value.rows}
  297. onDetail={(item: any) => {
  298. router.push({
  299. path: '/music-detail',
  300. query: {
  301. id: item.id
  302. }
  303. })
  304. }}
  305. />
  306. ) : (
  307. !loading.value && (
  308. <ColResult
  309. tips="暂无曲目"
  310. classImgSize="SMALL"
  311. btnStatus={false}
  312. />
  313. )
  314. )}
  315. </List>
  316. </div>
  317. </>
  318. )
  319. }
  320. }
  321. })