黑马 小兔鲜儿 uniapp 小程序开发- 商品详情模块- day05

黑马 小兔鲜儿 uniapp 小程序开发- 分类模块- day04-CSDN博客

小兔鲜儿 - 商品详情(登录前)-day05

商品详情页分为两部分讲解:

  1. 登录前:展示商品信息,轮播图交互(当前模块)
  2. 登录后:加入购物车,立即购买(SKU 模块)

准备工作

参考效果

用户点击商品列表,跳转到对应的商品详情页。

静态结构

新建商品详情页。

// src/pages/goods/goods.vue
<script setup lang="ts">
// 获取屏幕边界到安全区域距离
const { safeAreaInsets } = uni.getSystemInfoSync()
</script><template><scroll-view scroll-y class="viewport"><!-- 基本信息 --><view class="goods"><!-- 商品主图 --><view class="preview"><swiper circular><swiper-item><imagemode="aspectFill"src="https://yanxuan-item.nosdn.127.net/99c83709ca5f9fd5c5bb35d207ad7822.png"/></swiper-item><swiper-item><imagemode="aspectFill"src="https://yanxuan-item.nosdn.127.net/f9107d47c08f0b99c097e30055c39e1a.png"/></swiper-item><swiper-item><imagemode="aspectFill"src="https://yanxuan-item.nosdn.127.net/754c56785cc8c39f7414752f62d79872.png"/></swiper-item><swiper-item><imagemode="aspectFill"src="https://yanxuan-item.nosdn.127.net/ef16f8127610ef56a2a10466d6dae157.jpg"/></swiper-item><swiper-item><imagemode="aspectFill"src="https://yanxuan-item.nosdn.127.net/1f0c3f5d32b0e804deb9b3d56ea6c3b2.png"/></swiper-item></swiper><view class="indicator"><text class="current">1</text><text class="split">/</text><text class="total">5</text></view></view><!-- 商品简介 --><view class="meta"><view class="price"><text class="symbol">¥</text><text class="number">29.90</text></view><view class="name ellipsis">云珍·轻软旅行长绒棉方巾 </view><view class="desc"> 轻巧无捻小方巾,旅行便携 </view></view><!-- 操作面板 --><view class="action"><view class="item arrow"><text class="label">选择</text><text class="text ellipsis"> 请选择商品规格 </text></view><view class="item arrow"><text class="label">送至</text><text class="text ellipsis"> 请选择收获地址 </text></view><view class="item arrow"><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"><text class="label">属性名</text><text class="value">属性值</text></view><view class="item"><text class="label">属性名</text><text class="value">属性值</text></view></view><!-- 图片详情 --><imagemode="widthFix"src="https://yanxuan-item.nosdn.127.net/a8d266886d31f6eb0d7333c815769305.jpg"></image><imagemode="widthFix"src="https://yanxuan-item.nosdn.127.net/a9bee1cb53d72e6cdcda210071cbd46a.jpg"></image></view></view><!-- 同类推荐 --><view class="similar panel"><view class="title"><text>同类推荐</text></view><view class="content"><navigatorv-for="item in 4":key="item"class="goods"hover-class="none":url="`/pages/goods/goods?id=`"><imageclass="image"mode="aspectFill"src="https://yanxuan-item.nosdn.127.net/e0cea368f41da1587b3b7fc523f169d7.png"></image><view class="name ellipsis">简约山形纹全棉提花毛巾</view><view class="price"><text class="symbol">¥</text><text class="number">18.50</text></view></navigator></view></view></scroll-view><!-- 用户操作 --><viewclass="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><navigatorclass="icons-button"url="/pages/cart/cart"open-type="switchTab"><text class="icon-cart"></text>购物车</navigator></view><view class="buttons"><view class="addcart"> 加入购物车 </view><view class="buynow"> 立即购买 </view></view></view>
</template><style lang="scss">
page {height: 100%;overflow: hidden;display: flex;flex-direction: column;
}.viewport {background-color: #f4f4f4;
}.panel {margin-top: 20rpx;background-color: #fff;.title {display: flex;justify-content: space-between;align-items: center;height: 90rpx;line-height: 1;padding: 30rpx 60rpx 30rpx 6rpx;position: relative;text {padding-left: 10rpx;font-size: 28rpx;color: #333;font-weight: 600;border-left: 4rpx solid #27ba9b;}navigator {font-size: 24rpx;color: #666;}}
}.arrow {&::after {position: absolute;top: 50%;right: 30rpx;content: '\e6c2';color: #ccc;font-family: 'erabbit' !important;font-size: 32rpx;transform: translateY(-50%);}
}/* 商品信息 */
.goods {background-color: #fff;.preview {height: 750rpx;position: relative;.indicator {height: 40rpx;padding: 0 24rpx;line-height: 40rpx;border-radius: 30rpx;color: #fff;font-family: Arial, Helvetica, sans-serif;background-color: rgba(0, 0, 0, 0.3);position: absolute;bottom: 30rpx;right: 30rpx;.current {font-size: 26rpx;}.split {font-size: 24rpx;margin: 0 1rpx 0 2rpx;}.total {font-size: 24rpx;}}}.meta {position: relative;border-bottom: 1rpx solid #eaeaea;.price {height: 130rpx;padding: 25rpx 30rpx 0;color: #fff;font-size: 34rpx;box-sizing: border-box;background-color: #35c8a9;}.number {font-size: 56rpx;}.brand {width: 160rpx;height: 80rpx;overflow: hidden;position: absolute;top: 26rpx;right: 30rpx;}.name {max-height: 88rpx;line-height: 1.4;margin: 20rpx;font-size: 32rpx;color: #333;}.desc {line-height: 1;padding: 0 20rpx 30rpx;font-size: 24rpx;color: #cf4444;}}.action {padding-left: 20rpx;.item {height: 90rpx;padding-right: 60rpx;border-bottom: 1rpx solid #eaeaea;font-size: 26rpx;color: #333;position: relative;display: flex;align-items: center;&:last-child {border-bottom: 0 none;}}.label {width: 60rpx;color: #898b94;margin: 0 16rpx 0 10rpx;}.text {flex: 1;-webkit-line-clamp: 1;}}
}/* 商品详情 */
.detail {padding-left: 20rpx;.content {margin-left: -20rpx;}.properties {padding: 0 20rpx;margin-bottom: 30rpx;.item {display: flex;line-height: 2;padding: 10rpx;font-size: 26rpx;color: #333;border-bottom: 1rpx dashed #ccc;}.label {width: 200rpx;}.value {flex: 1;}}
}/* 同类推荐 */
.similar {padding-left: 20rpx;.content {padding: 0 20rpx 20rpx;margin-left: -20rpx;background-color: #f4f4f4;overflow: hidden;navigator {width: 345rpx;padding: 24rpx 20rpx 20rpx;margin: 20rpx 20rpx 0 0;border-radius: 10rpx;background-color: #fff;float: left;}.image {height: 260rpx;}.name {height: 80rpx;margin: 10rpx 0;font-size: 26rpx;color: #262626;}.price {line-height: 1;font-size: 20rpx;color: #cf4444;}.number {font-size: 26rpx;margin-left: 2rpx;}}navigator {&:nth-child(even) {margin-right: 0;}}
}/* 底部工具栏 */
.toolbar {background-color: #fff;height: 100rpx;padding: 0 20rpx;border-top: 1rpx solid #eaeaea;display: flex;justify-content: space-between;align-items: center;box-sizing: content-box;.buttons {display: flex;& > view {width: 220rpx;text-align: center;line-height: 72rpx;font-size: 26rpx;color: #fff;border-radius: 72rpx;}.addcart {background-color: #ffa868;}.buynow {background-color: #27ba9b;margin-left: 20rpx;}}.icons {padding-right: 10rpx;display: flex;align-items: center;flex: 1;.icons-button {flex: 1;text-align: center;line-height: 1.4;padding: 0;margin: 0;border-radius: 0;font-size: 20rpx;color: #333;background-color: #fff;}text {display: block;font-size: 34rpx;}}
}
</style>

获取数据

获取页面参数

根据商品的 id 查询到某个商品的详细信息,如图片、价格、型号等展示给用户。

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

接口调用

接口信息如下:

接口地址:/goods

请求方式:GET

请求参数:

Query

字段名称

是否必须

默认值

备注

id

商品 id

请求封装

/*** 商品详情* @param id 商品id*/
export const getGoodsByIdAPI = (id: string) => {return http<GoodsResult>({method: 'GET',url: '/goods',data: { id },})
}

类型声明

import type { GoodsItem } from './global'/** 商品信息 */
export type GoodsResult = {/** id */id: string/** 商品名称 */name: string/** 商品描述 */desc: string/** 当前价格 */price: number/** 原价 */oldPrice: number/** 商品详情: 包含详情属性 + 详情图片 */details: Details/** 主图图片集合[ 主图图片链接 ] */mainPictures: string[]/** 同类商品[ 商品信息 ] */similarProducts: GoodsItem[]/** sku集合[ sku信息 ] */skus: SkuItem[]/** 可选规格集合备注[ 可选规格信息 ] */specs: SpecItem[]/** 用户地址列表[ 地址信息 ] */userAddresses: AddressItem[]
}/** 商品详情: 包含详情属性 + 详情图片 */
export type Details = {/** 商品属性集合[ 属性信息 ] */properties: DetailsPropertyItem[]/** 商品详情图片集合[ 图片链接 ] */pictures: string[]
}/** 属性信息 */
export type DetailsPropertyItem = {/** 属性名称 */name: string/** 属性值 */value: string
}/** sku信息 */
export type SkuItem = {/** id */id: string/** 库存 */inventory: number/** 原价 */oldPrice: number/** sku图片 */picture: string/** 当前价格 */price: number/** sku编码 */skuCode: string/** 规格集合[ 规格信息 ] */specs: SkuSpecItem[]
}/** 规格信息 */
export type SkuSpecItem = {/** 规格名称 */name: string/** 可选值名称 */valueName: string
}/** 可选规格信息 */
export type SpecItem = {/** 规格名称 */name: string/** 可选值集合[ 可选值信息 ] */values: SpecValueItem[]
}/** 可选值信息 */
export type SpecValueItem = {/** 是否可售 */available: boolean/** 可选值备注 */desc: string/** 可选值名称 */name: string/** 可选值图片链接 */picture: string
}/** 地址信息 */
export type AddressItem = {/** 收货人姓名 */receiver: string/** 联系方式 */contact: string/** 省份编码 */provinceCode: string/** 城市编码 */cityCode: string/** 区/县编码 */countyCode: string/** 详细地址 */address: string/** 默认地址,1为是,0为否 */isDefault: number/** 收货地址 id */id: string/** 省市区 */fullLocation: string
}

接下来,将获取到的数据结合模板语法渲染到页面中。

轮播图交互

参考效果

当轮播图滑动切换的时候更新自定义下标,当图片被点击的时候大图预览

参考代码

商品详情页轮播图交互

<script setup lang="ts">
// 轮播图变化时
const currentIndex = ref(0)
const onChange: UniHelper.SwiperOnChange = (ev) => {currentIndex.value = ev.detail.current
}// 点击图片时
const onTapImage = (url: string) => {// 大图预览uni.previewImage({current: url,urls: goods.value!.mainPictures,})
}
</script><template><!-- 商品主图 --><view class="preview"><swiper @change="onChange" circular><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>
</template>

弹出层交互

参考效果

uni-ui 弹出层组件:uni-popup

静态结构

提供 服务说明收获地址 两个组件的静态结构,实现弹出层交互。

组件 1:服务说明

// ServicePanel.vue
<script setup lang="ts">
//
</script><template><view class="service-panel"><!-- 关闭按钮 --><text class="close icon-close"></text><!-- 标题 --><view class="title">服务说明</view><!-- 内容 --><view class="content"><view class="item"><view class="dt">无忧退货</view><view class="dd">自收到商品之日起30天内,可在线申请无忧退货服务(食品等特殊商品除外)</view></view><view class="item"><view class="dt">快速退款</view><view class="dd">收到退货包裹并确认无误后,将在48小时内办理退款,退款将原路返回,不同银行处理时间不同,预计1-5个工作日到账</view></view><view class="item"><view class="dt">满88元免邮费</view><view class="dd">单笔订单金额(不含运费)满88元可免邮费,不满88元, 单笔订单收取10元邮费</view></view></view></view>
</template><style lang="scss">
.service-panel {padding: 0 30rpx;border-radius: 10rpx 10rpx 0 0;position: relative;background-color: #fff;
}.title {line-height: 1;padding: 40rpx 0;text-align: center;font-size: 32rpx;font-weight: normal;border-bottom: 1rpx solid #ddd;color: #444;
}.close {position: absolute;right: 24rpx;top: 24rpx;
}.content {padding: 20rpx 20rpx 100rpx 20rpx;.item {margin-top: 20rpx;}.dt {margin-bottom: 10rpx;font-size: 28rpx;color: #333;font-weight: 500;position: relative;&::before {content: '';width: 10rpx;height: 10rpx;border-radius: 50%;background-color: #eaeaea;transform: translateY(-50%);position: absolute;top: 50%;left: -20rpx;}}.dd {line-height: 1.6;font-size: 26rpx;color: #999;}
}
</style>

组件 2:收获地址组件

// AddressPanel.vue
<script setup lang="ts">
//
</script><template><view class="address-panel"><!-- 关闭按钮 --><text class="close icon-close"></text><!-- 标题 --><view class="title">配送至</view><!-- 内容 --><view class="content"><view class="item"><view class="user">李明 13824686868</view><view class="address">北京市顺义区后沙峪地区安平北街6号院</view><text class="icon icon-checked"></text></view><view class="item"><view class="user">王东 13824686868</view><view class="address">北京市顺义区后沙峪地区安平北街6号院</view><text class="icon icon-ring"></text></view><view class="item"><view class="user">张三 13824686868</view><view class="address">北京市朝阳区孙河安平北街6号院</view><text class="icon icon-ring"></text></view></view><view class="footer"><view class="button primary"> 新建地址 </view><view v-if="false" class="button primary">确定</view></view></view>
</template><style lang="scss">
.address-panel {padding: 0 30rpx;border-radius: 10rpx 10rpx 0 0;position: relative;background-color: #fff;
}.title {line-height: 1;padding: 40rpx 0;text-align: center;font-size: 32rpx;font-weight: normal;border-bottom: 1rpx solid #ddd;color: #444;
}.close {position: absolute;right: 24rpx;top: 24rpx;
}.content {min-height: 300rpx;max-height: 540rpx;overflow: auto;padding: 20rpx;.item {padding: 30rpx 50rpx 30rpx 60rpx;background-size: 40rpx;background-repeat: no-repeat;background-position: 0 center;background-image: url(https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/images/locate.png);position: relative;}.icon {color: #999;font-size: 40rpx;transform: translateY(-50%);position: absolute;top: 50%;right: 0;}.icon-checked {color: #27ba9b;}.icon-ring {color: #444;}.user {font-size: 28rpx;color: #444;font-weight: 500;}.address {font-size: 26rpx;color: #666;}
}.footer {display: flex;justify-content: space-between;padding: 20rpx 0 40rpx;font-size: 28rpx;color: #444;.button {flex: 1;height: 72rpx;text-align: center;line-height: 72rpx;margin: 0 20rpx;color: #fff;border-radius: 72rpx;}.primary {color: #fff;background-color: #27ba9b;}.secondary {background-color: #ffa868;}
}
</style>

参考代码

商品详情页:通过组件 ref 获取弹出层组件实例,调用打开弹出层方法。

<script setup lang="ts">
import AddressPanel from './components/AddressPanel.vue'
import ServicePanel from './components/ServicePanel.vue'// uni-ui 弹出层组件 ref
const popup = ref<{open: (type?: UniHelper.UniPopupType) => voidclose: () => void
}>()// 弹出层条件渲染
const popupName = ref<'address' | 'service'>()
const openPopup = (name: typeof popupName.value) => {// 修改弹出层名称popupName.value = name// 打开弹出层popup.value?.open()
}
</script><template><!-- 操作面板 --><view class="action"><view class="item arrow"><text class="label">选择</text><text class="text ellipsis"> 请选择商品规格 </text></view><view @tap="openPopup('address')" class="item arrow"><text class="label">送至</text><text class="text ellipsis"> 请选择收获地址 </text></view><view @tap="openPopup('service')" class="item arrow"><text class="label">服务</text><text class="text ellipsis"> 无忧退 快速退款 免费包邮 </text></view></view><!-- uni-ui 弹出层 --><uni-popup ref="popup" type="bottom" background-color="#fff"><AddressPanel v-if="popupName === 'address'" @close="popup?.close()" /><ServicePanel v-if="popupName === 'service'" @close="popup?.close()" /></uni-popup>
</template>

服务说明收获地址 组件通讯:通过子调父,关闭弹出层。

<script setup lang="ts">
// 子调父
const emit = defineEmits<{(event: 'close'): void
}>()
</script><template><view class="service-panel"><!-- 关闭按钮 --><text class="close icon-close" @tap="emit('close')"></text>...省略</view>
</template>

骨架屏

参考效果

课后练习,大家自主独立完成。

参考代码(总)

商品详情页

<script setup lang="ts">
import { getGoodsByIdAPI } from '@/services/goods'
import type { GoodsResult } from '@/types/goods'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import AddressPanel from './components/AddressPanel.vue'
import ServicePanel from './components/ServicePanel.vue'// 获取屏幕边界到安全区域距离
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
}// 页面加载
onLoad(() => {getGoodsByIdData()
})// 轮播图变化时
const currentIndex = ref(0)
const onChange: UniHelper.SwiperOnChange = (ev) => {currentIndex.value = ev.detail!.current
}// 点击图片时
const onTapImage = (url: string) => {// 大图预览uni.previewImage({current: url,urls: goods.value!.mainPictures,})
}// uni-ui 弹出层组件 ref
const popup = ref<{open: (type?: UniHelper.UniPopupType) => voidclose: () => void
}>()// 弹出层条件渲染
const popupName = ref<'address' | 'service'>()
const openPopup = (name: typeof popupName.value) => {// 修改弹出层名称popupName.value = namepopup.value?.open()
}
</script><template><scroll-view scroll-y class="viewport"><!-- 基本信息 --><view class="goods"><!-- 商品主图 --><view class="preview"><swiper @change="onChange" circular><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"><text class="label">选择</text><text class="text ellipsis"> 请选择商品规格 </text></view><view @tap="openPopup('address')" class="item arrow"><text class="label">送至</text><text class="text ellipsis"> 请选择收获地址 </text></view><view @tap="openPopup('service')" class="item arrow"><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"><!-- 属性详情 --><viewclass="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><!-- 图片详情 --><imagev-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"><navigatorv-for="item in goods?.similarProducts":key="item.id"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><!-- 用户操作 --><viewclass="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"><text class="icon-cart"></text>购物车</navigator></view><view class="buttons"><view class="addcart"> 加入购物车 </view><view class="payment"> 立即购买 </view></view></view><!-- uni-ui 弹出层 --><uni-popup ref="popup" type="bottom" background-color="#fff"><AddressPanel v-if="popupName === 'address'" @close="popup?.close()" /><ServicePanel v-if="popupName === 'service'" @close="popup?.close()" /></uni-popup>
</template><style lang="scss">
page {height: 100%;overflow: hidden;display: flex;flex-direction: column;
}.viewport {background-color: #f4f4f4;
}.panel {margin-top: 20rpx;background-color: #fff;.title {display: flex;justify-content: space-between;align-items: center;height: 90rpx;line-height: 1;padding: 30rpx 60rpx 30rpx 6rpx;position: relative;text {padding-left: 10rpx;font-size: 28rpx;color: #333;font-weight: 600;border-left: 4rpx solid #27ba9b;}navigator {font-size: 24rpx;color: #666;}}
}.arrow {&::after {position: absolute;top: 50%;right: 30rpx;content: '\e6c2';color: #ccc;font-family: 'erabbit' !important;font-size: 32rpx;transform: translateY(-50%);}
}/* 商品信息 */
.goods {background-color: #fff;.preview {height: 750rpx;position: relative;.indicator {height: 40rpx;padding: 0 24rpx;line-height: 40rpx;border-radius: 30rpx;color: #fff;font-family: Arial, Helvetica, sans-serif;background-color: rgba(0, 0, 0, 0.3);position: absolute;bottom: 30rpx;right: 30rpx;.current {font-size: 26rpx;}.split {font-size: 24rpx;margin: 0 1rpx 0 2rpx;}.total {font-size: 24rpx;}}}.meta {position: relative;border-bottom: 1rpx solid #eaeaea;.price {height: 130rpx;padding: 25rpx 30rpx 0;color: #fff;font-size: 34rpx;box-sizing: border-box;background-color: #35c8a9;}.number {font-size: 56rpx;}.brand {width: 160rpx;height: 80rpx;overflow: hidden;position: absolute;top: 26rpx;right: 30rpx;}.name {max-height: 88rpx;line-height: 1.4;margin: 20rpx;font-size: 32rpx;color: #333;}.desc {line-height: 1;padding: 0 20rpx 30rpx;font-size: 24rpx;color: #cf4444;}}.action {padding-left: 20rpx;.item {height: 90rpx;padding-right: 60rpx;border-bottom: 1rpx solid #eaeaea;font-size: 26rpx;color: #333;position: relative;display: flex;align-items: center;&:last-child {border-bottom: 0 none;}}.label {width: 60rpx;color: #898b94;margin: 0 16rpx 0 10rpx;}.text {flex: 1;-webkit-line-clamp: 1;}}
}/* 商品详情 */
.detail {padding-left: 20rpx;.content {margin-left: -20rpx;}.properties {padding: 0 20rpx;margin-bottom: 30rpx;.item {display: flex;line-height: 2;padding: 10rpx;font-size: 26rpx;color: #333;border-bottom: 1rpx dashed #ccc;}.label {width: 200rpx;}.value {flex: 1;}}
}/* 同类推荐 */
.similar {padding-left: 20rpx;.content {padding: 0 20rpx 20rpx;margin-left: -20rpx;background-color: #f4f4f4;overflow: hidden;navigator {width: 345rpx;padding: 24rpx 20rpx 20rpx;margin: 20rpx 20rpx 0 0;border-radius: 10rpx;background-color: #fff;float: left;}.image {height: 260rpx;}.name {height: 80rpx;margin: 10rpx 0;font-size: 26rpx;color: #262626;}.price {line-height: 1;font-size: 20rpx;color: #cf4444;}.number {font-size: 26rpx;margin-left: 2rpx;}}navigator {&:nth-child(even) {margin-right: 0;}}
}/* 底部工具栏 */
.toolbar {background-color: #fff;height: 100rpx;padding: 0 20rpx;border-top: 1rpx solid #eaeaea;display: flex;justify-content: space-between;align-items: center;box-sizing: content-box;.buttons {display: flex;& > view {width: 220rpx;text-align: center;line-height: 72rpx;font-size: 26rpx;color: #fff;border-radius: 72rpx;}.addcart {background-color: #ffa868;}.payment {background-color: #27ba9b;margin-left: 20rpx;}}.icons {padding-right: 10rpx;display: flex;align-items: center;flex: 1;.icons-button {flex: 1;text-align: center;line-height: 1.4;padding: 0;margin: 0;border-radius: 0;font-size: 20rpx;color: #333;background-color: #fff;}text {display: block;font-size: 34rpx;}}
}
</style>

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

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

相关文章

Xcode中如何操作Git

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

[云原生案例1.] 构建LNMP架构并运行Wordpress个人博客平台

文章目录 1. 当前需求2. 前置准备3. 搭建过程3.1 创建自定义网络3.2 部署并配置nginx3.2.1 创建工作目录并上传相关软件包3.2.2 解压缩相关软件包3.2.3 编写Dockerfile文件3.2.4 编写nginx.conf文件3.2.5 创建nginx镜像3.2.6 运行容器 3.3 部署并配置mysql3.3.1 创建工作目录3.…

Python机器学习基础(二)---数据可视化

一.简单图形生成 1.Pandas生成折线图 import pandas as pd import numpy as np from matplotlib import pyplot #生成10行4列 标准正态分布的数据 df pd.DataFrame(np.random.randn(10,4),indexpd.date_range(1/1/2000,periods10), columnslist(ABCD)) df.plot() print(np.r…

分布式理论和分布式锁知识点总结

文章目录 (一) 分布式理论算法和协议1&#xff09;CAP理论总结 2&#xff09;BASE理论BASE 理论的核心思想基本可用软状态最终一致性 3&#xff09;Paxos算法Basic Paxos 算法4&#xff09; Raft算法1 拜占庭将军 5&#xff09;Gossip协议 (二) 分布式锁分布式锁应该具备哪些条…

89 柱状图中最大的矩形

柱状图中最大的矩形 类似接雨水&#xff08;反过来&#xff0c;相当于找接雨水最少的一段&#xff09;题解1 暴力搜索&#xff08;超时&#xff09; O ( N 2 ) O(N^2) O(N2)另一种 题解2 单调栈【重点学习】常数优化 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的…

看完这个,别说你还找不到免费好用的配音软件

有很多小伙伴还在找配音工具&#xff0c;今天就给大家一次性分享四款免费好用的配音工具&#xff0c;每一个都经过测试&#xff0c;并且是我们自己也在用的免费配音工具 第一款&#xff0c;悦音配音工具 拥有强悍的AI智能配音技术&#xff0c;更专业&#xff0c;完美贴近真人配…

算法升级之路(六)

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 输入: numRows 1 输出: [[1]] 解题思路&…

Spring IOC - ConfigurationClassPostProcessor源码解析

上文提到Spring在Bean扫描过程中&#xff0c;会手动将5个Processor类注册到beanDefinitionMap中&#xff0c;其中ConfigurationClassPostProcessor就是本文将要讲解的内容&#xff0c;该类会在refresh()方法中通过调用invokeBeanFactoryPosstProcessors(beanFactory)被调用。 5…

php收发邮件的多种方法?

1、添加扩展&#xff1a; # 第一种&#xff1a; composer require php-imap/php-imap # 第二种&#xff1a; composer require phpmailer/phpmailer2、这里采用第二种方式&#xff1a; <?php declare(strict_types1);namespace App\Controller\v1\email;use App\Controll…

【Android知识笔记】换肤专题

换肤其实也属于插件化专题的一个子话题,之所以单独拿出来,是因为它的处理方式比较特殊,相比插件化而言较简单一些。 系统内置的换肤功能支持 - Theme Android 系统中如果想修改应用的背景色,最简单的就是利用以下Theme相关的属性: 使用这些内置的属性可以实现一定程度上…

计算机视觉的相机选型

#你一般什么时候会用到GPT?# 目前市面上的工业相机大多是基于CCD&#xff08;ChargeCoupled Device&#xff09;或CMOS&#xff08;Complementary Metal Oxide Semiconductor&#xff09;芯片的相机。一般CCD制造工艺更加复杂&#xff0c;也会更贵一点&#xff01; 1、CCD工…

django如何连接sqlite数据库?

目录 一、SQLite数据库简介 二、Django连接SQLite数据库 1、配置数据库 2、创建数据库表 三、使用Django ORM操作SQLite数据库 1、定义模型 2、创建对象 3、查询对象 总结 本文将深入探讨如何在Django框架中连接和使用SQLite数据库。我们将介绍SQLite数据库的特点&…

k8spod

pod基本概念 (几种容器) pod 是k8s最小的创建和运行单元 一个pod包含几个容器&#xff0c;1个根容器/父容器/基础容器&#xff0c;一个或者多个应用容器/业务容器&#xff0c;pause容器 pod里面容器共享 network UTS IPC命令空间 k8s 创建的Pod 分为两种&#xff1a; 自主…

Android NDK开发详解之ndk-gdb

Android NDK开发详解之ndk-gdb 要求用法选项 线程支持 NDK 包含一个名为 ndk-gdb 的 Shell 脚本&#xff0c;可以启动命令行原生调试会话。偏好使用 GUI 的用户则应阅读在 Android Studio 中调试这篇文档。 要求 要运行命令行原生调试&#xff0c;必须满足以下要求&#xff1…

C#中LINQtoSQL的设置与连接

目录 一、首次安装LinqToSql类 二、非首次安装LinqToSql类 1.接受原有数据库连接 2.建立新的数据库连接 3.建立本地数据库连接 LINQ&#xff08;Language-Integrated Query&#xff0c;语言集成查询&#xff09;是微软公司提供的一项新技术&#xff0c;它能够将查询功能直…

2023年【熔化焊接与热切割】考试题及熔化焊接与热切割模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【熔化焊接与热切割】考试题及熔化焊接与热切割模拟考试&#xff0c;包含熔化焊接与热切割考试题答案和解析及熔化焊接与热切割模拟考试练习。安全生产模拟考试一点通结合国家熔化焊接与热切割考试最新大纲及熔…

亲测有效!盘点3款好用的录屏软件

随着社会的发展&#xff0c;视频内容的制作和共享变得比以往任何时候都更重要。无论是录制在线课程、游戏过程&#xff0c;还是制作教程或视频演示&#xff0c;一款好用的录屏软件都能让用户事半功倍。接下来&#xff0c;我们将介绍三款各自适用于不同场景的录屏软件&#xff0…

C# Onnx Ultra-Fast-Lane-Detection-v2 车道线检测

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; usi…

科东软件受邀参加2023国家工业软件大会,共话工业软件未来

10月28日&#xff0c;由中国自动化学会主办的2023国家工业软件大会在浙江湖州开幕。大会以“工业软件智造未来”为主题&#xff0c;一批两院院士、千余名专家学者齐聚一堂&#xff0c;共同探讨工业软件领域前沿理论和技术创新应用问题&#xff0c;共同谋划我国工业软件未来发展…

实用篇-Linux

一、Linux介绍 linux特点 免费开源多用户多任务 Linux系统版本分为内核版和发行版 发行版是基于内核版进行扩展&#xff0c;由各个Linux厂商开发和维护&#xff0c;因为我们真正使用linux最终安装的其实是linux的发行版 下面以CentOS为例来学习Linux 二、Linux安装 安装方式…