• 小程序实现搜索效果


    首页入口

    进入搜索页

    搜索结果页

    后台提供三个接口

    <?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;
             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;
                     500rpx;
                }
                .search-image {
                    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;
         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;
         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;
             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;
                     500rpx;
                }
                .search-image {
                    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 {
                 180rpx;
                height: 180rpx;
                // border: 1rpx solid red;
                image {
                     180rpx;
                    height: 180rpx;
                }
            }
            .item-content {
                margin-left:20rpx;
                 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 {
                         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 {
             350rpx;
            height: 313rpx;
            // border:1px solid blue;
            margin:0 auto;
            image {
                 350rpx;
                height: 313rpx;
            }
        }
        .msg {
            text-align: center;
            font-size: 32rpx;
            color:#BFBFBF;
            margin-top:69rpx;
        }
    }
    
  • 相关阅读:
    10-padding(内边距)
    09-盒模型
    07-css的继承性和层叠性
    Python之路【第09章】:Python模块和包的详细说明
    Python之路【第10章】:程序异常处理
    Python之路【第09章】:Python模块
    排序算法—冒泡排序算法
    算法总结
    递归函数与二分法
    练习题
  • 原文地址:https://www.cnblogs.com/jiqing9006/p/12191158.html
Copyright © 2020-2023  润新知