Showing
8 changed files
with
222 additions
and
11 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2022-05-26 19:50:27 | 2 | * @Date: 2022-05-26 19:50:27 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2022-06-18 00:15:08 | 4 | + * @LastEditTime: 2024-12-03 11:23:55 |
| 5 | * @FilePath: /tswj/src/api/C/book.js | 5 | * @FilePath: /tswj/src/api/C/book.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -10,6 +10,7 @@ import { fn, fetch } from '@/api/fn'; | ... | @@ -10,6 +10,7 @@ import { fn, fetch } from '@/api/fn'; |
| 10 | const Api = { | 10 | const Api = { |
| 11 | ADD_SUBSCRIBE: '/srv/?a=add_subscribe', | 11 | ADD_SUBSCRIBE: '/srv/?a=add_subscribe', |
| 12 | BOOK_INFO: '/srv/?a=book_info', | 12 | BOOK_INFO: '/srv/?a=book_info', |
| 13 | + PROD_LIST: '/srv/?a=prod_list', | ||
| 13 | } | 14 | } |
| 14 | 15 | ||
| 15 | /** | 16 | /** |
| ... | @@ -28,3 +29,14 @@ export const addSubscribeAPI = (params) => fn(fetch.post(Api.ADD_SUBSCRIBE, para | ... | @@ -28,3 +29,14 @@ export const addSubscribeAPI = (params) => fn(fetch.post(Api.ADD_SUBSCRIBE, para |
| 28 | * @returns | 29 | * @returns |
| 29 | */ | 30 | */ |
| 30 | export const bookInfoAPI = (params) => fn(fetch.get(Api.BOOK_INFO, params)); | 31 | export const bookInfoAPI = (params) => fn(fetch.get(Api.BOOK_INFO, params)); |
| 32 | + | ||
| 33 | +/** | ||
| 34 | + * @description: 作品列表 | ||
| 35 | + * @param {String} book_id 书籍 ID | ||
| 36 | + * @param {String} localism_type 方言类型 | ||
| 37 | + * @param {String} performer_name 搜索表演者姓名 | ||
| 38 | + * @param {*} limit | ||
| 39 | + * @param {*} offset | ||
| 40 | + * @returns | ||
| 41 | + */ | ||
| 42 | +export const prodListAPI = (params) => fn(fetch.get(Api.PROD_LIST, params)); | ... | ... |
src/assets/images/icon-search@2x.png
0 → 100644
5.32 KB
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2022-05-11 11:19:14 | 2 | * @Date: 2022-05-11 11:19:14 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2024-11-13 15:39:03 | 4 | + * @LastEditTime: 2024-12-03 15:07:53 |
| 5 | * @FilePath: /tswj/src/components/ShortcutFixed/index.vue | 5 | * @FilePath: /tswj/src/components/ShortcutFixed/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -37,12 +37,35 @@ | ... | @@ -37,12 +37,35 @@ |
| 37 | </div> | 37 | </div> |
| 38 | </template> | 38 | </template> |
| 39 | </van-popover> | 39 | </van-popover> |
| 40 | + <van-image v-if="isSearch" class="icon-box" :src="icon_search" @click="toSearch" /> | ||
| 40 | </div> | 41 | </div> |
| 41 | </template> | 42 | </template> |
| 42 | 43 | ||
| 43 | <script setup> | 44 | <script setup> |
| 44 | import Cookies from 'js-cookie' | 45 | import Cookies from 'js-cookie' |
| 45 | -import { icon_me, icon_home, icon_rank, icon_contact } from '@/utils/generateIcons.js' | 46 | +import { icon_me, icon_home, icon_rank, icon_contact, icon_search } from '@/utils/generateIcons.js' |
| 47 | +import { useRoute, useRouter } from 'vue-router' | ||
| 48 | +import { killPages, store } from '@/hooks/useKeepAlive'; | ||
| 49 | + | ||
| 50 | +// 删除所有的 keep-alive 缓存 | ||
| 51 | +killPages(); | ||
| 52 | +// 清空记录位置 | ||
| 53 | +store.changeScrollTop(0); | ||
| 54 | + | ||
| 55 | +const $route = useRoute(); | ||
| 56 | +const $router = useRouter(); | ||
| 57 | + | ||
| 58 | +const toSearch = () => { | ||
| 59 | + // 清空记录位置 | ||
| 60 | + store.changeScrollTop(0); | ||
| 61 | + $router.push({ | ||
| 62 | + path: '/client/searchPage', | ||
| 63 | + query: { | ||
| 64 | + book_id: $route.query.id, | ||
| 65 | + kg_id: $route.query.kg_id | ||
| 66 | + } | ||
| 67 | + }); | ||
| 68 | + } | ||
| 46 | </script> | 69 | </script> |
| 47 | 70 | ||
| 48 | <script> | 71 | <script> |
| ... | @@ -67,6 +90,9 @@ export default { | ... | @@ -67,6 +90,9 @@ export default { |
| 67 | isRank() { | 90 | isRank() { |
| 68 | return this.item.indexOf('rank') !== -1 ? true : false | 91 | return this.item.indexOf('rank') !== -1 ? true : false |
| 69 | }, | 92 | }, |
| 93 | + isSearch() { | ||
| 94 | + return this.item.indexOf('search') !== -1 ? true : false | ||
| 95 | + }, | ||
| 70 | }, | 96 | }, |
| 71 | mounted() { | 97 | mounted() { |
| 72 | }, | 98 | }, | ... | ... |
| 1 | <template> | 1 | <template> |
| 2 | <div class="video-wrapper"> | 2 | <div class="video-wrapper"> |
| 3 | - <div :id="'mui-player-' + item.id" class="video-div" /> | 3 | + <div :id="'mui-player-' + item.id + affix" class="video-div" /> |
| 4 | <div class="normal-module"> | 4 | <div class="normal-module"> |
| 5 | <div class="video-bar"> | 5 | <div class="video-bar"> |
| 6 | <van-row> | 6 | <van-row> |
| ... | @@ -43,6 +43,7 @@ import MuiPlayer from 'mui-player' | ... | @@ -43,6 +43,7 @@ import MuiPlayer from 'mui-player' |
| 43 | import { prodActionAPI, prodInfoAPI } from '@/api/C/prod.js' | 43 | import { prodActionAPI, prodInfoAPI } from '@/api/C/prod.js' |
| 44 | import { useDebounce } from '@/hooks/useDebounce.js' | 44 | import { useDebounce } from '@/hooks/useDebounce.js' |
| 45 | import { DEFAULT_COVER } from '@/constant' | 45 | import { DEFAULT_COVER } from '@/constant' |
| 46 | +import { v4 as uuidv4 } from 'uuid'; | ||
| 46 | 47 | ||
| 47 | const $router = useRouter(); | 48 | const $router = useRouter(); |
| 48 | const props = defineProps({ | 49 | const props = defineProps({ |
| ... | @@ -85,10 +86,11 @@ const getProductDetail = async (action_type, prod_id) => { | ... | @@ -85,10 +86,11 @@ const getProductDetail = async (action_type, prod_id) => { |
| 85 | } | 86 | } |
| 86 | 87 | ||
| 87 | let detail = ref({}); | 88 | let detail = ref({}); |
| 89 | +let affix = uuidv4(); | ||
| 88 | 90 | ||
| 89 | onMounted(() => { | 91 | onMounted(() => { |
| 90 | const mp = new MuiPlayer({ | 92 | const mp = new MuiPlayer({ |
| 91 | - container: '#mui-player-' + props.item.id, | 93 | + container: '#mui-player-' + props.item.id + affix, |
| 92 | title: props.item.title, | 94 | title: props.item.title, |
| 93 | src: props.item.video, | 95 | src: props.item.video, |
| 94 | poster: props.item.cover ? props.item.cover : DEFAULT_COVER, | 96 | poster: props.item.cover ? props.item.cover : DEFAULT_COVER, |
| ... | @@ -107,9 +109,9 @@ onMounted(() => { | ... | @@ -107,9 +109,9 @@ onMounted(() => { |
| 107 | handleAction('play', props.item.id) | 109 | handleAction('play', props.item.id) |
| 108 | }); | 110 | }); |
| 109 | // 配置16:9高度比 | 111 | // 配置16:9高度比 |
| 110 | - const width = document.getElementById('mui-player-' + props.item.id).clientWidth; | 112 | + const width = document.getElementById('mui-player-' + props.item.id + affix).clientWidth; |
| 111 | const height = (width * 9) / 16; | 113 | const height = (width * 9) / 16; |
| 112 | - document.getElementById('mui-player-' + props.item.id).height = height; | 114 | + document.getElementById('mui-player-' + props.item.id + affix).height = height; |
| 113 | }); | 115 | }); |
| 114 | 116 | ||
| 115 | const goTo = () => { // 跳转作品详情页 | 117 | const goTo = () => { // 跳转作品详情页 | ... | ... |
| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2022-05-25 18:03:54 | 3 | * @Date: 2022-05-25 18:03:54 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2022-05-31 17:42:23 | 5 | + * @LastEditTime: 2024-12-03 14:54:21 |
| 6 | * @FilePath: /tswj/src/router/routes/modules/client/index.js | 6 | * @FilePath: /tswj/src/router/routes/modules/client/index.js |
| 7 | * @Description: 家长端展示页路由表 | 7 | * @Description: 家长端展示页路由表 |
| 8 | */ | 8 | */ |
| ... | @@ -90,6 +90,15 @@ const index = [{ | ... | @@ -90,6 +90,15 @@ const index = [{ |
| 90 | name: 'personIndex' | 90 | name: 'personIndex' |
| 91 | }, | 91 | }, |
| 92 | children: [] | 92 | children: [] |
| 93 | +}, { | ||
| 94 | + path: '/client/searchPage', | ||
| 95 | + name: '搜索页面', | ||
| 96 | + component: () => import('@/views/client/searchPage.vue'), | ||
| 97 | + meta: { | ||
| 98 | + title: '搜索页面', | ||
| 99 | + name: 'searchPage' | ||
| 100 | + }, | ||
| 101 | + children: [] | ||
| 93 | }] | 102 | }] |
| 94 | 103 | ||
| 95 | export default index; | 104 | export default index; | ... | ... |
| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2022-05-17 11:34:35 | 3 | * @Date: 2022-05-17 11:34:35 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2024-11-13 15:32:45 | 5 | + * @LastEditTime: 2024-12-03 15:07:35 |
| 6 | * @FilePath: /tswj/src/utils/generateIcons.js | 6 | * @FilePath: /tswj/src/utils/generateIcons.js |
| 7 | * @Description: 图标集合 | 7 | * @Description: 图标集合 |
| 8 | */ | 8 | */ |
| ... | @@ -31,6 +31,7 @@ import icon_flower from '@images/xiaohua@2x.png' | ... | @@ -31,6 +31,7 @@ import icon_flower from '@images/xiaohua@2x.png' |
| 31 | import icon_refuse from '@images/icon-jujue@2x.png' | 31 | import icon_refuse from '@images/icon-jujue@2x.png' |
| 32 | import icon_apply from '@images/icon-shenhe@2x.png' | 32 | import icon_apply from '@images/icon-shenhe@2x.png' |
| 33 | import icon_enable from '@images/icon-tongguo@2x.png' | 33 | import icon_enable from '@images/icon-tongguo@2x.png' |
| 34 | +import icon_search from '@images/icon-search@2x.png' | ||
| 34 | 35 | ||
| 35 | export { | 36 | export { |
| 36 | icon_video, | 37 | icon_video, |
| ... | @@ -58,4 +59,5 @@ export { | ... | @@ -58,4 +59,5 @@ export { |
| 58 | icon_refuse, | 59 | icon_refuse, |
| 59 | icon_apply, | 60 | icon_apply, |
| 60 | icon_enable, | 61 | icon_enable, |
| 62 | + icon_search, | ||
| 61 | } | 63 | } | ... | ... |
| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2022-05-21 09:35:14 | 3 | * @Date: 2022-05-21 09:35:14 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2024-11-27 09:39:44 | 5 | + * @LastEditTime: 2024-12-03 15:02:57 |
| 6 | * @FilePath: /tswj/src/views/client/bookDetail.vue | 6 | * @FilePath: /tswj/src/views/client/bookDetail.vue |
| 7 | * @Description: | 7 | * @Description: |
| 8 | --> | 8 | --> |
| ... | @@ -105,7 +105,7 @@ | ... | @@ -105,7 +105,7 @@ |
| 105 | <my-button type="primary" @on-click="showDonate=true">为活动助力</my-button> | 105 | <my-button type="primary" @on-click="showDonate=true">为活动助力</my-button> |
| 106 | </div> | 106 | </div> |
| 107 | </div> | 107 | </div> |
| 108 | - <shortcut-fixed :type="USER_ROLE.CLIENT" :item="['home', 'me']" :custom-style="customStyle" /> | 108 | + <shortcut-fixed :type="USER_ROLE.CLIENT" :item="['home', 'me', 'search']" :custom-style="customStyle" /> |
| 109 | </div> | 109 | </div> |
| 110 | 110 | ||
| 111 | <!-- 上传时,如果没有默认儿童提示弹框, 如果没有实名认证提示弹框 --> | 111 | <!-- 上传时,如果没有默认儿童提示弹框, 如果没有实名认证提示弹框 --> | ... | ... |
src/views/client/searchPage.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-12-03 10:35:15 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-12-03 15:15:45 | ||
| 5 | + * @FilePath: /tswj/src/views/client/searchPage.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="search-page"> | ||
| 10 | + <div style="background-color: #F7F7F7; height: auto; padding: 1rem;"> | ||
| 11 | + <div style="background-color: #FFF; border-radius: 1rem; padding: 0.5rem 1rem; display: flex; align-items: center; justify-content: space-between;"> | ||
| 12 | + <input type="text" v-model="performer_name" placeholder="请输入要搜索的表演者姓名" @blur="onSearch" style="border: 0; width: 100%;"> | ||
| 13 | + <van-icon name="search" /> | ||
| 14 | + </div> | ||
| 15 | + </div> | ||
| 16 | + <div class="book-video-list"> | ||
| 17 | + <!-- <van-list ref="listRef" v-model:loading="loading" :finished="finished" :finished-text="finishedTextStatus ? '没有更多了' : ''" | ||
| 18 | + @load="onLoad" :immediate-check="immediateCheck"> --> | ||
| 19 | + <template v-for="item in search_prod_list" :key="item"> | ||
| 20 | + <video-card :item="item"> | ||
| 21 | + <template #bookDetailSub> | ||
| 22 | + <div style="color: #999999; padding: 0px 1rem 0.5rem;" @click="setComment(item)"> | ||
| 23 | + {{ item.kg_name }} | {{ item.localism_type }} | ||
| 24 | + </div> | ||
| 25 | + </template> | ||
| 26 | + </video-card> | ||
| 27 | + </template> | ||
| 28 | + <!-- </van-list> --> | ||
| 29 | + </div> | ||
| 30 | + <div style="height: 2rem;" /> | ||
| 31 | + <van-empty v-if="emptyStatus" class="custom-image" :image="no_image" description="暂无作品信息" /> | ||
| 32 | + </div> | ||
| 33 | +</template> | ||
| 34 | + | ||
| 35 | +<script setup> | ||
| 36 | +import { ref } from 'vue' | ||
| 37 | +import { useRoute, useRouter } from 'vue-router' | ||
| 38 | + | ||
| 39 | +import { Cookies, $, _, axios, storeToRefs, mainStore, useTitle } from '@/utils/generatePackage.js' | ||
| 40 | +//import { } from '@/utils/generateModules.js' | ||
| 41 | +import { no_image } from '@/utils/generateIcons.js' | ||
| 42 | +//import { } from '@/composables' | ||
| 43 | +import { VideoCard } from '@/utils/generateModules' | ||
| 44 | +import { prodListAPI } from '@/api/C/book' | ||
| 45 | +import { killPages, store } from '@/hooks/useKeepAlive'; | ||
| 46 | + | ||
| 47 | +killPages() | ||
| 48 | +const $route = useRoute(); | ||
| 49 | +const $router = useRouter(); | ||
| 50 | +console.warn($route.meta.title); | ||
| 51 | +useTitle($route.meta.title); | ||
| 52 | + | ||
| 53 | +const search_prod_list = ref([]); | ||
| 54 | +const limit = ref(10) | ||
| 55 | +const offset = ref(0) | ||
| 56 | + | ||
| 57 | +// 处理书籍下作品列表 | ||
| 58 | +const loading = ref(false); | ||
| 59 | +const finished = ref(false); | ||
| 60 | +const immediateCheck = ref(false); | ||
| 61 | + | ||
| 62 | +// 因为不能让空图标提前出来的写法 | ||
| 63 | +const finishedTextStatus = ref(false); | ||
| 64 | +const emptyStatus = ref(false); | ||
| 65 | + | ||
| 66 | +const book_id = $route.query.book_id; | ||
| 67 | +const kg_id = $route.query.kg_id; | ||
| 68 | + | ||
| 69 | + | ||
| 70 | +// 定义一个变量来表示是否滚动到底部 | ||
| 71 | +const isBottom = ref(false); | ||
| 72 | + | ||
| 73 | +// 标记是否是第一次进入页面 | ||
| 74 | +const isFirstMount = ref(true); | ||
| 75 | + | ||
| 76 | +// 滚动事件处理函数,这里添加了触发回调的逻辑 | ||
| 77 | +const handleScroll = () => { | ||
| 78 | + const scrollTop = window.scrollY; // 当前滚动距离 | ||
| 79 | + const clientHeight = document.documentElement.clientHeight; // 视口高度 | ||
| 80 | + const scrollHeight = document.documentElement.scrollHeight; // 页面总高度 | ||
| 81 | + | ||
| 82 | + if (scrollTop + clientHeight >= scrollHeight) { | ||
| 83 | + // 在这里触发你的回调逻辑 | ||
| 84 | + if (performer_name.value) { | ||
| 85 | + onLoad() | ||
| 86 | + } | ||
| 87 | + } | ||
| 88 | +}; | ||
| 89 | + | ||
| 90 | +// 在组件挂载时添加滚动事件监听,并将第一次进入页面的标记设为false | ||
| 91 | +onMounted(() => { | ||
| 92 | + window.addEventListener('scroll', handleScroll); | ||
| 93 | +}); | ||
| 94 | + | ||
| 95 | +// 在组件卸载时移除滚动事件监听 | ||
| 96 | +onUnmounted(() => { | ||
| 97 | + window.removeEventListener('scroll', handleScroll); | ||
| 98 | +}); | ||
| 99 | + | ||
| 100 | +const performer_name = ref(''); | ||
| 101 | + | ||
| 102 | +/** | ||
| 103 | + * 向下滚动查询数据 | ||
| 104 | + */ | ||
| 105 | +const onLoad = async () => { | ||
| 106 | + // 异步更新数据 | ||
| 107 | + const { data, code } = await prodListAPI({ book_id, kg_id, limit: limit.value, offset: offset.value, performer_name: performer_name.value }) | ||
| 108 | + if (code === 1) { | ||
| 109 | + search_prod_list.value = _.concat(search_prod_list.value, data.prod_list); | ||
| 110 | + search_prod_list.value = _.uniqBy(search_prod_list.value, 'id'); | ||
| 111 | + offset.value = search_prod_list.value.length; | ||
| 112 | + loading.value = false; | ||
| 113 | + // 数据全部加载完成 | ||
| 114 | + if (!data.prod_list.length) { | ||
| 115 | + // 加载状态结束 | ||
| 116 | + finished.value = true; | ||
| 117 | + } | ||
| 118 | + // 空数据提示 | ||
| 119 | + if (!search_prod_list.value.length) { | ||
| 120 | + finishedTextStatus.value = false; | ||
| 121 | + } | ||
| 122 | + emptyStatus.value = Object.is(search_prod_list.value.length, 0); | ||
| 123 | + } | ||
| 124 | +}; | ||
| 125 | + | ||
| 126 | +const onSearch = async() => { | ||
| 127 | + offset.value = 0 | ||
| 128 | + search_prod_list.value = [] | ||
| 129 | + loading.value = true; | ||
| 130 | + finished.value = false; | ||
| 131 | + onLoad() | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +</script> | ||
| 135 | + | ||
| 136 | +<style lang="less" scoped> | ||
| 137 | + | ||
| 138 | +.bottom-btn { | ||
| 139 | + position: fixed; | ||
| 140 | + bottom: 0; | ||
| 141 | + left: 0; | ||
| 142 | + right: 0; | ||
| 143 | + background-color: white; | ||
| 144 | + box-shadow: 0px -2px 4px 0px rgba(0, 0, 0, 0.07); | ||
| 145 | + z-index: 9999; | ||
| 146 | + | ||
| 147 | + .text { | ||
| 148 | + text-align: center; | ||
| 149 | + padding: 0.7rem; | ||
| 150 | + margin: 0.8rem; | ||
| 151 | + font-size: 1rem; | ||
| 152 | + font-weight: bold; | ||
| 153 | + border-radius: 24px; | ||
| 154 | + // border: 1px solid F7F7F7; | ||
| 155 | + color: @base-font-color; | ||
| 156 | + background-color: @base-color; | ||
| 157 | + box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.06); | ||
| 158 | + } | ||
| 159 | +} | ||
| 160 | +</style> |
-
Please register or login to post a comment