소스 검색

关键词库版本1.0.0版本上测试

yuwenjun1997 2 년 전
부모
커밋
0ff1620fac

+ 1 - 1
src/main/resources/static/css/encyclopedia/common.css

@@ -18,7 +18,7 @@ body{padding-top:80px;}
 .navbar .nav li a{height:80px;padding:0 28px}
 .navbar .nav li a:hover{color:#e15616}
 .navbar .search .search-control form{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;-webkit-box-align:center;-ms-flex-align:center;align-items:center}
-.navbar .search .search-control .search-input{display:block;width:272px;height:36px;padding:8px 16px;border:1px solid #e15616;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:2px 0 0 2px;color:#4a4f58}
+.navbar .search .search-control .search-input{display:block;width:272px;height:36px;padding:8px 16px;border:1px solid #e15616;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:2px 0 0 2px;color:#4a4f58;font-size: 14px;}
 .navbar .search .search-control .search-input::-webkit-input-placeholder{color:#9aa5b5;font-size:14px}
 .navbar .search .search-control .search-input::-moz-placeholder{color:#9aa5b5;font-size:14px}
 .navbar .search .search-control .search-input:-ms-input-placeholder{color:#9aa5b5;font-size:14px}

+ 55 - 32
src/main/resources/static/js/article/list.js

@@ -6,9 +6,9 @@ var requestUrlConfig = {
 
 var articleList = new Vue({
     el: '#articleList',
-    filters:{
-        keywordSlice: function(keyword){
-            return keyword.length > 6 ? keyword.slice(0,6) + '…' : keyword;
+    filters: {
+        keywordSlice: function (keyword) {
+            return keyword.length > 6 ? keyword.slice(0, 6) + '…' : keyword;
         }
     },
     data: {
@@ -63,9 +63,29 @@ var articleList = new Vue({
         this.$nextTick(function () {
             self.initQueryParam();
             self.initBase();
+            self.initAuthInputComplete();
         });
     },
+
     methods: {
+        // init auto-input complete
+        initAuthInputComplete(){
+            new AutoComplete({
+                el: '.auto-input',
+                callback: async function(keyword){
+                    try {
+                        const res = await PublicApi.fetchQueryKeywordList({keyword: keyword});
+                        if(!res.data) return [];
+                        return res.data.map(item => item.keyword);
+                    } catch (e) {
+                        console.log(e);
+                    }
+                },
+                itemClick: function (keyword) {
+                    window.location.href = '/info/search-1.html?keyword='+keyword;
+                }
+            });
+        },
         // 初始化链接参数
         initQueryParam() {
             if (isPC) {
@@ -143,8 +163,8 @@ var articleList = new Vue({
         },
 
         // 高亮关键词
-        highlightKeyword: function(str){
-            return str.replace(new RegExp(this.keyword, 'g'), '<span style="color: #E15616">'+ this.keyword +'</span>')
+        highlightKeyword: function (str) {
+            return str.replace(new RegExp(this.keyword, 'g'), '<span style="color: #E15616">' + this.keyword + '</span>')
         },
 
         // 获取文章列表
@@ -171,7 +191,7 @@ var articleList = new Vue({
                         });
                     });
                     // 处理标题和描述
-                    resultData = resultData.map(function (item){
+                    resultData = resultData.map(function (item) {
                         item.title = self.highlightKeyword(item.title);
                         item.intro = self.highlightKeyword(item.intro);
                         return item
@@ -281,53 +301,56 @@ var articleList = new Vue({
             })
         },
 
+        onPageScroll: debounce(function () {
+            var scrollTop = $('body').scrollTop();
+            var documentHeight = $(document).height();
+            var windowHeight = $('body').height();
+            // alert(scrollTop + windowHeight == documentHeight)
+            if (scrollTop > 600) {
+                $('#scrollTop').show();
+            } else {
+                $('#scrollTop').hide();
+            }
+            if (scrollTop + windowHeight + 100 > documentHeight) {
+                //此处是滚动条到底部时候触发的事件,在这里写要加载的数据,或者是拉动滚动条的操作
+                if (this.params.num < this.pageTotal) { // 获取列表数据
+                    if (this.requestFlag) {
+                        this.params.num = this.params.num + 1;
+                        this.requestAction(this.requestType);
+                    }
+                } else { //到底了
+                    this.noMore = true;
+                    $('footer').removeClass("noneImportant");
+                }
+            }
+        }),
+
         // 页面样式初始化
         initPageReset: function () {
-            var self = this;
             if (!isPC) {
                 $('footer').addClass("noneImportant");
                 //移动端上垃加载更多
-                $('body').on('scroll', function () {
-                    var scrollTop = $(this).scrollTop();
-                    var documentHeight = $(document).height();
-                    var windowHeight = $(this).height();
-                    // alert(scrollTop + windowHeight == documentHeight)
-                    if (scrollTop + windowHeight + 100 > documentHeight) {
-                        //此处是滚动条到底部时候触发的事件,在这里写要加载的数据,或者是拉动滚动条的操作
-                        var totalPage = Math.ceil(self.listRecord / self.params.size) ? Math.ceil(self.listRecord / self.params.size) : 1;
-                        self.params.num = self.params.num + 1;
-                        if (next <= totalPage) { // 获取列表数据
-                            if (self.requestFlag) {
-                                self.requestAction(self.requestType);
-                            }
-                            self.requestFlag = false;
-                        } else { //到底了
-                            self.noMore = false;
-                            $('footer').removeClass("noneImportant");
-                        }
-                    }
-                });
+                $('body').on('scroll', this.onPageScroll);
             }
         },
     }
 });
 
-function initFilterSort(option = {}){
+function initFilterSort(option = {}) {
     var sortControl = $(option.el);
     var sortItem = sortControl.find('.search__sort_select li');
     var sotrCurrent = sortControl.find('.search__sort_current');
 
-    $(window).on('click', function(el){
-        console.log(el);
+    $(window).on('click', function (el) {
         if (sortControl.has(el.target).length > 0) return;
         sortControl.removeClass('active');
     })
 
-    sortControl.on('click', function(){
+    sortControl.on('click', function () {
         $(this).toggleClass('active');
     })
 
-    sortItem.on('click', function(el){
+    sortItem.on('click', function (el) {
         $(this).addClass('selected').siblings('li').removeClass('selected');
         var status = parseInt($(this).attr('data-type'));
         console.log(status)

+ 205 - 0
src/main/resources/static/js/auto-input.js

@@ -0,0 +1,205 @@
+'use strict';
+
+class AutoComplete {
+    constructor(options) {
+        this.options = {
+            el: '#autoInput',
+            callback: (text) => [],
+            itemClick: () => {
+            },
+            itemTop: 'auto',
+            follow: 'container',
+            offsetTop: 5,
+            setValueFlag: true,
+        };
+        Object.assign(this.options, options);
+        this.handleInput = this.debounce(this.inputEvent).bind(this);
+        this.handleBlur = this.debounce(this.blurEvent).bind(this);
+        this.init();
+    }
+
+    /**
+     * 初始化dom
+     */
+    init() {
+        this.container = document.querySelector(this.options.el);
+        this.input = this.container.querySelector('input');
+        this.ul = document.createElement('ul');
+        this.ul.style.display = 'none';
+        this.container.appendChild(this.ul);
+        this.input.addEventListener('input', this.handleInput);
+        this.input.addEventListener('blur', this.handleBlur);
+        this.initStyle();
+    }
+
+    /**
+     * 初始化样式
+     */
+    initStyle() {
+        const containerStyle = getComputedStyle(this.container);
+        console.log(containerStyle.position);
+        if (containerStyle.position === 'static') {
+            this.container.style.position = 'relative';
+        }
+        if (this.options.itemTop === 'auto') {
+            const containerHeight = this.container.offsetHeight;
+            const inputHeight = this.input.offsetHeight;
+            const inputTop = this.input.offsetTop;
+            // const offset = containerHeight - inputHeight + inputTop - this.options.offsetTop;
+            this.ul.style.top = inputHeight + inputTop + this.options.offsetTop + 'px';
+        } else {
+            this.ul.style.top = this.options.itemTop;
+        }
+
+        if (this.options.follow === 'input') {
+            this.ul.style.left = this.input.offsetLeft + 'px';
+            this.ul.style.width = this.input.offsetWidth + 'px';
+        } else {
+            this.ul.style.left = 0;
+            this.ul.style.width = this.container.offsetWidth + 'px';
+        }
+
+        var style = document.createElement('style');
+        style.textContent = `
+        @media screen and (min-width: 768px) {
+            .auto-input ul{margin: 0;position:absolute;left:0;top:50px;width:50%;padding:8px 0;background:#fff; z-index: 999;box-shadow: 0px 6px 12px 1px rgba(0,0,0,0.1);max-height: 420px;overflow-y:auto;}
+            .auto-input ul::-webkit-scrollbar { width: 8px; background-color: #fff;}
+            .auto-input ul::-webkit-scrollbar-thumb { border-radius: 4px; background-color: #e2e2e2;}
+            .auto-input ul li{padding:0 16px;font-size:14px;line-height:36px;height:36px;color:#2c3e50;user-select: none;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}
+            .auto-input ul li:hover{background:#FEF6F3;}
+        }
+        @media screen and (max-width: 768px) {
+            .auto-input ul{margin: 0;position:absolute;left:0;top:5vw;width:50%;padding:2.4vw 0;background:#fff; z-index: 999;box-shadow: 0px 0.6vw 1.2vw 0.1vw rgba(0,0,0,0.1);max-height:82vw;overflow-y:auto;}
+            .auto-input ul::-webkit-scrollbar { width: 1.6vw; background-color: #fff;}
+            .auto-input ul::-webkit-scrollbar-thumb { border-radius: 0.8vw; background-color: #e2e2e2;}
+            .auto-input ul li{padding:0 3.2vw;font-size:3.4vw;line-height:8vw;height:8vw;color:#2c3e50;user-select: none;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}
+            .auto-input ul li:hover{background:#ecf0f1;}
+        }
+        `
+        this.container.appendChild(style);
+    }
+
+    /**
+     * 输入框input事件
+     */
+    async inputEvent(e) {
+        this.keyword = e.target.value;
+        this.list = await this.options.callback(this.keyword);
+        if (!(this.list instanceof Array)) {
+            throw Error('callback result mast an array');
+        }
+        this.ul.innerHTML = '';
+        this.renderList();
+        this.ul.style.display = this.list.length > 0 ? 'block' : 'none';
+    }
+
+    /**
+     * 输入框blur事件
+     */
+    blurEvent() {
+        this.ul.style.display = 'none';
+    }
+
+    /**
+     * 渲染列表
+     */
+    renderList() {
+        this.list.forEach((text) => {
+            const li = document.createElement('li');
+            li.innerHTML = text.replace(this.keyword, '<span style="color: #E15616;">' + this.keyword + '</span>');
+            li.addEventListener('click', () => this.listItemClick(text));
+            this.ul.appendChild(li);
+        });
+    }
+
+    /**
+     * 列表元素点击事件
+     */
+    listItemClick(text) {
+        if(this.options.setValueFlag){
+            this.input.value = text;
+        }
+        this.ul.innerHTML = '';
+        this.ul.style.display = 'none';
+        this.options.itemClick(text);
+    }
+
+    /**
+     * 防抖
+     */
+    debounce(func, wait = 400, immediate = false) {
+        let timeout, result;
+        return function () {
+            const context = this;
+            const args = arguments;
+            if (timeout) clearTimeout(timeout);
+            if (immediate) {
+                const callNow = !timeout;
+                timeout = setTimeout(function () {
+                    timeout = null;
+                }, wait);
+                if (callNow) result = func.apply(context, args);
+            } else {
+                timeout = setTimeout(function () {
+                    func.apply(context, args);
+                }, wait);
+            }
+            return result;
+        };
+    }
+}
+
+// test
+// function autocomplete(text) {
+//     return [
+//         '三全鲜食(北新泾店)',
+//         'Hot honey 首尔炸鸡(仙霞路)',
+//         '新旺角茶餐厅',
+//         '泷千家(天山西路店)',
+//         '胖仙女纸杯蛋糕(上海凌空店)',
+//         '贡茶',
+//         '豪大大香鸡排超级奶爸',
+//         '茶芝兰(奶茶,手抓饼)',
+//         '十二泷町',
+//         '星移浓缩咖啡',
+//         '阿姨奶茶/豪大大',
+//         '新麦甜四季甜品炸鸡',
+//         'Monica摩托主题咖啡店',
+//         '浮生若茶(凌空soho店)',
+//         'NONO JUICE  鲜榨果汁',
+//         'CoCo都可(北新泾店)',
+//         '快乐柠檬(神州智慧店)',
+//         'Merci Paul cafe',
+//         '猫山王(西郊百联店)',
+//         '枪会山',
+//         '纵食',
+//         '钱记',
+//         '壹杯加',
+//         '唦哇嘀咖',
+//         '爱茜茜里(西郊百联)',
+//         '爱茜茜里(近铁广场)',
+//         '鲜果榨汁(金沙江路和美广店)',
+//         '开心丽果(缤谷店)',
+//         '超级鸡车(丰庄路店)',
+//         '妙生活果园(北新泾店)',
+//         '香宜度麻辣香锅',
+//         '凡仔汉堡(老真北路店)',
+//         '港式小铺',
+//         '蜀香源麻辣香锅(剑河路店)',
+//         '北京饺子馆',
+//         '饭典*新简餐(凌空SOHO店)',
+//         '焦耳·川式快餐(金钟路店)',
+//         '动力鸡车',
+//         '浏阳蒸菜',
+//         '四海游龙(天山西路店)',
+//         '樱花食堂(凌空店)',
+//         '壹分米客家传统调制米粉(天山店)',
+//         '福荣祥烧腊(平溪路店)',
+//         '速记黄焖鸡米饭',
+//         '红辣椒麻辣烫',
+//         '(小杨生煎)西郊百联餐厅',
+//         '阳阳麻辣烫',
+//         '南拳妈妈龙虾盖浇饭',
+//     ].filter((item) => text && item.indexOf(text) > -1);
+// }
+

+ 46 - 1
src/main/resources/static/js/base.js

@@ -223,7 +223,26 @@ var globalHead = new Vue({
             if(!isPC){
                 $("#mGlobalMenu").hide().find(".cShow").hide();
             }
-        }
+        },
+
+        // init auto-input complete
+        initAuthInputComplete(){
+            new AutoComplete({
+                el: '.auto-input',
+                callback: async function(keyword){
+                    try {
+                        const res = await PublicApi.fetchQueryKeywordList({keyword: keyword});
+                        if(!res.data) return [];
+                        return res.data.map(item => item.keyword);
+                    } catch (e) {
+                        console.log(e);
+                    }
+                },
+                itemClick: function (keyword) {
+                    window.location.href = '/product/list.html?keyword='+keyword;
+                }
+            });
+        },
     },
     created: function () {
         var _self = this;
@@ -293,6 +312,7 @@ var globalHead = new Vue({
                 });
             }
         },500);
+        this.initAuthInputComplete();
     }
 });
 // 初始化效果
@@ -904,3 +924,28 @@ function param(json) {
         })
     ).join('&')
 }
+
+
+/**
+ * 防抖
+ */
+function debounce(func, wait = 200, immediate = false) {
+    let timeout, result;
+    return function () {
+        const context = this;
+        const args = arguments;
+        if (timeout) clearTimeout(timeout);
+        if (immediate) {
+            const callNow = !timeout;
+            timeout = setTimeout(function () {
+                timeout = null;
+            }, wait);
+            if (callNow) result = func.apply(context, args);
+        } else {
+            timeout = setTimeout(function () {
+                func.apply(context, args);
+            }, wait);
+        }
+        return result;
+    };
+}

+ 9 - 0
src/main/resources/static/js/common/serviceapi/utils.service.js

@@ -4,6 +4,15 @@
  * auther ZHJY
  */
 var PublicApi = {
+        // 获取搜索关键词
+        fetchQueryKeywordList: function(params){
+            return Http.AjaxService({
+                url:'/commodity/search/query/get/keyword/list',
+                type:'post',
+                data:params,
+                json:false,
+            })
+        },
         // oss 初始化 (临时凭证获取)
         fetchOssInitData: function(params){
             return Http.AjaxService({

+ 22 - 0
src/main/resources/static/js/document/beauty-archive.js

@@ -48,6 +48,7 @@ var beautyArchive = new Vue({
     },
     mounted() {
         this.getList();
+        this.initAuthInputComplete();
     },
     computed: {
         loadingText: function () {
@@ -82,6 +83,27 @@ var beautyArchive = new Vue({
         }
     },
     methods: {
+        // init auto-input complete
+        initAuthInputComplete(){
+            var _self = this;
+            new AutoComplete({
+                el: '.auto-input',
+                setValueFlag: false,
+                callback: async function(keyword){
+                    try {
+                        const res = await PublicApi.fetchQueryKeywordList({keyword: keyword});
+                        if(!res.data) return [];
+                        return res.data.map(item => item.keyword);
+                    } catch (e) {
+                        console.log(e);
+                    }
+                },
+                itemClick: function (keyword) {
+                    _self.keyword = keyword;
+                    _self.handleSearch(keyword);
+                }
+            });
+        },
         //页码跳转
         toPagination: function (pageNum) {
             if (pageNum > this.totalPage || pageNum <= 0) {

+ 18 - 0
src/main/resources/static/js/encyclopedia/common.js

@@ -396,4 +396,22 @@ $(function () {
         searchKeyword.val(val);
         if(!val) return false;
     });
+
+    // init auto-input complete
+    new AutoComplete({
+        el: '.auto-input',
+        setValueFlag: true,
+        callback: async function(keyword){
+            try {
+                const res = await PublicApi.fetchQueryKeywordList({keyword: keyword});
+                if(!res.data) return [];
+                return res.data.map(item => item.keyword);
+            } catch (e) {
+                console.log(e);
+            }
+        },
+        itemClick: function (keyword) {
+            window.location.href = '/encyclopedia/search.html?keyword=' + keyword;
+        }
+    });
 });

+ 2 - 2
src/main/resources/templates/article/components/article-header.html

@@ -17,8 +17,8 @@
             </div>
         </div>
         <!--搜索-->
-        <div class="search" id="topSearch">
-            <input class="keyword" type="text" placeholder="请输入关键词" />
+        <div class="search auto-input" id="topSearch">
+            <input class="keyword" type="text" placeholder="请输入关键词" autocomplete="off" />
             <a class="searchBtn icon" href="javascript:void(0);"></a>
         </div>
     </div>

+ 1 - 1
src/main/resources/templates/article/list.html

@@ -98,7 +98,7 @@
                 <p class="nofound">很抱歉,没有找到 “<span v-text="params.keyword"></span>” 相关结果!</p>
                 <p class="change">请修改或者尝试其他搜索词</p>
             </div>
-            <div v-if="(!isPC) && noMore" class="noMore">---- 没有更多了 ----</div>
+            <div v-if="(!isPC) && noMore" class="no-more">---- 没有更多了 ----</div>
             <!--分页-->
             <div v-if="isPC && pageTotal>1" class="pageWrap clear">
                 <a v-if="params.num>1" class="prev" :href="paginationUrl(params.num*1-1)"></a>

+ 1 - 0
src/main/resources/templates/components/foot-link.html

@@ -9,4 +9,5 @@
 <script charset="utf-8" type="text/javascript" th:src="@{/js/common/serviceapi/utils.service.js(v=${version})}"></script>
 <script charset="utf-8" type="text/javascript" th:src="@{/js/common/serviceapi/shopping.service.js(v=${version})}"></script>
 <script charset="utf-8" type="text/javascript" th:src="@{/js/utils.js(v=${version})}"></script>
+<script charset="utf-8" type="text/javascript" th:src="@{/js/auto-input.js(v=${version})}"></script>
 <script charset="utf-8" type="text/javascript" th:src="@{/js/base.js(v=${version})}"></script>

+ 1 - 1
src/main/resources/templates/components/header.html

@@ -80,7 +80,7 @@
                 </template>
             </div>
             <div class="searchBox" id="topSearch">
-                <div class="search">
+                <div class="search auto-input" id="autoInput">
                     <div class="jqSelect">
                         <div class="pc">
                             <span data-select="0">产品</span>

+ 3 - 1
src/main/resources/templates/document/beauty-archive.html

@@ -18,7 +18,7 @@
             <div class="cm-container cm-clearfix">
                 <div class="cm-fl cm-title" v-if="isPC">美业资料</div>
                 <div class="cm-fr">
-                    <div class="cm-search">
+                    <div class="cm-search auto-input">
                         <input class="cm-keyword" v-model="keyword" placeholder="请输入商品名称/供应商名" @keyup.enter="handleSearch(keyword)" type="text"/>
                         <a href="javascript:void(0)" @click="handleSearch(keyword)" class="cm-search-btn icon"></a>
                     </div>
@@ -99,8 +99,10 @@
 <script charset="utf-8" type="text/javascript" src="/lib/jquery-3.6.0.min.js"></script>
 <script charset="utf-8" type="text/javascript" src="/lib/lazyload.js"></script>
 <script charset="utf-8" type="text/javascript" th:src="@{/js/common/ajax.service.js(v=${version})}"></script>
+<script charset="utf-8" type="text/javascript" th:src="@{/js/common/serviceapi/utils.service.js(v=${version})}"></script>
 <script charset="utf-8" type="text/javascript"
         th:src="@{/js/common/serviceapi/beautyArchive.service.js(v=${version})}"></script>
+<script charset="utf-8" type="text/javascript" th:src="@{/js/auto-input.js(v=${version})}"></script>
 <script charset="utf-8" type="text/javascript" th:src="@{/js/document/beauty-archive.js(v=${version})}"></script>
 
 </body>

+ 3 - 0
src/main/resources/templates/encyclopedia/components/footer.html

@@ -13,4 +13,7 @@
 </footer>
 <!-- 底部公共js -->
 <script src="/lib/jquery-3.6.0.min.js"></script>
+<script charset="utf-8" type="text/javascript" th:src="@{/js/common/ajax.service.js(v=${version})}"></script>
+<script charset="utf-8" type="text/javascript" th:src="@{/js/common/serviceapi/utils.service.js(v=${version})}"></script>
+<script th:src="@{/js/auto-input.js(v=${version})}" xmlns:th="https://www.thymeleaf.org"></script>
 <script th:src="@{/js/encyclopedia/common.js(v=${version})}" xmlns:th="https://www.thymeleaf.org"></script>

+ 2 - 2
src/main/resources/templates/encyclopedia/components/header.html

@@ -20,9 +20,9 @@
             <li><span class="nav-close" id="#menuColseBtn"></span></li>
         </ul>
         <div class="search">
-            <div class="search-control">
+            <div class="search-control auto-input">
                 <form action="search.html">
-                    <input type="text" id="searchKeyword" class="search-input" name="keyword" placeholder="请输入产品/仪器名称"/>
+                    <input type="text" id="searchKeyword" class="search-input" name="keyword" placeholder="请输入产品/仪器名称" autocomplete="off"/>
                     <button class="search-btn">搜索</button>
                 </form>
                 <button class="hot-keyword" id="hotKeyword" data-target="#hotKeywords">热搜词</button>