基于前后端交互的购物车
分析表的设计:
* 用户信息表 userinf
* 商品信息表 goodslist
* 订单表 ordergoods
* 总价表 存总数量和总价:存储打钩准备购买但是没有结算的数据 存到本地
接口分析:
* 注册页:
* 验证用户名是否存在 select
* 注册 insert
* 登陆页
* 登陆接口 select
* 首页
* 数据渲染:查询部分数据 select
* 列表页:
* 查询第一页数据 select
* 分页或懒加载 select
* 排序 select
* 模糊查询 select
* 查找价格区间 select
* 详情页:
* 获取列表页传过来的id,查询数据,渲染到页面 select
* 点击加入购物车 insert 订单表
* 如果本来没有该商品 insert
* 如果本来有该商品 update
* 购物车:
* 查询所有商品数据渲染到页面 select
* 删除商品 delete
* 修改后端数据 update
* 存储总数量和总价 insert
* 全选的时候就要修改总数量和总价 update
* 如果有结算页面需要付款的话,需要调用支付接口(需要企业的营业执照才可以); 个人二维码收款也可以。哈哈
购物车功能:
* 查询订单表数据渲染(前提:详情页那边已经插入了数据)
* 数量的变化、小计变化,数据变化
* 删除当行:数据删除
* 全选:计算总数量和总价 :存数据
php
1、conn.php
<?php
//1.建立连接:文件名不能用con.php 系统有个文件就是con文件
$severname = 'localhost';//主机名
$username = 'root';//用户名
$password = 'nfq123456';//密码 变量名$pwd $psw可能会报错
$dbname = 'udata';//要连接的数据库名
$conn = new mysqli($severname,$username,$password,$dbname);
//获取对象的属性:js中arr.length;php用->获取属性和方法 $con->属性名;$conn->方法名();
if($conn->connect_error) {
//连接失败
die('失败的原因'.$conn->connect_error);
}else{
// echo '连接成功';//检测成功后就可以注释了
}
?>
2、select.php
<?php
//接口整理方案二:准备两个接口:select
include 'conn.php';
$sql = isset($_REQUEST['sql']) ? $_REQUEST['sql'] : '';//sql语句是传过来
$res = $conn->query($sql);
$arr = $res->fetch_all(MYSQLI_ASSOC);
echo json_encode($arr,JSON_UNESCAPED_UNICODE);//把数组转成字符串,传给前端
//3.关闭连接
$res->close();//关闭结果集
$conn->close();//关闭数据库
?>
3、other.php
<?php
//接口整理方案二:准备两个接口:update insert delete
include 'conn.php';
$sql = isset($_REQUEST['sql']) ? $_REQUEST['sql'] : '';//sql语句是传过来
$res = $conn->query($sql);//执行后得到的是布尔值
echo $res;
$conn->close();//关闭数据库
?>
html和css
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>购物车</title>
<style type="text/css">
li {
list-style: none;
clear: both;
width: 800px;
}
a {
text-decoration: none;
cursor: pointer;
color: red;
}
ul li p {
float: left;
margin: 10px;
}
ul li p span {
display: inline-block;
width: 20px;
height: 20px;
background: #d8d8d8;
cursor: pointer;
text-align: center;
line-height: 20px;
}
ul li p span::selection {
background: transparent;
}
div {
clear: both;
margin-left: 40px;
}
div p {
float: left;
margin: 10px;
}
</style>
</head>
<body>
<ul id="cart">
<li>
<p><input type="checkbox" name="" id="" value="" /></p>
<p>商品</p>
<p style="padding-left: 20px;">单价</p>
<p style="padding-left: 100px;">数量</p>
<p style="padding-left: 120px;">小计</p>
<p style="padding-left: 10px;">操作</p>
</li>
<!-- <li class="goods">
<p class="good_check"><input type="checkbox" name="good" value="" /></p>
<p class="good_name">西瓜</p>
<p class="good_price">¥ 99.99</p>
<p class="num">
<span class="cutnum">-</span>
<input class="nownum" data-num="10" type="text" value="1" />
<span class="addnum">+</span>
</p>
<p class="good_total">¥ 99.99</p>
<p class="good_del">
<a href="javascript:;">删除</a>
</p>
</li> -->
</ul>
<div id="del">
<p id="allchecked"><input type="checkbox" name="" id="" value="" />全选</p>
<p id="delall">
<a href="javascript:;">删除</a>
</p>
<p id="allnum">已选 0 件商品</p>
<p id="totalprice">总计(不含运费):¥0.00</p>
</div>
</body>
<script src="js/jquery.min.js"></script>
<script src="js/car.js"></script>
</html>
car.js
(function () {
// 查询订单表数据渲染
function getData(url, str, fn) {
//url 接口路径 str :sql语句 fn 成功获取数据后执行的回调,在里面做DOM操作
let p = new Promise(resolve => {
$.ajax({
type: "get",
url: url,
data: {
sql: str
},
// dataType: "dataType",
success: data => {
// console.log(str)
resolve(data) //把DOM放外面去操作
// fn(data)
}
})
});
// 把回调放到外面去处理
p.then(data => {
// 如果有就用,没有就不用 不传data也不影响
if (fn) {
fn(data)
}
})
}
function init() {
let url = "./api/select.php"
// uid 不能写死 从cookie中获取 但是登录才可以看,提示用户登录 或者非登录也可以看见购物车数据
let str = "select * from ordergoods where uid=1"
getData(url, str, data => {
let arr = JSON.parse(data)
let str = arr.map(item => {
return `<li class="goods" data-id="${item.id}">
<p class="good_check"><input type="checkbox" name="good" value="" /></p>
<p class="good_name">${item.title}</p>
<p class="good_price">¥ ${item.price}</p>
<p class="num">
<span class="cutnum">-</span>
<input class="nownum" data-num="10" type="text" value="${item.num}" />
<span class="addnum">+</span>
</p>
<p class="good_total">¥ ${item.total}</p>
<p class="good_del">
<a href="javascript:;">删除</a>
</p>
</li>`
}).join("")
$("#cart").html($("#cart").html() + str); //渲染数据到页面
})
}
init()
//数量的变化、小计变化,数据变化
let post = true
function updateNum(now, type) {
//页面数据改变
let num = $(now).parent().find('input').val(); //获取某条商品数量
let id = $(now).parent().parent().data('id'); //jq
let repertory = $(now).parent().find('input').data('num'); //库存量
if (type == 'add') {
//加数量
num++;
} else if (type == 'cut') {
//减数量
num--;
}
if (num > repertory) { //不能超过库存量
num = repertory;
alert('已经达到库存量');
post = false;
} else if (num < 1) {
alert("商品数量至少为1")
num = 1;
post = false;
} else {
post = true;
}
$(now).parent().find("input").val(num)
// 更新小计
// 取出单价
let price = $(now).parent().prev().html().split(";")[1]
// console.log(num)
// console.log(price)
// $(now).parent().next().html('¥ ' + num * price)
let xiaoji = num * price;
$(now).parent().next().html('¥ ' + xiaoji);
let url = "api/other.php"
// let str = `update ordergoods set num=${num} where id=${id}`
let str = `UPDATE ordergoods SET num = ${num},total = ${xiaoji} WHERE id=${id}`;
getData(url, str)
if (post) {
// 数量变化在统计
totalPrice()
}
}
// 加数量
$("#cart").on("click", '.addnum', function () {
updateNum($(this), 'add')
// totalPrice()
})
// 减数量
$("#cart").on("click", '.cutnum', function () {
updateNum($(this), 'cut')
// totalPrice()
})
// 删除当行
$("#cart").on("click", '.good_del a', function () {
let url = "api/other.php"
let id = $(this).parent().parent().data("id")
let str = `DELETE FROM ordergoods WHERE id=${id}`
let isOk = confirm("您是否要删除呢?")
if (isOk) {
getData(url, str) //删除数据库的数据
$(this).parent().parent().remove() //删除页面节点
}
totalPrice()
})
// 全选 ,统计总数量和总价
function getIndex() {
let arr = [] //存被勾选的下标
$(".good_check input").each((index, item) => {
if ($(item).prop("checked")) {
arr.push(index)
}
})
return arr
}
function totalPrice() {
// 统计总数量和总价
let arr = getIndex()
// console.log(arr)
// 计算总数量和总价
let total = 0
let price = 0
arr.forEach(item => {
// item是arr的内容,作为下标来使用
// * 1 是为了转成数字
total += $("#cart .nownum").eq(item).val() * 1
// 看 html 结构中截取两个 把¥和空格截取掉 从下标为2开始 ,0 1 不要
price += $("#cart .good_total").eq(item).html().split(";")[1] * 1
})
// 注意:如果其他页面要用 就把这两个值存起来 total表中
// console.log(total, price)
// 更新页面数据
$("#allnum").html(`已选 ${total} 件商品`)
$("#totalprice").html(`总计(不含运费):¥${price.toFixed(2)}`)
// 查询:如果没有总数量和总价 就插入最新数据 否则就更新数据
let url = "api/select.php"
let str = "select * from total where uid=1" //这里的uid也要自己查 从cookie中能获取
getData(url, str, data => {
// console.log(data)
let arr = JSON.parse(data)
let sql = ""
if (arr.length) {
// 非 0 有 更新数据
sql = `update total set total=${total},priceAll=${price}`
} else {
// 0 没有 插入数据
sql = `INSERT into total(total,priceALL) VALUES(${total},${price})`
}
let url2 = "api/other.php"
getData(url2, sql)
})
}
// 全选
$("#allchecked input").on("click", () => {
let isOk = $("#allchecked input").prop("checked")
$(".good_check input").prop("checked", isOk)
totalPrice()
})
// 反控到全选
function checkAll() {
let total = $(".good_check input").size()
let num = $(".good_check input:checked").size()
if (total == num) {
// 说明全选
$("#allchecked input").prop("checked", true)
} else {
$("#allchecked input").prop("checked", false)
}
}
// 点击之后判断全选和totalprice
$("#cart").on("click", ".good_check input", () => {
checkAll()
totalPrice()
})
// 全删
$('#delall').click(() => {
let arr = getIndex().reverse()
// 打印选中的索引
// console.log(arr);
let isok = confirm('您确定要删除多行吗?');
let idstr = '' //3,4,5
if (isok) {
arr.forEach(item => {
// 把当前的索引的元素删除 ,但是注意 删除一个后,数组的索引会自动排序 3变为2 4变为3 所以上面用倒序,在删除
let gid = $('#cart .goods').eq(item).data('id')
// console.log(gid);
idstr += gid + ','
$('#cart .goods').eq(item).remove()
})
// 删除数据库数据
let url = 'api/other.php';
let str = `DELETE FROM ordergoods WHERE id in (${idstr.slice(0, -1)})`
getData(url, str, data => {
// 这里也可以打印 检查是否有data数据
// console.log(data)
})
// console.log(str)
}
totalPrice()
})
})();
效果图(仅作为演示)
问题截图
获取自定义属性 比如 data -id