模拟瑞幸小程序购物车

是根据渡一袁老师的大师课写的,如有什么地方存在问题,还请大家指出来哟ど⁰̷̴͈꒨⁰̷̴͈う♡~

index.html


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>亚亚外卖</title>
    <link rel="shortcut icon" href="./assets/favicon.ico" type="image/x-icon" />
    <link rel="stylesheet" href="./css/common.css" />
    <link rel="stylesheet" href="./css/container.css" />
    <link rel="stylesheet" href="./css/footer.css" />
    <link rel="stylesheet" href="./css/add-to-car.css" />
  </head>
  <body>
    <div class="container">
      <div class="menu">
        <div class="menu-item active"><span>推荐</span></div>
        <div class="menu-item"><span>热销</span></div>
        <div class="menu-item"><span>折扣</span></div>
        <div class="menu-item"><span>夏日冰咖必喝榜</span></div>
        <div class="menu-item"><span>进店必喝</span></div>
        <div class="menu-item"><span>只喝美式</span></div>
        <div class="menu-item"><span>酷爽特调水果冰萃</span></div>
        <div class="menu-item"><span>经典奶咖</span></div>
        <div class="menu-item"><span>创意奶咖</span></div>
        <div class="menu-item"><span>瑞纳冰季</span></div>
        <div class="menu-item"><span>不喝咖啡</span></div>
        <div class="menu-item"><span>轻食甜品</span></div>
        <div class="menu-item"><span>热卖套餐</span></div>
      </div>
      <div class="goods-list"></div>
    </div>
    <div class="footer">
      <div class="footer-car-container">
        <div class="footer-car">
          <i class="iconfont i-gouwuchefill"></i>
          <span class="footer-car-badge">0</span>
        </div>
        <div class="footer-car-price">
          <span class="footer-car-unit">¥</span>
          <span class="footer-car-total">0.00</span>
        </div>
        <div class="footer-car-tip">配送费¥0</div>
      </div>
      <div class="footer-pay">
        <a href="">去结算</a>
        <span>还差¥0元起送</span>
      </div>
    </div>

    <!-- <div class="add-to-car">
      <i class="iconfont i-jiajianzujianjiahao"></i>
    </div> -->

    <script src="./js/data.js"></script>
    <script src="./js/index.js"></script>
  </body>
</html>

common.css

@import url('https://at.alicdn.com/t/c/font_3555577_me2a6tdmvu8.css');

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  font-size: 0.125vw;
}
body {
  font-size: 35rem;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
  user-select: none;
  font-family: 'Microsoft Yahei', 'sans-serif';
}
a {
  color: inherit;
  text-decoration: none;
}
.iconfont {
  font-size: inherit;
}

container.css

.container {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: calc(100% - 100rem);
  display: flex;
  color: #333;
}
.menu {
  background: #f5f5f5;
  width: 190rem;
  overflow-y: scroll;
  padding-bottom: 50rem;
  flex: 0 0 auto;
}
.menu::-webkit-scrollbar {
  width: 0;
}

.menu-item {
  height: 141rem;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0 30rem;
  position: relative;
}
.menu-item span {
  font-size: 30rem;
  line-height: 40rem;
  max-height: 80rem;
  overflow: hidden;
}
.menu-item.active {
  font-weight: bold;
  background: #fff;
}
.menu-item.active::before {
  content: '';
  position: absolute;
  left: 0;
  height: 100%;
  width: 7.5rem;
  background: #3190e8;
}

.goods-list {
  flex-grow: 1;
  overflow-y: scroll;
}
.goods-list::-webkit-scrollbar {
  width: 0;
}

.goods-item {
  border-bottom: 1rem solid #f8f8f8;
  padding: 30rem 20rem;
  display: flex;
}
.goods-pic {
  width: 200rem;
  height: 200rem;
  object-fit: contain;
  border: 1rem solid rgba(0, 0, 0, 0.06);
  flex: 0 0 auto;
}
.goods-info {
  flex: 1 1 auto;
  padding: 0 35rem;
  overflow: hidden;
}
.goods-title {
  font-size: 35rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-bottom: 20rem;
}
.goods-desc {
  font-size: 24rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 20rem;
}
.goods-sell {
  color: #858687;
  font-size: 24rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 20rem;
  display: flex;
}
.goods-sell span:first-child {
  margin-right: 18rem;
}
.goods-confirm {
  display: flex;
  justify-content: space-between;
}
.goods-price {
  display: flex;
  font-size: 35rem;
  font-weight: bold;
  color: #f60;
  align-items: flex-end;
}
.goods-price-unit {
  font-size: 25rem;
  margin-bottom: 4rem;
  font-weight: normal;
}
.goods-btns {
  display: flex;
  justify-content: center;
  align-items: center;
}
.goods-btns .iconfont {
  width: 40rem;
  height: 40rem;
  background: #4a90e1;
  color: #fff;
  border-radius: 50%;
  font-size: 23rem;
  line-height: 40rem;
  text-align: center;
}
.goods-btns span {
  margin: 0 15rem;
  display: none;
}
.goods-btns .i-jianhao {
  border: 1rem solid #4a90e1;
  background: #fff;
  color: #4a90e1;
  font-weight: bold;
  display: none;
}
.goods-item.active span {
  display: block;
}
.goods-item.active .i-jianhao {
  display: block;
}

footer.css

.footer {
  height: 100rem;
  color: #fff;
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  display: flex;
  z-index: 10;
}

.footer-car-container {
  flex-grow: 1;
  background: #3d3d3f;
  padding-left: 175rem;
  position: relative;
}
.footer-car {
  position: absolute;
  width: 118rem;
  height: 118rem;
  border: 9rem solid #444;
  left: 25rem;
  top: -35rem;
  border-radius: 50%;
  background: inherit;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 60rem;
}
.footer-car-badge {
  position: absolute;
  width: 35rem;
  height: 35rem;
  background: #ec5533;
  font-size: 25rem;
  text-align: center;
  border-radius: 50%;
  line-height: 35rem;
  right: 0;
  top: 0;
  display: none;
}
.footer-car.active {
  background: #4a90e1;
}
.footer-car.active .footer-car-badge {
  display: block;
}
.footer-car.animate {
  animation: footer-car-animate 500ms ease-in-out;
}

@keyframes footer-car-animate {
  0% {
    transform: scale(1);
  }
  25% {
    transform: scale(0.8);
  }
  50% {
    transform: scale(1.1);
  }
  75% {
    transform: scale(0.9);
  }
  100% {
    transform: scale(1);
  }
}

.footer-car-price {
  font-size: 40rem;
  display: flex;
  margin-top: 5rem;
}
.footer-car-tip {
  font-size: 20rem;
  margin-left: 6rem;
}
.footer-pay {
  background: #535356;
  width: 250rem;
  font-size: 35rem;
  line-height: 100rem;
  text-align: center;
}
.footer-pay > * {
  display: block;
  width: 100%;
  height: 100%;
}
.footer-pay a {
  display: none;
}
.footer-pay span {
  font-size: 30rem;
}
.footer-pay.active {
  background: #76d572;
}
.footer-pay.active a {
  display: block;
}
.footer-pay.active span {
  display: none;
}

add-to-car.css

.add-to-car {
  position: fixed;
  color: #fff;
  font-size: 23rem;
  line-height: 40rem;
  text-align: center;
  z-index: 9;
  margin-left: -20rem;
  margin-top: -20rem;
  left: 0;
  top: 0;
  /* 匀速动画 */
  transition: 0.5s linear;
}

.add-to-car .iconfont {
  width: 40rem;
  height: 40rem;
  background: #4a90e1;
  border-radius: 50%;
  display: block;
  /* i元素过渡动画,i不应该设置匀速动画。cubic-bezier函数,x1,y1,x2,y2分别代表起点和终点的坐标 */
  transition: 0.5s cubic-bezier(0.5, -0.5, 1, 1);
}

data.js

var goods = [
    {
      pic: './assets/g1.png',
      title: '椰云拿铁',
      // desc是富文本
      desc: `1人份【年度重磅,一口吞云】
      √原创椰云topping,绵密轻盈到飞起!
      原创瑞幸椰云™工艺,使用椰浆代替常规奶盖
      打造丰盈、绵密,如云朵般细腻奶沫体验
      椰香清甜饱满,一口滑入口腔
      
      【饮用建议】请注意不要用吸管,不要搅拌哦~`,
      sellNumber: 200,//销量,月售
      favorRate: 95,//好评率
      price: 32,//价格
    },
    {
      pic: './assets/g2.png',
      title: '生椰拿铁',
      desc: `1人份【YYDS,无限回购】
      现萃香醇Espresso,遇见优质冷榨生椰浆,椰香浓郁,香甜清爽,带给你不一样的拿铁体验!
      
      主要原料:浓缩咖啡、冷冻椰浆、原味调味糖浆
      图片及包装仅供参考,请以实物为准。建议送达后尽快饮用。到店饮用口感更佳。`,
      sellNumber: 1000,
      favorRate: 100,
      price: 19.9,
    },
    {
      pic: './assets/g3.png',
      title: '加浓 美式',
      desc: `1人份【清醒加倍,比标美多一份Espresso】
      口感更佳香醇浓郁,回味持久
      图片仅供参考,请以实物为准。建议送达后尽快饮用。`,
      sellNumber: 200,
      favorRate: 93,
      price: 20.3,
    },
    {
      pic: './assets/g4.png',
      title: '瓦尔登蓝钻瑞纳冰',
      desc: `1人份【爆款回归!蓝色治愈力量】
      灵感来自下澄明、碧蓝之境---瓦尔登湖。含藻蓝蛋白,梦幻蓝色源自天然植物成分,非人工合成色素,融入人气冷榨生椰浆,椰香浓郁,清冽冰爽;底部添加Q弹小料,0脂原味晶球,光泽剔透,如钻石般blingbling。搭配奶油顶和彩虹色棉花糖,满足你的少女心~
      【去奶油小提示】由于去掉奶油后顶料口味会受影响,为保证口感,选择“去奶油”选项时将同时去掉奶油及顶料,请注意哦!【温馨提示】瑞纳冰系列产品形态为冰沙,无法进行少冰、去冰操作,请您谅解。【图片仅供参考,请以实物为准】`,
      sellNumber: 17,
      favorRate: 80,
      price: 38,
    },
    {
      pic: './assets/g5.png',
      title: '椰云精萃美式',
      desc: `1人份【不用吸管 大口吞云!】
  
      1杯热量*≈0.6个苹果!
      原创瑞幸椰云™工艺,将「椰浆」变成绵密、丰盈的“云朵”,口感绵密顺滑!0乳糖植物基,清爽轻负担!
      
      *数据引自《中国食物成分表》第六版,苹果每100克可食部分中能量约为53千卡,以每个苹果250克/个计,1杯椰云精萃美式约80千卡,相当于约0.6个苹果。
      【图片仅供参考,请以实物为准】`,
      sellNumber: 50,
      favorRate: 90,
      price: 21.12,
    },
  ];
  

index.js

// 这里利用ES6中的类来实现单件商品的数据,这种写法是一种面向对象编程的写法,优势是可以将数据和方法进行封装,
// 单件商品的数据
class UIGoods {
  // 构造函数
  constructor(g) {
    this.data = g; // 初始化data属性为传入的参数g
    this.choose = 0; // 初始化choose属性为0
    // this.totalPrice=0;// 初始化totalPrice属性为0,但这样会导致每次计算总价都要重新计算,造成数据冗余
    // 数据冗余的解决方法:将totalPrice属性设置为私有属性,通过getter方法来获取和设置值
    // 数据冗余的优缺点:性能下降,但可以减少代码量。且可以提高代码的可读性、可维护性
  }

  /**
   * 获取、计算总价
   * @return {number} 总价
   */
  getTotalPrice() {
    return this.data.price * this.choose;
  }

  // 是否选中了此件商品
  isChoose() {
    // 如果choose大于0,则表示选中了此件商品
    return this.choose > 0;
  }

  /* 
  选择的数量+1
  这么写的好处是,可以避免多次判断,提高性能。而且可以提高代码的可读性、可维护性。如果想要在原有基础上增加数量,可以直接调用increase方法
  */
  increase() {
    this.choose++;
  }
  // 选择的数量-1
  decrease() {
    // 如果选择的数量为0,则表示没有选择此件商品,不需要减
    if (this.choose === 0) {
      return;
    }
    this.choose--;
  }
}

// 整个界面的数据
class UIData {
  constructor() {
    // 数组
    var uiGoods = [];
    // 遍历原始数据,将原始数据转换为单件商品的数据
    for (var i = 0; i < goods.length; i++) {
      var uig = new UIGoods(goods[i]);
      uiGoods.push(uig);
    }
    // 将单件商品的数据保存到uiGoods属性中
    this.uiGoods = uiGoods;
    // 起送标准 => 还差多少钱起送
    this.deliveryThreshold = 30;
    // 起送标准 => 起送价格,配送费用
    this.deliveryPrice = 5;
  }
// 总价
  getTotalPrice() {
    var sum = 0;
      // 遍历循环
    for (var i = 0; i < this.uiGoods.length; i++) {
      var g = this.uiGoods[i];
      sum += g.getTotalPrice();
    }
    return sum;
  }

  // 增加某件商品的选中数量,通过下标拿到对应的商品
  increase(index) {
    this.uiGoods[index].increase();
  }
  // 减少某件商品的选中数量
  decrease(index) {
    this.uiGoods[index].decrease();
  }

  // 得到总共的选择数量
  getTotalChooseNumber() {
    var sum = 0;
    for (var i = 0; i < this.uiGoods.length; i++) {
      sum += this.uiGoods[i].choose;
    }
    return sum;
  }

  // 判断购物车中有没有东西
  hasGoodsInCar() {
    // 这里调用了getTotalChooseNumber,如果数量大于0,那就代表购物车中有东西
    return this.getTotalChooseNumber() > 0;
  }

  // 是否跨过了起送标准
  isCrossDeliveryThreshold() {
    return this.getTotalPrice() >= this.deliveryThreshold;
  }

  // 判断是否选中了商品,利用了商品的下标
  isChoose(index) {
    return this.uiGoods[index].isChoose();
  }
}

// 整个界面
class UI {
  constructor() {
    // 商品数据,对商品进行封装,不管是对商品进行增删改查,还是对商品进行计算,都可以统一封装到一个对象中
    this.uiData = new UIData();
    // 是用来获取元素的,因为我们是用js来操作dom,所以需要用到dom元素。这doms里面包含了各种dom元素
    this.doms = {
      // 获取商品列表容器
      goodsContainer: document.querySelector(".goods-list"),
      // 获取配送费
      deliveryPrice: document.querySelector(".footer-car-tip"),
      // 获取页脚
      footerPay: document.querySelector(".footer-pay"),
      // 获取页脚内的span
      footerPayInnerSpan: document.querySelector(".footer-pay span"),
      // 获取总价
      totalPrice: document.querySelector(".footer-car-total"),
      // 获取购物车
      car: document.querySelector(".footer-car"),
      // 获取购物车的角标
      badge: document.querySelector(".footer-car-badge"),
    };
    //  获取购物车的位置
    var carRect = this.doms.car.getBoundingClientRect();

    // 获取购物车的中心点
    var jumpTarget = {
      x: carRect.left + carRect.width / 2,
      y: carRect.top + carRect.height / 5,
    };
    // 获取购物车的中心点
    this.jumpTarget = jumpTarget;

    // 创建商品列表 => 是为了循环创建商品列表元素
    this.createHTML();
    // 更新页脚
    this.updateFooter();
    // 监听各种事件
    this.listenEvent();
  }

  // 监听各种事件
  listenEvent() {
    // 购物车动画
    this.doms.car.addEventListener("animationend", function () {
      this.classList.remove("animate");
    });
  }

  // 根据商品数据创建商品列表元素
  /*
    两种方式(这里用第一种方式)
    1.遍历商品数据,将商品数据转换为html字符串 => 优点:可以减少代码量、简单,但性能下降、执行效率低。因为字符串得parse html,得解析成dom元素,且无法直接操作dom元素(总的来说,就是执行效率低,开发效率高)

    2.一个一个创建商品列表元素 => 优点:性能高、执行效率高,但代码量多,不好维护。而且不需要解析成dom元素,可以直接操作dom元素(总的来说,执行效率高,开发效率低)
  */
  createHTML() {
    // 生成html字符串
    var html = "";
    // 遍历商品数据
    for (var i = 0; i < this.uiData.uiGoods.length; i++) {
      // 获取单个商品数据
      var g = this.uiData.uiGoods[i];

      // 将单个商品数据转换为html字符串,这里进行了拼接。因为这里是拼接,所以需要使用+=。而且拼接之后就不用在html中添加<div>了
      html += `<div class="goods-item">
        <img src="${g.data.pic}" alt="" class="goods-pic">
        <div class="goods-info">
          <h2 class="goods-title">${g.data.title}</h2>
          <p class="goods-desc">${g.data.desc}</p>
          <p class="goods-sell">
            <span>月售 ${g.data.sellNumber}</span>
            <span>好评率${g.data.favorRate}%</span>
          </p>
          <div class="goods-confirm">
            <p class="goods-price">
              <span class="goods-price-unit">¥</span>
              <span>${g.data.price}</span>
            </p>
            <div class="goods-btns">
              <i index="${i}" class="iconfont i-jianhao"></i>
              <span>${g.choose}</span>
              <i index="${i}" class="iconfont i-jiajianzujianjiahao"></i>
            </div>
          </div>
        </div>
      </div>`;
    }

    // 将html字符串添加到商品列表容器中
    this.doms.goodsContainer.innerHTML = html;
  }

  // 界面的增加
  increase(index) {
    // 增加商品数量
    this.uiData.increase(index);
    // 调用更新某个商品元素的显示状态
    this.updateGoodsItem(index);
    // 更新页脚
    this.updateFooter();
    // 跳到对应的商品
    this.jump(index);
  }

  // 界面的减少
  decrease(index) {
    this.uiData.decrease(index);
    this.updateGoodsItem(index);
    this.updateFooter();
  }

  // 更新某个商品元素的显示状态
  updateGoodsItem(index) {
    // 获取商品元素
    var goodsDom = this.doms.goodsContainer.children[index];
    // 判断是否选中
    if (this.uiData.isChoose(index)) {
      // 选中,就加上active类
      goodsDom.classList.add("active");
    } else {
      // 未选中,就去掉active类
      goodsDom.classList.remove("active");
    }
    // 更新数量
    var span = goodsDom.querySelector(".goods-btns span");
    // 将span元素的文本设置为当前商品的数量
    span.textContent = this.uiData.uiGoods[index].choose;
  }

  // 更新页脚
  updateFooter() {
    // 得到总价数据
    var total = this.uiData.getTotalPrice();
    // 设置配送费
    this.doms.deliveryPrice.textContent = `配送费¥${this.uiData.deliveryPrice}`;
    // 设置起送费还差多少
    if (this.uiData.isCrossDeliveryThreshold()) {
      // 到达起送点,就加上active类
      this.doms.footerPay.classList.add("active");
    } else {
      // 没有到达起送点,就去掉active类
      this.doms.footerPay.classList.remove("active");
      // 如果没有到达起送点,就更新还差多少钱
      var dis = this.uiData.deliveryThreshold - total;
      // 四舍五入。因为计算机中小数点计算不准,所以要四舍五入
      dis = Math.round(dis);
      // 更新span元素的文本
      this.doms.footerPayInnerSpan.textContent = `还差¥${dis}元起送`;
    }

    // 设置总价,toFixed(2)表示保留两位小数 => 是因为小数点计算不准,所以要四舍五入。利用toFixed(2)将总价变为了字符串格式的数字
    this.doms.totalPrice.textContent = total.toFixed(2);

    // 设置购物车的样式状态
    if (this.uiData.hasGoodsInCar()) {
      // 有商品,就加上active类
      this.doms.car.classList.add("active");
    } else {
      // 没有商品,就去掉active类
      this.doms.car.classList.remove("active");
    }
    // 设置购物车中的数量,得到总数
    this.doms.badge.textContent = this.uiData.getTotalChooseNumber();
  }

  // 购物车动画
  carAnimate() {
    this.doms.car.classList.add("animate");

    // 去除动画结束事件,但是这样写的话,动画结束事件会被执行两次。而且每写一次,都会有一次动画结束事件。直接在开始写一个动画结束事件,在动画结束事件中去掉动画结束事件,这样就只会执行一次动画结束事件。=> 上面的listenEvent()方法中有写过,效果一样的
    // this.doms.car.addEventListener("animationend", function () {
    //   // 这里的this是动画事件触发的元素
    //   this.classList.remove("animate");
    // });
  }

  // 抛物线跳跃的元素
  jump(index) {
    // 找到对应商品的加号
    var btnAdd = this.doms.goodsContainer.children[index].querySelector(
      ".i-jiajianzujianjiahao"
    );
    // 得到加号的坐标
    var rect = btnAdd.getBoundingClientRect();
    // 起始坐标
    var start = {
      x: rect.left,
      y: rect.top,
    };
    // 跳吧
    var div = document.createElement("div");
    // div的样式
    div.className = "add-to-car";
    var i = document.createElement("i");
    // i的样式
    i.className = "iconfont i-jiajianzujianjiahao";
    // 设置初始位置,div管横向,i管纵向
    div.style.transform = `translateX(${start.x}px)`;
    i.style.transform = `translateY(${start.y}px)`;
    // 将i添加到div中
    div.appendChild(i);
    // 将div添加到body中
    document.body.appendChild(div);
    // 强行渲染
    div.clientWidth;

    // 设置结束位置,添加一个过渡效果
    div.style.transform = `translateX(${this.jumpTarget.x}px)`;
    i.style.transform = `translateY(${this.jumpTarget.y}px)`;
    var that = this;

    // 过渡结束后,删除div => 是为了防止动画结束后,div还在body中,导致动画结束后,div还会执行动画结束事件
    div.addEventListener(
      "transitionend",
      function () {
        div.remove();
        // 购物车动画得到触发
        that.carAnimate();
      },
      {
        once: true, // 事件仅触发一次
      }
    );
  }
}

var ui = new UI();

// 事件
// 添加点击事件
ui.doms.goodsContainer.addEventListener("click", function (e) {
  // 判断点击的元素是否是加号
  if (e.target.classList.contains("i-jiajianzujianjiahao")) {
    // 得到商品的索引,如果点击的是加好,就加1,如果点击的是减号,就减1。这里将索引(字符串)转成数字类型
    var index = +e.target.getAttribute("index");
    ui.increase(index);
  } else if (e.target.classList.contains("i-jianhao")) {
    var index = +e.target.getAttribute("index");
    ui.decrease(index);
  }
});

// 按键事件,如果用户按了+号,就输出Equal,如果按了-号,就输出Minus。这里只是演示,实际开发中,按键事件要用到keydown事件。
window.addEventListener("keypress", function (e) {
  if (e.code === "Equal") {
    ui.increase(0);
  } else if (e.code === "Minus") {
    ui.decrease(0);
  }
});



/*
也可以用这种方式写,但是用这种方式写的话,会导致代码冗余
function UIGoods(g) {
  this.data = g;
  this.choose = 1;
}
UIGoods.prototype.getTotalPrice = function(){
  return this.data.price * this.choose;
}
UIGoods.prototype.isChoose = function(){
  return this.choose >0;
}
new UIGoods(goods[0]);*/

// 提前优化的优缺点:永远不要提前优化,因为优化之后,代码会变得更复杂、可读性会变差。
// 什么时候优化:出问题的时候,优化一下。要么就是出问题了,要么就是出问题了,要么就是出问题了。

效果图

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

新增PostgreSQL数据库管理功能,1Panel开源面板v1.9.3发布

2024年1月15日&#xff0c;现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.9.3版本。 在这一版本中&#xff0c;1Panel新增了PostgreSQL数据库管理功能&#xff0c;并且支持设置PHP运行环境扩展模版。此外&#xff0c;我们进行了30多项功能更新和问题修复。1Panel应用…

如何应对Android面试官->RecyclerView回收复用LayoutManager,实战探探划一下

前言 上章我们讲了右半部分&#xff0c;本章我们讲解左半部分&#xff1b; 如何复用原理 我们在滑动的时候&#xff0c;才会触发 RecyclerView 的回收复用&#xff0c;所以我们从 RecyclerView 的 onTouchEvent 方法入手&#xff1b;我们来看下滑动的时候&#xff0c;是怎么…

SQL实践:利用tag检索文件的多种情况讨论(二)

在上一篇文章SQL实践&#xff1a;利用tag检索文件的多种情况讨论中&#xff0c;我们介绍了在使用外键的方式为数据关联tag后&#xff0c;如何筛选&#xff1a; 如何筛选包含某一个tag的数据如何筛选包含且只包含某一个tag的数据如何筛选包含多个指定tag的数据 这篇文章主要是…

LiveGBS流媒体平台GB/T28181功能-基础配置接入控制白名单黑名单配置控制设备安全接入设备单独配置接入密码

LiveGBS基础配置接入控制白名单黑名单配置控制设备安全接入设备单独配置接入密码 1、白名单配置应用场景2、接入控制2.1、白名单2.2、黑名单 3、搭建GB28181视频直播平台 1、白名单配置应用场景 LiveGBS国标流媒体服务&#xff0c;支持白名单配置。 可在设备注册前&#xff0…

机器学习_梯度下降

文章目录 什么是梯度梯度下降梯度下降有什么用 什么是梯度 计算梯度向量其几何意义&#xff0c;就是函数变化的方向&#xff0c;而且是变化最快的方向。对于函数f(x)&#xff0c;在点(xo,yo)&#xff0c;梯度向量的方向也就是y值增加最快的方向。也就是说&#xff0c;沿着梯度…

使用 Elasticsearch 和 LlamaIndex 进行高级文本检索:句子窗口检索

2023 年是检索增强生成 (RAG) 的一年&#xff0c;人们探索了许多用例&#xff0c;并使用该技术开发了数百种产品。 从 Q/A 聊天机器人到基于上下文的代理&#xff0c;RAG 的使用一直是 LLM 申请快速增长的主要因素。 支持不断发展的社区以及 Langchain 和 LlamaIndex 等强大框架…

Controller层自定义注解拦截request请求校验

一、背景 笔者工作中遇到一个需求&#xff0c;需要开发一个注解&#xff0c;放在controller层的类或者方法上&#xff0c;用以校验请求参数中(不管是url还是body体内&#xff0c;都要检查&#xff0c;有token参数&#xff0c;且符合校验规则就放行)是否传了一个token的参数&am…

Java工具类汇总

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; ExcelUtils public class ExcelUtils {/*** 注入的具有排序功能的handle*/private static final SortRowWriteHandler SORT_ROW_WRITE_HANDLER new SortRowWriteHan…

linux 网络文件共享服务

存储类型 DAS 直连式存储 SAN 存储区域网络 NAS 网络附近存储 FTP文件传输协议 文件传输协议 FTP 早期的三个应用级协议之一&#xff0c;基于c/s架构 数据传输格式&#xff1a;二进制&#xff08;默认&#xff09;和文本 tcp 21端口&#xff08;权限&#xff0c;…

centos7配置时间同步网络时间

centos7配置时间同步网络时间 1、安装 NTP 工具。 sudo yum install -y ntp2启动 NTP 服务。 sudo systemctl start ntpd3、将 NTP 服务设置为开机自启动。 sudo systemctl enable ntpd4、验证 date

超5000亿元,2024年国家电网预计电网建设投资总规模

近日&#xff0c;国家电网公司对外透露&#xff0c;2024年将继续加大数智化坚强电网的建设&#xff0c;促进能源绿色低碳转型&#xff0c;推动阿坝至成都东等特高压工程开工建设。围绕数字化配电网、新型储能调节控制、车网互动等应用场景&#xff0c;打造一批数智化坚强电网示…

WEB服务器-Tomcat

3. WEB服务器-Tomcat 3.1 简介 3.1.1 服务器概述 服务器硬件 指的也是计算机&#xff0c;只不过服务器要比我们日常使用的计算机大很多。 服务器&#xff0c;也称伺服器。是提供计算服务的设备。由于服务器需要响应服务请求&#xff0c;并进行处理&#xff0c;因此一般来说…

Relation-Aware Graph Transformer for SQL-to-Text Generation

Relation-Aware Graph Transformer for SQL-to-Text Generation Abstract SQL2Text 是一项将 SQL 查询映射到相应的自然语言问题的任务。之前的工作将 SQL 表示为稀疏图&#xff0c;并利用 graph-to-sequence 模型来生成问题&#xff0c;其中每个节点只能与 k 跳节点通信。由…

shell简单截取curl GET返回的body消息体

目录 需求背景&#xff1a; 示例&#xff1a; 解决方式&#xff1a; 需求背景&#xff1a; 用shell解析 curl命令GET到的消息体&#xff0c;获取body消息体里的某个字段的值,只是个简单的示例&#xff0c;可以在此基础上更改满足自己的需求 示例&#xff1a; curl一个API…

使用CSS计算高度铺满屏幕

前言 今天写项目时出现高度设置百分百却不占满屏幕&#xff0c;第一反应看自己设置的是块级元素还是行级元素。看了几篇博客&#xff0c;发现并不能解决问题。脱离文档流的做法都没考虑&#xff0c;前期模板搭建脱离文档流&#xff0c;后面开发会出现很多问题。 以上图片是我…

【EI会议征稿通知】2024年第三届能源互联网及能源交互技术国际会议(EIEIT 2024)

2024年第三届能源互联网及能源交互技术国际会议(EIEIT 2024) 2024 3rd International Conference on the Energy Internet and Energy Interactive Technology 随着EIEIT前2届的成功举办&#xff0c;我们很荣幸地宣布&#xff0c;2024年第三届能源互联网及能源交互技术国际学术…

HCIA——12题目-1章选择

学习目标&#xff1a; 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

FPGA之LUT

由于FPGA需要被反复烧写,它实现组合逻辑的基本结构不可能像ASIC那样通过固定的与非门来完成,而只能采用一种易于反复配置的结构。查找表可以很好地满足这一要求,目前主流FPGA都采用了基于SRAM工艺的查找表结构。LUT本质上就是一个RAM.它把数据事先写入RAM后,每当输入一个信号就…

【Mybatis】说一下 mybatis 的一级缓存和二级缓存

​ &#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Mybatis ⛳️ 功不唐捐&#xff0c;玉汝于成 ​ 目录 前言 正文 一级缓存&#xff08;Local Cache&#xff09;&#xff1a; 范围&#xff1a; 生命周期&#xff1a; 默认开启&…

PyTorch Tutorial 2.0

这里是对于PyTorch Tutorial-CSDN博客的补充&#xff0c;但是与其相关的NLP内容无关&#xff0c;只是一些基础的PyTorch用法的记录&#xff0c;主要目的是能够自己生成一些模拟的数据集。先介绍随机数的目的是因为based on随机数方法。 当然在看随机数的方法的时候&#xff0c…
最新文章