flask 与小程序 购物车删除和编辑库存功能

编辑 : 数量加减 价格汇总 数据清空

mina/pages/cart/index.wxml

XML 复制代码
<!--index.wxml-->
<view class="container">
    <view class="title-box" wx:if="{{ !list.length }}">
        购物车空空如也~
    </view>
    <view class="to-index-btn" bindtap="toIndexPage" wx:if="{{ !list.length }}">
        去逛逛
    </view>

    <view class="list-top" wx:if="{{ list.length }}">
        <view class="label">购物车</view>
        <view class="edit-btn" hidden="{{!saveHidden}}" bindtap="editTap">编辑</view>
        <view class="edit-btn" hidden="{{saveHidden}}" bindtap="saveTap">完成</view>
    </view>

    <view class="goodsList" wx:if="{{ list.length }}">
        <view class="a-gooods" wx:for="{{ list }}"  wx:key="{{index}}" >
            <view class="a-goods-conts {{item.active? 'active':''}}" bindtap="selectTap" data-index="{{index}}">
                <view class="goods-info">
                    <view class="img-box">
                        <image src="{{item.pic_url}}" class="img"/>
                    </view>
                    <view class="text-box">
                        <view class="goods-title">{{item.name}}</view>
                        <view class="goods-price">¥ {{item.price}}</view>
                        <view class="buy-num">
                            <view class="jian-btn" catchtap="jianBtnTap" data-index="{{index}}">-</view>
                            <input  type="number" value="{{item.number}}" disabled/>
                            <view class="jia-btn" catchtap="jiaBtnTap" data-index="{{index}}">+</view>
                        </view>
                    </view>
                </view>
            </view>
        </view>
    </view>
    <view class="jiesuan-box" wx:if="{{ list.length }}">
        <view class="left-price">
            <view class="all-selected  {{allSelect?'active':''}}" bindtap="bindAllSelect">全选</view>
            <view class="total" hidden="{{noSelect}}">合计:¥ {{totalPrice}}</view>
        </view>
        <view class="to-pay-btn {{noSelect?'no-select':''}}" hidden="{{!saveHidden}}" bindtap="toPayOrder">去结算</view>
        <view class="to-pay-btn {{noSelect?'no-select':''}}" hidden="{{saveHidden}}" bindtap="deleteSelected">删除</view>
    </view>
</view>

知识点1: <view class="jian-btn" catchtap="jianBtnTap" data-index="{{index}}">

是一个微信小程序中的一个视图组件,具有以下特点:

  • class="jian-btn":该组件的样式类名为jian-btn,可以通过CSS样式表对其进行样式设置。
  • catchtap="jianBtnTap":该组件绑定了一个catchtap事件,当用户点击该组件时,会触发名为jianBtnTap的事件处理函数。微信小程序 事件_w3cschool
  • data-index="{``{index}}":该组件设置了一个自定义属性data-index,其值为{``{index}},可以在事件处理函数中获取该属性的值。

根据提供的信息,这个组件可能是一个按钮,当用户点击该按钮时,会触发jianBtnTap事件处理函数,并且可以通过data-index属性传递一些额外的数据。

请注意,以上是根据提供的引用内容推测的答案,具体的功能和效果还需要根据实际代码和上下文来确定。

mina/pages/cart/index.js

javascript 复制代码
//index.js
var app = getApp();
Page({
    data: {},
    onLoad: function () {

    },
    onShow:function(){
        this.getCartList();
    },
    //每项前面的选中框
    selectTap: function (e) {
        var index = e.currentTarget.dataset.index;
        var list = this.data.list;
        if (index !== "" && index != null) {
            list[ parseInt(index) ].active = !list[ parseInt(index) ].active;
            this.setPageData(this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
        }
    },
    //计算是否全选了
    allSelect: function () {
        var list = this.data.list;
        var allSelect = false;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            if (curItem.active) {
                allSelect = true;
            } else {
                allSelect = false;
                break;
            }
        }
        return allSelect;
    },
    //计算是否都没有选
    noSelect: function () {
        var list = this.data.list;
        var noSelect = 0;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            if (!curItem.active) {
                noSelect++;
            }
        }
        if (noSelect == list.length) {
            return true;
        } else {
            return false;
        }
    },
    //全选和全部选按钮
    bindAllSelect: function () {
        var currentAllSelect = this.data.allSelect;
        var list = this.data.list;
        for (var i = 0; i < list.length; i++) {
            list[i].active = !currentAllSelect;
        }
        this.setPageData(this.getSaveHide(), this.totalPrice(), !currentAllSelect, this.noSelect(), list);
    },
    //加数量
    jiaBtnTap: function (e) {
        var that = this;
        var index = e.currentTarget.dataset.index;
        var list = that.data.list;
        list[parseInt(index)].number++;
        that.setPageData(that.getSaveHide(), that.totalPrice(), that.allSelect(), that.noSelect(), list);
        this.setCart( list[parseInt(index)].food_id,list[parseInt(index)].number );
    },
    //减数量
    jianBtnTap: function (e) {
        var index = e.currentTarget.dataset.index;
        var list = this.data.list;
        if (list[parseInt(index)].number > 1) {
            list[parseInt(index)].number--;
            this.setPageData(this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);

            this.setCart( list[parseInt(index)].food_id,list[parseInt(index)].number );
        }
    },
    //编辑默认全不选
    editTap: function () {
        var list = this.data.list;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            curItem.active = false;
        }
        this.setPageData(!this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
    },
    //选中完成默认全选
    saveTap: function () {
        var list = this.data.list;
        for (var i = 0; i < list.length; i++) {
            var curItem = list[i];
            curItem.active = true;
        }
        this.setPageData(!this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
    },
    getSaveHide: function () {
        return this.data.saveHidden;
    },
    totalPrice: function () {
        var list = this.data.list;
        var totalPrice = 0.00;
        for (var i = 0; i < list.length; i++) {
            if ( !list[i].active) {
                continue;
            }
            totalPrice = totalPrice + parseFloat( list[i].price ) * list[i].number;
        }
        return totalPrice;
    },
    setPageData: function (saveHidden, total, allSelect, noSelect, list) {
        this.setData({
            list: list,
            saveHidden: saveHidden,
            totalPrice: total,
            allSelect: allSelect,
            noSelect: noSelect,
        });
    },
    //去结算
    toPayOrder: function () {
        var data = {
            type:"cart",
            goods: []
        };

        var list = this.data.list;
        for (var i = 0; i < list.length; i++) {
            if ( !list[i].active) {
                continue;
            }
            data['goods'].push({
                "id": list[i].food_id,
                "price": list[i].price,
                "number": list[i].number
            });
        }

        wx.navigateTo({
            url: "/pages/order/index?data=" + JSON.stringify(data)
        });
    },
    //如果没有显示去光光按钮事件
    toIndexPage: function () {
        wx.switchTab({
            url: "/pages/food/index"
        });
    },
    //选中删除的数据
    deleteSelected: function () {
        var list = this.data.list;
        var goods = [];
        list = list.filter(function ( item ) {
            if( item.active ){
                goods.push( {
                    "id":item.food_id
                } )
            }

            return !item.active;
        });

        this.setPageData( this.getSaveHide(), this.totalPrice(), this.allSelect(), this.noSelect(), list);
        //发送请求到后台删除数据
        wx.request({
            url: app.buildUrl("/cart/del"),
            header: app.getRequestHeader(),
            method: 'POST',
            data: {
                goods: JSON.stringify( goods )
            },
            success: function (res) {
            }
        });
    },
    getCartList: function () {
        var that = this;
        wx.request({
            url: app.buildUrl("/cart/index"),
            header: app.getRequestHeader(),
            success: function (res) {
                var resp = res.data;
                if (resp.code != 200) {
                    app.alert({"content": resp.msg});
                    return;
                }
                that.setData({
                    list:resp.data.list,
                    saveHidden: true,
                    totalPrice: 0.00,
                    allSelect: true,
                    noSelect: false
                });

                that.setPageData(that.getSaveHide(), that.totalPrice(), that.allSelect(), that.noSelect(), that.data.list);
            }
        });
    },
    setCart:function( food_id, number ){
        var that = this;
        var data = {
            "id": food_id,
            "number": number
        };
        wx.request({
            url: app.buildUrl("/cart/set"),
            header: app.getRequestHeader(),
            method: 'POST',
            data: data,
            success: function (res) {
            }
        });
    }
});

setCart 数据统一提交

问题1: .push()

JavaScript push() 方法_w3cschool 类似python中append

push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。

注意: 新元素将添加在数组的末尾。

注意: 此方法改变数组的长度。

提示: 在数组起始位置添加元素请使用 unshift() 方法。

问题2: JSON.stringify( )

JSON.stringify()方法用于将JavaScript对象转换为JSON字符串。

下面是一个关于goods对象的例子:

javascript 复制代码
const goods = {
  name: "Apple",
  price: 2.99,
  quantity: 10
};

const jsonString = JSON.stringify(goods);
console.log(jsonString);

输出结果为:

javascript 复制代码
{"name":"Apple","price":2.99,"quantity":10}

这里,goods对象被转换为了一个JSON字符串,其中包含了对象的属性和对应的值。注意,JSON.stringify()方法会自动将对象的属性名和属性值转换为字符串,并且会忽略掉不可枚举的属性。

web/controllers/api/Cart.py

javascript 复制代码
# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from  flask import request,jsonify,g
from common.models.food.Food import Food
from common.models.member.MemberCart import MemberCart
from common.libs.member.CartService import CartService
from common.libs.Helper import selectFilterObj,getDictFilterField
from common.libs.UrlManager import UrlManager
from application import app,db
import json

@route_api.route("/cart/index")
def cartIndex():
    resp = {'code': 200, 'msg': '添加购物车成功~', 'data': {}}
    member_info = g.member_info
    if not member_info:
        resp['code'] = -1
        resp['msg'] = "获取失败,伪登录~~"
        return jsonify(resp)
    cart_list = MemberCart.query.filter_by( member_id=member_info.id).all()
    data_cart_list = []
    if cart_list:
        food_ids = selectFilterObj( cart_list,"food_id" )
        food_map = getDictFilterField( Food,Food.id,"id",food_ids )
        for item in cart_list:
            tmp_food_info = food_map[ item.food_id ]
            tmp_data = {
                "id":item.id,
                "number":item.quantity,
                "food_id": item.food_id,
                "name":tmp_food_info.name,
                "price":str( tmp_food_info.price ),
                "pic_url": UrlManager.buildImageUrl( tmp_food_info.main_image ),
                "active":True
            }
            data_cart_list.append( tmp_data )

    resp['data']['list'] = data_cart_list
    return jsonify(resp)

@route_api.route("/cart/set", methods=["POST"])
def setCart():
    resp = {'code': 200, 'msg': '添加购物车成功~', 'data': {}}
    req = request.values
    food_id = int(req['id']) if 'id' in req else 0
    number = int(req['number']) if 'number' in req else 0
    if food_id < 1 or number < 1:
        resp['code'] = -1
        resp['msg'] = "添加购物车失败-1~~"
        return jsonify(resp)

    member_info = g.member_info
    if not member_info:
        resp['code'] = -1
        resp['msg'] = "添加购物车失败-2~~"
        return jsonify(resp)

    food_info = Food.query.filter_by( id =  food_id ).first()
    if not food_info:
        resp['code'] = -1
        resp['msg'] = "添加购物车失败-3~~"
        return jsonify(resp)

    if food_info.stock < number:
        resp['code'] = -1
        resp['msg'] = "添加购物车失败,库存不足~~"
        return jsonify(resp)

    ret =  CartService.setItems( member_id=member_info.id,food_id = food_info.id,number = number )
    if not ret:
        resp['code'] = -1
        resp['msg'] = "添加购物车失败-4~~"
        return jsonify(resp)
    return jsonify(resp)

@route_api.route("/cart/del", methods=["POST"])
def delCart():
    resp = {'code': 200, 'msg': '添加购物车成功~', 'data': {}}
    req = request.values
    params_goods = req['goods'] if 'goods' in req else None

    items = []
    if params_goods:
        items = json.loads(params_goods)
    if not items or len( items ) < 1:
        return jsonify(resp)

    member_info = g.member_info
    if not member_info:
        resp['code'] = -1
        resp['msg'] = "删除购物车失败-1~~"
        return jsonify(resp)

    ret = CartService.deleteItem( member_id = member_info.id, items = items )
    if not ret:
        resp['code'] = -1
        resp['msg'] = "删除购物车失败-2~~"
        return jsonify(resp)
    return jsonify(resp)

@route_api.route("/cart/del", methods=["POST"])

问题1: json.loads()

json.loads()是Python标准库json模块中的一个方法,用于将JSON字符串转换为Python数据类型。它的使用方法如下所示:

python 复制代码
import json

json_str = '{"name": "John", "age": 30, "city": "New York"}'
data = json.loads(json_str)

print(data)  # 输出:{'name': 'John', 'age': 30, 'city': 'New York'}

在上面的例子中,我们首先导入了json模块。然后,我们定义了一个JSON字符串json_str,其中包含了一个名为"name"的键和对应的值"John",一个名为"age"的键和对应的值30,以及一个名为"city"的键和对应的值"New York"。接下来,我们使用json.loads()方法将JSON字符串转换为Python数据类型,并将结果赋值给变量data。最后,我们打印出data的值,即转换后的Python字典。

需要注意的是,json.loads()只适用于读取JSON字符串,如果想要从JSON文件中读取数据,请使用json.load()方法。

common/libs/Helper.py

python 复制代码
# -*- coding: utf-8 -*-
import hashlib,requests,random,string,json
from application import app,db
from common.models.member.MemberCart import MemberCart
from common.libs.Helper import getCurrentDate
class CartService():

    @staticmethod
    def deleteItem( member_id = 0,items = None ):
        if member_id < 1 or not items:
            return False
        for item in items:
            MemberCart.query.filter_by( food_id = item['id'],member_id = member_id ).delete()
        db.session.commit()
        return True

    @staticmethod
    def setItems( member_id = 0,food_id = 0,number = 0 ):
        if member_id < 1 or food_id < 1 or number < 1:
            return False
        cart_info = MemberCart.query.filter_by( food_id = food_id, member_id= member_id ).first()
        if cart_info:
            model_cart = cart_info
        else:
            model_cart = MemberCart()
            model_cart.member_id = member_id
            model_cart.created_time = getCurrentDate()

        model_cart.food_id = food_id
        model_cart.quantity = number
        model_cart.updated_time = getCurrentDate()
        db.session.add(model_cart)
        db.session.commit()
        return True
相关推荐
非凡ghost43 分钟前
Typora(跨平台MarkDown编辑器) v1.12.2 中文绿色版
前端·windows·智能手机·编辑器·软件需求
十五年专注C++开发1 小时前
CFF Explorer: 一款Windows PE 文件分析的好工具
c++·windows·microsoft
Bruce_Liuxiaowei2 小时前
Windows系统错误6118全面解决方案:修复此工作组的服务器列表当前无法使用
运维·服务器·windows·网络安全
狂团商城小师妹2 小时前
预约洗车小程序
微信小程序·小程序
future_studio2 小时前
聊聊 Unity(小白专享、C# 小程序 之 图片播放器)
unity·小程序·c#
水饺编程3 小时前
第3章,[标签 Win32] :窗口类03,窗口过程函数字段
c语言·c++·windows·visual studio
一苓二肆4 小时前
代码加密技术
linux·windows·python·spring·eclipse
LinXunFeng4 小时前
如何舒适地沉浸式编程,这是我的答案
windows·程序员·mac
初听于你5 小时前
深入了解—揭秘计算机底层奥秘
windows·tcp/ip·计算机网络·面试·架构·电脑·vim
Q_Q5110082857 小时前
python+uniapp基于微信小程序的心理咨询信息系统
spring boot·python·微信小程序·django·flask·uni-app·node.js