【完整代码已贴出。完整项目资源包可在我的资源区下载】
功能描述
- 商品分类展示;
- 商品详情
- 商品搜索
- 订单详情(购物车)
- 登录与注册
注意:登录状态可以将书籍加入购物车,为登录状态只能浏览书籍。页面布局设计大体仿的【孔夫子旧书网】。
使用到的技术
- 项目创建;
- 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.mess
if(mess=='f'){
alert("用户不存在")
return
}
else if(this.pwd==mess){
sessionStorage.username=this.name
alert("欢迎━(*`∀´*)ノ亻!")
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.mess
if(mess=='f'){
this.$store.commit('reg',user)
alert("注册成功,将为你自动登录")
sessionStorage.username=this.name
this.$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=true
this.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.bookname
this.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 行楷;
}
如果对你有帮助的话给我一个赞吧,这个作品是我的期末作业,时间比较紧很多地方写的粗糙,见谅。
以上是该网站的完整代码,如果懒得复制的话我也有打包完整资源在我的个人主页>资源区有分享。
【使用vscode打开,新建终端后输入输入(npm i),等相关资源下载完成再输入npm run serve运行】