123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- import {
- Sticky,
- Cell,
- Tag,
- Icon,
- Popup,
- Tabs,
- Tab,
- Dialog,
- Button,
- DropdownMenu,
- DropdownItem
- } from 'vant'
- import {
- RouterView,
- useRouter,
- useRoute,
- onBeforeRouteUpdate
- } from 'vue-router'
- import { defineComponent, nextTick, onMounted, reactive, ref, watch } from 'vue'
- import mitt from 'eventemitter3'
- import Search from '@/components/col-search'
- import { useLocalStorage, useThrottleFn } from '@vueuse/core'
- import styles from './index.module.less'
- import classNames from 'classnames'
- import { getRandomKey } from '../music'
- import SelectSubject from './select-subject'
- import { SubjectEnum, useSubjectId } from '@/helpers/hooks'
- import { state } from '@/state'
- import TheSticky from '@/components/the-sticky'
- import bgImg from '../../images/bg-image-search.png'
- import iconSearch from './icon-search.png'
- import request from '@/helpers/request'
- import { browser } from '@/helpers/utils'
- import ColHeader from '@/components/col-header'
- import ColResult from '@/components/col-result'
- import { postMessage } from '@/helpers/native-message'
- export const mitter = new mitt()
- const selectTagRef = ref()
- export const openWebViewOrWeb = (url: string, callback: any) => {
- if (browser().isApp) {
- postMessage({
- api: 'openWebView',
- content: {
- url: url, //`${location.origin}/tenant/#/music-album-detail/${item.id}`,
- orientation: 1,
- isHideTitle: false
- }
- })
- } else {
- // router.push({
- // path: '/music-album-detail/' + item.id
- // })
- callback && callback()
- }
- }
- export default defineComponent({
- name: 'MusicSearchHeader',
- setup() {
- const subjects: any = useSubjectId(SubjectEnum.SEARCH)
- // 判断是否已有数据
- if (!subjects.id) {
- const users = state.user.data
- const subjectId = users.subjectId
- ? Number(users.subjectId.split(',')[0])
- : ''
- const subjectName = users.subjectName
- ? users.subjectName.split(',')[0]
- : ''
- if (subjectId) {
- useSubjectId(
- SubjectEnum.SEARCH,
- JSON.stringify({
- id: subjectId,
- name: subjectName
- }),
- 'set'
- )
- }
- }
- localStorage.setItem('behaviorId', getRandomKey())
- const router = useRouter()
- const route = useRoute()
- const searchResultStatus = ref(false)
- const keyword = ref('')
- const tagids = ref('')
- const words = useLocalStorage<string[]>('music-search', [])
- const activeTab = ref('all')
- if (route.path === '/music-songbook/result') {
- keyword.value = route.query.search as string
- tagids.value = ''
- activeTab.value = 'all'
- }
- onBeforeRouteUpdate((to, form) => {
- const getSubject: any = useSubjectId(SubjectEnum.SEARCH)
- subject.name = getSubject.name || '全部声部'
- subject.id = getSubject.id
- if (route.path === '/music-songbook/search') {
- keyword.value = ''
- tagids.value = ''
- activeTab.value = 'all'
- try {
- selectTagRef.value?.resetTags?.()
- } catch (error) {
- console.log(error)
- }
- }
- if (to.path === '/music-songbook/result') {
- keyword.value = to.query.search as string
- console.log(keyword.value, 'value', route.query)
- tagids.value = ''
- activeTab.value = 'all'
- }
- return true
- })
- watch(activeTab, val => {
- mitter.emit('changeTab', val, keyword.value)
- })
- // 输入时搜索
- const searchList = ref<any>([])
- const onInputSearch = useThrottleFn(async (val: any) => {
- try {
- const { data } = await request.post('/api-student/music/sheet/search', {
- hideLoading: true,
- data: {
- subjectId: subjects.id,
- name: val,
- rows: 10
- }
- })
- const tempMusics = data.musicNames || []
- tempMusics.forEach((item: any, index: number) => {
- if (index < 10) {
- item.name = item.name.replace(val, `<span>${val}</span>`)
- }
- })
- searchList.value = tempMusics
- searchResultStatus.value = keyword.value ? true : false
- } catch {
- //
- }
- }, 300)
- const onSearch = val => {
- console.log('object :>> ', val)
- keyword.value = val
- const indexOf = words.value.indexOf(val)
- if (indexOf > -1) {
- words.value.splice(indexOf, 1)
- }
- if (val) {
- words.value.unshift(val)
- // console.log(words.value.length, 'words.value.length')
- words.value.length = Math.min(words.value.length, 10)
- if (route.path === '/music-songbook/search') defaultClose()
- }
- // mitter.emit('search', val)
- if (route.path !== '/music-songbook/result') {
- router.replace({
- path: '/music-songbook/result',
- query: {
- search: val
- }
- })
- searchResultStatus.value = false
- searchList.value = []
- } else {
- searchResultStatus.value = false
- mitter.emit('search', val)
- }
- }
- const searchRef = ref()
- const onComfirmSubject = (item: any) => {
- // console.log('onSort', item)
- subject.name = item.name
- subject.id = item.id
- searchRef.value.toggle()
- useSubjectId(
- SubjectEnum.SEARCH,
- JSON.stringify({
- id: item.id,
- name: item.name
- }),
- 'set'
- )
- subject.show = false
- mitter.emit('confirmSubject', subject)
- }
- const getSubject: any = useSubjectId(SubjectEnum.SEARCH)
- const subject = reactive({
- show: false,
- name: getSubject.name || '全部声部',
- id: getSubject.id || ''
- })
- const tagRef = ref<any>([])
- const collapse = reactive({
- line: 0,
- arrowStatus: false
- })
- // 历史搜索默认收起
- const defaultClose = () => {
- nextTick(() => {
- if (!words.value || !words.value.length) {
- return
- }
- let offsetLeft = -1
- collapse.line = 0
- const tags = tagRef.value
- tags.forEach((item: any, index: number) => {
- try {
- item.$el.style.display = 'block'
- if (index === 0) {
- collapse.line = 1
- offsetLeft = item.$el.offsetLeft
- } else if (item.$el.offsetLeft === offsetLeft && index != 0) {
- // 如果某个标签的offsetLeft和第一个标签的offsetLeft相等 说明增加了一行
- collapse.line += 1
- }
- if (!collapse.arrowStatus) {
- if (collapse.line > 2) {
- //从第3行开始 隐藏标签
- item.$el.style.display = 'none'
- } else {
- item.$el.style.display = 'block'
- }
- } else {
- item.$el.style.display = 'block'
- }
- } catch (e: any) {
- console.log(e, 'Error')
- }
- })
- })
- }
- // 首先调用默认收起的方法
- if (route.path === '/music-songbook/search') defaultClose()
- onMounted(() => {
- postMessage({
- api: 'backIconChange',
- content: { backIconHide: true }
- })
- })
- return () => {
- return (
- <div class={styles.search}>
- <div class={styles.sticky}>
- <TheSticky position="top">
- <ColHeader isFixed={false} background="transparent" title=" " />
- <Search
- modelValue={keyword.value}
- background="transparent"
- showAction
- onInput={(val: any) => {
- keyword.value = val
- if (val) {
- onInputSearch(val)
- } else {
- searchList.value = []
- searchResultStatus.value = false
- if (route.path === '/music-songbook/result') {
- router.replace('/music-songbook/search')
- }
- }
- }}
- onSearch={(val: any) => {
- if (!val) return
- keyword.value = val
- console.log(val, 'val')
- onSearch(val)
- // searchResultStatus.value = true
- }}
- type="tenant"
- v-slots={{
- left: () => (
- // <div
- // class={styles.label}
- // onClick={() => (subject.show = true)}
- // >
- // {subject.name}
- // <Icon
- // classPrefix="iconfont"
- // name="down"
- // size={12}
- // color="#333"
- // />
- // </div>
- <DropdownMenu>
- <DropdownItem
- titleClass={styles.titleActive}
- title="筛选"
- ref={searchRef}
- >
- <SelectSubject
- searchParams={subject}
- onComfirm={onComfirmSubject}
- />
- </DropdownItem>
- </DropdownMenu>
- ),
- action: () => (
- <span
- class={styles.searchCancel}
- onClick={() => {
- if (browser().isApp) {
- postMessage({ api: 'back' })
- } else {
- router.back()
- }
- }}
- >
- 取消
- </span>
- )
- }}
- />
- {route.path === '/music-songbook/result' &&
- !searchResultStatus.value && (
- <Tabs
- color="var(--van-primary)"
- background="transparent"
- lineWidth={20}
- shrink
- class={styles.tagTabs}
- v-model:active={activeTab.value}
- onChange={val => (activeTab.value = val)}
- >
- <Tab title="综合" name="all"></Tab>
- <Tab title="单曲" name="songe"></Tab>
- <Tab title="专辑" name="album"></Tab>
- </Tabs>
- )}
- </TheSticky>
- <img class={styles.bgImg} src={bgImg} />
- </div>
- {words.value.length > 0 && route.path === '/music-songbook/search' && (
- <div class={styles.keywordSection}>
- <div class={styles.keywordTitle}>
- <span class={styles.t}>搜索历史</span>
- <Icon
- class={styles.remove}
- name="delete-o"
- onClick={() => (words.value = [])}
- />
- </div>
- <div class={classNames(styles.keywords)}>
- <div class={styles.content}>
- {words.value.map((item: any, index: number) => (
- <Tag
- ref={(el: any) => (tagRef.value[index] = el)}
- round
- class={[styles.searchKeyword, 'van-ellipsis']}
- key={item}
- onClick={() => {
- keyword.value = item
- onSearch(item)
- }}
- >
- {item}
- </Tag>
- ))}
- {collapse.line > 2 && (
- <span
- class={[styles.arrowMore]}
- onClick={() => {
- collapse.arrowStatus = !collapse.arrowStatus
- defaultClose()
- }}
- >
- <Icon
- name={collapse.arrowStatus ? 'arrow-up' : 'arrow-down'}
- />
- </span>
- )}
- </div>
- </div>
- </div>
- )}
- {route.path === '/music-songbook/search' && (
- <Tabs
- color="var(--van-primary)"
- background="transparent"
- lineWidth={20}
- shrink
- class={styles.tagTabs}
- v-model:active={activeTab.value}
- onChange={val => (activeTab.value = val)}
- >
- <Tab title="综合" name="all"></Tab>
- <Tab title="单曲" name="songe"></Tab>
- <Tab title="专辑" name="album"></Tab>
- </Tabs>
- )}
- <RouterView />
- {/* 声部弹框 */}
- {/* <Popup
- show={subject.show}
- position="bottom"
- round
- closeable
- safe-area-inset-bottom
- onClose={() => (subject.show = false)}
- onClosed={() => (subject.show = false)}
- >
- <SelectSubject
- searchParams={subject}
- onComfirm={onComfirmSubject}
- />
- </Popup> */}
- <div
- class={[styles.searchResult]}
- style={{ display: searchResultStatus.value ? 'block' : 'none' }}
- >
- <div class={styles.searchGroups}>
- {searchList.value.map((item: any) => (
- <div
- class={styles.searchItem}
- onClick={() => {
- if (item.type === 'ALBUM') {
- openWebViewOrWeb(
- `${location.origin}/tenant/#/music-album-detail/${item.id}`,
- () => {
- router.push({
- path: '/music-album-detail/' + item.id
- })
- }
- )
- } else {
- openWebViewOrWeb(
- `${location.origin}/tenant/#/music-detail?id=${item.id}`,
- () => {
- router.push({
- path: '/music-detail',
- query: {
- id: item.id
- }
- })
- }
- )
- }
- }}
- >
- <img src={iconSearch} class={styles.iconSearch} />
- <span class={styles.rName} v-html={item.name}></span>
- </div>
- ))}
- {searchList.value.length <= 0 && (
- <ColResult tips="暂无搜索结果" btnStatus={false} />
- )}
- </div>
- </div>
- </div>
- )
- }
- }
- })
|