257 lines
5.5 KiB
Vue
257 lines
5.5 KiB
Vue
<template>
|
|
<z-paging ref="paging" v-model="courseList" auto-show-back-to-top :auto="false" class="search-page" @query="getSearchCourseList">
|
|
<template #top>
|
|
<!-- 导航栏 -->
|
|
<nav-bar>
|
|
<template #title>
|
|
<view class="search-box">
|
|
<wd-search
|
|
v-model="keyword"
|
|
hide-cancel
|
|
clearable
|
|
:placeholder="$t('courseSearch.placeholder')"
|
|
@search="handleSearch"
|
|
@clear="handleClear"
|
|
/>
|
|
</view>
|
|
</template>
|
|
</nav-bar>
|
|
</template>
|
|
|
|
<!-- 历史搜索区域 -->
|
|
<view v-if="!showResults" class="history-section">
|
|
<view class="history-title">{{ $t('courseSearch.historyTitle') }}</view>
|
|
<view class="history-tags">
|
|
<wd-tag
|
|
v-for="(item, index) in historyList"
|
|
:key="index"
|
|
@click="handleHistoryClick(item)"
|
|
>
|
|
{{ item }}
|
|
</wd-tag>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 搜索结果区域 -->
|
|
<view v-if="showResults" class="search-results">
|
|
<!-- 课程列表 -->
|
|
<view v-if="!loading && courseList.length > 0" class="course-section">
|
|
<view class="course-list">
|
|
<listItem
|
|
v-for="(item, index) in courseList"
|
|
:key="index"
|
|
:data="item"
|
|
:showToDetail="false"
|
|
desc="content"
|
|
/>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 空状态 -->
|
|
<view v-if="!loading && isEmpty" class="empty-wrapper">
|
|
<wd-divider :text="$t('courseSearch.noData')" />
|
|
</view>
|
|
</view>
|
|
</z-paging>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue'
|
|
import { onShow } from '@dcloudio/uni-app'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { courseApi } from '@/api/modules/course'
|
|
import type { ICourse } from '@/types/search'
|
|
import ListItem from '@/components/course/ListItem.vue'
|
|
|
|
const { t } = useI18n()
|
|
const paging = ref<any>(null)
|
|
|
|
// 状态定义
|
|
const keyword = ref<string>('') // 搜索关键词
|
|
const historyList = ref<string[]>([]) // 历史搜索记录
|
|
const courseList = ref<ICourse[]>([]) // 课程列表
|
|
const showResults = ref<boolean>(false) // 是否显示搜索结果
|
|
const loading = ref<boolean>(false) // 加载状态
|
|
const isEmpty = ref<boolean>(false) // 是否为空结果
|
|
|
|
/**
|
|
* 获取历史搜索记录
|
|
*/
|
|
const getHistory = () => {
|
|
try {
|
|
let records = uni.getStorageSync('hisRecords') || []
|
|
records = [...new Set(records)]
|
|
if (records.length > 10) {
|
|
records = records.slice(0, 10)
|
|
}
|
|
historyList.value = records
|
|
uni.setStorageSync('hisRecords', records)
|
|
} catch (error) {
|
|
console.error('获取历史记录失败:', error)
|
|
historyList.value = []
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 保存搜索记录
|
|
*/
|
|
const saveHistory = (kw: string) => {
|
|
try {
|
|
let records = uni.getStorageSync('hisRecords') || []
|
|
records.unshift(kw)
|
|
uni.setStorageSync('hisRecords', records)
|
|
} catch (error) {
|
|
console.error('保存历史记录失败:', error)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 执行搜索
|
|
*/
|
|
const handleSearch = async () => {
|
|
if (!keyword.value.trim()) {
|
|
uni.showToast({
|
|
icon: 'none',
|
|
title: t('courseSearch.pleaseInputKeyword')
|
|
})
|
|
return
|
|
}
|
|
|
|
loading.value = true
|
|
showResults.value = true
|
|
isEmpty.value = false
|
|
|
|
await paging.value.reload()
|
|
loading.value = false
|
|
isEmpty.value = courseList.value.length === 0
|
|
showResults.value = !isEmpty.value
|
|
|
|
// 保存搜索历史
|
|
saveHistory(keyword.value.trim())
|
|
}
|
|
/**
|
|
* 获取搜索课程列表
|
|
*/
|
|
const getSearchCourseList = async (pageNo: number, pageSize: number) => {
|
|
try {
|
|
const res = await courseApi.searchData({
|
|
title: keyword.value.trim(),
|
|
page: pageNo,
|
|
size: pageSize
|
|
})
|
|
paging.value.setLocalPaging(res.courseEntities)
|
|
|
|
} catch (error) {
|
|
paging.value.complete(false)
|
|
console.error('搜索失败:', error)
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 点击历史标签搜索
|
|
*/
|
|
const handleHistoryClick = (item: string) => {
|
|
keyword.value = item
|
|
handleSearch()
|
|
}
|
|
|
|
/**
|
|
* 清空搜索
|
|
*/
|
|
const handleClear = () => {
|
|
keyword.value = ''
|
|
showResults.value = false
|
|
courseList.value = []
|
|
isEmpty.value = false
|
|
getHistory()
|
|
}
|
|
|
|
/**
|
|
* 页面挂载
|
|
*/
|
|
onMounted(() => {
|
|
getHistory()
|
|
})
|
|
|
|
/**
|
|
* 页面显示
|
|
*/
|
|
onShow(() => {
|
|
getHistory()
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.search-page {
|
|
background: #f7faf9;
|
|
}
|
|
|
|
.search-box {
|
|
display: flex;
|
|
height: 100%;
|
|
align-items: center;
|
|
width: 100%;
|
|
--wot-search-padding: 0;
|
|
--wot-search-side-padding: 0;
|
|
|
|
:deep(.wd-search) {
|
|
background: transparent;
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
// 历史搜索样式
|
|
.history-section {
|
|
padding: 40rpx;
|
|
|
|
.history-title {
|
|
font-size: 30rpx;
|
|
font-weight: bold;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.history-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 20rpx;
|
|
}
|
|
}
|
|
|
|
// 搜索结果样式
|
|
.search-results {
|
|
padding: 20rpx;
|
|
padding-bottom: 0;
|
|
}
|
|
|
|
.loading-wrapper {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
padding: 100rpx 0;
|
|
}
|
|
|
|
.empty-wrapper {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
padding: 100rpx 0;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 40rpx;
|
|
color: #1e40af;
|
|
font-weight: bold;
|
|
letter-spacing: 2rpx;
|
|
margin-bottom: 30rpx;
|
|
text-shadow: 0 2rpx 4rpx rgba(0, 122, 255, 0.6);
|
|
}
|
|
|
|
// 课程列表样式
|
|
.course-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
</style>
|