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
相关推荐
Skrrapper1 小时前
Flask 入门到实战(2):使用 SQLAlchemy 打造可持久化的数据层
后端·python·flask
ljh5746491192 小时前
Airtest 的 Poco 框架中,offspring()
windows
2501_9159184111 小时前
Fiddler中文版全面评测:功能亮点、使用场景与中文网资源整合指南
android·ios·小程序·https·uni-app·iphone·webview
斜月三12 小时前
windows部署多实例filebeat监控相同路径下文件
windows·filebeat
说私域12 小时前
从品牌附庸到自我表达:定制开发开源AI智能名片S2B2C商城小程序赋能下的营销变革
人工智能·小程序
難釋懷12 小时前
第一个小程序
小程序
春哥的研究所12 小时前
可视化DIY小程序工具!开源拖拽式源码系统,自由搭建,完整的源代码包分享
小程序·开源·开源拖拽式源码系统·开源拖拽式源码·开源拖拽式系统
weixin_lynhgworld12 小时前
盲盒一番赏小程序技术实现方案:高并发与防作弊的平衡之道
小程序
今日热点13 小时前
小程序主体变更全攻略:流程、资料与异常处理方案
经验分享·微信·小程序·企业微信·微信公众平台·微信开放平台
尽兴-15 小时前
如何将多个.sql文件合并成一个:Windows和Linux/Mac详细指南
linux·数据库·windows·sql·macos