Browse Source

修改搜索逻辑

wolyshaw 2 years ago
parent
commit
79d7863a68

+ 4 - 0
src/components/col-search/index.module.less

@@ -2,6 +2,10 @@
   .van-search {
     padding-left: 14px;
     padding-right: 14px;
+    input {
+      -webkit-user-select: text !important;
+      user-select: text !important;
+    }
   }
 }
 .col-search {

+ 2 - 0
src/components/col-search/index.tsx

@@ -50,6 +50,7 @@ export default defineComponent({
       default: false
     }
   },
+  emits: ['click'],
   watch: {
     modelValue() {
       this.search = this.modelValue
@@ -79,6 +80,7 @@ export default defineComponent({
             this.search = ''
             this.onSearch()
           }}
+          onClick={() => this.$emit('click')}
           v-slots={{
             left: () => this.$slots.left && this.$slots.left(),
             'left-icon': () => <Icon name={iconSearch} size={16} />,

+ 30 - 5
src/router/routes-student.ts

@@ -114,11 +114,36 @@ export default [
       },
       {
         path: '/music-songbook',
-        component: () => import('@/student/music/songbook'),
-        meta: {
-          title: '乐谱库'
-        }
-      },
+        component: () => import('@/student/music/search/header'),
+        meta: {
+          title: '乐谱顶部'
+        },
+        children: [
+          {
+            path: '/music-songbook/search',
+            name: 'musicSearch',
+            component: () => import('@/student/music/search'),
+            meta: {
+              title: '搜索结果'
+            }
+          },
+          {
+            path: '',
+            name: 'musicSongbook',
+            component: () => import('@/student/music/songbook'),
+            meta: {
+              title: '乐谱库'
+            }
+          }
+        ]
+      },
+      // {
+      //   path: '/music-songbook',
+      //   component: () => import('@/student/music/songbook'),
+      //   meta: {
+      //     title: '乐谱库'
+      //   }
+      // },
       {
         path: '/music-album',
         component: () => import('@/student/music/album/index'),

+ 165 - 0
src/student/music/search/header.tsx

@@ -0,0 +1,165 @@
+import { Sticky, Cell, Tag, Icon, Popup, Tabs, Tab, Dialog } from 'vant'
+import {
+  RouterView,
+  useRouter,
+  useRoute,
+  onBeforeRouteUpdate,
+  onBeforeRouteLeave
+} from 'vue-router'
+import { defineComponent, onMounted, ref, watch } from 'vue'
+import mitt from 'mitt'
+import Search from '@/components/col-search'
+import { useLocalStorage } from '@vueuse/core'
+import styles from './index.module.less'
+import classNames from 'classnames'
+import SelectTag from './select-tag'
+import { getRandomKey, musicBuy } from '../music'
+
+export const mitter = mitt()
+
+const selectTagRef = ref()
+
+export default defineComponent({
+  name: 'MusicSearchHeader',
+  setup() {
+    const searchInputRef = ref()
+    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 = ''
+
+        console.log('onBeforeRouteUpdate')
+        selectTagRef.value.resetTags()
+      }
+    })
+
+    watch(activeTab, val => {
+      mitter.emit('changeTab', val)
+    })
+
+    const onSearch = val => {
+      keyword.value = val
+      const indexOf = words.value.indexOf(val)
+      if (indexOf > -1) {
+        words.value.splice(indexOf, 1)
+      }
+      if (val) {
+        words.value.unshift(val)
+        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)
+
+    onMounted(() => {
+      // const activeRef = activeTab.value === 'album' ? albumList : musicList
+      // ;(activeRef.value as any).onSearch?.('')
+      // console.log(searchInputRef.value)
+    })
+    return () => {
+      return (
+        <div class={styles.search}>
+          <Sticky class={styles.sticky}>
+            <Search
+              modelValue={keyword.value}
+              showAction
+              ref={searchInputRef}
+              onSearch={onSearch}
+              onFilter={() => (tagVisibility.value = true)}
+              filterDot={!!tagids.value}
+              onClick={() => {
+                if (route.path === '/music-songbook') {
+                  router.push({
+                    path: '/music-songbook/search',
+                    query: {
+                      keyword: keyword.value,
+                      tagids: tagids.value
+                    }
+                  })
+                }
+              }}
+            />
+            {route.path === '/music-songbook/search' && (
+              <Tabs
+                color="var(--van-primary)"
+                background="transparent"
+                lineWidth={20}
+                shrink
+                v-model:active={activeTab.value}
+                onChange={val => (activeTab.value = val)}
+              >
+                <Tab title="单曲" name="songe"></Tab>
+                <Tab title="专辑" name="album"></Tab>
+              </Tabs>
+            )}
+          </Sticky>
+          {words.value.length > 0 && route.path === '/music-songbook/search' && (
+            <div class={classNames(styles.keywords, 'van-hairline--bottom')}>
+              <div class={styles.content}>
+                {words.value.map(item => (
+                  <Tag
+                    round
+                    class={styles.searchKeyword}
+                    key={item}
+                    onClick={() => onSearch(item)}
+                  >
+                    {item}
+                  </Tag>
+                ))}
+              </div>
+              <Icon
+                class={styles.remove}
+                name="delete-o"
+                onClick={() => (words.value = [])}
+              />
+            </div>
+          )}
+          <RouterView />
+          <Popup
+            show={tagVisibility.value}
+            round
+            closeable
+            position="bottom"
+            style={{ height: '60%' }}
+            teleport="body"
+            onUpdate:show={val => (tagVisibility.value = val)}
+          >
+            <SelectTag
+              ref={selectTagRef}
+              onConfirm={onComfirm}
+              onCancel={() => {}}
+            />
+          </Popup>
+        </div>
+      )
+    }
+  }
+})

+ 32 - 97
src/student/music/search/index.tsx

@@ -1,33 +1,38 @@
 import { Sticky, Cell, Tag, Icon, Popup, Tabs, Tab, Dialog } from 'vant'
-import { defineComponent, onMounted, ref } from 'vue'
-import Search from '@/components/col-search'
+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 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 { useRouter } from 'vue-router'
+import { useRoute, useRouter } from 'vue-router'
 import { getRandomKey, musicBuy } from '../music'
+import { mitter } from './header'
 
 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('')
-    const tagids = ref('')
+    const keyword = ref(route.query.keyword || '')
+    const tagids = ref(route.query.tagids || '')
     const albumRows = ref([])
     const sheetRows = ref([])
     const tagVisibility = ref(false)
     const words = useLocalStorage<string[]>('music-search', [])
     const activeTab = ref('songe')
+
     const FetchList = async () => {
       // loading.value = true
       // try {
@@ -47,6 +52,7 @@ export default defineComponent({
       // } catch (error) {}
       // loading.value = false
     }
+
     const onSearch = val => {
       keyword.value = val
       const indexOf = words.value.indexOf(val)
@@ -58,6 +64,7 @@ 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()
     }
@@ -74,89 +81,27 @@ export default defineComponent({
     const albumList = ref(null)
     const musicList = ref(null)
 
+    const changeTab = (val: any) => {
+      activeTab.value = val
+    }
+
     onMounted(() => {
-      const activeRef = activeTab.value === 'album' ? albumList : musicList
-      ;(activeRef.value as any).onSearch?.('')
+      mitter.on('changeTab', changeTab)
+      mitter.on('search', onSearch)
+      mitter.on('confirm', onComfirm)
+      // ;(activeRef.value as any).onSearch?.('')
+      // console.log(searchInputRef.value)
+    })
+
+    onUnmounted(() => {
+      mitter.off('changeTab', changeTab)
+      mitter.off('search', onSearch)
+      mitter.off('confirm', onComfirm)
     })
+
     return () => {
       return (
         <div class={styles.search}>
-          <Sticky class={styles.sticky}>
-            <Search
-              modelValue={keyword.value}
-              showAction
-              autofocus
-              onSearch={onSearch}
-              onFilter={() => (tagVisibility.value = true)}
-              filterDot={!!tagids.value}
-            />
-            <Tabs
-              color="var(--van-primary)"
-              background="transparent"
-              lineWidth={20}
-              shrink
-              v-model:active={activeTab.value}
-              onChange={val => (activeTab.value = val)}
-            >
-              <Tab title="单曲" name="songe"></Tab>
-              <Tab title="专辑" name="album"></Tab>
-            </Tabs>
-          </Sticky>
-          {words.value.length > 0 && (
-            <div class={classNames(styles.keywords, 'van-hairline--bottom')}>
-              <div class={styles.content}>
-                {words.value.map(item => (
-                  <Tag
-                    round
-                    class={styles.searchKeyword}
-                    key={item}
-                    onClick={() => onSearch(item)}
-                  >
-                    {item}
-                  </Tag>
-                ))}
-              </div>
-              <Icon
-                class={styles.remove}
-                name="delete-o"
-                onClick={() => (words.value = [])}
-              />
-            </div>
-          )}
-
-          {/* {albumRows.value.length > 0 && (
-            <>
-              <Cell
-                class={styles.title}
-                title="专辑"
-                is-link
-                to={{
-                  path: '/music-album',
-                  query: {
-                    search: keyword.value,
-                    tagids: tagids.value
-                  }
-                }}
-                value="更多"
-              />
-              {albumRows.value.map(item => (
-                <AlbumItem data={item} />
-              ))}
-            </>
-          )} */}
-          {/* <Cell
-            class={styles.title}
-            title="曲谱"
-            is-link
-            to={{
-              path: '/music-list',
-              query: {
-                search: keyword.value,
-                tagids: tagids.value
-              }
-            }}
-            value="更多"
-          /> */}
           {activeTab.value === 'album' ? (
             <AlbumList
               hideSearch
@@ -186,17 +131,7 @@ export default defineComponent({
               }}
             />
           )}
-          {/* {sheetRows.value.map(item => (
-            <MusicItem data={item} />
-          ))} */}
-          {/* {!loading.value && sheetRows.value.length === 0 && (
-            <ColResult
-              tips={activeTab.value === 'album' ? '暂无专辑' : '暂无曲目'}
-              classImgSize="SMALL"
-              btnStatus={false}
-            />
-          )} */}
-          <Popup
+          {/* <Popup
             show={tagVisibility.value}
             round
             closeable
@@ -205,8 +140,8 @@ export default defineComponent({
             teleport="body"
             onUpdate:show={val => (tagVisibility.value = val)}
           >
-            <SelectTag onComfirm={onComfirm} onCancel={() => {}} />
-          </Popup>
+            <SelectTag onConfirm={onComfirm} onCancel={() => {}} />
+          </Popup> */}
         </div>
       )
     }

+ 9 - 11
src/student/music/search/select-tag.tsx

@@ -9,14 +9,6 @@ import styles from './select.module.less'
 export default defineComponent({
   name: 'SelectTag',
   props: {
-    onComfirm: {
-      type: Function,
-      default: () => {}
-    },
-    onCancel: {
-      type: Function,
-      default: () => {}
-    },
     defaultValue: {
       type: String,
       default: ''
@@ -30,7 +22,8 @@ export default defineComponent({
       default: true
     }
   },
-  setup({ onCancel, onComfirm, defaultValue, ...restProps }) {
+  emits: ['cancel', 'confirm'],
+  setup({ defaultValue, ...restProps }, { emit, expose }) {
     const prefix =
       appState.platformType === 'STUDENT' ? '/api-student' : '/api-teacher'
     const { isLoading, state } = useAsyncState(
@@ -43,7 +36,7 @@ export default defineComponent({
           delete tags[key]
         }
       }
-      onCancel()
+      emit('cancel')
     }
 
     const defaultTags = (defaultValue || '').split(',').map(id => Number(id))
@@ -63,6 +56,11 @@ export default defineComponent({
         }
       }
     })
+
+    expose({
+      resetTags
+    })
+
     return () => {
       const list = (state.value && state.value.data) || []
       return (
@@ -98,7 +96,7 @@ export default defineComponent({
               class={styles.btn}
               type="primary"
               round
-              onClick={() => onComfirm(tags, names)}
+              onClick={() => emit('confirm', tags, names)}
             >
               确认
             </Button>

+ 0 - 12
src/student/music/songbook/index.tsx

@@ -1,27 +1,15 @@
 import { defineComponent } from 'vue'
-import { Cell, Sticky } from 'vant'
-import Search from '@/components/col-search'
 import Album from './album'
 import List from './list'
 import styles from './index.module.less'
-import { useRouter } from 'vue-router'
 import { getRandomKey } from '../music'
 
 export default defineComponent({
   name: 'Songbook',
   setup() {
     localStorage.setItem('behaviorId', getRandomKey())
-    const router = useRouter()
     return () => (
       <div class={styles.songbook}>
-        <Sticky
-          class={styles.sticky}
-          onClick={() => {
-            router.push('/music-search')
-          }}
-        >
-          <Search disabled showAction />
-        </Sticky>
         <Album />
         <List />
       </div>