基于Vue2的图书销售网站(HTML+CSS+JS)

 【完整代码已贴出。完整项目资源包可在我的资源区下载】

功能描述 

  1. 商品分类展示;
  2. 商品详情
  3. 商品搜索
  4. 订单详情(购物车)
  5. 登录与注册

注意:登录状态可以将书籍加入购物车,为登录状态只能浏览书籍。页面布局设计大体仿的【孔夫子旧书网】

使用到的技术

  1. 项目创建;
  2. Vue指令应用:插值、数据绑定、计算属性、方法、侦听器、事件监听等 ;
  3. Vue组件创建和应用;
  4. Vue路由使用;
  5. 全局状态管理Vuex的使用;
  6. 前端基础知识的综合应用。

数据来源及描述

书籍数据文件位置:../data/books.js,使用的是模拟数据,数组名称为books,数据属性包括:

  1. isbn(书籍ISBN码,作为主键);
  2. bookname(书名);
  3. author(作者);
  4. type(书籍类型);
  5. price(单价);
  6. stock(库存);
  7. pubfirm(出版社);
  8. bookbrief(书籍简介);
  9. authorbrief(作者简介);
  10. 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">
      网罗天下图书&nbsp;&nbsp;传承中华文明
    </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:由一说一&nbsp;&nbsp;&nbsp;图书销售网站<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">
                网罗天下图书&nbsp;&nbsp;传承中华文明
            </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:由一说一&nbsp;&nbsp;&nbsp;图书销售网站<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:由一说一&nbsp;&nbsp;&nbsp;图书销售网站<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','')">&#60;&nbsp;返回书籍列表</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:由一说一&nbsp;&nbsp;&nbsp;图书销售网站<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运行】

评论 39
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋月华星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值