hookehuyr

✨ feat: 新增搜索页面

/*
* @Date: 2022-05-26 19:50:27
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-06-18 00:15:08
* @LastEditTime: 2024-12-03 11:23:55
* @FilePath: /tswj/src/api/C/book.js
* @Description: 文件描述
*/
......@@ -10,12 +10,13 @@ import { fn, fetch } from '@/api/fn';
const Api = {
ADD_SUBSCRIBE: '/srv/?a=add_subscribe',
BOOK_INFO: '/srv/?a=book_info',
PROD_LIST: '/srv/?a=prod_list',
}
/**
* @description: 订阅书籍操作
* @param {String} book_id 书籍 ID
* @returns
* @returns
*/
export const addSubscribeAPI = (params) => fn(fetch.post(Api.ADD_SUBSCRIBE, params));
......@@ -25,6 +26,17 @@ export const addSubscribeAPI = (params) => fn(fetch.post(Api.ADD_SUBSCRIBE, para
* @param {String} localism_type 方言类型
* @param {*} limit
* @param {*} offset
* @returns
* @returns
*/
export const bookInfoAPI = (params) => fn(fetch.get(Api.BOOK_INFO, params));
/**
* @description: 作品列表
* @param {String} book_id 书籍 ID
* @param {String} localism_type 方言类型
* @param {String} performer_name 搜索表演者姓名
* @param {*} limit
* @param {*} offset
* @returns
*/
export const prodListAPI = (params) => fn(fetch.get(Api.PROD_LIST, params));
......
<!--
* @Date: 2022-05-11 11:19:14
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-11-13 15:39:03
* @LastEditTime: 2024-12-03 15:07:53
* @FilePath: /tswj/src/components/ShortcutFixed/index.vue
* @Description: 文件描述
-->
......@@ -37,12 +37,35 @@
</div>
</template>
</van-popover>
<van-image v-if="isSearch" class="icon-box" :src="icon_search" @click="toSearch" />
</div>
</template>
<script setup>
import Cookies from 'js-cookie'
import { icon_me, icon_home, icon_rank, icon_contact } from '@/utils/generateIcons.js'
import { icon_me, icon_home, icon_rank, icon_contact, icon_search } from '@/utils/generateIcons.js'
import { useRoute, useRouter } from 'vue-router'
import { killPages, store } from '@/hooks/useKeepAlive';
// 删除所有的 keep-alive 缓存
killPages();
// 清空记录位置
store.changeScrollTop(0);
const $route = useRoute();
const $router = useRouter();
const toSearch = () => {
// 清空记录位置
store.changeScrollTop(0);
$router.push({
path: '/client/searchPage',
query: {
book_id: $route.query.id,
kg_id: $route.query.kg_id
}
});
}
</script>
<script>
......@@ -67,6 +90,9 @@ export default {
isRank() {
return this.item.indexOf('rank') !== -1 ? true : false
},
isSearch() {
return this.item.indexOf('search') !== -1 ? true : false
},
},
mounted() {
},
......
<template>
<div class="video-wrapper">
<div :id="'mui-player-' + item.id" class="video-div" />
<div :id="'mui-player-' + item.id + affix" class="video-div" />
<div class="normal-module">
<div class="video-bar">
<van-row>
......@@ -43,6 +43,7 @@ import MuiPlayer from 'mui-player'
import { prodActionAPI, prodInfoAPI } from '@/api/C/prod.js'
import { useDebounce } from '@/hooks/useDebounce.js'
import { DEFAULT_COVER } from '@/constant'
import { v4 as uuidv4 } from 'uuid';
const $router = useRouter();
const props = defineProps({
......@@ -85,10 +86,11 @@ const getProductDetail = async (action_type, prod_id) => {
}
let detail = ref({});
let affix = uuidv4();
onMounted(() => {
const mp = new MuiPlayer({
container: '#mui-player-' + props.item.id,
container: '#mui-player-' + props.item.id + affix,
title: props.item.title,
src: props.item.video,
poster: props.item.cover ? props.item.cover : DEFAULT_COVER,
......@@ -107,9 +109,9 @@ onMounted(() => {
handleAction('play', props.item.id)
});
// 配置16:9高度比
const width = document.getElementById('mui-player-' + props.item.id).clientWidth;
const width = document.getElementById('mui-player-' + props.item.id + affix).clientWidth;
const height = (width * 9) / 16;
document.getElementById('mui-player-' + props.item.id).height = height;
document.getElementById('mui-player-' + props.item.id + affix).height = height;
});
const goTo = () => { // 跳转作品详情页
......
......@@ -2,7 +2,7 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-25 18:03:54
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2022-05-31 17:42:23
* @LastEditTime: 2024-12-03 14:54:21
* @FilePath: /tswj/src/router/routes/modules/client/index.js
* @Description: 家长端展示页路由表
*/
......@@ -90,6 +90,15 @@ const index = [{
name: 'personIndex'
},
children: []
}, {
path: '/client/searchPage',
name: '搜索页面',
component: () => import('@/views/client/searchPage.vue'),
meta: {
title: '搜索页面',
name: 'searchPage'
},
children: []
}]
export default index;
......
......@@ -2,7 +2,7 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-17 11:34:35
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-11-13 15:32:45
* @LastEditTime: 2024-12-03 15:07:35
* @FilePath: /tswj/src/utils/generateIcons.js
* @Description: 图标集合
*/
......@@ -31,6 +31,7 @@ import icon_flower from '@images/xiaohua@2x.png'
import icon_refuse from '@images/icon-jujue@2x.png'
import icon_apply from '@images/icon-shenhe@2x.png'
import icon_enable from '@images/icon-tongguo@2x.png'
import icon_search from '@images/icon-search@2x.png'
export {
icon_video,
......@@ -58,4 +59,5 @@ export {
icon_refuse,
icon_apply,
icon_enable,
icon_search,
}
......
......@@ -2,7 +2,7 @@
* @Author: hookehuyr hookehuyr@gmail.com
* @Date: 2022-05-21 09:35:14
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-11-27 09:39:44
* @LastEditTime: 2024-12-03 15:02:57
* @FilePath: /tswj/src/views/client/bookDetail.vue
* @Description:
-->
......@@ -105,7 +105,7 @@
<my-button type="primary" @on-click="showDonate=true">为活动助力</my-button>
</div>
</div>
<shortcut-fixed :type="USER_ROLE.CLIENT" :item="['home', 'me']" :custom-style="customStyle" />
<shortcut-fixed :type="USER_ROLE.CLIENT" :item="['home', 'me', 'search']" :custom-style="customStyle" />
</div>
<!-- 上传时,如果没有默认儿童提示弹框, 如果没有实名认证提示弹框 -->
......
<!--
* @Date: 2024-12-03 10:35:15
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-12-03 15:15:45
* @FilePath: /tswj/src/views/client/searchPage.vue
* @Description: 文件描述
-->
<template>
<div class="search-page">
<div style="background-color: #F7F7F7; height: auto; padding: 1rem;">
<div style="background-color: #FFF; border-radius: 1rem; padding: 0.5rem 1rem; display: flex; align-items: center; justify-content: space-between;">
<input type="text" v-model="performer_name" placeholder="请输入要搜索的表演者姓名" @blur="onSearch" style="border: 0; width: 100%;">
<van-icon name="search" />
</div>
</div>
<div class="book-video-list">
<!-- <van-list ref="listRef" v-model:loading="loading" :finished="finished" :finished-text="finishedTextStatus ? '没有更多了' : ''"
@load="onLoad" :immediate-check="immediateCheck"> -->
<template v-for="item in search_prod_list" :key="item">
<video-card :item="item">
<template #bookDetailSub>
<div style="color: #999999; padding: 0px 1rem 0.5rem;" @click="setComment(item)">
{{ item.kg_name }} | {{ item.localism_type }}
</div>
</template>
</video-card>
</template>
<!-- </van-list> -->
</div>
<div style="height: 2rem;" />
<van-empty v-if="emptyStatus" class="custom-image" :image="no_image" description="暂无作品信息" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Cookies, $, _, axios, storeToRefs, mainStore, useTitle } from '@/utils/generatePackage.js'
//import { } from '@/utils/generateModules.js'
import { no_image } from '@/utils/generateIcons.js'
//import { } from '@/composables'
import { VideoCard } from '@/utils/generateModules'
import { prodListAPI } from '@/api/C/book'
import { killPages, store } from '@/hooks/useKeepAlive';
killPages()
const $route = useRoute();
const $router = useRouter();
console.warn($route.meta.title);
useTitle($route.meta.title);
const search_prod_list = ref([]);
const limit = ref(10)
const offset = ref(0)
// 处理书籍下作品列表
const loading = ref(false);
const finished = ref(false);
const immediateCheck = ref(false);
// 因为不能让空图标提前出来的写法
const finishedTextStatus = ref(false);
const emptyStatus = ref(false);
const book_id = $route.query.book_id;
const kg_id = $route.query.kg_id;
// 定义一个变量来表示是否滚动到底部
const isBottom = ref(false);
// 标记是否是第一次进入页面
const isFirstMount = ref(true);
// 滚动事件处理函数,这里添加了触发回调的逻辑
const handleScroll = () => {
const scrollTop = window.scrollY; // 当前滚动距离
const clientHeight = document.documentElement.clientHeight; // 视口高度
const scrollHeight = document.documentElement.scrollHeight; // 页面总高度
if (scrollTop + clientHeight >= scrollHeight) {
// 在这里触发你的回调逻辑
if (performer_name.value) {
onLoad()
}
}
};
// 在组件挂载时添加滚动事件监听,并将第一次进入页面的标记设为false
onMounted(() => {
window.addEventListener('scroll', handleScroll);
});
// 在组件卸载时移除滚动事件监听
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll);
});
const performer_name = ref('');
/**
* 向下滚动查询数据
*/
const onLoad = async () => {
// 异步更新数据
const { data, code } = await prodListAPI({ book_id, kg_id, limit: limit.value, offset: offset.value, performer_name: performer_name.value })
if (code === 1) {
search_prod_list.value = _.concat(search_prod_list.value, data.prod_list);
search_prod_list.value = _.uniqBy(search_prod_list.value, 'id');
offset.value = search_prod_list.value.length;
loading.value = false;
// 数据全部加载完成
if (!data.prod_list.length) {
// 加载状态结束
finished.value = true;
}
// 空数据提示
if (!search_prod_list.value.length) {
finishedTextStatus.value = false;
}
emptyStatus.value = Object.is(search_prod_list.value.length, 0);
}
};
const onSearch = async() => {
offset.value = 0
search_prod_list.value = []
loading.value = true;
finished.value = false;
onLoad()
}
</script>
<style lang="less" scoped>
.bottom-btn {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: white;
box-shadow: 0px -2px 4px 0px rgba(0, 0, 0, 0.07);
z-index: 9999;
.text {
text-align: center;
padding: 0.7rem;
margin: 0.8rem;
font-size: 1rem;
font-weight: bold;
border-radius: 24px;
// border: 1px solid F7F7F7;
color: @base-font-color;
background-color: @base-color;
box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.06);
}
}
</style>