Ver código fonte

feat(搜索): 添加搜索页面及相关功能组件

- 新增搜索页面,包含搜索框、历史记录和热门搜索功能
- 添加红包弹窗组件用于展示活动信息
- 在容器组件中增加搜索跳转功能
- 添加多张图标资源文件支持页面展示
ylong 1 semana atrás
pai
commit
2485b3d1c4

+ 197 - 0
pages-sell/components/packet-dialog/index.vue

@@ -0,0 +1,197 @@
+<template>
+	<view class="custom-popup" v-if="visible" @touchmove.stop.prevent>
+		<view class="popup-mask"></view>
+		<view class="packet-dialog-container">
+			<view class="dialog-body">
+				<image src="/pages-sell/static/search/packet-dialog.png" class="dialog-bg" mode="widthFix"></image>
+				<view class="content-overlay">
+					<text class="dialog-title">惊喜红包!</text>
+					<view class="amount-wrapper">
+						<text class="amount-num">15</text>
+						<text class="amount-unit">元</text>
+					</view>
+					<view class="condition-box">
+						<text>满0.01可用 24小时有效</text>
+					</view>
+					<view class="btn-accept" @click="close">
+						<text>开心收下</text>
+					</view>
+				</view>
+			</view>
+			<view class="close-area" @click="close">
+				<view class="close-icon-custom">×</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	name: 'PacketDialog',
+	props: {
+		value: {
+			type: Boolean,
+			default: false
+		}
+	},
+	data() {
+		return {
+			visible: false
+		}
+	},
+	watch: {
+		value: {
+			handler(val) {
+				this.visible = val;
+			},
+			immediate: true
+		},
+		visible(val) {
+			this.$emit('input', val);
+		}
+	},
+	methods: {
+		close() {
+			this.visible = false;
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.custom-popup {
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	z-index: 999;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	transition: all 0.3s ease-in-out;
+
+	.popup-mask {
+		position: absolute;
+		top: 0;
+		left: 0;
+		width: 100%;
+		height: 100%;
+		background: #000000;
+		opacity: 0.7;
+	}
+}
+
+.packet-dialog-container {
+	position: relative;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	z-index: 1000;
+	
+	.dialog-body {
+		position: relative;
+		width: 640rpx;
+		// height is determined by image aspect ratio
+		
+		.dialog-bg {
+			width: 100%;
+			display: block;
+		}
+		
+		.content-overlay {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 100%;
+			height: 100%;
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			justify-content: center;
+			padding-top: 120rpx;
+			padding-left: 50rpx;
+			
+			.dialog-title {
+				font-size: 38rpx;
+				font-weight: bold;
+				color: #B31700;
+				margin-bottom: 20rpx;
+				padding-top: 50rpx;
+			}
+			
+			.amount-wrapper {
+				display: flex;
+				align-items: baseline;
+				justify-content: center;
+				margin-bottom: 20rpx;
+				
+				.amount-num {
+					font-family: Arial;
+					font-weight: bold;
+					font-size: 80rpx;
+					color: #B31700;
+					background: linear-gradient(214deg, rgba(179,23,0,0.69) 0%, rgba(255,132,0,0.69) 100%);
+					-webkit-background-clip: text;
+					-webkit-text-fill-color: transparent;
+				}
+				
+				.amount-unit {
+					color: #B31700;
+					font-size: 38rpx;
+					font-weight: bold;
+					margin-left: 4rpx;
+				}
+			}
+			
+			.condition-box {
+				padding: 4rpx 20rpx;
+				border-radius: 8rpx;
+				
+				text {
+					font-size: 24rpx;
+					color: #B31700;
+				}
+			}
+			
+			.btn-accept {
+				width: 300rpx;
+				height: 96rpx;
+				background: linear-gradient(180deg, #FFF5D6 0%, #FFDFA8 100%);
+				border-radius: 48rpx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				box-shadow: 0 4rpx 10rpx rgba(179, 23, 0, 0.3);
+				margin-top: 20rpx; // Adjust positioning
+				
+				text {
+					color: #B31700;
+					font-size: 32rpx;
+					font-weight: bold;
+				}
+			}
+		}
+	}
+	
+	.close-area {
+		position: absolute;
+		top: 0rpx;
+		right: 0;
+		
+		.close-icon-custom {
+			width: 60rpx;
+			height: 60rpx;
+			border: 2rpx solid #fff;
+			border-radius: 50%;
+			color: #fff;
+			font-size: 50rpx;
+			line-height: 54rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			padding-bottom: 6rpx; // Visual adjustment for 'x'
+		}
+	}
+}
+</style>

+ 2 - 2
pages-sell/components/sell-container/index.vue

@@ -15,10 +15,10 @@
 		<!-- 主要内容区域 -->
 		<view class="main-content" :style="{ marginTop: (statusBarHeight + 44) + 'px' }">
 			<!-- 搜索框 -->
-			<view class="search-wrapper">
+			<view class="search-wrapper" @click="navigateTo('/pages-sell/pages/search')">
 				<view class="search-box-uview">
 					<u-search placeholder="搜索关键字" :show-action="false" bg-color="transparent" height="40"
-						:clearabled="true" v-model="keyword"
+						:clearabled="true" v-model="keyword" :disabled="true"
 						search-icon="/pages-sell/static/search-icon.png"></u-search>
 					<view class="search-btn-overlay">
 						<text>搜索</text>

+ 284 - 0
pages-sell/pages/search.vue

@@ -0,0 +1,284 @@
+<template>
+    <view class="search-page">
+        <!-- Navbar -->
+        <Navbar title="搜索"></Navbar>
+        <!-- Search Bar Area -->
+        <view class="search-area">
+            <view class="search-box">
+                <image src="/pages-sell/static/search/icon-scan.png" class="search-icon-left" mode="aspectFit"></image>
+                <input class="search-input" v-model="keyword" placeholder="书名 / 作者 / ISBN" confirm-type="search"
+                    @confirm="onSearch" :focus="true" />
+                <view class="search-btn" @click="onSearch">
+                    <text>搜索</text>
+                </view>
+            </view>
+        </view>
+
+        <!-- History -->
+        <view class="section history-section" v-if="historyList.length">
+            <view class="section-header">
+                <text class="title">搜索历史</text>
+                <image src="/pages-sell/static/search/icon-delete.png" class="icon-delete" mode="aspectFit"
+                    @click="clearHistory"></image>
+            </view>
+            <view class="tags-list">
+                <view class="tag-item history-tag" v-for="(item, index) in historyList" :key="index"
+                    @click="doSearch(item)">
+                    {{ item }}
+                </view>
+            </view>
+        </view>
+
+        <!-- Hot Search -->
+        <view class="section hot-section">
+            <view class="section-header">
+                <view class="left">
+                    <image src="/pages-sell/static/search/icon-fire.png" class="icon-fire" mode="aspectFit"></image>
+                    <text class="title">热门搜索</text>
+                </view>
+                <image
+                    :src="hotVisible ? '/pages-sell/static/search/icon-view.png' : '/pages-sell/static/search/icon-view.png'"
+                    class="icon-view" mode="aspectFit" @click="toggleHot" :style="{ opacity: hotVisible ? 1 : 0.5 }">
+                </image>
+            </view>
+            <view class="tags-list" v-if="hotVisible">
+                <view class="tag-item" v-for="(item, index) in hotList" :key="index"
+                    @click="doSearch(item.name)" :class="item.className">
+                    <image v-if="item.tag === 'NEW'" src="/pages-sell/static/search/icon-new.png" class="tag-icon-new"
+                        mode="heightFix"></image>
+                    <image v-if="item.tag === 'HOT'" src="/pages-sell/static/search/icon-fire.png" class="tag-icon-fire"
+                        mode="heightFix"></image>
+                    <text>{{ item.name }}</text>
+                </view>
+            </view>
+        </view>
+
+        <!-- Red Packet Float -->
+        <view class="red-packet-float" @click="openPacket">
+            <view class="time-badge">
+                <text>剩</text>
+                <u-count-down :timestamp="timestamp" separator="colon" color="#DF1407" bg-color="transparent" font-size="18" separator-size="18" separator-color="#DF1407"></u-count-down>
+            </view>
+            <image src="/pages-sell/static/search/icon-red-packet.png" class="packet-img" mode="aspectFit"></image>
+        </view>
+
+        <!-- Surprise Packet Dialog -->
+        <PacketDialog v-model="showPacketDialog"></PacketDialog>
+    </view>
+</template>
+
+<script>
+import Navbar from '@/components/navbar/navbar.vue';
+import PacketDialog from '@/pages-sell/components/packet-dialog/index.vue';
+
+export default {
+    components: {
+        Navbar,
+        PacketDialog
+    },
+    data() {
+        return {
+            keyword: '',
+            historyList: ['本朝纲目', '千金方', '墨菲定律', '狂人日记', '鲁迅经典', '资治通鉴'],
+            hotVisible: true,
+            hotList: [
+                { name: '毛概 2023', tag: 'NEW' },
+                { name: '吸引力法则', tag: 'HOT' },
+                { name: '神农本草经书', tag: '' }
+            ],
+            timestamp: 86400, // 24 hours countdown
+            showPacketDialog: false
+        }
+    },
+    methods: {
+        onSearch() {
+            if (!this.keyword.trim()) return;
+            this.doSearch(this.keyword);
+        },
+        doSearch(key) {
+            console.log('Search:', key);
+            this.keyword = key;
+            // Navigate to result page or show results
+            uni.showToast({
+                title: '搜索: ' + key,
+                icon: 'none'
+            });
+        },
+        clearHistory() {
+            uni.showModal({
+                title: '提示',
+                content: '确定清空搜索历史吗?',
+                success: (res) => {
+                    if (res.confirm) {
+                        this.historyList = [];
+                    }
+                }
+            });
+        },
+        toggleHot() {
+            this.hotVisible = !this.hotVisible;
+        },
+        openPacket() {
+            this.showPacketDialog = true;
+        },
+        closePacket() {
+            this.showPacketDialog = false;
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.search-page {
+    min-height: 100vh;
+    background-color: #fff;
+    font-family: 'Source Han Sans SC', sans-serif;
+}
+
+.search-area {
+    padding: 30rpx 30rpx;
+}
+
+.search-box {
+    display: flex;
+    align-items: center;
+    background-color: #F6F6F6;
+    border-radius: 40rpx;
+    height: 80rpx;
+    padding: 0 10rpx 0 30rpx;
+
+    .search-icon-left {
+        width: 36rpx;
+        height: 36rpx;
+        margin-right: 20rpx;
+    }
+
+    .search-input {
+        flex: 1;
+        height: 100%;
+        font-size: 28rpx;
+        color: #333;
+    }
+
+    .search-btn {
+        width: 120rpx;
+        height: 60rpx;
+        background: linear-gradient(0deg, #37C148 0%, #6ADD83 100%);
+        border-radius: 48rpx; // 24px
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-left: 20rpx;
+
+        text {
+            color: #fff;
+            font-size: 28rpx;
+            font-weight: 500;
+        }
+    }
+}
+
+.section {
+    padding: 30rpx;
+
+    .section-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 30rpx;
+
+        .left {
+            display: flex;
+            align-items: center;
+        }
+
+        .title {
+            font-size: 32rpx;
+            font-weight: bold;
+            color: #333;
+        }
+
+        .icon-delete,
+        .icon-view {
+            width: 32rpx;
+            height: 32rpx;
+        }
+
+        .icon-fire {
+            width: 36rpx;
+            height: 36rpx;
+            margin-right: 10rpx;
+        }
+    }
+
+    .tags-list {
+        display: flex;
+        flex-wrap: wrap;
+
+        .tag-item {
+            background: #F8F7F0;
+            border-radius: 30rpx;
+            padding: 8rpx 30rpx;
+            font-size: 26rpx;
+            color: #666;
+            margin-right: 20rpx;
+            margin-bottom: 20rpx;
+            display: flex;
+            align-items: center;
+
+            &.history-tag {
+                background-color: #EBF8EE;
+            }
+
+            &.hot-item {
+                background: #F5F3F9;
+            }
+
+            .tag-icon-new {
+                height: 16rpx;
+                margin-right: 8rpx;
+            }
+
+            .tag-icon-fire {
+                width: 28rpx;
+                height: 28rpx;
+                margin-right: 8rpx;
+            }
+        }
+    }
+}
+
+.red-packet-float {
+    position: fixed;
+    bottom: 200rpx;
+    right: 40rpx;
+    z-index: 100;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    
+    .time-badge {
+        background: #FFE173;
+        color: #DF1407;
+        font-size: 18rpx;
+        padding: 4rpx 10rpx;
+        border-radius: 10rpx;
+        position: absolute;
+        top: -40rpx;
+        right: -20rpx;
+        white-space: nowrap;
+        z-index: 2;
+        display: flex;
+        align-items: center;
+        
+        text {
+            margin-right: 4rpx;
+        }
+    }
+
+    .packet-img {
+        width: 100rpx;
+        height: 120rpx;
+    }
+}
+</style>

BIN
pages-sell/static/search/icon-delete.png


BIN
pages-sell/static/search/icon-fire.png


BIN
pages-sell/static/search/icon-new.png


BIN
pages-sell/static/search/icon-red-packet.png


BIN
pages-sell/static/search/icon-scan.png


BIN
pages-sell/static/search/icon-view.png


BIN
pages-sell/static/search/packet-dialog.png


+ 7 - 0
pages.json

@@ -298,6 +298,13 @@
                         "navigationStyle": "custom",
                         "navigationBarTitleText": ""
                     }
+                },
+                {
+                    "path": "pages/search",
+                    "style": {
+                        "navigationBarTitleText": "搜索",
+                        "navigationStyle": "custom"
+                    }
                 }
             ]
         }