Browse Source

关键词库

yuwenjun1997 2 years ago
parent
commit
f0ef2686fe
3 changed files with 274 additions and 163 deletions
  1. 173 0
      pages/search/components/search-header.vue
  2. 64 150
      pages/search/search-library.vue
  3. 37 13
      pages/search/search.vue

+ 173 - 0
pages/search/components/search-header.vue

@@ -0,0 +1,173 @@
+<template>
+    <view class="search-header">
+        <view class="search-container">
+            <view class="search-tab" @click="showBubblePopup = true">
+                <text v-text="menuName"></text>
+                <text class="iconfont icon-xiangxiajiantou"></text>
+            </view>
+            <view class="search-control">
+                <text class="iconfont icon-sousuo"></text>
+                <input
+                    class="control"
+                    type="text"
+                    :value="value"
+                    placeholder="请输入搜索关键字"
+                    @confirm="$emit('search', value)"
+                    @input="event => $emit('input', event.detail.value)"
+                    @blur="$emit('blur')"
+                />
+                <text class="iconfont icon-shanchu1" v-show="showClearBtn" @click="$emit('clear')"></text>
+            </view>
+            <view class="search-submit" @click="$emit('search', value)">搜索</view>
+        </view>
+
+        <!-- 下拉菜单 -->
+        <tui-bubble-popup
+            :show="showBubblePopup"
+            :mask="true"
+            position="fixed"
+            direction="top"
+            width="140rpx"
+            left="10rpx"
+            top="80rpx"
+            triangleRight="60rpx"
+            triangleTop="-22rpx"
+            maskBgColor="rgba(0,0,0,0)"
+            @close="showBubblePopup = false"
+        >
+            <view class="bubble-popup-container">
+                <view
+                    class="menu-item"
+                    v-for="(item, index) in menuList"
+                    :key="index"
+                    @click="onMenuItemClick(index)"
+                    v-text="item.name"
+                ></view>
+            </view>
+        </tui-bubble-popup>
+    </view>
+</template>
+
+<script>
+export default {
+    props: {
+        value: {
+            type: String,
+            default: ''
+        },
+        menuList: {
+            type: Array,
+            default: () => []
+        },
+        currentMenu: {
+            type: Number,
+            default: 0
+        }
+    },
+    model: {
+        event: 'input',
+        prop: 'value'
+    },
+    data() {
+        return {
+            showBubblePopup: false
+        }
+    },
+    computed: {
+        // 当前选中菜单
+        menuName() {
+            return this.menuList[this.currentMenu].name
+        },
+        // 显示输入框clear按钮
+        showClearBtn() {
+            return this.value.length > 0
+        }
+    },
+    methods: {
+        // menu-item 点击事件
+        onMenuItemClick(index) {
+            this.showBubblePopup = false
+            this.$emit('menuClick', index)
+        },
+
+        cursor() {}
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.search-header {
+    position: relative;
+    z-index: 9;
+}
+
+.search-container {
+    width: 100%;
+    box-sizing: border-box;
+    padding: 10rpx 24rpx;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    height: 86rpx;
+    background: #fff;
+
+    .search-tab {
+        font-size: 30rpx;
+        color: #666;
+        flex-shrink: 0;
+
+        .icon-xiangxiajiantou {
+            font-size: 34rpx;
+            color: #666;
+            margin-left: 10rpx;
+        }
+    }
+    .search-control {
+        width: 473rpx;
+        height: 100%;
+        background: #f7f7f7;
+        border-radius: 33rpx;
+        box-sizing: border-box;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .icon-sousuo {
+            display: block;
+            width: 36rpx;
+            margin-left: 32rpx;
+            margin-right: 16rpx;
+            flex-shrink: 0;
+            color: #999999;
+        }
+
+        .icon-shanchu1 {
+            width: 36rpx;
+            margin: 0 12rpx;
+            flex-shrink: 0;
+            color: #999999;
+        }
+
+        .control {
+            flex: 1;
+            height: 100%;
+            font-size: 28rpx;
+            color: #333333;
+        }
+    }
+    .search-submit {
+        font-size: 30rpx;
+        color: #e15616;
+        flex-shrink: 0;
+    }
+}
+
+.bubble-popup-container {
+    padding: 10rpx 0;
+    .menu-item {
+        text-align: center;
+        line-height: 60rpx;
+        font-size: 28rpx;
+    }
+}
+</style>

+ 64 - 150
pages/search/search-library.vue

@@ -1,27 +1,22 @@
 <template>
-    <view class="search-library">
+    <view class="search-library" :class="{ unScorll: showLibaray }">
         <!-- 搜索框区域 -->
         <view class="sticky-container">
-            <view class="search-container">
-                <view class="search-tab" @click="showBubblePopup = true">
-                    <text v-text="currentMenu.name"></text>
-                    <text class="iconfont icon-xiangxiajiantou"></text>
-                </view>
-                <view class="search-control">
-                    <text class="iconfont icon-sousuo"></text>
-                    <input
-                        class="control"
-                        type="text"
-                        v-model.trim="keyword"
-                        placeholder="请输入搜索关键字"
-                        @confirm="onSearch"
-                        @input="onInput"
-                        @blur="onBlur"
-                    />
-                    <text class="iconfont icon-shanchu1" v-show="showClearBtn" @click="onClear"></text>
-                </view>
-                <view class="search-submit" @click="onSearch">搜索</view>
-            </view>
+            <search-header
+                :menuList="menuItemList"
+                :currentMenu="currentMenu"
+                v-model="keyword"
+                @clear="
+                    onClear()
+                    hideLibrary()
+                "
+                @search="
+                    onSearch()
+                    hideLibrary()
+                "
+                @input="onInput"
+                @menuClick="onMenuItemClick"
+            ></search-header>
             <!-- 搜索分类区域 -->
             <view class="search-category">
                 <tui-tabs
@@ -57,7 +52,7 @@
             ></image>
             <text class="empty-text">抱歉,没有{{ currentTabItem.name }}!</text>
         </view>
-        <!-- 列表底部显示 -->
+        <!-- 加载 loading -->
         <template v-if="!isListEmpty">
             <tui-loadmore :index="2" :visible="isLoading"></tui-loadmore>
             <tui-nomore
@@ -67,38 +62,24 @@
             ></tui-nomore>
         </template>
 
-        <!-- 搜索设备分类 -->
-        <tui-bubble-popup
-            :show="showBubblePopup"
-            :mask="true"
-            position="fixed"
-            direction="top"
-            width="140rpx"
-            left="10rpx"
-            top="80rpx"
-            triangleRight="60rpx"
-            triangleTop="-22rpx"
-            maskBgColor="rgba(0,0,0,0)"
-            @close="showBubblePopup = false"
-        >
-            <view class="bubble-popup-container">
-                <view
-                    class="menu-item"
-                    v-for="item in menuItemList"
-                    :key="item.id"
-                    @click="onMenuItemClick(item)"
-                    v-text="item.name"
-                ></view>
-            </view>
-        </tui-bubble-popup>
         <!-- 搜索关键词库提示 -->
-        <view class="search-library" v-show="showLibaray">
-            <div class="search-library-wrapper">
-                <view class="keyword-item" v-for="item in libraryWordList" :key="item" @click="onLibraryClick(item)">
-                    <text class="iconfont icon-sousuo"></text>
-                    <view class="content" v-html="item.text"></view>
-                </view>
-            </div>
+        <view class="search-library-container" v-show="showLibaray">
+            <scroll-view scroll-y="true" class="search-library-scroll">
+                <div class="search-library-wrapper">
+                    <view
+                        class="keyword-item"
+                        v-for="item in libraryWordList"
+                        :key="item"
+                        @click="
+                            onLibraryClick(item)
+                            hideLibrary()
+                        "
+                    >
+                        <text class="iconfont icon-sousuo"></text>
+                        <view class="content" v-html="item.text"></view>
+                    </view>
+                </div>
+            </scroll-view>
         </view>
 
         <!-- 商品筛选框 -->
@@ -114,6 +95,7 @@ import ArticleList from './components/article-list.vue'
 import MaterialList from './components/material-list.vue'
 import EncyclopediaList from './components/encyclopedia-list.vue'
 import ProductFilter from './components/product-filter.vue'
+import SearchHeader from './components/search-header.vue'
 import { debounce } from '@/common/config/common'
 import { mapGetters } from 'vuex'
 const myDebounce = fn => debounce(fn, 200, false)
@@ -124,22 +106,21 @@ export default {
         ArticleList,
         MaterialList,
         EncyclopediaList,
-        ProductFilter
+        ProductFilter,
+        SearchHeader
     },
     data() {
         const menuItemList = [{ id: 1, name: '产品' }, { id: 2, name: '供应商' }]
-        const currentMenu = menuItemList[0]
         const tabs = [{ name: '相关产品' }, { name: '相关文章' }, { name: '相关资料' }, { name: '相关百科' }]
         return {
             // 容器相关
-            showLibaray: false,
-            showBubblePopup: false,
+            tabs: tabs,
+            currentTab: 0,
             menuItemList: menuItemList,
-            currentMenu: currentMenu,
+            currentMenu: 0,
             keyword: '',
+            showLibaray: false,
             libraryWordList: [],
-            tabs: tabs,
-            currentTab: 0,
             isLoading: true,
             // 用户信息
             userInfo: {
@@ -207,10 +188,7 @@ export default {
     },
     computed: {
         ...mapGetters(['identity']),
-        // 显示输入框clear按钮
-        showClearBtn() {
-            return this.keyword.length > 0
-        },
+
         // 当前选中tab
         currentTabItem() {
             return this.tabs[this.currentTab]
@@ -383,7 +361,7 @@ export default {
                 this.fetchProductPrice(result.items)
                 this.productListQuery.pageNum++
             } catch (e) {
-                console.log(e)
+                this.isLoading = false
             }
         }),
 
@@ -482,7 +460,7 @@ export default {
                     this.libraryWordList = []
                 }
                 this.libraryWordList = res.data.map(item => {
-                    item.text = item.keyword.replace(keyword, `<span sytle="color:#E15616;">${keyword}</span>`)
+                    item.text = item.keyword.replace(keyword, `<span style="color:#E15616;">${keyword}</span>`)
                     return item
                 })
                 if (this.libraryWordList.length <= 0) return
@@ -499,9 +477,8 @@ export default {
         },
 
         // menu-item 点击事件
-        onMenuItemClick(item) {
-            this.currentMenu = item
-            this.showBubblePopup = false
+        onMenuItemClick(index) {
+            this.currentMenu = index
         },
 
         // tab 切换
@@ -512,11 +489,10 @@ export default {
 
         // 搜索
         onSearch: myDebounce(function() {
-            if (this.currentMenu.id === 1) {
-                this.initList()
-            } else {
-                this.$api.navigateTo(`/pages/search/search-supplier?keyWord=${this.keyword}`)
+            if (this.currentMenu === 0) {
+                return this.initList()
             }
+            this.$api.navigateTo(`/pages/search/search-supplier?keyWord=${this.keyword}`)
         }),
 
         // 清空搜索框
@@ -524,16 +500,14 @@ export default {
             this.keyword = ''
         },
 
-        // 失去焦点
-        onBlur() {
-            setTimeout(() => {
-                this.showLibaray = false
-            }, 200)
-        },
-
         // 用户输入
         onInput() {
             this.fetchLibraryWordList()
+        },
+
+        // 隐藏library list
+        hideLibrary() {
+            this.showLibaray = false
         }
     }
 }
@@ -544,6 +518,11 @@ export default {
     min-height: 100vh;
     background: #f5f5f5;
 
+    &.unScorll {
+        height: 100vh;
+        overflow: hidden;
+    }
+
     .sticky-container {
         position: sticky;
         width: 100%;
@@ -553,66 +532,6 @@ export default {
         background: #f5f5f5;
     }
 
-    .search-container {
-        width: 100%;
-        box-sizing: border-box;
-        padding: 10rpx 24rpx;
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-        height: 86rpx;
-        background: #fff;
-
-        .search-tab {
-            font-size: 30rpx;
-            color: #666;
-            flex-shrink: 0;
-
-            .icon-xiangxiajiantou {
-                font-size: 34rpx;
-                color: #666;
-                margin-left: 10rpx;
-            }
-        }
-        .search-control {
-            width: 473rpx;
-            height: 100%;
-            background: #f7f7f7;
-            border-radius: 33rpx;
-            box-sizing: border-box;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-
-            .icon-sousuo {
-                display: block;
-                width: 36rpx;
-                margin-left: 32rpx;
-                margin-right: 16rpx;
-                flex-shrink: 0;
-                color: #999999;
-            }
-
-            .icon-shanchu1 {
-                width: 36rpx;
-                margin: 0 12rpx;
-                flex-shrink: 0;
-                color: #999999;
-            }
-
-            .control {
-                flex: 1;
-                height: 100%;
-                font-size: 28rpx;
-                color: #333333;
-            }
-        }
-        .search-submit {
-            font-size: 30rpx;
-            color: #e15616;
-            flex-shrink: 0;
-        }
-    }
     .search-category {
         padding: 20rpx 0;
         background: #fff;
@@ -642,16 +561,7 @@ export default {
         }
     }
 
-    .bubble-popup-container {
-        padding: 10rpx 0;
-        .menu-item {
-            text-align: center;
-            line-height: 60rpx;
-            font-size: 28rpx;
-        }
-    }
-
-    .search-library {
+    .search-library-container {
         position: fixed;
         top: 86rpx;
         left: 0;
@@ -660,6 +570,10 @@ export default {
         height: calc(100vh - 88rpx);
         background: #f5f5f5;
 
+        .search-library-scroll {
+            height: 95%;
+        }
+
         .search-library-wrapper {
             background: #fff;
             padding-top: 40rpx;

+ 37 - 13
pages/search/search.vue

@@ -1,5 +1,5 @@
 <template>
-    <view class="search-container">
+    <view class="search-container" :class="{ unScorll: showLibaray }">
         <view class="search-main">
             <view class="tui-header-tab">
                 <view class="search-tab">
@@ -120,12 +120,19 @@
         </view>
         <!-- 搜索关键词库提示 -->
         <view class="search-library" v-show="showLibaray && userIdentity === 1">
-            <div class="search-library-wrapper">
-                <view class="keyword-item" v-for="item in libraryWordList" :key="item" @click="onLibraryClick(item)">
-                    <text class="iconfont icon-sousuo"></text>
-                    <view class="content" v-html="item.text"></view>
-                </view>
-            </div>
+            <scroll-view scroll-y="true" class="search-library-scroll">
+                <div class="search-library-wrapper">
+                    <view
+                        class="keyword-item"
+                        v-for="item in libraryWordList"
+                        :key="item"
+                        @click="onLibraryClick(item)"
+                    >
+                        <text class="iconfont icon-sousuo"></text>
+                        <view class="content" v-html="item.text"></view>
+                    </view>
+                </div>
+            </scroll-view>
         </view>
         <!-- 搜索历史记录 -->
         <view class="search-container-history" v-if="!isShowWrapper">
@@ -593,9 +600,10 @@ export default {
                     this.libraryWordList = []
                 }
                 this.libraryWordList = res.data.map(item => {
-                    item.text = item.keyword.replace(keyword, `<span sytle="color:#E15616;">${keyword}</span>`)
+                    item.text = item.keyword.replace(keyword, `<span style="color:#E15616;">${keyword}</span>`)
                     return item
                 })
+                if (this.libraryWordList.length <= 0) return
                 this.showLibaray = true
             } catch (e) {
                 console.log(e)
@@ -604,6 +612,7 @@ export default {
 
         // 关键词点击
         onLibraryClick(item) {
+            this.showLibaray = false
             uni.navigateTo({
                 url: `/pages/search/search-library?keyword=${item.keyword}`
             })
@@ -611,9 +620,9 @@ export default {
 
         // 失去焦点
         onBlur() {
-            setTimeout(() => {
-                this.showLibaray = false
-            }, 200)
+            // setTimeout(() => {
+            //     this.showLibaray = false
+            // }, 200)
         },
 
         async initGetStotage(option) {
@@ -677,6 +686,7 @@ export default {
                 })
         },
         subMitSearch() {
+            this.showLibaray = false
             //搜索
             if (this.listQuery.keyword == '') {
                 this.$util.msg('请输入搜索关键词', 2000)
@@ -731,7 +741,10 @@ export default {
             this.ProductService.GetProductSearchList(this.listQuery)
                 .then(response => {
                     this.isShowWrapper = true
-                    const resData = JSON.parse(response.data)
+                    let resData = {}
+                    if (response.data) {
+                        resData = JSON.parse(response.data)
+                    }
                     const resList = resData.items
                     if (resList && resList.length > 0) {
                         this.total = resData.total
@@ -929,6 +942,7 @@ export default {
             this.isShowWrapper = false
             this.inputEmpty(this.listQuery.keyword)
             this.initGetSerachRecord()
+            this.showLibaray = false
         },
         keywordsClick(item) {
             //关键词搜索与历史搜索
@@ -1172,13 +1186,19 @@ page {
             line-height: 70rpx;
             float: right;
             text-align: center;
-            color: #E15616;
+            color: #e15616;
             font-size: 30rpx;
         }
     }
 }
 .search-container {
     padding-top: 89rpx;
+
+    &.unScorll {
+        height: 100vh;
+        overflow: hidden;
+        box-sizing: border-box;
+    }
 }
 /*screen*/
 .tui-header-screen {
@@ -1791,6 +1811,10 @@ page {
     width: 100vw;
     height: calc(100vh - 88rpx);
     background: #f5f5f5;
+    
+    .search-library-scroll {
+        height: 95%;
+    }
 
     .search-library-wrapper {
         background: #fff;