附录6-4 黑马优购项目-分类和购物车

news2024/11/25 14:44:07

目录

1  分类

1.1  接口

1.2  窗口限制

1.3  选中状态样式判断

1.4  点击左侧时右侧会到顶点

1.5  源码 

2  购物车

2.1  store

2.2  tabBar徽标

2.3  滑动删除

2.4  结算

2.4.1  结算前登录

2.4.2  结算功能

2.5  触发组件事件

2.6  源码


1  分类

分类最上部是搜索区域,与首页的搜索区域相同,这里直接复用

右侧区域的内容 会根据点击不同左侧区域 而变化

左侧区域和右侧区域均可以向下滚动

滚动后切换到别的页面,然后再切换回来,滚动的位置不变(记录位置是scroll-view的默认效果,不用额外进行修改)

1.1  接口

接口中包含三级标题。紫色框子是一级标题,橙色框子是二级标题,绿色框子是三级标题

url是https://api-hmugo-web.itheima.net/api/public/v1/categories 直接发get请求就行了

1.2  窗口限制

分类页面的最外层只有两个部分,一个是搜索框,除了搜索框剩下都属于另外一部分。为了让左侧和右侧都有拖动了效果,所以这里对高度进行了限制

如果取消高度限制,页面中的scroll-view-container就废了,左侧和右侧就会同时进行拖动

限制高度的值根据机型进行调节,wx.getWindowInfo()可以获得当前机型的高度,减50是减去屏幕最下方的tarbar高度。高度在页面初次加载的时候就进行计算

1.3  选中状态样式判断

左侧列表被选中后会有这个红色的部分

每次点击左侧列表会记录left_active_num,讲left_active_num与循环时的index进行比对,如果相同的多给一个active的类名

1.4  点击左侧时右侧会到顶点

每一次点击左侧的时候,右侧的内容是不同的,但实际上元素都是一个。所以点击左侧时,右侧不会默认回到顶点

这里用变量的原因是给0这个常量第二次就懒加载了,只能点击左侧之后每次都赋值一个新的0

1.5  源码 

wxml

<!--pages/category/category.wxml-->
<black_horse_search></black_horse_search>
<view class="scroll-view-container" style="height:{{windowHeight}};">
<!-- <view class="scroll-view-container" style="height:200px;"> -->
  <!-- 左侧滚动区域 -->
  <scroll-view class="left-scroll-view" scroll-y="true">
    <view  wx:for="{{cateList}}" wx:key="cat_id" class="{{['scroll-view-item',index==left_active_num?'active':'']}}" bindtap="left_scroll_click" data-click_item_index="{{index}}">{{item.cat_name}}</view>
  </scroll-view>
  <!-- 右侧滚动区域 -->
  <!-- 老版本的scroll-top不能给相同的值,也就是你一直给0是不行的 -->
  <scroll-view class="right-scroll-view" scroll-y="true" scroll-top="{{right_scrollTop}}">
    <view class="cate-lv2" wx:for="{{cateLevel2}}" wx:key="index">
      <view class="cate-lv2-title">/ {{item.cat_name}} /</view>
      <view class="cate-lv3-list">
        <view class="cate-lv3-item" wx:for="{{item.children}}" wx:for-index="index3" wx:for-item="item3" wx:key="index3" bindtap="cate_lv3_item_click" data-cat_name="{{item3.cat_name}}" data-cat_id="{{item3.cat_id}}">
          <image src="{{item3.cat_icon}}" mode="" data-cat_name="{{item3.cat_name}}" data-cat_id="{{item3.cat_id}}"/>
          <text data-cat_name="{{item3.cat_name}}" data-cat_id="{{item3.cat_id}}" >{{item3.cat_name}}</text>
        </view>
      </view>
    </view>
  </scroll-view>
</view>

wxss

/* pages/category/category.wxss */
.scroll-view-container {
  display: flex;
}

.scroll-view-container .left-scroll-view {
  width: 120px;
}

.scroll-view-container .left-scroll-view .scroll-view-item.active {
  position: relative;
  background-color: #ffffff;
}

.scroll-view-container .left-scroll-view .scroll-view-item.active::before {
 position:absolute;
 top:50%;
 left:0;
 content:' ';
 display:block;
 width: 3px;
 height:30px;
 background-color: #C00000;
 transform: translateY(-50%);
}

.scroll-view-container .left-scroll-view .scroll-view-item {
  background-color: #f7f7f7;
  line-height: 60px;
  text-align: center;
  font-size: 12px;
}

.cate-lv2-title {
  font-size:12px;
  font-weight:bold;
  text-align: center;
  padding: 15px 0;
}

.cate-lv3-list {
  display:flex;
  flex-wrap:wrap
}

.cate-lv3-list .cate-lv3-item {
  width:33.33%;
  display:flex;
  flex-direction:column;
  justify-content: center;
  align-items: center;
  margin-bottom:10px;
}

.cate-lv3-list .cate-lv3-item image{
  width:60px;
  height:60px;
}

.cate-lv3-list .cate-lv3-item text{
  font-size:12px;
}

js

// pages/category/category.js
import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store.js'

const App = getApp()

Page({
  cate_lv3_item_click(e) {
    wx.navigateTo({
      url:'/subpackage_goods_list/goods_list?cid=' + e.target.dataset.cat_id + '&&query=' + e.target.dataset.cat_name
    })
  },
  left_scroll_click(e) {
    const click_item_index = e.target.dataset.click_item_index
    this.setData({left_active_num:click_item_index})
    this.setData({cateLevel2:this.data.cateList[Number(click_item_index)].children})
    this.setData({right_scrollTop:0})
  },
  get_cateList() {
    wx.request({
      url:App.base_url + '/api/public/v1/categories',
      
      method:'GET',
      success:(val) => {
        // 获取所有分类
        this.setData({cateList:val.data.message})
        // 获取二级分类,二级分类的内容在一级分类中有,我们在这里弄好处理,这里给一个初始值,后面在左侧点击事件中还会再改
        this.setData({cateLevel2:val.data.message[0].children})
      },
      fail:() => {
        console.log('获取左侧失败')
        wx.showToast({
          title:'获取左侧失败',
          icon:'error',
          duration:2000
        })
      }
    })
  },
  /**
   * 页面的初始数据
   */
  data: {
    windowHeight:0 + 'px',
    cateList:[],
    cateLevel2:[],
    left_active_num:0,
    right_scrollTop:0
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.storeBindings = createStoreBindings(this,{
      store,
      actions:['set_cart_tabBar_badge']
    })

    this.setData({windowHeight:(wx.getWindowInfo().windowHeight-50) + 'px'})
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    // 获取分类列表
    this.get_cateList()
    // 设置购物车tabBar的徽标
    this.set_cart_tabBar_badge()
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

2  购物车

购物车中的内容在这个项目中都是放在本地的,在实际开发中一般是放在云端

购物车为空时会显示这个页面

2.1  store

store.js是放全局变量的js文件,创建方法可以参考 18.全局数据共享 mobx-miniprogram与mobx-miniprogram-bindings-CSDN博客

源码

import {
  action,
  observable
} from 'mobx-miniprogram'

export const store = observable({
  // 购物车总数的计算属性
  // 计算购物车一共多少件
  get cart_shop_total() {
    let total = 0
    this.cart_list.forEach(goods => total += goods.goods_count)
    return total
  },
  // 计算购物车选中的一共多少钱
  get cart_shop_choosed_total_price() {
    let total_price = 0
    this.cart_list.forEach(goods => {
      if (goods.goods_state == true) {
        total_price = total_price + goods.goods_count * goods.goods_price
      }
    })
    return total_price.toFixed(2)
  },
  // 计算购物车选中的一共多少件
  get cart_shop_choosed_total_num() {
    let total_num = 0
    this.cart_list.forEach(goods => {
      if (goods.goods_state == true) {
        total_num = total_num + goods.goods_count
      }
    })
    return total_num
  },
  // 计算是否全选
  get is_all_checked() {
    let all_checked = true
    this.cart_list.forEach(goods => {
      if (goods.goods_state == false) {
        all_checked = false
      }
    })
    return all_checked
  },
  // 从本地存储中获取购物车商品信息
  cart_list: wx.getStorageSync('cart_list') || [],
  // 添加购物车方法
  add_cart_obj: action(function (goods_obj) {
    let findResult = this.cart_list.find((x) => x.goods_id === goods_obj.goods_id)

    if (!findResult) {
      this.cart_list = [...this.cart_list, goods_obj]
    } else {
      findResult.goods_count++
    }

    wx.setStorageSync('cart_list', this.cart_list)
  }),
  // 设置购物车tabBar的徽标
  set_cart_tabBar_badge:action(
    function() {
      wx.setTabBarBadge({
        index: 2,
        text: String(this.cart_shop_total),
      })
    }
  ),
  // 改变购物车商品所有选中状态
  updateAllGoodsState:action(
    function(all_checked_now_state) {
      this.cart_list.forEach(goods => {
        goods.goods_state = !all_checked_now_state
      })
      let new_cart_list = JSON.stringify(this.cart_list)
      this.cart_list = JSON.parse(new_cart_list)
      wx.setStorageSync('cart_list', this.cart_list)
    }
  ),
  // 改变购物车商品选中状态
  updateGoodsState:action(
    function(goods) {
      let findResult = this.cart_list.find(x=>x.goods_id === goods.goods_id)

      if (findResult) {
        findResult.goods_state = !goods.goods_status
        let new_cart_list = JSON.stringify(this.cart_list)
        this.cart_list = JSON.parse(new_cart_list)
      }
      wx.setStorageSync('cart_list', this.cart_list)
    }
  ),
  // 购物车商品数量 + 1
  add_one_GoodsNum:action(
    function(goods) {
      let findResult = this.cart_list.find(x=>x.goods_id === goods.goods_id)

      if (findResult) {
          findResult.goods_count = findResult.goods_count + 1
          let new_cart_list = JSON.stringify(this.cart_list)
          this.cart_list = JSON.parse(new_cart_list)
      }
      wx.setStorageSync('cart_list', this.cart_list)
    }
  ),
  // 购物车商品数量 - 1
  sub_one_GoodsNum:action(
    function(goods) {
      let findResult = this.cart_list.find(x=>x.goods_id === goods.goods_id)

      if (findResult) {
        if (findResult.goods_count > 1) {
          findResult.goods_count = findResult.goods_count - 1
          let new_cart_list = JSON.stringify(this.cart_list)
          this.cart_list = JSON.parse(new_cart_list)
        }
      }
      wx.setStorageSync('cart_list', this.cart_list)
    }
  ),
  // 删除购物车商品
  delete_store_goods:action(
    function(goods) {
      this.cart_list = this.cart_list.filter(x=>x.goods_id != goods.goods_id)
      wx.setStorageSync('cart_list', this.cart_list)
    }
  ),
  // 是否是从“购物车”跳转到“我的”界面且需要跳转回“购物车”页面
  need_navigate_back:false,
  yes_need_navigate_back:action(function() {
    this.need_navigate_back = true
  }),
  cancel_need_navigate_back:action(function() {
    this.need_navigate_back = false
  })
})

2.2  tabBar徽标

tarBar上的徽标是购物车中商品的数量

用到的是wx.setTabBarBadge()这个api

index是第几个tarbar,按0、1、2这么排,购物车是第二个

text是要写什么东西,类型为字符串,也就是说可以写其他的文字上去

当切换到任意tarbar的时候会更新徽标,在加入购物车的时候会更新徽标,在改变商品数量的时候会更新徽标

使用方法时引入store然后用this调用就行了

2.3  滑动删除

用的是movable-area与movable-view

movable-view必须放在movable-area中,其余就没什么好讲的了,有例子照抄就行了

2.4  结算

2.4.1  结算前登录

这个功能需要“购物车”和“我的”这两个tarbar共同完成,所以需要用到全局数据

这个变量是给"我的"中的一键登录按钮用的,直接点一键登录按钮就不需要跳转,从购物车界面过来再点一键登录按钮就需要跳转

2.4.2  结算功能

目前小程序结算功能是不开放给个人开发者的,如果要开通的话只有一个公司的营业执照也是不行的,需要有实际的开发需求才能用微信支付的接口

2.5  触发组件事件

这些是触发组件的事件,感兴趣可以看一下这个 15-5.自定义组件的通信-CSDN博客

2.6  源码

wxml

<!--pages/cart/cart.wxml-->

<!-- 收货地址区域 -->
<view class="cart-container" wx:if="{{cart_list.length != 0}}">
  <view>
  <!-- 选择收货地址的盒子 -->
  <view class="address-choose-box" wx:if="{{!choosed_address.username}}">
    <button type="primary" size="mini" class="btnChooseAddress" bind:tap="go_to_choose_address">请选择收货地址+</button>
  </view>

  <!-- 渲染收货信息的盒子 -->
  <view class="address-info-box" wx:else bind:tap="go_to_choose_address">
    <view class="row1">
      <view class="row1-left">
        <view class="username">收货人:<text>{{choosed_address.username}}</text></view>
      </view>
      <view class="row1-right">
        <view class="phone">电话:<text>{{choosed_address.phone}}</text></view>
        <image src="/src/arrowright.png" mode="" style="width:16px;height:16px" />
      </view>
    </view>
    <view class="row2">
      <view class="row2-left">收货地址:</view>
      <view class="row2-right">{{choosed_address.address_detail}}</view>
    </view>
  </view>

  <!-- 底部的边框线 -->
  <image src="/src/cart_border@2x.png" class="address-border"></image>
  </view>

  <!-- 购物车标题 -->
  <view class="cart-title">
    <image src="../../src/shop.png" mode="" style="width:18px;height:18px;"/>
    <text class="cart-title-text">购物车</text>
  </view>

  <!-- 购物车内容 -->
  <view class="cart_content_view">
    <block wx:for="{{cart_list}}" wx:key="index" >
      <movable-area data-goods_id="{{item.goods_id}}">
        <movable-view direction="horizontal" data-goods_id="{{item.goods_id}}">
          <goods_list_item goods_small_logo="{{item.goods_small_logo}}" goods_id="{{item.goods_id}}" goods_price="{{item.goods_price}}" goods_name="{{item.goods_name}}" goods_count="{{item.goods_count}}" showRadio="true" showNumberBox="true" goods_checked="{{item.goods_state}}" bind:radio_change="change_radio_state" bind:add_one="add_one" bind:sub_one="sub_one"></goods_list_item>
          <view class="itemDelet" bindtap="delete_goods" data-goods_id="{{item.goods_id}}">删除</view>
        </movable-view>
      </movable-area>
    </block>
  </view>

  <!-- 底部结算区域 -->
  <view class="my-settle-container">
    <label class="radio">
      <checkbox color="#C00000" checked="{{is_all_checked}}" bind:tap="click_all_checked_button"/><text>全选</text>
    </label>
    <view class="amount-box">
      合计:<text class="amount">¥{{cart_shop_choosed_total_price}}</text>
    </view>
    <view class="btn-settle" bind:tap="buy_cart">结算({{cart_shop_choosed_total_num}})</view>
  </view>
</view>
<!-- 当购物车里什么都没有时出现的东西 -->
<view class="empty-cart" wx:else>
    <image src="/src/empty_cart.png" class="empty-img"></image>
    <text class="tip-text">空空如也~</text>
  </view>

wxss

/* pages/cart/cart.wxss */

/* 购物车标题 */
.cart-title {
  height:40px;
  display:flex;
  align-items:center;
  font-size:14px;
  padding-left:5px;
  border-bottom:1px solid #efefef;
  white-space: wrap;
}

.cart-title .cart-title-text {
  margin-left:10px;
  white-space: wrap;
}

/* 购物车内容的滑动效果 */
movable-area {
  display: flex;
  flex-direction: row;
  width: calc(100% + 120rpx);
  justify-content: center;
  left: -120rpx;
  height: 130px;
  z-index:0;
}
 
movable-view {
  display: flex;
  flex-direction: row;
  width: calc(100% - 120rpx);
  z-index: 1001;
  left: 120rpx;
}

.itemDelet {
  position: absolute;
  text-align: center;
  right: -125rpx;
  line-height: 130px;
  height:130px;
  background-color: rgb(194,0,2);
  margin-top: 0rpx;
  margin-right: 6rpx;
  width: 100rpx;
  text-align: right;
  padding-right: 20rpx;
  color: #fff;
}

/* 收货地址 */
.address-border {
  display: block;
  width: 100%;
  height: 5px;
}

.address-choose-box {
  height: 90px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.address-info-box {
  font-size:12px;
  height:90px;
  display:flex;
  flex-direction:column;
  justify-content:center;
  padding:0 5px;
}

.address-info-box .row1 {
  display: flex;
  justify-content: space-between;
}

.address-info-box .row1 .row1-right {
  display: flex;
  align-items: center;
}

.phone {
  margin-right: 5px;
}

.address-info-box .row2 {
  display: flex;
  align-items: center;
  margin-top: 10px;
}

.address-info-box .row2 .row2-left {
  white-space: nowrap;
}

/* 底部结算区域 */
.my-settle-container {
  position: fixed;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 50px;
  background-color: white;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-left: 5px;
  font-size: 14px;
  z-index:999;
}

.my-settle-container .radio {
  display:flex;
  align-items:center;
}

.my-settle-container .amount {
  color:#c00000
}

.my-settle-container .btn-settle {
  height: 50px;
  min-width: 100px;
  background-color: #c00000;
  color: white;
  line-height: 50px;
  text-align: center;
  padding: 0 10px;
}

.cart_content_view {
  padding-bottom:50px;
}

/* 当购物车什么都没有的时候的区域 */
.empty-cart {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 150px;
}

.empty-cart .empty-img {
  width:90px;
  height:90px;
}

.empty-cart .tip-text {
  font-size:12px;
  color:gray;
  margin-top:15px;
}

js

// pages/cart/cart.js
import {createStoreBindings} from 'mobx-miniprogram-bindings'
import {store} from '../../store/store.js'

const App = getApp()

Page({
  buy_cart() {
    if (this.data.cart_shop_choosed_total_num == 0) {
      wx.showToast({
        title: '请选择要结算的商品',
        mask:true,
        icon:'none'
      })
      setTimeout(function() {wx.hideToast()},800)
      return
    }
    if (!this.data.choosed_address.username) {
      wx.showToast({
        title: '请选择收货地址',
        mask:true,
        icon:'none'
      })
      setTimeout(function() {wx.hideToast()},800)
      return
    }
    if (this.data.userinfo == '') {
      wx.showToast({
        title: '请先登录',
        mask:true,
        icon:'none'
      })
      setTimeout(()=>{
        wx.hideToast()
        wx.switchTab({
          url: '/pages/my/my',
          success:()=>{
            this.yes_need_navigate_back()
          }
        })
      },800)
      return 
    }
  },
  click_all_checked_button() {
    this.updateAllGoodsState(this.data.is_all_checked)
  },
  go_to_choose_address() {
    wx.navigateTo({
      url:'/subpackage_choose_address/choose_address'
    })
  },
  change_radio_state(e) {
    this.updateGoodsState(e.detail)
  },
  add_one(e) {
    this.add_one_GoodsNum(e.detail)
    this.set_cart_tabBar_badge()
  },
  sub_one(e) {
    this.sub_one_GoodsNum(e.detail)
    this.set_cart_tabBar_badge()
  },
  delete_goods(e) {
    this.delete_store_goods(e.target.dataset)
    this.set_cart_tabBar_badge()
  },
  /**
   * 页面的初始数据
   */
  data: {
    // address:{'name':'suyu'}
    choosed_address:{},
    userinfo:'',
    from:''
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.storeBindings = createStoreBindings(this,{
      store,
      fields:['cart_list','cart_shop_choosed_total_price','cart_shop_choosed_total_num','is_all_checked'],
      actions:['set_cart_tabBar_badge','updateGoodsState','add_one_GoodsNum','sub_one_GoodsNum','delete_store_goods','updateAllGoodsState','yes_need_navigate_back']
    })
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    // 设置购物车tabBar的徽标
    this.set_cart_tabBar_badge()
    this.setData({choosed_address:wx.getStorageSync('choosed_address') || {}})
  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    this.setData({choosed_address:wx.getStorageSync('choosed_address') || {}})
    this.setData({userinfo:wx.getStorageSync('userinfo') || ''})
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {
    
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

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

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

相关文章

Flutter笔记:谈Material状态属性-为什么FlatButton等旧版按钮就废弃了

Flutter笔记 谈Material状态属性-为什么FlatButton等旧版按钮就废弃了 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this artic…

免安装SQL管理工具HeidiSQL建库如何选Collation字符校对

免安装SQL管理工具HeidiSQL 文章目录 免安装SQL管理工具HeidiSQL一、安装二、建库因此&#xff0c;通常我们选择&#xff1a; 一、安装 到官方网址&#xff1a;https://www.heidisql.com/ 下载后按不同版本安装或解压&#xff0c;运行目录中的heidisql应用程序。 该工具可以对…

「生存即赚」链接现实与游戏,打造3T平台生态

当前&#xff0c;在线角色扮演游戏&#xff08;RPG&#xff09;在区块链游戏市场中正迅速崛起&#xff0c;成为新宠。随着区块链技术的不断进步&#xff0c;众多游戏开发者纷纷将其游戏项目引入区块链领域&#xff0c;以利用这一新兴技术实现商业价值的最大化。在这一趋势中&am…

加州大学欧文分校英语中级语法专项课程02:Adjectives and Adjective Clauses 学习笔记

Adjectives and Adjective Clauses course certificate 本文是 https://www.coursera.org/learn/adjective-clauses 这门课的学习笔记。 文章目录 Adjectives and Adjective ClausesWeek 01: Adjectives and Adjective PhrasesLearning Objectives Adjectives Introduction Le…

基于Java的智慧社团综合管理系统的设计与实现(论文+源码)_kaic

摘 要 随着校园文化的不断丰富&#xff0c;大学里各种社团越来越多&#xff0c;社团活动也越来越频繁&#xff0c;社员也越来越多&#xff0c;而且大学生退社、入社比较频繁&#xff0c;社团管理就显得非常繁琐而又复杂,如果采用人工管理,对管理员来说将是一件很头疼的事情。设…

5个本地流畅运行大模型的免费工具

大家好&#xff0c;随着大型语言模型&#xff08;LLM&#xff09;驱动的聊天机器人逐渐普及&#xff0c;给人们的工作和生活带来了前所未有的便利。然而&#xff0c;这种便捷性背后潜藏着个人隐私信息被泄露的风险&#xff0c;例如AI公司会收集聊天记录和元数据来优化模型&…

【Vulhub靶场】Nginx 漏洞复现

Nginx 漏洞复现 一、Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09;1、影响版本2、漏洞原理3、漏洞复现 二、Nginx 解析漏洞1、版本信息&#xff1a;2、漏洞详情3、漏洞复现 一、Nginx 文件名逻辑漏洞&#xff08;CVE-2013-4547&#xff09; 1、影响版本 Nginx …

mysql 数据转excel文件

mysql 数据转excel文件 缘由 为售后拉取数据&#xff0c;用navicat太墨迹了&#xff0c;用python写一个main方法跑一下&#xff1b; 1.抽取共同方法&#xff0c;封装成传入mysql&#xff0c;直接下载成excel&#xff1b; 2.写入所有sql语句&#xff0c;传入参数&#xff1b; 代…

2024-05-02 商业分析-杭州小万科技-商业模式分析

摘要: 对杭州小万科技的商业模式进行分析,以对其做出客观的评估。 杭州小万科技的资料: 杭州小万科技有限公司 - 企知道 (qizhidao.com) 杭州小万科技有限公司网站备案查询 - 天眼查 (tianyancha.com) 杭州小万科技有限公司 - 爱企查 (baidu.com) ​ 2023年年报:

Android手写自己的路由SDK

实现自己的路由框架 ​ 在较大型的Android app中常会用到组件化技术&#xff0c;针对不同的业务/基础功能对模块进行划分&#xff0c;从上到下为壳工程、业务模块、基础模块。其中业务模块依赖基础模块&#xff0c;壳工程依赖业务模块。同级的横向模块&#xff08;比如多个业务…

BeanFactory 源码浅析

BeanFactory 功能介绍 BeanFactory 是核心容器&#xff0c;负责管理 Bean 对象 BeanFactory 接口的功能只有一个 getBean() 方法BeanFactory 的实现类&#xff08;DefaultListableBeanFactory&#xff09;包含&#xff1a;控制反转、基本的依赖注入、Bean 生命周期的各种功能…

【Python】函数设计

1.联系函数的设计 2.找质数 3.找因子 4.判断水仙花数 5.斐波拉契数列递归调用&#xff0c;并用数组存储已计算过的数&#xff0c;减少重复计算 1、计算利息和本息 编写两个函数分别按单利和复利计算利息,根据本金、年利率、存款年限得到本息和和利息。调用这两个函数计算1…

【算法刷题日志】吸氧羊的StarryCoding之旅 - 贡献法计算

题目链接&#xff1a;https://www.starrycoding.com/problem/3 题目描述 吸氧羊终于注册了一个StarryCoding账号&#xff01;&#xff08;她很开心&#xff09; 但是吸氧羊忘记了它的密码&#xff0c;她想起你是计算机大师&#xff0c;于是就来请教你。 她虽然不记得密码了…

java版数据结构:深入理解栈和队列:数据结构与应用(vector,stack,queue)

目录 前言 动态数组类&#xff08;vector&#xff09; 特点&#xff1a; 应用&#xff1a; 栈&#xff08;Stack&#xff09; 栈的基础概念&#xff1a; 栈的常用方法&#xff1a; 模拟栈操作&#xff1a; 队列&#xff08;Queue&#xff09; 队列的基础概念 队列的常…

golang学习笔记(协程的基础知识)

golang的协程 协程是一种轻量级的线程&#xff0c;它可以实现并发执行的并行操作。协程是Go语言中的一个核心特性&#xff0c;它使得程序能够以并发的方式运行&#xff0c;并且非常高效。与传统的线程相比&#xff0c;协程的创建和销毁成本非常低&#xff0c;可以方便地启动大…

三维坐标点按剖面分类

一、写在前面 ①配套文件&#xff1a;根据剖面对三维坐标点&#xff08;X,Y,Z&#xff09;分类资源-CSDN文库 ②脱敏处理&#xff1a;蚀变数据已采用随机数生成覆盖 ③剖面坐标按顺序排列在“剖面坐标点.xlsx”文件中 二、3点确定空间中平面方程 原理&#xff1a; 设3点A&…

C++深度解析教程笔记2

C深度解析教程笔记2 第3课 - 进化后的 const 分析实验-C与C的const区别实验-C与C的const区别&const作用域 第4课 - 布尔类型和引用小结 本文学习自狄泰软件学院 唐佐林老师的 C深度解析教程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 第3课 - 进化后…

列转行(spark 与presto语法)

一、Presto 语法 原始数据&#xff1a; 期望数据&#xff1a; 代码&#xff1a; SELECT info, value FROM ( select 张三 as name,18 as age,男 as gender,清华 as schoolunion allselect 李四 as name,18 as age,男 as gender,清华 as school ) as a CROSS JOIN UNNEST(…

Unreal 编辑器工具 批量重命名资源

右键 - Editor Utilities - Editor Utility Blueprint&#xff0c;基类选择 Asset Action Utility 在类默认值内&#xff0c;可以添加筛选器&#xff0c;筛选指定的类型 然后新建一个函数&#xff0c;加上4个输入&#xff1a;ReplaceFrom&#xff0c;ReplaceTo&#xff0c;Add…

使用Android Studio 搭建AOSP FrameWork 源码阅读开发环境

文章目录 概述安装Android Studio编译源码使用Android Studio打开源码制作ipr文件直接编译成功后自动打开Android Studio 修改SystemUI验证开发环境 概述 我们都知道Android的系统源码量非常之大&#xff0c;大致有frameworka层源码&#xff0c;硬件层(HAL)源码&#xff0c;内…