今天分享的是微信商城小程序的商品详情展示以及购物车展示添加功能的简单实现,同样还是基于前期分享的免费可商用的后台管理系统+微信小程序前端项目进行实现,不太清楚的可以点击下方链接查看前期分享内容:
效果展示
订单表
这里简单根据购物车的基本属性设计了一张简单的购物车数据表,外键、索引啥的都暂时没做考虑:
CREATE TABLE `ba_product_car` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` int(10) DEFAULT NULL COMMENT '用户ID',
`product_id` int(10) DEFAULT NULL COMMENT '商品ID',
`product_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '商品名称',
`product_img` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '商品封面图',
`product_price` int(10) DEFAULT NULL COMMENT '商品单价',
`product_original_price` int(10) DEFAULT NULL COMMENT '商品原价',
`count` int(10) DEFAULT NULL COMMENT '数量',
`status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '状态:0=删除,1=启用',
`create_time` bigint(16) unsigned DEFAULT NULL COMMENT '创建时间',
`update_time` bigint(16) unsigned DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='购物车';
API
API同样利用BuildAdmin框架的API能力进行开发,这里简单分享商品详情、购物车添加更新、查询的API,其他的类似开发即可~
商品详情
/**
* 根据商品ID查询商品详情
*
* @return void
*/
function detail(){
if (!$this->request->isGet()) $this->error(__('Request error'));
$pId = $this->request->get('pid', -1);
if(empty($pId) || $pId < 1){
$this->error('参数错误', [], -1);
return;
}
$cond = [
'id' => $pId,
'status'=> 1,
];
$data = Products::where($cond) -> find();
$data->cover_img = 'http://yinian.service1000.cn/' . $data->cover_img;
if(!$data){
$this->error('暂无数据', [], -1);
return;
}
$this->success('查询成功', $data, 200);
}
购物车
<?php
namespace app\api\controller;
use app\common\controller\Frontend;
use app\api\model\ProductCar;
/**
* 商城购物车相关接口
*/
class MiniCar extends Frontend
{
protected array $noNeedLogin = ['addCar', 'getCarList'];
/**
* 添加购物车
*/
public function addCar()
{
if (!$this->request->isPost()) $this->error(__('Request error'));
// 获取原始的 JSON 数据
$json = file_get_contents('php://input');
// 将 JSON 数据解码为 PHP 数组
// $data = json_decode($json, true);
if (self::checkParam($json)) {
// 参数校验通过,将数据插入数据库
self::checkCarData($json);
} else {
$this->customResponse('缺少参数', -1);
}
}
/**
* 检查购物车数据
*
* @param [type] $param
* @return void
*/
private function checkCarData($param)
{
$data = json_decode($param, true);
// echo $data;
// echo $data['user_id'];
// 根据商品id查询购物车是否存在相同的商品数据,如果存在,则更新添加的购物车数量,如果不存在,则直接新增购物车数据
$cond = [
'user_id' => $data['user_id'],
'product_id' => $data['product_id'],
'status' => 1,
];
$carData = ProductCar::where($cond) -> find();
if(empty($carData)){
self::insertCarData($data);
}else{
self::updateCarData($carData, $data);
}
}
/**
* 更新购物车数据
*
* @param [type] $carData
* @param [type] $data
* @return void
*/
private function updateCarData($carData, $data){
$count = $carData['count'] + $data['count'];
$carData = [
'count' => $count,
'update_time' => time()
];
$cond = [
'user_id' => $data['user_id'],
'product_id' => $data['product_id'],
'status' => 1,
];
$model = ProductCar::update($carData, $cond);
if ($model) {
$this -> customResponse("更新购物车成功", 200);
} else {
$this -> customResponse("更新购物车失败", -1);
}
}
/**
* 添加购物车数据
*
* @param [type] $data
* @return void
*/
private function insertCarData($data){
$carData = [
'user_id' => $data['user_id'],
'product_id' => $data['product_id'],
'product_name' => $data['product_name'],
'product_img' => $data['product_img'],
'product_price' => $data['product_price'],
'product_original_price'=> $data['product_original_price'],
'count' => $data['count'],
'crate_time' => time(),
'update_time' => time(),
];
$model = ProductCar::create($carData);
$model->save();
if ($model) {
$this -> customResponse("添加购物车成功", 200);
} else {
$this -> customResponse("添加购物车失败", -1);
}
}
/**
* 检查添加购物车参数是否完整
*
* @param [type] $param
* @return boolean
*/
private function checkParam($param): bool
{
if (!empty($param)) {
if (
strpos($param, 'user_id')
|| strpos($param, 'product_id')
|| strpos($param, 'product_name')
|| strpos($param, 'product_img')
|| strpos($param, 'product_price')
|| strpos($param, 'product_original_price')
|| strpos($param, 'count')
) {
return true;
}
}
return false;
}
/**
* 获取购物车列表
*/
public function getCarList()
{
if (!$this->request->isGet()) $this->error(__('Request error'));
$cond = [
'user_id' => $_GET['user_id'],
'status' => 1,
];
$carList = ProductCar::where($cond) -> select();
if ($carList) {
$this -> customResponse("获取购物车列表成功", 200, $carList);
}
}
}
微信小程序端
商品详情
onLoad(options) {
console.log("接收的参数:", options);
this.setData({
pid: options.pid
})
console.log("pid=", this.data.pid)
this.getDetail()
},
getDetail() {
const that = this
if (this.data.pid < 1) {
wx.showToast({
title: '商品id不能为空',
icon: 'none'
})
} else {
wx.request({
url: constants.URL_GET_PRODUCT_DETAIL + "&pid=" + this.data.pid,
success(res) {
console.log("res", res.data)
if (res.data.code == 200) {
that.setData({
goods: res.data.data
})
} else {
wx.showToast({
title: res.data,
msg: res.data.msg,
icon: 'error'
})
}
},
fail(err) {
wx.showToast({
title: '商品信息获取失败',
icon: 'error'
})
}
})
}
},
添加购物车
addToCart() {
const self = this;
const num = this.data.num;
let total = this.data.totalNum;
// 调用接口添加到购物车
let userId = wx.getStorageSync(constantsKeys.USER_ID);
if (userId > 0) {
let param = {
"user_id": userId,
"product_id": this.data.goods.id,
"product_name": this.data.goods.name,
"product_img": this.data.goods.cover_img,
"product_price": this.data.goods.price,
"product_original_price": this.data.goods.original_price,
"count": num
};
wx.request({
url: constants.URL_ADD_CAR,
method: 'POST',
data: param,
header: {
'Content-Type': 'application/json'
},
success(res) {
if (res.data.code == 200) {
console.log("购物车添加成功", res.data)
self.setData({
show: true
})
setTimeout(function () {
self.setData({
show: false,
scaleCart: true
})
setTimeout(function () {
self.setData({
scaleCart: false,
hasCarts: true,
totalNum: num + total
})
}, 200)
}, 300)
} else {
console.log("购物车添加失败", res.data.msg)
}
},
fail(err) {
console.log("购物车添加失败", res.data.msg)
}
})
}else{
// 获取失败可以跳转到登录页面进行登录
console.log("userId获取失败")
}
扩展
其实分享的内容、包括代码整体都是比较粗糙的,大家在实际的开发过程中需要注意的还是有一些,比如:
登录信息持久化
由于商城系统是需要身份权限的,所以当我们登录成功后,需要将用户信息缓存下来,供后续模块展示以及调用接口使用,这里常规的做法是使用wx.setStorageSync存储数据。
接口鉴权
使用BuildAdmin开发的API接口,如果不需要鉴权,只需要使用以下方式声明即可:
protected array $noNeedLogin = ['index', 'detail'];
而如果需要鉴权的,在请求API接口时需要在header中携带token数据,对应的键值对为:
ba-user-token: 登录时获取的token数据
写在最后
其实利用分享的这两套框架开发微信商城小程序是比较简单、快捷的,所以决定暂时暂停后续模块的实现分享,如果谁有需要,欢迎随时评论、私信交流~