如何使用Flutter+SpringBoot+Mysql开发一个简易的抽奖APP(Android)教学

如果你需要项目资源,欢迎来到我的个人博客:https://brath.top/2023/02/24/%E3%80%90Flutter&SpringBoot%E3%80%91%E5%A6%82%E4%BD%95%E7%94%A8Flutter%E5%92%8CJava%E6%9D%A5%E5%BC%80%E5%8F%91%E4%B8%80%E4%B8%AA%E6%8A%BD%E5%A5%96APP/

APP体验地址:http://interviewnote.online:8080/weat.apk


前言:


Weat 中文译为:吃啥

吃啥来自于女朋友的一个问题,问我可不可以做个抽奖的APP,奖品都是菜,抽中那个今天就做那个菜吃,我灵机一动,使用InterviewCoder公众号里面的chatGPT小程序编辑了下面的文案:
吃啥是一款新奇有趣的应用,旨在帮助你找到今天吃什么菜。它通过精心的菜谱抽奖模式,为你提供多样而有色彩的食物,让你的用餐经历变得更加美好。不仅如此,它还可以添加朋友和家人的偏好,为大家带来更多惊喜。加入吃啥,让你的用餐经历变得更加完美!

架构方面:

移动端:Flutter

后台服务:SpringBoot、Mysql

没有安装dart、flutter、Android Studio、vscode的同学可以看看以前的教程,这里就不 一 一 介绍了

本文将详细介绍weatapp的开发流程,前后端代码编写阶段,以及后台代码部署。

一、APP创建:


  1. 打开项目路径,输入cmd进入到命令行,输入 flutter create weat 进行flutter项目创建。

  1. 打开Android Studio整理项目,修改仓库配置

maven { url'https://maven.aliyun.com/repository/google' }

maven { url'https://maven.aliyun.com/repository/jcenter' }

maven { url'http://maven.aliyun.com/nexus/content/groups/public' }

3.点击Open for Editing in Android Studio 进入安卓视图,拉取gradle库

4.当Android主文件不暴红,说明配置完毕了,gradle库已经拉下来了

二、APP启动:


1.打开一个安卓模拟器,有条件的同学可以直接使用真机,老师这里为了方便就直接用模拟器了

2.使用vscode打开项目并启动flutter项目

至此,一个flutter项目,创建完成,并启动了!

三、APP图标配置


需要打开两个网址:

https://logo.aliyun.com/logo#/name 阿里云LOGO服务

https://icon.wuruihong.com/ 图标工厂

1.打开阿里云LOGO 输入APP名字,吃啥

2.生成图标:

购买一个你喜欢的图标,如果不购买的话,自己在网上找一个也行,但是一定要有商业授权!

得到图标后,进入图标工厂,生成一套ios和一套Android的图标文件:

进入安卓文件夹,将该目录的文件复制到你的项目下面 \android\app\src\main\res

成效:

至此,APP图标设置完成!

四、APP后台开发(SpringBoot+Mysql)


为什么先开发APP部分?,这个纯属个人习惯,我比较喜欢先有数据和接口,直接开发APP的感觉会更轻松!

整理需求:

每次进入app随机获取食物列表

点击开始抽奖 随机跳转 点击停止 按钮回显食物名称 点击查看菜谱 弹窗提示做法

根据如上需求,我明确了客户到底想要什么

1.这是一个服务类型的APP,服务于不知道吃什么的客户

2.每次进入抽奖页面需要获取不同的菜谱奖品列表

3.这个页面需要有个按钮,可以来重置奖品,并且要限制次数

4.点击抽奖按钮,开始抽奖,再次点击,或者超过限制时间,停止选择,并将按钮置为:查看食谱

5.点击查看食谱,进入食谱详情,展示过程

根据我的聪明思考,画出了如下UI:

开玩笑,画的很烂,但是就是这个意思!。

那么,开始开发后台数据,为我们的APP提供一个接口~!

经过一系列操作,得到以下数据:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS =0;
​
-- ----------------------------
-- Table structure for iv_dishes
-- ----------------------------
DROPTABLEIFEXISTS`iv_dishes`;
CREATETABLE`iv_dishes`  (`id`int(50)NOTNULLAUTO_INCREMENTCOMMENT'唯一ID',`dishes_name`varchar(255)CHARACTERSET utf8 COLLATE utf8_general_ci NULLDEFAULTNULLCOMMENT'菜品名字',`dishes_step`varchar(255)CHARACTERSET utf8 COLLATE utf8_general_ci NULLDEFAULTNULLCOMMENT'菜品做法',`dishes_url`varchar(255)CHARACTERSET utf8 COLLATE utf8_general_ci NULLDEFAULTNULLCOMMENT'菜品图片地址',PRIMARYKEY(`id`)USINGBTREE
)ENGINE=InnoDBAUTO_INCREMENT=9CHARACTERSET= utf8 COLLATE= utf8_general_ci COMMENT='菜品表'ROW_FORMAT= Compact;
​
-- ----------------------------
-- Records of iv_dishes
-- ----------------------------
INSERTINTO`iv_dishes`VALUES(1,'凉拌黄瓜虾仁','1.小米辣 白芝麻蒜未辣椒面 淋上少许热油\r\n2.生抽2勺 油 醋各1代糖半勺搅匀备用\r\n3.虾煮熟去壳 木耳焯水捞出 黄瓜拍块\r\n4.淋上酱汁拌匀即可','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224081935481.png');
INSERTINTO`iv_dishes`VALUES(2,'低卡酱油鸡蛋','1.生抽4勺 醋2香油1勺一把葱花\r\n2.鸡蛋冷水下锅煮8分钟盖盖焖1分钟后泡冷水\r\n3.温开水4勺搅匀\r\n4.鸡蛋剥壳切对半淋上酱汁拌匀即可','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224082035768.png');
INSERTINTO`iv_dishes`VALUES(3,'低卡葱香鸡腿','1.蒜末 葱花 白艺麻小米辣淋上少许热油\r\n2.生抽1勺 许盐搅匀\r\n3.鸡腿熟捞出微凉后撕成小块\r\n4.淋上酱汁拌匀即可','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224082101091.png');
INSERTINTO`iv_dishes`VALUES(4,'低卡平菇炒蛋','1.鸡蛋炒熟盛出\r\n2.油热下从蒜炒香\r\n3.下平菇炒出汁,倒入炒好的鸡蛋\r\n4.生抽 油 辣椒粉各1勺 少许盐炒匀即可','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224082137439.png');
INSERTINTO`iv_dishes`VALUES(5,'凉拌虾仁西兰花','1.蒜未 葱花 辣椒面白芝麻淋上少许热油\r\n2.生抽2勺 醋各1勺搅拌均匀\r\n3.西兰花焯水捞出,虾焯水去壳鸡蛋白切块\r\n4.淋上酱汁拌匀即可','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224082204322.png');
INSERTINTO`iv_dishes`VALUES(6,'凉拌黄瓜木耳鸡蛋','1.木耳鸡蛋各煮熟捞出 黄瓜拍块\r\n2.生抽2勺醋香油各11勺温开水拌匀即可开吃','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224082230282.png');
INSERTINTO`iv_dishes`VALUES(7,'凉拌黄瓜豆腐','1.白芝麻辣椒面小米辣,蒜未 葱花 淋少许热油\r\n2.生抽2勺 醋油各1勺 少许盐代糖拌匀\r\n3.黄瓜拍块去籽豆腐煮熟捞出\r\n4.撒上香葱淋上酱汁拌匀即可','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224082404878.png');
INSERTINTO`iv_dishes`VALUES(8,'木耳炒鸡蛋','1.鸡蛋炒熟盛出\r\n2.蒜未和胡萝人炒软倒木耳炒熟再倒鸡蛋\r\n3.耗油生抽各1勺少许盐-小半碗淀粉水\r\n4.炒匀下葱段即可','https://brath.oss-cn-shanghai.aliyuncs.com/pigo/image-20230224082512562.png');
​
SET FOREIGN_KEY_CHECKS =1;

接下来创建一个SpringBoot项目,并写出entity、 controller、service、impl、mapper、xml等需要的代码

entity:
/*** <p>* 菜品表* </p>** @author Brath* @since 2023-02-23*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("iv_dishes")
@ApiModel(value="IvDishes对象", description="菜品表")
public class IvDishes implements Serializable {
​private static final long serialVersionUID = 1L;
​@ApiModelProperty(value = "唯一ID")@TableId(value = "id", type = IdType.AUTO)private Integer id;
​@ApiModelProperty(value = "菜品名字")private String dishesName;
​@ApiModelProperty(value = "菜品做法")private String dishesStep;
​@ApiModelProperty(value = "菜品图片地址")private String dishesUrl;
}
controller:
/**
* <p>
* 菜品表 前端控制器
* </p>
*
* @author Brath
* @since 2023-02-23
*/
@RestController
@RequestMapping("/dishes")
publicclassIvDishesController {
​/**** SLF4J日志*/privateLoggerlogger=LoggerFactory.getLogger(IvDishesController.class);
​/*** 菜品服务接口*/@AutowiredprivateIvDishesServicedishesService;
​/**** 获取菜品列表** @param page* @param size* @return*/@GetMapping("/getDishes")publicObjectgetDishes(@RequestParam(value="page", defaultValue="1") Integerpage, @RequestParam(value="size", defaultValue="8") Integersize) {logger.info("【用户服务】获取菜品列表,开始");Map<Object, Object>result=newHashMap<>();IPage<IvDishes>prizeRecords=dishesService.getDishes(page, size);if (CollectionUtils.isEmpty(prizeRecords.getRecords())) {result.put("fail", ResponseCode.DATA_DOES_NOT_EXIST);logger.error("【用户服务】获取菜品列表,服务错误:{}", ResponseCode.DATA_DOES_NOT_EXIST);}result.put("prizeRecords", prizeRecords.getRecords());logger.info("【用户服务】获取菜品列表,完毕");returnResponseUtil.ok(result);}
}
​
service:
/**
* <p>
* 菜品表 服务类
* </p>
*
* @author Brath
* @since 2023-02-23
*/
publicinterfaceIvDishesServiceextendsIService<IvDishes> {
​/*** 获取菜品列表** @param page* @param size* @return*/IPage<IvDishes>getDishes(Integerpage, Integersize);
​
}
impl:
/**
* <p>
* 菜品表 服务实现类
* </p>
*
* @author Brath
* @since 2023-02-23
*/
@Service
publicclassIvDishesServiceImplextendsServiceImpl<IvDishesMapper, IvDishes>implementsIvDishesService {
​/*** 获取菜品列表** @param page* @param size* @return*/@OverridepublicIPage<IvDishes>getDishes(Integerpage, Integersize) {returnbaseMapper.getDishes(newPage<>(page, size), newQueryWrapper<>());}
}
mapper:
/**
* <p>
* 菜品表 Mapper 接口
* </p>
*
* @author Brath
* @since 2023-02-23
*/
@Mapper
publicinterfaceIvDishesMapperextendsBaseMapper<IvDishes> {
​/*** 获取菜品列表** @param objectPage* @param objectQueryWrapper* @return*/IPage<IvDishes>getDishes(Page<Object>objectPage, QueryWrapper<Object>objectQueryWrapper);
​
}
xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.brath.mapper.IvDishesMapper"><!-- 通用查询映射结果 --><resultMap id="DishesMap" type="cn.brath.entity.IvDishes"><id column="id" property="id"/><result column="dishes_name" property="dishesName"/><result column="dishes_step" property="dishesStep"/><result column="dishes_url" property="dishesUrl"/></resultMap><select id="getDishes" resultType="cn.brath.entity.IvDishes">select d.*from iv_dishes dORDER BY RAND()</select></mapper>
application.yaml配置:
server:port: 9999
spring:datasource:druid:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/iv-user-services?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=trueusername: 'root'password: 'root'initial-size: 10max-active: 100min-idle: 10max-wait: 6000pool-prepared-statements: truemax-pool-prepared-statement-per-connection-size: 20time-between-eviction-runs-millis: 60000min-evictable-idle-time-millis: 300000#Oracle需要打开注释#      validation-query: SELECT 1 FROM DUALtest-while-idle: truetest-on-borrow: falsetest-on-return: falsestat-view-servlet:enabled: trueurl-pattern: /druid/*#login-username: admin#login-password: admin#达梦数据库,需要注释掉,其他数据库可以打开filter:stat:log-slow-sql: trueslow-sql-millis: 1000merge-sql: falsewall:config:multi-statement-allow: true

经过如上一系列配置,我们项目启动成功并可以访问到接口:

接下来只要把程序部署上线就搞定了!

部署后台程序:

将我们的Dockerfile、运行脚本、jar包传入服务器

Dockerfile:

#java8环境
FROM openkbs/jdk11-mvn-py3#root用户
USER root#设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone#Auth
MAINTAINER Brath#设置工作目录集
WORKDIR /root/weatWork#复制jars和命令
ADD *.jar /root/weatWork/
ADD run.sh /root/weatWork/run.sh#脚本权限设置
RUN chmod +x /root/weatWork/run.sh#暴露端口
EXPOSE 9999

1.Dockerfile打包镜像

1.进入工作目录

2.docker build -t weat .

2.运行容器

docker run -dit -p 9999:9999 --privileged=true -P  --name  weat weat /bin/bash -c "tail -f /dev/null" -g "daemon off;"

3.启动Jar包

#进入容器

docker exec -it weat bash

#运行脚本

sh run.sh

#查看日志

tail -100f weatlog.log

4.联调接口

五、APP移动端开发(Flutter)


weatApp架构设计大概如下:

lib:

​ common 通用层

​ core 核心层

​ routers 路由曾

​ utils 工具层

​ viewmodel 视图模型层

​ views 视图层

需要安装的依赖:

  #网络请求dio: ^4.0.6#getx get: ^4.6.5#透明弹出框fluttertoast: ^8.0.8#屏幕适配flutter_screenutil: ^5.5.3+2#全局状态管理provider: ^6.0.1#轮播图flutter_swiper_plus: ^2.0.4# GET WIDGET UI库getwidget: ^2.0.5#图片缓存cached_network_image: ^3.2.0#图片放大缩小photo_view: ^0.13.0#权限申请permission_handler: ^9.2.0#贝壳组件库bruno: ^2.2.0#easyloadingflutter_easyloading: ^3.0.3

代码如下:

common.dart
import 'dart:io';
import 'dart:math';import 'package:bruno/bruno.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:getwidget/getwidget.dart';
import 'package:provider/provider.dart';
import 'package:weat/main.dart';/** Common组件库* @Auth: Brath*//** 获取title的AppBar*/
AppBar getAppBar(String title, {required context}) {return AppBar(toolbarHeight: 40.0.h,centerTitle: true,shadowColor: Color.fromARGB(255, 59, 82, 76),backgroundColor: Colors.transparent,leading: null,leadingWidth: 30.w,elevation: 0.0,actions: [],title: (Text(title,style: TextStyle(fontSize: 16.sp,color: Colors.black,fontFamily: '',fontWeight: FontWeight.bold),)));
}/** 获取卡片圆形背景容器*/
class getCardContainer extends StatelessWidget {getCardContainer({Key? key,this.isBorder,this.BorderCircular,this.width,this.height,this.widget,this.margin,}) : super(key: key);bool? isBorder;double? BorderCircular;double? height;double? width;Widget? widget;EdgeInsetsGeometry? margin;@overrideWidget build(BuildContext context) {return Container(margin: margin,decoration: isBorder == true? BoxDecoration(color: Colors.white,shape: BoxShape.rectangle,boxShadow: [BoxShadow(color: Colors.grey[200]!,offset: Offset(1.w, 1.h),blurRadius: 1.r,spreadRadius: 1.r,),],border: Border.all(color: Colors.white, width: 1.w), // borderborderRadius:BorderRadius.circular((BorderCircular ?? 15.r)), // 圆角): null,width: width,height: height,child: widget,);}
}
ZoomImage.dart
import 'dart:ui';import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';class ZoomImage extends StatefulWidget {ZoomImage({Key? key, this.url}) : super(key: key);String? url;@overrideState<StatefulWidget> createState() {return _ZoomImage();}
}class _ZoomImage extends State<ZoomImage> with SingleTickerProviderStateMixin {AnimationController? _controller;Animation<Offset>? _animation;Offset _offset = Offset.zero;double _scale = 1.0;Offset? _normalizedOffset;double? _previousScale;final double _kMinFlingVelocity = 600.0;bool _isEnlarge = false;bool _isHideTitleBar = false;@overridevoid initState() {super.initState();_controller = AnimationController(vsync: this);_controller?.addListener(() {setState(() {_offset = _animation!.value;});});}@overridevoid dispose() {super.dispose();_controller!.dispose();}Offset _clampOffset(Offset offset) {final Size size = context.size!;// widget的屏幕宽度final Offset minOffset = Offset(size.width, size.height) * (1.0 - _scale);// 限制他的最小尺寸return Offset(offset.dx.clamp(minOffset.dx, 0.0), offset.dy.clamp(minOffset.dy, 0.0));}_handleOnScaleStart(ScaleStartDetails details) {setState(() {_isHideTitleBar = true;_previousScale = _scale;_normalizedOffset = (details.focalPoint - _offset) / _scale;// 计算图片放大后的位置_controller!.stop();});}_handleOnScaleUpdate(ScaleUpdateDetails details) {setState(() {_scale = (_previousScale! * details.scale).clamp(1.0, 3.0);// 限制放大倍数 1~3倍_offset = _clampOffset(details.focalPoint - _normalizedOffset! * _scale);// 更新当前位置});}_handleOnScaleEnd(ScaleEndDetails details) {_setSystemUi();final double magnitude = details.velocity.pixelsPerSecond.distanceSquared;if (magnitude < _kMinFlingVelocity) return;final Offset direction = details.velocity.pixelsPerSecond / magnitude;// 计算当前的方向final double distance = (Offset.zero & context.size!).shortestSide;// 计算放大倍速,并相应的放大宽和高,比如原来是600*480的图片,放大后倍数为1.25倍时,宽和高是同时变化的_animation = _controller!.drive(Tween<Offset>(begin: _offset, end: _clampOffset(_offset + direction * distance)));_controller!..value = 0.0..fling(velocity: magnitude / 1000.0);}_onDoubleTap() {_isHideTitleBar = true;_setSystemUi();Size size = context.size!;_isEnlarge = !_isEnlarge;setState(() {if (!_isEnlarge) {_scale = 2.0;_offset = Offset(-(size.width / 2), -(size.height / 2));} else {_scale = 1.0;_offset = Offset.zero;}});}_onTap() {setState(() {_isHideTitleBar = !_isHideTitleBar;});_setSystemUi();}@overrideWidget build(BuildContext context) {return Stack(children: [_bodyView(), _titleBar()],);}_bodyView() {return GestureDetector(onScaleStart: _handleOnScaleStart,onScaleUpdate: _handleOnScaleUpdate,onScaleEnd: _handleOnScaleEnd,onDoubleTap: _onDoubleTap,onTap: _onTap,child: Container(color: _isHideTitleBar ? Colors.black : Colors.white,child: SizedBox.expand(child: ClipRect(child: Transform(transform: Matrix4.identity()..translate(_offset.dx, _offset.dy)..scale(_scale),child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [SizedBox(width: 700.0.w,height: 600.0.h,child: Image.network(widget.url!)),Container()],),),),),),);}_titleBar() {return Offstage(child: Container(alignment: Alignment.centerLeft,padding: EdgeInsets.only(top: MediaQueryData.fromWindow(window).padding.top,left: ScreenUtil().setWidth(24)),color: const Color.fromARGB(255, 32, 32, 32),height: MediaQuery.of(context).size.height * 0.1,width: MediaQuery.of(context).size.width,child: GestureDetector(child: Icon(Icons.arrow_back,size: 30.0.w,color: Colors.white,),onTap: () {Navigator.pop(context);},),),offstage: _isHideTitleBar,);}_setSystemUi() {if (_isHideTitleBar) {SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);} else {SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual);}}
}
Global.dart
import 'package:dio/dio.dart';class Global {static String BaseUrl = 'http://127.0.0.1:9999/';/*请求dio对象 */late Dio dio;/*通用超时 */int timeOut = 50000;/*请求单例 */static Global? _instance;/*获取实例 */static Global? getInstance() {if (_instance == null) _instance = Global();return _instance;}Global() {dio = Dio();dio.options = BaseOptions(baseUrl: BaseUrl,connectTimeout: timeOut,sendTimeout: timeOut,receiveTimeout: timeOut,contentType: Headers.jsonContentType,headers: {"Access-Control-Allow-Origin": "*",});// 请求拦截器 and 响应拦截机 and 错误处理dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {print("\n================== 请求数据 ==========================");print("url = ${options.uri.toString()}");print("headers = ${options.headers}");print("params = ${options.data}");print("\n================== 请求数据 ==========================");return handler.next(options);}, onResponse: (response, handler) {print("\n================== 响应数据 ==========================");print("code = ${response.statusCode}");print("data = ${response.data}");print("\n================== 响应数据 ==========================");handler.next(response);}, onError: (DioError e, handler) {print("\n================== 错误响应数据 ======================");print("type = ${e.type}");print("message = ${e.message}");print("\n================== 错误响应数据 ======================");return handler.next(e);}));}
}
routes.dart
// ignore_for_file: prefer_const_constructorsimport 'package:flutter/cupertino.dart';
import 'package:weat/views/index/IndexView.dart';Map<String, WidgetBuilder> routes = {"/": (context) => IndexView(),
};/** 渐隐跳转路由*/
void opcityPush(BuildContext context, Widget view, {int? milliseconds}) {Navigator.push(context,PageRouteBuilder(transitionDuration:Duration(milliseconds: milliseconds ?? 300), //动画时间为300毫秒pageBuilder: (BuildContext context, Animation<double> animation,Animation secondaryAnimation) {return FadeTransition(//使用渐隐渐入过渡,opacity: animation,child: view, //路由B);},),);
}/** 带路由树跳转*/
void Push(BuildContext context, Widget view) {Navigator.push(context,CupertinoPageRoute(builder: (context) => view,));
}void NavigatorPop(BuildContext context) {Navigator.of(context).pop();
}/** 返回上一级路由树,没有上级会黑屏*/
void Pop(BuildContext context, Widget view) {Navigator.pop(context,CupertinoPageRoute(builder: (context) => view,));
}
showmessage_util.dart
// ignore_for_file: prefer_equal_for_default_values, sized_box_for_whitespaceimport 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluttertoast/fluttertoast.dart';/// @author brath
/// @创建时间:2022/5/10
/// 封装自定义弹框
class DialogUtils {/// 显示普通消息static showMessage(String msg,{toastLength: Toast.LENGTH_LONG,gravity: ToastGravity.CENTER,timeInSecForIosWeb: 2,textColor: Colors.black,backgroundColor: Colors.grey,fontSize: 16.0}) {// 先关闭弹框再显示对应弹框Fluttertoast.cancel();Fluttertoast.showToast(msg: msg,toastLength: toastLength,webShowClose: true,gravity: gravity,textColor: textColor,timeInSecForIosWeb: timeInSecForIosWeb,backgroundColor: Colors.grey[50],fontSize: 13.0.sp,);}
index_viewmodel.dart
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';class IndexViewModel extends ChangeNotifier {bool? isLotte = false;Map? currentDishes = {};bool? get getIsLotte {return isLotte;}void setIsLotte(bool isLotte) {this.isLotte = isLotte;notifyListeners();}Map? get getCurrentDishes {return currentDishes;}void setCurrentDishes(Map currentDishes) {this.currentDishes = currentDishes;notifyListeners();}
}
IndexView.dart
import 'dart:math';import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:getwidget/getwidget.dart';
import 'package:provider/provider.dart';
import 'package:weat/common/ZoomImage.dart';
import 'package:weat/core/Global.dart';
import 'package:weat/routers/routes.dart';
import 'package:weat/utils/showmessage_util.dart';
import 'package:weat/viewmodel/index_viewmodel.dart';
import 'package:weat/views/index/DishesDetail.dart';/** 首页视图*/
class IndexView extends StatefulWidget {const IndexView({Key? key}) : super(key: key);@overrideState<IndexView> createState() => _IndexViewState();
}class _IndexViewState extends State<IndexView> {@overrideWidget build(BuildContext context) {return const LotterView();}
}/** 轮播抽奖页面*/
class LotterView extends StatefulWidget {const LotterView({Key? key}) : super(key: key);@overrideState<LotterView> createState() => _LotterViewState();
}class _LotterViewState extends State<LotterView> {//抽奖控制器final SimpleLotteryController _simpleLotteryController =SimpleLotteryController();int page = 1;int size = 8;//奖品列表List dishesList = [];//奖品lodingbool load = false;//初始化奖品列表_initPrizeList() async {Global.getInstance()!.dio.get("dishes/getDishes", queryParameters: {'page': 1,'size': 8,}).then((value) => {dishesList = value.data['data']['prizeRecords'],load = true,setState(() {})});}@overridevoid initState() {super.initState();_initPrizeList();}@overridevoid dispose() {_simpleLotteryController.dispose();super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(body: MediaQuery.removePadding(removeTop: true,context: context,child: ListView(children: [Container(width: MediaQuery.of(context).size.width,height: MediaQuery.of(context).size.height,decoration: BoxDecoration(gradient: LinearGradient(begin: Alignment.topLeft, //左中end: Alignment.bottomRight, //右中colors: [Theme.of(context).primaryColor,const Color.fromRGBO(180, 0, 0, 0.1),const Color.fromRGBO(187, 0, 0, 0.1),Theme.of(context).primaryColor]),),child: Column(children: [Container(padding: EdgeInsets.only(top: 50.h),child: Wrap(children: [Text('今日菜品',style: TextStyle(fontSize: 32.sp,fontWeight: FontWeight.w600,fontFamily: 'jinbu',color: Colors.white,)),Text('大放送',style: TextStyle(fontSize: 32.sp,fontWeight: FontWeight.w600,fontFamily: 'jinbu',color: const Color.fromARGB(255, 252, 217, 61)),)],),),Container(margin: EdgeInsets.only(top: 10.h),alignment: Alignment.center,child: Text('猜猜今天是什么菜系?',style: TextStyle(fontSize: 12.sp,color: Colors.white,fontFamily: 'jinbu',),),),SizedBox(height: 10.h,),Padding(padding: EdgeInsets.all(12.0.sp),child: Container(height: 400.h,padding: EdgeInsets.all(14.sp),decoration: BoxDecoration(gradient: LinearGradient(begin: Alignment.topLeft, //左中end: Alignment.bottomRight, //右中colors: [Theme.of(context).primaryColor,const Color.fromRGBO(180, 0, 0, 0.1),const Color.fromRGBO(187, 0, 0, 0.1),Theme.of(context).primaryColor]),// color: const Color.fromARGB(255, 205, 221, 235),border: Border.all(color: Colors.transparent, width: 14.w),borderRadius:BorderRadius.all(Radius.elliptical(20.r, 20.r))),child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [load? SimpleLotteryWidget(dishesList: dishesList,simpleLotteryController:_simpleLotteryController): SizedBox(width: double.infinity,height: 260.h,child: const GFLoader(type: GFLoaderType.ios,loaderColorOne: Colors.blue,loaderColorTwo: Colors.blue,loaderColorThree: Colors.blue,duration: Duration(milliseconds: 300)),),//抽奖按钮AnimatedSwitcher(duration: const Duration(milliseconds: 400),child: Provider.of<IndexViewModel>(context,listen: true).getIsLotte!? SizedBox(height: 34.h,width: MediaQuery.of(context).size.width -120.w,child: ElevatedButton(style: ElevatedButton.styleFrom(primary: Colors.red[200], //chanonPrimary: Colors.white, //change text color of buttonshape: RoundedRectangleBorder(borderRadius:BorderRadius.circular(30.r),),elevation: 3.0.h,),onPressed: () {//跳转详情页面Push(context,DishesDetailView(dishes:Provider.of<IndexViewModel>(context,listen: false).getCurrentDishes));//设置状态Provider.of<IndexViewModel>(context,listen: false).setIsLotte(false);},child: Row(mainAxisAlignment:MainAxisAlignment.center,children: [SizedBox(width: 4.w,),Text('点击查看:${Provider.of<IndexViewModel>(context, listen: false).getCurrentDishes!['dishesName']}',style: TextStyle(fontWeight: FontWeight.w500,fontFamily: '',color: Colors.white,fontSize: 14.0.sp),),],),)): SizedBox(height: 34.h,width: MediaQuery.of(context).size.width -220.w,child: ElevatedButton(style: ElevatedButton.styleFrom(primary: Colors.red[200], //chanonPrimary: Colors.white, //change text color of buttonshape: RoundedRectangleBorder(borderRadius:BorderRadius.circular(30.r),),elevation: 3.0.h,),onPressed: () {//开始抽奖_simpleLotteryController.start(Random.secure().nextInt(2)); //开启setState(() {});},child: Row(mainAxisAlignment:MainAxisAlignment.center,children: [SizedBox(width: 4.w,),Text('吃啥',style: TextStyle(fontWeight: FontWeight.w500,fontFamily: '',color: Colors.white,fontSize: 14.0.sp),),],),)),)],),),),],),),],),),);}
}//奖品参数
class SimpleLotteryValue {SimpleLotteryValue({this.target = 0, this.isFinish = false, this.isPlaying = false});/// 中奖目标int target = 0;bool isPlaying = false;bool isFinish = false;SimpleLotteryValue copyWith({int target = 0,bool isPlaying = false,bool isFinish = false,}) {return SimpleLotteryValue(target: target, isFinish: isFinish, isPlaying: isPlaying);}@overrideString toString() {return "target : $target , isPlaying : $isPlaying , isFinish : $isFinish";}
}//抽奖控制器
class SimpleLotteryController extends ValueNotifier {SimpleLotteryController() : super(SimpleLotteryValue());/// 开启抽奖////// [target] 中奖目标void start(int target) {// 九宫格抽奖里范围为0~8assert(target >= 0 && target <= 8);if (value.isPlaying) {return;}value = value.copyWith(target: target, isPlaying: true);}void finish() {value = value.copyWith(isFinish: true);}
}/** 奖品列表容器 */
class SimpleLotteryWidget extends StatefulWidget {final SimpleLotteryController simpleLotteryController;final List dishesList;const SimpleLotteryWidget({Key? key,required this.dishesList,required this.simpleLotteryController}): super(key: key);@overrideState<SimpleLotteryWidget> createState() => _SimpleLotteryWidgetState();
}class _SimpleLotteryWidgetState extends State<SimpleLotteryWidget>with TickerProviderStateMixin {Future<int>? future; // 标识@overrideWidget build(BuildContext context) {return FutureBuilder(future: future,builder: (context, snapshot) {return Container(margin: EdgeInsets.all(5.h),width: double.infinity,height: 280.h,child: GridView.builder(physics: const NeverScrollableScrollPhysics(),itemCount: 9,gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,crossAxisSpacing: 8.w,mainAxisSpacing: 8.h),itemBuilder: (context, index) {if (index != 4) {return commodity(index);}return Image.network('https://brath.cloud/app_log.png',fit: BoxFit.cover,);}));},);}// 奖品列表Widget commodity(int index) {final int toIndex;toIndex = _deserializeMap[index];return GestureDetector(onTap: () {opcityPush(context,ZoomImage(url: '${widget.dishesList[toIndex]['dishesUrl']}'));},child: Stack(children: [Container(decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(10.r)),color: widget.dishesList[toIndex]['id']! > 5? Colors.red[300]!.withAlpha(32): widget.dishesList[toIndex]['id']! >= 4 &&widget.dishesList[toIndex]['id'] <= 5? Colors.amber[300]!.withAlpha(32): Colors.blue[300]!.withAlpha(32),),child: SizedBox(width: double.infinity,height: double.infinity,child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Image.network('${widget.dishesList[toIndex]['dishesUrl']}',fit: BoxFit.cover,width: 60.w,height: 60.w,),SizedBox(height: 5.h,),Text('${widget.dishesList[toIndex]['dishesName']}',maxLines: 1,overflow: TextOverflow.ellipsis,style: TextStyle(fontFamily: 'jinbu',fontSize: 9.sp,color: Theme.of(context).primaryColor,),),],),),),Container(decoration: BoxDecoration(color: index == _currentSelect? Colors.yellow.withOpacity(0.5): Colors.transparent,borderRadius: BorderRadius.all(Radius.circular(10.r)),)),],),);}Animation? _selectedIndexTween;AnimationController? _startAnimateController;int _currentSelect = -1;int _target = 0;/// 旋转的圈数final int repeatRound = 4;VoidCallback? _listener;/// 选中下标的映射final Map _selectMap = {0: 0, 1: 3, 2: 6, 3: 7, 4: 8, 5: 5, 6: 2, 7: 1};//反下标的映射final Map _deserializeMap = {0: 0,3: 1,4: 8,6: 2,7: 3,8: 4,5: 5,2: 6,1: 7};simpleLotteryWidgetState() {_listener = () {// 开启抽奖动画if (widget.simpleLotteryController.value.isPlaying) {_startAnimateController?.reset();_target = widget.simpleLotteryController.value.target;_selectedIndexTween = _initSelectIndexTween(_target);_startAnimateController?.forward();}};}/// 初始化tween////// [target] 中奖的目标Animation _initSelectIndexTween(int target) =>StepTween(begin: 0, end: repeatRound * 8 + target).animate(CurvedAnimation(parent: _startAnimateController!, curve: Curves.easeOutQuart));@overridevoid initState() {super.initState();future = Future.value(42);_startAnimateController =AnimationController(vsync: this, duration: const Duration(seconds: 5));_selectedIndexTween = _initSelectIndexTween(_target);//开启动画simpleLotteryWidgetState();// 控制监听widget.simpleLotteryController.addListener(_listener!);// 动画监听_startAnimateController?.addListener(() {// 更新选中的下标_currentSelect = _selectMap[_selectedIndexTween?.value % 8];if (_startAnimateController!.isCompleted) {widget.simpleLotteryController.finish();_currentSelect = -1;dynamic dishes = widget.dishesList[_target];Provider.of<IndexViewModel>(context, listen: false).setIsLotte(true);Provider.of<IndexViewModel>(context, listen: false).setCurrentDishes(dishes);DialogUtils.showMessage('恭喜你,今天做:${dishes['dishesName']},点击按钮查看菜品做法!');}setState(() {});});}@overridevoid deactivate() {widget.simpleLotteryController.removeListener(_listener!);super.deactivate();}@overridevoid dispose() {_startAnimateController?.dispose();super.dispose();}
}//获取当前奖品出现的次数
getNumberTimesCurrentPrizeAppears(String? id, List<dynamic> arr) {//定义集合Map obj = {};List idList = [];for (var i = 0; i < arr.length; i++) {idList.add(arr[i]['id']);}for (var i = 0; i < idList.length; i++) {if (obj.containsValue([idList[i]])) {obj[idList[i]]++;} else {obj[idList[i]] = 1;}}return obj[int.parse(id!)];
}int next(int min, int max) {int res = min + Random().nextInt(max - min + 1);return res;
}
DishesDetail.dart
import 'package:bruno/bruno.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_swiper_plus/flutter_swiper_plus.dart';
import 'package:weat/common/common.dart';class DishesDetailView extends StatefulWidget {DishesDetailView({Key? key,required this.dishes}) : super(key: key);var dishes;@overrideState<DishesDetailView> createState() => _DishesDetailViewState();
}class _DishesDetailViewState extends State<DishesDetailView> {List steplist = [];@overridevoid initState() {super.initState();//分割步骤steplist = widget.dishes['dishesStep'].toString().split('\r\n');}@overrideWidget build(BuildContext context) {return WillPopScope(onWillPop: () {BrnDialogManager.showConfirmDialog(context,showIcon: false,barrierDismissible: false,title: "你正在做菜,要退出吗~",confirm: "退出",cancel: "不", onConfirm: () {Navigator.of(context).pop();Navigator.of(context).pop();}, onCancel: () {Navigator.of(context).pop();});return Future.value(false);},child: Scaffold(appBar: getAppBar(widget.dishes['dishesName'], context: context),body: ListView(children: [Padding(padding: const EdgeInsets.all(8.0),child: ImageFulWidget(imageList: [widget.dishes['dishesUrl']]),),getCardContainer(margin: EdgeInsets.only(top: 10.h, bottom: 10.h, left: 10.w, right: 10.w),height: 220.0.h,isBorder: true,BorderCircular: 5.r,width: double.infinity,widget: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Padding(padding: EdgeInsets.only(left: 10.w, top: 10.h),child: BrnCSS2Text.toTextView('步骤:',maxLines: 1,textOverflow: TextOverflow.ellipsis,defaultStyle:TextStyle(fontSize: 20.sp, fontFamily: 'jinbu'),),),Padding(padding: EdgeInsets.only(left: 10.w, top: 10.h),child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: steplist.map((e) {return Container(margin: EdgeInsets.only(top: 5.h),child: BrnCSS2Text.toTextView('$e',maxLines: 1,textOverflow: TextOverflow.ellipsis,defaultStyle: TextStyle(fontSize: 13.sp, fontFamily: 'jinbu'),),);}).toList(),),),],),)],)),);}
}/** 顶部轮播图Widget*/
class ImageFulWidget extends StatelessWidget {ImageFulWidget({Key? key,required this.imageList,}) : super(key: key);List<String>? imageList;@overrideWidget build(BuildContext context) {return ClipRRect(borderRadius: BorderRadius.vertical(top: Radius.circular(20.h), bottom: Radius.circular(20.h)),child: SizedBox(height: MediaQuery.of(context).size.height * 0.25,width: MediaQuery.of(context).size.width - 60.0.w,child: Swiper(autoplay: false,duration: 2000,curve: Curves.linearToEaseOut,itemBuilder: (BuildContext context, int index) {return Image.network(imageList![index],height: MediaQuery.of(context).size.height * 0.25,width: MediaQuery.of(context).size.width - 60.0.w,fit: BoxFit.cover,);},itemCount: imageList!.length,pagination: SwiperPagination(builder: DotSwiperPaginationBuilder(size: 8.sp, // 设置未选中的小点大小activeSize: 10.sp, // 设置选中的小点大小color: const Color.fromARGB(255, 219, 219, 219), // 设置为未选中的小点颜色activeColor: Colors.blue, // 设置选中的小点颜色),),control: const SwiperControl(color: Colors.transparent),),),);}
}
main.dart
import 'dart:async';
import 'dart:io';
import 'dart:math';import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';
import 'package:flutter/services.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get_navigation/src/root/get_material_app.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:provider/provider.dart';
import 'package:weat/routers/routes.dart';
import 'package:weat/viewmodel/index_viewmodel.dart';//全局路由key
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();/** 主函数*/
void main() async {initializeDateFormatting().then((_) => runApp(MultiProvider(providers: [ChangeNotifierProvider(create: (context) => IndexViewModel()),],child: MyApp(),)));//安卓屏蔽顶部阴影if (Platform.isAndroid) {SystemUiOverlayStyle systemUiOverlayStyle =SystemUiOverlayStyle(statusBarColor: Colors.transparent);SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);}
}//根节点
class MyApp extends StatefulWidget {@overrideState<MyApp> createState() => _MyAppState();
}class _MyAppState extends State<MyApp> {@overridevoid initState() {super.initState();_init();}//全局路由keyfinal GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();/// 程序初始化_init() async {await EasyLoading.init();EasyLoading.instance..displayDuration = const Duration(milliseconds: 2000)..indicatorType = EasyLoadingIndicatorType.fadingCircle..loadingStyle = EasyLoadingStyle.dark..indicatorSize = 45.0..radius = 10.0..progressColor = Colors.yellow..backgroundColor = Colors.green..indicatorColor = Colors.yellow..textColor = Colors.yellow..maskColor = Colors.blue.withOpacity(0.5)..userInteractions = true..dismissOnTap = false;await WidgetsFlutterBinding.ensureInitialized();await SystemChrome.setPreferredOrientations([// 竖屏 Portrait 模式DeviceOrientation.portraitUp,DeviceOrientation.portraitDown,],);}@overrideWidget build(BuildContext context) {return ScreenUtilInit(designSize: Size(375, 667),minTextAdapt: true,splitScreenMode: true,builder: (context, child) {return GetMaterialApp(theme: ThemeData(primarySwatch: Colors.blueGrey, //全局主题颜色splashColor: Colors.transparent, // 点击时的高亮效果设置为透明// backgroundColor: Color.fromARGB(255, 255, 255, 255), //系统背景主题颜色backgroundColor: Color(0xFFF3F4F6), //系统背景主题颜色highlightColor: Colors.transparent, // 长按时的扩散效果设置为透明primaryColor: Color.fromARGB(188, 0, 0, 97), //系统原色focusColor: Color.fromARGB(235, 73, 74, 116), //焦点主题颜色hoverColor: Color.fromARGB(235, 103, 104, 172), //悬停主题颜色disabledColor: Color.fromARGB(235, 105, 106, 133), //禁用主题颜色primaryColorLight: Colors.white, // 白色主题颜色primaryColorDark: Color.fromARGB(235, 73, 74, 116), //黑色主题颜色selectedRowColor: Color.fromARGB(255, 104, 80, 145), //选中效果颜色appBarTheme: AppBarTheme(backgroundColor: Colors.white),buttonTheme: ButtonThemeData(focusColor: Color.fromARGB(235, 73, 74, 116),hoverColor: Color.fromARGB(235, 103, 104, 172),),tabBarTheme: TabBarTheme(labelColor: Color.fromARGB(235, 103, 104, 172),),progressIndicatorTheme: ProgressIndicatorThemeData(color: Color.fromARGB(235, 101, 102, 158),),),navigatorKey: navigatorKey,routes: routes,debugShowCheckedModeBanner: false,initialRoute: "/", //初始化进入加载页面builder: (context, widget) {return MediaQuery(data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),child: widget!,);},);});}
}

代码编写完毕后 flutter build apk 打包到真机运行

最终呈现出我们想要的效果:


抽奖中:

中奖:

详情:

本期教程到此结束,欢迎你的观看~

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

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

相关文章

【先睹为快】李德毅 马楠:人工智能看教育

来源&#xff1a; 高等工程教育研究 作者简介&#xff1a;李德毅&#xff0c;中国工程院院士&#xff0c;国际欧亚科学院院士&#xff0c;中国人工智能学会名誉理事长&#xff0c;军事科学院研究员&#xff0c;清华大学博士生导师&#xff1b;马楠&#xff0c;北京工业大学教授…

深度学习各子领域略览及术语列表

诸神缄默不语-个人CSDN博文目录 最近更新时间&#xff1a;2023.6.16 最早更新时间&#xff1a;2023.1.5 有些内容附带了相应的超链接作为可参考资料&#xff0c;有些没有。很多内容可以参考我的其他博文&#xff0c;其中有一部分链接我也会挂到这里来。 文章目录 正文1. ML基…

这是我见过的对ChatGPT原理最佳的解释。

人类语言及其背后的思维模式在结构上比我们想象的更简单、更“符合规律”。 ChatGPT大火&#xff0c;甚至已经开始改变人类的工作和思考方式&#xff0c;充分了解并且认识它&#xff0c;同时看到未来的机会&#xff0c;已经成为每个人迫不及待需要建立的心智。而放眼全球&#…

领域驱动设计(DDD)实践之路(四):领域驱动在微服务设计中的应用

这是“领域驱动设计实践之路”系列的第四篇文章&#xff0c;从单体架构的弊端引入微服务&#xff0c;结合领域驱动的概念介绍了如何做微服务划分、设计领域模型并展示了整体的微服务化的系统架构设计。结合分层架构、六边形架构和整洁架构的思想&#xff0c;以实际使用场景为背…

ChatGPT——NLP大结局?大错特错!NLP还有很多事情可以搞

2022年12月&#xff0c;全球科技圈最瞩目的明星莫过于ChatGPT。这一款来自Open.AI的“聊天机器人”&#xff0c;基本上你可以与它讨论任何话题&#xff0c;不管是简单的问路&#xff0c;还是深刻的哲学探讨&#xff0c;甚至是凭空生成一段代码&#xff0c;它几乎有求必应。用一…

新书上市丨开启学习自然语言处理与ChatGPT的精彩旅程,你需要这本书!

2022年10月30日&#xff0c;ChatGPT 的横空出世&#xff0c;引起了全球范围内的广泛关注。微软创始人比尔盖茨 (Bill Gates) 认为 “ChatGTP 与互联网具有同等重要的意义”。作为一个人工智能系统&#xff0c;ChatGPT 能准确识别用户意图&#xff0c;与用户进行对话并提供有价值…

自然语言处理技术在ChatGPT中的应用

自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能领域的一个分支&#xff0c;它的目的是让计算机能够理解、分析、生成自然语言文本。NLP技术已经广泛应用于各个领域&#xff0c;例如机器翻译、语音识别、情感分析等。其中&#xff0c;基于大规…

NLPChatGPTLLMs技术、源码、案例实战210课

NLP&ChatGPT&LLMs技术、源码、案例实战210课 超过12.5万行NLP/ChatGPT/LLMs代码的AI课程 讲师介绍 现任职于硅谷一家对话机器人CTO&#xff0c;专精于Conversational AI 在美国曾先后工作于硅谷最顶级的机器学习和人工智能实验室 CTO、杰出AI工程师、首席机器学习工程…

托福、雅思、GRE、SAT、GMAT

文章目录 1.雅思 IELTS雅思介绍雅思满分 9分雅思只有2年有效期 2.托福 TOEFL托福介绍托福满分 120分 3.GREGRE介绍GRE满分 340分 4.SATSAT介绍SAT满分 1600分 5.GMATGMAT介绍 1.雅思 IELTS 雅思介绍 雅思考试&#xff0c; 全称为国际英语测试系统&#xff08;International E…

恶意代码分析——熊猫烧香

恶意代码分析——熊猫烧香 记录对一些恶意代码的分析的过程 熊猫烧香功能函数总览&#xff1a; 标题 恶意代码分析——熊猫烧香熊猫烧香功能函数总览&#xff1a; 静态分析IDA分析sub_40819Csub_40D18Csub_40A5B0sub_409348 sub_40C374sub_40BACC sub_40D088 参考链接 静态分…

熊猫烧香病毒分析报告

熊猫烧香 基本信息 报告名称&#xff1a;熊猫烧香病毒报告 作者&#xff1a;Pawn 文件名&#xff1a;xiongmao.exe 样本类型&#xff1a;EXE文件 样本文件大小&#xff1a;30,001 字节 样本文件的MD5校验值&#xff1a;512301c535c88255c9a252fdf70b7a03 样本文件SHA1校验值&am…

Prompt learning 教学[进阶篇]:简介Prompt框架并给出自然语言处理技术:Few-Shot Prompting、Self-Consistency等;项目实战搭建知识库内容机器人

Prompt learning 教学[进阶篇]&#xff1a;简介Prompt框架并给出自然语言处理技术&#xff1a;Few-Shot Prompting、Self-Consistency等&#xff1b;项目实战搭建知识库内容机器人 1.ChatGPT Prompt Framework 看完基础篇的各种场景介绍后&#xff0c;你应该对 Prompt 有较深…

ChatGPT如何提升数据开发效率

目录 一、ChatGPT介绍 二、ChatGPT数据应用场景 A、Pyspark代码样例生成 B、Python设计模式推荐 C、Python代码修复能力 D、异常代码的检测​编辑 E、测试数据内容生成 F、数据分析能力 G、报告生成展示 三、结语 一、ChatGPT介绍 1、GPT是什么&#xff1a;大型语言…

《花雕学AI》用Edge和chrome浏览器体验GPT-4智能聊天的神奇免费插件,Sider – 聊天机器人的新选择

你有没有想过和人工智能聊天&#xff1f;你有没有想过用浏览器就能和GPT-4这样的先进的聊天机器人对话&#xff1f;如果你有这样的想法&#xff0c;那么你一定要试试Sider这个神奇的免费插件。 Sider&#xff08;Sider – AI Sidebar&#xff09;是一款基于ChatGPT的智能侧边栏…

家人们,我用ChatGPT来做减肥指引,分享下心得

据我的了解&#xff0c;解决减肥难题可以利用AI技术提供有效的解决方案。通过对个人身体数据和运动习惯的分析&#xff0c;AI能够为每个人量身定制最适合的运动计划。此外&#xff0c;AI还能够运用智能化的语音互动和数据反馈&#xff0c;为每个人提供个性化的运动指导和鼓励&a…

Python 使用chatGPT帮忙写一个有序集类 OrderedSet

需求:需要实现一个有序的集合&#xff0c;像python普通集合一样&#xff0c;除了 它是有序的 我这边穿插着使用了gpt3.5和gpt4,发现确实还是gpt4好用&#xff0c;一分钱一分货啊 问&#xff1a;我的要求是这样&#xff0c;data是一个集合&#xff0c;往里面放了2&#xff0c;…

ChatGPT帮忙出Scrath少儿编程的教程

最近在思考&#xff0c;如何做一份关于Scrath少儿编程的教程&#xff0c;既可以满足目前对小孩的教学内容&#xff0c;也可以做一份相对完善的教程&#xff0c;于是就与ChatGPT开始了一场简单的对话&#xff0c;其中只是初步的目录&#xff0c;如大家有兴趣可以帮忙转发&#x…

闲来无事,摸鱼时让 chatgpt 帮忙,写了一个 console 样式增强库并发布 npm

前端Q 我是winty&#xff0c;专注分享前端知识和各类前端资源&#xff0c;乐于分享各种有趣的事&#xff0c;关注我&#xff0c;一起做个有趣的人&#xff5e; 公众号 点击上方 前端Q&#xff0c;关注公众号 回复加群&#xff0c;加入前端Q技术交流群 话不多说&#xff0c;直接…

三星被曝因ChatGPT泄露芯片机密!韩媒惊呼数据「原封不动」直传美国,软银已禁止员工使用...

点击上方“AI遇见机器学习”&#xff0c;选择“星标”公众号 第一时间获取价值内容 明敏 萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 三星引入ChatGPT不到20天&#xff0c;就发生3起数据外泄事件&#xff1f;&#xff01; 其中2次和半导体设备有关&#xff0c;1次和内部会议有关…

ChatGPT 泄露对话记录,CEO:开源库的错误

ChatGPT 泄露对话记录&#xff0c;CEO&#xff1a;开源库的错误 ChatGPT 会在界面左侧显示你过去与 AI 进行过的对话&#xff0c;并将内容保存在系统中&#xff0c;方便你时不时回顾之前的内容。只不过最近有用户发现&#xff0c;自己的聊天历史中显示了不曾发生过的对话内容&a…