浏览代码

合并v1.3

skyblued 2 年之前
父节点
当前提交
72f90b18a3

+ 185 - 146
src/views/article-center/theory.tsx

@@ -1,146 +1,185 @@
-import request from '@/helpers/request'
-import {
-  Cell,
-  List,
-  Sticky,
-  Image,
-  CellGroup,
-  Collapse,
-  CollapseItem
-} from 'vant'
-import { defineComponent } from 'vue'
-import styles from './theory.module.less'
-import ColSearch from '@/components/col-search'
-import ColResult from '@/components/col-result'
-
-export default defineComponent({
-  name: 'special',
-  data() {
-    const query = this.$route.query
-    return {
-      activeNames: [] as any,
-      list: [],
-      dataShow: true, // 判断是否有数据
-      loading: false,
-      finished: false,
-      // 1热门资讯,2开屏广告,3闪页管理,4轮播图管理 5按钮管理 6 乐理章节
-      params: {
-        search: '',
-        page: 1,
-        rows: 20
-      }
-    }
-  },
-  mounted() {
-    this.getList()
-  },
-  methods: {
-    async getList() {
-      try {
-        let params = this.params
-        const res = await request.post('/api-cms/music/theory/app/page', {
-          data: {
-            ...params
-          }
-        })
-        this.loading = false
-        const result = res.data || {}
-        // 处理重复请求数据
-        if (this.list.length > 0 && result.pageNo === 1) {
-          return
-        }
-        this.list = this.list.concat(result.rows || [])
-        this.finished = result.pageNo >= result.totalPage
-        this.params.page = result.pageNo + 1
-        this.dataShow = this.list.length > 0
-
-        const tempList: any = this.list
-        this.list.length > 0 && this.activeNames.push(tempList[0].id)
-      } catch {
-        this.dataShow = false
-        this.finished = true
-      }
-    },
-    onSearch(val: string) {
-      this.params.search = val
-      this.params.page = 1
-      this.list = []
-      this.dataShow = true // 判断是否有数据
-      this.loading = false
-      this.finished = false
-      this.getList()
-    },
-    onDetail(item: any) {
-      if (item.linkUrl) {
-        window.location.href = item.linkUrl
-      } else {
-        this.$router.push({
-          path: 'theoryDetail',
-          query: {
-            id: item.id
-          }
-        })
-      }
-    }
-  },
-  render() {
-    return (
-      <div class={styles['theory']}>
-        <Sticky offsetTop={0} position="top" class={'mb12'}>
-          <ColSearch onSearch={this.onSearch} />
-        </Sticky>
-        {this.dataShow ? (
-          <List
-            class={styles.videoList}
-            v-model:loading={this.loading}
-            finished={this.finished}
-            finishedText="没有更多了"
-            immediateCheck={false}
-            onLoad={this.getList}
-          >
-            {this.list.map((parent: any) => (
-              <Collapse v-model={this.activeNames} border={false}>
-                <CollapseItem
-                  title={parent.name}
-                  name={parent.id}
-                  center
-                  v-slots={{
-                    title: () => (
-                      <div class={[styles.groupTitle]}>
-                        {parent.url && (
-                          <Image
-                            src={parent.url}
-                            fit="cover"
-                            class={styles.groupImg}
-                          />
-                        )}
-
-                        <p class={['van-ellipsis', styles.musicTitle]}>
-                          {parent.name}
-                        </p>
-                      </div>
-                    )
-                  }}
-                >
-                  {parent.newsInformationList.map((item: any) => (
-                    <Cell
-                      title={item.title}
-                      class={styles.cell}
-                      border={false}
-                      onClick={() => {
-                        this.onDetail(item)
-                      }}
-                      titleClass={['van-ellipsis', styles.title]}
-                    />
-                  ))}
-                </CollapseItem>
-              </Collapse>
-            ))}
-          </List>
-        ) : (
-          <ColResult btnStatus={false} classImgSize="SMALL" tips="暂无内容" />
-        )}
-      </div>
-    )
-  }
-})
+import request from '@/helpers/request'
+import {
+  Cell,
+  List,
+  Sticky,
+  Image,
+  CellGroup,
+  Collapse,
+  CollapseItem
+} from 'vant'
+import { defineComponent } from 'vue'
+import styles from './theory.module.less'
+import ColSearch from '@/components/col-search'
+import ColResult from '@/components/col-result'
+import { postMessage, promisefiyPostMessage } from '@/helpers/native-message'
+import { state } from '@/state'
+
+export default defineComponent({
+  name: 'special',
+  data() {
+    const query = this.$route.query
+    return {
+      activeNames: [] as any,
+      list: [],
+      dataShow: true, // 判断是否有数据
+      loading: false,
+      finished: false,
+      // 1热门资讯,2开屏广告,3闪页管理,4轮播图管理 5按钮管理 6 乐理章节
+      params: {
+        search: '',
+        page: 1,
+        rows: 20
+      },
+      theory:null as null
+    }
+  },
+  mounted() {
+    let theoryStr = sessionStorage.getItem('theoryCache')
+    if (theoryStr) {
+      const theory = JSON.parse(theoryStr)
+      this.theory = theory
+      let activeNames = theory.activeNames.split(',').map(item => item * 1)
+      this.activeNames = activeNames
+      this.params.search = theory.search || ''
+
+    }
+    this.getList()
+  },
+  methods: {
+    async getList() {
+      try {
+        let params = this.params
+        const res = await request.post('/api-cms/music/theory/app/page', {
+          data: {
+            ...params
+          }
+        })
+        this.loading = false
+        const result = res.data || {}
+        // 处理重复请求数据
+        if (this.list.length > 0 && result.pageNo === 1) {
+          return
+        }
+        this.list = this.list.concat(result.rows || [])
+        this.finished = result.pageNo >= result.totalPage
+        this.params.page = result.pageNo + 1
+        this.dataShow = this.list.length > 0
+
+        const tempList: any = this.list
+        if (this.activeNames.length <= 0) {
+          this.list.length > 0 && this.activeNames.push(tempList[0].id)
+        }
+      } catch {
+        this.dataShow = false
+        this.finished = true
+      }
+      // if(this.theory&&this.theory.scrollTop as never){
+      //   this.$nextTick(()=>{
+      //     window.scrollTo(0, this.theory.scrollTop as never)
+      //   })
+      //   //
+      // }
+    },
+    onSearch(val: string) {
+      this.params.search = val
+      this.params.page = 1
+      this.list = []
+      this.dataShow = true // 判断是否有数据
+      this.loading = false
+      this.finished = false
+      this.getList()
+    },
+    onDetail(item: any) {
+      // let scrollTop  = document.documentElement.scrollTop || document.body.scrollTop;
+      // console.log(scrollTop)
+      // let obj = JSON.stringify({
+      //   search: this.params.search,
+      //   activeNames: this.activeNames.join(','),
+      //   scrollTop:scrollTop
+      // })
+
+      // sessionStorage.setItem('theoryCache', obj)
+
+      if (item.linkUrl) {
+        window.location.href = item.linkUrl
+      } else {
+        // this.$router.push({
+        //   path: 'theoryDetail',
+        //   query: {
+        //     id: item.id
+        //   }
+        // })
+        let client = state.platformType==='STUDENT'?'student':'teacher'
+        postMessage({
+          api: 'openWebView',
+          content: {
+            url: `${location.origin}/${client}/#/theoryDetail?id=${item.id}`,
+            orientation: 1,
+            isHideTitle: false
+          }
+        })
+      }
+    }
+  },
+  render() {
+    return (
+      <div class={[styles['theory'],'theory']}>
+        <Sticky offsetTop={0} position="top" class={'mb12'}>
+          <ColSearch onSearch={this.onSearch} modelValue={this.params.search} />
+        </Sticky>
+        {this.dataShow ? (
+          <List
+            class={styles.videoList}
+            v-model:loading={this.loading}
+            finished={this.finished}
+            finishedText="没有更多了"
+            immediateCheck={false}
+            onLoad={this.getList}
+          >
+            {this.list.map((parent: any) => (
+              <Collapse v-model={this.activeNames} border={false}>
+                <CollapseItem
+                  title={parent.name}
+                  name={parent.id}
+                  center
+                  v-slots={{
+                    title: () => (
+                      <div class={[styles.groupTitle]}>
+                        {parent.url && (
+                          <Image
+                            src={parent.url}
+                            fit="cover"
+                            class={styles.groupImg}
+                          />
+                        )}
+
+                        <p class={['van-ellipsis', styles.musicTitle]}>
+                          {parent.name}
+                        </p>
+                      </div>
+                    )
+                  }}
+                >
+                  {parent.newsInformationList.map((item: any) => (
+                    <Cell
+                      title={item.title}
+                      class={styles.cell}
+                      border={false}
+                      onClick={() => {
+                        this.onDetail(item)
+                      }}
+                      titleClass={['van-ellipsis', styles.title]}
+                    />
+                  ))}
+                </CollapseItem>
+              </Collapse>
+            ))}
+          </List>
+        ) : (
+          <ColResult btnStatus={false} classImgSize="SMALL" tips="暂无内容" />
+        )}
+      </div>
+    )
+  }
+})

+ 2 - 2
src/views/live-class/index.tsx

@@ -10,7 +10,7 @@ import LiveItem from './live-item'
 import banner from '../video-class/images/banner.png'
 import { state } from '@/state'
 import OrganSearch from '@/student/practice-class/model/organ-search'
-
+ 
 export default defineComponent({
   name: 'liveClass',
   data() {
@@ -40,7 +40,7 @@ export default defineComponent({
   },
   async mounted() {
     try {
-      const res = await request.get(`${this.apiSuffix}/subject/subjectSelect`)
+      const res = await request.get(`${this.apiSuffix}/subject/subjectSelect?type=LIVE`)
       this.subjectList = res.data || []
     } catch {
       //

+ 14 - 0
src/views/music/album/index.module.less

@@ -3,3 +3,17 @@
     box-shadow: 10px 10px 10px var(--box-shadow-color);
   }
 }
+.label {
+  margin-right: 8px;
+  font-size: 14px;
+  :global {
+    .van-list__loading,
+    .van-list__finished-text,
+    .van-list__error-text {
+      width: 100%;
+    }
+    .iconfont-down {
+      margin-left: 4px;
+    }
+  } 
+}

+ 47 - 2
src/views/music/album/index.tsx

@@ -1,5 +1,5 @@
 import { defineComponent, reactive, ref } from 'vue'
-import { Sticky, List, Popup } from 'vant'
+import { Sticky, List, Popup, Icon } from 'vant'
 import Search from '@/components/col-search'
 import request from '@/helpers/request'
 import Item from './item'
@@ -8,6 +8,7 @@ import { useRoute } from 'vue-router'
 import ColResult from '@/components/col-result'
 import styles from './index.module.less'
 import { state } from '@/state'
+import SelectSubject from '../search/select-subject'
 
 export default defineComponent({
   name: 'Album',
@@ -88,11 +89,28 @@ export default defineComponent({
       tagVisibility.value = false
     }
 
+    const onComfirmSubject = item => {
+      params.page = 1
+      params.subjectIds = item.id
+      subject.id = item.id
+      subject.name = item.name
+      data.value = null
+      FetchList()
+      subject.show = false
+    }
+
     expose({
       onSearch,
-      onComfirm
+      onComfirm,
+      onComfirmSubject
     })
 
+    const subject = reactive({
+      show: false,
+      name: '全部',
+      id: ''
+    });
+
     return () => {
       return (
         <>
@@ -113,6 +131,22 @@ export default defineComponent({
                   onSearch={onSearch}
                   onFilter={() => (tagVisibility.value = true)}
                   filterDot={!!params.albumTagIds}
+                  v-slots={{
+                    left: () => (
+                      <div
+                        class={styles.label}
+                        onClick={() => (subject.show = true)}
+                      >
+                        {subject.name}
+                        <Icon
+                          classPrefix="iconfont"
+                          name="down"
+                          size={12}
+                          color="#333"
+                        />
+                      </div>
+                    )
+                  }}
                 />
               </Sticky>
             )}
@@ -142,6 +176,17 @@ export default defineComponent({
               onCancel={() => {}}
             />
           </Popup>
+          <Popup
+            show={subject.show}
+            position="bottom"
+            round
+            closeable
+            safe-area-inset-bottom
+            onClose={() => (subject.show = false)}
+            onClosed={() => (subject.show = false)}
+          >
+            <SelectSubject isReset onComfirm={onComfirmSubject} /> 
+          </Popup>
         </>
       )
     }

+ 14 - 0
src/views/music/list/index.module.less

@@ -3,3 +3,17 @@
     box-shadow: 10px 10px 10px var(--box-shadow-color);
   }
 }
+.label {
+  margin-right: 8px;
+  font-size: 14px;
+  :global {
+    .van-list__loading,
+    .van-list__finished-text,
+    .van-list__error-text {
+      width: 100%;
+    }
+    .iconfont-down {
+      margin-left: 4px;
+    } 
+  }
+}

+ 48 - 2
src/views/music/list/index.tsx

@@ -1,5 +1,5 @@
 import { defineComponent, reactive, ref } from 'vue'
-import { Sticky, List, Popup } from 'vant'
+import { Sticky, List, Popup, Icon } from 'vant'
 import Search from '@/components/col-search'
 import request from '@/helpers/request'
 import Item from './item'
@@ -9,6 +9,7 @@ import ColResult from '@/components/col-result'
 import styles from './index.module.less'
 import { getRandomKey, musicBuy } from '../music'
 import { state } from '@/state'
+import SelectSubject from '../search/select-subject'
 
 const noop = () => {}
 
@@ -104,10 +105,26 @@ export default defineComponent({
       FetchList()
       tagVisibility.value = false
     }
+    const onComfirmSubject = (item) => {
+      params.page = 1
+      params.subjectIds = item.id
+      subject.id = item.id
+      subject.name = item.name
+      data.value = null
+      FetchList()
+      subject.show = false
+    }
+
+    const subject = reactive({
+      show: false,
+      name: '全部',
+      id: ''
+    })
 
     expose({
       onSearch,
-      onComfirm
+      onComfirm,
+      onComfirmSubject
     })
 
     return () => (
@@ -128,6 +145,22 @@ export default defineComponent({
                 onSearch={onSearch}
                 onFilter={() => (tagVisibility.value = true)}
                 filterDot={!!params.musicTagIds}
+                v-slots={{
+                  left: () => (
+                    <div
+                      class={styles.label}
+                      onClick={() => (subject.show = true)}
+                    >
+                      {subject.name}
+                      <Icon
+                        classPrefix="iconfont"
+                        name="down"
+                        size={12}
+                        color="#333"
+                      />
+                    </div>
+                  )
+                }}
               />
             </Sticky>
           )}
@@ -168,6 +201,19 @@ export default defineComponent({
             defaultValue={route.query.tagids as string}
           />
         </Popup>
+
+        {/* 声部弹框 */}
+        <Popup
+            show={subject.show}
+            position="bottom"
+            round
+            closeable
+            safe-area-inset-bottom
+            onClose={() => (subject.show = false)}
+            onClosed={() => (subject.show = false)}
+          >
+            <SelectSubject isReset onComfirm={onComfirmSubject} />
+          </Popup>
       </>
     )
   }

+ 2 - 2
src/views/music/list/item.tsx

@@ -51,7 +51,7 @@ export default defineComponent({
 
     const shareStatus = ref(false)
     const shareUrl = ref('')
-    console.log(data)
+    // console.log(data)
     const onShare = (evt: MouseEvent) => {
       evt.stopPropagation()
       // if (!shareStatus.value) {
@@ -123,7 +123,7 @@ export default defineComponent({
                   style={{ border: 'none' }}
                   class={styles.shareBtn}
                   onClick={onShare}
-                >
+                > 
                   <Icon class={styles.favorite} name={iconShare} />
                 </Button>
               )}

+ 47 - 20
src/views/music/search/header.tsx

@@ -3,10 +3,9 @@ import {
   RouterView,
   useRouter,
   useRoute,
-  onBeforeRouteUpdate,
-  onBeforeRouteLeave
+  onBeforeRouteUpdate
 } from 'vue-router'
-import { defineComponent, onMounted, ref, watch } from 'vue'
+import { defineComponent, onMounted, reactive, ref, watch } from 'vue'
 import mitt from 'mitt'
 import Search from '@/components/col-search'
 import { useLocalStorage } from '@vueuse/core'
@@ -14,6 +13,7 @@ import styles from './index.module.less'
 import classNames from 'classnames'
 import SelectTag from './select-tag'
 import { getRandomKey, musicBuy } from '../music'
+import SelectSubject from './select-subject'
 
 export const mitter = mitt()
 
@@ -26,22 +26,19 @@ export default defineComponent({
     localStorage.setItem('behaviorId', getRandomKey())
     const router = useRouter()
     const route = useRoute()
-    const loading = ref(false)
     const keyword = ref('')
     const tagids = ref('')
-    const albumRows = ref([])
-    const sheetRows = ref([])
     const tagVisibility = ref(false)
     const words = useLocalStorage<string[]>('music-search', [])
     const activeTab = ref('songe')
 
     onBeforeRouteUpdate(() => {
-      // console.log('onBeforeRouteUpdate', route.fullPath)
       if (route.path === '/music-songbook/search') {
         keyword.value = ''
         tagids.value = ''
+        subject.name = '全部'
+        subject.id = ''
         activeTab.value = 'songe'
-        // console.log('onBeforeRouteUpdate')
         try {
           selectTagRef.value?.resetTags?.()
         } catch (error) {
@@ -66,28 +63,29 @@ export default defineComponent({
         words.value.length = Math.min(words.value.length, 5)
       }
       mitter.emit('search', val)
-      // const activeRef = activeTab.value === 'album' ? albumList : musicList
-      // ;(activeRef.value as any).onSearch?.(val)
-      // FetchList()
     }
 
     const onComfirm = (tags, name = '') => {
       const data = Object.values(tags).flat().filter(Boolean).join(',')
       tagids.value = data
       mitter.emit('confirm', tags)
-      // FetchList()
-      // const activeRef = activeTab.value === 'album' ? albumList : musicList
-      // ;(activeRef.value as any).onComfirm?.(tags)
       tagVisibility.value = false
     }
 
-    // const albumList = ref(null)
-    // const musicList = ref(null)
+    const onComfirmSubject = (item: any) => {
+      // console.log('onSort', item)
+      subject.name = item.name
+      subject.id = item.id
+      mitter.emit('confirmSubject', subject)
+      subject.show = false
+    }
+
+    onMounted(() => {})
 
-    onMounted(() => {
-      // const activeRef = activeTab.value === 'album' ? albumList : musicList
-      // ;(activeRef.value as any).onSearch?.('')
-      // console.log(searchInputRef.value)
+    const subject = reactive({
+      show: false,
+      name: '全部',
+      id: ''
     })
     return () => {
       return (
@@ -107,6 +105,22 @@ export default defineComponent({
                   })
                 }
               }}
+              v-slots={{
+                left: () => (
+                  <div
+                    class={styles.label}
+                    onClick={() => (subject.show = true)}
+                  >
+                    {subject.name}
+                    <Icon
+                      classPrefix="iconfont"
+                      name="down"
+                      size={12}
+                      color="#333"
+                    />
+                  </div>
+                )
+              }}
             />
             {route.path === '/music-songbook/search' && (
               <Tabs
@@ -159,6 +173,19 @@ export default defineComponent({
               onCancel={() => {}}
             />
           </Popup>
+
+          {/* 声部弹框 */}
+          <Popup
+            show={subject.show}
+            position="bottom"
+            round
+            closeable
+            safe-area-inset-bottom
+            onClose={() => (subject.show = false)}
+            onClosed={() => (subject.show = false)}
+          >
+            <SelectSubject isReset onComfirm={onComfirmSubject} />
+          </Popup>
         </div>
       )
     }

+ 14 - 0
src/views/music/search/index.module.less

@@ -49,4 +49,18 @@
       font-size: 16px;
     }
   }
+  .label {
+    margin-right: 8px;
+    font-size: 14px;
+    :global {
+      .van-list__loading,
+      .van-list__finished-text,
+      .van-list__error-text {
+        width: 100%;
+      }
+      .iconfont-down {
+        margin-left: 4px; 
+      }
+    }
+  }
 }

+ 14 - 52
src/views/music/search/index.tsx

@@ -1,17 +1,8 @@
-import { Sticky, Cell, Tag, Icon, Popup, Tabs, Tab, Dialog } from 'vant'
 import { defineComponent, onMounted, onUnmounted, ref } from 'vue'
-// import Search from '@/components/col-search'
 import { useLocalStorage } from '@vueuse/core'
-// import AlbumItem from '../album/item'
 import AlbumList from '../album'
-// import MusicItem from '../list/item'
 import MusicList from '../list'
 import styles from './index.module.less'
-// import classNames from 'classnames'
-// import request from '@/helpers/request'
-import SelectTag from './select-tag'
-// import ColResult from '@/components/col-result'
-// import { orderStatus } from '@/views/order-detail/orderStatus'
 import { useRoute, useRouter } from 'vue-router'
 import { getRandomKey, musicBuy } from '../music'
 import { mitter } from './header'
@@ -20,39 +11,16 @@ export default defineComponent({
   name: 'MusicSearch',
   emits: ['confirm'],
   setup() {
-    const searchInputRef = ref()
     localStorage.setItem('behaviorId', getRandomKey())
     const route = useRoute()
     const router = useRouter()
-    const loading = ref(false)
     const keyword = ref(route.query.keyword || '')
     const tagids = ref(route.query.tagids || '')
-    const albumRows = ref([])
-    const sheetRows = ref([])
+    const subject = ref();
     const tagVisibility = ref(false)
     const words = useLocalStorage<string[]>('music-search', [])
     const activeTab = ref('songe')
 
-    const FetchList = async () => {
-      // loading.value = true
-      // try {
-      //   const res = await request.post(
-      //     '/api-student/music/sheet/albumAndSheetList',
-      //     {
-      //       data: {
-      //         albumRow: 3,
-      //         sheetRow: 10,
-      //         search: keyword.value,
-      //         musicTagIds: tagids.value
-      //       }
-      //     }
-      //   )
-      //   albumRows.value = res.data.musicAlbumList.rows
-      //   sheetRows.value = res.data.musicSheetList.rows
-      // } catch (error) {}
-      // loading.value = false
-    }
-
     const onSearch = val => {
       keyword.value = val
       const indexOf = words.value.indexOf(val)
@@ -64,20 +32,23 @@ export default defineComponent({
         words.value.length = Math.min(words.value.length, 5)
       }
       const activeRef = activeTab.value === 'album' ? albumList : musicList
-      console.log(val)
       ;(activeRef.value as any).onSearch?.(val)
-      // FetchList()
     }
 
     const onComfirm = tags => {
       const data = Object.values(tags).flat().filter(Boolean).join(',')
       tagids.value = data
-      // FetchList()
       const activeRef = activeTab.value === 'album' ? albumList : musicList
       ;(activeRef.value as any).onComfirm?.(tags)
       tagVisibility.value = false
     }
 
+    const onConfirmSubject = (item: any) => {
+      subject.value = item.id
+      const activeRef = activeTab.value === 'album' ? albumList : musicList
+      ;(activeRef.value as any).onComfirmSubject?.(item)
+    }
+
     const albumList = ref(null)
     const musicList = ref(null)
 
@@ -89,14 +60,14 @@ export default defineComponent({
       mitter.on('changeTab', changeTab)
       mitter.on('search', onSearch)
       mitter.on('confirm', onComfirm)
-      // ;(activeRef.value as any).onSearch?.('')
-      // console.log(searchInputRef.value)
+      mitter.on('confirmSubject', onConfirmSubject)
     })
 
     onUnmounted(() => {
       mitter.off('changeTab', changeTab)
       mitter.off('search', onSearch)
-      mitter.off('confirm', onComfirm)
+      mitter.off('confirm', onComfirm) 
+      mitter.off('confirmSubject', onConfirmSubject)
     })
 
     return () => {
@@ -108,7 +79,8 @@ export default defineComponent({
               ref={albumList}
               defauleParams={{
                 search: keyword.value,
-                tagids: tagids.value
+                tagids: tagids.value,
+                subjectIds: subject.value
               }}
             />
           ) : (
@@ -127,21 +99,11 @@ export default defineComponent({
               }}
               defauleParams={{
                 search: keyword.value,
-                tagids: tagids.value
+                tagids: tagids.value,
+                subjectIds: subject.value
               }}
             />
           )}
-          {/* <Popup
-            show={tagVisibility.value}
-            round
-            closeable
-            position="bottom"
-            style={{ height: '60%' }}
-            teleport="body"
-            onUpdate:show={val => (tagVisibility.value = val)}
-          >
-            <SelectTag onConfirm={onComfirm} onCancel={() => {}} />
-          </Popup> */}
         </div>
       )
     }

+ 79 - 0
src/views/music/search/select-subject.module.less

@@ -0,0 +1,79 @@
+.filterTitle {
+  font-size: 18px;
+  font-weight: 500;
+  color: #000000;
+  line-height: 25px;
+  text-align: center;
+  padding: 20px 0;
+}
+
+.searchResult {
+  padding: 0 16px;
+  overflow: hidden;
+  margin-bottom: 20px;
+  .searchTitle {
+    font-size: 16px;
+    color: #333333;
+    line-height: 22px; 
+  }
+}
+
+.radio-group {
+  display: flex;
+  margin-top: 10px;
+  margin-bottom: 20px;
+  flex-wrap: wrap;
+  .radio:first-child {
+    :global {
+      .van-radio__label {
+        margin-left: 0;
+      }
+    }
+  }
+}
+
+.radio {
+  :global {
+    .van-radio__icon {
+      display: none;
+    }
+    .van-tag--large {
+      width: 80px;
+      height: 32px;
+      font-size: 16px;
+      text-align: center;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+    .van-tag {
+      box-sizing: border-box;
+    }
+    .van-tag--default {
+      color: var(--van-tag-text-default-color);
+    }
+    .van-tag--primary {
+      background-color: var(--tag-bg-color);
+    }
+  }
+}
+
+.organ-radio {
+  :global {
+    .van-tag--large {
+      width: auto;
+      padding: 0 12px;
+      margin-bottom: 8px;
+      margin-right: 8px;
+      font-size: 14px;
+    }
+  }
+}
+
+.btn {
+  padding: 5px 14px;
+
+  & + .btn {
+    margin-left: 10px;
+  }
+}

+ 118 - 0
src/views/music/search/select-subject.tsx

@@ -0,0 +1,118 @@
+import { defineComponent } from 'vue'
+import styles from './select-subject.module.less'
+import { Tag, Button, Sticky } from 'vant'
+import { state } from '@/state'
+import request from '@/helpers/request'
+
+export default defineComponent({
+  name: 'selectSubject',
+  props: {
+    isReset: {
+      type: Boolean,
+      default: false
+    },
+    onComfirm: {
+      type: Function,
+      default: (item: any) => {}
+    }
+  },
+  data() {
+    return {
+      subject: {
+        name: '',
+        id: ''
+      },
+      subjectList: [] as any,
+      apiSuffix:
+        state.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
+    }
+  },
+  mounted() {
+    this.getList()
+  },
+  methods: {
+    async getList() {
+      const { data } = await request.get(
+        `${this.apiSuffix}/subject/subjectSelect?type=MUSIC`
+      )
+      if (Array.isArray(data)) {
+        this.subjectList = data
+      }
+    }
+  },
+  render() {
+    return (
+      <>
+        <div class={styles.filterTitle}>全部声部</div>
+        <div
+          class={styles.searchResult}
+          style={{ maxHeight: '45vh', overflowY: 'auto' }}
+        >
+          {this.subjectList.map(
+            (item: any) =>
+              item.subjects &&
+              item.subjects.length > 0 && (
+                <>
+                  <div class={styles.searchTitle}>{item.name}</div>
+                  <div
+                    class={[
+                      styles['radio-group'],
+                      styles.radio,
+                      styles['organ-radio']
+                    ]}
+                  >
+                    {item.subjects.map((subject: any) => {
+                      const isActive = subject.id === Number(this.subject.id)
+                      const type = isActive ? 'primary' : 'default'
+                      return (
+                        <Tag
+                          size="large"
+                          plain={isActive}
+                          type={type}
+                          round
+                          onClick={() => {
+                            this.subject = subject
+                          }}
+                        >
+                          {subject.name}
+                        </Tag>
+                      )
+                    })}
+                  </div>
+                </>
+              )
+          )}
+        </div>
+        <Sticky position="bottom" offsetBottom={0}>
+          <div class={['btnGroup', this.isReset ? 'btnMore' : '']}>
+            {this.isReset && (
+              <Button
+                type="primary"
+                plain
+                round
+                onClick={() => {
+                  this.subject.name = '全部'
+                  this.subject.id = ''
+                  this.onComfirm({...this.subject})
+                }}
+              >
+                重 置
+              </Button>
+            )}
+
+            <Button
+              type="primary"
+              round
+              block
+              onClick={() => {
+                this.onComfirm({ ...this.subject })
+              }}
+            >
+              确 认
+            </Button>
+          </div>
+        </Sticky>
+      </>
+    )
+  }
+})

+ 2 - 2
src/views/video-class/index.tsx

@@ -40,13 +40,13 @@ export default defineComponent({
   },
   async mounted() {
     try {
-      const res = await request.get(`${this.apiSuffix}/subject/subjectSelect`)
+      const res = await request.get(`${this.apiSuffix}/subject/subjectSelect?type=VIDEO`)
       this.subjectList = res.data || []
     } catch {
       //
     }
     let subjectName = ''
-    console.log(this.params.lessonSubject)
+    // console.log(this.params.lessonSubject)
     this.subjectList.forEach((item: any) => {
       item.subjects?.forEach((child: any) => {
         if (child.id === Number(this.params.lessonSubject)) {

+ 71 - 69
src/views/video-class/video-item.tsx

@@ -1,69 +1,71 @@
-import { defineComponent, PropType } from 'vue'
-import { Image } from 'vant'
-import styles from './video-item.module.less'
-
-import iconTeacher from '@common/images/icon_teacher.png'
-
-interface VideoItemProps {
-  id?: number
-  teacherId?: number
-  lessonName: string
-  userName: string
-  avatar: string
-  lessonCoverUrl: string
-  lessonCount: number
-  lessonPrice: number
-  countStudent: number
-  lessonSubjectName: string
-}
-
-export default defineComponent({
-  name: 'VideoItem',
-  props: {
-    item: Object as PropType<VideoItemProps>,
-    onClick: {
-      type: Function as PropType<(item: any) => void>,
-      default: (item: any) => {}
-    }
-  },
-  render() {
-    const item: any = this.item
-    return (
-      <div
-        class={styles.videoItem}
-        onClick={() => {
-          this.onClick(item)
-        }}
-      >
-        <div style={{ position: 'relative' }}>
-          <Image
-            class={styles.viCover}
-            fit="cover"
-            src={item?.lessonCoverUrl}
-          />
-          <span class={styles.subjectName}>{item?.lessonSubjectName}</span>
-        </div>
-
-        <div class={styles.viSection}>
-          <div class={[styles.viTitle, 'van-ellipsis']}>{item?.lessonName}</div>
-          <div class={styles.viUserInfo}>
-            <Image
-              src={item?.avatar || iconTeacher}
-              class={styles.viUserLogo}
-            />
-            <span class={[styles.viUserName, 'van-hairline--right']}>
-              {item?.userName ||
-                item?.username ||
-                `游客${item?.teacherId || ''}`}
-            </span>
-            <span class={styles.viUserNum}>{item?.countStudent}人已购买</span>
-          </div>
-          <div class={styles.viPrice}>
-            {item?.lessonPrice > 0 && <>¥{item?.lessonPrice}/</>}
-            {item?.lessonCount}课时
-          </div>
-        </div>
-      </div>
-    )
-  }
-})
+import { defineComponent, PropType } from 'vue'
+import { Image } from 'vant'
+import styles from './video-item.module.less'
+
+import iconTeacher from '@common/images/icon_teacher.png'
+
+interface VideoItemProps {
+  id?: number
+  teacherId?: number
+  lessonName: string
+  userName: string
+  avatar: string
+  lessonCoverUrl: string
+  lessonCount: number
+  lessonPrice: number
+  countStudent: number
+  lessonSubjectName: string
+}
+
+export default defineComponent({
+  name: 'VideoItem',
+  props: {
+    item: Object as PropType<VideoItemProps>,
+    onClick: {
+      type: Function as PropType<(item: any) => void>,
+      default: (item: any) => {}
+    }
+  },
+  render() {
+    const item: any = this.item
+    return (
+      <div
+        class={styles.videoItem}
+        onClick={() => {
+          this.onClick(item)
+        }}
+      >
+        <div style={{ position: 'relative' }}>
+          <Image
+            class={styles.viCover}
+            fit="cover"
+            src={item?.lessonCoverUrl}
+          />
+          <span class={styles.subjectName}>{item?.lessonSubjectName}</span>
+        </div>
+
+        <div class={styles.viSection}>
+          <div class={[styles.viTitle, 'van-ellipsis']}>{item?.lessonName}</div>
+          <div class={styles.viUserInfo}>
+            <Image
+              src={item?.avatar || iconTeacher}
+              class={styles.viUserLogo}
+            />
+            <span class={[styles.viUserName, 'van-hairline--right']}>
+              {item?.userName ||
+                item?.username ||
+                `游客${item?.teacherId || ''}`}
+            </span>
+            <span class={styles.viUserNum}>{item?.countStudent}人已购买</span>
+          </div>
+          <div class={styles.viPrice}>
+            {item?.lessonPrice > 0 && <>¥{item?.lessonPrice}/</>}
+            {item?.lessonPrice <= 0 &&item?.auditVersion &&<>¥{0}/</>}
+            {item?.lessonPrice <= 0 &&!item?.auditVersion &&<>免费/</>}
+            {item?.lessonCount}课时
+          </div>
+        </div>
+      </div>
+    )
+  }
+})