├── .github
└── FUNDING.yml
├── .gitignore
├── README.md
├── books
└── .keep
├── data
└── .keep
├── docker-compose.yml
├── imgs
├── 00.png
├── 01.png
├── 02.png
├── 03.png
├── 04.png
├── 05.png
├── 06.png
├── 07.png
└── 08.png
├── index.html
├── nginx
├── etc
│ └── calibre_site.conf
└── html
│ ├── css
│ └── page.css
│ └── index.html
├── run.ps1
├── run.sh
├── stop.ps1
└── stop.sh
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: exppoc
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: [ 'https://lyy289065406.github.io/sponsor/' ]
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | data/
2 | books/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # calibre-docker
2 |
3 | > docker 一键部署 calibre 在线书库
4 |
5 | ------
6 |
7 | ## 概要
8 |
9 | 你是否面临以下困扰:
10 |
11 | - 想翻看曾经看过的某本小说的时候,网上已经找不到了
12 | - 即使网上找到了,因为版权原因无法在线看、甚至无法下载
13 | - 可以在线看,但是要收费
14 | - 连载小说几个月才出一册,囤了一年后却不知道自己看到哪了
15 | - 在家看小说看了一半突然要出门,打算在路上看,于是不得不把小说发送到手机
16 | - ......
17 |
18 | 其实只需要搭建一个私人书库,这些问题就迎刃而解了:
19 |
20 | - Calibre: 一款强大且易用的电子书本地管理工具,可以在 Windows、macOS 和 Linux 平台搭建个人私人的电子书书库。
21 | - Calibre-web: Calibre 的 CMS 界面,用于读取和下载 Calibre 数据库中的电子书,同时它支持 OPDS 协议
22 | - [OPDS](https://en.wikipedia.org/wiki/OPDS): 全称是 Open Publication Distribution System 开放式出版发布系统,是基于 Atom 和 Http 的一种目录格式。OPDS 主要实现 2 个功能:(1) 让电子出版物被发现,可以使用简单的搜索和一些其他的浏览器技术;(2) 让用户下载电子出版物,直接免费下载或进行出售
23 |
24 | 
25 |
26 |
27 | ## 项目说明
28 |
29 | 本仓库包含三个 docker 镜像:
30 |
31 | | 镜像 | 用途 | 服务端口 | 端口说明 |
32 | |:------:|:------:|:------:|:------|
33 | | [calibre](https://github.com/kovidgoyal/calibre) | calibre 后端 | 8080 | calibre 管理页面 |
34 | | [calibre-web](https://github.com/janeczku/calibre-web) | calibre 前端 | 8083 | CMS 页面,同时提供 OPDS 服务 |
35 | | [nginx](https://www.nginx.com/) | 反向代理 calibre 服务 | 80 | 项目说明页面 |
36 |
37 |
38 | ## 目录结构说明
39 |
40 | ```
41 | calibre-docker
42 | ├── books ....................... [缓存目录:导入电子书到 calibre 时,仅可以选择在该目录下的电子书]
43 | ├── data ........................ [存档目录:calibre 的数据库(包括电子书本身),用于数据迁移]
44 | ├── calibre
45 | │ ├── cms
46 | │ │ └── Dockerfile .......... [calibre 前端镜像构建脚本]
47 | │ └── mgr
48 | │ └── Dockerfile .......... [calibre 后端镜像构建脚本]
49 | ├── nginx
50 | │ ├── etc
51 | │ │ └── calibre_site.conf ... [代理服务配置]
52 | │ └── html .................... [代理服务主页]
53 | ├── index.html .................. [Github Paget:自动跳转到代理服务主页]
54 | ├── docker-compose.yml .......... [calibre 镜像构建脚本]
55 | ├── run.sh ...................... [calibre 服务一键启动脚本]
56 | ├── stop.sh ..................... [calibre 服务一键停止脚本]
57 | ├── imgs ........................ [README 插图目录]
58 | └── README.md ................... [本仓库说明文档]
59 | ```
60 |
61 |
62 | ## 环境要求
63 |
64 |   
65 |
66 |
67 | ## 部署步骤
68 |
69 | ### 1. 项目构建
70 |
71 | - 宿主机安装 docker、docker-compose
72 | - 宿主机安全组/防火墙(iptables/firewall)放行这些端口的入口流量: 80、8080、8081、8083
73 | - 下载仓库: `git clone -b main --single-branch https://github.com/lyy289065406/calibre-docker /usr/local/calibre-docker` (只下载 main 主分支即可)
74 | - 打开仓库目录: `cd /usr/local/calibre-docker`
75 | - 构建镜像并运行: `./run.sh -u admin -p admin123` (**完全启动约需要 2 分钟,书库越大启动越慢**)
76 |
77 | > 构建时设置的是 calibre 后端管理页面的账密,calibre-web 前端账密只能在 CMS 上修改。
78 |
79 |
80 | ### 2. 配置 calibre
81 |
82 | - 登录后端管理页面:`http://${vps-ip}/mgr/`(或 `http://${vps-ip}:8080`)
83 | - 默认登录账密: `admin / admin123`
84 | - 参考下图,根据向导进行初始化设置(必须记得配置路径为 `/config/Calibre Library`,该路径用于存储 calibre 的配置库,默认挂载到宿主机的 [`data`](data) 目录)
85 |
86 | 
87 |
88 | 
89 |
90 |
91 | ### 3. 导入本地电子书
92 |
93 | 先把电子书上传到宿主机的 [`books`](books) 目录,然后登录后台管理页面,点击【Add books】,在【/books】目录找到所上传的电子书,点击【Open】即可导入到 calibre 数据库。
94 |
95 | > 可以把个人电子书存储到另一个 Repo(如 [ebooks-library](https://github.com/lyy289065406/ebooks-library)),使用时再通过 git clone 拉取到 [`books`](books) 目录
96 |
97 | 
98 |
99 |
100 | ### 4. 配置 calibre-web
101 |
102 | - 登录前端 CMS 页面:`http://${vps-ip}/cms/`(或 `http://${vps-ip}:8083`)
103 | - 默认登录账密: `admin / admin123`
104 | - 根据向导设置 calibre 配置库路径,路径就是前面的 `/config/Calibre Library`
105 | - 成功登录后即可看到在后端管理页面导入的电子书
106 |
107 | > 点击右上角的 【admin】 即可修改用户密码
108 |
109 | 
110 |
111 | 
112 |
113 |
114 | ## 阅读设置
115 |
116 | ### 1. PC 阅读
117 |
118 | 默认情况下 admin 用户是无法在线阅读电子书的,需要先授权阅读权限:
119 |
120 | 点击右上角的【管理权限】,编辑【admin】用户,勾选【允许在线阅读】即可。
121 |
122 | 之后点击任意一本电子书,会多出一个【在线阅读】按钮:
123 |
124 | 
125 |
126 | 
127 |
128 |
129 | ### 2. 手机阅读
130 |
131 | calibre-web 提供了 OPDS 协议的服务地址:`http://${vps-ip}/cms/opds/`(或 `http://${vps-ip}:8083/opds/`)。
132 |
133 | 换言之所有支持 OPDS 协议的 APP 都可以对接到 calibre-web 获取书库中的电子书,例如这些 APP :
134 |
135 | | APP | 适用设备/系统 | 说明 |
136 | |:---:|:---:|:---|
137 | | [FullReader](https://play.google.com/store/apps/details?id=com.fullreader&hl=zh_CN) | Android | 界面清新但是有广告,而且汉化不完全,有少量韩文 |
138 | | [AIReader](https://play.google.com/store/apps/details?id=com.neverland.alreader&hl=en&gl=US) | Android | 没有广告但是外观不好看 |
139 | | kybook3 | iOS | 目前已知 iOS 唯一支持 OPDS 的 APP |
140 | | kindle | kindle | 仅在 kindle 设备上支持 OPDS,在 Android/iOS 上不支持 |
141 |
142 |
143 |
144 | 以 [FullReader](https://play.google.com/store/apps/details?id=com.fullreader&hl=zh_CN) 为例:点击【网络图书馆】->【添加OPDS目录】,填写 calibre 的 OPDS 服务地址和 BasicAuth 账号密码即可。
145 |
146 | 
147 |
148 |
149 | ## FAQ
150 |
151 | ### Q1. 迁移 data 目录的数据库后无法运行 CMS 服务
152 |
153 | 理论上 data 目录挂载了 calibre 运行所需的全部数据(包括电子书本身),只要完整迁移到任何设备就可以直接运行。
154 |
155 | 但若 calibre 非正常停止过,就会导致 calibre-web (即 CMS 服务)无法运行。
156 |
157 | 解决方法也很简单:
158 |
159 | - 执行 [`stop.sh`](stop.sh) 脚本停止 calibre 服务
160 | - 查看 [`data/.config/calibre/gui.json`](data/.config/calibre/gui.json) 的 `library_usage_stats` 状态值是否为 `1`,若不是则修改为 `1`
161 | - 执行 [`run.sh`](stop.sh) 脚本重新启动 calibre 服务,此时 CMS 服务应该可以正常启动了
162 |
163 |
164 | ### Q2. 项目仓库太大无法下载到本地
165 |
166 | 本仓库包含 main 和 produce 两个分支,其中:
167 |
168 | - main: 干净分支,纯粹用于构建私人书库
169 | - produce: 我的生产环境分支,归档了我的个人书库数据,而且会越来越大
170 |
171 | 因此 produce 分支是不需要下载的,只下载 main 主分支即可:
172 |
173 | `git clone -b main --single-branch https://github.com/lyy289065406/calibre-docker`
174 |
--------------------------------------------------------------------------------
/books/.keep:
--------------------------------------------------------------------------------
1 | git clone https://github.com/lyy289065406/ebooks-library
--------------------------------------------------------------------------------
/data/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/data/.keep
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | # How to use :
2 | # username=admin pass_md5=0192023a7bbd73250516f069df18b500 uid=1000 gid=1000 docker-compose up -d
3 | # docker-compose down
4 | # --------------------------------------------------------------------------------
5 |
6 | version: '2'
7 | services:
8 | nginx:
9 | hostname: NGINX
10 | container_name: docker_nginx
11 | image: nginx:mainline
12 | volumes:
13 | - ./nginx/etc/calibre_site.conf:/etc/nginx/conf.d/calibre_site.conf
14 | - ./nginx/html:/usr/share/nginx/html
15 | ports:
16 | - "80:80"
17 | networks:
18 | vpn:
19 | ipv4_address: 172.168.25.2
20 | restart: on-failure
21 |
22 |
23 | calibre_mgr:
24 | image: linuxserver/calibre:version-v5.2.0
25 | hostname: CALIBRE_MGR
26 | container_name: docker_calibre_mgr
27 | environment:
28 | - PUID=${uid}
29 | - PGID=${gid}
30 | - TZ=Aisa/Shanghai
31 | - GUAC_USER=${username}
32 | - GUAC_PASS=${pass_md5}
33 | - UMASK_SET=022
34 | volumes:
35 | - ./data/:/config/
36 | - ./books/:/books/
37 | ports:
38 | - "8080:8080"
39 | networks:
40 | vpn:
41 | ipv4_address: 172.168.25.3
42 | depends_on:
43 | - nginx
44 | restart: on-failure
45 |
46 |
47 | calibre_cms:
48 | image: linuxserver/calibre-web:version-0.6.12
49 | hostname: CALIBRE_CMS
50 | container_name: docker_calibre_cms
51 | environment:
52 | - PUID=${uid}
53 | - PGID=${gid}
54 | - TZ=Aisa/Shanghai
55 | - DOCKER_MODS=linuxserver/calibre-web:calibre
56 | volumes:
57 | - ./data/:/config/
58 | - ./books/:/books/
59 | ports:
60 | - "8083:8083"
61 | networks:
62 | vpn:
63 | ipv4_address: 172.168.25.4
64 | depends_on:
65 | - calibre_mgr
66 | restart: on-failure
67 |
68 |
69 | networks:
70 | vpn:
71 | driver: bridge
72 | ipam:
73 | driver: default
74 | config:
75 | - subnet: 172.168.25.0/24
76 | gateway: 172.168.25.1
77 |
78 |
79 |
--------------------------------------------------------------------------------
/imgs/00.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/00.png
--------------------------------------------------------------------------------
/imgs/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/01.png
--------------------------------------------------------------------------------
/imgs/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/02.png
--------------------------------------------------------------------------------
/imgs/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/03.png
--------------------------------------------------------------------------------
/imgs/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/04.png
--------------------------------------------------------------------------------
/imgs/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/05.png
--------------------------------------------------------------------------------
/imgs/06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/06.png
--------------------------------------------------------------------------------
/imgs/07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/07.png
--------------------------------------------------------------------------------
/imgs/08.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EXP-Tools/calibre-docker/83a30c2999cef63f1f433b97d0701aee36f67e55/imgs/08.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | CalibreLibrary
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/nginx/etc/calibre_site.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name _;
4 | charset utf-8;
5 |
6 | location /mgr/ {
7 | proxy_pass http://172.168.25.3:8080/;
8 | proxy_set_header Host $host;
9 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
10 | proxy_set_header X-Real-IP $remote_addr;
11 | proxy_set_header Upgrade-Insecure-Requests 1;
12 | proxy_set_header X-Forwarded-Proto http;
13 | }
14 |
15 | location /cms {
16 | proxy_pass http://172.168.25.4:8083;
17 | proxy_set_header Host $http_host;
18 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
19 | proxy_set_header X-Scheme $scheme;
20 | proxy_set_header X-Script-Name /cms;
21 | }
22 |
23 | location / {
24 | root /usr/share/nginx/html;
25 | index index.html index.htm;
26 | }
27 |
28 | error_page 500 502 503 504 /50x.html;
29 |
30 | location = /50x.html {
31 | root /usr/share/nginx/html;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/nginx/html/css/page.css:
--------------------------------------------------------------------------------
1 | *
2 | {
3 | margin:0;
4 | padding:0;
5 | border:0;
6 | }
7 |
8 | body
9 | {
10 | font-family:PingFangSC-Regular, Verdana, Arial, '微软雅黑','宋体';
11 | font-size:14px;
12 | }
13 |
14 | strong
15 | {
16 | font-family:'微软雅黑';
17 | font-size:18px;
18 | color:#3f3f3f;
19 | font-weight:800;
20 | }
21 |
22 | div#maincontent h2
23 | {
24 | font-size: 18px;
25 | color:#3f3f3f;
26 | }
27 |
28 | body#homefirst div#maincontent, div#maincontent h1, div#maincontent h2, div#sidebar div#ad h2
29 | {
30 | font-family:'微软雅黑';
31 | }
32 |
33 | pre, pre code, div#maincontent input, div#maincontent select, div#maincontent textarea
34 | {
35 | font-family:Consolas, "Courier New", Courier, monospace;
36 | }
37 |
38 | h2, h3, h4, h5, h6, em
39 | {
40 | font-weight: bold;
41 | }
42 |
43 | p.note span, p.important span, p.tip span, p.inherited, p.inherited span, p.gototop, .html5_new_note span
44 | {
45 | font-weight: bold;
46 | }
47 |
48 | p.tip span {
49 | color:#ff9955;
50 | }
51 |
52 | p.tip2 {
53 | background: #BBEDB8 url(/ui2017/tip.png) top left no-repeat;
54 | display:block;
55 | padding:15px 15px 15px 50px;
56 | color:#000;
57 | border-radius:5px;
58 | background-position:15px 15px;
59 | }
60 |
61 | body#homesecond div#navsecond li
62 | {
63 | font-weight:bold;
64 | }
65 |
66 | div#sidebar div#ad h2, body#homefirst div#maincontent h3
67 | {
68 | font-size: 14px;
69 | }
70 |
71 | div#maincontent h3
72 | {
73 | font-size: 16px;
74 | }
75 |
76 | div#maincontent h4
77 | {
78 | font-size: 14px;
79 | }
80 |
81 | div#maincontent button, div#maincontent input, div#maincontent select, div#maincontent textarea
82 | {
83 | font-size:12px;
84 | }
85 |
86 | body#homefirst div#maincontent div#w3 h2
87 | {
88 | font-size:20px;
89 | }
90 |
91 | em
92 | {
93 | font-style:normal;
94 | }
95 |
96 | pre code
97 | {
98 | color:#0000dd;
99 | }
100 |
101 | .html5_new_note
102 | {
103 | background: #ffffff url(/i/html5_new_note.png) top left no-repeat;
104 | padding-left:20px;
105 | }
106 |
107 | .html5_new_note span
108 | {
109 | color:blue;
110 | }
111 |
112 | p.gototop
113 | {
114 | text-align:right;
115 | }
116 |
117 | div#maincontent button
118 | {
119 | margin-top:15px;
120 | }
121 |
122 |
123 |
124 |
125 | /* ----------------------------------- layout ----------------------------------- */
126 | html {
127 | min-width: 1210px;
128 | background-color: #fdfcf8;
129 | overflow:scroll;
130 | overflow-x:hidden;
131 | }
132 |
133 | body
134 | {
135 | text-align: center;
136 | margin: 0;
137 | padding: 0;
138 | border: 0;
139 | background: #fdfcf8;
140 | }
141 |
142 | div#wrapper
143 | {
144 | margin: 0 auto;
145 | padding: 0;
146 | border: 0;
147 | width: 1239px;
148 | text-align: left;
149 | background: transparent url(/ui2017/wrapper.png) top left repeat-y;
150 | }
151 |
152 | div#navsecond
153 | {
154 | float: left;
155 | margin: 0 0 0 6px;
156 | padding: 0;
157 | border: 0;
158 | width: 180px;
159 | background : transparent;
160 | }
161 |
162 | html>body div#navsecond
163 | {
164 | margin-left: 12px;
165 | }
166 |
167 | div#maincontent
168 | {
169 | float: left;
170 | margin: 0;
171 | padding: 30px 0 0 0;
172 | border: 0;
173 | width: 850px;
174 | background: transparent;
175 | }
176 |
177 | div#maincontent div{
178 | width: 810px;
179 | margin: 0 0 0 25px;
180 | padding: 30px 0 30px 0;
181 | border:0;
182 | border-bottom: 1px solid #aaa;
183 | }
184 |
185 | div#sidebar
186 | {
187 | float: left;
188 | margin: 0;
189 | padding: 0;
190 | border: 0;
191 | width: 180px;
192 | background: transparent;
193 | }
194 |
195 | div#footer
196 | {
197 | clear: both;
198 | margin: 0;
199 | padding-top: 16px;
200 | margin-left: 12px;
201 | width: 1210px;
202 | line-height:24px;
203 | background: #f0f0f0;
204 | border-top: 0px solid #fff;
205 | background: #fdfcf8 url(/ui2017/footer.png) top left repeat-x;
206 | font-family:PingFangSC-Regular, '微软雅黑', Verdana, Arial, '宋体';
207 | }
208 |
209 | div#footer #p1
210 | {
211 | font-size:12px;
212 | color:#777777;
213 | text-align:center;
214 | background: transparent url(/ui2017/alert.png) no-repeat;
215 | background-position:235px 2px;
216 | }
217 |
218 | div#footer #p2
219 | {
220 | margin: 30px 0 30px 0;
221 | font-size:14px;
222 | text-align:center;
223 | color:#777777;
224 | }
225 |
226 | div#footer #p1, div#footer #p2, div#footer #p2 a {
227 | max-height: 999999px;
228 | }
229 |
230 |
231 | /* ----------------------------------- header ----------------------------------- */
232 | div#header, div#header_index
233 | {
234 | margin: 0 0 0 12px;
235 | padding: 0;
236 | border: 0;
237 | width: 1210px;
238 | height: 100px;
239 | background-color:#fdfcf8;
240 | }
241 |
242 | div#header a, div#header_index a, div#header_index h1
243 | {
244 | text-indent: -9999px;
245 | margin: 0;
246 | padding: 0;
247 | border: 0;
248 | overflow:hidden;
249 | float:left;
250 | }
251 |
252 | div#header a:link, div#header a:visited
253 | {
254 | display: block;
255 | width: 372px;
256 | height: 90px;
257 | background : transparent url(/ui2017/bg.png) 0 -150px no-repeat;
258 | margin: 0;
259 | padding: 0;
260 | border: 0;
261 | }
262 |
263 | div#header a:hover
264 | {
265 | background: transparent url(/ui2017/bg.png) 0 -250px no-repeat;
266 | }
267 |
268 | div#header div#ad_head
269 | {
270 | float:right;
271 | width:728px;
272 | height:90px;
273 | background-color:#efefef;
274 | margin-top:5px;
275 | }
276 |
277 | div#header_index a:link, div#header_index a:visited, div#header_index h1
278 | {
279 | display: block;
280 | width: 500px;
281 | height: 100px;
282 | background : transparent url(/ui2017/bg.png) 0 -150px no-repeat;
283 | margin: 0;
284 | padding: 0;
285 | border: 0;
286 | }
287 |
288 | div#header_index h1
289 | {
290 | display: block;
291 | }
292 |
293 | div#header_index a:hover
294 | {
295 | background: transparent url(/ui2017/bg.png) 0 -250px no-repeat;
296 | }
297 |
298 |
299 |
300 | /* ----------------------------------- search form ----------------------------------- */
301 | div#searchui
302 | {
303 | margin:0;
304 | padding:0;
305 | width:306px;
306 | height:100px;
307 | background-color: transparent;
308 | float:right;
309 | }
310 |
311 | #searchui input.button
312 | {
313 | padding:0;
314 | margin:0;
315 | background:#AE4141;
316 | font:12px Verdana, Arial, Helvetica, sans-serif;
317 | color:#FFFFFF;
318 | width:30px;
319 | height:30px;
320 | }
321 |
322 | #searchui input.box
323 | {
324 | margin:0;
325 | margin-top:35px;
326 | width:256px;
327 | height:28px;
328 | background:#fdfdfd;
329 | font:12px Verdana, Arial, Helvetica, sans-serif;
330 | border:1px solid #ddd;
331 | }
332 |
333 |
334 |
335 | /* ----------------------------------- index -----------------------------------*/
336 |
337 |
338 | body#homefirst div#maincontent div
339 | {
340 | padding-top:0;
341 | padding-bottom:30px;
342 | width:810px;
343 | }
344 |
345 | body#homefirst div#maincontent div#d1
346 | {
347 | text-align:center;
348 | }
349 |
350 | body#homefirst div#maincontent div#partner
351 | {
352 | width: 307px;
353 | float: left;
354 | }
355 |
356 | body#homefirst div#maincontent div#update
357 | {
358 | width: 300px;
359 | float: left;
360 | margin:0;
361 | }
362 |
363 | body#homefirst div#maincontent div#d1 h2
364 | {
365 | margin-top:35px;
366 | font-size:24px;
367 | }
368 |
369 | body#homefirst div#maincontent div#d1 p
370 | {
371 | margin-left:0;
372 | font-size:18px;
373 | }
374 |
375 | body#homefirst div#maincontent p
376 | {
377 | font-size:16px;
378 | margin-left:110px;
379 | }
380 |
381 | body#homefirst div#maincontent h3
382 | {
383 | margin-top:35px;
384 | margin-left:110px;
385 | font-size:24px;
386 | }
387 |
388 | body#homefirst div#maincontent div.idea
389 | {
390 | padding: 0;
391 | padding-bottom:30px;
392 | min-height: 118px;
393 | }
394 |
395 | body#homefirst div#maincontent div#d2
396 | {
397 | background : transparent url(/ui2017/icon2.png) 0 0 no-repeat;
398 | }
399 |
400 | body#homefirst div#maincontent div#d3
401 | {
402 | background : transparent url(/ui2017/icon3.png) 0 0 no-repeat;
403 | }
404 |
405 | body#homefirst div#maincontent div#d4
406 | {
407 | background : transparent url(/ui2017/icon4.png) 0 0 no-repeat;
408 | }
409 |
410 | body#homefirst div#maincontent div#d5
411 | {
412 | background : transparent url(/ui2017/icon5.png) 0 0 no-repeat;
413 | }
414 |
415 | body#homefirst div#maincontent div#d6
416 | {
417 | background : transparent url(/ui2017/icon6.png) 0 0 no-repeat;
418 | }
419 |
420 | body#homefirst div#maincontent div#d7
421 | {
422 | background : transparent url(/ui2017/icon7.png) 0 0 no-repeat;
423 | }
424 |
425 | body#homefirst div#maincontent div#d8
426 | {
427 | background : transparent url(/ui2017/icon8.png) 0 0 no-repeat;
428 | border:0px;
429 | }
430 |
431 | body#homefirst div#maincontent div#d9 {
432 | background: transparent url(/ui2017/icon9.png) top left no-repeat;
433 | }
434 |
435 | body#homefirst div#maincontent div#d10 {
436 | background: transparent url(/ui2017/icon10.png) top left no-repeat;
437 | }
438 |
439 | body#homefirst div#maincontent div.idea img
440 | {
441 | margin:0;
442 | float:left;
443 | }
444 |
445 | body#homefirst div#maincontent div#d9, body#homefirst div#maincontent div#d10 {
446 | margin-left:75px;
447 | margin-top:10px;
448 | width:290px;
449 | float:left;
450 | border:0;
451 | }
452 |
453 | body#homefirst div#maincontent div#d9, body#homefirst div#maincontent div#d10 {
454 | margin-left:75px;
455 | margin-top:15px;
456 | float:left;
457 | border:0;
458 | min-height:87px;
459 | }
460 |
461 | body#homefirst div#maincontent div#d9, body#homefirst div#maincontent div#d10 {
462 | width:290px;
463 | }
464 |
465 | body#homefirst div#maincontent div#d10 {
466 | width:299px;
467 | }
468 |
469 | body#homefirst div#maincontent div#d9 h3, body#homefirst div#maincontent div#d10 h3 {
470 | font-size:14px;
471 | margin:23px 0 0 58px;
472 | color:#777;
473 | font-weight:400;
474 | }
475 |
476 | body#homefirst div#maincontent div#d9 p, body#homefirst div#maincontent div#d10 p {
477 | font-size:14px;
478 | margin:0 0 0 58px;
479 | line-height:normal;
480 | }
481 |
482 | div#d9 p a {
483 | color:#000;
484 | }
485 |
486 |
487 | /* ----------------------------------- navfirst -----------------------------------*/
488 | div#navfirst
489 | {
490 | height: 48px;
491 | width: 1210px;
492 | margin: 0 0 0 12px;
493 | padding: 0;
494 | border: 0;
495 | background: #E8E7E3;
496 | }
497 |
498 | div#navfirst ul#menu
499 | {
500 | height: 48px;
501 | width: 1210px;
502 | background: transparent url(/ui2017/bg.png) top left no-repeat;
503 | margin: 0;
504 | padding: 0;
505 | position: relative;
506 | }
507 |
508 | div#navfirst ul#menu li
509 | {
510 | margin:0;
511 | padding:0;
512 | list-style:none;
513 | position:absolute;
514 | top:0;
515 | }
516 |
517 | ul#menu li,ul#menu a
518 | {
519 | display: block;
520 | height: 48px;
521 | border-bottom:0;
522 | }
523 |
524 | div#navfirst ul#menu li a
525 | {
526 | text-indent: -9999px;
527 | overflow:hidden;
528 | text-decoration: none;
529 | }
530 |
531 | #h {left:0;width:155px;}
532 | #b {left:155px;width:157px;}
533 | #s {left:312px;width:167px;}
534 | #d {left:479px;width:158px;}
535 | #x {left:637px;width:101px;}
536 | #ws {left:738px;width:185px;}
537 | #w {left:923px;width:177px;}
538 |
539 | #h a:hover {background: transparent url(/ui2017/bg.png) 0 -48px no-repeat;}
540 | #b a:hover {background: transparent url(/ui2017/bg.png) -155px -48px no-repeat;}
541 | #s a:hover {background: transparent url(/ui2017/bg.png) -312px -48px no-repeat;}
542 | #d a:hover {background: transparent url(/ui2017/bg.png) -479px -48px no-repeat;}
543 | #x a:hover {background: transparent url(/ui2017/bg.png) -637px -48px no-repeat;}
544 | #ws a:hover {background: transparent url(/ui2017/bg.png) -738px -48px no-repeat;}
545 | #w a:hover {background: transparent url(/ui2017/bg.png) -923px -48px no-repeat;}
546 |
547 | body.html #h {background: transparent url(/ui2017/bg.png) 0 -48px no-repeat;}
548 | body.browserscripting #b {background: transparent url(/ui2017/bg.png) -155px -48px no-repeat;}
549 | body.serverscripting #s {background: transparent url(/ui2017/bg.png) -312px -48px no-repeat;}
550 | body.dotnet #d {background: transparent url(/ui2017/bg.png) -479px -48px no-repeat;}
551 | body.xml #x {background: transparent url(/ui2017/bg.png) -637px -48px no-repeat;}
552 | body.webservices #ws {background: transparent url(/ui2017/bg.png) -738px -48px no-repeat;}
553 | body.webbuilding #w {background: transparent url(/ui2017/bg.png) -923px -48px no-repeat;}
554 |
555 |
556 |
557 |
558 |
559 | /* Default links */
560 | a:link, a:visited {
561 | text-decoration : none;
562 | color : #900b09;
563 | background : transparent;
564 | border-bottom:1px solid #900b09;
565 | }
566 |
567 | a:hover {
568 | text-decoration : none;
569 | color: #ff0000;
570 | background : transparent;
571 | border-bottom:1px solid #ff0000;
572 | }
573 |
574 | a:active {
575 | text-decoration : none;
576 | color : #ff0000;
577 | background : transparent;
578 | }
579 |
580 | div#navsecond li.currentLink a:link, div#navsecond li.currentLink a:visited {
581 | text-decoration : none;
582 | color:#ff0000;
583 | background : transparent;
584 | }
585 |
586 | div#navsecond li.currentLink a:hover {
587 | text-decoration : underline;
588 | color : #ff0000;
589 | background : transparent;
590 | }
591 |
592 | div#navsecond a:link, div#navsecond a:visited {
593 | text-decoration : none;
594 | color:#000;
595 | background : transparent;
596 | }
597 |
598 | div#navsecond a:hover {
599 | text-decoration : underline;
600 | color : #000;
601 | background : transparent;
602 | }
603 |
604 | div#navsecond a:active {
605 | text-decoration : underline;
606 | color : #000;
607 | background : transparent;
608 | }
609 |
610 | div#navsecond a#link_help {
611 | color:#0479A7;
612 | }
613 |
614 | div#navsecond a#link_about {
615 | color:#0479A7;
616 | }
617 |
618 | div#maincontent .partner a {
619 | color:#000;
620 | }
621 |
622 | div#footer a {
623 | border-bottom:none;
624 | }
625 |
626 | div#footer a:link, div#footer a:visited {
627 | text-decoration : none;
628 | color:#777777;
629 | background : transparent;
630 | }
631 |
632 | div#footer a:hover {
633 | text-decoration : underline;
634 | color : #000;
635 | background : transparent;
636 | }
637 |
638 | div#footer a:active {
639 | text-decoration : underline;
640 | color : #000;
641 | background : transparent;
642 | }
643 |
644 |
645 | /* ----------------------------------- Typography ----------------------------------- */
646 |
647 | div#maincontent p
648 | {
649 | margin: 12px 0 0 0;
650 | line-height: 150%;
651 | }
652 |
653 | div#maincontent h1 {
654 | margin:0 0 0 25px;
655 | font-size: 28px;
656 | font-weight:400;
657 | }
658 |
659 | div#maincontent h3, div#maincontent h4{
660 | margin:25px 0 0 0;
661 | }
662 |
663 | #homefirst div#navsecond h2:first-child, #homefirst div#sidebar h2:first-child {
664 | margin:10px 0 0 0;
665 | }
666 |
667 | body#homesecond div#navsecond li {
668 | margin:5px 0 0 0;
669 | }
670 |
671 | div.backtoreference p{
672 | margin:0;
673 | }
674 |
675 | div#w3school p {
676 | margin-left:15px;
677 | }
678 |
679 | div#maincontent div p:first-child {
680 | margin: 0;
681 | }
682 |
683 | p.important span {
684 | color:#dd0000;
685 | }
686 |
687 | p.inherited {
688 | color:#ff0000;
689 | }
690 |
691 | p.inherited span {
692 | color:#999;
693 | }
694 |
695 | p.chinese span {
696 | color:#0000ff;
697 | }
698 |
699 | pre {
700 | width:765px;
701 | margin: 15px 0 0 0;
702 | padding: 20px;
703 | border: 0;
704 | border: 1px dotted #785;
705 | background: #f5f5f5;
706 | line-height:1.4;
707 | font-family:Consolas;
708 | }
709 |
710 | pre code {
711 | color:#0000dd;
712 | }
713 |
714 | pre span {
715 | color:#999;
716 | }
717 |
718 | pre span.code_comment {
719 | color:#999;
720 | }
721 |
722 | blockquote
723 | {
724 | margin:15px;
725 | }
726 |
727 | div#maincontent ul, div#maincontent ol {
728 | margin-top:10px;
729 | margin-left:35px;
730 | margin-bottom:0;
731 | }
732 |
733 | div#maincontent li {
734 | margin-top:3px;
735 | }
736 |
737 | div#navsecond ul, div#navsecond li, div#sidebar ul, div#sidebar li {
738 | margin: 0;
739 | padding: 0;
740 | }
741 |
742 | div#navsecond ul, div#sidebar ul {
743 | margin-left: 12px;
744 | }
745 |
746 | div#navsecond li, div#sidebar li {
747 | list-style: none;
748 | }
749 |
750 | div#navsecond li.list_apart {
751 | margin-top:10px;
752 | }
753 |
754 | img {
755 | border:0;
756 | }
757 |
758 | div#maincontent img {
759 | margin:25px 0 0 25px;
760 | }
761 |
762 | body#homesecond dl {
763 | margin:0;
764 | padding:0;
765 | }
766 |
767 | body#homesecond dt
768 | {
769 | font-weight: bold;
770 | font-size: 14px;
771 | margin:0;
772 | padding:0;
773 | }
774 |
775 | body#homesecond dd {
776 | color:#000088;
777 | margin:10px 0 0 0;
778 | padding:0;
779 | }
780 |
781 | body#homesecond dd p {
782 | margin:0;
783 | padding:0;
784 | }
785 |
786 |
787 | div#maincontent div#toc div {
788 | margin:0;
789 | margin-top:15px;
790 | margin-bottom:35px;
791 | padding:0;
792 | border:0;
793 | }
794 |
795 | div#toc img {
796 | float:left;
797 | margin:0;
798 | margin-right:10px;
799 | }
800 |
801 | div#toc div dt, div#toc div dl {
802 | margin-top:0;
803 | }
804 |
805 | div#example dl, div.example dl, div#moreexamples dl, div#toc dl, div#referencelist dl {
806 | margin: 10px 0 0 0;
807 | }
808 |
809 | div#example dt, div.example dt, div#moreexamples dt, div#toc dt, div#referencelist dt {
810 | margin:15px 0 5px 0;
811 | }
812 |
813 | div#example dd, div.example dd, div#moreexamples dd, div#toc dd, div#referencelist dd {
814 | margin:0;
815 | }
816 |
817 | dl.define
818 | {
819 | margin: 10px 0 0 0;
820 | }
821 |
822 | dl.define dt
823 | {
824 | margin:15px 0 3px 0;
825 | font-weight:bold;
826 | color:#0479A7;
827 | }
828 |
829 | dl.define dd
830 | {
831 | margin:10px 0 0 10px;
832 | line-height: 150%;
833 | }
834 |
835 | span.deprecated {
836 | color:#e80000;
837 | }
838 |
839 | .marked, pre code span.marked {
840 | color:#dd0000;
841 | }
842 |
843 | p.gototop {
844 | text-align:right;
845 | }
846 |
847 | div#maincontent canvas.canvas_example {
848 | border:1px solid #d3d3d3;
849 | background:#ffffff;
850 | width:300px;
851 | height:150px;
852 | margin-top:15px;
853 | }
854 |
855 | div#maincontent div.panel,p.flip {
856 | width:400px;
857 | margin:0;
858 | padding:5px;
859 | text-align:center;
860 | background:#e5eecc;
861 | border:solid 1px #c3c3c3;
862 | }
863 |
864 | div#maincontent p.flip {
865 | margin-top:15px;
866 | }
867 |
868 | div.panel {
869 | display:none;
870 | }
871 |
872 | div#maincontent input[type=text]
873 | {
874 | border:1px #bebebe solid;
875 | height:30px;
876 | padding-left:10px;
877 | margin:15px 0 0 0;
878 | }
879 |
880 | div#maincontent input[type=submit], button
881 | {
882 | border:1px #bebebe solid;
883 | height:30px;
884 | padding-left:5px;
885 | padding-right:5px;
886 | }
887 |
888 | div#maincontent input[type=submit]:hover, button:hover
889 | {
890 | border:1px #999 solid;
891 | }
892 |
893 | div#maincontent select
894 | {
895 | border:1px #bebebe solid;
896 | height:25px;
897 | margin:15px 0 0 0;
898 | }
899 |
900 |
901 | /* ----------------------------------- 表格 ----------------------------------- */
902 |
903 | table.dataintable {
904 | margin-top:15px;
905 | border-collapse:collapse;
906 | border:1px solid #aaa;
907 | width:100%;
908 | }
909 |
910 | table.dataintable th {
911 | vertical-align:baseline;
912 | padding:5px 15px 5px 6px;
913 | background-color:#3F3F3F;
914 | border:1px solid #3F3F3F;
915 | text-align:left;
916 | color:#fff;
917 | }
918 |
919 | table.dataintable td {
920 | vertical-align:text-top;
921 | padding:6px 15px 6px 6px;
922 | border:1px solid #aaa;
923 | }
924 |
925 | table.dataintable tr:nth-child(odd) {
926 | background-color:#F5F5F5;
927 | }
928 |
929 | table.dataintable tr:nth-child(even) {
930 | background-color:#fff;
931 | }
932 |
933 | table.dataintable pre {
934 | width:auto;
935 | margin:0;
936 | padding:0;
937 | border:0;
938 | background-color:transparent;
939 | }
940 |
941 | table.dataintable p {margin:0 0 2px 0;}
942 |
943 | div#maincontent table.dataintable ul, div#maincontent table.dataintable li {
944 | list-style-type:none;
945 | margin:0;
946 | padding:0;
947 | }
948 |
949 | table.dataintable td em
950 | {
951 | color:#0000ff;
952 | font-weight:normal;
953 | }
954 |
955 | table.dataintable .table_value {color:#0F93D2;}
956 |
957 | .no_wrap {white-space:nowrap;}
958 |
959 | div#maincontent table.dataintable ul.listintable {
960 | margin:20px;
961 | padding:0;
962 | }
963 |
964 | div#maincontent table.dataintable ul.listintable li{
965 | list-style-type:disc;
966 | }
967 |
968 |
969 | table.dataintable td.html5_new {
970 | background: transparent url(/ui2017/table_bg_html5.png) top right no-repeat;
971 | }
972 |
973 | tr.notsupported {
974 | color:#999999;
975 | }
976 |
977 |
978 |
979 | /* ----------------------------------- browsersupport ----------------------------------- */
980 | table.browsersupport td
981 | {
982 | text-align:center;
983 | }
984 |
985 | #jsref table.browsersupport td, #tags table.browsersupport td, #cssref table.browsersupport td
986 | {
987 | width:20%;
988 | }
989 |
990 | #jsref table.browsersupport th, #tags table.browsersupport th, #cssref table.browsersupport th
991 | {
992 | color:#333333;
993 | font-weight:400;
994 | }
995 |
996 | #jsref table.browsersupport, #tags table.browsersupport, #cssref table.browsersupport
997 | {
998 | width:70%;
999 | }
1000 |
1001 | table.browsersupport .bsIE {
1002 | background-image: url('/ui2017/compatible_ie.png');
1003 | }
1004 |
1005 | table.browsersupport .bsFirefox {
1006 | background-image: url('/ui2017/compatible_firefox.png');
1007 | }
1008 |
1009 | table.browsersupport .bsChrome {
1010 | background-image: url('/ui2017/compatible_chrome.png');
1011 | }
1012 |
1013 | table.browsersupport .bsSafari {
1014 | background-image: url('/ui2017/compatible_safari.png');
1015 | }
1016 |
1017 | table.browsersupport .bsOpera {
1018 | background-image: url('/ui2017/compatible_opera.png');
1019 | }
1020 |
1021 | table.browsersupport .bsNoIE {
1022 | background-image: url('/ui2017/incompatible_ie.png');
1023 | }
1024 |
1025 | table.browsersupport .bsNoFirefox {
1026 | background-image: url('/ui2017/incompatible_firefox.png');
1027 | }
1028 |
1029 | table.browsersupport .bsNoChrome {
1030 | background-image: url('/ui2017/incompatible_chrome.png');
1031 | }
1032 |
1033 | table.browsersupport .bsNoSafari {
1034 | background-image: url('/ui2017/incompatible_safari.png');
1035 | }
1036 |
1037 | table.browsersupport .bsNoOpera {
1038 | background-image: url('/ui2017/incompatible_opera.png');
1039 | }
1040 |
1041 | table.browsersupport .bsPreIE {
1042 | background-image: url('/i/precompatible_ie.gif');
1043 | }
1044 |
1045 | table.browsersupport .bsPreFirefox {
1046 | background-image: url('/i/precompatible_firefox.gif');
1047 | }
1048 |
1049 | table.browsersupport .bsPreChrome {
1050 | background-image: url('/i/precompatible_chrome.gif');
1051 | }
1052 |
1053 | table.browsersupport .bsPreSafari {
1054 | background-image: url('/i/precompatible_safari.gif');
1055 | }
1056 |
1057 | table.browsersupport .bsPreOpera {
1058 | background-image: url('/i/precompatible_opera.gif');
1059 | }
1060 |
1061 | table.browsersupport {
1062 | margin-top:15px;
1063 | border-collapse:collapse;
1064 | }
1065 |
1066 | table.browsersupport td {
1067 | padding: 0;
1068 | height: 86px;
1069 | width:86px;
1070 | vertical-align: middle;
1071 | background:#fdfcf8 no-repeat center;
1072 | border:1px solid #ddd;
1073 | }
1074 |
1075 | table.browsersupport .browser_version td {
1076 | padding: 0;
1077 | height: 36px;
1078 | vertical-align: middle;
1079 | text-align: center;
1080 | background-color:#F5F5F5;
1081 | border:1px solid #ddd;
1082 | }
1083 |
1084 | table.browsersupport td.bsProperty
1085 | {
1086 | font-family: courier new;
1087 | white-space: nowrap;
1088 | width:20%;
1089 | }
1090 |
1091 | table.browsersupport th {
1092 | padding: 0;
1093 | height: 36px;
1094 | vertical-align: middle;
1095 | text-align: center;
1096 | background-color:#F5F5F5;
1097 | border:1px solid #ddd;
1098 | }
1099 |
1100 |
1101 |
1102 | /* ----------------------------------- prenextnav ----------------------------------- */
1103 |
1104 | div#tpn, div#bpn {
1105 | height:29px;
1106 | width:230px;
1107 | margin: 0;
1108 | padding: 0;
1109 | border: 0;
1110 | background: transparent;
1111 | }
1112 |
1113 | div#tpn ul.prenext, div#bpn ul.prenext {
1114 | height:29px;
1115 | width:230px;
1116 | background: transparent url(/ui2017/bg.png) 0 -580px no-repeat;
1117 | margin:0;
1118 | padding:0;
1119 | border:0;
1120 | position:relative;
1121 | }
1122 |
1123 | div#tpn ul.prenext li, div#bpn ul.prenext li {
1124 | margin:0;
1125 | padding:0;
1126 | list-style:none;
1127 | position:absolute;
1128 | top:0px;
1129 | overflow:hidden;
1130 | }
1131 |
1132 | ul.prenext li, ul.prenext a {
1133 | display:block;
1134 | height:29px;
1135 | }
1136 |
1137 | div#tpn ul.prenext a, div#bpn ul.prenext a {
1138 | text-indent: -9999px;
1139 | text-decoration: none;
1140 | }
1141 |
1142 | .pre {left:0; width:105px;}
1143 | .next {left:125px; width:105px;}
1144 |
1145 | .pre a:hover {background: transparent url(/ui2017/bg.png) 0px -629px no-repeat;}
1146 | .next a:hover {background: transparent url(/ui2017/bg.png) -125px -629px no-repeat;}
1147 |
1148 |
1149 |
1150 |
1151 |
1152 | /* ----------------------------------- navsecond ----------------------------------- */
1153 | div#course {
1154 | background:transparent url(/ui2017/bg.png) 0 -700px no-repeat;
1155 | padding:66px 0 10px 0;
1156 | }
1157 |
1158 | div#afterschool {
1159 | background:transparent url(/ui2017/afterschool.png) 0 0 no-repeat;
1160 | padding:45px 0 10px 0;
1161 | }
1162 |
1163 | div#selected {
1164 | background:transparent url(/ui2017/bg.png) -200px -700px no-repeat;
1165 | padding:45px 0 10px 0;
1166 | }
1167 |
1168 |
1169 |
1170 |
1171 | /* ----------------------------------- sidebar ----------------------------------- */
1172 | div#tools {
1173 | background:transparent url(/ui2017/bg.png) -400px -700px no-repeat;
1174 | padding:79px 0 10px 22px;
1175 | margin:0;
1176 | }
1177 |
1178 | body#homesecond div#tools {
1179 | background:transparent url(/ui2017/bg.png) -400px -700px no-repeat;
1180 | padding:66px 0 10px 0;
1181 | margin:0;
1182 | }
1183 |
1184 | div#books {
1185 | background:transparent url(/ui/bg.gif) -450px -326px no-repeat;
1186 | padding:45px 0 0 15px;
1187 | margin:0;
1188 | }
1189 |
1190 | div#ad {
1191 | background:transparent url(/ui2017/bg.png) -600px -700px no-repeat;
1192 | padding:66px 0 10px 10px;
1193 | margin:0;
1194 | }
1195 |
1196 | div#sidebar div#ad:first-child {
1197 | background:transparent url(/ui2017/bg.png) -800px -700px no-repeat;
1198 | padding:66px 0 10px 10px;
1199 | margin:0;
1200 | }
1201 |
1202 |
1203 | div#sidebar div#ad h2 {
1204 | color:#000000;
1205 | margin:0 0 25px 25px;
1206 | }
1207 |
1208 | div#ad span {
1209 | margin:0 0 15px 0;
1210 | }
1211 |
1212 |
1213 | /* ----------------------------------- sidebar banner ----------------------------------- */
1214 |
1215 | div#tools h5 {
1216 | margin: 0 0 12px 0;
1217 | padding: 0;
1218 | overflow:hidden;
1219 | }
1220 |
1221 | div#tools h5#tools_reference, div#tools h5#tools_example, div#tools h5#tools_quiz, div#tools h5#tools_search {
1222 | text-indent: -9999px;
1223 | width: 136px;
1224 | height: 64px;
1225 | }
1226 |
1227 | div#tools h5#tools_reference a, div#tools h5#tools_example a, div#tools h5#tools_quiz a, div#tools h5#tools_search a {
1228 | display: block;
1229 | margin: 0;
1230 | padding: 0;
1231 | width: 100%;
1232 | height: 100%;
1233 | text-decoration: none;
1234 | }
1235 |
1236 | div#tools h5#tools_reference a {
1237 | background: transparent url(/ui2017/bg.png) 0 -400px no-repeat;
1238 | }
1239 |
1240 | div#tools h5#tools_reference a:hover {
1241 | background: transparent url(/ui2017/bg.png) 0 -464px no-repeat;
1242 | }
1243 |
1244 | div#tools h5#tools_example a {
1245 | background: transparent url(/ui2017/bg.png) -150px -400px no-repeat;
1246 | }
1247 |
1248 | div#tools h5#tools_example a:hover {
1249 | background: transparent url(/ui2017/bg.png) -150px -464px no-repeat;
1250 | }
1251 |
1252 | div#tools h5#tools_quiz a {
1253 | background: transparent url(/ui2017/bg.png) -300px -400px no-repeat;
1254 | }
1255 |
1256 | div#tools h5#tools_quiz a:hover {
1257 | background: transparent url(/ui2017/bg.png) -300px -464px no-repeat;
1258 | }
1259 |
1260 |
1261 |
1262 |
1263 |
1264 |
1265 | div#maincontent p.tiy{
1266 | border:none;
1267 | display:inline-block;
1268 | outline:0;
1269 | padding:8px 18px;
1270 | margin-top:15px;
1271 | margin-bottom:10px;
1272 | vertical-align:middle;
1273 | overflow:hidden;
1274 | text-decoration:none;
1275 | color:#fff;
1276 | background-color:#e9686b;
1277 | text-align:center;
1278 | transition:.2s ease-out;
1279 | cursor:pointer;
1280 | white-space:nowrap;
1281 | box-shadow:0px 2px 6px rgba(0,0,0,0.12), 0px 1px 2px rgba(0,0,0,0.24);
1282 | font-family:'微软雅黑';
1283 | border-radius:2px;
1284 | }
1285 |
1286 | div#maincontent p.tiy:last-child{
1287 | margin-bottom:0px;
1288 | }
1289 |
1290 | div#maincontent p.tiy a {
1291 | border:0px;
1292 | }
1293 |
1294 | div#maincontent p.tiy a:link, div#maincontent p.tiy a:visited {
1295 | color:#fff;
1296 | text-decoration:none;
1297 | }
1298 |
1299 | div#maincontent p.tiy:hover{
1300 | background-color:#ba3537;
1301 | color:#fff;
1302 | text-decoration:none;
1303 | }
1304 |
1305 | div#maincontent p.tiy a:active {
1306 | color:#fff;
1307 | text-decoration:none;
1308 | }
1309 |
1310 | div#navsecond h2, div#sidebar h2 {
1311 | font-size: 14px;
1312 | margin:0;
1313 | padding:10px 0 5px 10px;
1314 | color:#000;
1315 | display:block;
1316 | border-bottom:0px solid #ddd;
1317 | font-family:'微软雅黑';
1318 | }
1319 |
1320 | div#navsecond h2#link_about, div#navsecond h2#link_help {
1321 | font-size: 14px;
1322 | margin:0;
1323 | margin-left:10px;
1324 | padding:0;
1325 | color:#000;
1326 | display:block;
1327 | }
1328 |
1329 | div#navsecond h2#link_about {
1330 | margin-top:20px;
1331 | margin-bottom:15px;
1332 | }
1333 |
1334 | div#navsecond h2#link_help {
1335 | margin-bottom:20px;
1336 | }
1337 |
1338 | div#navsecond h2#link_about a, div#navsecond h2#link_help a {
1339 | display:inline;
1340 | padding:0;
1341 | font-size:14px;
1342 | border-bottom:0px solid #ddd;
1343 | text-decoration:none;
1344 | color:#0479A7;
1345 | }
1346 |
1347 | div#navsecond h2#link_about a:hover, div#navsecond h2#link_help a:hover {
1348 | border-bottom:1px solid #0479A7;
1349 | color:#0479A7;
1350 | background-color:transparent;
1351 | }
1352 |
1353 | div#navsecond ul, div#navsecond li, div#sidebar ul, div#sidebar li {
1354 | margin: 0;
1355 | padding: 0;
1356 | font-family:'微软雅黑';
1357 | }
1358 |
1359 |
1360 | div#navsecond li, div#sidebar li {
1361 | list-style: none;
1362 | }
1363 |
1364 | div#navsecond a, div#sidebar a {
1365 | display:block;
1366 | padding:5px 0 5px 15px;
1367 | font-size:12px;
1368 | border-bottom:0px solid #ddd;
1369 | text-decoration:none;
1370 | }
1371 |
1372 | div#navsecond ul a.active {
1373 | background : #f5f5f5;
1374 | color:#990000;
1375 | }
1376 |
1377 |
1378 | div#navsecond a:link, div#navsecond a:visited {
1379 | text-decoration : none;
1380 | color:#000000;
1381 | background : transparent;
1382 | }
1383 |
1384 | div#navsecond a:hover {
1385 | text-decoration : none;
1386 | color : #fff;
1387 | background : #aaa;
1388 | }
1389 |
1390 | div#sidebar a:hover {
1391 | text-decoration : none;
1392 | color : #fff;
1393 | background : #BD2D30;
1394 | }
1395 |
1396 | div#navsecond a:active {
1397 | text-decoration : none;
1398 | color : #fff;
1399 | background : #BD2D30;
1400 | }
1401 |
1402 | div#navsecond li.currentLink a:link, div#navsecond li.currentLink a:visited {
1403 | text-decoration : none;
1404 | color:#ffffff;
1405 | background-color: #BD2D30;
1406 | }
--------------------------------------------------------------------------------
/nginx/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Calibre-Library
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Calibre-Manager |
23 | http://${vps-ip}:8080 |
24 |
25 |
26 | Nginx Proxy URL |
27 | http://${vps-ip}/mgr |
28 |
29 |
30 | Login Username |
31 | admin |
32 |
33 |
34 | Login Password |
35 | admin123 |
36 |
37 |
38 | Modify Password |
39 | by docker build arguments |
40 |
41 |
42 | Details |
43 | Upload and manage your books |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | Calibre-CMS |
53 | http://${vps-ip}:8083 |
54 |
55 |
56 | Nginx Proxy URL |
57 | http://${vps-ip}/cms |
58 |
59 |
60 | OPDS URL |
61 | http://${vps-ip}/cms/opds/ |
62 |
63 |
64 | Login Username |
65 | admin |
66 |
67 |
68 | Login Password |
69 | 123456 |
70 |
71 |
72 | Modify Password |
73 | by WEB UI |
74 |
75 |
76 | Details |
77 | List and download your books |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/run.ps1:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 运行 Calibre 服务
3 | #------------------------------------------------
4 | # 命令执行示例:
5 | # ./run.ps1 -u admin -p admin123 -i 1000 -g 1000
6 | #------------------------------------------------
7 |
8 | param([string]$u="admin", [string]$p="admin123", [int]$i=1000, [int]$g=1000)
9 |
10 | $USERNAME = $u
11 | $PASSWORD = $p
12 | $U_ID = $i
13 | $G_ID = $g
14 |
15 | $MD5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
16 | $UTF8 = New-Object -TypeName System.Text.UTF8Encoding
17 | $PASS_MD5 = [System.BitConverter]::ToString(${MD5}.ComputeHash(${UTF8}.GetBytes(${PASSWORD}))).replace('-','').ToLower()
18 | $ENV:username=${USERNAME}; $ENV:pass_md5=${PASS_MD5}; $ENV:uid=${U_ID}; $ENV:gid=${G_ID}; docker-compose up -d
19 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 运行 Calibre 服务
3 | #------------------------------------------------
4 | # 命令执行示例:
5 | # ./run.sh -u admin -p admin123 -i 1000 -g 1000
6 | #------------------------------------------------
7 |
8 | USERNAME="admin"
9 | PASSWORD="admin123"
10 | U_ID=`id | awk -F '[(=]' '{print $2}'`
11 | G_ID=`id | awk -F '[(=]' '{print $4}'`
12 |
13 | set -- `getopt u:p:i:g: "$@"`
14 | while [ -n "$1" ]
15 | do
16 | case "$1" in
17 | -u) USERNAME="$2"
18 | shift ;;
19 | -p) PASSWORD="$2"
20 | shift ;;
21 | -i) U_ID="$2"
22 | shift ;;
23 | -g) G_ID="$2"
24 | shift ;;
25 | esac
26 | shift
27 | done
28 |
29 | PASS_MD5=`echo -n ${PASSWORD} | openssl md5 | awk '{print $2}'`
30 | username=${USERNAME} pass_md5=${PASS_MD5} uid=${U_ID} gid=${G_ID} docker-compose up -d
31 |
32 |
--------------------------------------------------------------------------------
/stop.ps1:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 停止 Calibre 服务
3 | #------------------------------------------------
4 | # 命令执行示例:
5 | # ./stop.ps1
6 | #------------------------------------------------
7 |
8 | docker-compose down
9 |
--------------------------------------------------------------------------------
/stop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # 停止 Calibre 服务
3 | #------------------------------------------------
4 | # 命令执行示例:
5 | # ./stop.sh
6 | #------------------------------------------------
7 |
8 | docker-compose down
9 |
--------------------------------------------------------------------------------