目录

09-搜索前端开发-搜索页面

09-搜索前端开发-搜索页面

3 搜索前端开发

3.1 搜索页面

3.1.1 需求分析

https://i-blog.csdnimg.cn/blog_migrate/5d0c76cca38630bdbb13e329242a2608.png

上图是课程搜索前端的界面,用户通过前端向服务端发起搜索请求,搜索功能包括:

1、界面默认查询所有课程,并分页显示

2、通过一级分类和二分类搜索课程,选择一级分类后将显示下属的二级分类

3、通过关键字搜索课程

4、通过课程等级搜索课程

3.1.2 页面布局

nuxt.js将/layout/default.vue作为所有页面的默认布局,通常布局包括:页头、内容区、页尾

default.vue内容如下:

https://i-blog.csdnimg.cn/blog_migrate/3543d3b8cc2032282c398fd50cb4707e.png

<template>
  <div>
    <Header />
    <nuxt/>
    <Footer />
  </div>
</template>
<script>
  import Footer from '../components/Footer.vue'
  import Header from '../components/Header.vue'
  export default {
    components: {
      Header,
      Footer
    }
  }
</script>
<style>

</style>

3.1.3 Nginx代理配置

搜索页面中以/static开头的静态资源通过nginx解析,如下:

/static/plugins:指向门户目录下的plugins目录。

/static/css:指向门户目录下的的css目录

修改Nginx中www.xuecheng.com虚拟主机的配置:

        location / {
            alias   E:/java_www/xcEduUI05/;
            index  index.html index.htm;
        }
        location /static/img/ {
            alias   E:/java_www/xcEduUI05/img/;
        }
        location /static/css/ {
            alias   E:/java_www/xcEduUI05/css/;
        }
        location /static/js/ {
            alias   E:/java_www/xcEduUI05/js/;
        }
        location /static/plugins/ {
            alias   E:/java_www/xcEduUI05/plugins/;
            add_header Access-Control‐Allow‐Origin http://ucenter.xuecheng.com;
            #add_header Access‐Control‐Allow‐Credentials true;
            #add_header Access‐Control‐Allow‐Methods GET;
        }

https://i-blog.csdnimg.cn/blog_migrate/e4a451f48c39fe010ec3f285dbf81e7f.png

配置搜索Url,下图是Nginx搜索转发流程图

https://i-blog.csdnimg.cn/blog_migrate/2fe4ae5122c9dc4627597eb0973811b0.png

用户请求/course/search时Nginx将请求转发到nuxt.js服务,nginx在转发时根据每台nuxt服务的负载情况进行转

发,实现负载均衡。

本教程开发环境Nuxt.js服务和www.xuecheng.com虚拟机主在同一台计算机,使用同一个nginx,配置如下:

#前端门户课程搜索
location ^~ /course/search {
proxy_pass http://dynamic_portal_server_pool;
}
#后端搜索服务
location /openapi/search/ {
proxy_pass http://search_server_pool/search/;
}
#分类信息
location /static/category/ {
proxy_pass http://static_server_pool;
}

dynamic_portal_server_pool配置如下 :

#前端动态门户
upstream dynamic_portal_server_pool{
server 127.0.0.1:10000 weight=10;
}
#后台搜索(公开api)
upstream search_server_pool{
server 127.0.0.1:40100 weight=10;
}

其它配置:

#开发环境webpack定时加载此文件
location ^~ /__webpack_hmr {
proxy_pass http://dynamic_portal_server_pool/__webpack_hmr;
}
#开发环境nuxt访问_nuxt
location ^~ /_nuxt/ {
proxy_pass http://dynamic_portal_server_pool/_nuxt/;
}

在静态虚拟主机中添加:

#学成网静态资源
server {
listen 91;
server_name localhost;
#分类信息
location /static/category/ {
alias F:/develop/xuecheng/static/category/;
}
...

nginx的配置文件全部代码如下:


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    #cms页面预览
    upstream cms_server_pool{
     server 127.0.0.1:31001 weight=10;
    }

    #静态资源服务
    upstream static_server_pool{
     server 127.0.0.1:91 weight=10;
    }

    #前端动态门户
    upstream dynamic_portal_server_pool{
    server 127.0.0.1:10000 weight=10;
    }
    #后台搜索(公开api)
    upstream search_server_pool{
    server 127.0.0.1:40100 weight=10;
    }

    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

    #门户的顶级域名,门户的主站
    server {
        listen       80;
        server_name  www.xuecheng.com;
        ssi on;
        ssi_silent_errors on;
        location / {
            alias   E:/java_www/xcEduUI05/;
            index  index.html index.htm;
        }
        location /static/img/ {
            alias   E:/java_www/xcEduUI05/img/;
        }
        location /static/css/ {
            alias   E:/java_www/xcEduUI05/css/;
        }
        location /static/js/ {
            alias   E:/java_www/xcEduUI05/js/;
        }
        location /static/plugins/ {
            alias   E:/java_www/xcEduUI05/plugins/;
            add_header Access-Control‐Allow‐Origin http://ucenter.xuecheng.com;
            #add_header Access‐Control‐Allow‐Credentials true;
            #add_header Access‐Control‐Allow‐Methods GET;
        }

        #页面预览
        location /cms/preview/ {
            proxy_pass http://cms_server_pool/cms/preview/;
        }
        location /static/company/ {
            proxy_pass http://static_server_pool;
        }
        location /static/teacher/ {
            proxy_pass http://static_server_pool;
        }
        location /static/stat/ {
            proxy_pass http://static_server_pool;
        }
        location /course/detail/ {
            proxy_pass http://static_server_pool;
        }
        #前端门户课程搜索
        location ^~ /course/search {
        proxy_pass http://dynamic_portal_server_pool;
        }
        #后端搜索服务
        location /openapi/search/ {
        proxy_pass http://search_server_pool/search/;
        }
        #分类信息
        location /static/category/ {
        proxy_pass http://static_server_pool;
        }
        #开发环境webpack定时加载此文件
        location ^~ /__webpack_hmr {
        proxy_pass http://dynamic_portal_server_pool/__webpack_hmr;
        }
        #开发环境nuxt访问_nuxt
        location ^~ /_nuxt/ {
        proxy_pass http://dynamic_portal_server_pool/_nuxt/;
        }

    }

    #学成网静态资源
    server {
        listen       91;
        server_name  localhost;

		#公司信息
        location /static/company/ {
            alias E:/java_www/xcEduUI05/static/company/;
        }
        #老师信息
        location /static/teacher/ {
            alias E:/java_www/xcEduUI05/static/teacher/;
        }
        #统计信息
        location /static/stat/ {
            alias E:/java_www/xcEduUI05/static/stat/;
        }
        location /course/detail/ {
            alias E:/java_www/xcEduUI05/course/detail/;
        }
        location /static/category/ {
             alias E:/java_www/xcEduUI05/static/category/;
        }
    }
}

3.1.4 搜索页面

创建搜索页面如下:

https://i-blog.csdnimg.cn/blog_migrate/3663e94bcd38c2f91cf3fdbddd6f3a18.png

将index_1.vue文件代码复制到index.vue中。

页面文件参考:“资料”–》“search”–》index_1.vue,重要代码如下:

nuxt.js支持定义header,本页面我们在header中引入css样式并定义头部信息。

https://i-blog.csdnimg.cn/blog_migrate/a4c3a2b09c3afe1286a69ded81200390.png

<template>
  <div>
    <div class="learing-list">
      <div class="list-box">
        <ul>
          <li>关键字ss:</li>
          <ol>
            <li>{{keyword}}

              <nuxt-link v-if="keyword" class="title-link" :to="'/course/search?keyword=&mt='+mt+'&st=' + st+'&grade='+grade">
                &Chi;
              </nuxt-link>
            </li>
          </ol>
        </ul>
        <ul>
          <li>一级分类:</li>
          <li v-if="mt!=''"><nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&grade='+grade">全部</nuxt-link></li>
          <li class="all" v-else>全部</li>
          <ol>
            <li v-for="category_v in first_category">
              <nuxt-link  class="title-link all" :to="'/course/search?keyword='+keyword+'&mt=' + category_v.id" v-if="category_v.id == mt">{{category_v.name}}</nuxt-link>
              <nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + category_v.id" v-else>{{category_v.name}}</nuxt-link>
            </li>
          </ol>
          <!--<ol>
            <li>数据分析</li>
            <li>机器学习工程</li>
            <li>前端开发工程</li>
          </ol>-->
        </ul>
        <ul>
          <li>二级分类:</li>
          <li v-if="st!=''"><nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&mt='+mt+'&grade='+grade">全部</nuxt-link></li>
          <li class="all" v-else>全部</li>
          <ol v-if="second_category.length>0">
            <li v-for="category_v in second_category">
              <nuxt-link  class="title-link all" :to="'/course/search?keyword='+keyword+'&mt='+mt+'&st=' + category_v.id" v-if="category_v.id == st">{{category_v.name}}</nuxt-link>
              <nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&mt='+mt+'&st=' + category_v.id" v-else>{{category_v.name}}</nuxt-link>
            </li>
            <!-- <li>大数据</li>
             <li>云计算</li>-->
          </ol>
          <!--<a href="#" class="more">更多 ∨</a>-->
        </ul>
        <ul>
          <li>难度等级:</li>
          <li v-if="grade!=''">
            <nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade='">全部
            </nuxt-link>
          </li>
          <li class="all" v-else>全部</li>
          <ol>
            <li v-if="grade=='200001'" class="all">初级</li>
            <li v-else><nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade=200001'">初级</nuxt-link></li>
            <li v-if="grade=='200002'" class="all">中级</li>
            <li v-else><nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade=200002'">中级</nuxt-link></li>
            <li v-if="grade=='200003'" class="all">高级</li>
            <li v-else><nuxt-link  class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade=200003'">高级</nuxt-link></li>
          </ol>
        </ul>
      </div>
    </div>

    <div class="container">
      <div class="row">
        <div class="col-md-9 list-row-left">
          <div class="list-cont-left">
            <div class="tit">
              <ul class="nav nav-tabs ">
                <!--<li class="active"><a href="#">推荐</a></li>
                <li><a href="#">最新</a></li>
                <li><a href="#">热评</a></li>-->
                <!-- <div class="page navbar-right">
                   <a href="#" class="prev">
                     < </a>
                   <span class="">1/28</span>
                   <a href="#" class="next"> ></a>
                 </div>-->
              </ul>
            </div>
            <div class="tab-content">
              <div class="content-list">

                <!--<div class="recom-item">
                  <a href="/course/detail?id=1010" target="_blank">
                    <p><img src="/img/widget-demo1.png" width="100%" alt=""><span class="lab">HOT</span></p>
                    <ul>
                      <li>Think PHP 5.0 博客系统实战项目演练 </li>
                      <li><span>高级</span> <em> · </em> 1125人在学习</li>
                    </ul>
                  </a>
                </div>-->
                <div class="recom-item" v-for="(course, index) in courselist">
                  <a :href="'/course/detail/'+course.id+'.html'" target="_blank">
                    <!--<a href="/course/detail/test.html" target="_blank">-->
                    <div v-if="course.pic">
                      <p><img :src="imgUrl+'/'+course.pic" width="100%" alt=""></p>
                    </div>
                    <div v-else>
                      <p><img src="/img/widget-demo1.png" width="100%" alt=""></p>
                    </div>
                    <ul >
                      <li class="course_title"><span v-html="course.name"></span></li>
                      <li style="float: left"><span v-if="course.charge == '203001'">免费</span><span v-if="course.charge == '203002'">¥{{course.price | money}}</span>
                        <!-- <em> · </em>-->&nbsp;&nbsp;<!--<em>1125人在学习</em>--></li>
                    </ul>
                    <!--</a>-->
                  </a>
                </div>

                <li class="clearfix"></li>
              </div>
              <div class="clearfix"></div>
            </div>
          </div>

          <div style="text-align: center">
            <el-pagination
              background
              layout="prev, pager, next"
              @current-change="handleCurrentChange"
              :total="total"
              :page-size="page_size"
              prev-text="上一页"
              next-text="下一页">
            </el-pagination>
          </div>
        </div>
        <div class="col-md-3 list-row-rit">
          <div class="list-cont-right">
            <!--精品推荐-->
            <!--#include virtual="/include/BestTop.html"-->
            <!--精品推荐结束-->
            <!--猜你喜欢开始-->
            <div class="right-box">
              <div class="tit">猜你喜欢</div>
              <div class="contList">
                <div class="contList-titB">通过对ThinkPHP框架基础,带领大家由浅入深轻松掌握ThinkPHP的理论基础,更加全面的掌握ThinkPHP框架运行机制……</div>
                <div class="contList-item">
                  <p>Think PHP 5.0 博客系统实战项目演练</p>
                  <li><span>高级</span> <em> · </em> 1125人在学习</li>
                </div>
                <div class="contList-item">
                  <p>Think PHP 5.0 博客系统实战项目演练</p>
                  <li><span>高级</span> <em> · </em> 1125人在学习</li>
                </div>
                <div class="contList-item">
                  <p>Think PHP 5.0 博客系统实战项目演练</p>
                  <li><span>高级</span> <em> · </em> 1125人在学习</li>
                </div>
                <div class="contList-item">
                  <p>Think PHP 5.0 博客系统实战项目演练</p>
                  <li><span>高级</span> <em> · </em> 1125人在学习</li>
                </div>
              </div>
            </div>
            <!--猜你喜欢结束-->
          </div>
        </div>
      </div>

    </div>

  </div>
</template>
<script>
  //配置文件
  let config = require('~/config/sysConfig')
  import querystring from 'querystring'
  import * as courseApi from '~/api/course'
  export default {
    head() {
      return {
        title: '传智播客-一样的教育,不一样的品质',
        meta: [
          {charset: 'utf-8'},
          {name: 'description', content: '传智播客专注IT培训,Java培训,Android培训,安卓培训,PHP培训,C++培训,网页设计培训,平面设计培训,UI设计培训,移动开发培训,网络营销培训,web前端培训,云计算大数据培训,全栈工程师培训,产品经理培训。'},
          {name: 'keywords', content: this.keywords}
        ],
        link: [
          {rel: 'stylesheet', href: '/static/plugins/normalize-css/normalize.css'},
          {rel: 'stylesheet', href: '/static/plugins/bootstrap/dist/css/bootstrap.css'},
          {rel: 'stylesheet', href: '/static/css/page-learing-list.css'}
        ]
      }
    },
    async asyncData({ store, route }) {//服务端调用方法
      return {
        courselist: {},
        first_category:{},
        second_category:{},
        mt:'',
        st:'',
        grade:'',
        keyword:'',
        page:1,
        total:0,
        imgUrl:config.imgUrl
      }
    },
    data(){
      return {
        courselist: {},
        first_category:{},
        second_category:{},
        mt:'',
        st:'',
        grade:'',
        keyword:'',
        imgUrl:config.imgUrl,
        total:0,//总记录数
        page:1,//页码
        page_size:12//每页显示个数
      }
    },
    watch:{//路由发生变化立即搜索search表示search方法
      '$route':'search'
    },
    methods:{
      //分页触发
      handleCurrentChange(page) {

      },
      search(){
        //刷新当前页面
        window.location.reload();
      }
    },
    mounted(){
      
    }
  }
</script>
<style>
  a {
    color: #000;
  }
  .el-icon-arrow-left:before {
    content: "<";
  }
  .el-icon-d-arrow-left:before {
    content: "...";
  }
  .el-icon-arrow-right:before {
    content: ">";
  }
  .el-icon-d-arrow-right:before {
    content: "...";
  }
  .el-icon-more:before {
    content: "...";
  }
  .el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li {
    background-color: #fff;
  }
  .course_title{
    height: 20px;
    width: 160px;
    overflow:hidden;
  }
  .eslight{
    color: #990000;
  }
</style>

3.1.5 测试

重启Nginx,

https://i-blog.csdnimg.cn/blog_migrate/9caa85708aa8349f30223e61930f7b46.png

请求:http://www.xuecheng.com/course/search,页面效果如下:

https://i-blog.csdnimg.cn/blog_migrate/447f1c0d34c6a3c618abc6ac83f82d65.png

当用户访问http://www.xuecheng.com/course/search,则ngnix执行以下代码:

        #前端门户课程搜索
        location ^~ /course/search {
        proxy_pass http://dynamic_portal_server_pool;
        }

这样到http://dynamic_portal_server_pool/course/search,然后ngnix执行以下代码:

    #前端动态门户
    upstream dynamic_portal_server_pool{
    server 127.0.0.1:10000 weight=10;
    }

这样到http:// 127.0.0.1:10000/course/search

所以需要启动xc-ui-pc-portal这个项目

https://i-blog.csdnimg.cn/blog_migrate/e3e2ee24496c43b6a51dc500399a29e1.png

右击查看源代码如下:

https://i-blog.csdnimg.cn/blog_migrate/bae0a5b5eed633b0ca263f03327c1702.png

我们发现title和description都有,因为我们使用了服务端渲染的技术,包括css都渲染出来

https://i-blog.csdnimg.cn/blog_migrate/a318337be1b3bc0cc1c6037a3bab1566.png

https://i-blog.csdnimg.cn/blog_migrate/bf440f36506e2150078be199ab36acab.png