-
+
-
+
{{ result.name }}
(预测结果)
@@ -102,7 +102,7 @@
// 查询垃圾分类的函数
search() {
if (this.word.trim().length > 0) {
- let key = '9aeb28ee8858a167c1755f856f830e22'
+ let key = '9636cec76ee2593ba6b195e5b770b394'
let url = `http://api.tianapi.com/txapi/lajifenlei/?key=${key}&word=${this.word}`
fetch(url)
.then(resp => resp.json())
diff --git a/Day21-30/code/垃圾分类查询/kitchen-waste.png b/Day21-30/code/垃圾分类查询/kitchen-waste.png
deleted file mode 100644
index cd52f47..0000000
Binary files a/Day21-30/code/垃圾分类查询/kitchen-waste.png and /dev/null differ
diff --git a/Day21-30/code/垃圾分类查询/other-waste.png b/Day21-30/code/垃圾分类查询/other-waste.png
deleted file mode 100644
index ef2222b..0000000
Binary files a/Day21-30/code/垃圾分类查询/other-waste.png and /dev/null differ
diff --git a/Day21-30/code/垃圾分类查询/recyclable.png b/Day21-30/code/垃圾分类查询/recyclable.png
deleted file mode 100644
index a82922f..0000000
Binary files a/Day21-30/code/垃圾分类查询/recyclable.png and /dev/null differ
diff --git a/Day21-30/res/baidu_echarts.png b/Day21-30/res/baidu_echarts.png
index e583e89..48ff43c 100644
Binary files a/Day21-30/res/baidu_echarts.png and b/Day21-30/res/baidu_echarts.png differ
diff --git a/Day21-30/res/bootstrap-layoutit.png b/Day21-30/res/bootstrap-layoutit.png
index ae39347..3735ac8 100644
Binary files a/Day21-30/res/bootstrap-layoutit.png and b/Day21-30/res/bootstrap-layoutit.png differ
diff --git a/Day21-30/res/browser-joke-1.png b/Day21-30/res/browser-joke-1.png
deleted file mode 100644
index 0e3efd8..0000000
Binary files a/Day21-30/res/browser-joke-1.png and /dev/null differ
diff --git a/Day21-30/res/browser-joke-2.png b/Day21-30/res/browser-joke-2.png
deleted file mode 100644
index b3ae531..0000000
Binary files a/Day21-30/res/browser-joke-2.png and /dev/null differ
diff --git a/Day21-30/res/browser-joke-3.png b/Day21-30/res/browser-joke-3.png
deleted file mode 100644
index bd6028f..0000000
Binary files a/Day21-30/res/browser-joke-3.png and /dev/null differ
diff --git a/Day21-30/res/dom-page.png b/Day21-30/res/dom-page.png
deleted file mode 100644
index 2777e9c..0000000
Binary files a/Day21-30/res/dom-page.png and /dev/null differ
diff --git a/Day21-30/res/dom-tree.png b/Day21-30/res/dom-tree.png
deleted file mode 100644
index ce5e74e..0000000
Binary files a/Day21-30/res/dom-tree.png and /dev/null differ
diff --git a/Day21-30/res/字体样式.png b/Day21-30/res/字体样式.png
index 9baacb6..8f592bb 100644
Binary files a/Day21-30/res/字体样式.png and b/Day21-30/res/字体样式.png differ
diff --git a/Day21-30/res/字符实体.png b/Day21-30/res/字符实体.png
index 4a1fd12..dd18622 100644
Binary files a/Day21-30/res/字符实体.png and b/Day21-30/res/字符实体.png differ
diff --git a/Day21-30/res/客户端对字体文件的支持.png b/Day21-30/res/客户端对字体文件的支持.png
index aa93eeb..1a0e5b0 100644
Binary files a/Day21-30/res/客户端对字体文件的支持.png and b/Day21-30/res/客户端对字体文件的支持.png differ
diff --git a/Day21-30/res/尺寸单位.png b/Day21-30/res/尺寸单位.png
index 3b71674..845e32b 100644
Binary files a/Day21-30/res/尺寸单位.png and b/Day21-30/res/尺寸单位.png differ
diff --git a/Day21-30/res/属性选择器.png b/Day21-30/res/属性选择器.png
index f6ae4dc..06fef27 100644
Binary files a/Day21-30/res/属性选择器.png and b/Day21-30/res/属性选择器.png differ
diff --git a/Day21-30/res/常用选择器.png b/Day21-30/res/常用选择器.png
index bf86166..a54f4de 100644
Binary files a/Day21-30/res/常用选择器.png and b/Day21-30/res/常用选择器.png differ
diff --git a/Day21-30/res/开始标签.png b/Day21-30/res/开始标签.png
index 29bd455..6f79eb4 100644
Binary files a/Day21-30/res/开始标签.png and b/Day21-30/res/开始标签.png differ
diff --git a/Day21-30/res/标签属性.png b/Day21-30/res/标签属性.png
index 21eb12f..7eb42f0 100644
Binary files a/Day21-30/res/标签属性.png and b/Day21-30/res/标签属性.png differ
diff --git a/Day21-30/res/样式属性.png b/Day21-30/res/样式属性.png
index 476ef50..9b63b89 100644
Binary files a/Day21-30/res/样式属性.png and b/Day21-30/res/样式属性.png differ
diff --git a/Day21-30/res/盒子模型.png b/Day21-30/res/盒子模型.png
index a2517f3..af181ff 100644
Binary files a/Day21-30/res/盒子模型.png and b/Day21-30/res/盒子模型.png differ
diff --git a/Day21-30/res/相对路径.png b/Day21-30/res/相对路径.png
index b0e6ec9..f9b75ff 100644
Binary files a/Day21-30/res/相对路径.png and b/Day21-30/res/相对路径.png differ
diff --git a/Day21-30/res/经典布局-1.png b/Day21-30/res/经典布局-1.png
index 42f4b94..16dfe2b 100644
Binary files a/Day21-30/res/经典布局-1.png and b/Day21-30/res/经典布局-1.png differ
diff --git a/Day21-30/res/经典布局-2.png b/Day21-30/res/经典布局-2.png
index 089133b..349c6d0 100644
Binary files a/Day21-30/res/经典布局-2.png and b/Day21-30/res/经典布局-2.png differ
diff --git a/Day21-30/res/结束标签.png b/Day21-30/res/结束标签.png
index c80a3c2..8034aa3 100644
Binary files a/Day21-30/res/结束标签.png and b/Day21-30/res/结束标签.png differ
diff --git a/Day21-30/res/网站地图.png b/Day21-30/res/网站地图.png
index 55a4daf..744e7d9 100644
Binary files a/Day21-30/res/网站地图.png and b/Day21-30/res/网站地图.png differ
diff --git a/Day21-30/res/衬线字体+非衬线字体+等宽字体.png b/Day21-30/res/衬线字体+非衬线字体+等宽字体.png
index 7693210..1fd0818 100644
Binary files a/Day21-30/res/衬线字体+非衬线字体+等宽字体.png and b/Day21-30/res/衬线字体+非衬线字体+等宽字体.png differ
diff --git a/Day21-30/res/选择器语法.png b/Day21-30/res/选择器语法.png
index 54c159d..75021ef 100644
Binary files a/Day21-30/res/选择器语法.png and b/Day21-30/res/选择器语法.png differ
diff --git a/Day31-35/31-35.玩转Linux操作系统.md b/Day31-35/31-35.玩转Linux操作系统.md
index c519043..ea59ac0 100644
--- a/Day31-35/31-35.玩转Linux操作系统.md
+++ b/Day31-35/31-35.玩转Linux操作系统.md
@@ -1,6 +1,6 @@
## 玩转Linux操作系统
-> 说明:本文中对Linux命令的讲解都是基于名为CentOS的Linux发行版本,我自己使用的是阿里云服务器,系统版本为CentOS Linux release 7.6.1810。不同的Linux发行版本在Shell命令和工具程序上会有一些差别,但是这些差别是很小的。
+> **说明**:本文中对Linux命令的讲解都是基于名为CentOS的Linux发行版本,我自己使用的是阿里云服务器,系统版本为CentOS Linux release 7.6.1810。不同的Linux发行版本在Shell命令和工具程序上会有一些差别,但是这些差别是很小的。
### 操作系统发展史
@@ -111,7 +111,7 @@ Linux系统的命令通常都是如下所示的格式:
Shell也被称为“壳”或“壳程序”,它是用户与操作系统内核交流的翻译官,简单的说就是人与计算机交互的界面和接口。目前很多Linux系统默认的Shell都是bash(B ourne A gain SH ell),因为它可以使用tab键进行命令和路径补全、可以保存历史命令、可以方便的配置环境变量以及执行批处理操作。
```Shell
- [root@izwz97tbgo9lkabnat2lo8z ~]# ps
+ [root ~]# ps
PID TTY TIME CMD
3531 pts/0 00:00:00 bash
3553 pts/0 00:00:00 ps
@@ -136,7 +136,7 @@ Linux系统的命令通常都是如下所示的格式:
4. 清除屏幕上显示的内容 - **clear**。
-5. 查看帮助文档 - **man** / **info** / **help** / **apropos**。
+5. 查看帮助文档 - **man** / **info** / **--help** / **apropos**。
```Shell
[root@izwz97tbgo9lkabnat2lo8z ~]# ps --help
Usage:
@@ -230,7 +230,7 @@ Linux系统的命令通常都是如下所示的格式:
[root@iZwz97tbgo9lkabnat2lo8Z ~]# !454
```
- > 说明:查看到历史命令之后,可以用`!历史命令编号`来重新执行该命令;通过`history -c`可以清除历史命令。
+ > **说明**:查看到历史命令之后,可以用`!历史命令编号`来重新执行该命令;通过`history -c`可以清除历史命令。
### 实用程序
@@ -308,7 +308,7 @@ Linux系统的命令通常都是如下所示的格式:
...
```
- > 说明:上面用到了一个名为`wget`的命令,它是一个网络下载器程序,可以从指定的URL下载资源。
+ > **说明**:上面用到了一个名为`wget`的命令,它是一个网络下载器程序,可以从指定的URL下载资源。
6. 拷贝/移动文件 - **cp** / **mv**。
@@ -350,7 +350,7 @@ Linux系统的命令通常都是如下所示的格式:
52:
...
```
- > 说明:`grep`在搜索字符串时可以使用正则表达式,如果需要使用正则表达式可以用`grep -E`或者直接使用`egrep`。
+ > **说明**:`grep`在搜索字符串时可以使用正则表达式,如果需要使用正则表达式可以用`grep -E`或者直接使用`egrep`。
9. 创建链接和查看链接 - **ln** / **readlink**。
@@ -372,7 +372,7 @@ Linux系统的命令通常都是如下所示的格式:
CentOS Linux release 7.4.1708 (Core)
```
- > 说明:链接可以分为硬链接和软链接(符号链接)。硬链接可以认为是一个指向文件数据的指针,就像Python中对象的引用计数,每添加一个硬链接,文件的对应链接数就增加1,只有当文件的链接数为0时,文件所对应的存储空间才有可能被其他文件覆盖。我们平常删除文件时其实并没有删除硬盘上的数据,我们删除的只是一个指针,或者说是数据的一条使用记录,所以类似于“文件粉碎机”之类的软件在“粉碎”文件时除了删除文件指针,还会在文件对应的存储区域填入数据来保证文件无法再恢复。软链接类似于Windows系统下的快捷方式,当软链接链接的文件被删除时,软链接也就失效了。
+ > **说明**:链接可以分为硬链接和软链接(符号链接)。硬链接可以认为是一个指向文件数据的指针,就像Python中对象的引用计数,每添加一个硬链接,文件的对应链接数就增加1,只有当文件的链接数为0时,文件所对应的存储空间才有可能被其他文件覆盖。我们平常删除文件时其实并没有删除硬盘上的数据,我们删除的只是一个指针,或者说是数据的一条使用记录,所以类似于“文件粉碎机”之类的软件在“粉碎”文件时除了删除文件指针,还会在文件对应的存储区域填入数据来保证文件无法再恢复。软链接类似于Windows系统下的快捷方式,当软链接链接的文件被删除时,软链接也就失效了。
10. 压缩/解压缩和归档/解归档 - **gzip** / **gunzip** / **xz**。
@@ -429,7 +429,7 @@ Linux系统的命令通常都是如下所示的格式:
[root@iZwz97tbgo9lkabnat2lo8Z ~]# xargs < a.txt > b.txt
```
- > 说明:这个命令就像上面演示的那样常在管道(实现进程间通信的一种方式)和重定向(重新指定输入输出的位置)操作中用到,后面的内容中会讲到管道操作和输入输出重定向操作。
+ > **说明**:这个命令就像上面演示的那样常在管道(实现进程间通信的一种方式)和重定向(重新指定输入输出的位置)操作中用到,后面的内容中会讲到管道操作和输入输出重定向操作。
13. 显示文件或目录 - **basename** / **dirname**。
@@ -1283,7 +1283,7 @@ build environment:
### 计划任务
-1. 在指定的时间执行命令
+1. 在指定的时间执行命令。
- **at** - 将任务排队,在指定的时间执行。
- **atq** - 查看待执行的任务队列。
@@ -1788,6 +1788,8 @@ echo '结果: '$sum
```Shell
#!/usr/bin/bash
+printf '输入文件夹名: '
+read dir
printf '输入文件名: '
read file
printf '输入文件数量(<1000): '
diff --git a/Day31-35/res/andrew.jpg b/Day31-35/res/andrew.jpg
index 8f001d3..41f37a5 100644
Binary files a/Day31-35/res/andrew.jpg and b/Day31-35/res/andrew.jpg differ
diff --git a/Day31-35/res/dmr.png b/Day31-35/res/dmr.png
index 2453340..2ca20e8 100644
Binary files a/Day31-35/res/dmr.png and b/Day31-35/res/dmr.png differ
diff --git a/Day31-35/res/file-mode.png b/Day31-35/res/file-mode.png
index 294139a..f80d500 100644
Binary files a/Day31-35/res/file-mode.png and b/Day31-35/res/file-mode.png differ
diff --git a/Day31-35/res/history-of-os.png b/Day31-35/res/history-of-os.png
deleted file mode 100644
index 22262ec..0000000
Binary files a/Day31-35/res/history-of-os.png and /dev/null differ
diff --git a/Day31-35/res/history-of-unix.png b/Day31-35/res/history-of-unix.png
index 401b706..1da969e 100644
Binary files a/Day31-35/res/history-of-unix.png and b/Day31-35/res/history-of-unix.png differ
diff --git a/Day31-35/res/ibm-col80-punched-card.png b/Day31-35/res/ibm-col80-punched-card.png
index 467ce12..8a797b1 100644
Binary files a/Day31-35/res/ibm-col80-punched-card.png and b/Day31-35/res/ibm-col80-punched-card.png differ
diff --git a/Day31-35/res/ken-and-dennis-pdp-11.png b/Day31-35/res/ken-and-dennis-pdp-11.png
index 28ad0f7..2a2b510 100644
Binary files a/Day31-35/res/ken-and-dennis-pdp-11.png and b/Day31-35/res/ken-and-dennis-pdp-11.png differ
diff --git a/Day31-35/res/ken_old.png b/Day31-35/res/ken_old.png
index 5d322c4..7fd7853 100644
Binary files a/Day31-35/res/ken_old.png and b/Day31-35/res/ken_old.png differ
diff --git a/Day31-35/res/ken_young.jpg b/Day31-35/res/ken_young.jpg
index 46e3009..4bf8fa6 100644
Binary files a/Day31-35/res/ken_young.jpg and b/Day31-35/res/ken_young.jpg differ
diff --git a/Day31-35/res/linus.png b/Day31-35/res/linus.png
index acbe3bf..b2e1620 100644
Binary files a/Day31-35/res/linus.png and b/Day31-35/res/linus.png differ
diff --git a/Day31-35/res/linux-network-config.png b/Day31-35/res/linux-network-config.png
index a3b01e6..1db952c 100644
Binary files a/Day31-35/res/linux-network-config.png and b/Day31-35/res/linux-network-config.png differ
diff --git a/Day31-35/res/pdp-11.jpg b/Day31-35/res/pdp-11.jpg
index 6b4486b..13cca8e 100644
Binary files a/Day31-35/res/pdp-11.jpg and b/Day31-35/res/pdp-11.jpg differ
diff --git a/Day31-35/res/pdp-7.png b/Day31-35/res/pdp-7.png
index 8e7ab9e..8246dd0 100644
Binary files a/Day31-35/res/pdp-7.png and b/Day31-35/res/pdp-7.png differ
diff --git a/Day31-35/res/vim-diff.png b/Day31-35/res/vim-diff.png
index 5fde982..5951e02 100644
Binary files a/Day31-35/res/vim-diff.png and b/Day31-35/res/vim-diff.png differ
diff --git a/Day31-35/res/vim-macro.png b/Day31-35/res/vim-macro.png
index 33b5eed..e80ef3e 100644
Binary files a/Day31-35/res/vim-macro.png and b/Day31-35/res/vim-macro.png differ
diff --git a/Day31-35/res/vim-multi-window.png b/Day31-35/res/vim-multi-window.png
index c6e17d7..5028d27 100644
Binary files a/Day31-35/res/vim-multi-window.png and b/Day31-35/res/vim-multi-window.png differ
diff --git a/Day36-40/36-38.关系型数据库MySQL.md b/Day36-40/36-38.关系型数据库MySQL.md
index 50e78d5..8b2b48d 100644
--- a/Day36-40/36-38.关系型数据库MySQL.md
+++ b/Day36-40/36-38.关系型数据库MySQL.md
@@ -74,6 +74,8 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
```Shell
rpm -ivh mysql-community-common-5.7.26-1.el7.x86_64.rpm
rpm -ivh mysql-community-libs-5.7.26-1.el7.x86_64.rpm
+ rpm -ivh mysql-community-libs-compat-5.7.26-1.el7.x86_64.rpm
+ rpm -ivh mysql-community-devel-5.7.26-1.el7.x86_64.rpm
rpm -ivh mysql-community-client-5.7.26-1.el7.x86_64.rpm
rpm -ivh mysql-community-server-5.7.26-1.el7.x86_64.rpm
```
@@ -174,7 +176,7 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
alter user 'root'@'localhost' identified by '123456';
```
- > 说明:MySQL较新的版本默认不允许使用弱口令作为用户口令,所以我们通过上面的前两条命令修改了验证用户口令的策略和口令的长度。事实上我们不应该使用弱口令,因为存在用户口令被暴力破解的风险。近年来,攻击数据库窃取数据和劫持数据库勒索比特币的事件屡见不鲜,要避免这些潜在的风险,最为重要的一点是不要让数据库服务器暴露在公网上(最好的做法是将数据库置于内网,至少要做到不向公网开放数据库服务器的访问端口),另外要保管好`root`账号的口令,应用系统需要访问数据库时,通常不使用`root`账号进行访问,而是创建其他拥有适当权限的账号来访问。
+ > **说明**:MySQL较新的版本默认不允许使用弱口令作为用户口令,所以我们通过上面的前两条命令修改了验证用户口令的策略和口令的长度。事实上我们不应该使用弱口令,因为存在用户口令被暴力破解的风险。近年来,攻击数据库窃取数据和劫持数据库勒索比特币的事件屡见不鲜,要避免这些潜在的风险,最为重要的一点是不要让数据库服务器暴露在公网上(最好的做法是将数据库置于内网,至少要做到不向公网开放数据库服务器的访问端口),另外要保管好`root`账号的口令,应用系统需要访问数据库时,通常不使用`root`账号进行访问,而是创建其他拥有适当权限的账号来访问。
再次使用客户端工具连接MySQL服务器时,就可以使用新设置的口令了。在实际开发中,为了方便用户操作,可以选择图形化的客户端工具来连接MySQL服务器,包括:
@@ -243,21 +245,21 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
-- 创建学院表
create table tb_college
(
- collid int auto_increment comment '编号',
- collname varchar(50) not null comment '名称',
- intro varchar(500) default '' comment '介绍',
+ collid int auto_increment comment '编号',
+ collname varchar(50) not null comment '名称',
+ collintro varchar(500) default '' comment '介绍',
primary key (collid)
);
-- 创建学生表
create table tb_student
(
- stuid int not null comment '学号',
- stuname varchar(20) not null comment '姓名',
- sex boolean default 1 comment '性别',
- birth date not null comment '出生日期',
- addr varchar(255) default '' comment '籍贯',
- collid int not null comment '所属学院',
+ stuid int not null comment '学号',
+ stuname varchar(20) not null comment '姓名',
+ stusex boolean default 1 comment '性别',
+ stubirth date not null comment '出生日期',
+ stuaddr varchar(255) default '' comment '籍贯',
+ collid int not null comment '所属学院',
primary key (stuid),
foreign key (collid) references tb_college (collid)
);
@@ -265,10 +267,10 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
-- 创建教师表
create table tb_teacher
(
- teaid int not null comment '工号',
- teaname varchar(20) not null comment '姓名',
- title varchar(10) default '助教' comment '职称',
- collid int not null comment '所属学院',
+ teaid int not null comment '工号',
+ teaname varchar(20) not null comment '姓名',
+ teatitle varchar(10) default '助教' comment '职称',
+ collid int not null comment '所属学院',
primary key (teaid),
foreign key (collid) references tb_college (collid)
);
@@ -276,10 +278,10 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
-- 创建课程表
create table tb_course
(
- couid int not null comment '编号',
- couname varchar(50) not null comment '名称',
- credit int not null comment '学分',
- teaid int not null comment '授课老师',
+ couid int not null comment '编号',
+ couname varchar(50) not null comment '名称',
+ coucredit int not null comment '学分',
+ teaid int not null comment '授课老师',
primary key (couid),
foreign key (teaid) references tb_teacher (teaid)
);
@@ -287,11 +289,11 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
-- 创建选课记录表
create table tb_record
(
- recid int auto_increment comment '选课记录编号',
- sid int not null comment '选课学生',
- cid int not null comment '所选课程',
- seldate datetime default now() comment '选课时间日期',
- score decimal(4,1) comment '考试成绩',
+ recid int auto_increment comment '选课记录编号',
+ sid int not null comment '选课学生',
+ cid int not null comment '所选课程',
+ seldate datetime default now() comment '选课时间日期',
+ score decimal(4,1) comment '考试成绩',
primary key (recid),
foreign key (sid) references tb_student (stuid),
foreign key (cid) references tb_course (couid),
@@ -548,13 +550,13 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
```SQL
-- 插入学院数据
- insert into tb_college (collname, intro) values
- ('计算机学院', '创建于1956年是我国首批建立计算机专业。学院现有计算机科学与技术一级学科和网络空间安全一级学科博士学位授予权,其中计算机科学与技术一级学科具有博士后流动站。计算机科学与技术一级学科在2017年全国第四轮学科评估中评为A;2019 U.S.News全球计算机学科排名26名;ESI学科排名0.945‰,进入全球前1‰,位列第43位。'),
- ('外国语学院', '1998年浙江大学、杭州大学、浙江农业大学、浙江医科大学四校合并,成立新的浙江大学。1999年原浙江大学外语系、原杭州大学外国语学院、原杭州大学大外部、原浙江农业大学公外部、原浙江医科大学外语教学部合并,成立浙江大学外国语学院。2003年学院更名为浙江大学外国语言文化与国际交流学院。'),
- ('经济管理学院', '四川大学经济学院历史悠久、传承厚重,其前身是创办于1905年的四川大学经济科,距今已有100多年的历史。已故著名经济学家彭迪先、张与九、蒋学模、胡寄窗、陶大镛、胡代光,以及当代著名学者刘诗白等曾先后在此任教或学习。在长期的办学过程中,学院坚持以马克思主义的立场、观点、方法为指导,围绕建设世界一流经济学院的奋斗目标,做实“两个伟大”深度融合,不断提高党的建设质量与科学推进一流事业深度融合。');
+ insert into tb_college (collname, collintro) values
+ ('计算机学院', '计算机学院1958年设立计算机专业,1981年建立计算机科学系,1998年设立计算机学院,2005年5月,为了进一步整合教学和科研资源,学校决定,计算机学院和软件学院行政班子合并统一运作、实行教学和学生管理独立运行的模式。 学院下设三个系:计算机科学与技术系、物联网工程系、计算金融系;两个研究所:图象图形研究所、网络空间安全研究院(2015年成立);三个教学实验中心:计算机基础教学实验中心、IBM技术中心和计算机专业实验中心。'),
+ ('外国语学院', '四川大学外国语学院设有7个教学单位,6个文理兼收的本科专业;拥有1个一级学科博士授予点,3个二级学科博士授予点,5个一级学科硕士学位授权点,5个二级学科硕士学位授权点,5个硕士专业授权领域,同时还有2个硕士专业学位(MTI)专业;有教职员工210余人,其中教授、副教授80余人,教师中获得中国国内外名校博士学位和正在职攻读博士学位的教师比例占专任教师的60%以上。'),
+ ('经济管理学院', '四川大学经济学院前身是创办于1905年的四川大学经济科;已故经济学家彭迪先、张与九、蒋学模、胡寄窗、陶大镛、胡代光,以及当代学者刘诗白等曾先后在此任教或学习;1905年,四川大学设经济科;1924年,四川大学经济系成立;1998年,四川大学经济管理学院变更为四川大学经济学院。');
-- 插入学生数据
- insert into tb_student (stuid, stuname, sex, birth, addr, collid) values
+ insert into tb_student (stuid, stuname, stusex, stubirth, stuaddr, collid) values
(1001, '杨逍', 1, '1990-3-4', '四川成都', 1),
(1002, '任我行', 1, '1992-2-2', '湖南长沙', 1),
(1033, '王语嫣', 0, '1989-12-3', '四川成都', 1),
@@ -571,10 +573,10 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
delete from tb_student where stuid=4040;
-- 更新学生数据
- update tb_student set stuname='杨过', addr='湖南长沙' where stuid=1001;
+ update tb_student set stuname='杨过', stuaddr='湖南长沙' where stuid=1001;
-- 插入老师数据
- insert into tb_teacher (teaid, teaname, title, collid) values
+ insert into tb_teacher (teaid, teaname, teatitle, collid) values
(1122, '张三丰', '教授', 1),
(1133, '宋远桥', '副教授', 1),
(1144, '杨逍', '副教授', 1),
@@ -582,7 +584,7 @@ MySQL在过去由于性能高、成本低、可靠性好,已经成为最流行
(3366, '韦一笑', '讲师', 3);
-- 插入课程数据
- insert into tb_course (couid, couname, credit, teaid) values
+ insert into tb_course (couid, couname, coucredit, teaid) values
(1111, 'Python程序设计', 3, 1122),
(2222, 'Web前端开发', 2, 1122),
(3333, '操作系统', 4, 1122),
@@ -936,15 +938,16 @@ drop index idx_student_name on tb_student;
创建视图。
```SQL
-create view vw_score
+create view vw_avg_score
as
- select sid, round(avg(score), 1) as avgscore from tb_record group by sid;
+ select sid, round(avg(score), 1) as avgscore
+ from tb_record group by sid;
create view vw_student_score
as
- select stuname, avgscore
- from tb_student, vw_score
- where stuid=sid;
+ select stuname, avgscore
+ from tb_student, vw_avg_score
+ where stuid=sid;
```
> **提示**:因为视图不包含数据,所以每次使用视图时,都必须执行查询以获得数据,如果你使用了连接查询、嵌套查询创建了较为复杂的视图,你可能会发现查询性能下降得很厉害。因此,在使用复杂的视图前,应该进行测试以确保其性能能够满足应用的需求。
@@ -1199,7 +1202,7 @@ insert into tb_emp values
# 1. 创建数据库连接对象
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
- user='root', password='123456')
+ user='yourname', password='yourpass')
try:
# 2. 通过连接对象获取游标
with con.cursor() as cursor:
@@ -1231,7 +1234,7 @@ insert into tb_emp values
no = int(input('编号: '))
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
- user='root', password='123456',
+ user='yourname', password='yourpass',
autocommit=True)
try:
with con.cursor() as cursor:
@@ -1263,7 +1266,7 @@ insert into tb_emp values
loc = input('所在地: ')
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
- user='root', password='123456',
+ user='yourname', password='yourpass',
autocommit=True)
try:
with con.cursor() as cursor:
@@ -1291,7 +1294,7 @@ insert into tb_emp values
def main():
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
- user='root', password='123456')
+ user='yourname', password='yourpass')
try:
with con.cursor(cursor=DictCursor) as cursor:
cursor.execute('select dno as no, dname as name, dloc as loc from tb_dept')
@@ -1334,7 +1337,7 @@ insert into tb_emp values
size = int(input('大小: '))
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
- user='root', password='123456')
+ user='yourname', password='yourpass')
try:
with con.cursor() as cursor:
cursor.execute(
diff --git a/Day36-40/39-40.NoSQL入门.md b/Day36-40/39-40.NoSQL入门.md
index c5fbe4c..0b97878 100644
--- a/Day36-40/39-40.NoSQL入门.md
+++ b/Day36-40/39-40.NoSQL入门.md
@@ -16,7 +16,7 @@ NoSQL数据库按照其存储类型可以大致分为以下几类:
| 图数据库 | Neo4J FlockDB JanusGraph | 使用图结构进行语义查询的数据库,它使用节点、边和属性来表示和存储数据。图数据库从设计上,就可以简单快速的检索难以在关系系统中建模的复杂层次结构。 |
| 对象数据库 | db4o Versant | 通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据。 |
-> 说明:想了解更多的NoSQL数据库,可以访问 。
+> **说明**:想了解更多的NoSQL数据库,可以访问 。
### Redis概述
@@ -107,7 +107,7 @@ redis-server
方式一:通过参数指定认证口令和AOF持久化方式。
```Shell
-redis-server --requirepass 1qaz2wsx --appendonly yes
+redis-server --requirepass yourpass --appendonly yes
```
方式二:通过指定的配置文件来修改Redis的配置。
@@ -119,7 +119,7 @@ redis-server /root/redis-5.0.4/redis.conf
下面我们使用第一种方式来启动Redis并将其置于后台运行,将Redis产生的输出重定向到名为redis.log的文件中。
```Shell
-redis-server --requirepass 1qaz2wsx > redis.log &
+redis-server --requirepass yourpass > redis.log &
```
可以通过ps或者netstat来检查Redis服务器是否启动成功。
@@ -133,7 +133,7 @@ netstat -nap | grep redis-server
```Shell
redis-cli
-127.0.0.1:6379> auth 1qaz2wsx
+127.0.0.1:6379> auth yourpass
OK
127.0.0.1:6379> ping
PONG
@@ -144,7 +144,7 @@ Redis有着非常丰富的数据类型,也有很多的命令来操作这些数

-> 说明:上面的插图来自付磊和张益军先生编著的《Redis开发与运维》一书。
+> **说明**:上面的插图来自付磊和张益军先生编著的《Redis开发与运维》一书。
```Shell
127.0.0.1:6379> set username admin
@@ -274,7 +274,7 @@ python3
```Python
>>> import redis
->>> client = redis.Redis(host='1.2.3.4', port=6379, password='1qaz2wsx')
+>>> client = redis.Redis(host='1.2.3.4', port=6379, password='yourpass')
>>> client.set('username', 'admin')
True
>>> client.hset('student', 'name', 'hao')
@@ -297,7 +297,7 @@ MongoDB是2009年问世的一个面向文档的数据库管理系统,由C++语
MongoDB将数据存储为一个文档,一个文档由一系列的“键值对”组成,其文档类似于JSON对象,但是MongoDB对JSON进行了二进制处理(能够更快的定位key和value),因此其文档的存储格式称为BSON。关于JSON和BSON的差别大家可以看看MongoDB官方网站的文章[《JSON and BSON》](https://www.mongodb.com/json-and-bson)。
-目前,MongoDB已经提供了对Windows、MacOS、Linux、Solaris等多个平台的支持,而且也提供了多种开发语言的驱动程序,Python当然是其中之一。
+目前,MongoDB已经提供了对Windows、macOS、Linux、Solaris等多个平台的支持,而且也提供了多种开发语言的驱动程序,Python当然是其中之一。
#### MongoDB的安装和配置
@@ -320,7 +320,7 @@ mongod --bind_ip 172.18.61.250
2018-06-03T18:03:28.945+0800 I NETWORK [initandlisten] waiting for connections on port 27017
```
-> 说明:上面的操作中,export命令是设置PATH环境变量,这样可以在任意路径下执行mongod来启动MongoDB服务器。MongoDB默认保存数据的路径是/data/db目录,为此要提前创建该目录。此外,在使用mongod启动MongoDB服务器时,--bind_ip参数用来将服务绑定到指定的IP地址,也可以用--port参数来指定端口,默认端口为27017。
+> **说明**:上面的操作中,export命令是设置PATH环境变量,这样可以在任意路径下执行mongod来启动MongoDB服务器。MongoDB默认保存数据的路径是/data/db目录,为此要提前创建该目录。此外,在使用mongod启动MongoDB服务器时,--bind_ip参数用来将服务绑定到指定的IP地址,也可以用--port参数来指定端口,默认端口为27017。
#### MongoDB基本概念
diff --git a/Day36-40/code/HRS_create_and_init.sql b/Day36-40/code/HRS_create_and_init.sql
index b8bc864..4b991e4 100644
--- a/Day36-40/code/HRS_create_and_init.sql
+++ b/Day36-40/code/HRS_create_and_init.sql
@@ -1,5 +1,5 @@
drop database if exists hrs;
-create database hrs default charset utf8;
+create database hrs default charset utf8mb4;
use hrs;
@@ -14,6 +14,8 @@ dloc varchar(20) not null comment '所在地',
primary key (dno)
);
+-- alter table tb_dept add constraint pk_dept_dno primary key(dno);
+
insert into tb_dept values
(10, '会计部', '北京'),
(20, '研发部', '成都'),
@@ -29,10 +31,13 @@ mgr int comment '主管编号',
sal int not null comment '员工月薪',
comm int comment '每月补贴',
dno int comment '所在部门编号',
-primary key (eno)
+primary key (eno),
+foreign key (dno) references tb_dept(dno),
+foreign key (mgr) references tb_emp(eno)
);
-alter table tb_emp add constraint fk_emp_dno foreign key (dno) references tb_dept (dno);
+-- alter table tb_emp add constraint fk_emp_mgr foreign key (mgr) references tb_emp (eno);
+-- alter table tb_emp add constraint fk_emp_dno foreign key (dno) references tb_dept (dno);
insert into tb_emp values
(7800, '张三丰', '总裁', null, 9000, 1200, 20),
@@ -51,7 +56,7 @@ insert into tb_emp values
(3588, '朱九真', '会计', 5566, 2500, null, 10);
--- 查询月薪最高的员工姓名和工资
+-- 查询月薪最高的员工姓名和月薪
-- 查询员工的姓名和年薪((月薪+补贴)*13)
@@ -59,14 +64,14 @@ insert into tb_emp values
-- 查询所有部门的名称和人数
--- 查询月薪最高的员工(Boss除外)的姓名和工资
+-- 查询月薪最高的员工(Boss除外)的姓名和月薪
--- 查询薪水超过平均薪水的员工的姓名和工资
+-- 查询薪水超过平均薪水的员工的姓名和月薪
--- 查询薪水超过其所在部门平均薪水的员工的姓名、部门编号和工资
+-- 查询薪水超过其所在部门平均薪水的员工的姓名、部门编号和月薪
--- 查询部门中薪水最高的人姓名、工资和所在部门名称
+-- 查询部门中薪水最高的人姓名、月薪和所在部门名称
-- 查询主管的姓名和职位
--- 查询月薪排名4~6名的员工姓名和工资
+-- 查询月薪排名4~6名的员工排名、姓名和月薪
diff --git a/Day36-40/code/SRS_create_and_init.sql b/Day36-40/code/SRS_create_and_init.sql
index 301c7bc..637e514 100644
--- a/Day36-40/code/SRS_create_and_init.sql
+++ b/Day36-40/code/SRS_create_and_init.sql
@@ -2,7 +2,7 @@
drop database if exists school;
-- 创建名为school的数据库并设置默认的字符集和排序方式
-create database school default charset utf8 collate utf8_bin;
+create database school default charset utf8;
-- 切换到school数据库上下文环境
use school;
@@ -10,35 +10,32 @@ use school;
-- 创建学院表
create table tb_college
(
-collid int not null auto_increment comment '编号',
-collname varchar(50) not null comment '名称',
-collmaster varchar(20) not null comment '院长',
-collweb varchar(511) default '' comment '网站',
+collid int auto_increment comment '编号',
+collname varchar(50) not null comment '名称',
+collintro varchar(500) default '' comment '介绍',
primary key (collid)
);
-- 创建学生表
create table tb_student
(
-stuid int not null comment '学号',
-stuname varchar(20) not null comment '姓名',
-stusex bit default 1 comment '性别',
-stubirth date not null comment '出生日期',
-stuaddr varchar(255) default '' comment '籍贯',
-collid int not null comment '所属学院',
+stuid int not null comment '学号',
+stuname varchar(20) not null comment '姓名',
+stusex boolean default 1 comment '性别',
+stubirth date not null comment '出生日期',
+stuaddr varchar(255) default '' comment '籍贯',
+collid int not null comment '所属学院',
primary key (stuid),
foreign key (collid) references tb_college (collid)
);
--- alter table tb_student add constraint fk_student_collid foreign key (collid) references tb_college (collid);
-
-- 创建教师表
create table tb_teacher
(
-teaid int not null comment '工号',
-teaname varchar(20) not null comment '姓名',
-teatitle varchar(10) default '助教' comment '职称',
-collid int not null comment '所属学院',
+teaid int not null comment '工号',
+teaname varchar(20) not null comment '姓名',
+teatitle varchar(10) default '助教' comment '职称',
+collid int not null comment '所属学院',
primary key (teaid),
foreign key (collid) references tb_college (collid)
);
@@ -46,48 +43,54 @@ foreign key (collid) references tb_college (collid)
-- 创建课程表
create table tb_course
(
-couid int not null comment '编号',
-couname varchar(50) not null comment '名称',
-coucredit int not null comment '学分',
-teaid int not null comment '授课老师',
+couid int not null comment '编号',
+couname varchar(50) not null comment '名称',
+coucredit int not null comment '学分',
+teaid int not null comment '授课老师',
primary key (couid),
foreign key (teaid) references tb_teacher (teaid)
);
-- 创建选课记录表
-create table tb_score
+create table tb_record
(
-scid int auto_increment comment '选课记录编号',
-stuid int not null comment '选课学生',
-couid int not null comment '所选课程',
-scdate datetime comment '选课时间日期',
-scmark decimal(4,1) comment '考试成绩',
-primary key (scid),
-foreign key (stuid) references tb_student (stuid),
-foreign key (couid) references tb_course (couid)
+recid int auto_increment comment '选课记录编号',
+sid int not null comment '选课学生',
+cid int not null comment '所选课程',
+seldate datetime default now() comment '选课时间日期',
+score decimal(4,1) comment '考试成绩',
+primary key (recid),
+foreign key (sid) references tb_student (stuid),
+foreign key (cid) references tb_course (couid),
+unique (sid, cid)
);
--- 添加唯一性约束(一个学生选某个课程只能选一次)
-alter table tb_score add constraint uni_score_stuid_couid unique (stuid, couid);
-
-- 插入学院数据
-insert into tb_college (collname, collmaster, collweb) values
-('计算机学院', '左冷禅', 'http://www.abc.com'),
-('外国语学院', '岳不群', 'http://www.xyz.com'),
-('经济管理学院', '风清扬', 'http://www.foo.com');
+insert into tb_college (collname, collintro) values
+('计算机学院', '计算机学院1958年设立计算机专业,1981年建立计算机科学系,1998年设立计算机学院,2005年5月,为了进一步整合教学和科研资源,学校决定,计算机学院和软件学院行政班子合并统一运作、实行教学和学生管理独立运行的模式。 学院下设三个系:计算机科学与技术系、物联网工程系、计算金融系;两个研究所:图象图形研究所、网络空间安全研究院(2015年成立);三个教学实验中心:计算机基础教学实验中心、IBM技术中心和计算机专业实验中心。'),
+('外国语学院', '四川大学外国语学院设有7个教学单位,6个文理兼收的本科专业;拥有1个一级学科博士授予点,3个二级学科博士授予点,5个一级学科硕士学位授权点,5个二级学科硕士学位授权点,5个硕士专业授权领域,同时还有2个硕士专业学位(MTI)专业;有教职员工210余人,其中教授、副教授80余人,教师中获得中国国内外名校博士学位和正在职攻读博士学位的教师比例占专任教师的60%以上。'),
+('经济管理学院', '四川大学经济学院前身是创办于1905年的四川大学经济科;已故经济学家彭迪先、张与九、蒋学模、胡寄窗、陶大镛、胡代光,以及当代学者刘诗白等曾先后在此任教或学习;1905年,四川大学设经济科;1924年,四川大学经济系成立;1998年,四川大学经济管理学院变更为四川大学经济学院。');
-- 插入学生数据
-insert into tb_student (stuid, stuname, stusex, stubirth, stuaddr, collid) values
-(1001, '杨逍', 1, '1990-3-4', '四川成都', 1),
-(1002, '任我行', 1, '1992-2-2', '湖南长沙', 1),
-(1033, '王语嫣', 0, '1989-12-3', '四川成都', 1),
-(1572, '岳不群', 1, '1993-7-19', '陕西咸阳', 1),
-(1378, '纪嫣然', 0, '1995-8-12', '四川绵阳', 1),
-(1954, '林平之', 1, '1994-9-20', '福建莆田', 1),
-(2035, '东方不败', 1, '1988-6-30', null, 2),
-(3011, '林震南', 1, '1985-12-12', '福建莆田', 3),
-(3755, '项少龙', 1, '1993-1-25', null, 3),
-(3923, '杨不悔', 0, '1985-4-17', '四川成都', 3);
+insert into tb_student (stuid, stuname, stusex, stubirth, stuaddr, collid)
+values
+ (1001, '杨逍', 1, '1990-3-4', '四川成都', 1),
+ (1002, '任我行', 1, '1992-2-2', '湖南长沙', 1),
+ (1033, '王语嫣', 0, '1989-12-3', '四川成都', 1),
+ (1572, '岳不群', 1, '1993-7-19', '陕西咸阳', 1),
+ (1378, '纪嫣然', 0, '1995-8-12', '四川绵阳', 1),
+ (1954, '林平之', 1, '1994-9-20', '福建莆田', 1),
+ (2035, '东方不败', 1, '1988-6-30', null, 2),
+ (3011, '林震南', 1, '1985-12-12', '福建莆田', 3),
+ (3755, '项少龙', 1, '1993-1-25', null, 3),
+ (3923, '杨不悔', 0, '1985-4-17', '四川成都', 3),
+ (4040, '炼腰的隔壁老王', 1, '1989-1-1', '四川成都', 2);
+
+-- 删除学生数据
+delete from tb_student where stuid=4040;
+
+-- 更新学生数据
+update tb_student set stuname='杨过', stuaddr='湖南长沙' where stuid=1001;
-- 插入老师数据
insert into tb_teacher (teaid, teaname, teatitle, collid) values
@@ -110,7 +113,7 @@ insert into tb_course (couid, couname, coucredit, teaid) values
(9999, '审计学', 3, 3366);
-- 插入选课数据
-insert into tb_score (stuid, couid, scdate, scmark) values
+insert into tb_record (sid, cid, seldate, score) values
(1001, 1111, '2017-09-01', 95),
(1001, 2222, '2017-09-01', 87.5),
(1001, 3333, '2017-09-01', 100),
@@ -125,9 +128,9 @@ insert into tb_score (stuid, couid, scdate, scmark) values
(1378, 1111, '2017-09-05', 82),
(1378, 7777, '2017-09-02', 65.5),
(2035, 7777, '2018-09-03', 88),
-(2035, 9999, curdate(), null),
-(3755, 1111, date(now()), null),
-(3755, 8888, date(now()), null),
+(2035, 9999, default, null),
+(3755, 1111, default, null),
+(3755, 8888, default, null),
(3755, 9999, '2017-09-01', 92);
-- 查询所有学生信息
@@ -227,8 +230,6 @@ select stuname, couname, scmark from tb_student t1 inner join tb_score t3 on t1.
select stuname, couname, scmark from tb_student t1 inner join tb_score t3 on t1.stuid=t3.stuid inner join tb_course t2 on t2.couid=t3.couid where scmark is not null order by scmark desc limit 10, 5;
--- 单表:65535TB
--- 单列:4G - LONGBLOB (Binary Large OBject) / LONGTEXT
-- 查询选课学生的姓名和平均成绩(子查询和连接查询)
select stuname, avgmark from tb_student t1, (select stuid, avg(scmark) as avgmark from tb_score group by stuid) t2 where t1.stuid=t2.stuid;
diff --git a/Day36-40/code/contact/main.py b/Day36-40/code/contact/main.py
index 2e95a33..70ebb36 100644
--- a/Day36-40/code/contact/main.py
+++ b/Day36-40/code/contact/main.py
@@ -171,8 +171,8 @@ def find_contacters(con):
def main():
- con = pymysql.connect(host='120.77.222.217', port=3306,
- user='root', passwd='123456',
+ con = pymysql.connect(host='1.2.3.4', port=3306,
+ user='yourname', passwd='yourpass',
db='address', charset='utf8',
autocommit=True,
cursorclass=pymysql.cursors.DictCursor)
diff --git a/Day36-40/res/conceptual_model.png b/Day36-40/res/conceptual_model.png
index 2b93a21..0e87815 100644
Binary files a/Day36-40/res/conceptual_model.png and b/Day36-40/res/conceptual_model.png differ
diff --git a/Day36-40/res/er_diagram.png b/Day36-40/res/er_diagram.png
index e851a30..434216e 100644
Binary files a/Day36-40/res/er_diagram.png and b/Day36-40/res/er_diagram.png differ
diff --git a/Day36-40/res/redis-aof.png b/Day36-40/res/redis-aof.png
index bdd13c6..f7575df 100644
Binary files a/Day36-40/res/redis-aof.png and b/Day36-40/res/redis-aof.png differ
diff --git a/Day36-40/res/redis-bind-and-port.png b/Day36-40/res/redis-bind-and-port.png
index 1abc58f..dc26d98 100644
Binary files a/Day36-40/res/redis-bind-and-port.png and b/Day36-40/res/redis-bind-and-port.png differ
diff --git a/Day36-40/res/redis-data-types.png b/Day36-40/res/redis-data-types.png
index bb6d74e..a45625c 100644
Binary files a/Day36-40/res/redis-data-types.png and b/Day36-40/res/redis-data-types.png differ
diff --git a/Day36-40/res/redis-databases.png b/Day36-40/res/redis-databases.png
index d076640..b6f8a92 100644
Binary files a/Day36-40/res/redis-databases.png and b/Day36-40/res/redis-databases.png differ
diff --git a/Day36-40/res/redis-hash.png b/Day36-40/res/redis-hash.png
index 29329af..0d86fd0 100644
Binary files a/Day36-40/res/redis-hash.png and b/Day36-40/res/redis-hash.png differ
diff --git a/Day36-40/res/redis-list.png b/Day36-40/res/redis-list.png
index 2ccd893..00f23f3 100644
Binary files a/Day36-40/res/redis-list.png and b/Day36-40/res/redis-list.png differ
diff --git a/Day36-40/res/redis-rdb-1.png b/Day36-40/res/redis-rdb-1.png
index 55dcc61..b868bc5 100644
Binary files a/Day36-40/res/redis-rdb-1.png and b/Day36-40/res/redis-rdb-1.png differ
diff --git a/Day36-40/res/redis-rdb-3.png b/Day36-40/res/redis-rdb-3.png
index fd9983e..958702f 100644
Binary files a/Day36-40/res/redis-rdb-3.png and b/Day36-40/res/redis-rdb-3.png differ
diff --git a/Day36-40/res/redis-replication.png b/Day36-40/res/redis-replication.png
index c1f67a0..657508b 100644
Binary files a/Day36-40/res/redis-replication.png and b/Day36-40/res/redis-replication.png differ
diff --git a/Day36-40/res/redis-security.png b/Day36-40/res/redis-security.png
index 44c2fee..3c70471 100644
Binary files a/Day36-40/res/redis-security.png and b/Day36-40/res/redis-security.png differ
diff --git a/Day36-40/res/redis-set.png b/Day36-40/res/redis-set.png
index 1962b16..b9f15c3 100644
Binary files a/Day36-40/res/redis-set.png and b/Day36-40/res/redis-set.png differ
diff --git a/Day36-40/res/redis-slow-logs.png b/Day36-40/res/redis-slow-logs.png
index 474a1db..10816aa 100644
Binary files a/Day36-40/res/redis-slow-logs.png and b/Day36-40/res/redis-slow-logs.png differ
diff --git a/Day36-40/res/redis-string.png b/Day36-40/res/redis-string.png
index 7cef9df..60d9b5b 100644
Binary files a/Day36-40/res/redis-string.png and b/Day36-40/res/redis-string.png differ
diff --git a/Day36-40/res/redis-zset.png b/Day36-40/res/redis-zset.png
index d3df613..c87b486 100644
Binary files a/Day36-40/res/redis-zset.png and b/Day36-40/res/redis-zset.png differ
diff --git a/Day41-55/41.Django快速上手.md b/Day41-55/41.Django快速上手.md
new file mode 100644
index 0000000..ff50eb7
--- /dev/null
+++ b/Day41-55/41.Django快速上手.md
@@ -0,0 +1,339 @@
+## Django快速上手
+
+Web开发的早期阶段,开发者需要手动编写每个页面,例如一个新闻门户网站,每天都要修改它的HTML页面,随着网站规模和体量的增大,这种做法一定是非常糟糕的。为了解决这个问题,开发人员想到了用程序来为Web服务器生成动态内容,也就是说网页中的动态内容不再通过手动编写而是通过程序自动生成。最早的时候,这项技术被称为CGI(公共网关接口),当然随着时间的推移,CGI暴露出的问题也越来越多,例如大量重复的样板代码,总体性能较为低下等。在时代呼唤新英雄的背景下,PHP、ASP、JSP这类Web应用开发技术在上世纪90年代中后期如雨后春笋般涌现。通常我们说的Web应用是指通过浏览器来访问网络资源的应用程序,因为浏览器的普及性以及易用性,Web应用使用起来方便简单,免除了安装和更新应用程序带来的麻烦;站在开发者的角度,也不用关心用户使用什么样的操作系统,甚至不用区分是PC端还是移动端。
+
+### Web应用机制和术语
+
+下图向我们展示了Web应用的工作流程,其中涉及到的术语如下表所示。
+
+
+
+> 说明:相信有经验的读者会发现,这张图中其实还少了很多东西,例如反向代理服务器、数据库服务器、防火墙等,而且图中的每个节点在实际项目部署时可能是一组节点组成的集群。当然,如果你对这些没有什么概念也不要紧,继续下去就行了,后面会给大家一一讲解的。
+
+| 术语 | 解释 |
+| ------------- | ------------------------------------------------------------ |
+| **URL/URI** | 统一资源定位符/统一资源标识符,网络资源的唯一标识 |
+| **域名** | 与Web服务器地址对应的一个易于记忆的字符串名字 |
+| **DNS** | 域名解析服务,可以将域名转换成对应的IP地址 |
+| **IP地址** | 网络上的主机的身份标识,通过IP地址可以区分不同的主机 |
+| **HTTP** | 超文本传输协议,构建在TCP之上的应用级协议,万维网数据通信的基础 |
+| **反向代理** | 代理客户端向服务器发出请求,然后将服务器返回的资源返回给客户端 |
+| **Web服务器** | 接受HTTP请求,然后返回HTML文件、纯文本文件、图像等资源给请求者 |
+| **Nginx** | 高性能的Web服务器,也可以用作[反向代理](https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86),[负载均衡](https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1) 和 [HTTP缓存](https://zh.wikipedia.org/wiki/HTTP%E7%BC%93%E5%AD%98) |
+
+#### HTTP协议
+
+这里我们先费一些笔墨来说说HTTP这个协议。HTTP(超文本传输协议)是构建于TCP(传输控制协议)之上应用级协议,它利用了TCP提供的可靠的传输服务实现了Web应用中的数据交换。按照维基百科上的介绍,设计HTTP最初的目的是为了提供一种发布和接收[HTML](https://zh.wikipedia.org/wiki/HTML)页面的方法,也就是说这个协议是浏览器和Web服务器之间传输的数据的载体。关于这个协议的详细信息以及目前的发展状况,大家可以阅读[《HTTP 协议入门》](http://www.ruanyifeng.com/blog/2016/08/http.html)、[《互联网协议入门》](http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html)系列以及[《图解HTTPS协议》](http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html)这几篇文章进行了解。下图是我在四川省网络通信技术重点实验室学习和工作期间使用开源协议分析工具Ethereal(抓包工具WireShark的前身)截取的访问百度首页时的HTTP请求和响应的报文(协议数据),由于Ethereal截取的是经过网络适配器的数据,因此可以清晰的看到从物理链路层到应用层的协议数据。
+
+HTTP请求(请求行+请求头+空行+[消息体]):
+
+
+
+HTTP响应(响应行+响应头+空行+消息体):
+
+
+
+> **说明**:这两张图是在2009年9月10日凌晨获得的,但愿这两张如同泛黄的照片般的截图能帮助你了解HTTP到底是什么样子的。当然,如果没有专业的抓包工具,也可以通过浏览器提供的“开发者工具”来查看HTTP请求和响应的数据格式。
+
+### Django概述
+
+Python的Web框架有上百个,比它的关键字还要多。所谓Web框架,就是用于开发Web服务器端应用的基础设施,说得通俗一点就是一系列封装好的模块和工具。事实上,即便没有Web框架,我们仍然可以通过socket或[CGI](https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3)来开发Web服务器端应用,但是这样做的成本和代价在商业项目中通常是不能接受的。通过Web框架,我们可以化繁为简,降低创建、更新、扩展应用程序的工作量。刚才我们说到Python有上百个Web框架,这些框架包括Django、Flask、Tornado、Sanic、Pyramid、Bottle、Web2py、web.py等。
+
+在上述Python的Web框架中,Django无疑是最有代表性的重量级选手,开发者可以基于Django快速的开发可靠的Web应用程序,因为它减少了Web开发中不必要的开销,对常用的设计和开发模式进行了封装,并对MVC架构提供了支持(Django中称之为MTV架构)。MVC是软件系统开发领域中一种放之四海而皆准的架构,它将系统中的组件分为模型(Model)、视图(View)和控制器(Controller)三个部分并借此实现模型(数据)和视图(显示)的解耦合。由于模型和视图进行了分离,所以需要一个中间人将解耦合的模型和视图联系起来,扮演这个角色的就是控制器。稍具规模的软件系统都会使用MVC架构(或者是从MVC演进出的其他架构),Django项目中我们称之为MTV,MTV中的M跟MVC中的M没有区别,就是代表数据的模型,T代表了网页模板(显示数据的视图),而V代表了视图函数,在Django框架中,视图函数和Django框架本身一起扮演了MVC中C的角色。
+
+
+
+Django框架诞生于2003年,它是一个在真正的应用中成长起来的项目,由劳伦斯出版集团旗下在线新闻网站的内容管理系统(CMS)研发团队(主要是Adrian Holovaty和Simon Willison)开发,以比利时的吉普赛爵士吉他手Django Reinhardt来命名。Django框架在2005年夏天作为开源框架发布,使用Django框架能用很短的时间构建出功能完备的网站,因为它代替程序员完成了那些重复乏味的劳动,剩下真正有意义的核心业务给程序员来开发,这一点就是对DRY(Don't Repeat Yourself)理念的最好践行。许多成功的网站和应用都是基于Python语言进行开发的,国内比较有代表性的网站包括:知乎、豆瓣网、果壳网、搜狐闪电邮箱、101围棋网、海报时尚网、背书吧、堆糖、手机搜狐网、咕咚、爱福窝、果库等,其中不乏使用了Django框架的产品。
+
+### 快速上手
+
+#### 第一个Django项目
+
+1. 检查Python环境:Django 1.11需要Python 2.7或Python 3.4以上的版本;Django 2.0需要Python 3.4以上的版本;Django 2.1和2.2需要Python 3.5以上的版本;Django 3.0需要Python 3.6以上版本。
+
+ > **说明**:Django框架不同版本所需的Python解释器环境,可以在Django官方文档的[FAQ](https://docs.djangoproject.com/zh-hans/3.0/faq/install/#faq-python-version-support)中找到。
+
+ 可以在macOS的终端中输入下面的命令检查Python解释器版本,Windows系统可以在命令行提示符中输入`python --version`。
+
+ ```Bash
+python3 --version
+ ```
+
+ 也可以在Python的交互式环境中执行下面的代码来查看Python解释器的版本。
+
+ ```Shell
+ import sys
+ sys.version
+ sys.version_info
+ ```
+
+2. 更新包管理工具并安装Django环境(用于创建Django项目)。
+
+ > **说明**:在更新这个文档时,Django最新的正式版本是3.0.7,Django 3.0提供了对ASGI的支持,可以实现全双工的异步通信,但是目前的使用体验一般,所以暂时不推荐大家使用Django 3.0,下面我们安装的是Django 2.2.13版本。使用`pip`安装三方库和工具时,可以通过`==`来指定安装的版本。
+
+ ```Bash
+ pip3 install -U pip
+ pip3 install django==2.2.13
+ ```
+
+3. 检查Django环境并使用`django-admin`命令创建Django项目(项目名称为hellodjango)。
+
+ ```Shell
+ django-admin --version
+ django-admin startproject hellodjango
+ ```
+
+4. 用PyCharm打开创建好的Djang项目,并为其添加虚拟环境。
+
+ 
+
+ 如上图所示,PyCharm的项目浏览器中,最顶层的文件夹`hellodjango`是Python项目文件夹,这个文件夹的名字并不重要,Django项目也不关心这个文件夹叫什么名字。该文件夹下有一个同名的文件夹,它是Django项目文件夹,其中包含了`__init__.py`、`settings.py`、`urls.py`、`wsgi.py`四个文件,与名为`hellodjango`的Django项目文件夹同级的还有一个名为`manage.py` 的文件,这些文件的作用如下所示:
+
+ - `hellodjango/__init__.py`:空文件,告诉Python解释器这个目录应该被视为一个Python的包。
+ - `hellodjango/settings.py`:Django项目的配置文件。
+ - `hellodjango/urls.py`:Django项目的URL映射声明,就像是网站的“目录”。
+ - `hellodjango/wsgi.py`:项目运行在WSGI兼容Web服务器上的入口文件。
+ - `manage.py`: 管理Django项目的脚本程序。
+
+ > 说明:WSGI全称是Web服务器网关接口,维基百科上给出的解释是“为Python语言定义的[Web服务器](https://zh.wikipedia.org/wiki/%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8)和[Web应用程序](https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F)或框架之间的一种简单而通用的接口”。
+
+ 创建虚拟环境的界面如下图所示。
+
+ 
+
+5. 安装项目依赖项。
+
+ 方法一:打开PyCharm的终端,在终端中通过`pip`命令安装Django项目的依赖项。
+
+ > **说明**:由于已经基于Python 3解释器环境为项目创建了虚拟环境,所以虚拟环境中的`python`命令对应的是Python 3的解释器,而`pip`命令对应的是Python 3的包管理工具。
+
+ ```Shell
+ pip install django==2.2.13
+ ```
+
+ 方法二:在PyCharm的偏好设置中,可以找到项目的解释器环境和已经安装的三方库,可以通过点击添加按钮来安装新的依赖项,需要提醒大家的是在安装Django依赖项时,需要指定版本号,否则将默认安装更新本文时最新的3.0.7版本。
+
+ 
+
+ 下图展示了Django版本和Python版本的对应关系,请大家自行对号入座。
+
+ | Django版本 | Python版本 |
+ | ---------- | ----------------------------------------- |
+ | 1.8 | 2.7、3.2、3.3、3.4、3.5 |
+ | 1.9、1.10 | 2.7、3.4、3.5 |
+ | 1.11 | 2.7、3.4、3.5、3.6、3.7(Django 1.11.17) |
+ | 2.0 | 3.4、3.5、3.6、3.7 |
+ | 2.1 | 3.5、3.6、3.7 |
+ | 2.2 | 3.5、3.6、3.7、3.8(Django 2.2.8) |
+ | 3.0 | 3.6、3.7、3.8 |
+
+6. 启动Django自带的服务器运行项目。
+
+ 方法一:在“Run”菜单选择“Edit Configuration”,配置“Django server”运行项目(适用于专业版PyCharm)。
+
+ 
+
+ 方法二:在“Run”菜单选择“Edit Configuration”,配置运行“Python”程序运行项目(适用于专业版和社区版PyCharm)。
+
+ 
+
+ 方法三:在PyCharm的终端(Terminal)中通过命令运行项目(适用于专业版和社区版PyCharm)。
+
+ ```Shell
+ python manage.py runserver
+ ```
+
+7. 查看运行效果。
+
+ 在浏览器中输入`http://127.0.0.1:8000`访问我们的服务器,效果如下图所示。
+
+ 
+
+ > **说明**:
+ >
+ > 1. 刚刚启动的Django自带的服务器只能用于开发和测试环境,因为这个服务器是纯Python编写的轻量级Web服务器,不适合在生产环境中使用。
+ > 2. 如果修改了代码,不需要为了让修改的代码生效而重新启动Django自带的服务器。但是,在添加新的项目文件时,该服务器不会自动重新加载,这个时候就得手动重启服务器。
+ > 3. 可以在终端中通过`python manage.py help`命令查看Django管理脚本程序可用的命令参数。
+ > 4. 使用`python manage.py runserver`启动服务器时,可以在后面添加参数来指定IP地址和端口号,默认情况下启动的服务器将运行在本机的`8000`端口。
+ > 5. 在终端中运行的服务器,可以通过Ctrl+C来停止它 。通过PyCharm的“运行配置”运行的服务器直接点击窗口上的关闭按钮就可以终止服务器的运行。
+ > 6. 不能在同一个端口上启动多个服务器,因为会导致地址的冲突(端口是对IP地址的扩展,也是计算机网络地址的一部分)。
+8. 修改项目的配置文件`settings.py`。
+
+ Django是一个支持国际化和本地化的框架,因此刚才我们看到的Django项目的默认首页也是支持国际化的,我们可以通过修改配置文件将默认语言修改为中文,时区设置为东八区。
+
+ 找到修改前的配置(在`settings.py`文件第100行以后)。
+
+ ```Python
+ LANGUAGE_CODE = 'en-us'
+ TIME_ZONE = 'UTC'
+ ```
+
+ 修改为以下内容。
+
+ ```Python
+ LANGUAGE_CODE = 'zh-hans'
+ TIME_ZONE = 'Asia/Chongqing'
+ ```
+
+ 刷新刚才的页面,可以看到修改语言代码和时区之后的结果。
+
+ 
+
+#### 创建自己的应用
+
+如果要开发自己的Web应用,需要先在Django项目中创建“应用”,一个Django项目可以包含一个或多个应用。
+
+1. 在PyCharm的终端中执行下面的命令,创建名为`first`的应用。
+
+ ```Shell
+ python manage.py startapp first
+ ```
+
+ 执行上面的命令会在当前路径下创建`first`目录,其目录结构如下所示:
+
+ - `__init__.py`:一个空文件,告诉Python解释器这个目录应该被视为一个Python的包。
+ - `admin.py`:可以用来注册模型,用于在Django框架自带的管理后台中管理模型。
+ - `apps.py`:当前应用的配置文件。
+ - `migrations`:存放与模型有关的数据库迁移信息。
+ - `__init__.py`:一个空文件,告诉Python解释器这个目录应该被视为一个Python的包。
+ - `models.py`:存放应用的数据模型(MTV中的M)。
+ - `tests.py`:包含测试应用各项功能的测试类和测试函数。
+ - `views.py`:处理用户HTTP请求并返回HTTP响应的函数或类(MTV中的V)。
+
+2. 修改应用目录下的视图文件`views.py`。
+
+ ```Python
+ from django.http import HttpResponse
+
+
+ def show_index(request):
+ return HttpResponse('
Hello, Django! ')
+ ```
+
+4. 修改Django项目目录下的`urls.py`文件,将视图函数和用户在浏览器中请求的路径对应。
+
+ ```Python
+ from django.contrib import admin
+ from django.urls import path, include
+
+ from first.views import show_index
+
+ urlpatterns = [
+ path('admin/', admin.site.urls),
+ path('hello/', show_index),
+ ]
+ ```
+
+5. 重新运行项目,并打开浏览器中访问`http://127.0.0.1:8000/hello/`。
+
+5. 上面我们通过代码为浏览器生成了内容,但仍然是静态内容,如果要生成动态内容,可以修改`views.py`文件并添加如下所示的代码。
+
+ ```Python
+ from random import sample
+
+ from django.http import HttpResponse
+
+
+ def show_index(request):
+ fruits = [
+ 'Apple', 'Orange', 'Pitaya', 'Durian', 'Waxberry', 'Blueberry',
+ 'Grape', 'Peach', 'Pear', 'Banana', 'Watermelon', 'Mango'
+ ]
+ selected_fruits = sample(fruits, 3)
+ content = '
今天推荐的水果是: '
+ content += '
'
+ content += '
'
+ for fruit in selected_fruits:
+ content += f'{fruit} '
+ content += ' '
+ return HttpResponse(content)
+ ```
+
+6. 刷新页面查看程序的运行结果,看看每次刷新的网页的时候,是不是可以看到不一样的内容。
+
+
+#### 使用模板
+
+上面通过拼接HTML代码的方式为浏览器生成动态内容的做法在实际开发中是无能接受的,因为实际项目中的前端页面可能非常复杂,无法用这种拼接动态内容的方式来完成,这一点大家一定能够想到。为了解决这个问题,我们可以提前准备一个模板页(MTV中的T),所谓模板页就是一个带占位符和模板指令的HTML页面。
+
+Django框架中有一个名为`render`的便捷函数可以来完成渲染模板的操作。所谓的渲染就是用数据替换掉模板页中的模板指令和占位符,当然这里的渲染称为后端渲染,即在服务器端完成页面的渲染再输出到浏览器中。后端渲染的做法在Web应用的访问量较大时,会让服务器承受较大的负担,所以越来越多的Web应用会选择前端渲染的方式,即服务器只提供页面所需的数据(通常是JSON格式),在浏览器中通过JavaScript代码获取这些数据并渲染页面上。关于前端渲染的内容,我们会在后续的课程中为大家讲解,目前我们使用的是通过模板页进行后端渲染的做法,具体步骤如下所示。
+
+使用模板页的步骤如下所示。
+
+1. 在项目目录下创建名为templates文件夹。
+
+ 
+
+2. 添加模板页`index.html`。
+
+ > **说明**:实际项目开发中,静态页由前端开发者提供,后端开发者需要将静态页修改为模板页,以便通过Python程序对其进行渲染,这种做法就是上面提到的后端渲染。
+
+ ```HTML
+
+
+
+
+
首页
+
+
+
+
今天推荐的水果是:
+
+
+ {% for fruit in fruits %}
+ {{ fruit }}
+ {% endfor %}
+
+
+
+ ```
+ 在上面的模板页中我们使用了`{{ fruit }}`这样的模板占位符语法,也使用了`{% for %}`这样的模板指令,这些都是Django模板语言(DTL)的一部分。关于模板语法和指令,大家可以看看官方文档,相信这些内容还是很容易理解的,并不需要过多的赘述,大家也可以参考[官方文档]()了解模板指令和语法。
+
+3. 修改`views.py`文件,调用`render`函数渲染模板页。
+
+ ```Python
+ from random import sample
+
+ from django.shortcuts import render
+
+
+ def show_index(request):
+ fruits = [
+ 'Apple', 'Orange', 'Pitaya', 'Durian', 'Waxberry', 'Blueberry',
+ 'Grape', 'Peach', 'Pear', 'Banana', 'Watermelon', 'Mango'
+ ]
+ selected_fruits = sample(fruits, 3)
+ return render(request, 'index.html', {'fruits': selected_fruits})
+ ```
+
+ `render`函数的第一个参数是请求对象request,第二个参数是我们要渲染的模板页的名字,第三个参数是要渲染到页面上的数据,我们通过一个字典将数据交给模板页,字典中的键就是模板页中使用的模板指令或占位符中的变量名。
+
+4. 到此为止,视图函数中的`render`还无法找到模板文件`index.html`,需要修改`settings.py`文件,配置模板文件所在的路径。修改`settings.py`文件,找到`TEMPLATES`配置,修改其中的`DIRS`配置。
+
+ ```Python
+ TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+ ]
+ ```
+
+5. 重新运行项目或直接刷新页面查看结果。
+
+### 总结
+
+至此,我们已经利用Django框架完成了一个非常小的Web应用,虽然它并没有任何的实际价值,但是可以通过这个项目对Django框架有一个感性的认识。学习Django最好的资料肯定是它的[官方文档](https://docs.djangoproject.com/zh-hans/2.0/),官方文档提供了对多国语言的支持,而且有新手教程引导初学者学习使用Django框架,建议大家通过阅读Django的官方文档来学习和使用这个框架。当然图灵社区出版的[《Django基础教程》](http://www.ituring.com.cn/book/2630)也是非常适合初学者的入门级读物,有兴趣的读者可以点击链接进行购买。
diff --git a/Day41-55/41.快速上手.md b/Day41-55/41.快速上手.md
deleted file mode 100644
index 76a9af0..0000000
--- a/Day41-55/41.快速上手.md
+++ /dev/null
@@ -1,430 +0,0 @@
-## 快速上手
-
-Web开发的早期阶段,开发者需要手动编写每个页面,例如一个新闻门户网站,每天都要修改它的HTML页面,随着网站规模和体量的增大,这种方式就变得极度糟糕。为了解决这个问题,开发人员想到了用外部程序来为Web服务器生成动态内容,也就是说HTML页面以及页面中的动态内容不再通过手动编写而是通过程序自动生成。最早的时候,这项技术被称为CGI(公共网关接口),当然随着时间的推移,CGI暴露出的问题也越来越多,例如大量重复的样板代码,总体性能较为低下等,因此在时代呼唤新英雄的背景下,PHP、ASP、JSP这类Web应用开发技术在上世纪90年代中后期如雨后春笋般涌现。通常我们说的Web应用是指通过浏览器来访问网络资源的应用程序,因为浏览器的普及性以及易用性,Web应用使用起来方便简单,免除了安装和更新应用程序带来的麻烦,而且也不用关心用户到底用的是什么操作系统,甚至不用区分是PC端还是移动端。
-
-### Web应用机制和术语
-
-下图向我们展示了Web应用的工作流程,其中涉及到的术语如下表所示。
-
-
-
-> 说明:相信有经验的读者会发现,这张图中其实还少了很多东西,例如反向代理服务器、数据库服务器、防火墙等,而且图中的每个节点在实际项目部署时可能是一组节点组成的集群。当然,如果你对这些没有什么概念也不要紧,继续下去就行了,后面会给大家一一讲解的。
-
-| 术语 | 解释 |
-| ------------- | ------------------------------------------------------------ |
-| **URL/URI** | 统一资源定位符/统一资源标识符,网络资源的唯一标识 |
-| **域名** | 与Web服务器地址对应的一个易于记忆的字符串名字 |
-| **DNS** | 域名解析服务,可以将域名转换成对应的IP地址 |
-| **IP地址** | 网络上的主机的身份标识,通过IP地址可以区分不同的主机 |
-| **HTTP** | 超文本传输协议,构建在TCP之上的应用级协议,万维网数据通信的基础 |
-| **反向代理** | 代理客户端向服务器发出请求,然后将服务器返回的资源返回给客户端 |
-| **Web服务器** | 接受HTTP请求,然后返回HTML文件、纯文本文件、图像等资源给请求者 |
-| **Nginx** | 高性能的Web服务器,也可以用作[反向代理](https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86),[负载均衡](https://zh.wikipedia.org/wiki/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1) 和 [HTTP缓存](https://zh.wikipedia.org/wiki/HTTP%E7%BC%93%E5%AD%98) |
-
-#### HTTP协议
-
-这里我们稍微费一些笔墨来谈谈上面提到的HTTP。HTTP(超文本传输协议)是构建于TCP(传输控制协议)之上应用级协议,它利用了TCP提供的可靠的传输服务实现了Web应用中的数据交换。按照维基百科上的介绍,设计HTTP最初的目的是为了提供一种发布和接收[HTML](https://zh.wikipedia.org/wiki/HTML)页面的方法,也就是说这个协议是浏览器和Web服务器之间传输的数据的载体。关于这个协议的详细信息以及目前的发展状况,大家可以阅读阮一峰老师的[《HTTP 协议入门》](http://www.ruanyifeng.com/blog/2016/08/http.html)、[《互联网协议入门》](http://www.ruanyifeng.com/blog/2012/05/internet_protocol_suite_part_i.html)系列以及[《图解HTTPS协议》](http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html)进行了解。下图是我在四川省网络通信技术重点实验室学习和工作期间使用开源协议分析工具Ethereal(抓包工具WireShark的前身)截取的访问百度首页时的HTTP请求和响应的报文(协议数据),由于Ethereal截取的是经过网络适配器的数据,因此可以清晰的看到从物理链路层到应用层的协议数据。
-
-HTTP请求(请求行+请求头+空行+[消息体]):
-
-
-
-HTTP响应(响应行+响应头+空行+消息体):
-
-
-
-> 说明:这两张图是在2009年9月10日截取的,但愿这两张如同泛黄的照片般的截图能帮助你了解HTTP到底是什么样子的。
-
-### Django概述
-
-Python的Web框架有上百个,比它的关键字还要多。所谓Web框架,就是用于开发Web服务器端应用的基础设施(通常指封装好的模块和一系列的工具)。事实上,即便没有Web框架,我们仍然可以通过socket或[CGI](https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E7%BD%91%E5%85%B3%E6%8E%A5%E5%8F%A3)来开发Web服务器端应用,但是这样做的成本和代价在实际开发中通常是不能接受的。通过Web框架,我们可以化繁为简,同时降低创建、更新、扩展应用程序的工作量。Python的Web框架中比较有名的有:Flask、Django、Tornado、Sanic、Pyramid、Bottle、Web2py、web.py等。
-
-在基于Python的Web框架中,Django是所有重量级选手中最有代表性的一位,开发者可以基于Django快速的开发可靠的Web应用程序,因为它减少了Web开发中不必要的开销,对常用的设计和开发模式进行了封装,并对MVC架构提供了支持(MTV)。许多成功的网站和App都是基于Django框架构建的,国内比较有代表性的网站包括:知乎、豆瓣网、果壳网、搜狐闪电邮箱、101围棋网、海报时尚网、背书吧、堆糖、手机搜狐网、咕咚、爱福窝、果库等。
-
-
-
-Django诞生于2003年,它是一个在真正的应用中成长起来的项目,由劳伦斯出版集团旗下在线新闻网站的内容管理系统(CMS)研发团队编写(主要是Adrian Holovaty和Simon Willison),以比利时的吉普赛爵士吉他手Django Reinhardt来命名,在2005年夏天作为开源框架发布。使用Django能用很短的时间构建出功能完备的网站,因为它代替程序员完成了所有乏味和重复的劳动,剩下真正有意义的核心业务给程序员,这一点就是对DRY(Don't Repeat Yourself)理念的最好践行。
-
-### 快速上手
-
-#### 准备工作
-
-1. 检查Python环境:Django 1.11需要Python 2.7或Python 3.4以上的版本;Django 2.0需要Python 3.4以上的版本;Django 2.1需要Python 3.5以上的版本。
-
- > 说明:我自己平时使用macOS做开发,macOS和Linux平台使用的命令跟Windows平台有较大的区别,这一点在之前也有过类似的说明,如果使用Windows平台做开发,替换一下对应的命令即可。
-
- ```Shell
- $ python3 --version
- ```
-
- ```Shell
- $ python3
- >>> import sys
- >>> sys.version
- >>> sys.version_info
- ```
-
-2. 创建项目文件夹并切换到该目录,例如我们要实例一个OA(办公自动化)项目。
-
- ```Shell
- $ mkdir oa
- $ cd oa
- ```
-
-3. 创建并激活虚拟环境。
-
- ```Shell
- $ python3 -m venv venv
- $ source venv/bin/activate
- ```
- > 说明:上面使用了Python自带的venv模块完成了虚拟环境的创建,当然也可以使用virtualenv或pipenv这样的工具。要激活虚拟环境,在Windows环境下可以通过"venv/Scripts/activate"执行批处理文件来实现。
-
-4. 更新包管理工具pip。
-
- ```Shell
- (venv)$ pip install -U pip
- ```
-
- 或
-
- ```Shell
- (venv)$ python -m pip install -U pip
- ```
- > 注意:请注意终端提示符发生的变化,前面的`(venv)`说明我们已经进入虚拟环境,而虚拟环境下的python和pip已经是Python 3的解释器和包管理工具了。
-
-5. 安装Django。
-
- ```Shell
- (venv)$ pip install django
- ```
-
- 或指定版本号来安装对应的Django的版本。
-
- ```Shell
- (venv)$ pip install django==2.1.8
- ```
-
-6. 检查Django的版本。
-
- ```Shell
- (venv)$ python -m django --version
- (venv)$ django-admin --version
- ```
-
- 或
-
- ```Shell
- (venv)$ python
- >>> import django
- >>> django.get_version()
- ```
- 当然,也可以通过pip来查看安装的依赖库及其版本,如:
-
- ```Shell
- (venv)$ pip freeze
- (venv)$ pip list
- ```
-
- 下图展示了Django版本和Python版本的对应关系,如果在安装时没有指定版本号,将自动选择最新的版本(在写作这段内容时,Django最新的版本是2.2)。
-
- | Django版本 | Python版本 |
- | ---------- | ----------------------- |
- | 1.8 | 2.7、3.2、3.3、3.4、3.5 |
- | 1.9、1.10 | 2.7、3.4、3.5 |
- | 1.11 | 2.7、3.4、3.5、3.6、3.7 |
- | 2.0 | 3.4、3.5、3.6、3.7 |
- | 2.1、2.2 | 3.5、3.6、3.7 |
-
-7. 使用`django-admin`创建项目,项目命名为oa。
-
- ```Shell
- (venv)$ django-admin startproject oa .
- ```
-
- > 注意:上面的命令最后的那个点,它表示在当前路径下创建项目。
-
- 执行上面的命令后看看生成的文件和文件夹,它们的作用如下所示:
-
- - `manage.py`: 一个让你可以管理Django项目的工具程序。
- - `oa/__init__.py`:一个空文件,告诉Python解释器这个目录应该被视为一个Python的包。
- - `oa/settings.py`:Django项目的配置文件。
- - `oa/urls.py`:Django项目的URL声明(URL映射),就像是你的网站的“目录”。
- - `oa/wsgi.py`:项目运行在WSGI兼容Web服务器上的接口文件。
-
- > 说明:WSGI全称是Web服务器网关接口,维基百科上给出的解释是“为Python语言定义的[Web服务器](https://zh.wikipedia.org/wiki/%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8)和[Web应用程序](https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F)或框架之间的一种简单而通用的接口”。
-
-8. 启动服务器运行项目。
-
- ```Shell
- (venv)$ python manage.py runserver
- ```
-
- 在浏览器中输入
访问我们的服务器,效果如下图所示。
-
- 
-
-
- > 说明1:刚刚启动的是Django自带的用于开发和测试的服务器,它是一个用纯Python编写的轻量级Web服务器,但它并不是真正意义上的生产级别的服务器,千万不要将这个服务器用于和生产环境相关的任何地方。
-
- > 说明2:用于开发的服务器在需要的情况下会对每一次的访问请求重新载入一遍Python代码。所以你不需要为了让修改的代码生效而频繁的重新启动服务器。然而,一些动作,比如添加新文件,将不会触发自动重新加载,这时你得自己手动重启服务器。
-
- > 说明3:可以通过`python manage.py help`命令查看可用命令列表;在启动服务器时,也可以通过`python manage.py runserver 1.2.3.4:5678`来指定将服务器运行于哪个IP地址和端口。
-
- > 说明4:可以通过Ctrl+C来终止服务器的运行。
-
-9. 接下来我们修改项目的配置文件settings.py,Django是一个支持国际化和本地化的框架,因此刚才我们看到的默认首页也是支持国际化的,我们将默认语言修改为中文,时区设置为东八区。
-
- ```Shell
- (venv)$ vim oa/settings.py
- ```
-
- ```Python
- # 此处省略上面的内容
-
- # 设置语言代码
- LANGUAGE_CODE = 'zh-hans'
- # 设置时区
- TIME_ZONE = 'Asia/Chongqing'
-
- # 此处省略下面的内容
- ```
-
-10. 刷新刚才的页面。
-
- 
-
-#### 动态页面
-
-1. 创建名为hrs(人力资源系统)的应用,一个Django项目可以包含一个或多个应用。
-
- ```Shell
- (venv)$ python manage.py startapp hrs
- ```
-
- 执行上面的命令会在当前路径下创建hrs目录,其目录结构如下所示:
-
- - `__init__.py`:一个空文件,告诉Python解释器这个目录应该被视为一个Python的包。
- - `admin.py`:可以用来注册模型,用于在Django的管理界面管理模型。
- - `apps.py`:当前应用的配置文件。
- - `migrations`:存放与模型有关的数据库迁移信息。
- - `__init__.py`:一个空文件,告诉Python解释器这个目录应该被视为一个Python的包。
- - `models.py`:存放应用的数据模型,即实体类及其之间的关系(MVC/MTV中的M)。
- - `tests.py`:包含测试应用各项功能的测试类和测试函数。
- - `views.py`:处理请求并返回响应的函数(MVC中的C,MTV中的V)。
-
-2. 修改应用目录下的视图文件views.py。
-
- ```Shell
- (venv)$ vim hrs/views.py
- ```
-
- ```Python
- from django.http import HttpResponse
-
-
- def index(request):
- return HttpResponse('Hello, Django! ')
- ```
-
-3. 在应用目录创建一个urls.py文件并映射URL。
-
- ```Shell
- (venv)$ touch hrs/urls.py
- (venv)$ vim hrs/urls.py
- ```
-
- ```Python
- from django.urls import path
-
- from hrs import views
-
- urlpatterns = [
- path('', views.index, name='index'),
- ]
- ```
- > 说明:上面使用的`path`函数是Django 2.x中新添加的函数,除此之外还可以使用支持正则表达式的URL映射函数`re_path`函数;Django 1.x中是用名为`url`函数来设定URL映射。
-
-4. 修改项目目录下的urls.py文件,对应用中设定的URL进行合并。
-
- ```Shell
- (venv) $ vim oa/urls.py
- ```
-
- ```Python
- from django.contrib import admin
- from django.urls import path, include
-
- urlpatterns = [
- path('admin/', admin.site.urls),
- path('hrs/', include('hrs.urls')),
- ]
- ```
-
- > 说明:上面的代码通过`include`函数将hrs应用中配置URL的文件包含到项目的URL配置中,并映射到`hrs/`路径下。
-
-5. 重新运行项目,并打开浏览器中访问。
-
- ```Shell
- (venv)$ python manage.py runserver
- ```
-
-6. 修改views.py生成动态内容。
-
- ```Shell
- (venv)$ vim hrs/views.py
- ```
-
- ```Python
- from io import StringIO
-
- from django.http import HttpResponse
-
- depts_list = [
- {'no': 10, 'name': '财务部', 'location': '北京'},
- {'no': 20, 'name': '研发部', 'location': '成都'},
- {'no': 30, 'name': '销售部', 'location': '上海'},
- ]
-
-
- def index(request):
- output = StringIO()
- output.write('\n')
- output.write('\n')
- output.write('\t \n')
- output.write('\t首页 ')
- output.write('\n')
- output.write('\n')
- output.write('\t部门信息 \n')
- output.write('\t \n')
- output.write('\t\n')
- output.write('\t\t\n')
- output.write('\t\t\t部门编号 \n')
- output.write('\t\t\t部门名称 \n')
- output.write('\t\t\t所在地 \n')
- output.write('\t\t \n')
- for dept in depts_list:
- output.write('\t\t\n')
- output.write(f'\t\t\t{dept["no"]} \n')
- output.write(f'\t\t\t{dept["name"]} \n')
- output.write(f'\t\t\t{dept["location"]} \n')
- output.write('\t\t \n')
- output.write('\t
\n')
- output.write('\n')
- output.write('\n')
- return HttpResponse(output.getvalue())
- ```
-
-7. 刷新页面查看程序的运行结果。
-
- 
-
-#### 使用视图模板
-
-上面通过拼接HTML代码的方式生成动态视图的做法在实际开发中是无能接受的,这一点大家一定能够想到。为了解决这个问题,我们可以提前准备一个模板页,所谓模板页就是一个带占位符的HTML页面,当我们将程序中获得的数据替换掉页面中的占位符时,一个动态页面就产生了。
-
-我们可以用Django框架中template模块的Template类创建模板对象,通过模板对象的render方法实现对模板的渲染,在Django框架中还有一个名为`render`的便捷函数可以来完成渲染模板的操作。所谓的渲染就是用数据替换掉模板页中的占位符,当然这里的渲染称为后端渲染,即在服务器端完成页面的渲染再输出到浏览器中,这种做法的主要坏处是当并发访问量较大时,服务器会承受较大的负担,所以今天有很多的Web应用都使用了前端渲染,即服务器只提供所需的数据(通常是JSON格式),在浏览器中通过JavaScript获取这些数据并渲染到页面上,这个我们在后面的内容中会讲到。
-
-1. 先回到manage.py文件所在的目录创建名为templates文件夹。
-
- ```Shell
- (venv)$ mkdir templates
- ```
-
-2. 创建模板页index.html。
-
- ```Shell
- (venv)$ touch templates/index.html
- (venv)$ vim templates/index.html
- ```
- ```HTML
-
-
-
-
- 首页
-
-
- 部门信息
-
-
-
- 部门编号
- 部门名称
- 所在地
-
- {% for dept in depts_list %}
-
- {{ dept.no }}
- {{ dept.name }}
- {{ dept.location }}
-
- {% endfor %}
-
-
-
- ```
- 在上面的模板页中我们使用了`{{ greeting }}`这样的模板占位符语法,也使用了`{% for %}`这样的模板指令,这些都是Django模板语言(DTL)的一部分。如果对此不熟悉并不要紧,我们会在后续的内容中进一步的讲解,而且我们刚才也说到了,渲染页面还有更好的选择就是使用前端渲染,当然这是后话。
-
-3. 回到应用目录,修改views.py文件。
-
- ```Shell
- (venv)$ vim hrs/views.py
- ```
-
- ```Python
- from django.shortcuts import render
-
- depts_list = [
- {'no': 10, 'name': '财务部', 'location': '北京'},
- {'no': 20, 'name': '研发部', 'location': '成都'},
- {'no': 30, 'name': '销售部', 'location': '上海'},
- ]
-
-
- def index(request):
- return render(request, 'index.html', {'depts_list': depts_list})
- ```
-
- > 说明:Django框架通过shortcuts模块的便捷函数`render`简化了渲染模板的操作,有了这个函数,就不用先创建`Template`对象再去调用`render`方法。。
-
- 到此为止,我们还没有办法让views.py中的`render`函数找到模板文件index.html,为此我们需要修改settings.py文件,配置模板文件所在的路径。
-
-4. 切换到项目目录修改settings.py文件。
-
- ```Shell
- (venv)$ vim oa/settings.py
- ```
-
- ```Python
- # 此处省略上面的内容
-
- TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR, 'templates')],
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- },
- ]
-
- # 此处省略下面的内容
- ```
-
-5. 重新运行项目或直接刷新页面查看结果。
-
- ```Shell
- (venv)$ python manage.py runserver
- ```
-
-
-### 总结
-
-至此,我们已经利用Django框架完成了一个非常小的Web应用,虽然它并没有任何的实际价值,但是可以通过这个项目对Django框架有一个感性的认识。当然,实际开发中我们可以用PyCharm来创建项目,如果使用专业版的PyCharm,可以直接创建Django项目。使用PyCharm的好处在于编写代码时可以获得代码提示、错误修复、自动导入等功能,从而提升开发效率,但是专业版的PyCharm需要按年支付相应的费用,社区版的PyCharm中并未包含对Django框架直接的支持,但是我们仍然可以使用它来创建Django项目,只是在使用上没有专业版的方便。关于PyCharm的使用,可以参考[《玩转PyCharm》](../玩转PyCharm.md)一文。此外,Django最好的学习资料肯定是它的[官方文档](https://docs.djangoproject.com/zh-hans/2.0/),当然图灵社区出版的[《Django基础教程》](http://www.ituring.com.cn/book/2630)也是非常适合初学者的入门级读物。
-
diff --git a/Day41-55/42.深入模型.md b/Day41-55/42.深入模型.md
index 3ba9035..dc9b86b 100644
--- a/Day41-55/42.深入模型.md
+++ b/Day41-55/42.深入模型.md
@@ -1,20 +1,76 @@
## 深入模型
-在上一个章节中,我们提到了Django是基于MVC架构的Web框架,MVC架构追求的是“模型”和“视图”的解耦合。所谓“模型”说得更直白一些就是数据(的表示),所以通常也被称作“数据模型”。在实际的项目中,数据模型通常通过数据库实现持久化操作,而关系型数据库在过去和当下都是持久化的首选方案,下面我们以MySQL为例来说明如何使用关系型数据库来实现持久化操作。
+在上一个章节中,我们提到了Django是基于MVC架构的Web框架,MVC架构追求的是“模型”和“视图”的解耦合。所谓“模型”说得更直白一些就是数据(的表示),所以通常也被称作“数据模型”。在实际的项目中,数据模型通常通过数据库实现持久化操作,而关系型数据库在过去和当下都是持久化的首选方案,下面我们通过完成一个投票项目来讲解和模型相关的知识点。投票项目的首页会展示某在线教育平台所有的学科;点击学科可以查看到该学科的老师及其信息;用户登录后在查看老师的页面为老师投票,可以投赞成票和反对票;未登录的用户可以通过登录页进行登录;尚未注册的用户可以通过注册页输入个人信息进行注册。在这个项目中,我们使用MySQL数据库来实现数据持久化操作。
+
+### 创建项目和应用
+
+我们首先创建Django项目`vote`并为其添加虚拟环境和依赖项。接下来,在项目下创建名为`polls`的应用和保存模板页的文件夹`tempaltes`,项目文件夹的结构如下所示。
+
+
+
+根据上面描述的项目需求,我们准备了四个静态页面,分别是展示学科的页面`subjects.html`,显示学科老师的页面`teachers.html`,登录页面`login.html`,注册页面`register.html`,稍后我们会将静态页修改为Django项目所需的模板页。
### 配置关系型数据库MySQL
-我们继续来完善上一个章节中的OA项目,首先从配置项目使用的数据库开始。
+1. 在MySQL中创建数据库,创建用户,授权用户访问该数据库。
-1. 修改项目的settings.py文件,首先将我们之前创建的应用hrs添加已安装的项目中,然后配置MySQL作为持久化方案。
-
- ```Shell
- (venv)$ vim oa/settings.py
+ ```SQL
+ create database vote default charset utf8;
+ create user 'hellokitty'@'%' identified by 'Hellokitty.618';
+ grant all privileges on vote.* to 'hellokitty'@'%';
+ flush privileges;
```
- ```Python
- # 此处省略上面的代码
+2. 在MySQL中创建保存学科和老师信息的二维表(保存用户信息的表稍后处理)。
+
+ ```SQL
+ use vote;
+ -- 创建学科表
+ create table `tb_subject`
+ (
+ `no` integer auto_increment comment '学科编号',
+ `name` varchar(50) not null comment '学科名称',
+ `intro` varchar(1000) not null default '' comment '学科介绍',
+ `is_hot` boolean not null default 0 comment '是不是热门学科',
+ primary key (`no`)
+ );
+ -- 创建老师表
+ create table `tb_teacher`
+ (
+ `no` integer auto_increment comment '老师编号',
+ `name` varchar(20) not null comment '老师姓名',
+ `sex` boolean not null default 1 comment '老师性别',
+ `birth` date not null comment '出生日期',
+ `intro` varchar(1000) not null default '' comment '老师介绍',
+ `photo` varchar(255) not null default '' comment '老师照片',
+ `gcount` integer not null default 0 comment '好评数',
+ `bcount` integer not null default 0 comment '差评数',
+ `sno` integer not null comment '所属学科',
+ primary key (`no`),
+ foreign key (`sno`) references `tb_subject` (`no`)
+ );
+ ```
+
+3. 在虚拟环境中安装连接MySQL数据库所需的依赖项。
+
+ ```Bash
+ pip install mysqlclient
+ ```
+
+ > **说明**:如果因为某些原因无法安装`mysqlclient`三方库,可以使用它的替代品`pymysql`,`pymysql`是用纯Python开发的连接MySQL的Python库,安装更容易成功,但是需要在Django项目文件夹的`__init__.py`中添加如下所示的代码。
+ >
+ > ```Python
+ > import pymysql
+ >
+ > pymysql.install_as_MySQLdb()
+ > ```
+ >
+ > 如果使用Django 2.2及以上版本,还会遇到PyMySQL跟Django框架的兼容性问题,兼容性问题会导致项目无法运行,需要按照GitHub上PyMySQL仓库[Issues](https://github.com/PyMySQL/PyMySQL/issues/790)中提供的方法进行处理。总体来说,使用`pymysql`会比较麻烦,强烈建议大家首选安装`mysqlclient`。
+
+4. 修改项目的settings.py文件,首先将我们创建的应用`polls`添加已安装的项目(`INSTALLED_APPS`)中,然后配置MySQL作为持久化方案。
+
+ ```Python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
@@ -22,290 +78,113 @@
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
- 'hrs',
+ 'polls',
]
DATABASES = {
'default': {
+ # 数据库引擎配置
'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'oa',
- 'HOST': '127.0.0.1',
+ # 数据库的名字
+ 'NAME': 'vote',
+ # 数据库服务器的IP地址(本机可以写localhost或127.0.0.1)
+ 'HOST': 'localhost',
+ # 启动MySQL服务的端口号
'PORT': 3306,
- 'USER': 'root',
- 'PASSWORD': '123456',
+ # 数据库用户名和口令
+ 'USER': 'hellokitty',
+ 'PASSWORD': 'Hellokitty.618',
+ # 数据库使用的字符集
+ 'CHARSET': 'utf8',
+ # 数据库时间日期的时区设定
+ 'TIME_ZONE': 'Asia/Chongqing',
}
}
-
- # 此处省略下面的代码
```
在配置ENGINE属性时,常用的可选值包括:
- `'django.db.backends.sqlite3'`:SQLite嵌入式数据库。
- `'django.db.backends.postgresql'`:BSD许可证下发行的开源关系型数据库产品。
- - `'django.db.backends.mysql'`:转手多次目前属于甲骨文公司的经济高效的数据库产品。
- - `'django.db.backends.oracle'`:甲骨文公司的关系型数据库旗舰产品。
+ - `'django.db.backends.mysql'`:甲骨文公司经济高效的数据库产品。
+ - `'django.db.backends.oracle'`:甲骨文公司关系型数据库旗舰产品。
其他的配置可以参考官方文档中[数据库配置](https://docs.djangoproject.com/zh-hans/2.0/ref/databases/#third-party-notes)的部分。
- NAME属性代表数据库的名称,如果使用SQLite它对应着一个文件,在这种情况下NAME的属性值应该是一个绝对路径;使用其他关系型数据库,则要配置对应的HOST(主机)、PORT(端口)、USER(用户名)、PASSWORD(口令)等属性。
+5. Django框架提供了ORM来解决数据持久化问题,ORM翻译成中文叫“对象关系映射”。因为Python是面向对象的编程语言,我们在Python程序中使用对象模型来保存数据,而关系型数据库使用关系模型,用二维表来保存数据,这两种模型并不匹配。使用ORM是为了实现对象模型到关系模型的**双向转换**,这样就不用在Python代码中书写SQL语句和游标操作,因为这些都会由ORM自动完成。利用Django的ORM,我们可以直接将刚才创建的学科表和老师表变成Django中的模型类。
-2. 安装Python操作MySQL的依赖库,Python 3中通常使用PyMySQL,Python 2中通常用MySQLdb。
-
- ```Shell
- (venv)$ pip install pymysql
+ ```Bash
+ python manage.py inspectdb > polls/models.py
```
- 如果使用Python 3需要修改**项目目录**下的`__init__.py`文件并加入如下所示的代码,这段代码的作用是将PyMySQL视为MySQLdb来使用,从而避免Django找不到连接MySQL的客户端工具而询问你:“Did you install mysqlclient? ”(你安装了mysqlclient吗?)。
-
- ```Python
- import pymysql
-
- pymysql.install_as_MySQLdb()
- ```
-
-3. 如果之前没有为应用程序创建数据库,那么现在是时候创建名为oa的数据库了。在MySQL中创建数据库的SQL语句如下所示:
-
- ```SQL
- create database oa default charset utf8;
- ```
-
-4. Django框架本身有自带的数据模型,我们稍后会用到这些模型,为此我们先做一次迁移操作。所谓迁移,就是根据模型自动生成关系数据库中的二维表,命令如下所示:
-
- ```Shell
- (venv)$ python manage.py migrate
- Operations to perform:
- Apply all migrations: admin, auth, contenttypes, sessions
- Running migrations:
- Applying contenttypes.0001_initial... OK
- Applying auth.0001_initial... OK
- Applying admin.0001_initial... OK
- Applying admin.0002_logentry_remove_auto_add... OK
- Applying contenttypes.0002_remove_content_type_name... OK
- Applying auth.0002_alter_permission_name_max_length... OK
- Applying auth.0003_alter_user_email_max_length... OK
- Applying auth.0004_alter_user_username_opts... OK
- Applying auth.0005_alter_user_last_login_null... OK
- Applying auth.0006_require_contenttypes_0002... OK
- Applying auth.0007_alter_validators_add_error_messages... OK
- Applying auth.0008_alter_user_username_max_length... OK
- Applying auth.0009_alter_user_last_name_max_length... OK
- Applying sessions.0001_initial... OK
- ```
-
-5. 接下来,我们为自己的应用创建数据模型。如果要在hrs应用中实现对部门和员工的管理,我们可以先创建部门和员工数据模型,代码如下所示。
-
- ```Shell
- (venv)$ vim hrs/models.py
- ```
+ 我们可以对自动生成的模型类稍作调整,代码如下所示。
```Python
from django.db import models
- class Dept(models.Model):
- """部门类"""
-
- no = models.IntegerField(primary_key=True, db_column='dno', verbose_name='部门编号')
- name = models.CharField(max_length=20, db_column='dname', verbose_name='部门名称')
- location = models.CharField(max_length=10, db_column='dloc', verbose_name='部门所在地')
+ class Subject(models.Model):
+ no = models.AutoField(primary_key=True, verbose_name='编号')
+ name = models.CharField(max_length=50, verbose_name='名称')
+ intro = models.CharField(max_length=1000, verbose_name='介绍')
+ is_hot = models.BooleanField(verbose_name='是否热门')
class Meta:
- db_table = 'tb_dept'
+ managed = False
+ db_table = 'tb_subject'
- class Emp(models.Model):
- """员工类"""
-
- no = models.IntegerField(primary_key=True, db_column='eno', verbose_name='员工编号')
- name = models.CharField(max_length=20, db_column='ename', verbose_name='员工姓名')
- job = models.CharField(max_length=10, verbose_name='职位')
- # 多对一外键关联(自参照)
- mgr = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='主管')
- sal = models.DecimalField(max_digits=7, decimal_places=2, verbose_name='月薪')
- comm = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True, verbose_name='补贴')
- # 多对一外键关联(参照部门模型)
- dept = models.ForeignKey(Dept, db_column='dno', on_delete=models.PROTECT, verbose_name='所在部门')
+ class Teacher(models.Model):
+ no = models.AutoField(primary_key=True, verbose_name='编号')
+ name = models.CharField(max_length=20, verbose_name='姓名')
+ sex = models.BooleanField(default=True, verbose_name='性别')
+ birth = models.DateField(verbose_name='出生日期')
+ intro = models.CharField(max_length=1000, verbose_name='个人介绍')
+ photo = models.ImageField(max_length=255, verbose_name='照片')
+ good_count = models.IntegerField(default=0, db_column='gcount', verbose_name='好评数')
+ bad_count = models.IntegerField(default=0, db_column='bcount', verbose_name='差评数')
+ subject = models.ForeignKey(Subject, models.DO_NOTHING, db_column='sno')
class Meta:
- db_table = 'tb_emp'
+ managed = False
+ db_table = 'tb_teacher'
```
- > 说明:上面定义模型时使用了字段类及其属性,其中IntegerField对应数据库中的integer类型,CharField对应数据库的varchar类型,DecimalField对应数据库的decimal类型,ForeignKey用来建立多对一外键关联。字段属性primary_key用于设置主键,max_length用来设置字段的最大长度,db_column用来设置数据库中与字段对应的列,verbose_name则设置了Django后台管理系统中该字段显示的名称。如果对这些东西感到很困惑也不要紧,文末提供了字段类、字段属性、元数据选项等设置的相关说明,不清楚的读者可以稍后查看对应的参考指南。
-
-6. 再次执行迁移操作,先通过模型生成迁移文件,再执行迁移创建二维表。
-
- ```Shell
- (venv)$ python manage.py makemigrations hrs
- Migrations for 'hrs':
- hrs/migrations/0001_initial.py
- - Create model Dept
- - Create model Emp
- (venv)$ python manage.py migrate
- Operations to perform:
- Apply all migrations: admin, auth, contenttypes, hrs, sessions
- Running migrations:
- Applying hrs.0001_initial... OK
- ```
-
- 执行完数据模型迁移操作之后,可以在通过图形化的MySQL客户端工具查看到E-R图(实体关系图)。
-
- 
-
-### 利用Django后台管理模型
-
-Django框架有自带的后台管理系统来实现对模型的管理。虽然实际应用中,这个后台可能并不能满足我们的需求,但是在学习Django框架时,我们暂时可以利用Django自带的后台管理系统来管理我们的模型,同时也可以了解一个项目的后台管理系统到底需要哪些功能。
-
-1. 创建超级管理员账号。
-
- ```Shell
- (venv)$ python manage.py createsuperuser
- Username (leave blank to use 'hao'): jackfrued
- Email address: jackfrued@126.com
- Password:
- Password (again):
- Superuser created successfully.
- ```
-
-2. 启动Web服务器,登录后台管理系统。
-
- ```Shell
- (venv)$ python manage.py runserver
- ```
-
- 访问,会来到如下图所示的登录界面。
-
- 
-
- 登录后进入管理员操作平台。
-
- 
-
- 至此我们还没有看到之前创建的模型类,需要在应用的admin.py文件中模型进行注册。
-
-3. 注册模型类。
-
- ```Shell
- (venv)$ vim hrs/admin.py
- ```
-
- ```Python
- from django.contrib import admin
- from hrs.models import Emp, Dept
-
- admin.site.register(Dept)
- admin.site.register(Emp)
- ```
-
- 注册模型类后,就可以在后台管理系统中看到它们。
-
- 
-
-4. 对模型进行CRUD操作。
-
- 可以在管理员平台对模型进行C(新增)、R(查看)、U(更新)、D(删除)操作,如下图所示。
-
- - 添加新的部门。
-
- 
-
- - 查看所有部门。
-
- 
-
- - 更新和删除部门。
-
- 
-
-5. 注册模型管理类。
-
- 可能大家已经注意到了,刚才在后台查看部门信息的时候,显示的部门信息并不直观,为此我们再修改admin.py文件,通过注册模型管理类,可以在后台管理系统中更好的管理模型。
-
- ```Python
- from django.contrib import admin
-
- from hrs.models import Emp, Dept
-
-
- class DeptAdmin(admin.ModelAdmin):
-
- list_display = ('no', 'name', 'location')
- ordering = ('no', )
-
-
- class EmpAdmin(admin.ModelAdmin):
-
- list_display = ('no', 'name', 'job', 'mgr', 'sal', 'comm', 'dept')
- search_fields = ('name', 'job')
-
-
- admin.site.register(Dept, DeptAdmin)
- admin.site.register(Emp, EmpAdmin)
- ```
-
- 
-
- 
-
- 为了更好的查看模型数据,可以为Dept和Emp两个模型类添加`__str__`魔法方法。
-
- ```Python
- from django.db import models
-
-
- class Dept(models.Model):
- """部门类"""
-
- # 此处省略上面的代码
-
- def __str__(self):
- return self.name
-
- # 此处省略下面的代码
-
-
- class Emp(models.Model):
- """员工类"""
-
- # 此处省略上面的代码
-
- def __str__(self):
- return self.name
-
- # 此处省略下面的代码
- ```
-
- 修改代码后刷新查看Emp模型的页面,效果如下图所示。
-
- 
+ > **说明**:模型类都直接或间接继承自`Model`类,模型类跟关系型数据库的二维表对应,模型对象跟表中的记录对应,模型对象的属性跟表中的字段对应。如果对上面模型类的属性定义不是特别理解,可以看看本文后面提供的“模型定义参考”部分的内容。
### 使用ORM完成模型的CRUD操作
-在了解了Django提供的模型管理平台之后,我们来看看如何从代码层面完成对模型的CRUD(Create / Read / Update / Delete)操作。我们可以通过manage.py开启Shell交互式环境,然后使用Django内置的ORM框架对模型进行CRUD操作。
+有了Django框架的ORM,我们可以直接使用面向对象的方式来实现对数据的CRUD(增删改查)操作。我们可以在PyCharm的终端中输入下面的命令进入到Django项目的交互式环境,然后尝试对模型的操作。
-```Shell
-(venv)$ python manage.py shell
-Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
-[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
-Type "help", "copyright", "credits" or "license" for more information.
-(InteractiveConsole)
->>>
+```Bash
+python manage.py shell
```
#### 新增
-```Shell
->>> from hrs.models import Dept, Emp
->>>
->>> dept = Dept(40, '研发2部', '深圳')
->>> dept.save()
+```Python
+from polls.models import Subject
+
+subject1 = Subject(name='Python全栈开发', intro='当下最热门的学科', is_hot=True)
+subject1.save()
+subject2 = Subject(name='全栈软件测试', intro='学习自动化测试的学科', is_hot=False)
+subject2.save()
+subject3 = Subject(name='JavaEE分布式开发', intro='基于Java语言的服务器应用开发', is_hot=True)
+```
+
+#### 删除
+
+```Python
+subject = Subject.objects.get(no=2)
+subject.delete()
```
#### 更新
```Shell
->>> dept.name = '研发3部'
->>> dept.save()
+subject = Subject.objects.get(no=1)
+subject.name = 'Python全栈+人工智能'
+subject.save()
```
#### 查询
@@ -313,89 +192,364 @@ Type "help", "copyright", "credits" or "license" for more information.
1. 查询所有对象。
```Shell
->>> Dept.objects.all()
-, , , ]>
+Subjects.objects.all()
```
2. 过滤数据。
```Shell
->>> Dept.objects.filter(name='研发3部') # 查询部门名称为“研发3部”的部门
-]>
->>>
->>> Dept.objects.filter(name__contains='研发') # 查询部门名称包含“研发”的部门(模糊查询)
-, ]>
->>>
->>> Dept.objects.filter(no__gt=10).filter(no__lt=40) # 查询部门编号大于10小于40的部门
-, ]>
->>>
->>> Dept.objects.filter(no__range=(10, 30)) # 查询部门编号在10到30之间的部门
-, , ]>
+# 查询名称为“Python全栈+人工智能”的学科
+Subject.objects.filter(name='Python全栈+人工智能')
+
+# 查询名称包含“全栈”的学科(模糊查询)
+Subject.objects.filter(name__contains='全栈')
+Subject.objects.filter(name__startswith='全栈')
+Subject.objects.filter(name__endswith='全栈')
+
+# 查询所有热门学科
+Subject.objects.filter(is_hot=True)
+
+# 查询编号大于3小于10的学科
+Subject.objects.filter(no__gt=3).filter(no__lt=10)
+Subject.objects.filter(no__gt=3, no__lt=10)
+
+# 查询编号在3到7之间的学科
+Subject.objects.filter(no__ge=3, no__le=7)
+Subject.objects.filter(no__range=(3, 7))
```
3. 查询单个对象。
```Shell
->>> Dept.objects.get(pk=10)
-
->>>
->>> Dept.objects.get(no=20)
-
->>>
->>> Dept.objects.get(no__exact=30)
-
->>>
->>> Dept.objects.filter(no=10).first()
-
+# 查询主键为1的学科
+Subject.objects.get(pk=1)
+Subject.objects.get(no=1)
+Subject.objects.filter(no=1).first()
+Subject.objects.filter(no=1).last()
```
-4. 排序数据。
+4. 排序。
```Shell
->>> Dept.objects.order_by('no') # 查询所有部门按部门编号升序排列
-, , , ]>
->>>
->>> Dept.objects.order_by('-no') # 查询所有部门按部门编号降序排列
-, , , ]>
+# 查询所有学科按编号升序排列
+Subject.objects.order_by('no')
+# 查询所有部门按部门编号降序排列
+Subject.objects.order_by('-no')
```
-5. 数据切片(分页查询)。
+5. 切片(分页查询)。
```Shell
->>> Dept.objects.order_by('no')[0:2] # 按部门编号排序查询1~2部门
-, ]>
->>>
->>> Dept.objects.order_by('no')[2:4] # 按部门编号排序查询3~4部门
-, ]>
+# 按编号从小到大查询前3个学科
+Subject.objects.order_by('no')[:3]
```
-6. 高级查询。
+6. 计数。
+
+```Python
+# 查询一共有多少个学科
+Subject.objects.count()
+```
+
+7. 高级查询。
```Shell
->>> Emp.objects.filter(dept__no=10) # 根据部门编号查询该部门的员工
-, , ]>
->>>
->>> Emp.objects.filter(dept__name__contains='销售') # 查询名字包含“销售”的部门的员工
-]>
->>>
->>> Dept.objects.get(pk=10).emp_set.all() # 通过部门反查部门所有的员工
-, , ]>
+# 查询编号为1的学科的老师
+Teacher.objects.filter(subject__no=1)
+Subject.objects.get(pk=1).teacher_set.all()
+
+# 查询学科名称有“全栈”二字的学科的老师
+Teacher.objects.filter(subject__name__contains='全栈')
```
-> 说明1:由于员工与部门之间存在多对一外键关联,所以也能通过部门反向查询该部门的员工(从一对多关系中“一”的一方查询“多”的一方),反向查询属性默认的名字是`类名小写_set`(如上面例子中的`emp_set`),当然也可以在创建模型时通过`ForeingKey`的`related_name`属性指定反向查询属性的名字。如果不希望执行反向查询可以将`related_name`属性设置为`'+'`或以`'+'`开头的字符串。
+> **说明1**:由于老师与学科之间存在多对一外键关联,所以能通过学科反向查询到该学科的老师(从一对多关系中“一”的一方查询“多”的一方),反向查询属性默认的名字是`类名小写_set`(如上面例子中的`teacher_set`),当然也可以在创建模型时通过`ForeingKey`的`related_name`属性指定反向查询属性的名字。如果不希望执行反向查询可以将`related_name`属性设置为`'+'`或者以`'+'`开头的字符串。
-> 说明2:查询多个对象的时候返回的是QuerySet对象,QuerySet使用了惰性查询,即在创建QuerySet对象的过程中不涉及任何数据库活动,等真正用到对象时(求值QuerySet)才向数据库发送SQL语句并获取对应的结果,这一点在实际开发中需要引起注意!
+> **说明2**:ORM查询多个对象时会返回QuerySet对象,QuerySet使用了惰性查询,即在创建QuerySet对象的过程中不涉及任何数据库活动,等真正用到对象时(对QuerySet求值)才向数据库发送SQL语句并获取对应的结果,这一点在实际开发中需要引起注意!
-> 说明3:可以在QuerySet上使用`update()`方法一次更新多个对象。
+> **说明3**:如果希望更新多条数据,不用先逐一获取模型对象再修改对象属性,可以直接使用QuerySet对象的`update()`方法一次性更新多条数据。
-#### 删除
-```Shell
->>> Dept.objects.get(pk=40).delete()
-(1, {'hrs.Dept': 1})
-```
+### 利用Django后台管理模型
-### Django模型最佳实践
+在创建好模型类之后,可以通过Django框架自带的后台管理应用(`admin`应用)实现对模型的管理。虽然实际应用中,这个后台可能并不能满足我们的需求,但是在学习Django框架时,我们可以利用`admin`应用来管理我们的模型,同时也通过它来了解一个项目的后台管理系统需要哪些功能。使用Django自带的`admin`应用步骤如下所示。
+
+1. 将`admin`应用所需的表迁移到数据库中。`admin`应用本身也需要数据库的支持,而且在`admin`应用中已经定义好了相关的数据模型类,我们只需要通过模型迁移操作就能自动在数据库中生成所需的二维表。
+
+ ```Bash
+ python manage.py migrate
+ ```
+
+2. 创建访问`admin`应用的超级用户账号,这里需要输入用户名、邮箱和口令。
+
+ ```Shell
+ python manage.py createsuperuser
+ ```
+
+ > **说明**:输入口令时没有回显也不能退格,需要一气呵成完成输入。
+
+3. 运行项目,在浏览器中访问`http://127.0.0.1:8000/admin`,输入刚才创建的超级用户账号和密码进行登录。
+
+ 
+
+ 登录后进入管理员操作平台。
+
+ 
+
+ 注意,我们暂时还没能在`admin`应用中看到之前创建的模型类,为此需要在`polls`应用的`admin.py`文件中对需要管理的模型进行注册。
+
+4. 注册模型类。
+
+ ```Python
+ from django.contrib import admin
+
+ from polls.models import Subject, Teacher
+
+ admin.site.register(Subject)
+ admin.site.register(Teacher)
+ ```
+
+ 注册模型类后,就可以在后台管理系统中看到它们。
+
+ 
+
+5. 对模型进行CRUD操作。
+
+ 可以在管理员平台对模型进行C(新增)、R(查看)、U(更新)、D(删除)操作,如下图所示。
+
+ - 添加学科。
+
+ 
+
+ - 查看所有学科。
+
+ 
+
+ - 删除和更新学科。
+
+ 
+
+6. 注册模型管理类。
+
+ 可能大家已经注意到了,刚才在后台查看部门信息的时候,显示的部门信息并不直观,为此我们再修改`admin.py`文件,通过注册模型管理类,可以在后台管理系统中更好的管理模型。
+
+ ```Python
+ from django.contrib import admin
+
+ from polls.models import Subject, Teacher
+
+
+ class SubjectModelAdmin(admin.ModelAdmin):
+ list_display = ('no', 'name', 'intro', 'is_hot')
+ search_fields = ('name', )
+ ordering = ('no', )
+
+
+ class TeacherModelAdmin(admin.ModelAdmin):
+ list_display = ('no', 'name', 'sex', 'birth', 'good_count', 'bad_count', 'subject')
+ search_fields = ('name', )
+ ordering = ('no', )
+
+
+ admin.site.register(Subject, SubjectModelAdmin)
+ admin.site.register(Teacher, TeacherModelAdmin)
+ ```
+
+ 
+
+ 
+
+ 为了更好的查看模型,我们为`Subject`类添加`__str__`魔法方法,并在该方法中返回学科名字。这样在如上图所示的查看老师的页面上显示老师所属学科时,就不再是`Subject object(1)`这样晦涩的信息,而是学科的名称。
+
+### 实现学科页和老师页效果
+
+1. 修改`polls/views.py`文件,编写视图函数实现对学科页和老师页的渲染。
+
+ ```Python
+ from django.shortcuts import render, redirect
+
+ from polls.models import Subject, Teacher
+
+
+ def show_subjects(request):
+ subjects = Subject.objects.all().order_by('no')
+ return render(request, 'subjects.html', {'subjects': subjects})
+
+
+ def show_teachers(request):
+ try:
+ sno = int(request.GET.get('sno'))
+ teachers = []
+ if sno:
+ subject = Subject.objects.only('name').get(no=sno)
+ teachers = Teacher.objects.filter(subject=subject).order_by('no')
+ return render(request, 'teachers.html', {
+ 'subject': subject,
+ 'teachers': teachers
+ })
+ except (ValueError, Subject.DoesNotExist):
+ return redirect('/')
+ ```
+
+2. 修改`templates/subjects.html`和`templates/teachers.html`模板页。
+
+ `subjects.html`
+
+ ```HTML
+
+
+
+
+ 学科信息
+
+
+
+
+
+
扣丁学堂所有学科
+
+
+ {% for subject in subjects %}
+
+
+ {{ subject.name }}
+ {% if subject.is_hot %}
+
+ {% endif %}
+
+ {{ subject.intro }}
+
+ {% endfor %}
+
+
+
+
+ ```
+
+ `teachers.html`
+
+ ```HTML
+
+
+
+
+ 老师信息
+
+
+
+
+
{{ subject.name }}学科的老师信息
+
+ {% if not teachers %}
+
暂无该学科老师信息
+ {% endif %}
+ {% for teacher in teachers %}
+
+
+
+
+
+
+ 姓名:{{ teacher.name }}
+ 性别:{{ teacher.sex | yesno:'男,女' }}
+ 出生日期:{{ teacher.birth | date:'Y年n月j日'}}
+
+
{{ teacher.intro }}
+
+
+
+ {% endfor %}
+
返回首页
+
+
+
+ ```
+
+3. 修改`vote/urls.py`文件,实现映射URL。
+
+ ```Python
+ from django.contrib import admin
+ from django.urls import path
+
+ from polls.views import show_subjects, show_teachers
+
+ urlpatterns = [
+ path('admin/', admin.site.urls),
+ path('', show_subjects),
+ path('teachers/', show_teachers),
+ ]
+ ```
+
+到此为止,页面上需要的图片(静态资源)还没有能够正常展示,我们在下一章节中为大家介绍如何处理模板页上的需要的静态资源。
+
+### 补充内容
+
+#### Django模型最佳实践
1. 正确的为模型和关系字段命名。
2. 设置适当的`related_name`属性。
@@ -412,11 +566,11 @@ Type "help", "copyright", "credits" or "license" for more information.
13. 定义`__str__`方法。
14. 不要将数据文件放在同一个目录中。
-> 说明:以上内容来自于STEELKIWI网站的[*Best Practice working with Django models in Python*](https://steelkiwi.com/blog/best-practices-working-django-models-python/),有兴趣的小伙伴可以阅读原文。
+> **说明**:以上内容来自于STEELKIWI网站的[*Best Practice working with Django models in Python*](https://steelkiwi.com/blog/best-practices-working-django-models-python/),有兴趣的小伙伴可以阅读原文。
-### 模型定义参考
+#### 模型定义参考
-#### 字段
+##### 字段
对字段名称的限制
@@ -425,114 +579,103 @@ Type "help", "copyright", "credits" or "license" for more information.
Django模型字段类
-| 字段类 | 说明 |
-| --------------------- | ------------------------------------------------------------ |
-| AutoField |自增ID字段 |
-| BigIntegerField |64位有符号整数 |
-| BinaryField | 存储二进制数据的字段,对应Python的bytes类型 |
-| BooleanField | 存储True或False |
-| CharField | 长度较小的字符串 |
-| DateField | 存储日期,有auto_now和auto_now_add属性 |
-| DateTimeField | 存储日期和日期,两个附加属性同上 |
-| DecimalField |存储固定精度小数,有max_digits(有效位数)和decimal_places(小数点后面)两个必要的参数 |
-| DurationField |存储时间跨度 |
-| EmailField | 与CharField相同,可以用EmailValidator验证 |
-| FileField | 文件上传字段 |
-| FloatField | 存储浮点数 |
-| ImageField | 其他同FileFiled,要验证上传的是不是有效图像 |
-| IntegerField | 存储32位有符号整数。 |
-| GenericIPAddressField | 存储IPv4或IPv6地址 |
-| NullBooleanField | 存储True、False或null值 |
-| PositiveIntegerField | 存储无符号整数(只能存储正数) |
-| SlugField | 存储slug(简短标注) |
-| SmallIntegerField | 存储16位有符号整数 |
-| TextField | 存储数据量较大的文本 |
-| TimeField | 存储时间 |
-| URLField | 存储URL的CharField |
-| UUIDField | 存储全局唯一标识符 |
+| 字段类 | 说明 |
+| ----------------------- | ------------------------------------------------------------ |
+| `AutoField` | 自增ID字段 |
+| `BigIntegerField` | 64位有符号整数 |
+| `BinaryField` | 存储二进制数据的字段,对应Python的`bytes`类型 |
+| `BooleanField` | 存储`True`或`False` |
+| `CharField` | 长度较小的字符串 |
+| `DateField` | 存储日期,有`auto_now`和`auto_now_add`属性 |
+| `DateTimeField` | 存储日期和日期,两个附加属性同上 |
+| `DecimalField` | 存储固定精度小数,有`max_digits`(有效位数)和`decimal_places`(小数点后面)两个必要的参数 |
+| `DurationField` | 存储时间跨度 |
+| `EmailField` | 与`CharField`相同,可以用`EmailValidator`验证 |
+| `FileField` | 文件上传字段 |
+| `FloatField` | 存储浮点数 |
+| `ImageField` | 其他同`FileFiled`,要验证上传的是不是有效图像 |
+| `IntegerField` | 存储32位有符号整数。 |
+| `GenericIPAddressField` | 存储IPv4或IPv6地址 |
+| `NullBooleanField` | 存储`True`、`False`或`null`值 |
+| `PositiveIntegerField` | 存储无符号整数(只能存储正数) |
+| `SlugField` | 存储slug(简短标注) |
+| `SmallIntegerField` | 存储16位有符号整数 |
+| `TextField` | 存储数据量较大的文本 |
+| `TimeField` | 存储时间 |
+| `URLField` | 存储URL的`CharField` |
+| `UUIDField` | 存储全局唯一标识符 |
-#### 字段属性
+##### 字段属性
通用字段属性
-| 选项 | 说明 |
-| -------------- | ------------------------------------------------------------ |
-| null | 数据库中对应的字段是否允许为NULL,默认为False |
-| blank | 后台模型管理验证数据时,是否允许为NULL,默认为False |
-| choices | 设定字段的选项,各元组中的第一个值是设置在模型上的值,第二值是人类可读的值 |
-| db_column | 字段对应到数据库表中的列名,未指定时直接使用字段的名称 |
-| db_index | 设置为True时将在该字段创建索引 |
-| db_tablespace | 为有索引的字段设置使用的表空间,默认为DEFAULT_INDEX_TABLESPACE |
-| default | 字段的默认值 |
-| editable | 字段在后台模型管理或ModelForm中是否显示,默认为True |
-| error_messages | 设定字段抛出异常时的默认消息的字典,其中的键包括null、blank、invalid、invalid_choice、unique和unique_for_date |
-| help_text | 表单小组件旁边显示的额外的帮助文本。 |
-| primary_key | 将字段指定为模型的主键,未指定时会自动添加AutoField用于主键,只读。 |
-| unique | 设置为True时,表中字段的值必须是唯一的 |
-| verbose_name | 字段在后台模型管理显示的名称,未指定时使用字段的名称 |
+| 选项 | 说明 |
+| ---------------- | ------------------------------------------------------------ |
+| `null` | 数据库中对应的字段是否允许为`NULL`,默认为`False` |
+| `blank` | 后台模型管理验证数据时,是否允许为`NULL`,默认为`False` |
+| `choices` | 设定字段的选项,各元组中的第一个值是设置在模型上的值,第二值是人类可读的值 |
+| `db_column` | 字段对应到数据库表中的列名,未指定时直接使用字段的名称 |
+| `db_index` | 设置为`True`时将在该字段创建索引 |
+| `db_tablespace` | 为有索引的字段设置使用的表空间,默认为`DEFAULT_INDEX_TABLESPACE` |
+| `default` | 字段的默认值 |
+| `editable` | 字段在后台模型管理或`ModelForm`中是否显示,默认为`True` |
+| `error_messages` | 设定字段抛出异常时的默认消息的字典,其中的键包括`null`、`blank`、`invalid`、`invalid_choice`、`unique`和`unique_for_date` |
+| `help_text` | 表单小组件旁边显示的额外的帮助文本。 |
+| `primary_key` | 将字段指定为模型的主键,未指定时会自动添加`AutoField`用于主键,只读。 |
+| `unique` | 设置为`True`时,表中字段的值必须是唯一的 |
+| `verbose_name` | 字段在后台模型管理显示的名称,未指定时使用字段的名称 |
-ForeignKey属性
+`ForeignKey`属性
-1. limit_choices_to:值是一个Q对象或返回一个Q对象,用于限制后台显示哪些对象。
-2. related_name:用于获取关联对象的关联管理器对象(反向查询),如果不允许反向,该属性应该被设置为`'+'`,或者以`'+'`结尾。
-3. to_field:指定关联的字段,默认关联对象的主键字段。
-4. db_constraint:是否为外键创建约束,默认值为True。
-5. on_delete:外键关联的对象被删除时对应的动作,可取的值包括django.db.models中定义的:
- - CASCADE:级联删除。
- - PROTECT:抛出ProtectedError异常,阻止删除引用的对象。
- - SET_NULL:把外键设置为null,当null属性被设置为True时才能这么做。
- - SET_DEFAULT:把外键设置为默认值,提供了默认值才能这么做。
+1. `limit_choices_to`:值是一个Q对象或返回一个Q对象,用于限制后台显示哪些对象。
+2. `related_name`:用于获取关联对象的关联管理器对象(反向查询),如果不允许反向,该属性应该被设置为`'+'`,或者以`'+'`结尾。
+3. `to_field`:指定关联的字段,默认关联对象的主键字段。
+4. `db_constraint`:是否为外键创建约束,默认值为`True`。
+5. `on_delete`:外键关联的对象被删除时对应的动作,可取的值包括`django.db.models`中定义的:
+ - `CASCADE`:级联删除。
+ - `PROTECT`:抛出`ProtectedError`异常,阻止删除引用的对象。
+ - `SET_NULL`:把外键设置为`null`,当`null`属性被设置为`True`时才能这么做。
+ - `SET_DEFAULT`:把外键设置为默认值,提供了默认值才能这么做。
-ManyToManyField属性
+`ManyToManyField`属性
-1. symmetrical:是否建立对称的多对多关系。
-2. through:指定维持多对多关系的中间表的Django模型。
-3. throughfields:定义了中间模型时可以指定建立多对多关系的字段。
-4. db_table:指定维持多对多关系的中间表的表名。
+1. `symmetrical`:是否建立对称的多对多关系。
+2. `through`:指定维持多对多关系的中间表的Django模型。
+3. `throughfields`:定义了中间模型时可以指定建立多对多关系的字段。
+4. `db_table`:指定维持多对多关系的中间表的表名。
-#### 模型元数据选项
+##### 模型元数据选项
-| 选项 | 说明 |
-| --------------------- | ------------------------------------------------------------ |
-| abstract | 设置为True时模型是抽象父类 |
-| app_label | 如果定义模型的应用不在INSTALLED_APPS中可以用该属性指定 |
-| db_table | 模型使用的数据表名称 |
-| db_tablespace | 模型使用的数据表空间 |
-| default_related_name | 关联对象回指这个模型时默认使用的名称,默认为_set |
-| get_latest_by | 模型中可排序字段的名称。 |
-| managed | 设置为True时,Django在迁移中创建数据表并在执行flush管理命令时把表移除 |
-| order_with_respect_to | 标记对象为可排序的 |
-| ordering | 对象的默认排序 |
-| permissions | 创建对象时写入权限表的额外权限 |
-| default_permissions | 默认为`('add', 'change', 'delete')` |
-| unique_together | 设定组合在一起时必须独一无二的字段名 |
-| index_together | 设定一起建立索引的多个字段名 |
-| verbose_name | 为对象设定人类可读的名称 |
-| verbose_name_plural | 设定对象的复数名称 |
+| 选项 | 说明 |
+| ----------------------- | ------------------------------------------------------------ |
+| `abstract` | 设置为True时模型是抽象父类 |
+| `app_label` | 如果定义模型的应用不在INSTALLED_APPS中可以用该属性指定 |
+| `db_table` | 模型使用的数据表名称 |
+| `db_tablespace` | 模型使用的数据表空间 |
+| `default_related_name` | 关联对象回指这个模型时默认使用的名称,默认为_set |
+| `get_latest_by` | 模型中可排序字段的名称。 |
+| `managed` | 设置为True时,Django在迁移中创建数据表并在执行flush管理命令时把表移除 |
+| `order_with_respect_to` | 标记对象为可排序的 |
+| `ordering` | 对象的默认排序 |
+| `permissions` | 创建对象时写入权限表的额外权限 |
+| `default_permissions` | 默认为`('add', 'change', 'delete')` |
+| `unique_together` | 设定组合在一起时必须独一无二的字段名 |
+| `index_together` | 设定一起建立索引的多个字段名 |
+| `verbose_name` | 为对象设定人类可读的名称 |
+| `verbose_name_plural` | 设定对象的复数名称 |
-### 查询参考
+#### 查询参考
-按字段查找可以用的条件:
+##### 按字段查找可以用的条件
-1. exact / iexact:精确匹配/忽略大小写的精确匹配查询
-2. contains / icontains / startswith / istartswith / endswith / iendswith:基于`like`的模糊查询
-3. in:集合运算
-4. gt / gte / lt / lte:大于/大于等于/小于/小于等于关系运算
-5. range:指定范围查询(SQL中的`between…and…`)
-6. year / month / day / week_day / hour / minute / second:查询时间日期
-7. isnull:查询空值(True)或非空值(False)
-8. search:基于全文索引的全文检索
-9. regex / iregex:基于正则表达式的模糊匹配查询
-
-Q对象(用于执行复杂查询)的使用:
-
-```Shell
->>> from django.db.models import Q
->>> Emp.objects.filter(
-... Q(name__startswith='张'),
-... Q(sal__gte=5000) | Q(comm__gte=1000)
-... ) # 查询名字以“张”开头且工资大于等于5000或补贴大于等于1000的员工
-]>
-```
+1. `exact` / `iexact`:精确匹配/忽略大小写的精确匹配查询
+2. `contains` / `icontains` / `startswith` / `istartswith` / `endswith` / `iendswith`:基于`like`的模糊查询
+3. `in` :集合运算
+4. `gt` / `gte` / `lt` / `lte`:大于/大于等于/小于/小于等于关系运算
+5. `range`:指定范围查询(SQL中的`between…and…`)
+6. `year` / `month` / `day` / `week_day` / `hour` / `minute` / `second`:查询时间日期
+7. `isnull`:查询空值(True)或非空值(False)
+8. `search`:基于全文索引的全文检索(一般很少使用)
+9. `regex` / `iregex`:基于正则表达式的模糊匹配查询
diff --git a/Day41-55/43.静态资源和Ajax请求.md b/Day41-55/43.静态资源和Ajax请求.md
index 18f5df1..c6332a4 100644
--- a/Day41-55/43.静态资源和Ajax请求.md
+++ b/Day41-55/43.静态资源和Ajax请求.md
@@ -1,216 +1,60 @@
## 静态资源和Ajax请求
-基于前面两个章节讲解的知识,我们已经可以使用Django框架来完成Web应用的开发了。接下来我们就尝试实现一个投票应用,具体的需求是用户进入应用首先查看到“学科介绍”页面,该页面显示了一个学校所开设的所有学科;通过点击某个学科,可以进入“老师介绍”页面,该页面展示了该学科所有老师的详细情况,可以在该页面上给老师点击“好评”或“差评”;如果用户没有登录,在投票时会先跳转到“登录页”要求用户登录,登录成功才能投票;对于未注册的用户,可以在“登录页”点击“新用户注册”进入“注册页”完成用户注册操作,注册成功后会跳转到“登录页”,注册失败会获得相应的提示信息。
-
-### 准备工作
-
-由于之前已经详细的讲解了如何创建Django项目以及项目的相关配置,因此我们略过这部分内容,唯一需要说明的是,从上面对投票应用需求的描述中我们可以分析出三个业务实体:学科、老师和用户。学科和老师之间通常是一对多关联关系(一个学科有多个老师,一个老师通常只属于一个学科),用户因为要给老师投票,所以跟老师之间是多对多关联关系(一个用户可以给多个老师投票,一个老师也可以收到多个用户的投票)。首先修改应用下的models.py文件来定义数据模型,先给出学科和老师的模型。
-
-```Python
-from django.db import models
-
-
-class Subject(models.Model):
- """学科"""
- no = models.IntegerField(primary_key=True, verbose_name='编号')
- name = models.CharField(max_length=20, verbose_name='名称')
- intro = models.CharField(max_length=511, default='', verbose_name='介绍')
- create_date = models.DateField(null=True, verbose_name='成立日期')
- is_hot = models.BooleanField(default=False, verbose_name='是否热门')
-
- def __str__(self):
- return self.name
-
- class Meta:
- db_table = 'tb_subject'
- verbose_name = '学科'
- verbose_name_plural = '学科'
-
-
-class Teacher(models.Model):
- """老师"""
- no = models.AutoField(primary_key=True, verbose_name='编号')
- name = models.CharField(max_length=20, verbose_name='姓名')
- detail = models.CharField(max_length=1023, default='', blank=True, verbose_name='详情')
- photo = models.CharField(max_length=1023, default='', verbose_name='照片')
- good_count = models.IntegerField(default=0, verbose_name='好评数')
- bad_count = models.IntegerField(default=0, verbose_name='差评数')
- subject = models.ForeignKey(to=Subject, on_delete=models.PROTECT, db_column='sno', verbose_name='所属学科')
-
- class Meta:
- db_table = 'tb_teacher'
- verbose_name = '老师'
- verbose_name_plural = '老师'
-```
-
-模型定义完成后,可以通过“生成迁移”和“执行迁移”来完成关系型数据库中二维表的创建,当然这需要提前启动数据库服务器并创建好对应的数据库,同时我们在项目中已经安装了PyMySQL而且完成了相应的配置,这些内容此处不再赘述。
-
-```Shell
-(venv)$ python manage.py makemigrations vote
-...
-(venv)$ python manage.py migrate
-...
-```
-
-> 注意:为了给vote应用生成迁移文件,需要修改Django项目settings.py文件,在INSTALLED_APPS中添加vote应用。
-
-完成模型迁移之后,我们可以直接使用Django提供的后台管理来添加学科和老师信息,这需要先注册模型类和模型管理类。
-
-```SQL
-from django.contrib import admin
-
-from poll2.forms import UserForm
-from poll2.models import Subject, Teacher
-
-
-class SubjectAdmin(admin.ModelAdmin):
- list_display = ('no', 'name', 'create_date', 'is_hot')
- ordering = ('no', )
-
-
-class TeacherAdmin(admin.ModelAdmin):
- list_display = ('no', 'name', 'detail', 'good_count', 'bad_count', 'subject')
- ordering = ('subject', 'no')
-
-
-admin.site.register(Subject, SubjectAdmin)
-admin.site.register(Teacher, TeacherAdmin)
-```
-
-接下来,我们就可以修改views.py文件,通过编写视图函数先实现“学科介绍”页面。
-
-```Python
-def show_subjects(request):
- """查看所有学科"""
- subjects = Subject.objects.all()
- return render(request, 'subject.html', {'subjects': subjects})
-```
-
-至此,我们还需要一个模板页,模板的配置以及模板页中模板语言的用法在之前已经进行过简要的介绍,如果不熟悉可以看看下面的代码,相信这并不是一件困难的事情。
-
-```HTML
-
-
-
-
- 所有学科信息
-
-
-
- 所有学科
-
- {% for subject in subjects %}
-
-
- {{ subject.name }}
- {% if subject.is_hot %}
-
- {% endif %}
-
-
{{ subject.intro }}
-
- {% endfor %}
-
-
-```
-
-在上面的模板中,我们为每个学科添加了一个超链接,点击超链接可以查看该学科的讲师信息,为此需要再编写一个视图函数来处理查看指定学科老师信息。
-
-```Python
-def show_teachers(request):
- """显示指定学科的老师"""
- try:
- sno = int(request.GET['sno'])
- subject = Subject.objects.get(no=sno)
- teachers = subject.teacher_set.all()
- return render(request, 'teachers.html', {'subject': subject, 'teachers': teachers})
- except (KeyError, ValueError, Subject.DoesNotExist):
- return redirect('/')
-```
-
-显示老师信息的模板页。
-
-```HTML
-
-{% load static %}
-
-
-
- 老师
-
-
-
- {{ subject.name }}学科老师信息
-
- {% if teachers %}
- {% for teacher in teachers %}
-
-
-
-
-
-
{{ teacher.name }}
-
{{ teacher.detail }}
-
-
-
- {% endfor %}
- {% else %}
- 暂时没有该学科的老师信息
- {% endif %}
-
- 返回首页
-
-
-
-```
-
### 加载静态资源
-在上面的模板页面中,我们使用了` `标签来加载老师的照片,其中使用了引用静态资源的模板指令`{% static %}`,要使用该指令,首先要使用`{% load static %}`指令来加载静态资源,我们将这段代码放在了页码开始的位置。在上面的项目中,我们将静态资源置于名为static的文件夹中,在该文件夹下又创建了三个文件夹:css、js和images,分别用来保存外部层叠样式表、外部JavaScript文件和图片资源。为了能够找到保存静态资源的文件夹,我们还需要修改Django项目的配置文件settings.py,如下所示:
+如果要在Django项目中使用静态资源,可以先创建一个用于保存静态资源的目录。在`vote`项目中,我们将静态资源置于名为`static`的文件夹中,在该文件夹包含了三个子文件夹:css、js和images,分别用来保存外部CSS文件、外部JavaScript文件和图片资源,如下图所示。
+
+
+
+为了能够找到保存静态资源的文件夹,我们还需要修改Django项目的配置文件`settings.py`,如下所示:
```Python
-# 此处省略上面的代码
-
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'), ]
STATIC_URL = '/static/'
-
-# 此处省略下面的代码
```
-接下来修改urls.py文件,配置用户请求的URL和视图函数的对应关系。
+配置好静态资源之后,大家可以运行项目,然后看看之前我们写的页面上的图片是否能够正常加载出来。需要说明的是,在项目正式部署到线上环境后,我们通常会把静态资源交给专门的静态资源服务器(如Nginx、Apache)来处理,而不是有运行Python代码的服务器来管理静态资源,所以上面的配置并不适用于生产环境,仅供项目开发阶段测试使用。使用静态资源的正确姿势我们会在后续的章节为大家讲解。
-```Python
-from django.contrib import admin
-from django.urls import path
+### Ajax概述
-from vote import views
+接下来就可以实现“好评”和“差评”的功能了,很明显如果能够在不刷新页面的情况下实现这两个功能会带来更好的用户体验,因此我们考虑使用[Ajax](https://zh.wikipedia.org/wiki/AJAX)技术来实现“好评”和“差评”。Ajax是Asynchronous Javascript And XML的缩写 , 简单的说,使用Ajax技术可以在不重新加载整个页面的情况下对页面进行局部刷新。
-urlpatterns = [
- path('', views.show_subjects),
- path('teachers/', views.show_teachers),
- path('admin/', admin.site.urls),
-]
+对于传统的Web应用,每次页面上需要加载新的内容都需要重新请求服务器并刷新整个页面,如果服务器短时间内无法给予响应或者网络状况并不理想,那么可能会造成浏览器长时间的空白并使得用户处于等待状态,在这个期间用户什么都做不了,如下图所示。很显然,这样的Web应用并不能带来很好的用户体验。
+
+
+
+对于使用Ajax技术的Web应用,浏览器可以向服务器发起异步请求来获取数据。异步请求不会中断用户体验,当服务器返回了新的数据,我们可以通过JavaScript代码进行DOM操作来实现对页面的局部刷新,这样就相当于在不刷新整个页面的情况下更新了页面的内容,如下图所示。
+
+
+
+在使用Ajax技术时,浏览器跟服务器通常会交换XML或JSON格式的数据,XML是以前使用得非常多的一种数据格式,近年来几乎已经完全被JSON取代,下面是两种数据格式的对比。
+
+XML格式:
+
+```XML
+
+
+ Alice
+ Bob
+ Dinner is on me!
+
```
-启动服务器运行项目,进入首页查看学科信息。
+JSON格式:
-
+```JSON
+{
+ "from": "Alice",
+ "to": "Bob",
+ "content": "Dinner is on me!"
+}
+```
-点击学科查看老师信息。
+通过上面的对比,明显JSON格式的数据要紧凑得多,所以传输效率更高,而且JSON本身也是JavaScript中的一种对象表达式语法,在JavaScript代码中处理JSON格式的数据更加方便。
-
+### 用Ajax实现投票功能
-### Ajax请求
-
-接下来就可以实现“好评”和“差评”的功能了,很明显如果能够在不刷新页面的情况下实现这两个功能会带来更好的用户体验,因此我们考虑使用[Ajax](https://zh.wikipedia.org/wiki/AJAX)技术来实现“好评”和“差评”,Ajax技术我们在Web前端部分已经介绍过了,此处不再赘述。
-
-首先修改项目的urls.py文件,为“好评”和“差评”功能映射对应的URL。
+下面,我们使用Ajax技术来实现投票的功能,首先修改项目的`urls.py`文件,为“好评”和“差评”功能映射对应的URL。
```Python
from django.contrib import admin
@@ -233,16 +77,18 @@ urlpatterns = [
def praise_or_criticize(request):
"""好评"""
try:
- tno = int(request.GET['tno'])
+ tno = int(request.GET.get('tno'))
teacher = Teacher.objects.get(no=tno)
if request.path.startswith('/praise'):
teacher.good_count += 1
+ count = teacher.good_count
else:
teacher.bad_count += 1
+ count = teacher.bad_count
teacher.save()
- data = {'code': 200, 'hint': '操作成功'}
- except (KeyError, ValueError, Teacher.DoseNotExist):
- data = {'code': 404, 'hint': '操作失败'}
+ data = {'code': 20000, 'mesg': '操作成功', 'count': count}
+ except (ValueError, Teacher.DoseNotExist):
+ data = {'code': 20001, 'mesg': '操作失败'}
return JsonResponse(data)
```
@@ -250,54 +96,90 @@ def praise_or_criticize(request):
```HTML
-{% load static %}
- 老师
-
+ 老师信息
+
- {{ subject.name }}学科老师信息
-
- {% if teachers %}
- {% for teacher in teachers %}
-
-
-
+
+
{{ subject.name }}学科的老师信息
+
+ {% if not teachers %}
+
暂无该学科老师信息
+ {% endif %}
+ {% for teacher in teachers %}
+
+
+
+
+
+
+ 姓名:{{ teacher.name }}
+ 性别:{{ teacher.sex | yesno:'男,女' }}
+ 出生日期:{{ teacher.birth }}
+
+
{{ teacher.intro }}
+
+
-
-
{{ teacher.name }}
-
{{ teacher.detail }}
-
-
-
- {% endfor %}
- {% else %}
-
暂时没有该学科的老师信息
- {% endif %}
-
+ {% endfor %}
返回首页
-
+
+
+
+
+```
+
+运行效果如下图所示。
+
+
diff --git a/Day41-55/46.报表和日志.md b/Day41-55/46.报表和日志.md
deleted file mode 100644
index dffdcfc..0000000
--- a/Day41-55/46.报表和日志.md
+++ /dev/null
@@ -1,351 +0,0 @@
-## 报表和日志
-
-### 导出Excel报表
-
-报表就是用表格、图表等格式来动态显示数据,所以有人用这样的公式来描述报表:
-
-```
-报表 = 多样的格式 + 动态的数据
-```
-
-有很多的三方库支持在Python程序中写Excel文件,包括[xlwt](
)、[xlwings](
)、[openpyxl]( )、[xlswriter]( )、[pandas]( )等,其中的xlwt虽然只支持写xls格式的Excel文件,但在性能方面的表现还是不错的。下面我们就以xlwt为例,来演示如何在Django项目中导出Excel报表,例如导出一个包含所有老师信息的Excel表格。
-
-```Python
-def export_teachers_excel(request):
- # 创建工作簿
- wb = xlwt.Workbook()
- # 添加工作表
- sheet = wb.add_sheet('老师信息表')
- # 查询所有老师的信息(注意:这个地方稍后需要优化)
- queryset = Teacher.objects.all()
- # 向Excel表单中写入表头
- colnames = ('姓名', '介绍', '好评数', '差评数', '学科')
- for index, name in enumerate(colnames):
- sheet.write(0, index, name)
- # 向单元格中写入老师的数据
- props = ('name', 'detail', 'good_count', 'bad_count', 'subject')
- for row, teacher in enumerate(queryset):
- for col, prop in enumerate(props):
- value = getattr(teacher, prop, '')
- if isinstance(value, Subject):
- value = value.name
- sheet.write(row + 1, col, value)
- # 保存Excel
- buffer = BytesIO()
- wb.save(buffer)
- # 将二进制数据写入响应的消息体中并设置MIME类型
- resp = HttpResponse(buffer.getvalue(), content_type='application/vnd.ms-excel')
- # 中文文件名需要处理成百分号编码
- filename = quote('老师.xls')
- # 通过响应头告知浏览器下载该文件以及对应的文件名
- resp['content-disposition'] = f'attachment; filename="{filename}"'
- return resp
-```
-
-映射URL。
-
-```Python
-urlpatterns = [
- # 此处省略上面的代码
- path('excel/', views.export_teachers_excel),
- # 此处省略下面的代码
-]
-```
-
-### 生成前端统计图表
-
-如果项目中需要生成前端统计图表,可以使用百度的[ECharts]( )。具体的做法是后端通过提供数据接口返回统计图表所需的数据,前端使用ECharts来渲染出柱状图、折线图、饼图、散点图等图表。例如我们要生成一个统计所有老师好评数和差评数的报表,可以按照下面的方式来做。
-
-```Python
-def get_teachers_data(request):
- # 查询所有老师的信息(注意:这个地方稍后也需要优化)
- queryset = Teacher.objects.all()
- # 用生成式将老师的名字放在一个列表中
- names = [teacher.name for teacher in queryset]
- # 用生成式将老师的好评数放在一个列表中
- good = [teacher.good_count for teacher in queryset]
- # 用生成式将老师的差评数放在一个列表中
- bad = [teacher.bad_count for teacher in queryset]
- # 返回JSON格式的数据
- return JsonResponse({'names': names, 'good': good, 'bad': bad})
-```
-
-映射URL。
-
-```Python
-urlpatterns = [
- # 此处省略上面的代码
- path('teachers_data/', views.export_teachers_excel),
- # 此处省略下面的代码
-]
-```
-
-使用ECharts生成柱状图。
-
-```HTML
-
-
-
-
- 老师评价统计
-
-
-
-
- 返回首页
-
-
-
-
-
-```
-
-运行效果如下图所示。
-
-
-
-### 配置日志
-
-项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的;项目上线以后,将系统运行时出现的警告、错误等信息记录下来以备相关人员了解系统运行状况并维护代码也是很有必要的。要做好这两件事件,我们需要为Django项目配置日志。
-
-Django的日志配置基本可以参照官方文档再结合项目实际需求来进行,这些内容基本上可以从官方文档上复制下来,然后进行局部的调整即可,下面给出一些参考配置。
-
-```Python
-LOGGING = {
- 'version': 1,
- # 是否禁用已经存在的日志器
- 'disable_existing_loggers': False,
- # 日志格式化器
- 'formatters': {
- 'simple': {
- 'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s',
- 'datefmt': '%Y-%m-%d %H:%M:%S',
- },
- 'verbose': {
- 'format': '%(asctime)s %(levelname)s [%(process)d-%(threadName)s] '
- '%(module)s.%(funcName)s line %(lineno)d: %(message)s',
- 'datefmt': '%Y-%m-%d %H:%M:%S',
- }
- },
- # 日志过滤器
- 'filters': {
- # 只有在Django配置文件中DEBUG值为True时才起作用
- 'require_debug_true': {
- '()': 'django.utils.log.RequireDebugTrue',
- },
- },
- # 日志处理器
- 'handlers': {
- # 输出到控制台
- 'console': {
- 'class': 'logging.StreamHandler',
- 'level': 'DEBUG',
- 'filters': ['require_debug_true'],
- 'formatter': 'simple',
- },
- # 输出到文件(每周切割一次)
- 'file1': {
- 'class': 'logging.handlers.TimedRotatingFileHandler',
- 'filename': 'access.log',
- 'when': 'W0',
- 'backupCount': 12,
- 'formatter': 'simple',
- 'level': 'INFO',
- },
- # 输出到文件(每天切割一次)
- 'file2': {
- 'class': 'logging.handlers.TimedRotatingFileHandler',
- 'filename': 'error.log',
- 'when': 'D',
- 'backupCount': 31,
- 'formatter': 'verbose',
- 'level': 'WARNING',
- },
- },
- # 日志器记录器
- 'loggers': {
- 'django': {
- # 需要使用的日志处理器
- 'handlers': ['console', 'file1', 'file2'],
- # 是否向上传播日志信息
- 'propagate': True,
- # 日志级别(不一定是最终的日志级别)
- 'level': 'DEBUG',
- },
- }
-}
-```
-
-大家可能已经注意到了,上面日志配置中的formatters是**日志格式化器**,它代表了如何格式化输出日志,其中格式占位符分别表示:
-
-1. %(name)s - 记录器的名称
-2. %(levelno)s - 数字形式的日志记录级别
-3. %(levelname)s - 日志记录级别的文本名称
-4. %(filename)s - 执行日志记录调用的源文件的文件名称
-5. %(pathname)s - 执行日志记录调用的源文件的路径名称
-6. %(funcName)s - 执行日志记录调用的函数名称
-7. %(module)s - 执行日志记录调用的模块名称
-8. %(lineno)s - 执行日志记录调用的行号
-9. %(created)s - 执行日志记录的时间
-10. %(asctime)s - 日期和时间
-11. %(msecs)s - 毫秒部分
-12. %(thread)d - 线程ID(整数)
-13. %(threadName)s - 线程名称
-14. %(process)d - 进程ID (整数)
-
-日志配置中的handlers用来指定**日志处理器**,简单的说就是指定将日志输出到控制台还是文件又或者是网络上的服务器,可用的处理器包括:
-
-1. logging.StreamHandler(stream=None) - 可以向类似与sys.stdout或者sys.stderr的任何文件对象输出信息
-2. logging.FileHandler(filename, mode='a', encoding=None, delay=False) - 将日志消息写入文件
-3. logging.handlers.DatagramHandler(host, port) - 使用UDP协议,将日志信息发送到指定主机和端口的网络主机上
-4. logging.handlers.HTTPHandler(host, url) - 使用HTTP的GET或POST方法将日志消息上传到一台HTTP 服务器
-5. logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False) - 将日志消息写入文件,如果文件的大小超出maxBytes指定的值,那么将重新生成一个文件来记录日志
-6. logging.handlers.SocketHandler(host, port) - 使用TCP协议,将日志信息发送到指定主机和端口的网络主机上
-7. logging.handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None, timeout=1.0) - 将日志输出到指定的邮件地址
-8. logging.MemoryHandler(capacity, flushLevel=ERROR, target=None, flushOnClose=True) - 将日志输出到内存指定的缓冲区中
-
-上面每个日志处理器都指定了一个名为“level”的属性,它代表了日志的级别,不同的日志级别反映出日志中记录信息的严重性。Python中定义了六个级别的日志,按照从低到高的顺序依次是:NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL。
-
-最后配置的**日志记录器**是用来真正输出日志的,Django框架提供了如下所示的内置记录器:
-
-1. django - 在Django层次结构中的所有消息记录器
-2. django.request - 与请求处理相关的日志消息。5xx响应被视为错误消息;4xx响应被视为为警告消息
-3. django.server - 与通过runserver调用的服务器所接收的请求相关的日志消息。5xx响应被视为错误消息;4xx响应被记录为警告消息;其他一切都被记录为INFO
-4. django.template - 与模板渲染相关的日志消息
-5. django.db.backends - 有与数据库交互产生的日志消息,如果希望显示ORM框架执行的SQL语句,就可以使用该日志记录器。
-
-日志记录器中配置的日志级别有可能不是最终的日志级别,因为还要参考日志处理器中配置的日志级别,取二者中级别较高者作为最终的日志级别。
-
-### 配置Django-Debug-Toolbar
-
-Django-Debug-Toolbar是项目开发阶段辅助调试和优化的神器,只要配置了它,就可以很方便的查看到如下表所示的项目运行信息,这些信息对调试项目和优化Web应用性能都是至关重要的。
-
-| 项目 | 说明 |
-| ----------- | --------------------------------- |
-| Versions | Django的版本 |
-| Time | 显示视图耗费的时间 |
-| Settings | 配置文件中设置的值 |
-| Headers | HTTP请求头和响应头的信息 |
-| Request | 和请求相关的各种变量及其信息 |
-| StaticFiles | 静态文件加载情况 |
-| Templates | 模板的相关信息 |
-| Cache | 缓存的使用情况 |
-| Signals | Django内置的信号信息 |
-| Logging | 被记录的日志信息 |
-| SQL | 向数据库发送的SQL语句及其执行时间 |
-
-1. 安装Django-Debug-Toolbar。
-
- ```Shell
- pip install django-debug-toolbar
- ```
-
-2. 配置 - 修改settings.py。
-
- ```Python
- INSTALLED_APPS = [
- 'debug_toolbar',
- ]
-
- MIDDLEWARE = [
- 'debug_toolbar.middleware.DebugToolbarMiddleware',
- ]
-
- DEBUG_TOOLBAR_CONFIG = {
- # 引入jQuery库
- 'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js',
- # 工具栏是否折叠
- 'SHOW_COLLAPSED': True,
- # 是否显示工具栏
- 'SHOW_TOOLBAR_CALLBACK': lambda x: True,
- }
- ```
-
-3. 配置 - 修改urls.py。
-
- ```Python
- if settings.DEBUG:
-
- import debug_toolbar
-
- urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))
- ```
-
-4. 使用 - 如下图所示,在配置好Django-Debug-Toolbar之后,页面右侧会看到一个调试工具栏,上面包括了如前所述的各种调试信息,包括执行时间、项目设置、请求头、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。
-
-### 优化ORM代码
-
-在配置了日志或Django-Debug-Toolbar之后,我们可以查看一下之前将老师数据导出成Excel报表的视图函数执行情况,这里我们关注的是ORM框架生成的SQL查询到底是什么样子的,相信这里的结果会让你感到有一些意外。执行`Teacher.objects.all()`之后我们可以注意到,在控制台看到的或者通过Django-Debug-Toolbar输出的SQL是下面这样的:
-
-```SQL
-SELECT `tb_teacher`.`no`, `tb_teacher`.`name`, `tb_teacher`.`detail`, `tb_teacher`.`photo`, `tb_teacher`.`good_count`, `tb_teacher`.`bad_count`, `tb_teacher`.`sno` FROM `tb_teacher`; args=()
-SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
-SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
-SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
-SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
-SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 103; args=(103,)
-SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 103; args=(103,)
-```
-
-这里的问题通常被称为“1+N查询”(或“N+1查询”),原本获取老师的数据只需要一条SQL,但是由于老师关联了学科,当我们查询到N条老师的数据时,Django的ORM框架又向数据库发出了N条SQL去查询老师所属学科的信息。每条SQL执行都会有较大的开销而且会给数据库服务器带来压力,如果能够在一条SQL中完成老师和学科的查询肯定是更好的做法,这一点也很容易做到,相信大家已经想到怎么做了。是的,我们可以使用连接查询,但是在使用Django的ORM框架时如何做到这一点呢?对于多对一关联(如投票应用中的老师和学科),我们可以使用`QuerySet`的用`select_related()`方法来加载关联对象;而对于多对多关联(如电商网站中的订单和商品),我们可以使用`prefetch_related()`方法来加载关联对象。
-
-在导出老师Excel报表的视图函数中,我们可以按照下面的方式优化代码。
-
-```Python
-queryset = Teacher.objects.all().select_related('subject')
-```
-
-事实上,用ECharts生成前端报表的视图函数中,查询老师好评和差评数据的操作也能够优化,因为在这个例子中,我们只需要获取老师的姓名、好评数和差评数这三项数据,但是在默认的情况生成的SQL会查询老师表的所有字段。可以用`QuerySet`的`only()`方法来指定需要查询的属性,也可以用`QuerySet`的`defer()`方法来指定暂时不需要查询的属性,这样生成的SQL会通过投影操作来指定需要查询的列,从而改善查询性能,代码如下所示:
-
-```Python
-queryset = Teacher.objects.all().only('name', 'good_count', 'bad_count')
-```
-
-当然,如果要统计出每个学科的老师好评和差评的平均数,利用Django的ORM框架也能够做到,代码如下所示:
-
-```Python
-queryset = Teacher.objects.values('subject').annotate(
- good=Avg('good_count'), bad=Avg('bad_count'))
-```
-
-这里获得的`QuerySet`中的元素是字典对象,每个字典中有三组键值对,分别是代表学科编号的`subject`、代表好评数的`good`和代表差评数的`bad`。如果想要获得学科的名称而不是编号,可以按照如下所示的方式调整代码:
-
-```Python
-queryset = Teacher.objects.values('subject__name').annotate(
- good=Avg('good_count'), bad=Avg('bad_count'))
-```
-
-可见,Django的ORM框架允许我们用面向对象的方式完成关系数据库中的分组和聚合查询。
\ No newline at end of file
diff --git a/Day41-55/46.日志和调试工具栏.md b/Day41-55/46.日志和调试工具栏.md
new file mode 100644
index 0000000..a880881
--- /dev/null
+++ b/Day41-55/46.日志和调试工具栏.md
@@ -0,0 +1,215 @@
+## 日志和调试工具栏
+
+### 配置日志
+
+项目开发阶段,显示足够的调试信息以辅助开发人员调试代码还是非常必要的;项目上线以后,将系统运行时出现的警告、错误等信息记录下来以备相关人员了解系统运行状况并维护代码也是很有必要的。与此同时,采集日志数据也是为网站做数字化运营奠定一个基础,通过对系统运行日志的分析,我们可以监测网站的流量以及流量分布,同时还可以挖掘出用户的使用习惯和行为模式。
+
+接下来,我们先看看如何通过Django的配置文件来配置日志。Django的日志配置基本可以参照官方文档再结合项目实际需求来进行,这些内容基本上可以从官方文档上复制下来,然后进行局部的调整即可,下面给出一些参考配置。
+
+```Python
+LOGGING = {
+ 'version': 1,
+ # 是否禁用已经存在的日志器
+ 'disable_existing_loggers': False,
+ # 日志格式化器
+ 'formatters': {
+ 'simple': {
+ 'format': '%(asctime)s %(module)s.%(funcName)s: %(message)s',
+ 'datefmt': '%Y-%m-%d %H:%M:%S',
+ },
+ 'verbose': {
+ 'format': '%(asctime)s %(levelname)s [%(process)d-%(threadName)s] '
+ '%(module)s.%(funcName)s line %(lineno)d: %(message)s',
+ 'datefmt': '%Y-%m-%d %H:%M:%S',
+ }
+ },
+ # 日志过滤器
+ 'filters': {
+ # 只有在Django配置文件中DEBUG值为True时才起作用
+ 'require_debug_true': {
+ '()': 'django.utils.log.RequireDebugTrue',
+ },
+ },
+ # 日志处理器
+ 'handlers': {
+ # 输出到控制台
+ 'console': {
+ 'class': 'logging.StreamHandler',
+ 'level': 'DEBUG',
+ 'filters': ['require_debug_true'],
+ 'formatter': 'simple',
+ },
+ # 输出到文件(每周切割一次)
+ 'file1': {
+ 'class': 'logging.handlers.TimedRotatingFileHandler',
+ 'filename': 'access.log',
+ 'when': 'W0',
+ 'backupCount': 12,
+ 'formatter': 'simple',
+ 'level': 'INFO',
+ },
+ # 输出到文件(每天切割一次)
+ 'file2': {
+ 'class': 'logging.handlers.TimedRotatingFileHandler',
+ 'filename': 'error.log',
+ 'when': 'D',
+ 'backupCount': 31,
+ 'formatter': 'verbose',
+ 'level': 'WARNING',
+ },
+ },
+ # 日志器记录器
+ 'loggers': {
+ 'django': {
+ # 需要使用的日志处理器
+ 'handlers': ['console', 'file1', 'file2'],
+ # 是否向上传播日志信息
+ 'propagate': True,
+ # 日志级别(不一定是最终的日志级别)
+ 'level': 'DEBUG',
+ },
+ }
+}
+```
+
+大家可能已经注意到了,上面日志配置中的`formatters`是**日志格式化器**,它代表了如何格式化输出日志,其中格式占位符分别表示:
+
+1. `%(name)s` - 记录器的名称
+2. `%(levelno)s` - 数字形式的日志记录级别
+3. `%(levelname)s` - 日志记录级别的文本名称
+4. `%(filename)s` - 执行日志记录调用的源文件的文件名称
+5. `%(pathname)s` - 执行日志记录调用的源文件的路径名称
+6. `%(funcName)s` - 执行日志记录调用的函数名称
+7. `%(module)s` - 执行日志记录调用的模块名称
+8. `%(lineno)s` - 执行日志记录调用的行号
+9. `%(created)s` - 执行日志记录的时间
+10. `%(asctime)s` - 日期和时间
+11. `%(msecs)s` - 毫秒部分
+12. `%(thread)d` - 线程ID(整数)
+13. `%(threadName)s` - 线程名称
+14. `%(process)d` - 进程ID (整数)
+
+日志配置中的handlers用来指定**日志处理器**,简单的说就是指定将日志输出到控制台还是文件又或者是网络上的服务器,可用的处理器包括:
+
+1. `logging.StreamHandler(stream=None)` - 可以向类似与`sys.stdout`或者`sys.stderr`的任何文件对象输出信息
+2. `logging.FileHandler(filename, mode='a', encoding=None, delay=False)` - 将日志消息写入文件
+3. `logging.handlers.DatagramHandler(host, port)` - 使用UDP协议,将日志信息发送到指定主机和端口的网络主机上
+4. `logging.handlers.HTTPHandler(host, url)` - 使用HTTP的GET或POST方法将日志消息上传到一台HTTP 服务器
+5. `logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)` - 将日志消息写入文件,如果文件的大小超出`maxBytes`指定的值,那么将重新生成一个文件来记录日志
+6. `logging.handlers.SocketHandler(host, port)` - 使用TCP协议,将日志信息发送到指定主机和端口的网络主机上
+7. `logging.handlers.SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None, timeout=1.0)` - 将日志输出到指定的邮件地址
+8. `logging.MemoryHandler(capacity, flushLevel=ERROR, target=None, flushOnClose=True)` - 将日志输出到内存指定的缓冲区中
+
+上面每个日志处理器都指定了一个名为`level`的属性,它代表了日志的级别,不同的日志级别反映出日志中记录信息的严重性。Python中定义了六个级别的日志,按照从低到高的顺序依次是:NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL。
+
+最后配置的**日志记录器**是用来真正输出日志的,Django框架提供了如下所示的内置记录器:
+
+1. `django` - 在Django层次结构中的所有消息记录器
+2. `django.request` - 与请求处理相关的日志消息。5xx响应被视为错误消息;4xx响应被视为为警告消息
+3. `django.server` - 与通过runserver调用的服务器所接收的请求相关的日志消息。5xx响应被视为错误消息;4xx响应被记录为警告消息;其他一切都被记录为INFO
+4. `django.template` - 与模板渲染相关的日志消息
+5. `django.db.backends` - 有与数据库交互产生的日志消息,如果希望显示ORM框架执行的SQL语句,就可以使用该日志记录器。
+
+日志记录器中配置的日志级别有可能不是最终的日志级别,因为还要参考日志处理器中配置的日志级别,取二者中级别较高者作为最终的日志级别。
+
+### 配置Django-Debug-Toolbar
+
+如果想调试你的Django项目,你一定不能不过名为Django-Debug-Toolbar的神器,它是项目开发阶段辅助调试和优化的必备工具,只要配置了它,就可以很方便的查看到如下表所示的项目运行信息,这些信息对调试项目和优化Web应用性能都是至关重要的。
+
+| 项目 | 说明 |
+| ----------- | --------------------------------- |
+| Versions | Django的版本 |
+| Time | 显示视图耗费的时间 |
+| Settings | 配置文件中设置的值 |
+| Headers | HTTP请求头和响应头的信息 |
+| Request | 和请求相关的各种变量及其信息 |
+| StaticFiles | 静态文件加载情况 |
+| Templates | 模板的相关信息 |
+| Cache | 缓存的使用情况 |
+| Signals | Django内置的信号信息 |
+| Logging | 被记录的日志信息 |
+| SQL | 向数据库发送的SQL语句及其执行时间 |
+
+1. 安装Django-Debug-Toolbar。
+
+ ```Shell
+ pip install django-debug-toolbar
+ ```
+
+2. 配置 - 修改settings.py。
+
+ ```Python
+ INSTALLED_APPS = [
+ 'debug_toolbar',
+ ]
+
+ MIDDLEWARE = [
+ 'debug_toolbar.middleware.DebugToolbarMiddleware',
+ ]
+
+ DEBUG_TOOLBAR_CONFIG = {
+ # 引入jQuery库
+ 'JQUERY_URL': 'https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js',
+ # 工具栏是否折叠
+ 'SHOW_COLLAPSED': True,
+ # 是否显示工具栏
+ 'SHOW_TOOLBAR_CALLBACK': lambda x: True,
+ }
+ ```
+
+3. 配置 - 修改urls.py。
+
+ ```Python
+ if settings.DEBUG:
+
+ import debug_toolbar
+
+ urlpatterns.insert(0, path('__debug__/', include(debug_toolbar.urls)))
+ ```
+
+4. 在配置好Django-Debug-Toolbar之后,页面右侧会看到一个调试工具栏,如下图所示,上面包括了如前所述的各种调试信息,包括执行时间、项目设置、请求头、SQL、静态资源、模板、缓存、信号等,查看起来非常的方便。
+
+ 
+
+### 优化ORM代码
+
+在配置了日志或Django-Debug-Toolbar之后,我们可以查看一下之前将老师数据导出成Excel报表的视图函数执行情况,这里我们关注的是ORM框架生成的SQL查询到底是什么样子的,相信这里的结果会让你感到有一些意外。执行`Teacher.objects.all()`之后我们可以注意到,在控制台看到的或者通过Django-Debug-Toolbar输出的SQL是下面这样的:
+
+```SQL
+SELECT `tb_teacher`.`no`, `tb_teacher`.`name`, `tb_teacher`.`detail`, `tb_teacher`.`photo`, `tb_teacher`.`good_count`, `tb_teacher`.`bad_count`, `tb_teacher`.`sno` FROM `tb_teacher`; args=()
+SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
+SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
+SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
+SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 101; args=(101,)
+SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 103; args=(103,)
+SELECT `tb_subject`.`no`, `tb_subject`.`name`, `tb_subject`.`intro`, `tb_subject`.`create_date`, `tb_subject`.`is_hot` FROM `tb_subject` WHERE `tb_subject`.`no` = 103; args=(103,)
+```
+
+这里的问题通常被称为“1+N查询”(有的地方也将其称之为“N+1查询”),原本获取老师的数据只需要一条SQL,但是由于老师关联了学科,当我们查询到`N`条老师的数据时,Django的ORM框架又向数据库发出了`N`条SQL去查询老师所属学科的信息。每条SQL执行都会有较大的开销而且会给数据库服务器带来压力,如果能够在一条SQL中完成老师和学科的查询肯定是更好的做法,这一点也很容易做到,相信大家已经想到怎么做了。是的,我们可以使用连接查询,但是在使用Django的ORM框架时如何做到这一点呢?对于多对一关联(如投票应用中的老师和学科),我们可以使用`QuerySet`的用`select_related()`方法来加载关联对象;而对于多对多关联(如电商网站中的订单和商品),我们可以使用`prefetch_related()`方法来加载关联对象。
+
+在导出老师Excel报表的视图函数中,我们可以按照下面的方式优化代码。
+
+```Python
+queryset = Teacher.objects.all().select_related('subject')
+```
+
+事实上,用ECharts生成前端报表的视图函数中,查询老师好评和差评数据的操作也能够优化,因为在这个例子中,我们只需要获取老师的姓名、好评数和差评数这三项数据,但是在默认的情况生成的SQL会查询老师表的所有字段。可以用`QuerySet`的`only()`方法来指定需要查询的属性,也可以用`QuerySet`的`defer()`方法来指定暂时不需要查询的属性,这样生成的SQL会通过投影操作来指定需要查询的列,从而改善查询性能,代码如下所示:
+
+```Python
+queryset = Teacher.objects.all().only('name', 'good_count', 'bad_count')
+```
+
+当然,如果要统计出每个学科的老师好评和差评的平均数,利用Django的ORM框架也能够做到,代码如下所示:
+
+```Python
+queryset = Teacher.objects.values('subject').annotate(good=Avg('good_count'), bad=Avg('bad_count'))
+```
+
+这里获得的`QuerySet`中的元素是字典对象,每个字典中有三组键值对,分别是代表学科编号的`subject`、代表好评数的`good`和代表差评数的`bad`。如果想要获得学科的名称而不是编号,可以按照如下所示的方式调整代码:
+
+```Python
+queryset = Teacher.objects.values('subject__name').annotate(good=Avg('good_count'), bad=Avg('bad_count'))
+```
+
+可见,Django的ORM框架允许我们用面向对象的方式完成关系数据库中的分组和聚合查询。
+
diff --git a/Day41-55/47.中间件的应用.md b/Day41-55/47.中间件的应用.md
index 4eecd40..1a670d0 100644
--- a/Day41-55/47.中间件的应用.md
+++ b/Day41-55/47.中间件的应用.md
@@ -1,55 +1,6 @@
## 中间件的应用
-### 实现登录验证
-
-我们继续来完善投票应用。在上一个章节中,我们在用户登录成功后通过session保留了用户信息,接下来我们可以应用做一些调整,要求在为老师投票时必须要先登录,登录过的用户可以投票,否则就将用户引导到登录页面,为此我们可以这样修改视图函数。
-
-```Python
-def praise_or_criticize(request: HttpRequest):
- """投票"""
- if 'username' in request.session:
- try:
- tno = int(request.GET.get('tno', '0'))
- teacher = Teacher.objects.get(no=tno)
- if request.path.startswith('/praise'):
- teacher.good_count += 1
- else:
- teacher.bad_count += 1
- teacher.save()
- data = {'code': 200, 'message': '操作成功'}
- except (ValueError, Teacher.DoesNotExist):
- data = {'code': 404, 'message': '操作失败'}
- else:
- data = {'code': 401, 'message': '请先登录'}
- return JsonResponse(data)
-```
-
-前端页面在收到`{'code': 401, 'message': '请先登录'}`后,可以将用户引导到登录页面,修改后的teacher.html页面的JavaScript代码部门如下所示。
-
-```HTML
-
-```
-
-> 注意:为了在登录成功之后能够回到刚才投票的页面,我们在跳转登录时设置了一个`backurl`参数,把当前浏览器中的URL作为返回的页面地址。
-
-这样我们已经实现了用户必须登录才能投票的限制,但是一个新的问题来了。如果我们的应用中有很多功能都需要用户先登录才能执行,例如将前面导出Excel报表和查看统计图表的功能都加以登录限制,那么我们是不是需要在每个视图函数中添加代码来检查session中是否包含了登录用户的信息呢?答案是否定的,如果这样做了,我们的视图函数中必然会充斥着大量的重复代码。编程大师*Martin Fowler*曾经说过:**代码有很多种坏味道,重复是最坏的一种**。在Django项目中,我们可以把验证用户是否登录这样的重复性代码放到中间件中。
+之前我们已经实现了用户必须登录才能投票的限制,但是一个新的问题来了。如果我们的应用中有很多功能都需要用户先登录才能执行,例如将前面导出Excel报表和查看统计图表的功能都做了必须登录才能访问的限制,那么我们是不是需要在每个视图函数中添加代码来检查session中是否包含`userid`的代码呢?答案是否定的,如果这样做了,我们的视图函数中必然会充斥着大量的重复代码。编程大师*Martin Fowler*曾经说过:**代码有很多种坏味道,重复是最坏的一种**。在Python程序中,我们可以通过装饰器来为函数提供额外的能力;在Django项目中,我们可以把类似于验证用户是否登录这样的重复性代码放到**中间件**中。
### Django中间件概述
@@ -71,20 +22,20 @@ MIDDLEWARE = [
我们稍微为大家解释一下这些中间件的作用:
-1. CommonMiddleware - 基础设置中间件,可以处理以下一些配置参数。
+1. `CommonMiddleware` - 基础设置中间件,可以处理以下一些配置参数。
- DISALLOWED_USER_AGENTS - 不被允许的用户代理(浏览器)
- APPEND_SLASH - 是否追加`/`
- USE_ETAG - 浏览器缓存相关
-2. SecurityMiddleware - 安全相关中间件,可以处理和安全相关的配置项。
+2. `SecurityMiddleware` - 安全相关中间件,可以处理和安全相关的配置项。
- SECURE_HSTS_SECONDS - 强制使用HTTPS的时间
- SECURE_HSTS_INCLUDE_SUBDOMAINS - HTTPS是否覆盖子域名
- SECURE_CONTENT_TYPE_NOSNIFF - 是否允许浏览器推断内容类型
- SECURE_BROWSER_XSS_FILTER - 是否启用跨站脚本攻击过滤器
- SECURE_SSL_REDIRECT - 是否重定向到HTTPS连接
- SECURE_REDIRECT_EXEMPT - 免除重定向到HTTPS
-3. SessionMiddleware - 会话中间件。
-4. CsrfViewMiddleware - 通过生成令牌,防范跨请求份伪的造中间件。
-5. XFrameOptionsMiddleware - 通过设置请求头参数,防范点击劫持攻击的中间件。
+3. `SessionMiddleware` - 会话中间件。
+4. `CsrfViewMiddleware` - 通过生成令牌,防范跨请求份伪的造中间件。
+5. `XFrameOptionsMiddleware` - 通过设置请求头参数,防范点击劫持攻击的中间件。
在请求的过程中,上面的中间件会按照书写的顺序从上到下执行,然后是URL解析,最后请求才会来到视图函数;在响应的过程中,上面的中间件会按照书写的顺序从下到上执行,与请求时中间件执行的顺序正好相反。
@@ -100,9 +51,7 @@ from django.http import JsonResponse
from django.shortcuts import redirect
# 需要登录才能访问的资源路径
-LOGIN_REQUIRED_URLS = {
- '/praise/', '/criticize/', '/excel/', '/teachers_data/',
-}
+LOGIN_REQUIRED_URLS = {'/praise/', '/criticize/', '/excel/', '/teachers_data/'}
def check_login_middleware(get_resp):
@@ -125,7 +74,37 @@ def check_login_middleware(get_resp):
return wrapper
```
-修改配置文件,激活中间件使其生效。
+当然,我们也可以定义一个类来充当装饰器,如果类中有`__call__`魔术方法,这个类的对象就像函数一样可调用,所以下面是另一种实现中间件的方式,道理跟上面的代码完全一样。
+
+还有一种基于类实现中间件的方式,这种方式在较新版本的Django中已经不推荐使用了,但是大家接触到的代码中,仍然有可能遇到这种写法,大致的代码如下所示。
+
+```Python
+from django.utils.deprecation import MiddlewareMixin
+
+
+class MyMiddleware(MiddlewareMixin):
+
+ def process_request(self, request):
+ pass
+
+ def process_view(self, request, view_func, view_args, view_kwargs):
+ pass
+
+ def process_template_response(self, request, response):
+ pass
+
+ def process_response(self, request, response):
+ pass
+
+ def process_exception(self, request, exception):
+ pass
+```
+
+上面类中的五个方法都是中间件的钩子函数,分别在收到用户请求、进入视图函数之前、渲染模板、返回响应和出现异常的时候被回调。当然,写不写这些方法是根据中间件的需求来确定的,并不是所有的场景都需要重写五个方法,下面的图相信能够帮助大家理解这种写法。
+
+
+
+写好中间件代码后,需要修改配置文件来激活中间件使其生效。
```Python
MIDDLEWARE = [
@@ -145,6 +124,3 @@ MIDDLEWARE = [
中间件执行的顺序是非常重要的,对于有依赖关系的中间件必须保证被依赖的中间件要置于依赖它的中间件的前面,就好比我们刚才自定义的中间件要放到`SessionMiddleware`的后面,因为我们要依赖这个中间件为请求绑定的`session`对象才能判定用户是否登录。
-### 小结
-
-至此,除了对用户投票数量加以限制的功能外,这个投票应用就算基本完成了,整个项目的完整代码请参考,其中用户注册时使用的手机验证码功能请大家使用自己注册的短信平台替代它。如果需要投票应用完整的视频讲解,可以在首页扫码打赏后留言联系作者获取视频下载地址,谢谢大家的理解和支持。
\ No newline at end of file
diff --git a/Day41-55/48.前后端分离开发入门.md b/Day41-55/48.前后端分离开发入门.md
index 2e0879e..bd41eaa 100644
--- a/Day41-55/48.前后端分离开发入门.md
+++ b/Day41-55/48.前后端分离开发入门.md
@@ -1,6 +1,6 @@
## 前后端分离开发入门
-在传统的Web应用开发中,大多数的程序员会将浏览器作为前后端的分界线。将浏览器中为用户进行页面展示的部分称之为前端,而将运行在服务器,为前端提供业务逻辑和数据准备的所有代码统称为后端。所谓前后端分离的开发,就是前后端工程师约定好数据交互接口,并行的进行开发和测试,后端只提供数据,不负责将数据渲染到页面上,前端通过HTTP请求获取数据并负责将数据渲染到页面上,这个工作是交给浏览器中的JavaScript代码来完成。
+在传统的Web应用开发中,大多数的程序员会将浏览器作为前后端的分界线。将浏览器中为用户进行页面展示的部分称之为前端,而将运行在服务器为前端提供业务逻辑和数据准备的所有代码统称为后端。所谓前后端分离的开发,就是前后端工程师约定好数据交互接口,并行的进行开发和测试,后端只提供数据,不负责将数据渲染到页面上,前端通过HTTP请求获取数据并负责将数据渲染到页面上,这个工作是交给浏览器中的JavaScript代码来完成。
使用前后端分离开发有诸多的好处,下面我们简要的说下这些好处:
@@ -30,9 +30,9 @@ def show_subjects(request):
上面的代码中,我们通过循环遍历查询学科得到的`QuerySet`对象,将每个学科的数据处理成一个字典,在将字典保存在名为`subjects`的列表容器中,最后利用`JsonResponse`完成对列表的序列化,向浏览器返回JSON格式的数据。由于`JsonResponse`序列化的是一个列表而不是字典,所以需要指定`safe`参数的值为`False`才能完成对`subjects`的序列化,否则会产生`TypeError`异常。
-可能大家已经发现了,自己写代码将一个对象转成字典是比较麻烦的,如果对象的属性很多而且某些属性又关联到一个比较复杂的对象时,情况会变得更加糟糕。为此我们可以使用一个名为bpmappers的三方库来简化将对象转成字典的操作,这个三方库本身也提供了对Django框架的支持。
+可能大家已经发现了,自己写代码将一个对象转成字典是比较麻烦的,如果对象的属性很多而且某些属性又关联到一个比较复杂的对象时,情况会变得更加糟糕。为此我们可以使用一个名为`bpmappers`的三方库来简化将对象转成字典的操作,这个三方库本身也提供了对Django框架的支持。
-安装三方库bpmappers。
+安装三方库`bpmappers`。
```Shell
pip install bpmappers
@@ -63,15 +63,24 @@ def show_subjects(request):
return JsonResponse(subjects, safe=False)
```
-配置URL映射,然后访问该接口,可以得到如下所示的JSON格式数据。
+配置URL映射。
+
+```Python
+urlpatterns = [
+
+ path('api/subjects/', show_subjects),
+
+]
+```
+
+然后访问该接口,可以得到如下所示的JSON格式数据。
```JSON
[
{
- "no": 101,
+ "no": 1,
"name": "Python全栈+人工智能",
"intro": "Python是一种计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。",
- "create_date": "2017-08-01",
"is_hot": true
},
// 此处省略下面的内容
@@ -92,7 +101,7 @@ class SubjectMapper(ModelMapper):
class Meta:
model = Subject
- exclude = ('create_date', 'is_hot')
+ exclude = ('is_hot', )
```
再次查看学科接口返回的JSON数据。
@@ -109,11 +118,11 @@ class SubjectMapper(ModelMapper):
]
```
-关于bpmappers详细的使用指南,请参考它的[官方文档]( ),这个官方文档是用日语书写的,可以使用浏览器的翻译功能将它翻译成你熟悉的语言即可。
+关于`bpmappers`详细的使用指南,请参考它的[官方文档]( ),这个官方文档是用日语书写的,可以使用浏览器的翻译功能将它翻译成你熟悉的语言即可。
### 使用Vue.js渲染页面
-关于Vue.js的知识,我们在第21天到第30天的内容中已经介绍过了,这里我们不再进行赘述。如果希望全面的了解和学习Vue.js,建议阅读它的[官方教程]( )或者在[YouTube]( )上搜索Vue.js的新手教程(Crash Course)进行学习。
+接下来我们通过前端框架Vue.js来实现页面的渲染。如果希望全面的了解和学习Vue.js,建议阅读它的[官方教程]( )或者在[YouTube]( )上搜索Vue.js的新手教程(Vue.js Crash Course)进行学习。
重新改写subjects.html页面,使用Vue.js来渲染页面。
@@ -122,36 +131,40 @@ class SubjectMapper(ModelMapper):
- 学科
+ 学科信息
+
- 所有学科
-
-
-
-
-
{{ subject.intro }}
+
-
+
@@ -161,4 +174,5 @@ class SubjectMapper(ModelMapper):
前后端分离的开发需要将前端页面作为静态资源进行部署,项目实际上线的时候,我们会对整个Web应用进行动静分离,静态资源通过Nginx或Apache服务器进行部署,生成动态内容的Python程序部署在uWSGI或者Gunicorn服务器上,对动态内容的请求由Nginx或Apache路由到uWSGI或Gunicorn服务器上。
-在开发阶段,我们通常会使用Django自带的测试服务器,如果要尝试前后端分离,可以先将静态页面放在之前创建的放静态资源的目录下,具体的做法可以参考[项目完整代码](
)。
\ No newline at end of file
+在开发阶段,我们通常会使用Django自带的测试服务器,如果要尝试前后端分离,可以先将静态页面放在之前创建的放静态资源的目录下,具体的做法可以参考[项目完整代码](https://gitee.com/jackfrued/django19062)。
+
diff --git a/Day41-55/49.RESTful架构和DRF入门.md b/Day41-55/49.RESTful架构和DRF入门.md
index 1af876f..1c2d7a7 100644
--- a/Day41-55/49.RESTful架构和DRF入门.md
+++ b/Day41-55/49.RESTful架构和DRF入门.md
@@ -1,4 +1,353 @@
## RESTful架构和DRF入门
+把软件(Software)、平台(Platform)、基础设施(Infrastructure)做成服务(Service)是很多IT企业都一直在做的事情,这就是大家经常听到的SasS(软件即服务)、PasS(平台即服务)和IasS(基础设置即服务)。实现面向服务的架构(SOA)有诸多的方式,包括RPC(远程过程调用)、Web Service、REST等,在技术层面上,SOA是一种**抽象的、松散耦合的粗粒度软件架构**;在业务层面上,SOA的核心概念是“**重用**”和“**互操作**”,它将系统资源整合成可操作的、标准的服务,使得这些资源能够被重新组合和应用。在实现SOA的诸多方案中,REST被认为是最适合互联网应用的架构,符合REST规范的架构也经常被称作RESTful架构。
+
+### REST概述
+
+REST这个词,是**Roy Thomas Fielding**在他2000年的博士论文中提出的,Roy是HTTP协议(1.0和1.1版)的主要设计者、Apache服务器软件主要作者、Apache基金会第一任主席。在他的博士论文中,Roy把他对互联网软件的架构原则定名为REST,即**RE**presentational **S**tate **T**ransfer的缩写,中文通常翻译为“**表现层状态转移**”或“**表述状态转移**”。
+
+这里的“表现层”其实指的是“资源”的“表现层”。所谓资源,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲或一种服务。我们可以用一个URI(统一资源定位符)指向资源,要获取到这个资源,访问它的URI即可,URI就是资源在互联网上的唯一标识。资源可以有多种外在表现形式。我们把资源具体呈现出来的形式,叫做它的“表现层”。比如,文本可以用`text/plain`格式表现,也可以用`text/html`格式、`text/xml`格式、`application/json`格式表现,甚至可以采用二进制格式;图片可以用`image/jpeg`格式表现,也可以用`image/png`格式表现。URI只代表资源的实体,不代表它的表现形式。严格地说,有些网址最后的`.html`后缀名是不必要的,因为这个后缀名表示格式,属于“表现层”范畴,而URI应该只代表“资源”的位置,它的具体表现形式,应该在HTTP请求的头信息中用`Accept`和`Content-Type`字段指定,这两个字段才是对“表现层”的描述。
+
+访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。Web应用通常使用HTTP作为其通信协议,客户端想要操作服务器,必须通过HTTP请求,让服务器端发生“状态转移”,而这种转移是建立在表现层之上的,所以就是“表现层状态转移”。客户端通过HTTP的动词GET、POST、PUT(或PATCH)、DELETE,分别对应对资源的四种基本操作,其中GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT(或PATCH)用来更新资源,DELETE用来删除资源。
+
+简单的说RESTful架构就是:“每一个URI代表一种资源,客户端通过四个HTTP动词,对服务器端资源进行操作,实现资源的表现层状态转移”。
+
+我们在设计Web应用时,如果需要向客户端提供资源,就可以使用REST风格的URI,这是实现RESTful架构的第一步。当然,真正的RESTful架构并不只是URI符合REST风格,更为重要的是“无状态”和“幂等性”两个词,我们在后面的课程中会为大家阐述这两点。下面的例子给出了一些符合REST风格的URI,供大家在设计URI时参考。
+
+| 请求方法(HTTP动词) | URI | 解释 |
+| -------------------- | -------------------------- | -------------------------------------------- |
+| **GET** | `/students/` | 获取所有学生 |
+| **POST** | `/students/` | 新建一个学生 |
+| **GET** | `/students/ID/` | 获取指定ID的学生信息 |
+| **PUT** | `/students/ID/` | 更新指定ID的学生信息(提供该学生的全部信息) |
+| **PATCH** | `/students/ID/` | 更新指定ID的学生信息(提供该学生的部分信息) |
+| **DELETE** | `/students/ID/` | 删除指定ID的学生信息 |
+| **GET** | `/students/ID/friends/` | 列出指定ID的学生的所有朋友 |
+| **DELETE** | `/students/ID/friends/ID/` | 删除指定ID的学生的指定ID的朋友 |
+
+### DRF使用入门
+
+在Django项目中,如果要实现REST架构,即将网站的资源发布成REST风格的API接口,可以使用著名的三方库`djangorestframework` ,我们通常将其简称为DRF。
+
+#### 安装和配置DRF
+
+安装DRF。
+
+```Shell
+pip install djangorestframework
+```
+
+配置DRF。
+
+```Python
+INSTALLED_APPS = [
+
+ 'rest_framework',
+
+]
+
+# 下面的配置根据项目需要进行设置
+REST_FRAMEWORK = {
+ # 配置默认页面大小
+ # 'PAGE_SIZE': 10,
+ # 配置默认的分页类
+ # 'DEFAULT_PAGINATION_CLASS': '...',
+ # 配置异常处理器
+ # 'EXCEPTION_HANDLER': '...',
+ # 配置默认解析器
+ # 'DEFAULT_PARSER_CLASSES': (
+ # 'rest_framework.parsers.JSONParser',
+ # 'rest_framework.parsers.FormParser',
+ # 'rest_framework.parsers.MultiPartParser',
+ # ),
+ # 配置默认限流类
+ # 'DEFAULT_THROTTLE_CLASSES': (
+ # '...'
+ # ),
+ # 配置默认授权类
+ # 'DEFAULT_PERMISSION_CLASSES': (
+ # '...',
+ # ),
+ # 配置默认认证类
+ # 'DEFAULT_AUTHENTICATION_CLASSES': (
+ # '...',
+ # ),
+}
+```
+
+#### 编写序列化器
+
+前后端分离的开发需要后端为前端、移动端提供API数据接口,而API接口通常情况下都是返回JSON格式的数据,这就需要对模型对象进行序列化处理。DRF中封装了`Serializer`类和`ModelSerializer`类用于实现序列化操作,通过继承`Serializer`类或`ModelSerializer`类,我们可以自定义序列化器,用于将对象处理成字典,代码如下所示。
+
+```Python
+from rest_framework import serializers
+class SubjectSerializer(serializers.ModelSerializer):
+
+ class Meta:
+ model = Subject
+ fields = '__all__'
+```
+
+上面的代码直接继承了`ModelSerializer`,通过`Meta`类的`model`属性指定要序列化的模型以及`fields`属性指定需要序列化的模型字段,稍后我们就可以在视图函数中使用该类来实现对`Subject`模型的序列化。
+
+#### 编写视图函数
+
+DRF框架支持两种实现数据接口的方式,一种是FBV(基于函数的视图),另一种是CBV(基于类的视图)。我们先看看FBV的方式如何实现数据接口,代码如下所示。
+
+```Python
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+
+
+@api_view(('GET', ))
+def show_subjects(request: HttpRequest) -> HttpResponse:
+ subjects = Subject.objects.all().order_by('no')
+ # 创建序列化器对象并指定要序列化的模型
+ serializer = SubjectSerializer(subjects, many=True)
+ # 通过序列化器的data属性获得模型对应的字典并通过创建Response对象返回JSON格式的数据
+ return Response(serializer.data)
+```
+
+对比上一个章节的使用`bpmapper`实现模型序列化的代码,使用DRF的代码更加简单明了,而且DRF本身自带了一套页面,可以方便我们查看我们使用DRF定制的数据接口,如下图所示。
+
+
+
+直接使用上一节写好的页面,就可以通过Vue.js把上面接口提供的学科数据渲染并展示出来,此处不再进行赘述。
+
+#### 实现老师信息数据接口
+
+编写序列化器。
+
+```Python
+class SubjectSimpleSerializer(serializers.ModelSerializer):
+
+ class Meta:
+ model = Subject
+ fields = ('no', 'name')
+
+
+class TeacherSerializer(serializers.ModelSerializer):
+
+ class Meta:
+ model = Teacher
+ exclude = ('subject', )
+```
+
+编写视图函数。
+
+```Python
+@api_view(('GET', ))
+def show_teachers(request: HttpRequest) -> HttpResponse:
+ try:
+ sno = int(request.GET.get('sno'))
+ subject = Subject.objects.only('name').get(no=sno)
+ teachers = Teacher.objects.filter(subject=subject).defer('subject').order_by('no')
+ subject_seri = SubjectSimpleSerializer(subject)
+ teacher_seri = TeacherSerializer(teachers, many=True)
+ return Response({'subject': subject_seri.data, 'teachers': teacher_seri.data})
+ except (TypeError, ValueError, Subject.DoesNotExist):
+ return Response(status=404)
+```
+
+配置URL映射。
+
+```Python
+urlpatterns = [
+
+ path('api/teachers/', show_teachers),
+
+]
+```
+
+通过Vue.js渲染页面。
+
+```HTML
+
+
+
+
+
老师信息
+
+
+
+
+
{{ subject.name }}学科的老师信息
+
+
暂无该学科老师信息
+
+
+
+
+
+
+ 姓名:{{ teacher.name }}
+ 性别:{{ teacher.sex | maleOrFemale }}
+ 出生日期:{{ teacher.birth }}
+
+
{{ teacher.intro }}
+
+
+
+
返回首页
+
+
+
+
+
+```
+
+### 前后端分离下的用户登录
+
+之前我们提到过, HTTP是无状态的,一次请求结束连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的。但是对于一个Web应用而言,它是需要有状态管理的,这样才能让服务器知道HTTP请求来自哪个用户,从而判断是否允许该用户请求以及为用户提供更好的服务,这个过程就是常说的**会话管理**。
+
+之前我们做会话管理(用户跟踪)的方法是:用户登录成功后,在服务器端通过一个session对象保存用户相关数据,然后把session对象的ID写入浏览器的cookie中;下一次请求时,HTTP请求头中携带cookie的数据,服务器从HTTP请求头读取cookie中的sessionid,根据这个标识符找到对应的session对象,这样就能够获取到之前保存在session中的用户数据。我们刚才说过,REST架构是最适合互联网应用的架构,它强调了HTTP的无状态性,这样才能保证应用的水平扩展能力(当并发访问量增加时,可以通过增加新的服务器节点来为系统扩容)。显然,基于session实现用户跟踪的方式需要服务器保存session对象,在做水平扩展增加新的服务器节点时,需要复制和同步session对象,这显然是非常麻烦的。解决这个问题有两种方案,一种是架设缓存服务器(如Redis),让多个服务器节点共享缓存服务并将session对象直接置于缓存服务器中;另一种方式放弃基于session的用户跟踪,使用**基于token的用户跟踪**。
+
+基于token的用户跟踪是在用户登录成功后,为用户生成身份标识并保存在浏览器本地存储(localStorage、sessionStorage、cookie等)中,这样的话服务器不需要保存用户状态,从而可以很容易的做到水平扩展。基于token的用户跟踪具体流程如下:
+
+1. 用户登录时,如果登录成功就按照某种方式为用户生成一个令牌(token),该令牌中通常包含了用户标识、过期时间等信息而且需要加密并生成指纹(避免伪造或篡改令牌),服务器将令牌返回给前端;
+2. 前端获取到服务器返回的token,保存在浏览器本地存储中(可以保存在`localStorage`或`sessionStorage`中,对于使用Vue.js的前端项目来说,还可以通过Vuex进行状态管理);
+3. 对于使用了前端路由的项目来说,前端每次路由跳转,可以先判断`localStroage`中有无token,如果没有则跳转到登录页;
+4. 每次请求后端数据接口,在HTTP请求头里携带token;后端接口判断请求头有无token,如果没有token以及token是无效的或过期的,服务器统一返回401;
+5. 如果前端收到HTTP响应状态码401,则重定向到登录页面。
+
+通过上面的描述,相信大家已经发现了,基于token的用户跟踪最为关键是在用户登录成功时,要为用户生成一个token作为用户的身份标识。生成token的方法很多,其中一种比较成熟的解决方案是使用JSON Web Token。
+
+#### JWT概述
+
+JSON Web Token通常简称为JWT,它是一种开放标准(RFC 7519)。随着RESTful架构的流行,越来越多的项目使用JWT作为用户身份认证的方式。JWT相当于是三个JSON对象经过编码后,用`.`分隔并组合到一起,这三个JSON对象分别是头部(header)、载荷(payload)和签名(signature),如下图所示。
+
+
+
+1. 头部
+
+ ```JSON
+ {
+ "alg": "HS256",
+ "typ": "JWT"
+ }
+ ```
+
+ 其中,`alg`属性表示签名的算法,默认是HMAC SHA256(简写成`HS256`);`typ`属性表示这个令牌的类型,JWT中都统一书写为`JWT`。
+
+2. 载荷
+
+ 载荷部分用来存放实际需要传递的数据。JWT官方文档中规定了7个可选的字段:
+
+ - iss :签发人
+ - exp:过期时间
+ - sub:主题
+ - aud:受众
+ - nbf:生效时间
+ - iat:签发时间
+ - jti:编号
+
+ 除了官方定义的字典,我们可以根据应用的需要添加自定义的字段,如下所示。
+
+ ```JSON
+ {
+ "sub": "1234567890",
+ "nickname": "jackfrued",
+ "role": "admin"
+ }
+ ```
+
+3. 签名
+
+ 签名部分是对前面两部分生成一个指纹,防止数据伪造和篡改。实现签名首先需要指定一个密钥。这个密钥只有服务器才知道,不能泄露给用户。然后,使用头部指定的签名算法(默认是`HS256`),按照下面的公式产生签名。
+
+ ```Python
+ HS256(base64Encode(header) + '.' + base64Encode(payload), secret)
+ ```
+
+ 算出签名以后,把头部、载荷、签名三个部分拼接成一个字符串,每个部分用`.`进行分隔,这样一个JWT就生成好了。
+
+#### JWT的优缺点
+
+使用JWT的优点非常明显,包括:
+
+1. 更容易实现水平扩展,因为令牌保存在浏览器中,服务器不需要做状态管理。
+2. 更容易防范CSRF攻击,因为在请求头中添加`localStorage`或`sessionStorage`中的token必须靠JavaScript代码完成,而不是自动添加到请求头中的。
+3. 可以防伪造和篡改,因为JWT有签名,伪造和篡改的令牌无法通过签名验证,会被认定是无效的令牌。
+
+当然,任何技术不可能只有优点没有缺点,JWT也有诸多缺点,大家需要在使用的时候引起注意,具体包括:
+
+1. 可能会遭受到XSS攻击(跨站脚本攻击),通过注入恶意脚本执行JavaScript代码获取到用户令牌。
+2. 在令牌过期之前,无法作废已经颁发的令牌,要解决这个问题,还需要额外的中间层和代码来辅助。
+3. JWT是用户的身份令牌,一旦泄露,任何人都可以获得该用户的所有权限。为了降低令牌被盗用后产生的风险,JWT的有效期应该设置得比较短。对于一些比较重要的权限,使用时应通过其他方式再次对用户进行认证,例如短信验证码等。
+
+#### 使用PyJWT
+
+在Python代码中,可以使用三方库`PyJWT`生成和验证JWT,下面是安装`PyJWT`的命令。
+
+```Bash
+pip install pyjwt
+```
+
+生成令牌。
+
+```Python
+payload = {
+ 'exp': datetime.datetime.utcnow() + datetime.timedelta(days=1),
+ 'userid': 10001
+}
+token = jwt.encode(payload, settings.SECRET_KEY).decode()
+```
+
+验证令牌。
+
+```Python
+try:
+ token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTQ4NzIzOTEsInVzZXJpZCI6MTAwMDF9.FM-bNxemWLqQQBIsRVvc4gq71y42I9m2zt5nlFxNHUo'
+ payload = jwt.decode(token, settings.SECRET_KEY)
+except InvalidTokenError:
+ raise AuthenticationFailed('无效的令牌或令牌已经过期')
+```
+
+如果不清楚JWT具体的使用方式,可以先看看第55天的内容,里面提供了完整的投票项目代码的地址。
\ No newline at end of file
diff --git a/Day41-55/50.RESTful架构和DRF进阶.md b/Day41-55/50.RESTful架构和DRF进阶.md
index 1325323..28083cc 100644
--- a/Day41-55/50.RESTful架构和DRF进阶.md
+++ b/Day41-55/50.RESTful架构和DRF进阶.md
@@ -1,4 +1,129 @@
## RESTful架构和DRF进阶
+除了上一节讲到的方法,使用DRF创建REST风格的数据接口也可以通过CBV(基于类的视图)的方式。使用CBV创建数据接口的特点是代码简单,开发效率高,但是没有FBV(基于函数的视图)灵活,因为使用FBV的方式,数据接口对应的视图函数执行什么样的代码以及返回什么的数据是高度可定制的。下面我们以定制学科的数据接口为例,讲解通过CBV方式定制数据接口的具体做法。
+
+### 使用CBV
+
+#### 继承APIView的子类
+
+修改之前项目中的`polls/views.py`,去掉`show_subjects`视图函数,添加一个名为`SubjectView`的类,该类继承自`ListAPIView`,`ListAPIView`能接收GET请求,它封装了获取数据列表并返回JSON数据的`get`方法。`ListAPIView`是`APIView` 的子类,`APIView`还有很多的子类,例如`CreateAPIView`可以支持POST请求,`UpdateAPIView`可以支持PUT和PATCH请求,`DestoryAPIView`可以支持DELETE请求。`SubjectView` 的代码如下所示。
+
+```Python
+from rest_framework.generics import ListAPIView
+class SubjectView(ListAPIView):
+ # 通过queryset指定如何获取学科数据
+ queryset = Subject.objects.all()
+ # 通过serializer_class指定如何序列化学科数据
+ serializer_class = SubjectSerializer
+```
+
+刚才说过,由于`SubjectView`的父类`ListAPIView`已经实现了`get`方法来处理获取学科列表的GET请求,所以我们只需要声明如何获取学科数据以及如何序列化学科数据,前者用`queryset`属性指定,后者用`serializer_class`属性指定。要使用上面的`SubjectView`,需要修改`urls.py`文件,如下所示。
+
+```Python
+urlpatterns = [
+ path('api/subjects/', SubjectView.as_view()),
+]
+```
+
+很显然,上面的做法较之之前讲到的FBV要简单很多。
+
+#### 继承ModelViewSet
+
+如果学科对应的数据接口需要支持GET、POST、PUT、PATCH、DELETE请求来支持对学科资源的获取、新增、更新、删除操作,更为简单的做法是继承`ModelViewSet`来编写学科视图类。再次修改`polls/views.py`文件,去掉`SubjectView`类,添加一个名为`SubjectViewSet`的类,代码如下所示。
+
+```Python
+from rest_framework.viewsets import ModelViewSet
+
+
+class SubjectViewSet(ModelViewSet):
+ queryset = Subject.objects.all()
+ serializer_class = SubjectSerializer
+```
+
+通过查看`ModelViewSet`类的源代码可以发现,该类共有6个父类,其中前5个父类分别实现对POST(新增学科)、GET(获取指定学科)、PUT/PATCH(更新学科)、DELETE(删除学科)和GET(获取学科列表)操作的支持,对应的方法分别是`create`、`retrieve`、`update`、`destroy`和`list`。由于`ModelViewSet`的父类中已经实现了这些方法,所以我们几乎没有编写任何代码就完成了学科数据全套接口的开发,我们要做的仅仅是指出如何获取到数据(通过`queryset`属性指定)以及如何序列化数据(通过`serializer_class`属性指定),这一点跟上面继承`APIView`的子类做法是一致的。
+
+```Python
+class ModelViewSet(mixins.CreateModelMixin,
+ mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.DestroyModelMixin,
+ mixins.ListModelMixin,
+ GenericViewSet):
+ """
+ A viewset that provides default `create()`, `retrieve()`, `update()`,
+ `partial_update()`, `destroy()` and `list()` actions.
+ """
+ pass
+```
+
+要使用上面的`SubjectViewSet`,需要在`urls.py`文件中进行URL映射。由于`ModelViewSet`相当于是多个视图函数的汇总,所以不同于之前映射URL的方式,我们需要先创建一个路由器并通过它注册`SubjectViewSet`,然后将注册成功后生成的URL一并添加到`urlspattern`列表中,代码如下所示。
+
+```Python
+from rest_framework.routers import DefaultRouter
+
+router = DefaultRouter()
+router.register('api/subjects', SubjectViewSet)
+urlpatterns += router.urls
+```
+
+除了`ModelViewSet`类外,DRF还提供了一个名为`ReadOnlyModelViewSet` 的类,从名字上就可以看出,该类是只读视图的集合,也就意味着,继承该类定制的数据接口只能支持GET请求,也就是获取单个资源和资源列表的请求。
+
+### 数据分页
+
+在使用GET请求获取资源列表时,我们通常不会一次性的加载所有的数据,除非数据量真的很小。大多数获取资源列表的操作都支持数据分页展示,也就说我们可以通过指定页码(或类似于页码的标识)和页面大小(一次加载多少条数据)来获取不同的数据。我们可以通过对`QuerySet`对象的切片操作来实现分页,也可以利用Django框架封装的`Paginator`和`Page`对象来实现分页。使用DRF时,可以在Django配置文件中修改`REST_FRAMEWORK`并配置默认的分页类和页面大小来实现分页,如下所示。
+
+```Python
+REST_FRAMEWORK = {
+ 'PAGE_SIZE': 10,
+ 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination'
+}
+```
+
+除了上面配置的`PageNumberPagination`分页器之外,DRF还提供了`LimitOffsetPagination`和`CursorPagination`分页器,值得一提的是`CursorPagination`,它可以避免使用页码分页时暴露网站的数据体量,有兴趣的读者可以自行了解。如果不希望使用配置文件中默认的分页设定,可以在视图类中添加一个`pagination_class`属性来重新指定分页器,通常可以将该属性指定为自定义的分页器,如下所示。
+
+```Python
+from rest_framework.pagination import PageNumberPagination
+
+
+class CustomizedPagination(PageNumberPagination):
+ # 默认页面大小
+ page_size = 5
+ # 页面大小对应的查询参数
+ page_size_query_param = 'size'
+ # 页面大小的最大值
+ max_page_size = 50
+```
+
+```Python
+class SubjectView(ListAPIView):
+ # 指定如何获取数据
+ queryset = Subject.objects.all()
+ # 指定如何序列化数据
+ serializer_class = SubjectSerializer
+ # 指定如何分页
+ pagination_class = CustomizedPagination
+```
+
+如果不希望数据分页,可以将`pagination_class`属性设置为`None`来取消默认的分页器。
+
+### 数据筛选
+
+如果希望使用CBV定制获取老师信息的数据接口,也可以通过继承`ListAPIView`来实现。但是因为要通过指定的学科来获取对应的老师信息,因此需要对老师数据进行筛选而不是直接获取所有老师的数据。如果想从请求中获取学科编号并通过学科编号对老师进行筛选,可以通过重写`get_queryset`方法来做到,代码如下所示。
+
+```Python
+class TeacherView(ListAPIView):
+ serializer_class = TeacherSerializer
+
+ def get_queryset(self):
+ queryset = Teacher.objects.defer('subject')
+ try:
+ sno = self.request.GET.get('sno', '')
+ queryset = queryset.filter(subject__no=sno)
+ return queryset
+ except ValueError:
+ raise Http404('No teachers found.')
+```
+
+除了上述方式之外,还可以使用三方库`django-filter`来配合DRF实现对数据的筛选,使用`django-filter`后,可以通过为视图类配置`filter-backends`属性并指定使用`DjangoFilterBackend`来支持数据筛选。在完成上述配置后,可以使用`filter_fields` 属性或`filterset_class`属性来指定如何筛选数据,有兴趣的读者可以自行研究。
\ No newline at end of file
diff --git a/Day41-55/51.使用缓存.md b/Day41-55/51.使用缓存.md
index ee55bf6..7e39e08 100644
--- a/Day41-55/51.使用缓存.md
+++ b/Day41-55/51.使用缓存.md
@@ -1,4 +1,147 @@
## 使用缓存
+通常情况下,Web应用的性能瓶颈都会出现在关系型数据库上,当并发访问量较大时,如果所有的请求都需要通过关系型数据库完成数据持久化操作,那么数据库一定会不堪重负。优化Web应用性能最为重要的一点就是使用缓存,把那些数据体量不大但访问频率非常高的数据提前加载到缓存服务器中,这又是典型的空间换时间的方法。通常缓存服务器都是直接将数据置于内存中而且使用了非常高效的数据存取策略(哈希存储、键值对方式等),在读写性能上远远优于关系型数据库的,因此我们可以让Web应用接入缓存服务器来优化其性能,其中一个非常好的选择就是使用Redis。
+
+Web应用的缓存架构大致如下图所示。
+
+
+
+### Django项目接入Redis
+
+在此前的课程中,我们介绍过Redis的安装和使用,此处不再进行赘述。如果需要在Django项目中接入Redis,可以使用三方库`django-redis`,这个三方库又依赖了一个名为`redis` 的三方库,它封装了对Redis的各种操作。
+
+安装`django-redis`。
+
+```Bash
+pip install django-redis
+```
+
+修改Django配置文件中关于缓存的配置。
+
+```Python
+CACHES = {
+ 'default': {
+ # 指定通过django-redis接入Redis服务
+ 'BACKEND': 'django_redis.cache.RedisCache',
+ # Redis服务器的URL
+ 'LOCATION': ['redis://1.2.3.4:6379/0', ],
+ # Redis中键的前缀(解决命名冲突)
+ 'KEY_PREFIX': 'vote',
+ # 其他的配置选项
+ 'OPTIONS': {
+ 'CLIENT_CLASS': 'django_redis.client.DefaultClient',
+ # 连接池(预置若干备用的Redis连接)参数
+ 'CONNECTION_POOL_KWARGS': {
+ # 最大连接数
+ 'max_connections': 512,
+ },
+ # 连接Redis的用户口令
+ 'PASSWORD': 'foobared',
+ }
+ },
+}
+```
+
+至此,我们的Django项目已经可以接入Redis,接下来我们修改项目代码,用Redis为之写的获取学科数据的接口提供缓存服务。
+
+### 为视图提供缓存服务
+
+#### 声明式缓存
+
+所谓声明式缓存是指不修改原来的代码,通过Python中的装饰器(代理)为原有的代码增加缓存功能。对于FBV,代码如下所示。
+
+```Python
+from django.views.decorators.cache import cache_page
+@api_view(('GET', ))
+@cache_page(timeout=86400, cache='default')
+def show_subjects(request):
+ """获取学科数据"""
+ queryset = Subject.objects.all()
+ data = SubjectSerializer(queryset, many=True).data
+ return Response({'code': 20000, 'subjects': data})
+```
+
+上面的代码通过Django封装的`cache_page`装饰器缓存了视图函数的返回值(响应对象),`cache_page`的本意是缓存视图函数渲染的页面,对于返回JSON数据的视图函数,相当于是缓存了JSON数据。在使用`cache_page`装饰器时,可以传入`timeout`参数来指定缓存过期时间,还可以使用`cache`参数来指定需要使用哪一组缓存服务来缓存数据。Django项目允许在配置文件中配置多组缓存服务,上面的`cache='default'`指定了使用默认的缓存服务(因为之前的配置文件中我们也只配置了名为`default`的缓存服务)。视图函数的返回值会被序列化成字节串放到Redis中(Redis中的str类型可以接收字节串),缓存数据的序列化和反序列化也不需要我们自己处理,因为`cache_page`装饰器会调用`django-redis`库中的`RedisCache`来对接Redis,该类使用了`DefaultClient`来连接Redis并使用了[pickle序列化](https://python3-cookbook.readthedocs.io/zh_CN/latest/c05/p21_serializing_python_objects.html),`django_redis.serializers.pickle.PickleSerializer`是默认的序列化类。
+
+如果缓存中没有学科的数据,那么通过接口访问学科数据时,我们的视图函数会通过执行`Subject.objects.all()`向数据库发出SQL语句来获得数据,视图函数的返回值会被缓存,因此下次请求该视图函数如果缓存没有过期,可以直接从缓存中获取视图函数的返回值,无需再次查询数据库。如果想了解缓存的使用情况,可以配置数据库日志或者使用Django-Debug-Toolbar来查看,第一次访问学科数据接口时会看到查询学科数据的SQL语句,再次获取学科数据时,不会再向数据库发出SQL语句,因为可以直接从缓存中获取数据。
+
+对于CBV,可以利用Django中名为`method_decorator`的装饰器将`cache_page`这个装饰函数的装饰器放到类中的方法上,效果跟上面的代码是一样的。需要提醒大家注意的是,`cache_page`装饰器不能直接放在类上,因为它是装饰函数的装饰器,所以Django框架才提供了`method_decorator`来解决这个问题,很显然,`method_decorator`是一个装饰类的装饰器。
+
+```Python
+from django.utils.decorators import method_decorator
+from django.views.decorators.cache import cache_page
+
+
+@method_decorator(decorator=cache_page(timeout=86400, cache='default'), name='get')
+class SubjectView(ListAPIView):
+ """获取学科数据的视图类"""
+ queryset = Subject.objects.all()
+ serializer_class = SubjectSerializer
+```
+
+#### 编程式缓存
+
+所谓编程式缓存是指通过自己编写的代码来使用缓存服务,这种方式虽然代码量会稍微大一些,但是相较于声明式缓存,它对缓存的操作和使用更加灵活,在实际开发中使用得更多。下面的代码去掉了之前使用的`cache_page`装饰器,通过`django-redis`提供的`get_redis_connection`函数直接获取Redis连接来操作Redis。
+
+```Python
+def show_subjects(request):
+ """获取学科数据"""
+ redis_cli = get_redis_connection()
+ # 先尝试从缓存中获取学科数据
+ data = redis_cli.get('vote:polls:subjects')
+ if data:
+ # 如果获取到学科数据就进行反序列化操作
+ data = json.loads(data)
+ else:
+ # 如果缓存中没有获取到学科数据就查询数据库
+ queryset = Subject.objects.all()
+ data = SubjectSerializer(queryset, many=True).data
+ # 将查到的学科数据序列化后放到缓存中
+ redis_cli.set('vote:polls:subjects', json.dumps(data), ex=86400)
+ return Response({'code': 20000, 'subjects': data})
+```
+
+需要说明的是,Django框架提供了`cache`和`caches`两个现成的变量来支持缓存操作,前者访问的是默认的缓存(名为`default`的缓存),后者可以通过索引运算获取指定的缓存服务(例如:`caches['default']`)。向`cache`对象发送`get`和`set`消息就可以实现对缓存的读和写操作,但是这种方式能做的操作有限,不如上面代码中使用的方式灵活。还有一个值得注意的地方,由于可以通过`get_redis_connection`函数获得的Redis连接对象向Redis发起各种操作,包括`FLUSHDB`、`SHUTDOWN`等危险的操作,所以在实际商业项目开发中,一般都会对`django-redis`再做一次封装,例如封装一个工具类,其中只提供了项目需要用到的缓存操作的方法,从而避免了直接使用`get_redis_connection`的潜在风险。当然,自己封装对缓存的操作还可以使用“Read Through”和“Write Through”的方式实现对缓存的更新,这个在下面会介绍到。
+
+### 缓存相关问题
+
+#### 缓存数据的更新
+
+在使用缓存时,一个必须搞清楚的问题就是,当数据改变时,如何更新缓存中的数据。通常更新缓存有如下几种套路,分别是:
+
+1. Cache Aside Pattern
+2. Read/Write Through Pattern
+3. Write Behind Caching Pattern
+
+第1种方式的具体做法就是,当数据更新时,先更新数据库,再删除缓存。注意,不能够使用先更新数据库再更新缓存的方式,也不能够使用先删除缓存再更新数据库的方式,大家可以自己想一想为什么(考虑一下有并发的读操作和写操作的场景)。当然,先更新数据库再删除缓存的做法在理论上也存在风险,但是发生问题的概率是极低的,所以不少的项目都使用了这种方式。
+
+第1种方式相当于编写业务代码的开发者要自己负责对两套存储系统(缓存和关系型数据库)的操作,代码写起来非常的繁琐。第2种方式的主旨是将后端的存储系统变成一套代码,对缓存的维护封装在这套代码中。其中,Read Through指在查询操作中更新缓存,也就是说,当缓存失效的时候,由缓存服务自己负责对数据的加载,从而对应用方是透明的;而Write Through是指在更新数据时,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由缓存服务自己更新数据库(同步更新)。刚才我们说过,如果自己对项目中的Redis操作再做一次封装,就可以实现“Read Through”和“Write Through”模式,这样做虽然会增加工作量,但无疑是一件“一劳永逸”且“功在千秋”的事情。
+
+第3种方式是在更新数据的时候,只更新缓存,不更新数据库,而缓存服务这边会**异步的批量更新**数据库。这种做法会大幅度提升性能,但代价是牺牲数据的**强一致性**。第3种方式的实现逻辑比较复杂,因为他需要追踪有哪数据是被更新了的,然后再批量的刷新到持久层上。
+
+#### 缓存穿透
+
+缓存是为了缓解数据库压力而添加的一个中间层,如果恶意的访问者频繁的访问缓存中没有的数据,那么缓存就失去了存在的意义,瞬间所有请求的压力都落在了数据库上,这样会导致数据库承载着巨大的压力甚至连接异常,类似于分布式拒绝服务攻击(DDoS)的做法。解决缓存穿透的一个办法是约定如果查询返回为空值,把这个空值也缓存起来,但是需要为这个空值的缓存设置一个较短的超时时间,毕竟缓存这样的值就是对缓存空间的浪费。另一个解决缓存穿透的办法是使用布隆过滤器,具体的做法大家可以自行了解。
+
+#### 缓存击穿
+
+在实际的项目中,可能存在某个缓存的key某个时间点过期,但恰好在这个时间点对有对该key的大量的并发请求过来,这些请求没有从缓存中找到key对应的数据,就会直接从数据库中获取数据并写回到缓存,这个时候大并发的请求可能会瞬间把数据库压垮,这种现象称为缓存击穿。比较常见的解决缓存击穿的办法是使用互斥锁,简单的说就是在缓存失效的时候,不是立即去数据库加载数据,而是先设置互斥锁(例如:Redis中的setnx),只有设置互斥锁的操作成功的请求,才能执行查询从数据库中加载数据并写入缓存,其他设置互斥锁失败的请求,可以先执行一个短暂的休眠,然后尝试重新从缓存中获取数据,如果缓存还没有数据,则重复刚才的设置互斥锁的操作,大致的参考代码如下所示。
+
+```Python
+data = redis_cli.get(key)
+while not data:
+ if redis_cli.setnx('mutex', 'x'):
+ redis.expire('mutex', timeout)
+ data = db.query(...)
+ redis.set(key, data)
+ redis.delete('mutex')
+ else:
+ time.sleep(0.1)
+ data = redis_cli.get(key)
+```
+
+#### 缓存雪崩
+
+缓存雪崩是指在将数据放入缓存时采用了相同的过期时间,这样就导致缓存在某一时刻同时失效,请求全部转发到数据库,导致数据库瞬时压力过大而崩溃。解决缓存雪崩问题的方法也比较简单,可以在既定的缓存过期时间上加一个随机时间,这样可以从一定程度上避免不同的key在同一时间集体失效。还有一种办法就是使用多级缓存,每一级缓存的过期时间都不一样,这样的话即便某个级别的缓存集体失效,但是其他级别的缓存还能够提供数据,避免所有的请求都落到数据库上。
\ No newline at end of file
diff --git a/Day41-55/52.接入三方平台.md b/Day41-55/52.接入三方平台.md
new file mode 100644
index 0000000..b6094cf
--- /dev/null
+++ b/Day41-55/52.接入三方平台.md
@@ -0,0 +1,201 @@
+## 接入三方平台
+
+在Web应用的开发过程中,有一些任务并不是我们自己能够完成的。例如,我们的Web项目中需要做个人或企业的实名认证,很显然我们并没有能力判断用户提供的认证信息的真实性,这个时候我们就要借助三方平台提供的服务来完成该项操作。再比如说,我们的项目中需要提供在线支付功能,这类业务通常也是借助支付网关来完成而不是自己去实现,我们只需要接入像微信、支付宝、银联这样的三方平台即可。
+
+在项目中接入三方平台基本上就两种方式:API接入和SDK接入。
+
+1. API接入指的是通过访问三方提供的URL来完成操作或获取数据。国内有很多这样的平台提供了大量常用的服务,例如[聚合数据](https://www.juhe.cn/)上提供了生活服务类、金融科技类、交通地理类、充值缴费类等各种类型的API。我们可以通过Python程序发起网络请求,通过访问URL获取数据,这些API接口跟我们项目中提供的数据接口是一样的,只不过我们项目中的API是供自己使用的,而这类三方平台提供的API是开放的。当然开放并不代表免费,大多数能够提供有商业价值的数据的API都是需要付费才能使用的。
+2. SDK接入指的是通过安装三方库并使用三方库封装的类、函数来使用三方平台提供的服务的方式。例如我们刚才说到的接入支付宝,就需要先安装支付宝的SDK,然后通过支付宝封装的类和方法完成对支付服务的调用。
+
+下面我们通过具体的例子来讲解如何接入三方平台。
+
+### 接入短信网关
+
+一个Web项目有很多地方都可以用到短信服务,例如:手机验证码登录、重要消息提醒、产品营销短信等。要实现发送短信的功能,可以通过接入短信网关来实现,国内比较有名的短信网关包括:云片短信、网易云信、螺丝帽、SendCloud等,这些短信网关一般都提供了免费试用功能。下面我们以[螺丝帽](https://luosimao.com/)平台为例,讲解如何在项目中接入短信网关,其他平台操作基本类似。
+
+1. 注册账号,新用户可以免费试用。
+
+2. 登录到管理后台,进入短信版块。
+
+3. 点击“触发发送”可以找到自己专属的API Key(身份标识)。
+
+ 
+
+4. 点击“签名管理”可以添加短信签名,短信都必须携带签名,免费试用的短信要在短信中添加“【铁壳测试】”这个签名,否则短信无法发送。
+
+ 
+
+5. 点击“IP白名单”将运行Django项目的服务器地址(公网IP地址,本地运行可以打开[xxx]()网站查看自己本机的公网IP地址)填写到白名单中,否则短信无法发送。
+
+ 
+
+6. 如果没有剩余的短信条数,可以到“充值”页面选择“短信服务”进行充值。
+
+ 
+
+接下来,我们可以通过调用螺丝帽短信网关实现发送短信验证码的功能,代码如下所示。
+
+```Python
+def send_mobile_code(tel, code):
+ """发送短信验证码"""
+ resp = requests.post(
+ url='http://sms-api.luosimao.com/v1/send.json',
+ auth=('api', 'key-自己的APIKey'),
+ data={
+ 'mobile': tel,
+ 'message': f'您的短信验证码是{code},打死也不能告诉别人哟。【Python小课】'
+ },
+ verify=False
+ )
+ return resp.json()
+```
+
+运行上面的代码需要先安装`requests`三方库,这个三方库封装了HTTP网络请求的相关功能,使用起来非常的简单,我们在之前的内容中也讲到过这个三方库。`send_mobile_code`函数有两个参数,第一个参数是手机号,第二个参数是短信验证码的内容,第5行代码需要提供自己的API Key,就是上面第2步中查看到的自己的API Key。请求螺丝帽的短信网关会返回JSON格式的数据,对于上面的代码如果返回`{'err': 0, 'msg': 'ok'}`,则表示短信发送成功,如果`err`字段的值不为`0`而是其他值,则表示短信发送失败,可以在螺丝帽官方的[开发文档](https://luosimao.com/docs/api/)页面上查看到不同的数值代表的含义,例如:`-20`表示余额不足,`-32`表示缺少短信签名。
+
+可以在视图函数中调用上面的函数来完成发送短信验证码的功能,稍后我们可以把这个功能跟用户注册结合起来。
+
+生成随机验证码和验证手机号的函数。
+
+```Python
+import random
+import re
+
+TEL_PATTERN = re.compile(r'1[3-9]\d{9}')
+
+
+def check_tel(tel):
+ """检查手机号"""
+ return TEL_PATTERN.fullmatch(tel) is not None
+
+
+def random_code(length=6):
+ """生成随机短信验证码"""
+ return ''.join(random.choices('0123456789', k=length))
+```
+
+发送短信验证码的视图函数。
+
+```Python
+@api_view(('GET', ))
+def get_mobilecode(request, tel):
+ """获取短信验证码"""
+ if check_tel(tel):
+ redis_cli = get_redis_connection()
+ if redis_cli.exists(f'vote:block-mobile:{tel}'):
+ data = {'code': 30001, 'message': '请不要在60秒内重复发送短信验证码'}
+ else:
+ code = random_code()
+ send_mobile_code(tel, code)
+ # 通过Redis阻止60秒内容重复发送短信验证码
+ redis_cli.set(f'vote:block-mobile:{tel}', 'x', ex=60)
+ # 将验证码在Redis中保留10分钟(有效期10分钟)
+ redis_cli.set(f'vote2:valid-mobile:{tel}', code, ex=600)
+ data = {'code': 30000, 'message': '短信验证码已发送,请注意查收'}
+ else:
+ data = {'code': 30002, 'message': '请输入有效的手机号'}
+ return Response(data)
+```
+
+> **说明**:上面的代码利用Redis实现了两个额外的功能,一个是阻止用户60秒内重复发送短信验证码,一个是将用户的短信验证码保留10分钟,也就是说这个短信验证码的有效期只有10分钟,我们可以要求用户在注册时提供该验证码来验证用户手机号的真实性。
+
+### 接入云存储服务
+
+当我们提到**云存储**这个词的时候,通常是指把数据存放在由第三方提供的虚拟服务器环境下,简单的说就是将某些数据或资源通过第三平台托管。一般情况下,提供云存储服务的公司都运营着大型的数据中心,需要云存储服务的个人或组织通过向其购买或租赁存储空间来满足数据存储的需求。在开发Web应用时,可以将静态资源,尤其是用户上传的静态资源直接置于云存储服务中,云存储通常会提供对应的URL使得用户可以访问该静态资源。国内外比较有名的云存储服务(如:亚马逊的S3、阿里的OSS2等)一般都物美价廉,相比自己架设静态资源服务器,云存储的代价更小,而且一般的云存储平台都提供了CDN服务,用于加速对静态资源的访问,所以不管从哪个角度出发,使用云存储的方式管理Web应用的数据和静态资源都是非常好的选择,除非这些资源涉及到个人或商业隐私,否则就可以托管到云存储中。
+
+下面我们以接入[七牛云](https://www.qiniu.com/)为例,讲解如何实现将用户上传的文件保存到七牛云存储。七牛云是国内知名的云计算及数据服务提供商,七牛云在海量文件存储、CDN、视频点播、互动直播以及大规模异构数据的智能分析与处理等领域都有自己的产品,而且非付费用户也可以免费接入,使用其提供的服务。下面是接入七牛云的流程:
+
+1. 注册账号,登录管理控制台。
+
+ 
+
+2. 选择左侧菜单中的对象存储。
+
+ 
+
+3. 在空间管理中选择新建空间(例如:myvote),如果提示空间名称已被占用,更换一个再尝试即可。注意,创建空间后会提示绑定自定义域名,如果暂时还没有自己的域名,可以使用七牛云提供的临时域名,但是临时域名会在30天后被回收,所以最好准备自己的域名(域名需要备案,不清楚如何操作的请自行查阅相关资料)。
+
+ 
+
+4. 在网页的右上角点击个人头像中的“密钥管理”,查看自己的密钥,稍后在代码中需要使用AK(AccessKey)和SK(SecretKey)两个密钥来认证用户身份。
+
+ 
+
+5. 点击网页上方菜单中的“文档”,进入到[七牛开发者中心](https://developer.qiniu.com/),选择导航菜单中的“SDK&工具”并点击“官方SDK”子菜单,找到Python(服务端)并点击“文档”查看官方文档。
+
+ 
+
+接下来,只要安装官方文档提供的示例,就可以接入七牛云,使用七牛云提供的云存储以及其他服务。首先可以通过下面的命令安装七牛云的三方库。
+
+```Bash
+pip install qiniu
+```
+
+接下来可以通过`qiniu`模块中的`put_file`和`put_stream`两个函数实现文件上传,前者可以上传指定路径的文件,后者可以将内存中的二进制数据上传至七牛云,具体的代码如下所示。
+
+```Python
+import qiniu
+
+AUTH = qiniu.Auth('密钥管理中的AccessKey', '密钥管理中的SecretKey')
+BUCKET_NAME = 'myvote'
+
+
+def upload_file_to_qiniu(key, file_path):
+ """上传指定路径的文件到七牛云"""
+ token = AUTH.upload_token(BUCKET_NAME, key)
+ return qiniu.put_file(token, key, file_path)
+
+
+def upload_stream_to_qiniu(key, stream, size):
+ """上传二进制数据流到七牛云"""
+ token = AUTH.upload_token(BUCKET_NAME, key)
+ return qiniu.put_stream(token, key, stream, None, size)
+```
+
+下面是一个文件上传的简单前端页。
+
+```HTML
+
+
+
+
+
上传文件
+
+
+
+
+
+```
+
+> **说明**:前端如果使用表单实现文件上传,表单的method属性必须设置为post,enctype属性需要设置为multipart/form-data,表单中type属性为file的input标签,就是上传文件的文件选择器。
+
+实现上传功能的视图函数如下所示。
+
+```Python
+from django.views.decorators.csrf import csrf_exempt
+
+
+@csrf_exempt
+def upload(request):
+ # 如果上传的文件小于2.5M,则photo对象的类型为InMemoryUploadedFile,文件在内存中
+ # 如果上传的文件超过2.5M,则photo对象的类型为TemporaryUploadedFile,文件在临时路径下
+ photo = request.FILES.get('photo')
+ _, ext = os.path.splitext(photo.name)
+ # 通过UUID和原来文件的扩展名生成独一无二的新的文件名
+ filename = f'{uuid.uuid1().hex}{ext}'
+ # 对于内存中的文件,可以使用上面封装好的函数upload_stream_to_qiniu上传文件到七牛云
+ # 如果文件保存在临时路径下,可以使用upload_file_to_qiniu实现文件上传
+ upload_stream_to_qiniu(filename, photo.file, photo.size)
+ return redirect('/static/html/upload.html')
+```
+
+> **注意**:上面的视图函数使用了`csrf_exempt`装饰器,该装饰器能够让表单免除必须提供CSRF令牌的要求。此外,代码第11行使用了`uuid`模块的`uuid1`函数来生成全局唯一标识符。
+
+运行项目尝试文件上传的功能,文件上传成功后,可以在七牛云“空间管理”中点击自己空间并进入“文件管理”界面,在这里可以看到我们刚才上传成功的文件,而且可以通过七牛云提供的域名获取该文件。
+
+
+
diff --git a/Day41-55/52.文件上传和富文本编辑.md b/Day41-55/52.文件上传和富文本编辑.md
deleted file mode 100644
index 33d5f3f..0000000
--- a/Day41-55/52.文件上传和富文本编辑.md
+++ /dev/null
@@ -1,4 +0,0 @@
-## 文件上传和富文本编辑
-
-
-
diff --git a/Day41-55/53.异步任务和定时任务.md b/Day41-55/53.异步任务和定时任务.md
new file mode 100644
index 0000000..61e320b
--- /dev/null
+++ b/Day41-55/53.异步任务和定时任务.md
@@ -0,0 +1,14 @@
+## 异步任务和定时任务
+
+在Web应用中,如果一个请求执行了耗时间的操作或者该请求的执行时间无法确定,而且对于用户来说只需要知道服务器接收了他的请求,并不需要马上得到请求的执行结果,这样的操作我们就应该对其进行异步化处理。如果说**使用缓存是优化网站性能的第一要义**,那么将耗时间或执行时间不确定的任务**异步化则是网站性能优化的第二要义**,简单的说就是**能推迟做的事情都不要马上做**。
+
+上一章节中讲到的发短信和上传文件到云存储为例,这两个操作前者属于时间不确定的操作(因为作为调用者,我们不能确定三方平台响应的时间),后者属于耗时间的操作(如果文件较大或者三方平台不稳定,都可能导致上传的时间较长),很显然,这两个操作都可以做异步化处理。
+
+在Python项目中实现异步化处理可以使用多线程或借助三方库Celery来完成。
+
+### 使用Celery实现异步化
+
+
+
+### 使用多线程实现异步化
+
diff --git a/Day41-55/53.短信和邮件.md b/Day41-55/53.短信和邮件.md
deleted file mode 100644
index f6f3431..0000000
--- a/Day41-55/53.短信和邮件.md
+++ /dev/null
@@ -1,4 +0,0 @@
-## 短信和邮件
-
-
-
diff --git a/Day41-55/54.单元测试.md b/Day41-55/54.单元测试.md
new file mode 100644
index 0000000..d86a111
--- /dev/null
+++ b/Day41-55/54.单元测试.md
@@ -0,0 +1,4 @@
+## 单元测试
+
+Python标准库中提供了名为`unittest` 的模块来支持我们对代码进行单元测试。所谓单元测试是指针对程序中最小的功能单元(在Python中指函数或类中的方法)进行的测试。
+
diff --git a/Day41-55/54.异步任务和定时任务.md b/Day41-55/54.异步任务和定时任务.md
deleted file mode 100644
index 8564288..0000000
--- a/Day41-55/54.异步任务和定时任务.md
+++ /dev/null
@@ -1,4 +0,0 @@
-## 异步任务和定时任务
-
-
-
diff --git a/Day41-55/55.单元测试和项目上线.md b/Day41-55/55.单元测试和项目上线.md
deleted file mode 100644
index 7793bc1..0000000
--- a/Day41-55/55.单元测试和项目上线.md
+++ /dev/null
@@ -1,3 +0,0 @@
-## 单元测试和项目上线
-
-
diff --git a/Day41-55/55.项目上线.md b/Day41-55/55.项目上线.md
new file mode 100644
index 0000000..eac5b54
--- /dev/null
+++ b/Day41-55/55.项目上线.md
@@ -0,0 +1,4 @@
+## 项目上线
+
+请各位读者移步到[《项目部署上线和性能调优》](../Day91-100/98.项目部署上线和性能调优.md)一文。
+
diff --git a/Day41-55/code/shop/cart/__init__.py b/Day41-55/code/hellodjango/first/__init__.py
similarity index 100%
rename from Day41-55/code/shop/cart/__init__.py
rename to Day41-55/code/hellodjango/first/__init__.py
diff --git a/Day41-55/code/hellodjango/first/admin.py b/Day41-55/code/hellodjango/first/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/Day41-55/code/hellodjango/first/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/Day41-55/code/hellodjango/first/apps.py b/Day41-55/code/hellodjango/first/apps.py
new file mode 100644
index 0000000..5cd3644
--- /dev/null
+++ b/Day41-55/code/hellodjango/first/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class FirstConfig(AppConfig):
+ name = 'first'
diff --git a/Day41-55/code/shop/cart/migrations/__init__.py b/Day41-55/code/hellodjango/first/migrations/__init__.py
similarity index 100%
rename from Day41-55/code/shop/cart/migrations/__init__.py
rename to Day41-55/code/hellodjango/first/migrations/__init__.py
diff --git a/Day41-55/code/hellodjango/first/models.py b/Day41-55/code/hellodjango/first/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/Day41-55/code/hellodjango/first/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/Day41-55/code/shop/cart/tests.py b/Day41-55/code/hellodjango/first/tests.py
similarity index 100%
rename from Day41-55/code/shop/cart/tests.py
rename to Day41-55/code/hellodjango/first/tests.py
diff --git a/Day41-55/code/hellodjango/first/views.py b/Day41-55/code/hellodjango/first/views.py
new file mode 100644
index 0000000..7bb5d36
--- /dev/null
+++ b/Day41-55/code/hellodjango/first/views.py
@@ -0,0 +1,11 @@
+from random import sample
+
+from django.shortcuts import render
+
+
+def show_index(request):
+ fruits = [
+ 'Apple', 'Orange', 'Pitaya', 'Durian', 'Waxberry', 'Blueberry',
+ 'Grape', 'Peach', 'Pear', 'Banana', 'Watermelon', 'Mango'
+ ]
+ return render(request, 'index.html', {'fruits': sample(fruits, 3)})
diff --git a/Day41-55/code/shop_origin/cart/__init__.py b/Day41-55/code/hellodjango/hellodjango/__init__.py
similarity index 100%
rename from Day41-55/code/shop_origin/cart/__init__.py
rename to Day41-55/code/hellodjango/hellodjango/__init__.py
diff --git a/Day41-55/code/shop_origin/shop/settings.py b/Day41-55/code/hellodjango/hellodjango/settings.py
similarity index 70%
rename from Day41-55/code/shop_origin/shop/settings.py
rename to Day41-55/code/hellodjango/hellodjango/settings.py
index 337b099..9888496 100644
--- a/Day41-55/code/shop_origin/shop/settings.py
+++ b/Day41-55/code/hellodjango/hellodjango/settings.py
@@ -1,13 +1,13 @@
"""
-Django settings for shop project.
+Django settings for hellodjango project.
-Generated by 'django-admin startproject' using Django 2.0.5.
+Generated by 'django-admin startproject' using Django 2.2.13.
For more information on this file, see
-https://docs.djangoproject.com/en/2.0/topics/settings/
+https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
-https://docs.djangoproject.com/en/2.0/ref/settings/
+https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
@@ -17,10 +17,10 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
+# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '+gqc54!5+uhvc^o0)fjvihmg&5uu^u+#s5m*fc+e+@bw*(+!w*'
+SECRET_KEY = 'x)q$(0m0^ttqii@^zn^9bdbh&%l$)wzjm=nv&_y+^y9e!37=-z'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
@@ -37,7 +37,6 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
- 'cart',
]
MIDDLEWARE = [
@@ -50,13 +49,12 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
-ROOT_URLCONF = 'shop.urls'
+ROOT_URLCONF = 'hellodjango.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR, 'templates')]
- ,
+ 'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
@@ -69,26 +67,22 @@ TEMPLATES = [
},
]
-WSGI_APPLICATION = 'shop.wsgi.application'
+WSGI_APPLICATION = 'hellodjango.wsgi.application'
# Database
-# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
+# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
DATABASES = {
'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'Shop',
- 'HOST': 'localhost',
- 'PORT': 3306,
- 'USER': 'root',
- 'PASSWORD': '123456',
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
-# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
+# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
@@ -107,11 +101,11 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization
-# https://docs.djangoproject.com/en/2.0/topics/i18n/
+# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
-TIME_ZONE = 'Asia/Chongqing'
+TIME_ZONE = 'UTC'
USE_I18N = True
@@ -121,6 +115,6 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/2.0/howto/static-files/
-STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
+# https://docs.djangoproject.com/en/2.2/howto/static-files/
+
STATIC_URL = '/static/'
diff --git a/Day41-55/code/shop_origin/shop/urls.py b/Day41-55/code/hellodjango/hellodjango/urls.py
similarity index 74%
rename from Day41-55/code/shop_origin/shop/urls.py
rename to Day41-55/code/hellodjango/hellodjango/urls.py
index fb34b04..a5f26e5 100644
--- a/Day41-55/code/shop_origin/shop/urls.py
+++ b/Day41-55/code/hellodjango/hellodjango/urls.py
@@ -1,7 +1,7 @@
-"""shop URL Configuration
+"""hellodjango URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/2.0/topics/http/urls/
+ https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
@@ -16,11 +16,9 @@ Including another URLconf
from django.contrib import admin
from django.urls import path
-from cart import views
+from first.views import show_index
urlpatterns = [
- path('', views.index),
- path('show_cart', views.show_cart),
- path('add_to_cart/
', views.add_to_cart),
path('admin/', admin.site.urls),
+ path('hello/', show_index),
]
diff --git a/Day41-55/code/shop/shop/wsgi.py b/Day41-55/code/hellodjango/hellodjango/wsgi.py
similarity index 57%
rename from Day41-55/code/shop/shop/wsgi.py
rename to Day41-55/code/hellodjango/hellodjango/wsgi.py
index 1aa46d9..0d73723 100644
--- a/Day41-55/code/shop/shop/wsgi.py
+++ b/Day41-55/code/hellodjango/hellodjango/wsgi.py
@@ -1,16 +1,16 @@
"""
-WSGI config for shop project.
+WSGI config for hellodjango project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
-https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
+https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "shop.settings")
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hellodjango.settings')
application = get_wsgi_application()
diff --git a/Day41-55/code/shop_origin/manage.py b/Day41-55/code/hellodjango/manage.py
old mode 100644
new mode 100755
similarity index 69%
rename from Day41-55/code/shop_origin/manage.py
rename to Day41-55/code/hellodjango/manage.py
index 175f50a..15272c0
--- a/Day41-55/code/shop_origin/manage.py
+++ b/Day41-55/code/hellodjango/manage.py
@@ -1,9 +1,11 @@
#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
import os
import sys
-if __name__ == "__main__":
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "shop.settings")
+
+def main():
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hellodjango.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
@@ -13,3 +15,7 @@ if __name__ == "__main__":
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/Day41-55/code/hellodjango/templates/index.html b/Day41-55/code/hellodjango/templates/index.html
new file mode 100644
index 0000000..545cb2d
--- /dev/null
+++ b/Day41-55/code/hellodjango/templates/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+ 首页
+
+
+
+ 今天推荐的水果是:
+
+
+ {% for fruit in fruits %}
+ {{ fruit }}
+ {% endfor %}
+
+
+
\ No newline at end of file
diff --git a/Day41-55/code/shop/cart/admin.py b/Day41-55/code/shop/cart/admin.py
deleted file mode 100644
index cc89c6c..0000000
--- a/Day41-55/code/shop/cart/admin.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from django.contrib import admin
-
-from cart.models import Goods
-
-
-class GoodsAdmin(admin.ModelAdmin):
-
- list_display = ('id', 'name', 'price', 'image')
- search_fields = ('name', )
-
-
-admin.site.register(Goods, GoodsAdmin)
diff --git a/Day41-55/code/shop/cart/apps.py b/Day41-55/code/shop/cart/apps.py
deleted file mode 100644
index 7cc6ec1..0000000
--- a/Day41-55/code/shop/cart/apps.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from django.apps import AppConfig
-
-
-class CartConfig(AppConfig):
- name = 'cart'
diff --git a/Day41-55/code/shop/cart/migrations/0001_initial.py b/Day41-55/code/shop/cart/migrations/0001_initial.py
deleted file mode 100644
index 0419831..0000000
--- a/Day41-55/code/shop/cart/migrations/0001_initial.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Generated by Django 2.0.5 on 2018-05-25 06:28
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- initial = True
-
- dependencies = [
- ]
-
- operations = [
- migrations.CreateModel(
- name='Goods',
- fields=[
- ('id', models.AutoField(db_column='gid', primary_key=True, serialize=False)),
- ('name', models.CharField(db_column='gname', max_length=50)),
- ('price', models.DecimalField(db_column='gprice', decimal_places=2, max_digits=10)),
- ('image', models.CharField(db_column='gimage', max_length=255)),
- ],
- options={
- 'db_table': 'tb_goods',
- 'ordering': ('id',),
- },
- ),
- ]
diff --git a/Day41-55/code/shop/cart/models.py b/Day41-55/code/shop/cart/models.py
deleted file mode 100644
index e65ff97..0000000
--- a/Day41-55/code/shop/cart/models.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from django.db import models
-
-
-class Goods(models.Model):
- """商品模型类"""
-
- id = models.AutoField(primary_key=True, db_column='gid')
- name = models.CharField(max_length=50, db_column='gname')
- price = models.DecimalField(max_digits=10, decimal_places=2, db_column='gprice')
- image = models.CharField(max_length=255, db_column='gimage')
-
- class Meta:
-
- db_table = 'tb_goods'
- ordering = ('id', )
diff --git a/Day41-55/code/shop/cart/views.py b/Day41-55/code/shop/cart/views.py
deleted file mode 100644
index dfbf6ee..0000000
--- a/Day41-55/code/shop/cart/views.py
+++ /dev/null
@@ -1,77 +0,0 @@
-from django.core import serializers
-from django.shortcuts import render, redirect
-
-from cart.models import Goods
-
-
-def index(request):
- goods_list = list(Goods.objects.all())
- return render(request, 'goods.html', {'goods_list': goods_list})
-
-
-class CartItem(object):
- """购物车中的商品项"""
-
- def __init__(self, goods, amount=1):
- self.goods = goods
- self.amount = amount
-
- @property
- def total(self):
- return self.goods.price * self.amount
-
-
-class ShoppingCart(object):
- """购物车"""
-
- def __init__(self):
- self.items = {}
- self.index = 0
-
- def add_item(self, item):
- if item.goods.id in self.items:
- self.items[item.goods.id].amount += item.amount
- else:
- self.items[item.goods.id] = item
-
- def remove_item(self, id):
- if id in self.items:
- self.items.remove(id)
-
- def clear_all_items(self):
- self.items.clear()
-
- @property
- def cart_items(self):
- return self.items.values()
-
- @property
- def total(self):
- val = 0
- for item in self.items.values():
- val += item.total
- return val
-
-
-def add_to_cart(request, id):
- goods = Goods.objects.get(pk=id)
- # 通过request对象的session属性可以获取到session
- # session相当于是服务器端用来保存用户数据的一个字典
- # session利用了Cookie保存sessionid
- # 通过sessionid就可以获取与某个用户对应的会话(也就是用户数据)
- # 如果在浏览器中清除了Cookie那么也就清除了sessionid
- # 再次访问服务器时服务器会重新分配新的sessionid这也就意味着之前的用户数据无法找回
- # 默认情况下Django的session被设定为持久会话而非浏览器续存期会话
- # 通过SESSION_EXPIRE_AT_BROWSER_CLOSE和SESSION_COOKIE_AGE参数可以修改默认设定
- # Django中的session是进行了持久化处理的因此需要设定session的序列化方式
- # 1.6版开始Django默认的session序列化器是JsonSerializer
- # 可以通过SESSION_SERIALIZER来设定其他的序列化器(例如PickleSerializer)
- cart = request.session.get('cart', ShoppingCart())
- cart.add_item(CartItem(goods))
- request.session['cart'] = cart
- return redirect('/')
-
-
-def show_cart(request):
- cart = serializers.deserialize(request.session.get('cart'))
- return render(request, 'cart.html', {'cart': cart})
diff --git a/Day41-55/code/shop/manage.py b/Day41-55/code/shop/manage.py
deleted file mode 100644
index 175f50a..0000000
--- a/Day41-55/code/shop/manage.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-import os
-import sys
-
-if __name__ == "__main__":
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "shop.settings")
- try:
- from django.core.management import execute_from_command_line
- except ImportError as exc:
- raise ImportError(
- "Couldn't import Django. Are you sure it's installed and "
- "available on your PYTHONPATH environment variable? Did you "
- "forget to activate a virtual environment?"
- ) from exc
- execute_from_command_line(sys.argv)
diff --git a/Day41-55/code/shop/shop/__init__.py b/Day41-55/code/shop/shop/__init__.py
deleted file mode 100644
index 9c0f756..0000000
--- a/Day41-55/code/shop/shop/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import pymysql
-
-pymysql.install_as_MySQLdb()
diff --git a/Day41-55/code/shop/shop/settings.py b/Day41-55/code/shop/shop/settings.py
deleted file mode 100644
index f90e37a..0000000
--- a/Day41-55/code/shop/shop/settings.py
+++ /dev/null
@@ -1,129 +0,0 @@
-"""
-Django settings for shop project.
-
-Generated by 'django-admin startproject' using Django 2.0.5.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/2.0/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/2.0/ref/settings/
-"""
-
-import os
-
-# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '3(n^av%_kt*^2zhz0!iwkxv6_wp^ed7-dpow*vqr7ck0_6=9^e'
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
-
-ALLOWED_HOSTS = []
-
-
-# Application definition
-
-INSTALLED_APPS = [
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'cart.apps.CartConfig',
-]
-
-MIDDLEWARE = [
- 'django.middleware.security.SecurityMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.common.CommonMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-]
-
-ROOT_URLCONF = 'shop.urls'
-
-TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [os.path.join(BASE_DIR, 'templates')]
- ,
- 'APP_DIRS': True,
- 'OPTIONS': {
- 'context_processors': [
- 'django.template.context_processors.debug',
- 'django.template.context_processors.request',
- 'django.contrib.auth.context_processors.auth',
- 'django.contrib.messages.context_processors.messages',
- ],
- },
- },
-]
-
-WSGI_APPLICATION = 'shop.wsgi.application'
-
-
-# Database
-# https://docs.djangoproject.com/en/2.0/ref/settings/#databases
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql',
- 'NAME': 'shop',
- 'HOST': 'localhost',
- 'PORT': 3306,
- 'USER': 'root',
- 'PASSWORD': '123456',
- }
-}
-
-
-# Password validation
-# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
-
-AUTH_PASSWORD_VALIDATORS = [
- {
- 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
- },
- {
- 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
- },
-]
-
-# SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
-
-# Internationalization
-# https://docs.djangoproject.com/en/2.0/topics/i18n/
-
-LANGUAGE_CODE = 'zh-hans'
-
-TIME_ZONE = 'Asia/Chongqing'
-
-USE_I18N = True
-
-USE_L10N = True
-
-USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/2.0/howto/static-files/
-
-STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]
-
-STATIC_URL = '/static/'
diff --git a/Day41-55/code/shop/shop/urls.py b/Day41-55/code/shop/shop/urls.py
deleted file mode 100644
index c308ec0..0000000
--- a/Day41-55/code/shop/shop/urls.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""shop URL Configuration
-
-The `urlpatterns` list routes URLs to views. For more information please see:
- https://docs.djangoproject.com/en/2.0/topics/http/urls/
-Examples:
-Function views
- 1. Add an import: from my_app import views
- 2. Add a URL to urlpatterns: path('', views.home, name='home')
-Class-based views
- 1. Add an import: from other_app.views import Home
- 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
-Including another URLconf
- 1. Import the include() function: from django.urls import include, path
- 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
-"""
-from django.contrib import admin
-from django.urls import path
-
-from cart import views
-
-urlpatterns = [
- path('', views.index),
- path('add_to_cart/', views.add_to_cart),
- path('show_cart', views.show_cart),
- path('admin/', admin.site.urls),
-]
diff --git a/Day41-55/code/shop/static/images/dolbee.jpg b/Day41-55/code/shop/static/images/dolbee.jpg
deleted file mode 100644
index 03e4a92..0000000
Binary files a/Day41-55/code/shop/static/images/dolbee.jpg and /dev/null differ
diff --git a/Day41-55/code/shop/static/images/lay.jpg b/Day41-55/code/shop/static/images/lay.jpg
deleted file mode 100644
index 254a4cc..0000000
Binary files a/Day41-55/code/shop/static/images/lay.jpg and /dev/null differ
diff --git a/Day41-55/code/shop/static/images/noodle.jpg b/Day41-55/code/shop/static/images/noodle.jpg
deleted file mode 100644
index 1907c18..0000000
Binary files a/Day41-55/code/shop/static/images/noodle.jpg and /dev/null differ
diff --git a/Day41-55/code/shop/static/images/oil.jpg b/Day41-55/code/shop/static/images/oil.jpg
deleted file mode 100644
index bcb3f7a..0000000
Binary files a/Day41-55/code/shop/static/images/oil.jpg and /dev/null differ
diff --git a/Day41-55/code/shop/static/images/wang.jpg b/Day41-55/code/shop/static/images/wang.jpg
deleted file mode 100644
index 8b94ca2..0000000
Binary files a/Day41-55/code/shop/static/images/wang.jpg and /dev/null differ
diff --git a/Day41-55/code/shop/static/images/wine.jpg b/Day41-55/code/shop/static/images/wine.jpg
deleted file mode 100644
index 96e1a56..0000000
Binary files a/Day41-55/code/shop/static/images/wine.jpg and /dev/null differ
diff --git a/Day41-55/code/shop/templates/cart.html b/Day41-55/code/shop/templates/cart.html
deleted file mode 100644
index 7b67433..0000000
--- a/Day41-55/code/shop/templates/cart.html
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
-
购物车列表
-
-
-
- {% if cart %}
-
-
- 商品名称
- 商品单价
- 商品数量
- 商品总价
- 操作
-
- {% for item in cart %}
-
- {{ item.goods.name }}
- ¥{{ item.goods.price }}
- {{ item.amount }}
- ¥{{ item.total }}
-
- 删除
-
-
- {% endfor %}
-
- ¥{{ cart.total }}元
-
-
- 清空购物车
- {% else %}
- 购物车中暂时没有商品!
- {% endif %}
-
-
\ No newline at end of file
diff --git a/Day41-55/code/shop/templates/goods.html b/Day41-55/code/shop/templates/goods.html
deleted file mode 100644
index 9e3c9b7..0000000
--- a/Day41-55/code/shop/templates/goods.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
-{% load staticfiles %}
-
-
-
-
-
-
-
-
商品列表
-
-
-
-
-
- 商品名称
- 商品价格
- 商品图片
- 操作
-
- {% for goods in goods_list %}
-
- {{ goods.name }}
- ¥{{ goods.price }}
-
-
-
-
- 加入购物车
-
-
- {% endfor %}
-
-
-
\ No newline at end of file
diff --git a/Day41-55/code/shop_origin/cart/admin.py b/Day41-55/code/shop_origin/cart/admin.py
deleted file mode 100644
index 33eb176..0000000
--- a/Day41-55/code/shop_origin/cart/admin.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from django.contrib import admin
-
-from cart.models import Goods
-
-
-class GoodsAdmin(admin.ModelAdmin):
-
- list_display = ('id', 'name', 'price', 'image')
-
-
-admin.site.register(Goods, GoodsAdmin)
diff --git a/Day41-55/code/shop_origin/cart/apps.py b/Day41-55/code/shop_origin/cart/apps.py
deleted file mode 100644
index 7cc6ec1..0000000
--- a/Day41-55/code/shop_origin/cart/apps.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from django.apps import AppConfig
-
-
-class CartConfig(AppConfig):
- name = 'cart'
diff --git a/Day41-55/code/shop_origin/cart/migrations/0001_initial.py b/Day41-55/code/shop_origin/cart/migrations/0001_initial.py
deleted file mode 100644
index a3c1f87..0000000
--- a/Day41-55/code/shop_origin/cart/migrations/0001_initial.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Generated by Django 2.0.5 on 2018-05-25 05:11
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- initial = True
-
- dependencies = [
- ]
-
- operations = [
- migrations.CreateModel(
- name='Goods',
- fields=[
- ('id', models.AutoField(db_column='gid', primary_key=True, serialize=False)),
- ('name', models.CharField(db_column='gname', max_length=50)),
- ('price', models.DecimalField(db_column='gprice', decimal_places=2, max_digits=10)),
- ('image', models.CharField(db_column='gimage', max_length=255)),
- ],
- options={
- 'db_table': 'tb_goods',
- 'ordering': ('id',),
- },
- ),
- ]
diff --git a/Day41-55/code/shop_origin/cart/models.py b/Day41-55/code/shop_origin/cart/models.py
deleted file mode 100644
index 5f6a9b8..0000000
--- a/Day41-55/code/shop_origin/cart/models.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from django.db import models
-
-
-class Goods(models.Model):
-
- id = models.AutoField(primary_key=True, db_column='gid')
- name = models.CharField(max_length=50, db_column='gname')
- price = models.DecimalField(max_digits=10, decimal_places=2, db_column='gprice')
- image = models.CharField(max_length=255, db_column='gimage')
-
- class Meta:
- db_table = 'tb_goods'
- ordering = ('id',)
diff --git a/Day41-55/code/shop_origin/cart/tests.py b/Day41-55/code/shop_origin/cart/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/Day41-55/code/shop_origin/cart/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/Day41-55/code/shop_origin/cart/views.py b/Day41-55/code/shop_origin/cart/views.py
deleted file mode 100644
index a1c3378..0000000
--- a/Day41-55/code/shop_origin/cart/views.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from django.shortcuts import render
-
-from cart.models import Goods
-
-
-def index(request):
- goods_list = list(Goods.objects.all())
- return render(request, 'goods.html', {'goods_list': goods_list})
-
-
-def show_cart(request):
- return render(request, 'cart.html')
-
-
-def add_to_cart(request, no):
- pass
diff --git a/Day41-55/code/shop_origin/shop/__init__.py b/Day41-55/code/shop_origin/shop/__init__.py
deleted file mode 100644
index aa60bed..0000000
--- a/Day41-55/code/shop_origin/shop/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-import pymysql
-
-pymysql.install_as_MySQLdb()
\ No newline at end of file
diff --git a/Day41-55/code/shop_origin/shop/wsgi.py b/Day41-55/code/shop_origin/shop/wsgi.py
deleted file mode 100644
index 1aa46d9..0000000
--- a/Day41-55/code/shop_origin/shop/wsgi.py
+++ /dev/null
@@ -1,16 +0,0 @@
-"""
-WSGI config for shop project.
-
-It exposes the WSGI callable as a module-level variable named ``application``.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
-"""
-
-import os
-
-from django.core.wsgi import get_wsgi_application
-
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "shop.settings")
-
-application = get_wsgi_application()
diff --git a/Day41-55/code/shop_origin/shop_create_sql.sql b/Day41-55/code/shop_origin/shop_create_sql.sql
deleted file mode 100644
index f60ee27..0000000
--- a/Day41-55/code/shop_origin/shop_create_sql.sql
+++ /dev/null
@@ -1,7 +0,0 @@
-insert into tb_goods values
-(default, '乐事(Lay’s)无限薯片', 8.2, 'images/lay.jpg'),
-(default, '旺旺 仙贝 加量装 540g', 18.5, 'images/wang.jpg'),
-(default, '多儿比(Dolbee)黄桃水果罐头', 6.8, 'images/dolbee.jpg'),
-(default, '王致和 精制料酒 500ml', 7.9, 'images/wine.jpg'),
-(default, '陈克明 面条 鸡蛋龙须挂面', 1.0, 'images/noodle.jpg'),
-(default, '鲁花 菜籽油 4L', 69.9, 'images/oil.jpg');
\ No newline at end of file
diff --git a/Day41-55/code/shop_origin/static/images/dolbee.jpg b/Day41-55/code/shop_origin/static/images/dolbee.jpg
deleted file mode 100644
index 03e4a92..0000000
Binary files a/Day41-55/code/shop_origin/static/images/dolbee.jpg and /dev/null differ
diff --git a/Day41-55/code/shop_origin/static/images/lay.jpg b/Day41-55/code/shop_origin/static/images/lay.jpg
deleted file mode 100644
index 254a4cc..0000000
Binary files a/Day41-55/code/shop_origin/static/images/lay.jpg and /dev/null differ
diff --git a/Day41-55/code/shop_origin/static/images/noodle.jpg b/Day41-55/code/shop_origin/static/images/noodle.jpg
deleted file mode 100644
index 1907c18..0000000
Binary files a/Day41-55/code/shop_origin/static/images/noodle.jpg and /dev/null differ
diff --git a/Day41-55/code/shop_origin/static/images/oil.jpg b/Day41-55/code/shop_origin/static/images/oil.jpg
deleted file mode 100644
index bcb3f7a..0000000
Binary files a/Day41-55/code/shop_origin/static/images/oil.jpg and /dev/null differ
diff --git a/Day41-55/code/shop_origin/static/images/wang.jpg b/Day41-55/code/shop_origin/static/images/wang.jpg
deleted file mode 100644
index 8b94ca2..0000000
Binary files a/Day41-55/code/shop_origin/static/images/wang.jpg and /dev/null differ
diff --git a/Day41-55/code/shop_origin/static/images/wine.jpg b/Day41-55/code/shop_origin/static/images/wine.jpg
deleted file mode 100644
index 96e1a56..0000000
Binary files a/Day41-55/code/shop_origin/static/images/wine.jpg and /dev/null differ
diff --git a/Day41-55/code/shop_origin/templates/cart.html b/Day41-55/code/shop_origin/templates/cart.html
deleted file mode 100644
index 2291b9c..0000000
--- a/Day41-55/code/shop_origin/templates/cart.html
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
-
购物车列表
-
-
-
- {% if cart_items %}
-
-
- 商品名称
- 商品单价
- 商品数量
- 商品总价
- 操作
-
- {% for item in cart_items %}
-
- {{ item.name }}
- ¥{{ item.unit_price }}
- {{ item.amount }}
- ¥{{ item.total_price }}
-
- 删除
-
-
- {% endfor %}
-
- ¥{{ cart.total }}元
-
-
- 清空购物车
- {% else %}
- 购物车中暂时没有商品!
- {% endif %}
-
-
\ No newline at end of file
diff --git a/Day41-55/code/shop_origin/templates/goods.html b/Day41-55/code/shop_origin/templates/goods.html
deleted file mode 100644
index 9e3c9b7..0000000
--- a/Day41-55/code/shop_origin/templates/goods.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
-{% load staticfiles %}
-
-
-
-
-
-
-
-
商品列表
-
-
-
-
-
- 商品名称
- 商品价格
- 商品图片
- 操作
-
- {% for goods in goods_list %}
-
- {{ goods.name }}
- ¥{{ goods.price }}
-
-
-
-
- 加入购物车
-
-
- {% endfor %}
-
-
-
\ No newline at end of file
diff --git a/Day41-55/res/CSRF.png b/Day41-55/res/CSRF.png
index 6e87482..3108524 100644
Binary files a/Day41-55/res/CSRF.png and b/Day41-55/res/CSRF.png differ
diff --git a/Day41-55/res/Django-Flowchart.png b/Day41-55/res/Django-Flowchart.png
index ef96033..2ed0cfe 100644
Binary files a/Day41-55/res/Django-Flowchart.png and b/Day41-55/res/Django-Flowchart.png differ
diff --git a/Day41-55/res/Django-MTV.png b/Day41-55/res/Django-MTV.png
index 76f330e..b075e93 100644
Binary files a/Day41-55/res/Django-MTV.png and b/Day41-55/res/Django-MTV.png differ
diff --git a/Day41-55/res/admin-login.png b/Day41-55/res/admin-login.png
deleted file mode 100644
index 15ea232..0000000
Binary files a/Day41-55/res/admin-login.png and /dev/null differ
diff --git a/Day41-55/res/admin-model-create.png b/Day41-55/res/admin-model-create.png
deleted file mode 100644
index 5d07891..0000000
Binary files a/Day41-55/res/admin-model-create.png and /dev/null differ
diff --git a/Day41-55/res/admin-model-delete-and-update.png b/Day41-55/res/admin-model-delete-and-update.png
deleted file mode 100644
index 87d709c..0000000
Binary files a/Day41-55/res/admin-model-delete-and-update.png and /dev/null differ
diff --git a/Day41-55/res/admin-model-depts.png b/Day41-55/res/admin-model-depts.png
deleted file mode 100644
index 7214544..0000000
Binary files a/Day41-55/res/admin-model-depts.png and /dev/null differ
diff --git a/Day41-55/res/admin-model-emps-modified.png b/Day41-55/res/admin-model-emps-modified.png
deleted file mode 100644
index 27c6205..0000000
Binary files a/Day41-55/res/admin-model-emps-modified.png and /dev/null differ
diff --git a/Day41-55/res/admin-model-emps.png b/Day41-55/res/admin-model-emps.png
deleted file mode 100644
index b9b7953..0000000
Binary files a/Day41-55/res/admin-model-emps.png and /dev/null differ
diff --git a/Day41-55/res/admin-model-read.png b/Day41-55/res/admin-model-read.png
deleted file mode 100644
index 135437b..0000000
Binary files a/Day41-55/res/admin-model-read.png and /dev/null differ
diff --git a/Day41-55/res/admin-model.png b/Day41-55/res/admin-model.png
deleted file mode 100644
index 12fa9e0..0000000
Binary files a/Day41-55/res/admin-model.png and /dev/null differ
diff --git a/Day41-55/res/admin-welcome.png b/Day41-55/res/admin-welcome.png
deleted file mode 100644
index 2371ffe..0000000
Binary files a/Day41-55/res/admin-welcome.png and /dev/null differ
diff --git a/Day41-55/res/asynchronous-web-request.png b/Day41-55/res/asynchronous-web-request.png
new file mode 100644
index 0000000..41bf070
Binary files /dev/null and b/Day41-55/res/asynchronous-web-request.png differ
diff --git a/Day41-55/res/captcha.png b/Day41-55/res/captcha.png
index 59b8065..a0a5ce5 100644
Binary files a/Day41-55/res/captcha.png and b/Day41-55/res/captcha.png differ
diff --git a/Day41-55/res/cookie_xstorage_indexeddb.png b/Day41-55/res/cookie_xstorage_indexeddb.png
index a08c257..e21643f 100644
Binary files a/Day41-55/res/cookie_xstorage_indexeddb.png and b/Day41-55/res/cookie_xstorage_indexeddb.png differ
diff --git a/Day41-55/res/csrf-simple.png b/Day41-55/res/csrf-simple.png
new file mode 100644
index 0000000..9ffae31
Binary files /dev/null and b/Day41-55/res/csrf-simple.png differ
diff --git a/Day41-55/res/debug-toolbar.png b/Day41-55/res/debug-toolbar.png
new file mode 100644
index 0000000..ffc1b15
Binary files /dev/null and b/Day41-55/res/debug-toolbar.png differ
diff --git a/Day41-55/res/django-admin-add-model.png b/Day41-55/res/django-admin-add-model.png
new file mode 100644
index 0000000..a38f2f2
Binary files /dev/null and b/Day41-55/res/django-admin-add-model.png differ
diff --git a/Day41-55/res/django-admin-apps.png b/Day41-55/res/django-admin-apps.png
new file mode 100644
index 0000000..26f6614
Binary files /dev/null and b/Day41-55/res/django-admin-apps.png differ
diff --git a/Day41-55/res/django-admin-delete-update-model.png b/Day41-55/res/django-admin-delete-update-model.png
new file mode 100644
index 0000000..ee5605a
Binary files /dev/null and b/Day41-55/res/django-admin-delete-update-model.png differ
diff --git a/Day41-55/res/django-admin-login.png b/Day41-55/res/django-admin-login.png
new file mode 100644
index 0000000..7a172d7
Binary files /dev/null and b/Day41-55/res/django-admin-login.png differ
diff --git a/Day41-55/res/django-admin-models.png b/Day41-55/res/django-admin-models.png
new file mode 100644
index 0000000..9ff5486
Binary files /dev/null and b/Day41-55/res/django-admin-models.png differ
diff --git a/Day41-55/res/django-admin-view-models-subject.png b/Day41-55/res/django-admin-view-models-subject.png
new file mode 100644
index 0000000..acbaf9d
Binary files /dev/null and b/Day41-55/res/django-admin-view-models-subject.png differ
diff --git a/Day41-55/res/django-admin-view-models-teacher.png b/Day41-55/res/django-admin-view-models-teacher.png
new file mode 100644
index 0000000..3036e41
Binary files /dev/null and b/Day41-55/res/django-admin-view-models-teacher.png differ
diff --git a/Day41-55/res/django-admin-view-models.png b/Day41-55/res/django-admin-view-models.png
new file mode 100644
index 0000000..e27dce3
Binary files /dev/null and b/Day41-55/res/django-admin-view-models.png differ
diff --git a/Day41-55/res/django-index-1.png b/Day41-55/res/django-index-1.png
index df4ba60..65ccc75 100644
Binary files a/Day41-55/res/django-index-1.png and b/Day41-55/res/django-index-1.png differ
diff --git a/Day41-55/res/django-index-2.png b/Day41-55/res/django-index-2.png
index 6b5edb9..7c19786 100644
Binary files a/Day41-55/res/django-index-2.png and b/Day41-55/res/django-index-2.png differ
diff --git a/Day41-55/res/django-middleware.png b/Day41-55/res/django-middleware.png
new file mode 100644
index 0000000..ab77a5d
Binary files /dev/null and b/Day41-55/res/django-middleware.png differ
diff --git a/Day41-55/res/drf-app.png b/Day41-55/res/drf-app.png
new file mode 100644
index 0000000..c60ed38
Binary files /dev/null and b/Day41-55/res/drf-app.png differ
diff --git a/Day41-55/res/echarts_bar_graph.png b/Day41-55/res/echarts_bar_graph.png
index a77571f..d2f40ea 100644
Binary files a/Day41-55/res/echarts_bar_graph.png and b/Day41-55/res/echarts_bar_graph.png differ
diff --git a/Day41-55/res/er-graph.png b/Day41-55/res/er-graph.png
deleted file mode 100644
index 9072a9d..0000000
Binary files a/Day41-55/res/er-graph.png and /dev/null differ
diff --git a/Day41-55/res/http-request.png b/Day41-55/res/http-request.png
index aca9287..67d0fb6 100644
Binary files a/Day41-55/res/http-request.png and b/Day41-55/res/http-request.png differ
diff --git a/Day41-55/res/http-response.png b/Day41-55/res/http-response.png
index f2b8ae3..0de1144 100644
Binary files a/Day41-55/res/http-response.png and b/Day41-55/res/http-response.png differ
diff --git a/Day41-55/res/json-web-token.png b/Day41-55/res/json-web-token.png
new file mode 100644
index 0000000..9af29ba
Binary files /dev/null and b/Day41-55/res/json-web-token.png differ
diff --git a/Day41-55/res/luosimao-pay-onlinebuy.png b/Day41-55/res/luosimao-pay-onlinebuy.png
new file mode 100644
index 0000000..a8c69b9
Binary files /dev/null and b/Day41-55/res/luosimao-pay-onlinebuy.png differ
diff --git a/Day41-55/res/luosimao-sms-apikey.png b/Day41-55/res/luosimao-sms-apikey.png
new file mode 100644
index 0000000..251ba93
Binary files /dev/null and b/Day41-55/res/luosimao-sms-apikey.png differ
diff --git a/Day41-55/res/luosimao-sms-signature.png b/Day41-55/res/luosimao-sms-signature.png
new file mode 100644
index 0000000..7fd2617
Binary files /dev/null and b/Day41-55/res/luosimao-sms-signature.png differ
diff --git a/Day41-55/res/luosimao-sms-whitelist.png b/Day41-55/res/luosimao-sms-whitelist.png
new file mode 100644
index 0000000..6f67168
Binary files /dev/null and b/Day41-55/res/luosimao-sms-whitelist.png differ
diff --git a/Day41-55/res/mvc.png b/Day41-55/res/mvc.png
index 7ba14ba..0481ccb 100644
Binary files a/Day41-55/res/mvc.png and b/Day41-55/res/mvc.png differ
diff --git a/Day41-55/res/pycharm-django-project.png b/Day41-55/res/pycharm-django-project.png
new file mode 100644
index 0000000..233b350
Binary files /dev/null and b/Day41-55/res/pycharm-django-project.png differ
diff --git a/Day41-55/res/pycharm-django-server.png b/Day41-55/res/pycharm-django-server.png
new file mode 100644
index 0000000..a6d0fae
Binary files /dev/null and b/Day41-55/res/pycharm-django-server.png differ
diff --git a/Day41-55/res/pycharm-django-static.png b/Day41-55/res/pycharm-django-static.png
new file mode 100644
index 0000000..a96a646
Binary files /dev/null and b/Day41-55/res/pycharm-django-static.png differ
diff --git a/Day41-55/res/pycharm-django-template.png b/Day41-55/res/pycharm-django-template.png
new file mode 100644
index 0000000..7242df8
Binary files /dev/null and b/Day41-55/res/pycharm-django-template.png differ
diff --git a/Day41-55/res/pycharm-django-virtual-environment.png b/Day41-55/res/pycharm-django-virtual-environment.png
new file mode 100644
index 0000000..2c4c8f7
Binary files /dev/null and b/Day41-55/res/pycharm-django-virtual-environment.png differ
diff --git a/Day41-55/res/pycharm-install-django.png b/Day41-55/res/pycharm-install-django.png
new file mode 100644
index 0000000..11d1eaf
Binary files /dev/null and b/Day41-55/res/pycharm-install-django.png differ
diff --git a/Day41-55/res/pycharm-python-manage.png b/Day41-55/res/pycharm-python-manage.png
new file mode 100644
index 0000000..ed1b614
Binary files /dev/null and b/Day41-55/res/pycharm-python-manage.png differ
diff --git a/Day41-55/res/pycharm-vote-project.png b/Day41-55/res/pycharm-vote-project.png
new file mode 100644
index 0000000..1a6eaf4
Binary files /dev/null and b/Day41-55/res/pycharm-vote-project.png differ
diff --git a/Day41-55/res/qiniu-document-python.png b/Day41-55/res/qiniu-document-python.png
new file mode 100644
index 0000000..1b2853e
Binary files /dev/null and b/Day41-55/res/qiniu-document-python.png differ
diff --git a/Day41-55/res/qiniu-file-management.png b/Day41-55/res/qiniu-file-management.png
new file mode 100644
index 0000000..a56244a
Binary files /dev/null and b/Day41-55/res/qiniu-file-management.png differ
diff --git a/Day41-55/res/qiniu-manage-console.png b/Day41-55/res/qiniu-manage-console.png
new file mode 100644
index 0000000..ef69a3e
Binary files /dev/null and b/Day41-55/res/qiniu-manage-console.png differ
diff --git a/Day41-55/res/qiniu-secretkey-management.png b/Day41-55/res/qiniu-secretkey-management.png
new file mode 100644
index 0000000..dc6c006
Binary files /dev/null and b/Day41-55/res/qiniu-secretkey-management.png differ
diff --git a/Day41-55/res/qiniu-storage-create.png b/Day41-55/res/qiniu-storage-create.png
new file mode 100644
index 0000000..6ec4205
Binary files /dev/null and b/Day41-55/res/qiniu-storage-create.png differ
diff --git a/Day41-55/res/qiniu-storage-service.png b/Day41-55/res/qiniu-storage-service.png
new file mode 100644
index 0000000..fbf4c8c
Binary files /dev/null and b/Day41-55/res/qiniu-storage-service.png differ
diff --git a/Day41-55/res/redis-cache-service.png b/Day41-55/res/redis-cache-service.png
new file mode 100644
index 0000000..06a618e
Binary files /dev/null and b/Day41-55/res/redis-cache-service.png differ
diff --git a/Day41-55/res/sessionid_from_cookie.png b/Day41-55/res/sessionid_from_cookie.png
index 6dfc76e..23b40aa 100644
Binary files a/Day41-55/res/sessionid_from_cookie.png and b/Day41-55/res/sessionid_from_cookie.png differ
diff --git a/Day41-55/res/show-depts.png b/Day41-55/res/show-depts.png
deleted file mode 100644
index ceaecc8..0000000
Binary files a/Day41-55/res/show-depts.png and /dev/null differ
diff --git a/Day41-55/res/show_subjects.png b/Day41-55/res/show_subjects.png
deleted file mode 100644
index 9e7612d..0000000
Binary files a/Day41-55/res/show_subjects.png and /dev/null differ
diff --git a/Day41-55/res/show_teachers.png b/Day41-55/res/show_teachers.png
deleted file mode 100644
index 031ac57..0000000
Binary files a/Day41-55/res/show_teachers.png and /dev/null differ
diff --git a/Day41-55/res/synchronous-web-request.png b/Day41-55/res/synchronous-web-request.png
new file mode 100644
index 0000000..1f5661b
Binary files /dev/null and b/Day41-55/res/synchronous-web-request.png differ
diff --git a/Day41-55/res/web-application.png b/Day41-55/res/web-application.png
index 89d2dec..5a18949 100644
Binary files a/Day41-55/res/web-application.png and b/Day41-55/res/web-application.png differ
diff --git a/Day56-60/56-60.用FastAPI开发数据接口.md b/Day56-60/56-60.用FastAPI开发数据接口.md
new file mode 100644
index 0000000..bca9652
--- /dev/null
+++ b/Day56-60/56-60.用FastAPI开发数据接口.md
@@ -0,0 +1,2 @@
+## 用FastAPI开发数据接口
+
diff --git a/Day56-60/56.Flask入门.md b/Day56-60/56.Flask入门.md
deleted file mode 100644
index 5c4d659..0000000
--- a/Day56-60/56.Flask入门.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## Flask入门
-
diff --git a/Day56-60/57.模板的使用.md b/Day56-60/57.模板的使用.md
deleted file mode 100644
index 3344e2e..0000000
--- a/Day56-60/57.模板的使用.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## 模板的使用
-
diff --git a/Day56-60/58.表单的处理.md b/Day56-60/58.表单的处理.md
deleted file mode 100644
index 895e910..0000000
--- a/Day56-60/58.表单的处理.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## 表单的处理
-
diff --git a/Day56-60/59.数据库操作.md b/Day56-60/59.数据库操作.md
deleted file mode 100644
index d8a6a1b..0000000
--- a/Day56-60/59.数据库操作.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## 数据库操作
-
diff --git a/Day56-60/60.项目实战.md b/Day56-60/60.项目实战.md
deleted file mode 100644
index dbbae84..0000000
--- a/Day56-60/60.项目实战.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## 项目实战
-
diff --git a/Day61-65/.gitkeep b/Day61-65/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/Day66-75/66.网络爬虫和相关工具.md b/Day61-65/61.网络爬虫和相关工具.md
similarity index 73%
rename from Day66-75/66.网络爬虫和相关工具.md
rename to Day61-65/61.网络爬虫和相关工具.md
index 16aa85a..157fc8f 100644
--- a/Day66-75/66.网络爬虫和相关工具.md
+++ b/Day61-65/61.网络爬虫和相关工具.md
@@ -27,7 +27,6 @@
大多数网站都会定义robots.txt文件,下面以淘宝的[robots.txt](http://www.taobao.com/robots.txt)文件为例,看看该网站对爬虫有哪些限制。
```
-
User-agent: Baiduspider
Allow: /article
Allow: /oshtml
@@ -108,17 +107,17 @@ HTTP响应(响应行+响应头+空行+消息体):

-2. POSTMAN:功能强大的网页调试与RESTful请求工具。
+2. Postman:功能强大的网页调试与RESTful请求工具。

3. HTTPie:命令行HTTP客户端。
- ```Shell
+ ```Bash
pip3 install httpie
```
- ```Shell
+ ```Bash
http --header http://www.scu.edu.cn
HTTP/1.1 200 OK
Accept-Ranges: bytes
@@ -138,9 +137,9 @@ HTTP响应(响应行+响应头+空行+消息体):
X-Frame-Options: SAMEORIGIN
```
-4. BuiltWith:识别网站所用技术的工具。
+4. `builtwith`库:识别网站所用技术的工具。
- ```Shell
+ ```Bash
pip3 install builtwith
```
@@ -155,9 +154,9 @@ HTTP响应(响应行+响应头+空行+消息体):
{'web-servers': ['Tengine'], 'web-frameworks': ['Twitter Bootstrap', 'Ruby on Rails'], 'programming-languages': ['Ruby']}
```
-5. python-whois:查询网站所有者的工具。
+5. `python-whois`库:查询网站所有者的工具。
- ```Shell
+ ```Bash
pip3 install python-whois
```
@@ -167,7 +166,7 @@ HTTP响应(响应行+响应头+空行+消息体):
{'domain_name': ['BAIDU.COM', 'baidu.com'], 'registrar': 'MarkMonitor, Inc.', 'whois_server': 'whois.markmonitor.com', 'referral_url': None, 'updated_date': [datetime.datetime(2017, 7, 28, 2, 36, 28), datetime.datetime(2017, 7, 27, 19, 36, 28)], 'creation_date': [datetime.datetime(1999, 10, 11, 11, 5, 17), datetime.datetime(1999, 10, 11, 4, 5, 17)], 'expiration_date': [datetime.datetime(2026, 10, 11, 11, 5, 17), datetime.datetime(2026, 10, 11, 0, 0)], 'name_servers': ['DNS.BAIDU.COM', 'NS2.BAIDU.COM', 'NS3.BAIDU.COM', 'NS4.BAIDU.COM', 'NS7.BAIDU.COM', 'dns.baidu.com', 'ns4.baidu.com', 'ns3.baidu.com', 'ns7.baidu.com', 'ns2.baidu.com'], 'status': ['clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited', 'clientTransferProhibited https://icann.org/epp#clientTransferProhibited', 'clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited', 'serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited', 'serverTransferProhibited https://icann.org/epp#serverTransferProhibited', 'serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited', 'clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)', 'clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)', 'clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)', 'serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)', 'serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)', 'serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)'], 'emails': ['abusecomplaints@markmonitor.com', 'whoisrelay@markmonitor.com'], 'dnssec': 'unsigned', 'name': None, 'org': 'Beijing Baidu Netcom Science Technology Co., Ltd.', 'address': None, 'city': None, 'state': 'Beijing', 'zipcode': None, 'country': 'CN'}
```
-6. robotparser:解析robots.txt的工具。
+6. `robotparser`模块:解析`robots.txt`的工具。
```Python
>>> from urllib import robotparser
@@ -199,110 +198,106 @@ HTTP响应(响应行+响应头+空行+消息体):
下面的例子给出了一个从“搜狐体育”上获取NBA新闻标题和链接的爬虫。
```Python
-from urllib.error import URLError
-from urllib.request import urlopen
-
import re
-import pymysql
-import ssl
+from collections import deque
+from urllib.parse import urljoin
-from pymysql import Error
+import requests
+
+LI_A_PATTERN = re.compile(r'.*? ')
+A_TEXT_PATTERN = re.compile(r']*?>(.*?) ')
+A_HREF_PATTERN = re.compile(r']*?href="(.*?)"\s*[^>]*?>')
-def decode_page(page_bytes, charsets=('utf-8',)):
- """通过指定的字符集对页面进行解码(不是每个网站都将字符集设置为utf-8)"""
- page_html = None
+def decode_page(page_bytes, charsets):
+ """通过指定的字符集对页面进行解码"""
for charset in charsets:
try:
- page_html = page_bytes.decode(charset)
- break
+ return page_bytes.decode(charset)
except UnicodeDecodeError:
pass
- # logging.error('Decode:', error)
- return page_html
-def get_page_html(seed_url, *, retry_times=3, charsets=('utf-8',)):
- """获取页面的HTML代码(通过递归实现指定次数的重试操作)"""
- page_html = None
- try:
- page_html = decode_page(urlopen(seed_url).read(), charsets)
- except URLError:
- # logging.error('URL:', error)
- if retry_times > 0:
- return get_page_html(seed_url, retry_times=retry_times - 1,
- charsets=charsets)
- return page_html
+def get_matched_parts(content_string, pattern):
+ """从字符串中提取所有跟正则表达式匹配的内容"""
+ return pattern.findall(content_string, re.I) \
+ if content_string else []
-def get_matched_parts(page_html, pattern_str, pattern_ignore_case=re.I):
- """从页面中提取需要的部分(通常是链接也可以通过正则表达式进行指定)"""
- pattern_regex = re.compile(pattern_str, pattern_ignore_case)
- return pattern_regex.findall(page_html) if page_html else []
+def get_matched_part(content_string, pattern, group_no=1):
+ """从字符串中提取跟正则表达式匹配的内容"""
+ match = pattern.search(content_string)
+ if match:
+ return match.group(group_no)
-def start_crawl(seed_url, match_pattern, *, max_depth=-1):
- """开始执行爬虫程序并对指定的数据进行持久化操作"""
- conn = pymysql.connect(host='localhost', port=3306,
- database='crawler', user='root',
- password='123456', charset='utf8')
- try:
- with conn.cursor() as cursor:
- url_list = [seed_url]
- # 通过下面的字典避免重复抓取并控制抓取深度
- visited_url_list = {seed_url: 0}
- while url_list:
- current_url = url_list.pop(0)
- depth = visited_url_list[current_url]
- if depth != max_depth:
- # 尝试用utf-8/gbk/gb2312三种字符集进行页面解码
- page_html = get_page_html(current_url, charsets=('utf-8', 'gbk', 'gb2312'))
- links_list = get_matched_parts(page_html, match_pattern)
- param_list = []
- for link in links_list:
- if link not in visited_url_list:
- visited_url_list[link] = depth + 1
- page_html = get_page_html(link, charsets=('utf-8', 'gbk', 'gb2312'))
- headings = get_matched_parts(page_html, r'(.*)]+test=a\s[^>]*href=["\'](.*?)["\']',
- max_depth=2)
+ start_crawl(
+ seed_url='http://sports.sohu.com/nba_a.shtml',
+ pattern=LI_A_PATTERN,
+ max_depth=2
+ )
if __name__ == '__main__':
main()
```
-由于使用了MySQL实现持久化操作,所以要先启动MySQL服务器并创建名为`crawler`的数据库和名为`tb_result`的二维表才能运行该程序。
-
### 爬虫注意事项
通过上面的例子,我们对爬虫已经有了一个感性的认识,在编写爬虫时有以下一些注意事项:
-1. 处理相对链接。有的时候我们从页面中获取的链接不是一个完整的绝对链接而是一个相对链接,这种情况下需要将其与URL前缀进行拼接(`urllib.parse`中的`urljoin()`函数可以完成此项操作)。
+1. 上面的代码使用了`requests`三方库来获取网络资源,这是一个非常优质的三方库,关于它的用法可以参考它的[官方文档](https://requests.readthedocs.io/zh_CN/latest/)。
-2. 设置代理服务。有些网站会限制访问的区域(例如美国的Netflix屏蔽了很多国家的访问),有些爬虫需要隐藏自己的身份,在这种情况下可以设置使用代理服务器,代理服务器有免费的服务器和付费的商业服务器,但后者稳定性和可用性都更好,强烈建议在商业项目中使用付费的代理服务器。可以通过修改`urllib.request`中的`ProxyHandler`来为请求设置代理服务器。
+2. 上面的代码中使用了双端队列(`deque`)来保存待爬取的URL。双端队列相当于是使用链式存储结构的`list`,在双端队列的头尾添加和删除元素性能都比较好,刚好可以用来构造一个FIFO(先进先出)的队列结构。
-3. 限制下载速度。如果我们的爬虫获取网页的速度过快,可能就会面临被封禁或者产生“损害动产”的风险(这个可能会导致吃官司且败诉),可以在两次下载之间添加延时从而对爬虫进行限速。
+3. 处理相对路径。有的时候我们从页面中获取的链接不是一个完整的绝对链接而是一个相对链接,这种情况下需要将其与URL前缀进行拼接(`urllib.parse`中的`urljoin()`函数可以完成此项操作)。
-4. 避免爬虫陷阱。有些网站会动态生成页面内容,这会导致产生无限多的页面(例如在线万年历通常会有无穷无尽的链接)。可以通过记录到达当前页面经过了多少个链接(链接深度)来解决该问题,当达到事先设定的最大深度时爬虫就不再像队列中添加该网页中的链接了。
+4. 设置代理服务。有些网站会限制访问的区域(例如美国的Netflix屏蔽了很多国家的访问),有些爬虫需要隐藏自己的身份,在这种情况下可以设置使用代理服务器,代理服务器有免费的服务器和付费的商业服务器,但后者稳定性和可用性都更好,强烈建议在商业项目中使用付费的商业代理服务器。如果使用`requests`三方库,可以在请求方法中添加`proxies`参数来指定代理服务器;如果使用标准库,可以通过修改`urllib.request`中的`ProxyHandler`来为请求设置代理服务器。
-5. SSL相关问题。在使用`urlopen`打开一个HTTPS链接时会验证一次SSL证书,如果不做出处理会产生错误提示“SSL: CERTIFICATE_VERIFY_FAILED”,可以通过以下两种方式加以解决:
+5. 限制下载速度。如果我们的爬虫获取网页的速度过快,可能就会面临被封禁或者产生“损害动产”的风险(这个可能会导致吃官司且败诉),可以在两次获取页面数据之间添加延时从而对爬虫进行限速。
+
+6. 避免爬虫陷阱。有些网站会动态生成页面内容,这会导致产生无限多的页面(例如在线万年历通常会有无穷无尽的链接)。可以通过记录到达当前页面经过了多少个链接(链接深度)来解决该问题,当达到事先设定的最大深度时,爬虫就不再像队列中添加该网页中的链接了。
+
+7. 避开蜜罐链接。网站上的有些链接是浏览器中不可见的,这种链接通常是故意诱使爬虫去访问的蜜罐,一旦访问了这些链接,服务器就会判定请求是来自于爬虫的,这样可能会导致被服务器封禁IP地址。如何避开这些蜜罐链接我们在后面为大家进行讲解。
+
+8. SSL相关问题。如果使用标准库的`urlopen`打开一个HTTPS链接时会验证一次SSL证书,如果不做出处理会产生错误提示“SSL: CERTIFICATE_VERIFY_FAILED”,可以通过以下两种方式加以解决:
- 使用未经验证的上下文
diff --git a/Day61-65/61.预备知识.md b/Day61-65/61.预备知识.md
deleted file mode 100644
index 4a95122..0000000
--- a/Day61-65/61.预备知识.md
+++ /dev/null
@@ -1,140 +0,0 @@
-## 预备知识
-
-### 并发编程
-
-所谓并发编程就是让程序中有多个部分能够并发或同时执行,并发编程带来的好处不言而喻,其中最为关键的两点是提升了执行效率和改善了用户体验。下面简单阐述一下Python中实现并发编程的三种方式:
-
-1. 多线程:Python中通过`threading`模块的`Thread`类并辅以`Lock`、`Condition`、`Event`、`Semaphore`和`Barrier`等类来支持多线程编程。Python解释器通过GIL(全局解释器锁)来防止多个线程同时执行本地字节码,这个锁对于CPython(Python解释器的官方实现)是必须的,因为CPython的内存管理并不是线程安全的。因为GIL的存在,Python的多线程并不能利用CPU的多核特性。
-
-2. 多进程:使用多进程可以有效的解决GIL的问题,Python中的`multiprocessing`模块提供了`Process`类来实现多进程,其他的辅助类跟`threading`模块中的类类似,由于进程间的内存是相互隔离的(操作系统对进程的保护),进程间通信(共享数据)必须使用管道、套接字等方式,这一点从编程的角度来讲是比较麻烦的,为此,Python的`multiprocessing`模块提供了一个名为`Queue`的类,它基于管道和锁机制提供了多个进程共享的队列。
-
- ```Python
- """
- 用下面的命令运行程序并查看执行时间,例如:
- time python3 example06.py
- real 0m20.657s
- user 1m17.749s
- sys 0m0.158s
- 使用多进程后实际执行时间为20.657秒,而用户时间1分17.749秒约为实际执行时间的4倍
- 这就证明我们的程序通过多进程使用了CPU的多核特性,而且这台计算机配置了4核的CPU
- """
- import concurrent.futures
- import math
-
- PRIMES = [
- 1116281,
- 1297337,
- 104395303,
- 472882027,
- 533000389,
- 817504243,
- 982451653,
- 112272535095293,
- 112582705942171,
- 112272535095293,
- 115280095190773,
- 115797848077099,
- 1099726899285419
- ] * 5
-
-
- def is_prime(num):
- """判断素数"""
- assert num > 0
- for i in range(2, int(math.sqrt(num)) + 1):
- if num % i == 0:
- return False
- return num != 1
-
-
- def main():
- """主函数"""
- with concurrent.futures.ProcessPoolExecutor() as executor:
- for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
- print('%d is prime: %s' % (number, prime))
-
-
- if __name__ == '__main__':
- main()
- ```
-
-3. 异步编程(异步I/O):所谓异步编程是通过调度程序从任务队列中挑选任务,调度程序以交叉的形式执行这些任务,我们并不能保证任务将以某种顺序去执行,因为执行顺序取决于队列中的一项任务是否愿意将CPU处理时间让位给另一项任务。异步编程通常通过多任务协作处理的方式来实现,由于执行时间和顺序的不确定,因此需要通过钩子函数(回调函数)或者`Future`对象来获取任务执行的结果。目前我们使用的Python 3通过`asyncio`模块以及`await`和`async`关键字(Python 3.5中引入,Python 3.7中正式成为关键字)提供了对异步I/O的支持。
-
- ```Python
- import asyncio
-
-
- async def fetch(host):
- """从指定的站点抓取信息(协程函数)"""
- print(f'Start fetching {host}\n')
- # 跟服务器建立连接
- reader, writer = await asyncio.open_connection(host, 80)
- # 构造请求行和请求头
- writer.write(b'GET / HTTP/1.1\r\n')
- writer.write(f'Host: {host}\r\n'.encode())
- writer.write(b'\r\n')
- # 清空缓存区(发送请求)
- await writer.drain()
- # 接收服务器的响应(读取响应行和响应头)
- line = await reader.readline()
- while line != b'\r\n':
- print(line.decode().rstrip())
- line = await reader.readline()
- print('\n')
- writer.close()
-
-
- def main():
- """主函数"""
- urls = ('www.sohu.com', 'www.douban.com', 'www.163.com')
- # 获取系统默认的事件循环
- loop = asyncio.get_event_loop()
- # 用生成式语法构造一个包含多个协程对象的列表
- tasks = [fetch(url) for url in urls]
- # 通过asyncio模块的wait函数将协程列表包装成Task(Future子类)并等待其执行完成
- # 通过事件循环的run_until_complete方法运行任务直到Future完成并返回它的结果
- loop.run_until_complete(asyncio.wait(tasks))
- loop.close()
-
-
- if __name__ == '__main__':
- main()
- ```
-
- > 说明:目前大多数网站都要求基于HTTPS通信,因此上面例子中的网络请求不一定能收到正常的响应,也就是说响应状态码不一定是200,有可能是3xx或者4xx。当然我们这里的重点不在于获得网站响应的内容,而是帮助大家理解`asyncio`模块以及`async`和`await`两个关键字的使用。
-
-我们对三种方式的使用场景做一个简单的总结。
-
-以下情况需要使用多线程:
-
-1. 程序需要维护许多共享的状态(尤其是可变状态),Python中的列表、字典、集合都是线程安全的,所以使用线程而不是进程维护共享状态的代价相对较小。
-2. 程序会花费大量时间在I/O操作上,没有太多并行计算的需求且不需占用太多的内存。
-
-以下情况需要使用多进程:
-
-1. 程序执行计算密集型任务(如:字节码操作、数据处理、科学计算)。
-2. 程序的输入可以并行的分成块,并且可以将运算结果合并。
-3. 程序在内存使用方面没有任何限制且不强依赖于I/O操作(如:读写文件、套接字等)。
-
-最后,如果程序不需要真正的并发性或并行性,而是更多的依赖于异步处理和回调时,异步I/O就是一种很好的选择。另一方面,当程序中有大量的等待与休眠时,也应该考虑使用异步I/O。
-
-> 扩展:关于进程,还需要做一些补充说明。首先,为了控制进程的执行,操作系统内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程使之继续执行,这种行为被称为进程切换(也叫调度)。进程切换是比较耗费资源的操作,因为在进行切换时首先要保存当前进程的上下文(内核再次唤醒该进程时所需要的状态,包括:程序计数器、状态寄存器、数据栈等),然后还要恢复准备执行的进程的上下文。正在执行的进程由于期待的某些事件未发生,如请求系统资源失败、等待某个操作完成、新数据尚未到达等原因会主动由运行状态变为阻塞状态,当进程进入阻塞状态,是不占用CPU资源的。这些知识对于理解到底选择哪种方式进行并发编程也是很重要的。
-
-### I/O模式和事件驱动
-
-对于一次I/O操作(以读操作为例),数据会先被拷贝到操作系统内核的缓冲区中,然后从操作系统内核的缓冲区拷贝到应用程序的缓冲区(这种方式称为标准I/O或缓存I/O,大多数文件系统的默认I/O都是这种方式),最后交给进程。所以说,当一个读操作发生时(写操作与之类似),它会经历两个阶段:(1)等待数据准备就绪;(2)将数据从内核拷贝到进程中。
-
-由于存在这两个阶段,因此产生了以下几种I/O模式:
-
-1. 阻塞 I/O(blocking I/O):进程发起读操作,如果内核数据尚未就绪,进程会阻塞等待数据直到内核数据就绪并拷贝到进程的内存中。
-2. 非阻塞 I/O(non-blocking I/O):进程发起读操作,如果内核数据尚未就绪,进程不阻塞而是收到内核返回的错误信息,进程收到错误信息可以再次发起读操作,一旦内核数据准备就绪,就立即将数据拷贝到了用户内存中,然后返回。
-3. 多路I/O复用( I/O multiplexing):监听多个I/O对象,当I/O对象有变化(数据就绪)的时候就通知用户进程。多路I/O复用的优势并不在于单个I/O操作能处理得更快,而是在于能处理更多的I/O操作。
-4. 异步 I/O(asynchronous I/O):进程发起读操作后就可以去做别的事情了,内核收到异步读操作后会立即返回,所以用户进程不阻塞,当内核数据准备就绪时,内核发送一个信号给用户进程,告诉它读操作完成了。
-
-通常,我们编写一个处理用户请求的服务器程序时,有以下三种方式可供选择:
-
-1. 每收到一个请求,创建一个新的进程,来处理该请求;
-2. 每收到一个请求,创建一个新的线程,来处理该请求;
-3. 每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
-
-第1种方式实现比较简单,但由于创建进程开销比较大,会导致服务器性能比较差;第2种方式,由于要涉及到线程的同步,有可能会面临竞争、死锁等问题;第3种方式,就是所谓事件驱动的方式,它利用了多路I/O复用和异步I/O的优点,虽然代码逻辑比前面两种都复杂,但能达到最好的性能,这也是目前大多数网络服务器采用的方式。
diff --git a/Day61-65/62.Tornado入门.md b/Day61-65/62.Tornado入门.md
deleted file mode 100644
index e1249f8..0000000
--- a/Day61-65/62.Tornado入门.md
+++ /dev/null
@@ -1,377 +0,0 @@
-## Tornado入门
-
-### Tornado概述
-
-Python的Web框架种类繁多(比Python语言的关键字还要多),但在众多优秀的Web框架中,Tornado框架最适合用来开发需要处理长连接和应对高并发的Web应用。Tornado框架在设计之初就考虑到性能问题,通过对非阻塞I/O和epoll(Linux 2.5.44内核引入的一种多路I/O复用方式,旨在实现高性能网络服务,在BSD和macOS中是kqueue)的运用,Tornado可以处理大量的并发连接,更轻松的应对C10K(万级并发)问题,是非常理想的实时通信Web框架。
-
-> 扩展:基于线程的Web服务器产品(如:Apache)会维护一个线程池来处理用户请求,当用户请求到达时就为该请求分配一个线程,如果线程池中没有空闲线程了,那么可以通过创建新的线程来应付新的请求,但前提是系统尚有空闲的内存空间,显然这种方式很容易将服务器的空闲内存耗尽(大多数Linux发行版本中,默认的线程栈大小为8M)。想象一下,如果我们要开发一个社交类应用,这类应用中,通常需要显示实时更新的消息、对象状态的变化和各种类型的通知,那也就意味着客户端需要保持请求连接来接收服务器的各种响应,在这种情况下,服务器上的工作线程很容易被耗尽,这也就意味着新的请求很有可能无法得到响应。
-
-Tornado框架源于FriendFeed网站,在FriendFeed网站被Facebook收购之后得以开源,正式发布的日期是2009年9月10日。Tornado能让你能够快速开发高速的Web应用,如果你想编写一个可扩展的社交应用、实时分析引擎,或RESTful API,那么Tornado框架就是很好的选择。Tornado其实不仅仅是一个Web开发的框架,它还是一个高性能的事件驱动网络访问引擎,内置了高性能的HTTP服务器和客户端(支持同步和异步请求),同时还对WebSocket提供了完美的支持。
-
-了解和学习Tornado最好的资料就是它的官方文档,在[tornadoweb.org](http://www.tornadoweb.org)上面有很多不错的例子,你也可以在Github上找到Tornado的源代码和历史版本。
-
-### 5分钟上手Tornado
-
-1. 创建并激活虚拟环境。
-
- ```Shell
- mkdir hello-tornado
- cd hello-tornado
- python3 -m venv venv
- source venv/bin/activate
- ```
-
-2. 安装Tornado。
-
- ```Shell
- pip install tornado
- ```
-
-3. 编写Web应用。
-
- ```Python
- """
- example01.py
- """
- import tornado.ioloop
- import tornado.web
-
-
- class MainHandler(tornado.web.RequestHandler):
-
- def get(self):
- self.write('Hello, world! ')
-
-
- def main():
- app = tornado.web.Application(handlers=[(r'/', MainHandler), ])
- app.listen(8888)
- tornado.ioloop.IOLoop.current().start()
-
-
- if __name__ == '__main__':
- main()
- ```
-
-4. 运行并访问应用。
-
- ```Shell
- python example01.py
- ```
-
- 
-
-在上面的例子中,代码example01.py通过定义一个继承自`RequestHandler`的类(`MainHandler`)来处理用户请求,当请求到达时,Tornado会实例化这个类(创建`MainHandler`对象),并调用与HTTP请求方法(GET、POST等)对应的方法,显然上面的`MainHandler`只能处理GET请求,在收到GET请求时,它会将一段HTML的内容写入到HTTP响应中。`main`函数的第1行代码创建了Tornado框架中`Application`类的实例,它代表了我们的Web应用,而创建该实例最为重要的参数就是`handlers`,该参数告知`Application`对象,当收到一个请求时应该通过哪个类的对象来处理这个请求。在上面的例子中,当通过HTTP的GET请求访问站点根路径时,就会调用`MainHandler`的`get`方法。 `main`函数的第2行代码通过`Application`对象的`listen`方法指定了监听HTTP请求的端口。`main`函数的第3行代码用于获取Tornado框架的`IOLoop`实例并启动它,该实例代表一个条件触发的I/O循环,用于持续的接收来自于客户端的请求。
-
-> 扩展:在Python 3中,`IOLoop`实例的本质就是`asyncio`的事件循环,该事件循环在非Windows系统中就是`SelectorEventLoop`对象,它基于`selectors`模块(高级I/O复用模块),会使用当前操作系统最高效的I/O复用选择器,例如在Linux环境下它使用`EpollSelector`,而在macOS和BSD环境下它使用的是`KqueueSelector`;在Python 2中,`IOLoop`直接使用`select`模块(低级I/O复用模块)的`epoll`或`kqueue`函数,如果这两种方式都不可用,则调用`select`函数实现多路I/O复用。当然,如果要支持高并发,你的系统最好能够支持epoll或者kqueue这两种多路I/O复用方式中的一种。
-
-如果希望通过命令行参数来指定Web应用的监听端口,可以对上面的代码稍作修改。
-
-```Python
-"""
-example01.py
-"""
-import tornado.ioloop
-import tornado.web
-
-from tornado.options import define, options, parse_command_line
-
-
-# 定义默认端口
-define('port', default=8000, type=int)
-
-
-class MainHandler(tornado.web.RequestHandler):
-
- def get(self):
- self.write('Hello, world! ')
-
-
-def main():
- # python example01.py --port=8000
- parse_command_line()
- app = tornado.web.Application(handlers=[(r'/', MainHandler), ])
- app.listen(options.port)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
-```
-
-在启动Web应用时,如果没有指定端口,将使用`define`函数中设置的默认端口8000,如果要指定端口,可以使用下面的方式来启动Web应用。
-
-```Shell
-python example01.py --port=8000
-```
-
-### 路由解析
-
-上面我们曾经提到过创建`Application`实例时需要指定`handlers`参数,这个参数非常重要,它应该是一个元组的列表,元组中的第一个元素是正则表达式,它用于匹配用户请求的资源路径;第二个元素是`RequestHandler`的子类。在刚才的例子中,我们只在`handlers`列表中放置了一个元组,事实上我们可以放置多个元组来匹配不同的请求(资源路径),而且可以使用正则表达式的捕获组来获取匹配的内容并将其作为参数传入到`get`、`post`这些方法中。
-
-```Python
-"""
-example02.py
-"""
-import os
-import random
-
-import tornado.ioloop
-import tornado.web
-
-from tornado.options import define, options, parse_command_line
-
-
-# 定义默认端口
-define('port', default=8000, type=int)
-
-
-class SayingHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- sayings = [
- '世上没有绝望的处境,只有对处境绝望的人',
- '人生的道路在态度的岔口一分为二,从此通向成功或失败',
- '所谓措手不及,不是说没有时间准备,而是有时间的时候没有准备',
- '那些你认为不靠谱的人生里,充满你没有勇气做的事',
- '在自己喜欢的时间里,按照自己喜欢的方式,去做自己喜欢做的事,这便是自由',
- '有些人不属于自己,但是遇见了也弥足珍贵'
- ]
- # 渲染index.html模板页
- self.render('index.html', message=random.choice(sayings))
-
-
-class WeatherHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self, city):
- # Tornado框架会自动处理百分号编码的问题
- weathers = {
- '北京': {'temperature': '-4~4', 'pollution': '195 中度污染'},
- '成都': {'temperature': '3~9', 'pollution': '53 良'},
- '深圳': {'temperature': '20~25', 'pollution': '25 优'},
- '广州': {'temperature': '18~23', 'pollution': '56 良'},
- '上海': {'temperature': '6~8', 'pollution': '65 良'}
- }
- if city in weathers:
- self.render('weather.html', city=city, weather=weathers[city])
- else:
- self.render('index.html', message=f'没有{city}的天气信息')
-
-
-class ErrorHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- # 重定向到指定的路径
- self.redirect('/saying')
-
-
-def main():
- """主函数"""
- parse_command_line()
- app = tornado.web.Application(
- # handlers是按列表中的顺序依次进行匹配的
- handlers=[
- (r'/saying/?', SayingHandler),
- (r'/weather/([^/]{2,})/?', WeatherHandler),
- (r'/.+', ErrorHandler),
- ],
- # 通过template_path参数设置模板页的路径
- template_path=os.path.join(os.path.dirname(__file__), 'templates')
- )
- app.listen(options.port)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
-```
-
-模板页index.html。
-
-```HTML
-
-
-
-
-
- Tornado基础
-
-
- {{message}}
-
-
-```
-
-模板页weather.html。
-
-```HTML
-
-
-
-
-
- Tornado基础
-
-
- {{city}}
-
- 温度:{{weather['temperature']}}摄氏度
- 污染指数:{{weather['pollution']}}
-
-
-```
-
-Tornado的模板语法与其他的Web框架中使用的模板语法并没有什么实质性的区别,而且目前的Web应用开发更倡导使用前端渲染的方式来减轻服务器的负担,所以这里我们并不对模板语法和后端渲染进行深入的讲解。
-
-### 请求处理器
-
-通过上面的代码可以看出,`RequestHandler`是处理用户请求的核心类,通过重写`get`、`post`、`put`、`delete`等方法可以处理不同类型的HTTP请求,除了这些方法之外,`RequestHandler`还实现了很多重要的方法,下面是部分方法的列表:
-
-1. `get_argument` / `get_arguments` / `get_body_argument` / `get_body_arguments` / `get_query_arugment` / `get_query_arguments`:获取请求参数。
-2. `set_status` / `send_error` / `set_header` / `add_header` / `clear_header` / `clear`:操作状态码和响应头。
-3. `write` / `flush` / `finish` / `write_error`:和输出相关的方法。
-4. `render` / `render_string`:渲染模板。
-5. `redirect`:请求重定向。
-6. `get_cookie` / `set_cookie` / `get_secure_cookie` / `set_secure_cookie` / `create_signed_value` / `clear_cookie` / `clear_all_cookies`:操作Cookie。
-
-我们用上面讲到的这些方法来完成下面的需求,访问页面时,如果Cookie中没有读取到用户信息则要求用户填写个人信息,如果从Cookie中读取到用户信息则直接显示用户信息。
-
-```Python
-"""
-example03.py
-"""
-import os
-import re
-
-import tornado.ioloop
-import tornado.web
-
-from tornado.options import define, options, parse_command_line
-
-
-# 定义默认端口
-define('port', default=8000, type=int)
-
-users = {}
-
-
-class User(object):
- """用户"""
-
- def __init__(self, nickname, gender, birthday):
- self.nickname = nickname
- self.gender = gender
- self.birthday = birthday
-
-
-class MainHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- # 从Cookie中读取用户昵称
- nickname = self.get_cookie('nickname')
- if nickname in users:
- self.render('userinfo.html', user=users[nickname])
- else:
- self.render('userform.html', hint='请填写个人信息')
-
-
-class UserHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def post(self):
- # 从表单参数中读取用户昵称、性别和生日信息
- nickname = self.get_body_argument('nickname').strip()
- gender = self.get_body_argument('gender')
- birthday = self.get_body_argument('birthday')
- # 检查用户昵称是否有效
- if not re.fullmatch(r'\w{6,20}', nickname):
- self.render('userform.html', hint='请输入有效的昵称')
- elif nickname in users:
- self.render('userform.html', hint='昵称已经被使用过')
- else:
- users[nickname] = User(nickname, gender, birthday)
- # 将用户昵称写入Cookie并设置有效期为7天
- self.set_cookie('nickname', nickname, expires_days=7)
- self.render('userinfo.html', user=users[nickname])
-
-
-def main():
- """主函数"""
- parse_command_line()
- app = tornado.web.Application(
- handlers=[
- (r'/', MainHandler), (r'/register', UserHandler)
- ],
- template_path=os.path.join(os.path.dirname(__file__), 'templates')
- )
- app.listen(options.port)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
-```
-
-模板页userform.html。
-
-```HTML
-
-
-
-
-
- Tornado基础
-
-
-
- 填写用户信息
-
- {{hint}}
-
-
-
-```
-
-模板页userinfo.html。
-
-```HTML
-
-
-
-
-
- Tornado基础
-
-
- 用户信息
-
- 昵称:{{user.nickname}}
- 性别:{{user.gender}}
- 出生日期:{{user.birthday}}
-
-
-```
diff --git a/Day66-75/67.数据采集和解析.md b/Day61-65/62.数据采集和解析.md
similarity index 55%
rename from Day66-75/67.数据采集和解析.md
rename to Day61-65/62.数据采集和解析.md
index 52227ae..e8caf86 100644
--- a/Day66-75/67.数据采集和解析.md
+++ b/Day61-65/62.数据采集和解析.md
@@ -2,12 +2,12 @@
通过上一个章节的讲解,我们已经了解到了开发一个爬虫需要做的工作以及一些常见的问题,下面我们给出一个爬虫开发相关技术的清单以及这些技术涉及到的标准库和第三方库,稍后我们会一一介绍这些内容。
-1. 下载数据 - **urllib** / **requests** / **aiohttp**。
+1. 下载数据 - **urllib** / **requests** / **aiohttp** / **httpx**。
2. 解析数据 - **re** / **lxml** / **beautifulsoup4** / **pyquery**。
-3. 缓存和持久化 - **pymysql** / **sqlalchemy** / **peewee**/ **redis** / **pymongo**。
+3. 缓存和持久化 - **mysqlclient** / **sqlalchemy** / **peewee** / **redis** / **pymongo**。
4. 生成数字签名 - **hashlib**。
5. 序列化和压缩 - **pickle** / **json** / **zlib**。
-6. 调度器 - 多进程(**multiprocessing**) / 多线程(**threading**)。
+6. 调度器 - **multiprocessing** / **threading** / **concurrent.futures**。
### HTML页面
@@ -79,47 +79,93 @@
```
-如果你对上面的代码并不感到陌生,那么你一定知道HTML页面通常由三部分构成,分别是用来承载内容的Tag(标签)、负责渲染页面的CSS(层叠样式表)以及控制交互式行为的JavaScript。通常,我们可以在浏览器的右键菜单中通过“查看网页源代码”的方式获取网页的代码并了解页面的结构;当然,我们也可以通过浏览器提供的开发人员工具来了解更多的信息。
+如上所示的HTML页面通常由三部分构成,分别是用来承载内容的Tag(标签)、负责渲染页面的CSS(层叠样式表)以及控制交互式行为的JavaScript。通常,我们可以在浏览器的右键菜单中通过“查看网页源代码”的方式获取网页的代码并了解页面的结构;当然,我们也可以通过浏览器提供的开发人员工具来了解更多的信息。
#### 使用requests获取页面
+在上一节课的代码中我们使用了三方库`requests`来获取页面,下面我们对`requests`库的用法做进一步说明。
+
1. GET请求和POST请求。
```Python
+ import requests
+ resp = requests.get('http://www.baidu.com/index.html')
+ print(resp.status_code)
+ print(resp.headers)
+ print(resp.cookies)
+ print(resp.content.decode('utf-8'))
+
+ resp = requests.post('http://httpbin.org/post', data={'name': 'Hao', 'age': 40})
+ print(resp.text)
+ data = resp.json()
+ print(type(data))
```
2. URL参数和请求头。
```Python
-
+ resp = requests.get(
+ url='https://movie.douban.com/top250',
+ headers={
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) '
+ 'AppleWebKit/537.36 (KHTML, like Gecko) '
+ 'Chrome/83.0.4103.97 Safari/537.36',
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;'
+ 'q=0.9,image/webp,image/apng,*/*;'
+ 'q=0.8,application/signed-exchange;v=b3;q=0.9',
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
+ }
+ )
+ print(resp.status_code)
```
3. 复杂的POST请求(文件上传)。
```Python
-
+ resp = requests.post(
+ url='http://httpbin.org/post',
+ files={'file': open('data.xlsx', 'rb')}
+ )
+ print(resp.text)
```
4. 操作Cookie。
```Python
+ cookies = {'key1': 'value1', 'key2': 'value2'}
+ resp = requests.get('http://httpbin.org/cookies', cookies=cookies)
+ print(resp.text)
+ jar = requests.cookies.RequestsCookieJar()
+ jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
+ jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
+ resp = requests.get('http://httpbin.org/cookies', cookies=jar)
+ print(resp.text)
```
5. 设置代理服务器。
```Python
-
+ requests.get('https://www.taobao.com', proxies={
+ 'http': 'http://10.10.1.10:3128',
+ 'https': 'http://10.10.1.10:1080',
+ })
```
+
+ > **说明**:关于`requests`库的相关知识,还是强烈建议大家自行阅读它的[官方文档](https://requests.readthedocs.io/zh_CN/latest/)。
+
+6. 设置请求超时。
-> 说明:关于requests的详细用法可以参考它的[官方文档](http://docs.python-requests.org/zh_CN/latest/user/quickstart.html)。
+ ```Python
+ requests.get('https://github.com', timeout=10)
+ ```
### 页面解析
@@ -131,13 +177,41 @@
| XPath解析 | lxml | 快 | 一般 | 需要安装C语言依赖库
唯一支持XML的解析器 |
| CSS选择器解析 | bs4 / pyquery | 不确定 | 简单 | |
-> 说明:BeautifulSoup可选的解析器包括:Python标准库(html.parser)、lxml的HTML解析器、lxml的XML解析器和html5lib。
+> **说明**:`BeautifulSoup`可选的解析器包括:Python标准库中的`html.parser`、`lxml`的HTML解析器、`lxml`的XML解析器和`html5lib`。
#### 使用正则表达式解析页面
-如果你对正则表达式没有任何的概念,那么推荐先阅读[《正则表达式30分钟入门教程》](),然后再阅读我们之前讲解在Python中如何使用正则表达式一文。
+如果你对正则表达式没有任何的概念,那么推荐先阅读[《正则表达式30分钟入门教程》](https://deerchao.cn/tutorials/regex/regex.htm),然后再阅读我们之前讲解在Python中如何使用正则表达式一文。
+下面的例子演示了如何用正则表达式解析“豆瓣电影Top250”中的中文电影名称。
+```Python
+import random
+import re
+import time
+
+import requests
+
+PATTERN = re.compile(r'
]*?>\s*(.*?) ')
+
+for page in range(10):
+ resp = requests.get(
+ url=f'https://movie.douban.com/top250?start={page * 25}',
+ headers={
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) '
+ 'AppleWebKit/537.36 (KHTML, like Gecko) '
+ 'Chrome/83.0.4103.97 Safari/537.36',
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;'
+ 'q=0.9,image/webp,image/apng,*/*;'
+ 'q=0.8,application/signed-exchange;v=b3;q=0.9',
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
+ },
+ )
+ items = PATTERN.findall(resp.text)
+ for item in items:
+ print(item)
+ time.sleep(random.randint(1, 5))
+```
#### XPath解析和lxml
@@ -196,13 +270,37 @@ XPath还支持通配符用法,如下所示。
| //title \| //price | 选取文档中的所有 title 和 price 元素。 |
| /bookstore/book/title \| //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
-> 说明:上面的例子来自于菜鸟教程网站上[XPath教程](),有兴趣的读者可以自行阅读原文。
+> **说明**:上面的例子来自于菜鸟教程网站上[XPath教程](),有兴趣的读者可以自行阅读原文。
当然,如果不理解或者不太熟悉XPath语法,可以在Chrome浏览器中按照如下所示的方法查看元素的XPath语法。

+下面的例子演示了如何用XPath解析“豆瓣电影Top250”中的中文电影名称。
+```Python
+from lxml import etree
+
+import requests
+
+for page in range(10):
+ resp = requests.get(
+ url=f'https://movie.douban.com/top250?start={page * 25}',
+ headers={
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) '
+ 'AppleWebKit/537.36 (KHTML, like Gecko) '
+ 'Chrome/83.0.4103.97 Safari/537.36',
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;'
+ 'q=0.9,image/webp,image/apng,*/*;'
+ 'q=0.8,application/signed-exchange;v=b3;q=0.9',
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
+ }
+ )
+ html = etree.HTML(resp.text)
+ spans = html.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li/div/div[2]/div[1]/a/span[1]')
+ for span in spans:
+ print(span.text)
+```
### BeautifulSoup的使用
@@ -219,42 +317,63 @@ BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库。它
- find / find_all
- select_one / select
-> 说明:更多内容可以参考BeautifulSoup的[官方文档](https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html)。
+> **说明**:更多内容可以参考BeautifulSoup的[官方文档](https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/)。
-### PyQuery的使用
-
-pyquery相当于jQuery的Python实现,可以用于解析HTML网页。
-
-### 实例 - 获取知乎发现上的问题链接
+下面的例子演示了如何用CSS选择器解析“豆瓣电影Top250”中的中文电影名称。
```Python
-from urllib.parse import urljoin
+import random
+import time
-import re
+import bs4
import requests
-from bs4 import BeautifulSoup
+for page in range(10):
+ resp = requests.get(
+ url=f'https://movie.douban.com/top250?start={page * 25}',
+ headers={
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) '
+ 'AppleWebKit/537.36 (KHTML, like Gecko) '
+ 'Chrome/83.0.4103.97 Safari/537.36',
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;'
+ 'q=0.9,image/webp,image/apng,*/*;'
+ 'q=0.8,application/signed-exchange;v=b3;q=0.9',
+ 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
+ },
+ )
+ soup = bs4.BeautifulSoup(resp.text, 'lxml')
+ elements = soup.select('.info>div>a')
+ for element in elements:
+ span = element.select_one('.title')
+ print(span.text)
+ time.sleep(random.random() * 5)
+
+```
+
+### 例子 - 获取知乎发现上的问题链接
+
+```Python
+import re
+from urllib.parse import urljoin
+
+import bs4
+import requests
def main():
headers = {'user-agent': 'Baiduspider'}
- proxies = {
- 'http': 'http://122.114.31.177:808'
- }
base_url = 'https://www.zhihu.com/'
- seed_url = urljoin(base_url, 'explore')
- resp = requests.get(seed_url,
- headers=headers,
- proxies=proxies)
- soup = BeautifulSoup(resp.text, 'lxml')
+ resp = requests.get(urljoin(base_url, 'explore'), headers=headers)
+ soup = bs4.BeautifulSoup(resp.text, 'lxml')
href_regex = re.compile(r'^/question')
- link_set = set()
+ links_set = set()
for a_tag in soup.find_all('a', {'href': href_regex}):
if 'href' in a_tag.attrs:
href = a_tag.attrs['href']
full_url = urljoin(base_url, href)
- link_set.add(full_url)
- print('Total %d question pages found.' % len(link_set))
+ links_set.add(full_url)
+ print('Total %d question pages found.' % len(links_set))
+ print(links_set)
if __name__ == '__main__':
diff --git a/Day61-65/63.存储数据.md b/Day61-65/63.存储数据.md
new file mode 100644
index 0000000..9857293
--- /dev/null
+++ b/Day61-65/63.存储数据.md
@@ -0,0 +1,118 @@
+## 存储数据
+
+### 存储海量数据
+
+数据持久化的首选方案应该是关系型数据库,关系型数据库的产品很多,包括:Oracle、MySQL、SQLServer、PostgreSQL等。如果要存储海量的低价值数据,文档数据库也是不错的选择,MongoDB是文档数据库中的佼佼者,有兴趣的读者可以自行研究。
+
+下面的代码演示了如何使用MySQL来保存从知乎发现上爬取到的链接和页面。
+
+```SQL
+create database zhihu default charset utf8;
+create user 'hellokitty'@'%' identified by 'Hellokitty.618';
+grant all privileges on zhihu.* to 'hellokitty'@'%';
+flush privileges;
+
+use zhihu;
+create table `tb_explore`
+(
+ `id` integer auto_increment,
+ `url` varchar(1024) not null,
+ `page` longblob not null,
+ `digest` char(48) unique not null,
+ `idate` datetime default now(),
+ primary key (`id`)
+);
+```
+
+```Python
+import hashlib
+import pickle
+import re
+import zlib
+from urllib.parse import urljoin
+
+import MySQLdb
+import bs4
+import requests
+
+conn = MySQLdb.connect(host='1.2.3.4', port=3306,
+ user='hellokitty', password='Hellokitty.618',
+ database='zhihu', charset='utf8',
+ autocommit=True)
+
+
+def write_to_db(url, page, digest):
+ try:
+ with conn.cursor() as cursor:
+ cursor.execute(
+ 'insert into tb_explore (url, page, digest) values (%s, %s, %s) ',
+ (url, page, digest)
+ )
+ except MySQLdb.MySQLError as err:
+ print(err)
+
+
+def main():
+ base_url = 'https://www.zhihu.com/'
+ seed_url = urljoin(base_url, 'explore')
+ headers = {'user-agent': 'Baiduspider'}
+ try:
+ resp = requests.get(seed_url, headers=headers)
+ soup = bs4.BeautifulSoup(resp.text, 'lxml')
+ href_regex = re.compile(r'^/question')
+ for a_tag in soup.find_all('a', {'href': href_regex}):
+ href = a_tag.attrs['href']
+ full_url = urljoin(base_url, href)
+ digest = hashlib.sha1(full_url.encode()).hexdigest()
+ html_page = requests.get(full_url, headers=headers).text
+ zipped_page = zlib.compress(pickle.dumps(html_page))
+ write_to_db(full_url, zipped_page, digest)
+ finally:
+ conn.close()
+
+
+if __name__ == '__main__':
+ main()
+```
+
+### 数据缓存
+
+通过[《网络数据采集和解析》](./67.数据采集和解析.md)一文,我们已经知道了如何从指定的页面中抓取数据,以及如何保存抓取的结果,但是我们没有考虑过这么一种情况,就是我们可能需要从已经抓取过的页面中提取出更多的数据,重新去下载这些页面对于规模不大的网站倒是问题也不大,但是如果能够把这些页面缓存起来,对应用的性能会有明显的改善。下面的例子演示了如何使用Redis来缓存知乎发现上的页面。
+
+```Python
+import hashlib
+import pickle
+import re
+import zlib
+from urllib.parse import urljoin
+
+import bs4
+import redis
+import requests
+
+
+def main():
+ base_url = 'https://www.zhihu.com/'
+ seed_url = urljoin(base_url, 'explore')
+ client = redis.Redis(host='1.2.3.4', port=6379, password='1qaz2wsx')
+ headers = {'user-agent': 'Baiduspider'}
+ resp = requests.get(seed_url, headers=headers)
+ soup = bs4.BeautifulSoup(resp.text, 'lxml')
+ href_regex = re.compile(r'^/question')
+ for a_tag in soup.find_all('a', {'href': href_regex}):
+ href = a_tag.attrs['href']
+ full_url = urljoin(base_url, href)
+ field_key = hashlib.sha1(full_url.encode()).hexdigest()
+ if not client.hexists('spider:zhihu:explore', field_key):
+ html_page = requests.get(full_url, headers=headers).text
+ zipped_page = zlib.compress(pickle.dumps(html_page))
+ client.hset('spider:zhihu:explore', field_key, zipped_page)
+ print('Total %d question pages found.' % client.hlen('spider:zhihu:explore'))
+
+
+if __name__ == '__main__':
+ main()
+```
+
+
+
diff --git a/Day61-65/63.异步化.md b/Day61-65/63.异步化.md
deleted file mode 100644
index 07963ca..0000000
--- a/Day61-65/63.异步化.md
+++ /dev/null
@@ -1,152 +0,0 @@
-## 异步化
-
-在前面的例子中,我们并没有对`RequestHandler`中的`get`或`post`方法进行异步处理,这就意味着,一旦在`get`或`post`方法中出现了耗时间的操作,不仅仅是当前请求被阻塞,按照Tornado框架的工作模式,其他的请求也会被阻塞,所以我们需要对耗时间的操作进行异步化处理。
-
-在Tornado稍早一些的版本中,可以用装饰器实现请求方法的异步化或协程化来解决这个问题。
-
-- 给`RequestHandler`的请求处理函数添加`@tornado.web.asynchronous`装饰器,如下所示:
-
- ```Python
- class AsyncReqHandler(RequestHandler):
-
- @tornado.web.asynchronous
- def get(self):
- http = httpclient.AsyncHTTPClient()
- http.fetch("http://example.com/", self._on_download)
-
- def _on_download(self, response):
- do_something_with_response(response)
- self.render("template.html")
- ```
-
-- 给`RequestHandler`的请求处理函数添加`@tornado.gen.coroutine`装饰器,如下所示:
-
- ```Python
- class GenAsyncHandler(RequestHandler):
-
- @tornado.gen.coroutine
- def get(self):
- http_client = AsyncHTTPClient()
- response = yield http_client.fetch("http://example.com")
- do_something_with_response(response)
- self.render("template.html")
- ```
-
-- 使用`@return_future`装饰器,如下所示:
-
- ```Python
- @return_future
- def future_func(arg1, arg2, callback):
- # Do stuff (possibly asynchronous)
- callback(result)
-
- async def caller():
- await future_func(arg1, arg2)
- ```
-
-在Tornado 5.x版本中,这几个装饰器都被标记为**deprcated**(过时),我们可以通过Python 3.5中引入的`async`和`await`(在Python 3.7中已经成为正式的关键字)来达到同样的效果。当然,要实现异步化还得靠其他的支持异步操作的三方库来支持,如果请求处理函数中用到了不支持异步操作的三方库,就需要靠自己写包装类来支持异步化。
-
-下面的代码演示了在读写数据库时如何实现请求处理的异步化。我们用到的数据库建表语句如下所示:
-
-```SQL
-create database hrs default charset utf8;
-
-use hrs;
-
-/* 创建部门表 */
-create table tb_dept
-(
- dno int not null comment '部门编号',
- dname varchar(10) not null comment '部门名称',
- dloc varchar(20) not null comment '部门所在地',
- primary key (dno)
-);
-
-insert into tb_dept values
- (10, '会计部', '北京'),
- (20, '研发部', '成都'),
- (30, '销售部', '重庆'),
- (40, '运维部', '深圳');
-```
-
-我们通过下面的代码实现了查询和新增部门两个操作。
-
-```Python
-import json
-
-import aiomysql
-import tornado
-import tornado.web
-
-from tornado.ioloop import IOLoop
-from tornado.options import define, parse_command_line, options
-
-define('port', default=8000, type=int)
-
-
-async def connect_mysql():
- return await aiomysql.connect(
- host='120.77.222.217',
- port=3306,
- db='hrs',
- user='root',
- password='123456',
- )
-
-
-class HomeHandler(tornado.web.RequestHandler):
-
- async def get(self, no):
- async with self.settings['mysql'].cursor(aiomysql.DictCursor) as cursor:
- await cursor.execute("select * from tb_dept where dno=%s", (no, ))
- if cursor.rowcount == 0:
- self.finish(json.dumps({
- 'code': 20001,
- 'mesg': f'没有编号为{no}的部门'
- }))
- return
- row = await cursor.fetchone()
- self.finish(json.dumps(row))
-
- async def post(self, *args, **kwargs):
- no = self.get_argument('no')
- name = self.get_argument('name')
- loc = self.get_argument('loc')
- conn = self.settings['mysql']
- try:
- async with conn.cursor() as cursor:
- await cursor.execute('insert into tb_dept values (%s, %s, %s)',
- (no, name, loc))
- await conn.commit()
- except aiomysql.MySQLError:
- self.finish(json.dumps({
- 'code': 20002,
- 'mesg': '添加部门失败请确认部门信息'
- }))
- else:
- self.set_status(201)
- self.finish()
-
-
-def make_app(config):
- return tornado.web.Application(
- handlers=[(r'/api/depts/(.*)', HomeHandler), ],
- **config
- )
-
-
-def main():
- parse_command_line()
- app = make_app({
- 'debug': True,
- 'mysql': IOLoop.current().run_sync(connect_mysql)
- })
- app.listen(options.port)
- IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
-```
-
-上面的代码中,我们用到了`aiomysql`这个三方库,它基于`pymysql`封装,实现了对MySQL操作的异步化。操作Redis可以使用`aioredis`,访问MongoDB可以使用`motor`,这些都是支持异步操作的三方库。
\ No newline at end of file
diff --git a/Day61-65/64.WebSocket的应用.md b/Day61-65/64.WebSocket的应用.md
deleted file mode 100644
index ef25c9e..0000000
--- a/Day61-65/64.WebSocket的应用.md
+++ /dev/null
@@ -1,228 +0,0 @@
-## WebSocket的应用
-
-Tornado的异步特性使其非常适合处理高并发的业务,同时也适合那些需要在客户端和服务器之间维持长连接的业务。传统的基于HTTP协议的Web应用,服务器和客户端(浏览器)的通信只能由客户端发起,这种单向请求注定了如果服务器有连续的状态变化,客户端(浏览器)是很难得知的。事实上,今天的很多Web应用都需要服务器主动向客户端(浏览器)发送数据,我们将这种通信方式称之为“推送”。过去很长一段时间,程序员都是用定时轮询(Polling)或长轮询(Long Polling)等方式来实现“推送”,但是这些都不是真正意义上的“推送”,而且浪费资源且效率低下。在HTML5时代,可以通过一种名为WebSocket的技术在服务器和客户端(浏览器)之间维持传输数据的长连接,这种方式可以实现真正的“推送”服务。
-
-### WebSocket简介
-
-WebSocket 协议在2008年诞生,2011年成为国际标准([RFC 6455](https://tools.ietf.org/html/rfc6455)),现在的浏览器都能够支持它,它可以实现浏览器和服务器之间的全双工通信。我们之前学习或了解过Python的Socket编程,通过Socket编程,可以基于TCP或UDP进行数据传输;而WebSocket与之类似,只不过它是基于HTTP来实现通信握手,使用TCP来进行数据传输。WebSocket的出现打破了HTTP请求和响应只能一对一通信的模式,也改变了服务器只能被动接受客户端请求的状况。目前有很多Web应用是需要服务器主动向客户端发送信息的,例如股票信息的网站可能需要向浏览器发送股票涨停通知,社交网站可能需要向用户发送好友上线提醒或聊天信息。
-
-
-
-WebSocket的特点如下所示:
-
-1. 建立在TCP协议之上,服务器端的实现比较容易。
-2. 与HTTP协议有着良好的兼容性,默认端口是80(WS)和443(WSS),通信握手阶段采用HTTP协议,能通过各种 HTTP 代理服务器(不容易被防火墙阻拦)。
-3. 数据格式比较轻量,性能开销小,通信高效。
-4. 可以发送文本,也可以发送二进制数据。
-5. 没有同源策略的限制,客户端(浏览器)可以与任意服务器通信。
-
-
-
-### WebSocket服务器端编程
-
-Tornado框架中有一个`tornado.websocket.WebSocketHandler`类专门用于处理来自WebSocket的请求,通过继承该类并重写`open`、`on_message`、`on_close` 等方法来处理WebSocket通信,下面我们对`WebSocketHandler`的核心方法做一个简单的介绍。
-
-1. `open(*args, **kwargs)`方法:建立新的WebSocket连接后,Tornado框架会调用该方法,该方法的参数与`RequestHandler`的`get`方法的参数类似,这也就意味着在`open`方法中可以执行获取请求参数、读取Cookie信息这样的操作。
-
-2. `on_message(message)`方法:建立WebSocket之后,当收到来自客户端的消息时,Tornado框架会调用该方法,这样就可以对收到的消息进行对应的处理,必须重写这个方法。
-
-3. `on_close()`方法:当WebSocket被关闭时,Tornado框架会调用该方法,在该方法中可以通过`close_code`和`close_reason`了解关闭的原因。
-
-4. `write_message(message, binary=False)`方法:将指定的消息通过WebSocket发送给客户端,可以传递utf-8字符序列或者字节序列,如果message是一个字典,将会执行JSON序列化。正常情况下,该方法会返回一个`Future`对象;如果WebSocket被关闭了,将引发`WebSocketClosedError`。
-
-5. `set_nodelay(value)`方法:默认情况下,因为TCP的Nagle算法会导致短小的消息被延迟发送,在考虑到交互性的情况下就要通过将该方法的参数设置为`True`来避免延迟。
-
-6. `close(code=None, reason=None)`方法:主动关闭WebSocket,可以指定状态码(详见[RFC 6455 7.4.1节](https://tools.ietf.org/html/rfc6455#section-7.4.1))和原因。
-
-### WebSocket客户端编程
-
-1. 创建WebSocket对象。
-
- ```JavaScript
- var webSocket = new WebSocket('ws://localhost:8000/ws');
- ```
-
- >说明:webSocket对象的readyState属性表示该对象当前状态,取值为CONNECTING-正在连接,OPEN-连接成功可以通信,CLOSING-正在关闭,CLOSED-已经关闭。
-
-2. 编写回调函数。
-
- ```JavaScript
- webSocket.onopen = function(evt) { webSocket.send('...'); };
- webSocket.onmessage = function(evt) { console.log(evt.data); };
- webSocket.onclose = function(evt) {};
- webSocket.onerror = function(evt) {};
- ```
-
- > 说明:如果要绑定多个事件回调函数,可以用addEventListener方法。另外,通过事件对象的data属性获得的数据可能是字符串,也有可能是二进制数据,可以通过webSocket对象的binaryType属性(blob、arraybuffer)或者通过typeof、instanceof运算符检查类型进行判定。
-
-### 项目:Web聊天室
-
-```Python
-"""
-handlers.py - 用户登录和聊天的处理器
-"""
-import tornado.web
-import tornado.websocket
-
-nicknames = set()
-connections = {}
-
-
-class LoginHandler(tornado.web.RequestHandler):
-
- def get(self):
- self.render('login.html', hint='')
-
- def post(self):
- nickname = self.get_argument('nickname')
- if nickname in nicknames:
- self.render('login.html', hint='昵称已被使用,请更换昵称')
- self.set_secure_cookie('nickname', nickname)
- self.render('chat.html')
-
-
-class ChatHandler(tornado.websocket.WebSocketHandler):
-
- def open(self):
- nickname = self.get_secure_cookie('nickname').decode()
- nicknames.add(nickname)
- for conn in connections.values():
- conn.write_message(f'~~~{nickname}进入了聊天室~~~')
- connections[nickname] = self
-
- def on_message(self, message):
- nickname = self.get_secure_cookie('nickname').decode()
- for conn in connections.values():
- if conn is not self:
- conn.write_message(f'{nickname}说:{message}')
-
- def on_close(self):
- nickname = self.get_secure_cookie('nickname').decode()
- del connections[nickname]
- nicknames.remove(nickname)
- for conn in connections.values():
- conn.write_message(f'~~~{nickname}离开了聊天室~~~')
-
-```
-
-```Python
-"""
-run_chat_server.py - 聊天服务器
-"""
-import os
-
-import tornado.web
-import tornado.ioloop
-
-from handlers import LoginHandler, ChatHandler
-
-
-if __name__ == '__main__':
- app = tornado.web.Application(
- handlers=[(r'/login', LoginHandler), (r'/chat', ChatHandler)],
- template_path=os.path.join(os.path.dirname(__file__), 'templates'),
- static_path=os.path.join(os.path.dirname(__file__), 'static'),
- cookie_secret='MWM2MzEyOWFlOWRiOWM2MGMzZThhYTk0ZDNlMDA0OTU=',
- )
- app.listen(8888)
- tornado.ioloop.IOLoop.current().start()
-```
-
-```HTML
-
-
-
-
-
- Tornado聊天室
-
-
-
-
-
-
-```
-
-```HTML
-
-
-
-
-
- Tornado聊天室
-
-
- 聊天室
-
-
-
-
-
-
-
-
-
- 退出聊天室
-
-
-
-
-
-```
-
diff --git a/Day66-75/69.并发下载.md b/Day61-65/64.并发下载.md
similarity index 64%
rename from Day66-75/69.并发下载.md
rename to Day61-65/64.并发下载.md
index a5c36c8..3b36f9c 100644
--- a/Day66-75/69.并发下载.md
+++ b/Day61-65/64.并发下载.md
@@ -1,14 +1,12 @@
## 并发下载
-### 多线程和多进程回顾
-
-在前面的[《进程和线程》](../Day01-15/Day13/进程和线程.md)一文中,我们已经对在Python中使用多进程和多线程实现并发编程进行了简明的讲解,在此我们补充几个知识点。
+### 多线程和多进程补充知识点
#### threading.local类
使用线程时最不愿意遇到的情况就是多个线程竞争资源,在这种情况下为了保证资源状态的正确性,我们可能需要对资源进行加锁保护的处理,这一方面会导致程序失去并发性,另外如果多个线程竞争多个资源时,还有可能因为加锁方式的不当导致[死锁](https://zh.wikipedia.org/wiki/%E6%AD%BB%E9%94%81)。要解决多个线程竞争资源的问题,其中一个方案就是让每个线程都持有资源的副本(拷贝),这样每个线程可以操作自己所持有的资源,从而规避对资源的竞争。
-要实现将资源和持有资源的线程进行绑定的操作,最简单的做法就是使用threading模块的local类,在网络爬虫开发中,就可以使用local类为每个线程绑定一个MySQL数据库连接或Redis客户端对象,这样通过线程可以直接获得这些资源,既解决了资源竞争的问题,又避免了在函数和方法调用时传递这些资源。具体的请参考本章多线程爬取“手机搜狐网”(Redis版)的实例代码。
+要实现将资源和持有资源的线程进行绑定的操作,最简单的做法就是使用`threading`模块的`local`类,在网络爬虫开发中,就可以使用`local`类为每个线程绑定一个MySQL数据库连接或Redis客户端对象,这样通过线程可以直接获得这些资源,既解决了资源竞争的问题,又避免了在函数和方法调用时传递这些资源。具体的请参考本章多线程爬取“手机搜狐网”(Redis版)的实例代码。
#### concurrent.futures模块
@@ -29,7 +27,7 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
1. 执行效率极高,因为子程序(函数)切换不是线程切换,由程序自身控制,没有切换线程的开销。
2. 不需要多线程的锁机制,因为只有一个线程,也不存在竞争资源的问题,当然也就不需要对资源加锁保护,因此执行效率高很多。
-> 说明:协程适合处理的是I/O密集型任务,处理CPU密集型任务并不是它的长处,如果要提升CPU的利用率可以考虑“多进程+协程”的模式。
+> **说明**:协程适合处理的是I/O密集型任务,处理CPU密集型任务并不是它擅长的,如果要提升CPU的利用率可以考虑“多进程+多线程”或者“多进程+协程”的工作模式。
#### 历史回顾
@@ -39,176 +37,39 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
4. Python 3.4:引入`asyncio.coroutine`装饰器用来标记作为协程的函数,协程函数和`asyncio`及其事件循环一起使用,来实现异步I/O操作。
5. Python 3.5:引入了`async`和`await`,可以使用`async def`来定义一个协程函数,这个函数中不能包含任何形式的`yield`语句,但是可以使用`return`或`await`从协程中返回值。
-#### 示例代码
+协程实现了协作式并发,通过提高CPU的利用率来达到改善性能的目的。著名的三方库[`aiohttp`](https://github.com/aio-libs/aiohttp)就是通过协程的方式实现了HTTP客户端和HTTP服务器的功能,较之`requests`有更好的获取数据的性能,有兴趣可以阅读它的[官方文档](https://aiohttp.readthedocs.io/en/stable/)。
-1. 生成器 - 数据的生产者。
+```Python
+import asyncio
+import aiohttp
- ```Python
- from time import sleep
-
-
- # 倒计数生成器
- def countdown(n):
- while n > 0:
- yield n
- n -= 1
-
-
- def main():
- for num in countdown(5):
- print(f'Countdown: {num}')
- sleep(1)
- print('Countdown Over!')
-
-
- if __name__ == '__main__':
- main()
-
- ```
- 生成器还可以叠加来组成生成器管道,代码如下所示。
+async def download(url):
+ print('Fetch:', url)
+ async with aiohttp.ClientSession() as session:
+ async with session.get(url, ssl=False) as resp:
+ print(url, '--->', resp.status)
+ print(url, '--->', resp.headers)
+ print('\n\n', await resp.text())
- ```Python
- # Fibonacci数生成器
- def fib():
- a, b = 0, 1
- while True:
- a, b = b, a + b
- yield a
-
-
- # 偶数生成器
- def even(gen):
- for val in gen:
- if val % 2 == 0:
- yield val
-
-
- def main():
- gen = even(fib())
- for _ in range(10):
- print(next(gen))
-
-
- if __name__ == '__main__':
- main()
- ```
-2. 协程 - 数据的消费者。
+def main():
+ loop = asyncio.get_event_loop()
+ urls = [
+ 'https://www.baidu.com',
+ 'http://www.sohu.com/',
+ 'http://www.sina.com.cn/',
+ 'https://www.taobao.com/',
+ 'http://jd.com/'
+ ]
+ tasks = [download(url) for url in urls]
+ loop.run_until_complete(asyncio.wait(tasks))
+ loop.close()
- ```Python
- from time import sleep
-
-
- # 生成器 - 数据生产者
- def countdown_gen(n, consumer):
- consumer.send(None)
- while n > 0:
- consumer.send(n)
- n -= 1
- consumer.send(None)
-
-
- # 协程 - 数据消费者
- def countdown_con():
- while True:
- n = yield
- if n:
- print(f'Countdown {n}')
- sleep(1)
- else:
- print('Countdown Over!')
-
-
- def main():
- countdown_gen(5, countdown_con())
-
-
- if __name__ == '__main__':
- main()
- ```
- > 说明:上面代码中countdown_gen函数中的第1行consumer.send(None)是为了激活生成器,通俗的说就是让生成器执行到有yield关键字的地方挂起,当然也可以通过next(consumer)来达到同样的效果。如果不愿意每次都用这样的代码来“预激”生成器,可以写一个包装器来完成该操作,代码如下所示。
-
- ```Python
- from functools import wraps
-
-
- def coroutine(fn):
-
- @wraps(fn)
- def wrapper(*args, **kwargs):
- gen = fn(*args, **kwargs)
- next(gen)
- return gen
-
- return wrapper
- ```
-
- 这样就可以使用`@coroutine`装饰器对协程进行预激操作,不需要再写重复代码来激活协程。
-
-3. 异步I/O - 非阻塞式I/O操作。
-
- ```Python
- import asyncio
-
-
- @asyncio.coroutine
- def countdown(name, n):
- while n > 0:
- print(f'Countdown[{name}]: {n}')
- yield from asyncio.sleep(1)
- n -= 1
-
-
- def main():
- loop = asyncio.get_event_loop()
- tasks = [
- countdown("A", 10), countdown("B", 5),
- ]
- loop.run_until_complete(asyncio.wait(tasks))
- loop.close()
-
-
- if __name__ == '__main__':
- main()
- ```
-
-4. `async`和`await`。
-
- ```Python
- import asyncio
- import aiohttp
-
-
- async def download(url):
- print('Fetch:', url)
- async with aiohttp.ClientSession() as session:
- async with session.get(url) as resp:
- print(url, '--->', resp.status)
- print(url, '--->', resp.cookies)
- print('\n\n', await resp.text())
-
-
- def main():
- loop = asyncio.get_event_loop()
- urls = [
- 'https://www.baidu.com',
- 'http://www.sohu.com/',
- 'http://www.sina.com.cn/',
- 'https://www.taobao.com/',
- 'https://www.jd.com/'
- ]
- tasks = [download(url) for url in urls]
- loop.run_until_complete(asyncio.wait(tasks))
- loop.close()
-
-
- if __name__ == '__main__':
- main()
- ```
-
- 上面的代码使用了[AIOHTTP](https://github.com/aio-libs/aiohttp)这个非常著名的第三方库,它实现了HTTP客户端和HTTP服务器的功能,对异步操作提供了非常好的支持,有兴趣可以阅读它的[官方文档](https://aiohttp.readthedocs.io/en/stable/)。
+if __name__ == '__main__':
+ main()
+```
### 实例 - 多线程爬取“手机搜狐网”所有页面
diff --git a/Day66-75/70.解析动态内容.md b/Day61-65/65.解析动态内容.md
similarity index 66%
rename from Day66-75/70.解析动态内容.md
rename to Day61-65/65.解析动态内容.md
index 537b815..7c048d6 100644
--- a/Day66-75/70.解析动态内容.md
+++ b/Day61-65/65.解析动态内容.md
@@ -14,8 +14,6 @@
那么结论就很简单了,只要我们找到了这些网络API接口,那么就能通过这些接口获取到数据,当然实际开发的时候可能还要对这些接口的参数以及接口返回的数据进行分析,了解每个参数的意义以及返回的JSON数据的格式,这样才能在我们的爬虫中使用这些数据。
-关于如何从网络API中获取JSON格式的数据并提取出我们需要的内容,在之前的[《文件和异常》](../Day01-15/Day11/文件和异常.md)一文中已经讲解过了,这里不再进行赘述。
-
### 使用Selenium
尽管很多网站对自己的网络API接口进行了保护,增加了获取数据的难度,但是只要经过足够的努力,绝大多数还是可以被逆向工程的,但是在实际开发中,我们可以通过浏览器渲染引擎来避免这些繁琐的工作,WebKit就是一个利用的渲染引擎。
@@ -79,4 +77,82 @@ selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executabl
export PATH=$PATH:/Users/Hao/Downloads/Tools/chromedriver/
```
-其中`/Users/Hao/Downloads/Tools/chromedriver/ `就是chromedriver所在的路径。
+其中`/Users/Hao/Downloads/Tools/chromedriver/ `就是chromedriver所在的路径。当然,更为简单的办法是把chromedriver直接放在虚拟环境中,跟Python解释器位于同一个路径下就可以了。
+
+### WebDriver用法详解
+
+表1. 定位页面元素的方法
+
+
+
+表2. WebDriver的常用属性
+
+| 属性 | 描述 |
+| --------------------- | ----------------------------- |
+| current_url | 当前页面的URL |
+| current_window_handle | 当前窗口的句柄(引用) |
+| name | WebDriver实例底层浏览器的名称 |
+| orientation | 当前设备的方向(横屏、竖屏) |
+| page_source | 当前页面的源代码(动态内容) |
+| title | 当前页面的标题 |
+| window_handles | WebDriver打开的所有窗口的句柄 |
+
+表3. WebDriver的常用方法
+
+| 方法 | 描述 |
+| ----------------------------------- | -------------------------------------- |
+| back() / forward() | 在浏览历史记录中后退/前进 |
+| close() / quit() | 关闭当前浏览器窗口 / 退出WebDriver实例 |
+| get(url) | 加载指定URL的页面到浏览器中 |
+| maximize_window() | 将浏览器窗口最大化 |
+| refresh() | 刷新当前页面 |
+| switch_to_active_element() | 获得页面上得到焦点的元素 |
+| switch_to_alert() | 把焦点切换至弹出的警告框 |
+| set_page_load_timeout(time_to_wait) | 设置页面加载超时时间 |
+| set_script_timeout(time_to_wait) | 设置JavaScript执行超时时间 |
+| implicit_wait(time_to_wait) | 设置等待元素被找到或目标指令完成 |
+
+### WebElement用法
+
+表1. WebElement常用属性
+
+| | |
+| ---- | ---- |
+| | |
+| | |
+| | |
+
+表2. WebElement常用方法
+
+| | |
+| ---- | ---- |
+| | |
+| | |
+| | |
+| | |
+| | |
+| | |
+| | |
+| | |
+| | |
+
+### Select用法
+
+### Alert用法
+
+### 元素等待机制
+
+#### 隐式等待
+
+#### 显示等待
+
+### 高级特性
+
+#### 鼠标和键盘事件
+
+#### 调用JavaScript
+
+#### 屏幕截图和录制
+
+#### 操作Cookie
+
diff --git a/Day61-65/65.项目实战.md b/Day61-65/65.项目实战.md
deleted file mode 100644
index dbbae84..0000000
--- a/Day61-65/65.项目实战.md
+++ /dev/null
@@ -1,2 +0,0 @@
-## 项目实战
-
diff --git a/Day61-65/code/.gitkeep b/Day61-65/code/.gitkeep
deleted file mode 100644
index e69de29..0000000
diff --git a/Day66-75/code/asyncio01.py b/Day61-65/code/asyncio01.py
similarity index 100%
rename from Day66-75/code/asyncio01.py
rename to Day61-65/code/asyncio01.py
diff --git a/Day66-75/code/asyncio02.py b/Day61-65/code/asyncio02.py
similarity index 100%
rename from Day66-75/code/asyncio02.py
rename to Day61-65/code/asyncio02.py
diff --git a/Day66-75/code/coroutine01.py b/Day61-65/code/coroutine01.py
similarity index 100%
rename from Day66-75/code/coroutine01.py
rename to Day61-65/code/coroutine01.py
diff --git a/Day66-75/code/coroutine02.py b/Day61-65/code/coroutine02.py
similarity index 100%
rename from Day66-75/code/coroutine02.py
rename to Day61-65/code/coroutine02.py
diff --git a/Day41-55/code/shop_origin/cart/migrations/__init__.py b/Day61-65/code/douban/douban/__init__.py
similarity index 100%
rename from Day41-55/code/shop_origin/cart/migrations/__init__.py
rename to Day61-65/code/douban/douban/__init__.py
diff --git a/Day66-75/code/douban/douban/items.py b/Day61-65/code/douban/douban/items.py
similarity index 100%
rename from Day66-75/code/douban/douban/items.py
rename to Day61-65/code/douban/douban/items.py
diff --git a/Day66-75/code/douban/douban/middlewares.py b/Day61-65/code/douban/douban/middlewares.py
similarity index 100%
rename from Day66-75/code/douban/douban/middlewares.py
rename to Day61-65/code/douban/douban/middlewares.py
diff --git a/Day66-75/code/douban/douban/pipelines.py b/Day61-65/code/douban/douban/pipelines.py
similarity index 100%
rename from Day66-75/code/douban/douban/pipelines.py
rename to Day61-65/code/douban/douban/pipelines.py
diff --git a/Day66-75/code/douban/douban/settings.py b/Day61-65/code/douban/douban/settings.py
similarity index 100%
rename from Day66-75/code/douban/douban/settings.py
rename to Day61-65/code/douban/douban/settings.py
diff --git a/Day66-75/code/douban/douban/spiders/__init__.py b/Day61-65/code/douban/douban/spiders/__init__.py
similarity index 100%
rename from Day66-75/code/douban/douban/spiders/__init__.py
rename to Day61-65/code/douban/douban/spiders/__init__.py
diff --git a/Day66-75/code/douban/douban/spiders/movie.py b/Day61-65/code/douban/douban/spiders/movie.py
similarity index 100%
rename from Day66-75/code/douban/douban/spiders/movie.py
rename to Day61-65/code/douban/douban/spiders/movie.py
diff --git a/Day66-75/code/douban/scrapy.cfg b/Day61-65/code/douban/scrapy.cfg
similarity index 100%
rename from Day66-75/code/douban/scrapy.cfg
rename to Day61-65/code/douban/scrapy.cfg
diff --git a/Day66-75/code/example01.py b/Day61-65/code/example01.py
similarity index 100%
rename from Day66-75/code/example01.py
rename to Day61-65/code/example01.py
diff --git a/Day66-75/code/example02.py b/Day61-65/code/example02.py
similarity index 100%
rename from Day66-75/code/example02.py
rename to Day61-65/code/example02.py
diff --git a/Day66-75/code/example03.py b/Day61-65/code/example03.py
similarity index 100%
rename from Day66-75/code/example03.py
rename to Day61-65/code/example03.py
diff --git a/Day66-75/code/example04.py b/Day61-65/code/example04.py
similarity index 100%
rename from Day66-75/code/example04.py
rename to Day61-65/code/example04.py
diff --git a/Day66-75/code/example05.py b/Day61-65/code/example05.py
similarity index 100%
rename from Day66-75/code/example05.py
rename to Day61-65/code/example05.py
diff --git a/Day66-75/code/example06.py b/Day61-65/code/example06.py
similarity index 100%
rename from Day66-75/code/example06.py
rename to Day61-65/code/example06.py
diff --git a/Day66-75/code/example07.py b/Day61-65/code/example07.py
similarity index 100%
rename from Day66-75/code/example07.py
rename to Day61-65/code/example07.py
diff --git a/Day66-75/code/example08.py b/Day61-65/code/example08.py
similarity index 100%
rename from Day66-75/code/example08.py
rename to Day61-65/code/example08.py
diff --git a/Day66-75/code/example09.py b/Day61-65/code/example09.py
similarity index 100%
rename from Day66-75/code/example09.py
rename to Day61-65/code/example09.py
diff --git a/Day66-75/code/example10.py b/Day61-65/code/example10.py
similarity index 100%
rename from Day66-75/code/example10.py
rename to Day61-65/code/example10.py
diff --git a/Day66-75/code/example10a.py b/Day61-65/code/example10a.py
similarity index 100%
rename from Day66-75/code/example10a.py
rename to Day61-65/code/example10a.py
diff --git a/Day66-75/code/example11.py b/Day61-65/code/example11.py
similarity index 100%
rename from Day66-75/code/example11.py
rename to Day61-65/code/example11.py
diff --git a/Day66-75/code/example11a.py b/Day61-65/code/example11a.py
similarity index 100%
rename from Day66-75/code/example11a.py
rename to Day61-65/code/example11a.py
diff --git a/Day66-75/code/example12.py b/Day61-65/code/example12.py
similarity index 100%
rename from Day66-75/code/example12.py
rename to Day61-65/code/example12.py
diff --git a/Day66-75/code/generator01.py b/Day61-65/code/generator01.py
similarity index 100%
rename from Day66-75/code/generator01.py
rename to Day61-65/code/generator01.py
diff --git a/Day66-75/code/generator02.py b/Day61-65/code/generator02.py
similarity index 100%
rename from Day66-75/code/generator02.py
rename to Day61-65/code/generator02.py
diff --git a/Day61-65/code/guido.jpg b/Day61-65/code/guido.jpg
new file mode 100644
index 0000000..a8f217c
Binary files /dev/null and b/Day61-65/code/guido.jpg differ
diff --git a/Day61-65/code/hello-tornado/chat_handlers.py b/Day61-65/code/hello-tornado/chat_handlers.py
deleted file mode 100644
index 528d8a1..0000000
--- a/Day61-65/code/hello-tornado/chat_handlers.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-handlers.py - 用户登录和聊天的处理器
-"""
-import tornado.web
-import tornado.websocket
-
-nicknames = set()
-connections = {}
-
-
-class LoginHandler(tornado.web.RequestHandler):
-
- def get(self):
- self.render('login.html', hint='')
-
- def post(self):
- nickname = self.get_argument('nickname')
- if nickname in nicknames:
- self.render('login.html', hint='昵称已被使用,请更换昵称')
- self.set_secure_cookie('nickname', nickname)
- self.render('chat.html')
-
-
-class ChatHandler(tornado.websocket.WebSocketHandler):
-
- def open(self):
- nickname = self.get_secure_cookie('nickname').decode()
- nicknames.add(nickname)
- for conn in connections.values():
- conn.write_message(f'~~~{nickname}进入了聊天室~~~')
- connections[nickname] = self
-
- def on_message(self, message):
- nickname = self.get_secure_cookie('nickname').decode()
- for conn in connections.values():
- if conn is not self:
- conn.write_message(f'{nickname}说:{message}')
-
- def on_close(self):
- nickname = self.get_secure_cookie('nickname').decode()
- del connections[nickname]
- nicknames.remove(nickname)
- for conn in connections.values():
- conn.write_message(f'~~~{nickname}离开了聊天室~~~')
diff --git a/Day61-65/code/hello-tornado/chat_server.py b/Day61-65/code/hello-tornado/chat_server.py
deleted file mode 100644
index 4985acd..0000000
--- a/Day61-65/code/hello-tornado/chat_server.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""
-chat_server.py - 聊天服务器
-"""
-import os
-
-import tornado.web
-import tornado.ioloop
-
-from chat_handlers import LoginHandler, ChatHandler
-
-
-def main():
- app = tornado.web.Application(
- handlers=[(r'/login', LoginHandler), (r'/chat', ChatHandler)],
- template_path=os.path.join(os.path.dirname(__file__), 'templates'),
- static_path=os.path.join(os.path.dirname(__file__), 'static'),
- cookie_secret='MWM2MzEyOWFlOWRiOWM2MGMzZThhYTk0ZDNlMDA0OTU=',
- )
- app.listen(8888)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example01.py b/Day61-65/code/hello-tornado/example01.py
deleted file mode 100644
index 6005256..0000000
--- a/Day61-65/code/hello-tornado/example01.py
+++ /dev/null
@@ -1,36 +0,0 @@
-"""
-example01.py - 五分钟上手Tornado
-"""
-import tornado.ioloop
-import tornado.web
-
-from tornado.options import define, options, parse_command_line
-
-# 定义默认端口
-define('port', default=8000, type=int)
-
-
-class MainHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- # 向客户端(浏览器)写入内容
- self.write('Hello, world! ')
-
-
-def main():
- """主函数"""
- # 解析命令行参数,例如:
- # python example01.py --port 8888
- parse_command_line()
- # 创建了Tornado框架中Application类的实例并指定handlers参数
- # Application实例代表了我们的Web应用,handlers代表了路由解析
- app = tornado.web.Application(handlers=[(r'/', MainHandler), ])
- # 指定了监听HTTP请求的TCP端口(默认8000,也可以通过命令行参数指定)
- app.listen(options.port)
- # 获取Tornado框架的IOLoop实例并启动它(默认启动asyncio的事件循环)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example02.py b/Day61-65/code/hello-tornado/example02.py
deleted file mode 100644
index c9ff9c0..0000000
--- a/Day61-65/code/hello-tornado/example02.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""
-example02.py - 路由解析
-"""
-import os
-import random
-
-import tornado.ioloop
-import tornado.web
-
-from tornado.options import define, options, parse_command_line
-
-
-# 定义默认端口
-define('port', default=8000, type=int)
-
-
-class SayingHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- sayings = [
- '世上没有绝望的处境,只有对处境绝望的人',
- '人生的道路在态度的岔口一分为二,从此通向成功或失败',
- '所谓措手不及,不是说没有时间准备,而是有时间的时候没有准备',
- '那些你认为不靠谱的人生里,充满你没有勇气做的事',
- '在自己喜欢的时间里,按照自己喜欢的方式,去做自己喜欢做的事,这便是自由',
- '有些人不属于自己,但是遇见了也弥足珍贵'
- ]
- # 渲染index.html模板页
- self.render('index.html', message=random.choice(sayings))
-
-
-class WeatherHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self, city):
- # Tornado框架会自动处理百分号编码的问题
- weathers = {
- '北京': {'temperature': '-4~4', 'pollution': '195 中度污染'},
- '成都': {'temperature': '3~9', 'pollution': '53 良'},
- '深圳': {'temperature': '20~25', 'pollution': '25 优'},
- '广州': {'temperature': '18~23', 'pollution': '56 良'},
- '上海': {'temperature': '6~8', 'pollution': '65 良'}
- }
- if city in weathers:
- self.render('weather.html', city=city, weather=weathers[city])
- else:
- self.render('index.html', message=f'没有{city}的天气信息')
-
-
-class ErrorHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- # 重定向到指定的路径
- self.redirect('/saying')
-
-
-def main():
- """主函数"""
- parse_command_line()
- app = tornado.web.Application(
- # handlers是按列表中的顺序依次进行匹配的
- handlers=[
- (r'/saying/?', SayingHandler),
- (r'/weather/([^/]{2,})/?', WeatherHandler),
- (r'/.+', ErrorHandler),
- ],
- # 通过template_path参数设置模板页的路径
- template_path=os.path.join(os.path.dirname(__file__), 'templates')
- )
- app.listen(options.port)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example03.py b/Day61-65/code/hello-tornado/example03.py
deleted file mode 100644
index 16ff8e5..0000000
--- a/Day61-65/code/hello-tornado/example03.py
+++ /dev/null
@@ -1,75 +0,0 @@
-"""
-example03.py - RequestHandler解析
-"""
-import os
-import re
-
-import tornado.ioloop
-import tornado.web
-
-from tornado.options import define, options, parse_command_line
-
-
-# 定义默认端口
-define('port', default=8000, type=int)
-
-users = {}
-
-
-class User(object):
- """用户"""
-
- def __init__(self, nickname, gender, birthday):
- self.nickname = nickname
- self.gender = gender
- self.birthday = birthday
-
-
-class MainHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- # 从Cookie中读取用户昵称
- nickname = self.get_cookie('nickname')
- if nickname in users:
- self.render('userinfo.html', user=users[nickname])
- else:
- self.render('userform.html', hint='请填写个人信息')
-
-
-class UserHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def post(self):
- # 从表单参数中读取用户昵称、性别和生日信息
- nickname = self.get_body_argument('nickname').strip()
- gender = self.get_body_argument('gender')
- birthday = self.get_body_argument('birthday')
- # 检查用户昵称是否有效
- if not re.fullmatch(r'\w{6,20}', nickname):
- self.render('userform.html', hint='请输入有效的昵称')
- elif nickname in users:
- self.render('userform.html', hint='昵称已经被使用过')
- else:
- users[nickname] = User(nickname, gender, birthday)
- # 将用户昵称写入Cookie并设置有效期为7天
- self.set_cookie('nickname', nickname, expires_days=7)
- self.render('userinfo.html', user=users[nickname])
-
-
-def main():
- """主函数"""
- parse_command_line()
- app = tornado.web.Application(
- handlers=[
- (r'/', MainHandler),
- (r'/register', UserHandler),
- ],
- template_path=os.path.join(os.path.dirname(__file__), 'templates'),
- )
- app.listen(options.port)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example04.py b/Day61-65/code/hello-tornado/example04.py
deleted file mode 100644
index 7b9204c..0000000
--- a/Day61-65/code/hello-tornado/example04.py
+++ /dev/null
@@ -1,42 +0,0 @@
-"""
-example04.py - 同步请求的例子
-"""
-import json
-import os
-
-import requests
-import tornado.gen
-import tornado.ioloop
-import tornado.web
-import tornado.websocket
-import tornado.httpclient
-from tornado.options import define, options, parse_command_line
-
-define('port', default=8888, type=int)
-
-REQ_URL = 'http://api.tianapi.com/guonei/'
-API_KEY = '772a81a51ae5c780251b1f98ea431b84'
-
-
-class MainHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- def get(self):
- resp = requests.get(f'{REQ_URL}?key={API_KEY}')
- newslist = json.loads(resp.text)['newslist']
- self.render('news.html', newslist=newslist)
-
-
-def main():
- """主函数"""
- parse_command_line()
- app = tornado.web.Application(
- handlers=[(r'/', MainHandler), ],
- template_path=os.path.join(os.path.dirname(__file__), 'templates'),
- )
- app.listen(options.port)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example05.py b/Day61-65/code/hello-tornado/example05.py
deleted file mode 100644
index e2f6117..0000000
--- a/Day61-65/code/hello-tornado/example05.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-example05.py - 异步请求的例子
-"""
-import aiohttp
-import json
-import os
-
-import tornado.gen
-import tornado.ioloop
-import tornado.web
-import tornado.websocket
-import tornado.httpclient
-from tornado.options import define, options, parse_command_line
-
-define('port', default=8888, type=int)
-
-REQ_URL = 'http://api.tianapi.com/guonei/'
-API_KEY = '772a81a51ae5c780251b1f98ea431b84'
-
-
-class MainHandler(tornado.web.RequestHandler):
- """自定义请求处理器"""
-
- async def get(self):
- async with aiohttp.ClientSession() as session:
- resp = await session.get(f'{REQ_URL}?key={API_KEY}')
- json_str = await resp.text()
- print(json_str)
- newslist = json.loads(json_str)['newslist']
- self.render('news.html', newslist=newslist)
-
-
-def main():
- """主函数"""
- parse_command_line()
- app = tornado.web.Application(
- handlers=[(r'/', MainHandler), ],
- template_path=os.path.join(os.path.dirname(__file__), 'templates'),
- )
- app.listen(options.port)
- tornado.ioloop.IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example06.py b/Day61-65/code/hello-tornado/example06.py
deleted file mode 100644
index 7143351..0000000
--- a/Day61-65/code/hello-tornado/example06.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
-example06.py - 异步操作MySQL
-"""
-import json
-
-import aiomysql
-import tornado
-import tornado.web
-
-from tornado.ioloop import IOLoop
-from tornado.options import define, parse_command_line, options
-
-define('port', default=8888, type=int)
-
-
-async def connect_mysql():
- return await aiomysql.connect(
- host='120.77.222.217',
- port=3306,
- db='hrs',
- charset='utf8',
- use_unicode=True,
- user='root',
- password='123456',
- )
-
-
-class HomeHandler(tornado.web.RequestHandler):
-
- async def get(self, no):
- async with self.settings['mysql'].cursor(aiomysql.DictCursor) as cursor:
- await cursor.execute("select * from tb_dept where dno=%s", (no, ))
- if cursor.rowcount == 0:
- self.finish(json.dumps({
- 'code': 20001,
- 'mesg': f'没有编号为{no}的部门'
- }))
- return
- row = await cursor.fetchone()
- self.finish(json.dumps(row))
-
- async def post(self, *args, **kwargs):
- no = self.get_argument('no')
- name = self.get_argument('name')
- loc = self.get_argument('loc')
- conn = self.settings['mysql']
- try:
- async with conn.cursor() as cursor:
- await cursor.execute('insert into tb_dept values (%s, %s, %s)',
- (no, name, loc))
- await conn.commit()
- except aiomysql.MySQLError:
- self.finish(json.dumps({
- 'code': 20002,
- 'mesg': '添加部门失败请确认部门信息'
- }))
- else:
- self.set_status(201)
- self.finish()
-
-
-def make_app(config):
- return tornado.web.Application(
- handlers=[(r'/api/depts/(.*)', HomeHandler), ],
- **config
- )
-
-
-def main():
- parse_command_line()
- app = make_app({
- 'debug': True,
- 'mysql': IOLoop.current().run_sync(connect_mysql)
- })
- app.listen(options.port)
- IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example07.py b/Day61-65/code/hello-tornado/example07.py
deleted file mode 100644
index e0d454c..0000000
--- a/Day61-65/code/hello-tornado/example07.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-example07.py - 将非异步的三方库封装为异步调用
-"""
-import asyncio
-import concurrent
-import json
-
-import tornado
-import tornado.web
-import pymysql
-
-from pymysql import connect
-from pymysql.cursors import DictCursor
-
-from tornado.ioloop import IOLoop
-from tornado.options import define, parse_command_line, options
-from tornado.platform.asyncio import AnyThreadEventLoopPolicy
-
-define('port', default=8888, type=int)
-
-
-def get_mysql_connection():
- return connect(
- host='120.77.222.217',
- port=3306,
- db='hrs',
- charset='utf8',
- use_unicode=True,
- user='root',
- password='123456',
- )
-
-
-class HomeHandler(tornado.web.RequestHandler):
- executor = concurrent.futures.ThreadPoolExecutor(max_workers=10)
-
- async def get(self, no):
- return await self._get(no)
-
- @tornado.concurrent.run_on_executor
- def _get(self, no):
- con = get_mysql_connection()
- try:
- with con.cursor(DictCursor) as cursor:
- cursor.execute("select * from tb_dept where dno=%s", (no, ))
- if cursor.rowcount == 0:
- self.finish(json.dumps({
- 'code': 20001,
- 'mesg': f'没有编号为{no}的部门'
- }))
- return
- row = cursor.fetchone()
- self.finish(json.dumps(row))
- finally:
- con.close()
-
- async def post(self, *args, **kwargs):
- return await self._post(*args, **kwargs)
-
- @tornado.concurrent.run_on_executor
- def _post(self, *args, **kwargs):
- no = self.get_argument('no')
- name = self.get_argument('name')
- loc = self.get_argument('loc')
- conn = get_mysql_connection()
- try:
- with conn.cursor() as cursor:
- cursor.execute('insert into tb_dept values (%s, %s, %s)',
- (no, name, loc))
- conn.commit()
- except pymysql.MySQLError:
- self.finish(json.dumps({
- 'code': 20002,
- 'mesg': '添加部门失败请确认部门信息'
- }))
- else:
- self.set_status(201)
- self.finish()
-
-
-def main():
- asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy())
- parse_command_line()
- app = tornado.web.Application(
- handlers=[(r'/api/depts/(.*)', HomeHandler), ]
- )
- app.listen(options.port)
- IOLoop.current().start()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example_of_aiohttp.py b/Day61-65/code/hello-tornado/example_of_aiohttp.py
deleted file mode 100644
index 362f6ff..0000000
--- a/Day61-65/code/hello-tornado/example_of_aiohttp.py
+++ /dev/null
@@ -1,30 +0,0 @@
-import asyncio
-import re
-
-import aiohttp
-
-PATTERN = re.compile(r'\(?P.*)\<\/title\>')
-
-
-async def show_title(url):
- async with aiohttp.ClientSession() as session:
- resp = await session.get(url, ssl=False)
- html = await resp.text()
- print(PATTERN.search(html).group('title'))
-
-
-def main():
- urls = ('https://www.python.org/',
- 'https://git-scm.com/',
- 'https://www.jd.com/',
- 'https://www.taobao.com/',
- 'https://www.douban.com/')
- # asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
- # 获取事件循环()
- loop = asyncio.get_event_loop()
- tasks = [show_title(url) for url in urls]
- loop.run_until_complete(asyncio.wait(tasks))
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example_of_asyncio.py b/Day61-65/code/hello-tornado/example_of_asyncio.py
deleted file mode 100644
index 0851f38..0000000
--- a/Day61-65/code/hello-tornado/example_of_asyncio.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import asyncio
-
-
-async def fetch(host):
- """从指定的站点抓取信息(协程函数)"""
- print(f'Start fetching {host}\n')
- # 跟服务器建立连接
- reader, writer = await asyncio.open_connection(host, 80)
- # 构造请求行和请求头
- writer.write(b'GET / HTTP/1.1\r\n')
- writer.write(f'Host: {host}\r\n'.encode())
- writer.write(b'\r\n')
- # 清空缓存区(发送请求)
- await writer.drain()
- # 接收服务器的响应(读取响应行和响应头)
- line = await reader.readline()
- while line != b'\r\n':
- print(line.decode().rstrip())
- line = await reader.readline()
- print('\n')
- writer.close()
-
-
-def main():
- """主函数"""
- urls = ('www.sohu.com', 'www.douban.com', 'www.163.com')
- # 获取系统默认的事件循环
- loop = asyncio.get_event_loop()
- # 用生成式语法构造一个包含多个协程对象的列表
- tasks = [fetch(url) for url in urls]
- # 通过asyncio模块的wait函数将协程列表包装成Task(Future子类)并等待其执行完成
- # 通过事件循环的run_until_complete方法运行任务直到Future完成并返回它的结果
- futures = asyncio.wait(tasks)
- print(futures, type(futures))
- loop.run_until_complete(futures)
- loop.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example_of_coroutine.py b/Day61-65/code/hello-tornado/example_of_coroutine.py
deleted file mode 100644
index 070dad2..0000000
--- a/Day61-65/code/hello-tornado/example_of_coroutine.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-协程(coroutine)- 可以在需要时进行切换的相互协作的子程序
-"""
-import asyncio
-
-from example_of_multiprocess import is_prime
-
-
-def num_generator(m, n):
- """指定范围的数字生成器"""
- for num in range(m, n + 1):
- print(f'generate number: {num}')
- yield num
-
-
-async def prime_filter(m, n):
- """素数过滤器"""
- primes = []
- for i in num_generator(m, n):
- if is_prime(i):
- print('Prime =>', i)
- primes.append(i)
-
- await asyncio.sleep(0.001)
- return tuple(primes)
-
-
-async def square_mapper(m, n):
- """平方映射器"""
- squares = []
- for i in num_generator(m, n):
- print('Square =>', i * i)
- squares.append(i * i)
-
- await asyncio.sleep(0.001)
- return squares
-
-
-def main():
- """主函数"""
- loop = asyncio.get_event_loop()
- start, end = 1, 100
- futures = asyncio.gather(prime_filter(start, end), square_mapper(start, end))
- futures.add_done_callback(lambda x: print(x.result()))
- loop.run_until_complete(futures)
- loop.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/example_of_multiprocess.py b/Day61-65/code/hello-tornado/example_of_multiprocess.py
deleted file mode 100644
index bef4c0f..0000000
--- a/Day61-65/code/hello-tornado/example_of_multiprocess.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-用下面的命令运行程序并查看执行时间,例如:
-time python3 example05.py
-real 0m20.657s
-user 1m17.749s
-sys 0m0.158s
-使用多进程后实际执行时间为20.657秒,而用户时间1分17.749秒约为实际执行时间的4倍
-这就证明我们的程序通过多进程使用了CPU的多核特性,而且这台计算机配置了4核的CPU
-"""
-import concurrent.futures
-import math
-
-PRIMES = [
- 1116281,
- 1297337,
- 104395303,
- 472882027,
- 533000389,
- 817504243,
- 982451653,
- 112272535095293,
- 112582705942171,
- 112272535095293,
- 115280095190773,
- 115797848077099,
- 1099726899285419
-] * 5
-
-
-def is_prime(num):
- """判断素数"""
- assert num > 0
- if num % 2 == 0:
- return False
- for i in range(3, int(math.sqrt(num)) + 1, 2):
- if num % i == 0:
- return False
- return num != 1
-
-
-def main():
- """主函数"""
- with concurrent.futures.ProcessPoolExecutor() as executor:
- for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
- print('%d is prime: %s' % (number, prime))
-
-
-if __name__ == '__main__':
- main()
diff --git a/Day61-65/code/hello-tornado/requirements.txt b/Day61-65/code/hello-tornado/requirements.txt
deleted file mode 100644
index 619660c..0000000
--- a/Day61-65/code/hello-tornado/requirements.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-aiohttp==3.5.4
-aiomysql==0.0.20
-asn1crypto==0.24.0
-async-timeout==3.0.1
-attrs==19.1.0
-certifi==2019.3.9
-cffi==1.12.2
-chardet==3.0.4
-cryptography==2.6.1
-idna==2.8
-multidict==4.5.2
-pycparser==2.19
-PyMySQL==0.9.2
-requests==2.21.0
-six==1.12.0
-tornado==5.1.1
-urllib3==1.24.1
-yarl==1.3.0
diff --git a/Day61-65/code/hello-tornado/templates/chat.html b/Day61-65/code/hello-tornado/templates/chat.html
deleted file mode 100644
index d83fd5c..0000000
--- a/Day61-65/code/hello-tornado/templates/chat.html
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
- Tornado聊天室
-
-
- 聊天室
-
-
-
-
-
-
-
-
-
- 退出聊天室
-
-
-
-
-
diff --git a/Day61-65/code/hello-tornado/templates/login.html b/Day61-65/code/hello-tornado/templates/login.html
deleted file mode 100644
index 69d6c55..0000000
--- a/Day61-65/code/hello-tornado/templates/login.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
- Tornado聊天室
-
-
-
-
-
-
diff --git a/Day61-65/code/hello-tornado/templates/news.html b/Day61-65/code/hello-tornado/templates/news.html
deleted file mode 100644
index 9665d6b..0000000
--- a/Day61-65/code/hello-tornado/templates/news.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
- 新闻列表
-
-
- 新闻列表
-
- {% for news in newslist %}
-
-
-
{{news['title']}}
-
- {% end %}
-
-
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/service/__init__.py b/Day61-65/code/image360/image360/__init__.py
similarity index 100%
rename from Day61-65/code/project_of_tornado/service/__init__.py
rename to Day61-65/code/image360/image360/__init__.py
diff --git a/Day66-75/code/image360/image360/items.py b/Day61-65/code/image360/image360/items.py
similarity index 100%
rename from Day66-75/code/image360/image360/items.py
rename to Day61-65/code/image360/image360/items.py
diff --git a/Day66-75/code/image360/image360/middlewares.py b/Day61-65/code/image360/image360/middlewares.py
similarity index 96%
rename from Day66-75/code/image360/image360/middlewares.py
rename to Day61-65/code/image360/image360/middlewares.py
index 13d9c46..10b3224 100644
--- a/Day66-75/code/image360/image360/middlewares.py
+++ b/Day61-65/code/image360/image360/middlewares.py
@@ -111,6 +111,9 @@ class TaobaoDownloaderMiddleWare(object):
def __init__(self, timeout=None):
self.timeout = timeout
+ # options = webdriver.ChromeOptions()
+ # options.add_argument('headless')
+ # self.browser = webdriver.Chrome(options=options)
self.browser = webdriver.Chrome()
self.browser.set_window_size(1000, 600)
self.browser.set_page_load_timeout(self.timeout)
diff --git a/Day66-75/code/image360/image360/pipelines.py b/Day61-65/code/image360/image360/pipelines.py
similarity index 100%
rename from Day66-75/code/image360/image360/pipelines.py
rename to Day61-65/code/image360/image360/pipelines.py
diff --git a/Day66-75/code/image360/image360/settings.py b/Day61-65/code/image360/image360/settings.py
similarity index 96%
rename from Day66-75/code/image360/image360/settings.py
rename to Day61-65/code/image360/image360/settings.py
index 76dbbfe..266eab4 100644
--- a/Day66-75/code/image360/image360/settings.py
+++ b/Day61-65/code/image360/image360/settings.py
@@ -71,10 +71,10 @@ IMAGES_STORE = './resources/'
# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
-# ITEM_PIPELINES = {
-# 'image360.pipelines.SaveImagePipeline': 300,
-# 'image360.pipelines.SaveToMongoPipeline': 301,
-# }
+ITEM_PIPELINES = {
+ 'image360.pipelines.SaveImagePipeline': 300,
+ 'image360.pipelines.SaveToMongoPipeline': 301,
+}
LOG_LEVEL = 'DEBUG'
diff --git a/Day66-75/code/image360/image360/spiders/__init__.py b/Day61-65/code/image360/image360/spiders/__init__.py
similarity index 100%
rename from Day66-75/code/image360/image360/spiders/__init__.py
rename to Day61-65/code/image360/image360/spiders/__init__.py
diff --git a/Day66-75/code/image360/image360/spiders/image.py b/Day61-65/code/image360/image360/spiders/image.py
similarity index 100%
rename from Day66-75/code/image360/image360/spiders/image.py
rename to Day61-65/code/image360/image360/spiders/image.py
diff --git a/Day66-75/code/image360/image360/spiders/taobao.py b/Day61-65/code/image360/image360/spiders/taobao.py
similarity index 100%
rename from Day66-75/code/image360/image360/spiders/taobao.py
rename to Day61-65/code/image360/image360/spiders/taobao.py
diff --git a/Day66-75/code/image360/scrapy.cfg b/Day61-65/code/image360/scrapy.cfg
similarity index 100%
rename from Day66-75/code/image360/scrapy.cfg
rename to Day61-65/code/image360/scrapy.cfg
diff --git a/Day66-75/code/main.py b/Day61-65/code/main.py
similarity index 100%
rename from Day66-75/code/main.py
rename to Day61-65/code/main.py
diff --git a/Day66-75/code/main_redis.py b/Day61-65/code/main_redis.py
similarity index 100%
rename from Day66-75/code/main_redis.py
rename to Day61-65/code/main_redis.py
diff --git a/Day66-75/code/myutils.py b/Day61-65/code/myutils.py
similarity index 100%
rename from Day66-75/code/myutils.py
rename to Day61-65/code/myutils.py
diff --git a/Day61-65/code/project_of_tornado/assets/css/admin.css b/Day61-65/code/project_of_tornado/assets/css/admin.css
deleted file mode 100644
index 3fd52e0..0000000
--- a/Day61-65/code/project_of_tornado/assets/css/admin.css
+++ /dev/null
@@ -1,373 +0,0 @@
-/**
- * admin.css
- */
-
-
-/*
- fixed-layout 固定头部和边栏布局
-*/
-
-html,
-body {
- height: 100%;
- overflow: hidden;
-}
-
-ul {
- margin-top: 0;
-}
-
-.admin-icon-yellow {
- color: #ffbe40;
-}
-
-.admin-header {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- z-index: 1500;
- font-size: 1.4rem;
- margin-bottom: 0;
-}
-
-.admin-header-list a:hover :after {
- content: none;
-}
-
-.admin-main {
- position: relative;
- height: 100%;
- padding-top: 51px;
- background: #f3f3f3;
-}
-
-.admin-menu {
- position: fixed;
- z-index: 10;
- bottom: 30px;
- right: 20px;
-}
-
-.admin-sidebar {
- width: 260px;
- min-height: 100%;
- float: left;
- border-right: 1px solid #cecece;
-}
-
-.admin-sidebar.am-active {
- z-index: 1600;
-}
-
-.admin-sidebar-list {
- margin-bottom: 0;
-}
-
-.admin-sidebar-list li a {
- color: #5c5c5c;
- padding-left: 24px;
-}
-
-.admin-sidebar-list li:first-child {
- border-top: none;
-}
-
-.admin-sidebar-sub {
- margin-top: 0;
- margin-bottom: 0;
- box-shadow: 0 16px 8px -15px #e2e2e2 inset;
- background: #ececec;
- padding-left: 24px;
-}
-
-.admin-sidebar-sub li:first-child {
- border-top: 1px solid #dedede;
-}
-
-.admin-sidebar-panel {
- margin: 10px;
-}
-
-.admin-content {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- background: #fff;
-}
-
-.admin-content,
-.admin-sidebar {
- height: 100%;
- overflow-x: hidden;
- overflow-y: scroll;
- -webkit-overflow-scrolling: touch;
-}
-
-.admin-content-body {
- -webkit-box-flex: 1;
- -webkit-flex: 1 0 auto;
- -ms-flex: 1 0 auto;
- flex: 1 0 auto;
-}
-
-.admin-content-footer {
- font-size: 85%;
- color: #777;
-}
-
-.admin-content-list {
- border: 1px solid #e9ecf1;
- margin-top: 0;
-}
-
-.admin-content-list li {
- border: 1px solid #e9ecf1;
- border-width: 0 1px;
- margin-left: -1px;
-}
-
-.admin-content-list li:first-child {
- border-left: none;
-}
-
-.admin-content-list li:last-child {
- border-right: none;
-}
-
-.admin-content-table a {
- color: #535353;
-}
-.admin-content-file {
- margin-bottom: 0;
- color: #666;
-}
-
-.admin-content-file p {
- margin: 0 0 5px 0;
- font-size: 1.4rem;
-}
-
-.admin-content-file li {
- padding: 10px 0;
-}
-
-.admin-content-file li:first-child {
- border-top: none;
-}
-
-.admin-content-file li:last-child {
- border-bottom: none;
-}
-
-.admin-content-file li .am-progress {
- margin-bottom: 4px;
-}
-
-.admin-content-file li .am-progress-bar {
- line-height: 14px;
-}
-
-.admin-content-task {
- margin-bottom: 0;
-}
-
-.admin-content-task li {
- padding: 5px 0;
- border-color: #eee;
-}
-
-.admin-content-task li:first-child {
- border-top: none;
-}
-
-.admin-content-task li:last-child {
- border-bottom: none;
-}
-
-.admin-task-meta {
- font-size: 1.2rem;
- color: #999;
-}
-
-.admin-task-bd {
- font-size: 1.4rem;
- margin-bottom: 5px;
-}
-
-.admin-content-comment {
- margin-bottom: 0;
-}
-
-.admin-content-comment .am-comment-bd {
- font-size: 1.4rem;
-}
-
-.admin-content-pagination {
- margin-bottom: 0;
-}
-.admin-content-pagination li a {
- padding: 4px 8px;
-}
-
-@media only screen and (min-width: 641px) {
- .admin-sidebar {
- display: block;
- position: static;
- background: none;
- }
-
- .admin-offcanvas-bar {
- position: static;
- width: auto;
- background: none;
- -webkit-transform: translate3d(0, 0, 0);
- -ms-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- overflow-y: visible;
- min-height: 100%;
- }
- .admin-offcanvas-bar:after {
- content: none;
- }
-}
-
-@media only screen and (max-width: 640px) {
- .admin-sidebar {
- width: inherit;
- }
-
- .admin-offcanvas-bar {
- background: #f3f3f3;
- }
-
- .admin-offcanvas-bar:after {
- background: #BABABA;
- }
-
- .admin-sidebar-list a:hover, .admin-sidebar-list a:active{
- -webkit-transition: background-color .3s ease;
- -moz-transition: background-color .3s ease;
- -ms-transition: background-color .3s ease;
- -o-transition: background-color .3s ease;
- transition: background-color .3s ease;
- background: #E4E4E4;
- }
-
- .admin-content-list li {
- padding: 10px;
- border-width: 1px 0;
- margin-top: -1px;
- }
-
- .admin-content-list li:first-child {
- border-top: none;
- }
-
- .admin-content-list li:last-child {
- border-bottom: none;
- }
-
- .admin-form-text {
- text-align: left !important;
- }
-
-}
-
-/*
-* user.html css
-*/
-.user-info {
- margin-bottom: 15px;
-}
-
-.user-info .am-progress {
- margin-bottom: 4px;
-}
-
-.user-info p {
- margin: 5px;
-}
-
-.user-info-order {
- font-size: 1.4rem;
-}
-
-/*
-* errorLog.html css
-*/
-
-.error-log .am-pre-scrollable {
- max-height: 40rem;
-}
-
-/*
-* table.html css
-*/
-
-.table-main {
- font-size: 1.4rem;
- padding: .5rem;
-}
-
-.table-main button {
- background: #fff;
-}
-
-.table-check {
- width: 30px;
-}
-
-.table-id {
- width: 50px;
-}
-
-@media only screen and (max-width: 640px) {
- .table-select {
- margin-top: 10px;
- margin-left: 5px;
- }
-}
-
-/*
-gallery.html css
-*/
-
-.gallery-list li {
- padding: 10px;
-}
-
-.gallery-list a {
- color: #666;
-}
-
-.gallery-list a:hover {
- color: #3bb4f2;
-}
-
-.gallery-title {
- margin-top: 6px;
- font-size: 1.4rem;
-}
-
-.gallery-desc {
- font-size: 1.2rem;
- margin-top: 4px;
-}
-
-/*
- 404.html css
-*/
-
-.page-404 {
- background: #fff;
- border: none;
- width: 200px;
- margin: 0 auto;
-}
diff --git a/Day61-65/code/project_of_tornado/assets/css/amazeui.datatables.min.css b/Day61-65/code/project_of_tornado/assets/css/amazeui.datatables.min.css
deleted file mode 100644
index f579a99..0000000
--- a/Day61-65/code/project_of_tornado/assets/css/amazeui.datatables.min.css
+++ /dev/null
@@ -1 +0,0 @@
-.am-datatable-hd{margin-bottom:10px}.am-datatable-hd label{font-weight:400}.am-datatable-filter{text-align:right}.am-datatable-filter input{margin-left:.5em}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_desc_disabled{cursor:pointer;position:relative}table.dataTable thead .sorting:after{position:absolute;top:50%;margin-top:-12px;right:8px;display:block;font-weight:400}table.dataTable thead .sorting_asc:after,table.dataTable thead .sorting_desc:after{position:absolute;top:50%;margin-top:-12px;right:8px;display:block;opacity:.5;font-weight:400}table.dataTable thead .sorting:after{opacity:.2;content:"\f0dc"}table.dataTable thead .sorting_asc:after{content:"\f15d"}table.dataTable thead .sorting_desc:after{content:"\f15e"}div.DTFC_LeftBodyWrapper table.dataTable thead .sorting:after,div.DTFC_LeftBodyWrapper table.dataTable thead .sorting_asc:after,div.DTFC_LeftBodyWrapper table.dataTable thead .sorting_desc:after,div.DTFC_RightBodyWrapper table.dataTable thead .sorting:after,div.DTFC_RightBodyWrapper table.dataTable thead .sorting_asc:after,div.DTFC_RightBodyWrapper table.dataTable thead .sorting_desc:after,div.dataTables_scrollBody table.dataTable thead .sorting:after,div.dataTables_scrollBody table.dataTable thead .sorting_asc:after,div.dataTables_scrollBody table.dataTable thead .sorting_desc:after{display:none}table.dataTable thead .sorting_asc_disabled:after,table.dataTable thead .sorting_desc_disabled:after{color:#eee}table.dataTable thead>tr>th{padding-right:30px}table.dataTable th:active{outline:none}table.dataTable.table-condensed thead>tr>th{padding-right:20px}table.dataTable.table-condensed thead .sorting:after,table.dataTable.table-condensed thead .sorting_asc:after,table.dataTable.table-condensed thead .sorting_desc:after{top:6px;right:6px}div.dataTables_scrollHead table{margin-bottom:0!important;border-bottom-left-radius:0;border-bottom-right-radius:0}div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child,div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,div.DTFC_RightHeadWrapper table thead tr:last-child td:first-child,div.DTFC_RightHeadWrapper table thead tr:last-child th:first-child,div.dataTables_scrollHead table thead tr:last-child td:first-child,div.dataTables_scrollHead table thead tr:last-child th:first-child{border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}div.dataTables_scrollBody table{border-top:none;margin-top:0!important;margin-bottom:0!important}div.DTFC_LeftBodyWrapper tbody tr:first-child td,div.DTFC_LeftBodyWrapper tbody tr:first-child th,div.DTFC_RightBodyWrapper tbody tr:first-child td,div.DTFC_RightBodyWrapper tbody tr:first-child th,div.dataTables_scrollBody tbody tr:first-child td,div.dataTables_scrollBody tbody tr:first-child th{border-top:none}div.dataTables_scrollFoot table{margin-top:0!important;border-top:none}table.table-bordered.dataTable{border-collapse:separate!important}table.table-bordered thead td,table.table-bordered thead th{border-left-width:0;border-top-width:0}table.table-bordered tbody td,table.table-bordered tbody th,table.table-bordered tfoot td,table.table-bordered tfoot th{border-left-width:0;border-bottom-width:0}table.table-bordered td:last-child,table.table-bordered th:last-child{border-right-width:0}div.dataTables_scrollHead table.table-bordered{border-bottom-width:0}.table.dataTable tbody tr.active td,.table.dataTable tbody tr.active th{background-color:#08c;color:#fff}.table.dataTable tbody tr.active:hover td,.table.dataTable tbody tr.active:hover th{background-color:#0075b0!important}.table.dataTable tbody tr.active td>a,.table.dataTable tbody tr.active th>a{color:#fff}.table-striped.dataTable tbody tr.active:nth-child(odd) td,.table-striped.dataTable tbody tr.active:nth-child(odd) th{background-color:#017ebc}table.DTTT_selectable tbody tr{cursor:pointer}div.DTTT .btn:hover{text-decoration:none!important}ul.DTTT_dropdown.dropdown-menu{z-index:2003}ul.DTTT_dropdown.dropdown-menu a{color:#333!important}ul.DTTT_dropdown.dropdown-menu li{position:relative}ul.DTTT_dropdown.dropdown-menu li:hover a{background-color:#08c;color:#fff!important}div.DTTT_collection_background{z-index:2002}div.DTTT_print_info,div.dataTables_processing{top:50%;left:50%;text-align:center;background-color:#fff}div.DTTT_print_info{color:#333;padding:10px 30px;opacity:.95;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0,0,0,.5);box-shadow:0 3px 7px rgba(0,0,0,.5);position:fixed;width:400px;height:150px;margin-left:-200px;margin-top:-75px}div.DTTT_print_info h6{font-weight:400;font-size:28px;line-height:28px;margin:1em}div.DTTT_print_info p{font-size:14px;line-height:20px}div.dataTables_processing{position:absolute;width:100%;height:60px;margin-left:-50%;margin-top:-25px;padding-top:20px;padding-bottom:20px;font-size:1.2em;background:-webkit-gradient(linear,left top,right top,color-stop(0%,rgba(255,255,255,0)),color-stop(25%,rgba(255,255,255,.9)),color-stop(75%,rgba(255,255,255,.9)),color-stop(100%,rgba(255,255,255,0)));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0%,rgba(255,255,255,.9) 25%,rgba(255,255,255,.9) 75%,rgba(255,255,255,0) 100%);background:-webkit-gradient(linear,left top,right top,from(rgba(255,255,255,0)),color-stop(25%,rgba(255,255,255,.9)),color-stop(75%,rgba(255,255,255,.9)),to(rgba(255,255,255,0)));background:linear-gradient(to right,rgba(255,255,255,0) 0%,rgba(255,255,255,.9) 25%,rgba(255,255,255,.9) 75%,rgba(255,255,255,0) 100%)}div.DTFC_LeftHeadWrapper table{background-color:#fff}div.DTFC_LeftFootWrapper table{background-color:#fff;margin-bottom:0}div.DTFC_RightHeadWrapper table{background-color:#fff}div.DTFC_RightFootWrapper table,table.DTFC_Cloned tr.even{background-color:#fff;margin-bottom:0}div.DTFC_LeftHeadWrapper table,div.DTFC_RightHeadWrapper table{border-bottom:none!important;margin-bottom:0!important;border-top-right-radius:0!important;border-bottom-left-radius:0!important;border-bottom-right-radius:0!important}div.DTFC_LeftBodyWrapper table,div.DTFC_RightBodyWrapper table{border-top:none;margin:0!important}div.DTFC_LeftFootWrapper table,div.DTFC_RightFootWrapper table{border-top:none;margin-top:0!important}div.FixedHeader_Cloned table{margin:0!important}.am-datatable-pager{margin-top:0;margin-bottom:0}.am-datatable-info{padding-top:6px;color:#555;font-size:1.4rem}table.dataTable.dtr-inline.collapsed>tbody>tr>td:first-child,table.dataTable.dtr-inline.collapsed>tbody>tr>th:first-child{position:relative;padding-left:30px;cursor:pointer}table.dataTable.dtr-inline.collapsed>tbody>tr>td:first-child:before,table.dataTable.dtr-inline.collapsed>tbody>tr>th:first-child:before{top:8px;left:4px;height:16px;width:16px;display:block;position:absolute;color:#fff;border:2px solid #fff;border-radius:16px;text-align:center;line-height:14px;-webkit-box-shadow:0 0 3px #444;box-shadow:0 0 3px #444;-webkit-box-sizing:content-box;box-sizing:content-box;content:'+';background-color:#31b131}table.dataTable.dtr-inline.collapsed>tbody>tr>td:first-child.dataTables_empty:before,table.dataTable.dtr-inline.collapsed>tbody>tr>th:first-child.dataTables_empty:before{display:none}table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td:first-child:before,table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th:first-child:before{content:'-';background-color:#d33333}table.dataTable.dtr-inline.collapsed>tbody>tr.child td:before{display:none}table.dataTable.dtr-inline.collapsed.compact>tbody>tr>td:first-child,table.dataTable.dtr-inline.collapsed.compact>tbody>tr>th:first-child{padding-left:27px}table.dataTable.dtr-inline.collapsed.compact>tbody>tr>td:first-child:before,table.dataTable.dtr-inline.collapsed.compact>tbody>tr>th:first-child:before{top:5px;left:4px;height:14px;width:14px;border-radius:14px;line-height:12px}table.dataTable.dtr-column>tbody>tr>td.control,table.dataTable.dtr-column>tbody>tr>th.control{position:relative;cursor:pointer}table.dataTable.dtr-column>tbody>tr>td.control:before,table.dataTable.dtr-column>tbody>tr>th.control:before{top:50%;left:50%;height:16px;width:16px;margin-top:-10px;margin-left:-10px;display:block;position:absolute;color:#fff;border:2px solid #fff;border-radius:16px;text-align:center;line-height:14px;-webkit-box-shadow:0 0 3px #666;box-shadow:0 0 3px #666;-webkit-box-sizing:content-box;box-sizing:content-box;content:'+';background-color:#5eb95e}table.dataTable.dtr-column>tbody>tr.parent td.control:before,table.dataTable.dtr-column>tbody>tr.parent th.control:before{content:'-';background-color:#dd514c}table.dataTable>tbody>tr.child{padding:.5em 1em}table.dataTable>tbody>tr.child:hover{background:0 0!important}table.dataTable>tbody>tr.child ul{display:inline-block;list-style-type:none;margin:0;padding:0}table.dataTable>tbody>tr.child ul li{border-bottom:1px solid #efefef;padding:.5em 0}table.dataTable>tbody>tr.child ul li:first-child{padding-top:0}table.dataTable>tbody>tr.child ul li:last-child{border-bottom:none}table.dataTable>tbody>tr.child span.dtr-title{display:inline-block;min-width:75px;font-weight:700}
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/assets/css/amazeui.min.css b/Day61-65/code/project_of_tornado/assets/css/amazeui.min.css
deleted file mode 100644
index 39263eb..0000000
--- a/Day61-65/code/project_of_tornado/assets/css/amazeui.min.css
+++ /dev/null
@@ -1 +0,0 @@
-/*! Amaze UI v2.7.2 | by Amaze UI Team | (c) 2016 AllMobilize, Inc. | Licensed under MIT | 2016-08-17T16:17:24+0800 */*,:after,:before{-webkit-box-sizing:border-box;box-sizing:border-box}body,html{min-height:100%}html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],script,template{display:none}a{background-color:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}a,ins{text-decoration:none}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{-webkit-box-sizing:border-box;box-sizing:border-box;vertical-align:middle;border:0}svg:not(:root){overflow:hidden}figure{margin:0}code,kbd,pre,samp{font-family:Monaco,Menlo,Consolas,"Courier New",FontAwesome,monospace;font-size:1em}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}input[type=checkbox],input[type=radio]{cursor:pointer;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top;resize:vertical}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{position:relative;background:#fff;font-family:"Segoe UI","Lucida Grande",Helvetica,Arial,"Microsoft YaHei",FreeSans,Arimo,"Droid Sans","wenquanyi micro hei","Hiragino Sans GB","Hiragino Sans GB W3",FontAwesome,sans-serif;font-weight:400;line-height:1.6;color:#333;font-size:1.6rem}body,button,input,select,textarea{text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-moz-font-feature-settings:"liga","kern"}@media only screen and (max-width:640px){body{word-wrap:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;-moz-hyphens:auto;hyphens:auto}}a{color:#0e90d2}a:focus,a:hover{color:#095f8a}a:focus{outline:thin dotted;outline:1px auto -webkit-focus-ring-color;outline-offset:-2px}ins{background:#ffa;color:#333}mark{background:#ffa;color:#333}abbr[title],dfn[title]{cursor:help}dfn[title]{border-bottom:1px dotted;font-style:normal}address,blockquote,dl,fieldset,figure,hr,ol,p,pre,ul{margin:0 0 1.6rem 0}*+address,*+blockquote,*+dl,*+fieldset,*+figure,*+hr,*+ol,*+p,*+pre,*+ul{margin-top:1.6rem}h1,h2,h3,h4,h5,h6{margin:0 0 1.6rem 0;font-weight:600;font-size:100%}h1{font-size:1.5em}h2{font-size:1.25em}*+h1,*+h2,*+h3,*+h4,*+h5,*+h6{margin-top:2em}ol,ul{padding-left:2em}ol>li>ol,ol>li>ul,ul>li>ol,ul>li>ul{margin:1em 0}dt{font-weight:700}dt+dd{margin-top:.5em}dd{margin-left:0}dd+dt{margin-top:1em}hr{display:block;padding:0;border:0;height:0;border-top:1px solid #eee;-webkit-box-sizing:content-box;box-sizing:content-box}address{font-style:normal}blockquote{padding-top:5px;padding-bottom:5px;padding-left:15px;border-left:4px solid #ddd;font-family:Georgia,"Times New Roman",Times,Kai,"Kaiti SC",KaiTi,BiauKai,FontAwesome,serif}blockquote small{display:block;color:#999;font-family:"Segoe UI","Lucida Grande",Helvetica,Arial,"Microsoft YaHei",FreeSans,Arimo,"Droid Sans","wenquanyi micro hei","Hiragino Sans GB","Hiragino Sans GB W3",FontAwesome,sans-serif;text-align:right}blockquote p:last-of-type{margin-bottom:0}iframe{border:0}button,input:not([type=radio]):not([type=checkbox]),select{vertical-align:middle}.am-scrollbar-measure{width:100px;height:100px;overflow:scroll;position:absolute;top:-9999px}.am-container{-webkit-box-sizing:border-box;box-sizing:border-box;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem;width:100%;max-width:1000px}.am-container:after,.am-container:before{content:" ";display:table}.am-container:after{clear:both}@media only screen and (min-width:641px){.am-container{padding-left:1.5rem;padding-right:1.5rem}}.am-container>.am-g{width:auto;margin-left:-1rem;margin-right:-1rem}@media only screen and (min-width:641px){.am-container>.am-g{margin-left:-1.5rem;margin-right:-1.5rem}}.am-g{margin:0 auto;width:100%}.am-g:after,.am-g:before{content:" ";display:table}.am-g:after{clear:both}.am-g .am-g{margin-left:-1rem;margin-right:-1rem;width:auto}.am-g .am-g.am-g-collapse{margin-left:0;margin-right:0;width:auto}@media only screen and (min-width:641px){.am-g .am-g{margin-left:-1.5rem;margin-right:-1.5rem}}.am-g.am-g-collapse .am-g{margin-left:0;margin-right:0}.am-g-collapse [class*=am-u-]{padding-left:0;padding-right:0}.am-g-fixed{max-width:1000px}[class*=am-u-]{width:100%;padding-left:1rem;padding-right:1rem;float:left;position:relative}[class*=am-u-]+[class*=am-u-]:last-child{float:right}[class*=am-u-]+[class*=am-u-].am-u-end{float:left}@media only screen and (min-width:641px){[class*=am-u-]{padding-left:1.5rem;padding-right:1.5rem}}[class*=am-u-pull-]{left:auto}[class*=am-u-push-]{right:auto}@media only screen{.am-u-sm-1{width:8.33333333%}.am-u-sm-2{width:16.66666667%}.am-u-sm-3{width:25%}.am-u-sm-4{width:33.33333333%}.am-u-sm-5{width:41.66666667%}.am-u-sm-6{width:50%}.am-u-sm-7{width:58.33333333%}.am-u-sm-8{width:66.66666667%}.am-u-sm-9{width:75%}.am-u-sm-10{width:83.33333333%}.am-u-sm-11{width:91.66666667%}.am-u-sm-12{width:100%}.am-u-sm-pull-0{right:0}.am-u-sm-pull-1{right:8.33333333%}.am-u-sm-pull-2{right:16.66666667%}.am-u-sm-pull-3{right:25%}.am-u-sm-pull-4{right:33.33333333%}.am-u-sm-pull-5{right:41.66666667%}.am-u-sm-pull-6{right:50%}.am-u-sm-pull-7{right:58.33333333%}.am-u-sm-pull-8{right:66.66666667%}.am-u-sm-pull-9{right:75%}.am-u-sm-pull-10{right:83.33333333%}.am-u-sm-pull-11{right:91.66666667%}.am-u-sm-push-0{left:0}.am-u-sm-push-1{left:8.33333333%}.am-u-sm-push-2{left:16.66666667%}.am-u-sm-push-3{left:25%}.am-u-sm-push-4{left:33.33333333%}.am-u-sm-push-5{left:41.66666667%}.am-u-sm-push-6{left:50%}.am-u-sm-push-7{left:58.33333333%}.am-u-sm-push-8{left:66.66666667%}.am-u-sm-push-9{left:75%}.am-u-sm-push-10{left:83.33333333%}.am-u-sm-push-11{left:91.66666667%}.am-u-sm-offset-0{margin-left:0}.am-u-sm-offset-1{margin-left:8.33333333%}.am-u-sm-offset-2{margin-left:16.66666667%}.am-u-sm-offset-3{margin-left:25%}.am-u-sm-offset-4{margin-left:33.33333333%}.am-u-sm-offset-5{margin-left:41.66666667%}.am-u-sm-offset-6{margin-left:50%}.am-u-sm-offset-7{margin-left:58.33333333%}.am-u-sm-offset-8{margin-left:66.66666667%}.am-u-sm-offset-9{margin-left:75%}.am-u-sm-offset-10{margin-left:83.33333333%}.am-u-sm-offset-11{margin-left:91.66666667%}.am-u-sm-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}[class*=am-u-].am-u-sm-centered{margin-left:auto;margin-right:auto;float:none}[class*=am-u-].am-u-sm-centered:last-child{float:none}[class*=am-u-].am-u-sm-uncentered{margin-left:0;margin-right:0;float:left}[class*=am-u-].am-u-sm-uncentered:last-child{float:left}}@media only screen and (min-width:641px){.am-u-md-1{width:8.33333333%}.am-u-md-2{width:16.66666667%}.am-u-md-3{width:25%}.am-u-md-4{width:33.33333333%}.am-u-md-5{width:41.66666667%}.am-u-md-6{width:50%}.am-u-md-7{width:58.33333333%}.am-u-md-8{width:66.66666667%}.am-u-md-9{width:75%}.am-u-md-10{width:83.33333333%}.am-u-md-11{width:91.66666667%}.am-u-md-12{width:100%}.am-u-md-pull-0{right:0}.am-u-md-pull-1{right:8.33333333%}.am-u-md-pull-2{right:16.66666667%}.am-u-md-pull-3{right:25%}.am-u-md-pull-4{right:33.33333333%}.am-u-md-pull-5{right:41.66666667%}.am-u-md-pull-6{right:50%}.am-u-md-pull-7{right:58.33333333%}.am-u-md-pull-8{right:66.66666667%}.am-u-md-pull-9{right:75%}.am-u-md-pull-10{right:83.33333333%}.am-u-md-pull-11{right:91.66666667%}.am-u-md-push-0{left:0}.am-u-md-push-1{left:8.33333333%}.am-u-md-push-2{left:16.66666667%}.am-u-md-push-3{left:25%}.am-u-md-push-4{left:33.33333333%}.am-u-md-push-5{left:41.66666667%}.am-u-md-push-6{left:50%}.am-u-md-push-7{left:58.33333333%}.am-u-md-push-8{left:66.66666667%}.am-u-md-push-9{left:75%}.am-u-md-push-10{left:83.33333333%}.am-u-md-push-11{left:91.66666667%}.am-u-md-offset-0{margin-left:0}.am-u-md-offset-1{margin-left:8.33333333%}.am-u-md-offset-2{margin-left:16.66666667%}.am-u-md-offset-3{margin-left:25%}.am-u-md-offset-4{margin-left:33.33333333%}.am-u-md-offset-5{margin-left:41.66666667%}.am-u-md-offset-6{margin-left:50%}.am-u-md-offset-7{margin-left:58.33333333%}.am-u-md-offset-8{margin-left:66.66666667%}.am-u-md-offset-9{margin-left:75%}.am-u-md-offset-10{margin-left:83.33333333%}.am-u-md-offset-11{margin-left:91.66666667%}.am-u-md-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}[class*=am-u-].am-u-md-centered{margin-left:auto;margin-right:auto;float:none}[class*=am-u-].am-u-md-centered:last-child{float:none}[class*=am-u-].am-u-md-uncentered{margin-left:0;margin-right:0;float:left}[class*=am-u-].am-u-md-uncentered:last-child{float:left}}@media only screen and (min-width:1025px){.am-u-lg-1{width:8.33333333%}.am-u-lg-2{width:16.66666667%}.am-u-lg-3{width:25%}.am-u-lg-4{width:33.33333333%}.am-u-lg-5{width:41.66666667%}.am-u-lg-6{width:50%}.am-u-lg-7{width:58.33333333%}.am-u-lg-8{width:66.66666667%}.am-u-lg-9{width:75%}.am-u-lg-10{width:83.33333333%}.am-u-lg-11{width:91.66666667%}.am-u-lg-12{width:100%}.am-u-lg-pull-0{right:0}.am-u-lg-pull-1{right:8.33333333%}.am-u-lg-pull-2{right:16.66666667%}.am-u-lg-pull-3{right:25%}.am-u-lg-pull-4{right:33.33333333%}.am-u-lg-pull-5{right:41.66666667%}.am-u-lg-pull-6{right:50%}.am-u-lg-pull-7{right:58.33333333%}.am-u-lg-pull-8{right:66.66666667%}.am-u-lg-pull-9{right:75%}.am-u-lg-pull-10{right:83.33333333%}.am-u-lg-pull-11{right:91.66666667%}.am-u-lg-push-0{left:0}.am-u-lg-push-1{left:8.33333333%}.am-u-lg-push-2{left:16.66666667%}.am-u-lg-push-3{left:25%}.am-u-lg-push-4{left:33.33333333%}.am-u-lg-push-5{left:41.66666667%}.am-u-lg-push-6{left:50%}.am-u-lg-push-7{left:58.33333333%}.am-u-lg-push-8{left:66.66666667%}.am-u-lg-push-9{left:75%}.am-u-lg-push-10{left:83.33333333%}.am-u-lg-push-11{left:91.66666667%}.am-u-lg-offset-0{margin-left:0}.am-u-lg-offset-1{margin-left:8.33333333%}.am-u-lg-offset-2{margin-left:16.66666667%}.am-u-lg-offset-3{margin-left:25%}.am-u-lg-offset-4{margin-left:33.33333333%}.am-u-lg-offset-5{margin-left:41.66666667%}.am-u-lg-offset-6{margin-left:50%}.am-u-lg-offset-7{margin-left:58.33333333%}.am-u-lg-offset-8{margin-left:66.66666667%}.am-u-lg-offset-9{margin-left:75%}.am-u-lg-offset-10{margin-left:83.33333333%}.am-u-lg-offset-11{margin-left:91.66666667%}.am-u-lg-reset-order{margin-left:0;margin-right:0;left:auto;right:auto;float:left}[class*=am-u-].am-u-lg-centered{margin-left:auto;margin-right:auto;float:none}[class*=am-u-].am-u-lg-centered:last-child{float:none}[class*=am-u-].am-u-lg-uncentered{margin-left:0;margin-right:0;float:left}[class*=am-u-].am-u-lg-uncentered:last-child{float:left}}[class*=am-avg-]{display:block;padding:0;margin:0;list-style:none}[class*=am-avg-]:after,[class*=am-avg-]:before{content:" ";display:table}[class*=am-avg-]:after{clear:both}[class*=am-avg-]>li{display:block;height:auto;float:left}@media only screen{.am-avg-sm-1>li{width:100%}.am-avg-sm-1>li:nth-of-type(n){clear:none}.am-avg-sm-1>li:nth-of-type(1n+1){clear:both}.am-avg-sm-2>li{width:50%}.am-avg-sm-2>li:nth-of-type(n){clear:none}.am-avg-sm-2>li:nth-of-type(2n+1){clear:both}.am-avg-sm-3>li{width:33.33333333%}.am-avg-sm-3>li:nth-of-type(n){clear:none}.am-avg-sm-3>li:nth-of-type(3n+1){clear:both}.am-avg-sm-4>li{width:25%}.am-avg-sm-4>li:nth-of-type(n){clear:none}.am-avg-sm-4>li:nth-of-type(4n+1){clear:both}.am-avg-sm-5>li{width:20%}.am-avg-sm-5>li:nth-of-type(n){clear:none}.am-avg-sm-5>li:nth-of-type(5n+1){clear:both}.am-avg-sm-6>li{width:16.66666667%}.am-avg-sm-6>li:nth-of-type(n){clear:none}.am-avg-sm-6>li:nth-of-type(6n+1){clear:both}.am-avg-sm-7>li{width:14.28571429%}.am-avg-sm-7>li:nth-of-type(n){clear:none}.am-avg-sm-7>li:nth-of-type(7n+1){clear:both}.am-avg-sm-8>li{width:12.5%}.am-avg-sm-8>li:nth-of-type(n){clear:none}.am-avg-sm-8>li:nth-of-type(8n+1){clear:both}.am-avg-sm-9>li{width:11.11111111%}.am-avg-sm-9>li:nth-of-type(n){clear:none}.am-avg-sm-9>li:nth-of-type(9n+1){clear:both}.am-avg-sm-10>li{width:10%}.am-avg-sm-10>li:nth-of-type(n){clear:none}.am-avg-sm-10>li:nth-of-type(10n+1){clear:both}.am-avg-sm-11>li{width:9.09090909%}.am-avg-sm-11>li:nth-of-type(n){clear:none}.am-avg-sm-11>li:nth-of-type(11n+1){clear:both}.am-avg-sm-12>li{width:8.33333333%}.am-avg-sm-12>li:nth-of-type(n){clear:none}.am-avg-sm-12>li:nth-of-type(12n+1){clear:both}}@media only screen and (min-width:641px){.am-avg-md-1>li{width:100%}.am-avg-md-1>li:nth-of-type(n){clear:none}.am-avg-md-1>li:nth-of-type(1n+1){clear:both}.am-avg-md-2>li{width:50%}.am-avg-md-2>li:nth-of-type(n){clear:none}.am-avg-md-2>li:nth-of-type(2n+1){clear:both}.am-avg-md-3>li{width:33.33333333%}.am-avg-md-3>li:nth-of-type(n){clear:none}.am-avg-md-3>li:nth-of-type(3n+1){clear:both}.am-avg-md-4>li{width:25%}.am-avg-md-4>li:nth-of-type(n){clear:none}.am-avg-md-4>li:nth-of-type(4n+1){clear:both}.am-avg-md-5>li{width:20%}.am-avg-md-5>li:nth-of-type(n){clear:none}.am-avg-md-5>li:nth-of-type(5n+1){clear:both}.am-avg-md-6>li{width:16.66666667%}.am-avg-md-6>li:nth-of-type(n){clear:none}.am-avg-md-6>li:nth-of-type(6n+1){clear:both}.am-avg-md-7>li{width:14.28571429%}.am-avg-md-7>li:nth-of-type(n){clear:none}.am-avg-md-7>li:nth-of-type(7n+1){clear:both}.am-avg-md-8>li{width:12.5%}.am-avg-md-8>li:nth-of-type(n){clear:none}.am-avg-md-8>li:nth-of-type(8n+1){clear:both}.am-avg-md-9>li{width:11.11111111%}.am-avg-md-9>li:nth-of-type(n){clear:none}.am-avg-md-9>li:nth-of-type(9n+1){clear:both}.am-avg-md-10>li{width:10%}.am-avg-md-10>li:nth-of-type(n){clear:none}.am-avg-md-10>li:nth-of-type(10n+1){clear:both}.am-avg-md-11>li{width:9.09090909%}.am-avg-md-11>li:nth-of-type(n){clear:none}.am-avg-md-11>li:nth-of-type(11n+1){clear:both}.am-avg-md-12>li{width:8.33333333%}.am-avg-md-12>li:nth-of-type(n){clear:none}.am-avg-md-12>li:nth-of-type(12n+1){clear:both}}@media only screen and (min-width:1025px){.am-avg-lg-1>li{width:100%}.am-avg-lg-1>li:nth-of-type(n){clear:none}.am-avg-lg-1>li:nth-of-type(1n+1){clear:both}.am-avg-lg-2>li{width:50%}.am-avg-lg-2>li:nth-of-type(n){clear:none}.am-avg-lg-2>li:nth-of-type(2n+1){clear:both}.am-avg-lg-3>li{width:33.33333333%}.am-avg-lg-3>li:nth-of-type(n){clear:none}.am-avg-lg-3>li:nth-of-type(3n+1){clear:both}.am-avg-lg-4>li{width:25%}.am-avg-lg-4>li:nth-of-type(n){clear:none}.am-avg-lg-4>li:nth-of-type(4n+1){clear:both}.am-avg-lg-5>li{width:20%}.am-avg-lg-5>li:nth-of-type(n){clear:none}.am-avg-lg-5>li:nth-of-type(5n+1){clear:both}.am-avg-lg-6>li{width:16.66666667%}.am-avg-lg-6>li:nth-of-type(n){clear:none}.am-avg-lg-6>li:nth-of-type(6n+1){clear:both}.am-avg-lg-7>li{width:14.28571429%}.am-avg-lg-7>li:nth-of-type(n){clear:none}.am-avg-lg-7>li:nth-of-type(7n+1){clear:both}.am-avg-lg-8>li{width:12.5%}.am-avg-lg-8>li:nth-of-type(n){clear:none}.am-avg-lg-8>li:nth-of-type(8n+1){clear:both}.am-avg-lg-9>li{width:11.11111111%}.am-avg-lg-9>li:nth-of-type(n){clear:none}.am-avg-lg-9>li:nth-of-type(9n+1){clear:both}.am-avg-lg-10>li{width:10%}.am-avg-lg-10>li:nth-of-type(n){clear:none}.am-avg-lg-10>li:nth-of-type(10n+1){clear:both}.am-avg-lg-11>li{width:9.09090909%}.am-avg-lg-11>li:nth-of-type(n){clear:none}.am-avg-lg-11>li:nth-of-type(11n+1){clear:both}.am-avg-lg-12>li{width:8.33333333%}.am-avg-lg-12>li:nth-of-type(n){clear:none}.am-avg-lg-12>li:nth-of-type(12n+1){clear:both}}code,kbd,pre,samp{font-family:Monaco,Menlo,Consolas,"Courier New",FontAwesome,monospace}code{padding:2px 4px;font-size:1.3rem;color:#c7254e;background-color:#f8f8f8;white-space:nowrap;border-radius:0}pre{display:block;padding:1rem;margin:1rem 0;font-size:1.3rem;line-height:1.6;word-break:break-all;word-wrap:break-word;color:#555;background-color:#f8f8f8;border:1px solid #dedede;border-radius:0}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.am-pre-scrollable{max-height:24rem;overflow-y:scroll}.am-btn{display:inline-block;margin-bottom:0;padding:.5em 1em;vertical-align:middle;font-size:1.6rem;font-weight:400;line-height:1.2;text-align:center;white-space:nowrap;background-image:none;border:1px solid transparent;border-radius:0;cursor:pointer;outline:0;-webkit-appearance:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:background-color .3s ease-out,border-color .3s ease-out;transition:background-color .3s ease-out,border-color .3s ease-out}.am-btn:active:focus,.am-btn:focus{outline:thin dotted;outline:1px auto -webkit-focus-ring-color;outline-offset:-2px}.am-btn:focus,.am-btn:hover{color:#444;text-decoration:none}.am-btn.am-active,.am-btn:active{background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.15);box-shadow:inset 0 3px 5px rgba(0,0,0,.15)}.am-btn.am-disabled,.am-btn[disabled],fieldset[disabled] .am-btn{pointer-events:none;border-color:transparent;cursor:not-allowed;opacity:.45;-webkit-box-shadow:none;box-shadow:none}.am-btn.am-round{border-radius:1000px}.am-btn.am-radius{border-radius:2px}.am-btn-default{color:#444;background-color:#e6e6e6;border-color:#e6e6e6}a.am-btn-default:visited{color:#444}.am-btn-default.am-active,.am-btn-default:active,.am-btn-default:focus,.am-btn-default:hover,.am-dropdown.am-active .am-btn-default.am-dropdown-toggle{color:#444;border-color:#c7c7c7}.am-btn-default:focus,.am-btn-default:hover{background-color:#d4d4d4}.am-btn-default.am-active,.am-btn-default:active,.am-dropdown.am-active .am-btn-default.am-dropdown-toggle{background-image:none;background-color:#c2c2c2}.am-btn-default.am-disabled,.am-btn-default.am-disabled.am-active,.am-btn-default.am-disabled:active,.am-btn-default.am-disabled:focus,.am-btn-default.am-disabled:hover,.am-btn-default[disabled],.am-btn-default[disabled].am-active,.am-btn-default[disabled]:active,.am-btn-default[disabled]:focus,.am-btn-default[disabled]:hover,fieldset[disabled] .am-btn-default,fieldset[disabled] .am-btn-default.am-active,fieldset[disabled] .am-btn-default:active,fieldset[disabled] .am-btn-default:focus,fieldset[disabled] .am-btn-default:hover{background-color:#e6e6e6;border-color:#e6e6e6}.am-btn-group .am-btn-default,.am-btn-group-stacked .am-btn-default{border-color:#d9d9d9}.am-btn-primary{color:#fff;background-color:#0e90d2;border-color:#0e90d2}a.am-btn-primary:visited{color:#fff}.am-btn-primary.am-active,.am-btn-primary:active,.am-btn-primary:focus,.am-btn-primary:hover,.am-dropdown.am-active .am-btn-primary.am-dropdown-toggle{color:#fff;border-color:#0a6999}.am-btn-primary:focus,.am-btn-primary:hover{background-color:#0c79b1}.am-btn-primary.am-active,.am-btn-primary:active,.am-dropdown.am-active .am-btn-primary.am-dropdown-toggle{background-image:none;background-color:#0a628f}.am-btn-primary.am-disabled,.am-btn-primary.am-disabled.am-active,.am-btn-primary.am-disabled:active,.am-btn-primary.am-disabled:focus,.am-btn-primary.am-disabled:hover,.am-btn-primary[disabled],.am-btn-primary[disabled].am-active,.am-btn-primary[disabled]:active,.am-btn-primary[disabled]:focus,.am-btn-primary[disabled]:hover,fieldset[disabled] .am-btn-primary,fieldset[disabled] .am-btn-primary.am-active,fieldset[disabled] .am-btn-primary:active,fieldset[disabled] .am-btn-primary:focus,fieldset[disabled] .am-btn-primary:hover{background-color:#0e90d2;border-color:#0e90d2}.am-btn-group .am-btn-primary,.am-btn-group-stacked .am-btn-primary{border-color:#0c80ba}.am-btn-secondary{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}a.am-btn-secondary:visited{color:#fff}.am-btn-secondary.am-active,.am-btn-secondary:active,.am-btn-secondary:focus,.am-btn-secondary:hover,.am-dropdown.am-active .am-btn-secondary.am-dropdown-toggle{color:#fff;border-color:#0f9ae0}.am-btn-secondary:focus,.am-btn-secondary:hover{background-color:#19a7f0}.am-btn-secondary.am-active,.am-btn-secondary:active,.am-dropdown.am-active .am-btn-secondary.am-dropdown-toggle{background-image:none;background-color:#0e93d7}.am-btn-secondary.am-disabled,.am-btn-secondary.am-disabled.am-active,.am-btn-secondary.am-disabled:active,.am-btn-secondary.am-disabled:focus,.am-btn-secondary.am-disabled:hover,.am-btn-secondary[disabled],.am-btn-secondary[disabled].am-active,.am-btn-secondary[disabled]:active,.am-btn-secondary[disabled]:focus,.am-btn-secondary[disabled]:hover,fieldset[disabled] .am-btn-secondary,fieldset[disabled] .am-btn-secondary.am-active,fieldset[disabled] .am-btn-secondary:active,fieldset[disabled] .am-btn-secondary:focus,fieldset[disabled] .am-btn-secondary:hover{background-color:#3bb4f2;border-color:#3bb4f2}.am-btn-group .am-btn-secondary,.am-btn-group-stacked .am-btn-secondary{border-color:#23abf0}.am-btn-warning{color:#fff;background-color:#F37B1D;border-color:#F37B1D}a.am-btn-warning:visited{color:#fff}.am-btn-warning.am-active,.am-btn-warning:active,.am-btn-warning:focus,.am-btn-warning:hover,.am-dropdown.am-active .am-btn-warning.am-dropdown-toggle{color:#fff;border-color:#c85e0b}.am-btn-warning:focus,.am-btn-warning:hover{background-color:#e0690c}.am-btn-warning.am-active,.am-btn-warning:active,.am-dropdown.am-active .am-btn-warning.am-dropdown-toggle{background-image:none;background-color:#be590a}.am-btn-warning.am-disabled,.am-btn-warning.am-disabled.am-active,.am-btn-warning.am-disabled:active,.am-btn-warning.am-disabled:focus,.am-btn-warning.am-disabled:hover,.am-btn-warning[disabled],.am-btn-warning[disabled].am-active,.am-btn-warning[disabled]:active,.am-btn-warning[disabled]:focus,.am-btn-warning[disabled]:hover,fieldset[disabled] .am-btn-warning,fieldset[disabled] .am-btn-warning.am-active,fieldset[disabled] .am-btn-warning:active,fieldset[disabled] .am-btn-warning:focus,fieldset[disabled] .am-btn-warning:hover{background-color:#F37B1D;border-color:#F37B1D}.am-btn-group .am-btn-warning,.am-btn-group-stacked .am-btn-warning{border-color:#ea6e0c}.am-btn-danger{color:#fff;background-color:#dd514c;border-color:#dd514c}a.am-btn-danger:visited{color:#fff}.am-btn-danger.am-active,.am-btn-danger:active,.am-btn-danger:focus,.am-btn-danger:hover,.am-dropdown.am-active .am-btn-danger.am-dropdown-toggle{color:#fff;border-color:#c62b26}.am-btn-danger:focus,.am-btn-danger:hover{background-color:#d7342e}.am-btn-danger.am-active,.am-btn-danger:active,.am-dropdown.am-active .am-btn-danger.am-dropdown-toggle{background-image:none;background-color:#be2924}.am-btn-danger.am-disabled,.am-btn-danger.am-disabled.am-active,.am-btn-danger.am-disabled:active,.am-btn-danger.am-disabled:focus,.am-btn-danger.am-disabled:hover,.am-btn-danger[disabled],.am-btn-danger[disabled].am-active,.am-btn-danger[disabled]:active,.am-btn-danger[disabled]:focus,.am-btn-danger[disabled]:hover,fieldset[disabled] .am-btn-danger,fieldset[disabled] .am-btn-danger.am-active,fieldset[disabled] .am-btn-danger:active,fieldset[disabled] .am-btn-danger:focus,fieldset[disabled] .am-btn-danger:hover{background-color:#dd514c;border-color:#dd514c}.am-btn-group .am-btn-danger,.am-btn-group-stacked .am-btn-danger{border-color:#d93c37}.am-btn-success{color:#fff;background-color:#5eb95e;border-color:#5eb95e}a.am-btn-success:visited{color:#fff}.am-btn-success.am-active,.am-btn-success:active,.am-btn-success:focus,.am-btn-success:hover,.am-dropdown.am-active .am-btn-success.am-dropdown-toggle{color:#fff;border-color:#429842}.am-btn-success:focus,.am-btn-success:hover{background-color:#4aaa4a}.am-btn-success.am-active,.am-btn-success:active,.am-dropdown.am-active .am-btn-success.am-dropdown-toggle{background-image:none;background-color:#3f913f}.am-btn-success.am-disabled,.am-btn-success.am-disabled.am-active,.am-btn-success.am-disabled:active,.am-btn-success.am-disabled:focus,.am-btn-success.am-disabled:hover,.am-btn-success[disabled],.am-btn-success[disabled].am-active,.am-btn-success[disabled]:active,.am-btn-success[disabled]:focus,.am-btn-success[disabled]:hover,fieldset[disabled] .am-btn-success,fieldset[disabled] .am-btn-success.am-active,fieldset[disabled] .am-btn-success:active,fieldset[disabled] .am-btn-success:focus,fieldset[disabled] .am-btn-success:hover{background-color:#5eb95e;border-color:#5eb95e}.am-btn-group .am-btn-success,.am-btn-group-stacked .am-btn-success{border-color:#4db14d}.am-btn-link{color:#0e90d2;font-weight:400;cursor:pointer;border-radius:0}.am-btn-link,.am-btn-link:active,.am-btn-link[disabled],fieldset[disabled] .am-btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.am-btn-link,.am-btn-link:active,.am-btn-link:focus,.am-btn-link:hover{border-color:transparent}.am-btn-link:focus,.am-btn-link:hover{color:#095f8a;text-decoration:underline;background-color:transparent}.am-btn-link[disabled]:focus,.am-btn-link[disabled]:hover,fieldset[disabled] .am-btn-link:focus,fieldset[disabled] .am-btn-link:hover{color:#999;text-decoration:none}.am-btn-xs{font-size:1.2rem}.am-btn-sm{font-size:1.4rem}.am-btn-lg{font-size:1.8rem}.am-btn-xl{font-size:2rem}.am-btn-block{display:block;width:100%;padding-left:0;padding-right:0}.am-btn-block+.am-btn-block{margin-top:5px}input[type=button].am-btn-block,input[type=reset].am-btn-block,input[type=submit].am-btn-block{width:100%}.am-btn.am-btn-loading .am-icon-spin{margin-right:5px}table{max-width:100%;background-color:transparent;empty-cells:show}table code{white-space:normal}th{text-align:left}.am-table{width:100%;margin-bottom:1.6rem;border-spacing:0;border-collapse:separate}.am-table>tbody>tr>td,.am-table>tbody>tr>th,.am-table>tfoot>tr>td,.am-table>tfoot>tr>th,.am-table>thead>tr>td,.am-table>thead>tr>th{padding:.7rem;line-height:1.6;vertical-align:top;border-top:1px solid #ddd}.am-table>thead>tr>th{vertical-align:bottom;border-bottom:1px solid #ddd}.am-table>caption+thead>tr:first-child>td,.am-table>caption+thead>tr:first-child>th,.am-table>colgroup+thead>tr:first-child>td,.am-table>colgroup+thead>tr:first-child>th,.am-table>thead:first-child>tr:first-child>td,.am-table>thead:first-child>tr:first-child>th{border-top:0}.am-table>tbody+tbody tr:first-child td{border-top:2px solid #ddd}.am-table-bordered{border:1px solid #ddd;border-left:none}.am-table-bordered>tbody>tr>td,.am-table-bordered>tbody>tr>th,.am-table-bordered>tfoot>tr>td,.am-table-bordered>tfoot>tr>th,.am-table-bordered>thead>tr>td,.am-table-bordered>thead>tr>th{border-left:1px solid #ddd}.am-table-bordered>tbody>tr:first-child>td,.am-table-bordered>tbody>tr:first-child>th{border-top:none}.am-table-bordered>thead+tbody>tr:first-child>td,.am-table-bordered>thead+tbody>tr:first-child>th{border-top:1px solid #ddd}.am-table-radius{border:1px solid #ddd;border-radius:2px}.am-table-radius>thead>tr:first-child>td:first-child,.am-table-radius>thead>tr:first-child>th:first-child{border-top-left-radius:2px;border-left:none}.am-table-radius>thead>tr:first-child>td:last-child,.am-table-radius>thead>tr:first-child>th:last-child{border-top-right-radius:2px;border-right:none}.am-table-radius>tbody>tr>td:first-child,.am-table-radius>tbody>tr>th:first-child{border-left:none}.am-table-radius>tbody>tr>td:last-child,.am-table-radius>tbody>tr>th:last-child{border-right:none}.am-table-radius>tbody>tr:last-child>td,.am-table-radius>tbody>tr:last-child>th{border-bottom:none}.am-table-radius>tbody>tr:last-child>td:first-child,.am-table-radius>tbody>tr:last-child>th:first-child{border-bottom-left-radius:2px}.am-table-radius>tbody>tr:last-child>td:last-child,.am-table-radius>tbody>tr:last-child>th:last-child{border-bottom-right-radius:2px}.am-table-striped>tbody>tr:nth-child(odd)>td,.am-table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.am-table-hover>tbody>tr:hover>td,.am-table-hover>tbody>tr:hover>th{background-color:#e9e9e9}.am-table-compact>tbody>tr>td,.am-table-compact>tbody>tr>th,.am-table-compact>tfoot>tr>td,.am-table-compact>tfoot>tr>th,.am-table-compact>thead>tr>td,.am-table-compact>thead>tr>th{padding:.4rem}.am-table-centered>tbody>tr>td,.am-table-centered>tbody>tr>th,.am-table-centered>tfoot>tr>td,.am-table-centered>tfoot>tr>th,.am-table-centered>thead>tr>td,.am-table-centered>thead>tr>th{text-align:center}.am-table>tbody>tr.am-active>td,.am-table>tbody>tr.am-active>th,.am-table>tbody>tr>td.am-active,.am-table>tbody>tr>th.am-active,.am-table>tfoot>tr.am-active>td,.am-table>tfoot>tr.am-active>th,.am-table>tfoot>tr>td.am-active,.am-table>tfoot>tr>th.am-active,.am-table>thead>tr.am-active>td,.am-table>thead>tr.am-active>th,.am-table>thead>tr>td.am-active,.am-table>thead>tr>th.am-active{background-color:#ffd}.am-table>tbody>tr.am-disabled>td,.am-table>tbody>tr.am-disabled>th,.am-table>tbody>tr>td.am-disabled,.am-table>tbody>tr>th.am-disabled,.am-table>tfoot>tr.am-disabled>td,.am-table>tfoot>tr.am-disabled>th,.am-table>tfoot>tr>td.am-disabled,.am-table>tfoot>tr>th.am-disabled,.am-table>thead>tr.am-disabled>td,.am-table>thead>tr.am-disabled>th,.am-table>thead>tr>td.am-disabled,.am-table>thead>tr>th.am-disabled{color:#999}.am-table>tbody>tr.am-primary>td,.am-table>tbody>tr.am-primary>th,.am-table>tbody>tr>td.am-primary,.am-table>tbody>tr>th.am-primary,.am-table>tfoot>tr.am-primary>td,.am-table>tfoot>tr.am-primary>th,.am-table>tfoot>tr>td.am-primary,.am-table>tfoot>tr>th.am-primary,.am-table>thead>tr.am-primary>td,.am-table>thead>tr.am-primary>th,.am-table>thead>tr>td.am-primary,.am-table>thead>tr>th.am-primary{color:#0b76ac;background-color:rgba(14,144,210,.115)}.am-table>tbody>tr.am-success>td,.am-table>tbody>tr.am-success>th,.am-table>tbody>tr>td.am-success,.am-table>tbody>tr>th.am-success,.am-table>tfoot>tr.am-success>td,.am-table>tfoot>tr.am-success>th,.am-table>tfoot>tr>td.am-success,.am-table>tfoot>tr>th.am-success,.am-table>thead>tr.am-success>td,.am-table>thead>tr.am-success>th,.am-table>thead>tr>td.am-success,.am-table>thead>tr>th.am-success{color:#5eb95e;background-color:rgba(94,185,94,.115)}.am-table>tbody>tr.am-warning>td,.am-table>tbody>tr.am-warning>th,.am-table>tbody>tr>td.am-warning,.am-table>tbody>tr>th.am-warning,.am-table>tfoot>tr.am-warning>td,.am-table>tfoot>tr.am-warning>th,.am-table>tfoot>tr>td.am-warning,.am-table>tfoot>tr>th.am-warning,.am-table>thead>tr.am-warning>td,.am-table>thead>tr.am-warning>th,.am-table>thead>tr>td.am-warning,.am-table>thead>tr>th.am-warning{color:#F37B1D;background-color:rgba(243,123,29,.115)}.am-table>tbody>tr.am-danger>td,.am-table>tbody>tr.am-danger>th,.am-table>tbody>tr>td.am-danger,.am-table>tbody>tr>th.am-danger,.am-table>tfoot>tr.am-danger>td,.am-table>tfoot>tr.am-danger>th,.am-table>tfoot>tr>td.am-danger,.am-table>tfoot>tr>th.am-danger,.am-table>thead>tr.am-danger>td,.am-table>thead>tr.am-danger>th,.am-table>thead>tr>td.am-danger,.am-table>thead>tr>th.am-danger{color:#dd514c;background-color:rgba(221,81,76,.115)}fieldset{border:none}legend{display:block;width:100%;margin-bottom:2rem;font-size:2rem;line-height:inherit;color:#333;border-bottom:1px solid #e5e5e5;padding-bottom:.5rem}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-size:inherit;font-style:inherit;font-family:inherit}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted;outline:1px auto -webkit-focus-ring-color;outline-offset:-2px}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}output{display:block;padding-top:1.6rem;font-size:1.6rem;line-height:1.6;color:#555;vertical-align:middle}.am-form input[type=number],.am-form input[type=search],.am-form input[type=text],.am-form input[type=password],.am-form input[type=datetime],.am-form input[type=datetime-local],.am-form input[type=date],.am-form input[type=month],.am-form input[type=time],.am-form input[type=week],.am-form input[type=email],.am-form input[type=url],.am-form input[type=tel],.am-form input[type=color],.am-form select,.am-form textarea,.am-form-field{display:block;width:100%;padding:.5em;font-size:1.6rem;line-height:1.2;color:#555;vertical-align:middle;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:0;-webkit-appearance:none;-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}.am-form input[type=number]:focus,.am-form input[type=search]:focus,.am-form input[type=text]:focus,.am-form input[type=password]:focus,.am-form input[type=datetime]:focus,.am-form input[type=datetime-local]:focus,.am-form input[type=date]:focus,.am-form input[type=month]:focus,.am-form input[type=time]:focus,.am-form input[type=week]:focus,.am-form input[type=email]:focus,.am-form input[type=url]:focus,.am-form input[type=tel]:focus,.am-form input[type=color]:focus,.am-form select:focus,.am-form textarea:focus,.am-form-field:focus{outline:0}.am-form input[type=number]:focus,.am-form input[type=search]:focus,.am-form input[type=text]:focus,.am-form input[type=password]:focus,.am-form input[type=datetime]:focus,.am-form input[type=datetime-local]:focus,.am-form input[type=date]:focus,.am-form input[type=month]:focus,.am-form input[type=time]:focus,.am-form input[type=week]:focus,.am-form input[type=email]:focus,.am-form input[type=url]:focus,.am-form input[type=tel]:focus,.am-form input[type=color]:focus,.am-form select:focus,.am-form textarea:focus,.am-form-field:focus{background-color:#fefffe;border-color:#3bb4f2;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px rgba(59,180,242,.3);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px rgba(59,180,242,.3)}.am-form input[type=number]::-webkit-input-placeholder,.am-form input[type=search]::-webkit-input-placeholder,.am-form input[type=text]::-webkit-input-placeholder,.am-form input[type=password]::-webkit-input-placeholder,.am-form input[type=datetime]::-webkit-input-placeholder,.am-form input[type=datetime-local]::-webkit-input-placeholder,.am-form input[type=date]::-webkit-input-placeholder,.am-form input[type=month]::-webkit-input-placeholder,.am-form input[type=time]::-webkit-input-placeholder,.am-form input[type=week]::-webkit-input-placeholder,.am-form input[type=email]::-webkit-input-placeholder,.am-form input[type=url]::-webkit-input-placeholder,.am-form input[type=tel]::-webkit-input-placeholder,.am-form input[type=color]::-webkit-input-placeholder,.am-form select::-webkit-input-placeholder,.am-form textarea::-webkit-input-placeholder,.am-form-field::-webkit-input-placeholder{color:#999}.am-form input[type=number]::-moz-placeholder,.am-form input[type=search]::-moz-placeholder,.am-form input[type=text]::-moz-placeholder,.am-form input[type=password]::-moz-placeholder,.am-form input[type=datetime]::-moz-placeholder,.am-form input[type=datetime-local]::-moz-placeholder,.am-form input[type=date]::-moz-placeholder,.am-form input[type=month]::-moz-placeholder,.am-form input[type=time]::-moz-placeholder,.am-form input[type=week]::-moz-placeholder,.am-form input[type=email]::-moz-placeholder,.am-form input[type=url]::-moz-placeholder,.am-form input[type=tel]::-moz-placeholder,.am-form input[type=color]::-moz-placeholder,.am-form select::-moz-placeholder,.am-form textarea::-moz-placeholder,.am-form-field::-moz-placeholder{color:#999}.am-form input[type=number]:-ms-input-placeholder,.am-form input[type=search]:-ms-input-placeholder,.am-form input[type=text]:-ms-input-placeholder,.am-form input[type=password]:-ms-input-placeholder,.am-form input[type=datetime]:-ms-input-placeholder,.am-form input[type=datetime-local]:-ms-input-placeholder,.am-form input[type=date]:-ms-input-placeholder,.am-form input[type=month]:-ms-input-placeholder,.am-form input[type=time]:-ms-input-placeholder,.am-form input[type=week]:-ms-input-placeholder,.am-form input[type=email]:-ms-input-placeholder,.am-form input[type=url]:-ms-input-placeholder,.am-form input[type=tel]:-ms-input-placeholder,.am-form input[type=color]:-ms-input-placeholder,.am-form select:-ms-input-placeholder,.am-form textarea:-ms-input-placeholder,.am-form-field:-ms-input-placeholder{color:#999}.am-form input[type=number]::placeholder,.am-form input[type=search]::placeholder,.am-form input[type=text]::placeholder,.am-form input[type=password]::placeholder,.am-form input[type=datetime]::placeholder,.am-form input[type=datetime-local]::placeholder,.am-form input[type=date]::placeholder,.am-form input[type=month]::placeholder,.am-form input[type=time]::placeholder,.am-form input[type=week]::placeholder,.am-form input[type=email]::placeholder,.am-form input[type=url]::placeholder,.am-form input[type=tel]::placeholder,.am-form input[type=color]::placeholder,.am-form select::placeholder,.am-form textarea::placeholder,.am-form-field::placeholder{color:#999}.am-form input[type=number]::-moz-placeholder,.am-form input[type=search]::-moz-placeholder,.am-form input[type=text]::-moz-placeholder,.am-form input[type=password]::-moz-placeholder,.am-form input[type=datetime]::-moz-placeholder,.am-form input[type=datetime-local]::-moz-placeholder,.am-form input[type=date]::-moz-placeholder,.am-form input[type=month]::-moz-placeholder,.am-form input[type=time]::-moz-placeholder,.am-form input[type=week]::-moz-placeholder,.am-form input[type=email]::-moz-placeholder,.am-form input[type=url]::-moz-placeholder,.am-form input[type=tel]::-moz-placeholder,.am-form input[type=color]::-moz-placeholder,.am-form select::-moz-placeholder,.am-form textarea::-moz-placeholder,.am-form-field::-moz-placeholder{opacity:1}.am-form input[type=number][disabled],.am-form input[type=number][readonly],.am-form input[type=search][disabled],.am-form input[type=search][readonly],.am-form input[type=text][disabled],.am-form input[type=text][readonly],.am-form input[type=password][disabled],.am-form input[type=password][readonly],.am-form input[type=datetime][disabled],.am-form input[type=datetime][readonly],.am-form input[type=datetime-local][disabled],.am-form input[type=datetime-local][readonly],.am-form input[type=date][disabled],.am-form input[type=date][readonly],.am-form input[type=month][disabled],.am-form input[type=month][readonly],.am-form input[type=time][disabled],.am-form input[type=time][readonly],.am-form input[type=week][disabled],.am-form input[type=week][readonly],.am-form input[type=email][disabled],.am-form input[type=email][readonly],.am-form input[type=url][disabled],.am-form input[type=url][readonly],.am-form input[type=tel][disabled],.am-form input[type=tel][readonly],.am-form input[type=color][disabled],.am-form input[type=color][readonly],.am-form select[disabled],.am-form select[readonly],.am-form textarea[disabled],.am-form textarea[readonly],.am-form-field[disabled],.am-form-field[readonly],fieldset[disabled] .am-form input[type=number],fieldset[disabled] .am-form input[type=search],fieldset[disabled] .am-form input[type=text],fieldset[disabled] .am-form input[type=password],fieldset[disabled] .am-form input[type=datetime],fieldset[disabled] .am-form input[type=datetime-local],fieldset[disabled] .am-form input[type=date],fieldset[disabled] .am-form input[type=month],fieldset[disabled] .am-form input[type=time],fieldset[disabled] .am-form input[type=week],fieldset[disabled] .am-form input[type=email],fieldset[disabled] .am-form input[type=url],fieldset[disabled] .am-form input[type=tel],fieldset[disabled] .am-form input[type=color],fieldset[disabled] .am-form select,fieldset[disabled] .am-form textarea,fieldset[disabled] .am-form-field{cursor:not-allowed;background-color:#eee}.am-form input[type=number].am-radius,.am-form input[type=search].am-radius,.am-form input[type=text].am-radius,.am-form input[type=password].am-radius,.am-form input[type=datetime].am-radius,.am-form input[type=datetime-local].am-radius,.am-form input[type=date].am-radius,.am-form input[type=month].am-radius,.am-form input[type=time].am-radius,.am-form input[type=week].am-radius,.am-form input[type=email].am-radius,.am-form input[type=url].am-radius,.am-form input[type=tel].am-radius,.am-form input[type=color].am-radius,.am-form select.am-radius,.am-form textarea.am-radius,.am-form-field.am-radius{border-radius:2px}.am-form input[type=number].am-round,.am-form input[type=search].am-round,.am-form input[type=text].am-round,.am-form input[type=password].am-round,.am-form input[type=datetime].am-round,.am-form input[type=datetime-local].am-round,.am-form input[type=date].am-round,.am-form input[type=month].am-round,.am-form input[type=time].am-round,.am-form input[type=week].am-round,.am-form input[type=email].am-round,.am-form input[type=url].am-round,.am-form input[type=tel].am-round,.am-form input[type=color].am-round,.am-form select.am-round,.am-form textarea.am-round,.am-form-field.am-round{border-radius:1000px}.am-form select[multiple],.am-form select[size],.am-form textarea{height:auto}.am-form select{-webkit-appearance:none!important;-moz-appearance:none!important;-webkit-border-radius:0;background:#fff url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+) no-repeat 100% center}.am-form select[multiple=multiple]{background-image:none}.am-form input[type=datetime-local],.am-form input[type=date],input[type=datetime-local].am-form-field,input[type=date].am-form-field{height:37px}.am-form input[type=datetime-local].am-input-sm,.am-form input[type=date].am-input-sm,input[type=datetime-local].am-form-field.am-input-sm,input[type=date].am-form-field.am-input-sm{height:32px}.am-form input[type=datetime-local] .am-input-lg,.am-form input[type=date] .am-input-lg,input[type=datetime-local].am-form-field .am-input-lg,input[type=date].am-form-field .am-input-lg{height:41px}.am-form-help{display:block;margin-top:5px;margin-bottom:10px;color:#999;font-size:1.3rem}.am-form-group{margin-bottom:1.5rem}.am-form-file{position:relative;overflow:hidden}.am-form-file input[type=file]{position:absolute;left:0;top:0;z-index:1;width:100%;opacity:0;cursor:pointer;font-size:50rem}.am-checkbox,.am-radio{display:block;min-height:1.92rem;margin-top:10px;margin-bottom:10px;padding-left:20px;vertical-align:middle}.am-checkbox label,.am-radio label{display:inline;margin-bottom:0;font-weight:400;cursor:pointer}.am-checkbox input[type=checkbox],.am-checkbox-inline input[type=checkbox],.am-radio input[type=radio],.am-radio-inline input[type=radio]{float:left;margin-left:-20px;outline:0}.am-checkbox+.am-checkbox,.am-radio+.am-radio{margin-top:-5px}.am-checkbox-inline,.am-radio-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.am-checkbox-inline+.am-checkbox-inline,.am-radio-inline+.am-radio-inline{margin-top:0;margin-left:10px}.am-checkbox-inline[disabled],.am-checkbox[disabled],.am-radio-inline[disabled],.am-radio[disabled],fieldset[disabled] .am-checkbox,fieldset[disabled] .am-checkbox-inline,fieldset[disabled] .am-radio,fieldset[disabled] .am-radio-inline,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.am-form-warning .am-checkbox,.am-form-warning .am-checkbox-inline,.am-form-warning .am-form-help,.am-form-warning .am-form-label,.am-form-warning .am-radio,.am-form-warning .am-radio-inline,.am-form-warning label{color:#F37B1D}.am-form-warning [class*=icon-]{color:#F37B1D}.am-form-warning .am-form-field{border-color:#F37B1D!important;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.am-form-warning .am-form-field:focus{background-color:#fefffe;border-color:#d2620b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px #f8b47e!important;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px #f8b47e!important}.am-form-error .am-checkbox,.am-form-error .am-checkbox-inline,.am-form-error .am-form-help,.am-form-error .am-form-label,.am-form-error .am-radio,.am-form-error .am-radio-inline,.am-form-error label{color:#dd514c}.am-form-error [class*=icon-]{color:#dd514c}.am-field-error,.am-form-error .am-form-field{border-color:#dd514c!important;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.am-field-error:focus,.am-form-error .am-form-field:focus{background-color:#fefffe;border-color:#cf2d27;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px #eda4a2!important;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px #eda4a2!important}.am-form-success .am-checkbox,.am-form-success .am-checkbox-inline,.am-form-success .am-form-help,.am-form-success .am-form-label,.am-form-success .am-radio,.am-form-success .am-radio-inline,.am-form-success label{color:#5eb95e}.am-form-success [class*=icon-]{color:#5eb95e}.am-field-valid,.am-form-success .am-form-field{border-color:#5eb95e!important;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.am-field-valid:focus,.am-form-success .am-form-field:focus{background-color:#fefffe;border-color:#459f45;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px #a5d8a5!important;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 5px #a5d8a5!important}.am-form-horizontal .am-checkbox,.am-form-horizontal .am-checkbox-inline,.am-form-horizontal .am-form-label,.am-form-horizontal .am-radio,.am-form-horizontal .am-radio-inline{margin-top:0;margin-bottom:0;padding-top:.6em}.am-form-horizontal .am-form-group:after,.am-form-horizontal .am-form-group:before{content:" ";display:table}.am-form-horizontal .am-form-group:after{clear:both}@media only screen and (min-width:641px){.am-form-horizontal .am-form-label{text-align:right}}@media only screen and (min-width:641px){.am-form-inline .am-form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.am-form-inline .am-form-field{display:inline-block;width:auto;vertical-align:middle}.am-form-inline .am-input-group{display:inline-table;vertical-align:middle}.am-form-inline .am-input-group .am-form-label,.am-form-inline .am-input-group .am-input-group-btn,.am-form-inline .am-input-group .am-input-group-label{width:auto}.am-form-inline .am-input-group>.am-form-field{width:100%}.am-form-inline .am-form-label{margin-bottom:0;vertical-align:middle}.am-form-inline .am-checkbox,.am-form-inline .am-radio{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.am-form-inline .am-checkbox input[type=checkbox],.am-form-inline .am-radio input[type=radio]{float:none;margin-left:0}}.am-input-sm{font-size:1.4rem!important}.am-input-lg{font-size:1.8rem!important}.am-form-group-sm .am-checkbox,.am-form-group-sm .am-form-field,.am-form-group-sm .am-form-label,.am-form-group-sm .am-radio{font-size:1.4rem!important}.am-form-group-lg .am-checkbox,.am-form-group-lg .am-form-field,.am-form-group-lg .am-form-label,.am-form-group-lg .am-radio{font-size:1.8rem!important}.am-form-group-lg input[type=checkbox],.am-form-group-lg input[type=radio]{margin-top:7px}.am-form-icon{position:relative}.am-form-icon .am-form-field{padding-left:1.75em!important}.am-form-icon [class*=am-icon-]{position:absolute;left:.5em;top:50%;display:block;margin-top:-.5em;line-height:1;z-index:2}.am-form-icon label~[class*=am-icon-]{top:70%}.am-form-feedback{position:relative}.am-form-feedback .am-form-field{padding-left:.5em!important;padding-right:1.75em!important}.am-form-feedback [class*=am-icon-]{right:.5em;left:auto}.am-form-horizontal .am-form-feedback [class*=am-icon-]{right:1.6em}.am-form-set{margin-bottom:1.5rem;padding:0}.am-form-set>input{position:relative;top:-1px;border-radius:0!important}.am-form-set>input:focus{z-index:2}.am-form-set>input:first-child{top:1px;border-top-right-radius:0!important;border-top-left-radius:0!important}.am-form-set>input:last-child{top:-2px;border-bottom-right-radius:0!important;border-bottom-left-radius:0!important}.am-img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:2px;line-height:1.6;background-color:#fff;border:1px solid #ddd;border-radius:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.am-img-thumbnail.am-radius{border-radius:2px}.am-img-responsive{display:block;max-width:100%;height:auto}.am-nav{margin-bottom:0;padding:0;list-style:none}.am-nav:after,.am-nav:before{content:" ";display:table}.am-nav:after{clear:both}.am-nav>li{position:relative;display:block}.am-nav>li+li{margin-top:5px}.am-nav>li+.am-nav-header{margin-top:1em}.am-nav>li>a{position:relative;display:block;padding:.4em 1em;border-radius:0}.am-nav>li>a:focus,.am-nav>li>a:hover{text-decoration:none;background-color:#eee}.am-nav>li.am-active>a,.am-nav>li.am-active>a:focus,.am-nav>li.am-active>a:hover{color:#fff;background-color:#0e90d2;cursor:default}.am-nav>li.am-disabled>a{color:#999}.am-nav>li.am-disabled>a:focus,.am-nav>li.am-disabled>a:hover{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.am-nav-header{padding:.4em 1em;text-transform:uppercase;font-weight:700;font-size:100%;color:#555}.am-nav-divider{margin:15px 1em!important;border-top:1px solid #ddd;-webkit-box-shadow:0 1px 0 #fff;box-shadow:0 1px 0 #fff}.am-nav-pills>li{float:left}.am-nav-pills>li+li{margin-left:5px;margin-top:0}.am-nav-tabs{border-bottom:1px solid #ddd}.am-nav-tabs>li{float:left;margin-bottom:-1px}.am-nav-tabs>li+li{margin-top:0}.am-nav-tabs>li>a{margin-right:5px;line-height:1.6;border:1px solid transparent;border-radius:0}.am-nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.am-nav-tabs>li.am-active>a,.am-nav-tabs>li.am-active>a:focus,.am-nav-tabs>li.am-active>a:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.am-nav-tabs.am-nav-justify{border-bottom:0}.am-nav-tabs.am-nav-justify>li>a{margin-right:0;border-bottom:1px solid #ddd;border-radius:0}.am-nav-tabs.am-nav-justify>.am-active>a,.am-nav-tabs.am-nav-justify>.am-active>a:focus,.am-nav-tabs.am-nav-justify>.am-active>a:hover{border-bottom-color:#fff}.am-nav-justify{width:100%}.am-nav-justify>li{float:none;display:table-cell;width:1%}.am-nav-justify>li>a{text-align:center;margin-bottom:0}.lte9 .am-nav-justify>li{display:table-cell;width:1%}.am-topbar{position:relative;min-height:50px;margin-bottom:1.6rem;background:#f8f8f8;border-width:0 0 1px;border-style:solid;border-color:#ddd;color:#666}.am-topbar:after,.am-topbar:before{content:" ";display:table}.am-topbar:after{clear:both}.am-topbar a{color:#666}.am-topbar-brand{margin:0}@media only screen and (min-width:641px){.am-topbar-brand{float:left}}.am-topbar-brand a:hover{color:#4d4d4d}.am-topbar-collapse{width:100%;overflow-x:visible;padding:10px;clear:both;-webkit-overflow-scrolling:touch}.am-topbar-collapse:after,.am-topbar-collapse:before{content:" ";display:table}.am-topbar-collapse:after{clear:both}.am-topbar-collapse.am-in{overflow-y:auto}@media only screen and (min-width:641px){.am-topbar-collapse{margin-top:0;padding:0;width:auto;clear:none}.am-topbar-collapse.am-collapse{display:block!important;height:auto!important;padding:0;overflow:visible!important}.am-topbar-collapse.am-in{overflow-y:visible}}.am-topbar-brand{padding:0 10px;float:left;font-size:1.8rem;height:50px;line-height:50px}.am-topbar-toggle{position:relative;float:right;margin-right:10px}@media only screen and (min-width:641px){.am-topbar-toggle{display:none}}@media only screen and (max-width:640px){.am-topbar-nav{margin-bottom:8px}.am-topbar-nav>li{float:none}}@media only screen and (max-width:640px){.am-topbar-nav>li+li{margin-left:0;margin-top:5px}}@media only screen and (min-width:641px){.am-topbar-nav{float:left}.am-topbar-nav>li>a{position:relative;line-height:50px;padding:0 10px}.am-topbar-nav>li>a:after{position:absolute;left:50%;margin-left:-7px;bottom:-1px;content:"";display:inline-block;width:0;height:0;vertical-align:middle;border-bottom:7px solid #f8f8f8;border-right:7px solid transparent;border-left:7px solid transparent;border-top:0 dotted;-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);opacity:0;-webkit-transition:opacity .1s;transition:opacity .1s}.am-topbar-nav>li>a:hover:after{opacity:1;border-bottom-color:#666}.am-topbar-nav>li.am-dropdown>a:after{display:none}.am-topbar-nav>li.am-active>a,.am-topbar-nav>li.am-active>a:focus,.am-topbar-nav>li.am-active>a:hover{border-radius:0;color:#0e90d2;background:0 0}.am-topbar-nav>li.am-active>a:after{opacity:1;border-bottom-color:#0e90d2}}@media only screen and (max-width:640px){.am-topbar-collapse .am-dropdown.am-active .am-dropdown-content{float:none;position:relative;width:100%}}@media only screen and (min-width:641px){.am-topbar-left{float:left}.am-topbar-right{float:right;margin-right:10px}}@media only screen and (max-width:640px){.am-topbar-form .am-form-group{margin-bottom:5px}}@media only screen and (min-width:641px){.am-topbar-form{padding:0 10px;margin-top:8px}.am-topbar-form .am-form-group+.am-btn{margin-left:5px}}.am-topbar-btn{margin-top:8px}@media only screen and (max-width:640px){.am-topbar-collapse .am-btn,.am-topbar-collapse .am-topbar-btn{display:block;width:100%}}.am-topbar-inverse{background-color:#0e90d2;border-color:#0b6fa2;color:#eee}.am-topbar-inverse a{color:#eee}.am-topbar-inverse .am-topbar-brand a{color:#fff}.am-topbar-inverse .am-topbar-brand a:focus,.am-topbar-inverse .am-topbar-brand a:hover{color:#fff;background-color:transparent}.am-topbar-inverse .am-topbar-nav>li>a{color:#eee}.am-topbar-inverse .am-topbar-nav>li>a:focus,.am-topbar-inverse .am-topbar-nav>li>a:hover{color:#fff;background-color:rgba(0,0,0,.05)}.am-topbar-inverse .am-topbar-nav>li>a:focus:after,.am-topbar-inverse .am-topbar-nav>li>a:hover:after{border-bottom-color:#0b6fa2}.am-topbar-inverse .am-topbar-nav>li>a:after{border-bottom-color:#0e90d2}.am-topbar-inverse .am-topbar-nav>li.am-active>a,.am-topbar-inverse .am-topbar-nav>li.am-active>a:focus,.am-topbar-inverse .am-topbar-nav>li.am-active>a:hover{color:#fff;background-color:rgba(0,0,0,.1)}.am-topbar-inverse .am-topbar-nav>li.am-active>a:after,.am-topbar-inverse .am-topbar-nav>li.am-active>a:focus:after,.am-topbar-inverse .am-topbar-nav>li.am-active>a:hover:after{border-bottom-color:#fff}.am-topbar-inverse .am-topbar-nav>li .disabled>a,.am-topbar-inverse .am-topbar-nav>li .disabled>a:focus,.am-topbar-inverse .am-topbar-nav>li .disabled>a:hover{color:#444;background-color:transparent}.am-topbar-fixed-bottom,.am-topbar-fixed-top{position:fixed;right:0;left:0;z-index:1000;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.am-topbar-fixed-top{top:0}.am-topbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.am-with-topbar-fixed-top{padding-top:51px}.am-with-topbar-fixed-bottom{padding-bottom:51px}@media only screen and (max-width:640px){.am-topbar-fixed-bottom .am-topbar-collapse{position:absolute;bottom:100%;margin-bottom:1px;background-color:#f8f8f8}.am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:after,.am-topbar-fixed-bottom .am-topbar-collapse .am-dropdown-content:before{display:none}.am-topbar-fixed-bottom.am-topbar-inverse .am-topbar-collapse{background-color:#0e90d2}}.am-breadcrumb{padding:.7em .5em;margin-bottom:2rem;list-style:none;background-color:transparent;border-radius:0;font-size:85%}.am-breadcrumb>li{display:inline-block}.am-breadcrumb>li [class*=am-icon-]:before{color:#999;margin-right:5px}.am-breadcrumb>li+li:before{content:"\00bb\00a0";padding:0 8px;color:#ccc}.am-breadcrumb>.am-active{color:#999}.am-breadcrumb-slash>li+li:before{content:"/\00a0"}.am-pagination{padding-left:0;margin:1.5rem 0;list-style:none;color:#999;text-align:left}.am-pagination:after,.am-pagination:before{content:" ";display:table}.am-pagination:after{clear:both}.am-pagination>li{display:inline-block}.am-pagination>li>a,.am-pagination>li>span{position:relative;display:block;padding:.5em 1em;text-decoration:none;line-height:1.2;background-color:#fff;border:1px solid #ddd;border-radius:0;margin-bottom:5px;margin-right:5px}.am-pagination>li:last-child>a,.am-pagination>li:last-child>span{margin-right:0}.am-pagination>li>a:focus,.am-pagination>li>a:hover,.am-pagination>li>span:focus,.am-pagination>li>span:hover{background-color:#eee}.am-pagination>.am-active>a,.am-pagination>.am-active>a:focus,.am-pagination>.am-active>a:hover,.am-pagination>.am-active>span,.am-pagination>.am-active>span:focus,.am-pagination>.am-active>span:hover{z-index:2;color:#fff;background-color:#0e90d2;border-color:#0e90d2;cursor:default}.am-pagination>.am-disabled>a,.am-pagination>.am-disabled>a:focus,.am-pagination>.am-disabled>a:hover,.am-pagination>.am-disabled>span,.am-pagination>.am-disabled>span:focus,.am-pagination>.am-disabled>span:hover{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed;pointer-events:none}.am-pagination .am-pagination-prev{float:left}.am-pagination .am-pagination-prev a{border-radius:0}.am-pagination .am-pagination-next{float:right}.am-pagination .am-pagination-next a{border-radius:0}.am-pagination-centered{text-align:center}.am-pagination-right{text-align:right}[class*=am-animation-]{-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out;-webkit-animation-fill-mode:both;animation-fill-mode:both}@media screen{.cssanimations [data-am-scrollspy*=animation]{opacity:0}}.am-animation-fade{-webkit-animation-name:am-fade;animation-name:am-fade;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-timing-function:linear;animation-timing-function:linear}.am-animation-scale-up{-webkit-animation-name:am-scale-up;animation-name:am-scale-up}.am-animation-scale-down{-webkit-animation-name:am-scale-down;animation-name:am-scale-down}.am-animation-slide-top{-webkit-animation-name:am-slide-top;animation-name:am-slide-top}.am-animation-slide-bottom{-webkit-animation-name:am-slide-bottom;animation-name:am-slide-bottom}.am-animation-slide-left{-webkit-animation-name:am-slide-left;animation-name:am-slide-left}.am-animation-slide-right{-webkit-animation-name:am-slide-right;animation-name:am-slide-right}.am-animation-slide-top-fixed{-webkit-animation-name:am-slide-top-fixed;animation-name:am-slide-top-fixed}.am-animation-shake{-webkit-animation-name:am-shake;animation-name:am-shake}.am-animation-spin{-webkit-animation:am-spin 2s infinite linear;animation:am-spin 2s infinite linear}.am-animation-left-spring{-webkit-animation:am-left-spring .3s ease-in-out;animation:am-left-spring .3s ease-in-out}.am-animation-right-spring{-webkit-animation:am-right-spring .3s ease-in-out;animation:am-right-spring .3s ease-in-out}.am-animation-reverse{-webkit-animation-direction:reverse;animation-direction:reverse}.am-animation-paused{-webkit-animation-play-state:paused!important;animation-play-state:paused!important}.am-animation-delay-1{-webkit-animation-delay:1s;animation-delay:1s}.am-animation-delay-2{-webkit-animation-delay:2s;animation-delay:2s}.am-animation-delay-3{-webkit-animation-delay:3s;animation-delay:3s}.am-animation-delay-4{-webkit-animation-delay:4s;animation-delay:4s}.am-animation-delay-5{-webkit-animation-delay:5s;animation-delay:5s}.am-animation-delay-6{-webkit-animation-delay:6s;animation-delay:6s}@-webkit-keyframes am-fade{0%{opacity:0}100%{opacity:1}}@keyframes am-fade{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes am-scale-up{0%{opacity:0;-webkit-transform:scale(.2);transform:scale(.2)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes am-scale-up{0%{opacity:0;-webkit-transform:scale(.2);transform:scale(.2)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes am-scale-down{0%{opacity:0;-webkit-transform:scale(1.8);transform:scale(1.8)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes am-scale-down{0%{opacity:0;-webkit-transform:scale(1.8);transform:scale(1.8)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes am-slide-top{0%{opacity:0;-webkit-transform:translateY(-100%);transform:translateY(-100%)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes am-slide-top{0%{opacity:0;-webkit-transform:translateY(-100%);transform:translateY(-100%)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes am-slide-bottom{0%{opacity:0;-webkit-transform:translateY(100%);transform:translateY(100%)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes am-slide-bottom{0%{opacity:0;-webkit-transform:translateY(100%);transform:translateY(100%)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes am-slide-left{0%{opacity:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes am-slide-left{0%{opacity:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes am-slide-right{0%{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes am-slide-right{0%{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%)}100%{opacity:1;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes am-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%{-webkit-transform:translateX(-9px);transform:translateX(-9px)}20%{-webkit-transform:translateX(8px);transform:translateX(8px)}30%{-webkit-transform:translateX(-7px);transform:translateX(-7px)}40%{-webkit-transform:translateX(6px);transform:translateX(6px)}50%{-webkit-transform:translateX(-5px);transform:translateX(-5px)}60%{-webkit-transform:translateX(4px);transform:translateX(4px)}70%{-webkit-transform:translateX(-3px);transform:translateX(-3px)}80%{-webkit-transform:translateX(2px);transform:translateX(2px)}90%{-webkit-transform:translateX(-1px);transform:translateX(-1px)}}@keyframes am-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%{-webkit-transform:translateX(-9px);transform:translateX(-9px)}20%{-webkit-transform:translateX(8px);transform:translateX(8px)}30%{-webkit-transform:translateX(-7px);transform:translateX(-7px)}40%{-webkit-transform:translateX(6px);transform:translateX(6px)}50%{-webkit-transform:translateX(-5px);transform:translateX(-5px)}60%{-webkit-transform:translateX(4px);transform:translateX(4px)}70%{-webkit-transform:translateX(-3px);transform:translateX(-3px)}80%{-webkit-transform:translateX(2px);transform:translateX(2px)}90%{-webkit-transform:translateX(-1px);transform:translateX(-1px)}}@-webkit-keyframes am-slide-top-fixed{0%{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes am-slide-top-fixed{0%{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes am-slide-bottom-fixed{0%{opacity:0;-webkit-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes am-slide-bottom-fixed{0%{opacity:0;-webkit-transform:translateY(10px);transform:translateY(10px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@-webkit-keyframes am-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes am-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-webkit-keyframes am-right-spring{0%{-webkit-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(-20%);transform:translateX(-20%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes am-right-spring{0%{-webkit-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(-20%);transform:translateX(-20%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes am-left-spring{0%{-webkit-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(20%);transform:translateX(20%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes am-left-spring{0%{-webkit-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(20%);transform:translateX(20%)}100%{-webkit-transform:translateX(0);transform:translateX(0)}}.am-article:after,.am-article:before{content:" ";display:table}.am-article:after{clear:both}.am-article>:last-child{margin-bottom:0}.am-article+.am-article{margin-top:2.4rem}.am-article-title{font-size:2.8rem;line-height:1.15;font-weight:400}.am-article-title a{color:inherit;text-decoration:none}.am-article-meta{font-size:1.2rem;line-height:1.5;color:#999}.am-article-lead{color:#666;font-size:1.4rem;line-height:1.5;border:1px solid #dedede;border-radius:2px;background:#f9f9f9;padding:10px}.am-article-divider{margin-bottom:2.4rem;border-color:#eee}*+.am-article-divider{margin-top:2.4rem}.am-article-bd blockquote{font-family:Georgia,"Times New Roman",Times,Kai,"Kaiti SC",KaiTi,BiauKai,FontAwesome,serif}.am-article-bd img{display:block;max-width:100%}.am-badge{display:inline-block;min-width:10px;padding:.25em .625em;font-size:1.2rem;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:0}.am-badge:empty{display:none}.am-badge.am-square{border-radius:0}.am-badge.am-radius{border-radius:2px}.am-badge.am-round{border-radius:1000px}a.am-badge:focus,a.am-badge:hover{color:#fff;text-decoration:none;cursor:pointer}.am-badge-primary{background-color:#0e90d2}.am-badge-secondary{background-color:#3bb4f2}.am-badge-success{background-color:#5eb95e}.am-badge-warning{background-color:#F37B1D}.am-badge-danger{background-color:#dd514c}.am-comment:after,.am-comment:before{content:" ";display:table}.am-comment:after{clear:both}.am-comment-avatar{float:left;width:32px;height:32px;border-radius:50%;border:1px solid transparent}@media only screen and (min-width:641px){.am-comment-avatar{width:48px;height:48px}}.am-comment-main{position:relative;margin-left:42px;border:1px solid #dedede;border-radius:0}.am-comment-main:after,.am-comment-main:before{position:absolute;top:10px;left:-8px;right:100%;width:0;height:0;display:block;content:" ";border-color:transparent;border-style:solid solid outset;border-width:8px 8px 8px 0;pointer-events:none}.am-comment-main:before{border-right-color:#dedede;z-index:1}.am-comment-main:after{border-right-color:#f8f8f8;margin-left:1px;z-index:2}@media only screen and (min-width:641px){.am-comment-main{margin-left:63px}}.am-comment-hd{background:#f8f8f8;border-bottom:1px solid #eee;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.am-comment-title{margin:0 0 8px 0;font-size:1.6rem;line-height:1.2}.am-comment-meta{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;padding:10px 15px;font-size:13px;color:#999;line-height:1.2;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.am-comment-meta a{color:#999}.am-comment-author{font-weight:700;color:#999}.am-comment-bd{padding:15px;overflow:hidden}.am-comment-bd>:last-child{margin-bottom:0}.am-comment-footer{padding:0 15px 5px}.am-comment-footer .am-comment-actions a+a{margin-left:5px}.am-comment-actions{font-size:13px;color:#999}.am-comment-actions a{display:inline-block;padding:10px 5px;line-height:1;color:#999;opacity:.7}.am-comment-actions a:hover{color:#0e90d2;opacity:1}.am-comment-hd .am-comment-actions{padding-right:.5rem}.am-comment-flip .am-comment-avatar{float:right}.am-comment-flip .am-comment-main{margin-left:auto;margin-right:42px}@media only screen and (min-width:641px){.am-comment-flip .am-comment-main{margin-right:63px}}.am-comment-flip .am-comment-main:after,.am-comment-flip .am-comment-main:before{left:auto;right:-8px;border-width:8px 0 8px 8px}.am-comment-flip .am-comment-main:before{border-left-color:#dedede}.am-comment-flip .am-comment-main:after{border-left-color:#f8f8f8;margin-right:1px;margin-left:auto}.am-comment-primary .am-comment-avatar{border-color:#0e90d2}.am-comment-primary .am-comment-main{border-color:#0e90d2}.am-comment-primary .am-comment-main:before{border-right-color:#0e90d2}.am-comment-primary.am-comment-flip .am-comment-main:before{border-left-color:#0e90d2;border-right-color:transparent}.am-comment-primary.am-comment-flip .am-comment-main:after{border-left-color:#f8f8f8}.am-comment-highlight .am-comment-avatar,.am-comment-secondary .am-comment-avatar{border-color:#3bb4f2}.am-comment-highlight .am-comment-main,.am-comment-secondary .am-comment-main{border-color:#3bb4f2}.am-comment-highlight .am-comment-main:before,.am-comment-secondary .am-comment-main:before{border-right-color:#3bb4f2}.am-comment-highlight.am-comment-flip .am-comment-main:before,.am-comment-secondary.am-comment-flip .am-comment-main:before{border-left-color:#3bb4f2;border-right-color:transparent}.am-comment-highlight.am-comment-flip .am-comment-main:after,.am-comment-secondary.am-comment-flip .am-comment-main:after{border-left-color:#f8f8f8}.am-comment-success .am-comment-avatar{border-color:#5eb95e}.am-comment-success .am-comment-main{border-color:#5eb95e}.am-comment-success .am-comment-main:before{border-right-color:#5eb95e}.am-comment-success.am-comment-flip .am-comment-main:before{border-left-color:#5eb95e;border-right-color:transparent}.am-comment-success.am-comment-flip .am-comment-main:after{border-left-color:#f8f8f8}.am-comment-warning .am-comment-avatar{border-color:#F37B1D}.am-comment-warning .am-comment-main{border-color:#F37B1D}.am-comment-warning .am-comment-main:before{border-right-color:#F37B1D}.am-comment-warning.am-comment-flip .am-comment-main:before{border-left-color:#F37B1D;border-right-color:transparent}.am-comment-warning.am-comment-flip .am-comment-main:after{border-left-color:#f8f8f8}.am-comment-danger .am-comment-avatar{border-color:#dd514c}.am-comment-danger .am-comment-main{border-color:#dd514c}.am-comment-danger .am-comment-main:before{border-right-color:#dd514c}.am-comment-danger.am-comment-flip .am-comment-main:before{border-left-color:#dd514c;border-right-color:transparent}.am-comment-danger.am-comment-flip .am-comment-main:after{border-left-color:#f8f8f8}.am-comments-list{padding:0;list-style:none}.am-comments-list .am-comment{margin:1.6rem 0 0 0;list-style:none}@media only screen and (min-width:641px){.am-comments-list-flip .am-comment-main{margin-right:64px}.am-comments-list-flip .am-comment-flip .am-comment-main{margin-left:64px}}.am-btn-group,.am-btn-group-stacked{position:relative;display:inline-block;vertical-align:middle}.am-btn-group-stacked>.am-btn,.am-btn-group>.am-btn{position:relative;float:left}.am-btn-group-stacked>.am-btn.active,.am-btn-group-stacked>.am-btn:active,.am-btn-group-stacked>.am-btn:focus,.am-btn-group-stacked>.am-btn:hover,.am-btn-group>.am-btn.active,.am-btn-group>.am-btn:active,.am-btn-group>.am-btn:focus,.am-btn-group>.am-btn:hover{z-index:2}.am-btn-group-stacked>.am-btn:focus,.am-btn-group>.am-btn:focus{outline:0}.am-btn-group .am-btn+.am-btn,.am-btn-group .am-btn+.am-btn-group,.am-btn-group .am-btn-group+.am-btn,.am-btn-group .am-btn-group+.am-btn-group{margin-left:-1px}.am-btn-toolbar{margin-left:-5px}.am-btn-toolbar:after,.am-btn-toolbar:before{content:" ";display:table}.am-btn-toolbar:after{clear:both}.am-btn-toolbar .am-btn-group,.am-btn-toolbar .am-input-group{float:left}.am-btn-toolbar>.am-btn,.am-btn-toolbar>.am-btn-group,.am-btn-toolbar>.am-input-group{margin-left:5px}.am-btn-group>.am-btn:not(:first-child):not(:last-child):not(.am-dropdown-toggle){border-radius:0}.am-btn-group>.am-btn:first-child{margin-left:0}.am-btn-group>.am-btn:first-child:not(:last-child):not(.am-dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.am-btn-group>.am-btn:last-child:not(:first-child),.am-btn-group>.am-dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.am-btn-group>.am-btn-group{float:left}.am-btn-group>.am-btn-group:not(:first-child):not(:last-child)>.am-btn{border-radius:0}.am-btn-group>.am-btn-group:first-child>.am-btn:last-child,.am-btn-group>.am-btn-group:first-child>.am-dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.am-btn-group>.am-btn-group:last-child>.am-btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.am-btn-group-xs>.am-btn{font-size:1.2rem}.am-btn-group-sm>.am-btn{font-size:1.4rem}.am-btn-group-lg>.am-btn{font-size:1.8rem}.am-btn-group-stacked>.am-btn,.am-btn-group-stacked>.am-btn-group,.am-btn-group-stacked>.am-btn-group>.am-btn{display:block;float:none;width:100%;max-width:100%}.am-btn-group-stacked>.am-btn-group:after,.am-btn-group-stacked>.am-btn-group:before{content:" ";display:table}.am-btn-group-stacked>.am-btn-group:after{clear:both}.am-btn-group-stacked>.am-btn-group>.am-btn{float:none}.am-btn-group-stacked>.am-btn+.am-btn,.am-btn-group-stacked>.am-btn+.am-btn-group,.am-btn-group-stacked>.am-btn-group+.am-btn,.am-btn-group-stacked>.am-btn-group+.am-btn-group{margin-top:-1px;margin-left:0}.am-btn-group-stacked>.am-btn:not(:first-child):not(:last-child){border-radius:0}.am-btn-group-stacked>.am-btn:first-child:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.am-btn-group-stacked>.am-btn:last-child:not(:first-child){border-bottom-left-radius:0;border-top-right-radius:0;border-top-left-radius:0}.am-btn-group-stacked>.am-btn-group:not(:first-child):not(:last-child)>.am-btn{border-radius:0}.am-btn-group-stacked>.am-btn-group:first-child:not(:last-child)>.am-btn:last-child,.am-btn-group-stacked>.am-btn-group:first-child:not(:last-child)>.am-dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.am-btn-group-stacked>.am-btn-group:last-child:not(:first-child)>.am-btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.am-btn-group-justify{display:table;table-layout:fixed;border-collapse:separate;width:100%}.am-btn-group-justify>.am-btn,.am-btn-group-justify>.am-btn-group{float:none;display:table-cell;width:1%}.am-btn-group-justify>.am-btn-group .am-btn{width:100%}.lte9 .am-btn-group-justify{display:table;table-layout:fixed;border-collapse:separate}.lte9 .am-btn-group-justify>.am-btn,.lte9 .am-btn-group-justify>.am-btn-group{float:none;display:table-cell;width:1%}.am-btn-group .am-dropdown{float:left;margin-left:-1px}.am-btn-group .am-dropdown>.am-btn{border-bottom-left-radius:0;border-top-left-radius:0}.am-btn-group .am-active .am-dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.am-btn-group .am-active .am-dropdown-toggle.am-btn-link{-webkit-box-shadow:none;box-shadow:none}.am-btn-group .am-active .am-dropdown-toggle,.am-btn-group .am-dropdown-toggle:active{outline:0}.am-btn-group-check>.am-btn>input[type=checkbox],.am-btn-group-check>.am-btn>input[type=radio],[data-am-button]>.am-btn>input[type=checkbox],[data-am-button]>.am-btn>input[type=radio]{position:absolute;z-index:-1;opacity:0}.am-close{display:inline-block;text-align:center;width:24px;font-size:20px;font-weight:700;line-height:24px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;-webkit-transition:all .3s;transition:all .3s}.am-close:focus,.am-close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;outline:0}.am-close[class*=am-icon-]{font-size:16px}button.am-close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}a.am-close:hover{color:inherit;text-decoration:none;cursor:pointer}.am-close-alt{border-radius:50%;background:#eee;opacity:.7;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.25);box-shadow:0 0 0 1px rgba(0,0,0,.25)}.am-close-alt:focus,.am-close-alt:hover{opacity:1}.am-close-spin:hover{-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}@font-face{font-family:FontAwesome;src:url(../fonts/fontawesome-webfont.eot?v=4.6.3);src:url(../fonts/fontawesome-webfont.eot?#iefix&v=4.6.3) format('embedded-opentype'),url(../fonts/fontawesome-webfont.woff2?v=4.6.3) format('woff2'),url(../fonts/fontawesome-webfont.woff?v=4.6.3) format('woff'),url(../fonts/fontawesome-webfont.ttf?v=4.6.3) format('truetype');font-weight:400;font-style:normal}[class*=am-icon-]{display:inline-block;font-style:normal}[class*=am-icon-]:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.am-icon-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}[class*=am-icon-].am-fl{margin-right:.3em}[class*=am-icon-].am-fr{margin-left:.3em}.am-icon-sm:before{font-size:150%;vertical-align:-10%}.am-icon-md:before{font-size:200%;vertical-align:-16%}.am-icon-lg:before{font-size:250%;vertical-align:-22%}.am-icon-btn{-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;width:48px;height:48px;font-size:24px;line-height:48px;border-radius:50%;background-color:#eee;color:#555;text-align:center}.am-icon-btn:focus,.am-icon-btn:hover{background-color:#f5f5f5;color:#333;text-decoration:none;outline:0}.am-icon-btn:active{background-color:#ddd;color:#333}.am-icon-btn.am-danger,.am-icon-btn.am-primary,.am-icon-btn.am-secondary,.am-icon-btn.am-success,.am-icon-btn.am-warning{color:#fff}.am-icon-btn.am-primary{background-color:#0e90d2}.am-icon-btn.am-secondary{background-color:#3bb4f2}.am-icon-btn.am-success{background-color:#5eb95e}.am-icon-btn.am-warning{background-color:#F37B1D}.am-icon-btn.am-danger{background-color:#dd514c}.am-icon-btn-sm{width:32px;height:32px;font-size:16px;line-height:32px}.am-icon-btn-lg{width:64px;height:64px;font-size:28px;line-height:64px}.am-icon-fw{width:1.25em;text-align:center}.am-icon-glass:before{content:"\f000"}.am-icon-music:before{content:"\f001"}.am-icon-search:before{content:"\f002"}.am-icon-envelope-o:before{content:"\f003"}.am-icon-heart:before{content:"\f004"}.am-icon-star:before{content:"\f005"}.am-icon-star-o:before{content:"\f006"}.am-icon-user:before{content:"\f007"}.am-icon-film:before{content:"\f008"}.am-icon-th-large:before{content:"\f009"}.am-icon-th:before{content:"\f00a"}.am-icon-th-list:before{content:"\f00b"}.am-icon-check:before{content:"\f00c"}.am-icon-close:before,.am-icon-remove:before,.am-icon-times:before{content:"\f00d"}.am-icon-search-plus:before{content:"\f00e"}.am-icon-search-minus:before{content:"\f010"}.am-icon-power-off:before{content:"\f011"}.am-icon-signal:before{content:"\f012"}.am-icon-cog:before,.am-icon-gear:before{content:"\f013"}.am-icon-trash-o:before{content:"\f014"}.am-icon-home:before{content:"\f015"}.am-icon-file-o:before{content:"\f016"}.am-icon-clock-o:before{content:"\f017"}.am-icon-road:before{content:"\f018"}.am-icon-download:before{content:"\f019"}.am-icon-arrow-circle-o-down:before{content:"\f01a"}.am-icon-arrow-circle-o-up:before{content:"\f01b"}.am-icon-inbox:before{content:"\f01c"}.am-icon-play-circle-o:before{content:"\f01d"}.am-icon-repeat:before,.am-icon-rotate-right:before{content:"\f01e"}.am-icon-refresh:before{content:"\f021"}.am-icon-list-alt:before{content:"\f022"}.am-icon-lock:before{content:"\f023"}.am-icon-flag:before{content:"\f024"}.am-icon-headphones:before{content:"\f025"}.am-icon-volume-off:before{content:"\f026"}.am-icon-volume-down:before{content:"\f027"}.am-icon-volume-up:before{content:"\f028"}.am-icon-qrcode:before{content:"\f029"}.am-icon-barcode:before{content:"\f02a"}.am-icon-tag:before{content:"\f02b"}.am-icon-tags:before{content:"\f02c"}.am-icon-book:before{content:"\f02d"}.am-icon-bookmark:before{content:"\f02e"}.am-icon-print:before{content:"\f02f"}.am-icon-camera:before{content:"\f030"}.am-icon-font:before{content:"\f031"}.am-icon-bold:before{content:"\f032"}.am-icon-italic:before{content:"\f033"}.am-icon-text-height:before{content:"\f034"}.am-icon-text-width:before{content:"\f035"}.am-icon-align-left:before{content:"\f036"}.am-icon-align-center:before{content:"\f037"}.am-icon-align-right:before{content:"\f038"}.am-icon-align-justify:before{content:"\f039"}.am-icon-list:before{content:"\f03a"}.am-icon-dedent:before,.am-icon-outdent:before{content:"\f03b"}.am-icon-indent:before{content:"\f03c"}.am-icon-video-camera:before{content:"\f03d"}.am-icon-image:before,.am-icon-photo:before,.am-icon-picture-o:before{content:"\f03e"}.am-icon-pencil:before{content:"\f040"}.am-icon-map-marker:before{content:"\f041"}.am-icon-adjust:before{content:"\f042"}.am-icon-tint:before{content:"\f043"}.am-icon-edit:before,.am-icon-pencil-square-o:before{content:"\f044"}.am-icon-share-square-o:before{content:"\f045"}.am-icon-check-square-o:before{content:"\f046"}.am-icon-arrows:before{content:"\f047"}.am-icon-step-backward:before{content:"\f048"}.am-icon-fast-backward:before{content:"\f049"}.am-icon-backward:before{content:"\f04a"}.am-icon-play:before{content:"\f04b"}.am-icon-pause:before{content:"\f04c"}.am-icon-stop:before{content:"\f04d"}.am-icon-forward:before{content:"\f04e"}.am-icon-fast-forward:before{content:"\f050"}.am-icon-step-forward:before{content:"\f051"}.am-icon-eject:before{content:"\f052"}.am-icon-chevron-left:before{content:"\f053"}.am-icon-chevron-right:before{content:"\f054"}.am-icon-plus-circle:before{content:"\f055"}.am-icon-minus-circle:before{content:"\f056"}.am-icon-times-circle:before{content:"\f057"}.am-icon-check-circle:before{content:"\f058"}.am-icon-question-circle:before{content:"\f059"}.am-icon-info-circle:before{content:"\f05a"}.am-icon-crosshairs:before{content:"\f05b"}.am-icon-times-circle-o:before{content:"\f05c"}.am-icon-check-circle-o:before{content:"\f05d"}.am-icon-ban:before{content:"\f05e"}.am-icon-arrow-left:before{content:"\f060"}.am-icon-arrow-right:before{content:"\f061"}.am-icon-arrow-up:before{content:"\f062"}.am-icon-arrow-down:before{content:"\f063"}.am-icon-mail-forward:before,.am-icon-share:before{content:"\f064"}.am-icon-expand:before{content:"\f065"}.am-icon-compress:before{content:"\f066"}.am-icon-plus:before{content:"\f067"}.am-icon-minus:before{content:"\f068"}.am-icon-asterisk:before{content:"\f069"}.am-icon-exclamation-circle:before{content:"\f06a"}.am-icon-gift:before{content:"\f06b"}.am-icon-leaf:before{content:"\f06c"}.am-icon-fire:before{content:"\f06d"}.am-icon-eye:before{content:"\f06e"}.am-icon-eye-slash:before{content:"\f070"}.am-icon-exclamation-triangle:before,.am-icon-warning:before{content:"\f071"}.am-icon-plane:before{content:"\f072"}.am-icon-calendar:before{content:"\f073"}.am-icon-random:before{content:"\f074"}.am-icon-comment:before{content:"\f075"}.am-icon-magnet:before{content:"\f076"}.am-icon-chevron-up:before{content:"\f077"}.am-icon-chevron-down:before{content:"\f078"}.am-icon-retweet:before{content:"\f079"}.am-icon-shopping-cart:before{content:"\f07a"}.am-icon-folder:before{content:"\f07b"}.am-icon-folder-open:before{content:"\f07c"}.am-icon-arrows-v:before{content:"\f07d"}.am-icon-arrows-h:before{content:"\f07e"}.am-icon-bar-chart-o:before,.am-icon-bar-chart:before{content:"\f080"}.am-icon-twitter-square:before{content:"\f081"}.am-icon-facebook-square:before{content:"\f082"}.am-icon-camera-retro:before{content:"\f083"}.am-icon-key:before{content:"\f084"}.am-icon-cogs:before,.am-icon-gears:before{content:"\f085"}.am-icon-comments:before{content:"\f086"}.am-icon-thumbs-o-up:before{content:"\f087"}.am-icon-thumbs-o-down:before{content:"\f088"}.am-icon-star-half:before{content:"\f089"}.am-icon-heart-o:before{content:"\f08a"}.am-icon-sign-out:before{content:"\f08b"}.am-icon-linkedin-square:before{content:"\f08c"}.am-icon-thumb-tack:before{content:"\f08d"}.am-icon-external-link:before{content:"\f08e"}.am-icon-sign-in:before{content:"\f090"}.am-icon-trophy:before{content:"\f091"}.am-icon-github-square:before{content:"\f092"}.am-icon-upload:before{content:"\f093"}.am-icon-lemon-o:before{content:"\f094"}.am-icon-phone:before{content:"\f095"}.am-icon-square-o:before{content:"\f096"}.am-icon-bookmark-o:before{content:"\f097"}.am-icon-phone-square:before{content:"\f098"}.am-icon-twitter:before{content:"\f099"}.am-icon-facebook-f:before,.am-icon-facebook:before{content:"\f09a"}.am-icon-github:before{content:"\f09b"}.am-icon-unlock:before{content:"\f09c"}.am-icon-credit-card:before{content:"\f09d"}.am-icon-feed:before,.am-icon-rss:before{content:"\f09e"}.am-icon-hdd-o:before{content:"\f0a0"}.am-icon-bullhorn:before{content:"\f0a1"}.am-icon-bell:before{content:"\f0f3"}.am-icon-certificate:before{content:"\f0a3"}.am-icon-hand-o-right:before{content:"\f0a4"}.am-icon-hand-o-left:before{content:"\f0a5"}.am-icon-hand-o-up:before{content:"\f0a6"}.am-icon-hand-o-down:before{content:"\f0a7"}.am-icon-arrow-circle-left:before{content:"\f0a8"}.am-icon-arrow-circle-right:before{content:"\f0a9"}.am-icon-arrow-circle-up:before{content:"\f0aa"}.am-icon-arrow-circle-down:before{content:"\f0ab"}.am-icon-globe:before{content:"\f0ac"}.am-icon-wrench:before{content:"\f0ad"}.am-icon-tasks:before{content:"\f0ae"}.am-icon-filter:before{content:"\f0b0"}.am-icon-briefcase:before{content:"\f0b1"}.am-icon-arrows-alt:before{content:"\f0b2"}.am-icon-group:before,.am-icon-users:before{content:"\f0c0"}.am-icon-chain:before,.am-icon-link:before{content:"\f0c1"}.am-icon-cloud:before{content:"\f0c2"}.am-icon-flask:before{content:"\f0c3"}.am-icon-cut:before,.am-icon-scissors:before{content:"\f0c4"}.am-icon-copy:before,.am-icon-files-o:before{content:"\f0c5"}.am-icon-paperclip:before{content:"\f0c6"}.am-icon-floppy-o:before,.am-icon-save:before{content:"\f0c7"}.am-icon-square:before{content:"\f0c8"}.am-icon-bars:before,.am-icon-navicon:before,.am-icon-reorder:before{content:"\f0c9"}.am-icon-list-ul:before{content:"\f0ca"}.am-icon-list-ol:before{content:"\f0cb"}.am-icon-strikethrough:before{content:"\f0cc"}.am-icon-underline:before{content:"\f0cd"}.am-icon-table:before{content:"\f0ce"}.am-icon-magic:before{content:"\f0d0"}.am-icon-truck:before{content:"\f0d1"}.am-icon-pinterest:before{content:"\f0d2"}.am-icon-pinterest-square:before{content:"\f0d3"}.am-icon-google-plus-square:before{content:"\f0d4"}.am-icon-google-plus:before{content:"\f0d5"}.am-icon-money:before{content:"\f0d6"}.am-icon-caret-down:before{content:"\f0d7"}.am-icon-caret-up:before{content:"\f0d8"}.am-icon-caret-left:before{content:"\f0d9"}.am-icon-caret-right:before{content:"\f0da"}.am-icon-columns:before{content:"\f0db"}.am-icon-sort:before,.am-icon-unsorted:before{content:"\f0dc"}.am-icon-sort-desc:before,.am-icon-sort-down:before{content:"\f0dd"}.am-icon-sort-asc:before,.am-icon-sort-up:before{content:"\f0de"}.am-icon-envelope:before{content:"\f0e0"}.am-icon-linkedin:before{content:"\f0e1"}.am-icon-rotate-left:before,.am-icon-undo:before{content:"\f0e2"}.am-icon-gavel:before,.am-icon-legal:before{content:"\f0e3"}.am-icon-dashboard:before,.am-icon-tachometer:before{content:"\f0e4"}.am-icon-comment-o:before{content:"\f0e5"}.am-icon-comments-o:before{content:"\f0e6"}.am-icon-bolt:before,.am-icon-flash:before{content:"\f0e7"}.am-icon-sitemap:before{content:"\f0e8"}.am-icon-umbrella:before{content:"\f0e9"}.am-icon-clipboard:before,.am-icon-paste:before{content:"\f0ea"}.am-icon-lightbulb-o:before{content:"\f0eb"}.am-icon-exchange:before{content:"\f0ec"}.am-icon-cloud-download:before{content:"\f0ed"}.am-icon-cloud-upload:before{content:"\f0ee"}.am-icon-user-md:before{content:"\f0f0"}.am-icon-stethoscope:before{content:"\f0f1"}.am-icon-suitcase:before{content:"\f0f2"}.am-icon-bell-o:before{content:"\f0a2"}.am-icon-coffee:before{content:"\f0f4"}.am-icon-cutlery:before{content:"\f0f5"}.am-icon-file-text-o:before{content:"\f0f6"}.am-icon-building-o:before{content:"\f0f7"}.am-icon-hospital-o:before{content:"\f0f8"}.am-icon-ambulance:before{content:"\f0f9"}.am-icon-medkit:before{content:"\f0fa"}.am-icon-fighter-jet:before{content:"\f0fb"}.am-icon-beer:before{content:"\f0fc"}.am-icon-h-square:before{content:"\f0fd"}.am-icon-plus-square:before{content:"\f0fe"}.am-icon-angle-double-left:before{content:"\f100"}.am-icon-angle-double-right:before{content:"\f101"}.am-icon-angle-double-up:before{content:"\f102"}.am-icon-angle-double-down:before{content:"\f103"}.am-icon-angle-left:before{content:"\f104"}.am-icon-angle-right:before{content:"\f105"}.am-icon-angle-up:before{content:"\f106"}.am-icon-angle-down:before{content:"\f107"}.am-icon-desktop:before{content:"\f108"}.am-icon-laptop:before{content:"\f109"}.am-icon-tablet:before{content:"\f10a"}.am-icon-mobile-phone:before,.am-icon-mobile:before{content:"\f10b"}.am-icon-circle-o:before{content:"\f10c"}.am-icon-quote-left:before{content:"\f10d"}.am-icon-quote-right:before{content:"\f10e"}.am-icon-spinner:before{content:"\f110"}.am-icon-circle:before{content:"\f111"}.am-icon-mail-reply:before,.am-icon-reply:before{content:"\f112"}.am-icon-github-alt:before{content:"\f113"}.am-icon-folder-o:before{content:"\f114"}.am-icon-folder-open-o:before{content:"\f115"}.am-icon-smile-o:before{content:"\f118"}.am-icon-frown-o:before{content:"\f119"}.am-icon-meh-o:before{content:"\f11a"}.am-icon-gamepad:before{content:"\f11b"}.am-icon-keyboard-o:before{content:"\f11c"}.am-icon-flag-o:before{content:"\f11d"}.am-icon-flag-checkered:before{content:"\f11e"}.am-icon-terminal:before{content:"\f120"}.am-icon-code:before{content:"\f121"}.am-icon-mail-reply-all:before,.am-icon-reply-all:before{content:"\f122"}.am-icon-star-half-empty:before,.am-icon-star-half-full:before,.am-icon-star-half-o:before{content:"\f123"}.am-icon-location-arrow:before{content:"\f124"}.am-icon-crop:before{content:"\f125"}.am-icon-code-fork:before{content:"\f126"}.am-icon-chain-broken:before,.am-icon-unlink:before{content:"\f127"}.am-icon-question:before{content:"\f128"}.am-icon-info:before{content:"\f129"}.am-icon-exclamation:before{content:"\f12a"}.am-icon-superscript:before{content:"\f12b"}.am-icon-subscript:before{content:"\f12c"}.am-icon-eraser:before{content:"\f12d"}.am-icon-puzzle-piece:before{content:"\f12e"}.am-icon-microphone:before{content:"\f130"}.am-icon-microphone-slash:before{content:"\f131"}.am-icon-shield:before{content:"\f132"}.am-icon-calendar-o:before{content:"\f133"}.am-icon-fire-extinguisher:before{content:"\f134"}.am-icon-rocket:before{content:"\f135"}.am-icon-maxcdn:before{content:"\f136"}.am-icon-chevron-circle-left:before{content:"\f137"}.am-icon-chevron-circle-right:before{content:"\f138"}.am-icon-chevron-circle-up:before{content:"\f139"}.am-icon-chevron-circle-down:before{content:"\f13a"}.am-icon-html5:before{content:"\f13b"}.am-icon-css3:before{content:"\f13c"}.am-icon-anchor:before{content:"\f13d"}.am-icon-unlock-alt:before{content:"\f13e"}.am-icon-bullseye:before{content:"\f140"}.am-icon-ellipsis-h:before{content:"\f141"}.am-icon-ellipsis-v:before{content:"\f142"}.am-icon-rss-square:before{content:"\f143"}.am-icon-play-circle:before{content:"\f144"}.am-icon-ticket:before{content:"\f145"}.am-icon-minus-square:before{content:"\f146"}.am-icon-minus-square-o:before{content:"\f147"}.am-icon-level-up:before{content:"\f148"}.am-icon-level-down:before{content:"\f149"}.am-icon-check-square:before{content:"\f14a"}.am-icon-pencil-square:before{content:"\f14b"}.am-icon-external-link-square:before{content:"\f14c"}.am-icon-share-square:before{content:"\f14d"}.am-icon-compass:before{content:"\f14e"}.am-icon-caret-square-o-down:before,.am-icon-toggle-down:before{content:"\f150"}.am-icon-caret-square-o-up:before,.am-icon-toggle-up:before{content:"\f151"}.am-icon-caret-square-o-right:before,.am-icon-toggle-right:before{content:"\f152"}.am-icon-eur:before,.am-icon-euro:before{content:"\f153"}.am-icon-gbp:before{content:"\f154"}.am-icon-dollar:before,.am-icon-usd:before{content:"\f155"}.am-icon-inr:before,.am-icon-rupee:before{content:"\f156"}.am-icon-cny:before,.am-icon-jpy:before,.am-icon-rmb:before,.am-icon-yen:before{content:"\f157"}.am-icon-rouble:before,.am-icon-rub:before,.am-icon-ruble:before{content:"\f158"}.am-icon-krw:before,.am-icon-won:before{content:"\f159"}.am-icon-bitcoin:before,.am-icon-btc:before{content:"\f15a"}.am-icon-file:before{content:"\f15b"}.am-icon-file-text:before{content:"\f15c"}.am-icon-sort-alpha-asc:before{content:"\f15d"}.am-icon-sort-alpha-desc:before{content:"\f15e"}.am-icon-sort-amount-asc:before{content:"\f160"}.am-icon-sort-amount-desc:before{content:"\f161"}.am-icon-sort-numeric-asc:before{content:"\f162"}.am-icon-sort-numeric-desc:before{content:"\f163"}.am-icon-thumbs-up:before{content:"\f164"}.am-icon-thumbs-down:before{content:"\f165"}.am-icon-youtube-square:before{content:"\f166"}.am-icon-youtube:before{content:"\f167"}.am-icon-xing:before{content:"\f168"}.am-icon-xing-square:before{content:"\f169"}.am-icon-youtube-play:before{content:"\f16a"}.am-icon-dropbox:before{content:"\f16b"}.am-icon-stack-overflow:before{content:"\f16c"}.am-icon-instagram:before{content:"\f16d"}.am-icon-flickr:before{content:"\f16e"}.am-icon-adn:before{content:"\f170"}.am-icon-bitbucket:before{content:"\f171"}.am-icon-bitbucket-square:before{content:"\f172"}.am-icon-tumblr:before{content:"\f173"}.am-icon-tumblr-square:before{content:"\f174"}.am-icon-long-arrow-down:before{content:"\f175"}.am-icon-long-arrow-up:before{content:"\f176"}.am-icon-long-arrow-left:before{content:"\f177"}.am-icon-long-arrow-right:before{content:"\f178"}.am-icon-apple:before{content:"\f179"}.am-icon-windows:before{content:"\f17a"}.am-icon-android:before{content:"\f17b"}.am-icon-linux:before{content:"\f17c"}.am-icon-dribbble:before{content:"\f17d"}.am-icon-skype:before{content:"\f17e"}.am-icon-foursquare:before{content:"\f180"}.am-icon-trello:before{content:"\f181"}.am-icon-female:before{content:"\f182"}.am-icon-male:before{content:"\f183"}.am-icon-gittip:before,.am-icon-gratipay:before{content:"\f184"}.am-icon-sun-o:before{content:"\f185"}.am-icon-moon-o:before{content:"\f186"}.am-icon-archive:before{content:"\f187"}.am-icon-bug:before{content:"\f188"}.am-icon-vk:before{content:"\f189"}.am-icon-weibo:before{content:"\f18a"}.am-icon-renren:before{content:"\f18b"}.am-icon-pagelines:before{content:"\f18c"}.am-icon-stack-exchange:before{content:"\f18d"}.am-icon-arrow-circle-o-right:before{content:"\f18e"}.am-icon-arrow-circle-o-left:before{content:"\f190"}.am-icon-caret-square-o-left:before,.am-icon-toggle-left:before{content:"\f191"}.am-icon-dot-circle-o:before{content:"\f192"}.am-icon-wheelchair:before{content:"\f193"}.am-icon-vimeo-square:before{content:"\f194"}.am-icon-try:before,.am-icon-turkish-lira:before{content:"\f195"}.am-icon-plus-square-o:before{content:"\f196"}.am-icon-space-shuttle:before{content:"\f197"}.am-icon-slack:before{content:"\f198"}.am-icon-envelope-square:before{content:"\f199"}.am-icon-wordpress:before{content:"\f19a"}.am-icon-openid:before{content:"\f19b"}.am-icon-bank:before,.am-icon-institution:before,.am-icon-university:before{content:"\f19c"}.am-icon-graduation-cap:before,.am-icon-mortar-board:before{content:"\f19d"}.am-icon-yahoo:before{content:"\f19e"}.am-icon-google:before{content:"\f1a0"}.am-icon-reddit:before{content:"\f1a1"}.am-icon-reddit-square:before{content:"\f1a2"}.am-icon-stumbleupon-circle:before{content:"\f1a3"}.am-icon-stumbleupon:before{content:"\f1a4"}.am-icon-delicious:before{content:"\f1a5"}.am-icon-digg:before{content:"\f1a6"}.am-icon-pied-piper-pp:before{content:"\f1a7"}.am-icon-pied-piper-alt:before{content:"\f1a8"}.am-icon-drupal:before{content:"\f1a9"}.am-icon-joomla:before{content:"\f1aa"}.am-icon-language:before{content:"\f1ab"}.am-icon-fax:before{content:"\f1ac"}.am-icon-building:before{content:"\f1ad"}.am-icon-child:before{content:"\f1ae"}.am-icon-paw:before{content:"\f1b0"}.am-icon-spoon:before{content:"\f1b1"}.am-icon-cube:before{content:"\f1b2"}.am-icon-cubes:before{content:"\f1b3"}.am-icon-behance:before{content:"\f1b4"}.am-icon-behance-square:before{content:"\f1b5"}.am-icon-steam:before{content:"\f1b6"}.am-icon-steam-square:before{content:"\f1b7"}.am-icon-recycle:before{content:"\f1b8"}.am-icon-automobile:before,.am-icon-car:before{content:"\f1b9"}.am-icon-cab:before,.am-icon-taxi:before{content:"\f1ba"}.am-icon-tree:before{content:"\f1bb"}.am-icon-spotify:before{content:"\f1bc"}.am-icon-deviantart:before{content:"\f1bd"}.am-icon-soundcloud:before{content:"\f1be"}.am-icon-database:before{content:"\f1c0"}.am-icon-file-pdf-o:before{content:"\f1c1"}.am-icon-file-word-o:before{content:"\f1c2"}.am-icon-file-excel-o:before{content:"\f1c3"}.am-icon-file-powerpoint-o:before{content:"\f1c4"}.am-icon-file-image-o:before,.am-icon-file-photo-o:before,.am-icon-file-picture-o:before{content:"\f1c5"}.am-icon-file-archive-o:before,.am-icon-file-zip-o:before{content:"\f1c6"}.am-icon-file-audio-o:before,.am-icon-file-sound-o:before{content:"\f1c7"}.am-icon-file-movie-o:before,.am-icon-file-video-o:before{content:"\f1c8"}.am-icon-file-code-o:before{content:"\f1c9"}.am-icon-vine:before{content:"\f1ca"}.am-icon-codepen:before{content:"\f1cb"}.am-icon-jsfiddle:before{content:"\f1cc"}.am-icon-life-bouy:before,.am-icon-life-buoy:before,.am-icon-life-ring:before,.am-icon-life-saver:before,.am-icon-support:before{content:"\f1cd"}.am-icon-circle-o-notch:before{content:"\f1ce"}.am-icon-ra:before,.am-icon-rebel:before,.am-icon-resistance:before{content:"\f1d0"}.am-icon-empire:before,.am-icon-ge:before{content:"\f1d1"}.am-icon-git-square:before{content:"\f1d2"}.am-icon-git:before{content:"\f1d3"}.am-icon-hacker-news:before,.am-icon-y-combinator-square:before,.am-icon-yc-square:before{content:"\f1d4"}.am-icon-tencent-weibo:before{content:"\f1d5"}.am-icon-qq:before{content:"\f1d6"}.am-icon-wechat:before,.am-icon-weixin:before{content:"\f1d7"}.am-icon-paper-plane:before,.am-icon-send:before{content:"\f1d8"}.am-icon-paper-plane-o:before,.am-icon-send-o:before{content:"\f1d9"}.am-icon-history:before{content:"\f1da"}.am-icon-circle-thin:before{content:"\f1db"}.am-icon-header:before{content:"\f1dc"}.am-icon-paragraph:before{content:"\f1dd"}.am-icon-sliders:before{content:"\f1de"}.am-icon-share-alt:before{content:"\f1e0"}.am-icon-share-alt-square:before{content:"\f1e1"}.am-icon-bomb:before{content:"\f1e2"}.am-icon-futbol-o:before,.am-icon-soccer-ball-o:before{content:"\f1e3"}.am-icon-tty:before{content:"\f1e4"}.am-icon-binoculars:before{content:"\f1e5"}.am-icon-plug:before{content:"\f1e6"}.am-icon-slideshare:before{content:"\f1e7"}.am-icon-twitch:before{content:"\f1e8"}.am-icon-yelp:before{content:"\f1e9"}.am-icon-newspaper-o:before{content:"\f1ea"}.am-icon-wifi:before{content:"\f1eb"}.am-icon-calculator:before{content:"\f1ec"}.am-icon-paypal:before{content:"\f1ed"}.am-icon-google-wallet:before{content:"\f1ee"}.am-icon-cc-visa:before{content:"\f1f0"}.am-icon-cc-mastercard:before{content:"\f1f1"}.am-icon-cc-discover:before{content:"\f1f2"}.am-icon-cc-amex:before{content:"\f1f3"}.am-icon-cc-paypal:before{content:"\f1f4"}.am-icon-cc-stripe:before{content:"\f1f5"}.am-icon-bell-slash:before{content:"\f1f6"}.am-icon-bell-slash-o:before{content:"\f1f7"}.am-icon-trash:before{content:"\f1f8"}.am-icon-copyright:before{content:"\f1f9"}.am-icon-at:before{content:"\f1fa"}.am-icon-eyedropper:before{content:"\f1fb"}.am-icon-paint-brush:before{content:"\f1fc"}.am-icon-birthday-cake:before{content:"\f1fd"}.am-icon-area-chart:before{content:"\f1fe"}.am-icon-pie-chart:before{content:"\f200"}.am-icon-line-chart:before{content:"\f201"}.am-icon-lastfm:before{content:"\f202"}.am-icon-lastfm-square:before{content:"\f203"}.am-icon-toggle-off:before{content:"\f204"}.am-icon-toggle-on:before{content:"\f205"}.am-icon-bicycle:before{content:"\f206"}.am-icon-bus:before{content:"\f207"}.am-icon-ioxhost:before{content:"\f208"}.am-icon-angellist:before{content:"\f209"}.am-icon-cc:before{content:"\f20a"}.am-icon-ils:before,.am-icon-shekel:before,.am-icon-sheqel:before{content:"\f20b"}.am-icon-meanpath:before{content:"\f20c"}.am-icon-buysellads:before{content:"\f20d"}.am-icon-connectdevelop:before{content:"\f20e"}.am-icon-dashcube:before{content:"\f210"}.am-icon-forumbee:before{content:"\f211"}.am-icon-leanpub:before{content:"\f212"}.am-icon-sellsy:before{content:"\f213"}.am-icon-shirtsinbulk:before{content:"\f214"}.am-icon-simplybuilt:before{content:"\f215"}.am-icon-skyatlas:before{content:"\f216"}.am-icon-cart-plus:before{content:"\f217"}.am-icon-cart-arrow-down:before{content:"\f218"}.am-icon-diamond:before{content:"\f219"}.am-icon-ship:before{content:"\f21a"}.am-icon-user-secret:before{content:"\f21b"}.am-icon-motorcycle:before{content:"\f21c"}.am-icon-street-view:before{content:"\f21d"}.am-icon-heartbeat:before{content:"\f21e"}.am-icon-venus:before{content:"\f221"}.am-icon-mars:before{content:"\f222"}.am-icon-mercury:before{content:"\f223"}.am-icon-intersex:before,.am-icon-transgender:before{content:"\f224"}.am-icon-transgender-alt:before{content:"\f225"}.am-icon-venus-double:before{content:"\f226"}.am-icon-mars-double:before{content:"\f227"}.am-icon-venus-mars:before{content:"\f228"}.am-icon-mars-stroke:before{content:"\f229"}.am-icon-mars-stroke-v:before{content:"\f22a"}.am-icon-mars-stroke-h:before{content:"\f22b"}.am-icon-neuter:before{content:"\f22c"}.am-icon-genderless:before{content:"\f22d"}.am-icon-facebook-official:before{content:"\f230"}.am-icon-pinterest-p:before{content:"\f231"}.am-icon-whatsapp:before{content:"\f232"}.am-icon-server:before{content:"\f233"}.am-icon-user-plus:before{content:"\f234"}.am-icon-user-times:before{content:"\f235"}.am-icon-bed:before,.am-icon-hotel:before{content:"\f236"}.am-icon-viacoin:before{content:"\f237"}.am-icon-train:before{content:"\f238"}.am-icon-subway:before{content:"\f239"}.am-icon-medium:before{content:"\f23a"}.am-icon-y-combinator:before,.am-icon-yc:before{content:"\f23b"}.am-icon-optin-monster:before{content:"\f23c"}.am-icon-opencart:before{content:"\f23d"}.am-icon-expeditedssl:before{content:"\f23e"}.am-icon-battery-4:before,.am-icon-battery-full:before{content:"\f240"}.am-icon-battery-3:before,.am-icon-battery-three-quarters:before{content:"\f241"}.am-icon-battery-2:before,.am-icon-battery-half:before{content:"\f242"}.am-icon-battery-1:before,.am-icon-battery-quarter:before{content:"\f243"}.am-icon-battery-0:before,.am-icon-battery-empty:before{content:"\f244"}.am-icon-mouse-pointer:before{content:"\f245"}.am-icon-i-cursor:before{content:"\f246"}.am-icon-object-group:before{content:"\f247"}.am-icon-object-ungroup:before{content:"\f248"}.am-icon-sticky-note:before{content:"\f249"}.am-icon-sticky-note-o:before{content:"\f24a"}.am-icon-cc-jcb:before{content:"\f24b"}.am-icon-cc-diners-club:before{content:"\f24c"}.am-icon-clone:before{content:"\f24d"}.am-icon-balance-scale:before{content:"\f24e"}.am-icon-hourglass-o:before{content:"\f250"}.am-icon-hourglass-1:before,.am-icon-hourglass-start:before{content:"\f251"}.am-icon-hourglass-2:before,.am-icon-hourglass-half:before{content:"\f252"}.am-icon-hourglass-3:before,.am-icon-hourglass-end:before{content:"\f253"}.am-icon-hourglass:before{content:"\f254"}.am-icon-hand-grab-o:before,.am-icon-hand-rock-o:before{content:"\f255"}.am-icon-hand-paper-o:before,.am-icon-hand-stop-o:before{content:"\f256"}.am-icon-hand-scissors-o:before{content:"\f257"}.am-icon-hand-lizard-o:before{content:"\f258"}.am-icon-hand-spock-o:before{content:"\f259"}.am-icon-hand-pointer-o:before{content:"\f25a"}.am-icon-hand-peace-o:before{content:"\f25b"}.am-icon-trademark:before{content:"\f25c"}.am-icon-registered:before{content:"\f25d"}.am-icon-creative-commons:before{content:"\f25e"}.am-icon-gg:before{content:"\f260"}.am-icon-gg-circle:before{content:"\f261"}.am-icon-tripadvisor:before{content:"\f262"}.am-icon-odnoklassniki:before{content:"\f263"}.am-icon-odnoklassniki-square:before{content:"\f264"}.am-icon-get-pocket:before{content:"\f265"}.am-icon-wikipedia-w:before{content:"\f266"}.am-icon-safari:before{content:"\f267"}.am-icon-chrome:before{content:"\f268"}.am-icon-firefox:before{content:"\f269"}.am-icon-opera:before{content:"\f26a"}.am-icon-internet-explorer:before{content:"\f26b"}.am-icon-television:before,.am-icon-tv:before{content:"\f26c"}.am-icon-contao:before{content:"\f26d"}.am-icon-500px:before{content:"\f26e"}.am-icon-amazon:before{content:"\f270"}.am-icon-calendar-plus-o:before{content:"\f271"}.am-icon-calendar-minus-o:before{content:"\f272"}.am-icon-calendar-times-o:before{content:"\f273"}.am-icon-calendar-check-o:before{content:"\f274"}.am-icon-industry:before{content:"\f275"}.am-icon-map-pin:before{content:"\f276"}.am-icon-map-signs:before{content:"\f277"}.am-icon-map-o:before{content:"\f278"}.am-icon-map:before{content:"\f279"}.am-icon-commenting:before{content:"\f27a"}.am-icon-commenting-o:before{content:"\f27b"}.am-icon-houzz:before{content:"\f27c"}.am-icon-vimeo:before{content:"\f27d"}.am-icon-black-tie:before{content:"\f27e"}.am-icon-fonticons:before{content:"\f280"}.am-icon-reddit-alien:before{content:"\f281"}.am-icon-edge:before{content:"\f282"}.am-icon-credit-card-alt:before{content:"\f283"}.am-icon-codiepie:before{content:"\f284"}.am-icon-modx:before{content:"\f285"}.am-icon-fort-awesome:before{content:"\f286"}.am-icon-usb:before{content:"\f287"}.am-icon-product-hunt:before{content:"\f288"}.am-icon-mixcloud:before{content:"\f289"}.am-icon-scribd:before{content:"\f28a"}.am-icon-pause-circle:before{content:"\f28b"}.am-icon-pause-circle-o:before{content:"\f28c"}.am-icon-stop-circle:before{content:"\f28d"}.am-icon-stop-circle-o:before{content:"\f28e"}.am-icon-shopping-bag:before{content:"\f290"}.am-icon-shopping-basket:before{content:"\f291"}.am-icon-hashtag:before{content:"\f292"}.am-icon-bluetooth:before{content:"\f293"}.am-icon-bluetooth-b:before{content:"\f294"}.am-icon-percent:before{content:"\f295"}.am-icon-gitlab:before{content:"\f296"}.am-icon-wpbeginner:before{content:"\f297"}.am-icon-wpforms:before{content:"\f298"}.am-icon-envira:before{content:"\f299"}.am-icon-universal-access:before{content:"\f29a"}.am-icon-wheelchair-alt:before{content:"\f29b"}.am-icon-question-circle-o:before{content:"\f29c"}.am-icon-blind:before{content:"\f29d"}.am-icon-audio-description:before{content:"\f29e"}.am-icon-volume-control-phone:before{content:"\f2a0"}.am-icon-braille:before{content:"\f2a1"}.am-icon-assistive-listening-systems:before{content:"\f2a2"}.am-icon-american-sign-language-interpreting:before,.am-icon-asl-interpreting:before{content:"\f2a3"}.am-icon-deaf:before,.am-icon-deafness:before,.am-icon-hard-of-hearing:before{content:"\f2a4"}.am-icon-glide:before{content:"\f2a5"}.am-icon-glide-g:before{content:"\f2a6"}.am-icon-sign-language:before,.am-icon-signing:before{content:"\f2a7"}.am-icon-low-vision:before{content:"\f2a8"}.am-icon-viadeo:before{content:"\f2a9"}.am-icon-viadeo-square:before{content:"\f2aa"}.am-icon-snapchat:before{content:"\f2ab"}.am-icon-snapchat-ghost:before{content:"\f2ac"}.am-icon-snapchat-square:before{content:"\f2ad"}.am-icon-pied-piper:before{content:"\f2ae"}.am-icon-first-order:before{content:"\f2b0"}.am-icon-yoast:before{content:"\f2b1"}.am-icon-themeisle:before{content:"\f2b2"}.am-icon-google-plus-circle:before,.am-icon-google-plus-official:before{content:"\f2b3"}.am-icon-fa:before,.am-icon-font-awesome:before{content:"\f2b4"}@-webkit-keyframes icon-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes icon-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.am-icon-spin{-webkit-animation:icon-spin 2s infinite linear;animation:icon-spin 2s infinite linear}.am-icon-pulse{-webkit-animation:icon-spin 1s infinite steps(8);animation:icon-spin 1s infinite steps(8)}.am-icon-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.am-icon-ul>li{position:relative}.am-icon-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.am-input-group{position:relative;display:table;border-collapse:separate}.am-input-group .am-form-field{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.am-input-group .am-form-field,.am-input-group-btn,.am-input-group-label{display:table-cell}.am-input-group .am-form-field:not(:first-child):not(:last-child),.am-input-group-btn:not(:first-child):not(:last-child),.am-input-group-label:not(:first-child):not(:last-child){border-radius:0}.am-input-group-btn,.am-input-group-label{width:1%;white-space:nowrap;vertical-align:middle}.am-input-group-label{height:38px;padding:0 1em;font-size:1.6rem;font-weight:400;line-height:36px;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:0}.am-input-group-label input[type=checkbox],.am-input-group-label input[type=radio]{margin-top:0}.am-input-group .am-form-field:first-child,.am-input-group-btn:first-child>.am-btn,.am-input-group-btn:first-child>.am-btn-group>.am-btn,.am-input-group-btn:first-child>.am-dropdown-toggle,.am-input-group-btn:last-child>.am-btn-group:not(:last-child)>.am-btn,.am-input-group-btn:last-child>.am-btn:not(:last-child):not(.dropdown-toggle),.am-input-group-label:first-child{border-bottom-right-radius:0;border-top-right-radius:0}.am-input-group-label:first-child{border-right:0}.am-input-group .am-form-field:last-child,.am-input-group-btn:first-child>.am-btn-group:not(:first-child)>.am-btn,.am-input-group-btn:first-child>.am-btn:not(:first-child),.am-input-group-btn:last-child>.am-btn,.am-input-group-btn:last-child>.am-btn-group>.am-btn,.am-input-group-btn:last-child>.am-dropdown-toggle,.am-input-group-label:last-child{border-bottom-left-radius:0;border-top-left-radius:0}.am-input-group-label:last-child{border-left:0}.am-input-group-btn{position:relative;font-size:0;white-space:nowrap}.am-input-group-btn>.am-btn{position:relative;border-color:#ccc}.am-input-group-btn>.am-btn+.am-btn{margin-left:-1px}.am-input-group-btn>.am-btn:active,.am-input-group-btn>.am-btn:focus,.am-input-group-btn>.am-btn:hover{z-index:2}.am-input-group-btn:first-child>.am-btn,.am-input-group-btn:first-child>.am-btn-group{margin-right:-2px}.am-input-group-btn:last-child>.am-btn,.am-input-group-btn:last-child>.am-btn-group{margin-left:-1px}.am-input-group .am-form-field,.am-input-group-btn>.am-btn{height:38px;padding-bottom:auto}.am-input-group-lg>.am-form-field,.am-input-group-lg>.am-input-group-btn>.am-btn,.am-input-group-lg>.am-input-group-label{height:42px;font-size:1.8rem!important}.am-input-group-lg>.am-input-group-label{line-height:40px}.am-input-group-sm>.am-form-field,.am-input-group-sm>.am-input-group-btn>.am-btn,.am-input-group-sm>.am-input-group-label{height:33px;font-size:1.4rem!important}.am-input-group-sm>.am-input-group-label{line-height:31px}.am-input-group-primary .am-input-group-label{background:#0e90d2;color:#fff}.am-input-group-primary .am-input-group-btn>.am-btn,.am-input-group-primary .am-input-group-label,.am-input-group-primary.am-input-group .am-form-field{border-color:#0e90d2}.am-input-group-secondary .am-input-group-label{background:#3bb4f2;color:#fff}.am-input-group-secondary .am-input-group-btn>.am-btn,.am-input-group-secondary .am-input-group-label,.am-input-group-secondary.am-input-group .am-form-field{border-color:#3bb4f2}.am-input-group-success .am-input-group-label{background:#5eb95e;color:#fff}.am-input-group-success .am-input-group-btn>.am-btn,.am-input-group-success .am-input-group-label,.am-input-group-success.am-input-group .am-form-field{border-color:#5eb95e}.am-input-group-warning .am-input-group-label{background:#F37B1D;color:#fff}.am-input-group-warning .am-input-group-btn>.am-btn,.am-input-group-warning .am-input-group-label,.am-input-group-warning.am-input-group .am-form-field{border-color:#F37B1D}.am-input-group-danger .am-input-group-label{background:#dd514c;color:#fff}.am-input-group-danger .am-input-group-btn>.am-btn,.am-input-group-danger .am-input-group-label,.am-input-group-danger.am-input-group .am-form-field{border-color:#dd514c}.am-list{margin-bottom:1.6rem;padding-left:0}.am-list>li{position:relative;display:block;margin-bottom:-1px;background-color:#fff;border:1px solid #dedede;border-width:1px 0}.am-list>li>a{display:block;padding:1rem 0}.am-list>li>a.am-active,.am-list>li>a.am-active:focus,.am-list>li>a.am-active:hover{z-index:2;color:#fff;background-color:#0e90d2;border-color:#0e90d2}.am-list>li>a.am-active .am-list-item-heading,.am-list>li>a.am-active:focus .am-list-item-heading,.am-list>li>a.am-active:hover .am-list-item-heading{color:inherit}.am-list>li>a.am-active .am-list-item-text,.am-list>li>a.am-active:focus .am-list-item-text,.am-list>li>a.am-active:hover .am-list-item-text{color:#b2e2fa}.am-list>li>.am-badge{float:right}.am-list>li>.am-badge+.am-badge{margin-right:5px}.am-list-static>li{padding:.8rem .2rem}.am-list-static.am-list-border>li{padding:1rem}.am-list-border>li,.am-list-bordered>li{border-width:1px}.am-list-border>li:first-child,.am-list-border>li:first-child>a,.am-list-bordered>li:first-child,.am-list-bordered>li:first-child>a{border-top-right-radius:0;border-top-left-radius:0}.am-list-border>li:last-child,.am-list-border>li:last-child>a,.am-list-bordered>li:last-child,.am-list-bordered>li:last-child>a{margin-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.am-list-border>li>a,.am-list-bordered>li>a{padding:1rem}.am-list-border>li>a:focus,.am-list-border>li>a:hover,.am-list-bordered>li>a:focus,.am-list-bordered>li>a:hover{background-color:#f5f5f5}.am-list-striped>li:nth-of-type(even){background:#f5f5f5}.am-list-item-hd{margin-top:0}.am-list-item-text{line-height:1.4;font-size:1.3rem;color:#999;margin:0}.am-panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.am-panel-hd{padding:.6rem 1.25rem;border-bottom:1px solid transparent;border-top-right-radius:0;border-top-left-radius:0}.am-panel-bd{padding:1.25rem}.am-panel-title{margin:0;font-size:100%;color:inherit}.am-panel-title>a{color:inherit}.am-panel-footer{padding:.6rem 1.25rem;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:0;border-bottom-left-radius:0}.am-panel-default{border-color:#ddd}.am-panel-default>.am-panel-hd{color:#444;background-color:#f5f5f5;border-color:#ddd}.am-panel-default>.am-panel-hd+.am-panel-collapse>.am-panel-bd{border-top-color:#ddd}.am-panel-default>.am-panel-footer+.am-panel-collapse>.am-panel-bd{border-bottom-color:#ddd}.am-panel-primary{border-color:#10a0ea}.am-panel-primary>.am-panel-hd{color:#fff;background-color:#0e90d2;border-color:#10a0ea}.am-panel-primary>.am-panel-hd+.am-panel-collapse>.am-panel-bd{border-top-color:#10a0ea}.am-panel-primary>.am-panel-footer+.am-panel-collapse>.am-panel-bd{border-bottom-color:#10a0ea}.am-panel-secondary{border-color:#caebfb}.am-panel-secondary>.am-panel-hd{color:#14a6ef;background-color:rgba(59,180,242,.15);border-color:#caebfb}.am-panel-secondary>.am-panel-hd+.am-panel-collapse>.am-panel-bd{border-top-color:#caebfb}.am-panel-secondary>.am-panel-footer+.am-panel-collapse>.am-panel-bd{border-bottom-color:#caebfb}.am-panel-success{border-color:#c9e7c9}.am-panel-success>.am-panel-hd{color:#5eb95e;background-color:rgba(94,185,94,.15);border-color:#c9e7c9}.am-panel-success>.am-panel-hd+.am-panel-collapse>.am-panel-bd{border-top-color:#c9e7c9}.am-panel-success>.am-panel-footer+.am-panel-collapse>.am-panel-bd{border-bottom-color:#c9e7c9}.am-panel-warning{border-color:#fbd0ae}.am-panel-warning>.am-panel-hd{color:#F37B1D;background-color:rgba(243,123,29,.15);border-color:#fbd0ae}.am-panel-warning>.am-panel-hd+.am-panel-collapse>.am-panel-bd{border-top-color:#fbd0ae}.am-panel-warning>.am-panel-footer+.am-panel-collapse>.am-panel-bd{border-bottom-color:#fbd0ae}.am-panel-danger{border-color:#f5cecd}.am-panel-danger>.am-panel-hd{color:#dd514c;background-color:rgba(221,81,76,.15);border-color:#f5cecd}.am-panel-danger>.am-panel-hd+.am-panel-collapse>.am-panel-bd{border-top-color:#f5cecd}.am-panel-danger>.am-panel-footer+.am-panel-collapse>.am-panel-bd{border-bottom-color:#f5cecd}.am-panel>.am-table{margin-bottom:0}.am-panel>.am-table:first-child{border-top-right-radius:0;border-top-left-radius:0}.am-panel>.am-table:first-child>tbody:first-child>tr:first-child td:first-child,.am-panel>.am-table:first-child>tbody:first-child>tr:first-child th:first-child,.am-panel>.am-table:first-child>thead:first-child>tr:first-child td:first-child,.am-panel>.am-table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:0}.am-panel>.am-table:first-child>tbody:first-child>tr:first-child td:last-child,.am-panel>.am-table:first-child>tbody:first-child>tr:first-child th:last-child,.am-panel>.am-table:first-child>thead:first-child>tr:first-child td:last-child,.am-panel>.am-table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:0}.am-panel>.am-table:last-child{border-bottom-right-radius:0;border-bottom-left-radius:0}.am-panel>.am-table:last-child>tbody:last-child>tr:last-child td:first-child,.am-panel>.am-table:last-child>tbody:last-child>tr:last-child th:first-child,.am-panel>.am-table:last-child>tfoot:last-child>tr:last-child td:first-child,.am-panel>.am-table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:0}.am-panel>.am-table:last-child>tbody:last-child>tr:last-child td:last-child,.am-panel>.am-table:last-child>tbody:last-child>tr:last-child th:last-child,.am-panel>.am-table:last-child>tfoot:last-child>tr:last-child td:last-child,.am-panel>.am-table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:0}.am-panel>.am-panel-bd+.am-table{border-top:1px solid #ddd}.am-panel>.am-table>tbody:first-child>tr:first-child td,.am-panel>.am-table>tbody:first-child>tr:first-child th{border-top:0}.am-panel>.am-table-bd{border:0}.am-panel>.am-table-bd>tbody>tr>td:first-child,.am-panel>.am-table-bd>tbody>tr>th:first-child,.am-panel>.am-table-bd>tfoot>tr>td:first-child,.am-panel>.am-table-bd>tfoot>tr>th:first-child,.am-panel>.am-table-bd>thead>tr>td:first-child,.am-panel>.am-table-bd>thead>tr>th:first-child{border-left:0}.am-panel>.am-table-bd>tbody>tr>td:last-child,.am-panel>.am-table-bd>tbody>tr>th:last-child,.am-panel>.am-table-bd>tfoot>tr>td:last-child,.am-panel>.am-table-bd>tfoot>tr>th:last-child,.am-panel>.am-table-bd>thead>tr>td:last-child,.am-panel>.am-table-bd>thead>tr>th:last-child{border-right:0}.am-panel>.am-table-bd>tbody>tr:first-child>td,.am-panel>.am-table-bd>tbody>tr:first-child>th,.am-panel>.am-table-bd>thead>tr:first-child>td,.am-panel>.am-table-bd>thead>tr:first-child>th{border-bottom:0}.am-panel>.am-table-bd>tbody>tr:last-child>td,.am-panel>.am-table-bd>tbody>tr:last-child>th,.am-panel>.am-table-bd>tfoot>tr:last-child>td,.am-panel>.am-table-bd>tfoot>tr:last-child>th{border-bottom:0}.am-panel>.am-list{margin:0}.am-panel>.am-list>li>a{padding-left:1rem;padding-right:1rem}.am-panel>.am-list-static li{padding-left:1rem;padding-right:1rem}.am-panel-group{margin-bottom:2rem}.am-panel-group .am-panel{margin-bottom:0;border-radius:0}.am-panel-group .am-panel+.am-panel{margin-top:6px}.am-panel-group .am-panel-hd{border-bottom:0}.am-panel-group .am-panel-hd+.am-panel-collapse .am-panel-bd{border-top:1px solid #ddd}.am-panel-group .am-panel-footer{border-top:0}.am-panel-group .am-panel-footer+.am-panel-collapse .am-panel-bd{border-bottom:1px solid #ddd}@-webkit-keyframes progress-bar-stripes{from{background-position:36px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:36px 0}to{background-position:0 0}}.am-progress{overflow:hidden;height:2rem;margin-bottom:2rem;background-color:#f5f5f5;border-radius:0;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.am-progress-bar{float:left;width:0;height:100%;font-size:1.2rem;line-height:2rem;color:#fff;text-align:center;background-color:#0e90d2;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.am-progress-striped .am-progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:36px 36px;background-size:36px 36px}.am-progress.am-active .am-progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.am-progress-bar[aria-valuenow="1"],.am-progress-bar[aria-valuenow="2"]{min-width:30px}.am-progress-bar[aria-valuenow="0"]{color:#999;min-width:30px;background:0 0;-webkit-box-shadow:none;box-shadow:none}.am-progress-bar-secondary{background-color:#3bb4f2}.am-progress-striped .am-progress-bar-secondary{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.am-progress-bar-success{background-color:#5eb95e}.am-progress-striped .am-progress-bar-success{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.am-progress-bar-warning{background-color:#F37B1D}.am-progress-striped .am-progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.am-progress-bar-danger{background-color:#dd514c}.am-progress-striped .am-progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(.25,rgba(255,255,255,.15)),color-stop(.25,transparent),color-stop(.5,transparent),color-stop(.5,rgba(255,255,255,.15)),color-stop(.75,rgba(255,255,255,.15)),color-stop(.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.am-progress-xs{height:.6rem}.am-progress-sm{height:1.2rem}.am-thumbnail{display:block;padding:2px;margin-bottom:2rem;background-color:#fff;border:1px solid #ddd;border-radius:0;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.am-thumbnail a>img,.am-thumbnail>img{margin-left:auto;margin-right:auto;display:block}.am-thumbnail a.am-thumbnail.active,.am-thumbnail a.am-thumbnail:focus,.am-thumbnail a.am-thumbnail:hover{border-color:#0e90d2;background-color:#fff}.am-thumbnail a>img,.am-thumbnail>img,img.am-thumbnail{max-width:100%;height:auto}.am-thumbnail-caption{margin:0;padding:.8rem;color:#333;font-weight:400}.am-thumbnail-caption :last-child{margin-bottom:0}.am-thumbnails{margin-left:-.5rem;margin-right:-.5rem}.am-thumbnails>li{padding:0 .5rem 1rem .5rem}.am-scrollable-horizontal{width:100%;overflow-y:hidden;overflow-x:auto;-ms-overflow-style:-ms-autohiding-scrollbar;-webkit-overflow-scrolling:touch}.am-scrollable-vertical{height:240px;overflow-y:scroll;-webkit-overflow-scrolling:touch;resize:vertical}.am-square{border-radius:0}.am-radius{border-radius:2px}.am-round{border-radius:1000px}.am-circle{border-radius:50%}.am-cf:after,.am-cf:before{content:" ";display:table}.am-cf:after{clear:both}.am-fl{float:left}.am-fr{float:right}.am-nbfc{overflow:hidden}.am-center{display:block;margin-left:auto;margin-right:auto}.am-block{display:block!important}.am-inline{display:inline!important}.am-inline-block{display:inline-block!important}.am-hide{display:none!important;visibility:hidden!important}.am-vertical-align{font-size:0}.am-vertical-align:before{content:'';display:inline-block;height:100%;vertical-align:middle}.am-vertical-align-bottom,.am-vertical-align-middle{display:inline-block;font-size:1.6rem;max-width:100%}.am-vertical-align-middle{vertical-align:middle}.am-vertical-align-bottom{vertical-align:bottom}.am-responsive-width{-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:auto}.am-margin{margin:1.6rem}.am-margin-0{margin:0!important}.am-margin-xs{margin:.5rem}.am-margin-sm{margin:1rem}.am-margin-lg{margin:2.4rem}.am-margin-xl{margin:3.2rem}.am-margin-horizontal{margin-left:1.6rem;margin-right:1.6rem}.am-margin-horizontal-0{margin-left:0!important;margin-right:0!important}.am-margin-horizontal-xs{margin-left:.5rem;margin-right:.5rem}.am-margin-horizontal-sm{margin-left:1rem;margin-right:1rem}.am-margin-horizontal-lg{margin-left:2.4rem;margin-right:2.4rem}.am-margin-horizontal-xl{margin-left:3.2rem;margin-right:3.2rem}.am-margin-vertical{margin-top:1.6rem;margin-bottom:1.6rem}.am-margin-vertical-0{margin-top:0!important;margin-bottom:0!important}.am-margin-vertical-xs{margin-top:.5rem;margin-bottom:.5rem}.am-margin-vertical-sm{margin-top:1rem;margin-bottom:1rem}.am-margin-vertical-lg{margin-top:2.4rem;margin-bottom:2.4rem}.am-margin-vertical-xl{margin-top:3.2rem;margin-bottom:3.2rem}.am-margin-top{margin-top:1.6rem}.am-margin-top-0{margin-top:0!important}.am-margin-top-xs{margin-top:.5rem}.am-margin-top-sm{margin-top:1rem}.am-margin-top-lg{margin-top:2.4rem}.am-margin-top-xl{margin-top:3.2rem}.am-margin-bottom{margin-bottom:1.6rem}.am-margin-bottom-0{margin-bottom:0!important}.am-margin-bottom-xs{margin-bottom:.5rem}.am-margin-bottom-sm{margin-bottom:1rem}.am-margin-bottom-lg{margin-bottom:2.4rem}.am-margin-bottom-xl{margin-bottom:3.2rem}.am-margin-left{margin-left:1.6rem}.am-margin-left-0{margin-left:0!important}.am-margin-left-xs{margin-left:.5rem}.am-margin-left-sm{margin-left:1rem}.am-margin-left-lg{margin-left:2.4rem}.am-margin-left-xl{margin-left:3.2rem}.am-margin-right{margin-right:1.6rem}.am-margin-right-0{margin-right:0!important}.am-margin-right-xs{margin-right:.5rem}.am-margin-right-sm{margin-right:1rem}.am-margin-right-lg{margin-right:2.4rem}.am-margin-right-xl{margin-right:3.2rem}.am-padding{padding:1.6rem}.am-padding-0{padding:0!important}.am-padding-xs{padding:.5rem}.am-padding-sm{padding:1rem}.am-padding-lg{padding:2.4rem}.am-padding-xl{padding:3.2rem}.am-padding-horizontal{padding-left:1.6rem;padding-right:1.6rem}.am-padding-horizontal-0{padding-left:0!important;padding-right:0!important}.am-padding-horizontal-xs{padding-left:.5rem;padding-right:.5rem}.am-padding-horizontal-sm{padding-left:1rem;padding-right:1rem}.am-padding-horizontal-lg{padding-left:2.4rem;padding-right:2.4rem}.am-padding-horizontal-xl{padding-left:3.2rem;padding-right:3.2rem}.am-padding-vertical{padding-top:1.6rem;padding-bottom:1.6rem}.am-padding-vertical-0{padding-top:0!important;padding-bottom:0!important}.am-padding-vertical-xs{padding-top:.5rem;padding-bottom:.5rem}.am-padding-vertical-sm{padding-top:1rem;padding-bottom:1rem}.am-padding-vertical-lg{padding-top:2.4rem;padding-bottom:2.4rem}.am-padding-vertical-xl{padding-top:3.2rem;padding-bottom:3.2rem}.am-padding-top{padding-top:1.6rem}.am-padding-top-0{padding-top:0!important}.am-padding-top-xs{padding-top:.5rem}.am-padding-top-sm{padding-top:1rem}.am-padding-top-lg{padding-top:2.4rem}.am-padding-top-xl{padding-top:3.2rem}.am-padding-bottom{padding-bottom:1.6rem}.am-padding-bottom-0{padding-bottom:0!important}.am-padding-bottom-xs{padding-bottom:.5rem}.am-padding-bottom-sm{padding-bottom:1rem}.am-padding-bottom-lg{padding-bottom:2.4rem}.am-padding-bottom-xl{padding-bottom:3.2rem}.am-padding-left{padding-left:1.6rem}.am-padding-left-0{padding-left:0!important}.am-padding-left-xs{padding-left:.5rem}.am-padding-left-sm{padding-left:1rem}.am-padding-left-lg{padding-left:2.4rem}.am-padding-left-xl{padding-left:3.2rem}.am-padding-right{padding-right:1.6rem}.am-padding-right-0{padding-right:0!important}.am-padding-right-xs{padding-right:.5rem}.am-padding-right-sm{padding-right:1rem}.am-padding-right-lg{padding-right:2.4rem}.am-padding-right-xl{padding-right:3.2rem}@media only screen{.am-hide-lg,.am-hide-lg-only,.am-hide-lg-up,.am-hide-md,.am-hide-md-only,.am-hide-md-up,.am-show-lg-down,.am-show-md-down,.am-show-sm,.am-show-sm-down,.am-show-sm-only,.am-show-sm-up{display:inherit!important}.am-hide-lg-down,.am-hide-md-down,.am-hide-sm,.am-hide-sm-down,.am-hide-sm-only,.am-hide-sm-up,.am-show-lg,.am-show-lg-only,.am-show-lg-up,.am-show-md,.am-show-md-only,.am-show-md-up{display:none!important}table.am-hide-lg,table.am-hide-lg-only,table.am-hide-lg-up,table.am-hide-md,table.am-hide-md-only,table.am-hide-md-up,table.am-show-lg-down,table.am-show-md-down,table.am-show-sm,table.am-show-sm-down,table.am-show-sm-only,table.am-show-sm-up{display:table!important}thead.am-hide-lg,thead.am-hide-lg-only,thead.am-hide-lg-up,thead.am-hide-md,thead.am-hide-md-only,thead.am-hide-md-up,thead.am-show-lg-down,thead.am-show-md-down,thead.am-show-sm,thead.am-show-sm-down,thead.am-show-sm-only,thead.am-show-sm-up{display:table-header-group!important}tbody.am-hide-lg,tbody.am-hide-lg-only,tbody.am-hide-lg-up,tbody.am-hide-md,tbody.am-hide-md-only,tbody.am-hide-md-up,tbody.am-show-lg-down,tbody.am-show-md-down,tbody.am-show-sm,tbody.am-show-sm-down,tbody.am-show-sm-only,tbody.am-show-sm-up{display:table-row-group!important}tr.am-hide-lg,tr.am-hide-lg-only,tr.am-hide-lg-up,tr.am-hide-md,tr.am-hide-md-only,tr.am-hide-md-up,tr.am-show-lg-down,tr.am-show-md-down,tr.am-show-sm,tr.am-show-sm-down,tr.am-show-sm-only,tr.am-show-sm-up{display:table-row!important}td.am-hide-lg,td.am-hide-lg-only,td.am-hide-lg-up,td.am-hide-md,td.am-hide-md-only,td.am-hide-md-up,td.am-show-lg-down,td.am-show-md-down,td.am-show-sm,td.am-show-sm-down,td.am-show-sm-only,td.am-show-sm-up,th.am-hide-lg,th.am-hide-lg-only,th.am-hide-lg-up,th.am-hide-md,th.am-hide-md-only,th.am-hide-md-up,th.am-show-lg-down,th.am-show-md-down,th.am-show-sm,th.am-show-sm-down,th.am-show-sm-only,th.am-show-sm-up{display:table-cell!important}}@media only screen and (min-width:641px){.am-hide-lg,.am-hide-lg-only,.am-hide-lg-up,.am-hide-sm,.am-hide-sm-down,.am-hide-sm-only,.am-show-lg-down,.am-show-md,.am-show-md-down,.am-show-md-only,.am-show-md-up,.am-show-sm-up{display:inherit!important}.am-hide-lg-down,.am-hide-md,.am-hide-md-down,.am-hide-md-only,.am-hide-md-up,.am-hide-sm-up,.am-show-lg,.am-show-lg-only,.am-show-lg-up,.am-show-sm,.am-show-sm-down,.am-show-sm-only{display:none!important}table.am-hide-lg,table.am-hide-lg-only,table.am-hide-lg-up,table.am-hide-sm,table.am-hide-sm-down,table.am-hide-sm-only,table.am-show-lg-down,table.am-show-md,table.am-show-md-down,table.am-show-md-only,table.am-show-md-up,table.am-show-sm-up{display:table!important}thead.am-hide-lg,thead.am-hide-lg-only,thead.am-hide-lg-up,thead.am-hide-sm,thead.am-hide-sm-down,thead.am-hide-sm-only,thead.am-show-lg-down,thead.am-show-md,thead.am-show-md-down,thead.am-show-md-only,thead.am-show-md-up,thead.am-show-sm-up{display:table-header-group!important}tbody.am-hide-lg,tbody.am-hide-lg-only,tbody.am-hide-lg-up,tbody.am-hide-sm,tbody.am-hide-sm-down,tbody.am-hide-sm-only,tbody.am-show-lg-down,tbody.am-show-md,tbody.am-show-md-down,tbody.am-show-md-only,tbody.am-show-md-up,tbody.am-show-sm-up{display:table-row-group!important}tr.am-hide-lg,tr.am-hide-lg-only,tr.am-hide-lg-up,tr.am-hide-sm,tr.am-hide-sm-down,tr.am-hide-sm-only,tr.am-show-lg-down,tr.am-show-md,tr.am-show-md-down,tr.am-show-md-only,tr.am-show-md-up,tr.am-show-sm-up{display:table-row!important}td.am-hide-lg,td.am-hide-lg-only,td.am-hide-lg-up,td.am-hide-sm,td.am-hide-sm-down,td.am-hide-sm-only,td.am-show-lg-down,td.am-show-md,td.am-show-md-down,td.am-show-md-only,td.am-show-md-up,td.am-show-sm-up,th.am-hide-lg,th.am-hide-lg-only,th.am-hide-lg-up,th.am-hide-sm,th.am-hide-sm-down,th.am-hide-sm-only,th.am-show-lg-down,th.am-show-md,th.am-show-md-down,th.am-show-md-only,th.am-show-md-up,th.am-show-sm-up{display:table-cell!important}}@media only screen and (min-width:1025px){.am-hide-md,.am-hide-md-down,.am-hide-md-only,.am-hide-sm,.am-hide-sm-down,.am-hide-sm-only,.am-show-lg,.am-show-lg-down,.am-show-lg-only,.am-show-lg-up,.am-show-md-up,.am-show-sm-up{display:inherit!important}.am-hide-lg,.am-hide-lg-down,.am-hide-lg-only,.am-hide-lg-up,.am-hide-md-up,.am-hide-sm-up,.am-show-md,.am-show-md-down,.am-show-md-only,.am-show-sm,.am-show-sm-down,.am-show-sm-only{display:none!important}table.am-hide-md,table.am-hide-md-down,table.am-hide-md-only,table.am-hide-sm,table.am-hide-sm-down,table.am-hide-sm-only,table.am-show-lg,table.am-show-lg-down,table.am-show-lg-only,table.am-show-lg-up,table.am-show-md-up,table.am-show-sm-up{display:table!important}thead.am-hide-md,thead.am-hide-md-down,thead.am-hide-md-only,thead.am-hide-sm,thead.am-hide-sm-down,thead.am-hide-sm-only,thead.am-show-lg,thead.am-show-lg-down,thead.am-show-lg-only,thead.am-show-lg-up,thead.am-show-md-up,thead.am-show-sm-up{display:table-header-group!important}tbody.am-hide-md,tbody.am-hide-md-down,tbody.am-hide-md-only,tbody.am-hide-sm,tbody.am-hide-sm-down,tbody.am-hide-sm-only,tbody.am-show-lg,tbody.am-show-lg-down,tbody.am-show-lg-only,tbody.am-show-lg-up,tbody.am-show-md-up,tbody.am-show-sm-up{display:table-row-group!important}tr.am-hide-md,tr.am-hide-md-down,tr.am-hide-md-only,tr.am-hide-sm,tr.am-hide-sm-down,tr.am-hide-sm-only,tr.am-show-lg,tr.am-show-lg-down,tr.am-show-lg-only,tr.am-show-lg-up,tr.am-show-md-up,tr.am-show-sm-up{display:table-row!important}td.am-hide-md,td.am-hide-md-down,td.am-hide-md-only,td.am-hide-sm,td.am-hide-sm-down,td.am-hide-sm-only,td.am-show-lg,td.am-show-lg-down,td.am-show-lg-only,td.am-show-lg-up,td.am-show-md-up,td.am-show-sm-up,th.am-hide-md,th.am-hide-md-down,th.am-hide-md-only,th.am-hide-sm,th.am-hide-sm-down,th.am-hide-sm-only,th.am-show-lg,th.am-show-lg-down,th.am-show-lg-only,th.am-show-lg-up,th.am-show-md-up,th.am-show-sm-up{display:table-cell!important}}@media only screen and (orientation:landscape){.am-hide-portrait,.am-show-landscape{display:inherit!important}.am-hide-landscape,.am-show-portrait{display:none!important}}@media only screen and (orientation:portrait){.am-hide-landscape,.am-show-portrait{display:inherit!important}.am-hide-portrait,.am-show-landscape{display:none!important}}.am-sans-serif{font-family:"Segoe UI","Lucida Grande",Helvetica,Arial,"Microsoft YaHei",FreeSans,Arimo,"Droid Sans","wenquanyi micro hei","Hiragino Sans GB","Hiragino Sans GB W3",FontAwesome,sans-serif}.am-serif{font-family:Georgia,"Times New Roman",Times,SimSun,FontAwesome,serif}.am-kai{font-family:Georgia,"Times New Roman",Times,Kai,"Kaiti SC",KaiTi,BiauKai,FontAwesome,serif}.am-monospace{font-family:Monaco,Menlo,Consolas,"Courier New",FontAwesome,monospace}.am-text-primary{color:#0e90d2}.am-text-secondary{color:#3bb4f2}.am-text-success{color:#5eb95e}.am-text-warning{color:#F37B1D}.am-text-danger{color:#dd514c}.am-link-muted{color:#666}.am-link-muted a{color:#666}.am-link-muted a:hover,.am-link-muted:hover{color:#555}.am-text-default{font-size:1.6rem}.am-text-xs{font-size:1.2rem}.am-text-sm{font-size:1.4rem}.am-text-lg{font-size:1.8rem}.am-text-xl{font-size:2.4rem}.am-text-xxl{font-size:3.2rem}.am-text-xxxl{font-size:4.2rem}.am-ellipsis,.am-text-truncate{word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-text-break{word-wrap:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;-moz-hyphens:auto;hyphens:auto}.am-text-nowrap{white-space:nowrap}[class*=am-align-]{margin-bottom:1rem}.am-align-left{margin-right:1rem;float:left}.am-align-right{margin-left:1rem;float:right}.am-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.am-text-ir{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}@media only screen{.am-text-left{text-align:left!important}.am-text-right{text-align:right!important}.am-text-center{text-align:center!important}.am-text-justify{text-align:justify!important}}@media only screen and (max-width:640px){.am-sm-only-text-left{text-align:left!important}.am-sm-only-text-right{text-align:right!important}.am-sm-only-text-center{text-align:center!important}.am-sm-only-text-justify{text-align:justify!important}}@media only screen and (min-width:641px) and (max-width:1024px){.am-md-only-text-left{text-align:left!important}.am-md-only-text-right{text-align:right!important}.am-md-only-text-center{text-align:center!important}.am-md-only-text-justify{text-align:justify!important}}@media only screen and (min-width:641px){.am-md-text-left{text-align:left!important}.am-md-text-right{text-align:right!important}.am-md-text-center{text-align:center!important}.am-md-text-justify{text-align:justify!important}}@media only screen and (min-width:1025px){.am-lg-text-left{text-align:left!important}.am-lg-text-right{text-align:right!important}.am-lg-text-center{text-align:center!important}.am-lg-text-justify{text-align:justify!important}}.am-text-top{vertical-align:top!important}.am-text-middle{vertical-align:middle!important}.am-text-bottom{vertical-align:bottom!important}.am-angle{position:absolute}.am-angle:after,.am-angle:before{position:absolute;display:block;content:"";width:0;height:0;border:8px dashed transparent;z-index:1}.am-angle-up{top:0}.am-angle-up:after,.am-angle-up:before{border-bottom-style:solid;border-width:0 8px 8px}.am-angle-up:before{border-bottom-color:#ddd;bottom:0}.am-angle-up:after{border-bottom-color:#fff;bottom:-1px}.am-angle-down{bottom:-9px}.am-angle-down:after,.am-angle-down:before{border-top-style:solid;border-width:8px 8px 0}.am-angle-down:before{border-top-color:#ddd;bottom:0}.am-angle-down:after{border-top-color:#fff;bottom:1px}.am-angle-left{left:-9px}.am-angle-left:after,.am-angle-left:before{border-right-style:solid;border-width:8px 8px 8px 0}.am-angle-left:before{border-right-color:#ddd;left:0}.am-angle-left:after{border-right-color:#fff;left:1px}.am-angle-right{right:0}.am-angle-right:after,.am-angle-right:before{border-left-style:solid;border-width:8px 0 8px 8px}.am-angle-right:before{border-left-color:#ddd;left:0}.am-angle-right:after{border-left-color:#fff;left:-1px}.am-alert{margin-bottom:1em;padding:.625em;background:#0e90d2;color:#fff;border:1px solid #0c7cb5;border-radius:0}.am-alert a{color:#fff}.am-alert h1,.am-alert h2,.am-alert h3,.am-alert h4,.am-alert h5,.am-alert h6{color:inherit}.am-alert .am-close{opacity:.4}.am-alert .am-close:hover{opacity:.6}*+.am-alert{margin-top:1em}.am-alert>:last-child{margin-bottom:0}.am-form-group .am-alert{margin:5px 0 0;padding:.25em .625em;font-size:1.3rem}.am-alert>.am-close:first-child{float:right;height:auto;margin:-3px -5px auto auto}.am-alert>.am-close:first-child+*{margin-top:0}.am-alert-secondary{background-color:#eee;border-color:#dfdfdf;color:#555}.am-alert-success{background-color:#5eb95e;border-color:#4bad4b;color:#fff}.am-alert-warning{background-color:#F37B1D;border-color:#e56c0c;color:#fff}.am-alert-danger{background-color:#dd514c;border-color:#d83832;color:#fff}.am-dropdown{position:relative;display:inline-block}.am-dropdown-toggle:focus{outline:0}.am-dropdown-content{position:absolute;top:100%;left:0;z-index:1020;display:none;float:left;min-width:160px;padding:15px;margin:9px 0 0;text-align:left;line-height:1.6;background-color:#fff;border:1px solid #ddd;border-radius:0;-webkit-background-clip:padding-box;background-clip:padding-box;-webkit-animation-duration:.15s;animation-duration:.15s}.am-dropdown-content:after,.am-dropdown-content:before{position:absolute;display:block;content:"";width:0;height:0;border:8px dashed transparent;z-index:1}.am-dropdown-content:after,.am-dropdown-content:before{border-bottom-style:solid;border-width:0 8px 8px}.am-dropdown-content:before{border-bottom-color:#ddd;bottom:0}.am-dropdown-content:after{border-bottom-color:#fff;bottom:-1px}.am-dropdown-content:after,.am-dropdown-content:before{left:10px;top:-8px;pointer-events:none}.am-dropdown-content:after{top:-7px}.am-active>.am-dropdown-content{display:block}.am-dropdown-content :first-child{margin-top:0}.am-dropdown-up .am-dropdown-content{top:auto;bottom:100%;margin:0 0 9px}.am-dropdown-up .am-dropdown-content:after,.am-dropdown-up .am-dropdown-content:before{border-bottom:none;border-top:8px solid #ddd;top:auto;bottom:-8px}.am-dropdown-up .am-dropdown-content:after{bottom:-7px;border-top-color:#fff}.am-dropdown-flip .am-dropdown-content{left:auto;right:0}.am-dropdown-flip .am-dropdown-content:after,.am-dropdown-flip .am-dropdown-content:before{left:auto;right:10px}ul.am-dropdown-content{list-style:none;padding:5px 0}ul.am-dropdown-content.am-fr{right:0;left:auto}ul.am-dropdown-content .am-divider{height:1px;margin:0rem 0;overflow:hidden;background-color:#e5e5e5}ul.am-dropdown-content>li>a{display:block;padding:6px 20px;clear:both;font-weight:400;color:#333;white-space:nowrap}ul.am-dropdown-content>li>a:focus,ul.am-dropdown-content>li>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}ul.am-dropdown-content>.am-active>a,ul.am-dropdown-content>.am-active>a:focus,ul.am-dropdown-content>.am-active>a:hover{color:#fff;text-decoration:none;outline:0;background-color:#0e90d2}ul.am-dropdown-content>.am-disabled>a,ul.am-dropdown-content>.am-disabled>a:focus,ul.am-dropdown-content>.am-disabled>a:hover{color:#999}ul.am-dropdown-content>.am-disabled>a:focus,ul.am-dropdown-content>.am-disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.am-dropdown-header{display:block;padding:6px 20px;font-size:1.2rem;color:#999}.am-fr>.am-dropdown-content{right:0;left:auto}.am-fr>.am-dropdown-content:before{right:10px;left:auto}.am-dropdown-animation{-webkit-animation:am-dropdown-animation .15s ease-out;animation:am-dropdown-animation .15s ease-out}@-webkit-keyframes am-dropdown-animation{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}}@keyframes am-dropdown-animation{0%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}100%{opacity:0;-webkit-transform:translateY(-10px);transform:translateY(-10px)}}.am-slider a:focus,.am-slider a:hover{outline:0}.am-control-nav,.am-direction-nav,.am-slides{margin:0;padding:0;list-style:none}.am-slider{margin:0;padding:0}.am-slider .am-slides:after,.am-slider .am-slides:before{content:" ";display:table}.am-slider .am-slides:after{clear:both}.am-slider .am-slides>li{display:none;-webkit-backface-visibility:hidden;position:relative}.no-js .am-slider .am-slides>li:first-child{display:block}.am-slider .am-slides img{width:100%;display:block}.am-pauseplay span{text-transform:capitalize}.am-slider{position:relative}.am-viewport{-webkit-transition:all 1s ease;transition:all 1s ease}.am-slider-carousel li{margin-right:5px}.am-control-nav{position:absolute}.am-control-nav li{display:inline-block}.am-control-thumbs{position:static;overflow:hidden}.am-control-thumbs img{-webkit-transition:all 1s ease;transition:all 1s ease}.am-slider-slide .am-slides>li{display:none;position:relative}@media all and (transform-3d),(-webkit-transform-3d){.am-slider-slide .am-slides>li{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.am-slider-slide .am-slides>li.active.right,.am-slider-slide .am-slides>li.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.am-slider-slide .am-slides>li.active.left,.am-slider-slide .am-slides>li.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.am-slider-slide .am-slides>li.active,.am-slider-slide .am-slides>li.next.left,.am-slider-slide .am-slides>li.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}.am-slider-slide .am-slides>.active,.am-slider-slide .am-slides>.next,.am-slider-slide .am-slides>.prev{display:block}.am-slider-slide .am-slides>.active{left:0}.am-slider-slide .am-slides>.next,.am-slider-slide .am-slides>.prev{position:absolute;top:0;width:100%}.am-slider-slide .am-slides>.next{left:100%}.am-slider-slide .am-slides>.prev{left:-100%}.am-slider-slide .am-slides>.next.left,.am-slider-slide .am-slides>.prev.right{left:0}.am-slider-slide .am-slides>.active.left{left:-100%}.am-slider-slide .am-slides>.active.right{left:100%}.am-slider-default{margin:0 0 20px;background-color:#fff;border-radius:2px;-webkit-box-shadow:0 0 2px rgba(0,0,0,.15);box-shadow:0 0 2px rgba(0,0,0,.15)}.am-slider-default .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-default .am-viewport{max-height:300px}.am-slider-default .carousel li{margin-right:5px}.am-slider-default .am-direction-nav a{position:absolute;top:50%;z-index:10;display:block;width:36px;height:36px;margin:-18px 0 0;overflow:hidden;opacity:.45;cursor:pointer;color:rgba(0,0,0,.65);-webkit-transition:all .3s ease;transition:all .3s ease}.am-slider-default .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);width:100%;color:#333;content:"\f137";font-size:24px!important;text-align:center;line-height:36px!important;height:36px}.am-slider-default .am-direction-nav a.am-next:before{content:"\f138"}.am-slider-default .am-direction-nav .am-prev{left:10px}.am-slider-default .am-direction-nav .am-next{right:10px;text-align:right}.am-slider-default .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-default:hover .am-prev{opacity:.7;left:10px}.am-slider-default:hover .am-prev:hover{opacity:1}.am-slider-default:hover .am-next{opacity:.7;right:10px}.am-slider-default:hover .am-next:hover{opacity:1}.am-slider-default .am-pauseplay a{display:block;width:20px;height:20px;position:absolute;bottom:5px;left:10px;opacity:.8;z-index:10;overflow:hidden;cursor:pointer;color:#000}.am-slider-default .am-pauseplay a::before{font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);font-size:20px;display:inline-block;content:"\f04c"}.am-slider-default .am-pauseplay a:hover{opacity:1}.am-slider-default .am-pauseplay a.am-play::before{content:"\f04b"}.am-slider-default .am-slider-desc{background-color:rgba(0,0,0,.7);position:absolute;bottom:0;padding:10px;width:100%;color:#fff}.am-slider-default .am-control-nav{width:100%;position:absolute;bottom:-15px;text-align:center}.am-slider-default .am-control-nav li{margin:0 6px;display:inline-block}.am-slider-default .am-control-nav li a{width:8px;height:8px;display:block;background-color:#666;background-color:rgba(0,0,0,.5);line-height:0;font-size:0;cursor:pointer;text-indent:-9999px;border-radius:20px;-webkit-box-shadow:inset 0 0 3px rgba(0,0,0,.3);box-shadow:inset 0 0 3px rgba(0,0,0,.3)}.am-slider-default .am-control-nav li a:hover{background-color:#333;background-color:rgba(0,0,0,.7)}.am-slider-default .am-control-nav li a.am-active{background-color:#000;background-color:#0e90d2;cursor:default}.am-slider-default .am-control-thumbs{margin:5px 0 0;position:static;overflow:hidden}.am-slider-default .am-control-thumbs li{width:25%;float:left;margin:0}.am-slider-default .am-control-thumbs img{width:100%;height:auto;display:block;opacity:.7;cursor:pointer}.am-slider-default .am-control-thumbs img:hover{opacity:1}.am-slider-default .am-control-thumbs .am-active{opacity:1;cursor:default}.am-slider-default .am-control-thumbs i{position:absolute}.am-modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1110;display:none;opacity:0;outline:0;text-align:center;-webkit-transform:scale(1.185);-ms-transform:scale(1.185);transform:scale(1.185);-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.am-modal:focus{outline:0}.am-modal.am-modal-active{opacity:1;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);overflow-x:hidden;overflow-y:auto}.am-modal.am-modal-out{opacity:0;z-index:1109;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transform:scale(.815);-ms-transform:scale(.815);transform:scale(.815)}.am-modal:before{content:"\200B";display:inline-block;height:100%;vertical-align:middle}.am-modal-dialog{position:relative;display:inline-block;vertical-align:middle;margin-left:auto;margin-right:auto;width:270px;max-width:100%;border-radius:0;background:#f8f8f8}@media only screen and (min-width:641px){.am-modal-dialog{width:540px}}.am-modal-hd{padding:15px 10px 5px 10px;font-size:1.8rem;font-weight:500}.am-modal-hd+.am-modal-bd{padding-top:0}.am-modal-hd .am-close{position:absolute;top:4px;right:4px}.am-modal-bd{padding:15px 10px;text-align:center;border-bottom:1px solid #dedede;border-radius:2px 2px 0 0}.am-modal-bd+.am-modal-bd{margin-top:5px}.am-modal-prompt-input{display:block;margin:5px auto 0 auto;border-radius:0;padding:5px;line-height:1.8rem;width:80%;border:1px solid #dedede;-webkit-appearance:none;-moz-appearance:none;-ms-appearance:none;appearance:none}.am-modal-prompt-input:focus{outline:0;border-color:#d6d6d6}.am-modal-footer{height:44px;overflow:hidden;display:table;width:100%;border-collapse:collapse}.am-modal-btn{display:table-cell!important;padding:0 5px;height:44px;-webkit-box-sizing:border-box!important;box-sizing:border-box!important;font-size:1.6rem;line-height:44px;text-align:center;color:#0e90d2;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;cursor:pointer;border-right:1px solid #dedede}.am-modal-btn:first-child{border-radius:0}.am-modal-btn:last-child{border-right:none;border-radius:0}.am-modal-btn:first-child:last-child{border-radius:0}.am-modal-btn.am-modal-btn-bold{font-weight:500}.am-modal-btn:active{background:#d4d4d4}.am-modal-btn+.am-modal-btn{border-left:1px solid #dedede}.am-modal-no-btn .am-modal-dialog{border-radius:0;border-bottom:none}.am-modal-no-btn .am-modal-bd{border-bottom:none}.am-modal-no-btn .am-modal-footer{display:none}.am-modal-loading .am-modal-bd{border-bottom:none}.am-modal-loading .am-icon-spin{display:inline-block;font-size:2.4rem}.am-modal-loading .am-modal-footer{display:none}.am-modal-actions{position:fixed;left:0;bottom:0;z-index:1110;width:100%;max-height:100%;overflow-x:hidden;overflow-y:auto;text-align:center;border-radius:0;-webkit-transform:translateY(100%);-ms-transform:translateY(100%);transform:translateY(100%);-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s}.am-modal-actions.am-modal-active{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.am-modal-actions.am-modal-out{z-index:1109;-webkit-transform:translateY(100%);-ms-transform:translateY(100%);transform:translateY(100%)}.am-modal-actions-group{margin:10px}.am-modal-actions-group .am-list{margin:0;border-radius:0}.am-modal-actions-group .am-list>li{margin-bottom:0;border-bottom:none;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;-webkit-box-shadow:inset 0 1px 0 rgba(0,0,0,.015);box-shadow:inset 0 1px 0 rgba(0,0,0,.015)}.am-modal-actions-group .am-list>li>a{padding:1rem;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-modal-actions-group .am-list>li:first-child{border-top:none;border-top-right-radius:0;border-top-left-radius:0}.am-modal-actions-group .am-list>li:last-child{border-bottom:none;border-bottom-right-radius:0;border-bottom-left-radius:0}.am-modal-actions-header{padding:1rem;color:#999;font-size:1.4rem}.am-modal-actions-danger{color:#dd514c}.am-modal-actions-danger a{color:inherit}.am-popup{position:fixed;left:0;top:0;width:100%;height:100%;z-index:1110;background:#fff;display:none;overflow:hidden;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transform:translateY(100%);-ms-transform:translateY(100%);transform:translateY(100%)}.am-popup.am-modal-active,.am-popup.am-modal-out{-webkit-transition-duration:.3s;transition-duration:.3s}.am-popup.am-modal-active{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.am-popup.am-modal-out{-webkit-transform:translateY(100%);-ms-transform:translateY(100%);transform:translateY(100%)}@media all and (min-width:630px) and (min-height:630px){.am-popup{width:630px;height:630px;left:50%;top:50%;margin-left:-315px;margin-top:-315px;-webkit-transform:translateY(1024px);-ms-transform:translateY(1024px);transform:translateY(1024px)}.am-popup.am-modal-active{-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}.am-popup.am-modal-out{-webkit-transform:translateY(1024px);-ms-transform:translateY(1024px);transform:translateY(1024px)}}.am-popup-inner{padding-top:44px;height:100%;overflow:auto;-webkit-overflow-scrolling:touch}.am-popup-hd{position:absolute;top:0;z-index:1000;width:100%;height:43px;border-bottom:1px solid #dedede;background-color:#fff}.am-popup-hd .am-popup-title{font-size:1.8rem;font-weight:700;line-height:43px;text-align:center;margin:0 30px;color:#333;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-popup-hd .am-close{position:absolute;right:10px;top:8px;cursor:pointer;-webkit-transition:all .3s;transition:all .3s;color:#999}.am-popup-hd .am-close:hover{-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);color:#555}.am-popup-bd{padding:15px;background:#f8f8f8;color:#555}.am-offcanvas{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1090;background:rgba(0,0,0,.15)}.am-offcanvas.am-active{display:block}.am-offcanvas-page{position:fixed;-webkit-transition:margin-left .3s ease-in-out;transition:margin-left .3s ease-in-out}.am-offcanvas-bar{position:fixed;top:0;bottom:0;left:0;z-index:1091;width:270px;max-width:100%;background:#333;overflow-y:auto;-webkit-overflow-scrolling:touch;-webkit-transition:-webkit-transform .3s ease-in-out;transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;transition:transform .3s ease-in-out,-webkit-transform .3s ease-in-out;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%)}.am-offcanvas-bar:after{content:"";display:block;position:absolute;top:0;bottom:0;right:0;width:1px;background:#262626}.am-offcanvas.am-active .am-offcanvas-bar.am-offcanvas-bar-active{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}.am-offcanvas-bar-flip{left:auto;right:0;-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.am-offcanvas-bar-flip:after{right:auto;left:0}.am-offcanvas-content{padding:15px;color:#999}.am-offcanvas-content a{color:#ccc}.am-popover{position:absolute;top:0;left:0;margin:0;border-radius:0;background:#333;color:#fff;border:1px solid #333;display:none;font-size:1.6rem;z-index:1150;opacity:0;-webkit-transition:opacity .3s;transition:opacity .3s}.am-popover.am-active{display:block!important;opacity:1}.am-popover-inner{position:relative;background:#333;padding:8px;z-index:110}.am-popover-caret{position:absolute;top:0;z-index:100;display:inline-block;width:0;height:0;vertical-align:middle;border-bottom:8px solid #333;border-right:8px solid transparent;border-left:8px solid transparent;border-top:0 dotted;-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);overflow:hidden}.am-popover-top .am-popover-caret{top:auto;bottom:-8px;-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.am-popover-bottom .am-popover-caret{top:-8px}.am-popover-bottom .am-popover-caret,.am-popover-top .am-popover-caret{left:50%;margin-left:-8px}.am-popover-left .am-popover-caret{top:auto;left:auto;right:-12px;-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.am-popover-right .am-popover-caret{right:auto;left:-12px;-webkit-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.am-popover-left .am-popover-caret,.am-popover-right .am-popover-caret{top:50%;margin-top:-4px}.am-popover-sm{font-size:1.4rem}.am-popover-sm .am-popover-inner{padding:5px}.am-popover-lg{font-size:1.8rem}.am-popover-primary{border-color:#0e90d2}.am-popover-primary .am-popover-inner{background:#0e90d2}.am-popover-primary .am-popover-caret{border-bottom-color:#0e90d2}.am-popover-secondary{border-color:#3bb4f2}.am-popover-secondary .am-popover-inner{background:#3bb4f2}.am-popover-secondary .am-popover-caret{border-bottom-color:#3bb4f2}.am-popover-success{border-color:#5eb95e}.am-popover-success .am-popover-inner{background:#5eb95e}.am-popover-success .am-popover-caret{border-bottom-color:#5eb95e}.am-popover-warning{border-color:#F37B1D}.am-popover-warning .am-popover-inner{background:#F37B1D}.am-popover-warning .am-popover-caret{border-bottom-color:#F37B1D}.am-popover-danger{border-color:#dd514c}.am-popover-danger .am-popover-inner{background:#dd514c}.am-popover-danger .am-popover-caret{border-bottom-color:#dd514c}#nprogress{pointer-events:none}#nprogress .nprogress-bar{position:fixed;top:0;left:0;z-index:2000;width:100%;height:2px;background:#5eb95e}#nprogress .nprogress-peg{display:block;position:absolute;right:0;width:100px;height:100%;-webkit-box-shadow:0 0 10px #5eb95e,0 0 5px #5eb95e;box-shadow:0 0 10px #5eb95e,0 0 5px #5eb95e;opacity:1;-webkit-transform:rotate(3deg) translate(0,-4px);-ms-transform:rotate(3deg) translate(0,-4px);transform:rotate(3deg) translate(0,-4px)}#nprogress .nprogress-spinner{position:fixed;top:15px;right:15px;z-index:2000;display:block}#nprogress .nprogress-spinner-icon{width:18px;height:18px;-webkit-box-sizing:border-box;box-sizing:border-box;border:solid 2px transparent;border-top-color:#5eb95e;border-left-color:#5eb95e;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nprogress-spinner{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.am-tabs-bd{position:relative;overflow:hidden;border:1px solid #ddd;border-top:none;z-index:100;-webkit-transition:height .3s;transition:height .3s}.am-tabs-bd:after,.am-tabs-bd:before{content:" ";display:table}.am-tabs-bd:after{clear:both}.am-tabs-bd .am-tab-panel{position:absolute;top:0;z-index:99;float:left;width:100%;padding:10px 10px 15px;visibility:hidden;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%)}.am-tabs-bd .am-tab-panel *{-webkit-user-drag:none}.am-tabs-bd .am-tab-panel.am-active{position:relative;z-index:100;visibility:visible;-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}.am-tabs-bd .am-tab-panel.am-active~.am-tab-panel{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%)}.am-tabs-bd .am-tabs-bd{border:none}.am-tabs-bd-ofv{overflow:visible}.am-tabs-bd-ofv>.am-tab-panel{display:none}.am-tabs-bd-ofv>.am-tab-panel.am-active{display:block}.am-tabs-fade .am-tab-panel{opacity:0;-webkit-transition:opacity .25s linear;transition:opacity .25s linear}.am-tabs-fade .am-tab-panel.am-in{opacity:1}.am-share{font-size:14px}.am-share-title{padding:10px 0 0;margin:0 10px;font-weight:400;text-align:center;color:#555;background-color:#f8f8f8;border-bottom:1px solid #fff;border-top-right-radius:2px;border-top-left-radius:2px}.am-share-title:after{content:"";display:block;width:100%;height:0;margin-top:10px;border-bottom:1px solid #dfdfdf}.am-share-sns{margin:0 10px;padding-top:15px;background-color:#f8f8f8;border-bottom-right-radius:2px;border-bottom-left-radius:2px}.am-share-sns li{margin-bottom:15px}.am-share-sns a{display:block;color:#555}.am-share-sns span{display:block}.am-share-sns [class*=am-icon]{background-color:#3bb4f2;border-radius:50%;width:36px;height:36px;line-height:36px;color:#fff;margin-bottom:5px;font-size:18px}.am-share-sns .am-icon-weibo{background-color:#ea1328}.am-share-sns .am-icon-qq{background-color:#009cda}.am-share-sns .am-icon-star{background-color:#ffc028}.am-share-sns .am-icon-tencent-weibo{background-color:#23ccfe}.am-share-sns .am-icon-wechat,.am-share-sns .am-icon-weixin{background-color:#44b549}.am-share-sns .am-icon-renren{background-color:#105ba3}.am-share-sns .am-icon-comment{background-color:#5eb95e}.am-share-footer{margin:10px}.am-share-footer .am-btn{color:#555}.am-share-wechat-qr{font-size:14px;color:#777}.am-share-wechat-qr .am-modal-dialog{background-color:#fff;border:1px solid #dedede}.am-share-wechat-qr .am-modal-hd{padding-top:10px;text-align:left;margin-bottom:10px}.am-share-wechat-qr .am-share-wx-qr{margin-bottom:10px}.am-share-wechat-qr .am-share-wechat-tip{text-align:left}.am-share-wechat-qr .am-share-wechat-tip em{color:#dd514c;font-weight:700;font-style:normal;margin-left:3px;margin-right:3px}.am-pureview{position:fixed;left:0;top:0;bottom:0;right:0;z-index:1120;width:100%;height:100%;background:rgba(0,0,0,.95);display:none;overflow:hidden;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;-webkit-transform:translate(0,100%);-ms-transform:translate(0,100%);transform:translate(0,100%)}.am-pureview.am-active{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.am-pureview ol,.am-pureview ul{list-style:none;padding:0;margin:0;width:100%}.am-pureview-slider{overflow:hidden;height:100%}.am-pureview-slider li{position:absolute;width:100%;height:100%;top:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;vertical-align:middle;-webkit-transition:all .3s linear;transition:all .3s linear;z-index:100;visibility:hidden}.am-pureview-slider li.am-pureview-slide-prev{-webkit-transform:translate(-100%,0);-ms-transform:translate(-100%,0);transform:translate(-100%,0);z-index:109}.am-pureview-slider li.am-pureview-slide-next{-webkit-transform:translate(100%,0);-ms-transform:translate(100%,0);transform:translate(100%,0);z-index:109}.am-pureview-slider li.am-active{position:relative;z-index:110;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);visibility:visible}.am-pureview-slider .pinch-zoom-container{width:100%;z-index:1121}.am-pureview-slider .am-pinch-zoom{position:relative;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center}.am-pureview-slider .am-pinch-zoom:after{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f110";-webkit-animation:icon-spin 2s infinite linear;animation:icon-spin 2s infinite linear;font-size:24px;line-height:24px;color:#eee;position:absolute;top:50%;left:50%;margin-left:-12px;margin-top:-12px;z-index:1}.am-pureview-slider .am-pinch-zoom.am-pureview-loaded:after{display:none}.am-pureview-slider img{position:relative;display:block;max-width:100%;max-height:100%;opacity:0;z-index:200;-webkit-user-drag:none;-webkit-transition:opacity .2s ease-in;transition:opacity .2s ease-in}.am-pureview-slider img.am-img-loaded{opacity:1}.am-pureview-direction{position:absolute;top:50%;width:100%;margin-top:-18px!important;z-index:1122}.am-pureview-only .am-pureview-direction,.am-touch .am-pureview-direction{display:none}.am-pureview-direction li{position:absolute;width:36px;height:36px}.am-pureview-direction a{display:block;height:36px;border:none;color:#ccc;opacity:.5;cursor:pointer;text-align:center;z-index:1125}.am-pureview-direction a:before{content:"\f137";line-height:36px;font-size:24px}.am-pureview-direction a:hover{opacity:1}.am-pureview-direction .am-pureview-prev{left:15px}.am-pureview-direction .am-pureview-next{right:15px}.am-pureview-direction .am-pureview-next a:before{content:"\f138"}.am-pureview-bar{position:absolute;bottom:0;height:45px;width:100%;background-color:rgba(0,0,0,.35);color:#eee;line-height:45px;padding:0 10px;font-size:14px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.am-pureview-bar .am-pureview-title{display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;margin-left:6px;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.am-pureview-bar .am-pureview-total{font-size:10px;line-height:48px}.am-pureview-actions{position:absolute;z-index:1130;left:0;right:0;top:0;height:45px;background-color:rgba(0,0,0,.35)}.am-pureview-actions a{position:absolute;left:10px;color:#ccc;display:block;width:45px;line-height:45px;text-align:left;font-size:16px}.am-pureview-actions a:hover{color:#fff}.am-pureview-actions [data-am-toggle=share]{left:auto;right:10px}.am-pureview-actions,.am-pureview-bar{opacity:0;-webkit-transition:all .15s;transition:all .15s;z-index:1130}.am-pureview-bar-active .am-pureview-actions,.am-pureview-bar-active .am-pureview-bar{opacity:1}.am-pureview-nav{position:absolute;bottom:15px;left:0;right:0;text-align:center;z-index:1131}.am-pureview-bar-active .am-pureview-nav{display:none}.am-pureview-nav li{display:inline-block;background:#ccc;background:rgba(255,255,255,.5);width:8px;height:8px;margin:0 3px;border-radius:50%;text-indent:-9999px;overflow:hidden;cursor:pointer}.am-pureview-nav .am-active{background:#fff;background:rgba(255,255,255,.9)}[data-am-pureview] img{cursor:pointer}.am-pureview-active{overflow:hidden}.ath-viewport *{-webkit-box-sizing:border-box;box-sizing:border-box}.ath-viewport{position:relative;z-index:2147483641;pointer-events:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;text-size-adjust:none}.ath-modal{pointer-events:auto!important;background:rgba(0,0,0,.6)}.ath-mandatory{background:#000}.ath-container{pointer-events:auto!important;position:absolute;z-index:2147483641;padding:.7em .6em;width:18em;background:#eee;-webkit-background-size:100% auto;background-size:100% auto;-webkit-box-shadow:0 .2em 0 #d1d1d1;box-shadow:0 .2em 0 #d1d1d1;font-family:sans-serif;font-size:15px;line-height:1.5em;text-align:center}.ath-container small{font-size:.8em;line-height:1.3em;display:block;margin-top:.5em}.ath-ios.ath-phone{bottom:1.8em;left:50%;margin-left:-9em}.ath-ios6.ath-tablet{left:5em;top:1.8em}.ath-ios7.ath-tablet{left:.7em;top:1.8em}.ath-ios8.ath-tablet{right:.4em;top:1.8em}.ath-android{bottom:1.8em;left:50%;margin-left:-9em}.ath-container:before{content:'';position:relative;display:block;float:right;margin:-.7em -.6em 0 .5em;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAMAAABmmnOVAAAAdVBMVEUAAAA5OTkzMzM7Ozs3NzdBQUFAQEA/Pz8+Pj5BQUFAQEA/Pz8+Pj5BQUFAQEA/Pz9BQUE+Pj4/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8+Pj4/Pz8+Pj4/Pz8/Pz8/Pz8/Pz8/Pz8+Pj4/Pz8/Pz8/Pz8/Pz9AQEA/Pz+fdCaPAAAAJnRSTlMACQoNDjM4OTo7PEFCQ0RFS6ytsbS1tru8vcTFxu7x8vX19vf4+C5yomAAAAJESURBVHgBvdzLTsJAGEfxr4C2KBcVkQsIDsK8/yPaqIsPzVlyzrKrX/5p0kkXEz81L23otc9NpIbbWia2YVLqdnhlqFlhGWpSDHe1aopsSIpRb8gK0dC3G30b9rVmhWZIimTICsvQtx/FsuYOrWHoDjX3Gu31gzJxdki934WrAIOsAIOsAIOiAMPhPsJTgKGN0BVsYIVsYIVpYIVpYIVpYIVpYIVpYIVpYIVpYIVlAIVgEBRs8BRs8BRs8BRs8BRs8BRs8BRs8BRTNmgKNngKNngKNngKNngKNhiKGxgiOlZoBlaYBlaYBlaYBlaYBlaYBlaYBlaYBlZIBlBMfQMrVAMr2KAqBENSHFHhGEABhi5CV6gGUKgGUKgGUKgGUFwuqgEUvoEVsoEVpoEUpgEUggF+gKTKY+h1fxSlC7/Z+RrxOQ3fcEoAPPHZBlaYBlaYBlaYBlZYBlYIhvLBCstw7PgM7hkiWOEZWGEaWGEaWGEaIsakEAysmHkGVpxmvoEVqoEVpoEVpoEVpoEVpoEVpoEVkoEVgkFQsEFSsEFQsGEcoSvY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnY4CnmbNAUT2c2WAo2eAo2eAo2eAo2eAo2eArNEPFACjZ4CjZ4CjZ4CjaIird/rBvFH6llNCvewdli1URWCIakSIZesUaDoFg36dKFWk9zCZDei3TtwmCj7pC22AwikiIZPEU29IpFNliKxa/hC9DFITjQPYhcAAAAAElFTkSuQmCC);background-color:rgba(255,255,255,.8);-webkit-background-size:50% 50%;background-size:50%;background-repeat:no-repeat;background-position:50%;width:2.7em;height:2.7em;text-align:center;overflow:hidden;color:#a33;z-index:2147483642}.ath-container.ath-icon:before{position:absolute;top:0;right:0;margin:0;float:none}.ath-mandatory .ath-container:before{display:none}.ath-container.ath-android:before{float:left;margin:-.7em .5em 0 -.6em}.ath-container.ath-android.ath-icon:before{position:absolute;right:auto;left:0;margin:0;float:none}.ath-action-icon{display:inline-block;vertical-align:middle;background-position:50%;background-repeat:no-repeat;text-indent:-9999em;overflow:hidden}.ath-ios7 .ath-action-icon,.ath-ios8 .ath-action-icon{width:1.6em;height:1.6em;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAACtCAYAAAB7l7tOAAAF6UlEQVR4AezZWWxUZRiH8VcQEdxZEFFiUZBFUCIa1ABBDARDcCciYGKMqTEGww3SOcNSAwQTjOBiiIpEhRjAhRgXRC8MFxojEhAFZUGttVhaoSxlaW3n8W3yXZxm6vTrOMM5Q98n+V9MMu1pvl++uZhKuypghu49KaaTWGdZSYoVN6VD95nMpLNYZ9XNbdQR2od2k88O3Gm6Bh0t7H0p5Vwp2Ax3ajpu2tYbciFWwkTFO63DY6+JcI4USFaSyYpWp8N7SVZJKR3EinkBk9JxvZFXxhnZSjBaoWp1ZL0ES8WKYXMZp0AndORgy8WKFe5Yf1zvvSBWDEpys2LU6MjD5kmEWQlGKsJRHXlcqUSQVcItEnDEA6gAb7LhjvD9WO6yIEfICQI5A1nzGCYB1T4og5bBiFcyv2f6ujYhl4iVxwKG6qp8MK55HsqPwK0rMr9v/yEo3uCPrJstVh5KMER30Aeh31Ioq0FrHfjXw9CYghnrvYFTuqfEymFzGSwBlT4ARYr7u+K6GLmCVGvAGg2NMG0d/sgJnpScZLjXSkC5z8H3eQ72/k24Q8NfzvwFyK4qtuJSZKaubRPyE/K/Mtx+EvCHL+7uasId1t10w0scz/RzSzYzAfgKV30D3LPaG7lRkR8RK4tKKJKAMp+D7r0EfmmOe0x3m2itAc/ZxBjgAt1mXHWKPPkdb+QGSTJdrDaU5EoJ2OtzwD0WwY7KNNzbRfMFFg24WPdtGHnS221Cflgsj56hjwTs8TnY7oq7/QDhjutGicsb2AVcovsO18l6uPPNNiE/JFaGAq7Q7fY50G4LYVtz3FrdaNGyBXbIl+q24DqhyHes9EaulwR3SwtZs+ktAT/7HORliru1gnCndONFyx44Dfn7MPLYN7yR6yTJZAllJeguAT/4HOBFz8I3ZWm4E0TLFbBD7qn7EVdtHYx53R9ZN0ksrZRuErDN5+AuLIWvm+Oe1k0ULdfADrmX7idcR0/DyBXeyCdlLuMMOGCBz4F1ng+f7yFcve5e0fIFHELeiav6BAx70Rt5p0yhY3u/wR0kyarW/uX35b403PtFyzewQ75ctwtXzSkY8WqruHslSV8RscrL6TJ1bcvfWJ0/HzbtIdw/ugdFyzdwOOAq3T6fmzxwGQ3vbmO8iFioIWqYSsHMj9M/ljfuTsOdItoZBXYBfXX7cVXVwvXLm/8+fU3lcdCqdEMNGBbgUmRmfQISQKd5sGEn4VK6YtEiAXYBA3QVuA4q8hCHrDcafR1ul65jewfuovsCl7vJrNlOuEbdo6JFCuwCrtb9hqusBu56Cw4cI1y1briIWEBn3Ue0XKPuMdGiBg4H9NdV0HJ/6QZLOEPmPN0GmpfSPS5arIBdwHUtIFfoBsl/ZsgfhHCfFi2WwC5goO4AmvanbqBkzJA76tboZokWa2AXMEi3RTdAvDLkDqJFAhzB32xFD2wZsGXA0WfAlgFbBmwZsGXAlgFbBpzk04JaKb0iA9ZnF9x5SQAFtRKKIgPWZxfaeRmwAZ/BGbAB37eaG6MCbnq2Aed5czYyKirgpmcbsAHHZAZswN0Wwo7KeG1fFf2jAm56dtzOQ42yB+65mDhWFBUwUETMUiMDNmADbp/APRaTAh6I2bpGCNw1bufRZJQ1cPdF/NueHZsgDEBBGLbMGoIu4AZu5gLOZeEaYmEXeznF3jRPyEv4frgJvvJe3qTefY0AAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwb8rwADBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgz4/sz1Nia/9hizA7zgklwy3RYwYMBzBRjw4bPjxAbAAizAAtwgwAIswAIswAIMGDBgARZgARZgAS4FWIAFWIAFWIABAwYswAIswAIswIUAC7AAC7AACzBgwIAFWIAFWIAFuBBgARZgARZgAQYMGPApQ99ZCdgWtzqwATbABtgAG2DbnxNb7zbRimsMLMACrDf2wMWI/WasfQAAAABJRU5ErkJggg==);margin-top:-.3em;-webkit-background-size:auto 100%;background-size:auto 100%}.ath-ios6 .ath-action-icon{width:1.8em;height:1.8em;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAAB0CAQAAADAmnOnAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAWwEAAFsBAXkZiFwAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAF4klEQVR4Ae3a/a+XdR3H8ec5HM45HDmKICoVohkZsxESRRCzcZM/2JKkdGR5MrSkleA0Pd00O4u5IVuNM2yYc6XSzCExU4oUNRPCJFdMUAhsYZpUGhscOHA4N8/WZzsL6HBxvofvdV3fa3yer//gsV3vH659KHzncBsJxUYhDzOEhCKQbORs+ip2wzgM+wvj+P9i35qAGLaHGcQSgKSTrxBLABJppZpYApCspoFYApBsZjSxBCD5OxOJJQBJG1cQSwCSLpqJJQCJ3MvgCGTinuSMCJS8LZwfgZL3FtMiUPIOcU0ESl4PLRHoRPsJtREoeRsYGYGS9yrvo6RmpbLaigWSfzOdErLs6+bLUMFA0sF1+QF1cz1UNlBYK9V5AHXyWSgEkKyiIWOgGh829Ki1lLcaxjCVK7mJRSxjBY+zgRf/u9pXcMB7jhEZAg32EUP3O6hMKOP5Iq2sZQeHMZXt5KKMgOpcY+iHVnFyjeQKlrCBdsxge5ieAVC9vzLUelI8H+A7bKIHM10H81IGGuKvDf1ggDxVTKOV1zG3/Yia1ICG+ltD32MgNTKfP2HuW0VDKkCNrjfUTOm9i6XswwrZJkaVHeh0f2fodkrtfO6jAytqrzG+rEDDfVG1x1sprZEs5RBW4PZxeT+Bbrf5hPu9arfzKaU6WjiAFbseWvoF1GW/6vYGSmkyW7Dit4xB5QHq9Br6Xx2t9GAhtp6zkoHsfNp1J9wX6H+jeR4LtJc4LxGopZZyNpN/YcG2mw9nBTSPLizgOmjKAujGgvJID3ekD7QYi7nGzkvmQtpA38Vi7iJf0TedlC7QTVjMfcY2QyvSBPpUMW/PIBfbo9pls1XpAX2EdizeznStob3OJpQO0DB2YfE21q2GtnghpAm0Gou3T9tm6BGHQppA12HRVt17eboNlydNoLHsx2JtmL801OYcQmkC/QKLtQt9ydBW3wNpA30ci7Ur3WdolUMhbaBqNhf/8qQJ9Hkszs5wjaH9XkUobaAqtmFRdoGbDb3sWMgG6DIs5852knO82RaXer+P+qyb3eWeo7ZNBrRZvm1otY2QFdBjeHIb6hTne49Put12+9ObMoDdYmfy5UkF6AK6cCCr9aM2u9IddptcOYCG+FNDB5xLKCugO7G01TndFp/xgAntdYvrfdwVLnORt3q9Vx25F27DUjbGPxr6qxMgW6Cd2N+d6wLXedA+6nKbK73Lr/pJxzusvE/wZrvX0FOOgGyBxmF/dprXutYOj6nNdS6xyYnWp/dGcaGdhr5vDWQN9E1MXrUzfcA2j2qPj/l1J1uT9iPOeh8w1O7nCGUN9HzyGZ7ndo9qp0ucanU2r1xH+wdDu5wIeQDVVx0+/kd1i697RNv8thdn+Qz4Uv9p6DeOhHyApmBfq3OBu+3Nfd7nVELZAX3Nw4ZarYG8gG7GY1dlk6/Zm3/2Rk8jlB1QvT82dNAmQjkBVf8Mj957fdrefM7ZVhPKEuidvmDob06CXIGGbsX/bZDf8KAhfdbJhLIGmuZuQ084HHIGatiLvRvrRkP6qldbBXkAzbfD0N0OhryBGqrEMOd50FC7d1hPKGugBh8ydMh5hPIGGouI1d5lj6F1vptQ9kDvcKOhN5wMlQH0QcRGnzC03yZCeQDN9G1D6xwBFQI07FI8x02GdjgB8gJqttPQcmuhYoAumzvG7YZWejrkA1TrPYYO+SVCFQO0aM4bqj0uJJQH0LluSP7PkyeQU9QOmyAvoBm+Zegpz4LKA/qYB/wE5AXUe3m81zqoRKAPOYWcuvP9dxvqcD6h7IAKkaNU3eUlHLcI9EzS5YlAi62h/zUy89QCqqKUmvgHywsJlEHnsQYxAvXVIJo5gIhnPhiBju1iNmLvLn85Ah1ZPYs5jBGo72awEzEC9dVwHqQHI9DxWoAYgSLQQKteGIESu/qhCJTYtT+PQBEoAkWgCBSBkotAEehUWwSKQBEoAkWg/BeBIlAEikARKAJFoFmealu4gVLy1Gt5dkARKAL9BzujPSurTmu/AAAAAElFTkSuQmCC);margin-bottom:.4em;-webkit-background-size:100% auto;background-size:100% auto}.ath-android .ath-action-icon{width:1.4em;height:1.4em;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAANlBMVEVmZmb///9mZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZW6fJrAAAAEXRSTlMAAAYHG21ub8fLz9DR8/T4+RrZ9owAAAB3SURBVHja7dNLDoAgDATQWv4gKve/rEajJOJiWLgg6WzpSyB0aHqHiNj6nL1lovb4C+hYzkSNAT7mryQFAVOeGAj4CjwEtgrWXpD/uZKtwEJApXt+Vn0flzRhgNiFZQkOXY0aADQZCOCPlsZJ46Rx0jhp3IiN2wGDHhxtldrlwQAAAABJRU5ErkJggg==);-webkit-background-size:100% auto;background-size:100% auto}.ath-container p{margin:0;padding:0;position:relative;z-index:2147483642;text-shadow:0 .1em 0 #fff;font-size:1.1em}.ath-ios.ath-phone:after{content:'';background:#eee;position:absolute;width:2em;height:2em;bottom:-.9em;left:50%;margin-left:-1em;-webkit-transform:scaleX(.9) rotate(45deg);-ms-transform:scaleX(.9) rotate(45deg);transform:scaleX(.9) rotate(45deg);-webkit-box-shadow:.2em .2em 0 #d1d1d1;box-shadow:.2em .2em 0 #d1d1d1}.ath-ios.ath-tablet:after{content:'';background:#eee;position:absolute;width:2em;height:2em;top:-.9em;left:50%;margin-left:-1em;-webkit-transform:scaleX(.9) rotate(45deg);-ms-transform:scaleX(.9) rotate(45deg);transform:scaleX(.9) rotate(45deg);z-index:2147483641}.ath-application-icon{position:relative;padding:0;border:0;margin:0 auto .2em auto;height:6em;width:6em;z-index:2147483642}.ath-container.ath-ios .ath-application-icon{border-radius:1em;-webkit-box-shadow:0 .2em .4em rgba(0,0,0,.3),inset 0 .07em 0 rgba(255,255,255,.5);box-shadow:0 .2em .4em rgba(0,0,0,.3),inset 0 .07em 0 rgba(255,255,255,.5);margin:0 auto .4em auto}@media only screen and (orientation:landscape){.ath-container.ath-phone{width:24em}.ath-android.ath-phone{margin-left:-12em}.ath-ios.ath-phone{margin-left:-12em}.ath-ios6:after{left:39%}.ath-ios8.ath-phone{left:auto;bottom:auto;right:.4em;top:1.8em}.ath-ios8.ath-phone:after{bottom:auto;top:-.9em;left:68%;z-index:2147483641;-webkit-box-shadow:none;box-shadow:none}}.am-checkbox,.am-checkbox-inline,.am-radio,.am-radio-inline{padding-left:22px;position:relative;-webkit-transition:color .25s linear;transition:color .25s linear;font-size:14px;line-height:1.5}label.am-checkbox,label.am-radio{font-weight:400}.am-ucheck-icons{color:#999;display:block;height:20px;top:0;left:0;position:absolute;width:20px;text-align:center;line-height:21px;font-size:18px;cursor:pointer}.am-checkbox .am-icon-checked,.am-checkbox .am-icon-unchecked,.am-checkbox-inline .am-icon-checked,.am-checkbox-inline .am-icon-unchecked,.am-radio .am-icon-checked,.am-radio .am-icon-unchecked,.am-radio-inline .am-icon-checked,.am-radio-inline .am-icon-unchecked{position:absolute;left:0;top:0;display:inline-table;margin:0;background-color:transparent;-webkit-transition:color .25s linear;transition:color .25s linear}.am-checkbox .am-icon-checked:before,.am-checkbox .am-icon-unchecked:before,.am-checkbox-inline .am-icon-checked:before,.am-checkbox-inline .am-icon-unchecked:before,.am-radio .am-icon-checked:before,.am-radio .am-icon-unchecked:before,.am-radio-inline .am-icon-checked:before,.am-radio-inline .am-icon-unchecked:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.am-checkbox .am-icon-checked,.am-checkbox-inline .am-icon-checked,.am-radio .am-icon-checked,.am-radio-inline .am-icon-checked{opacity:0}.am-checkbox .am-icon-checked:before,.am-checkbox-inline .am-icon-checked:before{content:"\f046"}.am-checkbox .am-icon-unchecked:before,.am-checkbox-inline .am-icon-unchecked:before{content:"\f096"}.am-radio .am-icon-checked:before,.am-radio-inline .am-icon-checked:before{content:"\f192"}.am-radio .am-icon-unchecked:before,.am-radio-inline .am-icon-unchecked:before{content:"\f10c"}.am-ucheck-checkbox,.am-ucheck-radio{position:absolute;left:0;top:0;margin:0;padding:0;width:20px;height:20px;opacity:0;outline:0!important}.am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons{color:#0e90d2}.am-ucheck-checkbox:checked+.am-ucheck-icons,.am-ucheck-radio:checked+.am-ucheck-icons{color:#0e90d2}.am-ucheck-checkbox:checked+.am-ucheck-icons .am-icon-unchecked,.am-ucheck-radio:checked+.am-ucheck-icons .am-icon-unchecked{opacity:0}.am-ucheck-checkbox:checked+.am-ucheck-icons .am-icon-checked,.am-ucheck-radio:checked+.am-ucheck-icons .am-icon-checked{opacity:1}.am-ucheck-checkbox:disabled+.am-ucheck-icons,.am-ucheck-radio:disabled+.am-ucheck-icons{cursor:default;color:#d8d8d8}.am-ucheck-checkbox:disabled:checked+.am-ucheck-icons .am-icon-unchecked,.am-ucheck-radio:disabled:checked+.am-ucheck-icons .am-icon-unchecked{opacity:0}.am-ucheck-checkbox:disabled:checked+.am-ucheck-icons .am-icon-checked,.am-ucheck-radio:disabled:checked+.am-ucheck-icons .am-icon-checked{opacity:1;color:#d8d8d8}.am-checkbox-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-secondary .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-secondary .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons{color:#3bb4f2}.am-checkbox-inline.am-secondary .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox-inline.am-secondary .am-ucheck-radio:checked+.am-ucheck-icons,.am-checkbox.am-secondary .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox.am-secondary .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio-inline.am-secondary .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio-inline.am-secondary .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio.am-secondary .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio.am-secondary .am-ucheck-radio:checked+.am-ucheck-icons{color:#3bb4f2}.am-checkbox-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-success .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-success .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons{color:#5eb95e}.am-checkbox-inline.am-success .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox-inline.am-success .am-ucheck-radio:checked+.am-ucheck-icons,.am-checkbox.am-success .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox.am-success .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio-inline.am-success .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio-inline.am-success .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio.am-success .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio.am-success .am-ucheck-radio:checked+.am-ucheck-icons{color:#5eb95e}.am-checkbox-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-warning .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-warning .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons{color:#F37B1D}.am-checkbox-inline.am-warning .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox-inline.am-warning .am-ucheck-radio:checked+.am-ucheck-icons,.am-checkbox.am-warning .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox.am-warning .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio-inline.am-warning .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio-inline.am-warning .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio.am-warning .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio.am-warning .am-ucheck-radio:checked+.am-ucheck-icons{color:#F37B1D}.am-checkbox-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-checkbox.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio-inline.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-danger .am-ucheck-checkbox:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons,.am-radio.am-danger .am-ucheck-radio:hover:not(.am-nohover):not(:disabled)+.am-ucheck-icons{color:#dd514c}.am-checkbox-inline.am-danger .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox-inline.am-danger .am-ucheck-radio:checked+.am-ucheck-icons,.am-checkbox.am-danger .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-checkbox.am-danger .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio-inline.am-danger .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio-inline.am-danger .am-ucheck-radio:checked+.am-ucheck-icons,.am-radio.am-danger .am-ucheck-checkbox:checked+.am-ucheck-icons,.am-radio.am-danger .am-ucheck-radio:checked+.am-ucheck-icons{color:#dd514c}.am-field-error+.am-ucheck-icons{color:#dd514c}.am-field-valid+.am-ucheck-icons{color:#5eb95e}.am-selected{width:200px}.am-selected-btn{width:100%;padding-left:10px;text-align:right}.am-selected-btn.am-btn-default{background:0 0}.am-invalid .am-selected-btn{border-color:#dd514c}.am-selected-header{height:45px;background-color:#f2f2f2;border-bottom:1px solid #ddd;display:none}.am-selected-status{text-align:left;width:100%;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-selected-content{padding:10px 0}.am-selected-search{padding:0 10px 10px}.am-selected-search .am-form-field{padding:.5em}.am-selected-list{margin:0;padding:0;list-style:none;font-size:1.5rem}.am-selected-list li{position:relative;cursor:pointer;padding:5px 10px;-webkit-transition:background-color .15s;transition:background-color .15s}.am-selected-list li:hover{background-color:#f8f8f8}.am-selected-list li:hover .am-icon-check{opacity:.6}.am-selected-list li.am-checked .am-icon-check{opacity:1;color:#0e90d2}.am-selected-list li.am-disabled{opacity:.5;pointer-events:none;cursor:not-allowed}.am-selected-list .am-selected-list-header{margin-top:8px;font-size:1.3rem;color:#999;border-bottom:1px solid #e5e5e5;cursor:default}.am-selected-list .am-selected-list-header:hover{background:0 0}.am-selected-list .am-selected-list-header:first-child{margin-top:0}.am-selected-list .am-selected-text{display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;margin-right:30px}.am-selected-list .am-icon-check{position:absolute;right:8px;top:5px;color:#999;opacity:0;-webkit-transition:opacity .15s;transition:opacity .15s}.am-selected-hint{line-height:1.2;color:#dd514c}.am-selected-hint:not(:empty){margin-top:10px;border-top:1px solid #e5e5e5;padding:10px 10px 0}.am-selected-placeholder{opacity:.65}.am-fade{opacity:0;-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.am-fade.am-in{opacity:1}.am-collapse{display:none}.am-collapse.am-in{display:block}tr.am-collapse.am-in{display:table-row}tbody.am-collapse.am-in{display:table-row-group}.am-collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .3s ease;transition:height .3s ease}.am-sticky{position:fixed!important;z-index:1010;-webkit-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0}[data-am-sticky][class*=am-animation-]{-webkit-animation-duration:.2s;animation-duration:.2s}.am-dimmer-active{overflow:hidden}.am-dimmer{position:fixed;top:0;right:0;bottom:0;left:0;display:none;width:100%;height:100%;background-color:rgba(0,0,0,.6);z-index:1100;opacity:0}.am-dimmer.am-active{opacity:1}[data-am-collapse]{cursor:pointer}.am-datepicker{top:0;left:0;border-radius:0;background:#fff;-webkit-box-shadow:0 0 10px #ccc;box-shadow:0 0 10px #ccc;padding-bottom:10px;margin-top:10px;width:238px;color:#555;display:none}.am-datepicker>div{display:none}.am-datepicker table{width:100%}.am-datepicker tr.am-datepicker-header{font-size:1.6rem;color:#fff;background:#3bb4f2}.am-datepicker td,.am-datepicker th{text-align:center;font-weight:400;cursor:pointer}.am-datepicker th{height:48px}.am-datepicker td{font-size:1.4rem}.am-datepicker td.am-datepicker-day{height:34px;width:34px}.am-datepicker td.am-datepicker-day:hover{background:#F0F0F0;height:34px;width:34px}.am-datepicker td.am-datepicker-day.am-disabled{cursor:no-drop;color:#999;background:#fafafa}.am-datepicker td.am-datepicker-new,.am-datepicker td.am-datepicker-old{color:#89d7ff}.am-datepicker td.am-active,.am-datepicker td.am-active:hover{border-radius:0;color:#0084c7;background:#F0F0F0}.am-datepicker td span{display:block;width:79.33px;height:40px;line-height:40px;float:left;cursor:pointer}.am-datepicker td span:hover{background:#F0F0F0}.am-datepicker td span.am-active{color:#0084c7;background:#F0F0F0}.am-datepicker td span.am-disabled{cursor:no-drop;color:#999;background:#fafafa}.am-datepicker td span.am-datepicker-old{color:#89d7ff}.am-datepicker .am-datepicker-dow{height:40px;color:#0c80ba}.am-datepicker-caret{display:block!important;display:inline-block;width:0;height:0;vertical-align:middle;border-bottom:7px solid #3bb4f2;border-right:7px solid transparent;border-left:7px solid transparent;border-top:0 dotted;-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);position:absolute;top:-7px;left:6px}.am-datepicker-right .am-datepicker-caret{left:auto;right:7px}.am-datepicker-up .am-datepicker-caret{top:auto;bottom:-7px;display:inline-block;width:0;height:0;vertical-align:middle;border-top:7px solid #fff;border-right:7px solid transparent;border-left:7px solid transparent;border-bottom:0 dotted;-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg)}.am-datepicker-select{height:34px;line-height:34px;text-align:center;-webkit-transition:background-color .3s ease-out;transition:background-color .3s ease-out}.am-datepicker-select:hover{background:rgba(154,217,248,.5);color:#0c80ba}.am-datepicker-next,.am-datepicker-prev{width:34px;height:34px}.am-datepicker-next-icon,.am-datepicker-prev-icon{width:34px;height:34px;line-height:34px;display:inline-block;-webkit-transition:background-color .3s ease-out;transition:background-color .3s ease-out}.am-datepicker-next-icon:hover,.am-datepicker-prev-icon:hover{background:rgba(154,217,248,.5);color:#0c80ba}.am-datepicker-prev-icon:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053"}.am-datepicker-next-icon:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f054"}.am-datepicker-dropdown{position:absolute;z-index:1120}@media only screen and (max-width:640px){.am-datepicker{width:100%}.am-datepicker td span{width:33.33%}.am-datepicker-caret{display:none!important}.am-datepicker-next,.am-datepicker-prev{width:44px;height:44px}}.am-datepicker-success tr.am-datepicker-header{background:#5eb95e}.am-datepicker-success td.am-datepicker-day.am-disabled{color:#999}.am-datepicker-success td.am-datepicker-new,.am-datepicker-success td.am-datepicker-old{color:#94df94}.am-datepicker-success td.am-active,.am-datepicker-success td.am-active:hover{color:#1b961b}.am-datepicker-success td span.am-datepicker-old{color:#94df94}.am-datepicker-success td span.am-active{color:#1b961b}.am-datepicker-success .am-datepicker-caret{border-bottom-color:#5eb95e}.am-datepicker-success .am-datepicker-dow{color:#367b36}.am-datepicker-success .am-datepicker-next-icon:hover,.am-datepicker-success .am-datepicker-prev-icon:hover,.am-datepicker-success .am-datepicker-select:hover{background:rgba(165,216,165,.5);color:#367b36}.am-datepicker-danger tr.am-datepicker-header{background:#dd514c}.am-datepicker-danger td.am-datepicker-day.am-disabled{color:#999}.am-datepicker-danger td.am-datepicker-new,.am-datepicker-danger td.am-datepicker-old{color:#f59490}.am-datepicker-danger td.am-active,.am-datepicker-danger td.am-active:hover{color:#c10802}.am-datepicker-danger td span.am-datepicker-old{color:#f59490}.am-datepicker-danger td span.am-active{color:#c10802}.am-datepicker-danger .am-datepicker-caret{border-bottom-color:#dd514c}.am-datepicker-danger .am-datepicker-dow{color:#a4241f}.am-datepicker-danger .am-datepicker-next-icon:hover,.am-datepicker-danger .am-datepicker-prev-icon:hover,.am-datepicker-danger .am-datepicker-select:hover{background:rgba(237,164,162,.5);color:#a4241f}.am-datepicker-warning tr.am-datepicker-header{background:#F37B1D}.am-datepicker-warning td.am-datepicker-day.am-disabled{color:#999}.am-datepicker-warning td.am-datepicker-new,.am-datepicker-warning td.am-datepicker-old{color:#ffad6d}.am-datepicker-warning td.am-active,.am-datepicker-warning td.am-active:hover{color:#aa4b00}.am-datepicker-warning td span.am-datepicker-old{color:#ffad6d}.am-datepicker-warning td span.am-active{color:#aa4b00}.am-datepicker-warning .am-datepicker-caret{border-bottom-color:#F37B1D}.am-datepicker-warning .am-datepicker-dow{color:#a14c09}.am-datepicker-warning .am-datepicker-next-icon:hover,.am-datepicker-warning .am-datepicker-prev-icon:hover,.am-datepicker-warning .am-datepicker-select:hover{background:rgba(248,180,126,.5);color:#a14c09}.am-datepicker>div{display:block}.am-datepicker>div span.am-datepicker-hour{width:59.5px}.am-datepicker-date{display:block}.am-datepicker-date.am-input-group{display:table}.am-datepicker-time-box{padding:30px 0 30px 0}.am-datepicker-time-box strong{font-size:5.2rem;display:inline-block;height:70px;width:70px;line-height:70px;font-weight:400}.am-datepicker-time-box strong:hover{border-radius:4px;background:#ECECEC}.am-datepicker-time-box em{display:inline-block;height:70px;width:20px;line-height:70px;font-size:5.2rem;font-style:normal}.am-datepicker-toggle{text-align:center;cursor:pointer;padding:10px 0}.am-datepicker-toggle:hover{background:#f0f0f0}@media print{*,:after,:before{background:0 0!important;color:#000!important;-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" [" attr(title) "] "}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}@page{margin:.5cm}select{background:#fff!important}.am-topbar{display:none}.am-table td,.am-table th{background-color:#fff!important}.am-table{border-collapse:collapse!important}.am-table-bordered td,.am-table-bordered th{border:1px solid #ddd!important}}.am-print-block{display:none!important}@media print{.am-print-block{display:block!important}}.am-print-inline{display:none!important}@media print{.am-print-inline{display:inline!important}}.am-print-inline-block{display:none!important}@media print{.am-print-inline-block{display:inline-block!important}}@media print{.am-print-hide{display:none!important}}.lte9 #nprogress .nprogress-spinner{display:none!important}.lte8 .am-dimmer{background-color:#000;filter:alpha(opacity=60)}.lte8 .am-modal-actions{display:none}.lte8 .am-modal-actions.am-modal-active{display:block}.lte8 .am-offcanvas.am-active{background:#000}.lte8 .am-popover .am-popover-caret{border:8px solid transparent}.lte8 .am-popover-top .am-popover-caret{border-top:8px solid #333;border-bottom:none}.lte8 .am-popover-left .am-popover-caret{right:-8px;margin-top:-6px;border-left:8px solid #333;border-right:none}.lte8 .am-popover-right .am-popover-caret{left:-8px;margin-top:-6px;border-right:8px solid #333;border-left:none}.am-accordion-item{margin:0}.am-accordion-title{font-weight:400;cursor:pointer}.am-accordion-item.am-disabled .am-accordion-title{cursor:default;pointer-events:none}.am-accordion-bd{margin:0!important;padding:0!important;border:none!important}.am-accordion-content{margin-top:0;padding:.8rem 1rem 1.2rem;font-size:1.4rem}.am-accordion-default{margin:1rem;border-radius:2px;-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.1);box-shadow:0 0 0 1px rgba(0,0,0,.1)}.am-accordion-default .am-accordion-item{border-top:1px solid rgba(0,0,0,.05)}.am-accordion-default .am-accordion-item:first-child{border-top:none}.am-accordion-default .am-accordion-title{color:rgba(0,0,0,.6);-webkit-transition:background-color .2s ease-out;transition:background-color .2s ease-out;padding:.8rem 1rem}.am-accordion-default .am-accordion-title:before{content:"\f0da";display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);-webkit-transition:-webkit-transform .2s ease;transition:-webkit-transform .2s ease;transition:transform .2s ease;transition:transform .2s ease,-webkit-transform .2s ease;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);margin-right:5px}.am-accordion-default .am-accordion-title:hover{color:#0e90d2}.am-accordion-default .am-accordion-content{color:#666}.am-accordion-default .am-active .am-accordion-title{background-color:#eee;color:#0e90d2}.am-accordion-default .am-active .am-accordion-title:before{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.am-accordion-basic{margin:1rem}.am-accordion-basic .am-accordion-title{color:#333;-webkit-transition:background-color .2s ease-out;transition:background-color .2s ease-out;padding:.8rem 0 0}.am-accordion-basic .am-accordion-title:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f0da";-webkit-transition:-webkit-transform .2s ease;transition:-webkit-transform .2s ease;transition:transform .2s ease;transition:transform .2s ease,-webkit-transform .2s ease;-webkit-transform:rotate(0);-ms-transform:rotate(0);transform:rotate(0);margin-right:.5rem}.am-accordion-basic .am-accordion-content{color:#666}.am-accordion-basic .am-active .am-accordion-title{color:#0e90d2}.am-accordion-basic .am-active .am-accordion-title:before{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.am-accordion-gapped{margin:.5rem 1rem}.am-accordion-gapped .am-accordion-item{border:1px solid #dedede;border-bottom:none;margin:.5rem 0}.am-accordion-gapped .am-accordion-item.am-active{border-bottom:1px solid #dedede}.am-accordion-gapped .am-accordion-title{color:rgba(0,0,0,.6);-webkit-transition:background-color .15s ease-out;transition:background-color .15s ease-out;border-bottom:1px solid #dedede;padding:.8rem 2rem .8rem 1rem;position:relative}.am-accordion-gapped .am-accordion-title:after{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f105";-webkit-transition:-webkit-transform .2s linear;transition:-webkit-transform .2s linear;transition:transform .2s linear;transition:transform .2s linear,-webkit-transform .2s linear;position:absolute;right:10px;top:50%;margin-top:-.8rem}.am-accordion-gapped .am-accordion-title:hover{color:rgba(0,0,0,.8)}.am-accordion-gapped .am-accordion-content{color:#666}.am-accordion-gapped .am-active .am-accordion-title{background-color:#f5f5f5;color:rgba(0,0,0,.8)}.am-accordion-gapped .am-active .am-accordion-title:after{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.am-divider{height:0;margin:1.5rem auto;overflow:hidden;clear:both}.am-divider-default{border-top:1px solid #ddd}.am-divider-dotted{border-top:1px dotted #ccc}.am-divider-dashed{border-top:1px dashed #ccc}.am-figure-zoomable{position:relative;cursor:pointer}.am-figure-zoomable:after{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f00e";position:absolute;top:1rem;right:1rem;color:#999;font-size:1.6rem;-webkit-transition:all .2s;transition:all .2s;pointer-events:none}.am-figure-zoomable:hover:after{color:#eee}.am-figure-default{margin:10px}.am-figure-default img{display:block;max-width:100%;height:auto;padding:2px;border:1px solid #eee;margin:10px auto}.am-figure-default figcaption{text-align:center;font-size:1.4rem;margin-bottom:15px;color:#333}.am-footer{text-align:center;padding:1em 0;font-size:1.6rem}.am-footer .am-switch-mode-ysp{cursor:pointer}.am-footer .am-footer-text{margin-top:10px;font-size:14px}.am-footer .am-footer-text-left{text-align:left;padding-left:10px}.am-modal-footer-hd{padding-bottom:10px}.am-footer-default{background-color:#fff}.am-footer-default a{color:#555}.am-footer-default .am-footer-switch{margin-bottom:10px;font-weight:700}.am-footer-default .am-footer-ysp{color:#555;cursor:pointer}.am-footer-default .am-footer-divider{color:#ccc}.am-footer-default .am-footer-desktop{color:#0e90d2}.am-footer-default .am-footer-miscs{color:#999;font-size:13px}.am-footer-default .am-footer-miscs p{margin:5px 0}@media only screen and (min-width:641px){.am-footer-default .am-footer-miscs p{display:inline-block;margin:5px}}.am-gallery{padding:5px 5px 0 5px;list-style:none}.am-gallery h3{margin:0}[data-am-gallery*=pureview] img{cursor:pointer}.am-gallery-default>li{padding:5px}.am-gallery-default .am-gallery-item img{width:100%;height:auto}.am-gallery-default .am-gallery-title{margin-top:10px;font-weight:400;font-size:1.4rem;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;color:#555}.am-gallery-default .am-gallery-desc{color:#999;font-size:1.2rem}.am-gallery-overlay>li{padding:5px}.am-gallery-overlay .am-gallery-item{position:relative}.am-gallery-overlay .am-gallery-item img{width:100%;height:auto}.am-gallery-overlay .am-gallery-title{font-weight:400;font-size:1.4rem;color:#FFF;position:absolute;bottom:0;width:100%;background-color:rgba(0,0,0,.5);text-indent:5px;height:30px;line-height:30px;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-gallery-overlay .am-gallery-desc{display:none}.am-gallery-bordered>li{padding:5px}.am-gallery-bordered .am-gallery-item{-webkit-box-shadow:0 0 3px rgba(0,0,0,.35);box-shadow:0 0 3px rgba(0,0,0,.35);padding:5px}.am-gallery-bordered .am-gallery-item img{width:100%;height:auto}.am-gallery-bordered .am-gallery-title{margin-top:10px;font-weight:400;font-size:1.4rem;color:#555;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-gallery-bordered .am-gallery-desc{color:#999;font-size:1.2rem}.am-gallery-imgbordered>li{padding:5px}.am-gallery-imgbordered .am-gallery-item img{width:100%;height:auto;border:3px solid #FFF;-webkit-box-shadow:0 0 3px rgba(0,0,0,.35);box-shadow:0 0 3px rgba(0,0,0,.35)}.am-gallery-imgbordered .am-gallery-title{margin-top:10px;font-weight:400;font-size:1.4rem;color:#555;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-gallery-imgbordered .am-gallery-desc{color:#999;font-size:1.2rem}.am-gotop a{display:inline-block;text-decoration:none}.am-gotop-default{text-align:center;margin:10px 0}.am-gotop-default a{background-color:#0e90d2;padding:.5em 1.5em;border-radius:0;color:#fff}.am-gotop-default a img{display:none}.am-gotop-fixed{position:fixed;right:10px;bottom:10px;z-index:1010;opacity:0;width:32px;min-height:32px;overflow:hidden;border-radius:0;text-align:center}.am-gotop-fixed.am-active{opacity:.9}.am-gotop-fixed.am-active:hover{opacity:1}.am-gotop-fixed a{display:block}.am-gotop-fixed .am-gotop-title{display:none}.am-gotop-fixed .am-gotop-icon-custom{display:inline-block;max-width:30px;vertical-align:middle}.am-gotop-fixed .am-gotop-icon{width:100%;line-height:32px;background-color:#555;vertical-align:middle;color:#ddd}.am-gotop-fixed .am-gotop-icon:hover{color:#fff}.am-with-fixed-navbar .am-gotop-fixed{bottom:60px}.am-header{position:relative;width:100%;height:49px;line-height:49px;padding:0 10px}.am-header h1{margin-top:0;margin-bottom:0}.am-header .am-header-title{margin:0 30%;font-size:2rem;font-weight:400;text-align:center;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-header .am-header-title img{margin-top:12px;height:25px;vertical-align:top}.am-header .am-header-nav{position:absolute;top:0}.am-header .am-header-nav img{height:16px;width:auto;vertical-align:middle}.am-header .am-header-left{left:10px}.am-header .am-header-right{right:10px}.am-header-fixed{position:fixed;top:0;left:0;right:0;width:100%;z-index:1010}.am-with-fixed-header{padding-top:49px}.am-header-default{background-color:#0e90d2}.am-header-default .am-header-title{color:#fff}.am-header-default .am-header-title a{color:#fff}.am-header-default .am-header-icon{font-size:20px}.am-header-default .am-header-nav{color:#eee}.am-header-default .am-header-nav>a{display:inline-block;min-width:36px;text-align:center;color:#eee}.am-header-default .am-header-nav>a+a{margin-left:5px}.am-header-default .am-header-nav .am-btn{margin-top:9px;height:31px;padding:0 .5em;line-height:30px;font-size:14px;vertical-align:top}.am-header-default .am-header-nav .am-btn .am-header-icon{font-size:inherit}.am-header-default .am-header-nav .am-btn-default{color:#999}.am-header-default .am-header-nav-title,.am-header-default .am-header-nav-title+.am-header-icon{font-size:14px}.am-intro{position:relative}.am-intro img{max-width:100%}.am-intro-hd{position:relative;height:45px;line-height:45px}.am-intro-title{font-size:18px;margin:0;font-weight:700}.am-intro-more-top{position:absolute;right:10px;top:0;font-size:1.4rem}.am-intro-bd{padding-top:15px;padding-bottom:15px;font-size:1.4rem}.am-intro-bd p:last-child{margin-bottom:0}.am-intro-more-bottom{clear:both;text-align:center}.am-intro-more-bottom .am-btn{font-size:14px}.am-intro-default .am-intro-hd{background-color:#0e90d2;color:#fff;padding:0 10px}.am-intro-default .am-intro-hd a{color:#eee}.am-intro-default .am-intro-right{padding-left:0}.am-list-news-hd{padding-top:1.2rem;padding-bottom:.8rem}.am-list-news-hd a{display:block}.am-list-news-hd h2{font-size:1.6rem;float:left;margin:0;height:2rem;line-height:2rem}.am-list-news-hd h3{margin:0}.am-list-news-hd .am-list-news-more{font-size:1.3rem;height:2rem;line-height:2rem}.am-list .am-list-item-dated a{padding-right:80px;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-list .am-list-item-dated a::after{display:none}.am-list .am-list-item-desced a,.am-list .am-list-item-thumbed a{padding-right:0}.am-list-news .am-list-item-hd{margin:0}.am-list-date{position:absolute;right:5px;font-size:1.3rem;top:1.3rem}.am-list-item-desced{padding-bottom:1rem}.am-list-item-desced>a{padding:1rem 0}.am-list-item-desced .am-list-date{position:static}.am-list-item-thumbed{padding-top:1em}.am-list-news-ft{text-align:center}.am-list-news .am-titlebar{margin-left:0;margin-right:0}.am-list-news .am-titlebar~.am-list-news-bd .am-list>li:first-child{border-top:none}.am-list-news-default{margin:10px}.am-list-news-default .am-g{margin-left:auto;margin-right:auto}.am-list-news-default .am-list-item-hd{font-weight:400}.am-list-news-default .am-list-date{color:#999}.am-list-news-default .am-list>li{border-color:#dedede}.am-list-news-default .am-list .am-list-item-desced{padding-top:1rem;padding-bottom:1rem}.am-list-news-default .am-list .am-list-item-desced>a{padding:0}.am-list-news-default .am-list .am-list-item-desced .am-list-item-text{margin-top:.5rem;color:#757575}.am-list-news-default .am-list .am-list-item-text{overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-box-orient:vertical;line-height:1.3em;-webkit-line-clamp:2;max-height:2.6em}.am-list-news-default .am-list .am-list-item-thumb-top .am-list-thumb{padding:0;margin-bottom:.8rem}.am-list-news-default .am-list .am-list-item-thumb-top .am-list-main{padding:0}.am-list-news-default .am-list .am-list-item-thumb-left .am-list-thumb{padding-left:0}.am-list-news-default .am-list .am-list-item-desced .am-list-main{padding:0}.am-list-news-default .am-list .am-list-item-thumb-right .am-list-thumb{padding-right:0}.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-item-hd{clear:both;padding-bottom:.5rem}.am-list-news-default .am-list .am-list-item-thumb-bottom-left .am-list-thumb{padding-left:0}.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-item-hd{clear:both;padding-bottom:.5rem}.am-list-news-default .am-list .am-list-item-thumb-bottom-right .am-list-thumb{padding-right:0}.am-list-news-default .am-list .am-list-thumb img{width:100%;display:block}@media only screen and (max-width:640px){.am-list-news-default .am-list-item-thumb-left .am-list-thumb,.am-list-news-default .am-list-item-thumb-right .am-list-thumb{max-height:80px;overflow:hidden}.am-list-news-default .am-list-item-thumb-bottom-left .am-list-item-text,.am-list-news-default .am-list-item-thumb-bottom-right .am-list-item-text{-webkit-line-clamp:3;max-height:3.9em}.am-list-news-default .am-list-item-thumb-bottom-left .am-list-thumb,.am-list-news-default .am-list-item-thumb-bottom-right .am-list-thumb{max-height:60px;overflow:hidden}}.am-map{width:100%;height:300px}.am-map-default #bd-map{width:100%;height:100%;overflow:hidden;margin:0;font-size:14px;line-height:1.4!important}.am-map-default .BMap_bubble_title{font-weight:700}.am-map-default #BMap_mask{width:100%}.am-mechat{margin:1rem}.am-mechat .section-cbox-wap .cbox-post-wap .post-action-wap .action-function-wap .function-list-wap .list-upload-wap .upload-mutual-wap{-webkit-box-sizing:content-box;box-sizing:content-box}.am-menu{position:relative;padding:0;margin:0}.am-menu ul{padding:0;margin:0}.am-menu li{list-style:none}.am-menu a:after,.am-menu a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.am-menu-sub{z-index:1050}.am-menu-toggle{display:none;z-index:1015}.am-menu-toggle img{display:inline-block;height:16px;width:auto;vertical-align:middle}.am-menu-nav a{display:block;padding:.8rem 0;-webkit-transition:all .45s;transition:all .45s}.am-menu-default .am-menu-nav{padding-top:8px;padding-bottom:8px}.am-menu-default .am-menu-nav a{text-align:center;height:36px;line-height:36px;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;padding:0;color:#0e90d2}.am-menu-default .am-menu-nav>.am-parent>a{position:relative;-webkit-transition:.15s;transition:.15s}.am-menu-default .am-menu-nav>.am-parent>a:after{content:"\f107";margin-left:5px;-webkit-transition:.15s;transition:.15s}.am-menu-default .am-menu-nav>.am-parent>a:before{position:absolute;top:100%;margin-top:-16px;left:50%;margin-left:-12px;content:"\f0d8";display:none;color:#f1f1f1;font-size:24px}.am-menu-default .am-menu-nav>.am-parent.am-open>a{color:#095f8a}.am-menu-default .am-menu-nav>.am-parent.am-open>a:before{display:block}.am-menu-default .am-menu-nav>.am-parent.am-open>a:after{-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.am-menu-default .am-menu-sub{position:absolute;left:5px;right:5px;background-color:#f1f1f1;border-radius:0;padding-top:8px;padding-bottom:8px}.am-menu-default .am-menu-sub>li>a{color:#555}@media only screen and (min-width:641px){.am-menu-default .am-menu-nav li{width:auto;float:left;clear:none;display:inline}.am-menu-default .am-menu-nav a{padding-left:1.5rem;padding-right:.5rem}}.am-menu-dropdown1{position:relative}.am-menu-dropdown1 .am-menu-toggle{position:absolute;right:5px;top:-47px;display:block;width:44px;height:44px;line-height:44px;text-align:center;color:#fff}.am-menu-dropdown1 a{-webkit-transition:all .4s;transition:all .4s;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-menu-dropdown1 .am-menu-nav{position:absolute;left:0;right:0;z-index:1050}.am-menu-dropdown1 .am-menu-nav a{padding:.8rem}.am-menu-dropdown1 .am-menu-nav>li{width:100%}.am-menu-dropdown1 .am-menu-nav>li.am-parent>a{position:relative}.am-menu-dropdown1 .am-menu-nav>li.am-parent>a::before{content:"\f067";position:absolute;right:1rem;top:1.4rem}.am-menu-dropdown1 .am-menu-nav>li.am-parent.am-open>a{background-color:#0c80ba;border-bottom:none;color:#fff}.am-menu-dropdown1 .am-menu-nav>li.am-parent.am-open>a:before{content:"\f068"}.am-menu-dropdown1 .am-menu-nav>li.am-parent.am-open>a:after{content:"";display:inline-block;width:0;height:0;vertical-align:middle;border-top:8px solid #0c80ba;border-right:8px solid transparent;border-left:8px solid transparent;border-bottom:0 dotted;-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);position:absolute;top:100%;left:50%;margin-left:-4px}.am-menu-dropdown1 .am-menu-nav>li>a{border-bottom:1px solid #0b76ac;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.05);background-color:#0e90d2;color:#fff;height:49px;line-height:49px;padding:0;text-indent:10px}.am-menu-dropdown1 .am-menu-sub{background-color:#fff}.am-menu-dropdown1 .am-menu-sub a{color:#555;height:44px;line-height:44px;text-indent:5px;padding:0}.am-menu-dropdown1 .am-menu-sub a:before{content:"\f105";color:#aaa;font-size:16px;margin-right:5px}.am-menu-dropdown2 .am-menu-toggle{position:absolute;right:5px;top:-47px;display:block;width:44px;height:44px;line-height:44px;text-align:center;color:#fff}.am-menu-dropdown2 .am-menu-nav{position:absolute;left:0;right:0;background-color:#f5f5f5;-webkit-box-shadow:0 0 5px rgba(0,0,0,.2);box-shadow:0 0 5px rgba(0,0,0,.2);z-index:1050;padding-top:8px;padding-bottom:8px}.am-menu-dropdown2 .am-menu-nav a{height:38px;line-height:38px;padding:0;text-align:center}.am-menu-dropdown2 .am-menu-nav>li>a{color:#333}.am-menu-dropdown2 .am-menu-nav>li.am-parent>a{position:relative}.am-menu-dropdown2 .am-menu-nav>li.am-parent>a:after{content:"\f107";margin-left:5px;-webkit-transition:-webkit-transform .2s;transition:-webkit-transform .2s;transition:transform .2s;transition:transform .2s,-webkit-transform .2s}.am-menu-dropdown2 .am-menu-nav>li.am-parent.am-open>a{position:relative}.am-menu-dropdown2 .am-menu-nav>li.am-parent.am-open>a:after{color:#0e90d2;-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.am-menu-dropdown2 .am-menu-nav>li.am-parent.am-open>a:before{position:absolute;top:100%;margin-top:-16px;left:50%;margin-left:-12px;font-size:24px;content:"\f0d8";color:rgba(0,0,0,.2)}.am-menu-dropdown2 .am-menu-sub{position:absolute;left:5px;right:5px;padding:8px 0;border-radius:2px;-webkit-box-shadow:0 0 3px rgba(0,0,0,.15);box-shadow:0 0 3px rgba(0,0,0,.15);background-color:#fff;z-index:1055}.am-menu-dropdown2 .am-menu-sub a{padding:0;height:35px;color:#555;line-height:35px}@media only screen and (min-width:641px){.am-menu-dropdown2 .am-menu-toggle{display:none!important}.am-menu-dropdown2 .am-menu-nav{position:static;display:block}.am-menu-dropdown2 .am-menu-nav>li{float:none;width:auto;display:inline-block}.am-menu-dropdown2 .am-menu-nav>li a{padding-left:1.5rem;padding-right:1.5rem}.am-menu-dropdown2 .am-menu-sub{left:auto;right:auto}.am-menu-dropdown2 .am-menu-sub>li{float:none;width:auto}.am-menu-dropdown2 .am-menu-sub a{padding-left:2rem;padding-right:2rem}}.am-menu-slide1 .am-menu-toggle{position:absolute;right:5px;top:-47px;display:block;width:44px;height:44px;line-height:44px;text-align:center;color:#fff}.am-menu-slide1 .am-menu-nav{background-color:#f5f5f5;padding-top:8px;padding-bottom:8px}.am-menu-slide1 .am-menu-nav.am-in:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f0d8";font-size:24px;color:#f5f5f5;position:absolute;right:16px;top:-16px}.am-menu-slide1 .am-menu-nav a{line-height:38px;height:38px;display:block;padding:0;text-align:center}.am-menu-slide1 .am-menu-nav>li>a{color:#333;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-menu-slide1 .am-menu-nav>.am-parent>a{position:relative;-webkit-transition:.15s;transition:.15s}.am-menu-slide1 .am-menu-nav>.am-parent>a:after{content:"\f107";margin-left:5px;-webkit-transition:.15s;transition:.15s}.am-menu-slide1 .am-menu-nav>.am-parent>a:before{position:absolute;top:100%;margin-top:-16px;left:50%;margin-left:-12px;content:"\f0d8";display:none;color:#0e90d2;font-size:24px}.am-menu-slide1 .am-menu-nav>.am-parent.am-open>a{color:#0e90d2}.am-menu-slide1 .am-menu-nav>.am-parent.am-open>a:before{display:block}.am-menu-slide1 .am-menu-nav>.am-parent.am-open>a:after{-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.am-menu-slide1 .am-menu-sub{position:absolute;left:5px;right:5px;background-color:#0e90d2;border-radius:0;padding-top:8px;padding-bottom:8px}.am-menu-slide1 .am-menu-sub>li>a{color:#fff}@media only screen and (min-width:641px){.am-menu-slide1 .am-menu-toggle{display:none!important}.am-menu-slide1 .am-menu-nav{background-color:#f5f5f5;display:block}.am-menu-slide1 .am-menu-nav.am-in:before{display:none}.am-menu-slide1 .am-menu-nav li{width:auto;clear:none}.am-menu-slide1 .am-menu-nav li a{padding-left:1.5rem;padding-right:1.5rem}}.am-menu-offcanvas1 .am-menu-toggle{position:absolute;right:5px;top:-47px;display:block;width:44px;height:44px;line-height:44px;text-align:center;color:#fff}.am-menu-offcanvas1 .am-menu-nav{border-bottom:1px solid rgba(0,0,0,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.05);box-shadow:0 1px 0 rgba(255,255,255,.05)}.am-menu-offcanvas1 .am-menu-nav>li>a{height:44px;line-height:44px;text-indent:15px;padding:0;position:relative;color:#ccc;border-top:1px solid rgba(0,0,0,.3);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 1px 0 rgba(0,0,0,.5)}.am-menu-offcanvas1 .am-menu-nav>.am-open>a,.am-menu-offcanvas1 .am-menu-nav>li>a:focus,.am-menu-offcanvas1 .am-menu-nav>li>a:hover{background-color:#474747;color:#fff;outline:0}.am-menu-offcanvas1 .am-menu-nav>.am-active>a{background-color:#1a1a1a;color:#fff}.am-menu-offcanvas1 .am-menu-nav>.am-parent>a{-webkit-transition:all .3s;transition:all .3s}.am-menu-offcanvas1 .am-menu-nav>.am-parent>a:after{content:"\f104";position:absolute;right:1.5rem;top:1.3rem}.am-menu-offcanvas1 .am-menu-nav>.am-parent.am-open>a:after{content:"\f107"}.am-menu-offcanvas1 .am-menu-sub{border-top:1px solid rgba(0,0,0,.3);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.05);padding:5px 0 5px 15px;background-color:#1a1a1a;font-size:1.4rem}.am-menu-offcanvas1 .am-menu-sub a{color:#eee}.am-menu-offcanvas1 .am-menu-sub a:hover{color:#fff}.am-menu-offcanvas1 .am-nav-divider{border-top:1px solid #1a1a1a}.am-menu-offcanvas2 .am-menu-toggle{position:absolute;right:5px;top:-47px;display:block;width:44px;height:44px;line-height:44px;text-align:center;color:#fff}.am-menu-offcanvas2 .am-menu-nav{padding:10px 5px}.am-menu-offcanvas2 .am-menu-nav>li{padding:5px}.am-menu-offcanvas2 .am-menu-nav>li>a{-webkit-transition:all .3s;transition:all .3s;background-color:#404040;color:#ccc;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;border:1px solid rgba(0,0,0,.3);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.05);text-shadow:0 1px 0 rgba(0,0,0,.5);height:44px;line-height:44px;padding:0;text-align:center}.am-menu-offcanvas2 .am-menu-nav>li>a:focus,.am-menu-offcanvas2 .am-menu-nav>li>a:hover{background-color:#262626;color:#fff;outline:0}.am-menu-offcanvas2 .am-menu-nav>.am-active>a{background-color:#262626;color:#fff}.am-menu-stack .am-menu-nav{border-bottom:1px solid #dedede;-webkit-box-shadow:0 1px 0 rgba(255,255,255,.05);box-shadow:0 1px 0 rgba(255,255,255,.05)}.am-menu-stack .am-menu-nav>.am-parent>a{-webkit-transition:all .3s;transition:all .3s}.am-menu-stack .am-menu-nav>.am-parent>a:after{content:"\f105";position:absolute;right:1.5rem;top:1.3rem;-webkit-transition:all .15s;transition:all .15s}.am-menu-stack .am-menu-nav>.am-parent.am-open>a:after{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.am-menu-stack .am-menu-nav>li>a{position:relative;color:#333;background-color:#f5f5f5;border-top:1px solid #dedede;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.05);height:49px;line-height:49px;text-indent:10px;padding:0}.am-menu-stack .am-menu-nav>.am-open>a,.am-menu-stack .am-menu-nav>li>a:focus,.am-menu-stack .am-menu-nav>li>a:hover{background-color:#e5e5e5;color:#222;outline:0}.am-menu-stack .am-menu-sub{padding:0;font-size:1.4rem;border-top:1px solid #dedede}.am-menu-stack .am-menu-sub a{border-bottom:1px solid #dedede;padding-left:2rem;color:#444}.am-menu-stack .am-menu-sub a:hover{color:#333}.am-menu-stack .am-menu-sub li:last-child a{border-bottom:none}.am-menu-stack .am-menu-sub>li>a{height:44px;line-height:44px;text-indent:15px;padding:0}@media only screen and (min-width:641px){.am-menu-stack .am-menu-nav{background-color:#f5f5f5}.am-menu-stack .am-menu-nav>li{float:left;width:auto;clear:none!important;display:inline-block}.am-menu-stack .am-menu-nav>li a{padding-left:1.5rem;padding-right:1.5rem}.am-menu-stack .am-menu-nav>li.am-parent>a:after{position:static;content:"\f107"}.am-menu-stack .am-menu-nav>li.am-parent.am-open a{border-bottom:none}.am-menu-stack .am-menu-nav>li.am-parent.am-open a:after{-webkit-transform:rotateX(-180deg);transform:rotateX(-180deg)}.am-menu-stack .am-menu-nav>li.am-parent.am-open .am-menu-sub{background-color:#e5e5e5}.am-menu-stack .am-menu-sub{position:absolute;left:0;right:0;background-color:#ddd;border-top:none}.am-menu-stack .am-menu-sub li{width:auto;float:left;clear:none}}.am-navbar{position:fixed;left:0;bottom:0;width:100%;height:49px;line-height:49px;z-index:1010}.am-navbar ul{padding-left:0;margin:0;list-style:none;width:100%}.am-navbar .am-navbar-nav{padding-left:8px;padding-right:8px;text-align:center;overflow:hidden}.am-navbar .am-navbar-nav li{display:table-cell;width:1%;float:none}.am-navbar-nav{position:relative;z-index:1015}.am-navbar-nav a{display:inline-block;width:100%;height:49px;line-height:20px}.am-navbar-nav a img{display:block;vertical-align:middle;height:24px;width:24px;margin:4px auto 0}.am-navbar-nav a [class*=am-icon]{width:24px;height:24px;margin:4px auto 0;display:block;line-height:24px}.am-navbar-nav a [class*=am-icon]:before{font-size:22px;vertical-align:middle}.am-navbar-nav a .am-navbar-label{padding-top:2px;line-height:1;font-size:12px;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-navbar-more [class*=am-icon-]{-webkit-transition:.15s;transition:.15s}.am-navbar-more.am-active [class*=am-icon-]{-webkit-transform:rotateX(-180deg);transform:rotateX(-180deg)}.am-navbar-actions{position:absolute;bottom:49px;right:0;left:0;z-index:1009;opacity:0;-webkit-transition:.3s;transition:.3s;-webkit-transform:translate(0,100%);-ms-transform:translate(0,100%);transform:translate(0,100%)}.am-navbar-actions.am-active{opacity:1;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.am-navbar-actions li{line-height:42px;position:relative}.am-navbar-actions li a{display:block;width:100%;height:40px;-webkit-box-shadow:inset 0 1px rgba(220,220,220,.25);box-shadow:inset 0 1px rgba(220,220,220,.25);padding-left:20px;padding-right:36px}.am-navbar-actions li a :after{font-family:FontAwesome,sans-serif;content:"\f105";display:inline-block;position:absolute;top:0;right:20px}.am-navbar-actions li a img{vertical-align:middle;height:20px;width:20px;display:inline}#am-navbar-qrcode{width:220px;height:220px;margin-left:-110px}#am-navbar-qrcode .am-modal-bd{padding:10px}#am-navbar-qrcode canvas{display:block;width:200px;height:200px}.am-with-fixed-navbar{padding-bottom:54px}.am-navbar-default a{color:#fff}.am-navbar-default .am-navbar-nav{background-color:#0e90d2}.am-navbar-default .am-navbar-actions{background-color:#0d86c4}.am-navbar-default .am-navbar-actions a{border-bottom:1px solid #0b6fa2}.am-pagination{position:relative}.am-pagination-default{margin-left:10px;margin-right:10px;font-size:1.6rem}.am-pagination-default .am-pagination-next,.am-pagination-default .am-pagination-prev{float:none}.am-pagination-select{margin-left:10px;margin-right:10px;font-size:1.6rem}.am-pagination-select>li>a{line-height:36px;background-color:#eee;padding:0 15px;border:0;color:#555}.am-pagination-select .am-pagination-select{position:absolute;top:0;left:50%;margin-left:-35px;width:70px;height:36px;text-align:center;border-radius:0}.am-pagination-select .am-pagination-select select{display:block;border:0;line-height:36px;width:70px;height:36px;border-radius:0;color:#555;background-color:#eee;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding-left:18px}.am-paragraph p{margin:10px 0}.am-paragraph img{max-width:100%}.am-paragraph h1,.am-paragraph h2,.am-paragraph h3,.am-paragraph h4,.am-paragraph h5,.am-paragraph h6{color:#222}.am-paragraph table{max-width:none}.am-paragraph-table-container{overflow:hidden;background:#eee;max-width:none}.am-paragraph-table-container table{width:100%;max-width:none}.am-paragraph-table-container table th{background:#bce5fb;height:40px;border:1px solid #999;text-align:center}.am-paragraph-table-container table td{border:1px solid #999;text-align:center;vertical-align:middle;background:#fff}.am-paragraph-table-container table td p{text-indent:0;font-size:1.4rem}.am-paragraph-table-container table td a{font-size:1.4rem}.am-paragraph-default{margin:0 10px;color:#333;background-color:transparent}.am-paragraph-default p{font-size:1.4rem}.am-paragraph-default img{max-width:98%;display:block;margin:5px auto;border:1px solid #eee;padding:2px}.am-paragraph-default a{color:#0e90d2}.am-slider-a1{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-a1 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-a1 .am-viewport{max-height:300px}.am-slider-a1 .am-control-nav{width:100%;position:absolute;bottom:5px;text-align:center;line-height:0}.am-slider-a1 .am-control-nav li{margin:0 6px;display:inline-block}.am-slider-a1 .am-control-nav li a{width:8px;height:8px;display:block;background-color:rgba(0,0,0,.5);cursor:pointer;text-indent:-9999px;border-radius:50%;-webkit-box-shadow:inset 0 0 3px rgba(0,0,0,.3);box-shadow:inset 0 0 3px rgba(0,0,0,.3)}.am-slider-a1 .am-control-nav li a:hover{background-color:rgba(0,0,0,.7)}.am-slider-a1 .am-control-nav li a.am-active{background-color:#0e90d2;cursor:default}.am-slider-a1 .am-direction-nav,.am-slider-a1 .am-pauseplay{display:none}.am-slider-a2{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-a2 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-a2 .am-viewport{max-height:300px}.am-slider-a2 .am-control-nav{width:100%;position:absolute;bottom:5px;text-align:center;line-height:0}.am-slider-a2 .am-control-nav li{margin:0 6px;display:inline-block}.am-slider-a2 .am-control-nav li a{width:8px;height:8px;display:block;background-color:rgba(0,0,0,.5);cursor:pointer;text-indent:-9999px;-webkit-box-shadow:inset 0 0 3px rgba(0,0,0,.3);box-shadow:inset 0 0 3px rgba(0,0,0,.3)}.am-slider-a2 .am-control-nav li a:hover{background-color:rgba(0,0,0,.7)}.am-slider-a2 .am-control-nav li a.am-active{background:#0e93d7;cursor:default}.am-slider-a2 .am-direction-nav,.am-slider-a2 .am-pauseplay{display:none}.am-slider-a3{margin-bottom:20px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-a3 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-a3 .am-viewport{max-height:300px}.am-slider-a3 .am-control-nav{width:100%;position:absolute;bottom:-20px;text-align:center;height:20px;background-color:#000;padding-top:5px;line-height:0}.am-slider-a3 .am-control-nav li{margin:0 6px;display:inline-block}.am-slider-a3 .am-control-nav li a{width:8px;height:8px;display:block;background-color:rgba(0,0,0,.5);cursor:pointer;text-indent:-9999px;border-radius:50%;-webkit-box-shadow:inset 0 0 3px rgba(200,200,200,.3);box-shadow:inset 0 0 3px rgba(200,200,200,.3)}.am-slider-a3 .am-control-nav li a:hover{background-color:rgba(0,0,0,.7)}.am-slider-a3 .am-control-nav li a.am-active{background:#0e90d2;cursor:default}.am-slider-a3 .am-direction-nav,.am-slider-a3 .am-pauseplay{display:none}.am-slider-a4{margin-bottom:30px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-a4 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-a4 .am-viewport{max-height:300px}.am-slider-a4 .am-control-nav{width:100%;position:absolute;bottom:-15px;text-align:center;line-height:0}.am-slider-a4 .am-control-nav li{margin:0 6px;display:inline-block}.am-slider-a4 .am-control-nav li a{width:8px;height:8px;display:block;background-color:rgba(0,0,0,.5);cursor:pointer;text-indent:-9999px;border-radius:50%;-webkit-box-shadow:inset 0 0 3px rgba(0,0,0,.3);box-shadow:inset 0 0 3px rgba(0,0,0,.3)}.am-slider-a4 .am-control-nav li a:hover{background-color:rgba(0,0,0,.7)}.am-slider-a4 .am-control-nav li a.am-active{background-color:#0e90d2;cursor:default}.am-slider-a4 .am-direction-nav,.am-slider-a4 .am-pauseplay{display:none}.am-slider-a5{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-a5 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-a5 .am-viewport{max-height:300px}.am-slider-a5 .am-control-nav{width:100%;position:absolute;text-align:center;height:6px;display:table;bottom:0;font-size:0;line-height:0}.am-slider-a5 .am-control-nav li{display:table-cell}.am-slider-a5 .am-control-nav li a{width:100%;height:6px;display:block;background-color:rgba(0,0,0,.5);cursor:pointer;text-indent:-9999px}.am-slider-a5 .am-control-nav li a:hover{background-color:rgba(0,0,0,.7)}.am-slider-a5 .am-control-nav li a.am-active{background-color:#0e90d2;cursor:default}.am-slider-a5 .am-direction-nav,.am-slider-a5 .am-pauseplay{display:none}.am-slider-b1{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-b1 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-b1 .am-viewport{max-height:300px}.am-slider-b1 .am-direction-nav a{-webkit-box-sizing:content-box;box-sizing:content-box;display:block;width:24px;height:24px;padding:8px 0;margin:-20px 0 0;position:absolute;top:50%;z-index:10;overflow:hidden;opacity:.45;cursor:pointer;color:#fff;text-shadow:1px 1px 0 rgba(255,255,255,.3);background-color:rgba(0,0,0,.5);font-size:0;text-align:center;-webkit-transition:all .3s ease;transition:all .3s ease}.am-slider-b1 .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053";font-size:24px}.am-slider-b1 .am-direction-nav a.am-prev{left:0;padding-right:5px;border-bottom-right-radius:5px;border-top-right-radius:5px}.am-slider-b1 .am-direction-nav a.am-next{right:0;padding-left:5px;border-bottom-left-radius:5px;border-top-left-radius:5px}.am-slider-b1 .am-direction-nav a.am-next:before{content:"\f054"}.am-slider-b1 .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-b1:hover .am-prev{opacity:.7}.am-slider-b1:hover .am-prev:hover{opacity:1}.am-slider-b1:hover .am-next{opacity:.7}.am-slider-b1:hover .am-next:hover{opacity:1}.am-slider-b1 .am-control-nav,.am-slider-b1 .am-pauseplay{display:none}.am-slider-b2{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-b2 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-b2 .am-viewport{max-height:300px}.am-slider-b2 .am-direction-nav a{-webkit-box-sizing:content-box;box-sizing:content-box;display:block;width:24px;height:24px;padding:4px;margin:-16px 0 0;position:absolute;top:50%;z-index:10;overflow:hidden;opacity:.45;cursor:pointer;color:#fff;text-shadow:1px 1px 0 rgba(255,255,255,.3);background-color:rgba(0,0,0,.5);font-size:0;text-align:center;border-radius:50%;-webkit-transition:all .3s ease;transition:all .3s ease}.am-slider-b2 .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053";font-size:16px;line-height:24px}.am-slider-b2 .am-direction-nav a.am-prev{left:5px}.am-slider-b2 .am-direction-nav a.am-next{right:5px}.am-slider-b2 .am-direction-nav a.am-next:before{content:"\f054"}.am-slider-b2 .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-b2:hover .am-prev{opacity:.7}.am-slider-b2:hover .am-prev:hover{opacity:1}.am-slider-b2:hover .am-next{opacity:.7}.am-slider-b2:hover .am-next:hover{opacity:1}.am-slider-b2 .am-control-nav,.am-slider-b2 .am-pauseplay{display:none}.am-slider-b3{margin:15px 30px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-b3 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-b3 .am-viewport{max-height:300px}.am-slider-b3 .am-direction-nav a{-webkit-box-sizing:content-box;box-sizing:content-box;display:block;width:24px;height:24px;padding:4px;margin:-16px 0 0;position:absolute;top:50%;z-index:10;overflow:hidden;opacity:.45;cursor:pointer;color:#333;text-shadow:1px 1px 0 rgba(255,255,255,.3);font-size:0;-webkit-transition:all .3s ease;transition:all .3s ease}.am-slider-b3 .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053";font-size:24px}.am-slider-b3 .am-direction-nav a.am-prev{left:-25px}.am-slider-b3 .am-direction-nav a.am-next{right:-25px;text-align:right}.am-slider-b3 .am-direction-nav a.am-next:before{content:"\f054"}.am-slider-b3 .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-b3:hover .am-prev{opacity:.7}.am-slider-b3:hover .am-prev:hover{opacity:1}.am-slider-b3:hover .am-next{opacity:.7}.am-slider-b3:hover .am-next:hover{opacity:1}.am-slider-b3 .am-control-nav,.am-slider-b3 .am-pauseplay{display:none}.am-slider-b4{margin:15px 20px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-b4 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-b4 .am-viewport{max-height:300px}.am-slider-b4 .am-direction-nav a{position:absolute;top:50%;z-index:10;display:block;-webkit-box-sizing:content-box;box-sizing:content-box;width:24px;height:24px;margin:-16px 0 0;padding:4px;overflow:hidden;opacity:.45;background-color:rgba(0,0,0,.8);cursor:pointer;text-shadow:1px 1px 0 rgba(255,255,255,.3);font-size:0;border-radius:50%;text-align:center;color:#fff;-webkit-transition:all .3s ease;transition:all .3s ease}.am-slider-b4 .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053";font-size:20px;line-height:24px}.am-slider-b4 .am-direction-nav a.am-prev{left:-15px}.am-slider-b4 .am-direction-nav a.am-next{right:-15px}.am-slider-b4 .am-direction-nav a.am-next:before{content:"\f054"}.am-slider-b4 .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-b4:hover .am-prev{opacity:.7}.am-slider-b4:hover .am-prev:hover{opacity:.9}.am-slider-b4:hover .am-next{opacity:.7}.am-slider-b4:hover .am-next:hover{opacity:.9}.am-slider-b4 .am-control-nav,.am-slider-b4 .am-pauseplay{display:none}.am-slider-c1{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-c1 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-c1 .am-viewport{max-height:300px}.am-slider-c1 .am-control-nav{position:absolute;bottom:0;display:table;width:100%;height:6px;font-size:0;line-height:0;text-align:center}.am-slider-c1 .am-control-nav li{display:table-cell;width:1%}.am-slider-c1 .am-control-nav li a{width:100%;height:6px;display:block;background-color:rgba(0,0,0,.7);cursor:pointer;text-indent:-9999px}.am-slider-c1 .am-control-nav li a:hover{background:rgba(0,0,0,.8)}.am-slider-c1 .am-control-nav li a.am-active{background-color:#0e90d2;cursor:default}.am-slider-c1 .am-slider-desc{background-color:rgba(0,0,0,.6);position:absolute;bottom:6px;padding:8px;width:100%;color:#fff;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-c1 .am-direction-nav,.am-slider-c1 .am-pauseplay{display:none}.am-slider-c2{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-c2 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-c2 .am-viewport{max-height:300px}.am-slider-c2 .am-control-nav{position:absolute;bottom:15px;right:0;height:6px;text-align:center;font-size:0;line-height:0}.am-slider-c2 .am-control-nav li{display:inline-block;margin-right:6px}.am-slider-c2 .am-control-nav li a{width:6px;height:6px;display:block;background-color:rgba(255,255,255,.4);cursor:pointer;text-indent:-9999px}.am-slider-c2 .am-control-nav li a:hover{background:rgba(230,230,230,.4)}.am-slider-c2 .am-control-nav li a.am-active{background-color:#0e90d2;cursor:default}.am-slider-c2 .am-slider-desc{background-color:rgba(0,0,0,.6);position:absolute;bottom:0;padding:8px 60px 8px 8px;width:100%;color:#fff;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-c2 .am-direction-nav,.am-slider-c2 .am-pauseplay{display:none}.am-slider-c3{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-c3 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-c3 .am-viewport{max-height:300px}.am-slider-c3 .am-slider-desc{background-color:rgba(0,0,0,.6);position:absolute;bottom:10px;right:60px;height:30px;left:0;padding-right:5px;color:#fff;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-c3 .am-slider-counter{margin-right:5px;display:inline-block;height:30px;background-color:#0e90d2;width:40px;text-align:center;line-height:30px;color:#eee;font-size:1rem}.am-slider-c3 .am-slider-counter .am-active{font-size:1.8rem;font-weight:700;color:#fff}.am-slider-c3 .am-direction-nav a{-webkit-box-sizing:content-box;box-sizing:content-box;display:block;width:24px;height:24px;padding:4px 0;margin:-16px 0 0;position:absolute;top:50%;z-index:10;overflow:hidden;opacity:.45;cursor:pointer;color:#fff;text-shadow:1px 1px 0 rgba(255,255,255,.3);background-color:rgba(0,0,0,.5);font-size:0;text-align:center;-webkit-transition:all .3s ease;transition:all .3s ease}.am-slider-c3 .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053";font-size:16px;line-height:24px}.am-slider-c3 .am-direction-nav a.am-prev{left:0;padding-right:5px}.am-slider-c3 .am-direction-nav a.am-next{right:0;padding-left:5px}.am-slider-c3 .am-direction-nav a.am-next:before{content:"\f054"}.am-slider-c3 .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-c3:hover .am-prev{opacity:.7}.am-slider-c3:hover .am-prev:hover{opacity:1}.am-slider-c3:hover .am-next{opacity:.7}.am-slider-c3:hover .am-next:hover{opacity:1}.am-slider-c3 .am-control-nav,.am-slider-c3 .am-pauseplay{display:none}.am-slider-c4{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-c4 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-c4 .am-viewport{max-height:300px}.am-slider-c4 .am-slider-desc{width:100%;background-color:rgba(0,0,0,.6);position:absolute;bottom:0;right:0;left:0;padding:8px 40px;color:#fff;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-c4 .am-direction-nav a{-webkit-box-sizing:content-box;box-sizing:content-box;display:block;width:24px;height:24px;padding:4px 0;margin:0;position:absolute;bottom:4px;z-index:10;overflow:hidden;opacity:.45;cursor:pointer;text-shadow:1px 1px 0 rgba(255,255,255,.3);font-size:0;text-align:center;color:rgba(0,0,0,.7);-webkit-transition:all .3s ease;transition:all .3s ease}.am-slider-c4 .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053";font-size:24px}.am-slider-c4 .am-direction-nav a.am-prev{left:0;padding-right:5px}.am-slider-c4 .am-direction-nav a.am-next{right:0;padding-left:5px}.am-slider-c4 .am-direction-nav a.am-next:before{content:"\f054"}.am-slider-c4 .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-c4:hover .am-prev{opacity:.7}.am-slider-c4:hover .am-prev:hover{opacity:1}.am-slider-c4:hover .am-next{opacity:.7}.am-slider-c4:hover .am-next:hover{opacity:1}.am-slider-c4 .am-control-nav,.am-slider-c4 .am-pauseplay{display:none}.am-slider-d1{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-d1 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-d1 .am-viewport{max-height:300px}.am-slider-d1 .am-slider-desc{padding:8px 35px;width:100%;color:#fff;background-color:#0e90d2}.am-slider-d1 .am-slider-title{font-weight:400;margin-bottom:2px;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-d1 .am-slider-more{color:#eee;font-size:1.3rem}.am-slider-d1 .am-direction-nav a{-webkit-box-sizing:content-box;box-sizing:content-box;display:block;width:24px;height:24px;margin:0;position:absolute;bottom:18px;z-index:10;overflow:hidden;opacity:.45;cursor:pointer;text-shadow:1px 1px 0 rgba(255,255,255,.3);font-size:0;text-align:center;border:1px solid rgba(255,255,255,.9);color:rgba(255,255,255,.9);border-radius:50%;-webkit-transition:all 3s ease;transition:all 3s ease}.am-slider-d1 .am-direction-nav a:before{display:inline-block;font:normal normal normal 1.6rem/1 FontAwesome,sans-serif;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);content:"\f053";font-size:16px;line-height:24px}.am-slider-d1 .am-direction-nav a.am-prev{left:5px}.am-slider-d1 .am-direction-nav a.am-next{right:5px}.am-slider-d1 .am-direction-nav a.am-next:before{content:"\f054"}.am-slider-d1 .am-direction-nav .am-disabled{opacity:0!important;cursor:default}.am-slider-d1:hover .am-prev{opacity:.7}.am-slider-d1:hover .am-prev:hover{opacity:1}.am-slider-d1:hover .am-next{opacity:.7}.am-slider-d1:hover .am-next:hover{opacity:1}.am-slider-d1 .am-control-nav,.am-slider-d1 .am-pauseplay{display:none}.am-slider-d2{margin-bottom:20px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-d2 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-d2 .am-viewport{max-height:300px}.am-slider-d2 .am-slider-desc{position:absolute;left:10px;bottom:20px;right:50px;color:#fff}.am-slider-d2 .am-slider-content{background-color:rgba(0,0,0,.7);padding:10px 6px;margin-bottom:10px}.am-slider-d2 .am-slider-content p{margin:0;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-size:1.4rem}.am-slider-d2 .am-slider-title{font-weight:400;margin-bottom:5px;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-d2 .am-slider-more{color:#eee;font-size:1.3rem;background-color:#0e90d2;padding:2px 10px}.am-slider-d2 .am-control-nav{width:100%;position:absolute;bottom:-15px;text-align:center}.am-slider-d2 .am-control-nav li{margin:0 6px;display:inline-block}.am-slider-d2 .am-control-nav li a{width:8px;height:8px;display:block;background-color:rgba(0,0,0,.5);cursor:pointer;text-indent:-9999px;border-radius:50%;font-size:0;line-height:0;-webkit-box-shadow:inset 0 0 3px rgba(0,0,0,.3);box-shadow:inset 0 0 3px rgba(0,0,0,.3)}.am-slider-d2 .am-control-nav li a:hover{background:rgba(0,0,0,.5)}.am-slider-d2 .am-control-nav li a.am-active{background:#0e90d2;cursor:default}.am-slider-d2 .am-direction-nav,.am-slider-d2 .am-pauseplay{display:none}.am-slider-d3{margin-bottom:10px;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.2);box-shadow:0 1px 4px rgba(0,0,0,.2)}.am-slider-d3 .am-viewport{max-height:2000px;-webkit-transition:all 1s ease;transition:all 1s ease}.loading .am-slider-d3 .am-viewport{max-height:300px}.am-slider-d3 .am-slider-desc{position:absolute;bottom:0;color:#fff;width:100%;background-color:rgba(0,0,0,.7);padding:8px 5px}.am-slider-d3 .am-slider-desc p{margin:0;font-size:1.3rem;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-d3 .am-slider-title{font-weight:400;margin-bottom:5px;display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-slider-d3 .am-control-thumbs{position:static;overflow:hidden}.am-slider-d3 .am-control-thumbs li{padding:12px 4px 4px;position:relative}.am-slider-d3 .am-control-thumbs img{width:100%;display:block;opacity:.85;cursor:pointer}.am-slider-d3 .am-control-thumbs img:hover{opacity:1}.am-slider-d3 .am-control-thumbs .am-active{opacity:1;cursor:default}.am-slider-d3 .am-control-thumbs .am-active+i{position:absolute;top:0;left:50%;content:"";display:inline-block;width:0;height:0;vertical-align:middle;border-top:8px solid rgba(0,0,0,.7);border-right:8px solid transparent;border-left:8px solid transparent;border-bottom:0 dotted;-webkit-transform:rotate(360deg);-ms-transform:rotate(360deg);transform:rotate(360deg);margin-left:-4px;-webkit-transition:all .2s;transition:all .2s}.am-slider-d3 .am-direction-nav,.am-slider-d3 .am-pauseplay{display:none}.am-slider-d3 .am-control-thumbs{display:table}.am-slider-d3 .am-control-thumbs li{display:table-cell;width:1%}[data-am-widget=tabs]{margin:10px}[data-am-widget=tabs] .am-tabs-nav{width:100%;padding:0;margin:0;list-style:none;text-align:center;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}[data-am-widget=tabs] .am-tabs-nav li{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}[data-am-widget=tabs] .am-tabs-nav a{display:block;word-wrap:normal;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.am-tabs-default .am-tabs-nav{line-height:40px;background-color:#eee}.am-tabs-default .am-tabs-nav a{color:#222;line-height:42px}.am-tabs-default .am-tabs-nav>.am-active a{background-color:#0e90d2;color:#fff}.am-tabs-d2 .am-tabs-nav{background-color:#eee}.am-tabs-d2 .am-tabs-nav li{height:42px}.am-tabs-d2 .am-tabs-nav a{color:#222;line-height:42px}.am-tabs-d2 .am-tabs-nav>.am-active{position:relative;background-color:#fcfcfc;border-bottom:2px solid #0e90d2}.am-tabs-d2 .am-tabs-nav>.am-active a{line-height:40px;color:#0e90d2}.am-tabs-d2 .am-tabs-nav>.am-active:after{position:absolute;width:0;height:0;bottom:0;left:50%;margin-left:-5px;border:6px rgba(0,0,0,0) solid;content:"";z-index:1;border-bottom-color:#0e90d2}.am-titlebar{margin-top:20px;height:45px;font-size:100%}.am-titlebar h2{margin-top:0;margin-bottom:0;font-size:1.6rem}.am-titlebar .am-titlebar-title img{height:24px;width:auto}.am-titlebar-default{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-left:10px;margin-right:10px;background-color:transparent;border-bottom:1px solid #dedede;line-height:44px}.am-titlebar-default a{color:#0e90d2}.am-titlebar-default .am-titlebar-title{position:relative;padding-left:12px;color:#0e90d2;font-size:1.8rem;text-align:left;font-weight:700}.am-titlebar-default .am-titlebar-title:before{content:"";position:absolute;left:2px;top:8px;bottom:8px;border-left:3px solid #0e90d2}.am-titlebar-default .am-titlebar-nav{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;text-align:right}.am-titlebar-default .am-titlebar-nav a{margin-right:10px}.am-titlebar-default .am-titlebar-nav a:last-child{margin-right:5px}.am-titlebar-multi{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;background-color:#f5f5f5;border-top:2px solid #3bb4f2;border-bottom:1px solid #e8e8e8}.am-titlebar-multi a{color:#0e90d2}.am-titlebar-multi .am-titlebar-title{padding-left:10px;color:#0e90d2;font-size:1.8rem;text-align:left;font-weight:700;line-height:42px}.am-titlebar-multi .am-titlebar-nav{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;text-align:right;line-height:42px}.am-titlebar-multi .am-titlebar-nav a{margin-right:10px}.am-titlebar-cols{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;padding-left:10px;background-color:#f5f5f5;color:#555;font-size:18px;border-top:2px solid #e1e1e1;line-height:41px}.am-titlebar-cols a{color:#555}.am-titlebar-cols .am-titlebar-title{color:#0e90d2;margin-right:15px;border-bottom:2px solid #0e90d2;font-weight:700}.am-titlebar-cols .am-titlebar-title a{color:#0e90d2}.am-titlebar-cols .am-titlebar-nav{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.am-titlebar-cols .am-titlebar-nav a{display:inline-block;margin-right:15px;line-height:41px;border-bottom:2px solid transparent}.am-titlebar-cols .am-titlebar-nav a:hover{color:#3c3c3c;border-bottom-color:#0e90d2}.am-titlebar-cols .am-titlebar-nav a:last-child{margin-right:10px}.am-wechatpay .am-wechatpay-btn{margin-top:1rem;margin-bottom:1rem}
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/assets/css/app.css b/Day61-65/code/project_of_tornado/assets/css/app.css
deleted file mode 100644
index 8b52e27..0000000
--- a/Day61-65/code/project_of_tornado/assets/css/app.css
+++ /dev/null
@@ -1,1912 +0,0 @@
-ul,
-li {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-header {
- z-index: 1200;
- position: relative;
-}
-.tpl-header-logo {
- width: 240px;
- height: 57px;
- display: table;
- text-align: center;
- position: relative;
- z-index: 1300;
-}
-.tpl-header-logo a {
- display: table-cell;
- vertical-align: middle;
-}
-.tpl-header-logo img {
- width: 170px;
-}
-.tpl-header-fluid {
- margin-left: 240px;
- height: 56px;
- padding-left: 20px;
- padding-right: 20px;
-}
-.tpl-header-switch-button {
- margin-top: 0px;
- margin-bottom: 0px;
- float: left;
- color: #cfcfcf;
- margin-left: -20px;
- margin-right: 0;
- border: 0;
- border-radius: 0;
- padding: 0px 22px;
- font-size: 22px;
- line-height: 55px;
-}
-.tpl-header-switch-button:hover {
- outline: none;
-}
-.tpl-header-search-form {
- height: 54px;
- line-height: 52px;
- margin-left: 10px;
-}
-.tpl-header-search-box,
-.tpl-header-search-btn {
- transition: all 0.4s ease-in-out;
- color: #848c90;
- background: none;
- border: none;
- outline: none;
-}
-.tpl-header-search-box {
- font-size: 14px;
-}
-.tpl-header-search-box:hover,
-.tpl-header-search-box:active {
- color: #fff;
-}
-.tpl-header-search-btn {
- font-size: 15px;
-}
-.tpl-header-search-btn:hover,
-.tpl-header-search-btn:active {
- color: #fff;
-}
-.tpl-header-navbar {
- color: #fff;
-}
-.tpl-header-navbar li {
- float: left;
-}
-.tpl-header-navbar a {
- line-height: 56px;
- display: block;
- padding: 0 16px;
- position: relative;
-}
-.tpl-header-navbar a .item-feed-badge {
- position: absolute;
- top: 9px;
- left: 25px;
-}
-ul.tpl-dropdown-content {
- padding: 10px;
- margin-top: 0;
- width: 300px;
- background-color: #2f3638;
- border: 1px solid #525e62;
- border-radius: 0;
-}
-ul.tpl-dropdown-content li {
- float: none;
-}
-ul.tpl-dropdown-content:before,
-ul.tpl-dropdown-content:after {
- display: none;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-title {
- font-size: 12px;
- float: left;
- color: rgba(255, 255, 255, 0.7);
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-time {
- float: right;
- text-align: right;
- color: rgba(255, 255, 255, 0.7);
- font-size: 11px;
- width: 50px;
- margin-left: 10px;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications:last-child .tpl-dropdown-menu-notifications-item {
- text-align: center;
- border: none;
- font-size: 12px;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications:last-child .tpl-dropdown-menu-notifications-item i {
- margin-left: -6px;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages:last-child .tpl-dropdown-menu-messages-item {
- text-align: center;
- border: none;
- font-size: 12px;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages:last-child .tpl-dropdown-menu-messages-item i {
- margin-left: -6px;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item {
- padding: 12px;
- color: #fff;
- line-height: 20px;
- border-bottom: 1px solid rgba(255, 255, 255, 0.15);
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item:hover,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item:hover,
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item:focus,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item:focus {
- background-color: #465154;
- color: #fff;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item .menu-messages-ico,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .menu-messages-ico {
- line-height: initial;
- float: left;
- width: 35px;
- height: 35px;
- border-radius: 50%;
- margin-right: 10px;
- margin-top: 6px;
- overflow: hidden;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item .menu-messages-ico img,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .menu-messages-ico img {
- width: 100%;
- height: auto;
- vertical-align: middle;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item .menu-messages-time,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .menu-messages-time {
- float: right;
- text-align: right;
- color: rgba(255, 255, 255, 0.7);
- font-size: 11px;
- width: 40px;
- margin-left: 10px;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item .menu-messages-content,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .menu-messages-content {
- display: block;
- font-size: 13px;
- margin-left: 45px;
- margin-right: 50px;
-}
-ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item .menu-messages-content .menu-messages-content-time,
-ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .menu-messages-content .menu-messages-content-time {
- margin-top: 3px;
- color: rgba(255, 255, 255, 0.7);
- font-size: 11px;
-}
-.am-dimmer {
- z-index: 1200;
-}
-.am-modal {
- z-index: 1300;
-}
-.am-datepicker-dropdown {
- z-index: 1400;
-}
-.tpl-skiner {
- transition: all 0.4s ease-in-out;
- position: fixed;
- z-index: 10000;
- right: -130px;
- top: 65px;
-}
-.tpl-skiner.active {
- right: 0px;
-}
-.tpl-skiner-content {
- background: rgba(0, 0, 0, 0.7);
- width: 130px;
- padding: 15px;
- border-radius: 4px 0 0 4px;
- overflow: hidden;
-}
-.fc-content .am-icon-close {
- position: absolute;
- right: 0;
- top: 0px;
-}
-.tpl-skiner-toggle {
- position: absolute;
- top: 5px;
- left: -40px;
- width: 40px;
- color: #969a9b;
- font-size: 20px;
- height: 40px;
- line-height: 40px;
- text-align: center;
- background: rgba(0, 0, 0, 0.7);
- cursor: pointer;
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
-}
-.tpl-skiner-content-title {
- margin: 0;
- margin-bottom: 4px;
- padding-bottom: 4px;
- font-size: 16px;
- text-transform: uppercase;
- color: #fff;
- border-bottom: 1px solid rgba(255, 255, 255, 0.3);
-}
-.tpl-skiner-content-bar {
- padding-top: 10px;
-}
-.tpl-skiner-content-bar .skiner-color {
- transition: all 0.4s ease-in-out;
- float: left;
- width: 25px;
- height: 25px;
- margin-right: 10px;
- cursor: pointer;
-}
-.tpl-skiner-content-bar .skiner-white {
- background: #fff;
- border: 2px solid #eee;
-}
-.tpl-skiner-content-bar .skiner-black {
- background: #000;
- border: 2px solid #222;
-}
-.sub-active {
- color: #fff!important;
-}
-.left-sidebar {
- transition: all 0.4s ease-in-out;
- width: 240px;
- min-height: 100%;
- padding-top: 57px;
- position: absolute;
- z-index: 1104;
- top: 0;
- left: 0px;
-}
-.left-sidebar.xs-active {
- left: 0px;
-}
-.left-sidebar.active {
- left: -240px;
-}
-.tpl-sidebar-user-panel {
- padding: 22px;
- padding-top: 28px;
-}
-.tpl-user-panel-profile-picture {
- border-radius: 50%;
- width: 82px;
- height: 82px;
- margin-bottom: 10px;
- overflow: hidden;
-}
-.tpl-user-panel-profile-picture img {
- width: auto;
- height: 82px;
- vertical-align: middle;
-}
-.tpl-user-panel-status-icon {
- margin-right: 2px;
-}
-.user-panel-logged-in-text {
- display: block;
- color: #cfcfcf;
- font-size: 14px;
-}
-.tpl-user-panel-action-link {
- color: #6d787c;
- font-size: 12px;
-}
-.tpl-user-panel-action-link:hover {
- color: #a2aaad;
-}
-.sidebar-nav {
- list-style-type: none;
- padding: 0;
- margin: 0;
-}
-.sidebar-nav-sub {
- display: none;
-}
-.sidebar-nav-sub .sidebar-nav-link {
- font-size: 12px;
- padding-left: 30px;
-}
-.sidebar-nav-sub .sidebar-nav-link a {
- font-size: 12px;
- padding-left: 0;
-}
-.sidebar-nav-sub .sidebar-nav-link-logo {
- margin-right: 8px;
- width: 20px;
- font-size: 16px;
-}
-.sidebar-nav-sub-ico-rotate {
- -webkit-transform: rotate(180deg);
- transform: rotate(180deg);
- -webkit-transition: all 300ms;
- transition: all 300ms;
-}
-.sidebar-nav-link-logo-ico {
- margin-top: 5px;
-}
-.sidebar-nav-heading {
- padding: 24px 17px;
- font-size: 15px;
- font-weight: 500;
-}
-.sidebar-nav-heading-info {
- font-size: 12px;
- color: #868E8E;
- padding-left: 10px;
-}
-.sidebar-nav-link-logo {
- margin-right: 8px;
- width: 20px;
- font-size: 16px;
-}
-.sidebar-nav-link {
- color: #fff;
-}
-.sidebar-nav-link a {
- display: block;
- color: #868E8E;
- padding: 10px 17px;
- border-left: #282d2f 3px solid;
- font-size: 14px;
- cursor: pointer;
-}
-.sidebar-nav-link a.active {
- cursor: pointer;
- border-left: #1CA2CE 3px solid;
- color: #fff;
-}
-.sidebar-nav-link a:hover {
- color: #fff;
-}
-.tpl-content-wrapper {
- transition: all 0.4s ease-in-out;
- position: relative;
- margin-left: 240px;
- z-index: 1101;
- min-height: 922px;
- border-bottom-left-radius: 3px;
-}
-.tpl-content-wrapper.xs-active {
- margin-left: 240px;
-}
-.tpl-content-wrapper.active {
- margin-left: 0;
-}
-.page-header {
- background: #424b4f;
- margin-top: 0;
- margin-bottom: 0;
- padding: 40px 0;
- border-bottom: 0;
-}
-.container-fluid {
- margin-top: 0;
- margin-bottom: 0;
- padding: 40px 0;
- border-bottom: 0;
- padding-left: 20px;
- padding-right: 20px;
-}
-.row {
- margin-right: -10px;
- margin-left: -10px;
-}
-.page-header-description {
- margin-top: 4px;
- margin-bottom: 0;
- font-size: 14px;
- color: #e6e6e6;
-}
-.page-header-heading {
- font-size: 20px;
- font-weight: 400;
-}
-.page-header-heading .page-header-heading-ico {
- font-size: 28px;
- position: relative;
- top: 3px;
-}
-.page-header-heading small {
- font-weight: normal;
- line-height: 1;
- color: #B3B3B3;
-}
-.page-header-button {
- transition: all 0.4s ease-in-out;
- opacity: 0.3;
- float: right;
- outline: none;
- border: 1px solid #fff;
- padding: 16px 36px;
- font-size: 23px;
- line-height: 23px;
- border-radius: 0;
- padding-top: 14px;
- color: #fff;
- background-color: rgba(0, 0, 0, 0);
- font-weight: 500;
-}
-.page-header-button:hover {
- background-color: #ffffff;
- color: #333;
- opacity: 1;
-}
-.widget {
- width: 100%;
- min-height: 148px;
- margin-bottom: 20px;
- border-radius: 0;
- position: relative;
-}
-.widget-head {
- width: 100%;
- padding: 15px;
-}
-.widget-title {
- font-size: 14px;
-}
-.widget-fluctuation-period-text {
- display: inline-block;
- font-size: 16px;
- line-height: 20px;
- margin-bottom: 9px;
-}
-.widget-body {
- padding: 13px 15px;
- width: 100%;
-}
-.row-content {
- padding: 20px;
-}
-.widget-fluctuation-description-text {
- margin-top: 4px;
- display: block;
- font-size: 12px;
- line-height: 13px;
-}
-.widget-fluctuation-description-amount {
- display: block;
- font-size: 20px;
- line-height: 22px;
-}
-.widget-statistic-header {
- position: relative;
- z-index: 35;
- display: block;
- font-size: 14px;
- text-transform: uppercase;
- margin-bottom: 8px;
-}
-.widget-body-md {
- height: 200px;
-}
-.widget-body-lg {
- min-height: 330px;
-}
-.widget-margin-bottom-lg {
- margin-bottom: 20px;
-}
-.tpl-table-black-operation a {
- display: inline-block;
- padding: 5px 6px;
- font-size: 12px;
- line-height: 12px;
-}
-.tpl-switch input[type="checkbox"] {
- position: absolute;
- opacity: 0;
- width: 50px;
- height: 20px;
-}
-.tpl-switch input[type="checkbox"].ios-switch + div {
- vertical-align: middle;
- width: 40px;
- height: 20px;
- border-radius: 999px;
- background-color: rgba(0, 0, 0, 0.1);
- -webkit-transition-duration: .4s;
- -webkit-transition-property: background-color, box-shadow;
- margin-top: 6px;
-}
-.tpl-switch input[type="checkbox"].ios-switch:checked + div {
- width: 40px;
- background-position: 0 0;
- background-color: #36c6d3;
-}
-.tpl-switch input[type="checkbox"].tinyswitch.ios-switch + div {
- width: 34px;
- height: 18px;
-}
-.tpl-switch input[type="checkbox"].bigswitch.ios-switch + div {
- width: 50px;
- height: 25px;
-}
-.tpl-switch input[type="checkbox"].green.ios-switch:checked + div {
- background-color: #00e359;
- border: 1px solid #00a23f;
- box-shadow: inset 0 0 0 10px #00e359;
-}
-.tpl-switch input[type="checkbox"].ios-switch + div > div {
- float: left;
- width: 18px;
- height: 18px;
- border-radius: inherit;
- background: #ffffff;
- -webkit-transition-timing-function: cubic-bezier(0.54, 1.85, 0.5, 1);
- -webkit-transition-duration: 0.4s;
- -webkit-transition-property: transform, background-color, box-shadow;
- -moz-transition-timing-function: cubic-bezier(0.54, 1.85, 0.5, 1);
- -moz-transition-duration: 0.4s;
- -moz-transition-property: transform, background-color;
- pointer-events: none;
- margin-top: 1px;
- margin-left: 1px;
-}
-.tpl-switch input[type="checkbox"].ios-switch:checked + div > div {
- -webkit-transform: translate3d(20px, 0, 0);
- -moz-transform: translate3d(20px, 0, 0);
- background-color: #ffffff;
-}
-.tpl-switch input[type="checkbox"].tinyswitch.ios-switch + div > div {
- width: 16px;
- height: 16px;
- margin-top: 1px;
-}
-.tpl-switch input[type="checkbox"].tinyswitch.ios-switch:checked + div > div {
- -webkit-transform: translate3d(16px, 0, 0);
- -moz-transform: translate3d(16px, 0, 0);
- box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3), 0px 0px 0 1px #0850ac;
-}
-.tpl-switch input[type="checkbox"].bigswitch.ios-switch + div > div {
- width: 23px;
- height: 23px;
- margin-top: 1px;
-}
-.tpl-switch input[type="checkbox"].bigswitch.ios-switch:checked + div > div {
- -webkit-transform: translate3d(25px, 0, 0);
- -moz-transform: translate3d(16px, 0, 0);
-}
-.tpl-switch input[type="checkbox"].green.ios-switch:checked + div > div {
- box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3), 0 0 0 1px #00a23f;
-}
-.tpl-page-state {
- width: 100%;
-}
-.tpl-page-state-title {
- font-size: 40px;
- font-weight: bold;
-}
-.tpl-page-state-content {
- padding: 10px 0;
-}
-.tpl-login {
- width: 100%;
-}
-.tpl-login-logo {
- max-width: 159px;
- height: 205px;
- margin: 0 auto;
- margin-bottom: 20px;
-}
-.tpl-login-title {
- width: 100%;
- font-size: 24px;
-}
-.tpl-login-content {
- width: 300px;
- margin: 12% auto 0;
-}
-.tpl-login-remember-me {
- color: #B3B3B3;
- font-size: 14px;
-}
-.tpl-login-remember-me label {
- position: relative;
- top: -2px;
-}
-.tpl-login-content-info {
- color: #B3B3B3;
- font-size: 14px;
-}
-.cl-p {
- padding: 0!important;
-}
-.tpl-table-line-img {
- max-width: 100px;
- padding: 2px;
-}
-.tpl-table-list-select {
- text-align: right;
-}
-.fc-button-group,
-.fc button {
- display: block;
-}
-.theme-white {
- background: #e9ecf3;
-}
-.theme-white .sidebar-nav-sub .sidebar-nav-link-logo {
- margin-left: 10px;
-}
-.theme-white .tpl-header-search-box:hover,
-.theme-white .tpl-header-search-box:active .tpl-error-title {
- color: #848c90;
-}
-.theme-white .tpl-error-title-info {
- line-height: 30px;
- font-size: 21px;
- margin-top: 20px;
- text-align: center;
- color: #dce2ec;
-}
-.theme-white .tpl-error-btn {
- background: #03a9f3;
- border: 1px solid #03a9f3;
- border-radius: 30px;
- padding: 6px 20px 8px;
-}
-.theme-white .tpl-error-content {
- margin-top: 20px;
- margin-bottom: 20px;
- font-size: 16px;
- text-align: center;
- color: #96a2b4;
-}
-.theme-white .tpl-calendar-box {
- background: #fff;
- border-radius: 4px;
- padding: 20px;
-}
-.theme-white .tpl-calendar-box .fc-event {
- border-radius: 0;
- background: #03a9f3;
- border: 1px solid #14b0f6;
-}
-.theme-white .tpl-calendar-box .fc-axis {
- color: #868E8E;
-}
-.theme-white .tpl-calendar-box .fc-unthemed .fc-today {
- background: #eee;
-}
-.theme-white .tpl-calendar-box .fc-more {
- color: #868E8E;
-}
-.theme-white .tpl-calendar-box .fc th.fc-widget-header {
- background: #32c5d2!important;
- color: #ffffff;
- font-size: 14px;
- line-height: 20px;
- padding: 7px 0px;
- text-transform: uppercase;
- border: none!important;
-}
-.theme-white .tpl-calendar-box .fc th.fc-widget-header a {
- color: #fff;
-}
-.theme-white .tpl-calendar-box .fc-center h2 {
- color: #868E8E;
-}
-.theme-white .tpl-calendar-box .fc-state-default {
- background-image: none;
- background: #fff;
- font-size: 14px;
- color: #868E8E;
-}
-.theme-white .tpl-calendar-box .fc th,
-.theme-white .tpl-calendar-box .fc td,
-.theme-white .tpl-calendar-box .fc hr,
-.theme-white .tpl-calendar-box .fc thead,
-.theme-white .tpl-calendar-box .fc tbody,
-.theme-white .tpl-calendar-box .fc-row {
- border-color: #eee!important;
-}
-.theme-white .tpl-calendar-box .fc-day-number {
- color: #868E8E;
- padding-right: 6px;
-}
-.theme-white .tpl-calendar-box .fc th {
- color: #868E8E;
- font-weight: normal;
- font-size: 14px;
- padding: 6px 0;
-}
-.theme-white .tpl-login-logo {
- background: url(../img/logoa.png) center no-repeat;
-}
-.theme-white .sub-active {
- color: #23abf0!important;
-}
-.theme-white .tpl-table-line-img {
- border: 1px solid #ddd;
-}
-.theme-white .tpl-pagination .am-disabled a,
-.theme-white .tpl-pagination li a {
- color: #23abf0;
- border-radius: 3px;
- padding: 6px 12px;
-}
-.theme-white .tpl-pagination .am-active a {
- background: #23abf0;
- color: #fff;
- border: 1px solid #23abf0;
- padding: 6px 12px;
-}
-.theme-white .tpl-login-btn {
- background-color: #32c5d2;
- border: none;
- padding: 10px 16px;
- font-size: 14px;
- line-height: 14px;
- outline: none;
-}
-.theme-white .tpl-login-btn:hover,
-.theme-white .tpl-login-btn:active {
- background: #22b2e1;
- color: #fff;
-}
-.theme-white .tpl-login-title {
- color: #697882;
-}
-.theme-white .tpl-login-title strong {
- color: #39bae4;
-}
-.theme-white .tpl-login-content {
- width: 500px;
- padding: 40px 40px 25px;
- background-color: #fff;
- border-radius: 4px;
-}
-.theme-white .tpl-form-line-form,
-.theme-white .tpl-form-border-form {
- padding-top: 20px;
-}
-.theme-white .tpl-form-border-form input[type=number]:focus,
-.theme-white .tpl-form-border-form input[type=search]:focus,
-.theme-white .tpl-form-border-form input[type=text]:focus,
-.theme-white .tpl-form-border-form input[type=password]:focus,
-.theme-white .tpl-form-border-form input[type=datetime]:focus,
-.theme-white .tpl-form-border-form input[type=datetime-local]:focus,
-.theme-white .tpl-form-border-form input[type=date]:focus,
-.theme-white .tpl-form-border-form input[type=month]:focus,
-.theme-white .tpl-form-border-form input[type=time]:focus,
-.theme-white .tpl-form-border-form input[type=week]:focus,
-.theme-white .tpl-form-border-form input[type=email]:focus,
-.theme-white .tpl-form-border-form input[type=url]:focus,
-.theme-white .tpl-form-border-form input[type=tel]:focus,
-.theme-white .tpl-form-border-form input[type=color]:focus,
-.theme-white .tpl-form-border-form select:focus,
-.theme-white .tpl-form-border-form textarea:focus,
-.theme-white .am-form-field:focus {
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.theme-white .tpl-form-border-form input[type=number],
-.theme-white .tpl-form-border-form input[type=search],
-.theme-white .tpl-form-border-form input[type=text],
-.theme-white .tpl-form-border-form input[type=password],
-.theme-white .tpl-form-border-form input[type=datetime],
-.theme-white .tpl-form-border-form input[type=datetime-local],
-.theme-white .tpl-form-border-form input[type=date],
-.theme-white .tpl-form-border-form input[type=month],
-.theme-white .tpl-form-border-form input[type=time],
-.theme-white .tpl-form-border-form input[type=week],
-.theme-white .tpl-form-border-form input[type=email],
-.theme-white .tpl-form-border-form input[type=url],
-.theme-white .tpl-form-border-form input[type=tel],
-.theme-white .tpl-form-border-form input[type=color],
-.theme-white .tpl-form-border-form select,
-.theme-white .tpl-form-border-form textarea,
-.theme-white .am-form-field {
- display: block;
- width: 100%;
- padding: 6px 12px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- border: 1px solid #c2cad8;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- text-indent: .5em;
- -o-border-radius: 0;
- border-radius: 0;
- color: #555;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-.theme-white .tpl-form-border-form .am-checkbox,
-.theme-white .tpl-form-border-form .am-checkbox-inline,
-.theme-white .tpl-form-border-form .am-form-label,
-.theme-white .tpl-form-border-form .am-radio,
-.theme-white .tpl-form-border-form .am-radio-inline {
- margin-top: 0;
- margin-bottom: 0;
-}
-.theme-white .tpl-form-border-form .am-form-group:after {
- clear: both;
-}
-.theme-white .tpl-form-border-form .am-form-group:after,
-.theme-white .tpl-form-border-form .am-form-group:before {
- content: " ";
- display: table;
-}
-.theme-white .tpl-form-border-form .am-form-label {
- padding-top: 5px;
- font-size: 16px;
- color: #888;
- font-weight: inherit;
- text-align: right;
-}
-.theme-white .tpl-form-border-form .am-form-group {
- /*padding: 20px 0;*/
-}
-.theme-white .tpl-form-border-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-.theme-white .tpl-form-line-form input[type=number]:focus,
-.theme-white .tpl-form-line-form input[type=search]:focus,
-.theme-white .tpl-form-line-form input[type=text]:focus,
-.theme-white .tpl-form-line-form input[type=password]:focus,
-.theme-white .tpl-form-line-form input[type=datetime]:focus,
-.theme-white .tpl-form-line-form input[type=datetime-local]:focus,
-.theme-white .tpl-form-line-form input[type=date]:focus,
-.theme-white .tpl-form-line-form input[type=month]:focus,
-.theme-white .tpl-form-line-form input[type=time]:focus,
-.theme-white .tpl-form-line-form input[type=week]:focus,
-.theme-white .tpl-form-line-form input[type=email]:focus,
-.theme-white .tpl-form-line-form input[type=url]:focus,
-.theme-white .tpl-form-line-form input[type=tel]:focus,
-.theme-white .tpl-form-line-form input[type=color]:focus,
-.theme-white .tpl-form-line-form select:focus,
-.theme-white .tpl-form-line-form textarea:focus,
-.theme-white .am-form-field:focus {
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.theme-white .tpl-form-line-form input[type=number],
-.theme-white .tpl-form-line-form input[type=search],
-.theme-white .tpl-form-line-form input[type=text],
-.theme-white .tpl-form-line-form input[type=password],
-.theme-white .tpl-form-line-form input[type=datetime],
-.theme-white .tpl-form-line-form input[type=datetime-local],
-.theme-white .tpl-form-line-form input[type=date],
-.theme-white .tpl-form-line-form input[type=month],
-.theme-white .tpl-form-line-form input[type=time],
-.theme-white .tpl-form-line-form input[type=week],
-.theme-white .tpl-form-line-form input[type=email],
-.theme-white .tpl-form-line-form input[type=url],
-.theme-white .tpl-form-line-form input[type=tel],
-.theme-white .tpl-form-line-form input[type=color],
-.theme-white .tpl-form-line-form select,
-.theme-white .tpl-form-line-form textarea,
-.theme-white .am-form-field {
- display: block;
- width: 100%;
- padding: 6px 12px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border: 1px solid #c2cad8;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- border-bottom: 1px solid #c2cad8;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- -o-border-radius: 0;
- border-radius: 0;
- color: #555;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-.theme-white .tpl-form-line-form .am-checkbox,
-.theme-white .tpl-form-line-form .am-checkbox-inline,
-.theme-white .tpl-form-line-form .am-form-label,
-.theme-white .tpl-form-line-form .am-radio,
-.theme-white .tpl-form-line-form .am-radio-inline {
- margin-top: 0;
- margin-bottom: 0;
-}
-.theme-white .tpl-form-line-form .am-form-group:after {
- clear: both;
-}
-.theme-white .tpl-form-line-form .am-form-group:after,
-.theme-white .tpl-form-line-form .am-form-group:before {
- content: " ";
- display: table;
-}
-.theme-white .tpl-form-line-form .am-form-label {
- padding-top: 5px;
- font-size: 16px;
- color: #888;
- font-weight: inherit;
- text-align: right;
-}
-.theme-white .tpl-form-line-form .am-form-group {
- /*padding: 20px 0;*/
-}
-.theme-white .tpl-form-line-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-.theme-white .tpl-table-black-operation a {
- border: 1px solid #36c6d3;
- color: #36c6d3;
-}
-.theme-white .tpl-table-black-operation a:hover {
- background: #36c6d3;
- color: #fff;
-}
-.theme-white .tpl-table-black-operation a.tpl-table-black-operation-del {
- border: 1px solid #e7505a;
- color: #e7505a;
-}
-.theme-white .tpl-table-black-operation a.tpl-table-black-operation-del:hover {
- background: #e7505a;
- color: #fff;
-}
-.theme-white .tpl-amendment-echarts {
- left: -17px;
-}
-.theme-white .tpl-user-card {
- border: 1px solid #3598dc;
- border-top: 2px solid #3598dc;
- background: #3598dc;
- color: #ffffff;
- border-radius: 4px;
-}
-.theme-white .tpl-user-card-title {
- font-size: 26px;
- margin-top: 0;
- font-weight: 300;
- margin-top: 25px;
- margin-bottom: 10px;
-}
-.theme-white .achievement-subheading {
- font-size: 12px;
- margin-top: 0;
- margin-bottom: 15px;
-}
-.theme-white .achievement-image {
- border-radius: 50%;
- margin-bottom: 22px;
-}
-.theme-white .achievement-description {
- margin: 0;
- font-size: 12px;
-}
-.theme-white .tpl-table-black {
- color: #838FA1;
-}
-.theme-white .tpl-table-black thead > tr > th {
- font-size: 14px;
- padding: 6px;
-}
-.theme-white .tpl-table-black tbody > tr > td {
- font-size: 14px;
- padding: 7px 6px;
-}
-.theme-white .tpl-table-black tfoot > tr > th {
- font-size: 14px;
- padding: 6px 0;
-}
-.theme-white .am-progress {
- height: 12px;
-}
-.theme-white .am-progress-title {
- font-size: 14px;
- margin-bottom: 8px;
-}
-.theme-white .widget-fluctuation-tpl-btn {
- margin-top: 6px;
- display: block;
- color: #fff;
- font-size: 12px;
- padding: 8px 14px;
- outline: none;
- background-color: #e7505a;
- border: 1px solid #e7505a;
-}
-.theme-white .widget-fluctuation-tpl-btn:hover {
- background: transparent;
- color: #e7505a;
-}
-.theme-white .widget-fluctuation-description-text {
- color: #c5cacd;
-}
-.theme-white .widget-fluctuation-period-text {
- color: #838FA1;
-}
-.theme-white .text-success {
- color: #5eb95e;
-}
-.theme-white .widget-head {
- border-bottom: 1px solid #eef1f5;
-}
-.theme-white .widget-function a {
- color: #838FA1;
-}
-.theme-white .widget-function a:hover {
- color: #a7bdcd;
-}
-.theme-white .widget {
- padding: 10px 20px 13px;
- background-color: #fff;
- border-radius: 4px;
- color: #838FA1;
-}
-.theme-white .widget-title {
- font-size: 16px;
-}
-.theme-white .widget-primary {
- min-height: 174px;
- border: 1px solid #32c5d2;
- border-top: 2px solid #32c5d2;
- background: #32c5d2;
- color: #ffffff;
- padding: 12px 17px;
- padding-left: 22px;
-}
-.theme-white .widget-statistic-icon {
- position: absolute;
- z-index: 30;
- right: 30px;
- top: 24px;
- font-size: 70px;
- color: #46cad6;
-}
-.theme-white .widget-statistic-description {
- position: relative;
- z-index: 35;
- display: block;
- font-size: 14px;
- line-height: 14px;
- padding-top: 8px;
- color: #fff;
-}
-.theme-white .widget-statistic-value {
- position: relative;
- z-index: 35;
- font-weight: 300;
- display: block;
- color: #fff;
- font-size: 46px;
- line-height: 46px;
- margin-bottom: 8px;
-}
-.theme-white .widget-statistic-header {
- padding-top: 18px;
- color: #fff;
-}
-.theme-white .widget-purple {
- padding: 12px 17px;
- border: 1px solid #8E44AD;
- border-top: 2px solid #8E44AD;
- background: #8E44AD;
- color: #ffffff;
- min-height: 174px;
-}
-.theme-white .widget-purple .widget-statistic-icon {
- color: #9956b5;
-}
-.theme-white .widget-purple .widget-statistic-header {
- color: #ded5e7;
-}
-.theme-white .widget-purple .widget-statistic-description {
- color: #ded5e7;
-}
-.theme-white .page-header-button {
- opacity: .8;
- border: 1px solid #32c5d2;
- background: #32c5d2;
- color: #fff;
-}
-.theme-white .page-header-button:hover {
- opacity: 1;
-}
-.theme-white .page-header-description {
- color: #666;
-}
-.theme-white .page-header-heading {
- color: #666;
-}
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .menu-messages-content .menu-messages-content-time {
- color: #96a5aa;
-}
-.theme-white ul.tpl-dropdown-content {
- background: #fff;
- border: 1px solid #ddd;
-}
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item,
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item {
- border-bottom: 1px solid #eee;
- color: #999;
-}
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item:hover,
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item:hover {
- background-color: #f5f5f5;
-}
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-item .tpl-dropdown-menu-notifications-time,
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .tpl-dropdown-menu-notifications-time {
- color: #999;
-}
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item:hover {
- background-color: #f5f5f5;
-}
-.theme-white ul.tpl-dropdown-content .tpl-dropdown-menu-notifications-title {
- color: #999;
-}
-.theme-white .sidebar-nav-link a {
- border-left: #fff 3px solid;
-}
-.theme-white .sidebar-nav-link a:hover {
- background: #f2f6f9;
- color: #868E8E;
- border-left: #3bb4f2 3px solid;
-}
-.theme-white .sidebar-nav-link a.active {
- background: #f2f6f9;
- color: #868E8E;
- border-left: #3bb4f2 3px solid;
-}
-.theme-white .sidebar-nav-heading {
- color: #999;
- border-bottom: 1px solid #eee;
-}
-.theme-white .tpl-sidebar-user-panel {
- background: #fff;
- border-bottom: 1px solid #eee;
-}
-.theme-white .tpl-content-wrapper {
- background: #e9ecf3;
-}
-.theme-white .tpl-header-fluid {
- background: #fff;
- border-top: 1px solid #eee;
-}
-.theme-white .tpl-header-logo {
- background: #fff;
- border-bottom: 1px solid #eee;
-}
-.theme-white .tpl-header-switch-button {
- background: #fff;
- border-right: 1px solid #eee;
- border-left: 1px solid #eee;
-}
-.theme-white .tpl-header-switch-button:hover {
- background: #fff;
- color: #999;
-}
-.theme-white .tpl-header-navbar a {
- color: #999;
-}
-.theme-white .tpl-header-navbar a:hover {
- color: #999;
-}
-.theme-white .left-sidebar {
- background: #fff;
-}
-.theme-white .widget-color-green {
- border: 1px solid #32c5d2;
- border-top: 2px solid #32c5d2;
- background: #32c5d2;
- color: #ffffff;
-}
-.theme-white .widget-color-green .widget-fluctuation-period-text {
- color: #fff;
-}
-.theme-white .widget-color-green .widget-head {
- border-bottom: 1px solid #2bb8c4;
-}
-.theme-white .widget-color-green .widget-fluctuation-description-text {
- color: #bbe7f6;
-}
-.theme-white .widget-color-green .widget-function a {
- color: #42bde5;
-}
-.theme-white .widget-color-green .widget-function a:hover {
- color: #fff;
-}
-.theme-black {
- background-color: #282d2f;
-}
-.theme-black .tpl-am-model-bd {
- background: #424b4f;
-}
-.theme-black .tpl-model-dialog {
- background: #424b4f;
-}
-.theme-black .tpl-error-title {
- font-size: 210px;
- line-height: 220px;
- color: #868E8E;
-}
-.theme-black .tpl-error-title-info {
- line-height: 30px;
- font-size: 21px;
- margin-top: 20px;
- text-align: center;
- color: #868E8E;
-}
-.theme-black .tpl-error-btn {
- background: #03a9f3;
- border: 1px solid #03a9f3;
- border-radius: 30px;
- padding: 6px 20px 8px;
-}
-.theme-black .tpl-error-content {
- margin-top: 20px;
- margin-bottom: 20px;
- font-size: 16px;
- text-align: center;
- color: #cfcfcf;
-}
-.theme-black .tpl-calendar-box {
- background: #424b4f;
- padding: 20px;
-}
-.theme-black .tpl-calendar-box .fc-button {
- border-radius: 0;
- box-shadow: 0;
-}
-.theme-black .tpl-calendar-box .fc-event {
- border-radius: 0;
- background: #03a9f3;
-}
-.theme-black .tpl-calendar-box .fc-axis {
- color: #fff;
-}
-.theme-black .tpl-calendar-box .fc-unthemed .fc-today {
- background: #3a4144;
-}
-.theme-black .tpl-calendar-box .fc-more {
- color: #fff;
-}
-.theme-black .tpl-calendar-box .fc th.fc-widget-header {
- background: #9675ce!important;
- color: #ffffff;
- font-size: 14px;
- line-height: 20px;
- padding: 7px 0px;
- text-transform: uppercase;
- border: none!important;
-}
-.theme-black .tpl-calendar-box .fc th.fc-widget-header a {
- color: #fff;
-}
-.theme-black .tpl-calendar-box .fc-center h2 {
- color: #fff;
-}
-.theme-black .tpl-calendar-box .fc-state-default {
- background-image: none;
- background: #fff;
- font-size: 14px;
-}
-.theme-black .tpl-calendar-box .fc th,
-.theme-black .tpl-calendar-box .fc td,
-.theme-black .tpl-calendar-box .fc hr,
-.theme-black .tpl-calendar-box .fc thead,
-.theme-black .tpl-calendar-box .fc tbody,
-.theme-black .tpl-calendar-box .fc-row {
- border-color: rgba(120, 130, 140, 0.4) !important;
-}
-.theme-black .tpl-calendar-box .fc-day-number {
- color: #868E8E;
- padding-right: 6px;
-}
-.theme-black .tpl-calendar-box .fc th {
- color: #868E8E;
- font-weight: normal;
- font-size: 14px;
- padding: 6px 0;
-}
-.theme-black .tpl-login-logo {
- background: url(../img/logob.png) center no-repeat;
-}
-.theme-black .tpl-table-line-img {
- max-width: 100px;
- padding: 2px;
- border: none;
-}
-.theme-black .tpl-table-list-field {
- border: none;
-}
-.theme-black .tpl-table-list-select .am-dropdown-content {
- color: #888;
-}
-.theme-black .tpl-table-list-select .am-selected-btn {
- border: 1px solid rgba(255, 255, 255, 0.2);
- color: #fff;
-}
-.theme-black .tpl-table-list-select .am-btn-default.am-active,
-.theme-black .tpl-table-list-select .am-btn-default:active,
-.theme-black .tpl-table-list-select .am-dropdown.am-active .am-btn-default.am-dropdown-toggle {
- border: 1px solid rgba(255, 255, 255, 0.2);
- color: #fff;
- background: #5d6468;
-}
-.theme-black .tpl-pagination .am-disabled a,
-.theme-black .tpl-pagination li a {
- color: #fff;
- padding: 6px 12px;
- background: #3f4649;
- border: none;
-}
-.theme-black .tpl-pagination .am-active a {
- background: #167fa1;
- color: #fff;
- border: 1px solid #167fa1;
- padding: 6px 12px;
-}
-.theme-black .tpl-login-btn {
- border: 1px solid #b5b5b5;
- background-color: rgba(0, 0, 0, 0);
- padding: 10px 16px;
- font-size: 14px;
- line-height: 14px;
- color: #b5b5b5;
-}
-.theme-black .tpl-login-btn:hover,
-.theme-black .tpl-login-btn:active {
- background: #b5b5b5;
- color: #fff;
-}
-.theme-black .tpl-login-title {
- color: #fff;
-}
-.theme-black .tpl-login-title strong {
- color: #39bae4;
-}
-.theme-black .tpl-form-line-form,
-.theme-black .tpl-form-border-form {
- padding-top: 20px;
-}
-.theme-black .tpl-form-line-form .am-btn-default,
-.theme-black .tpl-form-border-form .am-btn-default {
- color: #fff;
- border: 1px solid rgba(255, 255, 255, 0.2);
-}
-.theme-black .tpl-form-line-form .am-selected-text,
-.theme-black .tpl-form-border-form .am-selected-text {
- color: #888;
-}
-.theme-black .tpl-form-border-form input[type=number]:focus,
-.theme-black .tpl-form-border-form input[type=search]:focus,
-.theme-black .tpl-form-border-form input[type=text]:focus,
-.theme-black .tpl-form-border-form input[type=password]:focus,
-.theme-black .tpl-form-border-form input[type=datetime]:focus,
-.theme-black .tpl-form-border-form input[type=datetime-local]:focus,
-.theme-black .tpl-form-border-form input[type=date]:focus,
-.theme-black .tpl-form-border-form input[type=month]:focus,
-.theme-black .tpl-form-border-form input[type=time]:focus,
-.theme-black .tpl-form-border-form input[type=week]:focus,
-.theme-black .tpl-form-border-form input[type=email]:focus,
-.theme-black .tpl-form-border-form input[type=url]:focus,
-.theme-black .tpl-form-border-form input[type=tel]:focus,
-.theme-black .tpl-form-border-form input[type=color]:focus,
-.theme-black .tpl-form-border-form select:focus,
-.theme-black .tpl-form-border-form textarea:focus,
-.theme-black .am-form-field:focus {
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.theme-black .tpl-form-border-form input[type=number],
-.theme-black .tpl-form-border-form input[type=search],
-.theme-black .tpl-form-border-form input[type=text],
-.theme-black .tpl-form-border-form input[type=password],
-.theme-black .tpl-form-border-form input[type=datetime],
-.theme-black .tpl-form-border-form input[type=datetime-local],
-.theme-black .tpl-form-border-form input[type=date],
-.theme-black .tpl-form-border-form input[type=month],
-.theme-black .tpl-form-border-form input[type=time],
-.theme-black .tpl-form-border-form input[type=week],
-.theme-black .tpl-form-border-form input[type=email],
-.theme-black .tpl-form-border-form input[type=url],
-.theme-black .tpl-form-border-form input[type=tel],
-.theme-black .tpl-form-border-form input[type=color],
-.theme-black .tpl-form-border-form select,
-.theme-black .tpl-form-border-form textarea,
-.theme-black .am-form-field {
- display: block;
- width: 100%;
- padding: 6px 12px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border: 1px solid #c2cad8;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- text-indent: .5em;
- border: 1px solid rgba(255, 255, 255, 0.2);
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- -o-border-radius: 0;
- border-radius: 0;
- color: #fff;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-.theme-black .tpl-form-border-form .am-checkbox,
-.theme-black .tpl-form-border-form .am-checkbox-inline,
-.theme-black .tpl-form-border-form .am-form-label,
-.theme-black .tpl-form-border-form .am-radio,
-.theme-black .tpl-form-border-form .am-radio-inline {
- margin-top: 0;
- margin-bottom: 0;
-}
-.theme-black .tpl-form-border-form .am-form-group:after {
- clear: both;
-}
-.theme-black .tpl-form-border-form .am-form-group:after,
-.theme-black .tpl-form-border-form .am-form-group:before {
- content: " ";
- display: table;
-}
-.theme-black .tpl-form-border-form .am-form-label {
- padding-top: 5px;
- font-size: 16px;
- color: #fff;
- font-weight: inherit;
- text-align: right;
-}
-.theme-black .tpl-form-border-form .am-form-group {
- /*padding: 20px 0;*/
-}
-.theme-black .tpl-form-border-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-.theme-black .tpl-form-line-form input[type=number]:focus,
-.theme-black .tpl-form-line-form input[type=search]:focus,
-.theme-black .tpl-form-line-form input[type=text]:focus,
-.theme-black .tpl-form-line-form input[type=password]:focus,
-.theme-black .tpl-form-line-form input[type=datetime]:focus,
-.theme-black .tpl-form-line-form input[type=datetime-local]:focus,
-.theme-black .tpl-form-line-form input[type=date]:focus,
-.theme-black .tpl-form-line-form input[type=month]:focus,
-.theme-black .tpl-form-line-form input[type=time]:focus,
-.theme-black .tpl-form-line-form input[type=week]:focus,
-.theme-black .tpl-form-line-form input[type=email]:focus,
-.theme-black .tpl-form-line-form input[type=url]:focus,
-.theme-black .tpl-form-line-form input[type=tel]:focus,
-.theme-black .tpl-form-line-form input[type=color]:focus,
-.theme-black .tpl-form-line-form select:focus,
-.theme-black .tpl-form-line-form textarea:focus,
-.theme-black .am-form-field:focus {
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.theme-black .tpl-form-line-form input[type=number],
-.theme-black .tpl-form-line-form input[type=search],
-.theme-black .tpl-form-line-form input[type=text],
-.theme-black .tpl-form-line-form input[type=password],
-.theme-black .tpl-form-line-form input[type=datetime],
-.theme-black .tpl-form-line-form input[type=datetime-local],
-.theme-black .tpl-form-line-form input[type=date],
-.theme-black .tpl-form-line-form input[type=month],
-.theme-black .tpl-form-line-form input[type=time],
-.theme-black .tpl-form-line-form input[type=week],
-.theme-black .tpl-form-line-form input[type=email],
-.theme-black .tpl-form-line-form input[type=url],
-.theme-black .tpl-form-line-form input[type=tel],
-.theme-black .tpl-form-line-form input[type=color],
-.theme-black .tpl-form-line-form select,
-.theme-black .tpl-form-line-form textarea,
-.theme-black .am-form-field {
- display: block;
- width: 100%;
- padding: 6px 12px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border: 1px solid #c2cad8;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- border-bottom: 1px solid rgba(255, 255, 255, 0.2);
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- -o-border-radius: 0;
- border-radius: 0;
- color: #fff;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-.theme-black .tpl-form-line-form .am-checkbox,
-.theme-black .tpl-form-line-form .am-checkbox-inline,
-.theme-black .tpl-form-line-form .am-form-label,
-.theme-black .tpl-form-line-form .am-radio,
-.theme-black .tpl-form-line-form .am-radio-inline {
- margin-top: 0;
- margin-bottom: 0;
-}
-.theme-black .tpl-form-line-form .am-form-group:after {
- clear: both;
-}
-.theme-black .tpl-form-line-form .am-form-group:after,
-.theme-black .tpl-form-line-form .am-form-group:before {
- content: " ";
- display: table;
-}
-.theme-black .tpl-form-line-form .am-form-label {
- padding-top: 5px;
- font-size: 16px;
- color: #fff;
- font-weight: inherit;
- text-align: right;
-}
-.theme-black .tpl-form-line-form .am-form-group {
- /*padding: 20px 0;*/
-}
-.theme-black .tpl-form-line-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-.theme-black .tpl-table-black-operation a {
- border: 1px solid #7b878d;
- color: #7b878d;
-}
-.theme-black .tpl-table-black-operation a:hover {
- background: #7b878d;
- color: #fff;
-}
-.theme-black .tpl-table-black-operation a.tpl-table-black-operation-del {
- border: 1px solid #f35842;
- color: #f35842;
-}
-.theme-black .tpl-table-black-operation a.tpl-table-black-operation-del:hover {
- background: #f35842;
- color: #fff;
-}
-.theme-black .am-table-bordered {
- border: 1px solid #666d70;
-}
-.theme-black .am-table-bordered > tbody > tr > td,
-.theme-black .am-table-bordered > tbody > tr > th,
-.theme-black .am-table-bordered > tfoot > tr > td,
-.theme-black .am-table-bordered > tfoot > tr > th,
-.theme-black .am-table-bordered > thead > tr > td,
-.theme-black .am-table-bordered > thead > tr > th {
- border: 1px solid #666d70;
-}
-.theme-black .am-table-bordered > thead + tbody > tr:first-child > td,
-.theme-black .am-table-bordered > thead + tbody > tr:first-child > th {
- border: 1px solid #666d70;
-}
-.theme-black .am-table-striped > tbody > tr:nth-child(odd) > td,
-.theme-black .am-table-striped > tbody > tr:nth-child(odd) > th {
- background-color: #5d6468;
-}
-.theme-black .tpl-table-black {
- color: #fff;
-}
-.theme-black .tpl-table-black thead > tr > th {
- font-size: 14px;
- padding: 6px;
- border-bottom: 1px solid #666d70;
-}
-.theme-black .tpl-table-black tbody > tr > td {
- font-size: 14px;
- padding: 7px 6px;
- border-top: 1px solid #666d70;
-}
-.theme-black .tpl-table-black tfoot > tr > th {
- font-size: 14px;
- padding: 6px 0;
-}
-.theme-black .tpl-user-card {
- border: 1px solid #11627d;
- border-top: 2px solid #105f79;
- background: #1786aa;
- color: #ffffff;
-}
-.theme-black .tpl-user-card-title {
- font-size: 26px;
- margin-top: 0;
- font-weight: 300;
- margin-top: 25px;
- margin-bottom: 10px;
-}
-.theme-black .achievement-subheading {
- font-size: 12px;
- margin-top: 0;
- margin-bottom: 15px;
-}
-.theme-black .achievement-image {
- border-radius: 50%;
- margin-bottom: 22px;
-}
-.theme-black .achievement-description {
- margin: 0;
- font-size: 12px;
-}
-.theme-black .am-progress {
- height: 12px;
- margin-bottom: 14px;
- background: rgba(0, 0, 0, 0.15);
-}
-.theme-black .am-progress-title {
- font-size: 14px;
- margin-bottom: 8px;
-}
-.theme-black .am-progress-title-more {
- color: #a1a8ab;
-}
-.theme-black .widget-fluctuation-tpl-btn {
- margin-top: 6px;
- display: block;
- color: #fff;
- font-size: 12px;
- padding: 5px 10px;
- outline: none;
- background-color: rgba(255, 255, 255, 0);
- border: 1px solid #fff;
-}
-.theme-black .widget-fluctuation-tpl-btn:hover {
- background: #fff;
- color: #4b5357;
-}
-.theme-black .widget-fluctuation-description-text {
- color: #c5cacd;
-}
-.theme-black .text-success {
- color: #08ed72;
-}
-.theme-black .widget-fluctuation-period-text {
- color: #fff;
-}
-.theme-black .widget-head {
- border-bottom: 1px solid #3f4649;
-}
-.theme-black .widget-function a {
- color: #7b878d;
-}
-.theme-black .widget-function a:hover {
- color: #fff;
-}
-.theme-black .widget {
- border: 1px solid #33393c;
- border-top: 2px solid #313639;
- background: #4b5357;
- color: #ffffff;
-}
-.theme-black .widget-primary {
- border: 1px solid #11627d;
- border-top: 2px solid #105f79;
- background: #1786aa;
- color: #ffffff;
- padding: 12px 17px;
-}
-.theme-black .widget-statistic-icon {
- position: absolute;
- z-index: 30;
- right: 30px;
- top: 0px;
- font-size: 70px;
- color: #1b9eca;
-}
-.theme-black .widget-statistic-description {
- position: relative;
- z-index: 35;
- display: block;
- font-size: 14px;
- line-height: 14px;
- padding-top: 8px;
- color: #9cdcf2;
-}
-.theme-black .widget-statistic-value {
- position: relative;
- z-index: 35;
- font-weight: 300;
- display: block;
- color: #fff;
- font-size: 46px;
- line-height: 46px;
- margin-bottom: 8px;
-}
-.theme-black .widget-statistic-header {
- color: #9cdcf2;
-}
-.theme-black .widget-purple {
- padding: 12px 17px;
- border: 1px solid #5e4578;
- border-top: 2px solid #5c4375;
- background: #785799;
- color: #ffffff;
-}
-.theme-black .widget-purple .widget-statistic-icon {
- color: #8a6aaa;
-}
-.theme-black .widget-purple .widget-statistic-header {
- color: #ded5e7;
-}
-.theme-black .widget-purple .widget-statistic-description {
- color: #ded5e7;
-}
-.theme-black .page-header-description {
- color: #e6e6e6;
-}
-.theme-black .page-header-heading {
- color: #666;
-}
-.theme-black .container-fluid {
- background: #424b4f;
-}
-.theme-black .page-header-heading {
- color: #fff;
-}
-.theme-black .sidebar-nav-heading {
- color: #fff;
-}
-.theme-black .tpl-sidebar-user-panel {
- background: #1f2224;
- border-bottom: 1px solid #1f2224;
-}
-.theme-black .tpl-content-wrapper {
- background: #3a4144;
-}
-.theme-black .tpl-header-fluid {
- background: #2f3638;
-}
-.theme-black .sidebar-nav-link a.active {
- background: #232829;
-}
-.theme-black .sidebar-nav-link a:hover {
- background: #232829;
-}
-.theme-black .tpl-header-switch-button {
- background: #2f3638;
- border-right: 1px solid #282d2f;
-}
-.theme-black .tpl-header-switch-button:hover {
- background: #282d2f;
- color: #fff;
-}
-.theme-black .tpl-header-navbar a {
- color: #cfcfcf;
-}
-.theme-black .tpl-header-navbar a:hover {
- color: #fff;
-}
-.theme-black .left-sidebar {
- padding-top: 56px;
- background: #282d2f;
-}
-.theme-black .widget-color-green {
- border: 1px solid #11627d;
- border-top: 2px solid #105f79;
- background: #1786aa;
- color: #ffffff;
-}
-.theme-black .widget-color-green .widget-head {
- border-bottom: 1px solid #147494;
-}
-.theme-black .widget-color-green .widget-fluctuation-description-text {
- color: #bbe7f6;
-}
-.theme-black .widget-color-green .widget-function a {
- color: #42bde5;
-}
-.theme-black .widget-color-green .widget-function a:hover {
- color: #fff;
-}
-@media screen and (max-width: 1024px) {
- .tpl-index-settings-button {
- display: none;
- }
- .theme-black .left-sidebar {
- padding-top: 111px;
- }
- .left-sidebar {
- padding-top: 111px;
- }
- .tpl-content-wrapper {
- margin-left: 0;
- }
- .tpl-header-logo {
- float: none;
- width: 100%;
- }
- .tpl-header-navbar-welcome {
- display: none;
- }
- .tpl-sidebar-user-panel {
- border-top: 1px solid #eee;
- }
- .tpl-header-fluid {
- border-top: none;
- margin-left: 0;
- }
- .theme-white .tpl-header-fluid {
- border-top: none;
- }
- .theme-black .tpl-sidebar-user-panel {
- border-top: 1px solid #1f2224;
- }
-}
-@media screen and (min-width: 641px) {
- [class*=am-u-] {
- padding-left: 10px;
- padding-right: 10px;
- }
-}
-@media screen and (max-width: 641px) {
- .theme-white .tpl-error-title,
- .theme-black .tpl-error-title {
- font-size: 130px;
- line-height: 140px;
- }
- .theme-white .tpl-login-title {
- font-size: 20px;
- }
- .theme-white .tpl-login-content {
- width: 86%;
- padding: 22px 30px 25px;
- }
- .tpl-header-search {
- display: none;
- }
- ul.tpl-dropdown-content {
- position: fixed;
- width: 100%;
- left: 0;
- top: 112px;
- right: 0;
- }
-}
diff --git a/Day61-65/code/project_of_tornado/assets/css/app.less b/Day61-65/code/project_of_tornado/assets/css/app.less
deleted file mode 100644
index 1b8de9a..0000000
--- a/Day61-65/code/project_of_tornado/assets/css/app.less
+++ /dev/null
@@ -1,2056 +0,0 @@
-ul,li {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-a {
-
-}
-
-header {
- z-index: 1200;
- position: relative;
-}
-.tpl-header-logo {
- width: 240px;
- height: 57px;
- display: table;
- text-align:center;
- position: relative;
- z-index: 1300;
-
- a {
- display:table-cell;
- vertical-align:middle;
- }
-
- img {
- width:170px;
- }
-}
-
-
-.tpl-header-fluid {
- margin-left: 240px;
- height: 56px;
-
- padding-left: 20px;
- padding-right: 20px;
-}
-
-
-.tpl-header-switch-button {
-
- margin-top: 0px;
- margin-bottom: 0px;
- float: left;
- color: #cfcfcf;
- margin-left: -20px;
- margin-right: 0;
- border: 0;
- border-radius: 0;
- padding: 0px 22px;
- font-size: 22px;
- line-height: 55px;
-
- &:hover {
-
- outline: none;
- }
-}
-
-
-.tpl-header-search-form {
- height: 54px;
- line-height: 52px;
- margin-left: 10px;
-
-}
-.tpl-header-search-box , .tpl-header-search-btn {
- transition: all 0.4s ease-in-out;
- color: #848c90;
- background: none;
- border: none;
- outline: none;
-}
-
-.tpl-header-search-box {
- font-size: 14px;
-
- &:hover,&:active {
- color: #fff;
- }
-}
-
-.tpl-header-search-btn {
- font-size: 15px;
-
- &:hover,&:active {
- color: #fff;
- }
-}
-
-.tpl-header-navbar {
- color: #fff;
- li {
- float: left;
- }
- a {
- line-height: 56px;
- display: block;
- padding: 0 16px;
- position: relative;
-
-
- &:hover {
-
- }
-
- .item-feed-badge {
- position: absolute;
- top: 9px;
- left: 25px;
- }
- }
-}
-
-ul.tpl-dropdown-content {
- padding: 10px;
- margin-top: 0;
- width: 300px;
- background-color: #2f3638;
- border: 1px solid #525e62;
- border-radius: 0;
-
- li {
- float:none;
- }
-
- &:before , &:after {
- display: none;
- }
-}
-
-
-ul.tpl-dropdown-content {
-
-
- .tpl-dropdown-menu-notifications {
-
- }
-
- .tpl-dropdown-menu-notifications-title {
- font-size: 12px;
- float: left;
- color: rgba(255, 255, 255, 0.7);
- }
-
- .tpl-dropdown-menu-notifications-time {
- float: right;
- text-align: right;
- color: rgba(255, 255, 255, 0.7);
- font-size: 11px;
- width: 50px;
- margin-left: 10px;
- }
-
- .tpl-dropdown-menu-notifications:last-child .tpl-dropdown-menu-notifications-item {
- text-align: center;
- border: none;
- font-size: 12px;
- i {
- margin-left: -6px;
- }
- }
-
- .tpl-dropdown-menu-messages:last-child .tpl-dropdown-menu-messages-item {
- text-align: center;
- border: none;
- font-size: 12px;
- i {
- margin-left: -6px;
- }
- }
- .tpl-dropdown-menu-notifications-item , .tpl-dropdown-menu-messages-item {
- padding: 12px;
- color: #fff;
- line-height: 20px;
- border-bottom: 1px solid rgba(255, 255, 255, 0.15);
-
- &:hover , &:focus {
- background-color: #465154;
- color: #fff;
- }
-
-
-
- .menu-messages-ico {
- line-height: initial;
- float: left;
- width: 35px;
- height: 35px;
- border-radius: 50%;
- margin-right: 10px;
- margin-top: 6px;
- overflow: hidden;
-
- img {
- width: 100%;
- height: auto;
- vertical-align: middle;
- }
- }
-
- .menu-messages-time {
- float: right;
- text-align: right;
- color: rgba(255, 255, 255, 0.7);
- font-size: 11px;
- width: 40px;
- margin-left: 10px;
-
-
- }
-
- .menu-messages-content {
- display: block;
- font-size: 13px;
- margin-left: 45px;
- margin-right: 50px;
-
- .menu-messages-content-title {
-
- }
-
- .menu-messages-content-time {
- margin-top: 3px;
- color: rgba(255, 255, 255, 0.7);
- font-size: 11px;
- }
- }
-
-
- }
-}
-
-.am-dimmer {
- z-index: 1200;
-}
-.am-modal {
- z-index: 1300;
-}
-.am-datepicker-dropdown {
- z-index: 1400;
-}
-
-.tpl-skiner {
- transition: all 0.4s ease-in-out;
- position: fixed;
- z-index: 10000;
- right: -130px;
- top: 65px;
-}
-
-.tpl-skiner.active {
- right: 0px;
-}
-.tpl-skiner-content {
- background: rgba(0, 0, 0, 0.7);
- width: 130px;
- padding: 15px;
- border-radius: 4px 0 0 4px;
- overflow: hidden;
-}
-
-.fc-content .am-icon-close {
- position: absolute;
- right: 0;
- top: 0px;
-}
-.tpl-skiner-toggle {
- position: absolute;
- top: 5px;
- left: -40px;
- width: 40px;
- color:#969a9b;
- font-size: 20px;
- height: 40px;
- line-height: 40px;
- text-align: center;
- background: rgba(0, 0, 0, 0.7);
- cursor: pointer;
- border-top-left-radius: 4px;
- border-bottom-left-radius: 4px;
-
-}
-.tpl-skiner-content-title {
- margin: 0;
- margin-bottom: 4px;
- padding-bottom: 4px;
- font-size: 16px;
- text-transform: uppercase;
- color:#fff;
- border-bottom: 1px solid rgba(255, 255, 255, 0.3);
-}
-
-.tpl-skiner-content-bar {
- padding-top: 10px;
- .skiner-color {
- transition: all 0.4s ease-in-out;
- float: left;
- width: 25px;
- height: 25px;
- margin-right: 10px;
- cursor: pointer;
- }
- .skiner-white {
- background: #fff;
- border: 2px solid #eee;
- }
-
- .skiner-black {
- background: #000;
- border: 2px solid #222;
- }
-}
-
-.sub-active {
- color:#fff!important;
-}
-.left-sidebar {
- transition: all 0.4s ease-in-out;
- width: 240px;
- min-height: 100%;
- padding-top: 57px;
- position: absolute;
- z-index: 1104;
- top: 0;
- left: 0px;
- &.xs-active {
- left:0px;
- }
- &.active {
- left:-240px;
- }
-
-}
-.tpl-sidebar-user-panel {
- padding: 22px;
- padding-top: 28px;
-}
-
-.tpl-user-panel-slide-toggleable {
-
-}
-
-.tpl-user-panel-profile-picture {
- border-radius: 50%;
- width: 82px;
- height: 82px;
- margin-bottom: 10px;
- overflow: hidden;
-
- img {
- width: auto;
- height: 82px;
- vertical-align: middle;
- }
-}
-.tpl-user-panel-status-icon {
- margin-right: 2px;
-}
-.user-panel-logged-in-text {
- display: block;
-
- color:#cfcfcf;
- font-size: 14px;
-}
-.tpl-user-panel-action-link {
- color: #6d787c;
- font-size: 12px;
- &:hover {
- color: #a2aaad;
- }
-}
-
-.sidebar-nav {
- list-style-type: none;
- padding: 0;
- margin: 0;
-}
-
-.sidebar-nav-sub {
- display: none;
- .sidebar-nav-link {
- font-size: 12px;
- padding-left: 30px;
- a {
- font-size: 12px;
- padding-left: 0;
- }
- }
-
- .sidebar-nav-link-logo {
- margin-right: 8px;
- width: 20px;
- font-size: 16px;
- }
-}
-
-.sidebar-nav-sub-ico-rotate{
- -webkit-transform: rotate(180deg);
- transform: rotate(180deg);
- -webkit-transition: all 300ms;
- transition: all 300ms;
-}
-.sidebar-nav-link-logo-ico {
- margin-top: 5px;
-}
-.sidebar-nav-heading {
- padding: 24px 17px;
- font-size: 15px;
- font-weight: 500;
-}
-.sidebar-nav-heading-info {
- font-size: 12px;
- color:#868E8E;
- padding-left: 10px;
-}
-.sidebar-nav-link-logo {
- margin-right: 8px;
- width: 20px;
- font-size: 16px;
-}
-.sidebar-nav-link {
-
- color: #fff;
-
- a {
- display: block;
- color: #868E8E;
- padding: 10px 17px;
- border-left: #282d2f 3px solid;
- font-size: 14px;
- cursor: pointer;
-
- &.active {
- cursor: pointer;
- border-left: #1CA2CE 3px solid;
- color: #fff;
-
- }
-
- &:hover {
- color: #fff;
- }
- }
-}
-
-.tpl-content-wrapper {
- transition: all 0.4s ease-in-out;
- position: relative;
- margin-left: 240px;
- z-index: 1101;
- min-height: 922px;
- border-bottom-left-radius: 3px;
- &.xs-active {
- margin-left: 240px;
- }
- &.active {
- margin-left: 0;
- }
-}
-
-.page-header {
- background: #424b4f;
- margin-top: 0;
- margin-bottom: 0;
- padding: 40px 0;
- border-bottom: 0;
-}
-
-.container-fluid {
- margin-top: 0;
- margin-bottom: 0;
- padding: 40px 0;
- border-bottom: 0;
- padding-left: 20px;
- padding-right: 20px;
-}
-
-.row {
- margin-right: -10px;
- margin-left: -10px;
-}
-
-.page-header-description {
- margin-top: 4px;
- margin-bottom: 0;
- font-size: 14px;
- color: #e6e6e6;
-}
-.page-header-heading {
- font-size: 20px;
- font-weight: 400;
- .page-header-heading-ico {
- font-size: 28px;
- position: relative;
- top: 3px;
- }
- small {
- font-weight: normal;
- line-height: 1;
- color: #B3B3B3;
- }
-}
-
-.page-header-button {
- transition: all 0.4s ease-in-out;
- opacity: 0.3;
- font-weight: 500;
- border-radius: 0;
- float: right;
- outline: none;
- border: 1px solid #fff;
- padding: 16px 36px;
- font-size: 23px;
- line-height: 23px;
- border-radius: 0;
- padding-top: 14px;
- color: #fff;
- background-color: rgba(0, 0, 0, 0);
- font-weight: 500;
-
- &:hover {
- background-color: #ffffff;
- color: #333;
- opacity: 1;
- }
-}
-.widget {
- width: 100%;
- min-height: 148px;
- margin-bottom: 20px;
- border-radius: 0;
- position: relative;
-}
-
-.widget-head {
- width: 100%;
- padding: 15px;
-}
-
-.widget-title {
- font-size: 14px;
-}
-.widget-function {
-
-}
-.widget-fluctuation-period-text {
- display: inline-block;
- font-size: 16px;
- line-height: 20px;
- margin-bottom: 9px;
-}
-.widget-body {
- padding: 13px 15px;
- width: 100%;
-}
-.row-content {
- padding: 20px;
-}
-
-.widget-fluctuation-description-text{
-margin-top: 4px;
- display: block;
- font-size: 12px;
- line-height: 13px;
- }
-
-.text-success {
-
-}
-.widget-fluctuation-tpl-btn {
-
-}
-.widget-fluctuation-description-amount {
- display: block;
- font-size: 20px;
- line-height: 22px;
-}
-
-.widget-primary {
-
-}
-
-.widget-statistic-header {
- position: relative;
- z-index: 35;
- display: block;
- font-size: 14px;
- text-transform: uppercase;
- margin-bottom: 8px;
-}
- .widget-body-md {
- height: 200px;
- }
-.widget-body-lg {
- min-height: 330px;
- // height: 330px;
-}
-.widget-margin-bottom-lg {
- margin-bottom: 20px;
-}
-
-.tpl-table-black-operation {
-
-}
-
-
-.tpl-table-black-operation {
- a {
- display: inline-block;
- padding: 5px 6px;
- font-size: 12px;
- line-height: 12px;
- }
-}
-.tpl-switch input[type="checkbox"] {
- position: absolute;
- opacity: 0;
- width: 50px;
- height: 20px;
- }
-
-
- .tpl-switch input[type="checkbox"].ios-switch + div {
- vertical-align: middle;
- width: 40px;
- height: 20px;
-
- border-radius: 999px;
- background-color: rgba(0, 0, 0, 0.1);
- -webkit-transition-duration: .4s;
- -webkit-transition-property: background-color, box-shadow;
-
- margin-top: 6px;
- }
-
-
- .tpl-switch input[type="checkbox"].ios-switch:checked + div {
- width: 40px;
- background-position: 0 0;
- background-color: #36c6d3;
-
-
- }
-
-
- .tpl-switch input[type="checkbox"].tinyswitch.ios-switch + div {
- width: 34px;
- height: 18px;
- }
-
-
- .tpl-switch input[type="checkbox"].bigswitch.ios-switch + div {
- width: 50px;
- height: 25px;
- }
-
-
- .tpl-switch input[type="checkbox"].green.ios-switch:checked + div {
- background-color: #00e359;
- border: 1px solid rgba(0, 162, 63, 1);
- box-shadow: inset 0 0 0 10px rgba(0, 227, 89, 1);
- }
-
-
- .tpl-switch input[type="checkbox"].ios-switch + div > div {
- float: left;
- width: 18px;
- height: 18px;
- border-radius: inherit;
- background: #ffffff;
- -webkit-transition-timing-function: cubic-bezier(.54, 1.85, .5, 1);
- -webkit-transition-duration: 0.4s;
- -webkit-transition-property: transform, background-color, box-shadow;
- -moz-transition-timing-function: cubic-bezier(.54, 1.85, .5, 1);
- -moz-transition-duration: 0.4s;
- -moz-transition-property: transform, background-color;
-
- pointer-events: none;
- margin-top: 1px;
- margin-left: 1px;
- }
-
-
- .tpl-switch input[type="checkbox"].ios-switch:checked + div > div {
- -webkit-transform: translate3d(20px, 0, 0);
- -moz-transform: translate3d(20px, 0, 0);
- background-color: #ffffff;
-
- }
-
-
- .tpl-switch input[type="checkbox"].tinyswitch.ios-switch + div > div {
- width: 16px;
- height: 16px;
- margin-top: 1px;
- }
-
-
- .tpl-switch input[type="checkbox"].tinyswitch.ios-switch:checked + div > div {
- -webkit-transform: translate3d(16px, 0, 0);
- -moz-transform: translate3d(16px, 0, 0);
- box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3), 0px 0px 0 1px rgba(8, 80, 172, 1);
- }
-
-
- .tpl-switch input[type="checkbox"].bigswitch.ios-switch + div > div {
- width: 23px;
- height: 23px;
- margin-top: 1px;
- }
-
-
- .tpl-switch input[type="checkbox"].bigswitch.ios-switch:checked + div > div {
- -webkit-transform: translate3d(25px, 0, 0);
- -moz-transform: translate3d(16px, 0, 0);
-
- }
-
-
- .tpl-switch input[type="checkbox"].green.ios-switch:checked + div > div {
- box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(0, 162, 63, 1);
- }
-
-
-
-.tpl-page-state {
- width: 100%;
-}
-
-.tpl-page-state-title {
- font-size: 40px;
- font-weight: bold;
-}
-
-.tpl-page-state-content {
- padding: 10px 0;
-}
-
-.tpl-login {
- width: 100%;
-}
-
-.tpl-login-logo {
- max-width: 159px;
- height: 205px;
- margin: 0 auto;
- margin-bottom: 20px;
-}
-.tpl-login-title {
- width: 100%;
- font-size: 24px;
-}
-.tpl-login-content {
- width: 300px;
- margin: 12% auto 0;
-}
-.tpl-login-remember-me {
- color: #B3B3B3;
- font-size: 14px;
-
- label {
- position: relative;
- top: -2px;
- }
-}
-.tpl-login-content-info {
- color: #B3B3B3;
- font-size: 14px;
-}
-
-.tpl-pagination {
-
-}
-
-.cl-p {
- padding: 0!important;
-}
-.tpl-table-line-img {
- max-width: 100px;
- padding: 2px;
-}
-.tpl-table-list-select {
- text-align:right;
- }
-.fc-button-group, .fc button {
- display: block;
-}
-
-.theme-white {
-
- .sidebar-nav-sub {
- .sidebar-nav-link-logo {
- margin-left: 10px;
- }
- }
- .tpl-header-search-box:hover, .tpl-header-search-box:active
- .tpl-error-title {
-
- color: #848c90;
- }
- .tpl-error-title-info {
- line-height: 30px;
- font-size: 21px;
- margin-top: 20px;
- text-align: center;
- color: #dce2ec;
- }
- .tpl-error-btn {
- background: #03a9f3;
- border: 1px solid #03a9f3;
- border-radius: 30px;
- padding: 6px 20px 8px;
- }
- .tpl-error-content {
- margin-top: 20px;
- margin-bottom: 20px;
- font-size: 16px;
- text-align: center;
- color: #96a2b4;
- }
-.tpl-calendar-box {
- background: #fff;
- border-radius: 4px;
- padding: 20px;
- .fc-event {
- border-radius: 0;
- background: #03a9f3;
- border: 1px solid #14b0f6;
- }
- .fc-axis {
- color: #868E8E;
- }
- .fc-unthemed .fc-today {
- background: #eee;
- }
- .fc-more {
- color: #868E8E;
- }
-
- .fc th.fc-widget-header {
- background: #32c5d2!important;
-
- color: #ffffff;
- font-size: 14px;
- line-height: 20px;
- padding: 7px 0px;
- text-transform: uppercase;
- border:none!important;
- a {
- color: #fff;
- }
- }
-
- .fc-center {
- h2 {
- color:#868E8E;
- }
- }
- .fc-state-default {
- background-image: none;
- background: #fff;
- font-size: 14px;
- color: #868E8E;
-}
- .fc th, .fc td, .fc hr, .fc thead, .fc tbody, .fc-row {
- // background: rgba(0, 0, 0, 0)!important;
- border-color: #eee!important;
- }
- .fc-day-number {
- color: #868E8E;
- padding-right: 6px;
- }
- .fc th {
- color: #868E8E;
- font-weight: normal;
- font-size: 14px;
- padding: 6px 0;
- }
- }
-
- .tpl-login-logo {
- background: url(../img/logoa.png) center no-repeat;
-
- }
- .sub-active {
-
- color:#23abf0!important;
- }
-.tpl-table-line-img {
- border: 1px solid #ddd;
-}
-.tpl-pagination .am-disabled a , .tpl-pagination li a {
- color: #23abf0;
- border-radius: 3px;
- padding: 6px 12px;
-}
-
-.tpl-pagination .am-active a{
- background: #23abf0;color: #fff;
- border: 1px solid #23abf0;
- padding: 6px 12px;
-}
-
-
-.tpl-login-btn {
- background-color:#32c5d2;
- border: none;
- padding: 10px 16px;
- font-size: 14px;
- line-height: 14px;
- outline: none;
-
- &:hover,&:active {
- background: #22b2e1;
- color:#fff;
- }
-
-}
-.tpl-login-title {
- color: #697882;
- strong {
- color: #39bae4;
- }
-}
- .tpl-login-content{
- width: 500px;
- padding: 40px 40px 25px;
- background-color: #fff;
- border-radius: 4px;
- }
-
- .tpl-form-line-form , .tpl-form-border-form {
- padding-top: 20px;
- }
-
-
-.tpl-form-border-form input[type=number]:focus, .tpl-form-border-form input[type=search]:focus, .tpl-form-border-form input[type=text]:focus, .tpl-form-border-form input[type=password]:focus, .tpl-form-border-form input[type=datetime]:focus, .tpl-form-border-form input[type=datetime-local]:focus, .tpl-form-border-form input[type=date]:focus, .tpl-form-border-form input[type=month]:focus, .tpl-form-border-form input[type=time]:focus, .tpl-form-border-form input[type=week]:focus, .tpl-form-border-form input[type=email]:focus, .tpl-form-border-form input[type=url]:focus, .tpl-form-border-form input[type=tel]:focus, .tpl-form-border-form input[type=color]:focus, .tpl-form-border-form select:focus, .tpl-form-border-form textarea:focus, .am-form-field:focus{
- -webkit-box-shadow: none;
- box-shadow: none;
- }
-.tpl-form-border-form input[type=number], .tpl-form-border-form input[type=search], .tpl-form-border-form input[type=text], .tpl-form-border-form input[type=password], .tpl-form-border-form input[type=datetime], .tpl-form-border-form input[type=datetime-local], .tpl-form-border-form input[type=date], .tpl-form-border-form input[type=month], .tpl-form-border-form input[type=time], .tpl-form-border-form input[type=week], .tpl-form-border-form input[type=email], .tpl-form-border-form input[type=url], .tpl-form-border-form input[type=tel], .tpl-form-border-form input[type=color], .tpl-form-border-form select, .tpl-form-border-form textarea, .am-form-field {
- display: block;
- width: 100%;
-
- padding: 6px 12px;
- font-size: 14px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border: 1px solid #c2cad8;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- -webkit-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- border: 1px solid #c2cad8;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- text-indent: .5em;
- -o-border-radius: 0;
- border-radius: 0;
- color: #555;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-
-.tpl-form-border-form .am-checkbox, .tpl-form-border-form .am-checkbox-inline, .tpl-form-border-form .am-form-label, .tpl-form-border-form .am-radio, .tpl-form-border-form .am-radio-inline{
- margin-top: 0;
- margin-bottom: 0;
-
-}
-
-.tpl-form-border-form .am-form-group:after {
- clear: both;
-}
-.tpl-form-border-form .am-form-group:after, .tpl-form-border-form .am-form-group:before {
-content: " ";
- display: table;
-
-}
-.tpl-form-border-form .am-form-label{
- padding-top: 5px;
-font-size: 16px;
-color: #888;
-font-weight: inherit;
-text-align: right;
-}
-.tpl-form-border-form .am-form-group {
- /*padding: 20px 0;*/
-
-}
-.tpl-form-border-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-
- .tpl-form-line-form input[type=number]:focus, .tpl-form-line-form input[type=search]:focus, .tpl-form-line-form input[type=text]:focus, .tpl-form-line-form input[type=password]:focus, .tpl-form-line-form input[type=datetime]:focus, .tpl-form-line-form input[type=datetime-local]:focus, .tpl-form-line-form input[type=date]:focus, .tpl-form-line-form input[type=month]:focus, .tpl-form-line-form input[type=time]:focus, .tpl-form-line-form input[type=week]:focus, .tpl-form-line-form input[type=email]:focus, .tpl-form-line-form input[type=url]:focus, .tpl-form-line-form input[type=tel]:focus, .tpl-form-line-form input[type=color]:focus, .tpl-form-line-form select:focus, .tpl-form-line-form textarea:focus, .am-form-field:focus{
- -webkit-box-shadow: none;
- box-shadow: none;
- }
-.tpl-form-line-form input[type=number], .tpl-form-line-form input[type=search], .tpl-form-line-form input[type=text], .tpl-form-line-form input[type=password], .tpl-form-line-form input[type=datetime], .tpl-form-line-form input[type=datetime-local], .tpl-form-line-form input[type=date], .tpl-form-line-form input[type=month], .tpl-form-line-form input[type=time], .tpl-form-line-form input[type=week], .tpl-form-line-form input[type=email], .tpl-form-line-form input[type=url], .tpl-form-line-form input[type=tel], .tpl-form-line-form input[type=color], .tpl-form-line-form select, .tpl-form-line-form textarea, .am-form-field {
- display: block;
- width: 100%;
-
- padding: 6px 12px;
- font-size: 14px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border: 1px solid #c2cad8;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- -webkit-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- border-bottom: 1px solid #c2cad8;
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- -o-border-radius: 0;
- border-radius: 0;
- color: #555;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-
-.tpl-form-line-form .am-checkbox, .tpl-form-line-form .am-checkbox-inline, .tpl-form-line-form .am-form-label, .tpl-form-line-form .am-radio, .tpl-form-line-form .am-radio-inline{
- margin-top: 0;
- margin-bottom: 0;
-
-}
-
-.tpl-form-line-form .am-form-group:after {
- clear: both;
-}
-.tpl-form-line-form .am-form-group:after, .tpl-form-line-form .am-form-group:before {
-content: " ";
- display: table;
-
-}
-.tpl-form-line-form .am-form-label{
- padding-top: 5px;
-font-size: 16px;
-color: #888;
-font-weight: inherit;
-text-align: right;
-}
-.tpl-form-line-form .am-form-group {
- /*padding: 20px 0;*/
-
-}
-.tpl-form-line-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-
- .tpl-table-black-operation {
- a {
- border: 1px solid #36c6d3;
- color:#36c6d3;
- &:hover {
- background: #36c6d3;
- color:#fff;
- }
- }
- a.tpl-table-black-operation-del {
- border: 1px solid #e7505a;
- color:#e7505a;
- &:hover {
- background: #e7505a;
- color:#fff;
- }
- }
-}
- .tpl-amendment-echarts {
- left: -17px;
- }
- .tpl-user-card {
- border: 1px solid #3598dc;
- border-top: 2px solid #3598dc;
- background: #3598dc;
- color: #ffffff;
- border-radius: 4px;
- }
- .tpl-user-card-title {
- font-size: 26px;
- margin-top: 0;
- font-weight: 300;
- margin-top: 25px;
- margin-bottom: 10px;
- }
- .achievement-subheading {
- font-size: 12px;
- margin-top: 0;
- margin-bottom: 15px;
- }
- .achievement-image {
- border-radius: 50%;
- margin-bottom: 22px;
- }
- .achievement-description {
- margin: 0;
- font-size: 12px;
- }
-
- .tpl-table-black {
- color: #838FA1;
-
- thead>tr>th {
- font-size: 14px;
- padding: 6px;
- }
- tbody>tr>td {
- font-size: 14px;
- padding: 7px 6px;
-
- }
- tfoot>tr>th {
- font-size: 14px;
- padding: 6px 0;
- }
- }
-
-
- .am-progress {
- height: 12px;
- }
- .am-progress-title {
- font-size: 14px;
- margin-bottom: 8px;
- }
- .am-progress-title-more {
-
- }
- .widget-fluctuation-tpl-btn {
- margin-top: 6px;
- display: block;
- color: #fff;
- font-size: 12px;
- padding: 8px 14px;
- outline: none;
- background-color: #e7505a;
- border: 1px solid #e7505a;
- &:hover {
- background:transparent;
- color:#e7505a;
- }
-
- }
- .widget-fluctuation-description-text{
-color: #c5cacd;
- }
- background: #e9ecf3;
- .widget-fluctuation-period-text {
- color:#838FA1;
- }
-.text-success {
- color: #5eb95e;
-}
- .widget-head {
- border-bottom: 1px solid #eef1f5;
-}
- .widget-function {
- a {
- color: #838FA1;
- &:hover {
- color:#a7bdcd;
- }
- }
-
- }
- .widget {
- padding: 10px 20px 13px;
- background-color: #fff;
- border-radius: 4px;
- color: #838FA1;
-
- }
- .widget-title {
- font-size: 16px;
- }
-
- .widget-primary {
-
- min-height: 174px;
- border: 1px solid #32c5d2;
- border-top: 2px solid #32c5d2;
- background: #32c5d2;
- color: #ffffff;
- padding: 12px 17px;
- padding-left: 22px;
-}
-.widget-statistic-body {
-
-}
-.widget-statistic-icon {
- position: absolute;
- z-index: 30;
- right: 30px;
- top: 24px;
- font-size: 70px;
- color: #46cad6;
-}
-.widget-statistic-description {
- position: relative;
- z-index: 35;
- display: block;
- font-size: 14px;
- line-height: 14px;
- padding-top: 8px;
- color: #fff;
-}
-.widget-statistic-value {
- position: relative;
- z-index: 35;
- font-weight: 300;
- display: block;
- color: #fff;
- font-size: 46px;
- line-height: 46px;
- margin-bottom: 8px;
-}
-.widget-statistic-header {
- padding-top: 18px;
- color: #fff;
-}
-.widget-purple {
- padding: 12px 17px;
- border: 1px solid #8E44AD;
- border-top: 2px solid #8E44AD;
- background: #8E44AD;
- color: #ffffff;
- min-height: 174px;
- .widget-statistic-icon {
- color: #9956b5;
- }
- .widget-statistic-header {
- color: #ded5e7;
- }
- .widget-statistic-description {
- color: #ded5e7;
- }
-}
- .page-header-button {
- opacity: .8;
- border: 1px solid #32c5d2;
- background: #32c5d2;
- color:#fff;
- &:hover {
- opacity: 1;
- }
- }
- .page-header-description {
- color: #666;
- }
- .page-header-heading {
- color: #666;
- }
- .container-fluid {
-
- }
- ul.tpl-dropdown-content .tpl-dropdown-menu-messages-item .menu-messages-content .menu-messages-content-time {
- color: #96a5aa;
- }
- ul.tpl-dropdown-content {
- background: #fff;
- border: 1px solid #ddd;
- .tpl-dropdown-menu-notifications-item , .tpl-dropdown-menu-messages-item {
- border-bottom: 1px solid #eee;
- color:#999;
-
- &:hover{
- background-color: #f5f5f5;
- }
- .tpl-dropdown-menu-notifications-time {
- color: #999;
- }
- }
- .tpl-dropdown-menu-messages-item:hover {
- background-color: #f5f5f5;
- }
-
- .tpl-dropdown-menu-notifications-title {
- color:#999;
- }
-
-
- }
- .sidebar-nav-link {
- a {
- border-left: #fff 3px solid;
- }
- a:hover {
-
- background: #f2f6f9;
- color: #868E8E;
- border-left: #3bb4f2 3px solid;
- }
- }
-
- .sidebar-nav-link a.active {
- background: #f2f6f9;
- color: #868E8E;
- border-left: #3bb4f2 3px solid;
- }
- .sidebar-nav-heading {
- color: #999;
- border-bottom: 1px solid #eee;
- }
- .tpl-sidebar-user-panel {
- background: #fff;
- border-bottom: 1px solid #eee;
- }
-.tpl-content-wrapper {
- background: #e9ecf3;
- }
- .tpl-header-fluid {
- background: #fff;
- border-top: 1px solid #eee;
-}
- .tpl-header-logo {
- background: #fff;
- border-bottom: 1px solid #eee;
-}
-
-.tpl-header-switch-button {
- background: #fff;
- border-right: 1px solid #eee;
- border-left: 1px solid #eee;
- &:hover {
- background: #fff;
- color: #999;
- }
-}
- .tpl-header-navbar {
- a {
- color:#999;
-
- &:hover {
- color: #999;
- }
- }
- }
- .left-sidebar {
- background: #fff;
- }
-
- .widget-color-green {
- border: 1px solid #32c5d2;
- border-top: 2px solid #32c5d2;
- background: #32c5d2;
- color: #ffffff;
- .widget-fluctuation-period-text {
- color:#fff;
- }
- .widget-head {
- border-bottom: 1px solid #2bb8c4;
- }
- .widget-fluctuation-description-text {
- color:#bbe7f6;
- }
- .widget-function {
- a {
- color:#42bde5;
- &:hover {
- color: #fff;
- }
- }
- }
- }
-
-
-
-}
-
-
-.theme-black {
-
- .tpl-am-model-bd {
- background: #424b4f;
- }
- .tpl-model-dialog {
- background: #424b4f;
- }
- .tpl-error-title {
- font-size: 210px;
- line-height: 220px;
- color: #868E8E;
- }
- .tpl-error-title-info {
- line-height: 30px;
- font-size: 21px;
- margin-top: 20px;
- text-align: center;
- color: #868E8E;
- }
- .tpl-error-btn {
- background: #03a9f3;
- border: 1px solid #03a9f3;
- border-radius: 30px;
- padding: 6px 20px 8px;
- }
- .tpl-error-content {
- margin-top: 20px;
- margin-bottom: 20px;
- font-size: 16px;
- text-align: center;
- color: #cfcfcf;
- }
- .tpl-calendar-box {
- background: #424b4f;
- padding: 20px;
- .fc-button {
- border-radius: 0;
- box-shadow:0;
- }
- .fc-event {
- border-radius: 0;
- background: #03a9f3;
- }
- .fc-axis {
- color: #fff;
- }
- .fc-unthemed .fc-today {
- background: #3a4144;
- }
- .fc-more {
- color: #fff;
- }
- .fc th.fc-widget-header {
- background: #9675ce!important;
- color: #ffffff;
- font-size: 14px;
- line-height: 20px;
- padding: 7px 0px;
- text-transform: uppercase;
- border:none!important;
- a {
- color: #fff;
- }
- }
-
- .fc-center {
- h2 {
- color:#fff;
- }
- }
- .fc-state-default {
- background-image: none;
- background: #fff;
- font-size: 14px;
-}
- .fc th, .fc td, .fc hr, .fc thead, .fc tbody, .fc-row {
- // background: rgba(0, 0, 0, 0)!important;
- border-color: rgba(120, 130, 140, 0.4) !important;
- }
- .fc-day-number {
- color: #868E8E;
- padding-right: 6px;
- }
- .fc th {
- color: #868E8E;
- font-weight: normal;
- font-size: 14px;
- padding: 6px 0;
- }
- }
- .tpl-login-logo {
- background: url(../img/logob.png) center no-repeat;
-
- }
- .tpl-table-line-img {
- max-width: 100px;
- padding: 2px;
-border: none;
-}
- .tpl-table-list-field {
- border: none;
- }
- .tpl-table-list-select {
-
- .am-dropdown-content {
- color:#888;
- }
- .am-selected-btn {
- border:1px solid rgba(255, 255, 255, 0.2);
- color:#fff;
- }
-
- .am-btn-default.am-active, .am-btn-default:active, .am-dropdown.am-active .am-btn-default.am-dropdown-toggle {
- border:1px solid rgba(255, 255, 255, 0.2);
- color:#fff;
- background: #5d6468;
- }
- }
-.tpl-pagination .am-disabled a , .tpl-pagination li a {
- color: #fff;
- padding: 6px 12px;
- background: #3f4649;
- border: none;
-}
-
-.tpl-pagination .am-active a{
- background: #167fa1;color: #fff;
- border: 1px solid #167fa1;
- padding: 6px 12px;
-}
-
-.tpl-login-btn {
- border: 1px solid #b5b5b5;
- background-color: rgba(0, 0, 0, 0);
- padding: 10px 16px;
- font-size: 14px;
- line-height: 14px;
- color:#b5b5b5;
-
- &:hover,&:active {
- background: #b5b5b5;
- color:#fff;
- }
-
-}
-.tpl-login-title {
- color:#fff;
- strong {
- color: #39bae4;
- }
-}
-
-
-
-
- .tpl-form-line-form , .tpl-form-border-form {
- padding-top: 20px;
-
- .am-btn-default {
- color:#fff;
- border: 1px solid rgba(255, 255, 255, 0.2);
-
- }
- .am-selected-text {
- color:#888;
- }
- }
- .tpl-form-border-form input[type=number]:focus, .tpl-form-border-form input[type=search]:focus, .tpl-form-border-form input[type=text]:focus, .tpl-form-border-form input[type=password]:focus, .tpl-form-border-form input[type=datetime]:focus, .tpl-form-border-form input[type=datetime-local]:focus, .tpl-form-border-form input[type=date]:focus, .tpl-form-border-form input[type=month]:focus, .tpl-form-border-form input[type=time]:focus, .tpl-form-border-form input[type=week]:focus, .tpl-form-border-form input[type=email]:focus, .tpl-form-border-form input[type=url]:focus, .tpl-form-border-form input[type=tel]:focus, .tpl-form-border-form input[type=color]:focus, .tpl-form-border-form select:focus, .tpl-form-border-form textarea:focus, .am-form-field:focus{
- -webkit-box-shadow: none;
- box-shadow: none;
- }
-.tpl-form-border-form input[type=number], .tpl-form-border-form input[type=search], .tpl-form-border-form input[type=text], .tpl-form-border-form input[type=password], .tpl-form-border-form input[type=datetime], .tpl-form-border-form input[type=datetime-local], .tpl-form-border-form input[type=date], .tpl-form-border-form input[type=month], .tpl-form-border-form input[type=time], .tpl-form-border-form input[type=week], .tpl-form-border-form input[type=email], .tpl-form-border-form input[type=url], .tpl-form-border-form input[type=tel], .tpl-form-border-form input[type=color], .tpl-form-border-form select, .tpl-form-border-form textarea, .am-form-field {
- display: block;
- width: 100%;
-
- padding: 6px 12px;
- font-size: 14px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border: 1px solid #c2cad8;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- -webkit-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- text-indent: .5em;
- border: 1px solid rgba(255, 255, 255, 0.2);
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- -o-border-radius: 0;
- border-radius: 0;
- color: #fff;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-
-.tpl-form-border-form .am-checkbox, .tpl-form-border-form .am-checkbox-inline, .tpl-form-border-form .am-form-label, .tpl-form-border-form .am-radio, .tpl-form-border-form .am-radio-inline{
- margin-top: 0;
- margin-bottom: 0;
-
-}
-
-.tpl-form-border-form .am-form-group:after {
- clear: both;
-}
-.tpl-form-border-form .am-form-group:after, .tpl-form-border-form .am-form-group:before {
-content: " ";
- display: table;
-
-}
-.tpl-form-border-form .am-form-label{
- padding-top: 5px;
-font-size: 16px;
-color: #fff;
-font-weight: inherit;
-text-align: right;
-}
-.tpl-form-border-form .am-form-group {
- /*padding: 20px 0;*/
-
-}
-.tpl-form-border-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-
-
-
-
-
-
- .tpl-form-line-form input[type=number]:focus, .tpl-form-line-form input[type=search]:focus, .tpl-form-line-form input[type=text]:focus, .tpl-form-line-form input[type=password]:focus, .tpl-form-line-form input[type=datetime]:focus, .tpl-form-line-form input[type=datetime-local]:focus, .tpl-form-line-form input[type=date]:focus, .tpl-form-line-form input[type=month]:focus, .tpl-form-line-form input[type=time]:focus, .tpl-form-line-form input[type=week]:focus, .tpl-form-line-form input[type=email]:focus, .tpl-form-line-form input[type=url]:focus, .tpl-form-line-form input[type=tel]:focus, .tpl-form-line-form input[type=color]:focus, .tpl-form-line-form select:focus, .tpl-form-line-form textarea:focus, .am-form-field:focus{
- -webkit-box-shadow: none;
- box-shadow: none;
- }
-.tpl-form-line-form input[type=number], .tpl-form-line-form input[type=search], .tpl-form-line-form input[type=text], .tpl-form-line-form input[type=password], .tpl-form-line-form input[type=datetime], .tpl-form-line-form input[type=datetime-local], .tpl-form-line-form input[type=date], .tpl-form-line-form input[type=month], .tpl-form-line-form input[type=time], .tpl-form-line-form input[type=week], .tpl-form-line-form input[type=email], .tpl-form-line-form input[type=url], .tpl-form-line-form input[type=tel], .tpl-form-line-form input[type=color], .tpl-form-line-form select, .tpl-form-line-form textarea, .am-form-field {
- display: block;
- width: 100%;
-
- padding: 6px 12px;
- font-size: 14px;
- line-height: 1.42857;
- color: #4d6b8a;
- background-color: #fff;
- background-image: none;
- border: 1px solid #c2cad8;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
- -webkit-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- -o-transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- transition: border-color ease-in-out 0.15s,box-shadow ease-in-out 0.15s;
- background: 0 0;
- border: 0;
- border-bottom: 1px solid rgba(255, 255, 255, 0.2);
- -webkit-border-radius: 0;
- -moz-border-radius: 0;
- -ms-border-radius: 0;
- -o-border-radius: 0;
- border-radius: 0;
- color: #fff;
- box-shadow: none;
- padding-left: 0;
- padding-right: 0;
- font-size: 14px;
-}
-
-.tpl-form-line-form .am-checkbox, .tpl-form-line-form .am-checkbox-inline, .tpl-form-line-form .am-form-label, .tpl-form-line-form .am-radio, .tpl-form-line-form .am-radio-inline{
- margin-top: 0;
- margin-bottom: 0;
-
-}
-
-.tpl-form-line-form .am-form-group:after {
- clear: both;
-}
-.tpl-form-line-form .am-form-group:after, .tpl-form-line-form .am-form-group:before {
-content: " ";
- display: table;
-
-}
-.tpl-form-line-form .am-form-label{
- padding-top: 5px;
-font-size: 16px;
-color: #fff;
-font-weight: inherit;
-text-align: right;
-}
-
-
-
-.tpl-form-line-form .am-form-group {
- /*padding: 20px 0;*/
-
-}
-.tpl-form-line-form .am-form-label .tpl-form-line-small-title {
- color: #999;
- font-size: 12px;
-}
-
- background-color: #282d2f;
-
- .tpl-table-black-operation {
- a {
- border: 1px solid #7b878d;
- color:#7b878d;
- &:hover {
- background: #7b878d;
- color:#fff;
- }
- }
- a.tpl-table-black-operation-del {
- border: 1px solid #f35842;
- color:#f35842;
- &:hover {
- background: #f35842;
- color:#fff;
- }
- }
-}
- .am-table-bordered {
- border: 1px solid #666d70;
- }
- .am-table-bordered>tbody>tr>td, .am-table-bordered>tbody>tr>th, .am-table-bordered>tfoot>tr>td, .am-table-bordered>tfoot>tr>th, .am-table-bordered>thead>tr>td, .am-table-bordered>thead>tr>th {
- border: 1px solid #666d70;
- }
-
- .am-table-bordered>thead+tbody>tr:first-child>td, .am-table-bordered>thead+tbody>tr:first-child>th {
- border: 1px solid #666d70;
- }
-
- .am-table-striped>tbody>tr:nth-child(odd)>td, .am-table-striped>tbody>tr:nth-child(odd)>th {
- background-color: #5d6468;
- }
- .tpl-table-black {
- color:#fff;
-
- thead>tr>th {
- font-size: 14px;
- padding: 6px;
- border-bottom: 1px solid #666d70;
- }
- tbody>tr>td {
- font-size: 14px;
- padding: 7px 6px;
- border-top: 1px solid #666d70;
- }
- tfoot>tr>th {
- font-size: 14px;
- padding: 6px 0;
- }
- }
- .tpl-user-card {
- border: 1px solid #11627d;
- border-top: 2px solid #105f79;
- background: #1786aa;
- color: #ffffff;
- }
- .tpl-user-card-title {
- font-size: 26px;
- margin-top: 0;
- font-weight: 300;
- margin-top: 25px;
- margin-bottom: 10px;
- }
- .achievement-subheading {
- font-size: 12px;
- margin-top: 0;
- margin-bottom: 15px;
- }
- .achievement-image {
- border-radius: 50%;
- margin-bottom: 22px;
- }
- .achievement-description {
- margin: 0;
- font-size: 12px;
- }
-
-
-
- .am-progress {
- height: 12px;
- margin-bottom: 14px;
- background: rgba(0, 0, 0, 0.15);
- }
- .am-progress-title {
- font-size: 14px;
- margin-bottom: 8px;
- }
- .am-progress-title-more {
- color: #a1a8ab;
- }
- .widget-fluctuation-tpl-btn {
- margin-top: 6px;
- display: block;
- color: #fff;
- font-size: 12px;
- padding: 5px 10px;
- outline: none;
- background-color: rgba(255, 255, 255, 0);
- border: 1px solid #fff;
- &:hover {
- background: #fff;
- color:#4b5357;
- }
-
- }
-.widget-fluctuation-description-text{
-color: #c5cacd;
- }
-
- .text-success {
- color: #08ed72;
-}
-.widget-fluctuation-period-text {
- color:#fff;
- }
-
- .widget-head {
- border-bottom: 1px solid #3f4649;
-}
- .widget-function {
- a {
- color:#7b878d;
- &:hover {
- color:#fff;
- }
- }
-
- }
- .widget {
- border: 1px solid #33393c;
- border-top: 2px solid #313639;
- background: #4b5357;
- color: #ffffff;
- }
- .widget-primary {
- border: 1px solid #11627d;
- border-top: 2px solid #105f79;
- background: #1786aa;
- color: #ffffff;
- padding: 12px 17px;
-}
-.widget-statistic-body {
-
-}
-.widget-statistic-icon {
- position: absolute;
- z-index: 30;
- right: 30px;
- top: 0px;
- font-size: 70px;
- color: #1b9eca;
-}
-.widget-statistic-description {
- position: relative;
- z-index: 35;
- display: block;
- font-size: 14px;
- line-height: 14px;
- padding-top: 8px;
- color: #9cdcf2;
-}
-.widget-statistic-value {
- position: relative;
- z-index: 35;
- font-weight: 300;
- display: block;
- color: #fff;
- font-size: 46px;
- line-height: 46px;
- margin-bottom: 8px;
-}
-.widget-statistic-header {
- color: #9cdcf2;
-}
-
-.widget-purple {
- padding: 12px 17px;
- border: 1px solid #5e4578;
- border-top: 2px solid #5c4375;
- background: #785799;
- color: #ffffff;
- .widget-statistic-icon {
- color: #8a6aaa;
- }
- .widget-statistic-header {
- color: #ded5e7;
- }
- .widget-statistic-description {
- color: #ded5e7;
- }
-}
- .page-header-description {
- color: #e6e6e6;
- }
- .page-header-heading {
- color: #666;
- }
- .container-fluid {
- background: #424b4f;
- }
- .page-header-heading {
- color: #fff;
- }
- .sidebar-nav-heading {
- color:#fff;
- }
- .tpl-sidebar-user-panel {
- background: #1f2224;
- border-bottom: 1px solid #1f2224;
-}
- .tpl-content-wrapper {
- background: #3a4144;
- }
- .tpl-header-fluid {
- background: #2f3638;
-
-}
-
- .sidebar-nav-link {
- a.active {
- background: #232829;
- }
- a:hover {
-
- background: #232829;
- }
- }
-
-.tpl-header-switch-button {
- background: #2f3638;
- border-right: 1px solid #282d2f;
- &:hover {
- background: #282d2f;
- color: #fff;
- }
-}
- .tpl-header-navbar {
- a {
- color:#cfcfcf;
-
- &:hover {
- color: #fff;
- }
- }
- }
- .left-sidebar {
- padding-top: 56px;
- background: #282d2f;
- }
-
- .widget-color-green {
- border: 1px solid #11627d;
- border-top: 2px solid #105f79;
- background: #1786aa;
- color: #ffffff;
- .widget-head {
- border-bottom: 1px solid #147494;
- }
- .widget-fluctuation-description-text {
- color:#bbe7f6;
- }
- .widget-function {
- a {
- color:#42bde5;
- &:hover {
- color: #fff;
- }
- }
- }
- }
-}
-
-
-
-@media screen and (max-width: 1024px) {
- .tpl-index-settings-button {
- display: none;
- }
-
- .theme-black .left-sidebar {
- padding-top: 111px;
- }
- .left-sidebar {
- padding-top: 111px;
- }
- .tpl-content-wrapper {
- margin-left: 0
- }
- .tpl-header-logo {
- float:none;
- width: 100%;
- }
- .tpl-header-navbar-welcome {
- display: none;
- }
-
- .tpl-sidebar-user-panel {
- border-top: 1px solid #eee;
- }
- .tpl-header-fluid {
- border-top: none;
- margin-left: 0;
- }
-
- .theme-white .tpl-header-fluid {
- border-top: none;
- }
- .theme-black .tpl-sidebar-user-panel {
- border-top: 1px solid #1f2224;
- }
-}
-
-@media screen and (min-width: 641px) {
- [class*=am-u-] {
- padding-left: 10px;
- padding-right: 10px;
-}
-}
-@media screen and (max-width: 641px) {
-
- .theme-white , .theme-black {
- .tpl-error-title {
- font-size: 130px;
- line-height: 140px;
-
- }
- }
- .theme-white {
-
- .tpl-login-title {
- font-size: 20px;
- }
- .tpl-login-content{
- width: 86%;
- padding: 22px 30px 25px;
- }
- }
-
-
-
- .tpl-header-search {
- display: none;
- }
- ul.tpl-dropdown-content {
- position: fixed;
- width: 100%;
- left: 0;
- top: 112px;
- right: 0;
- }
-}
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/assets/css/fullcalendar.min.css b/Day61-65/code/project_of_tornado/assets/css/fullcalendar.min.css
deleted file mode 100644
index f9fa1c1..0000000
--- a/Day61-65/code/project_of_tornado/assets/css/fullcalendar.min.css
+++ /dev/null
@@ -1,5 +0,0 @@
-/*!
- * FullCalendar v0.0.0 Stylesheet
- * Docs & License: http://fullcalendar.io/
- * (c) 2016 Adam Shaw
- */.fc-icon,body .fc{font-size:1em}.fc-button-group,.fc-icon{display:inline-block}.fc-bg,.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-icon,.fc-unselectable{-khtml-user-select:none;-webkit-touch-callout:none}.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}.fc th,.fc-basic-view td.fc-week-number,.fc-icon,.fc-toolbar{text-align:center}.fc-unthemed .fc-content,.fc-unthemed .fc-divider,.fc-unthemed .fc-list-heading td,.fc-unthemed .fc-list-view,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-list-heading td,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666}.fc-unthemed .fc-today{background:#fcf8e3}.fc-highlight{background:#bce8f1;opacity:.3}.fc-bgevent{background:#8fdf82;opacity:.3}.fc-nonbusiness{background:#d7d7d7}.fc-icon{height:1em;line-height:1em;overflow:hidden;font-family:"Courier New",Courier,monospace;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon:after{position:relative}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;font-size:1em;white-space:nowrap;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;box-shadow:none}.fc-event.fc-draggable,.fc-event[href],.fc-popover .fc-header .fc-close,a[data-goto]{cursor:pointer}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-popover .fc-header .fc-close{font-size:.9em;margin-top:2px}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-bg table,.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc table{width:100%;box-sizing:border-box;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}a[data-goto]:hover{text-decoration:underline}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent;border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{-webkit-overflow-scrolling:touch}.fc-row.fc-rigid,.fc-time-grid-event{overflow:hidden}.fc-scroller>.fc-day-grid,.fc-scroller>.fc-time-grid{position:relative;width:100%}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad;font-weight:400}.fc-event,.fc-event-dot{background-color:#3a87ad}.fc-event,.fc-event:hover,.ui-widget .fc-event{color:#fff;text-decoration:none}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:4;display:none}.fc-event.fc-allow-mouse-resize .fc-resizer,.fc-event.fc-selected .fc-resizer{display:block}.fc-event.fc-selected .fc-resizer:before{content:"";position:absolute;z-index:9999;top:50%;left:50%;width:40px;height:40px;margin-left:-20px;margin-top:-20px}.fc-event.fc-selected{z-index:9999!important;box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event.fc-selected.fc-dragging{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-h-event.fc-selected:before{content:"";position:absolute;z-index:3;top:-10px;bottom:-10px;left:0;right:0}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-ltr .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-end-resizer{cursor:w-resize;left:-1px}.fc-ltr .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-start-resizer{cursor:e-resize;right:-1px}.fc-h-event.fc-allow-mouse-resize .fc-resizer{width:7px;top:-1px;bottom:-1px}.fc-h-event.fc-selected .fc-resizer{border-radius:4px;border-width:1px;width:6px;height:6px;border-style:solid;border-color:inherit;background:#fff;top:50%;margin-top:-4px}.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,.fc-rtl .fc-h-event.fc-selected .fc-end-resizer{margin-left:-4px}.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,.fc-rtl .fc-h-event.fc-selected .fc-start-resizer{margin-right:-4px}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}tr:first-child>td>.fc-day-grid-event{margin-top:2px}.fc-day-grid-event.fc-selected:after{content:"";position:absolute;z-index:1;top:-1px;right:-1px;bottom:-1px;left:-1px;background:#000;opacity:.25}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer{margin-left:-2px}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer{margin-right:-2px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-now-indicator{position:absolute;border:0 solid red}.fc-unselectable{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.fc-toolbar{margin-bottom:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc-toolbar .fc-center{display:inline-block}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar button{position:relative}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-day-top.fc-other-month{opacity:.3}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:2px}.fc-basic-view th.fc-day-number,.fc-basic-view th.fc-week-number{padding:0 2px}.fc-ltr .fc-basic-view .fc-day-top .fc-day-number{float:right}.fc-rtl .fc-basic-view .fc-day-top .fc-day-number{float:left}.fc-ltr .fc-basic-view .fc-day-top .fc-week-number{float:left;border-radius:0 0 3px}.fc-rtl .fc-basic-view .fc-day-top .fc-week-number{float:right;border-radius:0 0 0 3px}.fc-basic-view .fc-day-top .fc-week-number{min-width:1.5em;text-align:center;background-color:#f2f2f2;color:grey}.fc-basic-view td.fc-week-number>*{display:inline-block;min-width:1.25em}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px;white-space:nowrap}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.ui-widget td.fc-axis{font-weight:400}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3;position:relative}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-helper-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event.fc-selected{overflow:visible}.fc-time-grid-event.fc-selected .fc-bg{display:none}.fc-time-grid-event .fc-content{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em;white-space:nowrap}.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after{content:"="}.fc-time-grid-event.fc-selected .fc-resizer{border-radius:5px;border-width:1px;width:8px;height:8px;border-style:solid;border-color:inherit;background:#fff;left:50%;margin-left:-5px;bottom:-5px}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent}.fc-event-dot{display:inline-block;width:10px;height:10px;border-radius:5px}.fc-rtl .fc-list-view{direction:rtl}.fc-list-view{border-width:1px;border-style:solid}.fc .fc-list-table{table-layout:auto}.fc-list-table td{border-width:1px 0 0;padding:8px 14px}.fc-list-table tr:first-child td{border-top-width:0}.fc-list-heading{border-bottom-width:1px}.fc-list-heading td{font-weight:700}.fc-ltr .fc-list-heading-main{float:left}.fc-ltr .fc-list-heading-alt,.fc-rtl .fc-list-heading-main{float:right}.fc-rtl .fc-list-heading-alt{float:left}.fc-list-item.fc-has-url{cursor:pointer}.fc-list-item:hover td{background-color:#f5f5f5}.fc-list-item-marker,.fc-list-item-time{white-space:nowrap;width:1px}.fc-ltr .fc-list-item-marker{padding-right:0}.fc-rtl .fc-list-item-marker{padding-left:0}.fc-list-item-title a{text-decoration:none;color:inherit}.fc-list-item-title a[href]:hover{text-decoration:underline}.fc-list-empty-wrap2{position:absolute;top:0;left:0;right:0;bottom:0}.fc-list-empty-wrap1{width:100%;height:100%;display:table}.fc-list-empty{display:table-cell;vertical-align:middle;text-align:center}.fc-unthemed .fc-list-empty{background-color:#eee}
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/assets/css/fullcalendar.print.css b/Day61-65/code/project_of_tornado/assets/css/fullcalendar.print.css
deleted file mode 100644
index ad1a023..0000000
--- a/Day61-65/code/project_of_tornado/assets/css/fullcalendar.print.css
+++ /dev/null
@@ -1,208 +0,0 @@
-/*!
- * FullCalendar v0.0.0 Print Stylesheet
- * Docs & License: http://fullcalendar.io/
- * (c) 2016 Adam Shaw
- */
-
-/*
- * Include this stylesheet on your page to get a more printer-friendly calendar.
- * When including this stylesheet, use the media='print' attribute of the tag.
- * Make sure to include this stylesheet IN ADDITION to the regular fullcalendar.css.
- */
-
-.fc {
- max-width: 100% !important;
-}
-
-
-/* Global Event Restyling
---------------------------------------------------------------------------------------------------*/
-
-.fc-event {
- background: #fff !important;
- color: #000 !important;
- page-break-inside: avoid;
-}
-
-.fc-event .fc-resizer {
- display: none;
-}
-
-
-/* Table & Day-Row Restyling
---------------------------------------------------------------------------------------------------*/
-
-.fc th,
-.fc td,
-.fc hr,
-.fc thead,
-.fc tbody,
-.fc-row {
- border-color: #ccc !important;
- background: #fff !important;
-}
-
-/* kill the overlaid, absolutely-positioned components */
-/* common... */
-.fc-bg,
-.fc-bgevent-skeleton,
-.fc-highlight-skeleton,
-.fc-helper-skeleton,
-/* for timegrid. within cells within table skeletons... */
-.fc-bgevent-container,
-.fc-business-container,
-.fc-highlight-container,
-.fc-helper-container {
- display: none;
-}
-
-/* don't force a min-height on rows (for DayGrid) */
-.fc tbody .fc-row {
- height: auto !important; /* undo height that JS set in distributeHeight */
- min-height: 0 !important; /* undo the min-height from each view's specific stylesheet */
-}
-
-.fc tbody .fc-row .fc-content-skeleton {
- position: static; /* undo .fc-rigid */
- padding-bottom: 0 !important; /* use a more border-friendly method for this... */
-}
-
-.fc tbody .fc-row .fc-content-skeleton tbody tr:last-child td { /* only works in newer browsers */
- padding-bottom: 1em; /* ...gives space within the skeleton. also ensures min height in a way */
-}
-
-.fc tbody .fc-row .fc-content-skeleton table {
- /* provides a min-height for the row, but only effective for IE, which exaggerates this value,
- making it look more like 3em. for other browers, it will already be this tall */
- height: 1em;
-}
-
-
-/* Undo month-view event limiting. Display all events and hide the "more" links
---------------------------------------------------------------------------------------------------*/
-
-.fc-more-cell,
-.fc-more {
- display: none !important;
-}
-
-.fc tr.fc-limited {
- display: table-row !important;
-}
-
-.fc td.fc-limited {
- display: table-cell !important;
-}
-
-.fc-popover {
- display: none; /* never display the "more.." popover in print mode */
-}
-
-
-/* TimeGrid Restyling
---------------------------------------------------------------------------------------------------*/
-
-/* undo the min-height 100% trick used to fill the container's height */
-.fc-time-grid {
- min-height: 0 !important;
-}
-
-/* don't display the side axis at all ("all-day" and time cells) */
-.fc-agenda-view .fc-axis {
- display: none;
-}
-
-/* don't display the horizontal lines */
-.fc-slats,
-.fc-time-grid hr { /* this hr is used when height is underused and needs to be filled */
- display: none !important; /* important overrides inline declaration */
-}
-
-/* let the container that holds the events be naturally positioned and create real height */
-.fc-time-grid .fc-content-skeleton {
- position: static;
-}
-
-/* in case there are no events, we still want some height */
-.fc-time-grid .fc-content-skeleton table {
- height: 4em;
-}
-
-/* kill the horizontal spacing made by the event container. event margins will be done below */
-.fc-time-grid .fc-event-container {
- margin: 0 !important;
-}
-
-
-/* TimeGrid *Event* Restyling
---------------------------------------------------------------------------------------------------*/
-
-/* naturally position events, vertically stacking them */
-.fc-time-grid .fc-event {
- position: static !important;
- margin: 3px 2px !important;
-}
-
-/* for events that continue to a future day, give the bottom border back */
-.fc-time-grid .fc-event.fc-not-end {
- border-bottom-width: 1px !important;
-}
-
-/* indicate the event continues via "..." text */
-.fc-time-grid .fc-event.fc-not-end:after {
- content: "...";
-}
-
-/* for events that are continuations from previous days, give the top border back */
-.fc-time-grid .fc-event.fc-not-start {
- border-top-width: 1px !important;
-}
-
-/* indicate the event is a continuation via "..." text */
-.fc-time-grid .fc-event.fc-not-start:before {
- content: "...";
-}
-
-/* time */
-
-/* undo a previous declaration and let the time text span to a second line */
-.fc-time-grid .fc-event .fc-time {
- white-space: normal !important;
-}
-
-/* hide the the time that is normally displayed... */
-.fc-time-grid .fc-event .fc-time span {
- display: none;
-}
-
-/* ...replace it with a more verbose version (includes AM/PM) stored in an html attribute */
-.fc-time-grid .fc-event .fc-time:after {
- content: attr(data-full);
-}
-
-
-/* Vertical Scroller & Containers
---------------------------------------------------------------------------------------------------*/
-
-/* kill the scrollbars and allow natural height */
-.fc-scroller,
-.fc-day-grid-container, /* these divs might be assigned height, which we need to cleared */
-.fc-time-grid-container { /* */
- overflow: visible !important;
- height: auto !important;
-}
-
-/* kill the horizontal border/padding used to compensate for scrollbars */
-.fc-row {
- border: 0 !important;
- margin: 0 !important;
-}
-
-
-/* Button Controls
---------------------------------------------------------------------------------------------------*/
-
-.fc-button-group,
-.fc button {
- display: none; /* don't display any button-related controls */
-}
diff --git a/Day61-65/code/project_of_tornado/assets/fonts/FontAwesome.otf b/Day61-65/code/project_of_tornado/assets/fonts/FontAwesome.otf
deleted file mode 100644
index d4de13e..0000000
Binary files a/Day61-65/code/project_of_tornado/assets/fonts/FontAwesome.otf and /dev/null differ
diff --git a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.eot b/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.eot
deleted file mode 100644
index c7b00d2..0000000
Binary files a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.eot and /dev/null differ
diff --git a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.ttf b/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.ttf
deleted file mode 100644
index f221e50..0000000
Binary files a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.ttf and /dev/null differ
diff --git a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.woff b/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.woff
deleted file mode 100644
index 6e7483c..0000000
Binary files a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.woff and /dev/null differ
diff --git a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.woff2 b/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.woff2
deleted file mode 100644
index 7eb74fd..0000000
Binary files a/Day61-65/code/project_of_tornado/assets/fonts/fontawesome-webfont.woff2 and /dev/null differ
diff --git a/Day61-65/code/project_of_tornado/assets/html/404.html b/Day61-65/code/project_of_tornado/assets/html/404.html
deleted file mode 100644
index 48f614c..0000000
--- a/Day61-65/code/project_of_tornado/assets/html/404.html
+++ /dev/null
@@ -1,294 +0,0 @@
-
-
-
-
-
-
- Amaze UI Admin index Examples
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/assets/html/calendar.html b/Day61-65/code/project_of_tornado/assets/html/calendar.html
deleted file mode 100644
index 8c4cb41..0000000
--- a/Day61-65/code/project_of_tornado/assets/html/calendar.html
+++ /dev/null
@@ -1,453 +0,0 @@
-
-
-
-
-
-
- Amaze UI Admin index Examples
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/assets/html/chart.html b/Day61-65/code/project_of_tornado/assets/html/chart.html
deleted file mode 100644
index f247f77..0000000
--- a/Day61-65/code/project_of_tornado/assets/html/chart.html
+++ /dev/null
@@ -1,341 +0,0 @@
-
-
-
-
-
- Amaze UI Admin index Examples
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Day61-65/code/project_of_tornado/assets/html/form.html b/Day61-65/code/project_of_tornado/assets/html/form.html
deleted file mode 100644
index 453811e..0000000
--- a/Day61-65/code/project_of_tornado/assets/html/form.html
+++ /dev/null
@@ -1,619 +0,0 @@
-
-
-
-
-