twelve_前后端分离轮播_导航栏

2. 日志配置
# 在settings/dev.py文件中追加如下配置 # 日志配置 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(module)s %(lineno)d %(message)s' }, }, 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, 'handlers': { 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'file': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 日志位置,日志文件名,日志保存目录必须手动创建 'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/luffy.log"), # 日志文件的最大值,这里我们设置300M 'maxBytes': 300 * 1024 * 1024, # 日志文件的数量,设置最大日志数量为10 'backupCount': 10, # 日志格式:详细格式 'formatter': 'verbose' }, }, # 日志对象 'loggers': { 'django': { 'handlers': ['console', 'file'], 'propagate': True, # 是否让日志信息继续冒泡给其他的日志处理系统 }, } } # 注:有些人用django不行的可以改成luffy
2.1 异常处理
# 新建utils/exceptions.py from rest_framework.views import exception_handler from django.db import DatabaseError from rest_framework.response import Response from rest_framework import status import logging logger = logging.getLogger('luffy') def custom_exception_handler(exc, context): """ 自定义异常处理 :param exc: 异常类 :param context: 抛出异常的上下文 :return: Response响应对象 """ # 调用drf框架原生的异常处理方法 response = exception_handler(exc, context) if response is None: view = context['view'] if isinstance(exc, DatabaseError): # 数据库异常 logger.error('[%s] %s' % (view, exc)) response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) return response
# settings.py配置文件中添加 REST_FRAMEWORK = { # 异常处理 'EXCEPTION_HANDLER': 'luffy.utils.exceptions.custom_exception_handler', }
3. 前后端项目分离之数据库准备
create database luffycity default charset=utf8; # 终端里面,登录并创建数据库
# 创建只能看到该库的用户 create user luffy_user identified by 'luffy'; grant all privileges on luffycity.* to 'luffy_user'@'%'; flush privileges;
# 配置pycharm数据库连接 # 打开settings/dev.py文件,并配置 DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "HOST": "127.0.0.1", "PORT": 3306, "USER": "luffy_user", "PASSWORD": "luffy", "NAME": "luffycity", } }
# 在项目主模块的 __init__.py 中导入pymysql import pymysql pymysql.install_as_MySQLdb()
关于数据库两个错误的调整



4. 搭建前端项目

项目建好,并编辑运行即可

安装路由组件

在src目录下创建routers路由目录,在routers目录下创建index.js路由文件
# index.js路由文件中,编写初始化路由对象的代码 . import Vue from "vue" import Router from "vue-router" // 这里导入可以让让用户访问的组件 Vue.use(Router); export default new Router({ // 设置路由模式为‘history’,去掉默认的# mode: "history", routes:[ // 路由列表 ] })
注册路由信息
# 打开main.js文件,把router对象注册到vue中.代码: // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './routers/index'; Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' });
在视图中显示路由对应的内容

创建并提供前端首页的组件
# routers/index.js // import Vue from "vue" // import Router from "vue-router" // // // // 这里导入可以让让用户访问的组件 import Home from "../components/Home" // Vue.use(Router); // // export default new Router({ // // 设置路由模式为‘history’,去掉默认的# // mode: "history", // routes:[ // // 路由列表 { name:"Home", path:"/", component:Home, }, { name:"Home", path:"/home", component:Home, }, ] // })
创建Home 组件
# components/Home.vue <template> <div id="home"> 前端首页 </div> </template> <script> export default { name:"Home", data(){ return { } } } </script> <style scoped> </style>
5. 前端初始化全局变量和全局方法
# 在src目录下创建settings.js站点开发配置文件: export default { Host:"http://127.0.0.1", } # 在main.js中引入 // // The Vue build version to load with the `import` command // // (runtime-only or standalone) has been set in webpack.base.conf with an alias. // import Vue from 'vue' // import App from './App' // import router from './routers/index'; import settings from "./settings" // Vue.config.productionTip = false; Vue.prototype.$settings = settings; // // /* eslint-disable no-new */ // new Vue({ // el: '#app', // router, // components: { App }, // template: '<App/>' // });
引入ElementUI
npm i element-ui -S # 上面的命令等同于 npm install element-ui --save

配置ElementUI到项目中
# 在main.js中导入ElementUI,并调用。 // The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. // import Vue from 'vue' // import App from './App' // import router from './routers/index'; // 开发配置文件 // import settings from "./settings" // Vue.prototype.$settings = settings; // elementUI 导入 import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; // 调用插件 Vue.use(ElementUI); // Vue.config.productionTip = false; /* eslint-disable no-new */ // new Vue({ // el: '#app', // router, // components: { App }, // template: '<App/>' // });
成功引入了ElementUI以后,接下来我们就可以开始进入前端页面开发,首先是首页。
6. 跨域CORS
我们现在为前端和后端分别设置两个不同的域名:
位置 域名
前端 www.luffycity.cn
后端 api.luffycity.cn
# 查找nginx的进程 ps -ef|grep nginx # 关闭进程 sudo kill -9 nginx进程号

# 修改配置文件config/index.js host: 'www.luffycity.cn', // can be overwritten by process.env.HOST port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined autoOpenBrowser: true,

# 可以通过settings/dev.py的ALLOWED_HOSTS,设置允许访问 # 设置哪些客户端可以通过地址访问到后端 ALLOWED_HOSTS = [ 'api.luffycity.cn', ]
让用户访问的时候,使用api.luffycity.cn:8000
1. 修改pycharm的manage.py的配置参数

现在,前端与后端分处不同的域名,我们需要为后端添加跨域访问的支持
否则前端无法使用axios无法请求后端提供的api数据,我们使用CORS来解决后端对跨域访问的支持。
# 后端安装 pip install django-cors-headers
# dev配置添加应用 INSTALLED_APPS = ( ... 'corsheaders', ... ) # 中间层设置【必须写在第一个位置】 MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', ... ] # 添加白名单 # CORS组的配置信息 CORS_ORIGIN_WHITELIST = ( 'www.luffycity.cn:8080' ) CORS_ALLOW_CREDENTIALS = True # 允许ajax跨域请求时携带cookie

完成了上面的步骤,我们就可以通过后端提供数据给前端使用ajax访问了。
前端使用 axios就可以访问到后端提供给的数据接口,但是如果要附带cookie信息,前端还要设置一下。
前端引入axios插件并配置允许axios发送cookie信息[axios本身也不允许ajax发送cookie到后端]

# 在main.js中引用 axios插件 import axios from 'axios'; // 从node_modules目录中导入包 // 允许ajax发送请求时附带cookie axios.defaults.withCredentials = true; Vue.prototype.$axios = axios; // 把对象挂载vue中
7. 前端显示首页
# Home.vue <template> <div id="home"> <Header/> <Banner/> <Footer/> </div> </template> <script> import Header from "./common/Header" import Banner from "./common/Banner" import Footer from "./common/Footer" export default { name:"Home", data(){ return { } }, components:{ Header, Banner, Footer, } } </script> <style scoped> </style>
# Header.vue <template> <div class="header"> <el-container> <el-header> <el-row> <el-col class="logo" :span="3"> <a href="/"> <img src="@/assets/head-logo.svg" alt=""> </a> </el-col> <el-col class="nav" :span="16"> <el-row> <el-col :span="3"><router-link class="current" to="/course">免费课</router-link></el-col> <el-col :span="3"><router-link to="/">轻课</router-link></el-col> <el-col :span="3"><router-link to="/">学位课</router-link></el-col> <el-col :span="3"><router-link to="/">题库</router-link></el-col> <el-col :span="3"><router-link to="/">教育</router-link></el-col> </el-row> </el-col> <el-col class="login-bar" :span="5"> <el-row v-if="token"> <el-col class="cart-ico" :span="9"> <router-link to=""> <b class="goods-number">0</b> <img class="cart-icon" src="@/assets/cart.svg" alt=""> <span><router-link to="/cart">购物车</router-link></span> </router-link> </el-col> <el-col class="study" :span="8" :offset="2"><router-link to="">学习中心</router-link></el-col> <el-col class="member" :span="5"> <el-menu class="el-menu-demo" mode="horizontal"> <el-submenu index="2"> <template slot="title"><router-link to=""><img src="@/assets/logo@2x.png" alt=""></router-link></template> <el-menu-item index="2-1">我的账户</el-menu-item> <el-menu-item index="2-2">我的订单</el-menu-item> <el-menu-item index="2-3">我的优惠卷</el-menu-item> <el-menu-item index="2-3">退出登录</el-menu-item> </el-submenu> </el-menu> </el-col> </el-row> <el-row v-else> <el-col class="cart-ico" :span="9"> <router-link to=""> <img class="cart-icon" src="@/assets/cart.svg" alt=""> <span><router-link to="/cart">购物车</router-link></span> </router-link> </el-col> <el-col :span="10" :offset="5"> <span class="register"> <router-link to="/login">登录</router-link> | <router-link to="/register">注册</router-link> </span> </el-col> </el-row> </el-col> </el-row> </el-header> </el-container> </div> </template> <script> export default { name: "Header", data(){ return { // 设置一个登录标识,表示是否登录 token: false, }; } } </script> <style scoped> .header{ top:0; left:0; right:0; margin: auto; background-color: #fff; height: 80px; z-index: 1000; position: fixed; box-shadow: 0 0.5px 0.5px 0 #c9c9c9; } .header .el-container{ width: 1200px; margin: 0 auto; } .el-header{ height: 80px!important; padding:0; } .logo{ } .logo img{ padding-top: 22px; } .nav{ margin-top: 22px; } .nav .el-col a{ display: inline-block; text-align: center; padding-bottom: 16px; padding-left: 5px; padding-right: 5px; position: relative; font-size: 16px; margin-left: 20px; } .nav .el-col .current{ color: #4a4a4a; border-bottom: 4px solid #ffc210; } .login-bar{ margin-top: 22px; } .cart-ico{ position: relative; border-radius: 17px; } .cart-ico:hover{ background: #f0f0f0; } .goods-number{ width: 16px; height: 16px; line-height: 17px; font-size: 12px; color: #fff; text-align: center; background: #fa6240; border-radius: 50%; transform: scale(.8); position: absolute; left: 16px; top: -1px; } .cart-icon{ width: 15px; height: auto; margin-left: 6px; } .cart-ico span{ margin-left: 12px; } .member img{ width: 26px; height: 26px; border-radius: 50%; display: inline-block; } .member img:hover{ border: 1px solid yellow; } </style>
# Footer.vue <template> <div class="footer"> <el-container> <el-row> <el-col :span="4"><router-link to="">关于我们</router-link></el-col> <el-col :span="4"><router-link to="">联系我们</router-link></el-col> <el-col :span="4"><router-link to="">商务合作</router-link></el-col> <el-col :span="4"><router-link to="">帮助中心</router-link></el-col> <el-col :span="4"><router-link to="">意见反馈</router-link></el-col> <el-col :span="4"><router-link to="">新手指南</router-link></el-col> <el-col :span="24"><p class="copyright">Copyright © luffycity.com版权所有 | 京ICP备17072161号-1</p></el-col> </el-row> </el-container> </div> </template> <script> export default { name:"Footer", data(){ return {} } } </script> <style scoped> .footer{ width: 100%; height: 128px; background: #25292e; } .footer .el-container{ width: 1200px; margin: auto; } .footer .el-row { align-items: center; padding: 0 200px; padding-bottom: 15px; width: 100%; margin-top: 38px; } .footer .el-row a{ color: #fff; font-size: 14px; } .footer .el-row .copyright{ text-align: center; color: #fff; font-size: 14px; } </style>
# 轮播图子组件 Banner.vue <template> <div class="banner"> <el-carousel trigger="click" height="473px"> <el-carousel-item v-for="banner in banner_list"> <a :href="banner.link"><img width="100%" :src="banner.img" alt=""></a> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name:"Banner", data(){ return { banner_list:[ {link:"http://www.baidu.com",img:"/static/banner/1.png"}, {link:"http://www.baidu.com",img:"/static/banner/2.png"}, {link:"http://www.baidu.com",img:"/static/banner/3.png"}, ] }; } } </script> <style> .el-carousel__arrow{ width: 100px!important; height: 100px!important; } .el-icon-arrow-left{ font-size: 35px; margin-left: 50px; } .el-carousel__arrow--left{ left: -50px; } </style>
# 注册首页路由 import Vue from "vue" import Router from "vue-router" // 导入需要注册路由的组件 import Home from "../components/Home" Vue.use(Router); // 配置路由列表 export default new Router({ mode:"history", routes:[ // 路由列表 { name:"Home", path: "/home", component:Home, }, { name:"Home", path: "/", component:Home, } ] })
# 图片处理模块,安装过的不需要再按照
pip install pillow
# 上传文件相关配置 settings.py # 访问静态文件的url地址前缀 STATIC_URL = '/static/' # 设置django的静态文件目录 STATICFILES_DIRS = [ os.path.join(BASE_DIR,"luffy/statics") ] # 项目中存储上传文件的根目录[暂时配置],注意,static目录需要手动创建否则上传文件时报错 MEDIA_ROOT=os.path.join(BASE_DIR,"luffy/statics") # 访问上传文件的url地址前缀 MEDIA_URL ="/media/" # 在xadmin中输出上传文件的Url地址,总路由urls.py新增代码: from django.urls import re_path from django.conf import settings from django.views.static import serve urlpatterns = [ ... re_path(r'media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}), ]
# 注册home子应用,因为子应用的位置发生了改变,所以为了原来子应用的注册写法,所以新增一个导包路径: # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 新增一个系统导包路径 import sys sys.path.insert(0,os.path.join(BASE_DIR,"apps")) INSTALLED_APPS = [ # 注意,加上drf框架的注册 'rest_framework', # 子应用 'home', ] # home/models.py from django.db import models # Create your models here. class BannerInfo(models.Model): """ 轮播图 """ # upload_to 存储子目录,真实存放地址会使用配置中的MADIE_ROOT+upload_to image = models.ImageField(upload_to='banner', verbose_name='轮播图', null=True,blank=True) name = models.CharField(max_length=150, verbose_name='轮播图名称') note = models.CharField(max_length=150, verbose_name='备注信息') link = models.CharField(max_length=150, verbose_name='轮播图广告地址') orders = models.IntegerField(verbose_name='显示顺序') is_show=models.BooleanField(verbose_name="是否上架",default=False) is_delete=models.BooleanField(verbose_name="逻辑删除",default=False) class Meta: db_table = 'ly_banner' verbose_name = '轮播图' verbose_name_plural = verbose_name def __str__(self): return self.name
# 数据迁移 python manage.py makemigrations python manage.py migrate
# 序列化器home/serializers.py from rest_framework.serializers import ModelSerializer from .models import BannerInfo class BannerInfoSerializer(ModelSerializer): """轮播图序列化器""" class Meta: model=BannerInfo fields = ("image","link")
# 视图代码 views.py from django.db.models import Q from rest_framework.generics import ListAPIView from .models import BannerInfo from .serializers import BannerInfoSerializer class BannerInfoListAPIView(ListAPIView): """ 轮播图列表 """ queryset = BannerInfo.objects.filter( Q(is_show=True) & Q(is_delete=False) ).order_by("-orders") serializer_class = BannerInfoSerializer
# 路由代码 urls.py from django.urls import path,re_path from . import views urlpatterns = [ path(r"banner/",views.BannerInfoListAPIView.as_view()), ] # 把home的路由urls.py注册到总路由 from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('', include("home.urls")), ]
安装xadmin
pip install https://codeload.github.com/sshwsfc/xadmin/zip/django2
# 在配置文件中注册如下应用 INSTALLED_APPS = [ ... 'xadmin', 'crispy_forms', 'reversion', ... ] # 修改使用中文界面 LANGUAGE_CODE = 'zh-Hans' # 修改时区 TIME_ZONE = 'Asia/Shanghai'
# xadmin有建立自己的数据库模型类,需要进行数据库迁移 python manage.py makemigrations python manage.py migrate
# 在总路由中添加xadmin的路由信息 import xadmin xadmin.autodiscover() # version模块自动注册需要版本控制的 Model from xadmin.plugins import xversion xversion.register_models() urlpatterns = [ path(r'xadmin/', xadmin.site.urls), ]
# 如果之前没有创建超级用户,需要创建,如果有了,则可以直接使用之前的。 python manage.py createsuperuser
# 给xadmin设置基本站点配置信息 import xadmin from xadmin import views class BaseSetting(object): """xadmin的基本配置""" enable_themes = True # 开启主题切换功能 use_bootswatch = True xadmin.site.register(views.BaseAdminView, BaseSetting) class GlobalSettings(object): """xadmin的全局配置""" site_title = "路飞学城" # 设置站点标题 site_footer = "路飞学城有限公司" # 设置站点的页脚 menu_style = "accordion" # 设置菜单折叠 xadmin.site.register(views.CommAdminView, GlobalSettings) # 在当前子应用中创建adminx.py,添加如下代码 # 轮播图 from .models import BannerInfo class BannerInfoModelAdmin(object): list_display=["name","orders","is_show"] xadmin.site.register(BannerInfo, BannerInfoModelAdmin)
# 修改后端xadmin中子应用名称 apps.py class HomeConfig(AppConfig): name = 'home' verbose_name = '我的首页' # __init__.py default_app_config = "home.apps.HomeConfig"
给轮播图添加一些数据

# 客户端代码获取数据 Banner.vue代码: <template> <div class="banner"> <el-carousel trigger="click" height="506px"> <el-carousel-item v-for="item in banner_list"> <a :href="item.link"><img :src="item.image"></a> </el-carousel-item> </el-carousel> </div> </template> <script> export default { name:"Banner", data(){ return { banner_list:[], }; }, created: function(){ // 获取轮播图 this.$axios.get(this.$settings+"/banner/").then(response => { console.log(response.data) this.banner_list = response.data }).catch(error => { console.log(error.response); }); } } </script>
# 创建模型 # 引入一个公共模型【抽象模型,不会在数据迁移的时候为它创建表】 from django.db import models from luffy.utils.models import BaseModel # Create your models here. class BannerInfo(BaseModel): """ 轮播图 """ # upload_to 存储子目录,真实存放地址会使用配置中的MADIE_ROOT+upload_to image = models.ImageField(upload_to='banner', verbose_name='轮播图', null=True,blank=True) name = models.CharField(max_length=150, verbose_name='轮播图名称') note = models.CharField(max_length=150, verbose_name='备注信息') link = models.CharField(max_length=150, verbose_name='轮播图广告地址') class Meta: db_table = 'ly_banner' verbose_name = '轮播图' verbose_name_plural = verbose_name def __str__(self): return self.name class NavInfo(BaseModel): """ 导航 """ NAV_POSITION = ( (0, 'top'), (1, 'footer') ) name = models.CharField(max_length=50, verbose_name='导航名称') link = models.CharField(max_length=250, verbose_name='导航地址') opt = models.SmallIntegerField(choices=NAV_POSITION, default=0, verbose_name='位置') class Meta: db_table = 'ly_nav' verbose_name = '导航' verbose_name_plural = verbose_name def __str__(self): return self.name # 公共模型,保存项目的公共代码库目录下luffy/utils.py文件中。 from django.db import models class BaseModel(models.Model): """公共字段模型""" orders = models.IntegerField(verbose_name='显示顺序') is_show=models.BooleanField(verbose_name="是否上架",default=False) is_delete=models.BooleanField(verbose_name="逻辑删除",default=False) create_time = models.DateTimeField(auto_now_add=True,verbose_name="添加时间") update_time = models.DateTimeField(auto_now=True,verbose_name="更新时间") class Meta: # 设置当前模型在数据迁移的时候不要为它创建表 abstract = True
# 数据迁移 python manage.py makemigrations python manage.py migrate
# 序列化器代码 from rest_framework.serializers import ModelSerializer from .models import NavInfo class NavInfoSerializer(ModelSerializer): """导航序列化器""" class Meta: model=NavInfo fields = ("name","link") # 视图代码 views.py from .models import NavInfo from .serializers import NavInfoSerializer class NavInfoAPIView(ListAPIView): """ 导航列表 """ queryset = NavInfo.objects.filter( Q(is_show=True) & Q(is_delete=False) & Q(opt=0) ).order_by("-orders") serializer_class = NavInfoSerializer # 路由代码 urls.py from django.urls import path,re_path from . import views urlpatterns = [ ... path(r"nav/",views.NavInfoAPIView.as_view()), ] # 注册模型到xadmin中 在当前子应用adminx.py,添加如下代码 # 导航 from home.models import NavInfo class NavInfoInfoModelAdmin(object): list_display=["name","link","is_show"] xadmin.site.register(NavInfo, NavInfoInfoModelAdmin)
# 客户端代码获取数据 Header.vue代码: <template> <div class="header"> <el-container> <el-header> <el-row> <el-col class="logo" :span="3"> <a href="/"> <img src="@/assets/head-logo.svg" alt=""> </a> </el-col> <el-col class="nav" :span="16"> <el-row> <el-col v-for="nav in nav_list" :span="3"><a :class="check(nav.link)?'current':''" :href="nav.link">{{nav.name}}</a></el-col> </el-row> </el-col> <el-col class="login-bar" :span="5"> <el-row v-if="token"> <el-col class="cart-ico" :span="9"> <router-link to=""> <b class="goods-number">0</b> <img class="cart-icon" src="@/assets/cart.svg" alt=""> <span><router-link to="/cart">购物车</router-link></span> </router-link> </el-col> <el-col class="study" :span="8" :offset="2"><router-link to="">学习中心</router-link></el-col> <el-col class="member" :span="5"> <el-menu class="el-menu-demo" mode="horizontal"> <el-submenu index="2"> <template slot="title"><router-link to=""><img src="@/assets/logo@2x.png" alt=""></router-link></template> <el-menu-item index="2-1">我的账户</el-menu-item> <el-menu-item index="2-2">我的订单</el-menu-item> <el-menu-item index="2-3">我的优惠卷</el-menu-item> <el-menu-item index="2-3">退出登录</el-menu-item> </el-submenu> </el-menu> </el-col> </el-row> <el-row v-else> <el-col class="cart-ico" :span="9"> <router-link to=""> <img class="cart-icon" src="@/assets/cart.svg" alt=""> <span><router-link to="/cart">购物车</router-link></span> </router-link> </el-col> <el-col :span="10" :offset="5"> <span class="register"> <router-link to="/login">登录</router-link> | <router-link to="/register">注册</router-link> </span> </el-col> </el-row> </el-col> </el-row> </el-header> </el-container> </div> </template> <script> export default { name: "Header", data(){ return { // 设置一个登录标识,表示是否登录 token: false, nav_list:[], }; }, created() { // 获取导航 this.$axios.get(this.$settings.Host+"/nav/").then(response=>{ this.nav_list = response.data console.log(this.nav_list) }).catch(error=>{ console.log(error.response) }) }, methods:{ check(link){ return link==window.location.pathname } } } </script> <style scoped> .header{ top:0; left:0; right:0; margin: auto; background-color: #fff; height: 80px; z-index: 1000; position: fixed; box-shadow: 0 0.5px 0.5px 0 #c9c9c9; } .header .el-container{ width: 1200px; margin: 0 auto; } .el-header{ height: 80px!important; padding:0; } .logo{ } .logo img{ padding-top: 22px; } .nav{ margin-top: 22px; } .nav .el-col a{ display: inline-block; text-align: center; padding-bottom: 16px; padding-left: 5px; padding-right: 5px; position: relative; font-size: 16px; margin-left: 20px; } .nav .el-col .current{ color: #4a4a4a; border-bottom: 4px solid #ffc210; } .login-bar{ margin-top: 22px; } .cart-ico{ position: relative; border-radius: 17px; } .cart-ico:hover{ background: #f0f0f0; } .goods-number{ width: 16px; height: 16px; line-height: 17px; font-size: 12px; color: #fff; text-align: center; background: #fa6240; border-radius: 50%; transform: scale(.8); position: absolute; left: 16px; top: -1px; } .cart-icon{ width: 15px; height: auto; margin-left: 6px; } .cart-ico span{ margin-left: 12px; } .member img{ width: 26px; height: 26px; border-radius: 50%; display: inline-block; } .member img:hover{ border: 1px solid yellow; } </style>



浙公网安备 33010602011771号