Flask 小程序菜品搜索

mina/pages/food/index.wxml

<!--index.wxml-->
<!--1px = 750/320 = 2.34rpx;-->
<view class="container"><!--轮播图--><view class="swiper-container"><swiper class="swiper_box" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" bindchange="swiperchange"><block wx:for="{{banners}}" wx:key="id"><swiper-item><image bindtap="tapBanner" data-id="{{item.id}}" src="{{item.pic_url}}" class="slide-image" width="750rpx" height="562.5rpx" /></swiper-item></block></swiper><view class="dots"><block wx:for="{{banners}}" wx:key="unique"><view class="dot{{index == swiperCurrent ? ' active' : ''}}"></view></block></view></view><!--分类展示--><view class="type-container"><scroll-view class="type-navbar" scroll-x="true"><view class="type-box" wx:for-items="{{categories}}" wx:key="id"><view id="{{item.id}}" class="type-navbar-item {{activeCategoryId == item.id ? 'type-item-on' : ''}}" bindtap="catClick">{{item.name}}</view></view></scroll-view></view><!--搜索框--><view class="search-view" style="background:{{ scrollTop === 0 ?'-webkit-linear-gradient(top, rgba(105,195,170, 1), rgba(105,195,170, 0.3))' :( scrollTop<200 ? 'rgba(105,195,170,'+(scrollTop/400+0.3) +')' : 'rgba(105,195,170,1)')  }} "><view class="search-content"><image src="/images/search-pic.png" class="search-icon" /><input placeholder="请输入搜索内容" class="search-input" maxlength="30" confirm-type="搜索" bindinput='listenerSearchInput'></input><button class='search-btn' bindtap="toSearch">搜索</button></view></view><view class="goods-container"><view class="goods-box" wx:for-items="{{goods}}"  bindtap="toDetailsTap" data-id="{{item.id}}"><view class="img-box"><image src="{{item.pic_url}}" class="image" mode="aspectFill" lazy-load="true" /></view><view class="goods-title">{{item.name}}</view><view style='display:flex;'><view class="goods-price">¥ {{item.min_price}}</view><view wx:if="{{item.price && item.price > 0 && item.min_price != item.price}}" class="goods-price" style='color:#aaa;text-decoration:line-through'>¥ {{item.price}}</view></view></view></view><view hidden="{{loadingMoreHidden ? true : false}}" class="no-more-goods">哥也是有底线的</view>
</view>

分类展示    

用于展示一个包含滚动视图和下拉菜单的页面

scroll-view | 微信开放文档

该段代码是一个简单的小程序页面,包含了一个横向滚动的导航栏和对应的内容展示区域。下面是各部分功能的简单赘述:

  1. <view class="type-container">:定义一个视图容器,用于包裹整个页面的内容。

  2. <scroll-view class="type-navbar" scroll-x="true">:定义一个横向滚动的视图容器,用于展示导航栏。

  3. <view class="type-box" wx:for-items="{{categories}}" wx:key="id">:定义一个视图容器,用于包裹导航栏的每个选项。

  4. <view id="{{item.id}}" class="type-navbar-item {{activeCategoryId == item.id ? 'type-item-on' : ''}}" >:定义一个视图容器,表示导航栏的每个选项。根据activeCategoryId的值来判断当前选项是否被选中,如果选中则添加type-item-on样式。bindtap属性绑定了一个点击事件。

  5. {{item.name}}:展示导航栏选项的名称,使用双花括号{{}}来插入动态数据,在导航栏选项中显示当前元素的名称。

总体来说,该段代码实现了一个横向滚动的导航栏,点击不同的选项可以切换对应的内容展示区域。

事件 | 微信开放文档  如bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。

mina/pages/food/food.js 

实现网络相关请求的加载

//index.js
//获取应用实例
var app = getApp();
Page({data: {indicatorDots: true,autoplay: true,interval: 3000,duration: 1000,loadingHidden: false, // loadingswiperCurrent: 0,categories: [],activeCategoryId: 0,goods: [],scrollTop: "0",loadingMoreHidden: true,searchInput: '',p:1,processing:false},onLoad: function () {var that = this;wx.setNavigationBarTitle({title: app.globalData.shopName});},//解决切换不刷新维内托,每次展示都会调用这个方法onShow:function(){this.getBannerAndCat();},scroll: function (e) {var that = this, scrollTop = that.data.scrollTop;that.setData({scrollTop: e.detail.scrollTop});},//事件处理函数swiperchange: function (e) {this.setData({swiperCurrent: e.detail.current})},listenerSearchInput:function( e ){this.setData({searchInput: e.detail.value});},toSearch:function( e ){this.setData({p:1,goods:[],loadingMoreHidden:true});this.getFoodList();},tapBanner: function (e) {if (e.currentTarget.dataset.id != 0) {wx.navigateTo({url: "/pages/food/info?id=" + e.currentTarget.dataset.id});}},toDetailsTap: function (e) {wx.navigateTo({url: "/pages/food/info?id=" + e.currentTarget.dataset.id});},getBannerAndCat: function () {var that = this;wx.request({url: app.buildUrl("/food/index"),header: app.getRequestHeader(),success: function (res) {var resp = res.data;if (resp.code != 200) {app.alert({"content": resp.msg});return;}that.setData({banners: resp.data.banner_list,categories: resp.data.cat_list});that.getFoodList();}});},catClick: function (e) {this.setData({activeCategoryId: e.currentTarget.id});this.setData({loadingMoreHidden: true,p:1,goods:[]});this.getFoodList();},onReachBottom: function () {var that = this;setTimeout(function () {that.getFoodList();}, 500);},getFoodList: function () {var that = this;if( that.data.processing ){return;}if( !that.data.loadingMoreHidden ){return;}that.setData({processing:true});wx.request({url: app.buildUrl("/food/search"),header: app.getRequestHeader(),data: {cat_id: that.data.activeCategoryId,mix_kw: that.data.searchInput,p: that.data.p,},success: function (res) {var resp = res.data;if (resp.code != 200) {app.alert({"content": resp.msg});return;}var goods = resp.data.list;that.setData({goods: that.data.goods.concat( goods ),p: that.data.p + 1,processing:false});if( resp.data.has_more == 0 ){that.setData({loadingMoreHidden: false});}}});}
});

getBannerAndCat:function(){    }

banner   美/ˈbænər/ adj.极好的,出色的

RequestTask | 微信开放文档  发起 HTTPS 网络请求。

wx.request是微信小程序中用于发起网络请求的API。它可以向服务器发送HTTP请求,并在请求成功或失败时执行相应的回调函数。

以下是一个使用wx.request发起GET请求的示例:

wx.request({url: 'https://api.example.com/data',method: 'GET',success: function(res) {console.log(res.data); // 请求成功时的处理逻辑},fail: function(err) {console.error(err); // 请求失败时的处理逻辑},complete: function() {console.log('请求完成'); // 无论请求成功或失败都会执行的回调函数}
});

在上述示例中,我们通过传入一个对象作为参数来调用wx.request函数。该对象包含了请求的URL、请求方法、成功、失败和完成时的回调函数。

成功时的回调函数会接收一个参数res,其中包含了py服务器返回的数据。我们可以通过res.data来获取返回的数据。

失败时的回调函数会接收一个参数err,其中包含了请求失败的错误信息。

完成时的回调函数不论请求成功或失败都会执行。

需要注意的是,wx.request只能在小程序的前端代码中使用,不能在小程序的云函数中使用。

知识点1:setData({})

setData是小程序中用于更新页面数据的方法。它可以修改this.data中的数据,并将修改后的数据同步到页面上,从而实现页面的更新。

以下是使用setData方法的示例:

// 修改this.data中的数据
this.setData({text: 'changed data'
});// 修改对象或数组字段中的子字段
this.setData({'array[0].text': 'changed data'
});// 修改对象的某个属性
this.setData({'object.text': 'changed data'
});

需要注意的是,直接修改this.data而不调用setData是无法改变页面的状态的,还会造成数据不一致。因此,在小程序中应该始终使用setData来更新页面数据

getFoodList:function(){    }

cat_id 当前选中的id

mix_kw 搜索框的值

catClick:function(e){}

当选中选择分类的时候改变它当前的分类,并设置它的选中值

事件 | 微信开放文档  

currentTargetObject当前组件的一些属性值集合

this当前对象的setData

id就是 index.wxml中的view id对象值

数据库 common/models/member/MemberCart.py

DROP TABLE IF EXISTS `member_cart`;CREATE TABLE `member_cart` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`member_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '会员id',`food_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品id',`quantity` int(11) NOT NULL DEFAULT '0' COMMENT '数量',`updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后一次更新时间',`created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',PRIMARY KEY (`id`),KEY `idx_member_id` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='购物车';
flask-sqlacodegen 'mysql://root:root@127.0.0.1/food_db' --tables member_cart --outfile "common/models/member/MemberCart.py"  --flask

web/controllers/api/Food.py

# -*- coding: utf-8 -*-
from web.controllers.api import route_api
from  flask import request,jsonify,g
from common.models.food.FoodCat import FoodCat
from common.models.food.Food import Food
from common.models.member.MemberCart import MemberCart
from common.models.member.MemberComments import MemberComments
from common.models.member.Member import Member
from common.libs.UrlManager import UrlManager
from common.libs.Helper import getCurrentDate,getDictFilterField,selectFilterObj
from application import app,db
from sqlalchemy import  or_@route_api.route("/food/index" )
def foodIndex():resp = { 'code':200 ,'msg':'操作成功~','data':{} }cat_list = FoodCat.query.filter_by( status = 1 ).order_by( FoodCat.weight.desc() ).all()data_cat_list = []data_cat_list.append({'id': 0,'name': "全部"})if cat_list:for item in cat_list:tmp_data = {'id':item.id,'name':item.name}data_cat_list.append( tmp_data  )resp['data']['cat_list'] = data_cat_listfood_list = Food.query.filter_by( status = 1 )\.order_by( Food.total_count.desc(),Food.id.desc() ).limit(3).all()data_food_list = []if food_list:for item in food_list:tmp_data = {'id':item.id,'pic_url':UrlManager.buildImageUrl( item.main_image )}data_food_list.append( tmp_data )resp['data']['banner_list'] = data_food_listreturn jsonify( resp )@route_api.route("/food/search" )
def foodSearch():resp = {'code': 200, 'msg': '操作成功~', 'data': {}}req = request.valuescat_id = int( req['cat_id'] ) if 'cat_id' in req else 0mix_kw = str(req['mix_kw']) if 'mix_kw' in req else ''p = int( req['p'] ) if 'p' in req else 1if p < 1:p = 1page_size = 10offset = ( p - 1 ) * page_sizequery = Food.query.filter_by(status=1 )if cat_id > 0:query = query.filter_by(cat_id = cat_id)if mix_kw:rule = or_(Food.name.ilike("%{0}%".format(mix_kw)), Food.tags.ilike("%{0}%".format(mix_kw)))query = query.filter(rule)food_list = query.order_by(Food.total_count.desc(), Food.id.desc())\.offset( offset ).limit( page_size ).all()data_food_list = []if food_list:for item in food_list:tmp_data = {'id': item.id,'name': "%s"%( item.name ),'price': str( item.price ),'min_price':str( item.price ),'pic_url': UrlManager.buildImageUrl(item.main_image)}data_food_list.append(tmp_data)resp['data']['list'] = data_food_listresp['data']['has_more'] = 0 if len( data_food_list ) < page_size else 1return jsonify(resp)@route_api.route("/food/info" )
def foodInfo():resp = {'code': 200, 'msg': '操作成功~', 'data': {}}req = request.valuesid = int(req['id']) if 'id' in req else 0food_info = Food.query.filter_by( id = id ).first()if not food_info or not food_info.status :resp['code'] = -1resp['msg'] = "美食已下架"return jsonify(resp)member_info = g.member_infocart_number = 0if member_info:cart_number = MemberCart.query.filter_by( member_id =  member_info.id ).count()resp['data']['info'] = {"id":food_info.id,"name":food_info.name,"summary":food_info.summary,"total_count":food_info.total_count,"comment_count":food_info.comment_count,'main_image':UrlManager.buildImageUrl( food_info.main_image ),"price":str( food_info.price ),"stock":food_info.stock,"pics":[ UrlManager.buildImageUrl( food_info.main_image ) ]}resp['data']['cart_number'] = cart_numberreturn jsonify(resp)@route_api.route("/food/comments")
def foodComments():resp = {'code': 200, 'msg': '操作成功~', 'data': {}}req = request.valuesid = int(req['id']) if 'id' in req else 0query = MemberComments.query.filter( MemberComments.food_ids.ilike("%_{0}_%".format(id)) )list = query.order_by( MemberComments.id.desc() ).limit(5).all()data_list = []if list:member_map = getDictFilterField( Member,Member.id,"id",selectFilterObj( list,"member_id" ) )for item in list:if item.member_id not in member_map:continuetmp_member_info = member_map[ item.member_id ]tmp_data = {'score':item.score_desc,'date': item.created_time.strftime("%Y-%m-%d %H:%M:%S"),"content":item.content,"user":{'nickname':tmp_member_info.nickname,'avatar_url':tmp_member_info.avatar,}}data_list.append( tmp_data )resp['data']['list'] = data_listresp['data']['count'] = query.count()return jsonify(resp)

@route_member.route( "/index" )

将数据统一构造、统一返回  resp_data={}

data是字典类型,返回数据

从数据表中取出可以展示的分类信息   food_cat表

        step1: 取出可以展示的类别并进行排序

        step2: 将数据统一构造再返回

        step3:  条件判断: 字段查询到则进行循环展示

从数据表中取出销售排前的菜品信息  food表

        step1: 取出菜品信息进行倒叙排列【将销售量最大的3个商品展示出来】

        step2:  格式化该菜品信息以满足前端信息要求格式

        step3:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/345705.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ceph】在虚拟环境中需要给osd所在的虚拟盘扩容操作

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

用通俗易懂的方式讲解:内容讲解+代码案例,轻松掌握大模型应用框架 LangChain

本文介绍了 LangChain 框架&#xff0c;它能够将大型语言模型与其他计算或知识来源相结合&#xff0c;从而实现功能更加强大的应用。 接着&#xff0c;对LangChain的关键概念进行了详细说明&#xff0c;并基于该框架进行了一些案例尝试&#xff0c;旨在帮助读者更轻松地理解 L…

java方法的定义和使用

方法 今日目标&#xff1a; 能够知道方法的好处 能够根据两个明确分析方法的参数和返回值 能够编写方法完成授课案例&#xff0c;并在主方法中完成方法的调用 能够知道方法重载及其特点 1&#xff1a;方法的定义和使用 1.1 方法概述 方法(method)&#xff1a;就是完成特…

ubantu运维,nginx相关操作

1、使用 命令ps aux | grep nginx查找nginx 运行目录&#xff0c;如下图&#xff1a; 2、使用 ​​​​​​​命令cd /usr/sbin 切换到nginx 运行目录&#xff0c;如下图&#xff1a; 3、修改配置文件后&#xff0c;使用 nginx -t 命令测试nginx配置文件的语法是否正确&#x…

C# 图解教程 第5版 —— 第23章 异常

文章目录 23.1 什么是异常23.2 try 语句23.3 异常类23.4 catch 子句23.5 异常过滤器23.6 catch 子句段23.7 finally 块23.8 为异常寻找处理程序23.9 进一步搜索23.9.1 一般法则23.9.2 搜索调用栈的示例&#xff08;*&#xff09; 23.10 抛出异常23.11 不带异常对象的抛出23.12 …

Java内置锁:深度解析lock和trylock

lock和tryLock是两种获取锁的方式&#xff0c;它们在处理并发问题时有所不同&#xff0c;lock是阻塞性的&#xff0c;确保只有一个线程能访问被锁资源&#xff0c;但可能导致线程长时间等待&#xff1b;而tryLock非阻塞性&#xff0c;若锁被占用则立即返回失败&#xff0c;避免…

蓝桥杯AcWing学习笔记 8-1数论的学习(上)

蓝桥杯 我的AcWing 题目及图片来自蓝桥杯C AB组辅导课 数论&#xff08;上&#xff09; 蓝桥杯省赛中考的数论不是很多&#xff0c;这里讲几个蓝桥杯常考的知识点。 欧几里得算法——辗转相除法 欧几里得算法代码&#xff1a; import java.util.Scanner ;public class Main…

云服务器十大服务商——云服务器哪家好用

云服务器哪家便宜&#xff1f;2024最新整理你要的都在这&#xff01;头部云厂商阿里云、腾讯云、华为云、京东云、UCloud等都在降价&#xff0c;阿腾云atengyun.com分享2024年云服务器租用价格给你惊喜&#xff01; 便宜云服务器阿里云腾讯云华为云 2024年便宜云服务器汇总&…

6.2 声音编辑工具GoldWave5简介(6)

3&#xff0e;选择【选项】|【控制器属性】命名或单击“控制器”面板上的“设置控制器属性”按钮&#xff0c;打开“控制器属性”对话框&#xff0c;将“音量”选项卡中的“麦克风”选项打上勾&#xff0c;使GoldWave只能录制来自麦克风的声音。如果要录制电脑内部的声音&#…

RTMP 视频数据封装

RTMP 协议 与HTTP(超文本传输协议)同样是一个基于TCP的Real Time Messaging Protocol(实时消息传输协议)。由Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的一种开放协议 。在国内被广泛的应用于直 播领域。HTTP默认端口为80&#xff0c;RTMP则为1935…

第8章-第6节-Java中字符流的缓冲流

1、在说正题之前&#xff0c;先说一个小细节&#xff0c;不管是字节流还是字符流都要注意这个细节&#xff0c;具体看这篇博文&#xff1a;关于Java的IO流里面的方法read()的小细节 2、字符流的缓冲流&#xff1a; 1&#xff09;、BufferedWriter 方法名说明void newLine()写…

专业课145+合肥工业大学833信号分析与处理考研经验合工大电子信息通信

今年专业课145也是考研科目中最满意的一门&#xff0c;其他基本相对平平&#xff0c;所以这里我总结一下自己的专业课合肥工业大学833信号分析与处理的复习经验。 我所用的教材是郑君里的《信号与系统》&#xff08;第三版&#xff09;和高西全、丁玉美的《数字信号处理》&…