初始版本
This commit is contained in:
410
uniapp/src/bundle/pages/search/search.vue
Normal file
410
uniapp/src/bundle/pages/search/search.vue
Normal file
@@ -0,0 +1,410 @@
|
||||
<template>
|
||||
<page-meta :page-style="$theme.pageStyle">
|
||||
<!-- #ifndef H5 -->
|
||||
<navigation-bar
|
||||
:front-color="$theme.navColor"
|
||||
:background-color="$theme.navBgColor"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
</page-meta>
|
||||
<view class="search flex flex-col min-h-0 h-full">
|
||||
<!-- #ifndef H5 -->
|
||||
<u-sticky h5-nav-height="0" bg-color="transparent">
|
||||
<u-navbar
|
||||
:is-back="true"
|
||||
:is-fixed="true"
|
||||
:border-bottom="false"
|
||||
title="搜索"
|
||||
title-color="#000"
|
||||
:title-bold="false"
|
||||
:background="{ background: `rgba(256,256, 256, ${search.searching ? 1 : 0})` }"
|
||||
>
|
||||
</u-navbar>
|
||||
</u-sticky>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- 搜索框 --- 未搜索 -->
|
||||
<view
|
||||
class="p-[30rpx]"
|
||||
:style="{
|
||||
'background-color': !search.searching ? 'transparent' : '#ffffff'
|
||||
}"
|
||||
>
|
||||
<view
|
||||
class="search-input flex"
|
||||
:style="{
|
||||
'background-color': !search.searching ? '#ffffff' : '#F6F7F8'
|
||||
}"
|
||||
>
|
||||
<view class="search-input-icon flex items-center flex-none">
|
||||
<u-icon name="search"></u-icon>
|
||||
</view>
|
||||
<view class="search-input-wrapper flex items-center flex-1">
|
||||
<input
|
||||
class="search-input-inner flex-1"
|
||||
placeholder="请输入关键词"
|
||||
v-model="keyword"
|
||||
@confirm="handleSearch"
|
||||
@change="handleSearch"
|
||||
:focus="true"
|
||||
/>
|
||||
<view
|
||||
v-if="keyword.length"
|
||||
class="flex-none px-3 text-muted"
|
||||
@click="clearSearch"
|
||||
>
|
||||
<u-icon name="close-circle" size="34"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button
|
||||
class="search-input-btn flex-none"
|
||||
@click="handleSearch"
|
||||
>
|
||||
搜索
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 搜索 -->
|
||||
<view class="search-content flex flex-col min-h-0 h-full">
|
||||
<!-- 未搜索 -->
|
||||
<suggest
|
||||
v-show="!search.searching"
|
||||
:hot_search="search.hot_search"
|
||||
:his_search="search.his_search"
|
||||
@clear="handleClear"
|
||||
@search="(val) => {
|
||||
keyword = val;
|
||||
handleSearch()
|
||||
}"
|
||||
></suggest>
|
||||
|
||||
<!-- 搜索结果 -->
|
||||
<view
|
||||
class="flex flex-col min-h-0 h-full"
|
||||
v-show="search.searching"
|
||||
>
|
||||
<!-- 检索下拉组件 列表 -->
|
||||
<view class="bg-white">
|
||||
<u-dropdown
|
||||
ref="uDropdownRef"
|
||||
menu-icon="arrow-down-fill"
|
||||
menu-icon-size="20"
|
||||
border-radius="18"
|
||||
duration="0"
|
||||
:active-color="$theme.primaryColor"
|
||||
>
|
||||
<u-dropdown-item :title="sortOptions[sort].label">
|
||||
<view class="bg-white rounded-b-xl pt-4">
|
||||
<view
|
||||
v-for="(item, index) in sortOptions"
|
||||
:key="index"
|
||||
class="pb-4 text-content"
|
||||
:class="{
|
||||
'text-primary': index === sort
|
||||
}"
|
||||
@click="handleFiltrate('sort', index)"
|
||||
>
|
||||
<text class="ml-4">
|
||||
{{ item.label }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-dropdown-item>
|
||||
<u-dropdown-item
|
||||
title="销量"
|
||||
>
|
||||
<view class="bg-white rounded-b-xl pt-4">
|
||||
<view
|
||||
v-for="(item, index) in salesOptions"
|
||||
:key="index"
|
||||
class="pb-4 text-content"
|
||||
:class="{
|
||||
'text-primary': item.value === order_sales
|
||||
}"
|
||||
@click="handleFiltrate('order_sales', item.value)"
|
||||
>
|
||||
<text class="ml-4">
|
||||
{{ item.label }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-dropdown-item>
|
||||
<u-dropdown-item
|
||||
title="价格"
|
||||
>
|
||||
<view class="bg-white rounded-b-xl pt-4">
|
||||
<view
|
||||
v-for="(item, index) in salesOptions"
|
||||
:key="index"
|
||||
class="pb-4 text-content"
|
||||
:class="{
|
||||
'text-primary': item.value === price
|
||||
}"
|
||||
@click="handleFiltrate('price', item.value)"
|
||||
>
|
||||
<text class="ml-4">
|
||||
{{ item.label }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-dropdown-item>
|
||||
<u-dropdown-item
|
||||
:title="listOptions[list].label"
|
||||
>
|
||||
<view class="bg-white rounded-b-xl pt-4">
|
||||
<view
|
||||
v-for="(item, index) in listOptions"
|
||||
:key="index"
|
||||
class="pb-4 pl-4 text-content"
|
||||
:class="{
|
||||
'text-primary': item.value === list
|
||||
}"
|
||||
@click="handleFiltrate('list', item.value)"
|
||||
>
|
||||
<u-icon
|
||||
:name="item.icon"
|
||||
size="28"
|
||||
></u-icon>
|
||||
<text class="ml-2">
|
||||
{{ item.label }}展示
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-dropdown-item>
|
||||
</u-dropdown>
|
||||
</view>
|
||||
|
||||
<!-- 显示页面 列表 -->
|
||||
<view class="h-full">
|
||||
<z-paging
|
||||
ref="paging"
|
||||
v-model="search.result.content.goods_list"
|
||||
:fixed="false"
|
||||
height="100%"
|
||||
:empty-view-img="EmptySearch"
|
||||
@query="queryList"
|
||||
>
|
||||
<area-goods
|
||||
:content="search.result.content"
|
||||
:styles="search.result.styles"
|
||||
/>
|
||||
</z-paging>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, reactive, shallowRef} from 'vue'
|
||||
import Suggest from './component/suggest.vue'
|
||||
import {HISTORY} from '@/enums/constantEnums'
|
||||
import {getHotSearch, getServiceList} from '@/api/shop'
|
||||
import {locationState} from "@/hooks/useLocation";
|
||||
import cache from '@/utils/cache'
|
||||
import AreaGoods from "@/components/widgets/area-goods/area-goods.vue";
|
||||
import EmptySearch from "@/static/images/empty/search.png";
|
||||
|
||||
interface Search {
|
||||
hot_search: {
|
||||
data: any[]
|
||||
status: number
|
||||
}
|
||||
his_search: string[]
|
||||
result: any
|
||||
searching: boolean
|
||||
}
|
||||
|
||||
const search = reactive<Search>({
|
||||
hot_search: {
|
||||
data: [],
|
||||
status: 1
|
||||
},
|
||||
his_search: [],
|
||||
// 这里复用了首页装修的商品组组件数据。
|
||||
result: {
|
||||
content: {
|
||||
enabled: 1, // 是否启用
|
||||
type: 1, // 1-自动获取
|
||||
goods_type: 1, // 1-单列 2-双列 3-横向滑动 4-大图模式
|
||||
show_title: 1, // 商品标题
|
||||
show_server: 1, // 服务
|
||||
show_price: 1, // 商品价格
|
||||
show_scribing_price: 1, // 划线价格
|
||||
show_sales: 1, // 销量
|
||||
|
||||
btn_text: '立即下单', // 按钮文字
|
||||
show_num: 1, // 显示数量
|
||||
goods_list: [] // 商品数据
|
||||
},
|
||||
styles: {
|
||||
title_color: '#000000', // 标题颜色
|
||||
server_color: '#888888', // 服务颜色
|
||||
price_color: '#fc5447', // 价格颜色
|
||||
scribing_price_color: '#888888', // 划线价格颜色
|
||||
sales_color: '#888888', // 销量颜色
|
||||
btn_radius: 10, // 按钮圆角
|
||||
|
||||
root_bg_color: '', // 根背景颜色
|
||||
component_bg_color: '#ffffff', // 组件背景颜色
|
||||
goods_bg_color: '', // 商品背景颜色
|
||||
padding_top: 12, // 上内边距
|
||||
padding_horizontal: 12, // 左右内边距
|
||||
padding_bottom: 12, // 下内边距
|
||||
goods_horizontal: 12, // 商品左右内边距
|
||||
goods_vertical: 12, // 商品上下内边距
|
||||
|
||||
border_top_radius: 20,
|
||||
border_bottom_radius: 20,
|
||||
image_radius: 8
|
||||
}
|
||||
},
|
||||
searching: false
|
||||
})
|
||||
const keyword = ref<string>('')
|
||||
const order_sales = ref('') // 销量排序
|
||||
const price = ref('') // 价格排序
|
||||
const sort = ref('') // 综合排序
|
||||
const list = ref('card') // 列表展示
|
||||
const paging = shallowRef()
|
||||
const uDropdownRef = shallowRef()
|
||||
|
||||
const sortOptions = {
|
||||
'': {value: '', label: '综合排序'},
|
||||
// 'desc': { value: 'desc', label:'距离优先'},
|
||||
// 'asc': {value: 'asc', label: '销量优先'},
|
||||
'comment_sales': {value: 'desc', label: '好评优先'}
|
||||
}
|
||||
const salesOptions = [
|
||||
{value: '', label: '默认'},
|
||||
{value: 'desc', label: '从高到低'},
|
||||
{value: 'asc', label: '从低到高'}
|
||||
]
|
||||
const listOptions = {
|
||||
card: {value: 'card', icon: 'grid', label: '卡片'},
|
||||
list: {value: 'list', icon: 'list-dot', label: '列表'}
|
||||
}
|
||||
|
||||
const handleFiltrate = (type: string, value: string) => {
|
||||
switch (type) {
|
||||
case 'sort':
|
||||
sort.value = value
|
||||
paging.value.refresh()
|
||||
break
|
||||
case 'order_sales':
|
||||
order_sales.value = value
|
||||
paging.value.refresh()
|
||||
break
|
||||
case 'price':
|
||||
price.value = value
|
||||
paging.value.refresh()
|
||||
break
|
||||
case 'list':
|
||||
list.value = value
|
||||
value === 'card' ? (search.result.content.goods_type = 1) : (search.result.content.goods_type = 2)
|
||||
break
|
||||
}
|
||||
uDropdownRef.value?.close()
|
||||
}
|
||||
|
||||
const handleSearch = () => {
|
||||
if (keyword.value.trim() === '') {
|
||||
return
|
||||
}
|
||||
if (keyword.value) {
|
||||
if (!search.his_search.includes(keyword.value)) {
|
||||
search.his_search.unshift(keyword.value)
|
||||
cache.set(HISTORY, search.his_search)
|
||||
}
|
||||
}
|
||||
paging.value.reload()
|
||||
search.searching = true
|
||||
}
|
||||
|
||||
const clearSearch = () => {
|
||||
keyword.value = ''
|
||||
search.searching = false
|
||||
}
|
||||
|
||||
const getHotSearchFunc = async () => {
|
||||
try {
|
||||
search.hot_search = await getHotSearch()
|
||||
} catch (e) {
|
||||
//TODO handle the exception
|
||||
console.log('获取热门搜索失败=>', e)
|
||||
}
|
||||
}
|
||||
|
||||
const handleClear = async (): Promise<void> => {
|
||||
const resModel: any = await uni.showModal({
|
||||
title: '温馨提示',
|
||||
content: '是否清空历史记录?'
|
||||
})
|
||||
if (resModel.confirm) {
|
||||
cache.set(HISTORY, '')
|
||||
search.his_search = []
|
||||
}
|
||||
}
|
||||
|
||||
const queryList = async (page_no: number, page_size: number) => {
|
||||
try {
|
||||
const {lists} = await getServiceList({
|
||||
keyword: keyword.value,
|
||||
city_id: locationState.city_id,
|
||||
order_sales: order_sales.value,
|
||||
price: price.value,
|
||||
comment_sales: sort.value,
|
||||
page_no,
|
||||
page_size
|
||||
})
|
||||
paging.value.complete(lists)
|
||||
} catch (e) {
|
||||
console.log('报错=>', e)
|
||||
//TODO handle the exception
|
||||
paging.value.complete(false)
|
||||
}
|
||||
}
|
||||
|
||||
getHotSearchFunc()
|
||||
search.his_search = cache.get(HISTORY) || []
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search {
|
||||
.search-input {
|
||||
background-color: #ffffff;
|
||||
border-radius: 50px;
|
||||
padding: 10rpx 20rpx;
|
||||
|
||||
.search-input-icon {
|
||||
color: #666666;
|
||||
padding: 0 14rpx 0 14rpx;
|
||||
}
|
||||
|
||||
.search-input-wrapper {
|
||||
|
||||
}
|
||||
|
||||
.search-input-inner {
|
||||
|
||||
}
|
||||
|
||||
.search-input-btn {
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
font-size: 28rpx;
|
||||
@apply bg-primary text-white rounded-full;
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
|
||||
&-s {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user