Tornado實戰項目(僞JD商城)

預備知識  

在以前tornado商城項目中,在開始以前須要引入一些項目設計知識,如接口,抽象方法抽象類,組合,程序設計原則等,我的理解項目的合理設計可增長其靈活性,javascript

下降數據之間的耦合性,提升穩定性,下面介紹一些預備知識css

一、接口

其實py中沒有接口這個概念。要想實現接口的功能,能夠經過主動拋出異常來實現html

接口做用:對派生類起到限制的做用java

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
接口,python中的接口,經過在父類中主動拋出異常實現
接口的做用:起到了限制的做用
"""

class IFoo:
    def fun1(self):
        pass
        raise Exception("錯誤提示")

class Bar(IFoo):
    def fun1(self):
        #方法名必須和父類中的方法名相同,否則沒辦法正常執行,會拋出異常
        print("子類中若是想要調用父類中的方法,子類中必需要有父類中的方法名")
    def fun2(self):
        print("test")

obj = Bar()
obj.fun2()

2.抽象方法抽象類

抽象類,抽象方法是普通類和接口的綜合,便可以繼承也能夠起到限制做用python

因爲python 自己沒有抽象類、接口的概念,因此要實現這種功能得abc.py 這個類庫,mysql

具體實現方法以下 :jquery

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
抽象類,抽象方法
抽象類,抽象方法是普通類和接口的綜合,便可以繼承也能夠起到限制做用
"""

import abc
class Foo(metaclass=abc.ABCMeta):
    def fun1(self):
        print("fun1")

    def fun2(self):
        print("fun2")

    @abc.abstractclassmethod
    def fun3(self):
        pass


class Bar(Foo):
    def fun3(self):
        print("子類必須有父類的抽象方法名,否則會拋出異常")


obj = Bar()
obj.fun1()
obj.fun2()
obj.fun3()

 3.組合

python中「多用組合少用繼承」,由於繼承的偶合性太強,能夠把基類,當作參數傳入派生類中,用於解偶web

§繼承sql

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#繼承

class Animals:
    def eat(self):
        print(self.Name + " eat")
    def drink(self):
        print(self.Name + " drink")

class Person(Animals):
    def __init__(self, name):
        self.Name = name

    def think(self):
        print(self.Name + " think")
obj = Person("user1")
obj.drink()
obj.eat()
obj.think()

§組合
數據庫

class Animals:
    def __init__(self,name):
        self.Name = name

    def eat(self):
        print(self.Name + " eat")

    def drink(self):
        print(self.Name + " drink")

class Person:
    def __init__(self, obj):
        self.obj = obj

    def eat(self):
        self.obj.eat()

    def think(self,name):
        print(name + " think")

animals = Animals("animals")
obj = Person(animals)
obj.think("person")
obj.eat()

4.依賴注入

像上一例中,若是有多層關係時,須要傳入多個對象,爲了解決這個問題就引入了依賴注入,

如上例在Person類實例化時自動傳入Animals對象

class Foo:
    def __init__(self):
        self.name = 111
    
    
    def fun(self)
        print(self.name)
        
obj = Foo() #obj是Foo的實例化對象

在python中一切皆對象,Foo是經過type類建立的

#!/usr/bin/env python
# -*- coding:utf-8 -*-

class MyType(type):

    def __call__(cls, *args, **kwargs):
        obj = cls.__new__(cls, *args, **kwargs)
        obj.__init__(*args, **kwargs)
        return obj


class Foo(metaclass=MyType):

    def __init__(self, name):
        self.name = name

    def f1(self):
        print(self.name)
 解釋器解釋:
    1.遇到 class Foo,執行type的__init__方法
    1.Type的init的方法裏作什麼麼呢?不知道
        obj = Foo(123)
    3.執行Type的 __call__方法
        執行Foo類的 __new__方法
        執行Foo類的 __init__ 方法

new 和 __init()和__metaclass__:

  • __new__函數是實例一個類所要調用的函數,每當咱們調用obj = Foo()來實例一個類時,都是先調用__new__()

  • 而後再調用__init__()函數初始化實例. __init__()在__new__()執行後執行,

  • 類中還有一個屬性 __metaclass__,其用來表示該類由 誰 來實例化建立,因此,咱們能夠爲 __metaclass__ 設置一個type類的派生類,從而查看 類 建立的過程。

那麼依賴注入的實現方法,自定義一個type方法,實例化類的時候指定由自定義的type方法建立,

具體實現方法以下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 依賴注入應用
#DI
class Mapper:
    __mapper_relation ={}

    @staticmethod
    def register(cls,value):
        Mapper.__mapper_relation[cls] = value

    @staticmethod
    def exist(cls):
        if cls in Mapper.__mapper_relation:
            return True
        return False

    @staticmethod
    def value(cls):
        return Mapper.__mapper_relation[cls]


class MyType(type):
    def __call__(self, *args, **kwargs):
        obj = self.__new__(self, *args, **kwargs)
        arg_list = list(args)
        if Mapper.exist(self):
            value=Mapper.value(self)
            arg_list.append(value)
        obj.__init__(*arg_list, **kwargs)
        return obj


#定義由誰來實例化
class Foo(metaclass=MyType):
    def __init__(self,name):
        self.name = name

    def f1(self):
        print(self.name)

class Bar(metaclass=MyType):
    def __init__(self,name):
        self.name = name

    def f1(self):
        print(self.name)

Mapper.register(Foo,"test1")
Mapper.register(Bar,"test12")
f=Foo()
print(f.name)

5.程序的設計原則

  1. 單一責任原則(SRP)

一個對象只對一個元素負責

優勢;
  消除耦合,減少因需求變化引發代碼僵化

  2.開放封閉原則(OCP)

     例如裝飾器,能夠對獨立的功能實現擴展,但對源碼不能進行修改
對擴展開放,對修改封閉

    優勢:
      按照OCP原則設計出來的系統,下降了程序各部分之間的耦合性,其適應性、靈活性、穩定性都比較好。當已有軟件系統須要增長新的功能時,

      不須要對做爲系統基礎的抽象層進行修改,只須要在原有基礎上附加新的模塊就能實現所須要添加的功能。增長的新模塊對原有的模塊徹底沒有影響或影響很小,

      這樣就無須爲原有模塊進行從新測試

    如何實現 ? 

      在面向對象設計中,不容許更必的是系統的抽象層,面容許擴展的是系統的實現層,因此解決問題的關鍵是在於抽象化。

      在面向對象編程中,經過抽象類及接口,規定具體類的特徵做爲抽象層,相對穩定,不須要作更改的從面能夠知足「對修改關閉」的原則;而從抽象類導出的具體 類能夠

      改變系統 的行爲,從而知足「對擴展開放的原則"

  3.里氏替換原則(LSP)  

子類能夠替換父類,父類出現的地方均可以用子類替換
可使用任何派生類(子類)替換基類

    優勢:
      能夠很容易的實現同一父類下各個子類的互換,而客戶端能夠絕不察覺

  4.接口分享原則(ISP)    

對於接口進行分類避免一個接口的方法過多,避免」胖接口"
    優勢:
      會使一個軟件系統功能擴展時,修改的壓力不會傳到別的對象那裏
    如何實現 ?
      得用委託分離接口
      利用多繼承分離接口

  5.依賴倒置原則(DIP)

高層模塊不該該依賴低層模塊,兩者都應該依賴其抽象(理解爲接口);抽象不該該依賴細節;細節應該依賴抽象   

隔離關係,使用接口或抽象類代指
高層次的模塊不該該依賴於低層次的模塊,而是,都應該依賴於抽象
    優勢:
      使用傳統過程化程序設計所建立的依賴關係,策略依賴於細節,這是糟糕的,由於策略受到細節改變的影響。
      依賴倒置原則使細節和策略都依賴於抽象,抽象的穩定性決定了系統的穩定性

  6.依賴注入(DI)和控制反轉原則(ICO)        

使用鉤子再原來執行流程中注入其餘對象

tornado項目設計實例

 實例只包含登陸,寫此實例目的在於更好的理解及應用以上的內容

  一、目錄規劃

   

 說明:

  Infrastructure 目錄:公共組件目錄

  Model:業務邏輯處理目錄

  Repository: 數據倉庫及數據處理目錄

  Statics:靜態文件目錄如(css,js,images等)

  UIAdmin: UI層

  Views:模板文件目錄

  Application.py : 服務啓動文件

  2.業務訪問流程

 介紹完目錄規劃,那就來說講業務訪問流程及數據走向

啓動服務後,客戶端訪問URL,根據tornado路由找到相對的handler進行處理
找到handler後其相對方法(get/post/delete/put)中調用Model邏輯處理層方法進行處理並接收處理結果
Model邏輯處理層需
    ①建立接口
    ②建模
    ③建立協調層
   建立完以後 ,由協調層(這裏通用Services)調用數據層方法並接收處理結果返回給handler

  4.數據處理層接收到Model調用後,處理數據並將數據返回給Model業務邏輯處理層

  5.最終handler接收到最終結果,進行判斷處理,並將處理結果返回給用戶

  三、落實實施

1.啓動文件,路由關係配置

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.ioloop
import tornado.web
from UIAdmin.Controllers import Account
from UIAdmin.Controllers import Region
from UIAdmin.Controllers import Customer
from UIAdmin.Controllers import Merchant
from UIAdmin import mapper

settings = {
    'template_path': 'Views',
    'static_path': 'Statics',
    'static_url_prefix': '/statics/',
}
application = tornado.web.Application([
    (r"/login", Account.LoginHandler),
    (r"/check", Account.CheckCodeHandler),
],**settings)

if __name__ == "__main__":
    application.listen(8000)
    tornado.ioloop.IOLoop.instance().start()
Application.py

 

說明:

settings 中指定配置,如模板文件路徑,靜態文件路徑等

application :路由配置,那個路徑由那個handler進行處理

2.handler配置

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import io
from Infrastructure.Core.HttpRequest import BaseRequestHandler
from Infrastructure.utils import check_code
from Model.User import UserService


class LoginHandler(BaseRequestHandler):
    def get(self, *args, **kwargs):
        self.render("Admin/Account/login.html")

    def post(self, *args, **kwargs):
        username = self.get_argument("username",None)
        email = self.get_argument("email",None)
        pwd = self.get_argument("pwd",None)
        code = self.get_argument("checkcode",None)
        service = UserService()
        result = service.check_login(user=username,email=email,pwd=pwd)
        #obj封裝了全部的用戶信息,UserModel對象
        if result and code.upper() == self.session["CheckCode"].upper():
            self.session['username'] = result.username
            self.redirect("/ProvinceManager.html")
        else:
            self.write("alert('error')")
hanler.py

handler中主要是針對數據訪問方式的不一樣,給出不一樣的處理方法,並將結果返回給客戶端

3.Model 邏輯處理層

邏輯處理層中,着重看的有三點:
    建模
    接口
    協調
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#建模
from Infrastructure.DI.Meta import DIMetaClass

class VipType:

    VIP_TYPE = (
        {'nid': 1, 'caption': '銅牌'},
        {'nid': 2, 'caption': '銀牌'},
        {'nid': 3, 'caption': '金牌'},
        {'nid': 4, 'caption': '鉑金'},
    )

    def __init__(self, nid):
        self.nid = nid

    def get_caption(self):
        caption = None

        for item in VipType.VIP_TYPE:
            if item['nid'] == self.nid:
                caption = item['caption']
                break
        return caption

    caption = property(get_caption)


class UserType:

    USER_TYPE = (
        {'nid': 1, 'caption': '用戶'},
        {'nid': 2, 'caption': '商戶'},
        {'nid': 3, 'caption': '管理員'},
    )

    def __init__(self, nid):
        self.nid = nid

    def get_caption(self):
        caption = None

        for item in UserType.USER_TYPE:
            if item['nid'] == self.nid:
                caption = item['caption']
                break
        return caption

    caption = property(get_caption)


class UserModel:
    def __init__(self, nid, username,password, email, last_login, user_type_obj, vip_type_obj):
        self.nid = nid
        self.username = username
        self.email = email
        self.password = password
        self.last_login = last_login
        self.user_type_obj = user_type_obj
        self.vip_type_obj = vip_type_obj
建模

 

接口  IUseRepository類:接口類,用於約束數據庫訪問類的方法

class IUserRepository:

    def fetch_one_by_user(self,user,pwd):
        """
        根據用戶名和密碼獲取對象
        :param user:
        :param pwd:
        :return:
        """

    def fetch_one_by_email(self, user, pwd):
        """
        根據郵箱和密碼獲取對象
        :param user:
        :param pwd:
        :return:
        """
接口

 

 協調  協調做用主要是調用數據處理層的方法,並將數據處理層處理後的結果返回給它的上一層的調度者

class UserService(metaclass=DIMetaClass):
    def __init__(self, user_repository):
        """
        :param user_repository: 數據倉庫對象
        """
        self.userRepository = user_repository

    def check_login(self,user,email,pwd):
        if user:
            #數據倉庫執行SQL後返回的字典
            #{"nid":1,username:xxx,vip:2,usertype:1}
            ret = self.userRepository.fetch_one_by_user(user,pwd)
        else:
            ret = self.userRepository.fetch_one_by_email(email,pwd)
        return ret
協調

 

4.Repository數據處理層

將處理後結果(usermodel對象)返回給上一層調度者(UserService)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#數據表建立 
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy import Integer, Integer, CHAR, VARCHAR, ForeignKey, Index, DateTime, DECIMAL, TEXT
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine

engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/ShoppingDb?charset=utf8", max_overflow=5)

Base = declarative_base()


class Province(Base):
    """"""
    __tablename__ = 'province'
    nid = Column(Integer, primary_key=True)
    caption = Column(VARCHAR(16), index=True)


class City(Base):
    """"""
    __tablename__ = 'city'
    nid = Column(Integer, primary_key=True)
    caption = Column(VARCHAR(16), index=True)
    province_id = Column(Integer, ForeignKey('province.nid'))


class County(Base):
    """
    縣(區)
    """
    __tablename__ = 'county'
    nid = Column(Integer, primary_key=True)
    caption = Column(VARCHAR(16), index=True)
    city_id = Column(Integer, ForeignKey('city.nid'))


class UserInfo(Base):
    """
    用戶信息
    """

    __tablename__ = 'userinfo'

    nid = Column(Integer, primary_key=True)

    USER_TYPE = (
        {'nid': 1, 'caption': '用戶'},
        {'nid': 2, 'caption': '商戶'},
        {'nid': 3, 'caption': '管理員'},
    )
    user_type = Column(Integer)

    VIP_TYPE = (
        {'nid': 1, 'caption': '銅牌'},
        {'nid': 2, 'caption': '銀牌'},
        {'nid': 3, 'caption': '金牌'},
        {'nid': 4, 'caption': '鉑金'},
    )
    vip = Column(Integer)

    username = Column(VARCHAR(32))
    password = Column(VARCHAR(64))
    email = Column(VARCHAR(64))

    last_login = Column(DateTime)
    ctime = Column(DateTime)

    __table_args__ = (
        Index('ix_user_pwd', 'username', 'password'),
        Index('ix_email_pwd', 'email', 'password'),
    )
SqlAchemyOrm.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from Model.User import IUserRepository
from Model.User import UserModel
from Model.User import UserType
from Model.User import VipType
from Repository.Admin.DbConnection import DbConnection


class UserRepository(IUserRepository):

    def __init__(self):
        self.db_conn = DbConnection()

    def fetch_one_by_email(self, email, password):
        ret = None

        cursor = self.db_conn.connect()
        sql = """select nid,username,password,email,last_login,vip,user_type from userinfo where email=%s and password=%s"""
        cursor.execute(sql, (email, password))
        db_result = cursor.fetchone()
        self.db_conn.close()
        print(type(db_result), db_result)
        if db_result:
            ret = UserModel(nid=db_result['nid'],
                            username=db_result['username'],
                            password=db_result['password'],
                            email=db_result['email'],
                            last_login=db_result['last_login'],
                            user_type_obj=UserType(nid=db_result['user_type']),
                            vip_type_obj=VipType(nid=db_result['vip']),)
            return ret
        return db_result

    def fetch_one_by_user(self, username, password):
        ret = None
        cursor = self.db_conn.connect()
        sql = """select nid,username,password,email,last_login,vip,user_type from userinfo where username=%s and password=%s"""
        cursor.execute(sql, (username, password))
        db_result = cursor.fetchone()
        self.db_conn.close()

        if db_result:
    #建模,將usermodel對象返回給上一層調用者,由於要向用戶展現的user_type不可能爲1,2這些數據而應該是相對的caption
            ret = UserModel(nid=db_result['nid'],
                            username=db_result['username'],
                            password=db_result['password'],
                            email=db_result['email'],
                            last_login=db_result['last_login'],
                            user_type_obj=UserType(nid=db_result['user_type']),
                            vip_type_obj=VipType(nid=db_result['vip']),)
            return ret
        return db_result
數據處理層

 

5.Handler最終處理

接收到最終處理結果後判斷,並返回數據給用戶

說明:

  有沒有注意到UserService是怎麼和數據處理層創建聯繫的?

  這裏咱們用到了依賴注入,具體配置以下: 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#依賴注入

class DIMapper:

    __mapper_dict = {}

    @staticmethod
    def inject(cls, arg):
        if cls not in DIMapper.__mapper_dict:
            DIMapper.__mapper_dict[cls] = arg

    @staticmethod
    def get_mappers():
        return DIMapper.__mapper_dict


class DIMetaClass(type):

    def __call__(cls, *args, **kwargs):
        # 獲取配置的對應的對象,攜帶進入
        obj = cls.__new__(cls, *args, **kwargs)

        mapper_dict = DIMapper.get_mappers()
        if cls in mapper_dict:
            cls.__init__(obj, mapper_dict[cls])
        else:
            cls.__init__(obj, *args, **kwargs)
        return obj
Meta.py

 

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 依賴注入綁定
from Infrastructure.DI import Meta
from Model.User import UserService
from Repository.Admin.UserRepository import UserRepository


Meta.DIMapper.inject(UserService,UserRepository())
mapper.py

 

6.靜態文件代碼

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="viewport" content="width=device-width" />
    <meta http-equiv="X-UA-Compatible" content="IE=8" />
    <title>購物商城</title>
    <link href="/statics/Admin/Css/common.css" rel="stylesheet" />
    <link href="/statics/Admin/Css/account.css" rel="stylesheet" />
</head>
<body>

    <div class="account-container bg mt10">
        <div class='header clearfix'>
                <div>
                    <a href="/home/index">
                        <img src="/statics/Admin/Images/mll_logo.gif">
                    </a>
                </div>
            </div>
    </div>

    <div class='account-container mt30'>
        
        <div class='body clearfix pd10' style='position: relative;'>
            <div class='logo left'>
                <img style='height:350px;' src="/statics/Admin/Images/login_logo.png" />
            </div>
            <div class='login left mt30'>
                <form id='Form' action='/login' method='POST'>
                    
                    <div class='group mt10'>
                        <label class='tip'><span class="red">*</span>用戶名:</label>
                        <input type='text' require='true' label='用戶名' Field='string' range='4-40' name='username' />
                        <i class='i-name'></i>
                    </div>
                  
                    <div class='group'>
                        <label class='tip'><span class="red">*</span>密碼:</label>
                        <input  type='password' require='true'  label='密碼' min-len='6' name='pwd' />
                        <i class='i-pwd'></i>
                    </div>
                   
                    <div class='group'>
                        <label class='tip'><span class="red">*</span>驗證碼:</label>
                        <input  type='text' require='true' label='驗證碼' style='width:80px;' name='checkcode' />
                        <a style='width:125px;display:inline-block;'><img class='checkcode' onclick='ChangeCode();' id='imgCode' src='/check' /></a>
                    </div>
                    <div class='group font12 mb0'>
                        <label class='tip'></label>
                        <label style='width:246px;display: inline-block;'>
                            <input id='protocol' name='protocol' type='checkbox' checked='checked' />
                            <span>自動登陸</span>
                            <span class='ml10'><a href='#'>忘記密碼?</a></span>
                        </label>
                    </div>
                    <div class='group mt0'>
                        <label class='tip'></label>
                        <input type='submit' class='submit' value='登    錄' />
                    </div>
                </form>
                
                <div class='go-register'><a href='#'>免費註冊 >> </a></div>
            </div>
        </div>
        
    </div>
    
    <div class='account-container mt20' style='text-align:center;color:#555;'>
        © 2004-2015 www.xxxxx.com.cn All Rights Reserved. xxxxx 版權全部
    </div>
    <script src="/statics/Admin/js/jquery-1.8.2.min.js"></script>
    <script src="/statics/Admin/js/treebiao.js"></script>
    <script type="text/javascript">
        
        $(function(){
            $.login('#Form','');
        });
    
        function ChangeCode() {
            var code = document.getElementById('imgCode');
            code.src += '?';
        }
    </script>
</body>
</html>
login.py

 

.header{
    padding:15px 0px;
}

.body{
    border: 1px solid #d7d7d7;
    padding: 40px;
    padding-right: 0;
}
.body .logo{
    width:50%;
}
.body .login{
    width:50%;    
    color: #555;
}

.body .register{
    width: 630px;
    border-right: 1px dashed #e5e5e5;
    color: #555;
}
.body .register .group,.body .login .group{
    margin:15px 0px;
    height:38px;
    font-size:14px;
    position:relative;
    line-height:38px;
}
.body .register .group .tip,.body .login .group .tip{
    width: 100px;
    display: inline-block;
    text-align: right;
    font-size: 14px;
}
.body .register .group label .red,.body .login .group label .red{
    margin:0 5px;
}

.body .register .group input[type='text'],.body .register .group input[type='password'],
.body .login .group input[type='text'],.body .login .group input[type='password']{
    width:210px;
    height:32px;
    padding:0 30px 0 4px;
    border: 1px solid #cccccc;
    
}
.body .register .group i,.body .login .group i{
    position: absolute;
    left: 330px;
}
.body .register .group .i-name,.body .login .group .i-name{
    background: url(../Images/i_name.jpg) no-repeat scroll 0 0 transparent;
    height: 16px;
    top: 10px;
    width: 16px;
    
}
.body .register .group .i-pwd,.body .login .group .i-pwd{
    background: url(../Images/i_pwd.jpg) no-repeat scroll 0 0 transparent;
    height: 19px;
    top: 10px;
    width: 14px;
}
.body .register .group .i-phone,.body .register .login .i-phone{
    background: url(../Images/i_phone.jpg) no-repeat scroll 0 0 transparent;
    height: 21px;
    top: 10px;
    width: 14px;
}

.body .register .group .input-error{
    font-size:12px;
    color: #e4393c;
    display: inline-block;
    line-height: 32px;
    height: 32px;
    width: 260px;
    padding: 0 5px;
    background: #FFEBEB;
    border: 1px solid #ffbdbe;
}

.body .login .group .input-error{
    font-size:10px;
    position: absolute;
    color: #e4393c;
    background: #FFEBEB;
    border: 1px solid #ffbdbe;
    display: block;
    z-index: 10;
    height: 15px;
    width: 244px;
    line-height: 15px;
    left: 104px;
}

.body .register .group .checkcode,.body .login .group .checkcode{
    position:absolute;
    margin:-20px 0 0 5px;
}
.body .register .group .submit,.body .login .group .submit{
    background-color: #e4393c;
    padding:8px 20px;
    width:246px;
    color: white;
    text-align: center;
    border:1px solid #e4393c;
}


.body .more{
    padding:20px;
}
.body .login .go-register{
    position: absolute;
    right:0px;
    bottom:0px;
}
.body .login .go-register a{
    line-height: 32px;
    text-align: center;
    font-size: 14px;
    background: #7cbe56;
    width: 115px;
    height: 32px;
    display: block;
    color: #FFF;
}


.pg-footer{
    margin:20px 0;
    color: #555;
}
account.css

 

/*公共開始*/
body {
    margin: 0 auto;
    font-family: Arial;
    _font-family: 宋體,Arial;
    font-size: 12px;
}
body, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td, figure, div {
    margin: 0;
    padding: 0;
}

ol, ul, li {
    list-style: none;
}
a{
    cursor:pointer;
    text-decoration:none;
}
/*a:hover{
    color: #F60 !important;
    text-decoration: underline;
}*/
img{
    border:none;
    border-width:0px;
}
table{
    border-collapse: collapse;
    border-spacing: 0;
}

.red{
    color: #c00 !important;
}

.m8{
    margin:8px;
}
.mg20{
    margin:20px;
}
.mt0{
    margin-top:0px !important;
}
.mt10{
    margin-top:10px;
}
.mt20{
    margin-top:20px;
}
.mt30{
    margin-top:30px !important;
}
.mr5{
    margin-right:5px;
}
.ml5{
    margin-left:5px;
}

.ml10{
    margin-left:10px;
}
.mb0{
    margin-bottom:0px !important;
}
.mb20{
    margin-bottom:20px;
}
.mb10{
    margin-bottom:10px;
}
.pd10{
    padding:10px !important;
}
.pt18{
    padding-top:18px;
}
.pt20{
    padding-top:20px;
}
.pb20{
    padding-bottom:20px;
}
.nbr{
    border-right:0px;
}
.font12{
    font-size:12px !important;
}
.font13{
    font-size:13px !important;
}
.font14{
    font-size:14px;
}
.font16{
    font-size:16px;
}
.bold{
    font-weight:bold;
}
.left{
    float:left;
}
.right{
    float:right;
}
.hide{
    display:none;
}
.show{
     display:table;
}
.clearfix{
    clear:both;
}
.clearfix:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}
* html .clearfix {zoom: 1;}

.container{
    width:1190px;
    margin-left:auto;
    margin-right:auto;
}
.narrow{
    width:980px !important;
    margin-left:auto;
    margin-right:auto;
}

.account-container{
    width:980px;
    margin-left:auto;
    margin-right:auto;
}

.group-box-1 .title{
    height: 33px;
    line-height: 33px;
    border: 1px solid #DDD;
    background: #f5f5f5;
    padding-top: 0;
    padding-left: 0;
                
}
.group-box-1 .title .title-font{
    display: inline-block;
    font-size: 14px;
    font-family: 'Microsoft Yahei','SimHei';
    font-weight: bold;
    color: #333;
    padding-left: 10px;
}
.group-box-1 .body {
    border: 1px solid #e4e4e4;
    border-top: none;
}

.tab-menu-box1 {
    border: 1px solid #ddd;
    margin-bottom: 20px;
}

.tab-menu-box1 .menu {
    line-height: 33px;
    height: 33px;
    background-color: #f5f5f5;
}

.tab-menu-box1 .content {
    min-height: 100px;
    border-top: 1px solid #ddd;
    background-color: white;
}

.tab-menu-box1 .menu ul {
    padding: 0;
    margin: 0;
    list-style: none;
    /*position: absolute;*/
}

.tab-menu-box1 .menu ul li {
    position: relative;
    float: left;
    font-size: 14px;
    font-family: 'Microsoft Yahei','SimHei';
    text-align: center;
    font-size: 14px;
    font-weight: bold;
    border-right: 1px solid #ddd;
    padding: 0 18px;
    cursor: pointer;
}

.tab-menu-box1 .menu ul li:hover {
    color: #c9033b;
}

.tab-menu-box1 .menu .more {
    float: right;
    font-size: 12px;
    padding-right: 10px;
    font-family: "宋體";
    color: #666;
    text-decoration: none;
}

.tab-menu-box1 .menu a:hover {
    color: #f60 !important;
    text-decoration: underline;
}

.tab-menu-box1 .menu .current {
    margin-top: -1px;
    color: #c9033b;
    background: #fff;
    height: 33px;
    border-top: 2px solid #c9033b;
    z-index: 10;
}

.tab-menu-box-2 .float-title {
    display: none;
    top: 0px;
    position: fixed;
    z-index: 50;
}

.tab-menu-box-2 .title {
    width: 890px;
    border-bottom: 2px solid #b20101;
    border-left: 1px solid #e1e1e1;
    clear: both;
    height: 32px;
}

.tab-menu-box-2 .title a {
    float: left;
    width: 107px;
    height: 31px;
    line-height: 31px;
    font-size: 14px;
    font-weight: bold;
    text-align: center;
    border-top: 1px solid #e1e1e1;
    border-right: 1px solid #e1e1e1;
    background: url(../images/bg4.png?3) 0 -308px repeat-x;
    text-decoration: none;
    color: #333;
    cursor: pointer;
}

.tab-menu-box-2 .title a:hover {
    background-position: -26px -271px;
    text-decoration: none;
    color: #fff;
}

.tab-menu-box-2 .content {
    min-height: 100px;
    background-color: white;
}


.tab-menu-box3 {
    border: 1px solid #ddd;
}

.tab-menu-box3 .menu {
    line-height: 33px;
    height: 33px;
    background-color: #f5f5f5;
}

.tab-menu-box3 .content {
    height: 214px;
    border-top: 1px solid #ddd;
    background-color: white;
}

.tab-menu-box3 .menu ul {
    padding: 0;
    margin: 0;
    list-style: none;
    /*position: absolute;*/
}

.tab-menu-box3 .menu ul li {
    position: relative;
    float: left;
    font-size: 14px;
    font-family: 'Microsoft Yahei','SimHei';
    text-align: center;
    font-size: 14px;
    width:50%;
    cursor: pointer;
}
 
.tab-menu-box3 .menu ul li:hover {
    color: #c9033b;
}

.tab-menu-box3 .menu .more {
    float: right;
    font-size: 12px;
    padding-right: 10px;
    font-family: "宋體";
    color: #666;
    text-decoration: none;
}

.tab-menu-box3 .menu a:hover {
    color: #f60 !important;
    text-decoration: underline;
    font-weight: bold;
}

.tab-menu-box3 .menu .current {

    margin-top: -1px;
    color: #c9033b;
    background: #fff;
    height: 33px;
    border-top: 2px solid #c9033b;
    z-index: 10;
    font-weight: bold;
    
}

.quantity-bg{
    height:20px;
    width: 77px; 
    border: 1px solid #999;
}
 
.quantity-bg  .minus,.quantity-bg  .plus{
  height:20px;
  width:20px; 
  line-height:20px;
  text-align:center;
  vertical-align:middle;
}

.quantity-bg input{
    height:20px;
    width:35px;
    border:0px;
    border-left:1px solid #999;
    border-right:1px solid #999;
 }
 
/*公共結束*/
common.css

 

後續還有更新版本...

相關文章
相關標籤/搜索