├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── LICENSE ├── README.md ├── docker ├── Dockerfile ├── conf │ ├── nginx │ │ ├── myblog.conf │ │ └── nginx.conf │ ├── start.sh │ └── uwsgi │ │ └── uwsgi.ini └── requirements.txt ├── era_blog ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── static │ ├── codeBlock │ │ ├── codeBlockFuction.js │ │ ├── codeCopy.js │ │ ├── codeLang.js │ │ └── codeShrink.js │ ├── css │ │ ├── all.css │ │ ├── animate.min.css │ │ ├── aos.css │ │ ├── gitment.css │ │ ├── jqcloud.css │ │ ├── lightgallery.min.css │ │ ├── materialize.min.css │ │ ├── matery.css │ │ ├── monokai.css │ │ ├── my-gitalk.css │ │ ├── my.css │ │ ├── prism-a11y-dark.css │ │ ├── share.min.css │ │ └── tocbot.css │ ├── fonts │ │ ├── iconfont.eot │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ └── iconfont.woff │ ├── image │ │ ├── blog-1.png │ │ ├── blog-2.png │ │ ├── blog-3.png │ │ ├── blog-4.png │ │ ├── blog-5.png │ │ └── blog-6.png │ ├── js │ │ ├── Valine.min.js │ │ ├── aos.js │ │ ├── clicklove.js │ │ ├── echarts.min.js │ │ ├── instantpage.js │ │ ├── jqcloud-1.0.4.min.js │ │ ├── jquery-2.2.0.min.js │ │ ├── lightgallery-all.min.js │ │ ├── masonry.pkgd.min.js │ │ ├── materialize.min.js │ │ ├── matery.js │ │ ├── prism.js │ │ ├── scrollProgress.min.js │ │ ├── search.js │ │ ├── social-share.min.js │ │ └── tocbot.min.js │ ├── medias │ │ ├── comment_bg.png │ │ └── icp.png │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 ├── templates │ ├── about.html │ ├── archive.html │ ├── article_category.html │ ├── article_tag.html │ ├── banner.html │ ├── base.html │ ├── category.html │ ├── detail.html │ ├── friends.html │ ├── index.html │ └── tag.html ├── templatetags │ └── custom_tag.py ├── tests.py ├── urls.py └── views.py ├── logs └── erablog.log ├── manage.py ├── my_blog ├── __init__.py ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py └── uploads ├── article └── 2020 │ └── 06 │ ├── redis-1.jpg │ ├── redis-2.jpg │ ├── redis-3.jpg │ ├── springboot-1.jpg │ ├── springboot-2.jpg │ ├── springboot-3.jpg │ ├── springboot-4.jpg │ ├── springboot-5.jpg │ ├── springboot-6.jpg │ └── springboot-7.jpg └── editor ├── 10_20200616134632284905.png ├── 11_20200616134717228777.png ├── 12_20200616134816739711.png ├── 13_20200616135754965695.png ├── 14_20200616135858054073.png ├── 15_20200616135919544637.png ├── 16_20200616135953372215.png ├── 17_20200616141227921615.png ├── 1_20200615212409393721.png ├── 1_20200616114738209450.png ├── 2_20200615212444162345.png ├── 2_20200616114754184473.png ├── 3_20200615212458218775.png ├── 3_20200616115150788760.png ├── 4_20200615212526004507.png ├── 4_20200616115212770007.png ├── 5_20200615212622375867.png ├── 5_20200616115233644213.png ├── 6_20200616115251003814.png ├── 7_20200616115305401820.png ├── 8_20200616135051757889.png └── 9_20200616134548163771.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | local_settings.py 60 | db.sqlite3 61 | db.sqlite3-journal 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | target/ 75 | 76 | # Jupyter Notebook 77 | .ipynb_checkpoints 78 | 79 | # IPython 80 | profile_default/ 81 | ipython_config.py 82 | 83 | # pyenv 84 | .python-version 85 | 86 | # pipenv 87 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 88 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 89 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 90 | # install all needed dependencies. 91 | #Pipfile.lock 92 | 93 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 94 | __pypackages__/ 95 | 96 | # Celery stuff 97 | celerybeat-schedule 98 | celerybeat.pid 99 | 100 | # SageMath parsed files 101 | *.sage.py 102 | 103 | # Environments 104 | .env 105 | .venv 106 | env/ 107 | venv/ 108 | ENV/ 109 | env.bak/ 110 | venv.bak/ 111 | 112 | # Spyder project settings 113 | .spyderproject 114 | .spyproject 115 | 116 | # Rope project settings 117 | .ropeproject 118 | 119 | # mkdocs documentation 120 | /site 121 | 122 | # mypy 123 | .mypy_cache/ 124 | .dmypy.json 125 | dmypy.json 126 | 127 | # Pyre type checker 128 | .pyre/ 129 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "name": "Python: Django", 10 | "type": "python", 11 | "request": "launch", 12 | "program": "${workspaceFolder}/manage.py", 13 | "args": [ 14 | "runserver" 15 | ], 16 | "django": true 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.defaultInterpreterPath": "/Users/apple/opt/anaconda3/envs/myblog/bin/python", 3 | //"python.defaultInterpreterPath": "F:\\python\\Anaconda3\\envs\\blog\\python.exe", 4 | "python.linting.pylintArgs": [ 5 | "--load-plugins", 6 | "pylint_django" 7 | ], 8 | "python.linting.pylintEnabled": true, 9 | "python.linting.enabled": true 10 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # my_blog 2 | ## 我的个人博客 3 | - 在[Django-Hexo-Matery](https://github.com/sqlsec/Django-Hexo-Matery)项目的基础上开发 4 | - 基于python django框架的个人博客模版; 5 | 6 | # 项目地址 7 | - [my_blog](http://time.pings.fun) 8 | 9 | # 安装 10 | ## 安装运行环境 11 | pip install -r my_blog/docker/requirements.txt 12 | ## 正式环境部署 13 | - 通过docker方式部署; 14 | ``` 15 | docker build -t pings/my_blog -f my_blog/docker/Dockerfile . 16 | docker run -p 80:80 -p 8088:8088 -v /root/uploads/myblog:/opt/project/product/my_blog/uploads --name my_blog pings/my_blog 17 | ``` 18 | 19 | # 界面 20 | - github图片好像无法展示,这里展示链接; 21 | ## 首页 22 | ![首页](http://static.pings.fun/myblog/static/image/blog-1.png) 23 | ## 分类 24 | ![分类](http://static.pings.fun/myblog/static/image/blog-2.png) 25 | ## 文章 26 | ![文章](http://static.pings.fun/myblog/static/image/blog-3.png) 27 | ## 分类(移动端) 28 | ![分类(移动端)](http://static.pings.fun/myblog/static/image/blog-4.png) 29 | ## 文章(移动端) 30 | ![文章(移动端)](http://static.pings.fun/myblog/static/image/blog-5.png) 31 | ## 搜索(移动端) 32 | ![搜索(移动端)](http://static.pings.fun/myblog/static/image/blog-6.png) 33 | 34 | # 更新记录 35 | - 2020-06-17 项目开发完成 36 | - 2020-06-19 完善 37 | - 2020-06-20 静态资源改为cdn加速 -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7.7 2 | 3 | #**维护者 4 | MAINTAINER Pings 275598139@qq.com 5 | 6 | #**环境变量 7 | ENV LANG en_US.UTF-8 8 | #**设置时区 9 | RUN ln -s -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 10 | 11 | WORKDIR /opt/project/product 12 | COPY requirements.txt . 13 | RUN pip install -r requirements.txt 14 | 15 | # nginx 16 | # 安装 17 | RUN apt-get update 18 | RUN apt -y install nginx 19 | # 配置 20 | WORKDIR /etc/nginx/conf.d 21 | COPY conf/nginx/myblog.conf myblog.conf 22 | # 替换nginx.conf 23 | COPY conf/nginx/nginx.conf /etc/nginx/nginx.conf 24 | RUN rm -f default.conf 25 | 26 | # uwsgi 27 | RUN pip3 install uwsgi 28 | WORKDIR /opt/project/product/script 29 | COPY conf/uwsgi/uwsgi.ini uwsgi.ini 30 | 31 | # 启动脚本 32 | COPY conf/start.sh /opt/project/product/start.sh 33 | 34 | # 添加项目 35 | WORKDIR /opt/project/product 36 | RUN apt -y install git 37 | RUN git clone https://github.com/pingszi/my_blog.git 38 | 39 | # 正式模式配置settings 40 | WORKDIR /opt/project/product/my_blog/my_blog 41 | RUN sed -i "s/^DEBUG = True/DEBUG = False/" settings.py 42 | # 提取静态文件 43 | RUN python3 /opt/project/product/my_blog/manage.py collectstatic 44 | 45 | # 启动 46 | WORKDIR /opt/project/product 47 | CMD bash start.sh 48 | 49 | # docker build -t pings/my_blog -f my_blog/docker/Dockerfile . 50 | # docker run -p 80:80 -p 8088:8088 -v /root/uploads/myblog:/opt/project/product/my_blog/uploads --name my_blog pings/my_blog -------------------------------------------------------------------------------- /docker/conf/nginx/myblog.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | #charset koi8-r; 6 | access_log /var/log/nginx/my_blog.access.log main; 7 | 8 | location / { 9 | include uwsgi_params; 10 | uwsgi_connect_timeout 30; 11 | uwsgi_pass unix:///opt/project/product/script/uwsgi.sock; 12 | } 13 | 14 | location /static { 15 | alias /opt/project/product/my_blog/static; 16 | } 17 | 18 | location /media { 19 | alias /opt/project/product/my_blog/uploads; 20 | } 21 | 22 | #error_page 404 /404.html; 23 | 24 | # redirect server error pages to the static page /50x.html 25 | # 26 | error_page 500 502 503 504 /50x.html; 27 | location = /50x.html { 28 | root /usr/share/nginx/html; 29 | } 30 | 31 | # proxy the PHP scripts to Apache listening on 127.0.0.1:80 32 | # 33 | #location ~ \.php$ { 34 | # proxy_pass http://127.0.0.1; 35 | #} 36 | 37 | # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 38 | # 39 | #location ~ \.php$ { 40 | # root html; 41 | # fastcgi_pass 127.0.0.1:9000; 42 | # fastcgi_index index.php; 43 | # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; 44 | # include fastcgi_params; 45 | #} 46 | 47 | # deny access to .htaccess files, if Apache's document root 48 | # concurs with nginx's one 49 | # 50 | #location ~ /\.ht { 51 | # deny all; 52 | #} 53 | } 54 | 55 | -------------------------------------------------------------------------------- /docker/conf/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | user root; 2 | worker_processes 2; 3 | 4 | error_log /var/log/nginx/error.log warn; 5 | pid /var/run/nginx.pid; 6 | worker_rlimit_nofile 30000; 7 | 8 | events { 9 | worker_connections 2048; 10 | } 11 | 12 | 13 | http { 14 | include /etc/nginx/mime.types; 15 | default_type application/octet-stream; 16 | 17 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 18 | '$status $body_bytes_sent "$http_referer" ' 19 | '"$http_user_agent" "$http_x_forwarded_for"'; 20 | 21 | access_log /var/log/nginx/access.log main; 22 | 23 | sendfile on; 24 | #tcp_nopush on; 25 | 26 | keepalive_timeout 65; 27 | 28 | #gzip on; 29 | 30 | limit_req_zone $binary_remote_addr zone=promote_req_limit:50m rate=120r/m; 31 | 32 | include /etc/nginx/conf.d/*.conf; 33 | } 34 | -------------------------------------------------------------------------------- /docker/conf/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | nginx 3 | uwsgi --ini /opt/project/product/script/uwsgi.ini 4 | tail -f /var/log/nginx/error.log -------------------------------------------------------------------------------- /docker/conf/uwsgi/uwsgi.ini: -------------------------------------------------------------------------------- 1 | # uwsig使用配置文件启动 2 | [uwsgi] 3 | # 项目目录 4 | chdir=/opt/project/product/my_blog/ 5 | # 指定项目的application 6 | module=my_blog.wsgi:application 7 | # 指定sock的文件路径 8 | socket=/opt/project/product/script/uwsgi.sock 9 | # 进程个数 10 | workers=5 11 | pidfile=/opt/project/product/script/uwsgi.pid 12 | # 指定IP端口 13 | http=0.0.0.0:8088 14 | # 指定静态文件 15 | static-map=/static=/opt/project/product/my_blog/static 16 | # 启用主进程 17 | master=true 18 | # 自动移除unix Socket和pid文件当服务停止的时候 19 | vacuum=true 20 | # 序列化接受的内容,如果可能的话 21 | thunder-lock=true 22 | # 启用线程 23 | enable-threads=true 24 | # 设置自中断时间 25 | harakiri=30 26 | # 设置缓冲 27 | post-buffering=4096 28 | # 设置日志目录 29 | daemonize=/opt/project/product/script/uwsgi.log 30 | # 权限 31 | chmod-socket=666 32 | -------------------------------------------------------------------------------- /docker/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.2.7 2 | astroid==2.4.2 3 | certifi==2020.4.5.1 4 | colorama==0.4.3 5 | defusedxml==0.6.0 6 | diff-match-patch==20181111 7 | Django==2.2.27 8 | django-import-export==2.2.0 9 | django-mdeditor==0.1.18 10 | django-pure-pagination==0.3.0 11 | django-simpleui==4.0.2 12 | et-xmlfile==1.0.1 13 | isort==4.3.21 14 | jdcal==1.4.1 15 | lazy-object-proxy==1.4.3 16 | MarkupPy==1.14 17 | mccabe==0.6.1 18 | mistune==0.8.4 19 | PyMySQL==1.0.2 20 | odfpy==1.4.1 21 | openpyxl==3.0.3 22 | Pillow==9.0.0 23 | pylint==2.5.3 24 | pytz==2020.1 25 | PyYAML==5.4 26 | six==1.15.0 27 | sqlparse==0.3.1 28 | tablib==2.0.0 29 | toml==0.10.1 30 | typed-ast==1.4.1 31 | wincertstore==0.2 32 | wrapt==1.12.1 33 | xlrd==1.2.0 34 | xlwt==1.3.0 35 | -------------------------------------------------------------------------------- /era_blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/__init__.py -------------------------------------------------------------------------------- /era_blog/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.forms import TextInput, Textarea 3 | from django.db import models 4 | 5 | from .models import Links, Article, Category, Tag 6 | 7 | 8 | admin.site.site_header="Pings博客后台" 9 | admin.site.site_title="Pings博客" 10 | admin.site.index_title="Pings博客" 11 | 12 | 13 | # 文章 14 | @admin.register(Article) 15 | class ArticleAdmin(admin.ModelAdmin): 16 | list_display = ('id', 'title', 'category', 'cover_data', 'is_recommend', 'add_time', 'update_time') 17 | search_fields = ('title', 'desc', 'content') 18 | list_filter = ('category', 'tag', 'add_time') 19 | list_editable = ('category', 'is_recommend') 20 | list_per_page = 20 21 | 22 | fieldsets = ( 23 | ('编辑文章', { 24 | 'fields': ('title', 'content') 25 | }), 26 | ('其他设置', { 27 | 'classes': ('collapse', ), 28 | 'fields': ('cover', 'desc', 'is_recommend', 'click_count', 'tag', 'category', 'add_time'), 29 | }), 30 | ) 31 | 32 | formfield_overrides = { 33 | models.CharField: {'widget': TextInput(attrs={'size': '59'})}, 34 | models.TextField: {'widget': Textarea(attrs={'rows': 4, 'cols': 59})}, 35 | } 36 | 37 | 38 | # 分类 39 | @admin.register(Category) 40 | class CategoryAdmin(admin.ModelAdmin): 41 | list_display = ('id', 'name', 'index', 'active', 'get_items', 'icon', 'icon_data') 42 | search_fields = ('name', ) 43 | list_editable = ('active', 'index', 'icon') 44 | 45 | 46 | # 标签 47 | @admin.register(Tag) 48 | class TagAdmin(admin.ModelAdmin): 49 | list_display = ('id', 'name', 'get_items') 50 | search_fields = ('name', ) 51 | list_per_page = 20 52 | 53 | 54 | # 友链 55 | @admin.register(Links) 56 | class LinksAdmin(admin.ModelAdmin): 57 | list_display = ('id', 'title', 'url', 'avatar_data', 'desc') 58 | search_fields = ('title', 'url', 'desc') 59 | readonly_fields = ('avatar_admin', ) 60 | list_editable = ('url',) 61 | 62 | fieldsets = ( 63 | (None, { 64 | 'fields': ('title', 'url', 'desc', 'avatar_admin', 'image', ) 65 | }), 66 | ) 67 | 68 | formfield_overrides = { 69 | models.CharField: {'widget': TextInput(attrs={'size': '59'})}, 70 | models.TextField: {'widget': Textarea(attrs={'rows': 4, 'cols': 59})}, 71 | } 72 | 73 | -------------------------------------------------------------------------------- /era_blog/apps.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from django.apps import AppConfig 4 | 5 | 6 | class EraBlogConfig(AppConfig): 7 | name = 'era_blog' 8 | 9 | # **app名称 10 | verbose_name = "Pings博客后台" 11 | 12 | logger = logging.getLogger("erablog") 13 | -------------------------------------------------------------------------------- /era_blog/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-06-13 08:50 2 | 3 | import datetime 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | import mdeditor.fields 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Category', 19 | fields=[ 20 | ('id', models.AutoField(primary_key=True, serialize=False, verbose_name='编号')), 21 | ('name', models.CharField(max_length=30, verbose_name='分类名称')), 22 | ('index', models.IntegerField(default=99, verbose_name='分类排序')), 23 | ('active', models.BooleanField(default=True, verbose_name='是否添加到菜单')), 24 | ('icon', models.CharField(default='fa fa-home', max_length=30, verbose_name='菜单图标')), 25 | ], 26 | options={ 27 | 'verbose_name': '文章分类', 28 | 'verbose_name_plural': '文章分类', 29 | 'db_table': 'blog_category', 30 | }, 31 | ), 32 | migrations.CreateModel( 33 | name='Links', 34 | fields=[ 35 | ('id', models.AutoField(primary_key=True, serialize=False, verbose_name='编号')), 36 | ('title', models.CharField(max_length=50, verbose_name='标题')), 37 | ('url', models.URLField(verbose_name='地址')), 38 | ('desc', models.TextField(max_length=250, verbose_name='描述')), 39 | ('image', models.URLField(default='https://image.3001.net/images/20190330/1553875722169.jpg', verbose_name='头像')), 40 | ], 41 | options={ 42 | 'verbose_name': '友链', 43 | 'verbose_name_plural': '友链', 44 | 'db_table': 'blog_links', 45 | }, 46 | ), 47 | migrations.CreateModel( 48 | name='Tag', 49 | fields=[ 50 | ('id', models.AutoField(primary_key=True, serialize=False, verbose_name='编号')), 51 | ('name', models.CharField(max_length=30, verbose_name='标签名称')), 52 | ], 53 | options={ 54 | 'verbose_name': '文章标签', 55 | 'verbose_name_plural': '文章标签', 56 | 'db_table': 'blog_tag', 57 | }, 58 | ), 59 | migrations.CreateModel( 60 | name='Article', 61 | fields=[ 62 | ('id', models.AutoField(primary_key=True, serialize=False, verbose_name='编号')), 63 | ('title', models.CharField(max_length=50, verbose_name='文章标题')), 64 | ('desc', models.TextField(max_length=100, verbose_name='文章描述')), 65 | ('cover', models.CharField(default='https://image.3001.net/images/20200304/15832956271308.jpg', max_length=200, verbose_name='文章封面')), 66 | ('content', mdeditor.fields.MDTextField(verbose_name='文章内容')), 67 | ('click_count', models.IntegerField(default=0, verbose_name='点击次数')), 68 | ('is_recommend', models.BooleanField(default=False, verbose_name='是否推荐')), 69 | ('add_time', models.DateTimeField(default=datetime.datetime.now, verbose_name='发布时间')), 70 | ('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')), 71 | ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='articles', to='era_blog.Category', verbose_name='文章分类')), 72 | ('tag', models.ManyToManyField(related_name='articles', to='era_blog.Tag', verbose_name='文章标签')), 73 | ], 74 | options={ 75 | 'verbose_name': '文章', 76 | 'verbose_name_plural': '文章', 77 | 'db_table': 'blog_article', 78 | }, 79 | ), 80 | ] 81 | -------------------------------------------------------------------------------- /era_blog/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/migrations/__init__.py -------------------------------------------------------------------------------- /era_blog/models.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from django.db import models 3 | from django.utils.html import format_html 4 | from mdeditor.fields import MDTextField 5 | 6 | 7 | class Tag(models.Model): 8 | """ 9 | 文章标签 10 | """ 11 | 12 | class Meta: 13 | # **表名 14 | db_table = "blog_tag" 15 | # **菜单名 16 | verbose_name = "文章标签" 17 | verbose_name_plural = "文章标签" 18 | 19 | def __str__(self): 20 | return str(self.name) 21 | 22 | id = models.AutoField(primary_key=True, verbose_name="编号") 23 | name = models.CharField(max_length=30, verbose_name='标签名称') 24 | 25 | # 统计文章数 并放入后台 26 | def get_items(self): 27 | return self.article_set.all().count() 28 | get_items.short_description = '文章数' 29 | 30 | 31 | class Category(models.Model): 32 | """ 33 | 文章分类 34 | """ 35 | 36 | class Meta: 37 | # **表名 38 | db_table = "blog_category" 39 | # **菜单名 40 | verbose_name = "文章分类" 41 | verbose_name_plural = "文章分类" 42 | 43 | def __str__(self): 44 | return self.name 45 | 46 | id = models.AutoField(primary_key=True, verbose_name="编号") 47 | name = models.CharField(max_length=30, verbose_name='分类名称') 48 | index = models.IntegerField(default=99, verbose_name='分类排序') 49 | active = models.BooleanField(default=True, verbose_name='是否添加到菜单') 50 | icon = models.CharField(max_length=30, default='fa fa-home', verbose_name='菜单图标') 51 | 52 | # 统计文章数 并放入后台 53 | def get_items(self): 54 | return self.article_set.all().count() 55 | get_items.short_description = '文章数' 56 | 57 | def icon_data(self): 58 | return format_html( 59 | '', 60 | self.icon, 61 | ) 62 | icon_data.short_description = '图标预览' 63 | 64 | 65 | class Article(models.Model): 66 | """ 67 | 文章 68 | """ 69 | 70 | class Meta: 71 | # **表名 72 | db_table = "blog_article" 73 | # **菜单名 74 | verbose_name = '文章' 75 | verbose_name_plural = '文章' 76 | 77 | def __str__(self): 78 | return self.title 79 | 80 | id = models.AutoField(primary_key=True, verbose_name="编号") 81 | title = models.CharField(max_length=50, verbose_name='文章标题') 82 | desc = models.TextField(max_length=100, verbose_name='文章描述') 83 | cover = models.ImageField(upload_to='article/%Y/%m/',verbose_name='文章封面') 84 | content = MDTextField(verbose_name='文章内容') 85 | click_count = models.IntegerField(default=0, verbose_name='点击次数') 86 | is_recommend = models.BooleanField(default=False, verbose_name='是否推荐') 87 | add_time = models.DateTimeField(default=datetime.now, verbose_name='发布时间') 88 | update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') 89 | category = models.ForeignKey(Category, blank=True, null=True, verbose_name='文章分类', on_delete=models.DO_NOTHING) 90 | tag = models.ManyToManyField(Tag, verbose_name='文章标签') 91 | 92 | def cover_data(self): 93 | return format_html( 94 | '', 95 | self.cover.url, 96 | ) 97 | cover_data.short_description = '文章封面' 98 | 99 | def viewed(self): 100 | """ 101 | 增加阅读数 102 | """ 103 | self.click_count += 1 104 | self.save(update_fields=['click_count']) 105 | 106 | 107 | class Links(models.Model): 108 | """ 109 | 友情链接 110 | """ 111 | 112 | class Meta: 113 | # **表名 114 | db_table = "blog_links" 115 | # **菜单名 116 | verbose_name = '友链' 117 | verbose_name_plural = '友链' 118 | 119 | def __str__(self): 120 | return self.url 121 | 122 | id = models.AutoField(primary_key=True, verbose_name="编号") 123 | title = models.CharField(max_length=50, verbose_name='标题') 124 | url = models.URLField(verbose_name='地址') 125 | desc = models.TextField(verbose_name='描述', max_length=250) 126 | image = models.URLField(default='https://image.3001.net/images/20190330/1553875722169.jpg', verbose_name='头像') 127 | 128 | def avatar_data(self): 129 | return format_html( 130 | '', 131 | self.image, 132 | ) 133 | avatar_data.short_description = '头像' 134 | 135 | def avatar_admin(self): 136 | return format_html( 137 | '', 138 | self.image, 139 | ) 140 | avatar_admin.short_description = '头像预览' 141 | -------------------------------------------------------------------------------- /era_blog/static/codeBlock/codeBlockFuction.js: -------------------------------------------------------------------------------- 1 | // 代码块功能依赖 2 | 3 | $(function () { 4 | $('pre').wrap('
'); 5 | }); -------------------------------------------------------------------------------- /era_blog/static/codeBlock/codeCopy.js: -------------------------------------------------------------------------------- 1 | // 代码块一键复制 2 | 3 | $(function () { 4 | var $copyIcon = $('') 5 | var $notice = $('
') 6 | $('.code-area').prepend($copyIcon) 7 | $('.code-area').prepend($notice) 8 | // “复制成功”字出现 9 | function copy(text, ctx) { 10 | if (document.queryCommandSupported && document.queryCommandSupported('copy')) { 11 | try { 12 | document.execCommand('copy') // Security exception may be thrown by some browsers. 13 | $(ctx).prev('.codecopy_notice') 14 | .text("复制成功") 15 | .animate({ 16 | opacity: 1, 17 | top: 30 18 | }, 450, function () { 19 | setTimeout(function () { 20 | $(ctx).prev('.codecopy_notice').animate({ 21 | opacity: 0, 22 | top: 0 23 | }, 650) 24 | }, 400) 25 | }) 26 | } catch (ex) { 27 | $(ctx).prev('.codecopy_notice') 28 | .text("复制失败") 29 | .animate({ 30 | opacity: 1, 31 | top: 30 32 | }, 650, function () { 33 | setTimeout(function () { 34 | $(ctx).prev('.codecopy_notice').animate({ 35 | opacity: 0, 36 | top: 0 37 | }, 650) 38 | }, 400) 39 | }) 40 | return false 41 | } 42 | } else { 43 | $(ctx).prev('.codecopy_notice').text("浏览器不支持复制") 44 | } 45 | } 46 | // 复制 47 | $('.code-area .fa-copy').on('click', function () { 48 | var selection = window.getSelection() 49 | var range = document.createRange() 50 | range.selectNodeContents($(this).siblings('pre').find('code')[0]) 51 | selection.removeAllRanges() 52 | selection.addRange(range) 53 | var text = selection.toString() 54 | copy(text, this) 55 | selection.removeAllRanges() 56 | }) 57 | }); 58 | -------------------------------------------------------------------------------- /era_blog/static/codeBlock/codeLang.js: -------------------------------------------------------------------------------- 1 | // 代码块语言识别 2 | 3 | $(function () { 4 | var $highlight_lang = $('
'); 5 | 6 | $('pre').before($highlight_lang); 7 | $('pre').each(function () { 8 | var code_language = $(this).attr('class'); 9 | 10 | if (!code_language) { 11 | return true; 12 | }; 13 | var lang_name = code_language.replace("line-numbers", "").trim().replace("language-", "").trim(); 14 | 15 | // 首字母大写 16 | lang_name = lang_name.slice(0, 1).toUpperCase() + lang_name.slice(1); 17 | $(this).siblings(".code_lang").text(lang_name); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /era_blog/static/codeBlock/codeShrink.js: -------------------------------------------------------------------------------- 1 | // 代码块收缩 2 | 3 | $(function () { 4 | var $code_expand = $(''); 5 | 6 | $('.code-area').prepend($code_expand); 7 | $('.code-expand').on('click', function () { 8 | if ($(this).parent().hasClass('code-closed')) { 9 | $(this).siblings('pre').find('code').show(); 10 | $(this).parent().removeClass('code-closed'); 11 | } else { 12 | $(this).siblings('pre').find('code').hide(); 13 | $(this).parent().addClass('code-closed'); 14 | } 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /era_blog/static/css/gitment.css: -------------------------------------------------------------------------------- 1 | #gitment-content { 2 | padding: 1px 20px; 3 | } 4 | 5 | .gitment-card { 6 | margin-top: 20px; 7 | } 8 | 9 | .gitment-container { 10 | color: #34495e !important; 11 | } 12 | 13 | .gitment-container .gitment-header-like-btn { 14 | color: #ab47bc; 15 | } 16 | 17 | .gitment-container .gitment-header-like-btn svg { 18 | fill: #ab47bc; 19 | } 20 | 21 | .gitment-header-container span { 22 | color: #ab47bc; 23 | } 24 | 25 | .gitment-container .gitment-header-issue-link { 26 | color: #ab47bc; 27 | font-weight: 500; 28 | } 29 | 30 | .gitment-container a.gitment-header-issue-link, 31 | a.gitment-header-issue-link:visited { 32 | color: #ab47bc; 33 | } 34 | 35 | .gitment-container .gitment-comment-main { 36 | border: 1px solid #e1bee7; 37 | border-radius: 5px; 38 | } 39 | 40 | .gitment-container .gitment-comment-main .gitment-comment-header { 41 | background-color: #fff; 42 | } 43 | 44 | .gitment-container .gitment-comment-main .gitment-comment-like-btn { 45 | color: #ab47bc; 46 | } 47 | 48 | .gitment-container .gitment-comment-main .gitment-comment-like-btn svg { 49 | fill: #ab47bc; 50 | stroke: #ab47bc; 51 | stroke-width: 2px; 52 | } 53 | 54 | .gitment-editor-container .gitment-editor-avatar .gitment-github-icon { 55 | background-color: #ab47bc; 56 | } 57 | 58 | .gitment-editor-container .gitment-editor-main { 59 | border: 1px solid #e1bee7; 60 | border-radius: 3px; 61 | } 62 | 63 | .gitment-editor-container .gitment-editor-header { 64 | border-bottom: 0; 65 | border-radius: 3px; 66 | } 67 | 68 | .gitment-editor-main::after, 69 | .gitment-comment-main::after { 70 | border-right-color: #ab47bc !important; 71 | } 72 | 73 | .gitment-editor-main .gitment-editor-tabs { 74 | margin-left: 0; 75 | padding-left: 10px; 76 | background: linear-gradient(60deg, #ab47bc, #7b1fa2); 77 | } 78 | 79 | .gitment-editor-main .gitment-editor-tabs .gitment-editor-tab { 80 | color: #fff; 81 | border-radius: 3px; 82 | } 83 | 84 | .gitment-editor-main .gitment-editor-tabs .gitment-selected { 85 | background-color: rgba(255, 255, 255, 0.2); 86 | transition: 0.3s background-color 0.2s; 87 | border: 0 !important; 88 | color: #fff !important; 89 | font-weight: 500; 90 | } 91 | 92 | .gitment-editor-main .gitment-editor-login { 93 | margin-top: -40px; 94 | color: #ccc; 95 | } 96 | 97 | .gitment-editor-main .gitment-editor-login .gitment-editor-login-link { 98 | color: #fff; 99 | } 100 | 101 | .gitment-comments-init-btn:disabled, 102 | .gitment-editor-submit:disabled { 103 | background-color: #DFDFDF !important; 104 | color: #9F9F9F !important; 105 | border-radius: 0.2rem; 106 | box-shadow: 0 2px 2px 0 rgba(153, 153, 153, 0.14), 0 3px 1px -2px rgba(153, 153, 153, 0.2), 0 1px 5px 0 rgba(153, 153, 153, 0.12) !important; 107 | } 108 | 109 | .gitment-editor-footer .gitment-editor-submit, .gitment-comments-init-btn { 110 | color: #fff; 111 | background-color: #9c27b0; 112 | border-color: #9c27b0; 113 | border-radius: 0.2rem; 114 | box-shadow: 0 2px 2px 0 rgba(156, 39, 176, 0.14), 0 3px 1px -2px rgba(156, 39, 176, 0.2), 0 1px 5px 0 rgba(156, 39, 176, 0.12); 115 | } 116 | 117 | .gitment-footer-container { 118 | color: #34495e !important; 119 | } 120 | 121 | .gitment-comments-pagination .gitment-comments-page-item { 122 | display: inline-block; 123 | cursor: pointer; 124 | margin: 4px 5px; 125 | padding: .25rem .5rem; 126 | background-color: #9c27b0; 127 | color: #fff; 128 | border: 0; 129 | border-radius: 2px !important; 130 | box-shadow: 0 4px 5px 0 rgba(156, 39, 176, 0.14), 0 1px 10px 0 rgba(156, 39, 176, 0.12), 0 2px 4px -1px rgba(156, 39, 176, 0.2); 131 | } 132 | 133 | .gitment-footer-container a { 134 | padding: 0 2px; 135 | color: #ab47bc !important; 136 | font-weight: 500; 137 | } 138 | 139 | .gitment-comment-main .gitment-markdown p { 140 | color: #34495e; 141 | } 142 | 143 | .gitment-markdown p { 144 | margin: 2px 2px 10px; 145 | font-size: 1.05rem; 146 | line-height: 1.78rem; 147 | } 148 | 149 | .gitment-markdown blockquote p { 150 | text-indent: 0.2rem; 151 | } 152 | 153 | .gitment-markdown a { 154 | padding: 0 2px; 155 | color: #42b983; 156 | font-weight: 500; 157 | text-decoration: underline; 158 | } 159 | 160 | .gitment-markdown img { 161 | max-width: 100%; 162 | height: auto; 163 | cursor: pointer; 164 | } 165 | 166 | .gitment-markdown ol li { 167 | list-style-type: decimal; 168 | } 169 | 170 | .gitment-markdown ol, 171 | ul { 172 | display: block; 173 | padding-left: 2em; 174 | word-spacing: 0.05rem; 175 | } 176 | 177 | .gitment-markdown ul li, 178 | ol li { 179 | display: list-item; 180 | line-height: 1.8rem; 181 | font-size: 1rem; 182 | } 183 | 184 | .gitment-markdown ul li { 185 | list-style-type: disc; 186 | } 187 | 188 | .gitment-markdown ul ul li { 189 | list-style-type: circle; 190 | } 191 | 192 | .gitment-markdown table, th, td { 193 | padding: 12px 13px; 194 | border: 1px solid #dfe2e5; 195 | } 196 | 197 | .gitment-markdown table, th, td { 198 | border: 0; 199 | } 200 | 201 | table tr:nth-child(2n), thead { 202 | background-color: #fafafa; 203 | } 204 | 205 | .gitment-markdown table th { 206 | background-color: #f2f2f2; 207 | min-width: 80px; 208 | } 209 | 210 | .gitment-markdown table td { 211 | min-width: 80px; 212 | } 213 | 214 | .gitment-markdown h1 { 215 | font-size: 1.85rem; 216 | font-weight: bold; 217 | line-height: 2.2rem; 218 | } 219 | 220 | .gitment-markdown h2 { 221 | font-size: 1.65rem; 222 | font-weight: bold; 223 | line-height: 1.9rem; 224 | } 225 | 226 | .gitment-markdown h3 { 227 | font-size: 1.45rem; 228 | font-weight: bold; 229 | line-height: 1.7rem; 230 | } 231 | 232 | .gitment-markdown h4 { 233 | font-size: 1.25rem; 234 | font-weight: bold; 235 | line-height: 1.5rem; 236 | } 237 | 238 | .gitment-markdown h5 { 239 | font-size: 1.1rem; 240 | font-weight: bold; 241 | line-height: 1.4rem; 242 | } 243 | 244 | .gitment-markdown h6 { 245 | font-size: 1rem; 246 | line-height: 1.3rem; 247 | } 248 | 249 | .gitment-markdown p { 250 | font-size: 1rem; 251 | line-height: 1.5rem; 252 | } 253 | 254 | .gitment-markdown hr { 255 | margin: 12px 0; 256 | border: 0; 257 | border-top: 1px solid #ccc; 258 | } 259 | 260 | .gitment-markdown blockquote { 261 | margin: 15px 0; 262 | border-left: 5px solid #42b983; 263 | padding: 1rem 0.8rem 1rem 0.8rem; 264 | color: #666; 265 | background-color: rgba(66, 185, 131, .1); 266 | } 267 | 268 | .gitment-markdown pre { 269 | padding: 1.2em; 270 | margin: .5em 0; 271 | background: #272822; 272 | overflow: auto; 273 | border-radius: 0.3em; 274 | tab-size: 4; 275 | } 276 | 277 | .gitment-markdown code { 278 | padding: 1px 1px; 279 | font-size: 0.92rem; 280 | color: #e96900; 281 | background-color: #f8f8f8; 282 | border-radius: 2px; 283 | } 284 | 285 | .gitment-markdown pre code { 286 | padding: 0; 287 | color: #e8eaf6; 288 | background-color: #272822; 289 | } 290 | 291 | .gitment-markdown pre[class*="language-"] { 292 | padding: 1.2em; 293 | margin: .5em 0; 294 | } 295 | 296 | .gitment-markdown code[class*="language-"], 297 | pre[class*="language-"] { 298 | color: #e8eaf6; 299 | } 300 | 301 | .gitment-markdown b, 302 | strong { 303 | font-weight: bold; 304 | } 305 | 306 | .gitment-markdown dfn { 307 | font-style: italic; 308 | } 309 | 310 | .gitment-markdown small { 311 | font-size: 85%; 312 | } 313 | 314 | .gitment-markdown cite { 315 | font-style: normal; 316 | } 317 | 318 | .gitment-markdown mark { 319 | background-color: #fcf8e3; 320 | padding: .2em; 321 | } -------------------------------------------------------------------------------- /era_blog/static/css/jqcloud.css: -------------------------------------------------------------------------------- 1 | /* fonts */ 2 | 3 | div.jqcloud { 4 | font-family: "Helvetica", "Arial", sans-serif; 5 | font-size: 10px; 6 | line-height: normal; 7 | } 8 | 9 | div.jqcloud a { 10 | font-size: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | div.jqcloud span.w10 { font-size: 550%; } 15 | div.jqcloud span.w9 { font-size: 500%; } 16 | div.jqcloud span.w8 { font-size: 450%; } 17 | div.jqcloud span.w7 { font-size: 400%; } 18 | div.jqcloud span.w6 { font-size: 350%; } 19 | div.jqcloud span.w5 { font-size: 300%; } 20 | div.jqcloud span.w4 { font-size: 250%; } 21 | div.jqcloud span.w3 { font-size: 200%; } 22 | div.jqcloud span.w2 { font-size: 150%; } 23 | div.jqcloud span.w1 { font-size: 100%; } 24 | 25 | /* colors */ 26 | 27 | div.jqcloud { color: #09f; } 28 | div.jqcloud a { color: inherit; } 29 | div.jqcloud a:hover { color: #0df; } 30 | div.jqcloud a:hover { color: #0cf; } 31 | div.jqcloud span.w10 { color: #0cf; } 32 | div.jqcloud span.w9 { color: #0cf; } 33 | div.jqcloud span.w8 { color: #0cf; } 34 | div.jqcloud span.w7 { color: #39d; } 35 | div.jqcloud span.w6 { color: #90c5f0; } 36 | div.jqcloud span.w5 { color: #90a0dd; } 37 | div.jqcloud span.w4 { color: #90c5f0; } 38 | div.jqcloud span.w3 { color: #a0ddff; } 39 | div.jqcloud span.w2 { color: #99ccee; } 40 | div.jqcloud span.w1 { color: #aab5f0; } 41 | 42 | /* layout */ 43 | 44 | div.jqcloud { 45 | overflow: hidden; 46 | position: relative; 47 | } 48 | 49 | div.jqcloud span { padding: 0; } -------------------------------------------------------------------------------- /era_blog/static/css/monokai.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #49483e } 2 | .highlight { background: #272822; color: #f8f8f2 } 3 | .highlight .c { color: #75715e } /* Comment */ 4 | .highlight .err { color: #960050; background-color: #1e0010 } /* Error */ 5 | .highlight .k { color: #66d9ef } /* Keyword */ 6 | .highlight .l { color: #ae81ff } /* Literal */ 7 | .highlight .n { color: #f8f8f2 } /* Name */ 8 | .highlight .o { color: #f92672 } /* Operator */ 9 | .highlight .p { color: #f8f8f2 } /* Punctuation */ 10 | .highlight .ch { color: #75715e } /* Comment.Hashbang */ 11 | .highlight .cm { color: #75715e } /* Comment.Multiline */ 12 | .highlight .cp { color: #75715e } /* Comment.Preproc */ 13 | .highlight .cpf { color: #75715e } /* Comment.PreprocFile */ 14 | .highlight .c1 { color: #75715e } /* Comment.Single */ 15 | .highlight .cs { color: #75715e } /* Comment.Special */ 16 | .highlight .gd { color: #f92672 } /* Generic.Deleted */ 17 | .highlight .ge { font-style: italic } /* Generic.Emph */ 18 | .highlight .gi { color: #a6e22e } /* Generic.Inserted */ 19 | .highlight .go { color: #66d9ef } /* Generic.Output */ 20 | .highlight .gp { color: #f92672; font-weight: bold } /* Generic.Prompt */ 21 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 22 | .highlight .gu { color: #75715e } /* Generic.Subheading */ 23 | .highlight .kc { color: #66d9ef } /* Keyword.Constant */ 24 | .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ 25 | .highlight .kn { color: #f92672 } /* Keyword.Namespace */ 26 | .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ 28 | .highlight .kt { color: #66d9ef } /* Keyword.Type */ 29 | .highlight .ld { color: #e6db74 } /* Literal.Date */ 30 | .highlight .m { color: #ae81ff } /* Literal.Number */ 31 | .highlight .s { color: #e6db74 } /* Literal.String */ 32 | .highlight .na { color: #a6e22e } /* Name.Attribute */ 33 | .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ 34 | .highlight .nc { color: #a6e22e } /* Name.Class */ 35 | .highlight .no { color: #66d9ef } /* Name.Constant */ 36 | .highlight .nd { color: #a6e22e } /* Name.Decorator */ 37 | .highlight .ni { color: #f8f8f2 } /* Name.Entity */ 38 | .highlight .ne { color: #a6e22e } /* Name.Exception */ 39 | .highlight .nf { color: #a6e22e } /* Name.Function */ 40 | .highlight .nl { color: #f8f8f2 } /* Name.Label */ 41 | .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ 42 | .highlight .nx { color: #a6e22e } /* Name.Other */ 43 | .highlight .py { color: #f8f8f2 } /* Name.Property */ 44 | .highlight .nt { color: #f92672 } /* Name.Tag */ 45 | .highlight .nv { color: #f8f8f2 } /* Name.Variable */ 46 | .highlight .ow { color: #f92672 } /* Operator.Word */ 47 | .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ 48 | .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ 49 | .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ 50 | .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ 51 | .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ 52 | .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ 53 | .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ 54 | .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ 55 | .highlight .sc { color: #e6db74 } /* Literal.String.Char */ 56 | .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ 57 | .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ 58 | .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ 59 | .highlight .se { color: #ae81ff } /* Literal.String.Escape */ 60 | .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ 61 | .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ 62 | .highlight .sx { color: #e6db74 } /* Literal.String.Other */ 63 | .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ 64 | .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ 65 | .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ 66 | .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ 67 | .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ 68 | .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ 69 | .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ 70 | .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ 71 | .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ 72 | .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ 73 | -------------------------------------------------------------------------------- /era_blog/static/css/my-gitalk.css: -------------------------------------------------------------------------------- 1 | .gitalk-card { 2 | margin: 1.25rem auto; 3 | } 4 | 5 | .gitalk-card .card-content { 6 | padding: 1px 20px 20px 20px; 7 | } 8 | 9 | #gitalk-container .gt-no-init a { 10 | color: #42b983; 11 | text-decoration: underline; 12 | } 13 | 14 | #gitalk-container .gt-container .gt-btn, 15 | #gitalk-container .gt-btn-login, 16 | #gitalk-container .gt-container .gt-header-controls .gt-btn { 17 | border: 1px solid #4caf50; 18 | background-color: #4caf50; 19 | box-shadow: 0 2px 2px 0 rgba(76, 175, 80, 0.14), 0 3px 1px -2px rgba(76, 175, 80, 0.2), 0 1px 5px 0 rgba(76, 175, 80, 0.12); 20 | } 21 | 22 | #gitalk-container .gt-container .gt-link { 23 | color: #42b983; 24 | text-decoration: underline; 25 | } 26 | 27 | #gitalk-container .gt-container .gt-btn-preview { 28 | color: #4caf50; 29 | background-color: #fff !important; 30 | box-shadow: 0 2px 2px 0 rgba(76, 175, 80, 0.14), 0 3px 1px -2px rgba(76, 175, 80, 0.2), 0 1px 5px 0 rgba(76, 175, 80, 0.12); 31 | } 32 | 33 | #gitalk-container .gt-container .gt-header-textarea { 34 | background-color: #f6f9fc; 35 | border: 1px solid rgba(0, 0, 0, 0.05); 36 | } 37 | 38 | #gitalk-container .gt-container .gt-svg svg { 39 | fill: #42b983; 40 | } 41 | 42 | #gitalk-container .gt-container .gt-header-controls-tip, 43 | #gitalk-container .gt-container a, 44 | #gitalk-container .gt-container .gt-comment-username { 45 | color: #42b983; 46 | } 47 | 48 | #gitalk-container .gt-container .gt-ico-text { 49 | margin-left: 0.08rem; 50 | } 51 | 52 | #gitalk-container .gt-container .gt-comment-body { 53 | color: #34495e !important; 54 | } 55 | 56 | #gitalk-container .gt-container .gt-header-preview { 57 | border: 1px solid rgba(0, 0, 0, 0.02); 58 | background-color: #f9f9f9; 59 | } 60 | 61 | .markdown-body p { 62 | margin: 2px 2px 10px; 63 | font-size: 1.05rem; 64 | line-height: 1.78rem; 65 | } 66 | 67 | .markdown-body blockquote p { 68 | text-indent: 0.2rem; 69 | } 70 | 71 | .markdown-body a { 72 | padding: 0 2px; 73 | color: #42b983; 74 | font-weight: 500; 75 | text-decoration: underline; 76 | } 77 | 78 | .markdown-body img { 79 | max-width: 100%; 80 | height: auto; 81 | cursor: pointer; 82 | } 83 | 84 | .markdown-body ol li { 85 | list-style-type: decimal; 86 | } 87 | 88 | .markdown-body ol, 89 | ul { 90 | display: block; 91 | padding-left: 2em; 92 | word-spacing: 0.05rem; 93 | } 94 | 95 | .markdown-body ul li, 96 | ol li { 97 | display: list-item; 98 | line-height: 1.8rem; 99 | font-size: 1rem; 100 | } 101 | 102 | .markdown-body ul li { 103 | list-style-type: disc; 104 | } 105 | 106 | .markdown-body ul ul li { 107 | list-style-type: circle; 108 | } 109 | 110 | .markdown-body table, th, td { 111 | padding: 12px 13px; 112 | border: 1px solid #dfe2e5; 113 | } 114 | 115 | .markdown-body table, th, td { 116 | border: 0; 117 | } 118 | 119 | table tr:nth-child(2n), thead { 120 | background-color: #fafafa; 121 | } 122 | 123 | .markdown-body table th { 124 | background-color: #f2f2f2; 125 | min-width: 80px; 126 | } 127 | 128 | .markdown-body table td { 129 | min-width: 80px; 130 | } 131 | 132 | .markdown-body h1 { 133 | font-size: 1.85rem; 134 | font-weight: bold; 135 | line-height: 2.2rem; 136 | } 137 | 138 | .markdown-body h2 { 139 | font-size: 1.65rem; 140 | font-weight: bold; 141 | line-height: 1.9rem; 142 | } 143 | 144 | .markdown-body h3 { 145 | font-size: 1.45rem; 146 | font-weight: bold; 147 | line-height: 1.7rem; 148 | } 149 | 150 | .markdown-body h4 { 151 | font-size: 1.25rem; 152 | font-weight: bold; 153 | line-height: 1.5rem; 154 | } 155 | 156 | .markdown-body h5 { 157 | font-size: 1.1rem; 158 | font-weight: bold; 159 | line-height: 1.4rem; 160 | } 161 | 162 | .markdown-body h6 { 163 | font-size: 1rem; 164 | line-height: 1.3rem; 165 | } 166 | 167 | .markdown-body p { 168 | font-size: 1rem; 169 | line-height: 1.5rem; 170 | } 171 | 172 | .markdown-body hr { 173 | margin: 12px 0; 174 | border: 0; 175 | border-top: 1px solid #ccc; 176 | } 177 | 178 | .markdown-body blockquote { 179 | margin: 15px 0; 180 | border-left: 5px solid #42b983; 181 | padding: 1rem 0.8rem 1rem 0.8rem; 182 | color: #666; 183 | background-color: rgba(66, 185, 131, .1); 184 | } 185 | 186 | .markdown-body pre { 187 | padding: 1.2em; 188 | margin: .5em 0; 189 | background: #272822; 190 | overflow: auto; 191 | border-radius: 0.3em; 192 | tab-size: 4; 193 | } 194 | 195 | .markdown-body code { 196 | padding: 1px 1px; 197 | font-size: 0.92rem; 198 | color: #e96900; 199 | background-color: #f8f8f8; 200 | border-radius: 2px; 201 | } 202 | 203 | .markdown-body pre code { 204 | padding: 0; 205 | color: #e8eaf6; 206 | background-color: #272822; 207 | } 208 | 209 | .markdown-body pre[class*="language-"] { 210 | padding: 1.2em; 211 | margin: .5em 0; 212 | } 213 | 214 | .markdown-body code[class*="language-"], 215 | pre[class*="language-"] { 216 | color: #e8eaf6; 217 | } 218 | 219 | .markdown-body [type="checkbox"]:not(:checked), [type="checkbox"]:checked { 220 | position: inherit; 221 | margin-left: -1.3rem; 222 | margin-right: 0.4rem; 223 | margin-top: -1px; 224 | vertical-align: middle; 225 | left: unset; 226 | visibility: visible; 227 | } 228 | 229 | .markdown-body b, 230 | strong { 231 | font-weight: bold; 232 | } 233 | 234 | .markdown-body dfn { 235 | font-style: italic; 236 | } 237 | 238 | .markdown-body small { 239 | font-size: 85%; 240 | } 241 | 242 | .markdown-body cite { 243 | font-style: normal; 244 | } 245 | 246 | .markdown-body mark { 247 | background-color: #fcf8e3; 248 | padding: .2em; 249 | } -------------------------------------------------------------------------------- /era_blog/static/css/my.css: -------------------------------------------------------------------------------- 1 | /* Here is your custom css styles. */ 2 | 3 | /* hexo-filter-github-emojis */ 4 | .github-emoji{ 5 | height: 2em; 6 | width: 2em; 7 | display: inline-block !important; 8 | position: relative; 9 | margin: 0 3px !important; 10 | padding: 0; 11 | } 12 | .github-emoji:hover{ 13 | animation: emoji-face 5s infinite ease-in-out; 14 | } 15 | @keyframes emoji-face { 16 | 2% { 17 | transform: translate(0, 1.5px) rotate(1.5deg); 18 | } 19 | 4% { 20 | transform: translate(0, -1.5px) rotate(-0.5deg); 21 | } 22 | 6% { 23 | transform: translate(0, 1.5px) rotate(-1.5deg); 24 | } 25 | 8% { 26 | transform: translate(0, -1.5px) rotate(-1.5deg); 27 | } 28 | 10% { 29 | transform: translate(0, 2.5px) rotate(1.5deg); 30 | } 31 | 12% { 32 | transform: translate(0, -0.5px) rotate(1.5deg); 33 | } 34 | 14% { 35 | transform: translate(0, -1.5px) rotate(1.5deg); 36 | } 37 | 16% { 38 | transform: translate(0, -0.5px) rotate(-1.5deg); 39 | } 40 | 18% { 41 | transform: translate(0, 0.5px) rotate(-1.5deg); 42 | } 43 | 20% { 44 | transform: translate(0, -1.5px) rotate(2.5deg); 45 | } 46 | 22% { 47 | transform: translate(0, 0.5px) rotate(-1.5deg); 48 | } 49 | 24% { 50 | transform: translate(0, 1.5px) rotate(1.5deg); 51 | } 52 | 26% { 53 | transform: translate(0, 0.5px) rotate(0.5deg); 54 | } 55 | 28% { 56 | transform: translate(0, 0.5px) rotate(1.5deg); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /era_blog/static/css/prism-a11y-dark.css: -------------------------------------------------------------------------------- 1 | /** 2 | * a11y-dark theme for JavaScript, CSS, and HTML 3 | * Based on the okaidia theme: https://github.com/PrismJS/prism/blob/gh-pages/themes/prism-okaidia.css 4 | * @author ericwbailey 5 | */ 6 | 7 | code[class*="language-"], 8 | pre[class*="language-"] { 9 | color: #f8f8f2; 10 | background: none; 11 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 12 | text-align: left; 13 | white-space: pre; 14 | word-spacing: normal; 15 | word-break: normal; 16 | word-wrap: normal; 17 | line-height: 1.5; 18 | 19 | -moz-tab-size: 4; 20 | -o-tab-size: 4; 21 | tab-size: 4; 22 | 23 | -webkit-hyphens: none; 24 | -moz-hyphens: none; 25 | -ms-hyphens: none; 26 | hyphens: none; 27 | } 28 | 29 | /* Code blocks */ 30 | pre[class*="language-"] { 31 | padding: 1em; 32 | margin: 0.5em 0; 33 | overflow: auto; 34 | border-radius: 0.3em; 35 | } 36 | 37 | :not(pre) > code[class*="language-"], 38 | pre[class*="language-"] { 39 | background: #2b2b2b; 40 | } 41 | 42 | /* Inline code */ 43 | :not(pre) > code[class*="language-"] { 44 | padding: 0.1em; 45 | border-radius: 0.3em; 46 | white-space: normal; 47 | } 48 | 49 | .token.comment, 50 | .token.prolog, 51 | .token.doctype, 52 | .token.cdata { 53 | color: #d4d0ab; 54 | } 55 | 56 | .token.punctuation { 57 | color: #fefefe; 58 | } 59 | 60 | .token.property, 61 | .token.tag, 62 | .token.constant, 63 | .token.symbol, 64 | .token.deleted { 65 | color: #ffa07a; 66 | } 67 | 68 | .token.boolean, 69 | .token.number { 70 | color: #00e0e0; 71 | } 72 | 73 | .token.selector, 74 | .token.attr-name, 75 | .token.string, 76 | .token.char, 77 | .token.builtin, 78 | .token.inserted { 79 | color: #abe338; 80 | } 81 | 82 | .token.operator, 83 | .token.entity, 84 | .token.url, 85 | .language-css .token.string, 86 | .style .token.string, 87 | .token.variable { 88 | color: #00e0e0; 89 | } 90 | 91 | .token.atrule, 92 | .token.attr-value, 93 | .token.function { 94 | color: #ffd700; 95 | } 96 | 97 | .token.keyword { 98 | color: #00e0e0; 99 | } 100 | 101 | .token.regex, 102 | .token.important { 103 | color: #ffd700; 104 | } 105 | 106 | .token.important, 107 | .token.bold { 108 | font-weight: bold; 109 | } 110 | .token.italic { 111 | font-style: italic; 112 | } 113 | 114 | .token.entity { 115 | cursor: help; 116 | } 117 | 118 | @media screen and (-ms-high-contrast: active) { 119 | code[class*="language-"], 120 | pre[class*="language-"] { 121 | color: windowText; 122 | background: window; 123 | } 124 | 125 | :not(pre) > code[class*="language-"], 126 | pre[class*="language-"] { 127 | background: window; 128 | } 129 | 130 | .token.important { 131 | background: highlight; 132 | color: window; 133 | font-weight: normal; 134 | } 135 | 136 | .token.atrule, 137 | .token.attr-value, 138 | .token.function, 139 | .token.keyword, 140 | .token.operator, 141 | .token.selector { 142 | font-weight: bold; 143 | } 144 | 145 | .token.attr-value, 146 | .token.comment, 147 | .token.doctype, 148 | .token.function, 149 | .token.keyword, 150 | .token.operator, 151 | .token.property, 152 | .token.string { 153 | color: highlight; 154 | } 155 | 156 | .token.attr-value, 157 | .token.url { 158 | font-weight: normal; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /era_blog/static/css/share.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:"socialshare";src:url("../fonts/iconfont.eot");src:url("../fonts/iconfont.eot?#iefix") format("embedded-opentype"),url("../fonts/iconfont.woff") format("woff"),url("../fonts/iconfont.ttf") format("truetype"),url("../fonts/iconfont.svg#iconfont") format("svg")}.social-share{font-family:"socialshare" !important;font-size:16px;font-style:normal;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:0.2px;-moz-osx-font-smoothing:grayscale}.social-share *{font-family:"socialshare" !important}.social-share .icon-tencent:before{content:"\f07a"}.social-share .icon-qq:before{content:"\f11a"}.social-share .icon-weibo:before{content:"\f12a"}.social-share .icon-wechat:before{content:"\f09a"}.social-share .icon-douban:before{content:"\f10a"}.social-share .icon-heart:before{content:"\f20a"}.social-share .icon-like:before{content:"\f00a"}.social-share .icon-qzone:before{content:"\f08a"}.social-share .icon-linkedin:before{content:"\f01a"}.social-share .icon-diandian:before{content:"\f05a"}.social-share .icon-facebook:before{content:"\f03a"}.social-share .icon-google:before{content:"\f04a"}.social-share .icon-twitter:before{content:"\f06a"}.social-share a{position:relative;text-decoration:none;margin:4px;display:inline-block;outline:none}.social-share .social-share-icon{position:relative;display:inline-block;width:32px;height:32px;font-size:20px;border-radius:50%;line-height:32px;border:1px solid #666;color:#666;text-align:center;vertical-align:middle;transition:background 0.6s ease-out 0s}.social-share .social-share-icon:hover{background:#666;color:#fff}.social-share .icon-weibo{color:#ff763b;border-color:#ff763b}.social-share .icon-weibo:hover{background:#ff763b}.social-share .icon-tencent{color:#56b6e7;border-color:#56b6e7}.social-share .icon-tencent:hover{background:#56b6e7}.social-share .icon-qq{color:#56b6e7;border-color:#56b6e7}.social-share .icon-qq:hover{background:#56b6e7}.social-share .icon-qzone{color:#FDBE3D;border-color:#FDBE3D}.social-share .icon-qzone:hover{background:#FDBE3D}.social-share .icon-douban{color:#33b045;border-color:#33b045}.social-share .icon-douban:hover{background:#33b045}.social-share .icon-linkedin{color:#0077B5;border-color:#0077B5}.social-share .icon-linkedin:hover{background:#0077B5}.social-share .icon-facebook{color:#44619D;border-color:#44619D}.social-share .icon-facebook:hover{background:#44619D}.social-share .icon-google{color:#db4437;border-color:#db4437}.social-share .icon-google:hover{background:#db4437}.social-share .icon-twitter{color:#55acee;border-color:#55acee}.social-share .icon-twitter:hover{background:#55acee}.social-share .icon-diandian{color:#307DCA;border-color:#307DCA}.social-share .icon-diandian:hover{background:#307DCA}.social-share .icon-wechat{position:relative;color:#7bc549;border-color:#7bc549}.social-share .icon-wechat:hover{background:#7bc549}.social-share .icon-wechat .wechat-qrcode{display:none;border:1px solid #eee;position:absolute;z-index:9;top:-205px;left:-84px;width:200px;height:192px;color:#666;font-size:12px;text-align:center;background-color:#fff;box-shadow:0 2px 10px #aaa;transition:all 200ms;-webkit-tansition:all 350ms;-moz-transition:all 350ms}.social-share .icon-wechat .wechat-qrcode.bottom{top:40px;left:-84px}.social-share .icon-wechat .wechat-qrcode.bottom:after{display:none}.social-share .icon-wechat .wechat-qrcode h4{font-weight:normal;height:26px;line-height:26px;font-size:12px;background-color:#f3f3f3;margin:0;padding:0;color:#777}.social-share .icon-wechat .wechat-qrcode .qrcode{width:105px;margin:10px auto}.social-share .icon-wechat .wechat-qrcode .qrcode table{margin:0 !important}.social-share .icon-wechat .wechat-qrcode .help p{font-weight:normal;line-height:16px;padding:0;margin:0}.social-share .icon-wechat .wechat-qrcode:after{content:'';position:absolute;left:50%;margin-left:-6px;bottom:-13px;width:0;height:0;border-width:8px 6px 6px 6px;border-style:solid;border-color:#fff transparent transparent transparent}.social-share .icon-wechat:hover .wechat-qrcode{display:block} 2 | -------------------------------------------------------------------------------- /era_blog/static/css/tocbot.css: -------------------------------------------------------------------------------- 1 | .toc{overflow-y:auto}.toc>.toc-list{overflow:hidden;position:relative}.toc>.toc-list li{list-style:none}.toc-list{margin:0;padding-left:10px}a.toc-link{color:currentColor;height:100%}.is-collapsible{max-height:1000px;overflow:hidden;transition:all 300ms ease-in-out}.is-collapsed{max-height:0}.is-position-fixed{position:fixed !important;top:0}.is-active-link{font-weight:700}.toc-link::before{background-color:#EEE;content:' ';display:inline-block;height:inherit;left:0;margin-top:-1px;position:absolute;width:2px}.is-active-link::before{background-color:#4A9D64} 2 | -------------------------------------------------------------------------------- /era_blog/static/fonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/fonts/iconfont.eot -------------------------------------------------------------------------------- /era_blog/static/fonts/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Created by FontForge 20120731 at Sat Nov 28 22:48:50 2015 6 | By Ads 7 | 8 | 9 | 10 | 24 | 26 | 28 | 30 | 32 | 36 | 39 | 42 | 44 | 50 | 53 | 57 | 61 | 65 | 71 | 73 | 78 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /era_blog/static/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/fonts/iconfont.ttf -------------------------------------------------------------------------------- /era_blog/static/fonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/fonts/iconfont.woff -------------------------------------------------------------------------------- /era_blog/static/image/blog-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/image/blog-1.png -------------------------------------------------------------------------------- /era_blog/static/image/blog-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/image/blog-2.png -------------------------------------------------------------------------------- /era_blog/static/image/blog-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/image/blog-3.png -------------------------------------------------------------------------------- /era_blog/static/image/blog-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/image/blog-4.png -------------------------------------------------------------------------------- /era_blog/static/image/blog-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/image/blog-5.png -------------------------------------------------------------------------------- /era_blog/static/image/blog-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/era_blog/static/image/blog-6.png -------------------------------------------------------------------------------- /era_blog/static/js/aos.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AOS=t():e.AOS=t()}(this,function(){return function(e){function t(n){if(o[n])return o[n].exports;var i=o[n]={exports:{},id:n,loaded:!1};return e[n].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var o={};return t.m=e,t.c=o,t.p="dist/",t(0)}([function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}var i=Object.assign||function(e){for(var t=1;t-1?O(!0):document.addEventListener(j.startEvent,function(){O(!0)}),window.addEventListener("resize",(0,s["default"])(O,50,!0)),window.addEventListener("orientationchange",(0,s["default"])(O,50,!0)),window.addEventListener("scroll",(0,c["default"])(function(){(0,b["default"])(h,j.once)},99)),document.addEventListener("DOMNodeRemoved",function(e){var t=e.target;t&&1===t.nodeType&&t.hasAttribute&&t.hasAttribute("data-aos")&&(0,s["default"])(_,50,!0)}),(0,f["default"])("[data-aos]",_),h)};e.exports={init:S,refresh:O,refreshHard:_}},function(e,t){},,,,function(e,t,o){"use strict";function n(e,t,o){var n=!0,a=!0;if("function"!=typeof e)throw new TypeError(c);return i(o)&&(n="leading"in o?!!o.leading:n,a="trailing"in o?!!o.trailing:a),r(e,t,{leading:n,maxWait:t,trailing:a})}function i(e){var t="undefined"==typeof e?"undefined":a(e);return!!e&&("object"==t||"function"==t)}var a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e},r=o(6),c="Expected a function";e.exports=n},function(e,t){"use strict";function o(e,t,o){function n(t){var o=b,n=v;return b=v=void 0,O=t,y=e.apply(n,o)}function a(e){return O=e,w=setTimeout(d,t),_?n(e):y}function r(e){var o=e-h,n=e-O,i=t-o;return z?x(i,g-n):i}function u(e){var o=e-h,n=e-O;return!h||o>=t||0>o||z&&n>=g}function d(){var e=j();return u(e)?f(e):void(w=setTimeout(d,r(e)))}function f(e){return clearTimeout(w),w=void 0,A&&b?n(e):(b=v=void 0,y)}function l(){void 0!==w&&clearTimeout(w),h=O=0,b=v=w=void 0}function m(){return void 0===w?y:f(j())}function p(){var e=j(),o=u(e);if(b=arguments,v=this,h=e,o){if(void 0===w)return a(h);if(z)return clearTimeout(w),w=setTimeout(d,t),n(h)}return void 0===w&&(w=setTimeout(d,t)),y}var b,v,g,y,w,h=0,O=0,_=!1,z=!1,A=!0;if("function"!=typeof e)throw new TypeError(s);return t=c(t)||0,i(o)&&(_=!!o.leading,z="maxWait"in o,g=z?k(c(o.maxWait)||0,t):g,A="trailing"in o?!!o.trailing:A),p.cancel=l,p.flush=m,p}function n(e){var t=i(e)?h.call(e):"";return t==f||t==l}function i(e){var t="undefined"==typeof e?"undefined":u(e);return!!e&&("object"==t||"function"==t)}function a(e){return!!e&&"object"==("undefined"==typeof e?"undefined":u(e))}function r(e){return"symbol"==("undefined"==typeof e?"undefined":u(e))||a(e)&&h.call(e)==m}function c(e){if("number"==typeof e)return e;if(r(e))return d;if(i(e)){var t=n(e.valueOf)?e.valueOf():e;e=i(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(p,"");var o=v.test(e);return o||g.test(e)?y(e.slice(2),o?2:8):b.test(e)?d:+e}var u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol?"symbol":typeof e},s="Expected a function",d=NaN,f="[object Function]",l="[object GeneratorFunction]",m="[object Symbol]",p=/^\s+|\s+$/g,b=/^[-+]0x[0-9a-f]+$/i,v=/^0b[01]+$/i,g=/^0o[0-7]+$/i,y=parseInt,w=Object.prototype,h=w.toString,k=Math.max,x=Math.min,j=Date.now;e.exports=o},function(e,t){"use strict";function o(e,t){r.push({selector:e,fn:t}),!c&&a&&(c=new a(n),c.observe(i.documentElement,{childList:!0,subtree:!0,removedNodes:!0})),n()}function n(){for(var e,t,o=0,n=r.length;n>o;o++){e=r[o],t=i.querySelectorAll(e.selector);for(var a,c=0,u=t.length;u>c;c++)a=t[c],a.ready||(a.ready=!0,e.fn.call(a,a))}}Object.defineProperty(t,"__esModule",{value:!0});var i=window.document,a=window.MutationObserver||window.WebKitMutationObserver,r=[],c=void 0;t["default"]=o},function(e,t){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e,t){for(var o=0;oe.position?e.node.classList.add("aos-animate"):"undefined"!=typeof n&&("false"===n||!o&&"true"!==n)&&e.node.classList.remove("aos-animate")},n=function(e,t){var n=window.pageYOffset,i=window.innerHeight;e.forEach(function(e,a){o(e,i+n,t)})};t["default"]=n},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var i=o(11),a=n(i),r=function(e,t){return e.forEach(function(e,o){e.node.classList.add("aos-init"),e.position=(0,a["default"])(e.node,t.offset)}),e};t["default"]=r},function(e,t,o){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}Object.defineProperty(t,"__esModule",{value:!0});var i=o(12),a=n(i),r=function(e,t){var o=0,n=0,i=window.innerHeight,r={offset:e.getAttribute("data-aos-offset"),anchor:e.getAttribute("data-aos-anchor"),anchorPlacement:e.getAttribute("data-aos-anchor-placement")};switch(r.offset&&!isNaN(r.offset)&&(n=parseInt(r.offset)),r.anchor&&document.querySelectorAll(r.anchor)&&(e=document.querySelectorAll(r.anchor)[0]),o=(0,a["default"])(e).top,r.anchorPlacement){case"top-bottom":break;case"center-bottom":o+=e.offsetHeight/2;break;case"bottom-bottom":o+=e.offsetHeight;break;case"top-center":o+=i/2;break;case"bottom-center":o+=i/2+e.offsetHeight;break;case"center-center":o+=i/2+e.offsetHeight/2;break;case"top-top":o+=i;break;case"bottom-top":o+=e.offsetHeight+i;break;case"center-top":o+=e.offsetHeight/2+i}return r.anchorPlacement||r.offset||isNaN(t)||(n=t),o+n};t["default"]=r},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=function(e){for(var t=0,o=0;e&&!isNaN(e.offsetLeft)&&!isNaN(e.offsetTop);)t+=e.offsetLeft-("BODY"!=e.tagName?e.scrollLeft:0),o+=e.offsetTop-("BODY"!=e.tagName?e.scrollTop:0),e=e.offsetParent;return{top:o,left:t}};t["default"]=o},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o=function(e){e=e||document.querySelectorAll("[data-aos]");var t=[];return[].forEach.call(e,function(e,o){t.push({node:e})}),t};t["default"]=o}])}); 2 | //# sourceMappingURL=aos.js.map -------------------------------------------------------------------------------- /era_blog/static/js/clicklove.js: -------------------------------------------------------------------------------- 1 | !function(e,t,a){function r(){for(var e=0;e { 96 | // preload(linkElement.href) 97 | // mouseoverTimer = undefined 98 | // }, delayOnHover) 99 | } 100 | 101 | function mousedownListener(event) { 102 | const linkElement = event.target.closest('a') 103 | 104 | if (!isPreloadable(linkElement)) { 105 | return 106 | } 107 | 108 | linkElement.addEventListener('mouseout', mouseoutListener, { 109 | passive: true 110 | }) 111 | 112 | urlToPreload = linkElement.href 113 | 114 | preload(linkElement.href) 115 | } 116 | 117 | function mouseoutListener(event) { 118 | if (event.relatedTarget && event.target.closest('a') == event.relatedTarget.closest('a')) { 119 | return 120 | } 121 | 122 | if (mouseoverTimer) { 123 | clearTimeout(mouseoverTimer) 124 | mouseoverTimer = undefined 125 | } 126 | 127 | urlToPreload = undefined 128 | 129 | stopPreloading() 130 | } 131 | 132 | function isPreloadable(linkElement) { 133 | if (!linkElement || !linkElement.href) { 134 | return 135 | } 136 | 137 | if (urlToPreload == linkElement.href) { 138 | return 139 | } 140 | 141 | if (useWhitelist && !('instant' in linkElement.dataset)) { 142 | return 143 | } 144 | 145 | if (!allowExternalLinks && linkElement.origin != location.origin && !('instant' in linkElement.dataset)) { 146 | return 147 | } 148 | 149 | if (!['http:', 'https:'].includes(linkElement.protocol)) { 150 | return 151 | } 152 | 153 | if (linkElement.protocol == 'http:' && location.protocol == 'https:') { 154 | return 155 | } 156 | 157 | if (!allowQueryString && linkElement.search && !('instant' in linkElement.dataset)) { 158 | return 159 | } 160 | 161 | if (linkElement.hash && linkElement.pathname + linkElement.search == location.pathname + location.search) { 162 | return 163 | } 164 | 165 | if ('noInstant' in linkElement.dataset) { 166 | return 167 | } 168 | 169 | return true 170 | } 171 | 172 | function preload(url) { 173 | prefetcher.href = url 174 | } 175 | 176 | function stopPreloading() { 177 | prefetcher.removeAttribute('href') 178 | } 179 | -------------------------------------------------------------------------------- /era_blog/static/js/jqcloud-1.0.4.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQCloud Plugin for jQuery 3 | * 4 | * Version 1.0.4 5 | * 6 | * Copyright 2011, Luca Ongaro 7 | * Licensed under the MIT license. 8 | * 9 | * Date: 2013-05-09 18:54:22 +0200 10 | */ 11 | (function(e){"use strict";e.fn.jQCloud=function(t,n){var r=this,i=r.attr("id")||Math.floor(Math.random()*1e6).toString(36),s={width:r.width(),height:r.height(),center:{x:(n&&n.width?n.width:r.width())/2,y:(n&&n.height?n.height:r.height())/2},delayedMode:t.length>50,shape:!1,encodeURI:!0,removeOverflowing:!0};n=e.extend(s,n||{}),r.addClass("jqcloud").width(n.width).height(n.height),r.css("position")==="static"&&r.css("position","relative");var o=function(){var s=function(e,t){var n=function(e,t){return Math.abs(2*e.offsetLeft+e.offsetWidth-2*t.offsetLeft-t.offsetWidth)t.weight?-1:0});var u=n.shape==="rectangular"?18:2,a=[],f=n.width/n.height,l=function(o,l){var c=i+"_word_"+o,h="#"+c,p=6.28*Math.random(),d=0,v=0,m=0,g=5,y="",b="",w;l.html=e.extend(l.html,{id:c}),l.html&&l.html["class"]&&(y=l.html["class"],delete l.html["class"]),t[0].weight>t[t.length-1].weight&&(g=Math.round((l.weight-t[t.length-1].weight)/(t[0].weight-t[t.length-1].weight)*9)+1),w=e("").attr(l.html).addClass("w"+g+" "+y),l.link?(typeof l.link=="string"&&(l.link={href:l.link}),n.encodeURI&&(l.link=e.extend(l.link,{href:encodeURI(l.link.href).replace(/'/g,"%27")})),b=e("").attr(l.link).text(l.text)):b=l.text,w.append(b);if(!!l.handlers)for(var E in l.handlers)l.handlers.hasOwnProperty(E)&&typeof l.handlers[E]=="function"&&e(w).bind(E,l.handlers[E]);r.append(w);var S=w.width(),x=w.height(),T=n.center.x-S/2,N=n.center.y-x/2,C=w[0].style;C.position="absolute",C.left=T+"px",C.top=N+"px";while(s(w[0],a)){if(n.shape==="rectangular"){v++,v*u>(1+Math.floor(m/2))*u*(m%4%2===0?1:f)&&(v=0,m++);switch(m%4){case 1:T+=u*f+Math.random()*2;break;case 2:N-=u+Math.random()*2;break;case 3:T-=u*f+Math.random()*2;break;case 0:N+=u+Math.random()*2}}else d+=u,p+=(o%2===0?1:-1)*u,T=n.center.x-S/2+d*Math.cos(p)*f,N=n.center.y+d*Math.sin(p)-x/2;C.left=T+"px",C.top=N+"px"}if(n.removeOverflowing&&(T<0||N<0||T+S>n.width||N+x>n.height)){w.remove();return}a.push(w[0]),e.isFunction(l.afterWordRender)&&l.afterWordRender.call(w)},c=function(i){i=i||0;if(!r.is(":visible")){setTimeout(function(){c(i)},10);return}i= 450) { 27 | w = w + 21; 28 | } else if (w >= 350 && w < 450) { 29 | w = w + 18; 30 | } else if (w >= 300 && w < 350) { 31 | w = w + 16; 32 | } else { 33 | w = w + 14; 34 | } 35 | $('#' + targetId).width(w); 36 | }; 37 | 38 | /** 39 | * 修复footer部分的位置,使得在内容比较少时,footer也会在底部. 40 | */ 41 | let fixFooterPosition = function () { 42 | $('.content').css('min-height', window.innerHeight - 165); 43 | }; 44 | 45 | /** 46 | * 修复样式. 47 | */ 48 | let fixStyles = function () { 49 | fixPostCardWidth('navContainer'); 50 | fixPostCardWidth('artDetail', 'prenext-posts'); 51 | fixFooterPosition(); 52 | }; 53 | fixStyles(); 54 | 55 | /*调整屏幕宽度时重新设置文章列的宽度,修复小间距问题*/ 56 | $(window).resize(function () { 57 | fixStyles(); 58 | }); 59 | 60 | /*初始化瀑布流布局*/ 61 | $('#articles').masonry({ 62 | itemSelector: '.article' 63 | }); 64 | 65 | AOS.init({ 66 | easing: 'ease-in-out-sine', 67 | duration: 700, 68 | delay: 100 69 | }); 70 | 71 | /*文章内容详情的一些初始化特性*/ 72 | let articleInit = function () { 73 | $('#articleContent a').attr('target', '_blank'); 74 | 75 | $('#articleContent img').each(function () { 76 | let imgPath = $(this).attr('src'); 77 | $(this).wrap('
'); 78 | // 图片添加阴影 79 | $(this).addClass("img-shadow img-margin"); 80 | // 图片添加字幕 81 | let alt = $(this).attr('alt'); 82 | let title = $(this).attr('title'); 83 | let captionText = ""; 84 | // 如果alt为空,title来替 85 | if (alt === undefined || alt === "") { 86 | if (title !== undefined && title !== "") { 87 | captionText = title; 88 | } 89 | } else { 90 | captionText = alt; 91 | } 92 | // 字幕不空,添加之 93 | if (captionText !== "") { 94 | let captionDiv = document.createElement('div'); 95 | captionDiv.className = 'caption'; 96 | let captionEle = document.createElement('b'); 97 | captionEle.className = 'center-caption'; 98 | captionEle.innerText = captionText; 99 | captionDiv.appendChild(captionEle); 100 | this.insertAdjacentElement('afterend', captionDiv) 101 | } 102 | }); 103 | $('#articleContent, #myGallery').lightGallery({ 104 | selector: '.img-item', 105 | // 启用字幕 106 | subHtmlSelectorRelative: true 107 | }); 108 | 109 | // progress bar init 110 | const progressElement = window.document.querySelector('.progress-bar'); 111 | if (progressElement) { 112 | new ScrollProgress((x, y) => { 113 | progressElement.style.width = y * 100 + '%'; 114 | }); 115 | } 116 | }; 117 | articleInit(); 118 | 119 | $('.modal').modal(); 120 | 121 | /*回到顶部*/ 122 | $('#backTop').click(function () { 123 | $('body,html').animate({scrollTop: 0}, 400); 124 | return false; 125 | }); 126 | 127 | /*监听滚动条位置*/ 128 | let $nav = $('#headNav'); 129 | let $backTop = $('.top-scroll'); 130 | // 当页面处于文章中部的时候刷新页面,因为此时无滚动,所以需要判断位置,给导航加上绿色。 131 | showOrHideNavBg($(window).scrollTop()); 132 | $(window).scroll(function () { 133 | /* 回到顶部按钮根据滚动条的位置的显示和隐藏.*/ 134 | let scroll = $(window).scrollTop(); 135 | showOrHideNavBg(scroll); 136 | }); 137 | 138 | function showOrHideNavBg(position) { 139 | let showPosition = 100; 140 | if (position < showPosition) { 141 | $nav.addClass('nav-transparent'); 142 | $backTop.slideUp(300); 143 | } else { 144 | $nav.removeClass('nav-transparent'); 145 | $backTop.slideDown(300); 146 | } 147 | } 148 | 149 | 150 | $(".nav-menu>li").hover(function(){ 151 | $(this).children('ul').stop(true,true).show(); 152 | $(this).addClass('nav-show').siblings('li').removeClass('nav-show'); 153 | 154 | },function(){ 155 | $(this).children('ul').stop(true,true).hide(); 156 | $('.nav-item.nav-show').removeClass('nav-show'); 157 | }) 158 | 159 | $('.m-nav-item>a').on('click',function(){ 160 | if ($(this).next('ul').css('display') == "none") { 161 | $('.m-nav-item').children('ul').slideUp(300); 162 | $(this).next('ul').slideDown(100); 163 | $(this).parent('li').addClass('m-nav-show').siblings('li').removeClass('m-nav-show'); 164 | }else{ 165 | $(this).next('ul').slideUp(100); 166 | $('.m-nav-item.m-nav-show').removeClass('m-nav-show'); 167 | } 168 | }); 169 | }); 170 | -------------------------------------------------------------------------------- /era_blog/static/js/scrollProgress.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.ScrollProgress=e()}(this,function(){"use strict";function t(){}var e=function(e){this._handleUpdate="function"==typeof e?e:t,this._viewportHeight=this._getViewportHeight(),this._viewportWidth=this._getViewportWidth(),this._progress=this._getProgress(),this._handleUpdate(this._progress.x,this._progress.y),this._onScroll=this._onScroll.bind(this),this._onResize=this._onResize.bind(this),window.addEventListener("scroll",this._onScroll),window.addEventListener("resize",this._onResize)};return e.prototype._getViewportHeight=function(){return document.body.scrollHeight-window.innerHeight},e.prototype._getViewportWidth=function(){return document.body.scrollWidth-window.innerWidth},e.prototype._getProgress=function(){var t=void 0===window.scrollX?window.pageXOffset:window.scrollX,e=void 0===window.scrollY?window.pageYOffset:window.scrollY;return{x:0===this._viewportWidth?0:t/this._viewportWidth,y:0===this._viewportHeight?0:e/this._viewportHeight}},e.prototype._onScroll=function(){this._progress=this._getProgress(),this._handleUpdate(this._progress.x,this._progress.y)},e.prototype._onResize=function(){this._viewportHeight=this._getViewportHeight(),this._viewportWidth=this._getViewportWidth(),this._progress=this._getProgress(),this._handleUpdate(this._progress.x,this._progress.y)},e.prototype.trigger=function(){this._handleUpdate(this._progress.x,this._progress.y)},e.prototype.destroy=function(){window.removeEventListener("scroll",this._onScroll),window.removeEventListener("resize",this._onResize),this._handleUpdate=null},e}); -------------------------------------------------------------------------------- /era_blog/static/js/search.js: -------------------------------------------------------------------------------- 1 | var searchFunc = function (path, search_id, content_id) { 2 | 'use strict'; 3 | $.ajax({ 4 | url: path, 5 | dataType: "json", 6 | success: function (response) { 7 | // get the contents from search data 8 | var datas = response; 9 | var $input = document.getElementById(search_id); 10 | var $resultContent = document.getElementById(content_id); 11 | $input.addEventListener('input', function () { 12 | var str = '
"; 75 | $resultContent.innerHTML = str; 76 | }); 77 | } 78 | }); 79 | } -------------------------------------------------------------------------------- /era_blog/static/js/tocbot.min.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(o){if(n[o])return n[o].exports;var l=n[o]={i:o,l:!1,exports:{}};return e[o].call(l.exports,l,l.exports,t),l.l=!0,l.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){(function(o){var l,i,s;!function(n,o){i=[],l=o(n),void 0!==(s="function"==typeof l?l.apply(t,i):l)&&(e.exports=s)}(void 0!==o?o:this.window||this.global,function(e){"use strict";function t(){for(var e={},t=0;te.fixedSidebarOffset?-1===n.className.indexOf(e.positionFixedClass)&&(n.className+=h+e.positionFixedClass):n.className=n.className.split(h+e.positionFixedClass).join("")}function s(t){var n=document.documentElement.scrollTop||f.scrollTop;e.positionFixedSelector&&i();var o,l=t;if(m&&null!==document.querySelector(e.tocSelector)&&l.length>0){d.call(l,function(t,i){if(t.offsetTop>n+e.headingsOffset+10){return o=l[0===i?i:i-1],!0}if(i===l.length-1)return o=l[l.length-1],!0});var s=document.querySelector(e.tocSelector).querySelectorAll("."+e.linkClass);u.call(s,function(t){t.className=t.className.split(h+e.activeLinkClass).join("")});var c=document.querySelector(e.tocSelector).querySelectorAll("."+e.listItemClass);u.call(c,function(t){t.className=t.className.split(h+e.activeListItemClass).join("")});var a=document.querySelector(e.tocSelector).querySelector("."+e.linkClass+".node-name--"+o.nodeName+'[href="#'+o.id+'"]');-1===a.className.indexOf(e.activeLinkClass)&&(a.className+=h+e.activeLinkClass);var p=a.parentNode;p&&-1===p.className.indexOf(e.activeListItemClass)&&(p.className+=h+e.activeListItemClass);var C=document.querySelector(e.tocSelector).querySelectorAll("."+e.listClass+"."+e.collapsibleClass);u.call(C,function(t){-1===t.className.indexOf(e.isCollapsedClass)&&(t.className+=h+e.isCollapsedClass)}),a.nextSibling&&-1!==a.nextSibling.className.indexOf(e.isCollapsedClass)&&(a.nextSibling.className=a.nextSibling.className.split(h+e.isCollapsedClass).join("")),r(a.parentNode.parentNode)}}function r(t){return-1!==t.className.indexOf(e.collapsibleClass)&&-1!==t.className.indexOf(e.isCollapsedClass)?(t.className=t.className.split(h+e.isCollapsedClass).join(""),r(t.parentNode.parentNode)):t}function c(t){var n=t.target||t.srcElement;"string"==typeof n.className&&-1!==n.className.indexOf(e.linkClass)&&(m=!1)}function a(){m=!0}var u=[].forEach,d=[].some,f=document.body,m=!0,h=" ";return{enableTocAnimation:a,disableTocAnimation:c,render:n,updateToc:s}}},function(e,t){e.exports=function(e){function t(e){return e[e.length-1]}function n(e){return+e.nodeName.split("H").join("")}function o(t){var o={id:t.id,children:[],nodeName:t.nodeName,headingLevel:n(t),textContent:t.textContent.trim()};return e.includeHtml&&(o.childNodes=t.childNodes),o}function l(l,i){for(var s=o(l),r=n(l),c=i,a=t(c),u=a?a.headingLevel:0,d=r-u;d>0;)a=t(c),a&&void 0!==a.children&&(c=a.children),d--;return r>=e.collapseDepth&&(s.isCollapsed=!0),c.push(s),c}function i(t,n){var o=n;e.ignoreSelector&&(o=n.split(",").map(function(t){return t.trim()+":not("+e.ignoreSelector+")"}));try{return document.querySelector(t).querySelectorAll(o)}catch(e){return console.warn("Element not found: "+t),null}}function s(e){return r.call(e,function(e,t){return l(o(t),e.nest),e},{nest:[]})}var r=[].reduce;return{nestHeadingsArray:s,selectHeadings:i}}},function(e,t){function n(e){function t(e){return"a"===e.tagName.toLowerCase()&&(e.hash.length>0||"#"===e.href.charAt(e.href.length-1))&&(n(e.href)===s||n(e.href)+"#"===s)}function n(e){return e.slice(0,e.lastIndexOf("#"))}function l(e){var t=document.getElementById(e.substring(1));t&&(/^(?:a|select|input|button|textarea)$/i.test(t.tagName)||(t.tabIndex=-1),t.focus())}!function(){document.documentElement.style}();var i=e.duration,s=location.hash?n(location.href):location.href;!function(){function n(n){!t(n.target)||n.target.className.indexOf("no-smooth-scroll")>-1||"#"===n.target.href.charAt(n.target.href.length-2)&&"!"===n.target.href.charAt(n.target.href.length-1)||-1===n.target.className.indexOf(e.linkClass)||o(n.target.hash,{duration:i,callback:function(){l(n.target.hash)}})}document.body.addEventListener("click",n,!1)}()}function o(e,t){function n(e){s=e-i,window.scrollTo(0,c.easing(s,r,u,d)),s 6 | {% include 'banner.html' %} 7 | 8 | {% endblock %} 9 | 10 | {% block contents %} 11 |
12 |
13 |
14 |
2020-02-16:0
15 |
16 |
17 | 18 | 19 | 90 | 91 |
92 | {% for article in all_articles.object_list %} 93 |
94 |
95 | {{ article.add_time | date:"Y" }} 96 |
97 | 98 |
99 | {{ article.add_time | date:"m" }} 100 |
101 | 102 |
103 | {{ article.add_time | date:"d" }} 104 |
105 | 143 |
144 | {% endfor %} 145 |
146 | 147 |
148 | {% endblock %} 149 | 150 | {% block pagination %} 151 |
152 |
153 |
154 | {% if all_articles.has_previous %} 155 | 156 | {% else %} 157 | 158 | {% endif %} 159 | 160 | 161 |
162 | 163 | 164 |
165 |
{{ all_articles.number }} / {{ all_articles.pages | last }}
166 |
167 | 168 |
169 | {% if all_articles.has_next %} 170 | 171 | {% else%} 172 | 173 | {% endif %} 174 | 175 | 176 |
177 | 178 |
179 |
180 | {% endblock %} -------------------------------------------------------------------------------- /era_blog/templates/article_category.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load custom_tag %} 3 | {% block title %}文章分类 | {% endblock %} 4 | {% block banner %} 5 |
6 | {% include 'banner.html' %} 7 |
8 | {% endblock %} 9 | 10 | {% block custom_style%} 11 | 52 | {% endblock %} 53 | 54 | {% block contents %} 55 |
56 | 57 | 58 | 59 |
60 |
61 |
62 |
63 |   文章分类 64 |
65 |
66 | {% for i in categories %} 67 | 68 | {{ i.name }} 70 | {{ i.article_set.all | length }} 71 | 72 | 73 | {% endfor %} 74 |
75 |
76 |
77 |
78 | 79 | 80 | 81 | 129 |
130 | {% endblock %} 131 | 132 | {% block pagination %} 133 |
134 |
135 |
136 | {% if articles.has_previous %} 137 | 138 | {% else %} 139 | 140 | {% endif %} 141 | 142 | 143 |
144 | 145 | 146 |
147 |
{{ articles.number }} / {{ articles.pages | last }}
148 |
149 | 150 |
151 | {% if articles.has_next %} 152 | 153 | {% else%} 154 | 155 | {% endif %} 156 | 157 | 158 |
159 | 160 |
161 |
162 | {% endblock %} -------------------------------------------------------------------------------- /era_blog/templates/article_tag.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load custom_tag %} 3 | {% block title %}文章标签 | {% endblock %} 4 | {% block banner %} 5 |
6 | {% include 'banner.html' %} 7 |
8 | {% endblock %} 9 | 10 | {% block custom_style%} 11 | 52 | {% endblock %} 53 | 54 | {% block contents %} 55 |
56 | 57 | 58 | 59 |
60 |
61 |
62 |
63 |   文章标签 64 |
65 |
66 | {% for tag in tags %} 67 | 68 | {{ tag.name }} 70 | {{ tag.article_set.all | length }} 71 | 72 | 73 | {% endfor %} 74 |
75 |
76 |
77 |
78 | 79 | 80 | 81 | 129 |
130 | {% endblock %} 131 | 132 | {% block pagination %} 133 |
134 |
135 |
136 | {% if articles.has_previous %} 137 | 138 | {% else %} 139 | 140 | {% endif %} 141 | 142 | 143 |
144 | 145 | 146 |
147 |
{{ articles.number }} / {{ articles.pages | last }}
148 |
149 | 150 |
151 | {% if articles.has_next %} 152 | 153 | {% else%} 154 | 155 | {% endif %} 156 | 157 | 158 |
159 | 160 |
161 |
162 | {% endblock %} -------------------------------------------------------------------------------- /era_blog/templates/banner.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 | Pings博客 7 |
8 | 9 |
10 | 11 | 12 | 22 |
23 |
24 |
25 |
26 |
-------------------------------------------------------------------------------- /era_blog/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% load static %} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {% block title %}{% endblock %}{{ SITE_NAME }} 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | {% block css %}{% endblock %} 26 | {% block js %}{% endblock %} 27 | 28 | 29 | 30 | 117 | 118 | {% block custom_style %} 119 | 169 | {% endblock %} 170 | 171 | {% block banner %} 172 | {% endblock %} 173 | 174 | 188 | 189 | {% block contents %} 190 | {% endblock %} 191 | 192 | 193 | 194 | {% block pagination %} 195 | {% endblock %} 196 | 197 | 198 | 226 | 227 | 228 |
229 | 230 | 231 | 240 | 241 | 242 | 251 | 252 |
253 | 254 | 255 | 256 |
257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | -------------------------------------------------------------------------------- /era_blog/templates/category.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block title %}分类统计 | {% endblock %} 3 | {% load custom_tag %} 4 | {% load static %} 5 | {% block banner %} 6 |
7 | {% include 'banner.html' %} 8 |
9 | {% endblock %} 10 | 11 | {% block custom_style%} 12 | 53 | {% endblock %} 54 | 55 | {% block contents %} 56 |
57 | 58 | 59 | 60 |
61 |
62 |
63 |
64 |   文章分类 65 |
66 |
67 | {% for category in categories %} 68 | 69 | {{ category.name }} 71 | {{ category.article_set.all | length }} 72 | 73 | 74 | {% endfor %} 75 |
76 |
77 |
78 |
79 | 80 | 81 | 87 | 88 |
89 |
90 |
91 |
92 |
93 | 94 | 95 | 134 | 135 | 136 |
137 | {% endblock %} -------------------------------------------------------------------------------- /era_blog/templates/friends.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load custom_tag %} 3 | {% block title %}友情链接 | {% endblock %} 4 | {% block custom_style %} 5 | 194 | {% endblock %} 195 | 196 | {% block banner %} 197 |
198 | {% include 'banner.html' %} 199 |
200 | {% endblock %} 201 | 202 | {% block contents %} 203 | 204 |
205 |
206 |
207 |
208 |
209 |   友情链接 210 |
211 | 235 |
236 |
237 |
238 |
239 | {% endblock %} 240 | 241 | {% block pagination %} 242 | {% endblock %} 243 | 244 | -------------------------------------------------------------------------------- /era_blog/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block banner %} 3 | {% ifequal all_articles.number 1 %} 4 | 27 | {% else %} 28 |
29 | {% include 'banner.html' %} 30 |
31 | {% endifequal %} 32 | {% endblock %} 33 | 34 | {% block contents %} 35 | {% ifequal all_articles.number 1 %} 36 |
37 |
38 |
39 |
40 |
41 |
42 |   宁静致远 43 |
44 | 45 |
46 |
47 | __画船听雨:你看得到我打在屏幕上的字,看不到我落在键盘上的泪。 Kali Linux:The quieter you become, the more you are able to 48 | hear. 冰心:成功的花,人们只惊羡她现时的明艳!然而当初她的芽儿,浸透了奋斗的泪泉,洒遍了牺牲的血雨。 49 |
50 |
51 |
52 | 53 |
54 |
  推荐文章
55 |
56 | {% for i in top_articles %} 57 |
58 |
59 |
60 |
61 | 62 | {{ i.category }} 64 | 65 |
66 | 67 |

{{ i.title }}

68 |
69 |

70 | {{ i.desc }} 71 |

72 | 75 | 阅读更多 76 | 77 |
78 |
79 |
80 | {% endfor %} 81 |
82 |
83 |
84 |
85 |
86 |
87 | {% endifequal %} 88 | 89 |
90 | 129 |
130 | {% endblock %} 131 | 132 | {% block pagination %} 133 |
134 |
135 |
136 | {% if all_articles.has_previous %} 137 | 139 | {% else %} 140 | 141 | {% endif %} 142 | 143 | 144 |
145 | 146 |
147 |
{{ all_articles.number }} / {{ all_articles.pages | last }}
148 |
149 | 150 |
151 | {% if all_articles.has_next %} 152 | 154 | {% else%} 155 | 156 | {% endif %} 157 | 158 | 159 |
160 | 161 |
162 |
163 | {% endblock %} -------------------------------------------------------------------------------- /era_blog/templates/tag.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block title %}标签统计 | {% endblock %} 3 | {% load custom_tag %} 4 | {% load static %} 5 | {% block banner %} 6 |
7 | {% include 'banner.html' %} 8 |
9 | {% endblock %} 10 | 11 | {% block custom_style%} 12 | 53 | {% endblock %} 54 | 55 | {% block contents %} 56 |
57 |
58 |
59 |
60 |
61 |   文章标签 62 |
63 |
64 | {% for tag in tags %} 65 | 66 | {{ tag.name }} 68 | {{ tag.article_set.all | length }} 69 | 70 | 71 | {% endfor %} 72 |
73 |
74 |
75 |
76 | 77 | 78 | 79 | 85 | 86 |
87 |
88 |
89 |
90 |
91 | 92 | 93 | 100 | 101 | 102 |
103 | {% endblock %} -------------------------------------------------------------------------------- /era_blog/templatetags/custom_tag.py: -------------------------------------------------------------------------------- 1 | import re 2 | from random import randint 3 | from django import template 4 | from django.template.defaultfilters import stringfilter 5 | 6 | 7 | register = template.Library() 8 | 9 | 10 | @register.simple_tag() 11 | def random_num(): 12 | return randint(1, 10) 13 | 14 | 15 | @register.filter(is_safe=True) 16 | @stringfilter 17 | def custom_markdown(content): 18 | code_list = re.findall(r'
', content, re.M)
19 |     for code in code_list:
20 |         content = re.sub(r'
',
21 |                          '
'.format(code=code.lower()), content,
22 |                          1)
23 |     return content


--------------------------------------------------------------------------------
/era_blog/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 | 
3 | # Create your tests here.
4 | 


--------------------------------------------------------------------------------
/era_blog/urls.py:
--------------------------------------------------------------------------------
 1 | from django.conf.urls import url
 2 | from django.conf import settings
 3 | from django.urls import path, re_path, include
 4 | from django.conf.urls.static import static
 5 | 
 6 | from era_blog.views import Index, Friends, Detail, Archive, CategoryList, CategoryView, TagList, TagView, About, AllArticle
 7 | 
 8 | 
 9 | urlpatterns = [
10 |     # 首页
11 |     path('', Index.as_view(), name='index'),
12 | 
13 |     # 友情链接
14 |     path('friends/', Friends.as_view(), name='friends'),
15 | 
16 |     # 文章详情
17 |     re_path('article/av(?P\d+)', Detail.as_view(), name='detail'),
18 | 
19 |     # 文章归档
20 |     path('article/', Archive.as_view(), name='archive'),
21 | 
22 |     # 分类统计
23 |     path('category/', CategoryList.as_view(), name='category'),
24 | 
25 |     # 文章分类
26 |     re_path('category/cg(?P\d+)', CategoryView.as_view(), name='article_category'),
27 | 
28 |     # 标签统计
29 |     path('tag/', TagList.as_view(), name='tag'),
30 | 
31 |     # 文章标签
32 |     re_path('tag/tg(?P\d+)', TagView.as_view(), name='article_tag'),
33 | 
34 |     # 关于本站
35 |     path('about/', About.as_view(),name='about'),
36 | 
37 |     # 关于本站
38 |     path('allArchive/', AllArticle.as_view(), name='allArchive'),
39 | 
40 | ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)


--------------------------------------------------------------------------------
/era_blog/views.py:
--------------------------------------------------------------------------------
  1 | import random
  2 | import datetime
  3 | import mistune
  4 | import json
  5 | 
  6 | from operator import itemgetter
  7 | from django.shortcuts import render
  8 | from django.views.generic.base import View
  9 | from django.conf import settings
 10 | from django.http import HttpResponse
 11 | from django.core import serializers
 12 | from pure_pagination import Paginator, EmptyPage, PageNotAnInteger
 13 | 
 14 | from .models import Links, Article, Category, Tag
 15 | 
 16 | 
 17 | def global_setting(request):
 18 |     """
 19 |     将settings里面的变量 注册为全局变量
 20 |     """
 21 |     active_categories = Category.objects.filter(active=True).order_by('index')
 22 |     return {
 23 |         'SITE_NAME': settings.SITE_NAME,
 24 |         'SITE_DESC': settings.SITE_DESCRIPTION,
 25 |         'SITE_KEY': settings.SECRET_KEY,
 26 |         'SITE_MAIL': settings.SITE_MAIL,
 27 |         'SITE_ICP': settings.SITE_ICP,
 28 |         'SITE_ICP_URL': settings.SITE_ICP_URL,
 29 |         'SITE_TITLE': settings.SITE_TITLE,
 30 |         'SITE_TYPE_CHINESE': settings.SITE_TYPE_CHINESE,
 31 |         'SITE_TYPE_ENGLISH': settings.SITE_TYPE_ENGLISH,
 32 |         'active_categories': active_categories
 33 |     }
 34 | 
 35 | 
 36 | class Index(View):
 37 |     """
 38 |     首页展示
 39 |     """
 40 |     def get(self, request):
 41 |         all_articles = Article.objects.all().defer('content').order_by('-add_time')
 42 |         top_articles = Article.objects.filter(is_recommend=1).defer('content')
 43 |         # 首页分页功能
 44 |         try:
 45 |             page = request.GET.get('page', 1)
 46 |         except PageNotAnInteger:
 47 |             page = 1
 48 | 
 49 |         p = Paginator(all_articles, 9, request=request)
 50 |         articles = p.page(page)
 51 | 
 52 |         return render(request, 'index.html', {
 53 |             'all_articles': articles,
 54 |             'top_articles': top_articles,
 55 |         })
 56 | 
 57 | 
 58 | class Friends(View):
 59 |     """
 60 |     友链链接展示
 61 |     """
 62 |     def get(self, request):
 63 |         links = Links.objects.all()
 64 |         card_num = random.randint(1, 10)
 65 |         return render(request, 'friends.html', {
 66 |             'links': links,
 67 |             'card_num': card_num,
 68 |         })
 69 | 
 70 | 
 71 | class Detail(View):
 72 |     """
 73 |     文章详情页
 74 |     """
 75 |     def get(self, request, pk):
 76 |         article = Article.objects.get(id=int(pk))
 77 |         article.viewed()
 78 |         mk = mistune.Markdown()
 79 |         output = mk(article.content)
 80 | 
 81 |         #**查找上一篇
 82 |         previous_article = Article.objects.filter(category=article.category, id__lt=pk).defer('content').order_by('-id')[:1]
 83 |         previous_article = previous_article[0] if len(previous_article) else None
 84 |         #**查找下一篇
 85 |         next_article = Article.objects.filter(category=article.category, id__gt=pk).defer('content').order_by('id')[:1]
 86 |         next_article = next_article[0] if len(next_article) else None
 87 | 
 88 |         return render(request, 'detail.html', {
 89 |             'article': article,
 90 |             'previous_article': previous_article,
 91 |             'next_article': next_article,
 92 |             'detail_html': output,
 93 |         })
 94 | 
 95 | 
 96 | class Archive(View):
 97 |     """
 98 |     文章归档
 99 |     """
100 |     def get(self, request):
101 |         all_articles = Article.objects.all().defer('content').order_by('-add_time')
102 |         all_date = all_articles.values('add_time')
103 |         latest_date = all_date[0]['add_time']
104 |         all_date_list = []
105 |         for i in all_date:
106 |             all_date_list.append(i['add_time'].strftime("%Y-%m-%d"))
107 | 
108 |         # 遍历1年的日期
109 |         end = datetime.date(latest_date.year, latest_date.month, latest_date.day)
110 |         begin = datetime.date(latest_date.year-1, latest_date.month, latest_date.day)
111 |         d = begin
112 |         date_list = []
113 |         temp_list = []
114 | 
115 |         delta = datetime.timedelta(days=1)
116 |         while d <= end:
117 |             day = d.strftime("%Y-%m-%d")
118 |             if day in all_date_list:
119 |                 temp_list.append(day)
120 |                 temp_list.append(all_date_list.count(day))
121 |             else:
122 |                 temp_list.append(day)
123 |                 temp_list.append(0)
124 |             d += delta
125 |             date_list.append(temp_list)
126 |             temp_list = []
127 | 
128 |         # 文章归档分页
129 |         try:
130 |             page = request.GET.get('page', 1)
131 |         except PageNotAnInteger:
132 |             page = 1
133 | 
134 |         p = Paginator(all_articles, 10, request=request)
135 |         articles = p.page(page)
136 | 
137 |         return render(request, 'archive.html', {
138 |             'all_articles': articles,
139 |             'date_list': date_list,
140 |             'end': str(end),
141 |             'begin': str(begin),
142 |         })
143 | 
144 | 
145 | class CategoryList(View):
146 |     def get(self, request):
147 |         categories = Category.objects.all()
148 | 
149 |         return render(request, 'category.html', {
150 |             'categories': categories,
151 |         })
152 | 
153 | 
154 | class CategoryView(View):
155 |     def get(self, request, pk):
156 |         categories = Category.objects.all()
157 |         articles = Category.objects.get(id=int(pk)).article_set.all().defer('content')
158 | 
159 |         try:
160 |             page = request.GET.get('page', 1)
161 |         except PageNotAnInteger:
162 |             page = 1
163 | 
164 |         p = Paginator(articles, 9, request=request)
165 |         articles = p.page(page)
166 | 
167 |         return render(request, 'article_category.html', {
168 |             'categories': categories,
169 |             'pk': int(pk),
170 |             'articles': articles
171 |         })
172 | 
173 | 
174 | class TagList(View):
175 |     def get(self, request):
176 |         tags = Tag.objects.all()
177 |         return render(request, 'tag.html', {
178 |             'tags': tags,
179 |         })
180 | 
181 | 
182 | class TagView(View):
183 |     def get(self, request, pk):
184 |         tags = Tag.objects.all()
185 |         articles = Tag.objects.get(id=int(pk)).article_set.all().defer('content')
186 | 
187 |         try:
188 |             page = request.GET.get('page', 1)
189 |         except PageNotAnInteger:
190 |             page = 1
191 | 
192 |         p = Paginator(articles, 9, request=request)
193 |         articles = p.page(page)
194 | 
195 |         return render(request, 'article_tag.html', {
196 |             'tags': tags,
197 |             'pk': int(pk),
198 |             'articles': articles,
199 |         })
200 | 
201 | 
202 | class About(View):
203 |     def get(self, request):
204 |         articles = Article.objects.all().defer('content').order_by('-add_time')
205 |         categories = Category.objects.all()
206 |         tags = Tag.objects.all()
207 | 
208 |         all_date = articles.values('add_time')
209 | 
210 |         latest_date = all_date[0]['add_time']
211 |         end_year = latest_date.strftime("%Y")
212 |         end_month = latest_date.strftime("%m")
213 |         date_list = []
214 |         for i in range(int(end_month), 13):
215 |             date = str(int(end_year)-1)+'-'+str(i).zfill(2)
216 |             date_list.append(date)
217 | 
218 |         for j in range(1, int(end_month)+1):
219 |             date = end_year + '-' + str(j).zfill(2)
220 |             date_list.append(date)
221 | 
222 |         value_list = []
223 |         all_date_list = []
224 |         for i in all_date:
225 |             all_date_list.append(i['add_time'].strftime("%Y-%m"))
226 | 
227 |         for i in date_list:
228 |             value_list.append(all_date_list.count(i))
229 | 
230 |         temp_list = []  # 临时集合
231 |         tags_list = []  # 存放每个标签对应的文章数
232 |         tags = Tag.objects.all()
233 |         for tag in tags:
234 |             temp_list.append(tag.name)
235 |             temp_list.append(len(tag.article_set.all()))
236 |             tags_list.append(temp_list)
237 |             temp_list = []
238 | 
239 |         tags_list.sort(key=lambda x: x[1], reverse=True)  # 根据文章数排序
240 | 
241 |         top10_tags = []
242 |         top10_tags_values = []
243 |         for i in tags_list[:10]:
244 |             top10_tags.append(i[0])
245 |             top10_tags_values.append(i[1])
246 | 
247 |         return render(request, 'about.html', {
248 |             'articles': articles,
249 |             'categories': categories,
250 |             'tags': tags,
251 |             'date_list': date_list,
252 |             'value_list': value_list,
253 |             'top10_tags': top10_tags,
254 |             'top10_tags_values': top10_tags_values
255 |         })
256 | 
257 | 
258 | class AllArticle(View):
259 |     def get(self, request):
260 |         articles = Article.objects.order_by('-add_time').values('id', 'title', 'desc')
261 |         rst = [{'id': d['id'], 'title': d['title'], 'content': d['desc']} for d in articles]
262 |         return HttpResponse(json.dumps(rst, ensure_ascii=False))


--------------------------------------------------------------------------------
/logs/erablog.log:
--------------------------------------------------------------------------------
1 | WARNING 18/Jun/2020 10:20:04 django.request log_response 228 Not Found: /favicon.ico
2 | 


--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
 1 | #!/usr/bin/env python
 2 | """Django's command-line utility for administrative tasks."""
 3 | import os
 4 | import sys
 5 | 
 6 | 
 7 | def main():
 8 |     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_blog.settings')
 9 |     try:
10 |         from django.core.management import execute_from_command_line
11 |     except ImportError as exc:
12 |         raise ImportError(
13 |             "Couldn't import Django. Are you sure it's installed and "
14 |             "available on your PYTHONPATH environment variable? Did you "
15 |             "forget to activate a virtual environment?"
16 |         ) from exc
17 |     execute_from_command_line(sys.argv)
18 | 
19 | 
20 | if __name__ == '__main__':
21 |     main()
22 | 


--------------------------------------------------------------------------------
/my_blog/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/my_blog/__init__.py


--------------------------------------------------------------------------------
/my_blog/asgi.py:
--------------------------------------------------------------------------------
 1 | """
 2 | ASGI config for my_blog project.
 3 | 
 4 | It exposes the ASGI callable as a module-level variable named ``application``.
 5 | 
 6 | For more information on this file, see
 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/
 8 | """
 9 | 
10 | import os
11 | 
12 | from django.core.asgi import get_asgi_application
13 | 
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_blog.settings')
15 | 
16 | application = get_asgi_application()
17 | 


--------------------------------------------------------------------------------
/my_blog/settings.py:
--------------------------------------------------------------------------------
  1 | """
  2 | Django settings for my_blog project.
  3 | 
  4 | Generated by 'django-admin startproject' using Django 3.0.7.
  5 | 
  6 | For more information on this file, see
  7 | https://docs.djangoproject.com/en/3.0/topics/settings/
  8 | 
  9 | For the full list of settings and their values, see
 10 | https://docs.djangoproject.com/en/3.0/ref/settings/
 11 | """
 12 | 
 13 | import os
 14 | 
 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 17 | 
 18 | 
 19 | # Quick-start development settings - unsuitable for production
 20 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
 21 | 
 22 | # SECURITY WARNING: keep the secret key used in production secret!
 23 | SECRET_KEY = 'dbo1#dz$g%w(wo*7uw$h3$-&mj0qt1txns!y!rjd$-r)7_xy+l'
 24 | 
 25 | # SECURITY WARNING: don't run with debug turned on in production!
 26 | DEBUG = True
 27 | 
 28 | ALLOWED_HOSTS = ['*']
 29 | 
 30 | 
 31 | # Application definition
 32 | 
 33 | INSTALLED_APPS = [
 34 |     'simpleui',
 35 |     'era_blog.apps.EraBlogConfig',
 36 |     'import_export',
 37 |     'mdeditor',
 38 |     'pure_pagination',
 39 | 
 40 |     'django.contrib.admin',
 41 |     'django.contrib.auth',
 42 |     'django.contrib.contenttypes',
 43 |     'django.contrib.sessions',
 44 |     'django.contrib.messages',
 45 |     'django.contrib.staticfiles'
 46 | ]
 47 | 
 48 | MIDDLEWARE = [
 49 |     'django.middleware.security.SecurityMiddleware',
 50 |     'django.contrib.sessions.middleware.SessionMiddleware',
 51 |     'django.middleware.common.CommonMiddleware',
 52 |     'django.middleware.csrf.CsrfViewMiddleware',
 53 |     'django.contrib.auth.middleware.AuthenticationMiddleware',
 54 |     'django.contrib.messages.middleware.MessageMiddleware',
 55 |     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 56 | ]
 57 | 
 58 | ROOT_URLCONF = 'my_blog.urls'
 59 | 
 60 | TEMPLATES = [
 61 |     {
 62 |         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 63 |         'DIRS': [],
 64 |         'APP_DIRS': True,
 65 |         'OPTIONS': {
 66 |             'context_processors': [
 67 |                 'django.template.context_processors.debug',
 68 |                 'django.template.context_processors.request',
 69 |                 'django.contrib.auth.context_processors.auth',
 70 |                 'django.contrib.messages.context_processors.messages',
 71 |                 'era_blog.views.global_setting',
 72 |             ],
 73 |         },
 74 |     },
 75 | ]
 76 | 
 77 | WSGI_APPLICATION = 'my_blog.wsgi.application'
 78 | 
 79 | 
 80 | # Database
 81 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
 82 | 
 83 | # 数据库配置
 84 | DATABASES = {
 85 |     'default': {
 86 |         'ENGINE': 'django.db.backends.mysql',
 87 |         'NAME': 'myblog',
 88 |         'HOST': 'www.pingswms.com',
 89 |         'PORT': '31001',
 90 |         'USER': 'root',
 91 |         'PASSWORD': 'Zhou1182969',
 92 |     }
 93 | }
 94 | 
 95 | 
 96 | # Password validation
 97 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
 98 | 
 99 | AUTH_PASSWORD_VALIDATORS = [
100 |     {
101 |         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
102 |     },
103 |     {
104 |         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
105 |     },
106 |     {
107 |         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
108 |     },
109 |     {
110 |         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
111 |     },
112 | ]
113 | 
114 | 
115 | # Internationalization
116 | # https://docs.djangoproject.com/en/3.0/topics/i18n/
117 | 
118 | # 语言时区
119 | LANGUAGE_CODE = 'zh-hans'
120 | 
121 | TIME_ZONE = 'Asia/Shanghai'
122 | 
123 | USE_I18N = True
124 | 
125 | USE_L10N = True
126 | 
127 | USE_TZ = True
128 | 
129 | 
130 | # Static files (CSS, JavaScript, Images)
131 | # https://docs.djangoproject.com/en/3.0/howto/static-files/
132 | 
133 | # 日志记录
134 | LOGGING = {
135 |     'version': 1,
136 |     'disable_existing_loggers': False,
137 |     'formatters': {
138 |         'standard': {
139 |             'format': '%(levelname)s %(asctime)s %(name)s %(funcName)s %(lineno)d %(message)s',
140 |             'datefmt' :"%d/%b/%Y %H:%M:%S"
141 |         },
142 |     },
143 |     'handlers': {
144 |         'console': {
145 |             'level': 'DEBUG',
146 |             'class': 'logging.StreamHandler',
147 |             'formatter': 'standard',
148 |         },
149 |         'file': {
150 |             'level': 'INFO',
151 |             'class': 'logging.FileHandler',
152 |             'filename': os.path.join(BASE_DIR + '/logs/', 'erablog.log'),
153 |             'formatter': 'standard'
154 |         },
155 |     },
156 |     'loggers': {
157 |         'django.request': {
158 |             'handlers': ['console', 'file'],
159 |             'level': 'DEBUG' if DEBUG else "INFO",
160 |         },
161 |         'django.db.backends': {
162 |             'handlers': ['console', 'file'],
163 |             'level': 'DEBUG' if DEBUG else "INFO",
164 |         },
165 |         'erablog': {
166 |             'handlers': ['console', 'file'],
167 |             'level': 'DEBUG' if DEBUG else "INFO",
168 |         },
169 |     }
170 | }
171 | 
172 | # 静态文件配置
173 | STATIC_URL = '/static/'
174 | STATIC_ROOT = os.path.join(BASE_DIR, 'static')
175 | 
176 | MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')
177 | MEDIA_URL = '/media/'
178 | 
179 | # 网站的基本信息配置
180 | SITE_NAME = 'Pings博客'         # 站点名称
181 | SITE_DESCRIPTION = 'Pings博客'  # 站点描述
182 | SITE_KEYWORDS = 'Pings,博客'    # 站点关键词
183 | SITE_TITLE = 'Pings博客'        # 博客标题
184 | SITE_TYPE_CHINESE = '时代廊桥(增城)博客'  # 打字效果 中文内容
185 | SITE_TYPE_ENGLISH = 'Times langqiao (Zengcheng) blog'  # 打字效果 英文内容
186 | SITE_MAIL = '275598139@qq.com'  # 我的邮箱
187 | SITE_ICP = '粤ICP备18148895号'   # 网站备案号 
188 | SITE_ICP_URL = 'http://beian.miit.gov.cn'  # 备案号超链接地址  
189 | 
190 | # Simple Ui 相关设置
191 | SIMPLEUI_LOGIN_PARTICLES = False
192 | SIMPLEUI_ANALYSIS = False
193 | SIMPLEUI_STATIC_OFFLINE = True
194 | SIMPLEUI_LOADING = False
195 | SIMPLEUI_LOGO = 'https://image.3001.net/images/20191031/15724874583730.png'
196 | # **菜单图标
197 | SIMPLEUI_ICON = {
198 |     '文章分类': 'fa fa-folder',
199 |     '文章标签': 'fa fa-tag'
200 | }
201 | 
202 | #**django mysql客户端默认为mysqlclient,比较难安装。使用pymysql替换mysqlclient
203 | import pymysql
204 | pymysql.install_as_MySQLdb()


--------------------------------------------------------------------------------
/my_blog/urls.py:
--------------------------------------------------------------------------------
 1 | """my_blog URL Configuration
 2 | 
 3 | The `urlpatterns` list routes URLs to views. For more information please see:
 4 |     https://docs.djangoproject.com/en/3.0/topics/http/urls/
 5 | Examples:
 6 | Function views
 7 |     1. Add an import:  from my_app import views
 8 |     2. Add a URL to urlpatterns:  path('', views.home, name='home')
 9 | Class-based views
10 |     1. Add an import:  from other_app.views import Home
11 |     2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
12 | Including another URLconf
13 |     1. Import the include() function: from django.urls import include, path
14 |     2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path
18 | from django.urls.conf import include
19 | from django.conf.urls.static import static
20 | from django.conf import settings
21 | 
22 | urlpatterns = [
23 |     path('admin/', admin.site.urls),
24 |     path('mdeditor/', include('mdeditor.urls')),
25 | 
26 |     # **ear_blog
27 |     path('', include('era_blog.urls')),
28 | ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
29 | 


--------------------------------------------------------------------------------
/my_blog/wsgi.py:
--------------------------------------------------------------------------------
 1 | """
 2 | WSGI config for my_blog project.
 3 | 
 4 | It exposes the WSGI callable as a module-level variable named ``application``.
 5 | 
 6 | For more information on this file, see
 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
 8 | """
 9 | 
10 | import os
11 | 
12 | from django.core.wsgi import get_wsgi_application
13 | 
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'my_blog.settings')
15 | 
16 | application = get_wsgi_application()
17 | 


--------------------------------------------------------------------------------
/uploads/article/2020/06/redis-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/redis-1.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/redis-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/redis-2.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/redis-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/redis-3.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/springboot-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/springboot-1.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/springboot-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/springboot-2.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/springboot-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/springboot-3.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/springboot-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/springboot-4.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/springboot-5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/springboot-5.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/springboot-6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/springboot-6.jpg


--------------------------------------------------------------------------------
/uploads/article/2020/06/springboot-7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/article/2020/06/springboot-7.jpg


--------------------------------------------------------------------------------
/uploads/editor/10_20200616134632284905.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/10_20200616134632284905.png


--------------------------------------------------------------------------------
/uploads/editor/11_20200616134717228777.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/11_20200616134717228777.png


--------------------------------------------------------------------------------
/uploads/editor/12_20200616134816739711.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/12_20200616134816739711.png


--------------------------------------------------------------------------------
/uploads/editor/13_20200616135754965695.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/13_20200616135754965695.png


--------------------------------------------------------------------------------
/uploads/editor/14_20200616135858054073.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/14_20200616135858054073.png


--------------------------------------------------------------------------------
/uploads/editor/15_20200616135919544637.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/15_20200616135919544637.png


--------------------------------------------------------------------------------
/uploads/editor/16_20200616135953372215.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/16_20200616135953372215.png


--------------------------------------------------------------------------------
/uploads/editor/17_20200616141227921615.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/17_20200616141227921615.png


--------------------------------------------------------------------------------
/uploads/editor/1_20200615212409393721.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/1_20200615212409393721.png


--------------------------------------------------------------------------------
/uploads/editor/1_20200616114738209450.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/1_20200616114738209450.png


--------------------------------------------------------------------------------
/uploads/editor/2_20200615212444162345.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/2_20200615212444162345.png


--------------------------------------------------------------------------------
/uploads/editor/2_20200616114754184473.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/2_20200616114754184473.png


--------------------------------------------------------------------------------
/uploads/editor/3_20200615212458218775.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/3_20200615212458218775.png


--------------------------------------------------------------------------------
/uploads/editor/3_20200616115150788760.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/3_20200616115150788760.png


--------------------------------------------------------------------------------
/uploads/editor/4_20200615212526004507.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/4_20200615212526004507.png


--------------------------------------------------------------------------------
/uploads/editor/4_20200616115212770007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/4_20200616115212770007.png


--------------------------------------------------------------------------------
/uploads/editor/5_20200615212622375867.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/5_20200615212622375867.png


--------------------------------------------------------------------------------
/uploads/editor/5_20200616115233644213.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/5_20200616115233644213.png


--------------------------------------------------------------------------------
/uploads/editor/6_20200616115251003814.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/6_20200616115251003814.png


--------------------------------------------------------------------------------
/uploads/editor/7_20200616115305401820.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/7_20200616115305401820.png


--------------------------------------------------------------------------------
/uploads/editor/8_20200616135051757889.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/8_20200616135051757889.png


--------------------------------------------------------------------------------
/uploads/editor/9_20200616134548163771.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pingszi/my_blog/80396d21e8ca8fead70a32bdc18692074dd65ce4/uploads/editor/9_20200616134548163771.png


--------------------------------------------------------------------------------