基于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>

四、项目截图

五、源码获取

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

相关推荐
前端 贾公子24 分钟前
剖析源码Vue项目结构 (一)
前端·javascript·vue.js
局i1 小时前
【无标题】
前端·javascript·vue.js
点灯小铭1 小时前
基于单片机的蔬菜大棚温湿度远程测报系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
谢尔登2 小时前
Vue3 应用实例创建及页面渲染底层原理
javascript·vue.js·ecmascript
计算机毕设指导62 小时前
基于微信小程序的家政服务与互助平台【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
行思理3 小时前
css 样式新手教程
前端·css·html5
帅帅在睡觉3 小时前
组件的创建与挂载
javascript·vue.js·elementui
幽络源小助理3 小时前
基于SpringBoot+Vue的实验室管理系统源码 | 教育类JavaWeb项目免费下载 – 幽络源
vue.js·spring boot·后端
啊啊啊啊懒4 小时前
vite创建完项目之后vue文件中有标签报错
前端·javascript·vue.js
空白4 小时前
自学HTML5+CSS3丨第三天丨详解SEO
前端·css3·html5