主页
购物车
用户界面
商品详细介绍
实现方法
项目前端采用了jquery,并还引入了轮播图插件swiper用来制作轮播效果用户进入主界面时,前端采用ajax技术向后端请求轮播图和商品信息用户点击搜索时,后端根据用户搜索返回相应信息在商品信息页面,客户可以加入购物车,也可以点击进去查看商品,这里通过绑定点击事件直接将商品id传入,以便后续使用再加入购物车时,需要判定一下购物车是非存在该商品在购物车页面,用户可以增加,减少,删除,这个通过拿到text里面的值,点击加时就加一并将值重新赋给text文本框用户可以点击登录或注册完成登录,这里通过ajax向后台发送请求时要携带输入框中内容判定当用户登陆后,拿到后台给的信息并渲染欢迎页面后端在主页面需要解决跨域问题,封装res.send信息,并且需要收集错误信息并判断出错内容在路由代码模块,需要引入模式验证,对前端传来的用户名,密码,id进行模式验证,强度验证在路由处理中,注册用户名时需要先对用户名进行判定是否已经存在该用户名,判定没有该用户才将用户名和密码存入数据库中搜索处理中,拿到前端传入的信息进行比较,正确后向数据库进行查询 前端 主界面 HTMLDOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="../lib/font/iconfont.css">
<link rel="stylesheet" href="../lib/swiper8/swiper-bundle.min.css">
<link rel="stylesheet" href="../css/common.css">
<link rel="stylesheet" href="../css/index.css">
head>
<body>
<div id="head">
<div>云点餐项目div>
<div class="search">
<input type="text" name="search">
<span class="iconfont icon-sousuo">span>
div>
div>
<div id="main">
<div class="swiper">
<div class="swiper-wrapper">
div>
<div class="swiper-pagination">div>
<div class="swiper-button-prev">div>
<div class="swiper-button-next">div>
div>
<div class="specificFunctions">div>
<div class="render">
div>
div>
<div id="foot">
<span class="iconfont icon-dingdan">span>
<span class="iconfont icon-gouwuche">span>
<span class="iconfont icon-yonghu">span>
div>
<script src="../lib/swiper8/swiper-bundle.min.js">script>
<script src="../js/jquery.js">script>
<script src="../js/index.js">script>
body>
html>
JS
//获取轮播图信息
function getBanner(){
$.ajax({
url:'http://127.0.0.1:4000/api/banner',
method:'get',
success:function(data){
if(data.status==0){
let banner=data.data
//拿到数据遍历出来
let bannerStr=banner.map(item=>{
return `
${item.url}">
`
}).join('')
$('.swiper-wrapper').html(bannerStr)
//渲染完成后初始化轮播图
var mySwiper = new Swiper ('.swiper', {
direction: 'horizontal', // 垂直切换选项
loop: true, // 循环模式选项
autoplay:true,
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
// 如果需要滚动条
scrollbar: {
el: '.swiper-scrollbar',
},
})
}
}
})
}
//渲染商品列表
function render(){
$.ajax({
url:'http://127.0.0.1:4000/api/list',
method:'get',
success:function(data){
if(data.status==0){
let list=data.data
//拿到数据后遍历出来
let productStr=list.map(item=>{
return `
${item.url}" οnclick=shoplist(${item.id})>
${item.product}
¥
${item.id}
`
}).join('')
$('.render').html(productStr)
//加入购物车
addCart()
}
}
})
}
//搜索框搜索功能
function search(){
$('.icon-sousuo').on('click',function(){
$.ajax({
url:'http://127.0.0.1:4000/api/search',
method:'get',
data:{
info:$('input[name="search"]').val()
},
success:function(data){
if(data.status==1){
alert(data.message)
}else{
let list=data.data
let productStr=list.map(item=>{
return `
${item.url}">
${item.product}
¥
${item.id}
`
}).join('')
$('.render').html(productStr)
}
}
})
})
}
//底部跳转功能
function jump(){
$('#foot').on('click','.icon-dingdan',function(){
location.href='index.html'
}).on('click','.icon-gouwuche',function(){
location.href='gouwuche.html'
}).on('click','.icon-yonghu',function(){
location.href="user.html"
})
}
//加入购物车
function addCart(){
$('.listSingle').on('click','.icon-gouwuche',function(){
//获取购物车
let id=$(this).attr('data-index');
$.ajax({
url:'http://127.0.0.1:4000/api//list/id',
method:'get',
data:{
id:id
},
success:function(data){
console.log(data);
if(data.status==0){
//拿到本地存储的购物车信息
let product=localStorage.getItem('shopList')
let productArr=JSON.parse(product)||[]
//判定是否已经有该商品
let isOk=productArr.some(item=>item[0].id==id)
if(!isOk){
productArr.push(data.data)
localStorage.setItem('shopList',JSON.stringify(productArr))
}
}
}
})
})
}
//进入商品信息界面
function shoplist(id){
location.href='shoplist.html?id='+id
}
getBanner()
render()
search()
jump()
CSS
#main {
width: 100%;
flex: 1;
overflow: auto;
background-color: aquamarine;
}
#main .swiper {
width: 100%;
height: 350px;
}
#main .specificFunctions {
width: 100%;
height: 288px;
background: url("../images/bc1.jpg") no-repeat 0px -228px;
background-size: 700px auto;
}
#main .render .listSingle {
transition: 0.25s transform ease-in-out;
margin-top: 30px;
display: flex;
}
#main .render .listSingle img {
width: 438px;
height: 350px;
}
#main .render .listSingle div {
margin-left: 20px;
}
#main .render .listSingle div p:nth-child(1) {
font-size: 40px;
font-weight: 700;
}
#main .render .listSingle div p:nth-child(2) {
margin-top: 110px;
font-size: 20px;
color: grey;
}
#main .render .listSingle span {
margin-left: 18px;
margin-top: 86px;
font-size: 77px;
color: #f06c60;
}
/*# sourceMappingURL=index.css.map */
购物车代码
HTML
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="../lib/font/iconfont.css">
<link rel="stylesheet" href="../css/common.css">
<link rel="stylesheet" href="../css/gouwuche.css">
head>
<body>
<div id="head">
<div>云点餐项目div>
<div class="search">
<input type="text" name="search">
<span class="iconfont icon-sousuo">span>
div>
div>
<div id="main">
<table>table>
<div class="total">div>
div>
<div id="foot">
<span class="iconfont icon-dingdan">span>
<span class="iconfont icon-gouwuche">span>
<span class="iconfont icon-yonghu">span>
div>
<script src="../js/jquery.js">script>
<script src="../js/gouwuche.js">script>
body>
html>
JS
//底部跳转功能
function jump(){
$('#foot').on('click','.icon-dingdan',function(){
location.href='index.html'
}).on('click','.icon-gouwuche',function(){
location.href='gouwuche.html'
}).on('click','.icon-yonghu',function(){
location.href="user.html"
})
}
//渲染商品信息
function getlist(){
let product=localStorage.getItem('shopList')
let productArr=JSON.parse(product)||[]
let tableHead=`
商品名
图片
价格
数量
总价
删除
`
let tableStr=productArr.map(item=>{
return `
${item[0].product}
${item[0].url}">
${item[0].id}
${item[0].id}
删除
`
}).join('')
$('table').html(tableHead+tableStr)
}
//删除功能
$('table').on('click','.del',function(){
//拿到id根据id删除
let id=$(this).attr('data-index')
let data=JSON.parse(localStorage.getItem('shopList'))
let productIndex=data.findIndex(item=>item.id==id)
data.splice(productIndex,1)
localStorage.setItem('shopList',JSON.stringify(data))
getlist()
})
//增加和减少
$('table').on('click','input[name="sub"]',function(){
if($(this).next().val()>1){
$(this).next().val($(this).next().val()-1)
let priceAll=$(this).next().val()*$(this).parent().prev().html()
$(this).parent().next().html(priceAll.toFixed(2))
}
total()
}).on('click','input[name="add"]',function(){
$(this).prev().val(parseInt($(this).prev().val())+1)
let priceAll=$(this).prev().val()*$(this).parent().prev().html()
$(this).parent().next().html(priceAll.toFixed(2))
total()
})
//计算总价
function total(){
let sum=0
$('.singleTotal').each((index,item)=>{
sum=sum+Number($(item).html())
})
$('.total').html('¥'+sum)
}
total()
getlist()
jump()
CSS
#main {
width: 100%;
flex: 1;
overflow: auto;
background-color: aquamarine;
}
#main table {
width: 100%;
height: 100%;
}
#main table tr td img {
width: 80px;
height: 80px;
}
#main table tr .fun {
width: 100px;
}
#main table tr .fun input {
vertical-align: top;
width: 20px;
height: 20px;
}
#main .total {
margin-left: 30px;
font-size: 30px;
color: red;
}
/*# sourceMappingURL=gouwuche.css.map */
用户界面代码
HTML
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="../lib/font/iconfont.css">
<link rel="stylesheet" href="../css/common.css">
<style>
#head{
height: 300px;
}
#main{
height: 100%;
}
#main .login,.sigin,.siginout{
width: 700px;
height: 50px;
background-color: #f46c60;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.input{
width: 700px;
height: 50px;
text-align: center;
}
.input input{
width: 400px;
height: 50px;
outline: none;
}
style>
head>
<body>
<div id="head">
<div>云点餐项目div>
<div class="search">
<input type="text" name="search">
<span class="iconfont icon-sousuo">span>
div>
div>
<div id="main">
<div class="sigin">登录div>
<div class="login">注册div>
<div class="input">
div>
div>
<div id="foot">
<span class="iconfont icon-dingdan">span>
<span class="iconfont icon-gouwuche">span>
<span class="iconfont icon-yonghu">span>
div>
<script src="../js/jquery.js">script>
<script src="../js/user.js">script>
<script>
script>
body>
html>
JS
//底部跳转功能
function jump(){
$('#foot').on('click','.icon-dingdan',function(){
location.href='index.html'
}).on('click','.icon-gouwuche',function(){
location.href='gouwuche.html'
}).on('click','.icon-yonghu',function(){
location.href="user.html"
})
}
//渲染注册输入框
$('.login').on('click',function(){
let str=`
`
$('.input').html(str)
login()
})
//渲染登录输入框
$('.sigin').on('click',function(){
let str=`
`
$('.input').html(str)
sigin()
})
//注册功能
function login(){
$('.loginInput').on('submit',function(e){
e.preventDefault()
$.ajax({
url:'http://127.0.0.1:4000/api/login',
method:'get',
data:{
username:$('.loginInput input[name="name"]').val(),
password:$('.loginInput input[name="password"]').val(),
},
success:function(data){
if(data.status==0){
alert('注册成功')
}
}
})
})
}
//登录功能
function sigin(){
$('.siginInput').on('submit',function(e){
e.preventDefault()
console.log($('input[name="name"]').val());
$.ajax({
url:'http://127.0.0.1:4000/api/sigin',
method:'get',
data:{
username:$('input[name="name"]').val(),
password:$('input[name="password"]').val(),
},
success:function(data){
console.log(data);
if(data.status==0){
//登录成功渲染欢迎界面
alert('登录成功')
let str=`
欢迎${data.data[0].username}
退出
`
$('#main').html(str)
//退出功能
siginout()
}
}
})
})
}
//欢迎界面和退出
function siginout(){
$('.siginout').on('click',function(){
let str=`
登录
注册
`
$('#main').html(str)
})
}
jump()
商品详细代码
HTML
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<link rel="stylesheet" href="../lib/font/iconfont.css">
<link rel="stylesheet" href="../css/shoplist.css">
head>
<body>
<div class="back"><span class="iconfont icon-shangyiye">span>div>
<div class="render">div>
<script src="../js/jquery.js">script>
<script src="../js/shoplist.js">script>
body>
html>
JS
function getShop(){
//分割字符串拿到url中的id
let url=location.href
let idArr=url.substring((url.indexOf('?')+1))
let id=idArr.split('=')[1]
console.log(id);
$.ajax({
url:'http://127.0.0.1:4000/api//list/id',
method:'get',
data:{
id:id
},
success:function(data){
if(data.status==0){
let list=data.data
let productStr=list.map(item=>{
return `
${item.url}">
${item.product}
¥
${item.id}
立即购买
`
}).join('')
$('.render').html(productStr)
}
}
})
}
//回到主界面
$('.back').on('click',function(){
location.href='index.html'
})
getShop()
CSS
.back span {
margin-left: 10px;
font-size: 40px;
}
.listSingle img {
width: 700px;
}
.listSingle div p:nth-child(1) {
font-size: 30px;
color: black;
}
.listSingle div p:nth-child(2) {
font-size: 20px;
color: grey;
}
.buyNow {
width: 100px;
height: 50px;
border-radius: 25px;
background-color: #f4606c;
text-align: center;
line-height: 50px;
cursor: pointer;
}
/*# sourceMappingURL=shoplist.css.map */
后端
主界面代码app.js
//导入express模块
const express=require('express')
const app=express()
const joi=require('joi')
//解决跨域问题
const cors=require('cors')
app.use(cors())
//解析表单数据
app.use(express.urlencoded({extended:false}))
//封装res.send()响应错误信息
app.use(function(req,res,next){
//status值默认失败1
res.cc=function(err,status=1){
res.send({
status,
message:err instanceof Error ?err.message:err,
})
}
next()
})
//导入用户路由模块
const apiRouter=require('./router/api')
app.use('/api',apiRouter)
//定义错误级别中间件
app.use((err,req,res,next)=>{
//验证失败错误
if(err instanceof joi.ValidationError) return res.cc(err)
//身份认证出错
if(err.name==='UnauthorizedError') return res.cc('身份认证出错')
res.cc(err)
})
//启动监听端口
app.listen(4000,function(){
console.log('express listen running at 4000');
})
路由代码router/api.js
const express=require('express')
const router=express.Router()
//引入路由处理模块
const api_handler=require('../router_handler/api_handler')
//验证模块 模式验证
const expressJoi=require('@escook/express-joi')
const {login_schema,sigin_schema,listId_schema}=require('../schema/user')
//注册接口
router.get('/login',expressJoi(login_schema),api_handler.login)
//登录接口
router.get('/sigin',expressJoi(sigin_schema),api_handler.sigin)
//商品列表接口
router.get('/list',api_handler.list)
//查询商品接口
router.get('/list/id',expressJoi(listId_schema),api_handler.listId)
//搜索框搜索
router.get('/search',api_handler.search)
//轮播图
router.get('/banner',api_handler.banner)
module.exports=router
路由处理函数router_handler
const db=require('../db/index')
//注册处理函数
exports.login=function(req,res){
let userinfo=req.query
let sql='SELECT * FROM ev_users WHERE username=?'
db.query(sql,userinfo.username,function(err,results){
if(err) return res.cc(err)
if(results.length>0) return res.cc('用户名已存在')
//注册新用户
let sql='INSERT INTO ev_users SET ?'
db.query(sql,{username:userinfo.username,password:userinfo.password},function(err,results){
if(err) return res.cc(err)
if(results.affectedRows!==1) return res.cc('出错了')
res.cc('注册成功',0)
})
})
}
//登录处理函数api_handler.sigin
exports.sigin=function(req,res){
let userinfo=req.query
let sql='SELECT * FROM ev_users WHERE username=? AND password=?';
db.query(sql,[userinfo.username,userinfo.password],(err,results)=>{
if(err) return res.cc(err)
if(results.length!==1) return res.cc('出错')
res.send({
status:0,
message:'OK',
data:results
})
})
}
//商品列表
exports.list=function(req,res){
let sql='SELECT * FROM shoplist '
db.query(sql,(err,results)=>{
if(err) return res.cc(err)
if(results.affectedRows==0) return res.cc('数据为空')
res.send({
status:0,
message:'ok',
data:results
})
})
}
//查询商品
exports.listId=(req,res)=>{
let idinfo=req.query
let sql='SELECT * FROM shoplist WHERE id=?'
db.query(sql,idinfo.id,(err,results)=>{
if(err) return res.cc(err)
if(results.length!==1) return res.cc('查询出错')
res.send({
status:0,
message:'ok',
data:results
})
})
}
//轮播图
exports.banner=(req,res)=>{
let sql='SELECT * FROM shoplist LIMIT 0,3'
db.query(sql,(err,results)=>{
if(err) return res.cc(err)
res.send({
status:0,
message:'ok',
data:results
})
})
}
//搜索框搜索
exports.search=(req,res)=>{
let search=req.query
let sql='SELECT * FROM shoplist WHERE id=?'
if(search.info=='商品1'){
db.query(sql,1,(err,results)=>{
if(err) return res.cc(err)
if(results.length!==1) return res.cc('查询出错')
res.send({
status:0,
message:'ok',
data:results
})
})
}else if(search.info=='商品2'){
db.query(sql,2,(err,results)=>{
if(err) return res.cc(err)
if(results.length!==1) return res.cc('查询出错')
res.send({
status:0,
message:'ok',
data:results
})
})
}else if(search.info=='商品3'){
db.query(sql,3,(err,results)=>{
if(err) return res.cc(err)
if(results.length!==1) return res.cc('查询出错')
res.send({
status:0,
message:'ok',
data:results
})
})
}else if(search.info=='商品4'){
db.query(sql,4,(err,results)=>{
if(err) return res.cc(err)
if(results.length!==1) return res.cc('查询出错')
res.send({
status:0,
message:'ok',
data:results
})
})
}else if(search.info=='商品5'){
db.query(sql,5,(err,results)=>{
if(err) return res.cc(err)
if(results.length!==1) return res.cc('查询出错')
res.send({
status:0,
message:'ok',
data:results
})
})
}else{
res.cc('未找到商品',1)
}
}
连接数据库代码db/index.js
const mysql=require('mysql')
const db=mysql.createPool({
host:'127.0.0.1',
user:'root',
password:'123456',
database:'test2',
})
module.exports=db
验证模块schema/user.js
const joi =require('joi')
const username=joi.string().alphanum().min(4).required()
const password=joi.string().alphanum().min(4).required()
const id=joi.number().required()
exports.login_schema={
query:{
username,
password
}
}
exports.sigin_schema={
query:{
username,
password
}
}
exports.listId_schema={
query:{
id
}
}
欢迎分享,转载请注明来源:内存溢出
赞
(0)
打赏
微信扫一扫
支付宝扫一扫
【MySQL数据库】2022年MySQL必知必会,基础内容与常见面试题
上一篇
2022-05-21
【SSM直击大厂】第十三章:MyBatis 详解
下一篇
2022-05-21
评论列表(0条)