小程序-购物车-基于SKU电商规格组件实现

news2024/11/15 19:50:07
SKU 概念: 存货单位( Stock Keeping Unit ), 库存 管理的最小可用单元,通常称为“单品”。
SKU 常见于电商领域,对于前端工程师而言,更多关注 SKU 算法 ,基于后端的 SKU 数据 渲染页面 实现交互

SKU 模块 - 下载 SKU 插件

DCloud 插件市场  是 uni-app 官方插件生态集中地,有数千款插件

使用SKU插件:

组件安装到自己的项目

注意事项:项目进行 git 提交时会校验文件,可添加 /* eslint-disable */  禁用检查

<script>
/* eslint-disable */
// 省略组件源代码
</script>

打开购物车弹框,渲染商品信息   goods.vue

<!-- SKU 弹窗组件 -->

  <vk-data-goods-sku-popup v-model="isShowSku" :localdata="localdata" />

// 是否显示 SKU 组件

const isShowSku = ref(false)

// 商品信息

const localdata = ref({} as SkuPopupLocaldata)

//  渲染商品信息

// 获取商品详情信息

const goods = ref<GoodsResult>()

const getGoodsByIdData = async () => {

  const res = await getGoodsByIdAPI(query.id)

  goods.value = res.result

  // SKU 组件所需格式

  localdata.value = {

    _id: res.result.id,

    name: res.result.name,

    goods_thumb: res.result.mainPictures[0],

    spec_list: res.result.specs.map((v) => {

      return {

        name: v.name,

        list: v.values,

      }

    }),

    sku_list: res.result.skus.map((v) => {

      return {

        _id: v.id,

        goods_id: res.result.id,

        goods_name: res.result.name,

        image: v.picture,

        price: v.price * 100, // 注意:需要乘以 100

        stock: v.inventory,

        sku_name_arr: v.specs.map((vv) => vv.valueName),

      }

    }),

  }

}

打开sku 弹窗       渲染商品

打开SKU弹窗  =》 设置按钮模式    =》 微调组件样式

<!-- SKU 弹窗组件 -->

  <vk-data-goods-sku-popup

    v-model="isShowSku"

    :localdata="localdata"

    :mode="mode"

    add-cart-background-color="#ffa868"

    buy-now-background-color="#27ba98"

    :active-style="{

      color: '#27ba9b',

      borderColor: '#27ba9b',

      backgroundCColor: '#e9f8f5',

    }"

  />

// mode  设置按钮模式

// add-cart-background-color   设置即入购物车按钮背景色

// buy-now-background-color   设置立即购买按钮背景色

// :active-style  选择商品规格时的激活样式

// 按钮模式       枚举

enum SkuMode {

  Both = 1, // 购物车和立即购买都显示

  Cart = 2, // 只显示购物车

  Buy = 3, // 只显示立即购买

}

const mode = ref<SkuMode>(SkuMode.Both)

// 打开sku 弹窗 修改按钮模式

const openSkuPopup = (val: SkuMode) => {

  // 显示sku组件

  isShowSku.value = true

  // 修改按钮模式

  mode.value = val

}

<view class="item arrow" @tap="openSkuPopup(SkuMode.Both)">

          <text class="label">选择</text>

          <text class="text ellipsis"> 请选择商品规格 </text>

</view>

<view class="buttons">

      <view class="addcart" @tap="openSkuPopup(SkuMode.Cart)"> 加入购物车 </view>

      <view class="buynow" @tap="openSkuPopup(SkuMode.Buy)"> 立即购买 </view>

</view>

加入购物车事件        加入购物车在商品详情页面       goods.vue

<!-- SKU 弹窗组件 -->

  <vk-data-goods-sku-popup

    v-model="isShowSku"

    :localdata="localdata"

    :mode="mode"

    add-cart-background-color="#ffa868"

    buy-now-background-color="#27ba9b"

    ref="skuPopupRef"

    :actived-style="{

      color: '#27BA9B',

      borderColor: '#27BA9B',

      backgroundColor: '#E9F8F5',

    }"

    @add-cart="onAddCart"

  />

// 加入购物车事件

const onAddCart = (e: SkuPopupEvent) => {

  console.log(e)

}

控制台打印数据

封装购物车接口:cart.ts

1、加入购物车接口封装

import { http } from "@/utils/http"

/**

 * 加入购物车

 * @param data 请求体参数

 * @returns

 */

export const postMemberCartAPI = (data: { skuId: string; count: number}) => {

  return http({

    method: 'POST',

    url: '/member/cart',

    data,

  })

}

完善商品详情页面的加入购物车功能

// 加入购物车事件

const onAddCart = async (e: SkuPopupEvent) => {

  console.log(e)

  await postMemberCartAPI({ skuId: e._id, count: e.buy_num })

  uni.showToast({ icon: 'success', title: '已加入购物车' })

  // 关闭弹窗

  isShowSku.value = false

}

完整的商品详情页面代码:goods.vue

<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'
import { ref, computed } from 'vue'
import { getGoodsByIdAPI } from '@/services/goods'
import { postMemberCartAPI } from '@/services/cart'
import type { GoodsResult } from '@/types/goods'
import AddressPanel from './components/AddressPanel.vue'
import ServicePanel from './components/ServicePanel.vue'
import PageSkeleton from './components/PageSkeleton.vue'
import type {
  SkuPopupEvent,
  SkuPopupInstanceType,
  SkuPopupLocaldata,
} from '@/components/vk-data-goods-sku-popup/vk-data-goods-sku-popup'

// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()

// 接收页面参数
const query = defineProps<{
  id: string
}>()

// 获取商品详情信息
const goods = ref<GoodsResult>()
const getGoodsByIdData = async () => {
  const res = await getGoodsByIdAPI(query.id)
  goods.value = res.result
  // SKU 组件所需格式
  localdata.value = {
    _id: res.result.id,
    name: res.result.name,
    goods_thumb: res.result.mainPictures[0],
    spec_list: res.result.specs.map((v) => {
      return {
        name: v.name,
        list: v.values,
      }
    }),
    sku_list: res.result.skus.map((v) => {
      return {
        _id: v.id,
        goods_id: res.result.id,
        goods_name: res.result.name,
        image: v.picture,
        price: v.price * 100, // 注意:需要乘以 100
        stock: v.inventory,
        sku_name_arr: v.specs.map((vv) => vv.valueName),
      }
    }),
  }
}

// 是否数据加载完成
const isFinish = ref(false)

// 页面加载
onLoad(async () => {
  await getGoodsByIdData()
  isFinish.value = true
})

// 轮播图变化时
const currentIndex = ref(0)
const onChange: UniHelper.SwiperOnChange = (e) => {
  currentIndex.value = e.detail!.current
}

// 点击图片时
const onTapImage = (url: string) => {
  // 大图预览
  uni.previewImage({
    current: url, // 当前显示图片的链接
    urls: goods.value!.mainPictures, // 需要预览的图片链接列表  数组
  })
}
// uni-ui  弹出层组件 ref
const popup = ref<{
  open: (type?: UniHelper.UniPopupType) => void
  close: (type?: UniHelper.UniPopupType) => void
}>()

// 弹出层渲染
const popupName = ref<'address' | 'service'>()
const openPopup = (name: typeof popupName.value) => {
  // 修改弹出层名称
  popupName.value = name
  popup.value?.open()
}

// 是否显示 SKU 组件
const isShowSku = ref(false)
// 商品信息
const localdata = ref({} as SkuPopupLocaldata)
// 按钮模式
enum SkuMode {
  Both = 1, // 购物车和立即购买都显示
  Cart = 2, // 只显示购物车
  Buy = 3, // 只显示立即购买
}
const mode = ref<SkuMode>(SkuMode.Both)
// 打开sku 弹窗 修改按钮模式
const openSkuPopup = (val: SkuMode) => {
  // 显示sku组件
  isShowSku.value = true
  // 修改按钮模式
  mode.value = val
}
// SKU组件实例
const skuPopupRef = ref<SkuPopupInstanceType>()

// 计算被选中的值
const selectArrText = computed(() => {
  return skuPopupRef.value?.selectArr?.join(' ').trim() || '请选择商品规格'
})
// 加入购物车事件
const onAddCart = async (e: SkuPopupEvent) => {
  console.log(e)
  await postMemberCartAPI({ skuId: e._id, count: e.buy_num })
  uni.showToast({ icon: 'success', title: '已加入购物车' })
  // 关闭弹窗
  isShowSku.value = false
}
</script>

<template>
  <!-- SKU 弹窗组件 -->
  <vk-data-goods-sku-popup
    v-model="isShowSku"
    :localdata="localdata"
    :mode="mode"
    add-cart-background-color="#ffa868"
    buy-now-background-color="#27ba9b"
    ref="skuPopupRef"
    :actived-style="{
      color: '#27BA9B',
      borderColor: '#27BA9B',
      backgroundColor: '#E9F8F5',
    }"
    @add-cart="onAddCart"
  />
  <scroll-view scroll-y class="viewport" v-if="isFinish">
    <!-- 基本信息 -->
    <view class="goods">
      <!-- 商品主图 -->
      <view class="preview">
        <swiper circular @change="onChange">
          <swiper-item v-for="item in goods?.mainPictures" :key="item">
            <image @tap="onTapImage(item)" mode="aspectFill" :src="item" />
          </swiper-item>
        </swiper>
        <view class="indicator">
          <text class="current">{{ currentIndex + 1 }}</text>
          <text class="split">/</text>
          <text class="total">{{ goods?.mainPictures.length }}</text>
        </view>
      </view>

      <!-- 商品简介 -->
      <view class="meta">
        <view class="price">
          <text class="symbol">¥</text>
          <text class="number">{{ goods?.price }}</text>
        </view>
        <view class="name ellipsis">{{ goods?.name }} </view>
        <view class="desc"> {{ goods?.desc }} </view>
      </view>

      <!-- 操作面板 -->
      <view class="action">
        <view class="item arrow" @tap="openSkuPopup(SkuMode.Both)">
          <text class="label">选择</text>
          <text class="text ellipsis"> {{ selectArrText }} </text>
        </view>
        <view class="item arrow" @tap="openPopup('address')">
          <text class="label">送至</text>
          <text class="text ellipsis"> 请选择收获地址 </text>
        </view>
        <view class="item arrow" @tap="openPopup('service')">
          <text class="label">服务</text>
          <text class="text ellipsis"> 无忧退 快速退款 免费包邮 </text>
        </view>
      </view>
    </view>

    <!-- 商品详情 -->
    <view class="detail panel">
      <view class="title">
        <text>详情</text>
      </view>
      <view class="content">
        <view class="properties">
          <!-- 属性详情 -->
          <view class="item" v-for="item in goods?.details.properties" :key="item.name">
            <text class="label">{{ item.name }}</text>
            <text class="value">{{ item.value }}</text>
          </view>
        </view>
        <!-- 图片详情 -->
        <image
          v-for="item in goods?.details.pictures"
          :key="item"
          mode="widthFix"
          :src="item"
        ></image>
      </view>
    </view>

    <!-- 同类推荐 -->
    <view class="similar panel">
      <view class="title">
        <text>同类推荐</text>
      </view>
      <view class="content">
        <navigator
          v-for="item in goods?.similarProducts"
          :key="item"
          class="goods"
          hover-class="none"
          :url="`/pages/goods/goods?id=${item.id}`"
        >
          <image class="image" mode="aspectFill" :src="item.picture"></image>
          <view class="name ellipsis">{{ item.name }}</view>
          <view class="price">
            <text class="symbol">¥</text>
            <text class="number">{{ item.price }}</text>
          </view>
        </navigator>
      </view>
    </view>
  </scroll-view>
  <PageSkeleton v-else />

  <!-- 用户操作 -->
  <view class="toolbar" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
    <view class="icons">
      <button class="icons-button"><text class="icon-heart"></text>收藏</button>
      <button class="icons-button" open-type="contact">
        <text class="icon-handset"></text>客服
      </button>
      <navigator class="icons-button" url="/pages/cart/cart" open-type="switchTab">
        <text class="icon-cart"></text>购物车
      </navigator>
    </view>
    <view class="buttons">
      <view class="addcart" @tap="openSkuPopup(SkuMode.Cart)"> 加入购物车 </view>
      <view class="buynow" @tap="openSkuPopup(SkuMode.Buy)"> 立即购买 </view>
    </view>
  </view>

  <!-- uni-ui 弹出层 -->
  <uni-popup ref="popup" type="bottom">
    <AddressPanel v-if="popupName === 'address'" @close="popup?.close()" />
    <ServicePanel v-if="popupName === 'service'" @close="popup?.close()" />
  </uni-popup>
</template>

购物车列表页面:cart.vue

获取登录的用户信息  -->  条件渲染(是否登录)  -->  初始化调用  -->  列表渲染

 

封装购物车列表类型数据:cart.d.ts

/** 购物车类型 */

export type CartItem = {

  /** 商品 ID */

  id: string

  /** SKU ID */

  skuId: string

  /** 商品名称 */

  name: string

  /** 图片 */

  picture: string

  /** 数量 */

  count: number

  /** 加入时价格 */

  price: number

  /** 当前的价格 */

  nowPrice: number

  /** 库存 */

  stock: number

  /** 是否选中 */

  selected: boolean

  /** 属性文字 */

  attrsText: string

  /** 是否为有效商品 */

  isEffective: boolean

}

封装购物车列表接口:cart.ts

import type { CartItem } from '@/types/cart';

import { http } from '@/utils/http'

/**

 * 获取购物车列表数据

 * @returns

 */

export const getMemberCartAPI = () => {

  return http<CartItem[]>({

    method: 'GET',

    url: '/member/cart',

  })

}

初始化调用:cart.vue

// 获取购物车列表数据

const cartList = ref<CartItem>([])

const getMemberCartData = async () => {

  const res = await getMemberCartAPI()

  cartList.value = res.result

}

// onShow:页面显示就触发     页面初始化调用  因为加入购物车不是在这个页面的,所以用onShow调用更合适

onShow(() => {

  // 判断用户是否已经登录了

  if (memberStore.profile) {

    getMemberCartData()

  }

})

删除购物车列表中的商品:封装API、按钮绑定事件、弹窗二次确认、调用API、重新获取列表

封装购物车删除API 接口:

/**

 * 删除/清空购物车单品

 * @param data 请求体参数 ids SKUID 集合

 */

export const deleteMemberCartAPI = (data: { ids: string[] }) => {

  return http({

    method: 'DELETE',

    url: '/member/cart',

    data,

  })

}

点击删除按钮 - 删除购物车商品   cart.vue

// 点击删除按钮 - 删除购物车

const onDeleteCart = (skuId: string) => {

  // 弹窗二次确认

  uni.showModal({

    content: '是否确定删除?',

    success: async (res) => {

      if (res.confirm) {

        await deleteMemberCartAPI({ ids: [skuId] })

        // 更新购物车列表

        getMemberCartData()

      }

    },

  })

}

删除成功

修改商品数量:步进器组件

<view class="count">

                <!-- <text class="text">-</text>

                <input class="input" type="number" :value="item.count.toString()" />

                <text class="text">+</text> -->

                <vk-data-input-number-box

                  v-model="item.count"

                  :min="1"

                  :max="item.stock"

                  :index="item.skuId"

                  @change="onChangeCount"

                />

</view>

封装修改API

/**

 * 修改购物车单品

 * @param skuId SKUID

 * @param data selected 选中状态 count 商品数量

 */

export const putMemberCartBySkuIdAPI = ( skuId: string, data: { selected?: boolean; count?: number }) => {

  return http({

    method: 'PUT',

    url: `/member/cart/${skuId}`,

    data,

  })

}

修改方法:

// 修改商品数量

const onChangeCount = (e) => {

  console.log(e)

  putMemberCartBySkuIdAPI(e.index, { count: e.value })

}

修改商品的选中状态,即单选和全选功能实现

            <!-- 选中状态 -->

              <text

                @tap="onChangeSelected(item)"

                class="checkbox"

                :class="{ checked: item.selected }"

              ></text>

封装全选 / 取消全选API

/**

 * 购物车全选/取消全选

 * @param data selected 是否选中

 */

export const putMemberCartSelectedAPI = (data: { selected: boolean }) => {

  return http({

    method: 'PUT',

    url: '/member/cart/selected',

    data,

  })

}

// 修改选中状态  - 单选修改

const onChangeSelected = (good: CartItem) => {

  console.log(good)

// 前端数据更新  - 是否选中 取反

  good.selected = !good.selected

  // 后端数据更新    与修改数量接口是同一条接口  传递的参数不同

  putMemberCartBySkuIdAPI(good.skuId, { selected: good.selected })

}

// 计算全选状态

const isSelectedAll = computed(() => {

  return cartList.value.length && cartList.value.every((v) => v.selected)

})

// 修改选中状态-全选修改

const onChangeSelectedAll = () => {

  // 全选状态取法

  const _isSelectedAll = !isSelectedAll.value

  // 前端数据更新

  cartList.value.forEach((item) => {

    item.selected = _isSelectedAll

  })

  // 后端更新

  putMemberCartSelectedAPI({ selected: _isSelectedAll })

}

购物车页面 - 底部结算信息

<!-- 底部结算 -->

      <view class="toolbar">

        <text class="all" @tap="onChangeSelectedAll" :class="{ checked: isSelectedAll }">全选</text>

        <text class="text">合计:</text>

        <text class="amount">{{ selectedCartListMoney }}</text>

        <view class="button-grounp">

          <view

            @tap="gotoPayment"

            class="button payment-button"

            :class="{ disabled: selectedCartListCount === 0 }"

          >

            去结算({{ selectedCartListCount }})

          </view>

        </view>

      </view>

逻辑实现:

// 计算选中的商品列表

const selectedCartList = computed(() => {

  return cartList.value.filter((v) => v.selected)

})

// 计算选中商品的总件数

const selectedCartListCount = computed(() => {

  return selectedCartList.value.reduce((sum, item) => sum + item.count, 0)

})

// 计算选中商品的总金额

const selectedCartListMoney = computed(() => {

  return selectedCartList.value

    .reduce((sum, item) => sum + item.count * item.nowPrice, 0)

    .toFixed(2)

})

// 去结算按钮

const gotoPayment = () => {

  // 判断用户是否选择了商品    即商品数量不能为 0

  if (selectedCartListCount.value === 0) {

    return uni.showToast({ icon: 'none', title: '请选择商品' })

  }

  // 跳转到计算页面

  uni.showToast({ title: '此功能还未写' })

}

完整的购物车列表页面组件代码:cart.vue

<script setup lang="ts">
import { onShow } from '@dcloudio/uni-app'
import { ref, computed } from 'vue'
import {
  deleteMemberCartAPI,
  getMemberCartAPI,
  putMemberCartBySkuIdAPI,
  putMemberCartSelectedAPI,
} from '@/services/cart'
import { useMemberStore } from '@/stores/index'
import type { CartItem } from '@/types/cart'
import type { InputNumberBoxEvent } from '@/components/vk-data-input-number-box/vk-data-input-number-box'

// 获取会员 Store
const memberStore = useMemberStore()

// 获取购物车列表数据
const cartList = ref<CartItem>([])
const getMemberCartData = async () => {
  const res = await getMemberCartAPI()
  cartList.value = res.result
}

// onShow:页面显示就触发      页面初始化调用  因为加入购物车不是在这个页面的,所以用onShow调用更合适
onShow(() => {
  // 判断用户是否已经登录了
  if (memberStore.profile) {
    getMemberCartData()
  }
})

// 点击删除按钮 - 删除购物车
const onDeleteCart = (skuId: string) => {
  // 弹窗二次确认
  uni.showModal({
    content: '是否确定删除?',
    success: async (res) => {
      if (res.confirm) {
        await deleteMemberCartAPI({ ids: [skuId] })
        // 更新购物车列表
        getMemberCartData()
      }
    },
  })
}

// 修改商品数量
const onChangeCount = (e: InputNumberBoxEvent) => {
  console.log(e)
  putMemberCartBySkuIdAPI(e.index, { count: e.value })
}

// 修改选中状态 - 单品修改
const onChangeSelected = (good: CartItem) => {
  console.log(good)
  // 前端数据更新  - 是否选中 取反
  good.selected = !good.selected
  // 后端数据更新
  putMemberCartBySkuIdAPI(good.skuId, { selected: good.selected })
}

// 计算全选状态
const isSelectedAll = computed(() => {
  return cartList.value.length && cartList.value.every((v) => v.selected)
})

// 修改选中状态-全选修改
const onChangeSelectedAll = () => {
  // 全选状态取法
  const _isSelectedAll = !isSelectedAll.value
  // 前端数据更新
  cartList.value.forEach((item) => {
    item.selected = _isSelectedAll
  })
  // 后端更新
  putMemberCartSelectedAPI({ selected: _isSelectedAll })
}

// 计算选中的商品列表
const selectedCartList = computed(() => {
  return cartList.value.filter((v) => v.selected)
})

// 计算选中商品的总件数
const selectedCartListCount = computed(() => {
  return selectedCartList.value.reduce((sum, item) => sum + item.count, 0)
})

// 计算选中商品的总金额
const selectedCartListMoney = computed(() => {
  return selectedCartList.value
    .reduce((sum, item) => sum + item.count * item.nowPrice, 0)
    .toFixed(2)
})

// 去结算按钮
const gotoPayment = () => {
  // 判断用户是否选择了商品    即商品数量不能为 0
  if (selectedCartListCount.value === 0) {
    return uni.showToast({ icon: 'none', title: '请选择商品' })
  }
  // 跳转到计算页面
  uni.showToast({ title: '此功能还未写' })
}
</script>

<template>
  <scroll-view scroll-y class="scroll-view">
    <!-- 已登录: 显示购物车 -->
    <template v-if="memberStore.profile.token">
      <!-- 购物车列表 -->
      <view class="cart-list" v-if="cartList.length">
        <!-- 优惠提示 -->
        <view class="tips">
          <text class="label">满减</text>
          <text class="desc">满1件, 即可享受9折优惠</text>
        </view>
        <!-- 滑动操作分区 -->
        <uni-swipe-action>
          <!-- 滑动操作项 -->
          <uni-swipe-action-item v-for="item in cartList" :key="item.skuId" class="cart-swipe">
            <!-- 商品信息 -->
            <view class="goods">
              <!-- 选中状态 -->
              <text
                @tap="onChangeSelected(item)"
                class="checkbox"
                :class="{ checked: item.selected }"
              ></text>
              <navigator
                :url="`/pages/goods/goods?id=${item.id}`"
                hover-class="none"
                class="navigator"
              >
                <image mode="aspectFill" class="picture" :src="item.picture"></image>
                <view class="meta">
                  <view class="name ellipsis">{{ item.name }}</view>
                  <view class="attrsText ellipsis">{{ item.attrsText }}</view>
                  <view class="price">{{ item.nowPrice }}</view>
                </view>
              </navigator>
              <!-- 商品数量 -->
              <view class="count">
                <!-- <text class="text">-</text>
                <input class="input" type="number" :value="item.count.toString()" />
                <text class="text">+</text> -->
                <vk-data-input-number-box
                  v-model="item.count"
                  :min="1"
                  :max="item.stock"
                  :index="item.skuId"
                  @change="onChangeCount"
                />
              </view>
            </view>
            <!-- 右侧删除按钮 -->
            <template #right>
              <view class="cart-swipe-right">
                <button @tap="onDeleteCart(item.skuId)" class="button delete-button">删除</button>
              </view>
            </template>
          </uni-swipe-action-item>
        </uni-swipe-action>
      </view>
      <!-- 购物车空状态 -->
      <view class="cart-blank" v-else>
        <image src="/static/images/blank_cart.png" class="image" />
        <text class="text">购物车还是空的,快来挑选好货吧</text>
        <navigator open-type="switchTab" url="/pages/index/index" hover-class="none">
          <button class="button">去首页看看</button>
        </navigator>
      </view>
      <!-- 吸底工具栏 -->
      <view class="toolbar">
        <text class="all" @tap="onChangeSelectedAll" :class="{ checked: isSelectedAll }">全选</text>
        <text class="text">合计:</text>
        <text class="amount">{{ selectedCartListMoney }}</text>
        <view class="button-grounp">
          <view
            @tap="gotoPayment"
            class="button payment-button"
            :class="{ disabled: selectedCartListCount === 0 }"
          >
            去结算({{ selectedCartListCount }})
          </view>
        </view>
      </view>
    </template>
    <!-- 未登录: 提示登录 -->
    <view class="login-blank" v-else>
      <text class="text">登录后可查看购物车中的商品</text>
      <navigator url="/pages/login/login" hover-class="none">
        <button class="button">去登录</button>
      </navigator>
    </view>
    <!-- 猜你喜欢 -->
    <Guess ref="guessRef"></XtxGuess>
    <!-- 底部占位空盒子 -->
    <view class="toolbar-height"></view>
  </scroll-view>
</template>

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

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

相关文章

AI大模型探索之路-实战篇6: Function Calling技术调研之详细流程剖析

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;DB-GPT数据应用开发框架调研实践 AI大模型探索之路-实战篇5&#xff1a; Open Interpreter开放代码解释器调研实践 目录 系列篇章&#x1f4a5;一、前言二、Function Calling详细流程剖析1、创建OpenAI客户端2、定…

infoq读书笔记-Davide Taibi博士-花8年转型微服务却得不到回报,问题出在哪 儿?

InfoQ&#xff1a;您的论文“On the Definition of Microservice Bad Smells”涉及非常多的微服务不良做法&#xff0c;但如果要用几个大类别来列举危害性比较大的微服务反模式&#xff0c;您认为会是哪几类&#xff1f;另外&#xff0c;您能再大概分析说明下造成这个几个反模式…

《计算机网络微课堂》1-2:因特网概述

1-2&#xff1a;因特网概述 网络、互连网&#xff08;互联网&#xff09;和因特网因特网发展的三个阶段因特网的标准化工作因特网的组成 ‍ 网络、互连网&#xff08;互联网&#xff09;和因特网 我们首先介绍网络、互联网&#xff08;互连网&#xff09;因特网的基本概念&a…

c语言——宏offsetof

1.介绍 &#xff01;&#xff01;&#xff01; offsetof 是一个宏 2.使用举例 结构体章节的计算结构体占多少字节需要先掌握&#xff08;本人博客结构体篇章中已经讲解过&#xff09; 计算结构体中某变量相对于首地址的偏移&#xff0c;并给出说明 首先&#xff0c;结构体首个…

MyBatis常见报错:org.apache.ibatis.binding.BindingException

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 异常现象描述 当开发者在使用MyBatis进行数据库操作时&#xff0c;可能会遇到org.apache.ibatis.binding.BindingException: Parameter appId not found这样的错误提示。这个错误通常会让程序无法正常运行&#xff…

如何在华为手机上恢复已删除的视频[4种解决方案]

概括 在数字媒体时代&#xff0c;智能手机已成为我们的个人金库&#xff0c;存储以视频形式捕捉的珍贵记忆。然而&#xff0c;意外删除这些珍贵的文件可能会是一次令人心痛的经历。对于华为手机用户来说&#xff0c;由于删除或其他意外导致视频丢失尤其令人痛苦。但不用担心&a…

cadence23---PCB Editer 学习笔记

1.交互式布局 在Orcad中点击图标N生成第一网表&#xff1a; 在PCB Editer中导入第一网表&#xff0c; 之后点击移动命令并在右侧属性框中勾选Symbol选项卡&#xff1a; 设置--应用模式--点击常规编辑&#xff1a; 之后就可以进行交互式选择了。 绿色图标为打开全部飞线&#…

【Spring Security + OAuth2】OAuth2

Spring Security OAuth2 第一章 Spring Security 快速入门 第二章 Spring Security 自定义配置 第三章 Spring Security 前后端分离配置 第四章 Spring Security 身份认证 第五章 Spring Security 授权 第六章 OAuth2 文章目录 Spring Security OAuth21、OAuth2简介1.1、OAu…

力扣:92. 反转链表 II(Java)

目录 题目描述&#xff1a;示例 1&#xff1a;示例 2&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的…

刷代码随想录有感(78):回溯算法——关于树枝/树层去重的思考(涉及break/continue的使用)

在复原IP地址中&#xff0c;剪枝操作我们使用的是break: if(isvalid(s, start, i)){s.insert(s.begin() i 1, .);pointNum;backtracking(s, i 2, pointNum);s.erase(s.begin() i 1);pointNum--; }else break;在其他情况&#xff0c;举个例子&#xff0c;在含有重复元素求…

WiFi蓝牙模块开发配置过程中需要注意的细节

在很多产品的应用场景中&#xff0c;WIFI网络会给我们提供很多便捷&#xff0c;MCU开发中大多使用串口WIFI蓝牙模块来实现产品接入WIFI网络中。   具体的使用模型如下图所示&#xff1a;整个系统涉及到WIFI网络、手机、服务器平台以及我们设计的产品&#xff0c;一个完整的生…

第十一课,end关键字、简单while循环嵌套、初识for循环

一&#xff0c;end关键字 end关键字用于在print输出的内容后面声明结束的字符&#xff0c;我们之前学过并且十分了解print是默认输出内容之后跟着换行的&#xff0c;如果我们不希望换行而希望使用其它字符来代替换行&#xff0c;就可以用end关键字来实现 特殊的&#xff0c;en…

使用elementUI的form表单校验时,错误提示位置异常解决方法

问题 最近在做项目时遇到一个问题&#xff0c;使用elementUI的Descriptions 描述列表与form表单校验时&#xff0c;遇到校验信息显示的位置不对&#xff0c;效果如图&#xff1a; 期望显示在表格中。 效果 代码 html <el-form :model"form":rules"rules…

原始字面常量(C++11)

原始字面常量&#xff08;C11&#xff09; 文章目录 原始字面常量&#xff08;C11&#xff09;前言一、原始字面量二、代码示例总结 前言 字面量一般是指数值&#xff08;12、454等&#xff09;和字符串&#xff08;“Hw”、“h\t”&#xff09;&#xff0c;但是有时候我们想表…

用栈实现队列(C语言)

目录 题目题目分析 代码栈的实现结构体。栈的初始化栈的销毁 入栈删除查找顶部数据判空 答案结构体初始化插入数据删除数据获取队列开头元素判空销毁栈 题目 题目分析 链接: 题目 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、po…

MyBatis 学习笔记(一)

MyBatis 封装 JDBC :连接、访问、操作数据库中的数据 MyBatis 是一个持久层框架。 MyBatis 提供的持久层框架包括 SQLMaps 和 Data Access Objects&#xff08;DAO&#xff09; SQLMaps&#xff1a;数据库中的数据和 Java数据的一个映射关系 封装 JDBC 的过程Data Access Ob…

使用xxl-job-executor-go 接入xxl-job实现定时任务调度

定时任务是软件开发中很常见的一种处理业务的机制&#xff0c;xxl-job是近些年比较火的定时任务调用组件&#xff0c;其采用java 实现&#xff0c;是一个高可用&#xff0c;分布式调用的组件&#xff0c;还支持多种定时任务有关的特性&#xff0c;不仅能轻易的用java 客户端接入…

ChatGPT可以开车吗?分享大型语言模型在自动驾驶方面的应用案例

自动驾驶边缘案例需要复杂的、类似人类的推理&#xff0c;远远超出传统的算法和人工智能模型。而大型语言模型正在致力实现这一目标。 人工智能技术如今正在快速发展和应用&#xff0c;人工智能模型也是如此。拥有100亿个参数的通用模型的性能正在碾压拥有5000万个参数的任务特…

Pytorch-01 框架简介

智能框架概述 人工智能框架是一种软件工具&#xff0c;用于帮助开发人员构建和训练人工智能模型。这些框架提供了各种功能&#xff0c;如定义神经网络结构、优化算法、自动求导等&#xff0c;使得开发人员可以更轻松地实现各种人工智能任务。通过使用人工智能框架&#xff0c;…