shish 5 hónapja
szülő
commit
a29eda5230

+ 201 - 5
ghsPad/src/pages/home/components/rightItem.vue

@@ -1,10 +1,31 @@
 <template>
-    <view class="shop-listType_box">
+    <view class="shop-listType_box" @click="handlePageClick">
+        <!-- 搜索框(固定在上侧) -->
+        <view v-if="showSearchBox" class="search-box-fixed" @click.stop>
+            <view class="search-input-wrapper">
+                <text class="search-icon">🔍</text>
+                <input 
+                    v-model="searchKeyword" 
+                    class="search-input" 
+                    placeholder="输入中文搜索"
+                    @input="handleSearch"
+                    @confirm="handleSearch"
+                    @focus="clearSearch"
+                    autofocus
+                />
+                <text v-if="searchKeyword" class="clear-icon" @click="clearSearch">✕</text>
+                <text class="close-search-box" @click="closeSearchBox">✕</text>
+            </view>
+        </view>
+
         <view class="cat-list-area">
-            <view v-for="item in globalRightItemClass" :key="item.id" :class="[globalRightItemCategoryId===item.id?'active':'']" @click="globalChangeCategory(item)" > {{item.name}} </view>
+            <view v-for="item in globalRightItemClass" :key="item.id" :class="[globalRightItemCategoryId===item.id?'active':'']" @click="handleCategoryClick(item)" > {{item.name}} </view>
         </view>
         <view class="shop-show_box">
-            <view v-for="item in globalRightItemInfloList" :key="item.id" class="show-shop_box">
+            <view v-if="filteredItemList.length === 0" class="no-data-tip">
+                <text>{{ searchKeyword ? '未找到相关花材' : '暂无花材' }}</text>
+            </view>
+            <view v-for="item in filteredItemList" :key="item.id" class="show-shop_box">
                 <view class="item-detail" @click="popAddModelFn(item)">
                     <image class="img" :src="item.cover" lazy-load="true" :lazy-load-margin="0" mode="scaleToFill" ></image>
                     <!-- 多颜色类型标识 -->
@@ -22,6 +43,11 @@
         </view>
         <slot name="footer"></slot>
 
+        <!-- 搜索按钮(浮动圆圈) -->
+        <view class="search-fab" @click.stop="toggleSearchBox">
+            <text class="search-fab-icon">🔍</text>
+        </view>
+
         <!-- 开单选花材输入数量和金额 -->
         <uni-popup ref="selectNumPriceRef" background-color="#fff" type="center" :animation="false">
             <selectNum v-if="currentJobType=='make'" @confirmAddItemModel="confirmAddItemModel" :customData.sync="customData" @cancelKdSelectNumPrice="addItemModelHidden"></selectNum>
@@ -47,7 +73,9 @@ export default {
     data(){
         return {
             currentJobType:'bill',
-            currentJobId:0
+            currentJobId:0,
+            searchKeyword:'',
+            showSearchBox:false
         }
     },
 	props: {
@@ -73,6 +101,30 @@ export default {
 	created(){
 		this.listenScanItem()
     },
+    computed:{
+        filteredItemList(){
+            if(!this.searchKeyword.trim()){
+                return this.globalRightItemInfloList || []
+            }
+            // 按花材名称搜索,不区分大小写,搜索所有分类
+            const keyword = this.searchKeyword.toLowerCase().trim()
+            let allItems = []
+            
+            // 从所有分类中收集花材
+            if(this.globalRightAllItemInfo && typeof this.globalRightAllItemInfo === 'object'){
+                for(let categoryId in this.globalRightAllItemInfo){
+                    const categoryItems = this.globalRightAllItemInfo[categoryId]
+                    if(Array.isArray(categoryItems)){
+                        allItems = allItems.concat(categoryItems)
+                    }
+                }
+            }
+            
+            return allItems.filter(item => {
+                return item.name && item.name.toLowerCase().includes(keyword)
+            })
+        }
+    },
     watch:{
         customId:{
             handler(id){
@@ -98,6 +150,30 @@ export default {
     methods:{
         addToClear(){
             this.$msg('请扫码打开')
+        },
+        handlePageClick(){
+            // 点击页面任何地方时隐藏搜索框
+            if(this.showSearchBox){
+                this.closeSearchBox()
+            }
+        },
+        handleCategoryClick(item){
+            // 点击分类时清空搜索框
+            this.searchKeyword = ''
+            // 调用原来的分类切换方法
+            this.globalChangeCategory(item)
+        },
+        toggleSearchBox(){
+            this.showSearchBox = !this.showSearchBox
+        },
+        closeSearchBox(){
+            this.showSearchBox = false
+        },
+        handleSearch(){
+            // 搜索过程中自动过滤,计算属性会自动更新filteredItemList
+        },
+        clearSearch(){
+            this.searchKeyword = ''
         },
 		popAddModelFn(info) {
             this.$util.hitVoice()
@@ -124,6 +200,9 @@ export default {
     display: flex;
     flex-direction: column;
     box-sizing: border-box;
+    position: relative;
+    overflow: hidden;
+    
     & .shop-show_box{
         display:flex;
         justify-content:space-around;
@@ -201,11 +280,20 @@ export default {
     }
     & .shop-show_box {
         flex: 1;
-        padding: 2upx;
+        padding: 2upx 2upx 50upx 2upx;
         display: flex;
         flex-wrap: wrap;
         overflow-y: scroll;
         overflow-x: hidden;
+        & .no-data-tip {
+            width: 100%;
+            height: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-size: 14upx;
+            color: #999;
+        }
     }
     & .shop-footer_box {
         height: 40upx;
@@ -257,5 +345,113 @@ export default {
             color: #ffffff;
         }
     }
+
+    /* 搜索框(固定在顶部) */
+    & .search-box-fixed {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        background-color: #ffffff;
+        border-bottom: 1upx solid #e4e4e4;
+        padding: 12upx 15upx;
+        box-sizing: border-box;
+        z-index: 100;
+        box-shadow: 0 2upx 8upx rgba(0, 0, 0, 0.1);
+        animation: slideDown 0.3s ease;
+
+        & .search-input-wrapper {
+            display: flex;
+            align-items: center;
+            background-color: #f5f5f5;
+            border: 1upx solid #e4e4e4;
+            border-radius: 6upx;
+            padding: 6upx 10upx;
+
+            & .search-icon {
+                font-size: 18upx;
+                color: #999;
+                margin-right: 8upx;
+            }
+
+            & .search-input {
+                flex: 1;
+                height: 30upx;
+                font-size: 14upx;
+                border: none;
+                outline: none;
+                background-color: transparent;
+                color: #333;
+
+                &::placeholder {
+                    color: #bbb;
+                }
+            }
+
+            & .clear-icon {
+                font-size: 18upx;
+                color: #ccc;
+                cursor: pointer;
+                margin-left: 8upx;
+                transition: color 0.2s;
+                margin-right: 8upx;
+
+                &:active {
+                    color: #999;
+                }
+            }
+
+            & .close-search-box {
+                font-size: 20upx;
+                color: #ccc;
+                cursor: pointer;
+                transition: color 0.2s;
+
+                &:active {
+                    color: #999;
+                }
+            }
+        }
+    }
+
+    /* 搜索浮动按钮(FAB) */
+    & .search-fab {
+        position: fixed;
+        bottom: 4upx;
+        right: 60upx;
+        width: 50upx;
+        height: 50upx;
+        background: linear-gradient(135deg, #3385FF 0%, #2568d3 100%);
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        box-shadow: 0 4upx 12upx rgba(51, 133, 255, 0.4);
+        z-index: 99;
+        transition: all 0.3s ease;
+        cursor: pointer;
+
+        &:active {
+            transform: scale(0.95);
+            box-shadow: 0 2upx 8upx rgba(51, 133, 255, 0.6);
+        }
+
+        & .search-fab-icon {
+            font-size: 28upx;
+            color: #ffffff;
+        }
+    }
+}
+
+/* 动画 */
+@keyframes slideDown {
+    from {
+        opacity: 0;
+        transform: translateY(-100%);
+    }
+    to {
+        opacity: 1;
+        transform: translateY(0);
+    }
 }
 </style>

+ 204 - 5
hdPad/src/pages/home/components/rightItem.vue

@@ -1,10 +1,31 @@
 <template>
-    <view class="shop-listType_box">
+    <view class="shop-listType_box" @click="handlePageClick">
+        <!-- 搜索框(固定在上侧) -->
+        <view v-if="showSearchBox" class="search-box-fixed" @click.stop>
+            <view class="search-input-wrapper">
+                <text class="search-icon">🔍</text>
+                <input 
+                    v-model="searchKeyword" 
+                    class="search-input" 
+                    placeholder="输入中文搜索"
+                    @input="handleSearch"
+                    @confirm="handleSearch"
+                    @focus="clearSearch"
+                    autofocus
+                />
+                <text v-if="searchKeyword" class="clear-icon" @click="clearSearch">✕</text>
+                <text class="close-search-box" @click="closeSearchBox">✕</text>
+            </view>
+        </view>
+
         <view class="cat-list-area">
-            <view v-for="item in globalRightItemClass" :key="item.id" :class="[globalRightItemCatId===item.id?'active':'']" @click="changeCategory(item)" > {{item.name}} </view>
+            <view v-for="item in globalRightItemClass" :key="item.id" :class="[globalRightItemCatId===item.id?'active':'']" @click="handleCategoryClick(item)" > {{item.name}} </view>
         </view>
         <view class="shop-show_box">
-            <view v-for="item in globalItemInfoList" :key="item.id" class="show-shop_box">
+            <view v-if="filteredItemList.length === 0" class="no-data-tip">
+                <text>{{ searchKeyword ? '未找到相关花材' : '暂无花材' }}</text>
+            </view>
+            <view v-for="item in filteredItemList" :key="item.id" class="show-shop_box">
                 <view class="item-detail" @click="popAddModelFn(item)">
                     <image class="img" :src="item.cover" lazy-load="true" :lazy-load-margin="0" mode="scaleToFill" ></image>
                     <view class="shop-info_price">
@@ -20,6 +41,11 @@
         </view>
         <slot name="footer"></slot>
 
+        <!-- 搜索按钮(浮动圆圈) -->
+        <view class="search-fab" @click.stop="toggleSearchBox">
+            <text class="search-fab-icon">🔍</text>
+        </view>
+
         <!-- 开单选花材输入数量和金额 -->
         <uni-popup ref="selectNumPriceRef" background-color="#fff" type="center" :animation="false">
             <selectNum v-if="currentJobType=='make'" @confirmAddItemModel="confirmAddItemModel" :customData.sync="customData" @cancelKdSelectNumPrice="addItemModelHidden"></selectNum>
@@ -39,7 +65,9 @@ export default {
     data(){
         return {
             currentJobType:'bill',
-            currentJobId:0
+            currentJobId:0,
+            searchKeyword:'',
+            showSearchBox:false
         }
     },
 	props: {
@@ -65,6 +93,33 @@ export default {
 	created(){
 		this.listenScanItem()
     },
+    computed:{
+        filteredItemList(){
+            if(!this.searchKeyword.trim()){
+                return this.globalItemInfoList || []
+            }
+            // 按花材名称搜索,不区分大小写,搜索所有分类
+            const keyword = this.searchKeyword.toLowerCase().trim()
+            let allItems = []
+            
+            // 从所有分类中收集花材
+            if(this.globalAllItemInfo && typeof this.globalAllItemInfo === 'object'){
+                for(let categoryId in this.globalAllItemInfo){
+                    const categoryItems = this.globalAllItemInfo[categoryId]
+                    if(Array.isArray(categoryItems)){
+                        allItems = allItems.concat(categoryItems)
+                    }
+                }
+            } else if(this.globalItemInfoList && Array.isArray(this.globalItemInfoList)){
+                // 如果没有分类映射,直接使用当前列表中的所有项
+                allItems = this.globalItemInfoList
+            }
+            
+            return allItems.filter(item => {
+                return item.name && item.name.toLowerCase().includes(keyword)
+            })
+        }
+    },
     watch:{
         customId:{
             handler(id){
@@ -90,6 +145,30 @@ export default {
     methods:{
         addToClear(){
             this.$msg('请扫码打开')
+        },
+        handlePageClick(){
+            // 点击页面任何地方时隐藏搜索框
+            if(this.showSearchBox){
+                this.closeSearchBox()
+            }
+        },
+        handleCategoryClick(item){
+            // 点击分类时清空搜索框
+            this.searchKeyword = ''
+            // 调用原来的分类切换方法
+            this.changeCategory(item)
+        },
+        toggleSearchBox(){
+            this.showSearchBox = !this.showSearchBox
+        },
+        closeSearchBox(){
+            this.showSearchBox = false
+        },
+        handleSearch(){
+            // 搜索过程中自动过滤,计算属性会自动更新filteredItemList
+        },
+        clearSearch(){
+            this.searchKeyword = ''
         },
 		popAddModelFn(info) {
             this.$util.hitVoice()
@@ -116,6 +195,9 @@ export default {
     display: flex;
     flex-direction: column;
     box-sizing: border-box;
+    position: relative;
+    overflow: hidden;
+    
     & .shop-show_box{
         display:flex;
         justify-content:space-around;
@@ -181,11 +263,20 @@ export default {
     }
     & .shop-show_box {
         flex: 1;
-        padding: 2upx;
+        padding: 2upx 2upx 50upx 2upx;
         display: flex;
         flex-wrap: wrap;
         overflow-y: scroll;
         overflow-x: hidden;
+        & .no-data-tip {
+            width: 100%;
+            height: 100%;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-size: 14upx;
+            color: #999;
+        }
     }
     & .shop-footer_box {
         height: 40upx;
@@ -211,5 +302,113 @@ export default {
             }
         }
     }
+
+    /* 搜索框(固定在顶部) */
+    & .search-box-fixed {
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        background-color: #ffffff;
+        border-bottom: 1upx solid #e4e4e4;
+        padding: 12upx 15upx;
+        box-sizing: border-box;
+        z-index: 100;
+        box-shadow: 0 2upx 8upx rgba(0, 0, 0, 0.1);
+        animation: slideDown 0.3s ease;
+
+        & .search-input-wrapper {
+            display: flex;
+            align-items: center;
+            background-color: #f5f5f5;
+            border: 1upx solid #e4e4e4;
+            border-radius: 6upx;
+            padding: 6upx 10upx;
+
+            & .search-icon {
+                font-size: 18upx;
+                color: #999;
+                margin-right: 8upx;
+            }
+
+            & .search-input {
+                flex: 1;
+                height: 30upx;
+                font-size: 14upx;
+                border: none;
+                outline: none;
+                background-color: transparent;
+                color: #333;
+
+                &::placeholder {
+                    color: #bbb;
+                }
+            }
+
+            & .clear-icon {
+                font-size: 18upx;
+                color: #ccc;
+                cursor: pointer;
+                margin-left: 8upx;
+                transition: color 0.2s;
+                margin-right: 8upx;
+
+                &:active {
+                    color: #999;
+                }
+            }
+
+            & .close-search-box {
+                font-size: 20upx;
+                color: #ccc;
+                cursor: pointer;
+                transition: color 0.2s;
+
+                &:active {
+                    color: #999;
+                }
+            }
+        }
+    }
+
+    /* 搜索浮动按钮(FAB) */
+    & .search-fab {
+        position: fixed;
+        bottom: 4upx;
+        right: 60upx;
+        width: 50upx;
+        height: 50upx;
+        background: linear-gradient(135deg, #09C567 0%, #079052 100%);
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        box-shadow: 0 4upx 12upx rgba(9, 197, 103, 0.4);
+        z-index: 99;
+        transition: all 0.3s ease;
+        cursor: pointer;
+
+        &:active {
+            transform: scale(0.95);
+            box-shadow: 0 2upx 8upx rgba(9, 197, 103, 0.6);
+        }
+
+        & .search-fab-icon {
+            font-size: 28upx;
+            color: #ffffff;
+        }
+    }
+}
+
+/* 动画 */
+@keyframes slideDown {
+    from {
+        opacity: 0;
+        transform: translateY(-100%);
+    }
+    to {
+        opacity: 1;
+        transform: translateY(0);
+    }
 }
 </style>