功能描述
- 商品分类展示;
- 商品详情
- 商品搜索
- 订单详情(购物车)
- 登录与注册
注意:登录状态可以将书籍加入购物车,为登录状态只能浏览书籍。页面布局设计大体仿的【孔夫子旧书网】。
使用到的技术
- 项目创建;
- Vue指令应用:插值、数据绑定、计算属性、方法、侦听器、事件监听等 ;
- Vue组件创建和应用;
- Vue路由使用;
- 全局状态管理Vuex的使用;
- 前端基础知识的综合应用。
数据来源及描述
书籍数据文件位置:../data/books.js,使用的是模拟数据,数组名称为books,数据属性包括:
- isbn(书籍ISBN码,作为主键);
- bookname(书名);
- author(作者);
- type(书籍类型);
- price(单价);
- stock(库存);
- pubfirm(出版社);
- bookbrief(书籍简介);
- authorbrief(作者简介);
- good(是否为推荐书籍)。
全局状态变量设置(文件位置src>store>index.js):
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({state: {carts:[],user:[],mess:'',},getters:{total:function(state){var t=0;state.carts.forEach(function(ele){t+=ele.price*ele.num});return t;},count:function(state){var c=0;state.carts.forEach(function(ele){c+=ele.num});return c;},},mutations: {queryuser:function(state,user){var ele=state.user.find(function(ele){return ele.name==user.name//是否存在用户})if(ele) state.mess=ele.pwd//存在则返回用户信息else{return state.mess="f"}},reg:function(state,user){//添加用户state.user.push({...user})},addCart:function(state,book){var ele=state.carts.find(function(ele){return ele.isbn===book.isbn});if(ele) ele.num++else{state.carts.push({isbn:book.isbn,bookname:book.bookname,price:book.price,num:1})}},remove:function(state,index){state.carts.splice(index,1)}},actions: {},modules: {}
})
详细设计
为了读者能拥有良好的阅读体验,css代码统一放在文章结尾。
根页面
该页面包含三个子组件:Main.vue、PageShow.vue和ShopCart.vue。页面布局分为四个部分,登录通栏,显示一条语句和登录注册链接,登录后登录链接部分改为显示“书友+用户名”和退出登录链接。logo及搜索块,左边为logo图片,右边为书名搜索框和按钮。点击搜索按钮时若输入框不为空则跳转到“所有商品”页面展示搜索结果。导航块,显示三个子组件的路由链接,正在使用路由的链接变为绿色。下方则为路由视图部分,默认显示为首页子组件。
路由守卫,跳转除了首页和商品展示页以外的页面前判断是否登录。写在router下的index.js文件中。
App.vue被注释掉,留下一个路由窗口。
Home.vue替代作为根页面
<template>
<div id="Home"><!-- 登录通栏 --><div id="head"><div id="head-left">网罗天下图书 传承中华文明</div><div class="head-right"><ul> <li >{{username}}<span id="a" @click="init()">{{message}}</span></li></ul></div></div><!-- logo及搜索 --><div id="logo"><img alt="booklogo" src="../assets/logo.png"><form action=""><input v-model="bookname" type="text" id="searchinput" placeholder="请输入书名"><input @click="query()" type="button" value="搜索" id="formbutton"></form></div><!--导航 --><div id="nav"><table><tr><td><router-link to="/">首页</router-link></td><td><router-link to="pageshow">所有商品</router-link></td><td><router-link to="shopcart">购物车</router-link></td></tr></table></div><router-view/>
</div>
</template>
<style src="../style/home.css" scoped></style>
<script>
export default {data:function(){return{username:'',bookname:'',message:'登录/注册',}},mounted:function(){if(sessionStorage.username){this.username="书友"+sessionStorage.username+" /"this.message="退出登录"}},methods:{query:function(){if(this.bookname.trim()){this.$router.push({name:'pageshow',params:{bookname:this.bookname}})}},init:function(){if(sessionStorage.username){//已登录sessionStorage.removeItem("username")//注销登录}this.$router.push({path:'/init'})}},
}
</script>
首页
该页面为Main.vue,是Home.vue的子组件之一。主要布局包括横幅、广告活动、好书推荐。横幅为动态轮播图,好书推荐是书籍good属性值为1的书籍列表。点击好书推荐部分的书籍封面,将会跳转到“所有商品>书籍详情”页面。
页面HTML代码如下:
<template><div ><!--横幅 --><div id="banner"><div id="photo"><a href=""><img src="../assets/lb1.jpg"></a><a href=""><img src="../assets/lb2.jpg"></a><a href=""><img src="../assets/lb3.jpeg"></a><a href=""><img src="../assets/lb4.jpg"></a><a href=""><img src="../assets/lb5.jpg"></a></div></div><!-- 广告活动 --><div id="adver"><table><tr><td><a href=""><img src="../assets/pm1.png" class="pm"></a></td><td><a href=""><img src="../assets/pm2.png" class="pm"></a></td></tr><tr><td><a href=""><img src="../assets/pm3.png" class="pm"></a></td><td><a href=""><img src="../assets/pm4.png" class="pm"></a></td></tr><tr><td><a href=""><img src="../assets/pm5.png" class="pm"></a></td><td><a href=""><img src="../assets/pm6.jpg" class="pm"></a></td></tr></table></div><div id="gallery"><p><b>好书推荐</b></p><ul><li v-for="book in books1" :key="book.isbn"><span class="hlimg" @click="detail(book.isbn)"><img :src="require(`../assets/bookimg/${book.isbn}.jpg`)"></span><span class="title" >{{book.bookname}}</span><span class="writer">{{book.author}} 著</span><span class="price">¥{{book.price}}</span></li></ul></div><!--底部 --><div id="footer"><p>CSDN:由一说一 图书销售网站<br/>参考网站:<a href="https://www.kongfz.com/">孔夫子旧书网</a></p></div></div>
</template>
<script>
import {books} from "../data/books";
export default {data:function(){return{books1:[]}},computed:{books:() => books,},mounted:function(){this.goodshow()},methods:{detail:function(val){this.$router.push({name:'pageshow',params:{isbn:val}})},goodshow:function(){books.filter(item =>{if (item.good==1){this.books1.push({...item})}})}},
}
</script>
<style src="../style/main.css" scoped></style>
登录注册
该页面Init.vue包含两个子组件,Login.vue和Reg.vue。该页面布局主要分为两部分,头部显示一条语句和首页组件链接,主要容器包含一个图片和两个子组件路由链接和路由视图。路由视图默认显示登录页面。
路由路径代码如下:
登录注册初始页面init.vue代码如下:
<!--init.vue-->
<template><div id="init"><div id="head"><div id="head-left">网罗天下图书 传承中华文明</div><div id="head-right"><ul> <li ><router-link to="/">首页</router-link></li></ul></div></div><div id="logo"><img src="../assets/logo.png"/></div><div id="main"><div id="w"><div id="loginimg"><img src="../assets/init2.png" alt=""></div><div id="view"><div id=title><div id=title_left><router-link to="/init/">用户登录</router-link></div><div id=title_right><router-link to="/init/reg">用户注册</router-link></div></div><router-view/></div></div></div><div id="footer"><p>CSDN:由一说一 图书销售网站<br></p></div></div>
</template>
<style src="../style/init.css" scoped></style>
Login组件负责登录,接收到用户输入的信息后查询用户,“用户不存在”或“用户名或密码错误”则弹出提示,登录成功则跳转到首页并将用户信息存储到sessionStorage.username.
<!--Login.vue-->
<template><div id=form><span>用户名</span><input v-model="name" placeholder="请输入用户名" required autofocus><br><span>密码</span><input v-model="pwd" type="password" placeholder="请输入密码" required><br><button @click="login()" >登录</button><br><img class="ftimg" src="../assets/登录.png" alt=""></div>
</template>
<style src="../style/init.css" scoped></style>
<script>
export default {data:function(){return{name:"",pwd:"",}},methods:{login:function(){var user={name:this.name,pwd:this.pwd}this.$store.commit('queryuser',user)var mess=this.$store.state.messif(mess=='f'){alert("用户不存在")return}else if(this.pwd==mess){sessionStorage.username=this.namealert("欢迎━(*`∀´*)ノ亻!")this.$router.replace("/");//避免后退}else{alert("用户名或密码错误")}},},
}
</script>
Reg组件负责注册,接收到用户输入的信息后传送给$store的queryuser方法对全局状态变量user进行查找,若用户名已存在则弹出提示,否则将用户信息添加到全局变量user里,并自动登录跳转到首页。代码如下:
<template><div id=form><span>手机号码</span><input v-model="name" type="tel" title="请输入用户名" placeholder="请输入用户名" required autofocus><br/><span>密码</span><input v-model="pwd" type="password" placeholder="请输入密码" required><br/><button @click="register" >同意协议并注册</button><br/><img class="ftimg" src="../assets/注册.png"></div>
</template>
<style src="../style/init.css" scoped></style>
<script>
export default {data:function(){return{name:"",pwd:"",}},methods:{register:function(){var user={name:this.name,pwd:this.pwd}this.$store.commit('queryuser',user)var mess=this.$store.state.messif(mess=='f'){this.$store.commit('reg',user)alert("注册成功,将为你自动登录")sessionStorage.username=this.namethis.$router.replace("/");//避免后退}else{alert("用户名已存在")}},}
}
</script>
书籍页面显示
该页面为PageShow.vue,页面主要布局包括左边的分类筛选栏,和右边的组件显示块。页面PageShow.vue包含两个元素级子组件,Bookitems.vue和Detail.vue。
Bookitems负责显示书籍列表,默认显示所有书籍 。书名搜索和左边分类筛选功能都在pageshow页面查询后将的结果传送给该组件显示.点击该组件的书籍封面或书名即跳转到书籍详情。
Detail负责显示书籍详细信息,点击书籍封面可查看大图。
若未登录状态点击“加入购物车”按钮则会跳转到登录注册页面,子组件通过v-if 操控显示。
PageShow.vue页面代码如下:
<template><div id="page"><div id="query">{{num}}条结果</div><div id="main"><div id="left"><span>分类筛选:</span><div class="typeitem"><button @click="querytype('文学')">文学</button><button @click="querytype('历史')">历史</button><button @click="querytype('工学')">工学</button><button @click="querytype('理学')">理学</button><button @click="querytype('哲学')">哲学</button><button @click="querytype('小说')">小说</button><button @click="querytype('社会文化')">社会文化</button><button @click="querytype('自然科学')">自然科学</button></div></div><div id="right"><!-- 若搜索内容为空则输出全部书籍 --><template v-if="tf"><Bookitems :books="books1==null?books:books1" :mess="mess" @change="onchange"></Bookitems></template><template v-if="!tf"><Detail :book="book" @change="onchange"></Detail></template></div></div></div>
</template>
<style src="../style/pageshow.css" scoped>
</style>
<script>
import {books} from "../data/books";
import Bookitems from '../components/Bookitems.vue';
import Detail from '../components/Detail.vue'
export default {name: 'PageShow',components: {//组件Bookitems,Detail,},data:function(){return{bookname:this.$route.params.bookname?this.$route.params.bookname:null,mess:'',book:{},tf:true,books1:null,}},computed:{books:() => books,num(){return this.books1==null?this.books.length:this.books1.length}},mounted:function(){this.query()},methods:{querytype:function(type){this.tf=truethis.books1=[]books.forEach(item =>{if (item.type===type){this.books1.push({...item})}})},query:function(){if(this.$route.params.bookname){//Home查询书名结果this.bookname=this.$route.params.booknamethis.books1=[]books.filter(item =>{if (item.bookname.indexOf(this.bookname)>-1){this.books1.push({...item})}})if(this.books1.length==0) return this.mess="该书籍暂未入库"this.tf=true}if(this.$route.params.isbn){//Main点击书籍图片跳转详情books.filter(item =>{if (item.isbn==this.$route.params.isbn){this.book=item}})this.tf=false}},onchange:function(book){this.book=book,this.tf=!this.tf},},
}
</script>
书籍列表Bookitems.vue代码如下:
<template><div><div id="bookresult"><div class="item" v-for="book in books" :key="book.isbn"><span id="img-div"><img :src="require(`../assets/bookimg/${book.isbn}.jpg`)" @click="$emit('change',book)"></span><div class="bookmess"><span id="bookname" @click="$emit('change',book)">{{book.bookname}}</span><span>作者:{{book.author}}</span><span>出版社:{{book.pubfirm}}</span><span>类型:{{book.type}}</span></div><div class="money"><span id="num">¥{{book.price}}</span><span>库存:{{book.stock}}</span><button @click="addCart(book)">加入购物车</button></div></div><h3>{{mess}}</h3></div><!--底部 --><div id="footer"><p>CSDN:由一说一 图书销售网站<br/>参考网站:<a href="https://www.kongfz.com/">孔夫子旧书网</a></p></div></div>
</template>
<script>
export default {name: 'Bookitems',props: {books: [],mess:null,},methods:{addCart:function(book){if(sessionStorage.username){this.$store.commit('addCart',book)}else{this.$router.push({path:'/init'})}}},
}
</script>
<style src="../style/bookresult.css" scoped></style>
书籍详情Detail.vue代码如下:
<template><div><div class="detail"><span class="title">书籍详细信息</span><span id="link" @click="$emit('change','')">< 返回书籍列表</span><div class="info-main"><span id="img-div"><viewer><img :src="require(`../assets/bookimg/${book.isbn}.jpg`)"></viewer></span><div class="info-text"><p>{{book.bookname}}</p><div class="list-left"><span>作者:{{book.author}}</span><span>出版社:{{book.pubfirm}}</span><span>ISBN:{{book.isbn}}</span></div><div class="list-right"><span>类型:{{book.type}}</span><span>价格:{{book.price}}</span><button @click="addCart(book)">加入购物车</button></div></div></div><div class="brief"><dl><dt>内容简介:</dt><dd>{{book.bookbrief}}</dd></dl><dl><dt>作者简介:</dt><dd>{{book.authorbrief}}</dd></dl></div></div><!--底部 --><div id="footer"><p>CSDN:由一说一 图书销售网站<br/>参考网站:<a href="https://www.kongfz.com/">孔夫子旧书网</a></p></div></div>
</template>
<script>
export default {name:"Detail",props:{book:{},},methods:{addCart:function(book){if(sessionStorage.username){this.$store.commit('addCart',book)}else{this.$router.push({path:'/init'})}}},
}
</script>
<style src="../style/detail.css" scoped></style>
点击封面查看大图代码如下写在src>main.js文件中():
// 引入查看大图插件
import Viewer from 'v-viewer'
import 'viewerjs/dist/viewer.css'Vue.use(Viewer)
Viewer.setDefaults({Options: { // Options必须,否则会出现默认打开等等不可预知的错误'inline': true, 'button': true, // 显示右上角关闭按钮'navbar': false, // 缩略图导航'title': true, // 是否显示当前图片的标题'toolbar': false, // 显示工具栏'tooltip': true, // 显示缩放百分比'movable': false, // 图片是否可移动'zoomable': false, // 是否可缩放'rotatable': false, // 是否可旋转'scalable': false, // 是否可翻转'transition': true, // 是否使用 CSS3 过度'fullscreen': true, // 播放时是否全屏'keyboard': true, // 是否支持键盘'url': 'data-source' // 设置大图片的 url}
})
购物车
页面ShopCart.vue负责显示购物车信息。包括书籍封面、书名、单价、数量、小计和删除操作,最下方左边显示总金额和总商品数量,右边显示结算按钮。其中商品数量部分由元素级组件numbtn显示,提供按钮进行数量增减操作。购物车数据为全局状态变量。
购物车页面ShopCart.vue代码如下:
<template><div class="shopcart"><table id="tb" v-><tr id="tr1"><td colspan="2">商品</td><td>单价</td><td>数量</td><td>小计</td><td>操作</td></tr><tr v-for="cart,index in carts" :key="cart.id" id="items"><td><img :src="require(`../assets/bookimg/${cart.isbn}.jpg`)"></td><td><span>{{cart.bookname}}</span></td><td>{{cart.price}}</td><td><Numbtn :sp="cart"></Numbtn></td><td><span>{{cart.price*cart.num}}</span></td><td><button @click="remove(index)">删除</button></td></tr></table><div id="bottom"> 总价:{{total}},数量:{{count}}<button>结算</button></div></div>
</template>
<style src="../style/shopcart.css" scoped></style>
<script>
import { mapGetters, mapMutations, mapState } from 'vuex'
import Numbtn from '../components/numbtn.vue'
export default {components: {//组件Numbtn},computed:{ ...mapState(['carts']),...mapGetters(['total','count']),},methods:{...mapMutations(['remove'])},
}
</script>
元素级组件numbtn.vue代码如下:
<template><div><button @click="num(sp,-1)">-</button><span>{{sp.num}}</span><button @click="num(sp,1)">+</button></div>
</template>
<script>
export default {name:'numbtn',props:{sp:{},},methods:{num:function(sp,x){if(x==-1){if(sp.num<=0) return sp.num=0;else return sp.num--;}if(x==1){if(sp.num>=sp.stock) return sp.num=sp.stock;else return sp.num++;}},},}
</script>
<style scoped>
span{width: 30px;display: inline-block;
}
</style>
css部分
home.css
#head{width:100%;height:36px;background: #8c222c;float: left;
}
#head-left{width:157px;left: 280px;position:absolute;line-height: 36px;font-size: 12px;color: #e2c8ca;
}
ul{margin: 0px;padding: 0px;
}
.head-right{width:570px;right:280px;font-size: 14px;position: absolute;line-height: 36px;z-index: 1;
}
.head-right ul li{height:100%;list-style: none;float: left;display: inline;text-align: center;color: #e2d5d6;
}
#a{color: #e2d5d6;font-size: 13px;text-decoration: none;padding-left: 5px;
}
#a:hover{color: #ffffff;
}
#logo{height:130px;background: #f2f1ea;
}
#logo img{width:18%;margin-left: 275px;float: left;position: relative;top: 18px;
}
#logo form{height:35px;width:588px;font-size: 12px;right: 280px;position: absolute;top:65px;
}
#searchinput{height:32px;width:486px;border:none;line-height: 14px;border: 2px solid #8c222c;margin: 0px;position: relative;float: left;
}
#formbutton{width:76px;height:37px;margin-right: 0px;color: #fff;background-color: #8c222c;float: left;
}
#nav{height:50px;font-size: 18px;background: #fff;
}
#nav table{width:278px;height:50px;position: relative;left:275px;text-align: center;margin: 0px;}
#nav a:link,#nav a{text-decoration: none;color: black;
}
#nav a:hover{border-bottom: 2px solid rgb(151, 141, 141);
}
/* 使用样式 */
#nav a.router-link-exact-active {color: #42b983;}
init.css
/* 样式文件名:init.css
应用:登录注册页面
应用对象:init.vue*/#head{width:100%;height:36px;background: #8c222c;float: left;
}
#head-left{width:157px;left: 280px;position:absolute;line-height: 36px;font-size: 12px;color: #e2c8ca;
}
ul{margin: 0px;padding: 0px;
}
#head-right{width:570px;right:280px;font-size: 14px;position: absolute;line-height: 36px;z-index: 1;
}
#head-right ul li{height:100%;width:95px;list-style: none;float: left;display: inline;text-align: center;
}
#head-right ul li a{color: #e2d5d6;text-decoration: none;display: block;
}
#logo{height:130px;background: #f2f1ea;
}
#logo img{width:18%;margin-left: 275px;float: left;position: relative;top: 18px;
}#main{width:100%;height:530px;text-align: center;background-color:rgb(253, 252, 247);padding: 0px;}#w{width:897px;height:100%;margin:0 auto;} #loginimg{float:left;position:relative;top: 70px;}#loginimg img{width:400px;padding: 0px 50px;}#view{width:389px;height:340px;position:relative;float:left;top:95px;border: 3px solid rgba(137,153,169,.2);border-radius: 19px;background-color: rgb(253, 253, 253);}/*border-radius设置圆角*/#title{height:24px;padding: 28px 37px;}
#title a{font:bold 24px 行楷;text-decoration: none;color:rgb(167, 197, 221);
}/*设置字体大小样式、取消下划线*/
#title a:hover{color: rgb(62, 116, 233);
}
#title_left{width:155px;border-right: 1px solid #ccc;text-align: center;float: left;
}
#title_right{width:155px;float: left;text-align: center;
}
#title a.router-link-exact-active {color:rgb(62, 116, 233);}
#form{width:335px;height:230px;position:relative;float:left;padding:0px 25px;
}
#form input{width:208px;height:23px;margin: 10px;
}span{display: inline-block;text-align: center;width:66px;height:23px;
}
#form button{width:218px;height:36px;border-radius: 3px;line-height: 34px;font-size: 16px;margin:10px 10px 10px 77px;background-color: rgb(147, 181, 224);color: rgb(255, 255, 255);border-color:rgb(162, 194, 235) ;
}
.ftimg{position: relative;top:0px;display: block;max-width: 70%;/* 控制图片大小 */max-height:80px;min-width: 30%;min-height: 80px;}
#footer{width:100%;height:32px;font-size: 10px;text-align: center;background-color:rgb(255, 255, 255);vertical-align: middle;position: absolute;top:678px;
}
main.css
#banner{width:810px;height:270px;position: relative;overflow: hidden;left:350px;
}
#photo{width:4050px;height:270px;animation: switch 10s ease-out infinite;
}
#photo img{float: left;width:810px;height:270px;
}
@keyframes switch {0%, 20% {margin-left: 0;}21%, 40% {margin-left: -810px;}41%, 60% {margin-left: -1620px;}61%,80%{margin-left:-2430px}81%,100%{margin-left:-3240px}
}
#adver{width:1150px;height:107px;margin-top: 8px;position: relative;left:350px;
}
#adver table img{width:404px;height:35px;margin: 0px;
}
#gallery{background-color: #fcf9f9;height:570px;margin: 0 340px;border-bottom: 1px solid #ccc;
}
#gallery p{/* width:810px; */height: 22px;margin-bottom: 18px;border-bottom: 1px solid #ccc;margin-top: 20px;padding:10px 0px 10px 5px;}
#gallery ul{width:810px;text-align: justify;list-style: none;
}
#gallery ul li{width:140px;height:220px;position: relative;float: left;margin-bottom: 35px;margin-right: 20px;
}
#gallery span{display:block;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;/*用省略号替代多余文字*/
}
.hlimg{height:150px;
}
.hlimg img{width:100%;
}
.title{font-size: 15px;
}
.writer{font-size: 8px;color: rgb(114, 114, 112);line-height: 20px;margin-bottom: 5px;
}
.price{font-size: 16px;color: rgb(230, 152, 64);
}
#footer{width:100%;height:60px;text-align: center;position: relative;bottom: 5px;border-top: #ccc 2px;
}
pageshow.css
#page{height:100%;margin:0px 270px;position: relative;
}
#query{height:20px;/* border: 2px solid #e90fe9; */padding: 10px 0px;font-size: 14px;
}
#left{width: 180px;height: 100%;background: #f7f7f6;border-top: 1px solid #e5e5e5;border-right: 1px solid #e5e5e5;padding: 0 10px 16px 15px;position: relative;
}
#left span{margin-top: 18px;padding-bottom: 1px;font-size: 18px;color: #999;line-height: 20px;
}
/* #type1{padding: 10px;font-weight: 600;
} */
.typeitem button{display: block;margin: 10px;border: 0px;background-color: #f7f7f6;font-size: 15px;color: black;line-height: 25px;
}
.typeitem button:hover{border-bottom: 1px solid #999;
}
#right{border-top: 1px solid #e5e5e5;width:740px;height: 100%;position: absolute;left: 206px;top: 40px;padding-left: 30px;
}
bookresult.css
.item{padding: 20px 0;position: relative;border-bottom: 1px solid #e5e5e5;font:caption 13px 宋体;color:#000000;
}
#img-div{width: 130px;height: 130px;display: inline-block;text-align: center;border: 2px solid #e5e5e5;
}
.item img{max-width: 130px;max-height:130px;
}.bookmess{width: 460px;height:130px;display: inline-block;/* 换为行内块级元素 */padding: 0 15px;position: absolute;}
.bookmess span{display: block;/* 换为块级元素 */padding: 6px 0;
}
#bookname{font: 450 18px 行楷;color: #8c222c;
}
.money{display: inline-block;position: absolute;left: 630px;
}
.money span{display: block;padding: 5px 0;}
#num{font: 700 20px 宋体;color: #8c222c;
}
.money button{display:block;padding: 2px 5px;margin-top: 38px;border: 1px solid #f55212;background-color: #ffffff;color: #f55212;
}
#footer{width:100%;height:60px;text-align: center;position: relative;bottom: 5px;border-top: #ccc 2px;
}
detail.css
.detail{position: relative;border: 2px solid rgba(137,153,169,.2);width: 740px;height: auto;padding: 15px;margin-top: 15px;
}
.title{position: absolute;top:-10px;right: 20px;padding: 0 10px;background-color: rgb(255, 255, 255);font-size: 15px;font-weight: bolder;color: rgba(137,153,169,.5);
}
#link{display: block;text-align: left;font-size: 14px;color: rgb(99, 170, 236);
}
.info-main{padding-top: 15px;
}
#img-div{width: 150px;height: 150px;display: inline-block;text-align: center;
}
.info-main img{max-width: 150px;max-height:150px;}
.info-text{float: right;width: 570px;
}
.info-text p{margin: 0;margin-bottom: 10px;font: 600 18px 宋体;
}
.info-text span{display: block;padding: 5px;font: 400 15px 楷体;
}
.list-left{float: left;width: 300px;
}
.list-right{float: left;
}
.list-right button{padding: 2px 5px;border: 1px solid #f55212;background-color: #ffffff;color: #f55212;
}
dl,dt,dd{margin: 0;padding: 0;list-style: none;line-height: 22px;
}
.brief dl{padding-top: 20px;
}
.brief dt{font-weight: bolder;padding-bottom: 5px;
}
.brief dd{font-size: 14px;font-weight: 400;
}
#footer{width:100%;height:60px;text-align: center;position: relative;bottom: 5px;border-top: #ccc 2px;
}
shopcart.css
.shopcart{height:100%;margin:0px 270px;position: relative;
}
table{border-collapse: collapse;/* 两条边框合并为一条 */width: 980px;
}
table,tr{text-align: center;font: 200 17px 宋体;
}
table td{border-bottom: 2px solid #d8d8d8;padding: 20px;
}
tr img{max-width: 100px;max-height: 100px;border: 2px solid #e5e5e5;
}
span{color: #8c222c;
}
#bottom button{float: right;margin: 0px;width: 100px;height: 40px;background-color: #8c222c;color: aliceblue;font: 400 18px 行楷;
}
如果对你有帮助的话给我一个赞吧,这个作品是我的期末作业,时间比较紧很多地方写的粗糙,见谅。
以上是该网站的完整代码,如果懒得复制的话我也有打包完整资源在我的个人主页>资源区有分享。
【因为这个是用到vue的,所以运行前先打开终端输入(npm i),等相关资源下载完成再运行】