基于vue的商城小程序的毕业设计与实现(源码及报告)

环境搭建 ☞☞☞ ​​​Vue入手篇(一),防踩雷(全网最详细教程)_vue force-CSDN博客


目录

一、功能介绍

二、登录注册功能

三、首页

四、项目截图

五、源码获取


一、功能介绍

  1. 用户信息展示:页面顶部设有用户头像和昵称展示区,方便用户识别自己的账号信息。
  2. 搜索功能:配备有搜索栏,用户可以通过输入关键词来查找并可以删除历史查找记录。
  3. 商品分类:商品分为豆干制品、饼干点心、酒水饮料等
  4. 商品展示与选择:页面中间部分以缩略图形式展示多个商品,方便选择。每个商品下方附有价格标签并可以修改商品数量,已选商品会加入到购物车中。
  5. 购物结算:页面底部设有"选好了"红色按钮,然后在结算页面完成支付流程。
  6. 我的订单:查看订单内容。
  7. 登录和注册功能。

二、登录注册功能

页面代码

<template>
    <div class="warp">
	    <div class="container">
			<div ref="formBox" class="form-box">  
                <!-- 注册 -->  
                <div ref="registerBox" class="register-box hidden">  
                    <h1>register</h1>  
                    <input type="text" placeholder="请输入用户名" v-model="username">  
                    <input type="password" placeholder="请输入密码" v-model="password">  
                    <input type="password" placeholder="确认密码">  
                    <button @click="register">注册</button>  
                </div>  
                <!-- 登录 -->  ①
                <div ref="loginBox" class="login-box">  
                    <h1>login</h1>  
                    <input type="text" v-model="Lusername" placeholder="请输入用户名">  
                    <input type="password" v-model="Lpassword" placeholder="请输入密码">  
                    <button @click="login">登录</button>  
                </div>  
            </div>  
            <div class="con-box left">
                <h2><span>注册页面</span></h2>
                <p>快来注册<span>账号</span>吧</p>
                <img src="../../static/images/1.jpg" alt="" />
                <p>已有账号</p>
                <button id="login" @click="switchToLogin">去登录</button>
            </div>
            <div class="con-box right">
                <h2><span>登录页面</span></h2>
                <p>快来登录<span>账号</span>吧</p>
                <img src="../../static/images/2.jpg" alt="" />
                <p>没有账号?</p>
                <button id="register" @click="switchToRegister">去注册</button>
            </div>
        </div>	
    </div>
</template>

功能实现

<script>  
export default {  
  data() {  
          return {  
              // 注册表单数据  
                  username: '',  
                  password: '',  
 
              // 登录表单数据  
                  Lusername: '',  
                  Lpassword: ''  
          };  
      },
  methods: {  
    // 登录函数  
    login() {  
      const storedUsername = uni.getStorageSync('username');  
      const storedPassword = uni.getStorageSync('password');  
  
      if (!this.Lusername || !this.Lpassword) {  
        uni.showToast({ title: '账号密码为空', icon: 'none' });  
        return;  
      }  
  
      if (this.Lusername === storedUsername && this.Lpassword === storedPassword) {  
        // 账号密码一致,跳转到 /index 页面  
        uni.navigateTo({ url: '/pages/index/index' });  
      } else if (this.Lusername === storedUsername) {  
        // 账号正确,密码错误  
        uni.showToast({ title: '密码错误', icon: 'none' });  
      } else {  
        // 账号不一致  
        uni.showToast({ title: '未检测到该账号', icon: 'none' });  
      }  
    },  
    // 注册函数  
    register() {  
      if (this.username && this.password) { 
		  console.log(this.username);  
		  console.log(this.password); 
        // 将用户名和密码存储到localStorage中
        uni.setStorageSync('username', this.username);  
        uni.setStorageSync('password', this.password);  
        uni.showToast({ title: '注册成功!', icon: 'success' });  
        this.switchToLogin();  
      } else {  
        uni.showToast({ title: '用户名和密码不能为空!', icon: 'none' });  
      }  
    },  
	
	// 切换到注册界面的函数 
	switchToRegister() {  
	    this.$refs.formBox.style.transform = 'translateX(100%)';  
        this.$refs.loginBox.classList.add('hidden');  
        this.$refs.registerBox.classList.remove('hidden');  
    },  
    // 切换到登录界面的函数  
	switchToLogin() {  
	    this.$refs.formBox.style.transform = 'translateX(0%)';  
	    this.$refs.registerBox.classList.add('hidden');  
	    this.$refs.loginBox.classList.remove('hidden');  
	},  
  },  
};  
</script>

注册时的用户名和密码要和登录时保持一致即可登陆成功

三、首页

头部代码

<template>
	<view class="customHead" :style="{height:totalHeight+'px'}">
		<view class="bg">
			<image class="bgimg" src="../../static/images/1.jpg" mode="aspectFill"></image>
		</view>		
		<view class="container">
			<view class="statusBar" :style="{height:statusBarHeight+'px'}"></view>
			<view class="service" :style="{height:titleBarHeight+'px'}" v-if="!foldState">
				<view class="kefu">
					<u-icon name="server-fill" size="22" color="#fff"></u-icon>
				</view>
			</view>
			<view class="body" :class="foldState?'fold':''" :style="{height:bodyBarHeight+'px'}">
				<view class="brand">
					<view class="pic">
						<image class="img" src="../../static/images/DJ2.jpg" mode="aspectFill"></image>
					</view>
					<view class="text">
						<view class="title">
							<text class="font">微信搜'K学啦'</text>
							<u-icon class="icon" name="more-circle" size="22" color="#fff"></u-icon>
						</view>
						<view class="des">各项目源代码私聊,接期末毕设</view>
					</view>
				</view>
				<view class="code">
					<view class="pic">
						<image class="img" src="../../static/images/qrcode.png" mode="aspectFill"></image>
					</view>
					<text class="pay">付款</text>
				</view>
			</view>
			
		</view>
	</view>
</template>

<script>
	import {mapState,mapGetters} from "vuex"
	export default {
		name:"custom-head-bar",
		data() {
			return {
				
			};
		},
		computed:{
			...mapGetters(["statusBarHeight","titleBarHeight","bodyBarHeight","totalHeight","foldState"])
		},
		props:{
			
		}	
	}
</script>

<style lang="scss">
.customHead{
	height: 400rpx;
	overflow: hidden;
	position: relative;
	.bg{
		width: 100%;
		height: 100%;
		background: #000;
		.bgimg{
			width: 100%;
			height: 100%;
			filter: blur(30rpx);
			transform: scale(2);
		}
	}
	.container{
		position: absolute;
		top:0;
		left:0;		
		width: 100%;
		.statusBar{			
			
		}
		.service{			
			padding-left: 30rpx;
			@include flex-box-set(start);
			color:#fff;
			.manage{
				margin-left:20rpx;
				@include flex-box-set(start);
			}
		}
		.body{
			@include flex-box();
			padding:0 45rpx;
			height: 100px;			
			transition: 0.3s;			
			.brand{
				width: 580rpx;
				@include flex-box-set(start);
				.pic{
					width: 110rpx;
					height: 110rpx;
					border-radius: 50%;
					overflow: hidden;
					transition: 0.3s;
					.img{
						width: 100%;
						height: 100%;
					}
				}
				.text{
					flex:1;
					padding:0 30rpx;
					color:#fff;
					.title{
						font-size: 36rpx;
						font-weight: 800;						
						display: flex;
						align-items: center;
						.font{
							margin-right:10rpx;
						}
					}
					.des{
						font-size: 26rpx;
						width: 100%;
						opacity: 0.8;
						padding-top:5rpx;
						@include ellipsis()
					}
				}
			}	
			.code{
				width: 80rpx;
				height: 80rpx;
				border-left:1px solid rgba(255,255,255,0.6);
				@include flex-box-set(between);
				flex-direction: column;
				.pic{
					width: 40rpx;
					height: 40rpx;
					.img{
						width: 100%;
						height: 100%;
					}
				}
				.pay{
					font-size: 22rpx;
					color:#fff;
					text-align: center;
				}
			}		
			&.fold{
				padding:0 30rpx;
				.brand{
					.pic{
						width: 60rpx;
						height: 60rpx;						
					}
					.text{
						padding-left:15rpx;
						.title{
							font-size: 28rpx;
							.icon{
								transform: scale(0.9);
							}
						}
						.des{
							display: none;
						}
					}
					
				}
				.code{
					display: none;
				}
			}
					
		}
		
	}
	
}
</style>

下部代码

<template>
	<view class="home">
		<custom-head-bar id="customHeadBar"></custom-head-bar>
		<view class="wrapper">
			<view class="infoModel">
				<view class="left">
					免费配送
				</view>
				<navigator url="/pages/order/order" class="right">
					<u-icon name="order" color="#576b95" size="22"></u-icon>
					我的订单
				</navigator>
			</view>
			<view class="scrollLayout">
				<view class="leftScroll">
					<scroll-view scroll-y class="sContent" :scroll-top="leftScrollValue">
						<view class="navitem" :class="index==navIdx?'active':''" 
						v-for="(item,index) in dataList"
						:key="item.id"
							@click="clickNav(index)">{{item.name}}</view>
					</scroll-view>
				</view>
				<view class="rightScroll">
				
					<navigator url="/pages/search/search" class="searchView">
						<u-icon name="search" size="22" color="#576b95"></u-icon>
						搜索
					</navigator>
					<scroll-view @scroll="rightScrollEnt" :scroll-top="rightScrollValue" scroll-y scroll-with-animation
						class="sContent">
						<view class="productView" v-for="item in dataList">
							<u-sticky :customNavHeight="0" zIndex="2">
								<view class="proTitle">{{item.name}}</view>
							</u-sticky>
							<view class="proContent">
								<view class="proitem" v-for="pro in item.children">
									<product-item :item="pro"></product-item>
								</view>
							</view>
						</view>
					</scroll-view>
				</view>

			</view>
		</view>


		<car-layout v-if="buyNum>0"></car-layout>
	</view>
</template>

<script>
	import {
		mapState,
		mapMutations,
		mapGetters
	} from "vuex"
	export default {
		data() {
			return {
				navIdx: 0,
				leftScrollValue: 0,
				rightScrollValue: 0,
				leftHitArr: [],
				rightHitArr: [],
				foldState: false,
				dataList: [{
					id: 1,
					name: "豆干制品",
					children: [{
						id: 11,
						name: "魔芋~爽!",
						price: 10,
						before_price: 22,
						thumb: "https://img1.baidu.com/it/u=3237764698,677787850&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
						numvalue:0
					}, 
					{
						id: 12,
						name: "卫龙大面筋",
						price: 5,
						before_price: 12,
						thumb: "https://pic.rmb.bdstatic.com/bjh/0eecefb60e7b7c6c68ec6377ddb7025b7289.jpeg@h_1280",
						numvalue:0
					}]
				}, {
					id: 2,
					name: "饼干点心",
					children: [{
						id: 21,
						name: "奥利给饼干",
						price: 13,
						before_price: 22,
						thumb: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.alicdn.com%2Fimgextra%2Fi1%2F2200633062791%2FO1CN01WIfNhU1WUKGKS3ZnC_%21%212200633062791-0-scmitem6000.jpg_640x640.jpg&refer=http%3A%2F%2Fimg.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1720103940&t=0705e091433d282ae43ecb0f392b54bf",
						numvalue:0
					},
					{
						id: 22,
						name: "丹麦皇家曲奇",
						price: 50,
						before_price: 100,
						thumb: "https://btob.guangbo.net/uploadfile/all/image/20211118/20211118161710769_1637223429028.png",
						numvalue:0
					},
					{
						id: 23,
						name: "奶油小蛋糕",
						price: 33,
						before_price: 66,
						thumb: "https://img1.baidu.com/it/u=2341784055,4263735026&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667",
						numvalue:0
					}]
				}, {
					id: 3,
					name: "酒水饮料",
					children: [{
						id: 31,
						name: "诺文斯基核动力金牌格瓦斯",
						price: 18,
						before_price: 29,
						thumb: "http://img.eftarkov.com/upFiles/infoImg/202309301632468882.png",
						numvalue:0
					},
					{
						id: 32,
						name: "Pevko Light瓶装啤酒",
						price: 33,
						before_price: 66,
						thumb: "http://img.eftarkov.com/upFiles/infoImg/202309301624428851.png",
						numvalue:0
					},
					{
						id: 33,
						name: "Dan Jackiel瓶装威士忌",
						price: 66,
						before_price: 99,
						thumb: "http://img.eftarkov.com/upFiles/infoImg/202309301607342250.png",
						numvalue:0
					},
					{
						id: 34,
						name: "Tarkovskaya瓶装伏特加",
						price: 100,
						before_price: 200,
						thumb: "http://img.eftarkov.com/upFiles/infoImg/202309301613404375.png",
						numvalue:0
					},
					{
						id: 35,
						name: "凶狠跑刀崽-月光【私酒】",
						price: 9999,
						before_price: 99999,
						thumb: "https://tse3-mm.cn.bing.net/th/id/OIP-C.1_lcxKT6LlpbKMLRbEM6lgAAAA?rs=1&pid=ImgDetMain",
						numvalue:0
					}]
				}]
			}
		},
		onLoad() {
			this.$nextTick(() => {
				this.getHeightArr();
			})
		},
		computed: {
			...mapGetters(["buyNum"])
		},
		methods: {
			...mapMutations(["setFoldState"]),
			//点击导航菜单
			clickNav(index) {
				if (this.navIdx == index) return;
				this.navIdx = index;
				if (this.timeout) {
					clearTimeout(this.timeout);
				}
				this.timeout = setTimeout(() => {
					this.leftScrollValue = this.leftHitArr[index];
					this.rightScrollValue = this.rightHitArr[index];
				}, 100)
			},
			//获取滚动条内容高度
			getHeightArr() {
				let selectorQuery = uni.createSelectorQuery();
				let customHeadBar;
				//获取自定义导航高度				
				selectorQuery.select("#customHeadBar").boundingClientRect(rect => {
					customHeadBar = rect.height;
				}).exec()


				//左侧滚到区域的节点组
				selectorQuery.selectAll(".navitem").boundingClientRect(rects => {
					this.leftHitArr = rects.map(item => item.top - customHeadBar - 40)
				}).exec()
				console.log(this.leftHitArr);
				//右侧滚到区域的节点组
				selectorQuery.selectAll(".productView").boundingClientRect(rects => {
					this.rightHitArr = rects.map(item => item.top - customHeadBar - 40)
				}).exec()

			},

			//监听右侧滚动条的改变
			rightScrollEnt(e) {
				let scrollTop = Math.ceil(e.detail.scrollTop);
				let idx = this.rightHitArr.findIndex((value, index, arr) => scrollTop >= value && scrollTop < arr[index +
					1])
				this.navIdx = idx;
				this.leftScrollValue = this.leftHitArr[idx];

				if (scrollTop < 300) {
					this.setFoldState(false)
				}
				if (scrollTop > 400) {
					this.setFoldState(true)
				}
			}

		}
	}
</script>

四、项目截图

五、源码获取

看到这里你是否受益了呢?你的支持就是我创作的动力,点赞+收藏+关注,学习不迷路,评论区留下你的疑问,可私信获取源码。

相关推荐
丁总学Java8 分钟前
微信小程序中 “页面” 和 “非页面” 的区别
微信小程序·小程序
小万编程9 分钟前
基于SpringBoot+Vue毕业设计选题管理系统(高质量源码,提供文档,免费部署到本地)
java·vue.js·spring boot·计算机毕业设计·java毕业设计·web毕业设计
m0_748236581 小时前
【Nginx 】Nginx 部署前端 vue 项目
前端·vue.js·nginx
请叫我飞哥@2 小时前
HTML5 缩放动画(Zoom In/Out)详解
前端·html5·swift
请叫我飞哥@3 小时前
HTML5 弹跳动画(Bounce Animation)详解
前端·html·html5
qq_7556822403 小时前
微信小程序——创建滑动颜色条
微信小程序·小程序
hawk2014bj3 小时前
Vue Router 快速入门
前端·javascript·vue.js
橘子海全栈攻城狮3 小时前
【源码+文档+调试讲解】项目申报小程序
java·开发语言·servlet·微信小程序·小程序
小彭努力中4 小时前
58.在 Vue 3 中使用 OpenLayers 绘制点、线、圆、多边形
前端·javascript·vue.js·arcgis·ecmascript·openlayers
失眠的咕噜4 小时前
el-table 使用el-form 表单验证
前端·javascript·vue.js