秒杀基本功能开发(不考虑高并发情况)

文章目录

    • 1.显示秒杀状态
        • 1.controller
          • 修改GoodsController.java的toDetail方法,响应秒杀状态和秒杀剩余时间
        • 2.前端
          • 1.goodsDetail.html 图片下面添加一行秒杀开始时间
          • 2.goodsDetail.html 添加计时器js代码
        • 3.测试
          • 1.秒杀进行中
          • 2.修改db的秒杀开始时间为明天
          • 3.出现秒杀倒计时
          • 4.修改db的秒杀结束时间比目前要早
          • 5.秒杀已结束
    • 2.秒杀按钮
        • 1.前端
          • 1.goodsDetail.html 添加抢购按钮
          • 2.goodsDetail.html 根据秒杀状态,控制按钮状态
        • 2.测试
          • 1.秒杀已结束,按钮不可用
          • 2.秒杀进行中,按钮可用
          • 3.秒杀未开始,按钮不可用
    • 3.秒杀基本功能(不考虑高并发)
        • 1.数据库表设计
          • 1.普通订单表
          • 2.秒杀订单表
        • 2.MyBatis-Plus生成基础代码(以t_order表为例)
          • 1.首先 ctrl + shift + c 复制基础包名(一定要是带点的)
          • 2.右键表名选择 MybatisX-Generator
          • 3.选择模块和基础包以及实体类名字
          • 4.进行配置
          • 5.点击生成,检查代码
            • 1.整个目录概览
            • 2.把实体类移动到pojo并检查
            • 3.检查 OrderMapper.java 发现没有加@Mapper注解
            • 4.查看启动类有@MapperScan所以不用加@Mapper了
            • 5.检查OrderMapper.xml
            • 6.检查application.yml是否自动扫描了Mapper.xml
            • 7.检查OrderService.java
            • 8.检查OrderServiceImpl.java
          • 6.使用MyBatis-Plus生成基础代码的小结
          • 7.以同样的方式生成t_seckill_order
        • 3.Service层
          • 1.OrderService.java 新增秒杀方法,返回订单
          • 2.OrderServiceImpl.java
          • 3.SeckillOrderService.java 根据普通订单和商品id插入秒杀订单
          • 4.SeckillOrderServiceImpl.java
        • 4.Controller层
          • 1.SeckillController.java 完成基础版本的秒杀,简单考虑库存和复购问题
          • 2.SeckillOrderService.java 新增方法,根据用户id和商品id查找记录
          • 3.SeckillOrderServiceImpl.java
          • 4.SeckillOrderMapper.java
          • 5.SeckillOrderMapper.xml
        • 5.前端
          • 1.goodsDetail.html 修改点击抢购按钮的请求(区分多环境)
          • 2.引入orderDetail.html
          • 3.引入secKillFail.html
        • 6.测试
          • 1.正常秒杀
            • 1.初始秒杀商品表(库存为10)
            • 2.秒杀1号商品
            • 3.秒杀成功
            • 4.秒杀商品库存减1
            • 5.普通订单新增一条记录
            • 6.秒杀订单新增一条记录
          • 2.当前用户再次购买
            • 成功跳转到限购页面
          • 3.模拟库存不足的情况
            • 1.将1号商品的库存修改为0
            • 2.切换一个浏览器再次秒杀
            • 3.成功跳转到库存不足的页面

1.显示秒杀状态

1.controller
修改GoodsController.java的toDetail方法,响应秒杀状态和秒杀剩余时间
    // 进入到商品详情页@RequestMapping("/toDetail/{goodsId}")public String toDetail(Model model, User user, @PathVariable Long goodsId) {// 判断是否有用户信息if (null == user) {return "login";}// 查询商品详情GoodsVo goodsVoByGoodsId = goodsService.findGoodsVoByGoodsId(goodsId);model.addAttribute("goods", goodsVoByGoodsId);// secKillStatus:秒杀状态 0:未开始 1:进行中 2:已结束// remainSeconds:秒杀剩余时间 >0:未开始 0:进行中 -1:已结束// 获取该商品的秒杀开始时间和结束时间long startAt = goodsVoByGoodsId.getStartDate().getTime();long endAt = goodsVoByGoodsId.getEndDate().getTime();long now = System.currentTimeMillis();// 根据当前时间与秒杀开始时间和结束时间的比较,判断秒杀状态int secKillStatus = 0;int remainSeconds = 0;if (now < startAt) {// 秒杀未开始secKillStatus = 0;remainSeconds = (int) ((startAt - now) / 1000);} else if (now > endAt) {// 秒杀已结束secKillStatus = 2;remainSeconds = -1;} else {// 秒杀进行中secKillStatus = 1;remainSeconds = 0;}// 将秒杀状态和剩余时间存入model中,返回到前端model.addAttribute("secKillStatus", secKillStatus);model.addAttribute("remainSeconds", remainSeconds);// 将用户信息存入model中,返回到前端model.addAttribute("user", user);return "goodsDetail";}
2.前端
1.goodsDetail.html 图片下面添加一行秒杀开始时间
            <tr><td>秒杀开始时间</td><td id="startTime" th:text="${#dates.format(goods.startDate,'yyyy-MM-dd HH:mm:ss')}"></td><td id="seckillTip"><input type="hidden" id="remainSeconds"th:value="${remainSeconds}"/><span th:if="${secKillStatus eq 0}">秒杀倒计时:<span id="countDown"th:text="${remainSeconds}"> </span></span><span th:if="${secKillStatus eq 1}">秒杀进行中</span><span th:if="${secKillStatus eq 2}">秒杀已结束</span></td></tr>
2.goodsDetail.html 添加计时器js代码
<script>$(function () {countDown();});function countDown() {var remainSeconds = $("#remainSeconds").val();var timeout;
//秒杀还未开始if (remainSeconds > 0) {timeout = setTimeout(function () {$("#countDown").text(remainSeconds - 1);$("#remainSeconds").val(remainSeconds - 1);countDown();}, 1000);} else if (remainSeconds == 0) {//秒杀进行中if (timeout) {//清空计时器clearTimeout(timeout);}$("#seckillTip").html("秒杀进行中");} else {$("#seckillTip").html("秒杀已结束");}}
</script>
3.测试
1.秒杀进行中

image-20240508143812867

2.修改db的秒杀开始时间为明天

image-20240508143929455

3.出现秒杀倒计时

image-20240508143950826

image-20240508144003627

4.修改db的秒杀结束时间比目前要早

image-20240508144158474

5.秒杀已结束

image-20240508144206709

2.秒杀按钮

1.前端
1.goodsDetail.html 添加抢购按钮
                <td><form id="secKillForm" method="post" action="/seckill/doSeckill"><input type="hidden" id="goodsId" name="goodsId" th:value="${goods.id}"><button class="btn btn-primary btn-block" type="submit" id="buyButton"> 抢 购</button></form></td>

image-20240508144706778

2.goodsDetail.html 根据秒杀状态,控制按钮状态

image-20240508145140688

2.测试
1.秒杀已结束,按钮不可用

image-20240508145400768

2.秒杀进行中,按钮可用

image-20240508145447048

3.秒杀未开始,按钮不可用

image-20240508145514987

3.秒杀基本功能(不考虑高并发)

1.数据库表设计
1.普通订单表
use seckill;
DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order`
(`id`               BIGINT(20)     NOT NULL AUTO_INCREMENT,`user_id`          BIGINT(20)     NOT NULL DEFAULT 0,`goods_id`         BIGINT(20)     NOT NULL DEFAULT 0,`delivery_addr_id` BIGINT(20)     NOT NULL DEFAULT 0,`goods_name`       VARCHAR(16)    NOT NULL DEFAULT '',`goods_count`      INT(11)        NOT NULL DEFAULT '0',`goods_price`      DECIMAL(10, 2) NOT NULL DEFAULT '0.00',`order_channel`    TINYINT(4)     NOT NULL DEFAULT '0' COMMENT '订单渠道 1pc,2Android,
3ios',`status`           TINYINT(4)     NOT NULL DEFAULT '0' COMMENT '订单状态:0 新建未支付 1 已支付
2 已发货 3 已收货 4 已退款 5 已完成',`create_date`      DATETIME                DEFAULT NULL,`pay_date`         DATETIME                DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE = INNODBAUTO_INCREMENT = 600DEFAULT CHARSET = utf8mb4;
2.秒杀订单表
use seckill;
DROP TABLE IF EXISTS `t_seckill_order`;
CREATE TABLE `t_seckill_order`
(`id`       BIGINT(20) NOT NULL AUTO_INCREMENT,`user_id`  BIGINT(20) NOT NULL DEFAULT 0,`order_id` BIGINT(20) NOT NULL DEFAULT 0,`goods_id` BIGINT(20) NOT NULL DEFAULT 0,PRIMARY KEY (`id`),UNIQUE KEY `seckill_uid_gid` (`user_id`, `goods_id`) USING BTREE COMMENT ' 用户 id,商品 id 的唯一索引,解决同一个用户多次抢购'
) ENGINE = INNODBAUTO_INCREMENT = 300DEFAULT CHARSET = utf8mb4;
2.MyBatis-Plus生成基础代码(以t_order表为例)
1.首先 ctrl + shift + c 复制基础包名(一定要是带点的)

image-20240508155502412

2.右键表名选择 MybatisX-Generator

image-20240508154408364

3.选择模块和基础包以及实体类名字

image-20240508160422478

4.进行配置

image-20240508160551731

5.点击生成,检查代码
1.整个目录概览

image-20240508160625655

2.把实体类移动到pojo并检查

image-20240508160745738

3.检查 OrderMapper.java 发现没有加@Mapper注解

image-20240508160846981

4.查看启动类有@MapperScan所以不用加@Mapper了

image-20240508160923942

5.检查OrderMapper.xml

image-20240508161252522

6.检查application.yml是否自动扫描了Mapper.xml

image-20240508161352765

7.检查OrderService.java

image-20240508161437807

8.检查OrderServiceImpl.java

image-20240508161524301

6.使用MyBatis-Plus生成基础代码的小结
  • 启动类配置MapperScan注解,扫描Mapper接口
  • application.yml配置扫描Mapper.xml
  • 复制基础包名,要带点的
  • 将Mapper.xml生成的最下面的删除即可
7.以同样的方式生成t_seckill_order
3.Service层
1.OrderService.java 新增秒杀方法,返回订单
package com.sxs.seckill.service;import com.sxs.seckill.pojo.Order;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.vo.GoodsVo;/**
* @author 8615941515990
* @description 针对表【t_order】的数据库操作Service
* @createDate 2024-05-08 16:05:29
*/
public interface OrderService extends IService<Order> {/*** 方法:秒杀* @param user* @param goodsVo* @return*/Order seckill(User user, GoodsVo goodsVo);
}
2.OrderServiceImpl.java
package com.sxs.seckill.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxs.seckill.mapper.SeckillGoodsMapper;
import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillGoods;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.service.OrderService;
import com.sxs.seckill.mapper.OrderMapper;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.vo.GoodsVo;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @author 8615941515990* @description 针对表【t_order】的数据库操作Service实现* @createDate 2024-05-08 16:05:29*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>implements OrderService {@Resourceprivate SeckillGoodsMapper seckillGoodsMapper;@Resourceprivate SeckillOrderService seckillOrderService;@Overridepublic Order seckill(User user, GoodsVo goodsVo) {// 使用QueryWapper查询秒杀商品SeckillGoods seckillGoods = seckillGoodsMapper.selectOne(new QueryWrapper<SeckillGoods>().eq("goods_id", goodsVo.getId()));// 将库存减一seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);// 更新秒杀商品库存seckillGoodsMapper.updateById(seckillGoods);// 创建订单Order order = new Order();order.setUserId(user.getId());order.setGoodsId(goodsVo.getId());order.setDeliveryAddrId(0L);order.setGoodsName(goodsVo.getGoodsName());order.setGoodsCount(1);order.setGoodsPrice(goodsVo.getSeckillPrice());order.setOrderChannel(1);order.setStatus(0);order.setCreateDate(null);order.setPayDate(null);// 插入订单baseMapper.insert(order);// 生成秒杀商品订单seckillOrderService.insertSeckillOrder(order, goodsVo.getId());// 返回订单return order;}
}
3.SeckillOrderService.java 根据普通订单和商品id插入秒杀订单
package com.sxs.seckill.service;import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillOrder;
import com.baomidou.mybatisplus.extension.service.IService;/**
* @author 8615941515990
* @description 针对表【t_seckill_order】的数据库操作Service
* @createDate 2024-05-08 16:20:14
*/
public interface SeckillOrderService extends IService<SeckillOrder> {/*** 根据普通订单和商品id插入秒杀订单*/void insertSeckillOrder(Order order, Long goodsId);
}
4.SeckillOrderServiceImpl.java
package com.sxs.seckill.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillOrder;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.mapper.SeckillOrderMapper;
import org.springframework.stereotype.Service;/**
* @author 8615941515990
* @description 针对表【t_seckill_order】的数据库操作Service实现
* @createDate 2024-05-08 16:20:14
*/
@Service
public class SeckillOrderServiceImpl extends ServiceImpl<SeckillOrderMapper, SeckillOrder>implements SeckillOrderService{@Overridepublic void insertSeckillOrder(Order order, Long goodsId) {// 根据普通订单插入秒杀订单SeckillOrder seckillOrder = new SeckillOrder();seckillOrder.setUserId(order.getUserId());seckillOrder.setOrderId(order.getId());seckillOrder.setGoodsId(goodsId);baseMapper.insert(seckillOrder);}
}
4.Controller层
1.SeckillController.java 完成基础版本的秒杀,简单考虑库存和复购问题
package com.sxs.seckill.controller;import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.service.GoodsService;
import com.sxs.seckill.service.OrderService;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.vo.GoodsVo;
import com.sxs.seckill.vo.RespBeanEnum;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;/*** Description:** @Author sun* @Create 2024/5/8 18:49* @Version 1.0*/
@Controller
@RequestMapping("/seckill")
public class SeckillController {@Resourceprivate GoodsService goodsService;@Resourceprivate OrderService orderService;@Resourceprivate SeckillOrderService seckillOrderService;@RequestMapping("/doSeckill")public String doSeckill(Model model, User user, Long goodsId) {// 判断用户是否登录if (user == null) {return "login";}// 将用户信息传递到页面model.addAttribute("user", user);// 根据goodsId获取GoodsVoGoodsVo goodsVoByGoodsId = goodsService.findGoodsVoByGoodsId(goodsId);// 判断是否有库存if (goodsVoByGoodsId.getStockCount() < 1) {// 没有库存,返回秒杀失败页面model.addAttribute("errmsg", RespBeanEnum.EMPTY_STOCK.getMessage());return "secKillFail";}// 通过秒杀订单表判断是否复购if (seckillOrderService.findSeckillOrderByUserIdAndGoodsId(user.getId(), goodsId) != null) {// 重复购买,返回秒杀失败页面model.addAttribute("errmsg", RespBeanEnum.REPEATE_ERROR.getMessage());return "secKillFail";}// 秒杀Order seckill = orderService.seckill(user, goodsVoByGoodsId);// 判断秒杀是否成功if (seckill == null) {// 秒杀失败,返回秒杀失败页面model.addAttribute("errmsg", RespBeanEnum.ERROR.getMessage());return "secKillFail";}// 秒杀成功,返回订单详情页面model.addAttribute("order", seckill);model.addAttribute("goods", goodsVoByGoodsId);// 返回订单详情页面return "orderDetail";}
}
2.SeckillOrderService.java 新增方法,根据用户id和商品id查找记录
    /*** 根据用户id和商品id查询秒杀订单*/SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId);
3.SeckillOrderServiceImpl.java
    @Overridepublic SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId) {// 根据用户id和商品id查询秒杀订单return baseMapper.findSeckillOrderByUserIdAndGoodsId(userId, goodsId);}
4.SeckillOrderMapper.java
package com.sxs.seckill.mapper;import com.sxs.seckill.pojo.SeckillOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/**
* @author 8615941515990
* @description 针对表【t_seckill_order】的数据库操作Mapper
* @createDate 2024-05-08 16:20:14
* @Entity com.sxs.seckill.pojo.SeckillOrder
*/
public interface SeckillOrderMapper extends BaseMapper<SeckillOrder> {/*** 根据用户id和商品id查询秒杀订单*/SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId);
}
5.SeckillOrderMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sxs.seckill.mapper.SeckillOrderMapper"><resultMap id="BaseResultMap" type="com.sxs.seckill.pojo.SeckillOrder"><id property="id" column="id" jdbcType="BIGINT"/><result property="userId" column="user_id" jdbcType="BIGINT"/><result property="orderId" column="order_id" jdbcType="BIGINT"/><result property="goodsId" column="goods_id" jdbcType="BIGINT"/></resultMap><select id="findSeckillOrderByUserIdAndGoodsId" resultType="com.sxs.seckill.pojo.SeckillOrder">SELECT*FROMt_seckill_orderWHEREuser_id = #{userId}ANDgoods_id = #{goodsId}</select></mapper>
5.前端
1.goodsDetail.html 修改点击抢购按钮的请求(区分多环境)

image-20240508204340828

2.引入orderDetail.html
<html lang="en"xmlns:th="http://www.thymeleaf.org">
<head><title>订单详情</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><!--jquery--><script type="text/javascript" th:src="@{/js/jquery.min.js}"></script><!-- bootstrap --><link rel="stylesheet" type="text/css" th:href="@{/bootstrap/css/bootstrap.min.css}"/><script type="text/javascript" th:src="@{/bootstrap/js/bootstrap.js}"></script><!-- layer --><script type="text/javascript" th:src="@{/layer/layer.js}"></script><!-- common.js --><script type="text/javascript" th:src="@{/js/common.js}"></script><style>* {margin: 0;padding: 0;font-family: "Open Sans", sans-serif;text-transform: uppercase;letter-spacing: 3px;font-size: 11px;}body {background: #c9302c;}.main-header {width: 100%;height: 100px;background: whitesmoke;display: block;}.navbar {display: inline-block;float: right;margin-right: 50px;margin-top: 30px;}.logo {display: inline-block;margin-top: 30px;margin-left: 30px;text-decoration: none;}.logo-lg {font-size: 20px;font-weight: lighter;color: #232324;}.logo-lg > b {font-size: 20px;font-weight: lighter;color: #232324;}.container {background: #FFFFFF;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;width: 750px;}</style>
</head>
<body>
<header id="site-header" class="main-header"><!-- Logo --><a class="logo" onclick="toList()"><span class="logo-lg"><b>商品抢购</b></span></a><nav class="navbar navbar-static-top"><!-- Sidebar toggle button--><a href="#" class="sidebar-toggle" data-toggle="push-menu" role="button"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></a><div class="navbar-custom-menu"><ul class="nav navbar-nav"><li class="dropdown user user-menu"><a href="#" class="dropdown-toggle" data-toggle="dropdown"><img class="user-image" src="/imgs/user.png" height="32" alt="User
Image"><span class="hidden-xs"></span></a><ul class="dropdown-menu"><!-- User image --><li class="user-header"><img class="img-circle" alt="User Image"><p>Hello ABC - Hello ABC<small>Hello ABC</small></p></li><!-- Menu Body --><li class="user-body"></li><li class="user-footer"><div class="pull-middle"><a onclick="toList()" class="btn btn-lg btn-default btn-block">退出系统</a></div></li></ul></li></ul></div></nav>
</header>
<div class="panel panel-default"><div class="panel-heading" style="background: #c9302c;color: white">秒杀订单详情</div><div class="container"><table class="table" id="order"><tr><td>名称</td><td id="goodName" colspan="3" th:text="${goods.goodsName}"></td></tr><tr><td>图片</td><td colspan="2"><img id="goodImg" width="200" th:src="@{${goods.goodsImg}}" height="200"/></td></tr><tr><td>订单价格</td><td colspan="2" id="goodPrice" th:text="${order.goodsPrice}"></td></tr><tr><td>下单时间</td><td id="createDate" colspan="2"th:text="${#dates.format(order.createDate,'yyyy-MM-dd HH:mm:ss')}"></td></tr><tr><td>订单状态</td><td id="status" ><span th:if="${order.status eq 0}">未支付</span><span th:if="${order.status eq 1}">代发货</span><span th:if="${order.status eq 2}">已发货</span><span th:if="${order.status eq 3}">已收货</span><span th:if="${order.status eq 4}">已退款</span><span th:if="${order.status eq 5}">已完成</span></td><td><button class="btn btn-primary btn-block" type="submit"id="payButton">立即支付</button></td></tr><tr><td>收货人</td><td colspan="2">XXX 13300000000</td></tr><tr><td>收货地址</td><td colspan="2">北京市幸福小区 6 单元 101 号</td></tr></table></div>
</div>
<script>
</script>
</body>
</html>
3.引入secKillFail.html
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title><style>* {margin: 0;padding: 0;font-family: "Open Sans", sans-serif;text-transform: uppercase;letter-spacing: 3px;font-size: 11px;}</style>
</head>
<body>
<h1>秒杀失败 : </h1>
<p th:text="${errmsg}"></p>
</body>
</html>
6.测试
1.正常秒杀
1.初始秒杀商品表(库存为10)

image-20240508204704283

2.秒杀1号商品

image-20240508204758962

3.秒杀成功

image-20240508204812058

4.秒杀商品库存减1

image-20240508204939374

5.普通订单新增一条记录

image-20240508205006209

6.秒杀订单新增一条记录

image-20240508205031531

2.当前用户再次购买
成功跳转到限购页面

image-20240508205230614

3.模拟库存不足的情况
1.将1号商品的库存修改为0

image-20240508205330949

2.切换一个浏览器再次秒杀

image-20240508205543103

3.成功跳转到库存不足的页面

image-20240508205606440

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

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

相关文章

<Rust><iced>基于rust使用iced库构建GUI实例:动态改变主题色

前言 本专栏是Rust实例应用。 环境配置 平台&#xff1a;windows 软件&#xff1a;vscode 语言&#xff1a;rust 库&#xff1a;iced、iced_aw 概述 本篇构建了这样的一个实例&#xff0c;可以动态修改UI的主题&#xff0c;通过菜单栏来选择预设的自定义主题和官方主题&#…

python列表的扩展操作

列表的扩展操作 zip() 函数 我们先学习 zip() 函数&#xff0c;将排名与分数挂钩。 还记得期中考试的顺序排名和分数吗&#xff1f;我们把排名放在了列表 midterm_rank 中&#xff0c;把分数放在了 scores 中。不过当时 scores 并没有排序&#xff0c;我们要对数据进行预处理…

深入理解文件系统和日志分析

文件是存储在硬盘上的&#xff0c;硬盘上的最小存储单位是扇区&#xff0c;每个扇区的大小是512字节。 inode&#xff1a;存储元信息&#xff08;包括文件的属性&#xff0c;权限&#xff0c;创建者&#xff0c;创建日期等等&#xff09; block&#xff1a;块&#xff0c;连续…

小白跟做江科大32单片机之LED闪烁

原理介绍 原理介绍详见&#xff1a; 【STM32】江科大STM32学习笔记汇总(已完结)_stm32江科大笔记-CSDN博客https://blog.csdn.net/u010249597/article/details/134762513 项目准备 1.在项目文件夹中新建3-1 LED文件夹 2.keil新建项目&#xff0c;打开新建的3-1 LED&#xf…

【CC2530-操作外部flash】

zigbee cc2530操作flash&#xff0c;以cc2530读flash_id为例子&#xff1b; void InitIO() {CLKCONCMD & ~0x40; //设置系统时钟源为32MHZ晶振 while(CLKCONSTA & 0x40); //等待晶振稳定为32M CLKCONCMD & ~0x47; //设置系统主时钟频率为32MHZ…

面试(五)

目录 1. 知道大顶堆小顶端吗&#xff0c;代码怎么区分大顶端小顶端 2. 计算机中栈地址与内存地址增长方向相反吗&#xff1f; 3. %p和%d输出指针地址 4. 为什么定义第二个变量时候&#xff0c;地址反而减了 5. 12&#xff0c;32&#xff0c;64位中数据的占字节&#xff1f;…

物质的量质量,它们可不是一个概念

物质的量&质量&#xff0c;它们可不是一个概念。 物质的量&质量 乍一听物质的量&#xff0c;还以为是和质量有什么关系&#xff0c;是不是&#xff1f;其实物质的量和质量没什么直接的联系。 物质的量是国际单位制中7个基本物理量之一&#xff0c;其符号为n&#xf…

Aras Innovator-Team(群组)的使用方法

当Aras Innovator在处理权限时&#xff0c;在不使用Team的情况下&#xff0c;系统的权限配置可以满足大部分业务场景&#xff0c;如&#xff1a;常见的按照组织架构&#xff0c;成员和角色分配权限&#xff0c;按照生命周期分配权限等。 如果遇到比较复杂的权限需求&#xff0c…

AltiumDesigner/AD添加数据库连接

1.首先确保本机电脑有无对应的数据库驱动&#xff0c;例如我这边要添加MySQL的数据&#xff0c;则需要首先下载MySQL数据驱动&#xff1a;MySQL :: Download MySQL Connector/ODBC (Archived Versions) 2.运行“odbcad32.exe”&#xff0c;如下图添加对应的数据库配置&#xf…

【C/C++】C/C++车辆交通违章管理系统(源码+数据文件)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

面试题:useEffect的Clean Up 什么时候触发?

​ useEffect作为做常用的Hook&#xff0c;以下三个知识点你有必要了解下~ 防止写出奇怪的代码祸害队友&#xff0c;而我不幸就是这个受害者&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; useEffect的依赖项为空 useEffect的dependencyList作为一个可选参数…

Pytest框架中用例用例执行常用参数介绍

pytest 支持通过命令行参数来定制测试运行的方式。以下是一些常用的 pytest 执行参数介绍。 学习目录 -q 或 --quiet: 安静模式&#xff0c;只显示进度和摘要 -s : 选项允许在测试的输出中捕获 stdout 和 stderr。 -v : 选项会使 pytest 的输出更加详细。 -k &#xff1a;…

Git 恢复已删除的branch

六一节晚上改了点code, 做完之后commit, 然后误删了这个branch, 并且新建了branch. 那么怎样恢复已删除的branch呢&#xff1f; 网上查询一番&#xff0c;找到了答案&#xff1a; 1. git reflog 找到被删的branch中最后一笔commit, 记录它的SHA1。 怎么看SHA1是被删除的bra…

鸿蒙应用Stage模型【应用/组件级配置】

应用/组件级配置 在开发应用时&#xff0c;需要配置应用的一些标签&#xff0c;例如应用的包名、图标等标识特征的属性。本文描述了在开发应用需要配置的一些关键标签。 应用包名配置 应用需要在工程的AppScope目录下的[app.json5配置文件]中配置bundleName标签&#xff0c;…

Python PyInstaller打包方法介绍

为了将开发好的Python工具交付给其他人使用&#xff0c;除了在目标电脑部署Python编译环境以外&#xff0c;我们还可以将它打包成可执行文件&#xff0c;这样目标电脑不需要安装Python环境就可以运行。将Python程序打包成可执行文件的方法有多种&#xff0c;比如Nuitka、PyInst…

微博增强-tampermonkey脚本实现网页管理悄悄关注

不是很明白微博为什么不出个x的列表功能&#xff0c;毕竟现在信息洪流&#xff0c;有些东西只是要看要了解&#xff0c;但不希望天天在首页轰炸眼睛&#xff0c;扰乱心智。 这个tampermonkey脚本适配了pc web和手机pwa版本&#xff08;weibo.com/m.weibo.cn&#xff09;,解决了…

golang map部分原理源码个人走读-附个人理解过程图解

近期再写map的demo时出现了下面一段报错&#xff0c;于是带着疑惑去看了一下源码 目的&#xff1a;主要想知道为啥map不让并发读写 fatal error: concurrent map read and map write 一.map的数据结构 先有个印象&#xff0c;后续会详细介绍 // A header for a Go map. ty…

NDIS Filter开发-OID 请求

NDIS 定义对象标识符 (OID) 值来标识适配器参数&#xff0c;其中包括操作参数&#xff0c;例如设备特征、可配置的设置和统计信息。 Filter驱动程序可以查询或设置基础驱动程序的操作参数&#xff0c;或过滤/覆盖顶层驱动程序的 OID 请求。 NDIS 还为 NDIS 6.1 及更高版本的Fi…

Informer

I n f o r m e r Informer Informer 摘要&#xff1a; 长序列时间序列的预测 i n f o r m e r informer informer优点&#xff1a; P r o b s p a r e Probspare Probspare自关注机制&#xff0c;在时间复杂度和内存使用方面达到 O ( N l o g N ) O(NlogN) O(NlogN),在序列依…

IP协议1.0

基本概念&#xff1a; • 主机: 配有IP地址, 但是不进⾏路由控制的设备; • 路由器: 即配有IP地址, ⼜能进⾏路由控制; • 节点: 主机和路由器的统称; IP协议的报头 • 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4. • 4位头部⻓度(header length): IP头部的⻓…