首页入口
进入搜索页
搜索结果页
后台提供三个接口
<?php
/**
* 搜索商品
*/
class SearchAction extends CommonAction{
public function _initialize(){
parent::_initialize();
}
/**
* 获取搜索历史和热门搜索
*/
public function getHotAndHistory() {
if (!$uid = $_POST[\'uid\']) {
$this->json->setErr(\'10001\', \'缺少用户id\');
$this->json->Send();
}
// 历史
$data[\'history\'] = [];
$search_history = M(\'search_history\');
$search_history_list = $search_history->where([\'uid\'=>$uid,\'status\'=>1])->order(\'id desc\')->select();
foreach ($search_history_list as $k=>$v) {
$data[\'history\'][] = $v[\'keywords\'];
}
// 热门
$configs = M(\'configs\');
$hot_search = $configs->where([\'this_key\'=>\'hot_search\'])->getField(\'this_value\');
$data[\'hot\'] = explode(\',\',$hot_search); // 爆炸成数组
$this->json->S($data);
}
/**
* 搜索数据
*/
public function searchData() {
if (!$uid = $_POST[\'uid\']) {
$this->json->setErr(\'10001\', \'缺少用户id\');
$this->json->Send();
}
if (!$keywords = $_POST[\'keywords\']) {
$this->json->setErr(\'10001\', \'请输入要查询的内容\');
$this->json->Send();
}
if (!isset($_POST[\'page\']) || $_POST[\'page\'] < 1) {
$_POST[\'page\'] = 1;
}
if (!isset($_POST[\'page_size\']) || $_POST[\'page_size\'] < 1) {
$_POST[\'page_size\'] = C(\'PAGE_NORMAL_COUNT\');
}
$page = $_POST[\'page\'];
$page_size = $_POST[\'page_size\'];
if ($page == 1) {
// 删除之前的记录
$search_history = M(\'search_history\');
$search_history->where([\'uid\'=>$uid,\'keywords\'=>$keywords])->save([\'status\'=>0,\'update_time\'=>time()]);
// 添加新的记录
$search_history->add([\'uid\'=>$uid,\'keywords\'=>$keywords,\'update_time\'=>time(),\'create_time\'=>time()]);
}
$where[\'title\'] = [\'like\',\'%\'.$keywords.\'%\'];
$where[\'status\'] = 1; // 显示
$where[\'is_del\'] = 0; // 未删除
$where[\'spec_main\'] = 1; // 是否主商品
// 获取总数
$product = M(\'product\');
$count = $product->where($where)->count();
$total_page = ceil($count / $page_size);
if ($page > $total_page) {
$return_data = [\'data_list\' => [], \'total_page\' => $total_page, \'current_page\' => $page];
$this->json->S($return_data, \'没有更多了\');
}
$data_list = $product->where($where)
->order(\'id desc\')
->limit((($page - 1) * $page_size) . \',\' . $page_size)
->field(\'id,title,title_img,sales_count,price\')
->select();
if ($data_list) {
vendor(\'Func.Math\');
foreach ($data_list as $k => &$v) {
$v[\'price\'] = Math::div($v[\'price\'], 100);
}
}
$out_data = $data_list ?: [];
$return_data = [\'data_list\' => $out_data, \'total_page\' => $total_page, \'current_page\' => $page];
$this->json->S($return_data);
}
/**
* 清除数据
*/
public function clearData() {
if (!$uid = $_POST[\'uid\']) {
$this->json->setErr(\'10001\', \'缺少用户id\');
$this->json->Send();
}
// 删除之前的记录
$search_history = M(\'search_history\');
$clear_res = $search_history->where([\'uid\'=>$uid])->save([\'status\'=>0,\'update_time\'=>time()]);
if ($clear_res !== false) {
$this->json->S();
} else {
$this->json->E(\'清理失败\');
}
}
}
搜索页面
<view class="search">
<view class="search-container">
<view class="search-left">
<image class="search-image" src="/images/index/search.png" />
<input class="search-input" placeholder="请输入你喜欢的商品" bindinput=\'watchSearch\'/>
</view>
<view class="search-btn" data-keywords="{{keywords}}" bindtap="go_to_search_result">搜索</view>
</view>
</view>
<view class="history">
<view class="history-title">
<view class="history-title-left">搜索历史</view>
<view class="history-title-right" bindtap="clearSearchHistory">清除历史</view>
</view>
<view class="history-content">
<block wx:if="{{index_data.history != false}}">
<block wx:for="{{index_data.history}}" wx:key="id">
<view class="history-item" data-keywords="{{item}}" bindtap="go_to_search_result">{{item}}</view>
</block>
</block>
</view>
</view>
<view class="hot">
<view class="hot-title">热门搜索</view>
<view class="hot-content">
<block wx:if="{{index_data.hot != false}}">
<block wx:for="{{index_data.hot}}" wx:key="id">
<view class="hot-item" data-keywords="{{item}}" bindtap="go_to_search_result">{{item}}</view>
</block>
</block>
</view>
</view>
搜索页面业务逻辑
import { initNoPage } from "../../common/requestData";
import Storage from "../../common/auth/Storage";
import tips from "../../common/tips";
import request from "../../common/request";
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
index_data: [],
keywords: \'\'
},
// 清理
clearSearchHistory: function () {
tips.showConfirm("您确认清理搜索历史吗").then(() => {
const uid = app.globalData.uid || Storage.get().uid;
request("clearData", { uid: uid })
.then(() => {
tips.showMsg("清理成功");
this.setData({
"index_data.history": []
});
})
.catch(({ errdesc }) => {
return tips.showMsg(errdesc);
});
});
},
// 监听输入
watchSearch: function (event) {
console.log(event.detail.value);
let keywords = event.detail.value;
// 设置值
this.setData({
"keywords": keywords
});
},
go_to_search_result({
currentTarget: {
dataset: { keywords }
}
}) {
console.log(keywords);
if (keywords == \'\') {
return tips.showMsg("请输入要搜索的内容");
}
wx.navigateTo({
url: "/pages/search/result/index?keywords=" + keywords
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 展示
*/
onShow: function (options) {
const uid = app.globalData.uid || Storage.get().uid;
console.log(uid);
// 初始化
initNoPage(this, [
{
api: "getHotAndHistory",
outDataName: "index_data",
inData: { \'uid\': uid }
}
]);
setTimeout(() => {
this.setData({
wo_title: app.globalData.wo_title
});
}, 300);
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () { },
/**
* 用户点击右上角分享
*/
onShareAppMessage() { },
});
搜索页面样式
.search {
height: 124rpx;
background-color: #F7F7F7;
display: flex;
justify-content: center;
.search-container {
margin-top: 30rpx;
height: 64rpx;
// border:1px solid red;
margin-left:22rpx;
margin-right:33rpx;
width: 695rpx;
display: flex;
.search-left {
display: flex;
background-color: #FFFFFF;
border-radius: 32rpx;
.search-input {
// border:1px solid blue;
height: 64rpx;
line-height: 64rpx;
font-size: 28rpx;
width: 500rpx;
}
.search-image {
width:34rpx;
height: 34rpx;
margin-left: 30rpx;
margin-top:15rpx;
margin-right: 15rpx;
}
}
.search-btn {
font-size: 32rpx;
line-height: 64rpx;
font-weight: bold;
color:#313131;
text-align: center;
margin-left:30rpx;
}
}
}
.history {
margin:0 auto;
width: 710rpx;
margin-top:30rpx;
.history-title {
display: flex;
justify-content: space-between;
.history-title-left {
font-size: 28rpx;
color:#313131;
}
.history-title-right {
font-size: 28rpx;
color:#AAAAAA;
}
margin-bottom: 15rpx;
}
.history-content {
display: flex;
flex-wrap: wrap;
overflow: hidden;
.history-item {
margin-top:15rpx;
margin-left:10rpx;
margin-right:10rpx;
padding-left:20rpx;
padding-right: 20rpx;
height: 48rpx;
background-color: #eeeeee;
border-radius: 24rpx;
font-size: 24rpx;
line-height: 48rpx;
}
}
}
.hot {
margin:0 auto;
width: 710rpx;
margin-top:50rpx;
.hot-title {
display: flex;
justify-content: space-between;
font-size: 28rpx;
color:#313131;
margin-bottom: 15rpx;
}
.hot-content {
display: flex;
flex-wrap: wrap;
overflow: hidden;
.hot-item {
margin-top:15rpx;
margin-left:10rpx;
margin-right:10rpx;
padding-left:20rpx;
padding-right: 20rpx;
height: 48rpx;
background-color: #eeeeee;
border-radius: 24rpx;
font-size: 24rpx;
line-height: 48rpx;
}
}
}
搜索结果页面
<view class="search">
<view class="search-container">
<view class="search-left">
<image class="search-image" src="/images/index/search.png" />
<input class="search-input" placeholder="请输入你喜欢的商品" value="{{keywords}}" bindinput=\'watchSearch\' />
</view>
<view class="search-btn" data-keywords="{{keywords}}" bindtap="go_to_search_result">搜索</view>
</view>
</view>
<block wx:if="{{noData == 1}}">
<view class="no-data">
<view class="img">
<image class="search-image" src="/images/search/nodata.png" />
</view>
<view class="msg">什么也没搜到哦</view>
</view>
</block>
<block wx:else>
<view class="data-list">
<block wx:for="{{searchResult}}" wx:key="id">
<view class="data-item">
<view class="item-img">
<image src="{{item.title_img}}" />
</view>
<view class="item-content">
<view class="item-content-title">{{item.title}}</view>
<view class="item-content-property">
<view class="property-item">销量:{{item.sales_count}}</view>
<!-- <view class="property-item">库存:1970</view> -->
</view>
<view class="item-content-price">¥{{item.price}}</view>
<view class="item-content-add">
<image src="/images/common/buy_more.png" catch:tap="openTypeSelect" data-id="{{item.id}}" lazy-load="{{true}}"/>
</view>
</view>
</view>
</block>
<block wx:if="{{noMore==1}}">
<view class="no-more">无更多结果</view>
</block>
</view>
</block>
<goodsType id="goodsType" />
搜索结果页逻辑
import { initInPage } from "../../../common/requestData";
import Storage from "../../../common/auth/Storage";
import tips from "../../../common/tips";
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
index_data: [],
keywords: \'\'
},
openTypeSelect({
currentTarget: {
dataset: { id }
}
}) {
this.selectComponent("#goodsType").openTypeSelect(id);
},
// 监听输入
watchSearch: function (event) {
console.log(event.detail.value);
let keywords = event.detail.value;
// 设置值
this.setData({
"keywords": keywords
});
},
go_to_search_result({
currentTarget: {
dataset: { keywords }
}
}) {
console.log(keywords);
if (keywords == \'\') {
return tips.showMsg("请输入要搜索的内容");
}
const uid = app.globalData.uid || Storage.get().uid;
console.log(uid);
// 初始化
initInPage(
this,
"searchData",
{ \'uid\': uid, \'keywords\': keywords, page: 1, page_size: 5 },
{ inDataName: "inData", outDataName: "searchResult" }
);
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// 能获取到参数
console.log(options.keywords);
// 设置值
this.setData({
"keywords": options.keywords
});
},
/**
* 展示
*/
onShow: function (options) {
// 获取不到参数
let keywords = this.data.keywords;
const uid = app.globalData.uid || Storage.get().uid;
console.log(uid);
// 初始化
initInPage(
this,
"searchData",
{ \'uid\': uid, \'keywords\': keywords, page: 1, page_size: 5 },
{ inDataName: "inData", outDataName: "searchResult" }
);
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () { },
/**
* 用户点击右上角分享
*/
onShareAppMessage() { },
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
return initInPage(this, "searchData", this.inData, { inDataName: "inData", outDataName: "searchResult" });
},
});
搜索结果页样式
.search {
height: 124rpx;
background-color: #F7F7F7;
display: flex;
justify-content: center;
.search-container {
margin-top: 30rpx;
height: 64rpx;
// border:1px solid red;
margin-left:22rpx;
margin-right:33rpx;
width: 695rpx;
display: flex;
.search-left {
display: flex;
background-color: #FFFFFF;
border-radius: 32rpx;
.search-input {
// border:1px solid blue;
height: 64rpx;
line-height: 64rpx;
font-size: 28rpx;
width: 500rpx;
}
.search-image {
width:34rpx;
height: 34rpx;
margin-left: 30rpx;
margin-top:15rpx;
margin-right: 15rpx;
}
}
.search-btn {
font-size: 32rpx;
line-height: 64rpx;
font-weight: bold;
color:#313131;
text-align: center;
margin-left:30rpx;
}
}
}
.data-list {
margin-top:16rpx;
overflow: hidden;
.data-item {
height: 240rpx;
border-bottom: 1rpx solid #E2E2E2;
padding:30rpx 20rpx;
display: flex;
.item-img {
width: 180rpx;
height: 180rpx;
// border: 1rpx solid red;
image {
width: 180rpx;
height: 180rpx;
}
}
.item-content {
margin-left:20rpx;
width: 510rpx;
height: 180rpx;
// border:1rpx solid blue;
position: relative;
.item-content-title {
font-size:26rpx;
color:#313131;
}
.item-content-property {
margin-top:20rpx;
font-size: 24rpx;
height:24rpx; /* 防止上下空隙 */
line-height:24rpx;
color:#AAAAAA;
display: flex;
.property-item:nth-child(n+2) {
margin-left:20rpx;
}
}
.item-content-price {
margin-top:46rpx;
font-size:32rpx;
font-weight: bold;
color:#F6001F;
height:32rpx;
line-height:32rpx;
}
.item-content-add {
position: absolute;
right: 0rpx;
bottom: 0rpx;
line-height: 46rpx;
font-size: 46rpx;
height: 46rpx;
color: #F6001F;
image {
width: 46rpx;
height: 46rpx;
}
}
}
}
.no-more {
text-align: center;
color:#E2E2E2;
font-size: 32rpx;
font-weight: bold;
margin-top:30rpx;
}
}
.no-data {
// display: none; /* 暂时先隐藏 */
margin:0 auto;
margin-top:163rpx;
height: 420rpx;
// border:1px solid red;
.img {
width: 350rpx;
height: 313rpx;
// border:1px solid blue;
margin:0 auto;
image {
width: 350rpx;
height: 313rpx;
}
}
.msg {
text-align: center;
font-size: 32rpx;
color:#BFBFBF;
margin-top:69rpx;
}
}