music-list.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. import OEmpty from '@/components/o-empty'
  2. import { postMessage } from '@/helpers/native-message'
  3. import request from '@/helpers/request'
  4. import { state } from '@/state'
  5. import OFullRefresh from '@/components/o-full-refresh'
  6. import { Cell, CellGroup, DropdownItem, DropdownMenu, Icon, List, Picker, Popup } from 'vant'
  7. import { defineComponent, reactive, ref, onMounted, nextTick, computed } from 'vue'
  8. import { useRoute, useRouter } from 'vue-router'
  9. import { getImage } from './images'
  10. import styles from './index.module.less'
  11. import OSticky from '@/components/o-sticky'
  12. import OSearch from '@/components/o-search'
  13. import OHeader from '@/components/o-header'
  14. // import { getInstrumentName } from '@/constant/instruments'
  15. import { browser } from '@/helpers/utils'
  16. export default defineComponent({
  17. name: 'accompany-music-list',
  18. props: {
  19. musicTree: {
  20. type: Array,
  21. default: () => []
  22. }
  23. },
  24. setup() {
  25. const route = useRoute()
  26. const router = useRouter()
  27. const imgDefault = getImage('icon-music.svg')
  28. const userInfo = ref<any>({})
  29. const subjectKey = state.user?.data?.phone || 'accompany-music-list-subject'
  30. const subjectId =
  31. localStorage.getItem(subjectKey) || state.user?.data?.subjectId?.split(',')?.[0] || ''
  32. const data = reactive({
  33. loading: false,
  34. firstRender: false,
  35. finished: false,
  36. refreshing: false,
  37. musicTree: [] as any,
  38. pagenation: {
  39. page: 1,
  40. rows: 20
  41. },
  42. value1: null,
  43. value2: null,
  44. PopoverOpen: false,
  45. list: [] as any,
  46. keyword: '',
  47. musicSubject: subjectId,
  48. subjectList: [] as any
  49. })
  50. const getTree = async () => {
  51. try {
  52. // const res: any = await request.get(
  53. // state.platformApi + '/musicSheetCategories/queryTree?enable=true&parentId=' + route.query.categorieid
  54. // )
  55. const res: any = await request.post(
  56. state.platformApi + '/musicSheetCategories/queryTreeByParentId',
  57. {
  58. data: {
  59. parentId: route.query.categorieid,
  60. enable: true
  61. }
  62. }
  63. )
  64. if (Array.isArray(res?.data)) {
  65. data.musicTree = res.data
  66. }
  67. nextTick(() => {
  68. getList()
  69. })
  70. } catch (error) {
  71. console.log(error)
  72. }
  73. }
  74. // 获取声部信息
  75. const getSubjects = async () => {
  76. try {
  77. const subjects = await request.get(state.platformApi + '/subject/musicList', {
  78. params: {
  79. enableFlag: true,
  80. page: 1,
  81. rows: 100
  82. }
  83. })
  84. const rows = subjects.data || []
  85. rows.forEach((item: any) => {
  86. data.subjectList.push({
  87. text: item.name,
  88. value: item.id + ''
  89. })
  90. })
  91. data.subjectList.unshift({
  92. text: '全部声部',
  93. value: ''
  94. })
  95. } catch {
  96. //
  97. }
  98. }
  99. /**获取会员购买记录 */
  100. const getUserInfo = async () => {
  101. try {
  102. const res: any = await request.get(`/api-student/student/member`)
  103. userInfo.value = res.data || {}
  104. } catch (error) {
  105. console.log(error)
  106. }
  107. }
  108. const option1 = computed(() => {
  109. const v1: any = data.musicTree
  110. //.find((n: any) => n.id == route.query.categorieid)
  111. if (Array.isArray(v1)) {
  112. const list = [{ text: '全部级别', value: null }].concat(
  113. v1.map((m: any) => {
  114. // if (!data.value1) {
  115. data.value1 = null
  116. data.value2 = null
  117. // }
  118. return {
  119. text: m.name,
  120. value: m.id
  121. }
  122. })
  123. )
  124. return list
  125. }
  126. return []
  127. })
  128. const option2 = computed(() => {
  129. const v1: any = data.musicTree
  130. // .find((n: any) => n.id == route.query.categorieid)
  131. console.log(v1, '---')
  132. if (Array.isArray(v1)) {
  133. const v2: any = v1?.find((n: any) => n.id == data.value1)
  134. if (Array.isArray(v2?.musicSheetCategoriesList)) {
  135. const list = [{ text: '全部类型', value: null }].concat(
  136. v2.musicSheetCategoriesList.map((m: any) => {
  137. return {
  138. text: m.name,
  139. value: m.id
  140. }
  141. })
  142. )
  143. return list
  144. }
  145. }
  146. return [{ text: '全部类型', value: null }]
  147. })
  148. const getList = async () => {
  149. if (data.loading) return
  150. data.loading = true
  151. const bodyData: any = {
  152. ...data.pagenation,
  153. keyword: data.keyword,
  154. musicSheetCategoriesId: data.value2 || data.value1 || route.query.categorieid,
  155. status: 1
  156. }
  157. if (state.platformType == 'TEACHER') {
  158. bodyData.musicSubject = data.musicSubject
  159. }
  160. try {
  161. const res: any = await request.post(state.platformApi + '/musicSheet/page', {
  162. data: bodyData,
  163. hideLoading: true
  164. })
  165. if (Array.isArray(res?.data?.rows)) {
  166. data.list = [].concat(data.list, res.data.rows)
  167. data.pagenation.page += 1
  168. data.finished = res.data.rows.length < data.pagenation.rows ? true : false
  169. } else {
  170. data.finished = true
  171. }
  172. } catch (error) {
  173. data.finished = true
  174. }
  175. data.loading = false
  176. data.refreshing = false
  177. data.firstRender = true
  178. }
  179. // 重置搜索
  180. const onSearch = () => {
  181. data.pagenation.page = 1
  182. data.list = []
  183. data.finished = false
  184. data.list = []
  185. getList()
  186. }
  187. //进入云练习
  188. const openView = async (item: any) => {
  189. const src = `${location.origin}/orchestra-music-score/?id=${item.id}&part-index=${staffData.partIndex}`
  190. console.log('🚀 ~ src:', src)
  191. postMessage({
  192. api: 'openAccompanyWebView',
  193. content: {
  194. url: src,
  195. orientation: 0,
  196. isHideTitle: true,
  197. statusBarTextColor: false,
  198. isOpenLight: true
  199. }
  200. })
  201. }
  202. onMounted(() => {
  203. if (state.platformType == 'STUDENT') {
  204. getUserInfo()
  205. }
  206. if (state.platformType == 'TEACHER') {
  207. getSubjects()
  208. }
  209. getTree()
  210. })
  211. const staffData = reactive({
  212. open: false,
  213. musicXml: {} as any,
  214. instrumentName: '',
  215. partIndex: 0,
  216. partList: [] as any[]
  217. })
  218. // const getPartNames = async (item: any) => {
  219. // let partNames: any[] = []
  220. // try {
  221. // const { data } = await request.get(state.platformApi + '/musicSheet/detail/' + item.id)
  222. // let partList = data.background || []
  223. // partList = partList.filter(
  224. // (item: any) => !item.track?.toLocaleUpperCase()?.includes('COMMON')
  225. // )
  226. // partNames = partList.map((item: any, index: number) => {
  227. // const instrumentName = getInstrumentName(item.track)
  228. // return {
  229. // text: item.track + (instrumentName ? `(${instrumentName})` : ''),
  230. // value: index
  231. // }
  232. // })
  233. // } catch (error) {
  234. // console.log(error)
  235. // }
  236. // console.log('🚀 ~ partNames:', partNames)
  237. // return partNames
  238. // }
  239. // const openMutilPart = async (item: any) => {
  240. // if (staffData.musicXml[item.id]) {
  241. // staffData.instrumentName = item.id
  242. // staffData.open = true
  243. // return Promise.resolve()
  244. // }
  245. // staffData.musicXml[item.id] = await getPartNames(item)
  246. // staffData.instrumentName = item.id
  247. // staffData.open = true
  248. // }
  249. return () => (
  250. <div class={styles['accompany-music-list']}>
  251. <OSticky
  252. mode="sticky"
  253. class={styles.heade}
  254. onGetHeight={(height: number) => {
  255. document.documentElement.style.setProperty('--header-height', height + 'px')
  256. }}
  257. >
  258. <OHeader border={false} />
  259. <div>
  260. <DropdownMenu activeColor="var(--van-primary)">
  261. <DropdownItem
  262. v-model:modelValue={data.value1}
  263. options={option1.value as any}
  264. onChange={() => {
  265. data.value2 = null
  266. onSearch()
  267. }}
  268. ></DropdownItem>
  269. <DropdownItem
  270. v-model:modelValue={data.value2}
  271. options={option2.value as any}
  272. onChange={() => onSearch()}
  273. ></DropdownItem>
  274. </DropdownMenu>
  275. <div class={styles.filter}>
  276. <OSearch
  277. class={styles.filterBox}
  278. onSearch={(keyword: string) => {
  279. data.keyword = keyword
  280. onSearch()
  281. }}
  282. >
  283. {{
  284. left: () =>
  285. state.platformType == 'TEACHER' ? (
  286. <DropdownMenu activeColor="var(--van-primary)">
  287. <DropdownItem
  288. v-model:modelValue={data.musicSubject}
  289. options={data.subjectList}
  290. onChange={() => {
  291. localStorage.setItem(subjectKey, data.musicSubject)
  292. onSearch()
  293. }}
  294. ></DropdownItem>
  295. </DropdownMenu>
  296. ) : null
  297. }}
  298. </OSearch>
  299. </div>
  300. </div>
  301. </OSticky>
  302. <OFullRefresh
  303. v-model:modelValue={data.refreshing}
  304. onRefresh={onSearch}
  305. style="min-height: calc(100vh - var(--header-height))"
  306. >
  307. <List
  308. loading-text=" "
  309. immediateCheck={false}
  310. loading={data.loading}
  311. v-model:finished={data.finished}
  312. finishedText=" "
  313. onLoad={() => {
  314. getList()
  315. }}
  316. >
  317. <CellGroup inset>
  318. {data.list.map((item: any) => {
  319. return (
  320. <Cell
  321. size="large"
  322. center
  323. title={item.musicSheetName}
  324. isLink
  325. onClick={() => {
  326. if (browser().isApp) {
  327. const url = `${location.origin}${location.pathname}#/musicDetail?id=${item.id}`
  328. postMessage({
  329. api: 'openWebView',
  330. content: {
  331. url,
  332. orientation: 1,
  333. isHideTitle: true,
  334. statusBarTextColor: false,
  335. isOpenLight: false
  336. }
  337. })
  338. } else {
  339. router.push({
  340. path: '/musicDetail',
  341. query: {
  342. id: item.id
  343. }
  344. })
  345. }
  346. }}
  347. >
  348. {{
  349. icon: () => (
  350. <Icon style={{ marginRight: '12px' }} size={40} name={imgDefault} />
  351. )
  352. }}
  353. </Cell>
  354. )
  355. })}
  356. </CellGroup>
  357. <div style={{ height: '40px' }}></div>
  358. </List>
  359. {data.firstRender && !data.loading && !data.list.length && <OEmpty tips="暂无曲谱" />}
  360. </OFullRefresh>
  361. <Popup teleport="body" position="bottom" round v-model:show={staffData.open}>
  362. <Picker
  363. columns={staffData.musicXml[staffData.instrumentName]}
  364. onConfirm={(value) => {
  365. staffData.open = false
  366. staffData.partIndex = value.selectedValues[0]
  367. openView({ id: staffData.instrumentName })
  368. }}
  369. onCancel={() => (staffData.open = false)}
  370. />
  371. </Popup>
  372. </div>
  373. )
  374. }
  375. })