效果图
编辑
编辑
编辑 源码如下
页面设计
<template> <div class="container"> <!--商品详情 start--> <van-image class="goods-item-image" :src="goods.goodsHeadImg"></van-image> <div class="goods-price"> ¥<span>{{ goods.goodsPrice }}</span>.00起 </div> <div class="goods-name"> <el-button round size="small">{{ goods.goodsBrand.goodsBrandName }}</el-button> <span>{{ goods.goodsName }}</span> <span>{{ goods.goodsCaption }}</span> </div> <div class="goods-introduction"> <el-input style="width: 100%;" type="textarea" autosize v-model="goods.goodsIntroduction"></el-input> <!-- <el-text>{{ goods.goodsIntroduction }}</el-text>--> </div> <div class="goods-images" v-for="(img,imgIndex) in goods.images" :key="imgIndex"> <van-image class="goods-item-image" :src="img.goodsImageUrl"></van-image> </div> <!--商品详情 end--> <!--底部导航 start--> <van-action-bar style="margin-bottom: 50px "> <van-action-bar-icon icon="chat-o" text="客服" badge="12"/> <van-action-bar-icon icon="cart-o" text="购物车" badge="6" @click="onCartShow"/> <van-action-bar-icon icon="shop-o" text="店铺" badge="5"/> <van-action-bar-button type="warning" text="加入购物车" @click="onAddCartShow"/> <van-action-bar-button type="danger" text="立即购买"/> </van-action-bar> <!--底部导航 end--> <!--加入购物车弹出框 end--> <van-popup v-model:show="showCart" position="bottom" closeable> <div class="add-cart-show"> <!--顶部 start--> <div class="add-header"> <van-image class="add-goods-img" radius="10" :src="goods.goodsHeadImg"></van-image> <div class="add-goods-price"> ¥<span>{{ goods.goodsPrice }}</span> </div> </div> <!--顶部 end--> <!--地址 start--> <AddressList class="add-address"/> <!--地址 end--> <!--规格 start--> <div class="add-goods-specification"> <span class="goodsSpecificationName">{{ goods.specifications[0].goodsSpecificationName }}</span> <el-radio-group v-for="(o,index2) in goods.specifications[0].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio1" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[1]" class="goodsSpecificationName">{{ goods.specifications[1].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[1]" v-for="(o,index2) in goods.specifications[1].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio2" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[2]" class="goodsSpecificationName">{{ goods.specifications[2].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[2]" v-for="(o,index2) in goods.specifications[2].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio3" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[3]" class="goodsSpecificationName">{{ goods.specifications[3].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[3]" v-for="(o,index2) in goods.specifications[3].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio4" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[4]" class="goodsSpecificationName">{{ goods.specifications[4].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[4]" v-for="(o,index2) in goods.specifications[4].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio5" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[5]" class="goodsSpecificationName">{{ goods.specifications[5].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[5]" v-for="(o,index2) in goods.specifications[5].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio6" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> </div> <!--规格 end--> <!--底部 start--> <el-button class="add-goods-button" size="large" color="#ff9003" round @click="onAddCart">加入购物车</el-button> <!--底部 end--> </div> </van-popup> <!--加入购物车弹出框 end--> </div> </template>
逻辑编写
<script setup> import {onMounted, reactive, ref} from "vue"; import axios from "@/utils/request" import {useRoute, useRouter} from "vue-router" import {useDataStore} from "../../stores/dataStore" import AddressList from "../../components/AddressList/Index.vue" import {showSuccessToast} from 'vant'; const router = useRouter() const dataStore = useDataStore() const route = useRoute() //单选框选中的规格数据 const radio1 = ref("") const radio2 = ref("") const radio3 = ref("") const radio4 = ref("") const radio5 = ref("") const radio6 = ref("") //加入购物车弹出框控制器 const showCart = ref(false) //商品id const goodsId = route.params.name //商品数据 const goods = reactive({ goodsId: "", goodsHeadImg: "", goodsName: "", goodsCaption: "", goodsPrice: "", goodsIntroduction: "", goodsUse: "", goodsBrand: "", goodsType1: "", goodsType2: "", goodsType3: "", images: "", specifications: "" }) onMounted(() => { axios.get("front/goods/findDesc", { params: { goodsId: goodsId } }).then(res => { if (res.data.code == 200) { goods.goodsId = res.data.data.goodsId goods.goodsHeadImg = res.data.data.goodsHeadImg goods.goodsName = res.data.data.goodsName goods.goodsCaption = res.data.data.goodsCaption goods.goodsPrice = res.data.data.goodsPrice goods.goodsIntroduction = res.data.data.goodsIntroduction goods.goodsUse = res.data.data.goodsUse goods.goodsBrand = res.data.data.goodsBrand goods.goodsType1 = res.data.data.goodsType1 goods.goodsType2 = res.data.data.goodsType2 goods.goodsType3 = res.data.data.goodsType3 goods.images = res.data.data.images goods.specifications = res.data.data.specifications } }) }) /** * 加入购物车弹出框 */ const onAddCartShow = () => { if (!dataStore.isLogin) { router.push("/home/login") } else { showCart.value = true } } /** * 加入购物车 */ const onAddCart = () => { axios.post("front/cart/addGoodsCart", { userId: dataStore.userId, goodsId: goodsId, goodsHeadImg: goods.goodsHeadImg, goodsName: goods.goodsName, goodsPrice: goods.goodsPrice, specificationContent: radio1.value + " " + radio2.value + " " + radio3.value + " " + radio4.value + " " + radio5.value + " " + radio6.value, num: 1, }).then(res => { if (res.data.code == 200) { showSuccessToast('加入成功'); showCart.value = false } }) } /** * 查看购物车 */ const onCartShow = () => { router.push("/home/cart") } </script>
样式设计
<style scoped> .container { background-color: #ffffff; } /** 商品数据样式 */ .goods-price { margin-top: 10px; color: #ff4142; } .goods-price span { font-style: normal; font-family: JDZH-Regular, sans-serif; display: inline-block; font-size: 22px; font-weight: 500; line-height: normal; color: #f44d0b; } .goods-name { font-size: 21px; color: #181818; font-family: JDZH-Regular, sans-serif; } .goods-name button { margin: 4px; display: inline; color: #fdfdff; font-weight: 400; background-color: #fe012d; } .goods-introduction { background-color: #f9f9f9; font-size: 12px; margin-top: 10px; margin-bottom: 10px; } .goods-name span { margin-left: 5px; font-size: 16px; font-weight: bold; } /* 加入购物车弹出框样式 */ .add-cart-show { height: 600px; } .add-header { display: flex; left: 10px; background-color: #ffffff; } .add-goods-img { margin: 10px; width: 80px; } .add-goods-price { margin-left: 20px; margin-top: 35px; color: #ff4142; font-size: 15px; } .add-goods-price span { font-style: normal; font-family: JDZH-Regular, sans-serif; display: inline-block; font-size: 32px; font-weight: 500; line-height: normal; color: #f44d0b; } /** 地址 */ .add-address { margin-top: 10px; } /** 规格 */ .add-goods-specification { margin: 20px; } .goodsSpecificationName { display: block; line-height: 37px; color: #121212; font-size: 14px; font-weight: 700; } .goodsSpecificationOption { margin: 2px; } /** 底部 */ .add-goods-button { position: fixed; bottom: 10px; left: 10px; width: 350px; color: #faf7e7; font-weight: 700; } </style>
全部代码
<template> <div class="container"> <!--商品详情 start--> <van-image class="goods-item-image" :src="goods.goodsHeadImg"></van-image> <div class="goods-price"> ¥<span>{{ goods.goodsPrice }}</span>.00起 </div> <div class="goods-name"> <el-button round size="small">{{ goods.goodsBrand.goodsBrandName }}</el-button> <span>{{ goods.goodsName }}</span> <span>{{ goods.goodsCaption }}</span> </div> <div class="goods-introduction"> <el-input style="width: 100%;" type="textarea" autosize v-model="goods.goodsIntroduction"></el-input> <!-- <el-text>{{ goods.goodsIntroduction }}</el-text>--> </div> <div class="goods-images" v-for="(img,imgIndex) in goods.images" :key="imgIndex"> <van-image class="goods-item-image" :src="img.goodsImageUrl"></van-image> </div> <!--商品详情 end--> <!--底部导航 start--> <van-action-bar style="margin-bottom: 50px "> <van-action-bar-icon icon="chat-o" text="客服" badge="12"/> <van-action-bar-icon icon="cart-o" text="购物车" badge="6" @click="onCartShow"/> <van-action-bar-icon icon="shop-o" text="店铺" badge="5"/> <van-action-bar-button type="warning" text="加入购物车" @click="onAddCartShow"/> <van-action-bar-button type="danger" text="立即购买"/> </van-action-bar> <!--底部导航 end--> <!--加入购物车弹出框 end--> <van-popup v-model:show="showCart" position="bottom" closeable> <div class="add-cart-show"> <!--顶部 start--> <div class="add-header"> <van-image class="add-goods-img" radius="10" :src="goods.goodsHeadImg"></van-image> <div class="add-goods-price"> ¥<span>{{ goods.goodsPrice }}</span> </div> </div> <!--顶部 end--> <!--地址 start--> <AddressList class="add-address"/> <!--地址 end--> <!--规格 start--> <div class="add-goods-specification"> <span class="goodsSpecificationName">{{ goods.specifications[0].goodsSpecificationName }}</span> <el-radio-group v-for="(o,index2) in goods.specifications[0].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio1" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[1]" class="goodsSpecificationName">{{ goods.specifications[1].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[1]" v-for="(o,index2) in goods.specifications[1].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio2" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[2]" class="goodsSpecificationName">{{ goods.specifications[2].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[2]" v-for="(o,index2) in goods.specifications[2].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio3" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[3]" class="goodsSpecificationName">{{ goods.specifications[3].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[3]" v-for="(o,index2) in goods.specifications[3].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio4" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[4]" class="goodsSpecificationName">{{ goods.specifications[4].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[4]" v-for="(o,index2) in goods.specifications[4].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio5" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> <span v-if="goods.specifications[5]" class="goodsSpecificationName">{{ goods.specifications[5].goodsSpecificationName }}</span> <el-radio-group v-if="goods.specifications[5]" v-for="(o,index2) in goods.specifications[5].goodsSpecificationOptions" :key="index2" direction="horizontal" v-model="radio6" fill="#018cel" text-color="#ffffff"> <el-radio-button class="goodsSpecificationOption" :label="o.goodsSpecificationOptionName"></el-radio-button> </el-radio-group> </div> <!--规格 end--> <!--底部 start--> <el-button class="add-goods-button" size="large" color="#ff9003" round @click="onAddCart">加入购物车</el-button> <!--底部 end--> </div> </van-popup> <!--加入购物车弹出框 end--> </div> </template> <script setup> import {onMounted, reactive, ref} from "vue"; import axios from "@/utils/request" import {useRoute, useRouter} from "vue-router" import {useDataStore} from "../../stores/dataStore" import AddressList from "../../components/AddressList/Index.vue" import {showSuccessToast} from 'vant'; const router = useRouter() const dataStore = useDataStore() const route = useRoute() //单选框选中的规格数据 const radio1 = ref("") const radio2 = ref("") const radio3 = ref("") const radio4 = ref("") const radio5 = ref("") const radio6 = ref("") //加入购物车弹出框控制器 const showCart = ref(false) //商品id const goodsId = route.params.name //商品数据 const goods = reactive({ goodsId: "", goodsHeadImg: "", goodsName: "", goodsCaption: "", goodsPrice: "", goodsIntroduction: "", goodsUse: "", goodsBrand: "", goodsType1: "", goodsType2: "", goodsType3: "", images: "", specifications: "" }) onMounted(() => { axios.get("front/goods/findDesc", { params: { goodsId: goodsId } }).then(res => { if (res.data.code == 200) { goods.goodsId = res.data.data.goodsId goods.goodsHeadImg = res.data.data.goodsHeadImg goods.goodsName = res.data.data.goodsName goods.goodsCaption = res.data.data.goodsCaption goods.goodsPrice = res.data.data.goodsPrice goods.goodsIntroduction = res.data.data.goodsIntroduction goods.goodsUse = res.data.data.goodsUse goods.goodsBrand = res.data.data.goodsBrand goods.goodsType1 = res.data.data.goodsType1 goods.goodsType2 = res.data.data.goodsType2 goods.goodsType3 = res.data.data.goodsType3 goods.images = res.data.data.images goods.specifications = res.data.data.specifications } }) }) /** * 加入购物车弹出框 */ const onAddCartShow = () => { if (!dataStore.isLogin) { router.push("/home/login") } else { showCart.value = true } } /** * 加入购物车 */ const onAddCart = () => { axios.post("front/cart/addGoodsCart", { userId: dataStore.userId, goodsId: goodsId, goodsHeadImg: goods.goodsHeadImg, goodsName: goods.goodsName, goodsPrice: goods.goodsPrice, specificationContent: radio1.value + " " + radio2.value + " " + radio3.value + " " + radio4.value + " " + radio5.value + " " + radio6.value, num: 1, }).then(res => { if (res.data.code == 200) { showSuccessToast('加入成功'); showCart.value = false } }) } /** * 查看购物车 */ const onCartShow = () => { router.push("/home/cart") } </script> <style scoped> .container { background-color: #ffffff; } /** 商品数据样式 */ .goods-price { margin-top: 10px; color: #ff4142; } .goods-price span { font-style: normal; font-family: JDZH-Regular, sans-serif; display: inline-block; font-size: 22px; font-weight: 500; line-height: normal; color: #f44d0b; } .goods-name { font-size: 21px; color: #181818; font-family: JDZH-Regular, sans-serif; } .goods-name button { margin: 4px; display: inline; color: #fdfdff; font-weight: 400; background-color: #fe012d; } .goods-introduction { background-color: #f9f9f9; font-size: 12px; margin-top: 10px; margin-bottom: 10px; } .goods-name span { margin-left: 5px; font-size: 16px; font-weight: bold; } /* 加入购物车弹出框样式 */ .add-cart-show { height: 600px; } .add-header { display: flex; left: 10px; background-color: #ffffff; } .add-goods-img { margin: 10px; width: 80px; } .add-goods-price { margin-left: 20px; margin-top: 35px; color: #ff4142; font-size: 15px; } .add-goods-price span { font-style: normal; font-family: JDZH-Regular, sans-serif; display: inline-block; font-size: 32px; font-weight: 500; line-height: normal; color: #f44d0b; } /** 地址 */ .add-address { margin-top: 10px; } /** 规格 */ .add-goods-specification { margin: 20px; } .goodsSpecificationName { display: block; line-height: 37px; color: #121212; font-size: 14px; font-weight: 700; } .goodsSpecificationOption { margin: 2px; } /** 底部 */ .add-goods-button { position: fixed; bottom: 10px; left: 10px; width: 350px; color: #faf7e7; font-weight: 700; } </style>