【B站 heima】小兔鲜Vue3 项目学习笔记 Day06

news2024/12/23 22:53:03

文章目录

    • 购物车本地
      • 1. 列表购物车基础数据渲染
      • 2. 列表购物车单选功能
      • 3. 列表购物车全选功能
      • 4. 列表购物车统计列表实现
      • 5. 接口-加入购物车
      • 6. 接口-删除购物车
      • 7. 退出登录-清空购物车数据
      • 8. 合并购物车到服务器(重要)
    • 结算
      • 1. 路由配置和基础数据渲染
      • 2. 地址切换-打开弹框交互实现
      • 3. 切换地址-地址激活交互实现
      • 4. 生成订单功能实现
    • 支付
      • 1. 渲染基础数据
      • 2. 实现支付功能
      • 3. 支付结果展示
      • 4. 封装倒计数函数
    • 小结


购物车本地

1. 列表购物车基础数据渲染

在这里插入图片描述

  • 模板 views/CartList/index.vue
<script setup>
const cartList = []
</script>

<template>
  <div class="xtx-cart-page">
    <div class="container m-top-20">
      <div class="cart">
        <table>
          <thead>
            <tr>
              <th width="120">
                <el-checkbox/>
              </th>
              <th width="400">商品信息</th>
              <th width="220">单价</th>
              <th width="180">数量</th>
              <th width="180">小计</th>
              <th width="140">操作</th>
            </tr>
          </thead>
          <!-- 商品列表 -->
          <tbody>
            <tr v-for="i in cartList" :key="i.id">
              <td>
                <el-checkbox />
              </td>
              <td>
                <div class="goods">
                  <RouterLink to="/"><img :src="i.picture" alt="" /></RouterLink>
                  <div>
                    <p class="name ellipsis">
                      {{ i.name }}
                    </p>
                  </div>
                </div>
              </td>
              <td class="tc">
                <p>&yen;{{ i.price }}</p>
              </td>
              <td class="tc">
                <el-input-number v-model="i.count" />
              </td>
              <td class="tc">
                <p class="f16 red">&yen;{{ (i.price * i.count).toFixed(2) }}</p>
              </td>
              <td class="tc">
                <p>
                  <el-popconfirm title="确认删除吗?" confirm-button-text="确认" cancel-button-text="取消" @confirm="delCart(i)">
                    <template #reference>
                      <a href="javascript:;">删除</a>
                    </template>
                  </el-popconfirm>
                </p>
              </td>
            </tr>
            <tr v-if="cartList.length === 0">
              <td colspan="6">
                <div class="cart-none">
                  <el-empty description="购物车列表为空">
                    <el-button type="primary">随便逛逛</el-button>
                  </el-empty>
                </div>
              </td>
            </tr>
          </tbody>

        </table>
      </div>
      <!-- 操作栏 -->
      <div class="action">
        <div class="batch">
          共 10 件商品,已选择 2 件,商品合计:
          <span class="red">¥ 200.00 </span>
        </div>
        <div class="total">
          <el-button size="large" type="primary" >下单结算</el-button>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.xtx-cart-page {
  margin-top: 20px;

  .cart {
    background: #fff;
    color: #666;

    table {
      border-spacing: 0;
      border-collapse: collapse;
      line-height: 24px;

      th,
      td {
        padding: 10px;
        border-bottom: 1px solid #f5f5f5;

        &:first-child {
          text-align: left;
          padding-left: 30px;
          color: #999;
        }
      }

      th {
        font-size: 16px;
        font-weight: normal;
        line-height: 50px;
      }
    }
  }

  .cart-none {
    text-align: center;
    padding: 120px 0;
    background: #fff;

    p {
      color: #999;
      padding: 20px 0;
    }
  }

  .tc {
    text-align: center;

    a {
      color: $xtxColor;
    }

    .xtx-numbox {
      margin: 0 auto;
      width: 120px;
    }
  }

  .red {
    color: $priceColor;
  }

  .green {
    color: $xtxColor;
  }

  .f16 {
    font-size: 16px;
  }

  .goods {
    display: flex;
    align-items: center;

    img {
      width: 100px;
      height: 100px;
    }

    >div {
      width: 280px;
      font-size: 16px;
      padding-left: 10px;

      .attr {
        font-size: 14px;
        color: #999;
      }
    }
  }

  .action {
    display: flex;
    background: #fff;
    margin-top: 20px;
    height: 80px;
    align-items: center;
    font-size: 16px;
    justify-content: space-between;
    padding: 0 30px;

    .xtx-checkbox {
      color: #999;
    }

    .batch {
      a {
        margin-left: 20px;
      }
    }

    .red {
      font-size: 18px;
      margin-right: 20px;
      font-weight: bold;
    }
  }

  .tit {
    color: #666;
    font-size: 16px;
    font-weight: normal;
    line-height: 50px;
  }

}
</style>
  • 绑定路由,二级路由,测试可用
{
          path: 'cartlist',
          component: CartList
}

在这里插入图片描述

头部购物车点击 购物车结算 按钮,跳转到这个页面

<el-button size="large" type="primary" @click="$router.push('/cartlist')">去购物车结算</el-button>
  • 渲染列表
<!--cartLsit/index.vue-->
<script setup>
// const cartList = []
import { useCartStore } from '@/stores/cartStore';
const cartStore = useCartStore()
</script>

<template>
    <div class="xtx-cart-page">
        <div class="container m-top-20">
            <div class="cart">
                <table>
                    <thead>
                        <tr>
                            <th width="120">
                                <el-checkbox />
                            </th>
                            <th width="400">商品信息</th>
                            <th width="220">单价</th>
                            <th width="180">数量</th>
                            <th width="180">小计</th>
                            <th width="140">操作</th>
                        </tr>
                    </thead>
                    <!-- 商品列表 -->
                    <tbody>
                        <tr v-for="i in cartStore.cartList" :key="i.id">
                            <td>
                                <el-checkbox />
                            </td>
                            <td>
                                <div class="goods">
                                    <RouterLink to="/"><img :src="i.picture" alt="" /></RouterLink>
                                    <div>
                                        <p class="name ellipsis">
                                            {{ i.name }}
                                        </p>
                                    </div>
                                </div>
                            </td>
                            <td class="tc">
                                <p>&yen;{{ i.price }}</p>
                            </td>
                            <td class="tc">
                                <el-input-number v-model="i.count" />
                            </td>
                            <td class="tc">
                                <p class="f16 red">&yen;{{ (i.price * i.count).toFixed(2) }}</p>
                            </td>
                            <td class="tc">
                                <p>
                                    <el-popconfirm title="确认删除吗?" confirm-button-text="确认" cancel-button-text="取消"
                                        @confirm="delCart(i)">
                                        <template #reference>
                                            <a href="javascript:;">删除</a>
                                        </template>
                                    </el-popconfirm>
                                </p>
                            </td>
                        </tr>
                        <tr v-if="cartStore.cartList.length === 0">
                            <td colspan="6">
                                <div class="cart-none">
                                    <el-empty description="购物车列表为空">
                                        <el-button type="primary">随便逛逛</el-button>
                                    </el-empty>
                                </div>
                            </td>
                        </tr>
                    </tbody>

                </table>
            </div>
            <!-- 操作栏 -->
            <div class="action">
                <div class="batch">
                    共 10 件商品,已选择 2 件,商品合计:
                    <span class="red">¥ 200.00 </span>
                </div>
                <div class="total">
                    <el-button size="large" type="primary">下单结算</el-button>
                </div>
            </div>
        </div>
    </div>
</template>

<style scoped lang="scss">
.xtx-cart-page {
    margin-top: 20px;

    .cart {
        background: #fff;
        color: #666;

        table {
            border-spacing: 0;
            border-collapse: collapse;
            line-height: 24px;

            th,
            td {
                padding: 10px;
                border-bottom: 1px solid #f5f5f5;

                &:first-child {
                    text-align: left;
                    padding-left: 30px;
                    color: #999;
                }
            }

            th {
                font-size: 16px;
                font-weight: normal;
                line-height: 50px;
            }
        }
    }

    .cart-none {
        text-align: center;
        padding: 120px 0;
        background: #fff;

        p {
            color: #999;
            padding: 20px 0;
        }
    }

    .tc {
        text-align: center;

        a {
            color: $xtxColor;
        }

        .xtx-numbox {
            margin: 0 auto;
            width: 120px;
        }
    }

    .red {
        color: $priceColor;
    }

    .green {
        color: $xtxColor;
    }

    .f16 {
        font-size: 16px;
    }

    .goods {
        display: flex;
        align-items: center;

        img {
            width: 100px;
            height: 100px;
        }

        >div {
            width: 280px;
            font-size: 16px;
            padding-left: 10px;

            .attr {
                font-size: 14px;
                color: #999;
            }
        }
    }

    .action {
        display: flex;
        background: #fff;
        margin-top: 20px;
        height: 80px;
        align-items: center;
        font-size: 16px;
        justify-content: space-between;
        padding: 0 30px;

        .xtx-checkbox {
            color: #999;
        }

        .batch {
            a {
                margin-left: 20px;
            }
        }

        .red {
            font-size: 18px;
            margin-right: 20px;
            font-weight: bold;
        }
    }

    .tit {
        color: #666;
        font-size: 16px;
        font-weight: normal;
        line-height: 50px;
    }

}
</style>

在这里插入图片描述

2. 列表购物车单选功能

核心思路:单选的核心思路就是始终把单选框的状态和Piniastore对应的状态保持同步

注意事项: v-model双向绑定指令不方便进行命令式的操作(因为后续还需要调用接口),所以把v-model回退到一般模式,也就是:model-value @change 的配合实现

// 单选功能
const singleCheck = (skuId, selected) => {
  // 通过skuId找到要修改的那一项 然后把它的selected修改为传过来的selected
  const item = cartList.value.find((item) => item.skuId === skuId)
  item.selected = selected
}
<!--cartList/index.vue-->
<script setup>
// 单选回调
const singleCheck = (i, selected) => {
  console.log(i, selected)
  // store cartList 数组 无法知道要修改谁的选中状态?
  // 除了selected补充一个用来筛选的参数 - skuId
  cartStore.singleCheck(i.skuId, selected)
}
</script>

  
<template>
  <td>
    <!-- 单选框 -->
    <el-checkbox :model-value="i.selected" @change="(selected) => singleCheck(i, selected)" />
  </td>
</template>

3. 列表购物车全选功能

基础思想

  • 全选状态决定单选框状态 - 遍历cartList把每一项的selected都设置为何全选框状态一致

  • 单选框状态决定全选状态 - 只有所有单选框的selected都为true, 全选框才为true

// 全选功能action
const allCheck = (selected) => {
  // 把cartList中的每一项的selected都设置为当前的全选框状态
  cartList.value.forEach(item => item.selected = selected)
}


// 是否全选计算属性
const isAll = computed(() => cartList.value.every((item) => item.selected))
<script setup>
const allCheck = (selected) => {
  cartStore.allCheck(selected)
}

</script>

  
<template>
  <!-- 全选框 -->
  <el-checkbox :model-value="cartStore.isAll" @change="allCheck" />
</template>

4. 列表购物车统计列表实现

下面的价格/件数,与之前计算的同理同理

// 3. 已选择数量
const selectedCount = computed(() => cartList.value.filter(item => item.selected).reduce((a, c) => a + c.count, 0))
// 4. 已选择商品价钱合计
const selectedPrice = computed(() => cartList.value.filter(item => item.selected).reduce((a, c) => a + c.count * c.price, 0))
 <div class="batch">共 {{ cartStore.allCount }} 件商品,已选择 {{ cartStore.selectedCount }} 件,商品合计:<span class="red">¥ {{ cartStore.selectedPrice }} </span>
</div>

5. 接口-加入购物车

在这里插入图片描述

步骤:

  • 找到加入购物车addCartaction,判断是否是登录状态(看token

在这里插入图片描述

  • 封装调用加入购物车接口

apis新增cart.js

import httpInstance from "@/utils/http"

//加入购物车
export const insertCartAPI = ({ skuId, count }) => {
    return httpInstance({
        url: '/member/cart',
        method: 'POST',
        data: {
            skuId,
            count
        }
    })
}

//获取最新的购物车列表
export const findNewCartListAPI = () => {
    return httpInstance({
        url: '/member/cart'
    })
}
  • 封装调用获取购物车列表接口

  • 用接口购物车列表去覆盖本地购物车列表

// 封装购物车模块

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { computed } from 'vue'
import { useUserStore } from './user'
import { insertCartAPI, findNewCartListAPI } from '@/apis/cart.js'


export const useCartStore = defineStore('cart', () => {
    const userStore = useUserStore()
    //用computed映射一下token,方便数据转换,响应式更新
    const isLogin = computed(() => userStore.userInfo.token)

    // 1. 定义state - cartList购物车列表
    const cartList = ref([])
    // 2. 定义action - addCart添加购物车
    const addCart = async (goods) => {
        //解构出来
        const { skuId, count } = goods
        if (isLogin.value) {
            //登录状态下
            //调用加入购物车接口
            await insertCartAPI({ skuId, count })
            //调用获取购物车列表接口
            const res = await findNewCartListAPI()
            //覆盖本地购物车
            cartList.value = res.result
        } else {
            console.log('添加', goods)
            // 添加购物车操作
            // 已添加过 - count + 1
            // 没有添加过 - 直接push
            // 思路:通过匹配传递过来的商品对象中的skuId能不能在cartList中找到,找到了就是添加过
            const item = cartList.value.find((item) => goods.skuId === item.skuId)
            if (item) {
                // 找到了
                item.count++
            } else {
                // 没找到
                cartList.value.push(goods)
            }
        }
    }

    // 删除购物车
    const delCart = async (skuId) => {
        // 思路:
        // 1. 找到要删除项的下标值 - splice
        // 2. 使用数组的过滤方法 - filter
        const idx = cartList.value.findIndex((item) => skuId === item.skuId)
        cartList.value.splice(idx, 1)
    }

    // 单选功能
    const singleCheck = (skuId, selected) => {
        // 通过skuId找到要修改的那一项 然后把它的selected修改为传过来的selected
        const item = cartList.value.find((item) => item.skuId === skuId)
        item.selected = selected
    }
    // 全选功能action
    const allCheck = (selected) => {
        // 把cartList中的每一项的selected都设置为当前的全选框状态
        cartList.value.forEach(item => item.selected = selected)
    }


    // 是否全选计算属性
    const isAll = computed(() => cartList.value.every((item) => item.selected))


    //计算购物车件数和总价格
    //总数
    const allCount = computed(() => cartList.value.reduce((a, c) => a + c.count, 0))
    //总价
    const allPrice = computed(() => cartList.value.reduce((a, c) => a + c.count * c.price, 0))
    // 3. 已选择数量
    const selectedCount = computed(() => cartList.value.filter(item => item.selected).reduce((a, c) => a + c.count, 0))
    // 4. 已选择商品价钱合计
    const selectedPrice = computed(() => cartList.value.filter(item => item.selected).reduce((a, c) => a + c.count * c.price, 0))
    return {
        cartList,
        allCount,
        allPrice,
        selectedCount,
        selectedPrice,
        addCart,
        delCart,
        singleCheck,
        allCheck
    }
}, {
    persist: true,
})

6. 接口-删除购物车

思路和 加入购物车 类似

封装接口

// 删除购物车
export const delCartAPI = (ids) => {
  return httpInstance({
    url: '/member/cart',
    method: 'DELETE',
    data: {
      ids
    }
  })
}

书写逻辑

  // 删除购物车
  const delCart = async (skuId) => {
    if (isLogin.value) {
      // 调用接口实现接口购物车中的删除功能
      await delCartAPI([skuId])
      //调用获取购物车列表接口
      const res = await findNewCartListAPI()
      //覆盖本地购物车
      cartList.value = res.result
    } else {
      // 思路:
      // 1. 找到要删除项的下标值 - splice
      // 2. 使用数组的过滤方法 - filter
      const idx = cartList.value.findIndex((item) => skuId === item.skuId)
      cartList.value.splice(idx, 1)
    }
  }

在这里插入图片描述

  • 优化

    由于更新列表都需要重复使用下面两行代码,我们抽象成一个action函数方便使用(虽然就两行代码,但我们学习的是这种思想,有些公司就对于代码的重复度有要求。)

 //获取最新的购物车列表
    const updateNewList = async () => {
        //调用获取购物车列表接口
        const res = await findNewCartListAPI()
        //覆盖本地购物车
        cartList.value = res.result
    }

使用的时候调用updateNewList就可以了

7. 退出登录-清空购物车数据

  • 清除购物车action,记得return出去
//清空购物车  stores/cartStore.js
    const clearCart = () => {
        cartList = []
    }
  • 退出登录时清除购物车
//退出登录,数据清空  stores/user.js
    const clearData = () => {
        //用户数据清空
        userInfo.value = {}
        //购物车清空
        cartStore.clearCart()
    }

在这里插入图片描述

8. 合并购物车到服务器(重要)

目的是让用户在非登录状态下的行为有效,别白操作一顿

  • 登录时调用合并购物车接口
//合并购物车    apis/cart.js
export const mergeCartAPI = (data) => {
    return httpInstance({
        url: '/member/cart/merge',
        method: 'post',
        data
    })
}
//stores/user.js
//合并购物车的操作 根据现有数组经过映射得到一个全新的数组使用map
        mergeCartAPI(cartStore.cartList.map(item => {
            return {
                skuId: item.skuId,
                selected: item.selected,
                count: item.count
            }
        }))
  • 获取最新的购物车列表

  • 覆盖本地购物车列表

 cartStore.updateNewList()

如何测试?非登录添加新商品,登录看network的接口有没有merge
在这里插入图片描述


结算

1. 路由配置和基础数据渲染

在这里插入图片描述
在这里插入图片描述

  • views/Cheakout/index.vue组件模板
<script setup>
const checkInfo = {}  // 订单对象
const curAddress = {}  // 地址对象

</script>

<template>
  <div class="xtx-pay-checkout-page">
    <div class="container">
      <div class="wrapper">
        <!-- 收货地址 -->
        <h3 class="box-title">收货地址</h3>
        <div class="box-body">
          <div class="address">
            <div class="text">
              <div class="none" v-if="!curAddress">您需要先添加收货地址才可提交订单。</div>
              <ul v-else>
                <li><span><i /><i />人:</span>{{ curAddress.receiver }}</li>
                <li><span>联系方式:</span>{{ curAddress.contact }}</li>
                <li><span>收货地址:</span>{{ curAddress.fullLocation }} {{ curAddress.address }}</li>
              </ul>
            </div>
            <div class="action">
              <el-button size="large" @click="toggleFlag = true">切换地址</el-button>
              <el-button size="large" @click="addFlag = true">添加地址</el-button>
            </div>
          </div>
        </div>
        <!-- 商品信息 -->
        <h3 class="box-title">商品信息</h3>
        <div class="box-body">
          <table class="goods">
            <thead>
              <tr>
                <th width="520">商品信息</th>
                <th width="170">单价</th>
                <th width="170">数量</th>
                <th width="170">小计</th>
                <th width="170">实付</th>
              </tr>
            </thead>
            <tbody>
              <tr v-for="i in checkInfo.goods" :key="i.id">
                <td>
                  <a href="javascript:;" class="info">
                    <img :src="i.picture" alt="">
                    <div class="right">
                      <p>{{ i.name }}</p>
                      <p>{{ i.attrsText }}</p>
                    </div>
                  </a>
                </td>
                <td>&yen;{{ i.price }}</td>
                <td>{{ i.price }}</td>
                <td>&yen;{{ i.totalPrice }}</td>
                <td>&yen;{{ i.totalPayPrice }}</td>
              </tr>
            </tbody>
          </table>
        </div>
        <!-- 配送时间 -->
        <h3 class="box-title">配送时间</h3>
        <div class="box-body">
          <a class="my-btn active" href="javascript:;">不限送货时间:周一至周日</a>
          <a class="my-btn" href="javascript:;">工作日送货:周一至周五</a>
          <a class="my-btn" href="javascript:;">双休日、假日送货:周六至周日</a>
        </div>
        <!-- 支付方式 -->
        <h3 class="box-title">支付方式</h3>
        <div class="box-body">
          <a class="my-btn active" href="javascript:;">在线支付</a>
          <a class="my-btn" href="javascript:;">货到付款</a>
          <span style="color:#999">货到付款需付5元手续费</span>
        </div>
        <!-- 金额明细 -->
        <h3 class="box-title">金额明细</h3>
        <div class="box-body">
          <div class="total">
            <dl>
              <dt>商品件数:</dt>
              <dd>{{ checkInfo.summary?.goodsCount }}件</dd>
            </dl>
            <dl>
              <dt>商品总价:</dt>
              <dd>¥{{ checkInfo.summary?.totalPrice.toFixed(2) }}</dd>
            </dl>
            <dl>
              <dt><i></i>费:</dt>
              <dd>¥{{ checkInfo.summary?.postFee.toFixed(2) }}</dd>
            </dl>
            <dl>
              <dt>应付总额:</dt>
              <dd class="price">{{ checkInfo.summary?.totalPayPrice.toFixed(2) }}</dd>
            </dl>
          </div>
        </div>
        <!-- 提交订单 -->
        <div class="submit">
          <el-button type="primary" size="large" >提交订单</el-button>
        </div>
      </div>
    </div>
  </div>
  <!-- 切换地址 -->
  <!-- 添加地址 -->
</template>

<style scoped lang="scss">
.xtx-pay-checkout-page {
  margin-top: 20px;

  .wrapper {
    background: #fff;
    padding: 0 20px;

    .box-title {
      font-size: 16px;
      font-weight: normal;
      padding-left: 10px;
      line-height: 70px;
      border-bottom: 1px solid #f5f5f5;
    }

    .box-body {
      padding: 20px 0;
    }
  }
}

.address {
  border: 1px solid #f5f5f5;
  display: flex;
  align-items: center;

  .text {
    flex: 1;
    min-height: 90px;
    display: flex;
    align-items: center;

    .none {
      line-height: 90px;
      color: #999;
      text-align: center;
      width: 100%;
    }

    >ul {
      flex: 1;
      padding: 20px;

      li {
        line-height: 30px;

        span {
          color: #999;
          margin-right: 5px;

          >i {
            width: 0.5em;
            display: inline-block;
          }
        }
      }
    }

    >a {
      color: $xtxColor;
      width: 160px;
      text-align: center;
      height: 90px;
      line-height: 90px;
      border-right: 1px solid #f5f5f5;
    }
  }

  .action {
    width: 420px;
    text-align: center;

    .btn {
      width: 140px;
      height: 46px;
      line-height: 44px;
      font-size: 14px;

      &:first-child {
        margin-right: 10px;
      }
    }
  }
}

.goods {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;

  .info {
    display: flex;
    text-align: left;

    img {
      width: 70px;
      height: 70px;
      margin-right: 20px;
    }

    .right {
      line-height: 24px;

      p {
        &:last-child {
          color: #999;
        }
      }
    }
  }

  tr {
    th {
      background: #f5f5f5;
      font-weight: normal;
    }

    td,
    th {
      text-align: center;
      padding: 20px;
      border-bottom: 1px solid #f5f5f5;

      &:first-child {
        border-left: 1px solid #f5f5f5;
      }

      &:last-child {
        border-right: 1px solid #f5f5f5;
      }
    }
  }
}

.my-btn {
  width: 228px;
  height: 50px;
  border: 1px solid #e4e4e4;
  text-align: center;
  line-height: 48px;
  margin-right: 25px;
  color: #666666;
  display: inline-block;

  &.active,
  &:hover {
    border-color: $xtxColor;
  }
}

.total {
  dl {
    display: flex;
    justify-content: flex-end;
    line-height: 50px;

    dt {
      i {
        display: inline-block;
        width: 2em;
      }
    }

    dd {
      width: 240px;
      text-align: right;
      padding-right: 70px;

      &.price {
        font-size: 20px;
        color: $priceColor;
      }
    }
  }
}

.submit {
  text-align: right;
  padding: 60px;
  border-top: 1px solid #f5f5f5;
}

.addressWrapper {
  max-height: 500px;
  overflow-y: auto;
}

.text {
  flex: 1;
  min-height: 90px;
  display: flex;
  align-items: center;

  &.item {
    border: 1px solid #f5f5f5;
    margin-bottom: 10px;
    cursor: pointer;

    &.active,
    &:hover {
      border-color: $xtxColor;
      background: lighten($xtxColor, 50%);
    }

    >ul {
      padding: 10px;
      font-size: 14px;
      line-height: 30px;
    }
  }
}
</style>
  • 配置路由,引入组件配置二级路由
{
	path: 'checkout',
	component: Checkout
},
  • 给按钮绑定事件,实现跳转
 <el-button size="large" type="primary" @click="$router.push('/checkout')">下单结算</el-button>
  • 封装接口apis/checkout.js
import httpInstance from "@/utils/http";

//获取结算信息
export const getCheckoutInfoAPI = () => {
    return httpInstance({
        url: '/member/order/pre'
    })
}
  • 获取数据,渲染数据(默认地址、商品列表、统计数据)
<!-- 订单页 -->
<script setup>
import { getCheckoutInfoAPI } from '@/apis/checkout.js'
import { onMounted, ref } from 'vue'
const checkInfo = ref({})  // 订单对象
const curAddress = ref({})  // 地址对象
const getCheckoutInfo = async () => {

    //获取结算数据
    const res = await getCheckoutInfoAPI()
    console.log(res)
    checkInfo.value = res.result

    //适配默认地址,根据isDefault === 0筛选,使用filter或find筛选都可以
    const item = checkInfo.value.userAddresses.find(item => item.isDefault === 0)
    curAddress.value = item
}
onMounted(() => getCheckoutInfo())
</script>

<template>
    <div class="xtx-pay-checkout-page">
        <div class="container">
            <div class="wrapper">
                <!-- 收货地址 -->
                <h3 class="box-title">收货地址</h3>
                <div class="box-body">
                    <div class="address">
                        <div class="text">
                            <div class="none" v-if="!curAddress">您需要先添加收货地址才可提交订单。</div>
                            <ul v-else>
                                <li><span><i /><i />人:</span>{{ curAddress.receiver }}</li>
                                <li><span>联系方式:</span>{{ curAddress.contact }}</li>
                                <li><span>收货地址:</span>{{ curAddress.fullLocation }} {{ curAddress.address }}</li>
                            </ul>
                        </div>
                        <div class="action">
                            <el-button size="large" @click="toggleFlag = true">切换地址</el-button>
                            <el-button size="large" @click="addFlag = true">添加地址</el-button>
                        </div>
                    </div>
                </div>
                <!-- 商品信息 -->
                <h3 class="box-title">商品信息</h3>
                <div class="box-body">
                    <table class="goods">
                        <thead>
                            <tr>
                                <th width="520">商品信息</th>
                                <th width="170">单价</th>
                                <th width="170">数量</th>
                                <th width="170">小计</th>
                                <th width="170">实付</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="i in checkInfo.goods" :key="i.id">
                                <td>
                                    <a href="javascript:;" class="info">
                                        <img :src="i.picture" alt="">
                                        <div class="right">
                                            <p>{{ i.name }}</p>
                                            <p>{{ i.attrsText }}</p>
                                        </div>
                                    </a>
                                </td>
                                <td>&yen;{{ i.price }}</td>
                                <td>{{ i.price }}</td>
                                <td>&yen;{{ i.totalPrice }}</td>
                                <td>&yen;{{ i.totalPayPrice }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                <!-- 配送时间 -->
                <h3 class="box-title">配送时间</h3>
                <div class="box-body">
                    <a class="my-btn active" href="javascript:;">不限送货时间:周一至周日</a>
                    <a class="my-btn" href="javascript:;">工作日送货:周一至周五</a>
                    <a class="my-btn" href="javascript:;">双休日、假日送货:周六至周日</a>
                </div>
                <!-- 支付方式 -->
                <h3 class="box-title">支付方式</h3>
                <div class="box-body">
                    <a class="my-btn active" href="javascript:;">在线支付</a>
                    <a class="my-btn" href="javascript:;">货到付款</a>
                    <span style="color:#999">货到付款需付5元手续费</span>
                </div>
                <!-- 金额明细 -->
                <h3 class="box-title">金额明细</h3>
                <div class="box-body">
                    <div class="total">
                        <dl>
                            <dt>商品件数:</dt>
                            <dd>{{ checkInfo.summary?.goodsCount }}件</dd>
                        </dl>
                        <dl>
                            <dt>商品总价:</dt>
                            <dd>¥{{ checkInfo.summary?.totalPrice.toFixed(2) }}</dd>
                        </dl>
                        <dl>
                            <dt><i></i>费:</dt>
                            <dd>¥{{ checkInfo.summary?.postFee.toFixed(2) }}</dd>
                        </dl>
                        <dl>
                            <dt>应付总额:</dt>
                            <dd class="price">{{ checkInfo.summary?.totalPayPrice.toFixed(2) }}</dd>
                        </dl>
                    </div>
                </div>
                <!-- 提交订单 -->
                <div class="submit">
                    <el-button type="primary" size="large">提交订单</el-button>
                </div>
            </div>
        </div>
    </div>
    <!-- 切换地址 -->
    <!-- 添加地址 -->
</template>

<style scoped lang="scss">
.xtx-pay-checkout-page {
    margin-top: 20px;

    .wrapper {
        background: #fff;
        padding: 0 20px;

        .box-title {
            font-size: 16px;
            font-weight: normal;
            padding-left: 10px;
            line-height: 70px;
            border-bottom: 1px solid #f5f5f5;
        }

        .box-body {
            padding: 20px 0;
        }
    }
}

.address {
    border: 1px solid #f5f5f5;
    display: flex;
    align-items: center;

    .text {
        flex: 1;
        min-height: 90px;
        display: flex;
        align-items: center;

        .none {
            line-height: 90px;
            color: #999;
            text-align: center;
            width: 100%;
        }

        >ul {
            flex: 1;
            padding: 20px;

            li {
                line-height: 30px;

                span {
                    color: #999;
                    margin-right: 5px;

                    >i {
                        width: 0.5em;
                        display: inline-block;
                    }
                }
            }
        }

        >a {
            color: $xtxColor;
            width: 160px;
            text-align: center;
            height: 90px;
            line-height: 90px;
            border-right: 1px solid #f5f5f5;
        }
    }

    .action {
        width: 420px;
        text-align: center;

        .btn {
            width: 140px;
            height: 46px;
            line-height: 44px;
            font-size: 14px;

            &:first-child {
                margin-right: 10px;
            }
        }
    }
}

.goods {
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;

    .info {
        display: flex;
        text-align: left;

        img {
            width: 70px;
            height: 70px;
            margin-right: 20px;
        }

        .right {
            line-height: 24px;

            p {
                &:last-child {
                    color: #999;
                }
            }
        }
    }

    tr {
        th {
            background: #f5f5f5;
            font-weight: normal;
        }

        td,
        th {
            text-align: center;
            padding: 20px;
            border-bottom: 1px solid #f5f5f5;

            &:first-child {
                border-left: 1px solid #f5f5f5;
            }

            &:last-child {
                border-right: 1px solid #f5f5f5;
            }
        }
    }
}

.my-btn {
    width: 228px;
    height: 50px;
    border: 1px solid #e4e4e4;
    text-align: center;
    line-height: 48px;
    margin-right: 25px;
    color: #666666;
    display: inline-block;

    &.active,
    &:hover {
        border-color: $xtxColor;
    }
}

.total {
    dl {
        display: flex;
        justify-content: flex-end;
        line-height: 50px;

        dt {
            i {
                display: inline-block;
                width: 2em;
            }
        }

        dd {
            width: 240px;
            text-align: right;
            padding-right: 70px;

            &.price {
                font-size: 20px;
                color: $priceColor;
            }
        }
    }
}

.submit {
    text-align: right;
    padding: 60px;
    border-top: 1px solid #f5f5f5;
}

.addressWrapper {
    max-height: 500px;
    overflow-y: auto;
}

.text {
    flex: 1;
    min-height: 90px;
    display: flex;
    align-items: center;

    &.item {
        border: 1px solid #f5f5f5;
        margin-bottom: 10px;
        cursor: pointer;

        &.active,
        &:hover {
            border-color: $xtxColor;
            background: lighten($xtxColor, 50%);
        }

        >ul {
            padding: 10px;
            font-size: 14px;
            line-height: 30px;
        }
    }
}
</style>

在这里插入图片描述

2. 地址切换-打开弹框交互实现

在这里插入图片描述

  • 打开弹框,回显用户可选地址列表

弹框组件:checkout/index.vue

<!-- 切换地址 -->
<el-dialog title="切换收货地址" width="30%" center>
  <div class="addressWrapper">
    <div class="text item" v-for="item in checkInfo.userAddresses"  :key="item.id">
      <ul>
      <li><span><i /><i />人:</span>{{ item.receiver }} </li>
      <li><span>联系方式:</span>{{ item.contact }}</li>
      <li><span>收货地址:</span>{{ item.fullLocation + item.address }}</li>
      </ul>
    </div>
  </div>
  <template #footer>
    <span class="dialog-footer">
      <el-button>取消</el-button>
      <el-button type="primary">确定</el-button>
    </span>
  </template>
</el-dialog>

绑定数据showDialog,点击按钮控制弹框打开关闭,渲染可选地址列表

//控制弹框打开
const showDialog = ref(false)
...
<el-dialog title="切换收货地址" width="30%" center v-model="showDialog">
...
...
<el-button size="large" @click="showDialog = true">切换地址</el-button>
...

在这里插入图片描述

3. 切换地址-地址激活交互实现

在这里插入图片描述

这个需求是通用类需求,学习以后可以多多的用

绑定事件,拿到地址这一项

 <div class="text item" @click="switchAddress(item)" v-for="item in checkInfo.userAddresses" :key="item.id">
//激活拿到这个对象
const activeAddress = ref({})
const switchAddress = (item) => {
    //将拿到的这个对象记录下来
    activeAddress.value = item
}

激活样式,判断条件是激活对象id===当前项id

 :class="{ active: activeAddress.id === item.id }"

给确认按钮绑定事件,新地址覆盖原地址

 <el-button type="primary" @click="addressConfirm">确定</el-button>
//地址确认
const addressConfirm = () => {
    //覆盖当前的地址
    curAddress.value = activeAddress.value
    //关闭弹层
    showDialog.value = false
    //当前地址置为初始值
    activeAddress.value = {}
}

在这里插入图片描述

4. 生成订单功能实现

购物车清空

在这里插入图片描述

  • 准备 支付 路由 views/Pay/index.vue
<script setup>
const payInfo = {}
</script>


<template>
  <div class="xtx-pay-page">
    <div class="container">
      <!-- 付款信息 -->
      <div class="pay-info">
        <span class="icon iconfont icon-queren2"></span>
        <div class="tip">
          <p>订单提交成功!请尽快完成支付。</p>
          <p>支付还剩 <span>24分30秒</span>, 超时后将取消订单</p>
        </div>
        <div class="amount">
          <span>应付总额:</span>
          <span>¥{{ payInfo.payMoney?.toFixed(2) }}</span>
        </div>
      </div>
      <!-- 付款方式 -->
      <div class="pay-type">
        <p class="head">选择以下支付方式付款</p>
        <div class="item">
          <p>支付平台</p>
          <a class="btn wx" href="javascript:;"></a>
          <a class="btn alipay" :href="payUrl"></a>
        </div>
        <div class="item">
          <p>支付方式</p>
          <a class="btn" href="javascript:;">招商银行</a>
          <a class="btn" href="javascript:;">工商银行</a>
          <a class="btn" href="javascript:;">建设银行</a>
          <a class="btn" href="javascript:;">农业银行</a>
          <a class="btn" href="javascript:;">交通银行</a>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.xtx-pay-page {
  margin-top: 20px;
}

.pay-info {

  background: #fff;
  display: flex;
  align-items: center;
  height: 240px;
  padding: 0 80px;

  .icon {
    font-size: 80px;
    color: #1dc779;
  }

  .tip {
    padding-left: 10px;
    flex: 1;

    p {
      &:first-child {
        font-size: 20px;
        margin-bottom: 5px;
      }

      &:last-child {
        color: #999;
        font-size: 16px;
      }
    }
  }

  .amount {
    span {
      &:first-child {
        font-size: 16px;
        color: #999;
      }

      &:last-child {
        color: $priceColor;
        font-size: 20px;
      }
    }
  }
}

.pay-type {
  margin-top: 20px;
  background-color: #fff;
  padding-bottom: 70px;

  p {
    line-height: 70px;
    height: 70px;
    padding-left: 30px;
    font-size: 16px;

    &.head {
      border-bottom: 1px solid #f5f5f5;
    }
  }

  .btn {
    width: 150px;
    height: 50px;
    border: 1px solid #e4e4e4;
    text-align: center;
    line-height: 48px;
    margin-left: 30px;
    color: #666666;
    display: inline-block;

    &.active,
    &:hover {
      border-color: $xtxColor;
    }

    &.alipay {
      background: url(https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7b6b02396368c9314528c0bbd85a2e06.png) no-repeat center / contain;
    }

    &.wx {
      background: url(https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/c66f98cff8649bd5ba722c2e8067c6ca.jpg) no-repeat center / contain;
    }
  }
}
</style>
  • 路由,二级
{
	path: 'pay',
	component: Pay
}
  • 接口封装
// 创建订单
export const createOrderAPI = (data) => {
    return httpInstance({
        url: '/member/order',
        method: 'POST',
        data
    })
}
  • checkout/index.vue引入,给 提交订单 绑定事件,调用接口传参,从res获得id,使用orderId记录,然后路由传参。
<el-button type="primary" size="large" @click="createOrder">提交订单</el-button>
// 创建订单
const createOrder = async () => {
  const res = await createOrderAPI({
    deliveryTimeType: 1,
    payType: 1,
    payChannel: 1,
    buyerMessage: '',
    goods: checkInfo.value.goods.map(item => {
      return {
        skuId: item.skuId,
        count: item.count
      }
    }),
    addressId: curAddress.value.id
  })
  const orderId = res.result.id
  router.push({
    path: '/pay',
    query: {
      id: orderId
    }
  })
}

在这里插入图片描述

更新购物车


支付

1. 渲染基础数据

在这里插入图片描述

支付页有俩个关键数据,一个是要支付的钱数,一个是倒计时数据(超时不支付商品释放)

  • 获取并调用订单详情的接口apis/pay.js
import httpInstance from '@/utils/http'

export const getOrderAPI = (id) => {
    return httpInstance({
        url: `/member/order/${id}`
    })
}
<script setup>
import { getOrderAPI } from '@/apis/pay.js'
import { onMounted, ref } from 'vue'
const payInfo = ref({})  //支付信息
const getPayInfo = async () => {
    //获取支付详情
    const res = await getOrderAPI(route.query.id)
    payInfo.value = res.result

    onMounted(() => getPayInfo())
}
</script>

2. 实现支付功能

在这里插入图片描述

支付携带参数:放到Pay/index.vue中,绑定给按钮即可

// 支付地址
const baseURL = 'http://pcapi-xiaotuxian-front-devtest.itheima.net/'
const backURL = 'http://127.0.0.1:5173/paycallback'
const redirectUrl = encodeURIComponent(backURL)
const payUrl = `${baseURL}pay/aliPay?orderId=${route.query.id}&redirect=${redirectUrl}`

绑定:

<!-- 微信 -->
<a class="btn wx" href="javascript:;"></a>
<!-- 支付宝 -->
<a class="btn alipay" :href="payUrl"></a>

在这里插入图片描述

支付宝沙箱账号信息:

账号jfjbwb4477@sandbox.com
登录密码111111
支付密码111111

应该是支付不了,但是正常跳转没问题

3. 支付结果展示

没法支付了,这个模块没法验证了,那我们来看看具体的写法吧,以后应该会用到

在这里插入图片描述

  • Pay/PayBack.vue
<script setup>

</script>


<template>
  <div class="xtx-pay-page">
    <div class="container">
      <!-- 支付结果 -->
      <div class="pay-result">
        <span class="iconfont icon-queren2 green"></span>
        <span class="iconfont icon-shanchu red"></span>
        <p class="tit">支付成功</p>
        <p class="tip">我们将尽快为您发货,收货期间请保持手机畅通</p>
        <p>支付方式:<span>支付宝</span></p>
        <p>支付金额:<span>¥200.00</span></p>
        <div class="btn">
          <el-button type="primary" style="margin-right:20px">查看订单</el-button>
          <el-button>进入首页</el-button>
        </div>
        <p class="alert">
          <span class="iconfont icon-tip"></span>
          温馨提示:小兔鲜儿不会以订单异常、系统升级为由要求您点击任何网址链接进行退款操作,保护资产、谨慎操作。
        </p>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.pay-result {
  padding: 100px 0;
  background: #fff;
  text-align: center;
  margin-top: 20px;

  >.iconfont {
    font-size: 100px;
  }

  .green {
    color: #1dc779;
  }

  .red {
    color: $priceColor;
  }

  .tit {
    font-size: 24px;
  }

  .tip {
    color: #999;
  }

  p {
    line-height: 40px;
    font-size: 16px;
  }

  .btn {
    margin-top: 50px;
  }

  .alert {
    font-size: 12px;
    color: #999;
    margin-top: 50px;
  }
}
</style>
  • 路由配置,二级,path不是随便写的昂
{
	path: 'paycallback',
	component: PayBack
}
  • 根据支付结果payResult适配支付状态
 <!-- 支付图标 -->
<span class="iconfont icon-queren2 green" v-if="$route.query.payResult === 'true'"></span>
<span class="iconfont icon-shanchu red" v-else></span>
<p class="tit">支付{{ $route.query.payResult === 'true' ? '成功' : '失败' }}</p>
<!--PayBack.vue--> 
<script setup>
import { getOrderAPI } from '@/apis/pay'
import { onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const orderInfo = ref({})

//获取订单信息
const getOrderInfo = async () => {
    const res = await getOrderAPI(route.query.orderId)
    orderInfo.value = res.result
}

onMounted(() => getOrderInfo())
</script>

 <p>支付金额:<span>¥{{ orderInfo.payMoney?.toFixed(2) }}</span></p>

4. 封装倒计数函数

在这里插入图片描述

编写一个函数 useCountDown 可以把秒数格式化为倒计时的显示状态

formatTime为显示的倒计时时间

start是倒计时启动函数,调用时可以设置初始值并且开始倒计时

步骤

  • 编写函数框架,确定参数和返回值
  • 编写核心倒计时逻辑实现基础倒计时
  • 实现格式化

装一个dayjs插件:npm i dayjs

//comppsables/useCountDown.js
// 封装倒计时逻辑函数
import { computed, onUnmounted, ref } from 'vue'
import dayjs from 'dayjs'

export const useCountDown = () => {
    // 1. 响应式的数据
    let timer = null
    const time = ref(0)

    // 格式化时间 为 xx分xx秒
    const formatTime = computed(() => dayjs.unix(time.value).format('mm分ss秒'))

    // 2. 开启倒计时的函数
    const start = (currentTime) => {
        // 开始倒计时的逻辑
        // 核心逻辑的编写:每隔1s就减一
        time.value = currentTime
        timer = setInterval(() => {
            time.value--
        }, 1000)
    }

    // 组件销毁时清除定时器
    onUnmounted(() => {
        timer && clearInterval(timer)
    })
    return {
        formatTime,
        start
    }
}

<!--Pay/index.vue-->
<script>
import { useCountDown } from '@/composables/useCountDown.js'
// 倒计时
const { start, formatTime } = useCountDown()

// 获取订单数据
const route = useRoute()
const payInfo = ref({})
const getPayInfo = async () => {
    const res = await getOrderAPI(route.query.id)
    payInfo.value = res.result
    //初始化倒计数秒数
    start(res.result.countdown)
}
onMounted(() => getPayInfo())

//跳转支付
// 携带订单id以及回调地址跳转到支付地址(get)
// 支付地址
const baseURL = 'http://pcapi-xiaotuxian-front-devtest.itheima.net/'
const backURL = 'http://127.0.0.1:5173/paycallback'
const redirectUrl = encodeURIComponent(backURL)
const payUrl = `${baseURL}pay/aliPay?orderId=${route.query.id}&redirect=${redirectUrl}`
</script>

 <p>支付还剩 <span>{{ formatTime }}</span>, 超时后将取消订单</p>

在这里插入图片描述

接口老是崩掉emmm


小结

功能有些杂,代码书写的位置要仔细斟酌以便后期维护。

看网络请求的时候,要记得打开检查左上角的录制网络日志不然不显示(默认是开的),我不知道点哪了给关了,找这个bug找半天。
祝大家学习顺利
在这里插入图片描述

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

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

相关文章

【渗透测试】|文件上传

1、安装使用蚁剑 https://blog.csdn.net/weixin_42474304/article/details/116376746 1、登陆dvwa,进入初级文件上传&#xff0c;上传一句话木马文件cmd.php&#xff0c; //cmd.php <?php eval($_POST[ccit]); ?> //eval: 执行命令的函数 //ccit:一句话木马文件的参数…

刷代码随想录有感(83):贪心算法——最大子数组和

题干&#xff1a; 代码&#xff1a; class Solution { public:int maxSubArray(vector<int>& nums) {int res INT_MIN;int count 0;for(int i 0; i < nums.size(); i){count nums[i];if(count > res) res count;if(count < 0)count 0;}return res;} …

解决Android studio 一直提示下载gradle-xxx-all.zip问题

今天用AndroidStdiod打开一个新工程的时候&#xff0c;发现项目一直卡在正在下载gradle-xxx-all.zip的任务上&#xff0c;网络出奇的慢&#xff0c;即使配了VPN也无济于事&#xff0c;于是按照以往经验&#xff1a;将gradle-xxx-all.zip下载到.gradle\gradle\wrapper\dists目录…

2024年3月电子学会青少年软件编程 中小学生Python编程等级考试一级真题解析(选择题)

2024年3月Python编程等级考试一级真题解析 选择题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1、下列哪个命令&#xff0c;可以将2024转换成2024呢 A、str(2024) B、int(2024) C、float(2024) D、bool(2024) 答案&#xff1a;A 考点分析&…

【Linux】Linux环境基础开发工具_2

文章目录 四、Linux环境基础开发工具2. vimvim的常见模式 未完待续 四、Linux环境基础开发工具 2. vim vim 是Linux下的一款 多模式编辑器 &#xff0c;可以用来写代码&#xff0c;是 vi 的升级版。 此时无法输入&#xff0c;需要切换模式。 如上图&#xff0c;i 就是切换成…

数据库学习笔记1-数据库实验1

文章目录 创建表格的时候出现的一些错误查询所有的表格实验一查询单个表格分块修改大学数据库表格创建大学数据库表格系课程教师课程段授课学生选课注意吐槽 修改大学数据库表格2&#xff08;英文版本&#xff09;abcde 自建项目-在线书店数据库 创建表格的时候出现的一些错误 …

【ONE·Git || 基本用法入门】

总言 主要内容&#xff1a;主要介绍Git中常用的指令。   PS&#xff1a;多人协作与企业开发模型使用&#xff0c;此部分内容不作博文总结。             文章目录 总言1、初识Git1.1、版本控制器1.2、git安装 2、基本操作2.1、Git本地仓库2.1.1、创建Git本地仓库&…

C++【缺省参数|函数重载|引用】

目录 1 缺省参数 1.1 全缺省 1.2 半缺省 注意 1.3 应用 2 函数重载 函数重载的概念 1、参数类型不同 2、参数个数不同 3、参数类型顺序不同 3 引用 3.1 引用概念 3.2 引用特性 3.3 常引用 3.4 使用场景 3.5 传值、传引用效率比较 3.6 引用和指针的区别 1 缺…

RestTemplet 自定义消息转换器总结

在RestTemplet 请求中&#xff0c;请求发送一个 HTTP 请求时&#xff0c;RestTemplet 会根据请求中的内容类型&#xff08;Content-Type&#xff09;选择合适的 HttpMessageConverter 来处理请求体的数据。同样地&#xff0c;当服务器返回一个 HTTP 响应时&#xff0c;RestTemp…

上位机图像处理和嵌入式模块部署(f103 mcu中main入口函数误解)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 学习stm32代码的时候&#xff0c;关于汇编文件&#xff0c;大家一般都会参考官方给出的汇编文件。通常情况下&#xff0c;不会自己去写汇编文件。特…

决策树模型-预测用户是否购买某母婴产品

1&#xff0c;场景描述 假设我们是京东的数据分析师&#xff0c;负责分析母婴产品的购买行为。我们想预测用户是否会购买一款新上线的母婴产品。为了进行预测&#xff0c;我们将利用用户的历史购买数据、浏览行为和其他特征&#xff0c;通过决策树模型进行分析&#xff0c;并提…

全球市值最高的能源公司沙特阿美股份拟出售,筹集百亿美元

KlipC报道&#xff1a;据5月28日市场消息&#xff0c;沙特政府可能最快会在本周宣布拟出售国营石油公司沙特阿美股份&#xff0c;筹集100亿-200亿美元。 沙特阿美是世界最大的石油生产商&#xff0c;2019年在沙特证交所上市。沙特的经济高度依赖石油出口。此前&#xff0c;受石…

Vue2基本创建项目

简单版项目初始化 新建一个vue2 官网文档&#xff1a;介绍 — Vue.js 先确保下载了vue的脚手架 npm install -g vue-cli npm install -g vue/cli --force vue -V 创建项目 vue create 自己起个名字 选择自己选择特性 选择&#xff1a; Babel&#xff1a;他可以将我们写…

算法的时间复杂度(详解)

前言&#xff1a; 算法(Algorithm):就是定义良好的计算过程&#xff0c;他取一个或一组的值为输入&#xff0c;并产生出一个或一组值作为 输出。简单来说算法就是一系列的计算步骤&#xff0c;用来将输入数据转化成输出结果 一、算法效率 1.1 如何衡量一个算法的好坏 如何衡…

人工智能初识

&#x1f31e;欢迎来到人工智能基础的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年5月1…

小程序内的分包与数据共享

一:数据共享 小程序内的数据共享和vue当中不一样,vue当中的vue实例可以使得所有的组件都能this.store 但是小程序它只有page对象,和组件实例对象.对于vue而言,vue实例可以使得添加的组件都有. 但是page对象页面对象,不能使得页面内部有.只能使得这个页面内能访问.vue实例,会…

微信聊天内容怎么监控? | 三款可以监控电脑微信聊天记录的软件大盘点

你是否听说过监控微信呢&#xff1f; 有时出于特定需求&#xff0c;比如家长对孩子上网行为的关心&#xff0c;或者企业对员工工作效率的监控&#xff0c;可能需要了解某些情况下的微信聊天记录。 但请注意&#xff0c;任何未经授权的监控行为都是违法的&#xff0c;并且可能…

使用C语言实现学生信息管理系统

前言 在我们实现学生信息管理系统的过程中&#xff0c;我们几乎会使用到C语言最常用最重要的知识&#xff0c;对于刚学习完C语言的同学来说是一次很好的巩固机会&#xff0c;其中还牵扯到数据结果中链表的插入和删除内容。 实现学生信息管理系统 文件的创建与使用 对于要实现…

【国产中颖】SH79F9202U单片机驱动LCD段码液晶学习笔记

1. 引言 因新公司之前液晶数显表产品单片机一直用的是 C51单片机(SH79F9202U9)&#xff0c;本人之前没有接触过这款单片机&#xff0c;为了维护老产品不得不重新研究研究这款单片机。 10位ADC LCD的增强型8051微控制器 SH79F9202是一种高速高效率8051可兼容单片机。在同样振…

5G工厂长啥样

5G工厂是一种新型的工业互联网基础设施&#xff0c;利用5G为代表的新一代信息通信技术集成&#xff0c;打造新型工业互联网基础设施。在5G工厂中&#xff0c;自动化和智能化设备广泛使用&#xff0c;高度互联的工厂网络得以实现&#xff0c;远程监控和管理成为可能&#xff0c;…